The Official Radare2 Book — страница 49 из 64

cp -f anal_snes.$(SO_EXT) $(R2_PLUGIN_PATH)


uninstall:

rm -f $(R2_PLUGIN_PATH)/anal_snes.$(SO_EXT)

anal_snes.c:

/* radare - LGPL - Copyright 2015 - condret */


#include 

#include 

#include 

#include 

#include 

#include "snes_op_table.h"


static int snes_anop(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *data, int len) {

memset (op, '\0', sizeof (RAnalOp));

op->size = snes_op[data[0]].len;

op->addr = addr;

op->type = R_ANAL_OP_TYPE_UNK;

switch (data[0]) {

case 0xea:

op->type = R_ANAL_OP_TYPE_NOP;

break;

}

return op->size;

}


struct r_anal_plugin_t r_anal_plugin_snes = {

.name = "snes",

.desc = "SNES analysis plugin",

.license = "LGPL3",

.arch = R_SYS_ARCH_NONE,

.bits = 16,

.init = NULL,

.fini = NULL,

.op = &snes_anop,

.set_reg_profile = NULL,

.fingerprint_bb = NULL,

.fingerprint_fcn = NULL,

.diff_bb = NULL,

.diff_fcn = NULL,

.diff_eval = NULL

};


#ifndef R2_PLUGIN_INCORE

R_API RLibStruct radare_plugin = {

.type = R_LIB_TYPE_ANAL,

.data = &r_anal_plugin_snes,

.version = R2_VERSION

};

#endif

After compiling radare2 will list this plugin in the output:

_dA_ _8_16 snes LGPL3 SuperNES CPU

snes_op_table.h: https://github.com/radareorg/radare2/blob/master/libr/asm/arch/snes/snes_op_table.h

Example:

   • 6502: https://github.com/radareorg/radare2/commit/64636e9505f9ca8b408958d3c01ac8e3ce254a9b

   • SNES: https://github.com/radareorg/radare2/commit/60d6e5a1b9d244c7085b22ae8985d00027624b49

Implementing a new format

To enable virtual addressing

In info add et->has_va = 1; and ptr->srwx with the R_BIN_SCN_MAP; attribute

Create a folder with file format name in libr/bin/format

Makefile:

NAME=bin_nes

R2_PLUGIN_PATH=$(shell r2 -H R2_USER_PLUGINS)

LIBEXT=$(shell r2 -H LIBEXT)

CFLAGS=-g -fPIC $(shell pkg-config --cflags r_bin)

LDFLAGS=-shared $(shell pkg-config --libs r_bin)

OBJS=$(NAME).o

LIB=$(NAME).$(LIBEXT)


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)


bin_nes.c:

#include 

#include 


static bool load_buffer(RBinFile *bf, void **bin_obj, RBuffer *b, ut64 loadaddr, Sdb *sdb) {

ut64 size;

const ut8 *buf = r_buf_data (b, &size);

r_return_val_if_fail (buf, false);

*bin_obj = r_bin_internal_nes_load (buf, size);

return *bin_obj != NULL;

}


static void destroy(RBinFile *bf) {

r_bin_free_all_nes_obj (bf->o->bin_obj);

bf->o->bin_obj = NULL;

}


static bool check_buffer(RBuffer *b) {

if (!buf || length < 4) return false;

return (!memcmp (buf, "\x4E\x45\x53\x1A", 4));

}


static RBinInfo* info(RBinFile *arch) {

RBinInfo \*ret = R_NEW0 (RBinInfo);

if (!ret) return NULL;


if (!arch || !arch->buf) {

free (ret);

return NULL;

}

ret->file = strdup (arch->file);

ret->type = strdup ("ROM");

ret->machine = strdup ("Nintendo NES");

ret->os = strdup ("nes");

ret->arch = strdup ("6502");

ret->bits = 8;


return ret;

}


struct r_bin_plugin_t r_bin_plugin_nes = {

.name = "nes",

.desc = "NES",

.license = "BSD",

.get_sdb = NULL,

.load_buffer = &load_buffer,

.destroy = &destroy,

.check_buffer = &check_buffer,

.baddr = NULL,

.entries = NULL,

.sections = NULL,

.info = &info,

};


#ifndef R2_PLUGIN_INCORE

R_API RLibStruct radare_plugin = {

.type = R_LIB_TYPE_BIN,

.data = &r_bin_plugin_nes,

.version = R2_VERSION

};

#endif


Some Examples

   • XBE - https://github.com/radareorg/radare2/pull/972

   • COFF - https://github.com/radareorg/radare2/pull/645

   • TE - https://github.com/radareorg/radare2/pull/61

   • Zimgz - https://github.com/radareorg/radare2/commit/d1351cf836df3e2e63043a6dc728e880316f00eb

   • OMF - https://github.com/radareorg/radare2/commit/44fd8b2555a0446ea759901a94c06f20566bbc40

Write a debugger plugin

   • 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.

More to come..

   • Related article: http://radare.today/posts/extending-r2-with-new-plugins/

Some commits related to "Implementing a new architecture"

   • Extensa: https://github.com/radareorg/radare2/commit/6f1655c49160fe9a287020537afe0fb8049085d7

   • Malbolge: https://github.com/radareorg/radare2/pull/579

   • 6502: https://github.com/radareorg/radare2/pull/656

   • h8300: https://github.com/radareorg/radare2/pull/664

   • GBA: https://github.com/radareorg/radare2/pull/702

   • CR16: https://github.com/radareorg/radare2/pull/721/