Skip to content

Commit 39d2d04

Browse files
committed
Preserve registered types when linking DWARF prototypes ##analysis
1 parent 6c66c2b commit 39d2d04

2 files changed

Lines changed: 69 additions & 28 deletions

File tree

libr/anal/dwarf_process.c

Lines changed: 35 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -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);

test/db/formats/dwarf

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,40 @@ int overridden (int x);
3535
EOF
3636
RUN
3737

38+
NAME="DWARF mismatch preserves registered type and stable name"
39+
FILE=bins/elf/dwarf3_cpp.elf
40+
ARGS=-e bin.dbginfo=false -e asm.dwarf=false
41+
CMDS=<<EOF
42+
t- fly
43+
e bin.dbginfo=true
44+
iddi
45+
aaa
46+
tf- fly
47+
k anal/types/fly=func
48+
k anal/types/func.fly.ret=FutureType *
49+
k anal/types/func.fly.args=0
50+
k anal/types/func.fly.cc=cdecl
51+
k anal/types/func.fly=
52+
iddi
53+
aaa
54+
k anal/dwarf/fcn.fly.typed_name
55+
k anal/types/fcnlink.0000137a~?
56+
afs @ 0x137a
57+
iddi
58+
k anal/dwarf/fcn.fly.typed_name
59+
k anal/types/func.fly.ret
60+
k anal/types/*~^fly_137a~?
61+
EOF
62+
EXPECT=<<EOF
63+
fly
64+
0
65+
FutureType * fly ();
66+
fly
67+
FutureType *
68+
0
69+
EOF
70+
RUN
71+
3872
NAME=test dwarf2
3973
FILE=bins/elf/dwarf/hello-dwarf2
4074
CMDS=<<EOF

0 commit comments

Comments
 (0)