Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add demangling as plugins and libdemangle as external dependency #1656

Merged
merged 18 commits into from
Oct 1, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -137,3 +137,4 @@ subprojects/packagecache/
subprojects/sdb/
subprojects/tree-sitter-*/
subprojects/zlib-*/
subprojects/libdemangle/
2 changes: 1 addition & 1 deletion librz/bin/bfile.c
Original file line number Diff line number Diff line change
Expand Up @@ -555,7 +555,7 @@ RZ_IPI bool rz_bin_file_set_obj(RzBin *bin, RzBinFile *bf, RzBinObject *obj) {
return false;
}
if (!obj->info->lang) {
obj->info->lang = rz_bin_lang_tostring(obj->lang);
obj->info->lang = rz_bin_language_to_string(obj->lang);
}
}
return true;
Expand Down
172 changes: 170 additions & 2 deletions librz/bin/bin.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
// SPDX-License-Identifier: LGPL-3.0-only

#include <rz_bin.h>
#include <rz_types.h>
#include <rz_demangler.h>
#include <rz_util.h>
#include <rz_lib.h>
#include <rz_io.h>
Expand Down Expand Up @@ -478,6 +478,7 @@ RZ_API void rz_bin_free(RzBin *bin) {
rz_id_storage_free(bin->ids);
rz_event_free(bin->event);
rz_str_constpool_fini(&bin->constpool);
rz_demangler_free(bin->demangler);
free(bin);
}

