Refactoring function r_type_func_guess

This commit is contained in:
Alexis Ehret 2021-01-11 23:03:18 +01:00 committed by pancake
parent 78dc2b5b5f
commit 8ad2d817c2

View File

@ -580,86 +580,103 @@ R_API const char *r_type_func_args_name(Sdb *TDB, R_NONNULL const char *func_nam
#define MIN_MATCH_LEN 4
static inline bool is_function(const char *name) {
return name && !strcmp("func", name);
}
static R_OWN char *type_func_try_guess(Sdb *TDB, R_NONNULL char *name) {
const char *res;
if (r_str_nlen (name, MIN_MATCH_LEN) < MIN_MATCH_LEN) {
if (strlen(name) < MIN_MATCH_LEN) {
return NULL;
}
if ((res = sdb_const_get (TDB, name, NULL))) {
bool is_func = res && !strcmp ("func", res);
if (is_func) {
return strdup (name);
}
const char *res = sdb_const_get(TDB, name, NULL);
if (is_function(res)) {
return strdup(name);
}
return NULL;
}
static inline bool is_auto_named(char *func_name, size_t slen) {
return slen > 4 && (r_str_startswith (func_name, "fcn.") || r_str_startswith (func_name, "loc."));
}
static inline bool has_r_prefixes(char *func_name, int offset, size_t slen) {
return slen > 4 && (offset + 3 < slen) && func_name[offset + 3] == '.';
}
static char *strip_r_prefixes(char *func_name, size_t slen) {
// strip r2 prefixes (sym, sym.imp, etc')
int offset = 0;
while (has_r_prefixes(func_name, offset, slen)) {
offset += 4;
}
return func_name + offset;
}
static char *strip_common_prefixes_stdlib(char *func_name) {
// strip common prefixes from standard lib functions
if (r_str_startswith (func_name, "__isoc99_")) {
func_name += 9;
} else if (r_str_startswith (func_name, "__libc_") && !strstr(func_name, "_main")) {
func_name += 7;
} else if (r_str_startswith (func_name, "__GI_")) {
func_name += 5;
}
return func_name;
}
static char *strip_dll_prefix(char *func_name) {
char *tmp = strstr(func_name, "dll_");
if (tmp) {
return tmp + 3;
}
return func_name;
}
static void clean_function_name(char *func_name) {
char *last = (char *)r_str_lchr (func_name, '_');
if (!last || !r_str_isnumber(last + 1)) {
return;
}
*last = '\0';
}
// TODO:
// - symbol names are long and noisy, some of them might not be matched due
// to additional information added around name
R_API R_OWN char *r_type_func_guess(Sdb *TDB, R_NONNULL char *func_name) {
int offset = 0;
char *str = func_name;
char *result = NULL;
char *first;
r_return_val_if_fail (TDB, false);
r_return_val_if_fail (func_name, false);
size_t slen = strlen (str);
if (slen < MIN_MATCH_LEN) {
if (slen < MIN_MATCH_LEN || is_auto_named(str, slen)) {
return NULL;
}
if (slen > 4) { // were name-matching so ignore autonamed
if (!strncmp (str, "fcn.", 4) || !strncmp (str, "loc.", 4)) {
return NULL;
}
}
// strip r2 prefixes (sym, sym.imp, etc')
while (slen > 4 && (offset + 3 < slen) && str[offset + 3] == '.') {
offset += 4;
}
str += offset;
// strip common prefixes from standard lib functions
if (!strncmp (str, "__isoc99_", 9)) {
str += 9;
} else if (!strncmp (str, "__libc_", 7) && !strstr(str,"_main")) {
str += 7;
} else if (!strncmp (str, "__GI_", 5)) {
str += 5;
}
str = strip_r_prefixes(str, slen);
str = strip_common_prefixes_stdlib(str);
str = strip_dll_prefix(str);
if ((result = type_func_try_guess (TDB, str))) {
return result;
}
str = strdup (str);
clean_function_name(str);
if (*str == '_' && (result = type_func_try_guess (TDB, str + 1))) {
free (str);
return result;
}
str = strdup (str);
// Remove func-number from module_func-number
// sym._ExitProcess_4 ==> ExitProcess
char *l = (char *)r_str_lchr (str, '_');
if (l) {
char *tmp = l + 1;
char *first = strchr (str, '_');
while (tmp && IS_DIGIT (*tmp)) {
tmp++;
}
if (tmp && first && !*tmp) {
*l = '\0';
if (*str == '_' && (result = type_func_try_guess (TDB, str + 1))) {
free (str);
return result;
}
}
}
// some names are in format module.dll_function_number, try to remove those
// also try module.dll_function and function_number
if ((first = strstr (str, "dll_"))) {
result = type_func_try_guess (TDB, first + 4);
goto out;
}
out:
free (str);
return result;
}