Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 5 additions & 31 deletions src/plugins/dev-analysis.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ and so on. This is because Rizin requires every architecture plugin
to provide also analysis information about every opcode. At the moment
the implementation of disassembly and opcodes analysis is separated between
two modules - RzAsm and RzAnalysis. Thus, we need to write an analysis plugin too.
The principle is very similar - you just need to create a C file and
corresponding Makefile.
The principle is very similar - you just need to create a C file in `librz/arch/p/analysis/` and declare it in corresponding architecture plugin file `librz/arch/p/arch_mycpu.c`.

They structure of RzAnalysis plugin looks like

Expand All @@ -30,32 +29,6 @@ ESIL, which is enabled in `.esil = true` statement. Thus, `mycpu_op` obliged to
corresponding RzAnalysisOp ESIL field for the opcodes. Second important thing for ESIL uplifting and
emulation - register profile, like in debugger, which is set within `set_reg_profile` function.

**Makefile**

```makefile
NAME=analysis_mycpu
RZ_PLUGIN_PATH=$(shell rizin -H RZ_USER_PLUGINS)
LIBEXT=$(shell rizin -H LIBEXT)
CFLAGS=-g -fPIC $(shell pkg-config --cflags rz_analysis)
LDFLAGS=-shared $(shell pkg-config --libs rz_analysis)
OBJS=$(NAME).o
LIB=$(NAME).$(LIBEXT)

all: $(LIB)

clean:
rm -f $(LIB) $(OBJS)

$(LIB): $(OBJS)
$(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) -o $(LIB)

install:
cp -f analysis_mycpu.$(SO_EXT) $(RZ_PLUGIN_PATH)

uninstall:
rm -f $(RZ_PLUGIN_PATH)/analysis_mycpu.$(SO_EXT)
```

Comment on lines -33 to -58

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this needs a meson equivalent.

