Optionally use r2 apis instead of pugixml dependency

* --with-rxml / -Duse_rxml
* Not enabled by default, but builds and works fine
* Requires r2-6.1.6
This commit is contained in:
pancake authored and GitHub committed 2026-05-02 21:00:06 +02:00
1 parent 72094a120e
commit 36d15b6617
9 files changed
+220 -35

No files matched your search

+1 -1
View File
@@ -19,7 +19,7 @@ if [ $? = 0 ]; then
fi
else
echo "Running acr..."
acr -p
acr -p || exit 1
fi
V=`./configure -qV | cut -d - -f -1`
meson rewrite kwargs set project / version "$V"
+1
View File
@@ -2,5 +2,6 @@
#define R2GHIDRA_CONFIG_H 1
#define R2GHIDRA_VERSION "@R2GHIDRA_VERSION@"
#define R2GHIDRA_USE_RXML @USE_RXML@
#endif
+2
View File
@@ -13,5 +13,7 @@ R2_CFLAGS=@R2_CFLAGS@
R2_LDFLAGS=@R2_LDFLAGS@
VERSION=@VERSION@
R2GHIDRA_USE_RXML=@USE_RXML@
R2_USER_PLUGINS=@R2_USER_PLUGINS@
R2_LIBR_PLUGINS=@R2_LIBR_PLUGINS@
Vendored
+9 -2
View File
@@ -18,6 +18,7 @@ control_c() {
exit 1
}
trap control_c 2
USE_RXML=0
split_host() {
S="$"
while : ; do
@@ -173,6 +174,10 @@ System types:
--target=TARGET configure for building compilers for TARGET [HOST]
EOF2
printf "
Optional Features:
--with-rxml use r2 apis instead of pugixml
"
printf "
Some influential environment variables:
CXX C++ compiler command
@@ -240,6 +245,7 @@ echo "AUTHOR: pancake"
echo "EMAIL: [email protected]"
echo "LANGS: c++"
echo "PKGCONFIG: r_core r_asm r_anal"
echo "FLAGS: --with-rxml"
exit 0
;;
--cache-file)
@@ -291,6 +297,7 @@ echo "PKGCONFIG: r_core r_asm r_anal"
--mandir)
MANDIR="$value"; ;;
"--with-rxml") USE_RXML="1"; ;;
*) if [ "$value" ]; then eval "`echo $flag2=$value`" ;
else echo ; echo "WARNING: Unknown flag '$flag'." >&2 ; echo ; fi ;;
esac
@@ -308,7 +315,7 @@ parse_options "$1"
shift
done
ENVWORDS="MANDIR DESCRIPTION INFODIR LIBDIR INCLUDEDIR LOCALSTATEDIR ETCDIR SYSCONFDIR DATADIR DOCDIR LIBEXECDIR SBINDIR BINDIR EPREFIX PREFIX SPREFIX TARGET HOST BUILD INSTALL INSTALL_LIB INSTALL_MAN INSTALL_PROGRAM INSTALL_PROGRAM_STRIP INSTALL_DIR INSTALL_SCRIPT INSTALL_DATA HOST_OS HOST_CPU BUILD_OS BUILD_CPU TARGET_OS TARGET_CPU VERSION VERSION_MAJOR VERSION_MINOR VERSION_PATCH VERSION_NUMBER PKGCFG_LIBDIR PKGCFG_INCDIR PKGNAME VPATH CONTACT CONTACT_NAME CONTACT_MAIL CXX CXXFLAGS LDFLAGS HAVE_LANG_CXX CPP HAVE_GIT GIT PKGCONFIG R2_CFLAGS R2_LDFLAGS HAVE_PKGCFG_R_CORE R2ASM_CFLAGS R2ASM_LDFLAGS HAVE_PKGCFG_R_ASM R2ANAL_CFLAGS R2ANAL_LDFLAGS HAVE_PKGCFG_R_ANAL HAVE_R2 R2 R2_PREFIX R2_USER_PLUGINS R2_LIBR_PLUGINS R2GHIDRA_VERSION"
ENVWORDS="MANDIR DESCRIPTION INFODIR LIBDIR INCLUDEDIR LOCALSTATEDIR ETCDIR SYSCONFDIR DATADIR DOCDIR LIBEXECDIR SBINDIR BINDIR EPREFIX PREFIX SPREFIX TARGET HOST BUILD INSTALL INSTALL_LIB INSTALL_MAN INSTALL_PROGRAM INSTALL_PROGRAM_STRIP INSTALL_DIR INSTALL_SCRIPT INSTALL_DATA HOST_OS HOST_CPU BUILD_OS BUILD_CPU TARGET_OS TARGET_CPU VERSION VERSION_MAJOR VERSION_MINOR VERSION_PATCH VERSION_NUMBER PKGCFG_LIBDIR PKGCFG_INCDIR PKGNAME VPATH CONTACT CONTACT_NAME CONTACT_MAIL CXX CXXFLAGS LDFLAGS HAVE_LANG_CXX CPP HAVE_GIT GIT PKGCONFIG R2_CFLAGS R2_LDFLAGS HAVE_PKGCFG_R_CORE R2ASM_CFLAGS R2ASM_LDFLAGS HAVE_PKGCFG_R_ASM R2ANAL_CFLAGS R2ANAL_LDFLAGS HAVE_PKGCFG_R_ANAL HAVE_R2 R2 USE_RXML R2_PREFIX R2_USER_PLUGINS R2_LIBR_PLUGINS R2GHIDRA_VERSION"
create_environ
@@ -559,7 +566,7 @@ do_remove
if [ "$QUIET" = 0 ]; then
echo
echo "Final report:"
for A in VERSION R2_PREFIX PREFIX PKGCONFIG ; do
for A in USE_RXML VERSION R2_PREFIX PREFIX PKGCONFIG ; do
eval VAL="\$${A}"
[ -z "${VAL}" ] && VAL="\"\""
echo " - ${A} = ${VAL}"
+3 -1
View File
@@ -15,6 +15,8 @@ CHKPRG BISON bison
CHKPRG FLEX flex
))
ARG_WITH USE_RXML rxml use r2 apis instead of pugixml ;
EXEC! R2_PREFIX r2 -H R2_PREFIX ;
EXEC! R2_USER_PLUGINS r2 -H R2_USER_PLUGINS ;
EXEC! R2_LIBR_PLUGINS r2 -H R2_LIBR_PLUGINS ;
@@ -23,4 +25,4 @@ R2GHIDRA_VERSION = $VERSION ;
SUBDIRS config.mk config.h Makefile ;
REPORT VERSION R2_PREFIX PREFIX PKGCONFIG ;
REPORT USE_RXML VERSION R2_PREFIX PREFIX PKGCONFIG ;
+12 -3
View File
@@ -3,7 +3,7 @@ project(
['c', 'cpp'],
license : 'LGPL3',
meson_version : '>=0.50.1',
version : '6.1.4',
version : '6.1.4',
default_options : ['c_std=c11', 'cpp_std=c++20']
)
@@ -101,7 +101,15 @@ ghidra_incs = ghidra.get_variable('incs')
libdecomp_static = ghidra.get_variable('libdecomp_static')
slgh_static = ghidra.get_variable('slgh_static')
pugixml = subproject('pugixml').get_variable('pugixml_dep')
r2ghidra_deps = [r_core, zlib]
r2ghidra_cpp_args = []
if get_option('rxml')
r2ghidra_cpp_args += ['-DR2GHIDRA_USE_RXML=1']
else
pugixml = subproject('pugixml').get_variable('pugixml_dep')
r2ghidra_deps += pugixml
r2ghidra_cpp_args += ['-DR2GHIDRA_USE_RXML=0']
endif
r2ghidra_core_sources = [
r2ghidra_sources,
@@ -121,7 +129,8 @@ sleighc_sources = [
r2ghidra_core_plugin = shared_library('core_r2ghidra',
r2ghidra_core_sources,
link_with: libdecomp_static,
dependencies: [r_core, zlib, pugixml],
dependencies: r2ghidra_deps,
cpp_args: r2ghidra_cpp_args,
override_options : ['c_std=c11', 'cpp_std=c++20'],
include_directories: [ghidra_incs, r2ghidra_incdirs],
install: true,
+1
View File
@@ -0,0 +1 @@
option('rxml', type: 'boolean', value: true, description: 'Use radare2 rxml APIs instead of pugixml')
+185 -27
View File
@@ -7,12 +7,15 @@
#endif
#define TEST_UNKNOWN_NODES 0
#define USE_RXML 0 /* only for r2-5.8 */
#ifndef R2GHIDRA_USE_RXML
#define R2GHIDRA_USE_RXML 1
#endif
#include <funcdata.hh>
#include <r_util.h>
#if USE_RXML
#include <r_util/r_xml.h>
#if R2GHIDRA_USE_RXML
#include "r_util/r_xml.h"
#else
#include <pugixml.hpp>
#endif
@@ -46,6 +49,142 @@ struct ParseCodeXMLContext {
}
};
#if R2GHIDRA_USE_RXML
#define ANNOTATOR_RXML_PARAMS RXmlNode *node, ParseCodeXMLContext *ctx, std::vector<RCodeMetaItem> *out
#define ANNOTATOR_RXML [](ANNOTATOR_RXML_PARAMS) -> void
void AnnotateOprefRxml(ANNOTATOR_RXML_PARAMS) {
const char *opref_str = rxml_dom_get_attribute(node, "opref");
if (!opref_str) {
return;
}
ut64 opref = r_num_get(NULL, opref_str);
if (opref == UT64_MAX) {
return;
}
auto opit = ctx->ops.find((uintm)opref);
if (opit == ctx->ops.end()) {
return;
}
auto op = opit->second;
out->emplace_back();
auto &annotation = out->back();
annotation = {};
annotation.type = R_CODEMETA_TYPE_OFFSET;
annotation.offset.offset = op->getAddr().getOffset();
}
void AnnotateFunctionNameRxml(ANNOTATOR_RXML_PARAMS) {
const char *func_name = rxml_dom_child_value(node);
if (!func_name) {
return;
}
RCodeMetaItem annotation = {};
annotation.type = R_CODEMETA_TYPE_FUNCTION_NAME;
const char *opref_str = rxml_dom_get_attribute(node, "opref");
if (!opref_str) {
if (ctx->func->getName() == func_name) {
annotation.reference.name = strdup(ctx->func->getName().c_str());
annotation.reference.offset = ctx->func->getAddress().getOffset();
out->push_back(annotation);
// Code below makes an offset annotation for the function name(for the currently decompiled function)
RCodeMetaItem offsetAnnotation = {};
offsetAnnotation.type = R_CODEMETA_TYPE_OFFSET;
offsetAnnotation.offset.offset = annotation.reference.offset;
out->push_back(offsetAnnotation);
}
return;
}
ut64 opref = r_num_get(NULL, opref_str);
if (opref == UT64_MAX) {
return;
}
auto opit = ctx->ops.find((uintm)opref);
if (opit == ctx->ops.end()) {
return;
}
PcodeOp *op = opit->second;
FuncCallSpecs *call_func_spec = ctx->func->getCallSpecs(op);
if (call_func_spec) {
annotation.reference.name = strdup(call_func_spec->getName().c_str());
annotation.reference.offset = call_func_spec->getEntryAddress().getOffset();
out->push_back(annotation);
}
}
void AnnotateCommentOffsetRxml(ANNOTATOR_RXML_PARAMS) {
const char *off_str = rxml_dom_get_attribute(node, "off");
if (!off_str) {
return;
}
ut64 off = r_num_get(NULL, off_str);
if (off == UT64_MAX) {
return;
}
out->emplace_back();
auto &annotation = out->back();
annotation = {};
annotation.type = R_CODEMETA_TYPE_OFFSET;
annotation.offset.offset = off;
}
void AnnotateColorRxml(ANNOTATOR_RXML_PARAMS);
void AnnotateVariableRxml(ANNOTATOR_RXML_PARAMS);
static const std::map<std::string, std::vector<void (*)(ANNOTATOR_RXML_PARAMS)>> annotators_rxml = {
{ "statement", { AnnotateOprefRxml } },
{ "op", { AnnotateOprefRxml, AnnotateColorRxml } },
{ "comment", { AnnotateCommentOffsetRxml, AnnotateColorRxml } },
{ "variable", { AnnotateVariableRxml, AnnotateColorRxml } },
{ "funcname", { AnnotateFunctionNameRxml, AnnotateColorRxml } },
{ "type", { AnnotateColorRxml } },
{ "syntax", { AnnotateColorRxml } }
};
static void ParseNodeRxml(RXmlNode *node, ParseCodeXMLContext *ctx, std::ostream &stream, RCodeMeta *code) {
if (rxml_dom_is_text(node)) {
char* cleaned = strdup(node->text ? node->text : "");
if (strlen(cleaned) > 1) {
r_str_trim(cleaned);
}
stream << cleaned;
R_FREE(cleaned);
return;
}
std::vector<RCodeMetaItem> annotations;
const char *name = rxml_dom_name(node);
if (name && !strcmp(name, "break")) {
stream << "\n";
int indent = rxml_dom_attr_int(node, "indent", 0);
stream << std::string(indent, ' ');
} else if (name) {
auto it = annotators_rxml.find(name);
if (it != annotators_rxml.end()) {
auto &callbacks = it->second;
for (auto &callback : callbacks) {
callback(node, ctx, &annotations);
}
for (auto &annotation : annotations) {
annotation.start = stream.tellp();
}
}
}
for (RXmlNode *child = rxml_dom_first_child(node); child; child = rxml_dom_next_sibling(child)) {
ParseNodeRxml(child, ctx, stream, code);
}
for (auto &annotation : annotations) {
annotation.end = stream.tellp();
RCodeMetaItem *item = r_codemeta_item_clone(&annotation);
r_codemeta_add_item(code, item);
}
}
#else
#define ANNOTATOR_PARAMS pugi::xml_node node, ParseCodeXMLContext *ctx, std::vector<RCodeMetaItem> *out
#define ANNOTATOR [](ANNOTATOR_PARAMS) -> void
@@ -124,17 +263,23 @@ void AnnotateCommentOffset(ANNOTATOR_PARAMS) {
annotation.type = R_CODEMETA_TYPE_OFFSET;
annotation.offset.offset = off;
}
#endif
/**
* Translate Ghidra's color annotations, which are essentially
* loose token classes of the high level decompiled source code.
**/
#if R2GHIDRA_USE_RXML
void AnnotateColorRxml(ANNOTATOR_RXML_PARAMS) {
int color = rxml_dom_attr_int(node, "color", -1);
#else
void AnnotateColor(ANNOTATOR_PARAMS) {
pugi::xml_attribute attr = node.attribute("color");
if (attr.empty ()) {
return;
}
int color = attr.as_int(-1);
#endif
if (color < 0) {
return;
}
@@ -169,32 +314,9 @@ void AnnotateColor(ANNOTATOR_PARAMS) {
case Emit::syntax_highlight::error_color:
case Emit::syntax_highlight::special_color:
#endif
default:
default:
return;
}
#if 0
std::string color = attr.as_string();
RSyntaxHighlightType type;
if (color == "keyword") {
type = R_SYNTAX_HIGHLIGHT_TYPE_KEYWORD;
} else if (color == "comment") {
type = R_SYNTAX_HIGHLIGHT_TYPE_COMMENT;
} else if (color == "type") {
type = R_SYNTAX_HIGHLIGHT_TYPE_DATATYPE;
} else if (color == "funcname") {
type = R_SYNTAX_HIGHLIGHT_TYPE_FUNCTION_NAME;
} else if (color == "param") {
type = R_SYNTAX_HIGHLIGHT_TYPE_FUNCTION_PARAMETER;
} else if (color == "var") {
type = R_SYNTAX_HIGHLIGHT_TYPE_LOCAL_VARIABLE;
} else if (color == "const") {
type = R_SYNTAX_HIGHLIGHT_TYPE_CONSTANT_VARIABLE;
} else if (color == "global") {
type = R_SYNTAX_HIGHLIGHT_TYPE_GLOBAL_VARIABLE;
} else {
return;
}
#endif
RCodeMetaItem annotation = {};
annotation.type = R_CODEMETA_TYPE_SYNTAX_HIGHLIGHT;
annotation.syntax_highlight.type = type;
@@ -228,6 +350,24 @@ void AnnotateLocalVariable(Symbol *symbol, std::vector<RCodeMetaItem> *out) {
out->push_back (annotation);
}
#if R2GHIDRA_USE_RXML
void AnnotateVariableRxml(ANNOTATOR_RXML_PARAMS) {
const char* varref_str = rxml_dom_get_attribute(node, "varref");
if (!varref_str) {
RXmlNode* parent = rxml_dom_parent(node);
const char *parent_name = rxml_dom_name(parent);
if (parent_name && !strcmp(parent_name, "vardecl")) {
const char* symref_str = rxml_dom_get_attribute(parent, "symref");
if (symref_str) {
ut64 symref = r_num_get(NULL, symref_str);
Symbol *symbol = ctx->symbols[symref];
AnnotateLocalVariable (symbol, out);
}
}
return;
}
ut64 varref = r_num_get(NULL, varref_str);
#else
void AnnotateVariable(ANNOTATOR_PARAMS) {
pugi::xml_attribute attr = node.attribute ("varref");
if (attr.empty ()) {
@@ -241,6 +381,7 @@ void AnnotateVariable(ANNOTATOR_PARAMS) {
return;
}
ut64 varref = attr.as_ullong(UT64_MAX);
#endif
if (varref == UT64_MAX) {
return;
}
@@ -264,6 +405,7 @@ void AnnotateVariable(ANNOTATOR_PARAMS) {
}
}
#if !R2GHIDRA_USE_RXML
static const std::map<std::string, std::vector <void (*)(ANNOTATOR_PARAMS)> > annotators = {
{ "statement", { AnnotateOpref } },
{ "op", { AnnotateOpref, AnnotateColor } },
@@ -345,19 +487,35 @@ static void ParseNode(pugi::xml_node node, ParseCodeXMLContext *ctx, std::ostrea
}
#endif
}
#endif
R_API RCodeMeta *ParseCodeXML(ghidra::Funcdata *func, const char *xml) {
#if R2GHIDRA_USE_RXML
RXmlNode *doc = rxml_dom_parse(xml);
if (!doc) {
return nullptr;
}
#else
pugi::xml_document doc;
if(!doc.load_string (xml, pugi::parse_default | pugi::parse_ws_pcdata)) {
return nullptr;
}
#endif
std::stringstream ss;
RCodeMeta *code = r_codemeta_new("");
if (!code) {
#if R2GHIDRA_USE_RXML
rxml_dom_free(doc);
#endif
return nullptr;
}
ParseCodeXMLContext ctx (func);
#if R2GHIDRA_USE_RXML
ParseNodeRxml (rxml_dom_first_child(doc), &ctx, ss, code);
rxml_dom_free(doc);
#else
ParseNode (doc.child ("function"), &ctx, ss, code);
#endif
std::string str = ss.str ();
code->code = strdup (str.c_str ());
return code;
+6 -1
View File
@@ -25,6 +25,10 @@ R2GHIDRA_SRCS+=SleighInstruction.cpp
R2G_PLUG_SRCS= anal_ghidra.cpp core_ghidra.cpp
R2G_PLUG_SRCS+= anal_ghidra_plugin.o core_ghidra_plugin.o
#R2GHIDRA_USE_RXML?=1
CXXFLAGS+=-DR2GHIDRA_USE_RXML=$(R2GHIDRA_USE_RXML)
ifeq ($(R2GHIDRA_USE_RXML),0)
PUGIXML_HOME=../subprojects/pugixml/src/
PUGIXML_CFLAGS=-I$(PUGIXML_HOME)
PUGIXML_SRCS= $(PUGIXML_HOME)/pugixml.cpp
@@ -35,6 +39,7 @@ $(PUGIXML_OBJS): $(PUGIXML_SRCS)
$(CXX) -c $(R2_LDFLAGS) $(CXXFLAGS) -o $@ $<
CXXFLAGS+=$(PUGIXML_CFLAGS)
endif
# CXXFLAGS+=-DR2GHIDRA_SLEIGHHOME_DEFAULT=\"$(GHIDRA_HOME)\"
R2GHIDRA_OBJS=$(subst .cpp,.o,$(R2GHIDRA_SRCS))
@@ -75,7 +80,7 @@ endif
subprojects-zlib: ../subprojects/zlib/libz.a
clean:
rm -f *.o $(PUGIXML_HOME)/*.o
rm -f *.o $(PUGIXML_OBJS)
rm -f *.o $(GHIDRA_DECOMPILER)/*.o
rm -f $(R2G_CORE_PLUGIN) $(R2G_ASM_PLUGIN) $(R2G_ANAL_PLUGIN) sleighc