ccode: prefer radare2's realname when emitting clean identifiers

When e r2ghidra.ccode is enabled, resolve flags to their realname (the
clean import or demangled name radare2 already derives from the binary)
instead of the sym.imp.<lib>_<fn> or mangled flag name. sanitizeCName stays
as the fallback for names with no realname, such as anonymous functions.
This commit is contained in:
Kirby Kuehl authored and pancake committed 2026-10-12 19:18:42 +02:00
1 parent 4138f27e3b
commit 29400ddf78
3 files changed
+11 -7

No files matched your search

+1 -1
View File
@@ -274,7 +274,7 @@ void PcodeFixupPreprocessor::fixupResolvedIndirectCalls(RAnalFunction *r2Func, F
// PE imports are reached through the IAT: `call qword [sym.imp.KERNEL32.dll_WriteFile]`.
// radare2 emits a CALL ref from the call site to the import flag, but pcode still renders
// the call as an indirect dereference `(*_WriteFile)(...)`. Deindirect each such call so
// the decompiler prints a direct `WriteFile(...)`, which C tools (e.g. Semgrep) can match.
// the decompiler prints a direct `WriteFile(...)` instead of an indirect pointer dereference.
void PcodeFixupPreprocessor::fixupImportCallDeindirection(RAnalFunction *r2Func, Funcdata *ghFunc, RCore *core, R2Architecture &arch) {
RVecAnalRef *refs = r_anal_function_get_refs (r2Func);
if (!refs) {
+9 -5
View File
@@ -20,7 +20,7 @@
// flags `sym.imp.<lib>_<fn>` / `imp.<lib>_<fn>` (e.g. `sym.imp.KERNEL32.dll_memcpy`),
// plus `sub.<lib>_<fn>` stubs and anonymous/dotted symbols `fcn.ADDR` / `sym.lib.fn`,
// none of which are legal C identifiers. Map those back to bare symbol names so
// the decompiled C can be parsed by C tools (e.g. Semgrep).
// the emitted C uses only legal identifiers.
static std::string sanitizeCName(const char *raw) {
std::string s = raw? raw : "";
// Import stubs: sub.<lib>_<fn> -> <fn>
@@ -781,10 +781,13 @@ FunctionSymbol *R2Scope::registerFunction(RAnalFunction *fcn) const {
FunctionSymbol *R2Scope::registerFunctionFlag(RFlagItem *flag) const {
RCoreLock core (arch->getCore ());
const char *name = (core->flags->realnames && flag->realname)
// radare2 stores the clean import/demangled name in realname; prefer it over the
// sym.imp.<lib>_<fn> / mangled flag name when requesting clean output.
bool ccode = r_config_get_b (core->config, "r2ghidra.ccode");
const char *name = ((core->flags->realnames || ccode) && flag->realname)
? flag->realname : flag->name;
std::string clean = name;
if (r_config_get_b (core->config, "r2ghidra.ccode")) {
if (ccode) {
clean = sanitizeCName (name);
}
FunctionSymbol *funcsym = cache->addFunction (Address (arch->getDefaultCodeSpace (), flag->addr), clean.c_str ());
@@ -829,9 +832,10 @@ Symbol *R2Scope::registerFlag(RFlagItem *flag) const {
}
// Check whether flags should be displayed by their real name
const char *name = (core->flags->realnames && flag->realname) ? flag->realname : flag->name;
bool ccode = r_config_get_b (core->config, "r2ghidra.ccode");
const char *name = ((core->flags->realnames || ccode) && flag->realname) ? flag->realname : flag->name;
std::string clean = name;
if (r_config_get_b (core->config, "r2ghidra.ccode")) {
if (ccode) {
clean = sanitizeCName (name);
}
+1 -1
View File
@@ -234,7 +234,7 @@ static void Decompile(RCore *core, ut64 addr, DecompileMode mode, std::stringstr
if (cfg_var_ccode.GetBool (core->config)) {
// CCODE-style output: no casts, hide implied ZEXT/SEXT extensions, drop the
// calling convention from prototypes — closer to what Ghidra's toggleCCode
// emits and far more parseable by C tools (Semgrep).
// emits and closer to plain standard C.
auto cc = dynamic_cast<PrintC *>(arch.print);
cc->setNoCastPrinting (true);
cc->setHideImpliedExts (true);