-
Notifications
You must be signed in to change notification settings - Fork 0
Implementing a new architecture
radare2 splits the logic of a CPU into several modules. You should write more than one plugin to get full support for a specific arch. Let's see which are those:
- r_asm : assembler and disassembler
- r_anal : code analysis (opcode,type,esil,..)
- r_reg : registers
- r_syscall : system calls
- r_debug : debugger
The most basic feature you usually want to support from a specific architecture is the disassembler. You first need to read into a human readable form the bytes in there.
Bear in mind that plugins can be compiled static or dynamically, this means that the arch will be embedded inside the core libraries or it will distributed as a separated shared library.
To configure which plugins you want to compile use the ./configure-plugins
script which accepts the flags --shared and --static to specify them. You can also add it manually inside the plugins.def.cfg
and then remove the plugins.cfg
and run ./configure-plugins
again to update the libr/config.mk
and libr/config.h
.
You may find some examples of external plugins in the radare2-capstone
and radare2-extras
repositories:
1. https://github.com/radare/radare2-capstone 2. https://github.com/radare/radare2-extras
The official way to make third-party plugins is to distribute them into a separate repository. This is a sample disasm plugin:
$ cd my-cpu
$ cat Makefile
NAME=mycpu
R2_PLUGIN_PATH=$(shell r2 -hh|grep LIBR_PLUGINS|awk '{print $$2}')
CFLAGS=-g -fPIC $(shell pkg-config --cflags r_asm)
LDFLAGS=-shared $(shell pkg-config --libs r_asm)
OBJS=$(NAME).o
SO_EXT=$(shell uname|grep -q Darwin && echo dylib || echo so)
LIB=$(NAME).$(SO_EXT)
all: $(LIB)
clean:
rm -f $(LIB) $(OBJS)
$(LIB): $(OBJS)
$(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) -o $(LIB)
install:
cp -f $(NAME).$(SO_EXT) $(R2_PLUGIN_PATH)
uninstall:
rm -f $(R2_PLUGIN_PATH)/$(NAME).$(SO_EXT)
$ cat mycpu.c
/* example r_asm plugin by pancake at 2014 */
#include <r_asm.h>
#include <r_lib.h>
#define OPS 17
static const char *ops[OPS*2] = {
"nop", NULL,
"if", "r",
"ifnot", "r",
"add", "rr",
"addi", "ri",
"sub", "ri",
"neg", "ri",
"xor", "ri",
"mov", "ri",
"cmp", "rr",
"load", "ri",
"store", "ri",
"shl", "ri",
"br", "r",
"bl", "r",
"ret", NULL,
"sys", "i"
};
//b for byte, l for length
static int disassemble (RAsm *a, RAsmOp *op, const ut8 *b, int l) {
char arg[32];
int idx = (b[0]&0xf)*2;
op->size = 2;
if (idx>=(OPS*2)) {
strcpy (op->buf_asm, "invalid");
return -1;
}
strcpy (op->buf_asm, ops[idx]);
if (ops[idx+1]) {
const char *p = ops[idx+1];
arg[0] = 0;
if (!strcmp (p, "rr")) {
sprintf (arg, "r%d, r%d", b[1]>>4, b[1]&0xf);
} else
if (!strcmp (p, "i")) {
sprintf (arg, "%d", (char)b[1]);
} else
if (!strcmp (p, "r")) {
sprintf (arg, "r%d, r%d", b[1]>>4, b[1]&0xf);
} else
if (!strcmp (p, "ri")) {
sprintf (arg, "r%d, %d", b[1]>>4, (char)b[1]&0xf);
}
if (*arg) {
strcat (op->buf_asm, " ");
strcat (op->buf_asm, arg);
}
}
return op->size;
}
RAsmPlugin r_asm_plugin_mycpu = {
.name = "mycpu",
.arch = "mycpu",
.license = "LGPL3",
.bits = 32,
.desc = "My CPU disassembler",
.disassemble = &disassemble,
};
#ifndef CORELIB
struct r_lib_struct_t radare_plugin = {
.type = R_LIB_TYPE_ASM,
.data = &r_asm_plugin_mycpu
};
#endif
To build and install this plugin just type this:
$ make
$ sudo make install
This plugin is used by rasm2 and r2. You can verify that the plugin is properly loaded with this command:
$ rasm2 -L | grep mycpu
_d mycpu My CPU disassembler (LGPL3)
Let's open an empty file using the 'mycpu' arch and write some random code there.
$ r2 -
-- I endians swap
[0x00000000]> e asm.arch=mycpu
[0x00000000]> woR
[0x00000000]> pd 10
0x00000000 888e mov r8, 14
0x00000002 b2a5 ifnot r10, r5
0x00000004 3f67 ret
0x00000006 7ef6 bl r15, r6
0x00000008 2701 xor r0, 1
0x0000000a 9826 mov r2, 6
0x0000000c 478d xor r8, 13
0x0000000e 6b6b store r6, 11
0x00000010 1382 add r8, r2
0x00000012 7f15 ret
Yay! it works.. and the mandatory oneliner too!
r2 -nqamycpu -cwoR -cpd' 10' -
Pushing a new architecture into the main branch of r2 requires to modify several files in order to make it fit into the way the rest of plugins are built.
List of affected files:
-
plugins.def.cfg
: add the asm.mycpu plugin name string in there -
libr/asm/p/mycpu.mk
: build instructions -
libr/asm/p/asm_mycpu.c
: implementation -
libr/include/r_asm.h
: add the struct definition in there
Check out how the NIOS II cpu was implemented by reading those commits:
Implement RAsm plugin: https://github.com/radare/radare2/commit/933dc0ef6ddfe44c88bbb261165bf8f8b531476b
Implement RAnal plugin: https://github.com/radare/radare2/commit/ad430f0d52fbe933e0830c49ee607e9b0e4ac8f2
More examples to come...
- Adding the debugger registers profile into the shlr/gdb/src/core.c
- Adding the registers profile and architecture support in the libr/debug/p/debug_native.c and libr/debug/p/debug_gdb.c
- Add the code to apply the profiles into the function
r_debug_gdb_attach(RDebug *dbg, int pid)
If you want to add support for the gdb, you can see the register profile in the active gdb session using command maint print registers
.
The next logic step would be to implement and analysis plugin.
...
- Related article: http://radare.today/extending-r2-with-new-plugins/
Some commits related to "Implementing a new architecture"
- Extensa: https://github.com/radare/radare2/commit/6f1655c49160fe9a287020537afe0fb8049085d7
- Malbolge: https://github.com/radare/radare2/pull/579
- 6502: https://github.com/radare/radare2/pull/656
- h8300: https://github.com/radare/radare2/pull/664
- GBA: https://github.com/radare/radare2/pull/702
- CR16: https://github.com/radare/radare2/pull/721/ && https://github.com/radare/radare2/pull/726
- XCore: https://github.com/radare/radare2/commit/bb16d1737ca5a471142f16ccfa7d444d2713a54d
- Sharp LH5801: https://github.com/neuschaefer/radare2/commit/f4993cca634161ce6f82a64596fce45fe6b818e7
- MSP430: https://github.com/radare/radare2/pull/1426
- HP PA-RISC: https://github.com/radare/radare2/commit/f8384feb6ba019b91229adb8fd6e0314b0656f7b
- V810: https://github.com/radare/radare2/pull/2899
- TMS320: https://github.com/radare/radare2/pull/596