Expand Down Expand Up @@ -706,9 +707,14 @@ RZ_API RzBin *rz_bin_new(void) {
if (!bin) {
return NULL;
}
if (!rz_str_constpool_init(&bin->constpool)) {
/* demanglers */
bin->demangler = rz_demangler_new();
if (!bin->demangler) {
goto trashbin;
}
if (!rz_str_constpool_init(&bin->constpool)) {
goto trashbin_demangler;
}
bin->event = rz_event_new(bin);
if (!bin->event) {
goto trashbin_constpool;
Expand Down Expand Up @@ -756,7 +762,9 @@ RZ_API RzBin *rz_bin_new(void) {
free(static_ldr_plugin);
}
}

return bin;

trashbin_binldrs:
rz_list_free(bin->binldrs);
trashbin_binxtrs:
Expand All @@ -766,6 +774,8 @@ RZ_API RzBin *rz_bin_new(void) {
rz_event_free(bin->event);
trashbin_constpool:
rz_str_constpool_fini(&bin->constpool);
trashbin_demangler:
rz_demangler_free(bin->demangler);
trashbin:
free(bin);
return NULL;
Expand Down Expand Up @@ -1296,3 +1306,161 @@ RZ_API const RzBinLdrPlugin *rz_bin_ldrplugin_get(RzBin *bin, const char *name)
}
return NULL;
}

static char *bin_demangle_cxx(RzBinFile *bf, const char *symbol, ut64 vaddr) {
XVilka marked this conversation as resolved.
Show resolved Hide resolved
char *out = rz_demangler_cxx(symbol);
if (!out || !bf) {
return out;
}
char *sign = (char *)strchr(out, '(');
if (!sign) {
return out;
}

char *str = out;
char *ptr = NULL;
char *method_name = NULL;
ret2libc marked this conversation as resolved.
Show resolved Hide resolved
for (;;) {
ptr = strstr(str, "::");
if (!ptr || ptr > sign) {
break;
}
method_name = ptr;
str = ptr + 1;
}

if (RZ_STR_ISEMPTY(method_name)) {
return out;
}

*method_name = 0;
RzBinSymbol *sym = rz_bin_file_add_method(bf, out, method_name + 2, 0);
if (sym) {
if (sym->vaddr != 0 && sym->vaddr != vaddr) {
RZ_LOG_INFO("Duplicated method found: %s\n", sym->name);
}
if (sym->vaddr == 0) {
sym->vaddr = vaddr;
}
}
*method_name = ':';
return out;
}

static char *bin_demangle_rust(RzBinFile *binfile, const char *symbol, ut64 vaddr) {
char *str = NULL;
if (!(str = bin_demangle_cxx(binfile, symbol, vaddr))) {
return str;
}
free(str);
return rz_demangler_rust(symbol);
}

/**
* \brief Demangles a symbol based on the language or the RzBinFile data
*
* This function demangles a symbol based on the language or the RzBinFile data
* When a c++ or rust is selected as language, it will add methods into the
* RzBinFile structure based on the demangled symbol.
* When libs is set to true, the demangled symbol will be appended to the
* library name <libname>_<demangled symbol>.
*/
RZ_API RZ_OWN char *rz_bin_demangle(RZ_NULLABLE RzBinFile *bf, RZ_NULLABLE const char *language, RZ_NULLABLE const char *symbol, ut64 vaddr, bool libs) {
if (RZ_STR_ISEMPTY(symbol)) {
return NULL;
}

RzBinLanguage type = RZ_BIN_LANGUAGE_UNKNOWN;
RzBin *bin = bf ? bf->rbin : NULL;
RzBinObject *o = bf ? bf->o : NULL;

if (!language && o && o->info && o->info->lang) {
language = o->info->lang;
}

RzListIter *iter;
const char *lib = NULL;
if (!strncmp(symbol, "reloc.", 6)) {
symbol += 6;
}
if (!strncmp(symbol, "sym.", 4)) {
symbol += 4;
}
if (!strncmp(symbol, "imp.", 4)) {
symbol += 4;
}
if (!strncmp(symbol, "target.", 7)) {
symbol += 7;
}
if (o) {
bool found = false;
rz_list_foreach (o->libs, iter, lib) {
size_t len = strlen(lib);
if (!rz_str_ncasecmp(symbol, lib, len)) {
symbol += len;
if (*symbol == '_') {
symbol++;
}
found = true;
break;
}
}
if (!found) {
lib = NULL;
}
size_t len = strlen(bin->file);
if (!rz_str_ncasecmp(symbol, bin->file, len)) {
lib = bin->file;
symbol += len;
if (*symbol == '_') {
symbol++;
}
}
}

if (RZ_STR_ISEMPTY(symbol)) {
return NULL;
}

if (!strncmp(symbol, "__", 2)) {
if (symbol[2] == 'T') {
type = RZ_BIN_LANGUAGE_SWIFT;
} else {
type = RZ_BIN_LANGUAGE_CXX;
}
}

if (type == RZ_BIN_LANGUAGE_UNKNOWN) {
type = rz_bin_language_to_id(language);
// ignore "with blocks"
type = RZ_BIN_LANGUAGE_MASK(type);
language = rz_bin_language_to_string(type);
}
if (!language) {
return NULL;
}
char *demangled = NULL;
switch (type) {
case RZ_BIN_LANGUAGE_UNKNOWN: return NULL;
case RZ_BIN_LANGUAGE_KOTLIN:
/* fall-thru */
wargio marked this conversation as resolved.
Show resolved Hide resolved
case RZ_BIN_LANGUAGE_GROOVY:
/* fall-thru */
case RZ_BIN_LANGUAGE_DART:
/* fall-thru */
case RZ_BIN_LANGUAGE_JAVA: demangled = rz_demangler_java(symbol); break;
case RZ_BIN_LANGUAGE_OBJC: demangled = rz_demangler_objc(symbol); break;
case RZ_BIN_LANGUAGE_MSVC: demangled = rz_demangler_msvc(symbol); break;
#if WITH_GPL
case RZ_BIN_LANGUAGE_RUST: demangled = bin_demangle_rust(bf, symbol, vaddr); break;
case RZ_BIN_LANGUAGE_CXX: demangled = bin_demangle_cxx(bf, symbol, vaddr); break;
#endif
default: rz_demangler_resolve(bin->demangler, symbol, language, &demangled);
}
if (libs && demangled && lib) {
char *d = rz_str_newf("%s_%s", lib, demangled);
free(demangled);
demangled = d;
}
return demangled;
}
Loading