mirror of
https://github.com/radareorg/r2ghidra.git
synced 2026-11-07 06:25:57 -10:00
Migrate the RAnal plugin into the RArch
This commit is contained in:
1 parent
b707fb6b01
commit
0318eeacd4
9 files changed
+354
-126
No files matched your search
@@ -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
@@ -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
@@ -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)
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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 ®name) {
|
||||
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 ®name = sanal->reg_mapping[p->name];
|
||||
const std::string ®type = 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
@@ -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
@@ -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;
|
||||
|
||||
Reference in new issue
Block a user