122 lines
3.3 KiB
C
122 lines
3.3 KiB
C
// SPDX-FileCopyrightText: 2023 RizinOrg <info@rizin.re>
|
|
// SPDX-FileCopyrightText: 2023 deroad <wargio@libero.it>
|
|
// SPDX-License-Identifier: LGPL-3.0-only
|
|
|
|
#include <rz_bin.h>
|
|
#include <rz_util.h>
|
|
|
|
#define skip_prefix_s(s, p) \
|
|
do { \
|
|
if (!strncmp(s, p, strlen(p))) { \
|
|
s += strlen(p); \
|
|
} \
|
|
} while (0)
|
|
|
|
#define skip_prefix_n(s, p, n) \
|
|
do { \
|
|
if (!strncmp(s, p, strlen(p))) { \
|
|
s += n; \
|
|
} \
|
|
} while (0)
|
|
|
|
static const char *get_mangled_name(const char *mangled) {
|
|
if (!mangled || !strncmp(mangled, "__OBJC_$", strlen("__OBJC_$"))) {
|
|
// this is never a mangled name
|
|
return NULL;
|
|
}
|
|
|
|
skip_prefix_n(mangled, "__OBJC_", 1);
|
|
|
|
return RZ_STR_ISEMPTY(mangled) ? NULL : mangled;
|
|
}
|
|
#undef skip_prefix_s
|
|
#undef skip_prefix_n
|
|
|
|
RZ_IPI bool rz_bin_demangle_symbol(RzBinSymbol *bsym, const RzDemanglerPlugin *plugin, RzDemanglerFlag flags, bool force) {
|
|
if (!plugin || (bsym->dname && !force)) {
|
|
return false;
|
|
}
|
|
|
|
const char *mangled = get_mangled_name(bsym->name);
|
|
if (!mangled) {
|
|
return false;
|
|
}
|
|
|
|
free(bsym->dname);
|
|
bsym->dname = plugin->demangle(mangled, flags);
|
|
return bsym->dname != NULL;
|
|
}
|
|
|
|
RZ_IPI bool rz_bin_demangle_import(RzBinImport *import, const RzDemanglerPlugin *plugin, RzDemanglerFlag flags, bool force) {
|
|
if (!plugin || (import->dname && !force)) {
|
|
return false;
|
|
}
|
|
|
|
const char *mangled = get_mangled_name(import->name);
|
|
if (!mangled) {
|
|
return false;
|
|
}
|
|
|
|
char *demangled = plugin->demangle(mangled, flags);
|
|
if (!demangled) {
|
|
return false;
|
|
}
|
|
|
|
free(import->dname);
|
|
import->dname = demangled;
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* \brief Demangles a symbol based on the language or by iterating all demanglers.
|
|
*
|
|
* This function demangles a symbol based on the language or by iterating all demanglers.
|
|
* The iteration of all demanglers is available only if the RzBin pointer is not NULL.
|
|
*
|
|
* \param bin The RzBin context to used for demangling
|
|
* \param language The language to be used for demangling
|
|
* \param mangled The mangled string to be demangled
|
|
* \return On success returns a valid pointer, otherwise NULL.
|
|
*/
|
|
RZ_API RZ_OWN char *rz_bin_demangle(RZ_NULLABLE RzBin *bin, RZ_NULLABLE const char *language, RZ_NULLABLE const char *mangled) {
|
|
if (RZ_STR_ISEMPTY(mangled)) {
|
|
return NULL;
|
|
}
|
|
|
|
RzBinLanguage type = language ? rz_bin_language_to_id(language) : RZ_BIN_LANGUAGE_UNKNOWN;
|
|
type = RZ_BIN_LANGUAGE_MASK(type);
|
|
RzDemanglerFlag flags = bin ? rz_demangler_get_flags(bin->demangler) : RZ_DEMANGLER_FLAG_ENABLE_ALL;
|
|
|
|
switch (type) {
|
|
case RZ_BIN_LANGUAGE_KOTLIN:
|
|
/* fall-thru */
|
|
case RZ_BIN_LANGUAGE_GROOVY:
|
|
/* fall-thru */
|
|
case RZ_BIN_LANGUAGE_DART:
|
|
/* fall-thru */
|
|
case RZ_BIN_LANGUAGE_JAVA:
|
|
return rz_demangler_java(mangled, flags);
|
|
case RZ_BIN_LANGUAGE_OBJC:
|
|
return rz_demangler_objc(mangled, flags);
|
|
case RZ_BIN_LANGUAGE_MSVC:
|
|
return rz_demangler_msvc(mangled, flags);
|
|
case RZ_BIN_LANGUAGE_PASCAL:
|
|
return rz_demangler_pascal(mangled, flags);
|
|
case RZ_BIN_LANGUAGE_RUST:
|
|
return rz_demangler_rust(mangled, flags);
|
|
case RZ_BIN_LANGUAGE_CXX:
|
|
return rz_demangler_cxx(mangled, flags);
|
|
case RZ_BIN_LANGUAGE_DLANG:
|
|
return rz_demangler_dlang(mangled, flags);
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (!bin || RZ_STR_ISEMPTY(language)) {
|
|
return NULL;
|
|
}
|
|
|
|
char *demangled = NULL;
|
|
bool res = rz_demangler_resolve(bin->demangler, mangled, language, &demangled);
|
|
return res ? demangled : NULL;
|
|
}
|