@@ -1614,35 +1614,27 @@ static bool dwarf_function_type_matches(Sdb *types, const char *name, const char
16141614 return true;
16151615}
16161616
1617- static char * dwarf_function_type_name (Context * ctx , const char * sname , const Function * dwarf_fcn , const char * ret_type , RList /*<Variable*>*/ * variables , bool has_unspecified_parameters , bool * type_matches ) {
1618- R_RETURN_VAL_IF_FAIL (ctx && ctx -> anal && sname && dwarf_fcn && ret_type && variables && type_matches , NULL );
1619- * type_matches = false;
1617+ static char * dwarf_function_type_name (Context * ctx , const char * sname , const Function * dwarf_fcn , const char * ret_type , RList /*<Variable*>*/ * variables , bool has_unspecified_parameters ) {
1618+ R_RETURN_VAL_IF_FAIL (ctx && ctx -> anal && sname && dwarf_fcn && ret_type && variables , NULL );
16201619 Sdb * types = ctx -> anal -> sdb_types ;
16211620 const char * previous_name = sdb_const_getf (ctx -> sdb , NULL , "fcn.%s.name" , sname );
16221621 const char * previous = sdb_const_getf (ctx -> sdb , NULL , "fcn.%s.typed_name" , sname );
1622+ const ut64 previous_addr = sdb_num_getf (ctx -> sdb , NULL , "fcn.%s.addr" , sname );
16231623 if (previous_name && !strcmp (previous_name , dwarf_fcn -> name )
1624- && previous && dwarf_function_type_matches (types , previous ,
1625- ret_type , variables , has_unspecified_parameters )) {
1626- * type_matches = true;
1624+ && previous && previous_addr == dwarf_fcn -> addr ) {
16271625 return strdup (previous );
16281626 }
16291627 char * name = sanitize_c_identifier (dwarf_fcn -> name );
1630- if (!name || !sdb_const_get (types , name , 0 )) {
1631- return name ;
1632- }
1633- if (dwarf_function_type_matches (types , name , ret_type ,
1628+ if (!name || !sdb_const_get (types , name , 0 )
1629+ || dwarf_function_type_matches (types , name , ret_type ,
16341630 variables , has_unspecified_parameters )) {
1635- * type_matches = true;
16361631 return name ;
16371632 }
16381633 char * candidate = r_str_newf ("%s_%" PFMT64x , name , dwarf_fcn -> addr );
16391634 int suffix = 2 ;
1640- while (candidate && sdb_const_get (types , candidate , 0 )) {
1641- if (dwarf_function_type_matches (types , candidate , ret_type ,
1642- variables , has_unspecified_parameters )) {
1643- * type_matches = true;
1644- break ;
1645- }
1635+ while (candidate && sdb_const_get (types , candidate , 0 )
1636+ && !dwarf_function_type_matches (types , candidate , ret_type ,
1637+ variables , has_unspecified_parameters )) {
16461638 free (candidate );
16471639 candidate = r_str_newf ("%s_%" PFMT64x "_%d" , name , dwarf_fcn -> addr , suffix ++ );
16481640 }
@@ -1713,7 +1705,7 @@ static bool import_dwarf_function_fallback(RAnal *anal, const char *typed_name,
17131705 return true;
17141706}
17151707
1716- static void import_dwarf_function_type (Context * ctx , const char * sname , const char * typed_name , Function * dwarf_fcn , const char * ret_type , RList /*<Variable*>*/ * variables , bool has_unspecified_parameters , bool type_matches ) {
1708+ static void import_dwarf_function_type (Context * ctx , const char * sname , const char * typed_name , Function * dwarf_fcn , const char * ret_type , RList /*<Variable*>*/ * variables , bool has_unspecified_parameters ) {
17171709 R_RETURN_IF_FAIL (ctx && ctx -> anal && sname && typed_name && dwarf_fcn && ret_type && variables );
17181710 RAnal * anal = (RAnal * )ctx -> anal ;
17191711 sdb_setf (ctx -> sdb , typed_name , 0 , "fcn.%s.typed_name" , sname );
@@ -1739,7 +1731,8 @@ static void import_dwarf_function_type(Context *ctx, const char *sname, const ch
17391731 sdb_setf (ctx -> sdb , csig , 0 , "fcn.%s.csig" , sname );
17401732 r_strbuf_fini (& args_buf );
17411733
1742- if (!r_type_func_exist (anal -> sdb_types , typed_name )) {
1734+ const bool type_existed = !!sdb_const_get (anal -> sdb_types , typed_name , 0 );
1735+ if (!type_existed ) {
17431736 /* Only attempt C parsing for C-like languages. Non-C languages
17441737 (Rust, Go, D, etc.) produce type names that are not valid C and
17451738 would choke the parser. Use the fallback which writes the same
@@ -1755,19 +1748,34 @@ static void import_dwarf_function_type(Context *ctx, const char *sname, const ch
17551748 }
17561749 free (errmsg );
17571750 }
1758- if (!imported ) {
1751+ if (!dwarf_function_type_matches (anal -> sdb_types , typed_name ,
1752+ ret_type , variables , has_unspecified_parameters )
1753+ && r_type_func_exist (anal -> sdb_types , typed_name )) {
1754+ /* The C importer can normalize a declaration into a different
1755+ prototype. Replace only the function record created above;
1756+ referenced or preexisting types remain registered. */
1757+ (void )r_anal_function_del_signature (anal , typed_name );
1758+ }
1759+ if (!r_type_func_exist (anal -> sdb_types , typed_name )) {
17591760 (void )import_dwarf_function_fallback (anal , typed_name , ret_type , variables , has_unspecified_parameters );
17601761 }
17611762 }
1762- if (dwarf_fcn -> prototype_complete && r_type_func_exist (anal -> sdb_types , typed_name )
1763- && (type_matches || dwarf_function_type_matches (anal -> sdb_types , typed_name ,
1764- ret_type , variables , has_unspecified_parameters ))) {
1765- const char * linked = sdb_const_getf (anal -> sdb_types , NULL ,
1766- "fcnlink.%08" PFMT64x , dwarf_fcn -> addr );
1763+ const bool type_matches = dwarf_fcn -> prototype_complete
1764+ && dwarf_function_type_matches (anal -> sdb_types , typed_name ,
1765+ ret_type , variables , has_unspecified_parameters );
1766+ const char * linked = sdb_const_getf (anal -> sdb_types , NULL ,
1767+ "fcnlink.%08" PFMT64x , dwarf_fcn -> addr );
1768+ if (type_matches ) {
17671769 if (!linked || !strcmp (linked , typed_name )) {
17681770 sdb_setf (anal -> sdb_types , typed_name , 0 ,
17691771 "fcnlink.%08" PFMT64x , dwarf_fcn -> addr );
17701772 }
1773+ } else if (linked && !strcmp (linked , typed_name )) {
1774+ char * link_key = r_str_newf ("fcnlink.%08" PFMT64x , dwarf_fcn -> addr );
1775+ if (link_key ) {
1776+ sdb_unset (anal -> sdb_types , link_key , 0 );
1777+ }
1778+ free (link_key );
17711779 }
17721780 free (csig );
17731781}
@@ -1781,9 +1789,8 @@ static void sdb_save_dwarf_function(Context *ctx, Function *dwarf_fcn, const cha
17811789 free (real_name );
17821790 return ;
17831791 }
1784- bool type_matches = false;
17851792 char * typed_name = dwarf_function_type_name (ctx , sname , dwarf_fcn ,
1786- ret_type , variables , has_unspecified_parameters , & type_matches );
1793+ ret_type , variables , has_unspecified_parameters );
17871794 sdb_set (sdb , sname , "fcn" , 0 );
17881795
17891796 char * addr_val = r_str_newf ("0x%" PFMT64x , dwarf_fcn -> addr );
@@ -1835,7 +1842,7 @@ static void sdb_save_dwarf_function(Context *ctx, Function *dwarf_fcn, const cha
18351842 r_strbuf_fini (& vars_buf );
18361843 r_strbuf_fini (& args_buf );
18371844 if (typed_name ) {
1838- import_dwarf_function_type (ctx , sname , typed_name , dwarf_fcn , ret_type , variables , has_unspecified_parameters , type_matches );
1845+ import_dwarf_function_type (ctx , sname , typed_name , dwarf_fcn , ret_type , variables , has_unspecified_parameters );
18391846 }
18401847 free (typed_name );
18411848 free (real_name );
0 commit comments