**analysis_mycpu.c:**
This is a dummy example please go check real life examples
[in the source](https://github.com/rizinorg/rizin/blob/dev/librz/analysis/p/analysis_snes.c).
Expand Down Expand Up @@ -124,6 +97,8 @@ RZ_API RzLibStruct rizin_plugin = {
#endif
```

After creating this plugin, include this plugin file in corresponding `librz/arch/p/arch_mycpu.c`

After compiling rizin will list this plugin in the rz-asm output:

```
Expand All @@ -134,6 +109,5 @@ Note the `A` just appeared on the left column (a=asm, d=disasm, A=analyze, e=ESI

Examples:

* [RzAnalysis plugin for 6502](https://github.com/rizinorg/rizin/commit/64636e9505f9ca8b408958d3c01ac8e3ce254a9b)
* [RzAnalysis plugin for SNES](https://github.com/rizinorg/rizin/commit/60d6e5a1b9d244c7085b22ae8985d00027624b49)

- [RzAnalysis plugin for Alpha architecture using Capstone](https://github.com/rizinorg/rizin/blob/dev/librz/arch/p/analysis/analysis_alpha_cs.c)
- [RzAnalysis plugin for AVR architecture](https://github.com/rizinorg/rizin/blob/dev/librz/arch/p/analysis/analysis_avr.c)
101 changes: 47 additions & 54 deletions src/plugins/dev-asm.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

Rizin has modular architecture, thus adding support for a new architecture is very easy, if you
are fluent in C. For various reasons it might be easier to implement it out of the tree. For this we
will need to create single C file, called `asm_mycpu.c` and a meson file for it.
will need two C files mainly, called `asm_mycpu.c` in `librz/arch/p/asm/` , `arch_mycpu.c` in `librz/arch/p/` and declare the asm plugin in architecture plugin file .
Add the newly created architecture plugin file in meson.build

The key thing of RzAsm plugin is a structure

Expand All @@ -25,23 +26,6 @@ and length:
static int disassemble(RzAsm *a, RzAsmOp *op, const ut8 *buf, int len)
```

**Meson**

```bash
project('asm_mycpu', 'c')

rz_asm_dep = dependency('rz_asm')
plugins_dir = get_option('prefix') / rz_asm_dep.get_variable(pkgconfig: 'plugindir', cmake: 'rz_asm_PLUGINDIR')
message('Plugins install directory: ' + plugins_dir)

library('asm_mycpu',
['asm_mycpu.c'],
dependencies: [rz_asm_dep],
install: true,
install_dir: plugins_dir,
)
```

**asm_mycpu.c**

```c
Expand Down Expand Up @@ -86,66 +70,75 @@ RZ_API RzLibStruct rizin_plugin = {
#endif
```

After compiling rizin will list this plugin in the rz-asm output:
**arch_mycpu.c**

```
$ rz-asm -L |grep myc
_d__ _8_32 mycpu LGPL3 MYCPU disassembly plugin
This file is an architecture plugin wrapper that ties together assembler,analysis, and (optionally) parsing components into a single `RzArchPlugin` which is registered using macros from `deprecated_arch_helper.h`

```c
#include <deprecated_arch_helper.h>

#include "analysis/analysis_mycpu.c"
#include "asm/asm_mycpu.c"

RZ_ARCH_PLUGIN_DEFINE_DEPRECATED(mycpu); // or any other suitable macro from deprecated_arch_helper.h
```

**If neeeded also add:**

- `librz/arch/isa/mycpu/` — create this directory with your ISA definition files (instruction tables, opcode maps, disassembler/assembler logic)

- `librz/arch/opcodes/mycpu.sdb.txt` — optional, human-readable instruction descriptions

### Moving plugin into the tree

Pushing a new architecture into the main branch of rizin requires to modify several files in order to make it fit
into the way the rest of plugins are built.

__List of affected files:__
**List of affected files:**

* `librz/asm/p/asm_mycpu.c`
That's where most of our code will be, the key part is to declare a `RzAsmPlugin` containing a valid `disassemble`
field, a function pointer to the actual disassembler function.
- `librz/arch/p/asm_mycpu.c`
That's where most of our code will be, the key part is to declare a `RzAsmPlugin` containing a valid `disassemble`
field, a function pointer to the actual disassembler function.

- `librz/arch/meson.build`
The build is handled by meson, we have to add our plugin to the list of things to be compiled :

* `librz/asm/meson.build`
The build is handled by meson, we have to add our plugin to the list of things to be compiled :
```diff
@@ -49,6 +49,7 @@ asm_plugins_list = [
@@ -49,6 +49,7 @@ arch_plugins_list = [
'x86_nz',
'xap',
'xcore_cs',
+ 'mycpu',
]

@@ -129,6 +130,7 @@ rz_asm_sources = [
#'p/asm_x86_vm.c',
'p/asm_xap.c',
'p/asm_xcore_cs.c',
+ 'p/asm_mycpu.c',
#'arch/6502/6502dis.c',
'arch/amd29k/amd29k.c',
#'arch/8051/8051_disas.c',
+ 'arch/mycpu/mycpu_disas.c',
'arch/arm/armass.c',

@@ -129,6 +130,7 @@ rz_asm_inc = [
+ 'arch/mycpu',
@@ -129,6 +130,7 @@ arch_plugin_sources = [
#'p/arch_x86_vm.c',
'p/arch_xap.c',
'p/arch_xcore_cs.c',
+ 'p/arch_mycpu.c',
]

@@ -129,6 +131,8 @@ arch_isa_sources = [
+ 'isa/mycpu/disas.c',
+ 'isa/mycpu/mycpu.c', // any other related files if exist
]
```

* `librz/include/rz_asm.h`
Make Rizin aware of our plugin by defining our struct:
```diff
@@ -265,6 +265,7 @@ extern RzAsmPlugin rz_asm_plugin_xcore_cs;
extern RzAsmPlugin rz_asm_plugin_xtensa;
extern RzAsmPlugin rz_asm_plugin_z80;
extern RzAsmPlugin rz_asm_plugin_pyc;
+extern RzAsmPlugin rz_asm_plugin_mycpu;
After compiling rizin will list this plugin in the rz-asm output:

#endif
```
$ rz-asm -L |grep myc
_d__ _8_32 mycpu LGPL3 MYCPU disassembly plugin
```

Check out how AVR and Alpha architectures have been implemented by having a look at the following files

Check out how the NIOS II CPU disassembly plugin was implemented by reading those commits:
[RzAsm plugin for AVR](https://github.com/rizinorg/rizin/blob/dev/librz/arch/p/asm/asm_avr.c)

[The RzAsm plugin](https://github.com/rizinorg/rizin/commit/933dc0ef6ddfe44c88bbb261165bf8f8b531476b)
[AVR arch plugin](https://github.com/rizinorg/rizin/blob/dev/librz/arch/p/arch_avr.c)

[The RzAnalysis plugin](https://github.com/rizinorg/rizin/commit/ad430f0d52fbe933e0830c49ee607e9b0e4ac8f2)
[RzAsm plugin for Alpha using Capstone](https://github.com/rizinorg/rizin/blob/dev/librz/arch/p/asm/asm_alpha_cs.c)

[Alpha arch plugin](https://github.com/rizinorg/rizin/blob/dev/librz/arch/p/arch_alpha.c)

Note: Create a disassembly parser plugin if needed under `librz/arch/p/parse/` which will be used when specific evaluable variables are set such as `asm.pseudo`, `asm.sub.jmp`, `asm.sub.reg`, `asm.sub.rel` etc