Using r2 with 8051
- [x] Disassembler
- [x] Emulation (esil)
- [x] Basic address space mapping
- [ ] Debugger
- [ ] Assembler
- [ ] Full emulation of memory-mapped registers
- [ ] Memory banking for address spaces > 64K
- [ ] Advanced analysis like local variables, function parameters ..
- [ ] More predefined CPU models
Set architecture to 8051:
r2 -a 8051
Set cpu to desired model:
e asm.cpu = ?
After changing the cpu model, run 'aei' to initalize/reset the registers and mapped memory. For example:
e asm.cpu = 8051-generic aei
Enable substitution of jumps, call and branches:
e asm.jmpsub = true
Address spaces and memory mapping
Pseudo registers are used to control how r2 emulates the multiple address spaces of the 8051. The registers hold the base address where the 8051 memory area is located in r2 address space.
|_code||CODE||Program memory. Typically located at 0.|
|_idata||IDATA||256 bytes of internal RAM.|
|_sfr||SFR||128 bytes for special function registers. _sfr is the base address. Registers start at _sfr+0x80.|
|_xdata||XDATA||64K of external RAM.|
|_pdata||PDATA, XREG||MSB of address of 256-byte page in XDATA accessed with 'movx @Ri' op codes.|
The registers are initalized based on the selected cpu. See command 'e asm.cpu=?'.
The registers can be viewed and modified with the 'ar' command. When modifying the pseudo registers or updating 'asm.cpu', memory will be (re)allocated automatically when the analyzer is invoked the next time (e.g. during 'aei'). Use the 'om' command to see the list of allocated memory blocks.
[0x00000000]> e asm.cpu=8051.generic [0x00000000]> aei [0x00000000]> om 4 fd: 6 +0x00000000 0x00000000 - 0x0000ffff -rwx 3 fd: 5 +0x00000000 0x20000000 - 0x2000ffff -rw- xdata 2 fd: 4 +0x00000000 0x10000180 - 0x100001ff -rw- sfr 1 fd: 3 +0x00000000 0x10000000 - 0x100000ff -rw- idata
Analysis and emulation rely on the address mapping. Setup the pseudo registers before running analysis, or rerun analysis after updating pseudo registers.
Address spaces can overlap in r2 memory. This allows to emulate 8051 variants that mirror IDATA and SFR into XDATA, or have shared XDATA and CODE address spaces.
For example, the CC2430 from Texas Instruments maps SFR to 0xDF80 and IDATA to 0xFF00 in XDATA memory space. In r2 this can be setup with:
ar _sfr = _xdata + 0xdf00 ar _idata = _xdata + 0xff00
For overlapping areas, r2 will prioritze smaller memory blocks over larger ones. For example, if IDATA is mapped into XDATA, all r2 operations will use IDATA in the overlapping addresses. If you want to use XDATA instead, you can delete the offending map with the command 'om-'. See 'om?'for more information.
For using emulation with overlapping code and RAM spaces, the r2 memory holding the firmware must allow write access. This is best achieved with the command 'omf 4 rwx', with 4 being the id of the firmware file's IO map entry. See 'om?' for more information.
Some 8051 variants use memory banking to address memory spaces larger than 64K. Currently, memory banking is not supported by r2.
Tips & tricks
Use pseudo registers in r2 commands to calculate addresses. For example:
Hex dump of all special function registers:
px @ _sfr
Write a value to a location in external RAM
wx deadbeef @ _xdata + 0x1234
Set a flag for a variable stored at 0x20 in internal RAM:
f sym.secret @ _idata + 0x20
Adding support for new 8051 variants
Follow these steps to add support for new 8051 variants to r2.
- Clone latest version of radare2
- In '/libr/anal/p/anal_8051.c' add new entry to array 'cpu_models' to define name and memory mapping. Name of last entry in array must be NULL
- In 'libr/asm/p/asm_8051.c' append entry with same name to '.cpus' attribute
- Compile and test your addtion, and submit a pull request