Migrate the RAnal plugin into the RArch

This commit is contained in:
pancake authored and GitHub committed 2023-07-09 10:51:17 +02:00
1 parent b707fb6b01
commit 0318eeacd4
9 files changed
+354 -126

No files matched your search

+6
View File
@@ -75,6 +75,12 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Installing radare2 from deb
run: |
wget https://github.com/radareorg/radare2/releases/download/5.8.8/radare2_5.8.8_amd64.deb
wget https://github.com/radareorg/radare2/releases/download/5.8.8/radare2-dev_5.8.8_amd64.deb
sudo dpkg -i *.deb
rm *.deb
- name: Building tars
run: make -C dist/tarball
- name: Uploading balls
+4 -4
View File
@@ -183,10 +183,10 @@ static const std::map<std::string, std::string> compiler_map = {
};
std::string CompilerFromCore(RCore *core) {
if (!core) {
if (core == nullptr) {
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 ();
}
@@ -239,9 +239,9 @@ int ai(RCore *core, std::string cpu, int query) {
const ArchMapper *am = &arch_it->second;
// auto res = arch_it->second.Map(core);
switch (query) {
case R_ANAL_ARCHINFO_MIN_OP_SIZE:
case R_ARCH_INFO_MIN_OP_SIZE:
return am->minopsz;
case R_ANAL_ARCHINFO_MAX_OP_SIZE:
case R_ARCH_INFO_MAX_OP_SIZE:
return am->maxopsz;
// case R_ANAL_ARCHINFO_ALIGN: return am->align; // proc.align;
}
+3 -2
View File
@@ -46,8 +46,9 @@ CFLAGS+=-Wshadow
CFLAGS+=-I$(GHIDRA_DECOMPILER)
CFLAGS+=-I.
# CFLAGS+=-g
CXXFLAGS+=-g
CFLAGS+=-g -ggdb
LDFLAGS+=-g -ggdb
CXXFLAGS+=-g -ggdb
CXXFLAGS+=-std=c++11
CFLAGS+=$(R2_CFLAGS)
+1 -1
View File
@@ -40,7 +40,7 @@ std::string FilenameFromCore(RCore *core) {
R2Architecture::R2Architecture(RCore *core, const std::string &sleigh_id)
: SleighArchitecture (FilenameFromCore (core), sleigh_id.empty () ? SleighIdFromCore (core) : sleigh_id, &std::cout),
coreMutex (core) {
#if 0
#if 1
collectSpecFiles(std::cerr); ///< Gather specification files in normal locations
auto langs = getLanguageDescriptions ();
#endif
+80 -40
View File
@@ -1,18 +1,25 @@
/* r2ghidra - LGPL - Copyright 2020-2021 - FXTi, pancake */
/* r2ghidra - LGPL - Copyright 2020-2023 - FXTi, pancake */
#include "SleighAsm.h"
#include "ArchMap.h"
// define it here because sleighc needs to compile without anal_ghidra.cpp
R_API RCore *Gcore = nullptr;
void SleighAsm::init(const char *cpu, int bits, bool bigendian, RIO *io, RConfig *cfg) {
if (!io) {
throw LowlevelError ("Can't get RIO from RBin");
if (Gcore == nullptr) {
throw LowlevelError ("Can't get RIO from RBin");
}
io = Gcore->io;
cfg = Gcore->config;
}
if (description.empty()) {
/* Initialize sleigh spec files */
scanSleigh (getSleighHome (cfg));
collectSpecfiles ();
}
std::string new_sleigh_id = SleighIdFromSleighAsmConfig (nullptr, cpu, bits, bigendian, description);
std::string new_sleigh_id = SleighIdFromSleighAsmConfig (Gcore, cpu, bits, bigendian, description);
if (!sleigh_id.empty() && sleigh_id == new_sleigh_id) {
return;
}
@@ -151,23 +158,32 @@ static std::unordered_map<std::string, std::string> parseRegisterData(const Elem
*/
void SleighAsm::parseProcConfig(DocumentStorage &store) {
const Element *el = store.getTag ("processor_spec");
if (!el) {
if (el == nullptr) {
throw LowlevelError ("No processor configuration tag found");
}
const List &list(el->getChildren ());
List::const_iterator iter;
XmlDecode decoder(&trans, el);
for (iter = list.begin(); iter != list.end (); iter++) {
const string &elname ((*iter)->getName ());
if (elname == "context_data") {
context.decodeFromSpec (decoder); // , &trans);
} else if (elname == "programcounter") {
pc_name = (*iter)->getAttributeValue ("register");
} else if (elname == "register_data") {
reg_group = parseRegisterData (*iter);
XmlDecode decoder (&trans, el);
uint4 elemId = decoder.openElement (ELEM_PROCESSOR_SPEC);
for (;;) {
uint4 subId = decoder.peekElement();
if(subId == 0) {
break;
}
if (subId == ELEM_PROGRAMCOUNTER) {
decoder.openElement();
pc_name = decoder.readString(ATTRIB_REGISTER);
decoder.closeElement(subId);
} else if (subId == ELEM_CONTEXT_DATA) {
context.decodeFromSpec(decoder);
} else if (subId == ELEM_REGISTER_DATA) {
decoder.openElement();
parseRegisterData(decoder.getCurrentXmlElement());
decoder.closeElement(subId);
} else {
decoder.openElement();
decoder.closeElementSkipping(subId);
}
}
decoder.closeElement(elemId);
}
/*
@@ -243,10 +259,12 @@ void SleighAsm::resolveArch(const string &archid) {
languageindex = -1;
for (size_t i = 0; i < description.size(); i++) {
std::string id = description[i].getId();
// std::string id = description[i].getProcessor();
if (id == archid || id == baseid) {
languageindex = i;
if (description[i].isDeprecated())
if (description[i].isDeprecated()) {
throw LowlevelError ("Language " + baseid + " is deprecated");
}
break;
}
}
@@ -267,6 +285,8 @@ void SleighAsm::scanSleigh(const string &rootpath) {
std::vector<std::string> procdir2;
std::vector<std::string> languagesubdirs;
// /Users/pancake/.local/share/radare2/plugins/r2ghidra_sleigh/
FileManage::scanDirectoryRecursive(ghidradir, ".", rootpath, 2);
FileManage::scanDirectoryRecursive(ghidradir, "Ghidra", rootpath, 2);
size_t i;
for (i = 0; i < ghidradir.size(); i++) {
@@ -309,27 +329,33 @@ void SleighAsm::scanSleigh(const string &rootpath) {
* This function is used to read a SLEIGH .ldefs file.
*/
void SleighAsm::loadLanguageDescription(const string &specfile) {
ifstream s (specfile.c_str ());
ifstream s(specfile.c_str());
if (!s) {
throw LowlevelError ("Unable to open: " + specfile);
throw LowlevelError("Unable to open: " + specfile);
}
Document *doc;
try {
doc = xml_tree (s);
} catch (DecoderError &err) {
throw LowlevelError ("Unable to parse sleigh specfile: " + specfile);
XmlDecode decoder ((const AddrSpaceManager *)0);
try
{
decoder.ingestStream (s);
} catch(DecoderError &err) {
throw LowlevelError("Unable to parse sleigh specfile: " + specfile);
}
Element *el = doc->getRoot();
const List &list(el->getChildren());
List::const_iterator iter;
for (iter = list.begin(); iter != list.end (); iter++) {
if ((*iter)->getName() != "language") {
continue;
uint4 elemId = decoder.openElement(ELEM_LANGUAGE_DEFINITIONS);
for (;;) {
uint4 subId = decoder.peekElement();
if (subId == 0) {
break;
}
if (subId == ELEM_LANGUAGE) {
description.emplace_back ();
description.back ().decode (decoder);
} else {
decoder.openElement ();
decoder.closeElementSkipping (subId);
}
description.push_back(LanguageDescription());
// UHM description.back().decoder(*iter);
}
delete doc;
decoder.closeElement (elemId);
}
/*
@@ -348,15 +374,27 @@ void SleighAsm::collectSpecfiles(void) {
}
}
RConfig *SleighAsm::getConfig(RAsm *a) {
RCore *core = a->num ? (RCore *)(a->num->userptr) : NULL;
return core? core->config: nullptr;
RConfig *SleighAsm::getConfig(RCore *core) {
if (core == nullptr) {
if (Gcore == nullptr) {
throw LowlevelError ("Can't get RCore from RAnal's RCoreBind");
} else {
core = Gcore;
}
}
return core->config;
}
RConfig *SleighAsm::getConfig(RAnal *a) {
RCore *core = a ? (RCore *)a->coreb.core : nullptr;
if (!core)
throw LowlevelError ("Can't get RCore from RAnal's RCoreBind");
if (core == nullptr) {
if (Gcore == nullptr) {
throw LowlevelError ("Can't get RCore from RAnal's RCoreBind");
} else {
core = Gcore;
}
}
return core->config;
}
@@ -378,12 +416,14 @@ std::string SleighAsm::getSleighHome(RConfig *cfg) {
if (cfg) {
r_config_set (cfg, varname, ev);
}
std::string res(ev);
std::string res (ev);
free (ev);
return res;
}
#if R2_VERSION_NUMBER >= 50709
#if R2_VERSION_NUMBER >= 50809
path = r_xdg_datadir ("radare2/plugins/r2ghidra_sleigh");
#elif R2_VERSION_NUMBER >= 50709
path = r_xdg_datadir ("radare2/r2pm/git/ghidra");
#else
path = r_str_home (".local/share/radare2/r2pm/git/ghidra");
+1 -1
View File
@@ -222,7 +222,7 @@ public:
int disassemble(RAnalOp *op, unsigned long long offset);
int genOpcode(PcodeSlg &pcode_slg, Address &addr);
std::vector<R2Reg> getRegs(void);
static RConfig *getConfig(RAsm *a);
static RConfig *getConfig(RCore *c);
static RConfig *getConfig(RAnal *a);
void check(ut64 offset, const ut8 *buf, int len);
};
+186 -36
View File
@@ -21,20 +21,32 @@
#define R_ANAL_ESIL_PARM_REG R_ESIL_PARM_REG
#define R_ANAL_ESIL_OP_TYPE_CUSTOM R_ESIL_OP_TYPE_CUSTOM
#endif
// XXX dont use globals
static SleighAsm *sanal = nullptr;
extern RCore *Gcore;
static char *slid(RCore *core, const char *cpu, int bits, bool be) {
R_LOG_DEBUG ("slid (%s:%d:%d)", cpu, bits, be);
if (core == nullptr) {
core = Gcore;
} else if (Gcore == nullptr) {
Gcore = core;
}
if (sanal == nullptr) {
sanal = new SleighAsm ();
}
if (!strchr (cpu, ':')) {
auto langs = SleighArchitecture::getLanguageDescriptions();
std::string res = SleighIdFromSleighAsmConfig(core, cpu, bits, be, langs);
return strdup (res.c_str());
auto langs = SleighArchitecture::getLanguageDescriptions ();
std::string res = SleighIdFromSleighAsmConfig (core, cpu, bits, be, langs);
return strdup (res.c_str ());
}
return strdup (cpu);
}
static char *slid_arch(RAnal *anal) {
#if R2_VERSION_NUMBER >= 50609
// const char *cp = anal->config->cpu;
const char *cp = anal->config->cpu;
int bi = anal->config->bits;
bool be = anal->config->big_endian;
@@ -57,6 +69,25 @@ static char *slid_arch(RAnal *anal) {
return cpu;
}
#if R2_VERSION_NUMBER >= 50809
extern "C" int archinfo(RArchSession *as, ut32 query) {
r_return_val_if_fail (as, 1);
char *arch = slid_arch (Gcore->anal); // is this initializing sanal global ptr?
if (sanal != nullptr) {
switch (query) {
case R_ARCH_INFO_MAX_OP_SIZE:
return sanal->maxopsz;
case R_ARCH_INFO_MIN_OP_SIZE:
return sanal->minopsz;
case R_ARCH_INFO_CODE_ALIGN:
case R_ARCH_INFO_DATA_ALIGN:
return sanal->alignment;
}
}
return 1;
}
#else
extern "C" int archinfo(RAnal *anal, int query) {
// This is to check if RCore plugin set cpu properly.
r_return_val_if_fail (anal, -1);
@@ -81,6 +112,7 @@ extern "C" int archinfo(RAnal *anal, int query) {
return -1;
}
#endif
static std::vector<std::string> string_split(const std::string &s) {
std::vector<std::string> tokens;
@@ -350,7 +382,6 @@ static ut32 anal_type_XPUSH(RAnal *anal, RAnalOp *anal_op, const std::vector<Pco
continue;
}
out.mem (iter->output->size);
#if R2_VERSION_NUMBER >= 50809
if ((out.reg && sanal->reg_mapping[sanal->sp_name] == out.reg) ||
(out.regdelta && sanal->reg_mapping[sanal->sp_name] == out.regdelta))
@@ -967,7 +998,6 @@ static void sleigh_esil(RAnal *a, RAnalOp *anal_op, ut64 addr, const ut8 *data,
}
break;
}
case CPUI_LOAD:
{
if (iter->input0 && iter->input1 && iter->output) {
@@ -1429,17 +1459,16 @@ static void sleigh_esil(RAnal *a, RAnalOp *anal_op, ut64 addr, const ut8 *data,
#if 0
/* Not in use for now. */
static bool anal_type_NOP(const std::vector<Pcodeop> &Pcodes)
{ // All p-codes have no side affects.
for (auto iter = Pcodes.cbegin(); iter != Pcodes.cend(); iter++)
{
if (iter->type == CPUI_STORE)
static bool anal_type_NOP(const std::vector<Pcodeop> &Pcodes) {
// All p-codes have no side affects.
for (auto iter = Pcodes.cbegin(); iter != Pcodes.cend(); iter++) {
if (iter->type == CPUI_STORE) {
return false;
if (iter->output && !iter->output->is_unique())
}
if (iter->output && !iter->output->is_unique()) {
return false;
}
}
return true;
}
#endif
@@ -1572,7 +1601,7 @@ extern "C" int sleigh_op(RAnal *a, RAnalOp *anal_op, ut64 addr, const ut8 *data,
break;
case FlowType::CONDITIONAL_COMPUTED_CALL:
{
char *reg = getIndirectReg(ins, isRefed);
char *reg = getIndirectReg (ins, isRefed);
if (reg) {
if (isRefed) {
anal_op->ireg = reg;
@@ -1612,7 +1641,7 @@ extern "C" int sleigh_op(RAnal *a, RAnalOp *anal_op, ut64 addr, const ut8 *data,
break;
}
default:
throw LowlevelError("Unexpected FlowType occured in sleigh_op.");
throw LowlevelError("Unexpected FlowType occured in sleigh_op");
}
} else {
anal_type (a, anal_op, pcode_slg, assem);
@@ -1669,19 +1698,19 @@ extern "C" int sleigh_op(RAnal *a, RAnalOp *anal_op, ut64 addr, const ut8 *data,
std::cerr << " dst: ";
char *tmp = r_anal_value_to_string (anal_op->dst);
std::cerr << tmp;
free(tmp);
free (tmp);
}
if (anal_op->src[0]) {
std::cerr << " in0: ";
char *tmp = r_anal_value_to_string (anal_op->src[0]);
std::cerr << tmp;
free(tmp);
free (tmp);
}
if (anal_op->src[1]) {
std::cerr << " in1: ";
char *tmp = r_anal_value_to_string (anal_op->src[1]);
std::cerr << tmp;
free(tmp);
free (tmp);
}
#endif
std::cerr << std::endl;
@@ -1703,6 +1732,22 @@ extern "C" int sleigh_op(RAnal *a, RAnalOp *anal_op, ut64 addr, const ut8 *data,
}
}
#if R2_VERSION_NUMBER >= 50809
extern "C" bool sleigh_decode(RArchSession *as, RAnalOp *aop, RArchDecodeMask mask) {
REsil *esil = as->arch->esil;
RIO *io = Gcore->io;
RBin *bin = Gcore->bin;
RAnal *anal = Gcore->anal;
if (bin != nullptr && esil != nullptr) {
io = bin->iob.io;
anal = esil->anal;
// sanal->init (cpu, bi, be, anal? anal->iob.io: nullptr, SleighAsm::getConfig (anal));
}
return sleigh_op (anal, aop, aop->addr, aop->bytes, aop->size, (RAnalOpMask)mask) > 0;
}
#endif
/*
* By 2020-05-24, there are 17 kinds of group of registers in SLEIGH.
* I map them to r_reg.h's RRegisterType:
@@ -1896,17 +1941,17 @@ static std::string regtype_name(const char *cpu, const std::string &regname) {
return "gpr";
}
extern "C" char *get_reg_profile(RAnal *anal) {
r_return_val_if_fail (anal, nullptr);
#if R2_VERSION_NUMBER >= 50609
const char *cpu = anal->config->cpu;
#else
const char *cpu = anal->cpu;
#endif
#if R2_VERSION_NUMBER >= 50809
extern "C" char *r2ghidra_regs(RArchSession *as) {
r_return_val_if_fail (as, nullptr);
const char *cpu = r_config_get (Gcore->config, "asm.cpu"); // (as->config != nullptr)? as->config->cpu: "arm";
if (R_STR_ISEMPTY (cpu)) {
return nullptr;
}
char *sa = slid_arch (anal);
// slid-arch finds and initializes the plugin, needs a better name
char *sa = slid_arch (Gcore->anal);
if (!sa) {
return nullptr;
}
@@ -1924,11 +1969,9 @@ extern "C" char *get_reg_profile(RAnal *anal) {
<< p->offset << "\t" << "0\n";
continue;
}
for (size_t i = 0;; i++) {
if (!r_reg_type_arr[i]) {
eprintf ("anal_ghidra.cpp:get_reg_profile() -> Unexpected register group(%s) from SLEIGH, abort.",
group.c_str());
R_LOG_WARN ("Unexpected register group(%s) from SLEIGH, abort", group.c_str());
return nullptr;
}
if (group == r_reg_type_arr[i]) {
@@ -1966,6 +2009,77 @@ extern "C" char *get_reg_profile(RAnal *anal) {
return strdup (res.c_str ());
}
#else
extern "C" char *get_reg_profile(RAnal *anal) {
r_return_val_if_fail (anal, nullptr);
#if R2_VERSION_NUMBER >= 50609
const char *cpu = anal->config->cpu;
#else
const char *cpu = anal->cpu;
#endif
if (R_STR_ISEMPTY (cpu)) {
return nullptr;
}
char *sa = slid_arch (anal);
if (!sa) {
return nullptr;
}
free (sa);
auto reg_list = sanal->getRegs();
std::stringstream buf;
for (auto p = reg_list.begin(); p != reg_list.end(); p++) {
const std::string &group = sanal->reg_group[p->name];
const std::string &regname = sanal->reg_mapping[p->name];
const std::string &regtype = regtype_name (cpu, regname);
if (group.empty()) {
buf << regtype << "\t" << regname << "\t." << p->size * 8 << "\t"
<< p->offset << "\t" << "0\n";
continue;
}
for (size_t i = 0;; i++) {
if (!r_reg_type_arr[i]) {
R_LOG_WARN ("Unexpected register group(%s) from SLEIGH, abort", group.c_str());
return nullptr;
}
if (group == r_reg_type_arr[i]) {
buf << r_reg_string_arr[i] << '\t';
break;
}
}
buf << sanal->reg_mapping[p->name] << "\t." << p->size * 8 << "\t" << p->offset << "\t" << "0\n";
}
if (!sanal->pc_name.empty()) {
buf << "=PC\t" << sanal->reg_mapping[sanal->pc_name] << '\n';
}
if (!sanal->sp_name.empty()) {
buf << "=SP\t" << sanal->reg_mapping[sanal->sp_name] << '\n';
}
for (unsigned i = 0; i != sanal->arg_names.size() && i <= 9; i++) {
buf << "=A" << i << '\t' << sanal->reg_mapping[sanal->arg_names[i]] << '\n';
}
for (unsigned i = 0; i != sanal->ret_names.size() && i <= 3; i++) {
buf << "=R" << i << '\t' << sanal->reg_mapping[sanal->ret_names[i]] << '\n';
}
ut64 pp = 0;
string arch = sanal->sleigh_id.substr(pp, sanal->sleigh_id.find (':', pp) - pp);
pp = sanal->sleigh_id.find (':', pp) + 1;
bool little = sanal->sleigh_id.substr(pp, sanal->sleigh_id.find (':', pp) - pp) == "LE";
pp = sanal->sleigh_id.find (':', pp) + 1;
int bits = std::stoi (sanal->sleigh_id.substr(pp, sanal->sleigh_id.find (':', pp) - pp));
pp = sanal->sleigh_id.find (':', pp) + 1;
append_hardcoded_regs (buf, arch, little, bits);
const std::string &res = buf.str ();
// fprintf(stderr, "%s\n", res.c_str());
return strdup (res.c_str ());
}
#endif
#define ERR(x) \
if (esil->verbose) { \
eprintf ("%s\n", x); \
@@ -2010,9 +2124,8 @@ static bool sleigh_esil_consts_pick(RAnalEsil *esil) {
goto end;
}
ret = true;
end:
free(idx);
free (idx);
return ret;
}
@@ -2020,7 +2133,6 @@ static bool sleigh_esil_popcount(RAnalEsil *esil) {
bool ret = false;
ut64 s, res = 0;
char *src = r_anal_esil_pop (esil);
if (src) {
if (src && r_anal_esil_get_parm (esil, src, &s)) {
while (s) {
@@ -2035,10 +2147,10 @@ static bool sleigh_esil_popcount(RAnalEsil *esil) {
} else {
ERR ("sleigh_esil_popcount: fail to get element from stack.");
}
return ret;
}
extern "C" int esil_sleigh_init(RAnalEsil *esil) {
if (!esil) {
return false;
@@ -2049,7 +2161,7 @@ extern "C" int esil_sleigh_init(RAnalEsil *esil) {
return true;
}
extern "C" int sanal_init(void *p) {
extern "C" bool sanal_init(void *p) {
if (sanal == nullptr) {
sanal = new SleighAsm ();
}
@@ -2057,11 +2169,30 @@ extern "C" int sanal_init(void *p) {
}
extern "C" int esil_sleigh_fini(RAnalEsil *esil) {
//float_mem.clear();
// float_mem.clear();
return true;
}
extern "C" int sanal_fini(void *p) {
#if R2_VERSION_NUMBER >= 50809
extern "C" bool r2ghidra_esilcb(RArchSession *as, RArchEsilAction action) {
REsil *esil = as->arch->esil;
if (!esil) {
R_LOG_ERROR ("esil is null");
return false;
}
switch (action) {
case R_ARCH_ESIL_INIT:
return esil_sleigh_init (esil);
case R_ARCH_ESIL_FINI:
return esil_sleigh_fini (esil);
default:
R_LOG_WARN ("Unhandled ArchEsil action");
break;
}
}
#endif
extern "C" bool sanal_fini(void *p) {
if (sanal) {
delete sanal;
sanal = nullptr;
@@ -2069,6 +2200,24 @@ extern "C" int sanal_fini(void *p) {
return true;
}
#if R2_VERSION_NUMBER >= 50809
extern "C" RList *r2ghidra_preludes(RArchSession *as) {
RListIter *iter;
void *_plugin;
const char *cpu = as->config->cpu;
// reuse r2 preludes
if (R_STR_ISEMPTY (cpu)) {
return NULL;
}
r_list_foreach (as->arch->plugins, iter, _plugin) {
RArchPlugin *plugin = (RArchPlugin*)_plugin;
if (plugin->meta.name && !strcmp (plugin->meta.name, cpu)) {
return plugin->preludes (as);
}
}
return NULL;
}
#else
extern "C" RList *anal_preludes(RAnal *anal) {
RListIter *iter;
void *_plugin;
@@ -2089,3 +2238,4 @@ extern "C" RList *anal_preludes(RAnal *anal) {
}
return NULL;
}
#endif
+42 -20
View File
@@ -1,20 +1,54 @@
/* r2ghidra - LGPL - Copyright 2020-2022 - pancake */
/* r2ghidra - LGPL - Copyright 2020-2023 - pancake */
#include <r_lib.h>
#include <r_anal.h>
#include <r_arch.h>
#if R2_VERSION_NUMBER >= 50709
#define RAnalEsil REsil
#endif
extern int sanal_init(void *p);
extern int sanal_fini(void *p);
extern int archinfo(RAnal *anal, int query);
extern int sleigh_op(RAnal *a, RAnalOp *anal_op, ut64 addr, const ut8 *data, int len, RAnalOpMask mask);
extern char *get_reg_profile(RAnal *anal);
extern int esil_sleigh_fini(RAnalEsil *esil);
extern int esil_sleigh_init(RAnalEsil *esil);
extern bool sanal_init(void *p);
extern bool sanal_fini(void *p);
extern int archinfo(RArchSession *as, ut32 query);
extern RList *anal_preludes(RAnal *anal);
#if R2_VERSION_NUMBER >= 50809
extern RList *r2ghidra_preludes(RArchSession *as);
extern char *r2ghidra_regs(RArchSession *as);
extern bool r2ghidra_esilcb(RArchSession *as, RArchEsilAction action);
// extern bool sleigh_decode(RArchSession *as, RAnal *a, RAnalOp *anal_op, ut64 addr, const ut8 *data, int len, RAnalOpMask mask);
extern char *get_reg_profile(RAnal *anal);
static bool sleigh_decode(RArchSession *as, RAnalOp *op, RArchDecodeMask mask);
RArchPlugin r_arch_plugin_ghidra = {
.meta = {
.name = "r2ghidra",
.desc = "SLEIGH Disassembler from Ghidra",
.license = "GPL3",
.author = "FXTi, pancake",
.version = R2_VERSION,
},
.arch = "sleigh",
.endian = R_SYS_ENDIAN_LITTLE | R_SYS_ENDIAN_BIG,
.cpus = "6502,6805,8051,arm,avr,cr16,dalvik,hppa,java,m68k,m8c,mips,mcs96,msp430,pic24,ppc,sh,sparc,stm8,tricore,toy,v850,wasm,x86,z80",
.bits = 0,
.init = &sanal_init,
.fini = &sanal_fini,
.info = &archinfo,
.preludes = r2ghidra_preludes,
.decode = &sleigh_decode,
.regs = &r2ghidra_regs,
.esilcb = r2ghidra_esilcb,
.mnemonics = NULL,
};
#else
extern RList *r2ghidra_preludes(RAnal *anal);
extern char *get_reg_profile(RAnal *anal);
extern int sleigh_op(RAnal *a, RAnalOp *anal_op, ut64 addr, const ut8 *data, int len, RAnalOpMask mask);
extern int esil_sleigh_fini(RAnalEsil *esil);
extern int esil_sleigh_init(RAnalEsil *esil);
RAnalPlugin r_anal_plugin_ghidra = {
.name = "r2ghidra",
.desc = "SLEIGH Disassembler from Ghidra",
@@ -41,16 +75,4 @@ RAnalPlugin r_anal_plugin_ghidra = {
.mnemonics = NULL,
#endif
};
#if 0
#ifndef CORELIB
R_API RLibStruct radare_plugin = {
.type = R_LIB_TYPE_ANAL,
.data = &r_anal_plugin_ghidra,
.version = R2_VERSION,
.pkgname = "r2ghidra"
};
#endif
#endif
+31 -22
View File
@@ -18,12 +18,14 @@
#include "R2PrintC.h"
#include <r_core.h>
#include <r_arch.h>
#include <vector>
#include <mutex>
#undef DEBUG_EXCEPTIONS
extern "C" RCore *Gcore;
typedef bool (*ConfigVarCb)(void *user, void *data);
@@ -54,23 +56,24 @@ std::vector<const ConfigVar *> ConfigVar::vars_all;
bool SleighHomeConfig(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)");
static const ConfigVar cfg_var_anal ("vars", "false", "Honor local variable / argument analysis from r2 (may cause segfaults if enabled)");
static const ConfigVar cfg_var_cmt_cpp ("cmt.cpp", "true", "C++ comment style");
static const ConfigVar cfg_var_cmt_indent ("cmt.indent", "4", "Comment indent");
#define CV static const ConfigVar
CV cfg_var_sleighhome ("sleighhome", "", "SLEIGHHOME", SleighHomeConfig);
CV cfg_var_sleighid ("lang", "", "Custom Sleigh ID to override auto-detection (e.g. x86:LE:32:default)");
CV cfg_var_anal ("vars", "false", "Honor local variable / argument analysis from r2 (may cause segfaults if enabled)");
CV cfg_var_cmt_cpp ("cmt.cpp", "true", "C++ comment style");
CV cfg_var_cmt_indent ("cmt.indent", "4", "Comment indent");
#if 0
static const ConfigVar cfg_var_nl_brace ("nl.brace", "false", "Newline before opening '{'");
static const ConfigVar cfg_var_nl_else ("nl.else", "false", "Newline before else");
CV cfg_var_nl_brace ("nl.brace", "false", "Newline before opening '{'");
CV cfg_var_nl_else ("nl.else", "false", "Newline before else");
#endif
static const ConfigVar cfg_var_indent ("indent", "4", "Indent increment");
static const ConfigVar cfg_var_linelen ("linelen", "120", "Max line length");
static const ConfigVar cfg_var_maximplref ("maximplref", "2", "Maximum number of references to an expression before showing an explicit variable.");
static const ConfigVar cfg_var_rawptr ("rawptr", "true", "Show unknown globals as raw addresses instead of variables");
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", "0", "Propagate read-only constants (0,1,2,3,4)");
static const ConfigVar cfg_var_timeout ("timeout", "0", "Run decompilation in a separate process and kill it after a specific time");
CV cfg_var_indent ("indent", "4", "Indent increment");
CV cfg_var_linelen ("linelen", "120", "Max line length");
CV cfg_var_maximplref ("maximplref", "2", "Maximum number of references to an expression before showing an explicit variable.");
CV cfg_var_rawptr ("rawptr", "true", "Show unknown globals as raw addresses instead of variables");
CV cfg_var_verbose ("verbose", "false", "Show verbose warning messages while decompiling");
CV cfg_var_casts ("casts", "false", "Show type casts where needed");
CV cfg_var_roprop ("roprop", "0", "Propagate read-only constants (0,1,2,3,4)");
CV cfg_var_timeout ("timeout", "0", "Run decompilation in a separate process and kill it after a specific time");
static std::recursive_mutex decompiler_mutex;
@@ -149,7 +152,7 @@ static void Decompile(RCore *core, ut64 addr, DecompileMode mode, std::stringstr
R2Architecture arch (core, cfg_var_sleighid.GetString (core->config));
DocumentStorage store = DocumentStorage ();
arch.max_implied_ref = cfg_var_maximplref.GetInt (core->config);
arch.readonlypropagate = cfg_var_ropropagate.GetBool (core->config);
arch.readonlypropagate = cfg_var_roprop.GetBool (core->config);
arch.setRawPtr (cfg_var_rawptr.GetBool (core->config));
arch.init (store);
@@ -444,7 +447,7 @@ static void SetInitialSleighHome(RConfig *cfg) {
std::string path = SleighAsm::getSleighHome (cfg);
cfg_var_sleighhome.Set (cfg, path.c_str ());
} catch (LowlevelError &err) {
// eprintf ("Cannot find detfaault paz%c", 10);
// eprintf ("Cannot find sleigh in the default path\n");
}
}
@@ -548,7 +551,7 @@ static void _cmd(RCore *core, const char *input) {
if (pid == 0) {
runcmd (core, input);
r_cons_flush ();
fflush(stdout);
fflush (stdout);
write (fds[1], "\x12", 1);
exit (0);
} else {
@@ -598,20 +601,26 @@ bool SleighHomeConfig(void */* user */, void *data) {
SleighArchitecture::shutdown();
SleighArchitecture::specpaths = FileManage ();
if (R_STR_ISNOTEMPTY (node->value)) {
SleighArchitecture::scanForSleighDirectories(node->value);
SleighArchitecture::scanForSleighDirectories (node->value);
}
return true;
}
// TODO: should be an arch plugin
#if R2_VERSION_NUMBER >= 50809
extern "C" RArchPlugin r_arch_plugin_ghidra;
#else
extern "C" RAnalPlugin r_anal_plugin_ghidra;
#endif
extern "C" int r2ghidra_core_init(void *user, const char *cmd) {
std::lock_guard<std::recursive_mutex> lock(decompiler_mutex);
startDecompilerLibrary (nullptr);
auto *rcmd = reinterpret_cast<RCmd *>(user);
auto *core = reinterpret_cast<RCore *>(rcmd->data);
#if R2_VERSION_NUMBER < 50809
Gcore = core;
#if R2_VERSION_NUMBER >= 50809
r_arch_plugin_add (core->anal->arch, &r_arch_plugin_ghidra);
#else
r_anal_add (core->anal, &r_anal_plugin_ghidra);
#endif
RConfig *cfg = core->config;