From 957eed5767b17b9e7f713354caa91cb10d612b7e Mon Sep 17 00:00:00 2001 From: pancake Date: Tue, 26 Jul 2022 17:30:15 -0400 Subject: [PATCH] Add r2ghidra.compiler variable to list and use compiler profiles * Honor RBinInfo.compiler and the hardcoded list --- src/ArchMap.cpp | 247 +++++++++++++++++++++++++++++++++++++++++++- src/core_ghidra.cpp | 22 +++- 2 files changed, 264 insertions(+), 5 deletions(-) diff --git a/src/ArchMap.cpp b/src/ArchMap.cpp index 4d62f803..a3fb09a9 100644 --- a/src/ArchMap.cpp +++ b/src/ArchMap.cpp @@ -172,25 +172,264 @@ static const std::map arch_map = { }} }; +#if 0 +Supported compiler profiles. r2 should have a configuration option for that: + +For X86: +* default +* clang +* gcc +* Borland C++ +* Visual Studio +* Delphi + +``` +# list all arch.compiler from ghidra +$ cd ghidra-native +$ git grep 'compiler name=' | grep ldefs| cut -d '"' -f 1,2 |cut -d '/' -f 6- |sed -e 's,",.,' | cut -d . -f1,3|sort -u + +6502.default +68000.default +6805.default +8048.default +8051.Archimedes +8051.default +8085.default +AARCH64.Visual Studio +AARCH64.default +ARM.Visual Studio +ARM.default +AppleSilicon.default +CP1600.default +CR16.default +Dalvik.default +HC05.default +HC08.default +HCS08.default +HCS12.default +JVM.default +MCS96.default +PIC24.default +STM8.default +SparcV9.default +SuperH4.Visual Studio +SuperH4.default +TI_MSP430.default +V850.default +avr32a.default +avr8.gcc +avr8.iarV1 +avr8.imgCraftV8 +hexagon.default +m8c.default +mips.Visual Studio +mips.default +mips.n32 +mips.o32 +mips.o64 +old/v01stuff/toy.default +pa-risc.default +pic12c5xx.default +pic16.default +pic16c5x.default +pic17c7xx.default +pic18.default +ppc.Mac OS X +ppc.Visual Studio +ppc.default +riscv.gcc +superh.default +toy.default +toy.posStack +tricore.default +x86.Borland C++ +x86.Delphi +x86.Visual Studio +x86.clang +x86.default +x86.gcc +z80.default + + +# list all compiler support from ghidra + +$ git grep compiler' name=' | cut -d '"' -f 2|sort -u +Archimedes +Borland C++ +Delphi +Mac OS X +Sleigh-PowerPC 32-bit +Visual Studio +clang +default +gcc +iarV1 +imgCraftV8 +n32 +o32 +o64 +pointer16 +pointer32 +pointer64 +posStack +``` +#endif +const char *ghidraCompilers[] = { + "6502.default", + "68000.default", + "6805.default", + "8048.default", + "8051.Archimedes", + "8051.default", + "8085.default", + "AARCH64.Visual Studio", + "AARCH64.default", + "ARM.Visual Studio", + "ARM.default", + "AppleSilicon.default", + "CP1600.default", + "CR16.default", + "Dalvik.default", + "HC05.default", + "HC08.default", + "HCS08.default", + "HCS12.default", + "JVM.default", + "MCS96.default", + "PIC24.default", + "STM8.default", + "SparcV9.default", + "SuperH4.Visual Studio", + "SuperH4.default", + "TI_MSP430.default", + "V850.default", + "avr32a.default", + "avr8.gcc", + "avr8.iarV1", + "avr8.imgCraftV8", + "hexagon.default", + "m8c.default", + "mips.Visual Studio", + "mips.default", + "mips.n32", + "mips.o32", + "mips.o64", + "old/v01stuff/toy.default", + "pa-risc.default", + "pic12c5xx.default", + "pic16.default", + "pic16c5x.default", + "pic17c7xx.default", + "pic18.default", + "ppc.Mac OS X", + "ppc.Visual Studio", + "ppc.default", + "riscv.gcc", + "superh.default", + "toy.default", + "toy.posStack", + "tricore.default", + "x86.Borland C++", + "x86.Delphi", + "x86.Visual Studio", + "x86.clang", + "x86.default", + "x86.gcc", + "z80.default", + NULL +}; + +static const std::map compiler_alias = { + { "vs", "Visual Studio" }, + { "mach0", "Mac OS X" }, +}; + static const std::map compiler_map = { { "elf", "gcc" }, - { "pe", "windows" }, - { "mach0", "clang" } + { "pe", "Visual Studio" }, + // { "mach0", "clang" }, + { "mach0", "clang" }, }; +std::string findGhidraCompiler(RCore *core, const char *bin_compiler) { + const char *arch = r_config_get (core->config, "asm.arch"); + if (R_STR_ISEMPTY (arch)) { + return std::string("default"); + } + if (!strcmp (arch, "r2ghidra")) { + arch = r_config_get (core->config, "asm.cpu"); + } + + char *a = strdup (arch); + // take arch name by splitting by the dot. + char *dot = strchr (a, '.'); + if (dot) { + *dot = 0; + } + char *b = r_str_newf ("%s.", a); + const char *uc = bin_compiler; // r_config_get (core->config, "r2ghidra.compiler"); + if (!strcmp (uc, "?")) { + for (int i = 0; ghidraCompilers[i]; i++) { + if (r_str_startswith (ghidraCompilers[i], b)) { + const char *c = ghidraCompilers[i] + strlen (b); + r_cons_printf ("%s\n", c); + } + } + free (b); + return std::string("default"); + } + if (R_STR_ISEMPTY (bin_compiler) || !strcmp (uc, "default")) { + bin_compiler = uc; + } + const char *goodcompiler = NULL; + for (int i = 0; ghidraCompilers[i]; i++) { + if (r_str_startswith (ghidraCompilers[i], b)) { + const char *c = ghidraCompilers[i] + strlen (b); + goodcompiler = c; + if (R_STR_ISEMPTY (bin_compiler) || !r_str_casecmp (c, bin_compiler)) { + break; + } + //eprintf ("-> %s\n", c); + } + } + free (b); + free (a); + if (goodcompiler != NULL) { + return std::string(goodcompiler); + } + if (r_str_startswith (arch, "x86")) { + return std::string("gcc"); + } + return std::string("default"); +/* + if (!r_str_startswith (arch, "x86")) { + "x86.Borland C++", + "x86.Delphi", + "x86.Visual Studio", + "x86.clang", + "x86.default", + "x86.gcc", + "z80.default", + } +*/ +} + std::string CompilerFromCore(RCore *core) { if (!core) { return "gcc"; } - RBinInfo *info = r_bin_get_info(core->bin); + RBinInfo *info = r_bin_get_info (core->bin); if (!info || !info->rclass) { return std::string (); } + if (R_STR_ISNOTEMPTY (info->compiler)) { + auto gcompiler = findGhidraCompiler(core, info->compiler); + return std::string(info->compiler); + } auto comp_it = compiler_map.find (info->rclass); if (comp_it == compiler_map.end ()) { return std::string (); } - return comp_it->second; } diff --git a/src/core_ghidra.cpp b/src/core_ghidra.cpp index a87fb64c..a39f353a 100644 --- a/src/core_ghidra.cpp +++ b/src/core_ghidra.cpp @@ -50,7 +50,9 @@ struct ConfigVar { std::vector ConfigVar::vars_all; +std::string findGhidraCompiler(RCore *core, const char *bin_compiler); bool SleighHomeConfig(void *user, void *data); +bool ConfigCompiler(void *user, void *data); static const ConfigVar cfg_var_sleighhome ("sleighhome", "", "SLEIGHHOME", SleighHomeConfig); static const ConfigVar cfg_var_sleighid ("lang", "", "Custom Sleigh ID to override auto-detection (e.g. x86:LE:32:default)"); @@ -67,7 +69,7 @@ static const ConfigVar cfg_var_rawptr ("rawptr", "true", "Show un static const ConfigVar cfg_var_verbose ("verbose", "false", "Show verbose warning messages while decompiling"); static const ConfigVar cfg_var_casts ("casts", "false", "Show type casts where needed"); static const ConfigVar cfg_var_ropropagate ("roprop", "true", "Propagate read-only constants"); - +static const ConfigVar cfg_var_compiler ("compiler", "default", "Select compiler for calling conventions", ConfigCompiler); static std::recursive_mutex decompiler_mutex; @@ -533,6 +535,24 @@ extern "C" int r2ghidra_core_cmd(void *user, const char *input) { return false; } +bool ConfigCompiler(void *user, void *data) { + RCore *core = (RCore *) user; + std::lock_guard lock(decompiler_mutex); + auto node = reinterpret_cast(data); + if (!strcmp (node->value, "?")) { + auto c = findGhidraCompiler (core, node->value); + // eprintf ("list compilers%c", 10); + return false; + } else { + auto c = findGhidraCompiler (core, node->value); + free (node->value); + node->value = strdup (c.c_str()); + // eprintf ("%s%c", c.c_str(), 10); + // print c.c_str() + } + return true; +} + bool SleighHomeConfig(void */* user */, void *data) { std::lock_guard lock(decompiler_mutex); auto node = reinterpret_cast(data);