Build as a static r2plugin with tcc in the CI

This commit is contained in:
pancake authored and pancake committed 2026-01-19 21:23:06 +01:00
1 parent 605334bf21
commit cd30d40b73
12 files changed
+124 -90

No files matched your search

+1 -1
View File
@@ -55,7 +55,7 @@ jobs:
release:
name: Create release and upload tarball
runs-on: ubuntu-latest
needs: build
needs: [build]
if: needs.build.outputs.tag != ''
steps:
+49
View File
@@ -0,0 +1,49 @@
name: CI
env:
R2V: 6.0.8
permissions:
contents: write
on:
push:
workflow_dispatch: {}
jobs:
tcc-r2git:
name: Test unified r2plugin with TinyCC
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Checkout TinyCC repository
run: |
git clone https://github.com/TinyCC/tinycc
cd tinycc
git checkout mob
git reset --hard 4fccaf61241a5eb72b0777b3a44bd7abbea48604
sh ./configure --prefix=/usr
make -j
sudo make install
- name: Build radare2 from git with TCC
run: |
git clone --depth=1 https://github.com/radareorg/radare2.git
cd radare2
echo core.r2hermes > libr/xps/static.cfg
export CC=tcc
cp -f ../r2plugin/config.mk libr/xps/config.mk
git clone .. libr/xps/p/r2hermes
make -C libr/xps/p/r2hermes include/hbc/version.h
make -C libr/xps/p/r2hermes
make -C libr/xps
./configure --prefix=/usr --with-compiler=tcc
make -j
sudo make install
- name: Test if r2plugin is available
run: |
r2 -q -c La~hbc -c Lb~hbc -c Lc~hbc -- | grep -E "(core|arch|bin).*hbc"
+1
View File
@@ -17,6 +17,7 @@ PARSERS_SRC = $(wildcard $(SRC_DIR)/parsers/*.c)
DISASM_SRC = $(wildcard $(SRC_DIR)/disassembly/*.c)
DECOMPILE_SRC = $(wildcard $(SRC_DIR)/decompilation/*.c)
OPCODES_SRC = $(filter-out $(SRC_DIR)/opcodes/%.inc.c,$(wildcard $(SRC_DIR)/opcodes/*.c))
# TODO: data provider must be refactored into struct with callbacks, right now we just move it away from libhbc to solve build problems
DATA_PROVIDER_SRC = $(SRC_DIR)/data_provider_file.c $(SRC_DIR)/data_provider_buffer.c
LIB_SRC = $(UTILS_SRC) $(PARSERS_SRC) $(DISASM_SRC) $(DECOMPILE_SRC) $(OPCODES_SRC) $(DATA_PROVIDER_SRC) \
$(SRC_DIR)/hbc.c $(SRC_DIR)/opcodes/encoder.c $(SRC_DIR)/opcodes/decoder.c $(SRC_DIR)/r2.c
+17 -31
View File
@@ -153,13 +153,14 @@ HBC *hbc_new_buf(const u8 *data, size_t size);
* Returns NULL if bf is NULL or invalid.
*/
typedef struct r_bin_file_t RBinFile;
HBC *hbc_new_r2(RBinFile *bf);
HBC *r2_hbc_new_r2(RBinFile *bf);
/**
* Free a provider and all associated resources.
* After this call, all pointers returned by provider queries are invalid.
*/
void hbc_free(HBC *provider);
void r2_hbc_free(HBC *provider);
/* ============================================================================
* Query Methods - Access parsed binary data
@@ -168,16 +169,14 @@ void hbc_free(HBC *provider);
/**
* Get the HBC file header.
*/
Result hbc_hdr(
HBC *provider,
HBCHeader *out);
Result hbc_hdr(HBC *provider, HBCHeader *out);
Result r2_hbc_hdr(HBC *provider, HBCHeader *out);
/**
* Get the total number of functions in the binary.
*/
Result hbc_func_count(
HBC *provider,
u32 *out_count);
Result hbc_func_count(HBC *provider, u32 *out_count);
Result r2_hbc_func_count(HBC *provider, u32 *out_count);
/**
* Function metadata structure
@@ -192,42 +191,32 @@ typedef struct {
/**
* Get metadata for a specific function.
*/
Result hbc_func_info(
HBC *provider,
u32 function_id,
HBCFunc *out);
Result hbc_func_info(HBC *provider, u32 function_id, HBCFunc *out);
Result r2_hbc_func_info(HBC *provider, u32 function_id, HBCFunc *out);
/**
* Get the total number of strings in the binary.
*/
Result hbc_str_count(
HBC *provider,
u32 *out_count);
Result hbc_str_count(HBC *provider, u32 *out_count);
Result r2_hbc_str_count(HBC *provider, u32 *out_count);
/**
* Get a string by index.
*/
Result hbc_str(
HBC *provider,
u32 string_id,
const char **out_str);
Result hbc_str(HBC *provider, u32 string_id, const char **out_str);
Result r2_hbc_str(HBC *provider, u32 string_id, const char **out_str);
/**
* Get metadata for a string (offset, length, kind).
*/
Result hbc_str_meta(
HBC *provider,
u32 string_id,
HBCStringMeta *out);
Result hbc_str_meta(HBC *provider, u32 string_id, HBCStringMeta *out);
Result r2_hbc_str_meta(HBC *provider, u32 string_id, HBCStringMeta *out);
/**
* Get the raw bytecode bytes for a function.
*/
Result hbc_bytecode(
HBC *provider,
u32 function_id,
const u8 **out_ptr,
u32 *out_size);
Result hbc_bytecode(HBC *provider, u32 function_id, const u8 **out_ptr, u32 *out_size);
Result r2_hbc_bytecode(HBC *provider, u32 function_id, const u8 **out_ptr, u32 *out_size);
/**
* String table data.
@@ -239,10 +228,7 @@ typedef struct {
u64 string_storage_offset;
} HBCStrs;
Result hbc_str_tbl(
HBC *provider,
HBCStrs *out);
Result hbc_str_tbl(HBC *provider, HBCStrs *out);
/**
* Get source/module name associated with a function.
*/
+10
View File
@@ -0,0 +1,10 @@
EXTERNAL_PLUGINS+=r2hermes
# EXTERNAL_PLUGINS+=hi
.PHONY: r2hermes
r2hermes: p/r2hermes
p/r2hermes:
cd p && git clone https://github.com/radareorg/r2hermes
cd p/r2hermes && git checkout r2plugone
+1 -1
View File
@@ -1,6 +1,6 @@
HBC_CORE_WD=$(LIBR)/xps/p/r2hermes
CFLAGS+=-I$(HBC_CORE_WD)/include
HBC_CORE_OBJ=$(HBC_CORE_WD)/src/r2/core_hbc.o
HBC_CORE_OBJ=$(HBC_CORE_WD)/src/r2/core_hbc_one.o
HBC_CORE_OBJ+=$(HBC_CORE_WD)/src/r2/data_provider_r2.o
LDFLAGS+=$(HBC_CORE_WD)/build/libhbc.a
EXTERNAL_STATIC_OBJS+=$(HBC_CORE_OBJ)
+3 -2
View File
@@ -56,7 +56,8 @@ HERMES_LIB = $(HERMES_LIB_DIR)/libhbc.a
HERMES_LIB_NO_FILE_PROVIDER = $(HERMES_LIB_DIR)/libhbc_nofile.a
# All targets
ALL_TARGETS = $(ARCH_PLUGIN) $(BIN_PLUGIN) $(ASM_PLUGIN) $(CORE_PLUGIN) $(CORE_ONE_PLUGIN)
ALL_TARGETS = $(ARCH_PLUGIN) $(BIN_PLUGIN) $(ASM_PLUGIN) $(CORE_PLUGIN)
# $(CORE_ONE_PLUGIN)
.PHONY: all clean install help check-r2 r2one
@@ -147,7 +148,7 @@ user-install:
cp -f $(BIN_PLUGIN) $(R2_PLUGDIR)
cp -f $(ASM_PLUGIN) $(R2_PLUGDIR)
cp -f $(CORE_PLUGIN) $(R2_PLUGDIR)
cp -f $(CORE_ONE_PLUGIN) $(R2_PLUGDIR)
# cp -f $(CORE_ONE_PLUGIN) $(R2_PLUGDIR)
user-uninstall:
rm -f $(R2_PLUGDIR)/$(ARCH_PLUGIN)
+2 -2
View File
@@ -508,7 +508,7 @@ static bool decode(RArchSession *s, RAnalOp *op, RArchDecodeMask mask) {
return true;
}
static int info(RArchSession *s, ut32 q) {
static int archinfo(RArchSession *s, ut32 q) {
(void)s;
switch (q) {
case R_ARCH_INFO_CODE_ALIGN:
@@ -642,7 +642,7 @@ const RArchPlugin r_arch_plugin_r2hermes = {
.decode = &decode,
.encode = &encode,
.regs = regs,
.info = info,
.info = archinfo,
.mnemonics = mnemonics,
.init = init,
.fini = fini,
+5 -5
View File
@@ -1,4 +1,4 @@
/* radare2 - LGPL - Copyright 2025 - pancake */
/* radare2 - LGPL - Copyright 2025-2026 - pancake */
#include <r_bin.h>
#include <hbc/hbc.h>
@@ -128,7 +128,7 @@ static void fill_info(RBinInfo *ret, const char *file_path, bool has_version, ut
ret->cpu = has_version? r_str_newf ("%u", version): strdup ("unknown");
}
static RBinInfo *info(RBinFile *bf) {
static RBinInfo *bininfo(RBinFile *bf) {
RBinInfo *ret = R_NEW0 (RBinInfo);
bool has_version = false;
ut32 version = 0;
@@ -300,14 +300,14 @@ static RList *strings(RBinFile *bf) {
return ret;
}
RBinPlugin r_bin_plugin_r2hermes = {
const RBinPlugin r_bin_plugin_r2hermes = {
.meta = {
.name = "hbc.bin",
.author = "pancake",
.desc = "Hermes bytecode format",
.license = "BSD",
},
.info = &info,
.info = &bininfo,
.load = &load,
.destroy = &destroy,
.check = &check,
@@ -321,7 +321,7 @@ RBinPlugin r_bin_plugin_r2hermes = {
#ifndef R2_PLUGIN_INCORE
R_API RLibStruct radare_plugin = {
.type = R_LIB_TYPE_BIN,
.data = &r_bin_plugin_r2hermes,
.data = (void*)&r_bin_plugin_r2hermes,
.version = R2_VERSION,
.abiversion = R2_ABIVERSION
};
+7 -6
View File
@@ -7,8 +7,8 @@
/* Plugin registration - need these when HBC_CORE_REGISTER_PLUGINS is enabled */
#ifdef HBC_CORE_REGISTER_PLUGINS
extern RArchPlugin r_arch_plugin_r2hermes;
extern RBinPlugin r_bin_plugin_r2hermes;
extern const RArchPlugin r_arch_plugin_r2hermes;
extern const RBinPlugin r_bin_plugin_r2hermes;
#endif
typedef struct {
@@ -91,7 +91,8 @@ static Result hbc_load_current_binary(HbcContext *ctx, RCore *core) {
}
/* Create provider from r2 RBinFile (NO file I/O) */
ctx->hbc = hbc_new_r2 (bf);
// XXX r2 provider is flawed ctx->hbc = r2_hbc_new_r2 (bf);
ctx->hbc = hbc_new_file (file_path);
if (!ctx->hbc) {
return ERROR_RESULT (RESULT_ERROR_MEMORY_ALLOCATION, "Failed to create provider");
}
@@ -530,10 +531,10 @@ static bool plugin_init(RCorePluginSession *s) {
#ifdef HBC_CORE_REGISTER_PLUGINS
/* Register arch and bin plugins when enabled */
if (core->anal && core->anal->arch) {
r_arch_plugin_add (core->anal->arch, &r_arch_plugin_r2hermes);
r_arch_plugin_add (core->anal->arch, (RArchPlugin*)&r_arch_plugin_r2hermes);
}
if (core->bin) {
r_bin_plugin_add (core->bin, &r_bin_plugin_r2hermes);
r_bin_plugin_add (core->bin, (RBinPlugin*)&r_bin_plugin_r2hermes);
}
#endif
@@ -614,7 +615,7 @@ static bool plugin_fini(RCorePluginSession *s) {
}
/* Plugin initialization */
const RCorePlugin r_core_plugin_r2hermes = {
RCorePlugin r_core_plugin_r2hermes = {
.meta = {
.name = "core_hbc",
.desc = "Hermes bytecode decompiler plugin",
+5 -2
View File
@@ -2,5 +2,8 @@
/* Core HBC plugin with plugin registration enabled for r2one */
#define HBC_CORE_REGISTER_PLUGINS
#include "core_hbc.c"
#define HBC_CORE_REGISTER_PLUGINS 1
#define R2_PLUGIN_INCORE 1
#include "bin_hbc.c"
#include "arch_hbc.c"
#include "core_hbc.c"
+23 -40
View File
@@ -1,4 +1,4 @@
/* radare2 - LGPL - Copyright 2025 - pancake */
/* radare2 - LGPL - Copyright 2025-2026 - pancake */
/* R2 HBC Provider: Read HBC data from r2 RBinFile without separate file I/O */
#include <r_bin.h>
@@ -179,29 +179,18 @@ static Result parse_string_tables(HBC *hbc) {
* Public API Implementation
* ============================================================================ */
HBC *hbc_new_r2(RBinFile *bf) {
HBC *r2_hbc_new_r2(RBinFile *bf) {
if (!bf || !bf->buf) {
return NULL;
}
HBC *hbc = (HBC *)malloc (sizeof (HBC));
if (!hbc) {
return NULL;
}
memset (hbc, 0, sizeof (HBC));
HBC *hbc = R_NEW0 (HBC);
hbc->bf = bf;
hbc->bin = bf->rbin;
hbc->buf = bf->buf;
hbc->header_loaded = false;
hbc->string_tables_loaded = false;
hbc->tmp_read_buffer = NULL;
hbc->tmp_buffer_size = 0;
return hbc;
}
Result hbc_hdr(HBC *hbc, HBCHeader *out) {
Result r2_hbc_hdr(HBC *hbc, HBCHeader *out) {
if (!hbc || !out) {
return ERROR_RESULT (RESULT_ERROR_INVALID_ARGUMENT, "NULL pointer");
}
@@ -221,13 +210,13 @@ Result hbc_hdr(HBC *hbc, HBCHeader *out) {
return SUCCESS_RESULT ();
}
Result hbc_func_count(HBC *hbc, u32 *out_count) {
Result r2_hbc_func_count(HBC *hbc, u32 *out_count) {
if (!hbc || !out_count) {
return ERROR_RESULT (RESULT_ERROR_INVALID_ARGUMENT, "NULL pointer");
}
HBCHeader header;
Result res = hbc_hdr (hbc, &header);
Result res = r2_hbc_hdr (hbc, &header);
if (res.code != RESULT_SUCCESS) {
return res;
}
@@ -236,7 +225,7 @@ Result hbc_func_count(HBC *hbc, u32 *out_count) {
return SUCCESS_RESULT ();
}
Result hbc_func_info(HBC *hbc, u32 function_id, HBCFunc *out) {
Result r2_hbc_func_info(HBC *hbc, u32 function_id, HBCFunc *out) {
if (!hbc || !out) {
return ERROR_RESULT (RESULT_ERROR_INVALID_ARGUMENT, "NULL pointer");
}
@@ -265,13 +254,13 @@ Result hbc_func_info(HBC *hbc, u32 function_id, HBCFunc *out) {
return ERROR_RESULT (RESULT_ERROR_NOT_FOUND, "Function not found");
}
Result hbc_str_count(HBC *hbc, u32 *out_count) {
Result r2_hbc_str_count(HBC *hbc, u32 *out_count) {
if (!hbc || !out_count) {
return ERROR_RESULT (RESULT_ERROR_INVALID_ARGUMENT, "NULL pointer");
}
HBCHeader header;
Result res = hbc_hdr (hbc, &header);
Result res = r2_hbc_hdr (hbc, &header);
if (res.code != RESULT_SUCCESS) {
return res;
}
@@ -280,7 +269,7 @@ Result hbc_str_count(HBC *hbc, u32 *out_count) {
return SUCCESS_RESULT ();
}
Result hbc_str(HBC *hbc, u32 string_id, const char **out_str) {
Result r2_hbc_str(HBC *hbc, u32 string_id, const char **out_str) {
if (!hbc || !out_str) {
return ERROR_RESULT (RESULT_ERROR_INVALID_ARGUMENT, "NULL pointer");
}
@@ -306,7 +295,7 @@ Result hbc_str(HBC *hbc, u32 string_id, const char **out_str) {
return ERROR_RESULT (RESULT_ERROR_NOT_FOUND, "String not found");
}
Result hbc_str_meta(HBC *hbc, u32 string_id, HBCStringMeta *out) {
Result r2_hbc_str_meta(HBC *hbc, u32 string_id, HBCStringMeta *out) {
if (!hbc || !out) {
return ERROR_RESULT (RESULT_ERROR_INVALID_ARGUMENT, "NULL pointer");
}
@@ -335,13 +324,13 @@ Result hbc_str_meta(HBC *hbc, u32 string_id, HBCStringMeta *out) {
return ERROR_RESULT (RESULT_ERROR_NOT_FOUND, "String not found");
}
Result hbc_bytecode(HBC *hbc, u32 function_id, const u8 **out_ptr, u32 *out_size) {
Result r2_hbc_bytecode(HBC *hbc, u32 function_id, const u8 **out_ptr, u32 *out_size) {
if (!hbc || !out_ptr || !out_size) {
return ERROR_RESULT (RESULT_ERROR_INVALID_ARGUMENT, "NULL pointer");
}
HBCFunc info;
Result res = hbc_func_info (hbc, function_id, &info);
Result res = r2_hbc_func_info (hbc, function_id, &info);
if (res.code != RESULT_SUCCESS) {
return res;
}
@@ -365,7 +354,7 @@ Result hbc_bytecode(HBC *hbc, u32 function_id, const u8 **out_ptr, u32 *out_size
return SUCCESS_RESULT ();
}
Result hbc_str_tbl(HBC *hbc, HBCStrs *out) {
Result r2_hbc_str_tbl(HBC *hbc, HBCStrs *out) {
if (!hbc || !out) {
return ERROR_RESULT (RESULT_ERROR_INVALID_ARGUMENT, "NULL pointer");
}
@@ -381,7 +370,7 @@ Result hbc_str_tbl(HBC *hbc, HBCStrs *out) {
return SUCCESS_RESULT ();
}
Result hbc_src(HBC *hbc, u32 function_id, const char **out_src) {
Result r2_hbc_src(HBC *hbc, u32 function_id, const char **out_src) {
if (!hbc || !out_src) {
return ERROR_RESULT (RESULT_ERROR_INVALID_ARGUMENT, "NULL pointer");
}
@@ -390,7 +379,7 @@ Result hbc_src(HBC *hbc, u32 function_id, const char **out_src) {
return SUCCESS_RESULT ();
}
Result hbc_read(HBC *hbc, u64 offset, u32 size, const u8 **out_ptr) {
Result r2_hbc_read(HBC *hbc, u64 offset, u32 size, const u8 **out_ptr) {
if (!hbc || !out_ptr) {
return ERROR_RESULT (RESULT_ERROR_INVALID_ARGUMENT, "NULL pointer");
}
@@ -413,19 +402,13 @@ Result hbc_read(HBC *hbc, u64 offset, u32 size, const u8 **out_ptr) {
return SUCCESS_RESULT ();
}
void hbc_free(HBC *hbc) {
if (!hbc) {
return;
}
if (hbc->string_tables_loaded) {
free ((void *)hbc->cached_string_tables.small_string_table);
free ((void *)hbc->cached_string_tables.overflow_string_table);
}
if (hbc->tmp_read_buffer) {
void r2_hbc_free(HBC *hbc) {
if (R_LIKELY (hbc)) {
if (hbc->string_tables_loaded) {
free ((void *)hbc->cached_string_tables.small_string_table);
free ((void *)hbc->cached_string_tables.overflow_string_table);
}
free (hbc->tmp_read_buffer);
free (hbc);
}
free (hbc);
}