22
33#include <ctype.h>
44#include <r_anal.h>
5+ #include <r_anal_priv.h>
56#include <r_bin_dwarf.h>
67
78typedef struct dwarf_parse_context_t {
@@ -13,6 +14,7 @@ typedef struct dwarf_parse_context_t {
1314 HtUP /*<offset, RBinDwarfLocList*>*/ * locations ;
1415 const char * lang ; // for demangling
1516 RArena * arena ;
17+ Sdb * pass_sdb ;
1618} Context ;
1719
1820typedef struct dwarf_function_t {
@@ -1614,14 +1616,18 @@ static bool dwarf_function_type_matches(Sdb *types, const char *name, const char
16141616 return true;
16151617}
16161618
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 ) {
1619+ 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 seen_in_pass ) {
16181620 R_RETURN_VAL_IF_FAIL (ctx && ctx -> anal && sname && dwarf_fcn && ret_type && variables , NULL );
16191621 Sdb * types = ctx -> anal -> sdb_types ;
16201622 const char * previous_name = sdb_const_getf (ctx -> sdb , NULL , "fcn.%s.name" , sname );
16211623 const char * previous = sdb_const_getf (ctx -> sdb , NULL , "fcn.%s.typed_name" , sname );
16221624 const ut64 previous_addr = sdb_num_getf (ctx -> sdb , NULL , "fcn.%s.addr" , sname );
16231625 if (previous_name && !strcmp (previous_name , dwarf_fcn -> name )
1624- && previous && previous_addr == dwarf_fcn -> addr ) {
1626+ && previous && previous_addr == dwarf_fcn -> addr
1627+ && (!seen_in_pass
1628+ || dwarf_function_type_matches (types , previous , ret_type ,
1629+ variables , has_unspecified_parameters )
1630+ || sdb_const_getf (ctx -> pass_sdb , NULL , "type.%s.quality" , previous ))) {
16251631 return strdup (previous );
16261632 }
16271633 char * name = sanitize_c_identifier (dwarf_fcn -> name );
@@ -1731,6 +1737,8 @@ static void import_dwarf_function_type(Context *ctx, const char *sname, const ch
17311737 sdb_setf (ctx -> sdb , csig , 0 , "fcn.%s.csig" , sname );
17321738 r_strbuf_fini (& args_buf );
17331739
1740+ const char * pass_quality = sdb_const_getf (ctx -> pass_sdb , NULL ,
1741+ "type.%s.quality" , typed_name );
17341742 const bool type_existed = !!sdb_const_get (anal -> sdb_types , typed_name , 0 );
17351743 if (!type_existed ) {
17361744 /* Only attempt C parsing for C-like languages. Non-C languages
@@ -1759,21 +1767,28 @@ static void import_dwarf_function_type(Context *ctx, const char *sname, const ch
17591767 if (!r_type_func_exist (anal -> sdb_types , typed_name )) {
17601768 (void )import_dwarf_function_fallback (anal , typed_name , ret_type , variables , has_unspecified_parameters );
17611769 }
1770+ if (r_type_func_exist (anal -> sdb_types , typed_name )) {
1771+ sdb_setf (ctx -> pass_sdb , dwarf_fcn -> prototype_complete ? "complete" : "incomplete" , 0 ,
1772+ "type.%s.quality" , typed_name );
1773+ }
1774+ } else if (pass_quality && !strcmp (pass_quality , "incomplete" )
1775+ && dwarf_fcn -> prototype_complete
1776+ && !dwarf_function_type_matches (anal -> sdb_types , typed_name ,
1777+ ret_type , variables , has_unspecified_parameters )) {
1778+ /* Only a function record created by an inferior DIE in this pass is
1779+ replaceable. Registered and prior-pass types remain untouched. */
1780+ (void )r_anal_function_del_signature (anal , typed_name );
1781+ (void )import_dwarf_function_fallback (anal , typed_name , ret_type , variables , has_unspecified_parameters );
1782+ sdb_setf (ctx -> pass_sdb , "complete" , 0 , "type.%s.quality" , typed_name );
1783+ } else if (pass_quality && dwarf_fcn -> prototype_complete ) {
1784+ sdb_setf (ctx -> pass_sdb , "complete" , 0 , "type.%s.quality" , typed_name );
17621785 }
17631786 const bool type_matches = dwarf_fcn -> prototype_complete
17641787 && dwarf_function_type_matches (anal -> sdb_types , typed_name ,
17651788 ret_type , variables , has_unspecified_parameters );
1766- const char * linked = sdb_const_getf (anal -> sdb_types , NULL ,
1767- "fcnlink.%08" PFMT64x , dwarf_fcn -> addr );
17681789 if (type_matches ) {
17691790 sdb_setf (anal -> sdb_types , typed_name , 0 ,
17701791 "fcnlink.%08" PFMT64x , dwarf_fcn -> addr );
1771- } else if (linked && !strcmp (linked , typed_name )) {
1772- char * link_key = r_str_newf ("fcnlink.%08" PFMT64x , dwarf_fcn -> addr );
1773- if (link_key ) {
1774- sdb_unset (anal -> sdb_types , link_key , 0 );
1775- }
1776- free (link_key );
17771792 }
17781793 free (csig );
17791794}
@@ -1787,8 +1802,25 @@ static void sdb_save_dwarf_function(Context *ctx, Function *dwarf_fcn, const cha
17871802 free (real_name );
17881803 return ;
17891804 }
1805+ const char * pass_name = sdb_const_getf (ctx -> pass_sdb , NULL ,
1806+ "fcn.%08" PFMT64x ".%s.name" , dwarf_fcn -> addr , sname );
1807+ const bool seen_in_pass = pass_name && !strcmp (pass_name , real_name );
1808+ const char * pass_quality = seen_in_pass
1809+ ? sdb_const_getf (ctx -> pass_sdb , NULL ,
1810+ "fcn.%08" PFMT64x ".%s.quality" , dwarf_fcn -> addr , sname )
1811+ : NULL ;
1812+ if (pass_quality && (!strcmp (pass_quality , "complete" )
1813+ || !dwarf_fcn -> prototype_complete )) {
1814+ free (real_name );
1815+ free (sname );
1816+ return ;
1817+ }
1818+ sdb_setf (ctx -> pass_sdb , real_name , 0 ,
1819+ "fcn.%08" PFMT64x ".%s.name" , dwarf_fcn -> addr , sname );
1820+ sdb_setf (ctx -> pass_sdb , dwarf_fcn -> prototype_complete ? "complete" : "incomplete" , 0 ,
1821+ "fcn.%08" PFMT64x ".%s.quality" , dwarf_fcn -> addr , sname );
17901822 char * typed_name = dwarf_function_type_name (ctx , sname , dwarf_fcn ,
1791- ret_type , variables , has_unspecified_parameters );
1823+ ret_type , variables , has_unspecified_parameters , seen_in_pass );
17921824 sdb_set (sdb , sname , "fcn" , 0 );
17931825
17941826 char * addr_val = r_str_newf ("0x%" PFMT64x , dwarf_fcn -> addr );
@@ -2105,8 +2137,13 @@ static void parse_type_entry(Context *ctx, ut64 idx) {
21052137 */
21062138R_API void r_anal_dwarf_process_info (const RAnal * anal , RAnalDwarfContext * ctx ) {
21072139 R_RETURN_IF_FAIL (ctx && anal );
2140+ r_anal_types_ensure_loaded ((RAnal * )anal );
21082141 Sdb * dwarf_sdb = sdb_ns (anal -> sdb , "dwarf" , 1 );
21092142 sdb_unset_like (anal -> sdb_types , "fcnlink.*" );
2143+ Sdb * pass_sdb = sdb_new0 ();
2144+ if (!pass_sdb ) {
2145+ return ;
2146+ }
21102147
21112148 const RBinDwarfDebugInfo * info = ctx -> info ;
21122149 const RBinDwarfCompUnit * unit ;
@@ -2120,13 +2157,15 @@ R_API void r_anal_dwarf_process_info(const RAnal *anal, RAnalDwarfContext *ctx)
21202157 .sdb = dwarf_sdb ,
21212158 .locations = ctx -> loc ,
21222159 .lang = NULL ,
2123- .arena = arena
2160+ .arena = arena ,
2161+ .pass_sdb = pass_sdb
21242162 };
21252163 R_VEC_FOREACH_I (unit -> dies , j ) {
21262164 parse_type_entry (& dw_context , j );
21272165 }
21282166 }
21292167 r_arena_free (arena );
2168+ sdb_free (pass_sdb );
21302169}
21312170
21322171bool filter_sdb_function_names (void * user , const char * k , const char * v ) {
0 commit comments