Compare commits

...
281 Commits
Author SHA1 Message Date
pancake 73960d34df Fix MN103 installation and VC4 tests in CI 2026-11-09 13:53:48 +01:00
dependabot[bot] 2afaceab6a build(deps): bump iced-x86 from 1.21.0 to 1.22.0 in /x86iced
Bumps [iced-x86](https://github.com/icedland/iced) from 1.21.0 to 1.22.0.
- [Release notes](https://github.com/icedland/iced/releases)
- [Commits](https://github.com/icedland/iced/compare/v1.21.0...v1.22.0)

---
updated-dependencies:
- dependency-name: iced-x86
  dependency-version: 1.22.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
2026-11-09 13:23:27 +01:00
n0p a29ce917c1 mn103: r2r test databases in the extras tree
test/db/extras/asm/mn103 (55 disassembly vectors) and test/db/extras/mn103
(disassembly, analysis, pseudo syntax, cpu levels and ESIL emulation),
run by the CI like the microblaze and ppcdisasm databases; the radare2
test target is no longer needed.
2026-11-08 15:31:12 +01:00
n0p 8c738204dd mn103: build and test the plugin in CI
Add mn103 to LOCAL_BUILDS (installed through the r2pm package) and to
TESTS (the r2r database test/db/extras/asm/mn103 of radare2). The
Makefile honours R2PM_PLUGDIR as the r2pm package expects.
2026-11-08 15:31:12 +01:00
n0p 031b077f2c mn103: tests, sweep tool and docs
Unit checks of the decoder, analysis, ESIL and the length rule of every
table row; r2 integration tests (disassembly, pseudo syntax, cpu levels,
aoj metadata, function analysis, emulation of multiply/divide, flags,
call/ret and movm frames, memory bit operations, loops); the mn103-dis
linear sweep tool; README, doc/mn103.md and CHANGELOG.
2026-11-08 15:31:12 +01:00
n0p 2a44edead6 mn103: MN10300/AM33 architecture plugin from the binutils opcode table
The GNU binutils MN10300 opcode table (opcodes/m10300-opc.c, 1129 rows)
as generated C arrays, a C port of the length rule, first-match lookup
and operand extraction of opcodes/m10300-dis.c, and the RArchPlugin:
analysis types for every row, control flow (branches, setlb/lXX loops,
jumps and calls, returns), loads/stores with size and addressing mode,
stack deltas for add/sub sp, movm and the call/ret register-list frames,
a register profile with the PSW flags and the AM33/FPU registers, and
ESIL for the integer core. asm.cpu selects the machine level
(mn10300 < am30 < am33 < am33-2); the udf placeholder rows are looked up
after the named rows of the same encoding (mulq, mulqu, swap, ...).
A pseudo-syntax parse plugin covers the common forms.
2026-11-08 15:31:12 +01:00
pancake ee031a7021 vc4: upstream cgen tables, assembler, ESIL emulation and analysis
- Update the cgen generated sources to puppeh/binutils-vc4 (branch vc4),
  which decodes the vector unit and fixes sized ld/st, scaled immediates
  and the signed 12 bit offsets
- Decode 80 bit vector insns (16 byte buffer, 10 byte max op size)
- Decode what the tables miss or get wrong: tbb/tbh, 48 bit b/bl pc+o32,
  the missing 48 bit alu ops, and the shift of 32 bit addscale immediates
- Treat the 16 bit sp offset of lea/add sp as signed, print float6
  immediates as values so they assemble back
- Add an assembler on top of the cgen one, pc relative operands, relaxed
  wider forms, 48 bit fallbacks, and a check that rejects encodings cgen
  silently truncates
- Replace the analysis with a text driven one that emits ESIL for all
  scalar insns: flags in sr, conditions, compare and branch, ldm/stm,
  table branches, floats and conversions; vector insns are typed only
- Rewrite the pseudo plugin for the upstream syntax
- Drop libvc4 from the builds, the plugin never used it
2026-11-04 20:19:45 +01:00
pancake 0a0327aa45 vc4: pseudo compare-and-branch forms and meson include path fix
- Translate addcmpb<cond> and 3 operand b<cond> into compare and goto
- Render the never-taken f condition as false and fix 'x -N' spacing
- Resolve ../../include with realpath since p/vc4 is usually a symlink
- Document the separate arch.vc4 and asm.vc4 XPS plugins
2026-11-04 18:41:02 +01:00
pancake 9870775224 Add r2plugin xps interface and pseudo for vc4 2026-11-04 18:31:28 +01:00
pancake d5e7a28186 Ignore vc4 plugin build artifacts and editor caches 2026-11-04 11:33:25 +01:00
pancake c9571534b9 Add standalone Makefile to build the vc4 asm/anal plugin
Allows building arch_vc4 from libr/asm/arch/vc4 directly instead of
going through the whole r2 build. Mirrors libr/asm/p/vc4.mk but
resolves the sources locally, links libr/libvc4 objects and the
libr/asm/p/arch_vc4.c glue, and adds an install target.
2026-11-04 11:33:09 +01:00
pancake 5fff0016a3 Support bits:// packed and be16 unpacked roms for r2tama 2026-11-03 18:30:00 +01:00
pancake f2199032a7 Add Tamagotchi P1/P2 ESIL emulator 2026-11-03 18:10:09 +01:00
n0p 5d28dc6de4 md32: tests and docs for the scq16 table update and the public test vectors
test/test_scq16.py (267 checks) and test/test_md32.c cover the new forms, the open marker, the broadcast ports, the confidence levels and ctz(0). test/scq16_vectors.json carries 195 public bytes-only vectors with the expected result in the big-endian regime of the harness and in the little-endian regime of the core data memory; test/test_scq16_vectors.py runs both and the Makefile adds it to make test. doc/scq16.md, README and CHANGELOG describe the hypothesis file, the confidence levels and the open question on ctz(0).
2026-11-03 10:17:01 +01:00
n0p 645f4154ff md32: scq16 table update (229 forms), the open-reading marker, the broadcast ports and the confidence levels
jr rn (6f ec) reads a 5-bit register field (r0-r31); btst rd, rd, #pos (67 f8-fb) has a 5-bit position; ctz is its own form without the hypothetical flag and sqr? belongs to the op41 placeholder; and rd, rs, #0x1|#0x3|#0xf (2 bytes), add rd, rs, #-1 (2 bytes) and the 4-byte sb are high, the 4-byte btst rd, rs, #pos is medium (settled by execution results).

The exporter marks an open reading (a family placeholder or a provisional name) with SCQ16_FL_OPEN and gives an open alternative without a template the uniform ESIL marker REF,ALT,open; export --hyp applies the declared plugin hypotheses of isa/scq16_hyp.json, which is empty: the packing ESIL of op41.fld rd, rs, rt, #pos is carried by the ISA source, still flagged hypothetical.

The scalar ports v0-v31 are the broadcast ports of the vector register file: a write by vbcast / vbcast.i reaches the 64 lanes of vr_k; the custom op open has no effect; aoj reports open, reading, hypothetical and confidence per unit. ctz of a zero operand gives -1 under the table ESIL; whether the hardware returns 32 is an open question. asm: the pseudo rule of op41.fld.
2026-11-03 10:17:01 +01:00
n0p 899e3344ff md32: document the three encodings the plugin serves and its scope
The README introduction states what MS15E30, uSIP and SCQ16 are and how they relate: two MD32 encodings and one distinct byte-granular encoding that shares the MD32 scalar programming model, which is why it is a cpu mode of this plugin; the remaining DSP cores of the same modem use an unrelated SIMD ISA and are out of scope. doc/scq16.md carries the same note.
2026-11-03 08:31:29 +01:00
n0p 6493987c72 md32: tests and docs for the scq16 table update and the vector unit model
test/test_scq16.py: bytes-only checks of ctz (established) next to the
provisional sqr?, sra? rd, rd, #pos, vrd? rd, vb1[x], op41.fld with three
registers, the provisional and? masks, lw.post of 2 bytes with a 4-bit
destination, the signed post-increment of the 6e page, vector ops with
non-zero fields, a vector head and B slots with the new forms; analysis
(ctz named, sqr? / sra? / vrd? provisional, op41.fld with rt, the lw.post
destination r11); the ESIL of ctz / sqr? / sra? / vrd?, the .post
templates writing rd last (rd == rb), the signed post-increments and the
vector unit model (vset.a / vmem.set, v.mem.ld with a count and with the
whole register, v.mem.ld + v.mem.st through the VU, v.move.mv back and
forth, F2 >= 4 without effect, a bundle with a vector load, unmodelled
vector ops stepped over).  test/test_md32.c: ctz, lw.post r11, sra?,
v.mem.ld with its fields.  doc/scq16.md: the new forms, the .post
convention, the VU model and its limits, the register profile with vr*,
the calling convention (r16-r31 callee-saved, r0-r15 caller-saved, lr
saved by the functions that call); README "SCQ16 mode": the VU model,
the provisional sqr? / sra?, the calling convention; CHANGELOG entry.
2026-11-03 08:31:29 +01:00
n0p ba096f3546 md32: scq16 table update (402 bit alternatives), the .post convention and the vector unit model
isa/scq16_isa.json is re-exported by the `export` command of
tools/gen_scq16_tables.py: 228 forms / 402 bit alternatives.  ctz rd, rs
(41 f3 0x22) is an established operation with the ESIL rd = 31 - clz(rs
& -rs); new provisional readings: sqr? rd, rs (41 f3 0x23, rd = rs * rs),
sra? rd, rd, #pos (67 fc-fd), vrd? rd, vb1[x] (1a xy, a 32-bit read of
the VU scalar bank with rd = w[3:0] + 1), and? #0xf000? (67 98-9b and the
2-byte 00/01 with k = 6) and and? #0xc000? (67 b4-b7); op41.fld rd, rs,
rt, #pos reads its third field as a register; lw.post rd, [rb] += 4 (21)
has a 4-bit destination (r1-r16); the 3-bit post-increment of the 6e
.post family (sh.post, lw.post, lhu.post?, lbu.post) is signed (x = 4..7
is -4..-1 units); sra rd, rd, #imm (09) is established; the load
templates with a post-increment write rd last, so with rd == rb the
loaded value wins (a declared convention: the public MD32 documents rd
written first).

scq16_vu.inc.c (new, included by scq16_arch.inc.c): the vector unit
model of the ESIL.  The register profile gains the vector register file
vr0-vr31 (128 bytes each, exposed as the four 256-bit quarters
vrK_0..vrK_3; lane 16q is the low 16 bits of quarter q); vp0-vp7 (written
by vmem.set and the hypothetical vcfg4c? #0xc) and va0-va7 (written by
vset.a) are the existing scalar ports.  The custom ESIL op vop models the
three established vector operations and nothing else: v.mem.ld copies n
halves from DM[p] into vr[F1 >> 2] and v.mem.st copies n halves from vr0
to DM[p], with p = vp[2 * F2 + F3[4]] when F2 < 4 and n = va[A] when
1..64 (otherwise the whole register), post-incrementing the pointer by
the bytes accessed; v.move.mv copies vr[F3] into vr[F1].  A memory op
with F2 >= 4, the pair mode B = 2 of v.move.mv and every other op9 pop
their operands and have no effect.  The data memory is read and written
through the ESIL memory callbacks; the vector registers are kept in the
register arena.

asm_md32.c: pseudo rule of sqr (rd = (rs * rs)).  Makefile: the new
include file among the dependencies of the arch plugin.
2026-11-03 08:31:29 +01:00
n0p bfab794507 md32: tests and docs for the scq16 table update
test/test_scq16.py: bytes-only checks of the page 42 (cmov.ge, cmov.eq
with a register, the provisional cmov.*?, the remaining sel? codes), the
67 page (mv, bset/btst rd, rd, #pos, and #0x3fff), lbu.post with 5-bit
registers and the 23 page with a signed post-increment, the 6-byte and
#imm16, ctz?/clb?, vcfg4c? #0xc, ld46?, the established vector names
(v.move.mv, v.mem.ld, v.mem.st) next to the provisional ones, addsp 14 8x,
halt, sys41, lbu? off(sp), the 4-byte beq of 5c 40-6f, j.d1 decided by its
target (also in a B slot), the ESIL of the new forms, negative frame
offsets, halt/sys41 without effect and ret.d2 / jr.d2 across two aes
steps (a packet in the first slot).  test/test_md32.c: cmov.ge, mv 67 c8,
j.d1 by target, lbu.post of the 23 page, v.mem.ld.  doc/scq16.md: the
j.d1 length by target, the vector names (established / provisional), the
page 42, 46, 4c, 41 f3, 22/23, 67, 6e and 74 families, the ESIL
conventions (.d2 across two aes steps, 32-bit addresses, no-effect units,
the memory order inside a packet), the hypothetical alternatives of the
table, the limits (rd == rb post-increment, the vector unit), the
data-space bases; README "SCQ16 mode" updates; CHANGELOG entry;
tools/scq16_flags.r2 (DM, I/O window and DM2 bases as flags).
2026-11-02 16:26:48 +01:00
n0p 619f60a7df md32: scq16 table update (228 forms), decoder rules and generator features
isa/scq16_isa.json is re-exported by the `export` command of
tools/gen_scq16_tables.py: 228 forms / 400 bit alternatives.  The ESIL
templates, the delayed transfers (SETJT/SETD) and the hypothetical flag
come from the form-description module itself (its HYP table), so the
exporter applies no overlay of its own.  The vector names carry the ? of
a provisional name in the table string and none when the operation is
established (v.move.mv, v.mem.ld, v.mem.st: vector.firm_op9).  New or
renamed forms: cmov.ge rd, rs, #imm, ra; cmov.eq rd, rs, rx, ra (register
form); the provisional cmov.leu? / cmov.ltu? / cmov.lt? / cmov.le?; mv rd,
rs (67 c8); bset / btst rd, rd, #pos (3 bytes); lbu.post rd, [rb] += inc
with 5-bit registers (6e q2) and the 23 page as lbu.post rd, [rb] += simm3
(-4..-1); and rd, rs, #0x3fff (67 a4-a7); the 6-byte and rd, rs, #imm16
(74 sub 1); the provisional ctz? / clb? (41 f3); vcfg4c? #0xc with the
hypothetical p_k <- rs; ld46? as a hypothetical byte load with a
post-increment; lbu? rd, off(sp) (ex lb?); addsp sp, #imm (14 8x-fx); fxts
without the ?; halt and sys41 with the empty ESIL; the length leaves make
5c 40-6f a 4-byte beq rA, rB.

scq16_decode.c: a first byte 56 with the top two bits of the second byte
clear is the 4-byte j.d1 when its 22-bit target (from the packet start in
a B slot) is a plausible code address, else a formless 2-byte unit
(without a function table the plugin cannot decide by membership).  Every
ESIL memory access cuts its address to 32 bits: the ESIL machine computes
in 64 bits and aes does not mask addresses, so a negative frame offset
over sp wrapped above 4 GB.  The ? of a vector name now comes with the
table string (scq16_vname_firm).  scq16_arch.inc.c: a unit whose ESIL is
the empty string (nop, halt, ieon/ieoff, loopend, vwait?, sys41) no
longer blocks the ESIL of its packet; the override hook counts as the
unit ESIL; opex named / provisional of a vector op follow the table name.

asm_md32.c: pseudo rules of cmov.ge / cmov.leu / cmov.le (the ? of a
provisional name is stripped before the lookup), sys41, ctz / clb.
2026-11-02 16:26:48 +01:00
n0p f4f11b90c3 md32: tests and docs for the uSIP table update 2026-11-02 06:43:08 +01:00
n0p f58de93399 md32: uSIP table update (760 forms), decoder rules and generator features 2026-11-02 06:43:08 +01:00
n0p 58a5ac18e6 md32: English output text for the scq16 loop, jump and trap forms 2026-11-01 20:21:45 +01:00
n0p 9b0adabca8 md32: tests and docs for the scq16 mode
test/test_scq16.py exercises cpu=scq16 inside r2 with loose bytes only
(disassembly of units, packets, vector operations and bundles; analysis;
ESIL; the pseudo parser) and runs from make test; test/test_md32.c gets
three decode checks.  README section "SCQ16 mode", doc/scq16.md and the
CHANGELOG entry.
2026-11-01 20:21:45 +01:00
n0p 219b1f7c07 md32: scq16 cpu mode (table, decoder, arch and asm)
Add cpu=scq16, the SCQ16 variant of the MD32 family with a byte-granular
packet encoding, as a third cpu of the plugin.

isa/scq16_isa.json is the ISA table (218 forms, 389 bit alternatives, the
length-rule leaves of stand-alone units and packet heads, the vector op9
classes and provisional names, the register names) and
tools/gen_scq16_tables.py generates scq16_opcodes.h from it (the VU scalar
ports as ESIL registers, vector operations as the custom op vop, delayed
transfers as SETJT/SETD, the no-effect system forms and the hypothetical
readings flagged).

scq16_decode.c implements the length and packet rule by first-byte leaves
(stand-alone units, packet heads read shifted by one bit with the borrowed
bit of the B slot, masked orphans, 4-byte vector operations, vector heads,
8-byte bundles), the form match over the transformed unit, the operand
text and the ESIL expansion with the parallel-packet register remap and
the VU scalar-port registers.

scq16_arch.inc.c carries the analysis of the SCQ16 decode (types,
jump/fail with the delay slots counted in instructions, do as a loop
reference, loads/stores, stack ops, opex with the unit/packet/bundle
structure), the ESIL (the scalar forms; a packet as A then B with the
registers B reads and A writes copied to temporaries first; delayed
transfers through SETJT/SETD; the VU ports as registers; vector operations
as the custom op vop, a no-op) and the register profile (sp/lr as
csr14/csr15, a0, the loop registers, the VU ports).  arch_md32.c
dispatches decode, info and regs on cpu=scq16 and registers vop through
esilcb; asm_md32.c gets the SCQ16 pseudo-syntax (packets as
parallel { a; b; }, memory, stack, bit-field and transfer rules).
2026-11-01 20:21:45 +01:00
n0p a1b8861f9d md32: tests and docs for the uSIP table update
Plugin vectors for the loop count, the F' = 0 / h = 1 / m = 1 loops
(validated and unverified), the 4- and 3-unit bz.s (validated and unknown),
beq9sp, the bgt rA, #-1 cell, the W6 h = 1 cells and the loop guard, op2z?,
the h = 1 shifts, the 16-bit lea, the splits (R-slot4n, R-op4imm in 2 and
more units, S0-slot, S3), op72?, saturate?, sat40 H H T T, R-waw with the
P2W prefix, R-b111pre, R-b111ctl, R-bsnext, the omitted weak cell of
R-brHHTT, sub r14, st.w [sp], st.abs hi F' = 0, addq / cell E by value,
mtcsr of the accumulator CSRs, R-1eX0F0, R-movi6d; the lea, loop#, mtcsr,
movi #-32768 / #-32767, ld.h / ld.hu of R-1eX0 / R-ldF0 / R-hhttF0 / R-F0d,
op2z? and two R-waw vectors updated to the new readings; pseudo vectors for
the new rules; README, doc/usip.md (the loop cells, the post-layout splits
and the fusion, the explicit candidates, score rules and layout
constraints, the cells added with the table, the unverified fallback and
the order of the packet-level passes) and CHANGELOG.
2026-11-01 18:45:09 +01:00
n0p 85f40b5d6c md32: uSIP table update (726 forms), decoder rules and generator features
Regenerate isa/usip_isa.json and usip_opcodes.h (52 forms added, 13 retired,
14 modified): the loop #N count is the collected head field (bits 13:5, no
+1), loop #N with the F' = 0 tail exactly at +2, with h = 1 (N >= 128) and
with m = 1 (N >= 256, printed loop #N?), bz.s in 4- and 3-unit packets, the
split entries of the slot family stslot / stslot? / ldslot? (F-slot0,
S0-slot, the S3 cells ldslot/stslot #48-63), the fusion entry
op72? rA, #k, asr#b, op2z? rA, lsl/asr r8-r15, #B, the W6 cells
ld.h/st.h rB, [r8+rrr] and [rA]+ with h = 1, sub r14, #f12/2 with any F/F'
(spfix_sub_sp retired), st.w [sp], #imm14, st.abs with the hi F' = 0,
add rB, rB, #imm27 / st.h? [rB], #sat selected by the immediate value (also
the cell-E triples), add? rB, r15, #rot12 and ld.h? / ld.hu? rB, [r15+off]
with the F' = 0 tail, saturate? rd, rs1, movi #simm6 in the delay slot of a
validated branch, mtcsr #0x30-0x3e, ld.h / ld.hu / lea / movi #-32768 /
#-32767 / ld.hu [rA+rB] without the ?; the constraints of beq_imm8_d (the
op 9 beq.d with base sp and the adjacent tail is not a branch) and of the
seven op a *_s0f1 / *_imm8_F0 entries (the bgt rA, #-1 head class takes
only the adjacent S = 1 tail); the ABI passes eight arguments in r0-r7.

The generator emits the flags FUSE, SPLIT / SPLITBARE (with a USIP_FORM_*
index for every split and fusion entry), the constraint op instr_index,
any with up to four alternatives that may be a context condition or an
instruction position and six new context conditions; the loopn operand
type is the collected field.

The decoder keeps the score in twentieths (al1 = 0.3), adds the explicit
candidates loopcand / R-brHHTT / R-b111pre / R-b111ctl with the b111_layout
context extended to them, the bz.s rules of 4- and 3-unit packets (the rest
re-parsed as the delay slot, the 3-unit one with the target beyond the
packet and no write of rA), the S3 renames and the split pass of the slot
family with the split-tail reading and the nowaw guardian, the fusion after
the renames, R-movi6d, the R-w6h1 loop guard evaluated with the packet being
parsed, the R-loopA adjacency (.word at any distance but +2), rf0dmidwaw,
the score rules R-waw / al1 / R-bsnext / P2W-P2H prefix / sat40 H H T T /
rf0dpen and the instruction position of the renames. The loop entries with
the F' = 0 tail at +2 and the h = 1 heads with the S = 1 tail (and the
adjacent F = 0 tail) are accepted unverified; the m = 1 (loop #N?) and the
other h = 1 entries are not.

The arch plugin reports the stores of an immediate ([rB] / [sp], #imm) with
the value in val and [sp] as a stack access; the new mnemonics keep their
kinds (op2z? / op72? / saturate? are unknown operations). Pseudo syntax for
the stores of an immediate (also to [sp]), the absolute st.abs / ld.abs and
the ? of a count (loop#? #256?).
2026-11-01 18:45:09 +01:00
n0p a8d4a6a520 md32: tests and docs for the uSIP table update
Plugin vectors for the F = S = 0 and R-br0 cells (validated by the session,
rejected with fall-through, unknown backward, unverified forward), ret.s.d,
movi #-1 with F = 0, the op 2 shifts, the open b.s rejected and unverified,
bz.s P5, the m = 1 slots, loop.b1? and the ?ss=N loops, movi? #-32767, the
asr16 clamp, the bit-field pair and the BF_SEL cells, ld.bu/st.b with the
byte displacement, ld.b/st.h with F != S at +2 and the undo at +1, the
ld.h?/ld.hu? of R-hhttF0 / R-F0d, the sp adjustment pair, the ld.w?/st.w?
word classes, .stimm16? and mtcsr? with a named tail; the loop, open b.s,
mtcsr, movhi and save vectors updated; pseudo vectors; README, doc/usip.md
and CHANGELOG (the target validation filter, the address views, the F = 0
branch cells, the split and context groups, the new tie-breaks and what the
plugin can see of the guards).
2026-11-01 18:45:09 +01:00
n0p e108f90f79 md32: uSIP table update (687 forms), decoder rules and generator features
Regenerate isa/usip_isa.json and usip_opcodes.h (56 forms added, 3 retired,
71 modified): the b<cond>.d cells with head F = 0 (bne.d, ble.d, bgeu.d,
bge.d, bne.u8.d, beq.u8.d, bleu.d, read only in the (B class, tail distance)
cells of usip_br0_cells; the five weak cells of usip_br0_cells_weak are never
taken), bgt.d of the F = S = 0 cell back in the table, ret.s.d, loop.b1? and
the ?ss=N loops, bz.s with bit 3 = 0, the ld/st type 111 ld.bu / st.b with
the byte displacement (st.b? retired), ld.b / st.h with F != S of op 1
exactly at +2, ld.h? / ld.hu? with the F' = 0 tail as the second head of
H H T T and by the deferred tail of a head with base sp, the bit-field pair
in H H T T and the BF_SEL cells renamed from .bf?, the 16-bit op 2 shifts
lsl/lsl?/asr/asr? (addi4 retired), ldslot/stslot with m = 1, .stimm16?,
ld.w?/st.w? for the f12 = 1 / 3 mod 4 word classes, add r14 / sub r14,
movi? #-32767, movi rA, #-1 with F = 0, mtcsr? of the accumulator CSRs with
a named 16-bit tail; the known target as a validation filter on the
F = S = 0 cells, bne.d #-1, the loops with the F' = 1 tail, the open b.s and
the near b, with fall-through on failure (USIP_F_GUARDFT); the operand
conventions of six families revised. Thirty-one entries are post-layout
renames.

The generator emits the operand type offb, the flags GUARDFT / B111 / F0CTX
(flags is ut32), the constraint ops br0_cells / br0_cells_live, bf_valid,
the guards tail_named16 and target_packet_start_any_or_function_start, the
any sub-operations packet_len, guard, range and br0_cells, the large value
sets (usip_value_sets), the new context conditions and the tables
usip_br0_cells, usip_br0_cells_weak and usip_c48sym_table; form names are
sanitised into C identifiers.

The decoder implements the fall-through guards, the fifth guard kind with
the optional packet_start_any callback, the R-br0 cells by B class and tail
distance, the b111 group in the 2-unit packet and in H H T T (which now
takes tt = 11 tails), the context conditions b111_layout, hhtt_second_head,
f0d_triple, bfpair, bf_dst_not_written and rest_named_no_q, the f0ctx pass
on the .word pairs and the re-read of the R-F0d middle unit, R-op1fs, the
bz_s_P5 context rule, the m = 1 R7 slots, P2H, R-lr16, R-align48 and
R-c48sym in the score, the b.s guard admitting a function start and the
loop F' = 0 rule by field; immediates glued to a letter or '=' print in
decimal. The forms whose guard is a validation filter keep their reading
unverified when the target is unknown (conditional branches only forward);
a definite "not a packet start" rejects them.

The arch plugin initialises UsipGuardCtx by field, separates "not a packet
start" from "unknown" for backward targets with the lowest packet start
decoded in the session, reports offb as a disp operand in opex and sets the
stack deltas of addsp and the add r14, r14, #imm / sub r14, #imm pairs.
Pseudo syntax for the 2-operand lsl / asr.
2026-11-01 18:45:09 +01:00
n0p 5b9a32f8c4 md32: tests and docs for the uSIP table update
Plugin vectors for the 14-bit word displacement, nop.ctl, the bit-field
family, mtacc?, movi? #-32768, sgt #-1, the register bset/bext, the S0F1
branches (unverified, validated by the session, not validated), the r15-based
loads, .ldF0?, the F' = 0 ld.h?, the 48-bit value table, .3eX0?, the
lsl/sext16/zext16 renames, cop with addi, .hi, movhi with the tt = 10 tail
and .op4t0; the op8 slot split vector updated; pseudo vectors; README,
doc/usip.md and CHANGELOG (the post-layout renames, the K-tie cascade and
what the plugin can see of it, the extended target-guard fallback).
2026-11-01 18:45:09 +01:00
n0p 71ab77c46b md32: uSIP table update (634 forms), decoder rules and generator features
Regenerate isa/usip_isa.json and usip_opcodes.h (52 forms added, 12
retired, 103 modified): the 14-bit word displacement of the two-unit
ld.w/st.w, nop.ctl, the bit-field family fxtu/fxts/fup, movi? #-32768, the
register bset/bext, mtacc?, sgt #-1 with F = S = 1, addi #32 next to cop,
the 16-bit lsl/sext16/zext16 variants, the r15-based loads, .ldF0? and the
F' = 0 ld.h?/ld.hu?, .3eX0?, the b<cond>.d cells with the [0][1][tt] tail at
+2, movhi with the tt = 10 tail, the 48-bit constants admitted by value, the
double-class split; the .hi/.hilo pair entries and every not_hi1010
constraint are gone. Twenty entries are post-layout renames.

The generator emits the rename_from lists, the constraint ops tail_adjacent,
ieee_short and the 48-bit value table membership, the tail_adjacent
sub-operation of any, the context conditions cop_rA_in_packet and
not_c48_lo_follows, USIP_MAXVALS 12 and the tables usip_never_tail,
usip_never_head_with_tail and usip_c48_table; the rename entries are exempt
from the 16-bit position-class checks.

The decoder implements W14, the never-tail and never-head-with-tail units
from the tables, H1 (the forced hi(1010) decode is gone; .hi/.lo only after
a 48-bit-family head in the packet), the 48-bit value table in the partial
admission, P2W (no alignment penalty for the 2 mod 4 word offsets in the
H H T T layout), callin through a new guard callback, the post-layout
renames and the K-tie cascade: dedup and nowaw on the tied readings of the
packet, du2 over the neighbouring packets the caller supplies (packet_at /
branch_target callbacks, first-pass readings with USIP_GUARD_NO_CASCADE).
UsipPacket reports how a tie was decided; a failed guard of the op C
compare-and-branch cell prints the pair as .dsp. The unverified fallback
accepts the S0F1 cells whose unverified readings are right in nearly every
case and loop rX with the F' = 0 tail when the head has F = 1 and the S = 1
tail sits at +2.

The arch plugin answers the cascade callbacks with the packets decoded
earlier in the session, the first-pass readings of the packets inside the
bytes at hand and the branch targets seen so far, reports the tie-break in
opex, sets ireg for the r15-based loads and types fxtu/fxts as cast and fup
as or. Pseudo syntax for fxtu/fxts/fup, mtacc, the 2-operand addi,
sext16/zext16 and asr16; nop.ctl reads nop.
2026-11-01 18:45:09 +01:00
n0p b6da363492 md32: tests and docs for the uSIP table update
Plugin vectors for loop# (validated at +1 and +2, unverified), b<cond>.l
(validated, unverified, not taken, 64-bit), the signed 64-bit pairs, the
negative offsets, seq/sle/sgt, movhi, the 16-bit first-slot st.h, the
deferred st.h and its undo by a validated b.s, H H T T, the op8 split, the
0e10 trio, cop with F = S = 0, xor, movi rA!, bset rd!, osl and the
cmulr16/cmuli16 names; the jr, ld.d, movhi and bank-bit vectors updated;
pseudo vectors; README, doc/usip.md and CHANGELOG.
2026-11-01 18:45:09 +01:00
n0p 4932f31af9 md32: cmulr16/cmuli16 names follow the little-endian data memory
The names of 0xDA00 (cmulr16, a*c - b*d) and 0xDC00 (cmuli16, a*d + b*c)
follow the little-endian layout of the data memory: the high half of a 32-bit
complex word is at +2 and holds the real part. The earlier assignment assumed
a big-endian data memory.
2026-11-01 18:45:09 +01:00
n0p cdd0753019 md32: new uSIP mnemonics and conditions in the arch and asm plugins
Conditions bequ/bneu of the 48-bit forms, types for sle (cmp) and osl (shl),
val = N for loop #N, the signed offsets as disp operands in opex; pseudo
syntax for loop#, sle, bequ/bneu, the 2-operand xor, mfacc, the bset family
and osl; the ? marker is stripped repeatedly and ld.d/ld.w are not
sign-extended.
2026-11-01 18:45:09 +01:00
n0p 8b98f544d7 md32: uSIP table update (594 forms) and prior-free packet layout
The uSIP table grows to 594 forms (137 added, 18 retired, 76 modified): the
48/64-bit b<cond>.l prefix forms with the complete condition table, loop #N,
the op 6 set-on-compare family, movhi by its 20-bit value, the 48-bit
constants by one formula, the signed ld.d/st.d, the closed negative
half-word and word offsets, the deferred st.h tail, the position cells and
the slot split.

The generator gains the operand types offh/offw/loopn and the redefined
movhi, the flags ADJDEF/PREFIX/RENAME/HHTT, 8 ranges per field, 64-bit
entries, the constraints gt/odd/packet_len_ge/head_index/head_pos_ge/ctx and
the b.s guard, any with up to three alternatives, the bcc48 condition table
and save w=4.

The decoder matches the prefix forms before the layout, ranks the readings
with the prior-free total order (s0, I, Fv, -A, K) instead of the enumeration
order and the group count, and implements the grammar rules (5e0d never a
tail, the deferred st.h tail with its undo and the validated-b.s guard, the
.d SP-negative rejection, the 3-unit and H H T T candidates with the forced
decode of hi(1010) heads, the 0e10 trio, the loop #N adjacency, the op8
split), the new penalties, the deferred constraints with fall-through, the
late guard evaluation, three tails for the 64-bit forms and the unverified
fallback for the prefix forms and loop #N.
2026-11-01 18:45:09 +01:00
n0p 4ad1a62408 md32: docs for the uSIP table update
README uSIP mode: the F' = 0 control tails, the target guards and what the
plugin can check, the new mnemonics and analysis types.  doc/usip.md: the
packet-model rules R0/R7, the table additions (movhi, base/offset, scale, the
new constraints, kinds io/jr), confidence census, ABI without a classic CSR
bank, and a section on the target-guard knowledge and the fallbacks.
CHANGELOG entry.
2026-11-01 18:45:09 +01:00
n0p 39458c3b5b md32: tests for the uSIP table update
test_plugin.py: vectors for ior/iow, nop32, the 32-bit ret of the sys shape,
jr?, addsp, ld.d?, the first-slot ldslot/lea? forms, movhi? and the guarded
3-unit control packets (loop with the tail at +2 and the end at the next
packet, beqz.d validated by a forward packet start and read as data when the
target is not one, call with the F' = 0 tail read unverified); the mov32 and
ld.b vectors show the bank bit on the register it applies to (r15!).
test_parse.c: the new pseudo rules.
2026-11-01 18:45:09 +01:00
n0p b07fcf44b1 md32: new uSIP mnemonics in the arch and asm plugins
arch_md32.c: operation types for the forms of the updated table: io for
ior/iow (ireg = the port register), rjmp for jr? rB (register jump with the
delay slot of a return), ret for rti, trap for trap?, nop for nop32, add for
addsp, lea for lea?, cmp for sne/scmp?, cast for extu, refptr 8 for the
ld.d?/st.d? pairs; the mnemonic test ignores the trailing ? of the medium
forms; extended CSR names in opex.

asm_md32.c: pseudo syntax for ior/iow, mfcsr/mtcsr, addsp (sp += / sp -=),
ldslot/stslot, jr, nop32, sne, scmp, movhi, extu, cop, rti, ieon/ieoff, idle,
isync, lpexit, trap and the 64-bit loads/stores; the trailing ? marker of
lea?/jr?/call? is ignored.
2026-11-01 18:45:09 +01:00
n0p 58536ef4e9 md32: uSIP table update (475 forms), generator features and decoder rules
isa/usip_isa.json goes from 386 to 475 forms (110 added, 24 retired, 140
modified): port I/O ior/iow instead of mfcr/mtcr, mtcsr and mfcsr with F' = 0,
the sys shape split by its tail field (cop, rti, lpexit?, isync?, ieon, ieoff,
trap?, sys?, ret, ret?, jr?, call rB), nop32, cmov r15, add rB, rA, #rot12 for
the whole op 0 cell, sne, scmp?, movhi?, extu, movi #-1, addsp, lea?, the
stack-slot closers (ldslot/stslot, .slot?, lsl #1/#2, movi #simm6, .bit4?,
.ext8?), ld.d?/st.d? (64-bit pairs), st.b?, ld.hu for type 110, unsigned
12-bit ld/st offsets, ld.bu in the class-E cells, per-operand bank bits
(rB! by x, rA! by m, rs1! by ss), save w=2 = four words; the 48-bit call with
the far tail is retired (those packets are call/b with the F' = 0 tail at +2).

tools/gen_usip_tables.py: the movhi operand type, base as a constant added to
register/immediate fields, scale on immediates, the ge and any constraints,
membership masks for the large CSR sets, the target guards as constraint
records, flag USIP_F_ADJ2, kinds io/jr, the sys name table, extended CSR names
and kind names.  The header stays byte-identical on regeneration.

usip_decode.c: packet guards, adjacency rule and tie-breaks.  F' = 0 control
tails exactly at +2 (otherwise data), target guards evaluated after the mask
match (32-bit forms: a failure is .word, no fall-through; the 16-bit call.s
falls through), packet_len constraints with the real packet length so that
the stand-alone closers never count as named 16-bit ops, closers matched with
bit 15, rules R0 (the final closer may be its own group) and R7 (first-slot
ldslot/stslot/lea? when the rest of the packet is named), the 1dX6 + named
tail and validated-guard tie-breaks; the enumeration order is unchanged.

The decoder asks the caller about branch targets through UsipGuardCtx.  The
arch plugin answers packet starts from the stream: the packets decoded so far
in the session and a scan of the bytes radare2 hands it (64 bytes of
lookahead).  Function starts are not available to an arch plugin, so the
decoder applies a documented fallback: the call / b / compare-and-branch with
immediate forms whose F' = 0 tail sits at +2 and beqz.d are read unverified
(trailing ?, confidence medium, opex.target_guard = unverified); loop, far b,
bnez.d, the register compare-and-branch and the open-packet call.s are
treated as a failed guard.
2026-11-01 18:45:09 +01:00
n0p 3dfb0180d0 md32: changelog note for the emulator test expectation in usip mode 2026-11-01 18:45:09 +01:00
n0p 73831a1ee2 md32: emulator test expects the delayed-return stop in usip mode
With the packet decoder, 5ef9 is ret.d and the rest of the packet is its
delay slot, so md32-run stops with unsupported_delay_slot_execution and
zero completed steps, exactly as for the MS15E30 delayed branch.  README:
make test passes against radare2 6.2.5 on Linux as well.
2026-11-01 18:45:09 +01:00
n0p 68e9f6dfe3 md32: six group-5 16-bit forms missing from the MS15E30 table
rem16, ctz16 and the four complex half-word products (cmulcr16, cmuli16,
cmulr16, cmulci16) occupy 0xCA80-0xCABF, 0xCB00-0xCBFF and 0xD800-0xDFFF,
which the public table leaves undecoded.  Names and operand order follow
the neighbouring group-5 forms; the semantics are inferred from usage
(rem16 as a non-negative modulo, the cmul* variants as the cross-sum and
straight-difference terms) and are marked as such in the source.
2026-10-30 19:53:17 +01:00
n0p 2c54fda563 md32: document the uSIP mode
README: the uSIP mode section (packet model, what one pd line is,
mnemonics and operands, analysis, limitations) replaces the partial
support notes; build note for radare2 6.2.2.  CHANGELOG entry.
doc/usip.md: table format, constraint and context-rule semantics,
confidence levels, ABI, known limitations of the table-driven reading.
2026-10-30 16:28:21 +01:00
n0p a0ccecf534 md32: uSIP packet vectors in the plugin test
Exercise the usip mode on real packets: conditional branch with its tail,
b.s with a 48-bit delay-slot op, call with the S S O O layout (.unit
tails, delay = 3), interleaved 48-bit call.abs, hardware loop reference,
ret.d, the two-unit bz.s context rule, a truncated packet at the end of
the buffer, save/restore/ret and basic blocks that keep the delay slot.
2026-10-30 16:28:21 +01:00
n0p e94cc3060d md32: uSIP pseudo syntax
Pseudo rules for the uSIP mnemonics: # immediates, [base+off], [base]+
and [sp+off] memory operands, compare-and-branch, ld/st as dmemN[...],
movi/mov32, ALU, cmov, loop, save/restore.  test_parse.c updated.
2026-10-30 16:28:21 +01:00
n0p ac1af9c612 md32: wire the uSIP packet decoder into the arch plugin
In usip mode the plugin decodes whole packets (cached per session, 64
entries) and emits one op per run of adjacent units of the same
instruction; displaced tails become .unit ops that name their head.
Types, conditions, jump/fail/delay, loads/stores, immediates, save and
restore, sys and loop references come from the table; opex reports the
form, its confidence, the slot, the unit addresses and the packet
summary.  MAXOP_SIZE is 16 in this mode and regs() exposes the ABI.
The previous five hard-coded uSIP patterns are replaced by the table.
MS15E30 decoding is unchanged.
2026-10-30 16:28:21 +01:00
n0p 94bccea25c md32: table-driven VLIW packet decoder for uSIP
usip_decode.c reads the 16-bit big-endian units of a packet (closed by
bit 15), enumerates the group splits and head/tail assignments the table
allows (heads first, tails round-robin), scores them (unknown units,
instructions, groups, documented tie-break penalties), applies the
adjacency and context rules and returns one instruction per head with
the addresses of its units.  Control flow is restricted to slot 0 and
the rest of an open packet is its delay slot.
2026-10-30 16:28:21 +01:00
n0p 3f8dada173 md32: add the uSIP instruction table and its header generator
isa/usip_isa.json describes the uSIP (MD32 family, VLIW packet variant)
instruction set: 386 forms with masks, operand fields, constraints,
packet rules and a confidence level, plus the packet model (unit scan,
head/tail layout, tie-breaks, context rules) and the register/CSR model.
tools/gen_usip_tables.py generates usip_opcodes.h from it: every field
referenced by a format string or a constraint, constraints as structured
UsipCons records, 16-bit flags and the indices of the context-only forms.
2026-10-30 16:28:21 +01:00
pancake a21d29689b Add support for md32 architecture 2026-10-30 10:31:15 +01:00
pancake 099cb94abf Initial import of the gamegear emulator 2026-10-29 13:35:02 +01:00
pancake de674fbeb0 Add gameboy emulation documentation 2026-10-29 13:30:02 +01:00
pancake f81d48eaca Add gameboy usleep delays 2026-10-29 13:16:44 +01:00
pancake 610dd48707 Fix standalone r2gb test loading and ignore build outputs 2026-10-27 00:35:12 +01:00
pancake c6663b87e9 Initial import of the r2gb plugin 2026-10-27 00:30:24 +01:00
pancake f7dca9d52b Add asynchronous PCM streaming through auq 2026-10-27 00:28:32 +01:00
pancake f2a4b1dfa0 Fix the arpeggio demo 2026-10-26 23:37:46 +01:00
pancake b5b1101110 Fix the doom song 2026-10-26 23:30:34 +01:00
pancake 445c6a5a57 Fix build of r2au 2026-10-26 23:08:44 +01:00
Ricardo J. Rodríguez 5ab2c6aa7d msl: follow spec 1.1.1 register names and thread states
Thread Context (0x0011) changed in Memory Slice spec 1.1.0/1.1.1:
register names are now normative (Table 19g) and the block gained
Suspended/Partial flags, thread states 0x05-0x07 and a per-thread Arch
byte at +0x13.

debug.msl: map the ARM64 aliases fp/lr (and cpsr) that 1.1.0 producers
could write to x29/x30/pstate when seeding (consumer rule 29), using the
thread's Arch byte with the file header as fallback. `dpt` derives the
status letter from ThreadState (r/S/s/z) instead of only the Current flag.

core.msl (`dgm`): never write the fp/lr aliases on ARM64, tag the frame
pointer, status and link registers via r2's BP/SR/LR aliases, and set
Suspended alongside Current since the registers come from a halted
debuggee.
2026-10-26 18:38:36 +01:00
dependabot[bot] 1e989215d9 Bump libc from 0.2.190 to 0.2.191 in /x86iced
Bumps [libc](https://github.com/rust-lang/libc) from 0.2.190 to 0.2.191.
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Changelog](https://github.com/rust-lang/libc/blob/0.2.191/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.190...0.2.191)

---
updated-dependencies:
- dependency-name: libc
  dependency-version: 0.2.191
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
2026-10-26 13:48:46 +01:00
dependabot[bot] a2692a2380 Bump libc from 0.2.172 to 0.2.190 in /x86iced
Bumps [libc](https://github.com/rust-lang/libc) from 0.2.172 to 0.2.190.
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Changelog](https://github.com/rust-lang/libc/blob/0.2.190/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.172...0.2.190)

---
updated-dependencies:
- dependency-name: libc
  dependency-version: 0.2.190
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
2026-10-13 08:46:15 +02:00
pancake 614d94959e r2ida: import IDB C types into radare2 scripts 2026-09-27 07:36:17 +02:00
pancake 7a0269097b Fix PowerPC disassembler plugin 2026-09-27 07:14:34 +02:00
pancake c8f032c01d Fix MicroBlaze plugin build 2026-09-27 07:05:38 +02:00
pancake 188d102f6b Initial chrome devtools interface for radare2 2026-08-31 19:22:37 +02:00
Abhi 3275d32127 Build CI plugins from checkout 2026-07-29 15:13:39 +01:00
Abhi f4218097d2 Use radare2 GitHub Action in CI 2026-07-29 15:13:39 +01:00
Abhi 96dbf53b1c Fix x86iced for r2 6.1 ABI 2026-07-29 15:13:39 +01:00
pancake e3111fcba3 Remove the r2jadx attic 2026-06-27 18:51:29 +02:00
dependabot[bot] 5b0ea473f9 Bump libc from 0.2.154 to 0.2.172 in /x86iced
Bumps [libc](https://github.com/rust-lang/libc) from 0.2.154 to 0.2.172.
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Changelog](https://github.com/rust-lang/libc/blob/0.2.172/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.154...0.2.172)

---
updated-dependencies:
- dependency-name: libc
  dependency-version: 0.2.172
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
2026-06-27 18:39:34 +02:00
f28a2ec94c Add plugins for memory slice (msl)
* msl: add Memory Slice (.msl) plugins (io/bin/debug/core)

Loadable radare2 plugins for the Memory Slice process-dump format:

- io_msl    open a slice as a process address space (msl://); verifies
            the SHA-256 block chain and End-of-Capture FileHash on open,
            warning on a truncated or tampered slice
- bin_msl   parse a slice as a CORE object (arch/bits/os, entry, maps)
- debug_msl emulated ESIL debug backend, incl. reverse exec (dsb/aesb)
- core_msl  producer: "dgm"/"dgma" write a slice from a live debug session

Build/install with the local Makefile (pkg-config r_core) or via r2pm.
test/genmsl.py emits a valid synthetic slice for exercising the read path.

* msl: select and list captured threads in the debug backend

A slice can capture several threads (one Thread Context block each); the debug
backend only seeded the Current thread. Expose every captured thread:

- .threads callback: `dpt` / `dptj` lists each captured thread with its PC.
- .select callback: `dpt=<tid>` re-seeds the register file from that thread
  and seeks to its captured PC, so any thread can be emulated.

msl_seed_regs now takes a target tid (>=0 exact, <0 Current with first-thread
fallback) and reports the chosen tid, which msl_ensure stores in dbg->tid.

Also fixes a double-unref of the mmap buffer (msl_seed_regs used to unref a
buffer owned by its caller), and accounts for r_debug_select swapping the
register arena after .select returns (seed both arenas so the new thread's
registers survive the swap). test/genmsl.py gains --mt to emit a second,
non-Current thread for exercising listing and selection.

* msl: resolve module symbols and PE exports in bin.msl

The bin plugin presented a slice as maps only. Parse ModuleEntry (0x0002)
blocks and expose them as libraries (`il`) and symbols (`is`): one symbol per
module base plus, for PE images whose headers are captured, one FUNC symbol per
exported function at its address. A VA->file-offset translator over the
captured-run maps reads the module image (DOS/PE headers, export directory).
radare2 then names call targets -- `sym.kernel32.dll_CreateFileW` -- instead of
bare addresses.

test/genmsl.py gains --pe (a minimal in-memory PE export table) and a
memory_region() helper. ELF .dynsym resolution is left to the Python tools.

* msl: note thread listing/selection in the plugin table

The debug.msl row documented reverse execution but not the `dpt` / `dpt=<tid>`
thread listing and selection; mention it for consistency with the body.

---------

Co-authored-by: Ricardo J. Rodríguez <ricardo@thanatos>
Co-authored-by: Claude Opus 4.8 (1M context) <[email protected]>
2026-06-27 09:51:49 +02:00
pancake 80925aeba6 r2jadx: Use r2.log instead of console.log 2026-05-11 15:44:41 +02:00
pancake 45f9bc841c r2jadx: Use better r2js and improve xrefs caching and more 2026-05-11 12:09:41 +02:00
pancake 69f93467a1 r2jadx: refactor into separate files 2026-05-11 07:53:17 +02:00
pancake 67b24be239 r2jadx: add -s to search words 2026-05-11 07:43:26 +02:00
pancake cd9cc5c190 r2jadx: add pd:j alias 2026-05-11 07:26:42 +02:00
pancake 568a7fd146 r2jadx: config -e with optable color and addresses 2026-05-11 07:22:21 +02:00
pancake d276feb5e8 Fix help message for r2jadx 2026-05-11 06:11:22 +02:00
pancake c3b9864f1d Rewrite r2jadx to typescript 2026-05-10 09:57:56 +02:00
Nerijus Bendžiūnas 7a6e3737c8 fix(r2k): allow Linux module to compile using clang
__FORCE_ORDER is a GCC-specific input constraint not supported
by clang. Use a "memory" clobber on clang instead.

Signed-off-by: Nerijus Bendžiūnas <[email protected]>
2026-02-28 17:46:22 +01:00
pancake 430b6fa559 Minor fix for the rar cpu code 2026-01-09 07:29:22 +01:00
pancake 1cf58513ad Fix r2doom build 2025-10-03 23:15:11 +02:00
Takumi Matsuura da8623bdbe Change to prioritize using uv 2025-10-03 13:58:38 +02:00
pancake 43057468c6 Add r2604 badge 2025-09-30 14:07:19 +02:00
pancake 7ed4cb393f Assume keys in afen can have spaces 2025-09-30 14:05:07 +02:00
pancake 031b7c20c0 Implement 'afen*' command to dump the database 2025-09-30 14:01:32 +02:00
pancake 9edd5e922b Release 6.0.0 2025-09-22 18:38:39 +02:00
satk0 dea1f62f8f Remove global var in afen 2025-09-22 15:54:03 +02:00
pancake e9306ef9fe Fix x86iced build for r2-6.0 2025-09-16 17:10:17 +02:00
pancake 941e0e8f81 Fix the VC4 build 2025-09-16 16:41:11 +02:00
satk0 fdcf847944 Make afen work 2025-09-16 15:41:57 +02:00
pancake e9035eda1c Rewrite all the asm plugins into arch ones 2025-09-04 12:08:37 +02:00
pancake f2d4e0d371 Fix vc4 build 2025-09-04 11:17:25 +02:00
pancake f06bef6f21 Do not build afen 2025-09-04 01:06:35 +02:00
pancake aac87e940d Fix build of the bin.gguf plugin 2025-09-02 19:38:24 +02:00
Abhi 6c0afb35c2 r2angr: fix latest cmake issues on termux (#386)
* fix latest cmake issues on termux

Affected packages: unicorn, pypcode

* pin angr version

angr since `9.2.155` moved to rust toolchain, which can't be compiled in termux due to bug in rustc not us.

* Update angr

just in case user installed r2 from package manager

* small fixes

* fix: illegal number

```shell
r2angr: 8: [: Illegal number:
```
2025-08-30 01:39:59 +02:00
pancake 1b276095d4 Add a chiptune song created with r2ai 2025-08-27 18:33:22 +02:00
pancake e90d99b9f4 Add more openai-generated versions of the "doom song" 2025-08-27 18:06:47 +02:00
pancake e0bb03cdd1 Fix r2au for the r2-6.x 2025-08-27 17:38:01 +02:00
pancake 6c9df38c66 FIx vc4 and blackfin 2025-03-13 19:27:49 +01:00
pancake 38e79b50b1 Fix build with latest r2 from git 2025-03-12 16:28:10 +01:00
pancake b03125fc99 Move rlcc from libr/egg/rlcc and shlr/mpc 2025-02-06 23:02:37 +01:00
pancake 36f9503eda Fix gguf plugin name 2025-02-06 19:18:10 +01:00
pancake 3a25b7f345 Fix hexagon install 2024-12-11 15:31:52 +01:00
pancake b91c295be3 Remove awful function and warning from squashfs 2024-12-04 16:47:19 +01:00
pancake 9e4c70872e Fix build of fs-squashfs 2024-12-04 11:50:32 +01:00
pancake 94f8d2dc94 Update build instructions for the r2k plugin 2024-12-02 15:37:00 +01:00
pancake 89624cc37c r2k: Fix write on protected regions, lock RCU when acessing tasks fixing races 2024-12-02 15:32:27 +01:00
NighterMan 42aed83113 Fix r2k-linux build on latest Linux kernels 6.4.x 2024-12-01 23:52:32 +01:00
pancake 4d944cce9a Release 5.9.6 2024-11-05 18:30:09 +01:00
pancake 49a91651d2 Fix invalid pfb string in r2svd when the bitstruct have 0 fields 2024-10-31 08:50:51 +01:00
Roman Valls Guimera 3596e7f1a5 Repoint cmsis-svd repo to upstream cmsis-svd org 2024-10-22 06:52:53 +02:00
Abhi 54ff412976 Fix setup on termux (#367)
* Fix installation on termux
* remove binutils & build-essential
  * They should already be present if the user has installed R2.
* remove un-necessary install
2024-10-21 17:49:49 +02:00
dependabot[bot] 3d2fa7985b Bump serde_json from 1.0.124 to 1.0.132 in /x86iced
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.124 to 1.0.132.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.124...1.0.132)

---
updated-dependencies:
- dependency-name: serde_json
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-10-21 17:49:10 +02:00
pancake 3064bbcb7f Fix license names 2024-10-21 17:48:39 +02:00
pancake 97d8b87bf5 Fix license name for blackfin 2024-10-21 17:48:35 +02:00
pancake 26450ea9b9 Fix the CI 2024-09-30 20:10:22 +02:00
pancake 14d385082c Inverse r2 version check for r2svd 2024-09-30 13:10:12 +02:00
pancake 3a92956545 os.path.join is UB. thank you py3 2024-09-30 12:41:05 +02:00
pancake 5ef0b34d57 Install r2svd with symlink 2024-09-30 12:30:36 +02:00
pancake 57f3c159e0 Setuptools is dead, not just deprecated. workarounding with more hacks 2024-09-30 12:26:21 +02:00
pancake 991ee0f685 Setuptools was deprecated, so we need it now 2024-09-30 12:19:41 +02:00
pancake 4e72a04103 Join paths properly 2024-09-30 12:16:14 +02:00
pancake 9a61bb6f7d Use our cmsis-svd fork 2024-09-30 12:15:39 +02:00
pancake 9c22aa709d Parse register fields and support ascii art stuff for r2svd 2024-09-29 19:23:14 +02:00
Roman Valls Guimera ccefb4237d Fix setuptools deprecations and switch to version-1.0 of cmsis_svd 2024-09-29 12:11:59 +02:00
Roman Valls Guimera ef93ab4c91 Deprecate setuptools:
% r2svd --help
/Users/rvalls/.local/share/radare2/prefix/bin/r2svd:9: DeprecationWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html
  import pkg_resources
2024-09-29 12:11:59 +02:00
sha0coder 496b46918b r2ida first version 2024-09-27 22:05:03 +02:00
Nitan Alexandru Marcel 82b3a8e97d Use TMPDIR env or fallback to /tmp for temporary log file (#360) 2024-09-05 16:27:41 +02:00
pancake 0350bec1e7 One venv for angr and arg for structurer 2024-08-31 16:18:57 +02:00
pancake 6e06bcd365 Force the latest capstone to fix angr on arm64 boxes 2024-08-31 16:11:48 +02:00
pancake b170500a27 Honor R2_BADDR in r2angr if set 2024-08-29 20:54:47 +02:00
pancake ece2da866a Show r2poke version 2024-08-29 20:53:41 +02:00
pancake fecf53943b Enable the alien tokens for gnupoke4 2024-08-29 20:53:36 +02:00
pancake dda5cb2d70 Improved output and hints for r2angr 2024-08-29 18:31:16 +02:00
pancake ebe772353a oops 2024-08-29 18:22:22 +02:00
pancake d6f4f63aca Add r2angr wrapper script for decompiling 2024-08-29 17:55:45 +02:00
pancake 343dce1014 atombios not ported, but at least dont break the build 2024-08-26 10:55:50 +02:00
dependabot[bot] 3bb3fbf753 Bump serde from 1.0.201 to 1.0.208 in /x86iced
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.201 to 1.0.208.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.201...v1.0.208)

---
updated-dependencies:
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-08-19 10:53:02 +02:00
dependabot[bot] 42131f6bd6 Bump serde_json from 1.0.117 to 1.0.124 in /x86iced
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.117 to 1.0.124.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.117...v1.0.124)

---
updated-dependencies:
- dependency-name: serde_json
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-08-19 09:25:47 +02:00
satk0 663b25a8fc Make afen function specific (#351) 2024-08-01 22:43:01 +02:00
pancake b0f48b0194 Support GNU Poke4 for r2poke 2024-07-11 17:08:10 +02:00
satk0 6e4ece2732 Fix rparse to rcore binding for afen (#346) 2024-06-25 18:07:32 +02:00
Sylvain Pelissier 628a9d20d0 Update ci.yml with afen plugin
Add r2afen build in CI.
2024-05-22 08:16:50 +02:00
pancake 315256b0ef Release 5.9.0 2024-05-21 17:18:27 +02:00
satk0 eef6f4a39f Fix to make afen installable 2024-05-20 17:38:01 +02:00
satk0 306cc36d80 Add possibility to build afen plugin 2024-05-20 07:36:08 +02:00
satk0 39f897acfe Mention pancake help in README 2024-05-20 07:36:08 +02:00
satk0 33c681dadf Add an example usage 2024-05-20 07:36:08 +02:00
satk0 fd6d8979ea Add afen plugin 2024-05-20 07:36:08 +02:00
Sylvain Pelissier 167e5c48b2 Update ci.yml with VC4 test
Brings back the VC4 test in CI.
2024-05-13 08:17:46 +02:00
Sylvain Pelissier 82d0276127 Update ci.yml with x86iced plugin
Add x86iced pulgin in CI.
2024-05-12 07:40:36 +02:00
GRAUX Pierre d9273fc53e Enable CI for vc4 plugin 2024-05-11 23:49:37 +02:00
GRAUX Pierre 26d8b75ffe Remove compilation warnings for vc4 plugin 2024-05-11 21:12:56 +02:00
GRAUX Pierre fc38eb7862 Add instruction analysis information for vc4 plugin 2024-05-11 21:12:56 +02:00
GRAUX Pierre da11f75c73 Translate the vc4 plugin from asm to arch 2024-05-11 21:12:56 +02:00
pancake 7be547f648 Some minor improvements for r2jadx 2024-05-10 20:37:25 +02:00
Richard Patel 31fba0eafd x86iced: add register access info 2024-05-09 08:37:58 +02:00
Richard Patel 77269480b3 x86iced: support mnemonic 2024-05-09 08:37:58 +02:00
pancake 8903ddf7ef r2sarif is now in a separate repository 2024-05-09 01:59:40 +02:00
Richard Patel a88eecf962 x86iced: fix crash 2024-05-08 14:54:20 +02:00
Richard Patel f912df64a2 x86iced: add metadata
- Enable Dependabot so we get automatic PRs for iced-x86 updates
- Add Cargo metadata (disable publish, MIT license, description)
2024-05-08 14:54:20 +02:00
pancake 6dd7921729 Rename r2iced to x86iced 2024-05-07 17:42:37 +02:00
pancake ae05525a78 Add makefile for r2iced. Rename to x86-iced 2024-05-07 17:02:03 +02:00
Richard Patel 78f4e70ca7 r2iced: support AT&T, masm syntax 2024-05-07 15:59:51 +02:00
Richard Patel ec94bfcd50 Add r2iced 2024-05-04 14:24:13 +02:00
Sylvain Pelissier 6de9a49e88 Update ci.yml
Bring back blackfin build in CI
2024-05-01 14:30:39 +02:00
GRAUX Pierre a36564eaa9 Fix blackfin plugin compilation 2024-04-29 18:05:22 +02:00
pancake ccc7d46e92 Initial work to support revng decompiler for r2, for now just a docker image 2024-03-29 17:36:39 +01:00
pancake 6c21ca2a7d Implement sarif -i to import findings 2024-03-10 20:20:56 +01:00
pancake adf9e7aca8 Make rules supported by sarif generic from external file instead of hardcoded 2024-03-10 20:08:16 +01:00
pancake d1f90741b0 Initial working version of Sarif and add a couple of finding types more 2024-03-01 16:59:06 +01:00
pancake bb15dc4562 Add Makefile, readme and some more code for the Sarif plugin 2024-02-29 12:43:03 +01:00
pancake 90567f4c80 Add sample sarif script for r2 2024-02-19 19:41:16 +01:00
silur e8d1cb20b2 remove libr/asm/arch/evm 2024-02-09 23:26:29 +01:00
pancake 98e6d29133 leftover? 2024-02-07 09:42:51 +01:00
pancake e5ef780da8 Rewrite the r2jadx plugin into r2js
* nodejs code was broken because syspipe was no longer compatible with latest node
* This is very experimental
2023-12-05 20:28:35 +01:00
pancake 6f8c8f0836 Initial import of the GGUF bin plugin 2023-11-21 11:26:25 +01:00
Sylvain Pelissier c28cf25f7a Fix CI badge 2023-10-30 21:48:26 +01:00
Sylvain Pelissier 6a7a636ebe Update ci.yml with asahi plugin
Add asahi build in CI
2023-10-23 13:38:20 +02:00
pancake e3b6897bda apt update 2023-10-19 21:39:01 +02:00
pancake 209c82d674 Bump ubuntu and checkout version 2023-10-19 21:37:46 +02:00
pancake e68f98a223 Fix build of the asahi plugin 2023-10-19 21:30:18 +02:00
pancake 84aa166231 r2ai has been permanently moved into its own repository 2023-10-16 14:37:20 +02:00
pancake a005f0402b Add support for tinyllama queries 2023-10-16 14:30:18 +02:00
pancake 1a1e68a882 Remove unused code_interpreter.py 2023-10-16 01:35:46 +02:00
pancake 68a8e3d4e5 Add conversational example and refactoring the templater logic in r2ai 2023-10-10 00:18:02 +02:00
pancake 7d6afc0855 Support multiple AIs instances 2023-10-09 21:31:13 +02:00
pancake a0fd4013b0 Always decolor the command queries and improve <<SYS>> prompt 2023-10-09 20:43:44 +02:00
pancake dd78a53a1a Fix r2ai from shell 2023-10-09 18:58:19 +02:00
pancake 5a13ac3032 More cleanup and tweaks for r2ai 2023-10-09 12:37:33 +02:00
pancake d3fe9b7223 Use r2lang.cmd if needed 2023-10-09 12:14:22 +02:00
pancake 90b782e683 Add uninstall target 2023-10-09 12:06:33 +02:00
pancake 36feb1733c Add make user-install 2023-10-09 12:06:01 +02:00
pancake 0fd38b8121 Add live mode option to fully integrate r2ai with r2js 2023-10-09 11:53:07 +02:00
pancake 229188050e Remove r2ai/cli 2023-10-09 10:54:32 +02:00
pancake 31a841c561 Use rlang if available, so we can register a core plugin for r2ai 2023-10-09 10:48:33 +02:00
Sylvain Pelissier 5469876cfa Remove r2yara from ci.yml
Now in it's own package
2023-10-06 22:19:51 +00:00
pancake 8c90086fc2 Remove r2yara because it's now living in its own repo
* https://github.com/radareorg/r2yara
2023-10-06 16:45:29 +02:00
Sylvain Pelissier 82734d3371 Uptade CI 2023-10-03 10:09:44 +00:00
pancake edeadec44c Add 'model' command and bring back the hugging face download 2023-10-03 00:44:47 +02:00
pancake d5a88f6b41 Fix yara 'scan S' regression and add short command 'yr' 2023-10-02 12:29:33 +02:00
pancake 4f67e1af9a Add yara version command in r2yara 2023-10-02 12:08:26 +02:00
Sylvain Pelissier e1ace49642 Update core_yara.c
Fix options parsing.
2023-10-02 09:35:24 +00:00
pancake 046db11e95 Fix segfault in yara scan 2023-10-02 11:22:46 +02:00
pancake e1edea1405 Prepend cwd in model path 2023-09-29 02:30:52 +02:00
pancake a5a042cecc Fix crash and improve chat model query construction 2023-09-28 11:25:05 +02:00
pancake d91308a818 Support uncensored models, more tokens and custom query templates 2023-09-28 10:37:12 +02:00
pancake bb205b2607 Add torrent file for the models 2023-09-27 17:28:33 +02:00
pancake 3636cc53ff Fix r2poke build 2023-09-26 23:16:38 +02:00
pancake b652ff1305 Add r2ai.pdf 2023-09-26 16:42:02 +02:00
pancake e50cfcc008 Fix r2yara null deref and help message 2023-09-26 11:39:34 +02:00
pancake 7044515214 Fix build of the keystone plugins 2023-09-26 11:25:44 +02:00
pancake 1c83c693ba Update gitignore 2023-09-26 11:22:40 +02:00
pancake d3f44531c7 path fixes for r2yara 2023-09-26 11:21:00 +02:00
pancake 9a2cd79b6c Move yara/yara into r2yara 2023-09-26 11:17:37 +02:00
pancake 44ae4f46c5 Update r2yara core plugin to fix build and fix other UB bugs 2023-09-26 11:01:00 +02:00
pancake 296ff27e42 py3 just in case 2023-09-25 20:33:24 +02:00
pancake 400d67c472 Download the cherrypop model 2023-09-25 20:24:42 +02:00
pancake 01ef784858 r2pm init is deprecated 2023-09-22 17:56:49 +02:00
pancake 8a2c686105 More fixes for r2ai to handle ^C and solve installation issues 2023-09-22 13:28:32 +02:00
pancake d12ef02a13 Add env, improve prompt, clear screen, better prompting, etc 2023-09-22 12:45:27 +02:00
pancake 3fcb7ecf9b Fix prompt glitches in r2ai 2023-09-21 02:50:14 +02:00
pancake e7c8f4e7e5 Initial implementation of the local r2ai based on open-interpreter
* Improved shell with, $role :slurp !r2 !!r2pipe commands
* See readme for default model download
2023-09-21 02:08:28 +02:00
robman2444 848a1b2eeb added -fPIC to hexagon makefile. Kindof a kludge, but it works 2023-09-16 00:01:56 +02:00
pancake 1947df56fd Missing file 2023-09-15 16:27:33 +02:00
pancake c12d4badff Fix crash 2023-09-12 22:28:55 +02:00
pancake fd3871893a Reword the anal and asm hexagon plugins into an arch one 2023-09-12 22:08:55 +02:00
pancake 0a7590f748 Add hugging face test script 2023-08-18 16:04:02 +02:00
pancake 9ae0981f5a Improve optimized decompilation with bard 2023-08-01 12:56:54 +02:00
pancake bdb04b54fa Minor help improvement for bard 2023-07-19 18:42:34 +02:00
pancake 1318082a67 Make the bard script a plugin 2023-07-19 18:30:03 +02:00
pancake e72b5010c8 Add bard setup instructions 2023-07-18 13:50:54 +02:00
pancake 9b5b0013f9 Add hello world for r2ai with Google Bard 2023-07-18 13:49:05 +02:00
pancake c4b7f76081 Fix unicorn build with latest r2 2023-07-11 16:31:18 +02:00
pancake 71eb56d619 Add r2doom ai-image logo 2023-06-19 11:04:27 +02:00
pancake d3911fa5a5 Add support for delimited alien tokens in r2poke 2023-05-18 16:55:53 +02:00
pancake 5cf30b4af2 Fix enemy's health 2023-05-18 15:17:54 +02:00
pancake 0b983e477e Add beep support to r2doom 2023-05-18 11:23:33 +02:00
pancake 822a45ab18 Go realtime in r2doom 2023-05-17 12:12:17 +02:00
pancake cd4e396bcd Rename sysz to s390x and add evm to keystone 2023-05-15 12:32:28 +02:00
pancake 22f196cecc Implement strife, locked doors, ascii perspective, better damage, flash weapon when shooting 2023-05-15 10:48:59 +02:00
pancake f8dea3b7e2 Fix x86.ks 2023-05-14 22:08:38 +02:00
pancake 3a7484b467 Fix build of the keystone plugins 2023-05-14 22:07:30 +02:00
pancake 4901c49c4e Fix r2au assembler, visual piano, phone and other demos 2023-05-14 21:44:42 +02:00
pancake 90765cc641 Minor improvements for the r2au plugin 2023-05-13 21:29:03 +02:00
pancake f665a9eb11 Update r2au plugin for r2-5.8.x 2023-05-13 21:08:37 +02:00
pancake e0a8b8b3e3 Fix shooting and damage computations 2023-05-13 20:13:25 +02:00
pancake 3584dee33b Handle arrow and wasd keys in r2doom 2023-05-13 20:04:05 +02:00
pancake 0c113bdea8 Faster clear primitives to fix the blinking hud in r2doom 2023-05-13 19:50:10 +02:00
pancake 23fc638c27 Fix collisions precission bug in r2doom 2023-05-13 19:35:25 +02:00
pancake 7d67e6343d Fix infinite loop on large screens running r2doom 2023-05-12 12:36:07 +02:00
pancake ad95329c1e facepalm 2023-05-09 11:49:08 +02:00
pancake d10a5257cd glibc fix 2023-05-09 11:41:58 +02:00
pancake 9896414afb Fix linux build 2023-05-09 11:37:26 +02:00
pancake a599c6c2d6 Add screenshot and fix the readme 2023-05-09 11:25:19 +02:00
pancake ba754bed7b Fix linux build of r2doom 2023-05-09 11:08:13 +02:00
pancake a745e3cd65 Initial import of the r2doom 2023-05-09 10:56:05 +02:00
pancake 4235786fab Fix #322 - filter newlines in comments 2023-03-10 12:46:06 +01:00
pancake 6fc39af6e2 Support call commands in r2svd if available 2023-03-10 12:42:41 +01:00
pancake 6a0781ab3f Add initial json.pk for r2poke from mnabipoor <3 2023-02-28 00:30:13 +01:00
pancake c31f8fb226 Fix reg profile for blackfin 2023-02-27 00:22:41 +01:00
pancake 831b8579ee Upgrade the blackfin disassembler from latest -plus code 2023-02-27 00:03:31 +01:00
pancake 6bd03e5642 Improve the blackfin analysis details 2023-02-26 23:38:28 +01:00
pancake 77c8e95061 Translate the blackfin plugin from asm to arch 2023-02-26 19:33:48 +01:00
pancake 730aff1b19 Use rpath for home's poke 2023-02-16 20:28:46 +01:00
pancake eba95758d2 Support alien tokens thanks to the cuki lexic
* WIP: Use $r2cmd::.... to run commands or resolve flags
2023-02-16 17:21:43 +01:00
pancake 9836aa3b73 r2poke: Add eprint and use it from the runtime exception handler 2023-02-16 17:04:44 +01:00
pancake ab97757ada Implement eprintf() for the r2poke 2023-02-16 16:58:19 +01:00
dependabot[bot] ad856dee2d Bump minimist and mkdirp in /r2jadx
Bumps [minimist](https://github.com/substack/minimist) and [mkdirp](https://github.com/isaacs/node-mkdirp). These dependencies needed to be updated together.

Updates `minimist` from 1.2.0 to 1.2.6
- [Release notes](https://github.com/substack/minimist/releases)
- [Commits](https://github.com/substack/minimist/commits)

Updates `mkdirp` from 0.5.1 to 0.5.6
- [Release notes](https://github.com/isaacs/node-mkdirp/releases)
- [Changelog](https://github.com/isaacs/node-mkdirp/blob/main/CHANGELOG.md)
- [Commits](https://github.com/isaacs/node-mkdirp/compare/0.5.1...v0.5.6)

---
updated-dependencies:
- dependency-name: minimist
  dependency-type: indirect
- dependency-name: mkdirp
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <[email protected]>
2023-02-16 16:28:28 +01:00
pancake 07c8150329 Initial the exception handler and open the R2 io device 2023-02-16 16:27:52 +01:00
pancake 913874da41 Add runtime exception handler for r2poke 2023-02-16 15:48:03 +01:00
pancake 75a4f63391 Improve the poke plugin 2023-02-16 00:46:35 +01:00
pancake d834af469c Link to the system wide poke 2023-02-09 22:38:06 +01:00
pancake 7e0235ea45 Add the fosdem 2023 slides 2023-02-08 11:01:01 +01:00
pancake e49a1bb2e3 Build fixes 2023-01-19 16:50:40 +01:00
pancake c563cdd8f8 More standard makefile stuff 2023-01-19 11:47:35 +01:00
pancake bb4a2bdb6d Show help on poke 2023-01-19 11:37:59 +01:00
pancake 97070385b4 Initial import of the r2poke plugin 2023-01-19 03:58:54 +01:00
pancake 18d26928e6 Fix m32c build for r2-5.8 2023-01-17 17:32:05 +01:00
pancake 5baebd4620 Initial publication of the EAST decompiler (Vlang)
* It's just a PoC that aims to combine the vlang compiler internals
* Feel free to play or contribute! I wrote pdq based on this codebase
* Based on ESIL parsing and analysis to create an AST that can be
* printed into C-like syntax.
2022-12-30 12:20:37 +01:00
449 changed files with 385725 additions and 20315 deletions

No files matched your search

+6
View File
@@ -0,0 +1,6 @@
version: 2
updates:
- package-ecosystem: "cargo"
directory: "/x86iced"
schedule:
interval: "weekly"
+19 -37
View File
@@ -10,59 +10,41 @@ jobs:
build-extras:
name: Build radare2 extras and r2pipe
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
env:
BUILDS: 'armthumb atombios ba2 baleful bcl blackfin blessr2 keystone-lib keystone mc6809 microblaze msil pcap ppcdisasm psosvm r2svd rlang-duktape swf unicorn-lib vc4 x86udis x86bea x86tab x86olly x86zyan yara yara-r2 z80-nc'
TESTS: 'keystone mc6809 microblaze olly-extras udis86 vc4 yara'
R2PIPE_TESTS: 'r2pipe-js r2pipe-py'
EXTERNAL_BUILDS: 'keystone-lib unicorn-lib'
LOCAL_BUILDS: 'asahi blackfin blessr2 keystone microblaze ppcdisasm r2svd vc4 x86iced'
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
with:
repository: radareorg/radare2
ref: master
path: ./radare2
- name: Install dependencies
run: sudo apt-get --assume-yes install libjansson-dev libboost-dev libcurl4-openssl-dev python3-wheel python3-setuptools && sudo pip3 install meson ninja
- name: Install radare2
run: |
export PATH=$PATH:/usr/local/bin
meson --prefix=/usr --buildtype=release build && ninja -C build && sudo ninja -C build install
working-directory: radare2
- uses: actions/checkout@v2
- uses: radareorg/github-actions@v3
with:
from-git: true
- uses: actions/checkout@v3
with:
ref: ${{ github.event.pull_request.head.sha }}
path: ./radare2-extras
- name: Init r2pm
run: r2pm init
run: r2pm -U
- name: Compile and install plugins
run: |
set -e
export R2PM_GITDIR=`pwd`
export R2PM_GITSKIP=1
for p in $BUILDS ; do
for p in $EXTERNAL_BUILDS ; do
echo $p
r2pm -i $p
done
set +e
R2PM_GITDIR="$(r2pm -H R2PM_GITDIR)"
for p in $LOCAL_BUILDS ; do
echo $p
ln -s "$GITHUB_WORKSPACE/radare2-extras" "$R2PM_GITDIR/$p"
R2PM_OFFLINE=1 r2pm -i $p
done
make -C radare2-extras/mn103 install
- name: Test plugins
working-directory: radare2/test
run: |
set -e
export R2PM_GITDIR=`pwd`
export R2PM_GITSKIP=1
for p in $TESTS ; do
echo $p
make $p
done
set +e
- name: Compile and install r2pipe
run: |
set -e
export R2PM_GITDIR=`pwd`
export R2PM_GITSKIP=1
for p in $R2PIPE_TESTS ; do
echo $p
r2pm -i $p
done
set +e
make keystone
r2r -u "$GITHUB_WORKSPACE/radare2-extras/test/db/extras"
+1
View File
@@ -17,6 +17,7 @@
*.swo
*.un~
/Makefile
r2yara/Makefile
/options.mk
# misc
+5
View File
@@ -15,6 +15,7 @@ help:
@echo "Usage make [target] .. Targets:"
@echo " all - build everything"
@echo " baleful - build baleful r2 plugin"
@echo " afen - build afen r2 plugin"
@echo " asm - build armthumb, ppc, psosvm, x86bea, m68k plugins"
@echo " io - build io plugins"
@echo " anal - build analysis plugins (RAnal)"
@@ -26,6 +27,8 @@ help:
# @echo " install-yara{2,3} - install Yara 2 or 3 from Git"
afen:
$(MAKE) -C afen
baleful:
$(MAKE) -C baleful
debug unicorn:
@@ -53,6 +56,8 @@ yara:
$(MAKE) -C yara/$@
yara-clean:
$(MAKE) -C yara/yara clean
afen-install:
$(MAKE) -C afen install DESTDIR=$(DESTDIR)
baleful-install:
$(MAKE) -C baleful install DESTDIR=$(DESTDIR)
debug-install unicorn-install:
+13 -12
View File
@@ -1,7 +1,7 @@
radare2-extras
==============
# radare2-extras
[![GithubCI Status](https://github.com/radareorg/radare2-extras/workflows/CI/badge.svg?branch=master)](https://github.com/radareorg/radare2-extras/actions?query=workflow%3A%22ci%22)|
[![GithubCI Status](https://github.com/radareorg/radare2-extras/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/radareorg/radare2-extras/actions?query=workflow%3A%22ci%22)
[![radare2](https://img.shields.io/badge/radare2-6.0.4-green)](https://github.com/radareorg/radare2)
This repository contains extra plugins for radare2.
@@ -15,13 +15,6 @@ repository are the following:
* Duplicates functionality from r2 (no need to have
multiple disassemblers for the same arch in core)
The compiled plugins will be installed at
/usr/lib/radare2-extras/$(VERSION)
Some of the plugins/code doesnt compiles, it will be reviewed
and cleaned up, merged into core, updated or removed.
In addition, this repository will be useful to new contributors,
comers who want to write his own r2 plugins for example.
@@ -30,8 +23,16 @@ repository to be as concise as possible, and reduce the
amount of unnecessary plugins to shrink the install size and
keep it usable for 99% of users.
Building
========
## Building
The recommended way to build and install those plugins for users
is to use r2pm. See the [radare2 plugins](https://github.com/radareorg/radare2#plugins) documentation for details.
## Notable plugins
* [`msl`](msl/) — Memory Slice (`.msl`) support: open/emulate process memory
dumps (`io`/`bin`/`debug` plugins, with ESIL reverse execution) and produce
them from a live debug session (`dgm`/`dgma`, `core` plugin).
* [`r2gg`](r2gg/) — Game Gear emulation through Z80 ESIL, with color terminal
display, controls, Sega cartridge banking, interrupts, and stereo PSG audio.
+22
View File
@@ -0,0 +1,22 @@
LIBEXT=$(shell r2 -HR2_LIBEXT)
CFLAGS+=$(shell pkg-config --cflags r_core)
LDFLAGS+=$(shell pkg-config --libs r_core)
R2_USER_PLUGINS=$(shell r2 -HR2_USER_PLUGINS)
CORE_AFEN=src/libcoreafen.$(LIBEXT)
OBJS=src/main.o
all: $(CORE_AFEN)
$(CORE_AFEN): $(OBJS)
r2pm -r $(CC) $(LDFLAGS) -shared -fPIC -o $(CORE_AFEN) $(OBJS)
clean:
rm -f $(OBJS) $(CORE_AFEN)
user-install install:
mkdir -p $(R2_USER_PLUGINS)
cp -f $(CORE_AFEN) $(R2_USER_PLUGINS)
user-uninstall uninstall:
rm -f $(R2_USER_PLUGINS)/$(CORE_AFEN)
+30
View File
@@ -0,0 +1,30 @@
# afen plugin
Author: satk0
NOTE: Making this plugin would not be possible without the help from pancake. Big thanks to him!
Radare2 plugin to rename expressions
This plugin should register a new `afen` command that should rename any expression
to any text, thus enabling a creation of variables from expressions.
## Building and installing the plugin:
Build:
r2pm -r meson setup build
Install:
meson install -C build
## Run:
r2 -e asm.parser=afen -e asm.pseudo=true <file>
## Usage:
For instance, to rename `rbp + rax - 0x1020` expression to `cwd[i]`, you could use the following command:
afen cmd[i] "rbp + rax - 0x1020"
+12
View File
@@ -0,0 +1,12 @@
project('r2-afen', 'c', license : 'MIT', meson_version : '>=1.00', version : '0.1.0')
r2_plugdir = run_command('r2', '-H', 'R2_USER_PLUGINS', check: true).stdout().strip()
sources = [ 'src/main.c' ]
lib = library('coreafen', sources,
dependencies : [
dependency('r_core')
],
install_dir: r2_plugdir,
install: true
)
+269
View File
@@ -0,0 +1,269 @@
/* radare - Copyright 2024 - satk0 */
#define R_LOG_ORIGIN "core.afen"
#include <r_core.h>
typedef struct RAfenRepl {
char *old_name;
char *new_name;
} RAfenRepl;
#if R2_VERSION_NUMBER >= 50909
#else
static R_TH_LOCAL HtUP *ht; // hash table
#endif
#if R2_VERSION_NUMBER >= 50909
static void fini(RAsmPluginSession *aps) {
RParse *p = aps->rasm->parse;
R_FREE (p->retleave_asm);
}
#endif
static char *parse(RCore *core, const char *data, HtUP *ht) {
char *out = strdup (data);
#if R2_VERSION_NUMBER >= 50909
RAnalFunction *fcn = r_anal_get_function_at (core->anal, core->addr);
#else
RAnalFunction *fcn = r_anal_get_function_at (core->anal, core->offset);
#endif
if (fcn) {
RVector *vec = ht_up_find (ht, fcn->addr, NULL);
if (vec) {
RAfenRepl *repl;
r_vector_foreach (vec, repl) {
out = r_str_replace_all (out, repl->old_name, repl->new_name);
}
}
}
return out;
}
// afen parser
#if R2_VERSION_NUMBER >= 50909
static char *r_parse_afen(RAsmPluginSession *aps, const char *data) {
char* out = parse ((RCore *) aps->rasm->user, data, aps->data);
return out;
}
#else
static int r_parse_afen(RParse *p, const char *data, char *str) {
char* out = parse ((RCore *) p->analb.anal->user, data, ht);
strcpy (str, out);
return true;
}
#endif
// RParse plugin Definition Info
#if R2_VERSION_NUMBER >= 50909
RAsmPlugin r_parse_plugin_afen = {
.meta = {
.name = "afen",
.desc = "Afen parse plugin",
},
.parse = r_parse_afen,
.fini = fini,
// .subvar = subvar,
};
#else
RParsePlugin r_parse_plugin_afen = {
.name = "afen",
.desc = "Afen parse plugin",
.parse = r_parse_afen,
};
#endif
static inline void repl_free_afen(void *e, void *user ) {
RAfenRepl *repl = (RAfenRepl *) e;
if (repl) {
R_FREE (repl->old_name);
R_FREE (repl->new_name);
}
}
static inline void vector_value_free_afen(HtUPKv *kv) {
RVector *vec = (RVector *) kv->value;
if (vec) {
r_vector_free (vec);
}
}
static bool print_afen_rules(void *user, const ut64 key, const void *value) {
RCore *core = (RCore *) user;
RVector *vec = (RVector *) value;
RAfenRepl *repl;
r_vector_foreach (vec, repl) {
r_cons_printf (core->cons, "'@0x%08"PFMT64x"'afen \"%s\" \"%s\"\n", key, repl->new_name, repl->old_name);
}
return true;
}
// setup afen parser
#if R2_VERSION_NUMBER >= 50909
static bool r_core_init_afen(RCorePluginSession *cps) {
RCore *core = (RCore *) cps->core;
r_asm_plugin_add (core->rasm, &r_parse_plugin_afen);
RAsmPluginSession *afen_aps = NULL;
RListIter *iter;
RAsmPluginSession *aps;
r_list_foreach (core->rasm->sessions, iter, aps) {
if (aps && aps->plugin && aps->plugin->meta.name &&
!strcmp(aps->plugin->meta.name, "afen")) {
afen_aps = aps;
break;
}
}
if (!afen_aps) {
R_LOG_ERROR ("Failed to find afen plugin session");
return false;
}
HtUP /*<ut64, RVector<RAfenRepl*>>*/ *ht = ht_up_new (NULL, vector_value_free_afen, NULL);
if (!ht) {
R_LOG_ERROR ("Fail to initialize hashtable");
ht_up_free (ht);
return false;
}
afen_aps->data = ht;
cps->data = ht;
return true;
}
#else
static bool r_core_init_afen(void *user, const char *input) {
RCmd *rcmd = (RCmd *) user;
RCore *core = (RCore *) rcmd->data;
r_parse_plugin_add (core->parser, &r_parse_plugin_afen);
/*<ut64, RVector<RAfenRepl*>>*/ ht = ht_up_new (NULL, vector_value_free_afen, NULL);
if (!ht) {
R_LOG_ERROR ("Fail to initialize hashtable");
ht_up_free (ht);
return false;
}
return true;
}
#endif
#if R2_VERSION_NUMBER >= 50909
static bool r_core_fini_afen(RCorePluginSession *cps) {
HtUP *ht = cps->data;
ht_up_free (ht);
ht = NULL;
return true;
}
#else
static bool r_core_fini_afen(void *user, const char *input) {
ht_up_free (ht);
ht = NULL;
return true;
}
#endif
static bool check_for_afen_command(RCore *core, const char *input, HtUP *ht) {
if (r_str_startswith (input, "afen*")) {
ht_up_foreach(ht, print_afen_rules, core);
return true;
} else if (r_str_startswith (input, "afen")) {
int argc = 0;
char **argv = r_str_argv (input, &argc);
if (!argv || argc != 3) {
R_LOG_INFO ("Usage: afen new_name old_name");
r_str_argv_free (argv);
return true;
}
#if R2_VERSION_NUMBER >= 50909
RAnalFunction *fcn = r_anal_get_function_at (core->anal, core->addr);
#else
RAnalFunction *fcn = r_anal_get_function_at (core->anal, core->offset);
#endif
if (!fcn) {
#if R2_VERSION_NUMBER >= 50909
R_LOG_ERROR ("No Function at 0x%08" PFMT64x, core->addr);
#else
R_LOG_ERROR ("No Function at 0x%08" PFMT64x, core->offset);
#endif
R_LOG_INFO ("Use afen inside a function!");
r_str_argv_free (argv);
return false;
}
RVector *vec = ht_up_find (ht, fcn->addr, NULL);
if (!vec) {
vec = r_vector_new (sizeof (RAfenRepl), repl_free_afen, NULL);
ht_up_insert (ht, fcn->addr, vec);
}
bool updated = false;
RAfenRepl *repl;
r_vector_foreach (vec, repl) {
if (repl->old_name && argv[2] && !strcmp (repl->old_name, argv[2])) {
if (repl->new_name) {
R_FREE (repl->new_name);
}
repl->new_name = strdup (argv[1]);
updated = true;
break;
}
}
if (updated) {
r_str_argv_free (argv);
return true;
}
repl = R_NEW0 (RAfenRepl);
repl->new_name = strdup (argv[1]);
repl->old_name = strdup (argv[2]);
r_vector_push (vec, repl);
r_str_argv_free (argv);
return true;
}
return false;
}
#if R2_VERSION_NUMBER >= 50909
static bool r_core_call_afen(RCorePluginSession *cps, const char *input) {
return check_for_afen_command(cps->core, input, cps->data);
}
#else
static bool r_core_call_afen(void *user, const char *input) {
return check_for_afen_command((RCore *) user, input, ht);
}
#endif
// RCore plugin Definition Info
RCorePlugin r_core_plugin_afen = {
.meta = {
.name = "core-afen",
.desc = "Rename expressions",
.author = "satk0",
.license = "GPLv3",
},
.call = r_core_call_afen,
.init = r_core_init_afen,
.fini = r_core_fini_afen
};
#ifndef R2_PLUGIN_INCORE
R_API RLibStruct radare_plugin = {
.type = R_LIB_TYPE_CORE,
.data = &r_core_plugin_afen,
.version = R2_VERSION,
#if R2_VERSION_NUMBER >= 50909
.abiversion = R2_ABIVERSION,
#endif
};
#endif
+3 -3
View File
@@ -6,7 +6,7 @@ LDFLAGS+=$(shell pkg-config --libs r_core)
CFLAGS+=-Igpu/wrap
all: gpu
$(CC) $(CFLAGS) $(LDFLAGS) -shared -fPIC asm_asahi.c -o asm_asahi.$(R2_LIBEXT)
$(CC) $(CFLAGS) $(LDFLAGS) -shared -fPIC arch_asahi.c -o arch_asahi.$(R2_LIBEXT)
mrproper clean:
rm -f *.$(R2_LIBEXT)
@@ -16,7 +16,7 @@ gpu:
install:
mkdir -p "$(R2_USER_PLUGINS)"
cp -f asm_asahi.$(R2_LIBEXT) $(R2_USER_PLUGINS)
cp -f arch_asahi.$(R2_LIBEXT) $(R2_USER_PLUGINS)
uninstall:
rm -f $(R2_USER_PLUGINS)/asm_asahi.$(R2_LIBEXT)
rm -f $(R2_USER_PLUGINS)/arch_asahi.$(R2_LIBEXT)
+40
View File
@@ -0,0 +1,40 @@
/* radare2 - GPL3 - Copyright 2021-2023 - pancake */
#include <r_lib.h>
#include <r_arch.h>
#include "gpu/disasm/disasm.c"
static bool decode(RArchSession *as, RAnalOp *op, RAnalOpMask mask) {
char out[128];
FILE *fp = fmemopen (out, sizeof (out), "w");
*out = 0;
bool stop = false;
int res = agx_disassemble_instr ((uint8_t*)op->bytes, &stop, false, fp);
fclose (fp);
r_str_replace_char (out, '\n', ' ');
free (op->mnemonic);
op->mnemonic = r_str_trim_dup (out);
op->size = res;
return op->size;
}
static RArchPlugin r_arch_plugin_asahi = {
.meta = {
.name = "asahi",
.license = "MIT",
.desc = "Asahi: Apple's M1 GPU",
},
.arch = "asahi",
.bits = 32,
.decode = &decode,
};
#ifndef CORELIB
RLibStruct radare_plugin = {
.type = R_LIB_TYPE_ARCH,
.data = &r_arch_plugin_asahi,
.version = R2_VERSION
};
#endif
-38
View File
@@ -1,38 +0,0 @@
/* radare2 - GPL3 - Copyright 2021 - pancake */
#include <stdbool.h>
#include <r_lib.h>
#include <r_asm.h>
#include "gpu/disasm/disasm.c"
static int disassemble(RAsm *a, RAsmOp *op, const ut8 *buf, int len) {
char out[128];
FILE *fp = fmemopen (out, sizeof (out), "w");
*out = 0;
bool stop = false;
int res = agx_disassemble_instr ((uint8_t*)buf, &stop, false, fp);
fclose (fp);
r_strbuf_set (&op->buf_asm, out);
op->size = res;
return op->size;
}
RAsmPlugin r_asm_plugin_asahi = {
.name = "asahi",
.arch = "asahi",
.bits = 32,
.license = "MIT",
.desc = "Asahi: Apple's M1 GPU",
.disassemble = &disassemble,
};
#ifndef CORELIB
RLibStruct radare_plugin = {
.type = R_LIB_TYPE_ASM,
.data = &r_asm_plugin_asahi,
.version = R2_VERSION
};
#endif
+13 -10
View File
@@ -4,30 +4,33 @@
#include <r_types.h>
#include <r_lib.h>
#include <r_asm.h>
// #include <r_arch.h>
#include <r_anal.h>
#include <stdio.h>
#include <fcntl.h>
static int ptsHandle=0;
static int ptsHandle = 0;
static int reg_read(RAnalEsil *esil, const char *regname, ut64 *num) {
static bool reg_read(RAnalEsil *esil, const char *regname, ut64 *num) {
RRegItem *reg = r_reg_get (esil->anal->reg, regname, -1);
if (reg) {
if (num)
if (num) {
*num = r_reg_get_value (esil->anal->reg, reg);
return 1;
}
return true;
}
return 0;
return false;
}
static int reg_write(RAnalEsil *esil, const char *regname, ut64 num) {
static bool reg_write(RAnalEsil *esil, const char *regname, ut64 num) {
RRegItem *reg = r_reg_get (esil->anal->reg, regname, -1);
if (reg) {
if (num)
if (num) {
r_reg_set_value (esil->anal->reg, reg,num);
return 1;
}
return true;
}
return 0;
return false;
}
/*
@@ -544,7 +547,7 @@ static int esil_baleful_intr (RAnalEsil *esil, int intr) {
}
static bool esil_bale_interrupt_wrapper_cb (RAnalEsil *esil, ut32 interrupt, void *user) { //user is always NULL, bc we has no init and fini
return !!esil_baleful_intr(esil, interrupt);
return !!esil_baleful_intr (esil, interrupt);
}
static int set_reg_profile(RAnal *anal) {
Vendored
+49 -19
View File
@@ -1,5 +1,5 @@
#!/bin/sh
# This script was automatically generated by ACR v2.0.0
# This script was automatically generated by ACR v2.2.4
# @author: pancake <nopcode.org>
# @url: http://www.nopcode.org
# @repo: git clone https://github.com/radare/acr
@@ -67,13 +67,27 @@ if [ -e "${VPATH}/config.guess" ]; then
sh ${VPATH}/config.guess
return
fi
CPU="`uname -m|sed -e 's, ,,g'|cut -d - -f 1`"
CPU="`uname -m | tr 'A-Z' 'a-z' | sed -e 's, ,,g' | cut -d - -f 1`"
OS="`uname -s|tr A-Z a-z`"
uname -r | grep -qE "(Microsoft|WSL)" 2>/dev/null && OS="wsl"
GNU="`uname --help 2>&1 | grep gnu`"
[ "${GNU}" ] && OS="${OS}-gnu"
[ "${CPU}" = ppc ] && CPU="powerpc"
echo "${CPU}-unknown-${OS}"
# normalize CPU
case "${CPU}" in
ppc*|powermac*|powermacintosh*|powerpc*)
if echo "${CPU}" | grep -q '64'; then
CPU=powerpc64
else
CPU=powerpc
fi
;;
*) ;;
esac
VENDOR="unknown"
if [ "${OS}" = "darwin" ]; then
VENDOR=apple
fi
echo "${CPU}-${VENDOR}-${OS}"
}
SEARCHPATH="/usr /usr/local /usr/pkg /sw"
@@ -85,6 +99,7 @@ HOST="${BUILD}"
TARGET="${HOST}"
ETCDIR="/etc"
SYSCONFDIR=""
DESCRIPTION=""
create_environ() {
: ${EPREFIX:="${PREFIX}"}
@@ -93,6 +108,8 @@ create_environ() {
: ${SBINDIR:="${PREFIX}/sbin"}
: ${ETCDIR:="${SPREFIX}/etc"}
: ${LIBDIR:="${SPREFIX}/lib"}
: ${PKGCFG_LIBDIR:='${exec_prefix}/lib'}
: ${PKGCFG_INCDIR:='${prefix}/include'}
: ${LIBEXECDIR:="${SPREFIX}/libexec"}
: ${INCLUDEDIR:="${SPREFIX}/include"}
: ${DATADIR:="${SPREFIX}/share"}
@@ -111,12 +128,12 @@ done
: ${INSTALL_PROGRAM_STRIP:=${INSTALL} -m 755 -s}
: ${INSTALL_MAN:=${INSTALL} -m 444}
: ${INSTALL_LIB:=${INSTALL} -m 755 -c}
PKGNAME='radare2-extras' ; VERSION='5.8.0' ; VERSION_MAJOR=5; VERSION_MINOR=8; VERSION_PATCH=0; VERSION_NUMBER=50800; CONTACT_MAIL="[email protected]" ; CONTACT_NAME="pancake" ; CONTACT="pancake <[email protected]>" ;
PKGNAME='radare2-extras' ; VERSION='6.0.0' ; VERSION_MAJOR=6; VERSION_MINOR=0; VERSION_PATCH=0; VERSION_NUMBER=60000; CONTACT_MAIL="[email protected]" ; CONTACT_NAME="pancake" ; CONTACT="pancake <[email protected]>" ;
}
show_usage() {
cat <<EOF2
'configure' configures radare2-extras-5.8.0 to adapt to many kinds of systems.
'configure' configures radare2-extras-6.0.0 to adapt to many kinds of systems.
Usage: ./configure [OPTION]... [VAR=VALUE]...
@@ -198,10 +215,10 @@ ocho() {
show_version() {
if [ "$QUIET" = 1 ]; then
echo "5.8.0"
echo "6.0.0"
exit 0
fi
echo "radare2-extras-5.8.0 configuration script done with acr v2.0.0.
echo "radare2-extras-6.0.0 configuration script done with acr v2.2.4.
The 'Free Software Foundation' message is only for autodetection.
Originally written by pancake <nopcode.org>."
exit 0
@@ -229,12 +246,14 @@ case $flag in
-V|-version|--version)
show_version ; ;;
-r|--r|--report)
echo "PKGNAME: radare2-extras"
echo "VERSION: 5.8.0"
echo "LANGS: c"
echo "OPTIONAL: libewf libyara"
echo "PKG-CONFIG: r_core libewf unicorn yara"
echo "FLAGS: --with-ostype=auto --without-ewf"
echo "PKGNAME: radare2-extras"
echo "VERSION: 6.0.0"
echo "AUTHOR: pancake"
echo "EMAIL: [email protected]"
echo "LANGS: c"
echo "OPTIONAL: libewf libyara"
echo "PKGCONFIG: r_core libewf unicorn yara"
echo "FLAGS: --with-ostype=auto --without-ewf"
exit 0
;;
--cache-file)
@@ -274,10 +293,12 @@ echo "FLAGS: --with-ostype=auto --without-ewf"
--localstatedir)
LOCALSTATEDIR="$value"; ;;
--libdir)
LIBDIR="$value"; ;;
LIBDIR="$value"
PKGCFG_LIBDIR="$value"; ;;
--libpath)
LDFLAGS="${LDFLAGS} ${LIBPATH}$value"; ;;
--includedir)
PKGCFG_INCDIR="$value"
INCLUDEDIR="$value"; CFLAGS="${CFLAGS} -I$value"; ;;
--infodir)
INFODIR="$value"; ;;
@@ -303,7 +324,7 @@ parse_options "$1"
shift
done
ENVWORDS="MANDIR INFODIR LIBDIR INCLUDEDIR LOCALSTATEDIR ETCDIR SYSCONFDIR DATADIR DOCDIR LIBEXECDIR SBINDIR BINDIR EPREFIX PREFIX SPREFIX TARGET HOST BUILD INSTALL INSTALL_LIB INSTALL_MAN INSTALL_PROGRAM INSTALL_PROGRAM_STRIP INSTALL_DIR INSTALL_SCRIPT INSTALL_DATA HOST_OS HOST_CPU BUILD_OS BUILD_CPU TARGET_OS TARGET_CPU VERSION VERSION_MAJOR VERSION_MINOR VERSION_PATCH VERSION_NUMBER PKGNAME VPATH CONTACT CONTACT_NAME CONTACT_MAIL PKGCONFIG CC CFLAGS CPPFLAGS LDFLAGS HAVE_LANG_C R2_CFLAGS R2_LDFLAGS HAVE_PKGCFG_R_CORE USEROSTYPE HAVE_LIB_EWF EWF_CFLAGS EWF_LDFLAGS HAVE_PKGCFG_LIBEWF WANT_EWF UC_CFLAGS UC_LDFLAGS HAVE_PKGCFG_UNICORN HAVE_LIB_YARA YARA_CFLAGS YARA_LDFLAGS HAVE_PKGCFG_YARA"
ENVWORDS="MANDIR DESCRIPTION INFODIR LIBDIR INCLUDEDIR LOCALSTATEDIR ETCDIR SYSCONFDIR DATADIR DOCDIR LIBEXECDIR SBINDIR BINDIR EPREFIX PREFIX SPREFIX TARGET HOST BUILD INSTALL INSTALL_LIB INSTALL_MAN INSTALL_PROGRAM INSTALL_PROGRAM_STRIP INSTALL_DIR INSTALL_SCRIPT INSTALL_DATA HOST_OS HOST_CPU BUILD_OS BUILD_CPU TARGET_OS TARGET_CPU VERSION VERSION_MAJOR VERSION_MINOR VERSION_PATCH VERSION_NUMBER PKGCFG_LIBDIR PKGCFG_INCDIR PKGNAME VPATH CONTACT CONTACT_NAME CONTACT_MAIL PKGCONFIG CC CFLAGS CPPFLAGS LDFLAGS HAVE_LANG_C R2_CFLAGS R2_LDFLAGS HAVE_PKGCFG_R_CORE USEROSTYPE HAVE_LIB_EWF EWF_CFLAGS EWF_LDFLAGS HAVE_PKGCFG_LIBEWF WANT_EWF UC_CFLAGS UC_LDFLAGS HAVE_PKGCFG_UNICORN HAVE_LIB_YARA YARA_CFLAGS YARA_LDFLAGS HAVE_PKGCFG_YARA"
create_environ
@@ -318,8 +339,8 @@ ocho "checking for working directories... ${WODIS}"
ocho "using prefix '${PREFIX}'"
ACR_RMFILES=" test.c a.out a.exe"
ochof "checking for pkg-config... "
ENVWORDS="${ENVWORDS} HAVE_PKGCONFIG"
if [ -n "$PKGCONFIG" ]; then
if [ -x "$PKGCONFIG" ]; then
_HAVE_PKGCONFIG="${PKGCONFIG}"
@@ -343,7 +364,9 @@ else
fi
if [ -n "${PKGCONFIG}" ]; then
ocho ${PKGCONFIG}
HAVE_PKGCONFIG=1
else
HAVE_PKGCONFIG=0
echo "Cannot find pkg-config or pkgconf in PATH" >&2
exit 1
ocho no; fi
@@ -355,7 +378,7 @@ if [ "${CROSSBUILD}" = 1 ]; then
if [ $? = 0 ]; then CC="${HOST}-${CC}"; fi
fi
echo "int main(int argc, char **argv){return 0;}" > test.c
(exec ${CC} ${CFLAGS} ${CPPFLAGS} ${LDFLAGS} test.c >/dev/null 2>&1)
(exec ${CC} -o a.out ${CFLAGS} ${CPPFLAGS} ${LDFLAGS} test.c >/dev/null 2>&1)
if [ $? = 0 ]; then echo ${CC}; else
echo no ; HAVE_LANG_C=0
do_remove
@@ -446,7 +469,14 @@ for A in ${ENVWORDS} ; do
[ "${A}" = VPATH ] && continue
[ "${A}" = srcdir ] && continue
eval "VAR=\$${A}"
VAR="`echo ${VAR} | sed -e 's/\,/\\\,/g'`"
case "" in
mingw*|cygwin*|msys*)
VAR="`echo ${VAR} | sed -e 's/\\/\\\\/g' -e 's/\,/\\\,/g'`"
;;
*)
VAR="`echo ${VAR} | sed -e 's/\,/\\\,/g'`"
;;
esac
[ $COUNT = 10 ] && COUNT=0 && SEDFLAGS="${SEDFLAGS}' -e '"
COUNT=$(($COUNT+1))
SEDFLAGS="${SEDFLAGS}s,@${A}@,${VAR},g;"
+1 -1
View File
@@ -1,5 +1,5 @@
PKGNAME radare2-extras
VERSION 5.8.0
VERSION 6.0.0
CONTACT pancake ; [email protected]
USE_PKGCONFIG!
+23
View File
@@ -0,0 +1,23 @@
R2_PLUGDIR=$(shell r2 -H R2_USER_PLUGINS)
R2_LIBEXT=$(shell r2 -H R2_LIBEXT)
LDFLAGS=-L/opt/homebrew/lib
# VFLAGS+=-gc none
ifeq ($(R2_LIBEXT),)
all:
@echo Cannot find r2
else
all:
v install --once
v fmt -w pdv.v main.v east
v -o a.c -shared pdv.v
LDFLAGS=$(LDFLAGS) v -o pdv.$(R2_LIBEXT) -shared pdv.v
install -m 0755 pdv.$(R2_LIBEXT) $(R2_PLUGDIR)
v $(VFLAGS) -g main.v
./main
setup:
v install
endif
+48
View File
@@ -0,0 +1,48 @@
# VESIL
## Description
V library to provide high level analysis on top of esil
## Usage
See the `main.v` and run it with `make`.
## Known bugs
There are some r2 instances that arent killed somehow by v-r2pipe
## Random
```
paπcake, [3/29/2022 7:03 PM]
typedef struct {
char *name;
void *ref;
} Symbol;
// hook memory reads to find access to variables
// hook register names to track transfers of symbols
"0,rax,:="
:= will trigger reg_write, if 'rax' is associated to a symbol then we can name that operation
for example if rax is associated to the symbol containing the return value of a function
the esil box can create that symbol and handle the function call expression like foo = call()
symbols can be invalidated at any time and their meaning can change backwards.
using esilbox;
int main() {
Symbol *argc = r_esil_box_symbol_new ("argc", "rbp,10,-");
EsilBox *eb = r_esil_box_new ();
r_esil_box_add_symbol (eb, argc);
r_esil_box_set_address (eb, 0x8048000);
do {
r_esil_box_step (eb);
} white (r_esil_box_running (eb));
// eb := esilbox.new()
// eb.set_address(0x80488)
// eb.step()
}
```
+12
View File
@@ -0,0 +1,12 @@
# EAST
Esil Abstract Structured Tree
## Description
This is a work in progress project that aims to provide work in progress
and experimental development towards getting a decompiler on top of the
R2 intermediate language (ESIL).
The main objective of this project is to raise esil to the level where
we can use it for decompilation, type propagation and advanced analysis.
+168
View File
@@ -0,0 +1,168 @@
module east
pub enum NodeStatement {
_none
_break
_switch
_comment
_case
_block
_if
_condition
_symbol
_register
_string
_local
_operation // + - < > << || ...
_return
_function
_else
_for
_argument
_while
_dowhile
_call
_number // number
_goto // symbol or label
_label // symbol
_assign // dst, src
_oparen
_cparen
}
pub struct Node {
pub mut:
name string
typ NodeStatement
// typ EsilType
addr string
pos int
parent int
children []NodeIndex
}
type NodeIndex = int
pub fn (mut e Program) add_name(typ NodeStatement, name string, nodes []NodeIndex) NodeIndex {
ni := e.new_node(name)
mut n := e.node(ni)
n.typ = typ
n.children = nodes
return ni
}
pub fn (mut e Program) add(typ NodeStatement, nodes []NodeIndex) NodeIndex {
return e.add_name(typ, '?', nodes)
}
pub fn (mut e Program) add_operation(name string) NodeIndex {
ni := e.new_node(name)
mut n := e.node(ni)
n.typ = ._operation
return ni
}
pub fn (mut e Program) add_block(addr string) NodeIndex {
ni := e.new_node(addr)
mut n := e.node(ni)
n.typ = ._block
return ni
}
pub fn (mut e Program) add_goto(addr string) NodeIndex {
ni := e.new_node(addr)
mut n := e.node(ni)
n.typ = ._goto
return ni
}
pub fn (mut e Program) add_return(arg string) NodeIndex {
ni := e.new_node(arg)
mut n := e.node(ni)
n.typ = ._return
return ni
}
pub fn (mut e Program) add_label(addr string) NodeIndex {
ni := e.new_node(addr)
mut n := e.node(ni)
n.typ = ._label
return ni
}
pub fn (mut e Program) add_number(addr u64) NodeIndex {
ni := e.new_node('$addr')
mut n := e.node(ni)
n.typ = ._number
return ni
}
pub fn (mut e Program) add_argument(addr u64, name string) NodeIndex {
ni := e.new_node('$name')
mut n := e.node(ni)
n.typ = ._argument
return ni
}
pub fn (mut e Program) add_symbol(addr u64, name string) NodeIndex {
ni := e.new_node('$name')
mut n := e.node(ni)
n.typ = ._symbol
return ni
}
pub fn (mut e Program) add_string(addr u64, name string) NodeIndex {
ni := e.new_node('$name')
mut n := e.node(ni)
n.typ = ._string
return ni
}
pub fn (mut e Program) new_local(addr u64, name string) NodeIndex {
ni := e.new_node('$name')
mut n := e.node(ni)
n.typ = ._local
// f := e.node(e.state().in_function)
return ni
}
pub fn (mut e Program) new_node(name string) NodeIndex {
mut n := &Node{}
n.parent = e.state().last_node
n.name = name
n.addr = e.pc()
n.pos = e.state().pos
e.ast.nodes << n
return e.ast.nodes.len - 1
}
pub fn (mut e Program) node(n int) &Node {
return &e.ast.nodes[n]
}
// XXX not working as expected
pub fn (mut e Program) del_child(n int, c int) {
if n < 0 || n >= e.ast.nodes.len {
return
}
for i, _ in e.node(n).children {
cn := e.node(n).children[int(i)]
if cn == c {
eprintln('$cn vs $c')
mut nn := e.node(n)
if nn.children.len < 1 {
eprintln('delete')
// nn.children.delete(idx)
}
// dump(e.node(e.ast.nodes[n].children)
// break
}
}
}
pub fn (mut e Program) add_child(n int, c int) {
e.ast.nodes[n].children << c
}
pub fn (mut e Program) new_node_condition(name string, a int, b int) {
}
+347
View File
@@ -0,0 +1,347 @@
module east
/*
struct EsilOperation {
name string
}
*/
type EsilOperationCallback = fn (e Program) bool
struct EsilOperation {
mut:
cb EsilOperationCallback
}
enum EsilType {
number
register
command
}
struct EsilState {
mut:
// esil
pos int
last_node int
tokens []string
}
struct East {
pub mut:
// ast
nodes []Node
in_function int
find_type NodeStatement
}
pub interface R2PipeInterface {
cmd(a string) string
}
// TODO: rename to Program
struct Program {
a int
r2 R2PipeInterface
mut:
deep int
stack []string
stack_index []NodeIndex
states []EsilState
ops map[string]EsilOperation
// codegen
ast East
indent_level int
}
pub fn new_program(r2 R2PipeInterface) Program {
mut e := Program{0, r2, 0, []string{}, []NodeIndex{}, []EsilState{}, map[string]EsilOperation{}, East{}, 0}
// XXX unused ops
e.ops['+'] = EsilOperation{fn (e Program) bool {
// pop 2
println('add')
return true
}}
e.ops['-'] = EsilOperation{fn (e Program) bool {
// pop 2
println('sub')
return true
}}
return e
}
pub fn (mut e Program) load_instruction(ni NodeIndex, addr string, expr string) NodeIndex {
// add label
return e.eval(ni, expr)
}
pub fn (mut program Program) new_statement(addr string, esil string) NodeIndex {
block := program.add_name(._block, addr, [])
program.add_child(block, program.add_name(._comment, esil, []))
program.add_child(block, program.add_label(addr))
return program.load_instruction(block, addr, esil)
}
pub fn (mut e Program) new_function(name string, statements []NodeIndex) NodeIndex {
return e.add_name(._function, name, statements)
}
pub fn (mut e Program) load_function(name string) NodeIndex {
e.load_at(name)
mut statements := []NodeIndex{}
for expr in e.r2.cmd('pief').split('\n') {
addr := expr.split(' ')
esil := if addr.len > 1 { addr[1] } else { '' }
statements << e.new_statement(addr[0], esil)
}
return e.new_function(name, statements)
}
pub fn (mut e Program) load_function2(name string) NodeIndex {
mut statements := []NodeIndex{}
e.load_at(name)
bbs := e.r2.cmd('afb@$name').trim_space()
for bb in bbs.split('\n') {
bbw := bb.split(' ')
addr := bbw[0]
mut addr_j := ''
mut addr_f := ''
for j in 0 .. bbw.len {
if bbw[j] == 'j' {
addr_j = bbw[j + 1]
}
if bbw[j] == 'f' {
addr_f = bbw[j + 1]
}
}
println('$addr -> $addr_j -> $addr_f ')
ni := e.add_block(addr)
if addr_j == '' {
// return basic block
e.add_child(ni, e.add_return(''))
} else if addr_f == '' {
// only true jump
e.add_child(ni, e.add_goto(addr_j))
} else {
// have true and false jumps
e.add_child(ni, e.add_goto(addr_j))
e.add_child(ni, e.add_goto(addr_f))
}
statements << ni
}
eprintln(statements)
return e.new_function(name, statements)
}
pub fn (mut e Program) load_at(a string) bool {
e.r2.cmd('aeim;ar0;aei')
e.r2.cmd('s $a;af;aepc $$')
return true
}
pub fn (mut e Program) is_operation(op string) ?EsilOperation {
if op in e.ops {
return e.ops[op]
}
return error('no op')
}
pub fn (mut e Program) step() bool {
expr := e.r2.cmd('aoeq@r:PC')
for tok in expr.split(',') {
println('$tok')
op := e.is_operation(tok) or {
eprintln('oops')
eprintln(err)
break
}
eprintln(op)
}
e.r2.cmd('ar PC=PC+\$l@r:PC')
// e.r2.cmd('aes')
return true
}
pub fn (mut e Program) expr(addr string) string {
return e.r2.cmd('aoeq@$addr').trim_space()
}
pub fn (mut e Program) find_type() EsilType {
s := e.state().tokens[e.state().pos]
// b := if s.len > 0 { s[0] } else { 0 }
if s != '' && s[0] >= `0` && s[0] <= `9` {
return .number
}
return match s {
'+', '-' {
.command
}
else {
.register
}
}
}
pub fn (mut e Program) find_statement_type() NodeStatement {
s := e.state().tokens[e.state().pos]
// b := if s.len > 0 { s[0] } else { 0 }
if s != '' && s[0] >= `0` && s[0] <= `9` {
return ._number
}
return match s {
'+', '+=', '!', '-', '|', '&', '&=', '-=', '*', '*=', '/', '%', '^', '^=', '<<', '>>',
'<<<', '<<<<', '>>>', '>>>>' {
._operation
}
'=[8]', '=[4]', '=[2]', '=[1]' {
._operation
}
'[8]', '[4]', '[2]', '[1]' {
._assign
}
'=', ':=' {
._assign
}
'GOTO' {
._goto
}
'==', '!=' {
._condition
}
else {
._symbol
}
}
}
pub fn (mut e Program) push_state() {
e.states << EsilState{}
}
pub fn (mut e Program) pop_state() {
e.states.pop()
}
pub fn (mut e Program) pop_index() NodeIndex {
if e.stack_index.len == 0 {
return 0
}
return e.stack_index.pop()
}
pub fn (mut e Program) pop() string {
if e.stack.len == 0 {
return ''
}
return e.stack.pop()
}
pub fn (mut e Program) push_index(s NodeIndex) {
e.stack_index << s
}
pub fn (mut e Program) push(s string) {
e.stack << s
}
pub fn (mut e Program) state() &EsilState {
if e.states.len == 0 {
e.push_state()
}
return &e.states[e.states.len - 1]
}
pub fn (mut e Program) eval(ni NodeIndex, esil string) NodeIndex {
e.push_state()
e.state().pos = 0
e.stack = []
e.state().tokens = esil.split(',')
pc := e.pc().u64()
for pos in 0 .. e.state().tokens.len {
e.state().pos = pos
// create node for token nth
node := e.cur_node()
// dump(node)
match node.typ {
._operation {
if false {
dst := e.pop_index()
src := e.pop_index()
// pc := '${e.pc()}.$e.state().pos'.u64()
eqop := e.add_name(._operation, node.name, [
dst,
src,
])
// e.add_symbol(pc, dst), e.add_symbol(pc, src), ])
e.add_child(ni, eqop)
} else {
dst := e.pop()
src := e.pop()
// pc := '${e.pc()}.$e.state().pos'.u64()
eqop := e.add_name(._operation, node.name, [
e.add_symbol(pc, dst),
e.add_symbol(pc, src),
])
// e.add_symbol(pc, dst), e.add_symbol(pc, src), ])
e.add_child(ni, eqop)
}
}
._condition {}
._assign {
dst := e.pop()
src := e.pop()
// eprintln('assign $src $dst')
if false {
_ := e.add_name(._register, dst, [])
_ := e.add_name(._register, src, [])
var_res := e.new_local(4, 'res')
var_rus := e.new_local(4, 'rus')
res_byebye := e.add(._assign, [var_res, var_rus])
e.add_child(ni, res_byebye)
}
eqop := e.add(._assign, [
e.add_symbol(pc, dst),
e.add_symbol(pc, src),
])
e.add_child(ni, eqop)
}
._symbol {
//
e.push(node.name)
e.push_index(pos)
}
._goto {
// process and convert
}
._number {
//
e.push(node.name)
e.push_index(pos)
}
else {
eprintln('unk $node.name')
}
}
// dump(node)
e.state().pos++
}
e.pop_state()
return ni
}
pub fn (mut e Program) cur_node() &Node {
mut n := &Node{}
n.typ = e.find_statement_type()
/*
e.state().push('')
e.state().pop()
*/
n.addr = e.pc()
n.pos = e.state().pos
n.name = e.state().tokens[n.pos]
return n
}
pub fn (e Program) pc() string {
return e.r2.cmd('ar?PC').trim_space()
}
+28
View File
@@ -0,0 +1,28 @@
module east
pub fn (mut e Program) optimize(ni NodeIndex) {
// run different levels of optimizations starting on given node
// this function must replicate the code in print() to walk the ast
// and find optimizations and modify the ast accordingly
e.optimize_const(ni)
// e.optimize_empty(ni)
}
pub fn (mut e Program) optimize_const(ni NodeIndex) {
// propagate constant values and fold unnecessary nodes
}
pub fn (mut e Program) optimize_empty(ni NodeIndex) {
mut n := e.node(ni)
mut children := []NodeIndex{}
for c in n.children {
cn := e.node(c)
if cn.children.len >= 0 {
e.del_child(ni, c)
// children << c
children << c
}
// e.optimize_empty(c)
}
n.children = children
}
+265
View File
@@ -0,0 +1,265 @@
module east
pub fn (mut e Program) str() string {
return e.str_node(0)
}
pub fn (mut e Program) incdent(inc int) {
e.indent_level += inc
}
pub fn (mut e Program) indent() string {
mut s := []string{}
for _ in 0 .. e.indent_level {
s << ''
}
return s.join(' ')
}
pub fn (mut e Program) str_args(idx int) string {
e.ast.find_type = ._argument
s := e.str_code(idx)
e.ast.find_type = ._none
return s.trim_space().split('\n').join(', ')
}
pub fn (mut e Program) str_locals(idx int) string {
e.ast.find_type = ._local
s := e.str_code(idx)
e.ast.find_type = ._none
return s
}
pub fn (mut e Program) str_code(idx int) string {
e.deep++
if e.deep > 10 {
eprintln('yamete kudasai')
e.deep--
return ''
}
mut s := []string{}
n := e.node(idx)
typ := e.ast.find_type
match n.typ {
._call {
sym := e.str_code(n.children[0]).trim_space()
arg := e.str_code(n.children[1]).trim_space()
if typ == ._none {
// s << e.indent()
s << '$sym ($arg)'
} else {
s << sym
s << arg
}
}
._block {
if n.children.len == 0 {
// nothing
} else if typ == ._none {
s << '{\n'
e.incdent(2)
for c in n.children {
e.indent()
s << e.str_code(c) + '\n'
}
e.incdent(-2)
s << e.indent() + '}\n'
} else {
for c in n.children {
s << e.str_code(c)
}
}
}
._function {
if typ == ._none {
args := e.str_args(idx)
s << 'fn ${n.name}($args) {\n'
e.incdent(2)
mut locals := []string{}
for loc in e.str_locals(idx).split('\n') {
if loc !in locals {
if loc != '' {
// TODO: use r2 to resolve type for this variable
locals << loc
}
}
}
for loc in locals {
s << e.indent()
s << 'var $loc\n'
}
for c in n.children {
s << e.indent()
s << e.str_code(c) + '\n'
}
e.incdent(-2)
s << '}\n'
} else {
for c in n.children {
s << e.str_code(c)
}
}
}
._if {
if typ == ._none {
s << 'if '
s << e.str_code(n.children[0])
s << ' {\n'
e.incdent(2)
s << e.str_code(n.children[1])
if n.children.len > 2 {
// TODO: handle else if
e.incdent(-2)
s << e.indent()
s << '} else {\n'
e.incdent(2)
s << e.str_code(n.children[2])
e.incdent(-2)
s << e.indent()
s << '}\n'
} else {
e.incdent(-2)
s << e.indent()
s << '}\n'
}
} else {
s << e.str_code(n.children[0])
s << e.str_code(n.children[1])
if n.children.len > 2 {
s << e.str_code(n.children[2])
}
}
}
._comment {
if typ == ._none {
if n.name != '' {
s << e.indent()
s << '// $n.name '
}
}
}
._operation {
if typ == ._none {
s << e.indent()
if _ := n.name.index('=') {
s << e.str_code(n.children[0])
s << ' $n.name '
s << 'tmp'
} else {
s << 'tmp = '
s << e.str_code(n.children[0])
s << ' $n.name '
// nn := e.node(n.children[1])
// s << ' ($nn) '
dos := e.str_code(n.children[1])
if dos == '' {
s << 'tmp'
} else {
s << dos
}
}
}
}
._condition {
if typ != ._none {
for c in n.children {
s << e.str_code(c)
}
} else {
s << '('
for c in n.children {
s << e.str_code(c).trim_space()
}
s << ')'
}
}
._while {
if typ == ._none {
s << 'while $n.name {\n'
e.incdent(2)
for c in n.children {
s << e.indent()
s << e.str_code(c) + '\n'
}
e.incdent(-2)
s << '}\n'
} else {
for c in n.children {
s << e.str_code(c)
}
}
}
._argument {
if typ == ._none || typ == ._argument {
s << '$n.name\n'
}
}
._assign {
if typ == ._none {
s << e.indent()
s << e.str_code(n.children[0]).trim_space()
s << ' = '
s << e.str_code(n.children[1]).trim_space()
} else {
s << e.str_code(n.children[0])
s << e.str_code(n.children[1])
}
}
._register, ._symbol {
if typ == ._none {
s << '$n.name'
}
}
._number {
if typ == ._none {
s << '$n.name'
}
}
._label {
if typ == ._none && n.name != '' {
s << e.indent() + '$n.name:\n'
}
}
._string {
if typ == ._none {
s << '"$n.name"'
}
}
._local {
if typ == ._none || typ == ._local {
name := '$n.name\n'
if name !in s {
s << name
}
}
}
else {
// eprintln('Unhandled node $n')
}
}
e.deep--
return s.join('')
}
pub fn (mut e Program) str_node(idx int) string {
n := e.node(idx)
mut s := []string{}
/*
s << 'node_name: $n.name\n'
for c in n.children {
s << '- $c\n'
}
s << '## Nodes\n'
for c in e.state().nodes {
s << '- $c\n'
}
s << '## Decompilation\n'
*/
if n.typ == ._function {
//
s << e.str_code(idx)
} else {
eprintln('We can only start decompiling from a function')
}
return s.join('')
}
+194
View File
@@ -0,0 +1,194 @@
import east
import os
import cli { Command, Flag }
import radare.r2pipe
struct Options {
esil string
file string
arch string
}
fn pdvtool() Options {
mut cmd := Command{
name: 'east'
description: 'esil-ast based decompiler on top of r2'
version: '0.0.1'
}
cmd.add_flag(Flag{
flag: .string
name: 'file'
abbrev: 'f'
description: 'program file to open'
})
cmd.add_flag(Flag{
flag: .string
name: 'esil'
abbrev: 'e'
description: 'esil expression to decompile'
})
/*
mut test_cmd := Command{
name: 'test'
description: 'decompile an esil expression'
}
cmd.add_command(test_cmd)
*/
cmd.setup()
cmd.parse(os.args)
if os.args.len == 1 {
exit(1)
}
mut arch := ''
if e := cmd.flags.get_string('arch') {
if e != '' {
arch = e
}
}
mut file := '-'
if e := cmd.flags.get_string('file') {
if e != '' {
file = e
}
}
mut esil := ''
if e := cmd.flags.get_string('esil') {
if e != '' {
esil = e
}
}
return Options{
arch: arch
esil: esil
file: file
}
}
fn main() {
mut opt := pdvtool()
println(opt)
if opt.esil != '' {
main_hello(opt)
} else {
main_hello(opt)
main_hello2()
main_hello3()
}
}
fn main_hello(opt Options) {
r2 := r2pipe.spawn(opt.file, '') or {
eprintln('r2pipe.spawn: $err')
exit(1)
}
if opt.arch != '' {
r2.cmd('e asm.arch=$opt.arch')
}
esil := if opt.esil == '' { '1,eax,:=' } else { opt.esil }
mut program := east.new_program(r2)
mut statements := []east.NodeIndex{}
statements << program.new_statement('0x1000', esil)
mut function := program.new_function('test', statements)
kode := program.str_node(function)
println(kode)
}
fn main_hello2() {
r2 := r2pipe.spawn('test/bins/hello', '') or {
eprintln('r2pipe.spawn: $err')
exit(1)
}
mut program := east.new_program(r2)
func := program.load_function('main')
// test adding node
{
var_res := program.new_local(4, 'res')
var_rus := program.new_local(4, 'rus')
res_byebye := program.add(._assign, [var_res, var_rus])
program.add_child(func, res_byebye)
}
kode := program.str_node(func)
println(kode)
exit(0)
}
fn main_hello3() {
r2 := r2pipe.spawn('test/bins/hello', '') or {
eprintln('r2pipe.spawn: $err')
exit(1)
}
mut e := east.new_program(r2)
// e.on('reg_read', fn (name) => { if name == 'PC' { } })
/*
e.add_symbol('esi', 'arg0')
e.add_symbol('rsi', 'arg0')
e.add_symbol('esi', 'arg1')
e.add_symbol('rsi', 'arg1')
if s := e.find_symbol('rsi') {
println('arg0 is accessed')
// e.propagate_symbol()
}
*/
for _ in 0 .. 10 {
pc := e.pc()
e.step()
expr := e.expr(pc)
e.eval(0, expr)
eprintln('before($pc) now($e.pc()) $expr')
}
/*
e.add_type('int', 'int')
e.add_type('hello_t', 'struct { int msg; }')
*/
sym_puts := e.add_symbol(0x808080, 'puts')
sym_win := e.add_string(0, 'win')
sym_fail := e.add_string(0, 'fail')
cn_bb_true := e.add(._block, [
e.add(._call, [sym_puts, sym_win]),
])
cn_bb_false := e.add(._block, [
e.add(._call, [sym_puts, sym_fail]),
])
arg_argc := e.add_argument(0, 'argc')
cn_cmp := e.add(._condition, [
arg_argc,
e.add_operation('<'),
e.add_number(10),
])
ifelse := e.add(._if, [
cn_cmp,
cn_bb_true,
cn_bb_false,
])
sym_byebye := e.add_string(0, 'byebye')
call_byebye := e.add(._call, [sym_puts, sym_byebye])
var_res := e.new_local(4, 'tmp')
res_byebye := e.add(._assign, [var_res, call_byebye])
sym_exit := e.add_symbol(0, 'exit')
call_exit := e.add(._call, [sym_exit, var_res])
n_func := e.add(._function, [
ifelse,
res_byebye,
call_exit,
])
e.node(n_func).name = 'main'
// optimize function
e.optimize(n_func)
code := e.str_node(n_func)
println(code)
r2.cmd('q')
}
+75
View File
@@ -0,0 +1,75 @@
module pdv
import east
import json
import radare.r2
struct R2ijcore {
file string
size int
fd int
}
struct R2ij {
core R2ijcore
}
pub struct RCore {}
fn plugin_call(coreptr voidptr, cmd &char) int {
// eprintln('cal')
core := r2.cast(coreptr)
c := unsafe { cmd.vstring() }
if c.starts_with('pdv') {
core.cmd('?E decompiler not yet integrated')
ij := core.cmd('ij')
a := json.decode(R2ij, ij) or {
eprintln('failed to decode ij JSON')
return 0
}
eprintln(a.core.file)
//
r2p := r2.cast(core)
mut e := east.new_program(r2p)
fname := r2p.cmd('afi.')
if fname.len > 0 {
func := e.load_function(fname)
e.optimize(func)
kode := e.str_node(func)
println(kode)
} else {
eprintln('No function?')
}
// e.free ()
return 1
}
return 0
}
// definition
// ignored
[export: 'radare_plugin_function']
[manual_free]
fn radare_plugin_function() &C.r_lib_struct_t {
pdv_plugin := &C.r_core_plugin_t{
name: 'pdv'.str
desc: 'the v decompiler for r2'.str
license: 'MIT'.str
call: plugin_call
}
unsafe {
pp := C.malloc(1024) // too large
C.memcpy(pp, pdv_plugin, 1024)
p := &C.r_lib_struct_t{
@type: C.R_LIB_TYPE_CORE
data: pp // &pdv_plugin
pkgname: 'pdv'.str
}
ppp := C.malloc(1024) // too large
C.memcpy(ppp, p, 1024)
return ppp
}
// C.fprintf(C.stderr, '%p\n'.str, p)
// return p
}
BIN
View File
Binary file not shown.
+19
View File
@@ -0,0 +1,19 @@
#include <stdio.h>
void fn_hello(void) {
puts ("Hello World");
}
int fn_ifelse(int argc) {
if (argc < 3) {
puts ("one");
return 1;
}
return 0;
}
int main(int argc) {
fn_hello ();
int res = fn_ifelse (argc);
return res;
}
BIN
View File
Binary file not shown.
+9
View File
@@ -0,0 +1,9 @@
Module {
name: 'east'
description: 'An ESIL-based decommpiler for r2 written in V'
version: '0.1.0'
author: 'pancake'
license: 'MIT'
repo_url: 'https://github.com/vlang/v'
dependencies: ['radare.r2', 'radare.r2pipe']
}
+11 -8
View File
@@ -1,8 +1,8 @@
include build.mk
PLUGINS=arm x86 mips sparc ppc hexagon sysz
PLUGINS=arm x86 mips sparc ppc hexagon s390x evm
LIBS=$(addsuffix _ks.$(SO_EXT),$(addprefix asm_,${PLUGINS}))
LIBS=$(addsuffix _ks.$(SO_EXT),$(addprefix arch_,${PLUGINS}))
#R2PM_PLUGDIR?=${LIBDIR}/radare2/last/
R2PM_PLUGDIR?=~/.config/radare2/plugins
R2PM_PREFIX?=~/.config/radare2/prefix
@@ -23,27 +23,30 @@ all: $(PLUGINS)
define kscc
$(CC) -c -fPIC -Wall\
$(R2_CFLAGS) $(KS_CFLAGS)\
-o asm_$(1)_ks.$(O_EXT) asm_$(1)_ks.c
-o arch_$(1)_ks.$(O_EXT) arch_$(1)_ks.c
$(CXX) $(LDFLAGS_SHARED)\
$(R2_LDFLAGS) $(KS_LDFLAGS)\
-o asm_$(1)_ks.$(SO_EXT) asm_$(1)_ks.$(O_EXT) $(KS_LINK)
rm asm_$(1)_ks.$(O_EXT)
-o arch_$(1)_ks.$(SO_EXT) arch_$(1)_ks.$(O_EXT) $(KS_LINK)
rm arch_$(1)_ks.$(O_EXT)
endef
define ksmake
asm_$(1)_ks.$(SO_EXT): asm_$(1)_ks.c keystone.c
arch_$(1)_ks.$(SO_EXT): arch_$(1)_ks.c keystone.c
$$(call kscc,$(1))
endef
$(foreach lib,$(PLUGINS),$(eval $(call ksmake,$(lib))))
$(PLUGINS):
$(MAKE) asm_$@_ks.$(SO_EXT)
$(MAKE) arch_$@_ks.$(SO_EXT)
install:
$(foreach lib,$(LIBS),$(INSTALL_LIB) $(lib) $(R2PM_PLUGDIR);)
uninstall:
user-install:
$(foreach lib,$(LIBS),$(INSTALL_LIB) $(lib) $(R2PM_PLUGDIR);)
user-uninstall uninstall:
rm -rf $(R2PM_PLUGDIR)/*_ks.*
test:
@@ -1,12 +1,12 @@
/* radare2-keystone - GPL - Copyright 2016 - pancake */
/* radare2-keystone - GPL - Copyright 2016-2023 - pancake */
#include <r_asm.h>
#include <r_arch.h>
#include <r_lib.h>
#include <keystone/keystone.h>
#include <keystone/arm.h>
#include "keystone.c"
static int assemble(RAsm *a, RAsmOp *ao, const char *str) {
static bool assemble(RArchSession *a, RAnalOp *ao, RArchEncodeMask mask) {
ks_arch arch = KS_ARCH_ARM;
ks_mode mode = KS_MODE_ARM;
switch (a->config->bits) {
@@ -22,22 +22,25 @@ static int assemble(RAsm *a, RAsmOp *ao, const char *str) {
if (a->config->big_endian) {
mode = (ks_mode)((int)mode | KS_MODE_BIG_ENDIAN);
}
return keystone_assemble (a, ao, str, arch, mode);
return keystone_assemble (a, ao, ao->mnemonic, arch, mode);
}
RAsmPlugin r_asm_plugin_arm_ks = {
.name = "arm.ks",
.desc = "ARM keystone assembler",
.license = "GPL",
RArchPlugin r_arch_plugin_arm_ks = {
.meta = {
.name = "arm.ks",
.desc = "ARM keystone assembler",
.license = "GPL",
},
.arch = "arm",
.bits = 16|32|64,
.assemble = &assemble,
.bits = R_SYS_BITS_PACK3 (16, 32, 64),
.encode = &assemble,
.decode = NULL,
};
#ifndef CORELIB
RLibStruct radare_plugin = {
.type = R_LIB_TYPE_ASM,
.data = &r_asm_plugin_arm_ks,
.type = R_LIB_TYPE_ARCH,
.data = &r_arch_plugin_arm_ks,
.version = R2_VERSION
};
#endif
+34
View File
@@ -0,0 +1,34 @@
/* radare2-keystone - GPL - Copyright 2016-2023 - pancake */
#include <r_arch.h>
#include <r_lib.h>
#include <keystone/keystone.h>
#include <keystone/evm.h>
#include "keystone.c"
static bool assemble(RArchSession *a, RAnalOp *ao, RArchEncodeMask mask) {
ks_mode mode = (ks_mode)0;
if (a->config->big_endian) {
mode = (ks_mode)((int)mode | KS_MODE_BIG_ENDIAN);
}
return keystone_assemble (a, ao, ao->mnemonic, KS_ARCH_SYSTEMZ, mode);
}
RArchPlugin r_arch_plugin_evm_ks = {
.meta = {
.name = "evm.ks",
.desc = "EVM keystone assembler",
.license = "GPL",
},
.arch = "evm",
.bits = 32,
.encode = &assemble,
};
#ifndef CORELIB
RLibStruct radare_plugin = {
.type = R_LIB_TYPE_ARCH,
.data = &r_arch_plugin_evm_ks,
.version = R2_VERSION
};
#endif
+34
View File
@@ -0,0 +1,34 @@
/* radare2-keystone - GPL - Copyright 2016 - pancake */
#include <r_arch.h>
#include <r_lib.h>
#include <keystone/keystone.h>
#include <keystone/hexagon.h>
#include "keystone.c"
static bool assemble(RArchSession *a, RAnalOp *ao, RArchEncodeMask mask) {
ks_mode mode = (ks_mode)0;
if (a->config->big_endian) {
mode = (ks_mode)((int)mode | KS_MODE_BIG_ENDIAN);
}
return keystone_assemble (a, ao, ao->mnemonic, KS_ARCH_HEXAGON, mode);
}
RArchPlugin r_arch_plugin_hexagon_ks = {
.meta = {
.name = "hexagon.ks",
.desc = "Hexagon keystone assembler",
.license = "GPL",
},
.arch = "hexagon",
.bits = 32,
.encode = &assemble,
};
#ifndef CORELIB
RLibStruct radare_plugin = {
.type = R_LIB_TYPE_ARCH,
.data = &r_arch_plugin_hexagon_ks,
.version = R2_VERSION
};
#endif
@@ -1,12 +1,12 @@
/* radare2-keystone - GPL - Copyright 2016 - pancake */
/* radare2-keystone - GPL - Copyright 2016-2023 - pancake */
#include <r_asm.h>
#include <r_arch.h>
#include <r_lib.h>
#include <keystone/keystone.h>
#include <keystone/mips.h>
#include "keystone.c"
static int assemble(RAsm *a, RAsmOp *ao, const char *str) {
static bool assemble(RArchSession *a, RAnalOp *ao, RArchEncodeMask mask) {
ks_mode mode;
switch (a->config->bits) {
case 16:
@@ -22,22 +22,24 @@ static int assemble(RAsm *a, RAsmOp *ao, const char *str) {
if (a->config->big_endian) {
mode = (ks_mode)((int)mode | KS_MODE_BIG_ENDIAN);
}
return keystone_assemble (a, ao, str, KS_ARCH_MIPS, mode);
return keystone_assemble (a, ao, ao->mnemonic, KS_ARCH_MIPS, mode);
}
RAsmPlugin r_asm_plugin_mips_ks = {
.name = "mips.ks",
.desc = "MIPS keystone assembler",
.license = "GPL",
RArchPlugin r_arch_plugin_mips_ks = {
.meta = {
.name = "mips.ks",
.desc = "MIPS keystone assembler",
.license = "GPL",
},
.arch = "mips",
.bits = 16|32|64,
.assemble = &assemble,
.bits = R_SYS_BITS_PACK3 (16, 32, 64),
.encode = &assemble,
};
#ifndef CORELIB
struct r_lib_struct_t radare_plugin = {
.type = R_LIB_TYPE_ASM,
.data = &r_asm_plugin_mips_ks,
.type = R_LIB_TYPE_ARCH,
.data = &r_arch_plugin_mips_ks,
.version = R2_VERSION
};
#endif
+42
View File
@@ -0,0 +1,42 @@
/* radare2-keystone - GPL - Copyright 2016-2023 - pancake */
#include <r_arch.h>
#include <r_lib.h>
#include <keystone/keystone.h>
#include <keystone/ppc.h>
#include "keystone.c"
static bool assemble(RArchSession *a, RAnalOp *ao, RArchEncodeMask mask) {
ks_mode mode = (ks_mode)0;
switch (a->config->bits) {
case 32:
mode = KS_MODE_PPC32;
break;
case 64:
mode = KS_MODE_PPC64;
break;
}
if (a->config->big_endian) {
mode = (ks_mode)((int)mode | KS_MODE_BIG_ENDIAN);
}
return keystone_assemble (a, ao, ao->mnemonic, KS_ARCH_PPC, mode);
}
RArchPlugin r_arch_plugin_ppc_ks = {
.meta = {
.name = "ppc.ks",
.desc = "powerpc keystone assembler",
.license = "GPL",
},
.arch = "ppc",
.bits = R_SYS_BITS_PACK2 (32,64),
.encode = &assemble,
};
#ifndef CORELIB
RLibStruct radare_plugin = {
.type = R_LIB_TYPE_ARCH,
.data = &r_arch_plugin_ppc_ks,
.version = R2_VERSION
};
#endif
+34
View File
@@ -0,0 +1,34 @@
/* radare2-keystone - GPL - Copyright 2016-2023 - pancake */
#include <r_arch.h>
#include <r_lib.h>
#include <keystone/keystone.h>
#include <keystone/systemz.h>
#include "keystone.c"
static bool assemble(RArchSession *a, RAnalOp *ao, RArchEncodeMask mask) {
ks_mode mode = (ks_mode)0;
if (a->config->big_endian) {
mode = (ks_mode)((int)mode | KS_MODE_BIG_ENDIAN);
}
return keystone_assemble (a, ao, ao->mnemonic, KS_ARCH_SYSTEMZ, mode);
}
RArchPlugin r_arch_plugin_s390x_ks = {
.meta = {
.name = "s390x.ks",
.desc = "SystemZ keystone assembler (S390X)",
.license = "GPL",
},
.arch = "s390x",
.bits = 32,
.encode = &assemble,
};
#ifndef CORELIB
RLibStruct radare_plugin = {
.type = R_LIB_TYPE_ARCH,
.data = &r_arch_plugin_s390x_ks,
.version = R2_VERSION
};
#endif
@@ -1,12 +1,12 @@
/* radare2-keystone - GPL - Copyright 2016 - pancake */
#include <r_asm.h>
#include <r_arch.h>
#include <r_lib.h>
#include <keystone/keystone.h>
#include <keystone/sparc.h>
#include "keystone.c"
static int assemble(RAsm *a, RAsmOp *ao, const char *str) {
static bool assemble(RArchSession *a, RAnalOp *ao, RArchEncodeMask mask) {
ks_mode mode = (ks_mode)0;
switch (a->config->bits) {
case 32:
@@ -19,22 +19,24 @@ static int assemble(RAsm *a, RAsmOp *ao, const char *str) {
if (a->config->big_endian) {
mode = (ks_mode)((int)mode | KS_MODE_BIG_ENDIAN);
}
return keystone_assemble (a, ao, str, KS_ARCH_SPARC, mode);
return keystone_assemble (a, ao, ao->mnemonic, KS_ARCH_SPARC, mode);
}
RAsmPlugin r_asm_plugin_sparc_ks = {
.name = "sparc.ks",
.desc = "sparc keystone assembler",
.license = "GPL",
RArchPlugin r_arch_plugin_sparc_ks = {
.meta = {
.name = "sparc.ks",
.desc = "sparc keystone assembler",
.license = "GPL",
},
.arch = "sparc",
.bits = 32|64,
.assemble = &assemble,
.bits = R_SYS_BITS_PACK2 (32, 64),
.encode = &assemble,
};
#ifndef CORELIB
struct r_lib_struct_t radare_plugin = {
.type = R_LIB_TYPE_ASM,
.data = &r_asm_plugin_sparc_ks,
RLibStruct radare_plugin = {
.type = R_LIB_TYPE_ARCH,
.data = &r_arch_plugin_sparc_ks,
.version = R2_VERSION
};
#endif
+42
View File
@@ -0,0 +1,42 @@
/* radare2-keystone - GPL - Copyright 2016-2023 - pancake */
#include <r_arch.h>
#include <r_lib.h>
#include <keystone/keystone.h>
#include <keystone/x86.h>
#include "keystone.c"
static bool assemble(RArchSession *a, RAnalOp *ao, RArchEncodeMask mask) {
ks_mode mode = (ks_mode)0;
switch (a->config->bits) {
case 16:
mode = KS_MODE_16;
break;
case 32:
mode = KS_MODE_32;
break;
case 64:
mode = KS_MODE_64;
break;
}
return keystone_assemble (a, ao, ao->mnemonic, KS_ARCH_X86, mode);
}
RArchPlugin r_arch_plugin_x86_ks = {
.meta = {
.name = "x86.ks",
.desc = "x86 keystone assembler",
.license = "GPL",
},
.arch = "x86",
.bits = R_SYS_BITS_PACK3 (16, 32, 64),
.encode = &assemble,
};
#ifndef CORELIB
RLibStruct radare_plugin = {
.type = R_LIB_TYPE_ARCH,
.data = &r_arch_plugin_x86_ks,
.version = R2_VERSION
};
#endif
-32
View File
@@ -1,32 +0,0 @@
/* radare2-keystone - GPL - Copyright 2016 - pancake */
#include <r_asm.h>
#include <r_lib.h>
#include <keystone/keystone.h>
#include <keystone/hexagon.h>
#include "keystone.c"
static int assemble(RAsm *a, RAsmOp *ao, const char *str) {
ks_mode mode = (ks_mode)0;
if (a->config->big_endian) {
mode = (ks_mode)((int)mode | KS_MODE_BIG_ENDIAN);
}
return keystone_assemble (a, ao, str, KS_ARCH_HEXAGON, mode);
}
RAsmPlugin r_asm_plugin_hexagon_ks = {
.name = "hexagon.ks",
.desc = "Hexagon keystone assembler",
.license = "GPL",
.arch = "hexagon",
.bits = 32,
.assemble = &assemble,
};
#ifndef CORELIB
struct r_lib_struct_t radare_plugin = {
.type = R_LIB_TYPE_ASM,
.data = &r_asm_plugin_hexagon_ks,
.version = R2_VERSION
};
#endif
-40
View File
@@ -1,40 +0,0 @@
/* radare2-keystone - GPL - Copyright 2016 - pancake */
#include <r_asm.h>
#include <r_lib.h>
#include <keystone/keystone.h>
#include <keystone/ppc.h>
#include "keystone.c"
static int assemble(RAsm *a, RAsmOp *ao, const char *str) {
ks_mode mode = (ks_mode)0;
switch (a->config->bits) {
case 32:
mode = KS_MODE_PPC32;
break;
case 64:
mode = KS_MODE_PPC64;
break;
}
if (a->config->big_endian) {
mode = (ks_mode)((int)mode | KS_MODE_BIG_ENDIAN);
}
return keystone_assemble (a, ao, str, KS_ARCH_PPC, mode);
}
RAsmPlugin r_asm_plugin_ppc_ks = {
.name = "ppc.ks",
.desc = "powerpc keystone assembler",
.license = "GPL",
.arch = "ppc",
.bits = 32|64,
.assemble = &assemble,
};
#ifndef CORELIB
struct r_lib_struct_t radare_plugin = {
.type = R_LIB_TYPE_ASM,
.data = &r_asm_plugin_ppc_ks,
.version = R2_VERSION
};
#endif
-32
View File
@@ -1,32 +0,0 @@
/* radare2-keystone - GPL - Copyright 2016 - pancake */
#include <r_asm.h>
#include <r_lib.h>
#include <keystone/keystone.h>
#include <keystone/systemz.h>
#include "keystone.c"
static int assemble(RAsm *a, RAsmOp *ao, const char *str) {
ks_mode mode = (ks_mode)0;
if (a->config->big_endian) {
mode = (ks_mode)((int)mode | KS_MODE_BIG_ENDIAN);
}
return keystone_assemble (a, ao, str, KS_ARCH_SYSTEMZ, mode);
}
RAsmPlugin r_asm_plugin_sysz_ks = {
.name = "sysz.ks",
.desc = "SystemZ keystone assembler (S390X)",
.license = "GPL",
.arch = "sysz",
.bits = 32,
.assemble = &assemble,
};
#ifndef CORELIB
struct r_lib_struct_t radare_plugin = {
.type = R_LIB_TYPE_ASM,
.data = &r_asm_plugin_sysz_ks,
.version = R2_VERSION
};
#endif
-40
View File
@@ -1,40 +0,0 @@
/* radare2-keystone - GPL - Copyright 2016 - pancake */
#include <r_asm.h>
#include <r_lib.h>
#include <keystone/keystone.h>
#include <keystone/x86.h>
#include "keystone.c"
static int assemble(RAsm *a, RAsmOp *ao, const char *str) {
ks_mode mode = (ks_mode)0;
switch (a->config->bits) {
case 16:
mode = KS_MODE_16;
break;
case 32:
mode = KS_MODE_32;
break;
case 64:
mode = KS_MODE_64;
break;
}
return keystone_assemble (a, ao, str, KS_ARCH_X86, mode);
}
RAsmPlugin r_asm_plugin_x86_ks = {
.name = "x86.ks",
.desc = "x86 keystone assembler",
.license = "GPL",
.arch = "x86",
.bits = 16 | 32 | 64,
.assemble = &assemble,
};
#ifndef CORELIB
struct r_lib_struct_t radare_plugin = {
.type = R_LIB_TYPE_ASM,
.data = &r_asm_plugin_x86_ks,
.version = R2_VERSION
};
#endif
+44 -15
View File
@@ -1,5 +1,5 @@
#!/bin/sh
# This script was automatically generated by ACR v2.0.0
# This script was automatically generated by ACR v2.2.4
# @author: pancake <nopcode.org>
# @url: http://www.nopcode.org
# @repo: git clone https://github.com/radare/acr
@@ -65,13 +65,27 @@ if [ -e "${VPATH}/config.guess" ]; then
sh ${VPATH}/config.guess
return
fi
CPU="`uname -m|sed -e 's, ,,g'|cut -d - -f 1`"
CPU="`uname -m | tr 'A-Z' 'a-z' | sed -e 's, ,,g' | cut -d - -f 1`"
OS="`uname -s|tr A-Z a-z`"
uname -r | grep -qE "(Microsoft|WSL)" 2>/dev/null && OS="wsl"
GNU="`uname --help 2>&1 | grep gnu`"
[ "${GNU}" ] && OS="${OS}-gnu"
[ "${CPU}" = ppc ] && CPU="powerpc"
echo "${CPU}-unknown-${OS}"
# normalize CPU
case "${CPU}" in
ppc*|powermac*|powermacintosh*|powerpc*)
if echo "${CPU}" | grep -q '64'; then
CPU=powerpc64
else
CPU=powerpc
fi
;;
*) ;;
esac
VENDOR="unknown"
if [ "${OS}" = "darwin" ]; then
VENDOR=apple
fi
echo "${CPU}-${VENDOR}-${OS}"
}
SEARCHPATH="/usr /usr/local /usr/pkg /sw"
@@ -83,6 +97,7 @@ HOST="${BUILD}"
TARGET="${HOST}"
ETCDIR="/etc"
SYSCONFDIR=""
DESCRIPTION=""
create_environ() {
: ${EPREFIX:="${PREFIX}"}
@@ -91,6 +106,8 @@ create_environ() {
: ${SBINDIR:="${PREFIX}/sbin"}
: ${ETCDIR:="${SPREFIX}/etc"}
: ${LIBDIR:="${SPREFIX}/lib"}
: ${PKGCFG_LIBDIR:='${exec_prefix}/lib'}
: ${PKGCFG_INCDIR:='${prefix}/include'}
: ${LIBEXECDIR:="${SPREFIX}/libexec"}
: ${INCLUDEDIR:="${SPREFIX}/include"}
: ${DATADIR:="${SPREFIX}/share"}
@@ -198,7 +215,7 @@ if [ "$QUIET" = 1 ]; then
echo "0.2"
exit 0
fi
echo "radare2-keystone-0.2 configuration script done with acr v2.0.0.
echo "radare2-keystone-0.2 configuration script done with acr v2.2.4.
The 'Free Software Foundation' message is only for autodetection.
Originally written by pancake <nopcode.org>."
exit 0
@@ -226,10 +243,12 @@ case $flag in
-V|-version|--version)
show_version ; ;;
-r|--r|--report)
echo "PKGNAME: radare2-keystone"
echo "VERSION: 0.2"
echo "LANGS: c c++"
echo "PKG-CONFIG: r_asm keystone"
echo "PKGNAME: radare2-keystone"
echo "VERSION: 0.2"
echo "AUTHOR: pancake"
echo "EMAIL: [email protected]"
echo "LANGS: c c++"
echo "PKGCONFIG: r_asm keystone"
exit 0
;;
--cache-file)
@@ -269,10 +288,12 @@ echo "PKG-CONFIG: r_asm keystone"
--localstatedir)
LOCALSTATEDIR="$value"; ;;
--libdir)
LIBDIR="$value"; ;;
LIBDIR="$value"
PKGCFG_LIBDIR="$value"; ;;
--libpath)
LDFLAGS="${LDFLAGS} ${LIBPATH}$value"; ;;
--includedir)
PKGCFG_INCDIR="$value"
INCLUDEDIR="$value"; CFLAGS="${CFLAGS} -I$value"; ;;
--infodir)
INFODIR="$value"; ;;
@@ -296,7 +317,7 @@ parse_options "$1"
shift
done
ENVWORDS="MANDIR INFODIR LIBDIR INCLUDEDIR LOCALSTATEDIR ETCDIR SYSCONFDIR DATADIR DOCDIR LIBEXECDIR SBINDIR BINDIR EPREFIX PREFIX SPREFIX TARGET HOST BUILD INSTALL INSTALL_LIB INSTALL_MAN INSTALL_PROGRAM INSTALL_PROGRAM_STRIP INSTALL_DIR INSTALL_SCRIPT INSTALL_DATA HOST_OS HOST_CPU BUILD_OS BUILD_CPU TARGET_OS TARGET_CPU VERSION VERSION_MAJOR VERSION_MINOR VERSION_PATCH VERSION_NUMBER PKGNAME VPATH CONTACT CONTACT_NAME CONTACT_MAIL CC CFLAGS CPPFLAGS LDFLAGS HAVE_LANG_C CXX CXXFLAGS HAVE_LANG_CXX PKGCONFIG R2_CFLAGS R2_LDFLAGS HAVE_PKGCFG_R_ASM KS_CFLAGS KS_LDFLAGS HAVE_PKGCFG_KEYSTONE"
ENVWORDS="MANDIR DESCRIPTION INFODIR LIBDIR INCLUDEDIR LOCALSTATEDIR ETCDIR SYSCONFDIR DATADIR DOCDIR LIBEXECDIR SBINDIR BINDIR EPREFIX PREFIX SPREFIX TARGET HOST BUILD INSTALL INSTALL_LIB INSTALL_MAN INSTALL_PROGRAM INSTALL_PROGRAM_STRIP INSTALL_DIR INSTALL_SCRIPT INSTALL_DATA HOST_OS HOST_CPU BUILD_OS BUILD_CPU TARGET_OS TARGET_CPU VERSION VERSION_MAJOR VERSION_MINOR VERSION_PATCH VERSION_NUMBER PKGCFG_LIBDIR PKGCFG_INCDIR PKGNAME VPATH CONTACT CONTACT_NAME CONTACT_MAIL CC CFLAGS CPPFLAGS LDFLAGS HAVE_LANG_C CXX CXXFLAGS HAVE_LANG_CXX PKGCONFIG R2_CFLAGS R2_LDFLAGS HAVE_PKGCFG_R_ASM KS_CFLAGS KS_LDFLAGS HAVE_PKGCFG_KEYSTONE"
create_environ
@@ -311,8 +332,6 @@ ocho "checking for working directories... ${WODIS}"
ocho "using prefix '${PREFIX}'"
ACR_RMFILES=" test.c a.out a.exe test.c test.cxx a.out a.exe"
COMPILER=CC
ochof "checking for c compiler... "
HAVE_LANG_C=1
@@ -321,7 +340,7 @@ if [ "${CROSSBUILD}" = 1 ]; then
if [ $? = 0 ]; then CC="${HOST}-${CC}"; fi
fi
echo "int main(int argc, char **argv){return 0;}" > test.c
(exec ${CC} ${CFLAGS} ${CPPFLAGS} ${LDFLAGS} test.c >/dev/null 2>&1)
(exec ${CC} -o a.out ${CFLAGS} ${CPPFLAGS} ${LDFLAGS} test.c >/dev/null 2>&1)
if [ $? = 0 ]; then echo ${CC}; else
echo no ; HAVE_LANG_C=0
do_remove
@@ -346,6 +365,7 @@ do_remove
exit 1
fi
ochof "checking for pkg-config... "
ENVWORDS="${ENVWORDS} HAVE_PKGCONFIG"
if [ -n "$PKGCONFIG" ]; then
if [ -x "$PKGCONFIG" ]; then
_HAVE_PKGCONFIG="${PKGCONFIG}"
@@ -369,7 +389,9 @@ else
fi
if [ -n "${PKGCONFIG}" ]; then
ocho ${PKGCONFIG}
HAVE_PKGCONFIG=1
else
HAVE_PKGCONFIG=0
echo "Cannot find pkg-config or pkgconf in PATH" >&2
exit 1
ocho no; fi
@@ -407,7 +429,14 @@ for A in ${ENVWORDS} ; do
[ "${A}" = VPATH ] && continue
[ "${A}" = srcdir ] && continue
eval "VAR=\$${A}"
VAR="`echo ${VAR} | sed -e 's/\,/\\\,/g'`"
case "" in
mingw*|cygwin*|msys*)
VAR="`echo ${VAR} | sed -e 's/\\/\\\\/g' -e 's/\,/\\\,/g'`"
;;
*)
VAR="`echo ${VAR} | sed -e 's/\,/\\\,/g'`"
;;
esac
[ $COUNT = 10 ] && COUNT=0 && SEDFLAGS="${SEDFLAGS}' -e '"
COUNT=$(($COUNT+1))
SEDFLAGS="${SEDFLAGS}s,@${A}@,${VAR},g;"
+11 -10
View File
@@ -12,18 +12,18 @@ static R_TH_LOCAL void *oldcur = NULL;
static R_TH_LOCAL ks_engine *ks = NULL;
static R_TH_LOCAL int oldbit = 0;
static int keystone_assemble(RAsm *a, RAsmOp *ao, const char *str, ks_arch arch, ks_mode mode) {
static bool keystone_assemble(RArchSession *a, RAnalOp *ao, const char *str, ks_arch arch, ks_mode mode) {
ks_err err = KS_ERR_ARCH;
bool must_init = false;
size_t count, size;
ut8 *insn = NULL;
if (!ks_arch_supported (arch)) {
return -1;
return false;
}
must_init = true; //!oldcur || (a->cur != oldcur || oldbit != a->bits);
oldcur = a->cur;
// oldcur = a->cur;
oldbit = a->config->bits;
if (must_init) {
@@ -33,13 +33,13 @@ static int keystone_assemble(RAsm *a, RAsmOp *ao, const char *str, ks_arch arch,
}
err = ks_open (arch, mode, &ks);
if (err || !ks) {
eprintf ("Cannot initialize keystone\n");
R_LOG_ERROR ("Cannot initialize keystone");
ks_free (insn);
if (ks) {
ks_close (ks);
ks = NULL;
}
return -1;
return false;
}
}
@@ -49,14 +49,14 @@ static int keystone_assemble(RAsm *a, RAsmOp *ao, const char *str, ks_arch arch,
ks_close (ks);
ks = NULL;
}
return -1;
return false;
}
if (a->config->syntax == ATTSYNTAX) {
ks_option (ks, KS_OPT_SYNTAX, KS_OPT_SYNTAX_ATT);
} else {
ks_option (ks, KS_OPT_SYNTAX, KS_OPT_SYNTAX_NASM);
}
int rc = ks_asm (ks, str, a->pc, &insn, &size, &count);
int rc = ks_asm (ks, str, ao->addr, &insn, &size, &count);
if (rc) {
eprintf ("ks_asm: (%s) %s\n", str, ks_strerror ((ks_err)ks_errno (ks)));
ks_free (insn);
@@ -64,13 +64,14 @@ static int keystone_assemble(RAsm *a, RAsmOp *ao, const char *str, ks_arch arch,
ks_close (ks);
ks = NULL;
}
return -1;
return false;
}
r_asm_op_set_buf (ao, insn, size);
ao->size = size;
ao->bytes = r_mem_dup (insn, size);
ks_free (insn);
if (ks) {
ks_close (ks);
ks = NULL;
}
return size;
return size > 0;
}
-7
View File
@@ -34,11 +34,7 @@ zyan:
$(MAKE) -C asm zyan
evm:
$(MAKE) -C asm evm
$(MAKE) -C anal evm
$(MAKE) -C io evm
$(MAKE) -C debug evm
nios:
$(MAKE) -C anal nios
@@ -77,10 +73,7 @@ zyan-install:
cp -f asm/p/asm_x86_zyan.$(LIBEXT) $(R2PM_PLUGDIR)
evm-install:
cp -f asm/p/asm_evm.$(LIBEXT) $(R2PM_PLUGDIR)
cp -f anal/p/anal_evm.$(LIBEXT) $(R2PM_PLUGDIR)
cp -f io/p/io_evm.$(LIBEXT) $(R2PM_PLUGDIR)
cp -f debug/p/debug_evm.$(LIBEXT) $(R2PM_PLUGDIR)
nios-install:
cp -f asm/p/asm_nios.$(LIBEXT) $(R2PM_PLUGDIR)
-7
View File
@@ -5,9 +5,6 @@ rl78:
ba2:
cd p ; $(MAKE) anal_ba2.$(LIBEXT)
qdsp6 hexagon:
$(MAKE) -C p anal_hexagon.$(LIBEXT)
bea:
cd p ; $(MAKE) anal_x86_bea.$(LIBEXT)
@@ -20,9 +17,6 @@ m68k_net:
atombios:
cd p ; $(MAKE) anal_atombios.$(LIBEXT)
evm:
cd p ; $(MAKE) anal_evm.$(LIBEXT)
nios:
cd p ; $(MAKE) anal_nios.$(LIBEXT)
@@ -32,6 +26,5 @@ clean:
rm -f p/anal_m68k_net.$(LIBEXT)
rm -f p/anal_atombios.{$(LIBEXT),o}
rm -f p/anal_nios.$(LIBEXT)
rm -f p/anal_hexagon.$(LIBEXT)
include ../../options.mk
-244
View File
@@ -1,244 +0,0 @@
/* radare - LGPL - Copyright 2018-2021 - xvilka */
#include <stdio.h>
#include <stdbool.h>
#include <r_types.h>
#include <r_lib.h>
#include <r_util.h>
#include <r_asm.h>
#include "hexagon.h"
// TODO: Handle also control reg pairs
char* hex_get_cntl_reg(int opreg){
switch (opreg) {
case HEX_REG_SA0:
return "SA0";
case HEX_REG_LC0:
return "LC0";
case HEX_REG_SA1:
return "SA1";
case HEX_REG_LC1:
return "LC1";
case HEX_REG_P:
return "P";
case HEX_REG_M0:
return "M0";
case HEX_REG_M1:
return "M1";
case HEX_REG_USR:
return "USR";
case HEX_REG_PC:
return "PC";
case HEX_REG_UGP:
return "UGP";
case HEX_REG_GP:
return "GP";
case HEX_REG_CS0:
return "CS0";
case HEX_REG_CS1:
return "CS1";
case HEX_REG_UPCYCLELO:
return "UPCYCLELO";
case HEX_REG_UPCYCLEHI:
return "UPCYCLEHI";
case HEX_REG_FRAMELIMIT:
return "FRAMELIMIT";
case HEX_REG_FRAMEKEY:
return "FRAMEKEY";
case HEX_REG_PKTCOUNTLO:
return "PKTCOUNTLO";
case HEX_REG_PKTCOUNTHI:
return "PKTCOUNTHI";
case HEX_REG_UTIMERLO:
return "UTIMERLO";
case HEX_REG_UTIMERHI:
return "UTIMERHI";
default:
return "<CRerr>";
}
}
char* hex_get_sys_reg(int opreg)
{
static char tmp[5];
switch (opreg) {
case HEX_REG_SGP0:
return "SGP0";
case HEX_REG_SGP1:
return "SGP1";
case HEX_REG_STID:
return "STID";
case HEX_REG_ELR:
return "ELR";
case HEX_REG_BADVA0:
return "BADVA0";
case HEX_REG_BADVA1:
return "BADVA1";
case HEX_REG_SSR:
return "SSR";
case HEX_REG_CCR:
return "CCR";
case HEX_REG_HTID:
return "HTID";
case HEX_REG_BADVA:
return "BADVA";
case HEX_REG_IMASK:
return "IMASK";
case HEX_REG_EVB:
return "EVB";
case HEX_REG_MODECTL:
return "MODECTL";
case HEX_REG_SYSCFG:
return "SYSCFG";
case HEX_REG_IPEND:
return "IPEND";
case HEX_REG_VID:
return "VID";
case HEX_REG_IAD:
return "IAD";
case HEX_REG_IEL:
return "IEL";
case HEX_REG_IAHL:
return "IAHL";
case HEX_REG_CFGBASE:
return "CFGBASE";
case HEX_REG_DIAG:
return "DIAG";
case HEX_REG_REV:
return "REV";
case HEX_REG_PCYCLELO:
return "PCYCLELO";
case HEX_REG_PCYCLEHI:
return "PCYCLEHI";
case HEX_REG_ISDBST:
return "ISDBST";
case HEX_REG_ISDBCFG0:
return "ISDBCFG0";
case HEX_REG_ISDBCFG1:
return "ISDBCFG1";
case HEX_REG_BRKPTPC0:
return "BRKPTPC0";
case HEX_REG_BRKPTCFG0:
return "BRKPTCFG0";
case HEX_REG_BRKPTPC1:
return "BRKPTPC1";
case HEX_REG_BRKPTCFG1:
return "BRKPTCFG1";
case HEX_REG_ISDBMBXIN:
return "ISDBMBXIN";
case HEX_REG_ISDBMBXOUT:
return "ISDBMBXOUT";
case HEX_REG_ISDBEN:
return "ISDBEN";
case HEX_REG_ISDBGPR:
return "ISDBGPR";
case HEX_REG_PMUCNT0:
return "PMUCNT0";
case HEX_REG_PMUCNT1:
return "PMUCNT1";
case HEX_REG_PMUCNT2:
return "PMUCNT2";
case HEX_REG_PMUCNT3:
return "PMUCNT3";
case HEX_REG_PMUEVTCFG:
return "PMUEVTCFG";
case HEX_REG_PMUCFG:
return "PMUCFG";
default:
sprintf(tmp, "S%d", opreg);
return tmp;
}
}
char* hex_get_sub_reg(int opreg)
{
switch (opreg) {
case HEX_SUB_REG_R0:
return "R0";
case HEX_SUB_REG_R1:
return "R1";
case HEX_SUB_REG_R2:
return "R2";
case HEX_SUB_REG_R3:
return "R3";
case HEX_SUB_REG_R4:
return "R4";
case HEX_SUB_REG_R5:
return "R5";
case HEX_SUB_REG_R6:
return "R6";
case HEX_SUB_REG_R7:
return "R7";
case HEX_SUB_REG_R16:
return "R16";
case HEX_SUB_REG_R17:
return "R17";
case HEX_SUB_REG_R18:
return "R18";
case HEX_SUB_REG_R19:
return "R19";
case HEX_SUB_REG_R20:
return "R20";
case HEX_SUB_REG_R21:
return "R21";
case HEX_SUB_REG_R22:
return "R22";
case HEX_SUB_REG_R23:
return "R23";
default:
return "<err>";
}
}
char* hex_get_sub_regpair(int opreg)
{
switch (opreg) {
case HEX_SUB_REGPAIR_R1_R0:
return "R1:R0";
case HEX_SUB_REGPAIR_R3_R2:
return "R3:R2";
case HEX_SUB_REGPAIR_R5_R4:
return "R5:R4";
case HEX_SUB_REGPAIR_R7_R6:
return "R7:R6";
case HEX_SUB_REGPAIR_R17_R16:
return "R17:R16";
case HEX_SUB_REGPAIR_R19_R18:
return "R19:R18";
case HEX_SUB_REGPAIR_R21_R20:
return "R21:R20";
case HEX_SUB_REGPAIR_R23_R22:
return "R23:R22";
default:
return "<err>";
}
}
inline bool hex_if_duplex(uint32_t insn_word)
{
if ((insn_word & (3 << 14)) == 0) {
return true;
}
return false;
}
// Constant extender value
ut32 constant_extender = 1;
void hex_op_extend(HexOp *op)
{
if ((constant_extender != 1) && (op->type == HEX_OP_TYPE_IMM)) {
op->op.imm = ((op->op.imm) & 0x3F) | (constant_extender);
}
constant_extender = 1;
}
void hex_op_extend_off(HexOp *op, int offset)
{
if ((constant_extender != 1) && (op->type == HEX_OP_TYPE_IMM)) {
op->op.imm = (op->op.imm) >> offset;
hex_op_extend(op);
}
}
-2
View File
@@ -6,10 +6,8 @@ ARCHS+=x86_bea.mk
ARCHS+=x86_simple.mk
ARCHS+=x86_udis.mk
ARCHS+=m68k_net.mk
ARCHS+=evm.mk
ARCHS+=atombios.mk
ARCHS+=rl78.mk
ARCHS+=nios.mk
ARCHS+=hexagon.mk
include ../../plugs.mk
-638
View File
@@ -1,638 +0,0 @@
#include <string.h>
#include <errno.h>
#include <jansson.h>
#include <r_types.h>
#include <r_lib.h>
#include <r_asm.h>
#include <r_anal.h>
#include <r_util.h>
#include <sdb.h>
#include "evm.h"
struct evm_anal_info {
Sdb *pushs_db;
};
static struct evm_anal_info *evm_ai = NULL;
static unsigned opcodes_types[] = {
[EVM_OP_STOP] = R_ANAL_OP_TYPE_RET,
[EVM_OP_ADD] = R_ANAL_OP_TYPE_ADD,
[EVM_OP_MUL] = R_ANAL_OP_TYPE_MUL,
[EVM_OP_SUB] = R_ANAL_OP_TYPE_SUB,
[EVM_OP_DIV] = R_ANAL_OP_TYPE_DIV,
[EVM_OP_SDIV] = R_ANAL_OP_TYPE_DIV,
[EVM_OP_MOD] = R_ANAL_OP_TYPE_MOD,
[EVM_OP_SMOD] = R_ANAL_OP_TYPE_MOD,
[EVM_OP_ADDMOD] = R_ANAL_OP_TYPE_ADD,
[EVM_OP_MULMOD] = R_ANAL_OP_TYPE_MUL,
[EVM_OP_EXP] = R_ANAL_OP_TYPE_MUL,
[EVM_OP_SIGNEXTEND] = R_ANAL_OP_TYPE_CAST,
[EVM_OP_LT] = R_ANAL_OP_TYPE_COND,
[EVM_OP_GT] = R_ANAL_OP_TYPE_COND,
[EVM_OP_SLT] = R_ANAL_OP_TYPE_COND,
[EVM_OP_SGT] = R_ANAL_OP_TYPE_COND,
[EVM_OP_EQ] = R_ANAL_OP_TYPE_CMP,
[EVM_OP_ISZERO] = R_ANAL_OP_TYPE_CMP,
[EVM_OP_AND] = R_ANAL_OP_TYPE_AND,
[EVM_OP_OR] = R_ANAL_OP_TYPE_OR,
[EVM_OP_XOR] = R_ANAL_OP_TYPE_XOR,
[EVM_OP_NOT] = R_ANAL_OP_TYPE_NOT,
[EVM_OP_BYTE] = R_ANAL_OP_TYPE_MOV,
[EVM_OP_SHA3] = R_ANAL_OP_TYPE_CRYPTO,
[EVM_OP_ADDRESS] = R_ANAL_OP_TYPE_CRYPTO,
[EVM_OP_BALANCE] = R_ANAL_OP_TYPE_CRYPTO,
[EVM_OP_ORIGIN] = R_ANAL_OP_TYPE_CRYPTO,
[EVM_OP_CALLER] = R_ANAL_OP_TYPE_CRYPTO,
[EVM_OP_CALLVALUE] = R_ANAL_OP_TYPE_CRYPTO,
[EVM_OP_CALLDATALOAD] = R_ANAL_OP_TYPE_CRYPTO,
[EVM_OP_CALLDATASIZE] = R_ANAL_OP_TYPE_CRYPTO,
[EVM_OP_CALLDATACOPY] = R_ANAL_OP_TYPE_CRYPTO,
[EVM_OP_CODESIZE] = R_ANAL_OP_TYPE_CRYPTO,
[EVM_OP_CODECOPY] = R_ANAL_OP_TYPE_CRYPTO,
[EVM_OP_GASPRICE] = R_ANAL_OP_TYPE_CRYPTO,
[EVM_OP_EXTCODESIZE] = R_ANAL_OP_TYPE_CRYPTO,
[EVM_OP_EXTCODECOPY] = R_ANAL_OP_TYPE_CRYPTO,
[EVM_OP_RETURNDATASIZE] = R_ANAL_OP_TYPE_PUSH,
[EVM_OP_RETURNDATACOPY] = R_ANAL_OP_TYPE_STORE,
[EVM_OP_BLOCKHASH] = R_ANAL_OP_TYPE_CRYPTO,
[EVM_OP_COINBASE] = R_ANAL_OP_TYPE_CRYPTO,
[EVM_OP_TIMESTAMP] = R_ANAL_OP_TYPE_CRYPTO,
[EVM_OP_NUMBER] = R_ANAL_OP_TYPE_CRYPTO,
[EVM_OP_DIFFICULTY] = R_ANAL_OP_TYPE_CRYPTO,
[EVM_OP_GASLIMIT] = R_ANAL_OP_TYPE_CRYPTO,
[EVM_OP_POP] = R_ANAL_OP_TYPE_POP,
[EVM_OP_MLOAD] = R_ANAL_OP_TYPE_LOAD,
[EVM_OP_MSTORE] = R_ANAL_OP_TYPE_STORE,
[EVM_OP_MSTORE8] = R_ANAL_OP_TYPE_STORE,
[EVM_OP_SLOAD] = R_ANAL_OP_TYPE_LOAD,
[EVM_OP_SSTORE] = R_ANAL_OP_TYPE_STORE,
[EVM_OP_JUMP] = R_ANAL_OP_TYPE_JMP,
[EVM_OP_JUMPI] = R_ANAL_OP_TYPE_JMP,
[EVM_OP_PC] = R_ANAL_OP_TYPE_MOV,
[EVM_OP_MSIZE] = R_ANAL_OP_TYPE_MOV,
[EVM_OP_GAS] = R_ANAL_OP_TYPE_MOV,
[EVM_OP_JUMPDEST] = R_ANAL_OP_TYPE_NOP,
[EVM_OP_PUSH1] = R_ANAL_OP_TYPE_PUSH,
[EVM_OP_PUSH2] = R_ANAL_OP_TYPE_PUSH,
[EVM_OP_PUSH3] = R_ANAL_OP_TYPE_PUSH,
[EVM_OP_PUSH4] = R_ANAL_OP_TYPE_PUSH,
[EVM_OP_PUSH5] = R_ANAL_OP_TYPE_PUSH,
[EVM_OP_PUSH6] = R_ANAL_OP_TYPE_PUSH,
[EVM_OP_PUSH7] = R_ANAL_OP_TYPE_PUSH,
[EVM_OP_PUSH8] = R_ANAL_OP_TYPE_PUSH,
[EVM_OP_PUSH9] = R_ANAL_OP_TYPE_PUSH,
[EVM_OP_PUSH10] = R_ANAL_OP_TYPE_PUSH,
[EVM_OP_PUSH11] = R_ANAL_OP_TYPE_PUSH,
[EVM_OP_PUSH12] = R_ANAL_OP_TYPE_PUSH,
[EVM_OP_PUSH13] = R_ANAL_OP_TYPE_PUSH,
[EVM_OP_PUSH14] = R_ANAL_OP_TYPE_PUSH,
[EVM_OP_PUSH15] = R_ANAL_OP_TYPE_PUSH,
[EVM_OP_PUSH16] = R_ANAL_OP_TYPE_PUSH,
[EVM_OP_PUSH17] = R_ANAL_OP_TYPE_PUSH,
[EVM_OP_PUSH18] = R_ANAL_OP_TYPE_PUSH,
[EVM_OP_PUSH19] = R_ANAL_OP_TYPE_PUSH,
[EVM_OP_PUSH20] = R_ANAL_OP_TYPE_PUSH,
[EVM_OP_PUSH21] = R_ANAL_OP_TYPE_PUSH,
[EVM_OP_PUSH22] = R_ANAL_OP_TYPE_PUSH,
[EVM_OP_PUSH23] = R_ANAL_OP_TYPE_PUSH,
[EVM_OP_PUSH24] = R_ANAL_OP_TYPE_PUSH,
[EVM_OP_PUSH25] = R_ANAL_OP_TYPE_PUSH,
[EVM_OP_PUSH26] = R_ANAL_OP_TYPE_PUSH,
[EVM_OP_PUSH27] = R_ANAL_OP_TYPE_PUSH,
[EVM_OP_PUSH28] = R_ANAL_OP_TYPE_PUSH,
[EVM_OP_PUSH29] = R_ANAL_OP_TYPE_PUSH,
[EVM_OP_PUSH30] = R_ANAL_OP_TYPE_PUSH,
[EVM_OP_PUSH31] = R_ANAL_OP_TYPE_PUSH,
[EVM_OP_PUSH32] = R_ANAL_OP_TYPE_PUSH,
[EVM_OP_DUP1] = R_ANAL_OP_TYPE_MOV,
[EVM_OP_DUP2] = R_ANAL_OP_TYPE_MOV,
[EVM_OP_DUP3] = R_ANAL_OP_TYPE_MOV,
[EVM_OP_DUP4] = R_ANAL_OP_TYPE_MOV,
[EVM_OP_DUP5] = R_ANAL_OP_TYPE_MOV,
[EVM_OP_DUP6] = R_ANAL_OP_TYPE_MOV,
[EVM_OP_DUP7] = R_ANAL_OP_TYPE_MOV,
[EVM_OP_DUP8] = R_ANAL_OP_TYPE_MOV,
[EVM_OP_DUP9] = R_ANAL_OP_TYPE_MOV,
[EVM_OP_DUP10] = R_ANAL_OP_TYPE_MOV,
[EVM_OP_DUP11] = R_ANAL_OP_TYPE_MOV,
[EVM_OP_DUP12] = R_ANAL_OP_TYPE_MOV,
[EVM_OP_DUP13] = R_ANAL_OP_TYPE_MOV,
[EVM_OP_DUP14] = R_ANAL_OP_TYPE_MOV,
[EVM_OP_DUP15] = R_ANAL_OP_TYPE_MOV,
[EVM_OP_DUP16] = R_ANAL_OP_TYPE_MOV,
[EVM_OP_SWAP1] = R_ANAL_OP_TYPE_MOV,
[EVM_OP_SWAP2] = R_ANAL_OP_TYPE_MOV,
[EVM_OP_SWAP3] = R_ANAL_OP_TYPE_MOV,
[EVM_OP_SWAP4] = R_ANAL_OP_TYPE_MOV,
[EVM_OP_SWAP5] = R_ANAL_OP_TYPE_MOV,
[EVM_OP_SWAP6] = R_ANAL_OP_TYPE_MOV,
[EVM_OP_SWAP7] = R_ANAL_OP_TYPE_MOV,
[EVM_OP_SWAP8] = R_ANAL_OP_TYPE_MOV,
[EVM_OP_SWAP9] = R_ANAL_OP_TYPE_MOV,
[EVM_OP_SWAP10] = R_ANAL_OP_TYPE_MOV,
[EVM_OP_SWAP11] = R_ANAL_OP_TYPE_MOV,
[EVM_OP_SWAP12] = R_ANAL_OP_TYPE_MOV,
[EVM_OP_SWAP13] = R_ANAL_OP_TYPE_MOV,
[EVM_OP_SWAP14] = R_ANAL_OP_TYPE_MOV,
[EVM_OP_SWAP15] = R_ANAL_OP_TYPE_MOV,
[EVM_OP_SWAP16] = R_ANAL_OP_TYPE_MOV,
[EVM_OP_LOG0] = R_ANAL_OP_TYPE_TRAP,
[EVM_OP_LOG1] = R_ANAL_OP_TYPE_TRAP,
[EVM_OP_LOG2] = R_ANAL_OP_TYPE_TRAP,
[EVM_OP_LOG3] = R_ANAL_OP_TYPE_TRAP,
[EVM_OP_LOG4] = R_ANAL_OP_TYPE_TRAP,
[EVM_OP_CREATE] = R_ANAL_OP_TYPE_CRYPTO,
[EVM_OP_CALL] = R_ANAL_OP_TYPE_CRYPTO,
[EVM_OP_CALLCODE] = R_ANAL_OP_TYPE_CRYPTO,
[EVM_OP_RETURN] = R_ANAL_OP_TYPE_RET,
[EVM_OP_DELEGATECALL] = R_ANAL_OP_TYPE_CRYPTO,
[EVM_OP_REVERT] = R_ANAL_OP_TYPE_RET,
[EVM_OP_SELFDESTRUCT] = R_ANAL_OP_TYPE_CRYPTO,
};
struct evm_sigs_info {
RIO *rio;
RIODesc *riodesc;
ut8 *contents;
size_t contents_len;
json_t *root;
Sdb *sigs_db;
Sdb *found_sigs_db;
};
static struct evm_sigs_info *sigs_info = 0;
static int evm_oplen(ut8 opcode) {
int ret;
const EvmOpDef *opdef = &opcodes[opcode];
if (opdef->txt) {
return opdef->len;
}
switch (opcode) {
case EVM_OP_PUSH1:
case EVM_OP_PUSH2:
case EVM_OP_PUSH3:
case EVM_OP_PUSH4:
case EVM_OP_PUSH5:
case EVM_OP_PUSH6:
case EVM_OP_PUSH7:
case EVM_OP_PUSH8:
case EVM_OP_PUSH9:
case EVM_OP_PUSH10:
case EVM_OP_PUSH11:
case EVM_OP_PUSH12:
case EVM_OP_PUSH13:
case EVM_OP_PUSH14:
case EVM_OP_PUSH15:
case EVM_OP_PUSH16:
case EVM_OP_PUSH17:
case EVM_OP_PUSH18:
case EVM_OP_PUSH19:
case EVM_OP_PUSH20:
case EVM_OP_PUSH21:
case EVM_OP_PUSH22:
case EVM_OP_PUSH23:
case EVM_OP_PUSH24:
case EVM_OP_PUSH25:
case EVM_OP_PUSH26:
case EVM_OP_PUSH27:
case EVM_OP_PUSH28:
case EVM_OP_PUSH29:
case EVM_OP_PUSH30:
case EVM_OP_PUSH31:
case EVM_OP_PUSH32:
{
int pushSize = opcode - EVM_OP_PUSH1;
/*
op->imm = 0;
for (i = 0; i < pushSize + 1; i++) {
op->imm <<= 8;
op->imm |= buf[i + 1];
}
settxtf (op, "push%d 0x%x", pushSize + 1, op->imm);
*/
ret = 2 + pushSize;
}
break;
case EVM_OP_DUP1:
case EVM_OP_DUP2:
case EVM_OP_DUP3:
case EVM_OP_DUP4:
case EVM_OP_DUP5:
case EVM_OP_DUP6:
case EVM_OP_DUP7:
case EVM_OP_DUP8:
case EVM_OP_DUP9:
case EVM_OP_DUP10:
case EVM_OP_DUP11:
case EVM_OP_DUP12:
case EVM_OP_DUP13:
case EVM_OP_DUP14:
case EVM_OP_DUP15:
case EVM_OP_DUP16:
{
// settxtf (op, "dup%d", dupSize);
ret = 1;
}
break;
case EVM_OP_SWAP1:
case EVM_OP_SWAP2:
case EVM_OP_SWAP3:
case EVM_OP_SWAP4:
case EVM_OP_SWAP5:
case EVM_OP_SWAP6:
case EVM_OP_SWAP7:
case EVM_OP_SWAP8:
case EVM_OP_SWAP9:
case EVM_OP_SWAP10:
case EVM_OP_SWAP11:
case EVM_OP_SWAP12:
case EVM_OP_SWAP13:
case EVM_OP_SWAP14:
case EVM_OP_SWAP15:
case EVM_OP_SWAP16:
{
// settxtf (op, "swap%d", swapSize);
ret = 1;
}
break;
case EVM_OP_LOG0:
case EVM_OP_LOG1:
case EVM_OP_LOG2:
case EVM_OP_LOG3:
case EVM_OP_LOG4:
{
// settxtf (op, "log%d", logSize);
ret = 1;
}
break;
default:
// settxtf (op, "invalid");
ret = 1;
break;
}
return ret;
}
/* Jumps/calls in EVM are done via first pushing dst value
* on the stack, and then calling a jump/jumpi instruction, for example:
* 0x0000000d push 0x42
* 0x0000000f jumpi
*
* we are storing the value in push instruction to db, but not at the
* addr of the push instruction, but at the addr of next jumpi instruction.
* So in our example we are inserting (0xf, 0x42)
*/
static int evm_add_push_to_db(ut64 addr, const ut8 *buf, int len) {
ut8 opcode = buf[0];
ut64 next_cmd_addr = addr + evm_oplen (opcode);
ut64 dst_addr = 0;
size_t i, push_size;
char key[16] = {0}, value[16] = {0};
push_size = opcode - EVM_OP_PUSH1;
for (i = 0; i < push_size + 1; i++) {
dst_addr <<= 8;
dst_addr |= buf[i + 1];
}
if (evm_ai) {
snprintf (key, sizeof(key) - 1, "%08x", (unsigned) next_cmd_addr);
snprintf (value, sizeof(value) - 1, "%08x", (unsigned) dst_addr);
sdb_set (evm_ai->pushs_db, key, value, 0);
}
return 0;
}
static st64 evm_get_jmp_addr(ut64 addr) {
char key[16] = {0};
const char *value;
unsigned ret;
snprintf (key, sizeof(key) - 1, "%08x", (unsigned) addr);
value = sdb_const_get (evm_ai->pushs_db, key, 0);
if (value) {
sscanf(value, "%08x", &ret);
return ret;
} else {
return -1;
}
}
static int evm_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *buf, int len) {
ut32 *push4op;
st64 ret;
ut8 opcode;
char sig[64] = {0};
opcode = buf[0];
memset (op, 0, sizeof(RAnalOp));
op->type = opcodes_types[opcode];
if (!op->type) {
op->type = R_ANAL_OP_TYPE_UNK;
}
op->addr = addr;
op->jump = op->fail = -1;
op->ptr = op->val = -1;
r_strbuf_init (&op->esil);
switch (opcode) {
case EVM_OP_JUMP:
case EVM_OP_JUMPI:
op->fail = addr + 1;
if (opcode == EVM_OP_JUMP) {
op->type = R_ANAL_OP_TYPE_JMP;
} else {
op->type = R_ANAL_OP_TYPE_CJMP;
}
ret = evm_get_jmp_addr(addr);
if (ret >= 0) {
op->jump = ret;
} else {
op->type = R_ANAL_OP_TYPE_UJMP;
}
op->eob = true;
break;
case EVM_OP_PC:
break;
case EVM_OP_MSIZE:
break;
case EVM_OP_GAS:
break;
case EVM_OP_JUMPDEST:
break;
case EVM_OP_PUSH1:
case EVM_OP_PUSH2:
case EVM_OP_PUSH3:
case EVM_OP_PUSH4:
evm_add_push_to_db (addr, buf, len);
if (opcode == EVM_OP_PUSH4 && sigs_info && sigs_info->sigs_db) {
push4op = (ut32 *)(buf + 1);
snprintf(sig, sizeof(sig) - 1, "0x%08x", ntohl((unsigned)(*push4op)));
const char *data = sdb_const_get (sigs_info->sigs_db, sig, 0);
if (data) {
char addr_str[16];
char value[1024];
snprintf(addr_str, sizeof(addr_str) - 1, "0x%08x", (unsigned int)addr);
addr_str[16 - 1] = '\0';
snprintf(value, sizeof(value) - 1, "calls a function %s with signature %s",
data, sig);
value[1023] = '\0';
sdb_set(sigs_info->found_sigs_db, addr_str, value, 0);
r_meta_set_string(anal, 'C', addr, data);
}
}
break;
default:
break;
}
op->size = evm_oplen (opcode);
return evm_oplen (opcode);
}
static int evm_load_symbol_map (RAnal *anal, const char *file) {
size_t i;
int ret = 0;
bool rc;
if (sigs_info) {
r_io_close (sigs_info->rio);
r_io_free (sigs_info->rio);
sdb_free (sigs_info->sigs_db);
sdb_free (sigs_info->found_sigs_db);
free (sigs_info->contents);
free (sigs_info);
}
sigs_info = malloc(sizeof(*sigs_info));
memset(sigs_info, 0, sizeof(*sigs_info));
if (!sigs_info) {
ret = -1;
goto out;
}
if (sigs_info) {
sigs_info->rio = r_io_new ();
sigs_info->riodesc = r_io_open (sigs_info->rio, file, R_PERM_R, 0644);
if (!sigs_info->riodesc) {
printf ("Failed to open %s: %s\n", file, strerror (errno));
ret = -1;
goto out_free;
} else {
json_error_t error;
sigs_info->contents_len = r_io_size (sigs_info->rio);
sigs_info->contents = malloc(sigs_info->contents_len + 1);
rc = r_io_read (sigs_info->rio, sigs_info->contents, sigs_info->contents_len);
if (rc == false) {
printf ("Failed to read file\n");
ret = -1;
goto out_close;
}
sigs_info->contents[sigs_info->contents_len] = '\0';
sigs_info->root = json_loads ((const char*)sigs_info->contents, 0, &error);
if (!sigs_info->root) {
printf ("Failed to parse json document on line %d: %s\n",
error.line, error.text);
} else {
printf ("Parsed successfully\n");
sigs_info->sigs_db = sdb_new0 ();
sigs_info->found_sigs_db = sdb_new0 ();
for (i = 0; i < json_array_size (sigs_info->root); i++) {
json_t *elem, *sig, *args, *name;
char *name_str, *sig_str, *args_str, *value;
size_t value_size;
elem = json_array_get (sigs_info->root, i);
if (!elem) {
continue;
}
sig = json_object_get (elem, "sig");
name = json_object_get (elem, "name");
args = json_object_get (elem, "args");
if (!sig || !name || !args) {
continue;
}
sig_str = strdup (json_string_value (sig));
name_str = strdup (json_string_value (name));
args_str = strdup (json_string_value (args));
value_size = strlen(name_str) + strlen(args_str) + 8;
value = malloc(sizeof(char) * value_size);
snprintf(value, value_size - 1, "%s(%s)", name_str, args_str);
sdb_set (sigs_info->sigs_db, sig_str, value, 0);
free (value);
free (args_str);
free (name_str);
free (sig_str);
}
json_decref (sigs_info->root);
free (sigs_info->contents);
sigs_info->root = 0;
sigs_info->contents = 0;
}
}
}
goto out;
out_close:
r_io_close (sigs_info->rio);
out_free:
r_io_free (sigs_info->rio);
sigs_info->rio = NULL;
free (sigs_info);
sigs_info = NULL;
out:
return ret;
}
static int evm_list_found_symbols_cb (void *user, const char *k, const char *v) {
printf ("%s | %s\n", k, v);
return 1;
}
static int evm_list_found_symbols (RAnal *anal) {
if (sigs_info && sigs_info->found_sigs_db) {
sdb_foreach (sigs_info->found_sigs_db, evm_list_found_symbols_cb, NULL);
}
return 0;
}
static void evm_cmd_ext_help () {
printf ("a!l <file path> - Read a JSON file with function signatures\n"
"a!f - List found function signatures\n"
"a!h - Show this help message\n");
}
static int evm_cmd_ext (RAnal *anal, const char *input) {
const char *arg = input;
arg++;
while (*arg == ' ') {
arg++;
}
switch (input[0]) {
case 'l':
printf("here %s\n", arg);
evm_load_symbol_map (anal, arg);
break;
case 'f':
evm_list_found_symbols (anal);
break;
case 'h':
default:
evm_cmd_ext_help ();
return -1;
}
return 0;
}
static int evm_anal_init (void *user) {
if (!evm_ai) {
evm_ai = (struct evm_anal_info*)malloc (sizeof(*evm_ai));
evm_ai->pushs_db = sdb_new0 ();
}
return 0;
}
static int evm_anal_fini (void *user) {
if (evm_ai) {
if (evm_ai->pushs_db) {
sdb_free (evm_ai->pushs_db);
}
free(evm_ai);
evm_ai = NULL;
}
return 0;
}
RAnalPlugin r_anal_plugin_evm = {
.name = "evm",
.desc = "ETHEREUM VM code analysis plugin",
.license = "LGPL3",
.arch = "evm",
.bits = 8,
.op = evm_op,
.init = evm_anal_init,
.fini = evm_anal_fini,
.esil = false,
.cmd_ext = evm_cmd_ext,
};
#ifndef CORELIB
struct r_lib_struct_t radare_plugin = {
.type = R_LIB_TYPE_ANAL,
.data = &r_anal_plugin_evm,
.version = R2_VERSION
};
#endif
-18
View File
@@ -1,18 +0,0 @@
OBJ_EVM=anal_evm.o
OBJ_EVM+=../../asm/arch/evm/evm.o
STATIC_OBJ+=${OBJ_EVM}
TARGET_evm=anal_evm.${LIBEXT}
ALL_TARGETS+=${TARGET_evm}
LINKFLAGS+=-ljansson
CFLAGS_EVM=$(CFLAGS)
CFLAGS_EVM+=-I../../asm/arch/evm
CFLAGS_EVM+=-Wall -shared -fPIC ${LDFLAGS_LIB}
$(OBJ_EVM): %.o : %.c
$(CC) -c $(CFLAGS_EVM) $< -o $@
${TARGET_evm}: ${OBJ_EVM} ${SHARED_OBJ}
${CC} $(call libname,anal_evm) ${LDFLAGS} ${CFLAGS_EVM} -o ${TARGET_evm} ${OBJ_EVM} ${LINKFLAGS}
-15
View File
@@ -1,15 +0,0 @@
OBJ_HEXAGON=anal_hexagon.o
OBJ_HEXAGON+=../../anal/arch/hexagon/hexagon.o
OBJ_HEXAGON+=../../anal/arch/hexagon/hexagon_disas.o
OBJ_HEXAGON+=../../anal/arch/hexagon/hexagon_anal.o
CFLAGS +=-I../arch/hexagon
STATIC_OBJ+=${OBJ_HEXAGON}
TARGET_HEXAGON=anal_hexagon.${EXT_SO}
ALL_TARGETS+=${TARGET_HEXAGON}
${TARGET_HEXAGON}: ${OBJ_HEXAGON}
${CC} $(call libname,anal_hexagon) ${LDFLAGS} ${CFLAGS} \
-o $(TARGET_HEXAGON) $(OBJ_HEXAGON)
+23
View File
@@ -0,0 +1,23 @@
SO=$(shell r2 -H R2_LIBEXT)
PD=$(shell r2 -H R2_USER_PLUGINS)
CFLAGS+=$(shell pkg-config --cflags r_util r_arch) -fPIC
LDFLAGS+=$(shell pkg-config --libs r_util r_arch)
CFLAGS+=-g
OBJS=arch_hexagon.o
OBJS+=hexagon.o
OBJS+=hexagon_anal.o
OBJS+=hexagon_disas.o
all: arch_hexagon.${SO}
arch_hexagon.$(SO): $(OBJS)
$(CC) -shared -fPIC -o arch_hexagon.$(SO) $(OBJS) $(LDFLAGS)
rm -f $(PD)/arch_hexagon.$(SO)
mkdir -p $(PD)
cp -f arch_hexagon.$(SO) $(PD)/arch_hexagon.$(SO)
clean:
rm -f arch_hexagon.$(SO) $(OBJS)
@@ -1,3 +1,4 @@
#if 0
/* radare - LGPL - Copyright 2018-2021 - xvilka, pancake */
#include <r_types.h>
@@ -112,3 +113,4 @@ R_API RLibStruct radare_plugin = {
.version = R2_VERSION
};
#endif
#endif
+113
View File
@@ -0,0 +1,113 @@
/* radare - LGPL - Copyright 2015-2023 - condret */
#include <r_arch.h>
#include <r_lib.h>
#include "hexagon.h"
#include "hexagon_insn.h"
#include "hexagon_anal.h"
static bool mal_decode(RArchSession *s, RAnalOp *op, RArchEncodeMask mask) {
if (op->size < 4 || !op->bytes) {
return false;
}
ut32 data = r_read_le32 (op->bytes);
HexInsn hi = {0};
int size = hexagon_disasm_instruction (data, &hi, (ut32) (op->addr & UT32_MAX));
if (size > 0 && mask & R_ARCH_OP_MASK_DISASM) {
op->mnemonic = strdup (hi.mnem);
}
op->size = size;
if (size < 1) {
return false;
}
op->vliw = hi.op_count;
int res = hexagon_anal_instruction (&hi, op);
if (op->size != res) {
R_LOG_DEBUG ("shouldnt happen invalid instruction at 0x%08"PFMT64x, op->addr);
}
op->size = res;
return true;
}
static char* regs(RArchSession *as) {
return strdup (
"=PC pc\n"
"=SP r29\n"
"=A0 r0\n"
"=A1 r1\n"
"=A2 r2\n"
"=A3 r3\n"
"=A4 r4\n"
"=A5 r5\n"
"=BP r30\n"
"=LR r31\n"
"=SN r6\n"
"=ZF z\n"
"=SF s\n"
"=OF ov\n"
"=CF cy\n"
"gpr r0 .32 0 0\n"
"gpr r1 .32 4 0\n"
"gpr r2 .32 8 0\n"
"gpr r3 .32 12 0\n"
"gpr r4 .32 16 0\n"
"gpr r5 .32 20 0\n"
"gpr r6 .32 24 0\n"
"gpr r7 .32 28 0\n"
"gpr r8 .32 32 0\n"
"gpr r9 .32 36 0\n"
"gpr r10 .32 40 0\n"
"gpr r11 .32 44 0\n"
"gpr r12 .32 48 0\n"
"gpr r13 .32 52 0\n"
"gpr r14 .32 56 0\n"
"gpr r15 .32 60 0\n"
"gpr r16 .32 64 0\n"
"gpr r17 .32 68 0\n"
"gpr r18 .32 72 0\n"
"gpr r19 .32 76 0\n"
"gpr r20 .32 80 0\n"
"gpr r21 .32 84 0\n"
"gpr r22 .32 88 0\n"
"gpr r23 .32 92 0\n"
"gpr r24 .32 96 0\n"
"gpr r25 .32 100 0\n"
"gpr r26 .32 104 0\n"
"gpr r27 .32 108 0\n"
"gpr r28 .32 112 0\n"
"gpr r29 .32 116 0\n"
"gpr r30 .32 120 0\n"
"gpr r31 .32 124 0\n"
"gpr pc .32 128 0\n"
"gpr psw .32 132 0\n"
"gpr np .1 132.16 0\n"
"gpr ep .1 132.17 0\n"
"gpr ae .1 132.18 0\n"
"gpr id .1 132.19 0\n"
"flg cy .1 132.28 0\n"
"flg ov .1 132.29 0\n"
"flg s .1 132.30 0\n"
"flg z .1 132.31 0\n");
}
RArchPlugin r_arch_plugin_hexagon = {
.meta = {
.name = "hexagon",
.desc = "Qualcomm Hexagon (QDSP6) V6",
.author = "pancake,condret,xvilka",
.license = "LGPL3",
},
.regs = regs,
.arch = "hexagon",
.bits = 32,
.decode = &mal_decode,
};
#ifndef R2_PLUGIN_INCORE
R_API RLibStruct radare_plugin = {
.type = R_LIB_TYPE_ARCH,
.data = &r_arch_plugin_hexagon,
.version = R2_VERSION
};
#endif
File renamed without changes.
+239
View File
@@ -0,0 +1,239 @@
/* radare - LGPL - Copyright 2018-2021 - xvilka */
#include <stdio.h>
#include <stdbool.h>
#include <r_types.h>
#include <r_lib.h>
#include <r_util.h>
#include <r_asm.h>
#include "hexagon.h"
// TODO: Handle also control reg pairs
char* hex_get_cntl_reg(int opreg) {
switch (opreg) {
case HEX_REG_SA0:
return "SA0";
case HEX_REG_LC0:
return "LC0";
case HEX_REG_SA1:
return "SA1";
case HEX_REG_LC1:
return "LC1";
case HEX_REG_P:
return "P";
case HEX_REG_M0:
return "M0";
case HEX_REG_M1:
return "M1";
case HEX_REG_USR:
return "USR";
case HEX_REG_PC:
return "PC";
case HEX_REG_UGP:
return "UGP";
case HEX_REG_GP:
return "GP";
case HEX_REG_CS0:
return "CS0";
case HEX_REG_CS1:
return "CS1";
case HEX_REG_UPCYCLELO:
return "UPCYCLELO";
case HEX_REG_UPCYCLEHI:
return "UPCYCLEHI";
case HEX_REG_FRAMELIMIT:
return "FRAMELIMIT";
case HEX_REG_FRAMEKEY:
return "FRAMEKEY";
case HEX_REG_PKTCOUNTLO:
return "PKTCOUNTLO";
case HEX_REG_PKTCOUNTHI:
return "PKTCOUNTHI";
case HEX_REG_UTIMERLO:
return "UTIMERLO";
case HEX_REG_UTIMERHI:
return "UTIMERHI";
default:
return "<CRerr>";
}
}
char* hex_get_sys_reg(int opreg) {
static char tmp[5];
switch (opreg) {
case HEX_REG_SGP0:
return "SGP0";
case HEX_REG_SGP1:
return "SGP1";
case HEX_REG_STID:
return "STID";
case HEX_REG_ELR:
return "ELR";
case HEX_REG_BADVA0:
return "BADVA0";
case HEX_REG_BADVA1:
return "BADVA1";
case HEX_REG_SSR:
return "SSR";
case HEX_REG_CCR:
return "CCR";
case HEX_REG_HTID:
return "HTID";
case HEX_REG_BADVA:
return "BADVA";
case HEX_REG_IMASK:
return "IMASK";
case HEX_REG_EVB:
return "EVB";
case HEX_REG_MODECTL:
return "MODECTL";
case HEX_REG_SYSCFG:
return "SYSCFG";
case HEX_REG_IPEND:
return "IPEND";
case HEX_REG_VID:
return "VID";
case HEX_REG_IAD:
return "IAD";
case HEX_REG_IEL:
return "IEL";
case HEX_REG_IAHL:
return "IAHL";
case HEX_REG_CFGBASE:
return "CFGBASE";
case HEX_REG_DIAG:
return "DIAG";
case HEX_REG_REV:
return "REV";
case HEX_REG_PCYCLELO:
return "PCYCLELO";
case HEX_REG_PCYCLEHI:
return "PCYCLEHI";
case HEX_REG_ISDBST:
return "ISDBST";
case HEX_REG_ISDBCFG0:
return "ISDBCFG0";
case HEX_REG_ISDBCFG1:
return "ISDBCFG1";
case HEX_REG_BRKPTPC0:
return "BRKPTPC0";
case HEX_REG_BRKPTCFG0:
return "BRKPTCFG0";
case HEX_REG_BRKPTPC1:
return "BRKPTPC1";
case HEX_REG_BRKPTCFG1:
return "BRKPTCFG1";
case HEX_REG_ISDBMBXIN:
return "ISDBMBXIN";
case HEX_REG_ISDBMBXOUT:
return "ISDBMBXOUT";
case HEX_REG_ISDBEN:
return "ISDBEN";
case HEX_REG_ISDBGPR:
return "ISDBGPR";
case HEX_REG_PMUCNT0:
return "PMUCNT0";
case HEX_REG_PMUCNT1:
return "PMUCNT1";
case HEX_REG_PMUCNT2:
return "PMUCNT2";
case HEX_REG_PMUCNT3:
return "PMUCNT3";
case HEX_REG_PMUEVTCFG:
return "PMUEVTCFG";
case HEX_REG_PMUCFG:
return "PMUCFG";
default:
sprintf(tmp, "S%d", opreg);
return tmp;
}
}
char* hex_get_sub_reg(int opreg) {
switch (opreg) {
case HEX_SUB_REG_R0:
return "R0";
case HEX_SUB_REG_R1:
return "R1";
case HEX_SUB_REG_R2:
return "R2";
case HEX_SUB_REG_R3:
return "R3";
case HEX_SUB_REG_R4:
return "R4";
case HEX_SUB_REG_R5:
return "R5";
case HEX_SUB_REG_R6:
return "R6";
case HEX_SUB_REG_R7:
return "R7";
case HEX_SUB_REG_R16:
return "R16";
case HEX_SUB_REG_R17:
return "R17";
case HEX_SUB_REG_R18:
return "R18";
case HEX_SUB_REG_R19:
return "R19";
case HEX_SUB_REG_R20:
return "R20";
case HEX_SUB_REG_R21:
return "R21";
case HEX_SUB_REG_R22:
return "R22";
case HEX_SUB_REG_R23:
return "R23";
default:
return "<err>";
}
}
char* hex_get_sub_regpair(int opreg)
{
switch (opreg) {
case HEX_SUB_REGPAIR_R1_R0:
return "R1:R0";
case HEX_SUB_REGPAIR_R3_R2:
return "R3:R2";
case HEX_SUB_REGPAIR_R5_R4:
return "R5:R4";
case HEX_SUB_REGPAIR_R7_R6:
return "R7:R6";
case HEX_SUB_REGPAIR_R17_R16:
return "R17:R16";
case HEX_SUB_REGPAIR_R19_R18:
return "R19:R18";
case HEX_SUB_REGPAIR_R21_R20:
return "R21:R20";
case HEX_SUB_REGPAIR_R23_R22:
return "R23:R22";
default:
return "<err>";
}
}
inline bool hex_if_duplex(uint32_t insn_word)
{
if ((insn_word & (3 << 14)) == 0) {
return true;
}
return false;
}
// Constant extender value
ut32 constant_extender = 1;
void hex_op_extend(HexOp *op) {
if ((constant_extender != 1) && (op->type == HEX_OP_TYPE_IMM)) {
op->op.imm = ((op->op.imm) & 0x3F) | (constant_extender);
}
constant_extender = 1;
}
void hex_op_extend_off(HexOp *op, int offset) {
return;
if ((constant_extender != 1) && (op->type == HEX_OP_TYPE_IMM)) {
op->op.imm = (op->op.imm) >> offset;
hex_op_extend(op);
}
}
@@ -68,7 +68,7 @@ typedef struct {
bool last; // is last in instruction packet?
int shift; // Optional shift left is it true?
ut8 op_count;
HexOp ops[6];
HexOp ops[8];
char mnem[128]; // Instruction mnemonic
} HexInsn;
+9
View File
@@ -0,0 +1,9 @@
OBJ_MALBOLGE=anal_malbolge.o
STATIC_OBJ+=${OBJ_MALBOLGE}
TARGET_MALBOLGE=anal_malbolge.${EXT_SO}
ALL_TARGETS+=${TARGET_MALBOLGE}
${TARGET_MALBOLGE}: ${OBJ_MALBOLGE}
${CC} $(call libname,anal_malbolge) ${LDFLAGS} ${CFLAGS} -o anal_malbolge.${EXT_SO} ${OBJ_MALBOLGE}
+8
View File
@@ -0,0 +1,8 @@
crz=crazy operation
end=end
in=inputs a character, as an ascii code
jmp=jump
mov=moves data from src to dst
nop=do nothing
out=prints the value, as an ascii character, to the screen
rotr=rotates the value by one ternary digit
File renamed without changes.
File renamed without changes.
@@ -27055,7 +27055,7 @@ int hexagon_disasm_instruction(ut32 hi_u32, HexInsn *hi, ut32 addr) {
hi->ops[1].type = HEX_OP_TYPE_IMM;
hi->ops[1].op.imm = (((hi_u32 & 0x1f0000) >> 11) | ((hi_u32 & 0xe0) >> 3) | ((hi_u32 & 0x3) >> 0));
hi->predicate = HEX_NOPRED;
hex_op_extend_off(&hi->ops[0], 2);
hex_op_extend_off (&hi->ops[0], 2);
sprintf(hi->mnem, "loop0 (0x%x, 0x%x)", hi->ops[0].op.imm, hi->ops[1].op.imm);
break;
}
@@ -27071,7 +27071,7 @@ int hexagon_disasm_instruction(ut32 hi_u32, HexInsn *hi, ut32 addr) {
hi->ops[1].type = HEX_OP_TYPE_IMM;
hi->ops[1].op.imm = (((hi_u32 & 0x1f0000) >> 11) | ((hi_u32 & 0xe0) >> 3) | ((hi_u32 & 0x3) >> 0));
hi->predicate = HEX_NOPRED;
hex_op_extend_off(&hi->ops[0], 2);
hex_op_extend_off (&hi->ops[0], 2);
sprintf(hi->mnem, "loop1 (0x%x, 0x%x)", hi->ops[0].op.imm, hi->ops[1].op.imm);
break;
}
File renamed without changes.
+6 -4
View File
@@ -64,17 +64,19 @@ static bool mal_decode(RArchSession *s, RAnalOp *op, RArchEncodeMask mask) {
}
RArchPlugin r_arch_plugin_malbolge = {
.name = "malbolge",
.desc = "Malbolge analysis plugin",
.meta = {
.name = "malbolge",
.desc = "Malbolge analysis plugin",
.license = "LGPL3",
},
.arch = "malbolge",
.license = "LGPL3",
.bits = 32,
.decode = &mal_decode,
};
#ifndef R2_PLUGIN_INCORE
R_API RLibStruct radare_plugin = {
.type = R_LIB_TYPE_ANAL,
.type = R_LIB_TYPE_ARCH,
.data = &r_arch_plugin_malbolge,
.version = R2_VERSION
};
+3 -3
View File
@@ -1,5 +1,8 @@
R2PM_PLUGDIR ?=$(HOME)/.config/radare2/plugins
all:
@echo
atombios:
cd p ; $(MAKE) asm_atombios.$(LIBEXT)
@@ -39,9 +42,6 @@ m68k_net:
zyan:
$(MAKE) -C p asm_x86_zyan.$(LIBEXT)
evm:
$(MAKE) -C p asm_evm.$(LIBEXT)
zyan-install: zyan
mkdir -p $(R2PM_PLUGDIR)
cp -f p/asm_x86_zyan.$(LIBEXT) $(R2PM_PLUGDIR)
File diff suppressed because it is too large. Load diff
-263
View File
@@ -1,263 +0,0 @@
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <stdarg.h>
#include <sys/types.h>
#include "evm.h"
const EvmOpDef opcodes[256] = {
[EVM_OP_STOP] = { "stop", 1 },
[EVM_OP_ADD] = { "add", 1 },
[EVM_OP_MUL] = { "mul", 1 },
[EVM_OP_SUB] = { "sub", 1 },
[EVM_OP_DIV] = { "div", 1 },
[EVM_OP_SDIV] = { "sdiv", 1 },
[EVM_OP_MOD] = { "mod", 1 },
[EVM_OP_SMOD] = { "smod", 1 },
[EVM_OP_ADDMOD] = { "addmod", 1 },
[EVM_OP_MULMOD] = { "mulmod", 1 },
[EVM_OP_EXP] = { "exp", 1 },
[EVM_OP_SIGNEXTEND] = { "signextend", 1 },
[EVM_OP_LT] = { "lt", 1 },
[EVM_OP_GT] = { "gt", 1 },
[EVM_OP_SLT] = { "slt", 1 },
[EVM_OP_SGT] = { "sgt", 1 },
[EVM_OP_EQ] = { "eq", 1 },
[EVM_OP_ISZERO] = { "iszero", 1 },
[EVM_OP_AND] = { "and", 1 },
[EVM_OP_OR] = { "or", 1 },
[EVM_OP_XOR] = { "xor", 1 },
[EVM_OP_NOT] = { "not", 1 },
[EVM_OP_BYTE] = { "byte", 1 },
[EVM_OP_SHL] = { "shl", 1 },
[EVM_OP_SHR] = { "shr", 1 },
[EVM_OP_SAR] = { "sar", 1 },
[EVM_OP_SHA3] = { "sha3", 1 },
[EVM_OP_ADDRESS] = { "address", 1 },
[EVM_OP_BALANCE] = { "balance", 1 },
[EVM_OP_ORIGIN] = { "origin", 1 },
[EVM_OP_CALLER] = { "caller", 1 },
[EVM_OP_CALLVALUE] = { "callvalue", 1 },
[EVM_OP_CALLDATALOAD] = { "calldataload", 1 },
[EVM_OP_CALLDATASIZE] = { "calldatasize", 1 },
[EVM_OP_CALLDATACOPY] = { "calldatacopy", 1 },
[EVM_OP_CODESIZE] = { "codesize", 1 },
[EVM_OP_CODECOPY] = { "codecopy", 1 },
[EVM_OP_GASPRICE] = { "gasprice", 1 },
[EVM_OP_EXTCODESIZE] = { "extcodesize", 1 },
[EVM_OP_EXTCODECOPY] = { "extcodecopy", 1 },
[EVM_OP_RETURNDATASIZE] = { "returndatasize", 1},
[EVM_OP_RETURNDATACOPY] = { "returndatacopy", 1},
[EVM_OP_EXTCODEHASH] = { "extcodehash", 1},
[EVM_OP_BLOCKHASH] = { "blockhash", 1 },
[EVM_OP_COINBASE] = { "coinbase", 1 },
[EVM_OP_TIMESTAMP] = { "timestamp", 1 },
[EVM_OP_NUMBER] = { "number", 1 },
[EVM_OP_DIFFICULTY] = { "difficulty", 1 },
[EVM_OP_GASLIMIT] = { "gaslimit", 1 },
[EVM_OP_CHAINID] = { "chainid", 1 },
[EVM_OP_SELFBALANCE] = { "selfbalance", 1 },
[EVM_OP_POP] = { "pop", 1 },
[EVM_OP_MLOAD] = { "mload", 1 },
[EVM_OP_MSTORE] = { "mstore", 1 },
[EVM_OP_MSTORE8] = { "mstore8", 1 },
[EVM_OP_SLOAD] = { "sload", 1 },
[EVM_OP_SSTORE] = { "sstore", 1 },
[EVM_OP_JUMP] = { "jump", 1 },
[EVM_OP_JUMPI] = { "jumpi", 1 },
[EVM_OP_PC] = { "pc", 1 },
[EVM_OP_MSIZE] = { "msize", 1 },
[EVM_OP_GAS] = { "gas", 1 },
[EVM_OP_JUMPDEST] = { "jumpdest", 1 },
// ....
[EVM_OP_CREATE] = { "create", 1 },
[EVM_OP_CALL] = { "call", 1 },
[EVM_OP_CALLCODE] = { "callcode", 1 },
[EVM_OP_RETURN] = { "return", 1 },
[EVM_OP_DELEGATECALL] = { "delegatecall", 1 },
[EVM_OP_CREATE2] = { "create2", 1 },
[EVM_OP_STATICCALL] = { "staticcall", 1 },
[EVM_OP_REVERT] = { "revert", 1 },
[EVM_OP_INVALID] = { "invalid", 1 },
[EVM_OP_SELFDESTRUCT] = { "selfdestruct", 1 },
};
static void settxtf(EvmOp *op, const char *fmt, ...) {
if (strchr (fmt, '%')) {
va_list ap;
va_start (ap, fmt);
op->txt = op->txt_buf;
vsnprintf (op->txt_buf, sizeof (op->txt_buf), fmt, ap);
va_end (ap);
} else {
op->txt = fmt;
}
}
int evm_asm(const char *str, RStrBuf *buf, int buf_len) {
int i, len = -1;
for (i = 0; i < 0xff; i++) {
const EvmOpDef *opdef = &opcodes[i];
if (opdef->txt) {
if (!strcmp (opdef->txt, str)) {
r_strbuf_appendf (buf, "%d", i);
return 1;
}
}
}
// TODO: add support for: push, swap, dup, log
return len;
}
int evm_dis(EvmOp *op, const unsigned char *buf, int buf_len) {
op->len = 1;
op->op = buf[0];
const EvmOpDef *opdef = &opcodes[buf[0]];
if (opdef->txt) {
op->txt = opdef->txt;
op->len = opdef->len;
if (op->len < 1) {
op->len = 1;
}
return op->len;
}
switch (op->op) {
case EVM_OP_PUSH1:
case EVM_OP_PUSH2:
case EVM_OP_PUSH3:
case EVM_OP_PUSH4:
case EVM_OP_PUSH5:
case EVM_OP_PUSH6:
case EVM_OP_PUSH7:
case EVM_OP_PUSH8:
case EVM_OP_PUSH9:
case EVM_OP_PUSH10:
case EVM_OP_PUSH11:
case EVM_OP_PUSH12:
case EVM_OP_PUSH13:
case EVM_OP_PUSH14:
case EVM_OP_PUSH15:
case EVM_OP_PUSH16:
case EVM_OP_PUSH17:
case EVM_OP_PUSH18:
case EVM_OP_PUSH19:
case EVM_OP_PUSH20:
case EVM_OP_PUSH21:
case EVM_OP_PUSH22:
case EVM_OP_PUSH23:
case EVM_OP_PUSH24:
case EVM_OP_PUSH25:
case EVM_OP_PUSH26:
case EVM_OP_PUSH27:
case EVM_OP_PUSH28:
case EVM_OP_PUSH29:
case EVM_OP_PUSH30:
case EVM_OP_PUSH31:
case EVM_OP_PUSH32:
{
int pushSize = buf[0] - EVM_OP_PUSH1;
char hexbuf[64] = {0};
int res = r_hex_bin2str (buf + 1, pushSize + 1, hexbuf);
if (res < 1 || !*hexbuf) {
strcpy (hexbuf, "0");
}
settxtf (op, "push%d 0x%s", pushSize + 1, hexbuf);
op->len = 2 + pushSize;
}
break;
case EVM_OP_DUP1:
case EVM_OP_DUP2:
case EVM_OP_DUP3:
case EVM_OP_DUP4:
case EVM_OP_DUP5:
case EVM_OP_DUP6:
case EVM_OP_DUP7:
case EVM_OP_DUP8:
case EVM_OP_DUP9:
case EVM_OP_DUP10:
case EVM_OP_DUP11:
case EVM_OP_DUP12:
case EVM_OP_DUP13:
case EVM_OP_DUP14:
case EVM_OP_DUP15:
case EVM_OP_DUP16:
{
int dupSize = buf[0] - EVM_OP_DUP1 + 1;
settxtf (op, "dup%d", dupSize);
op->len = 1;
}
break;
case EVM_OP_SWAP1:
case EVM_OP_SWAP2:
case EVM_OP_SWAP3:
case EVM_OP_SWAP4:
case EVM_OP_SWAP5:
case EVM_OP_SWAP6:
case EVM_OP_SWAP7:
case EVM_OP_SWAP8:
case EVM_OP_SWAP9:
case EVM_OP_SWAP10:
case EVM_OP_SWAP11:
case EVM_OP_SWAP12:
case EVM_OP_SWAP13:
case EVM_OP_SWAP14:
case EVM_OP_SWAP15:
case EVM_OP_SWAP16:
{
int swapSize = buf[0] - EVM_OP_SWAP1 + 1;
settxtf (op, "swap%d", swapSize);
op->len = 1;
}
break;
case EVM_OP_LOG0:
case EVM_OP_LOG1:
case EVM_OP_LOG2:
case EVM_OP_LOG3:
case EVM_OP_LOG4:
{
int logSize = buf[0] - EVM_OP_LOG0;
settxtf (op, "log%d", logSize);
op->len = 1;
}
break;
default:
settxtf (op, "unassigned");
op->len = 0;
break;
}
return op->len;
}
typedef const unsigned char *buf_t;
#if HAS_MAIN
int main() {
#if 0
[1] 6060 PUSH1 0x60
[3] 6040 PUSH1 0x40
[4] 52 MSTORE
[5] 36 CALLDATASIZE
[6] 15 ISZERO// WRONG ?? should be 11
[9] PUSH2 0x00da
[10] JUMPI
[12] PUSH1 0xe0
[14] PUSH1 0x02
[15] EXP
#endif
int i;
EvmOp op = {
0
};
buf_t b = (buf_t) "\x60\x60\x60\x40\x52\x36\x15\x61\x00\xda\x57\x60\xe0\x60\x02";
for (i = 0; i < sizeof (b); i++) {
evm_dis (&op, b + i, sizeof (b) - i);
printf ("len=%d op=0x%02x %s\n", op.len, op.op, op.txt);
if (op.len < 1) {
break;
}
i += op.len - 1;
}
return 0;
}
#endif
-174
View File
@@ -1,174 +0,0 @@
#ifndef EVM_EVM_H
#define EVM_EVM_H
#include <r_util.h>
typedef enum {
EVM_OP_STOP = 0x00,
EVM_OP_ADD,
EVM_OP_MUL,
EVM_OP_SUB,
EVM_OP_DIV,
EVM_OP_SDIV,
EVM_OP_MOD,
EVM_OP_SMOD,
EVM_OP_ADDMOD,
EVM_OP_MULMOD,
EVM_OP_EXP,
EVM_OP_SIGNEXTEND,
EVM_OP_LT = 0x10,
EVM_OP_GT,
EVM_OP_SLT,
EVM_OP_SGT,
EVM_OP_EQ,
EVM_OP_ISZERO,
EVM_OP_AND,
EVM_OP_OR,
EVM_OP_XOR,
EVM_OP_NOT,
EVM_OP_BYTE,
EVM_OP_SHL,
EVM_OP_SHR,
EVM_OP_SAR,
EVM_OP_SHA3 = 0x20,
EVM_OP_ADDRESS = 0x30,
EVM_OP_BALANCE,
EVM_OP_ORIGIN,
EVM_OP_CALLER,
EVM_OP_CALLVALUE,
EVM_OP_CALLDATALOAD,
EVM_OP_CALLDATASIZE,
EVM_OP_CALLDATACOPY,
EVM_OP_CODESIZE,
EVM_OP_CODECOPY,
EVM_OP_GASPRICE,
EVM_OP_EXTCODESIZE,
EVM_OP_EXTCODECOPY,
EVM_OP_RETURNDATASIZE,
EVM_OP_RETURNDATACOPY,
EVM_OP_EXTCODEHASH,
EVM_OP_BLOCKHASH,
EVM_OP_COINBASE,
EVM_OP_TIMESTAMP,
EVM_OP_NUMBER,
EVM_OP_DIFFICULTY,
EVM_OP_GASLIMIT,
EVM_OP_CHAINID,
EVM_OP_SELFBALANCE,
EVM_OP_POP = 0x50,
EVM_OP_MLOAD,
EVM_OP_MSTORE,
EVM_OP_MSTORE8,
EVM_OP_SLOAD,
EVM_OP_SSTORE,
EVM_OP_JUMP,
EVM_OP_JUMPI,
EVM_OP_PC,
EVM_OP_MSIZE,
EVM_OP_GAS,
EVM_OP_JUMPDEST,
EVM_OP_PUSH1 = 0x60,
EVM_OP_PUSH2,
EVM_OP_PUSH3,
EVM_OP_PUSH4,
EVM_OP_PUSH5,
EVM_OP_PUSH6,
EVM_OP_PUSH7,
EVM_OP_PUSH8,
EVM_OP_PUSH9,
EVM_OP_PUSH10,
EVM_OP_PUSH11,
EVM_OP_PUSH12,
EVM_OP_PUSH13,
EVM_OP_PUSH14,
EVM_OP_PUSH15,
EVM_OP_PUSH16,
EVM_OP_PUSH17,
EVM_OP_PUSH18,
EVM_OP_PUSH19,
EVM_OP_PUSH20,
EVM_OP_PUSH21,
EVM_OP_PUSH22,
EVM_OP_PUSH23,
EVM_OP_PUSH24,
EVM_OP_PUSH25,
EVM_OP_PUSH26,
EVM_OP_PUSH27,
EVM_OP_PUSH28,
EVM_OP_PUSH29,
EVM_OP_PUSH30,
EVM_OP_PUSH31,
EVM_OP_PUSH32,
EVM_OP_DUP1,
EVM_OP_DUP2,
EVM_OP_DUP3,
EVM_OP_DUP4,
EVM_OP_DUP5,
EVM_OP_DUP6,
EVM_OP_DUP7,
EVM_OP_DUP8,
EVM_OP_DUP9,
EVM_OP_DUP10,
EVM_OP_DUP11,
EVM_OP_DUP12,
EVM_OP_DUP13,
EVM_OP_DUP14,
EVM_OP_DUP15,
EVM_OP_DUP16,
EVM_OP_SWAP1,
EVM_OP_SWAP2,
EVM_OP_SWAP3,
EVM_OP_SWAP4,
EVM_OP_SWAP5,
EVM_OP_SWAP6,
EVM_OP_SWAP7,
EVM_OP_SWAP8,
EVM_OP_SWAP9,
EVM_OP_SWAP10,
EVM_OP_SWAP11,
EVM_OP_SWAP12,
EVM_OP_SWAP13,
EVM_OP_SWAP14,
EVM_OP_SWAP15,
EVM_OP_SWAP16,
EVM_OP_LOG0 = 0xa0,
EVM_OP_LOG1,
EVM_OP_LOG2,
EVM_OP_LOG3,
EVM_OP_LOG4,
EVM_OP_CREATE = 0xf0,
EVM_OP_CALL,
EVM_OP_CALLCODE,
EVM_OP_RETURN,
EVM_OP_DELEGATECALL,
EVM_OP_CREATE2,
EVM_OP_STATICCALL = 0xfa,
EVM_OP_REVERT = 0xfd,
EVM_OP_INVALID,
EVM_OP_SELFDESTRUCT
} EvmOpcodes;
typedef struct EvmOp {
EvmOpcodes op;
int len;
const char *txt;
// Largest opcode is "push32 0x" followed by hex value of 32 bytes.
char txt_buf[9+64+1];
} EvmOp;
typedef struct {
const char *txt;
int len;
} EvmOpDef;
extern const EvmOpDef opcodes[256];
int evm_dis(EvmOp *op, const unsigned char *buf, int buf_len);
int evm_asm(const char *str, RStrBuf *buf, int buf_len);
#endif /* EVM_EVM_H */
+30 -10
View File
@@ -39,7 +39,7 @@ extern "C" {
#define bfd_malloc malloc
#define xmalloc malloc
typedef int (*fprintf_ftype) (void *, const char*, ...) ATTRIBUTE_FPTR_PRINTF_2;
typedef int (*fprintf_ftype) (void *, const char*, ...) ATTRIBUTE_FPTR_PRINTF_2;
enum dis_insn_type
{
@@ -322,6 +322,7 @@ extern int print_insn_tilegx (bfd_vma, disassemble_info *);
extern int print_insn_tilepro (bfd_vma, disassemble_info *);
extern int print_insn_v850 (bfd_vma, disassemble_info *);
extern int print_insn_vax (bfd_vma, disassemble_info *);
extern int print_insn_vc4 (bfd_vma, disassemble_info *);
extern int print_insn_visium (bfd_vma, disassemble_info *);
extern int print_insn_w65 (bfd_vma, disassemble_info *);
extern int print_insn_xc16x (bfd_vma, disassemble_info *);
@@ -336,6 +337,7 @@ extern int print_insn_rl78 (bfd_vma, disassemble_info *);
extern int print_insn_rl78_g10 (bfd_vma, disassemble_info *);
extern int print_insn_rl78_g13 (bfd_vma, disassemble_info *);
extern int print_insn_rl78_g14 (bfd_vma, disassemble_info *);
extern int print_insn_loongarch (bfd_vma, disassemble_info *);
extern disassembler_ftype arc_get_disassembler (bfd *);
extern disassembler_ftype cris_get_disassembler (bfd *);
@@ -420,10 +422,10 @@ extern bfd_boolean generic_symbol_is_valid
/* Method to initialize a disassemble_info struct. This should be
called by all applications creating such a struct. */
extern void init_disassemble_info (struct disassemble_info *dinfo, void *stream,
extern void init_disassemble_info(struct disassemble_info *dinfo, void *stream,
fprintf_ftype fprintf_func);
extern int print_insn_tricore (bfd_vma memaddr, struct disassemble_info *info);
extern int print_insn_tricore(bfd_vma memaddr, struct disassemble_info *info);
/* For compatibility with existing code. */
#define INIT_DISASSEMBLE_INFO(INFO, STREAM, FPRINTF_FUNC) \
@@ -431,8 +433,31 @@ extern int print_insn_tricore (bfd_vma memaddr, struct disassemble_info *info);
#define INIT_DISASSEMBLE_INFO_NO_ARCH(INFO, STREAM, FPRINTF_FUNC) \
init_disassemble_info (&(INFO), (STREAM), (fprintf_ftype) (FPRINTF_FUNC))
#define DECLARE_GENERIC_FPRINTF_FUNC_NOGLOBALS() \
static inline int generic_fprintf_func(void *stream, const char *format, ...) { \
int ret; \
va_list ap; \
RStrBuf *sb = (RStrBuf *)stream; \
if (!sb || !format) { \
return 0; \
} \
va_start (ap, format); \
ret = r_strbuf_vappendf (sb, format, ap); \
va_end (ap); \
return ret; \
}
#define DECLARE_GENERIC_PRINT_ADDRESS_FUNC_NOGLOBALS() \
static inline void generic_print_address_func(bfd_vma address, struct disassemble_info *info) { \
RStrBuf *sb = (RStrBuf *)info->stream; \
if (!sb) { \
return; \
} \
r_strbuf_appendf (sb, "0x%08"PFMT64x, (ut64)address); \
}
#define DECLARE_GENERIC_FPRINTF_FUNC() \
static int generic_fprintf_func(void *stream, const char *format, ...) { \
static inline int generic_fprintf_func(void *stream, const char *format, ...) { \
int ret; \
va_list ap; \
if (!buf_global || !format) { \
@@ -445,20 +470,15 @@ static int generic_fprintf_func(void *stream, const char *format, ...) { \
}
#define DECLARE_GENERIC_PRINT_ADDRESS_FUNC() \
static void generic_print_address_func(bfd_vma address, struct disassemble_info *info) { \
static inline void generic_print_address_func(bfd_vma address, struct disassemble_info *info) { \
if (!buf_global) { \
return; \
} \
r_strbuf_appendf (buf_global, "0x%08"PFMT64x, (ut64)address); \
}
#ifdef __cplusplus
}
#endif
#ifdef _MSC_VER
#undef xmalloc
#endif
#endif /* ! defined (DIS_ASM_H) */
+66 -1
View File
@@ -1,5 +1,5 @@
/* bfin.h -- Header file for ADI Blackfin opcode table
Copyright 2005, 2010, 2011 Free Software Foundation, Inc.
Copyright (C) 2005-2017 Free Software Foundation, Inc.
This file is part of GDB, GAS, and the GNU binutils.
@@ -41,6 +41,23 @@
#define M_IH 11
#define M_IU 12
#define M32_NS 1
#define M32_T 1
#define M32_IS 2
#define M32_IS_NS 3
#define M32_FU 4
#define M32_TFU 5
#define M32_IU 6
#define M32_IU_NS 7
#define M32_M 8
#define M32_M_T 9
#define M32_M_IS 10
#define M32_M_IS_NS 11
#define CMODE_DEFAULT 13
#define CMODE_T 14
#define CMODE_IS 15
static inline int is_macmod_pmove (int x)
{
return (x == 0) || (x == M_IS) || (x == M_FU) || (x == M_S2RND)
@@ -1259,6 +1276,54 @@ typedef struct
LoopSetup_code_bits, LoopSetup_code_mask \
};
/* LDIMM
+---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
| 1 | 1 | 0 | 1 | 1 | 0 | 1 | 0 | 0 | 0 |.grp.......|.reg.......|
|.imm[31:16]....................................................|
+---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
|.imm[15:0].....................................................|
+---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
|.dummy[15:0]...................................................|
+---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
*/
typedef struct
{
unsigned long long opcode;
int bits_dummy;
int mask_dummy;
int bits_imm;
int mask_imm;
int bits_reg;
int mask_reg;
int bits_grp;
int mask_grp;
int bits_code;
int mask_code;
} LDIMM;
#define LDIMM_opcode ((unsigned long long)0xda00000000000000)
#define LDIMM_dummy_bits 0
#define LDIMM_dummy_mask 0xffff
#define LDIMM_imm_bits 16
#define LDIMM_imm_mask 0xffffffff
#define LDIMM_reg_bits 48
#define LDIMM_reg_mask 0x7
#define LDIMM_grp_bits 51
#define LDIMM_grp_mask 0x7
#define LDIMM_code_bits 54
#define LDIMM_code_mask 0x3ff
#define init_LDIMM \
{ \
LDIMM_opcode, \
LDIMM_dummy_bits, LDIMM_dummy_mask, \
LDIMM_imm_bits, LDIMM_imm_mask, \
LDIMM_reg_bits, LDIMM_reg_mask, \
LDIMM_grp_bits, LDIMM_grp_mask, \
LDIMM_code_bits, LDIMM_code_mask \
};
/* LDIMMhalf
+---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
| 1 | 1 | 1 | 0 | 0 | 0 | 0 | 1 |.Z.|.H.|.S.|.grp...|.reg.......|
+1 -1
View File
@@ -11,7 +11,7 @@ all:
$(MAKE) test
test:
r2 -qcq -a m32c.gnu -b32 -c 'woe 1 0xff 1' -c 'pd 10' -
r2 -qcq -a m32c -b32 -c 'woe 1 0xff 1' -c 'pd 10' -
install:
mkdir -p $(R2HOME)
+73 -1
View File
@@ -6,11 +6,83 @@
#include <r_asm.h>
#include <r_anal.h>
#include "disas-asm.h"
#include "mybfd.h"
int m32c_assemble(const char *str, ut64 pc, ut8 *out);
static unsigned long Offset = 0;
static RStrBuf *buf_global = NULL;
static unsigned char bytes[8];
static char *pre_cpu = NULL;
static char *pre_features = NULL;
static int m32c_buffer_read_memory(bfd_vma memaddr, bfd_byte *myaddr, unsigned int length, struct disassemble_info *info) {
int delta = (memaddr - Offset);
if (delta < 0) {
return -1; // disable backward reads
}
if ((delta + length) > sizeof (bytes)) {
return -1;
}
memcpy (myaddr, bytes + delta, length);
return 0;
}
static int symbol_at_address(bfd_vma addr, struct disassemble_info * info) {
return 0;
}
static void memory_error_func(int status, bfd_vma memaddr, struct disassemble_info *info) {
//--
}
DECLARE_GENERIC_PRINT_ADDRESS_FUNC()
DECLARE_GENERIC_FPRINTF_FUNC()
static int disassemble(RAnal *a, RAnalOp *op, const ut8 *buf, int len) {
struct disassemble_info disasm_obj = {0};
if (len < sizeof (bytes)) {
return -1;
}
buf_global = r_strbuf_new ("");
memcpy (bytes, buf, R_MIN (sizeof (bytes), len));
Offset = op->addr;
memcpy (bytes, buf, R_MIN (len, sizeof (bytes)));
/* prepare disassembler */
// disasm_obj.mach = bfd_mach_m32c;
disasm_obj.disassembler_options = "";
disasm_obj.buffer = bytes;
disasm_obj.read_memory_func = &m32c_buffer_read_memory;
disasm_obj.symbol_at_address_func = &symbol_at_address;
disasm_obj.memory_error_func = &memory_error_func;
disasm_obj.print_address_func = &generic_print_address_func;
disasm_obj.buffer_vma = Offset;
disasm_obj.buffer_length = R_MIN (len, sizeof (bytes));
disasm_obj.endian = !a->config->big_endian;
disasm_obj.endian_code = disasm_obj.endian;
disasm_obj.fprintf_func = &generic_fprintf_func;
disasm_obj.stream = stdout;
op->size = print_insn_m32c ((bfd_vma)Offset, &disasm_obj);
if (op->size == -1) {
op->mnemonic = strdup ("(data)");
// r_strbuf_set (&op->buf_asm, "(data)");
r_strbuf_free (buf_global);
} else {
op->mnemonic = r_strbuf_drain (buf_global);
}
return op->size;
}
static int m32c_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *b, int len, RAnalOpMask mask) {
if (!op) {
return 1;
}
op->size = 4;
if (mask & R_ARCH_OP_MASK_DISASM) {
op->addr = addr;
disassemble (anal, op, b, len);
}
return op->size;
}
@@ -18,7 +90,7 @@ static int m32c_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *b, int len, R
RAnalPlugin r_anal_plugin_m32c = {
.name = "m32c",
.desc = "m32c analysis plugin",
.license = "LGPL3",
.license = "LGPL-3.0-only",
.arch = "m32c",
.esil = false,
.bits = 32,
+4 -1
View File
@@ -1,3 +1,5 @@
// asm plugins died in r2-5.8
#if 0
/* radare - LGPL - Copyright 2021 - pancake */
#include <stdio.h>
@@ -92,7 +94,7 @@ RAsmPlugin r_asm_plugin_m32c_gnu = {
.name = "m32c.gnu",
.arch = "m32c",
.author = "pancake",
.license = "GPL3",
.license = "GPL-3.0-only",
.bits = 16 | 32,
.endian = R_SYS_ENDIAN_LITTLE,
.desc = "M32C CPU",
@@ -107,3 +109,4 @@ R_API RLibStruct radare_plugin = {
.version = R2_VERSION
};
#endif
#endif
+10
View File
@@ -0,0 +1,10 @@
# build artifacts
*.o
*.dylib
*.so
*.a
# editor / assistant caches
.pmai/
.DS_Store
build/
+68
View File
@@ -0,0 +1,68 @@
# Build the r2 vc4 asm/anal plugin straight from this directory.
# Mirrors libr/asm/p/vc4.mk + libr/plugs.mk but works standalone.
CC?=cc
VC4DIR=$(shell pwd)
PLUGDIR=$(abspath $(VC4DIR)/../../p)
PLUGSRC=$(PLUGDIR)/arch_vc4.c
R2_CFLAGS?=$(shell pkg-config --cflags r_arch r_asm r_util 2>/dev/null || pkg-config --cflags r_asm r_util 2>/dev/null || echo -I$(shell r2 -H R2_INCDIR 2>/dev/null))
R2_LDFLAGS?=$(shell pkg-config --libs r_arch r_asm r_util 2>/dev/null || pkg-config --libs r_asm r_util 2>/dev/null || echo -L$(shell r2 -H R2_LIBDIR 2>/dev/null) -lr_anal -lr_arch -lr_asm -lr_util)
R2HOME?=$(shell r2 -H R2_USER_PLUGINS 2>/dev/null || echo $(HOME)/.local/share/radare2/plugins)
UNAME_S?=$(shell uname -s)
ifeq ($(UNAME_S),Darwin)
LIBEXT?=dylib
else
LIBEXT?=so
endif
TARGET=arch_vc4.$(LIBEXT)
PSEUDO=asm_vc4.$(LIBEXT)
CFLAGS+=$(R2_CFLAGS)
CFLAGS+=-g -O2 -Wall -fPIC
CFLAGS+=-I$(VC4DIR) -I$(VC4DIR)/include -I$(VC4DIR)/include/opcode
CFLAGS+=-I$(VC4DIR)/../include
LDFLAGS+=$(R2_LDFLAGS) -lr_anal
LDFLAGS+=-shared
OBJ=arch_vc4.o \
vc4-dis.o vc4-asm.o vc4-desc.o vc4-ibld.o vc4-opc.o \
cgen-bitset.o cgen-dis.o cgen-asm.o cgen-opc.o
all: $(TARGET) $(PSEUDO)
%.o: %.c
$(CC) -c $(CFLAGS) $< -o $@
# binutils/cgen generated sources use the dashes in their names
vc4-%.o: vc4-%.c
$(CC) -c $(CFLAGS) $< -o $@
# the r2 glue lives in libr/asm/p/
arch_vc4.o: $(PLUGSRC) vc4_anal.inc.c
$(CC) -c $(CFLAGS) $(PLUGSRC) -o $@
$(TARGET): $(OBJ)
$(CC) -o $(TARGET) $(OBJ) $(LDFLAGS)
$(PSEUDO): pseudo.o
$(CC) -o $(PSEUDO) pseudo.o $(LDFLAGS)
install: $(TARGET) $(PSEUDO)
mkdir -p $(R2HOME)
cp -f $(TARGET) $(R2HOME)
-codesign -f -s - $(R2HOME)/$(TARGET) 2>/dev/null || true
uninstall:
rm -f $(R2HOME)/$(TARGET) $(R2HOME)/$(PSEUDO)
clean:
rm -f $(OBJ) $(TARGET) pseudo.o $(PSEUDO)
mrproper: clean
$(MAKE) -C libvc4 clean 2>/dev/null || true
.PHONY: all install uninstall clean mrproper
+16
View File
@@ -0,0 +1,16 @@
/* Minimal safe-ctype.h for the vc4 cgen sources, avoids depending on
libiberty's _sch_istable. */
#ifndef SAFE_CTYPE_H
#define SAFE_CTYPE_H
#include <ctype.h>
#define ISALNUM(c) isalnum ((unsigned char) (c))
#define ISALPHA(c) isalpha ((unsigned char) (c))
#define ISDIGIT(c) isdigit ((unsigned char) (c))
#define ISSPACE(c) isspace ((unsigned char) (c))
#define TOLOWER(c) tolower ((unsigned char) (c))
#define TOUPPER(c) toupper ((unsigned char) (c))
#endif
+2
View File
@@ -28,6 +28,8 @@
file (check in a non-ANSI environment!), it should be. */
#include "ansidecl.h"
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
+291
View File
@@ -0,0 +1,291 @@
/* radare - LGPL - Copyright 2026 - pancake */
#include <r_asm.h>
static const char *pseudo_rules[] = {
"mov/2/$1 = $2",
"add/2/$1 += $2",
"add/3/$1 = $2 + $3",
"sub/2/$1 -= $2",
"sub/3/$1 = $2 - $3",
"rsub/2/$1 = $2 - $1",
"rsub/3/$1 = $3 - $2",
"mul/2/$1 *= $2",
"mul/3/$1 = $2 * $3",
"div/3/$1 = $2 / $3",
"mulhd/3/$1 = ($2 * $3) >> 32",
"and/2/$1 &= $2",
"and/3/$1 = $2 & $3",
"or/2/$1 |= $2",
"or/3/$1 = $2 | $3",
"eor/2/$1 ^= $2",
"eor/3/$1 = $2 ^ $3",
"bic/2/$1 &= ~$2",
"bic/3/$1 = $2 & ~$3",
"not/2/$1 = ~$2",
"neg/2/$1 = -$2",
"abs/2/$1 = abs ($2)",
"shl/2/$1 <<= $2",
"shl/3/$1 = $2 << $3",
"lsr/2/$1 >>= $2",
"lsr/3/$1 = $2 >> $3",
"asr/2/$1 = (st32)$1 >> $2",
"asr/3/$1 = (st32)$2 >> $3",
"ror/2/$1 = ror ($1, $2)",
"ror/3/$1 = ror ($2, $3)",
"min/2/$1 = min ($1, $2)",
"min/3/$1 = min ($2, $3)",
"max/2/$1 = max ($1, $2)",
"max/3/$1 = max ($2, $3)",
"bitset/2/$1 |= 1 << $2",
"bitset/3/$1 = $2 | (1 << $3)",
"bitclear/2/$1 &= ~(1 << $2)",
"bitclear/3/$1 = $2 & ~(1 << $3)",
"bitflip/2/$1 ^= 1 << $2",
"bitflip/3/$1 = $2 ^ (1 << $3)",
"btest/2/flags = $1 & (1 << $2)",
"bmask/2/$1 &= (1 << $2) - 1",
"bmask/3/$1 = $2 & ((1 << $3) - 1)",
"signext/2/$1 = signext ($1, $2)",
"signext/3/$1 = signext ($2, $3)",
"addscale/2/$1 += $2",
"addscale/3/$1 = $2 + $3",
"subscale/2/$1 -= $2",
"subscale/3/$1 = $2 - $3",
"adds/3/$1 = sat ($2 + $3)",
"subs/3/$1 = sat ($2 - $3)",
"msb/2/$1 = msb ($2)",
"count/2/$1 = popcount ($2)",
"brev/2/$1 = bitreverse ($2)",
"clamp16/2/$1 = clamp16 ($2)",
"cmp/2/flags = $1 - $2",
"cmn/2/flags = $1 + $2",
"fadd/3/$1 = $2 + $3",
"fsub/3/$1 = $2 - $3",
"frsub/3/$1 = $3 - $2",
"fmul/3/$1 = $2 * $3",
"fnmul/3/$1 = -($2 * $3)",
"fdiv/3/$1 = $2 / $3",
"fmax/3/$1 = fmax ($2, $3)",
"fmin/3/$1 = fmin ($2, $3)",
"fabs/2/$1 = fabs ($2)",
"frcp/2/$1 = 1 / $2",
"frsqrt/2/$1 = 1 / sqrt ($2)",
"fceil/2/$1 = ceil ($2)",
"ffloor/2/$1 = floor ($2)",
"flog2/2/$1 = log2 ($2)",
"fexp2/2/$1 = exp2 ($2)",
"fcmp/2/flags = $1 - $2",
"ftrunc/3/$1 = (int)($2 $3)",
"floor/3/$1 = (int)floor ($2 $3)",
"flts/3/$1 = (float)($2 $3)",
"fltu/3/$1 = (float)(unsigned)($2 $3)",
"lea/2/$1 = &$2",
"ld/2/$1 = (ut32)$2",
"ldh/2/$1 = (ut16)$2",
"ldsh/2/$1 = (st16)$2",
"ldb/2/$1 = (ut8)$2",
"ldsb/2/$1 = (st8)$2",
"st/2/(ut32)$2 = $1",
"sth/2/(ut16)$2 = $1",
"stb/2/(ut8)$2 = $1",
"b/1/goto $1",
"j/1/goto $1",
"bl/1/$1 ()",
"jl/1/$1 ()",
"tbb/1/goto table8[$1]",
"tbh/1/goto table16[$1]",
"version/1/$1 = cpuid",
"rts/0/return",
"rti/0/return from interrupt",
"swi/1/syscall ($1)",
"bkpt/0/breakpoint",
"ei/0/enable interrupts",
"di/0/disable interrupts",
"nop/0/",
NULL
};
// condition suffix and the operator used by compare and branch forms
static const char *conds[][2] = {
{ "eq", "==" }, { "ne", "!=" }, { "lt", "<" }, { "le", "<=" },
{ "gt", ">" }, { "ge", ">=" }, { "hi", ">u" }, { "ls", "<=u" },
{ "cs", "<u" }, { "lo", "<u" }, { "cc", ">=u" }, { "hs", ">=u" },
{ "mi", NULL }, { "pl", NULL }, { "vs", NULL }, { "vc", NULL },
{ "f", NULL }, { NULL, NULL }
};
static int cond_index(const char *s) {
int i;
for (i = 0; conds[i][0]; i++) {
if (!strcmp (s, conds[i][0])) {
return i;
}
}
return -1;
}
// "(r1+8)" -> "[r1 + 8]", "(r1)" -> "[r1]", "#imm" -> "imm"
static char *normalize(const char *data) {
RStrBuf *sb = r_strbuf_new ("");
const char *p;
for (p = data; *p; p++) {
if (*p == '#') {
continue;
}
if (*p == '(' && p > data && (p[-1] == ',' || p[-1] == ' ')) {
const char *close = strchr (p, ')');
if (close) {
char *in = r_str_ndup (p + 1, close - p - 1);
in = r_str_replace (in, "+-", " - ", 1);
in = r_str_replace (in, "+", " + ", 1);
in = r_str_replace (in, " + + ", "++", 1);
r_strbuf_appendf (sb, "[%s]", in);
free (in);
p = close;
continue;
}
}
r_strbuf_append_n (sb, p, 1);
}
return r_strbuf_drain (sb);
}
static char *transform(const char *data) {
char *res = r_str_pseudo_transform (pseudo_rules, data);
if (res && strcmp (res, data)) {
return res;
}
free (res);
return NULL;
}
// "addcmpb<cond> a,b,c,dst" and "b<cond> a,b,dst" compare after the add
static char *cmpbranch(const char *str, const char *cond, const char *op, bool add) {
char *rule;
if (!strcmp (cond, "f")) {
rule = add? strdup ("x/4/$1 += $2"): strdup ("x/3/");
} else if (add) {
rule = op? r_str_newf ("x/4/$1 += $2; if ($1 %s $3) goto $4", op)
: r_str_newf ("x/4/$1 += $2; if (%s ($1 - $3)) goto $4", cond);
} else {
rule = op? r_str_newf ("x/3/if ($1 %s $2) goto $3", op)
: r_str_newf ("x/3/if (%s ($1 - $2)) goto $3", cond);
}
const char *rules[] = { rule, NULL };
const char *args = strchr (str, ' ');
char *s = r_str_newf ("x%s", args? args: "");
char *res = r_str_pseudo_transform (rules, s);
free (s);
free (rule);
return res;
}
// r_str_pseudo_transform turns "a + -1" into "a -1", make it "a - 1"
static char *fix_minus(char *s) {
RStrBuf *sb = r_strbuf_new ("");
char *p;
for (p = s; *p; p++) {
r_strbuf_append_n (sb, p, 1);
if (p > s && p[0] == ' ' && p[1] == '-' && isdigit ((ut8)p[2]) && isalnum ((ut8)p[-1])) {
r_strbuf_append (sb, "- ");
p++;
}
}
free (s);
return r_strbuf_drain (sb);
}
static char *parse(RAsmPluginSession *aps, const char *data) {
char *str = normalize (data);
char *sp = strchr (str, ' ');
char *args = sp? sp: "";
char *mn = r_str_ndup (str, sp? sp - str: strlen (str));
// mnemonic: base[.cond][.m|.s][.ss|.su|.us|.uu]
int cond = -1;
char *dot = strchr (mn, '.');
if (dot) {
char *t = dot;
*dot = 0;
while (t) {
char *part = t + 1;
t = strchr (part, '.');
if (t) {
*t = 0;
}
int c = cond_index (part);
if (c >= 0) {
cond = c;
}
}
}
char *res = NULL;
int ci = -1;
int nargs = *args? (int)r_str_char_count (args, ',') + 1: 0;
if (r_str_startswith (mn, "addcmpb")) {
ci = mn[7]? cond_index (mn + 7): -1;
if (!mn[7]) {
char *s = r_str_newf ("x%s", args);
const char *rules[] = { "x/4/$1 += $2; goto $4", NULL };
res = r_str_pseudo_transform (rules, s);
free (s);
} else if (ci >= 0) {
res = cmpbranch (str, conds[ci][0], conds[ci][1], true);
}
} else if (mn[0] == 'b' && mn[1] && (ci = cond_index (mn + 1)) >= 0) {
if (nargs == 3) {
res = cmpbranch (str, conds[ci][0], conds[ci][1], false);
} else if (strcmp (conds[ci][0], "f")) {
res = r_str_newf ("if (%s) goto%s", conds[ci][0], args);
}
} else if (!strcmp (mn, "ldm") || !strcmp (mn, "stm")) {
// ldm r6-r7,pc,(sp++) / stm r6-r7,lr,(--sp)
char *regs = r_str_trim_dup (args);
char *last = (char *)r_str_rchr (regs, NULL, ',');
if (last) {
*last = 0;
}
bool ret = strstr (regs, ",pc") || !strcmp (regs, "pc");
res = r_str_newf ("%s %s%s", (*mn == 'l')? "pop": "push", regs, ret? "; return": "");
free (regs);
} else {
char *s = r_str_newf ("%s%s", mn, args);
char *body = transform (s);
free (s);
if (body) {
if (cond >= 0 && strcmp (conds[cond][0], "f")) {
res = r_str_newf ("if (%s) %s", conds[cond][0], body);
free (body);
} else if (cond >= 0) {
free (body);
} else {
res = body;
}
}
}
free (mn);
free (str);
if (!res) {
return strdup (data);
}
res = r_str_replace (res, "+= -", "-= ", 1);
return fix_minus (res);
}
RAsmPlugin r_asm_plugin_vc4 = {
.meta = {
.name = "vc4",
.desc = "VideoCore IV pseudo syntax",
.author = "pancake",
.license = "LGPL-3.0-only",
},
.parse = parse,
};
#ifndef R2_PLUGIN_INCORE
R_API RLibStruct radare_plugin = {
.type = R_LIB_TYPE_ASM,
.data = &r_asm_plugin_vc4,
.version = R2_VERSION
};
#endif
+49
View File
@@ -0,0 +1,49 @@
# r2plugin
This directory contains the make and meson files required to link the
vc4 (VideoCore IV) plugins statically inside radare2, using the XPS
(static external plugins) mechanism. See `libr/xps/README.md` in the
radare2 source tree for the full details.
Two plugins are registered directly, without a core wrapper, so both
`rasm2` and `r2` get them:
- `arch.vc4`: cgen based disassembler and analysis, linked into libr_arch
- `asm.vc4`: pseudo syntax (`e asm.pseudo=true`), linked into libr_asm
## Usage
Run these commands from the radare2 source tree:
```console
mkdir -p libr/xps/p
ln -s ../../../../radare2-extras/libr/asm/arch/vc4 libr/xps/p/vc4
echo 'EXTERNAL_PLUGINS+=vc4' >> libr/xps/config.mk
make -C libr/xps clean all
```
Then build radare2 as usual:
```console
./configure && make -j
# or
meson setup build --reconfigure && meson compile -C build
```
The meson build needs a radare2 that provides `xps_arch_plugins`,
`xps_asm_plugins` and `r_{arch,asm}_additional_{sources,inc}`.
Verify the plugins are linked in:
```console
rasm2 -L | grep vc4
rasm2 -a vc4 -d 01000200
r2 -NN -qc 'La~vc4;Lp~vc4' --
```
## Notes
- `libvc4/` is not linked: the plugin only uses the cgen disassembler.
- `r2plugin/arch/arch_vc4.c` includes `libr/asm/p/arch_vc4.c`, which
lives outside this directory.
- Object files for the make build are stored under `build/r2plugin/`.
@@ -0,0 +1,4 @@
/* radare - LGPL - Copyright 2026 - pancake */
/* the r2 glue lives in libr/asm/p, outside the XPS directory */
#include "../../../../p/arch_vc4.c"
+5
View File
@@ -0,0 +1,5 @@
/* radare - LGPL - Copyright 2026 - pancake */
#ifdef R2_ARCH_H
extern RArchPlugin r_arch_plugin_vc4;
#endif
+22
View File
@@ -0,0 +1,22 @@
VC4_ARCH_WD=$(LIBR)/xps/p/vc4
VC4_ARCH_BUILD=$(VC4_ARCH_WD)/build/r2plugin/arch
VC4_ARCH_SRC=\
vc4-dis.c vc4-asm.c vc4-desc.c vc4-ibld.c vc4-opc.c \
cgen-bitset.c cgen-dis.c cgen-asm.c cgen-opc.c
VC4_ARCH_OBJ=$(addprefix $(VC4_ARCH_BUILD)/,$(VC4_ARCH_SRC:.c=.o))
VC4_ARCH_OBJ+=$(VC4_ARCH_BUILD)/arch_vc4.o
EXTERNAL_STATIC_OBJS+=$(VC4_ARCH_OBJ)
# must come before r2's libr/arch/include, which ships its own sysdep.h, mybfd.h..
VC4_ARCH_CFLAGS=-I$(VC4_ARCH_WD) -I$(VC4_ARCH_WD)/include \
-I$(VC4_ARCH_WD)/include/opcode -I$(VC4_ARCH_WD)/../include
$(VC4_ARCH_BUILD)/arch_vc4.o: $(VC4_ARCH_WD)/r2plugin/arch/arch_vc4.c $(VC4_ARCH_WD)/../../p/arch_vc4.c
@mkdir -p $(dir $@)
$(CC) -c $(VC4_ARCH_CFLAGS) $(CFLAGS) -o $@ $<
$(VC4_ARCH_BUILD)/%.o: $(VC4_ARCH_WD)/%.c
@mkdir -p $(dir $@)
$(CC) -c $(VC4_ARCH_CFLAGS) $(CFLAGS) -o $@ $<
-include $(VC4_ARCH_OBJ:.o=.d)
+5
View File
@@ -0,0 +1,5 @@
/* radare - LGPL - Copyright 2026 - pancake */
#ifdef R2_ASM_H
extern RAsmPlugin r_asm_plugin_vc4;
#endif
+9
View File
@@ -0,0 +1,9 @@
VC4_ASM_WD=$(LIBR)/xps/p/vc4
VC4_ASM_OBJ=$(VC4_ASM_WD)/build/r2plugin/asm/pseudo.o
EXTERNAL_STATIC_OBJS+=$(VC4_ASM_OBJ)
$(VC4_ASM_OBJ): $(VC4_ASM_WD)/pseudo.c
@mkdir -p $(dir $@)
$(CC) -c $(CFLAGS) -o $@ $<
-include $(VC4_ASM_OBJ:.o=.d)
+9
View File
@@ -0,0 +1,9 @@
EXTERNAL_PLUGINS+=vc4
.PHONY: vc4
vc4: p/vc4
p/vc4:
cd p && git clone --depth 1 https://github.com/radareorg/radare2-extras
ln -fs radare2-extras/libr/asm/arch/vc4 p/vc4
+35
View File
@@ -0,0 +1,35 @@
# vc4 XPS integration for radare2.
# Included from libr/xps/meson.build when this directory lives under
# libr/xps/p/vc4/. Links the arch plugin into libr_arch and the pseudo
# plugin into libr_asm, so rasm2 and r2 get vc4 without external files.
xps_arch_plugins += ['vc4']
# p/vc4 is usually a symlink, resolve it before going above this directory
vc4_shared_inc = run_command('realpath',
join_paths(meson.current_source_dir(), '..', '..', 'include'),
check: true).stdout().strip()
r_arch_additional_inc += include_directories(
'..',
'../include',
'../include/opcode',
vc4_shared_inc,
)
r_arch_additional_sources += files(
'../vc4-dis.c',
'../vc4-asm.c',
'../vc4-desc.c',
'../vc4-ibld.c',
'../vc4-opc.c',
'../cgen-bitset.c',
'../cgen-dis.c',
'../cgen-asm.c',
'../cgen-opc.c',
'arch/arch_vc4.c',
)
xps_asm_plugins += ['vc4']
r_asm_additional_sources += files('../pseudo.c')
+8
View File
@@ -0,0 +1,8 @@
/* radare - LGPL - Copyright 2026 - pancake */
#ifdef R2_ARCH_H
#include "arch/deps.h"
#endif
#ifdef R2_ASM_H
#include "asm/deps.h"
#endif
+2
View File
@@ -0,0 +1,2 @@
arch.vc4
asm.vc4
File diff suppressed because it is too large. Load diff
+52977 -655
View File
File diff suppressed because it is too large. Load diff
+128 -32
View File
@@ -42,12 +42,12 @@ This file is part of the GNU Binutils and/or GDB, the GNU debugger.
/* Maximum size of any insn (in bytes). */
#define CGEN_MAX_INSN_SIZE 10
#define CGEN_MAX_EXTRA_OPCODE_OPERANDS 2
#define CGEN_MAX_EXTRA_OPCODE_OPERANDS 3
#define CGEN_INT_INSN_P 0
/* Maximum number of syntax elements in an instruction. */
#define CGEN_ACTUAL_MAX_SYNTAX_ELEMENTS 20
#define CGEN_ACTUAL_MAX_SYNTAX_ELEMENTS 26
/* CGEN_MNEMONIC_OPERANDS is defined if mnemonics have operands.
e.g. In "b,a foo" the ",a" is an operand. If mnemonics have operands
@@ -55,7 +55,7 @@ This file is part of the GNU Binutils and/or GDB, the GNU debugger.
#define CGEN_MNEMONIC_OPERANDS
/* Maximum number of fields in an instruction. */
#define CGEN_ACTUAL_MAX_IFMT_OPERANDS 9
#define CGEN_ACTUAL_MAX_IFMT_OPERANDS 15
/* Enums. */
@@ -76,7 +76,7 @@ typedef enum insn_op15_13 {
/* Enum declaration for insn float ops. */
typedef enum insn_floatops {
ALUFOP_FADD, ALUFOP_FSUB, ALUFOP_FMUL, ALUFOP_FDIV
, ALUFOP_FCMP, ALUFOP_FABS, ALUFOP_FRSB, ALUFOP_FMAX
, ALUFOP_FCMP, ALUFOP_FABS, ALUFOP_FRSUB, ALUFOP_FMAX
, ALUFOP_FRCP, ALUFOP_FRSQRT, ALUFOP_FNMUL, ALUFOP_FMIN
, ALUFOP_FCEIL, ALUFOP_FFLOOR, ALUFOP_FLOG2, ALUFOP_FEXP2
} INSN_FLOATOPS;
@@ -86,7 +86,7 @@ typedef enum insn_alu16op {
ALU16OP_MOV, ALU16OP_CMN, ALU16OP_ADD, ALU16OP_BIC
, ALU16OP_MUL, ALU16OP_EOR, ALU16OP_SUB, ALU16OP_AND
, ALU16OP_NOT, ALU16OP_ROR, ALU16OP_CMP, ALU16OP_RSUB
, ALU16OP_BTST, ALU16OP_OR, ALU16OP_BMASK, ALU16OP_MAX
, ALU16OP_BTEST, ALU16OP_OR, ALU16OP_BMASK, ALU16OP_MAX
, ALU16OP_BSET, ALU16OP_MIN, ALU16OP_BCLR, ALU16OP_ADDS2
, ALU16OP_BCHG, ALU16OP_ADDS4, ALU16OP_ADDS8, ALU16OP_ADDS16
, ALU16OP_SIGNEXT, ALU16OP_NEG, ALU16OP_LSR, ALU16OP_MSB
@@ -96,7 +96,7 @@ typedef enum insn_alu16op {
/* Enum declaration for insn alu16 imm ops. */
typedef enum insn_alu16opi {
ALU16OPI_MOV, ALU16OPI_ADD, ALU16OPI_MUL, ALU16OPI_SUB
, ALU16OPI_NOT, ALU16OPI_CMP, ALU16OPI_BTST, ALU16OPI_BMASK
, ALU16OPI_NOT, ALU16OPI_CMP, ALU16OPI_BTEST, ALU16OPI_BMASK
, ALU16OPI_BSET, ALU16OPI_BCLR, ALU16OPI_BCHG, ALU16OPI_ADDS8
, ALU16OPI_SIGNEXT, ALU16OPI_LSR, ALU16OPI_SHL, ALU16OPI_ASR
} INSN_ALU16OPI;
@@ -106,7 +106,7 @@ typedef enum insn_alu32op {
ALU32OP_MOV, ALU32OP_CMN, ALU32OP_ADD, ALU32OP_BIC
, ALU32OP_MUL, ALU32OP_EOR, ALU32OP_SUB, ALU32OP_AND
, ALU32OP_NOT, ALU32OP_ROR, ALU32OP_CMP, ALU32OP_RSUB
, ALU32OP_BTST, ALU32OP_OR, ALU32OP_BMASK, ALU32OP_MAX
, ALU32OP_BTEST, ALU32OP_OR, ALU32OP_BMASK, ALU32OP_MAX
, ALU32OP_BSET, ALU32OP_MIN, ALU32OP_BCLR, ALU32OP_ADDS2
, ALU32OP_BCHG, ALU32OP_ADDS4, ALU32OP_ADDS8, ALU32OP_ADDS16
, ALU32OP_SIGNEXT, ALU32OP_NEG, ALU32OP_LSR, ALU32OP_MSB
@@ -141,10 +141,17 @@ typedef enum insn_op7_6 {
OP7_6_0, OP7_6_1, OP7_6_2, OP7_6_3
} INSN_OP7_6;
/* Enum declaration for access sizes. */
typedef enum accsz_op7_6 {
ACCSZ7_6_, ACCSZ7_6_H, ACCSZ7_6_B, ACCSZ7_6_SH
} ACCSZ_OP7_6;
/* Enum declaration for access size. */
typedef enum accsz_10_8 {
ACCSZ10_8_LD, ACCSZ10_8_ST, ACCSZ10_8_LDH, ACCSZ10_8_STH
, ACCSZ10_8_LDB, ACCSZ10_8_STB, ACCSZ10_8_LDSH, ACCSZ10_8_LDSB
} ACCSZ_10_8;
/* Enum declaration for access size (32 bit insns). */
typedef enum accsz_7_5 {
ACCSZ7_5_LD, ACCSZ7_5_ST, ACCSZ7_5_LDH, ACCSZ7_5_STH
, ACCSZ7_5_LDB, ACCSZ7_5_STB, ACCSZ7_5_LDSH, ACCSZ7_5_LDSB
} ACCSZ_7_5;
/* Enum declaration for insn bits 7-5. */
typedef enum insn_op7_5 {
@@ -205,6 +212,67 @@ typedef enum insn_op22_21 {
OP22_21_0, OP22_21_1, OP22_21_2, OP22_21_3
} INSN_OP22_21;
/* Enum declaration for Vector ops (< 48). */
typedef enum insn_vecops {
VECOP_MOV, VECOP_BITPLANES, VECOP_EVEN, VECOP_ODD
, VECOP_INTERL, VECOP_INTERH, VECOP_BITREV, VECOP_ROR
, VECOP_SHL, VECOP_SHLS, VECOP_LSR, VECOP_ASR
, VECOP_SIGNSHL, VECOP_OP13, VECOP_SIGNASL, VECOP_SIGNASLS
, VECOP_AND, VECOP_OR, VECOP_EOR, VECOP_BIC
, VECOP_COUNT, VECOP_MSB, VECOP_OP22, VECOP_OP23
, VECOP_MIN, VECOP_MAX, VECOP_DIST, VECOP_DISTS
, VECOP_CLIP, VECOP_SIGN, VECOP_CLIPS, VECOP_TESTMAG
, VECOP_ADD, VECOP_ADDS, VECOP_ADDC, VECOP_ADDSC
, VECOP_SUB, VECOP_SUBS, VECOP_SUBC, VECOP_SUBSC
, VECOP_RSUB, VECOP_RSUBS, VECOP_RSUBC, VECOP_RSUBSC
, VECOP_OP44, VECOP_OP45, VECOP_OP46, VECOP_OP47
} INSN_VECOPS;
/* Enum declaration for Vector memory ops. */
typedef enum insn_vecmemops {
VMEMOP_LD, VMEMOP_LOOKUPM, VMEMOP_LOOKUPML, VMEMOP_MEM03
, VMEMOP_ST, VMEMOP_INDEXWRITEM, VMEMOP_INDEXWRITEML, VMEMOP_MEM07
, VMEMOP_MEMREAD, VMEMOP_MEMWRITE, VMEMOP_MEM10, VMEMOP_MEM11
, VMEMOP_MEM12, VMEMOP_MEM13, VMEMOP_MEM14, VMEMOP_MEM15
, VMEMOP_MEM16, VMEMOP_MEM17, VMEMOP_MEM18, VMEMOP_MEM19
, VMEMOP_MEM20, VMEMOP_MEM21, VMEMOP_MEM22, VMEMOP_MEM23
, VMEMOP_GETACC, VMEMOP_MEM25, VMEMOP_MEM26, VMEMOP_MEM27
, VMEMOP_MEM28, VMEMOP_MEM29, VMEMOP_MEM30, VMEMOP_MEM31
} INSN_VECMEMOPS;
/* Enum declaration for Vector memory op width. */
typedef enum insn_memwidth {
VMEMWIDTH_8, VMEMWIDTH_16, VMEMWIDTH_32, VMEMWIDTH_UNK
} INSN_MEMWIDTH;
/* Enum declaration for Vector memory op saturation. */
typedef enum insn_memsat {
VMEMSAT_, VMEMSAT_S32, VMEMSAT_UNK, VMEMSAT_S16
} INSN_MEMSAT;
/* Enum declaration for Multiply operations. */
typedef enum insn_mulop {
VMULXOP_MULLSS = 48, VMULXOP_OP481 = 48, VMULXOP_MULLSSS = 49, VMULXOP_OP491 = 49
, VMULXOP_MULMSS = 50, VMULXOP_OP501 = 50, VMULXOP_MULMSSS = 51, VMULXOP_OP511 = 51
, VMULXOP_MULHDSS = 52, VMULXOP_MUL32SS = 52, VMULXOP_MULHDSU = 53, VMULXOP_MUL32SU = 53
, VMULXOP_MULHDUS = 54, VMULXOP_MUL32US = 54, VMULXOP_MULHDUU = 55, VMULXOP_MUL32UU = 55
, VMULXOP_MULHNSS = 56, VMULXOP_OP561 = 56, VMULXOP_MULHNSU = 57, VMULXOP_OP571 = 57
, VMULXOP_MULHNUS = 58, VMULXOP_OP581 = 58, VMULXOP_MULHNUU = 59, VMULXOP_OP591 = 59
, VMULXOP_MULHDTSS = 60, VMULXOP_OP601 = 60, VMULXOP_MULHDTSU = 61, VMULXOP_OP611 = 61
, VMULXOP_OP620 = 62, VMULXOP_OP621 = 62, VMULXOP_OP630 = 63, VMULXOP_OP631 = 63
} INSN_MULOP;
/* Enum declaration for SREG setting for 48-bit ops. */
typedef enum insn_sreg {
SREG_R0, SREG_R1, SREG_R2, SREG_R3
, SREG_R4, SREG_R5, SREG_R6, SREG_R7
} INSN_SREG;
/* Enum declaration for Vector direction bit for 48-bit ops. */
typedef enum insn_vec48dir {
VECDIR_H, VECDIR_V
} INSN_VEC48DIR;
/* Attributes. */
/* Enum declaration for machine type selection. */
@@ -248,7 +316,7 @@ typedef enum cgen_ifld_attr {
typedef enum ifield_type {
VC4_F_NIL, VC4_F_ANYOF, VC4_F_OPLEN, VC4_F_OP15_13
, VC4_F_OP15_11, VC4_F_OP11_8, VC4_F_LDSTOFF, VC4_F_OP11_9
, VC4_F_OP11_10, VC4_F_OP11, VC4_F_OP10_9, VC4_F_OP10_7
, VC4_F_OP11_10, VC4_F_OP11, VC4_F_OP10_8, VC4_F_OP10_7
, VC4_F_ADDSPOFFSET, VC4_F_OP10_0, VC4_F_ALU16OP, VC4_F_ALU16OPI
, VC4_F_OP9_8, VC4_F_OP9_5, VC4_F_SPOFFSET, VC4_F_OP8_5
, VC4_F_OP8_4, VC4_F_OP8_4_SHL3, VC4_F_OP8, VC4_F_OP7_4
@@ -265,7 +333,18 @@ typedef enum ifield_type {
, VC4_F_OP21_16S_SHL6, VC4_F_OP21_16S_SHL7, VC4_F_OP21_16S_SHL8, VC4_F_OP20_16
, VC4_F_OP47_16, VC4_F_PCREL32_48, VC4_F_OP47_43, VC4_F_OFFSET27_48
, VC4_F_PCREL27_48, VC4_F_OP79_48, VC4_F_OFFSET23BITS, VC4_F_OFFSET27BITS
, VC4_F_OFFSET12, VC4_F_MAX
, VC4_F_OFFSET12, VC4_F_OP15_10, VC4_F_OP9, VC4_F_OP8_3
, VC4_F_OP2_0, VC4_F_OP4_3, VC4_F_OP31_22, VC4_F_OP31_28
, VC4_F_OP31_29, VC4_F_OP28, VC4_F_OP27_22, VC4_F_OP21_19
, VC4_F_OP21_18, VC4_F_OP18, VC4_F_OP17_16, VC4_F_OP37_32
, VC4_F_OP38, VC4_F_OP41_32, VC4_F_OP42, VC4_F_OP43
, VC4_F_OP47_44, VC4_F_OP38_32, VC4_F_OP41_39, VC4_F_OP41_38
, VC4_F_OP51_48, VC4_F_OP57_52, VC4_F_OP63_58, VC4_F_OP69_64
, VC4_F_OP76_70, VC4_F_OP79_77, VC4_F_OP65_64, VC4_F_OP69_66
, VC4_F_VEC80DREG, VC4_F_VEC80AREG, VC4_F_VEC80BREG, VC4_F_VEC80MODS
, VC4_F_VEC80MODS_MEM, VC4_F_VEC80IMM, VC4_F_VEC80LDADDR, VC4_F_VEC80STADDR
, VC4_F_DUMMYABITS, VC4_F_VEC48DREG, VC4_F_VEC48AREG, VC4_F_VEC48BREG
, VC4_F_MAX
} IFIELD_TYPE;
#define MAX_IFLD ((int) VC4_F_MAX)
@@ -291,9 +370,9 @@ typedef enum cgen_hw_attr {
/* Enum declaration for vc4 hardware types. */
typedef enum cgen_hw_type {
HW_H_MEMORY, HW_H_SINT, HW_H_UINT, HW_H_ADDR
, HW_H_IADDR, HW_H_REG, HW_H_FASTREG, HW_H_PPREG
, HW_H_BASEREG, HW_H_COND, HW_H_ACCSZ, HW_H_PC
, HW_MAX
, HW_H_IADDR, HW_H_REG, HW_H_FASTREG, HW_H_PREG
, HW_H_PPREG, HW_H_BASEREG, HW_H_COND, HW_H_DOTCOND
, HW_H_PC, HW_H_ELTSIZE, HW_MAX
} CGEN_HW_TYPE;
#define MAX_HW ((int) HW_MAX)
@@ -325,23 +404,37 @@ typedef enum cgen_operand_attr {
typedef enum cgen_operand_type {
VC4_OPERAND_PC, VC4_OPERAND_CONDCODE, VC4_OPERAND_PCRELCC, VC4_OPERAND_LDSTOFF
, VC4_OPERAND_ALU16SREG, VC4_OPERAND_ALU16IMM, VC4_OPERAND_ALU16IMM_SHL3, VC4_OPERAND_ALU16DREG
, VC4_OPERAND_ALU32DREG, VC4_OPERAND_IMM6, VC4_OPERAND_FLOATIMM6, VC4_OPERAND_IMM6_SHL1
, VC4_OPERAND_IMM6_SHL2, VC4_OPERAND_IMM6_SHL3, VC4_OPERAND_IMM6_SHL4, VC4_OPERAND_IMM6_SHL5
, VC4_OPERAND_IMM6_SHL6, VC4_OPERAND_IMM6_SHL7, VC4_OPERAND_IMM6_SHL8, VC4_OPERAND_ALU32BREG
, VC4_OPERAND_PPSTARTREG, VC4_OPERAND_PPENDREG0, VC4_OPERAND_PPENDREG6, VC4_OPERAND_PPENDREG16
, VC4_OPERAND_PPENDREG24, VC4_OPERAND_SWI_IMM, VC4_OPERAND_SPOFFSET, VC4_OPERAND_ADDSPOFFSET
, VC4_OPERAND_ALU32AREG, VC4_OPERAND_ALU32COND, VC4_OPERAND_ALU48ISREG, VC4_OPERAND_ALU48IDREG
, VC4_OPERAND_ALU32DREG, VC4_OPERAND_PREGDST, VC4_OPERAND_PREGSRC, VC4_OPERAND_DISP5
, VC4_OPERAND_IMM6, VC4_OPERAND_FLOATIMM6, VC4_OPERAND_IMM6_SHL1, VC4_OPERAND_IMM6_SHL2
, VC4_OPERAND_IMM6_SHL3, VC4_OPERAND_IMM6_SHL4, VC4_OPERAND_IMM6_SHL5, VC4_OPERAND_IMM6_SHL6
, VC4_OPERAND_IMM6_SHL7, VC4_OPERAND_IMM6_SHL8, VC4_OPERAND_ALU32BREG, VC4_OPERAND_PPSTARTREG
, VC4_OPERAND_PPENDREG0, VC4_OPERAND_PPENDREG6, VC4_OPERAND_PPENDREG16, VC4_OPERAND_PPENDREG24
, VC4_OPERAND_SWI_IMM, VC4_OPERAND_SPOFFSET, VC4_OPERAND_ADDSPOFFSET, VC4_OPERAND_ALU32AREG
, VC4_OPERAND_ALU32MISSINGAREG, VC4_OPERAND_ALU32COND, VC4_OPERAND_ALU48ISREG, VC4_OPERAND_ALU48IDREG
, VC4_OPERAND_MEM48SREG, VC4_OPERAND_ALU48IMMU, VC4_OPERAND_ALU48PCREL, VC4_OPERAND_MEM48OFFSET27
, VC4_OPERAND_MEM48PCREL27, VC4_OPERAND_ACCSZ, VC4_OPERAND_ACCSZ32, VC4_OPERAND_CONDCODEBCC32
, VC4_OPERAND_BCC32SREG, VC4_OPERAND_PCREL10BITS, VC4_OPERAND_PCREL8BITS, VC4_OPERAND_BCC32IMM
, VC4_OPERAND_ADDCMPBAREG, VC4_OPERAND_ADDCMPBIMM, VC4_OPERAND_OFFSET23BITS, VC4_OPERAND_OFFSET27BITS
, VC4_OPERAND_OFFSET12, VC4_OPERAND_OFFSET16, VC4_OPERAND_OFFSET16_SHL1, VC4_OPERAND_OFFSET16_SHL2
, VC4_OPERAND_OFFSET16_SHL3, VC4_OPERAND_OFFSET16_SHL4, VC4_OPERAND_PCREL16, VC4_OPERAND_OFF16BASEREG
, VC4_OPERAND_OPERAND10_0, VC4_OPERAND_OPERAND47_16, VC4_OPERAND_OPERAND79_48, VC4_OPERAND_MAX
, VC4_OPERAND_MEM48PCREL27, VC4_OPERAND_CONDCODEBCC32, VC4_OPERAND_BCC32SREG, VC4_OPERAND_PCREL10BITS
, VC4_OPERAND_PCREL8BITS, VC4_OPERAND_BCC32IMM, VC4_OPERAND_ADDCMPBAREG, VC4_OPERAND_ADDCMPBIMM
, VC4_OPERAND_OFFSET23BITS, VC4_OPERAND_OFFSET27BITS, VC4_OPERAND_OFFSET12, VC4_OPERAND_OFFSET16
, VC4_OPERAND_OFFSET16_SHL1, VC4_OPERAND_OFFSET16_SHL2, VC4_OPERAND_OFFSET16_SHL3, VC4_OPERAND_OFFSET16_SHL4
, VC4_OPERAND_PCREL16, VC4_OPERAND_OFF16BASEREG, VC4_OPERAND_OPERAND10_0, VC4_OPERAND_OPERAND47_16
, VC4_OPERAND_OPERAND79_48, VC4_OPERAND_SHL1, VC4_OPERAND_SHL2, VC4_OPERAND_SHL3
, VC4_OPERAND_SHL4, VC4_OPERAND_SHL5, VC4_OPERAND_SHL6, VC4_OPERAND_SHL7
, VC4_OPERAND_SHL8, VC4_OPERAND_V80D32REG, VC4_OPERAND_V80A32REG, VC4_OPERAND_V80B32REG
, VC4_OPERAND_V80IMM, VC4_OPERAND_V80MODS, VC4_OPERAND_V80MODS_MEM, VC4_OPERAND_SETF_MOD
, VC4_OPERAND_V48IMM_MODS, VC4_OPERAND_VMEMWIDTH, VC4_OPERAND_VEC_LDADDR, VC4_OPERAND_VEC_STADDR
, VC4_OPERAND_DUMMYABITS, VC4_OPERAND_DUMMYDBITS, VC4_OPERAND_V48SCLR, VC4_OPERAND_V48IMM
, VC4_OPERAND_V48DREG_H, VC4_OPERAND_V48DREG_V, VC4_OPERAND_V48AREG_H, VC4_OPERAND_V48AREG_V
, VC4_OPERAND_V48BREG_H, VC4_OPERAND_V48BREG_V, VC4_OPERAND_DPLUS_SR0, VC4_OPERAND_APLUS_SR0
, VC4_OPERAND_BPLUS_SR0, VC4_OPERAND_DPLUS_SR1, VC4_OPERAND_APLUS_SR1, VC4_OPERAND_BPLUS_SR1
, VC4_OPERAND_DPLUS_SR2, VC4_OPERAND_APLUS_SR2, VC4_OPERAND_BPLUS_SR2, VC4_OPERAND_DPLUS_SR3
, VC4_OPERAND_APLUS_SR3, VC4_OPERAND_BPLUS_SR3, VC4_OPERAND_DPLUS_SR4, VC4_OPERAND_APLUS_SR4
, VC4_OPERAND_BPLUS_SR4, VC4_OPERAND_DPLUS_SR5, VC4_OPERAND_APLUS_SR5, VC4_OPERAND_BPLUS_SR5
, VC4_OPERAND_DPLUS_SR6, VC4_OPERAND_APLUS_SR6, VC4_OPERAND_BPLUS_SR6, VC4_OPERAND_DPLUS_SR7
, VC4_OPERAND_APLUS_SR7, VC4_OPERAND_BPLUS_SR7, VC4_OPERAND_MAX
} CGEN_OPERAND_TYPE;
/* Number of operands types. */
#define MAX_OPERANDS 59
#define MAX_OPERANDS 114
/* Maximum number of operands referenced by any insn. */
#define MAX_OPERAND_INSTANCES 8
@@ -352,8 +445,8 @@ typedef enum cgen_operand_type {
typedef enum cgen_insn_attr {
CGEN_INSN_ALIAS, CGEN_INSN_VIRTUAL, CGEN_INSN_UNCOND_CTI, CGEN_INSN_COND_CTI
, CGEN_INSN_SKIP_CTI, CGEN_INSN_DELAY_SLOT, CGEN_INSN_RELAXABLE, CGEN_INSN_RELAXED
, CGEN_INSN_NO_DIS, CGEN_INSN_PBB, CGEN_INSN_END_BOOLS, CGEN_INSN_START_NBOOLS = 31
, CGEN_INSN_MACH, CGEN_INSN_END_NBOOLS
, CGEN_INSN_NO_DIS, CGEN_INSN_PBB, CGEN_INSN_SWITCH, CGEN_INSN_END_BOOLS
, CGEN_INSN_START_NBOOLS = 31, CGEN_INSN_MACH, CGEN_INSN_END_NBOOLS
} CGEN_INSN_ATTR;
/* Number of non-boolean elements in cgen_insn_attr. */
@@ -371,6 +464,7 @@ typedef enum cgen_insn_attr {
#define CGEN_ATTR_CGEN_INSN_RELAXED_VALUE(attrs) (((attrs)->bool_ & (1 << CGEN_INSN_RELAXED)) != 0)
#define CGEN_ATTR_CGEN_INSN_NO_DIS_VALUE(attrs) (((attrs)->bool_ & (1 << CGEN_INSN_NO_DIS)) != 0)
#define CGEN_ATTR_CGEN_INSN_PBB_VALUE(attrs) (((attrs)->bool_ & (1 << CGEN_INSN_PBB)) != 0)
#define CGEN_ATTR_CGEN_INSN_SWITCH_VALUE(attrs) (((attrs)->bool_ & (1 << CGEN_INSN_SWITCH)) != 0)
/* cgen.h uses things we just defined. */
#include "opcode/cgen.h"
@@ -387,10 +481,12 @@ extern const CGEN_ATTR_TABLE vc4_cgen_insn_attr_table[];
extern CGEN_KEYWORD vc4_cgen_opval_h_reg;
extern CGEN_KEYWORD vc4_cgen_opval_h_fastreg;
extern CGEN_KEYWORD vc4_cgen_opval_h_preg;
extern CGEN_KEYWORD vc4_cgen_opval_h_ppreg;
extern CGEN_KEYWORD vc4_cgen_opval_h_basereg;
extern CGEN_KEYWORD vc4_cgen_opval_h_cond;
extern CGEN_KEYWORD vc4_cgen_opval_h_accsz;
extern CGEN_KEYWORD vc4_cgen_opval_h_dotcond;
extern CGEN_KEYWORD vc4_cgen_opval_h_eltsize;
extern const CGEN_HW_ENTRY vc4_cgen_hw_table[];
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+68136 -870
View File
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+2 -2
View File
@@ -1,5 +1,7 @@
ARCHS=
ARCHS=
ARCHS+=x86_udis.mk
ARCHS+=spc700.mk
ARCHS+=ba2.mk
@@ -17,9 +19,7 @@ ARCHS+=vc4.mk
ARCHS+=mc6809.mk
ARCHS+=z80_nc.mk
ARCHS+=x86_zyan.mk
ARCHS+=evm.mk
ARCHS+=atombios.mk
include ../../plugs.mk
+51
View File
@@ -0,0 +1,51 @@
#include <r_lib.h>
#include <r_arch.h>
#include "../arch/arm/arm.h"
static bool decode(RArchSession *as, RAnalOp *op, RArchDecodeMask mask) {
int *p = (int*)op->bytes; // thumb is 16-bit, using host endianness assumption here
char buf_asm[64] = {0};
int len = armthumb_disassemble(buf_asm, (ut32)op->addr, *p);
if (len <= 0) {
op->type = R_ANAL_OP_TYPE_UNK;
op->size = 0;
if (mask & R_ARCH_OP_MASK_DISASM) op->mnemonic = strdup("(data)");
return false;
}
op->size = len;
if (mask & R_ARCH_OP_MASK_DISASM) op->mnemonic = strdup(buf_asm);
return true;
}
static int info(RArchSession *s, ut32 q) {
switch (q) {
case R_ARCH_INFO_MINOP_SIZE: return 2;
case R_ARCH_INFO_MAXOP_SIZE: return 4;
default: return 2;
}
}
RArchPlugin r_arch_plugin_armthumb = {
.meta = {
.name = "arm.thumb",
.desc = "ARM THUMB disassembler",
.author = "pancake",
.version = R2_VERSION,
.license = "LGPL3",
.status = R_PLUGIN_STATUS_OK,
},
.arch = "arm",
.bits = R_SYS_BITS_PACK1(16),
.endian = R_SYS_ENDIAN_LITTLE,
.info = &info,
.decode = &decode,
};
#ifndef R2_PLUGIN_INCORE
R_API RLibStruct radare_plugin = {
.type = R_LIB_TYPE_ARCH,
.data = &r_arch_plugin_armthumb,
.version = R2_VERSION
};
#endif
+54
View File
@@ -0,0 +1,54 @@
#include <r_lib.h>
#include <r_arch.h>
#include <r_util.h>
#include "../arch/atombios/atombios.h"
static bool decode(RArchSession *as, RAnalOp *op, RArchDecodeMask mask) {
if (!(mask & R_ARCH_OP_MASK_DISASM)) {
op->size = 0;
return true;
}
char out[1024];
out[0] = 0;
int sz = atombios_disassemble(op->bytes, op->size, out);
if (sz <= 0) {
op->mnemonic = strdup("invalid");
op->size = 0;
return false;
}
op->mnemonic = strdup(out);
op->size = sz;
return true;
}
static int info(RArchSession *s, ut32 q) {
switch (q) {
case R_ARCH_INFO_MINOP_SIZE: return 1;
case R_ARCH_INFO_MAXOP_SIZE: return 8;
default: return 1;
}
}
RArchPlugin r_arch_plugin_atombios = {
.meta = {
.name = "atombios",
.desc = "AtomBIOS",
.author = "damo22",
.version = R2_VERSION,
.license = "LGPL3",
.status = R_PLUGIN_STATUS_OK,
},
.arch = "atombios",
.bits = R_SYS_BITS_PACK3(16, 32, 64),
.endian = R_SYS_ENDIAN_NONE,
.info = &info,
.decode = &decode,
};
#ifndef R2_PLUGIN_INCORE
R_API RLibStruct radare_plugin = {
.type = R_LIB_TYPE_ARCH,
.data = &r_arch_plugin_atombios,
.version = R2_VERSION
};
#endif
+64
View File
@@ -0,0 +1,64 @@
/* RArch plugin for BA2 using local disassembler */
#include <r_lib.h>
#include <r_arch.h>
#include <r_util.h>
#include <string.h>
#include "../arch/ba2/ba2_disas.c"
static bool decode(RArchSession *as, RAnalOp *op, RArchDecodeMask mask) {
struct op_cmd cmd = { .instr = "", .operands = "" };
int ret = ba2_decode_opcode(op->addr, op->bytes, op->size, &cmd, NULL, NULL);
if ((op->size < ret) || (!ret && op->size < 6)) {
if (mask & R_ARCH_OP_MASK_DISASM) op->mnemonic = strdup("truncated");
op->size = 0;
op->type = R_ANAL_OP_TYPE_ILL;
return false;
}
if (ret > 0) {
if (mask & R_ARCH_OP_MASK_DISASM) {
char buf[128];
if (*cmd.operands) snprintf(buf, sizeof(buf), "%s %s", cmd.instr, cmd.operands);
else snprintf(buf, sizeof(buf), "%s", cmd.instr);
op->mnemonic = strdup(buf);
}
op->size = ret;
return true;
}
if (mask & R_ARCH_OP_MASK_DISASM) op->mnemonic = strdup("invalid");
op->size = 0;
op->type = R_ANAL_OP_TYPE_ILL;
return false;
}
static int info(RArchSession *s, ut32 q) {
switch (q) {
case R_ARCH_INFO_MINOP_SIZE: return 2;
case R_ARCH_INFO_MAXOP_SIZE: return 8;
default: return 2;
}
}
RArchPlugin r_arch_plugin_ba2 = {
.meta = {
.name = "ba2",
.desc = "Beyond Architecture 2 disassembler",
.author = "radare2-extras",
.version = R2_VERSION,
.license = "LGPL3",
.status = R_PLUGIN_STATUS_OK,
},
.arch = "ba2",
.bits = R_SYS_BITS_PACK1(32),
.endian = R_SYS_ENDIAN_LITTLE,
.info = &info,
.decode = &decode,
};
#ifndef R2_PLUGIN_INCORE
R_API RLibStruct radare_plugin = {
.type = R_LIB_TYPE_ARCH,
.data = &r_arch_plugin_ba2,
.version = R2_VERSION
};
#endif
+259
View File
@@ -0,0 +1,259 @@
/* radare - LGPL - Copyright 2015-2024 - pancake */
#include <r_lib.h>
#include <r_asm.h>
#include <r_arch.h>
#define BUFSZ 8
#include "disas-asm.h"
#include "blackfin/bfin-dis.c"
#include "blackfin/bfin-asm.c"
static int blackfin_buffer_read_memory(bfd_vma memaddr, bfd_byte *myaddr, ut32 length, struct disassemble_info *info) {
int delta = (memaddr - info->buffer_vma);
if (delta < 0) {
return -1; // disable backward reads
}
if (delta >= BUFSZ) {
return -1;
}
ut8 *bytes = info->buffer;
int nlen = R_MIN (length, BUFSZ - delta);
if (nlen > 0) {
memcpy (myaddr, bytes + delta, nlen);
}
return 0;
}
static int symbol_at_address(bfd_vma addr, struct disassemble_info *info) {
return 0;
}
static void memory_error_func(int status, bfd_vma memaddr, struct disassemble_info *info) {
//--
}
DECLARE_GENERIC_PRINT_ADDRESS_FUNC_NOGLOBALS()
DECLARE_GENERIC_FPRINTF_FUNC_NOGLOBALS()
static bool encode(RArchSession *a, RAnalOp *op, RArchEncodeMask mask) {
// static int assemble(RAsm *a, RAsmOp *op, const char *buf) {
ut8 hexbuf[8];
int oplen = bfin_assemble (op->mnemonic, (uint32_t)(op->addr), hexbuf);
r_anal_op_set_bytes (op, op->addr, hexbuf, oplen);
return oplen > 1;
}
static bool decode(RArchSession *a, RAnalOp *op, RArchDecodeMask mask) {
ut8 bytes[BUFSZ] = {0};
struct disassemble_info disasm_obj = {0};
if (op->size < 2) {
op->mnemonic = strdup ("truncated");
return false;
}
RStrBuf *sb = r_strbuf_new (NULL);
memcpy (bytes, op->bytes, R_MIN (op->size, BUFSZ));
/* prepare disassembler */
disasm_obj.disassembler_options = NULL;
// bfin_cpu_t bfin_cpu_type = BFIN_CPU_BF707; // UNKNOWN;
disasm_obj.buffer = bytes;
disasm_obj.buffer_vma = op->addr;
disasm_obj.read_memory_func = &blackfin_buffer_read_memory;
disasm_obj.symbol_at_address_func = &symbol_at_address;
disasm_obj.memory_error_func = &memory_error_func;
disasm_obj.print_address_func = &generic_print_address_func;
disasm_obj.endian = !a->config->big_endian;
disasm_obj.fprintf_func = &generic_fprintf_func;
disasm_obj.stream = sb;
op->size = print_insn_bfin ((bfd_vma)op->addr, &disasm_obj);
if (op->size < 1) {
op->type = R_ANAL_OP_TYPE_ILL;
return false;
}
char *instr = sb? r_strbuf_drain (sb): NULL;
if (instr) {
r_str_case (instr, false);
char *colon = strstr (instr, ";");
if (colon) {
*colon = 0;
}
const char *arg = strstr (instr, "0x");
ut64 n = 0;
if (arg) {
n = r_num_get (NULL, arg);
}
if (r_str_startswith (instr, "invalid") || !strcmp (instr, "illegal")) {
R_FREE (instr);
op->type = R_ANAL_OP_TYPE_ILL;
op->size = 4;
if (mask & R_ARCH_OP_MASK_DISASM) {
op->mnemonic = strdup ("invalid");
}
free (instr);
return false;
}
if (!strcmp (instr, "nop") || !strcmp (instr, "mnop")) {
op->type = R_ANAL_OP_TYPE_NOP;
} else if (r_str_startswith (instr, "if ")) {
op->type = R_ANAL_OP_TYPE_CJMP;
op->jump = n;
op->fail = op->addr + 2;
} else if (r_str_startswith (instr, "rts")) {
op->type = R_ANAL_OP_TYPE_RET;
} else if (r_str_startswith (instr, "call ")) {
op->type = R_ANAL_OP_TYPE_CALL;
op->jump = n;
op->fail = op->addr + 2;
} else if (r_str_startswith (instr, "j")) {
op->type = R_ANAL_OP_TYPE_JMP;
op->jump = n;
} else if (strstr (instr, " = [")) {
op->type = R_ANAL_OP_TYPE_LOAD;
} else if (strstr (instr, "] = ")) {
op->type = R_ANAL_OP_TYPE_STORE;
} else if (strstr (instr, ">>>")) {
op->type = R_ANAL_OP_TYPE_ROR;
op->val = n;
} else if (strstr (instr, ">>=")) {
op->type = R_ANAL_OP_TYPE_SHR;
op->val = n;
} else if (strstr (instr, "<<<")) {
op->type = R_ANAL_OP_TYPE_ROL;
op->val = n;
} else if (strstr (instr, "<<=")) {
op->type = R_ANAL_OP_TYPE_SHL;
op->val = n;
} else if (strstr (instr, "=")) {
op->type = R_ANAL_OP_TYPE_MOV;
op->val = n;
}
}
if (mask & R_ARCH_OP_MASK_DISASM) {
if (op->size > 0) {
op->mnemonic = instr? instr: strdup ("");
r_str_replace_char (op->mnemonic, '\t', ' ');
} else {
free (instr);
op->mnemonic = strdup ("(data)");
}
} else {
free (instr);
}
return true;
}
#if 0
REG_R0, REG_R1, REG_R2, REG_R3, REG_R4, REG_R5, REG_R6, REG_R7,
REG_P0, REG_P1, REG_P2, REG_P3, REG_P4, REG_P5, REG_SP, REG_FP,
REG_I0, REG_I1, REG_I2, REG_I3, REG_M0, REG_M1, REG_M2, REG_M3,
REG_B0, REG_B1, REG_B2, REG_B3, REG_L0, REG_L1, REG_L2, REG_L3,
REG_A0x, REG_A0w, REG_A1x, REG_A1w, REG_LASTREG, REG_LASTREG, REG_ASTAT, REG_RETS,
REG_LASTREG, REG_LASTREG, REG_LASTREG, REG_LASTREG, REG_LASTREG, REG_LASTREG, REG_LASTREG, REG_LASTREG,
REG_LC0, REG_LT0, REG_LB0, REG_LC1, REG_LT1, REG_LB1, REG_CYCLES, REG_CYCLES2,
REG_USP, REG_SEQSTAT, REG_SYSCFG, REG_RETI, REG_RETX, REG_RETN, REG_RETE, REG_EMUDAT,
REG_LASTREG,
#endif
static char *getregs(RArchSession *as) {
const char *const p =
"=PC pc\n"
"=SP sp\n"
"=BP fp\n"
"=A0 r0\n"
"=A1 r1\n"
"=A2 r2\n"
"=A3 r3\n"
"=SN r0\n"
"=R0 r0\n"
"=R1 r1\n"
"gpr r0 .32 0 0\n"
"gpr r1 .32 8 0\n"
"gpr r2 .32 16 0\n"
"gpr r3 .32 24 0\n"
"gpr r4 .32 32 0\n"
"gpr r5 .32 40 0\n"
"gpr r6 .32 48 0\n"
"gpr r7 .32 56 0\n"
"gpr p0 .32 64 0\n"
"gpr p1 .32 72 0\n"
"gpr p2 .32 80 0\n"
"gpr p3 .32 88 0\n"
"gpr p4 .32 96 0\n"
"gpr p5 .32 104 0\n"
"gpr sp .32 112 0\n"
"gpr fp .32 120 0\n"
"gpr i0 .32 128 0\n"
"gpr i1 .32 136 0\n"
"gpr i2 .32 144 0\n"
"gpr i3 .32 152 0\n"
"gpr m0 .32 160 0\n"
"gpr m1 .32 168 0\n"
"gpr m2 .32 176 0\n"
"gpr m3 .32 184 0\n"
"gpr b0 .32 192 0\n"
"gpr b1 .32 200 0\n"
"gpr b2 .32 208 0\n"
"gpr b3 .32 216 0\n"
"gpr l0 .32 224 0\n"
"gpr l1 .32 232 0\n"
"gpr l2 .32 240 0\n"
"gpr l3 .32 248 0\n"
"gpr pc .32 256 0\n";
return strdup (p);
}
static int info(RArchSession *s, ut32 q) {
switch (q) {
#if R2_VERSION_NUMBER >= 50909
case R_ARCH_INFO_MINOP_SIZE:
return 2;
case R_ARCH_INFO_MAXOP_SIZE:
return 4;
}
#else
case R_ARCH_INFO_MIN_OP_SIZE:
return 2;
case R_ARCH_INFO_MAX_OP_SIZE:
return 4;
}
#endif
// i think data align is 4
return 2;
}
static RList *preludes(RArchSession *as) {
RList *l = r_list_newf (free);
// must be aligned to 4 i think
r_list_append (l, r_str_newf ("00 e8"));
return l;
}
RArchPlugin r_arch_plugin_blackfin = {
.meta = {
.name = "blackfin",
.desc = "BlackFIN architecture plugin",
.author = "pancake",
.version = "0.2",
.license = "GPL-3.0-only",
.status = R_PLUGIN_STATUS_OK,
},
.arch = "blackfin",
.bits = R_SYS_BITS_PACK1 (32),
.endian = R_SYS_ENDIAN_LITTLE,
.info = &info,
.regs = getregs,
.preludes = preludes,
.encode = &encode,
.decode = &decode
};
#ifndef R2_PLUGIN_INCORE
R_API RLibStruct radare_plugin = {
.type = R_LIB_TYPE_ARCH,
.data = &r_arch_plugin_blackfin,
.version = R2_VERSION
};
#endif
Loaded 100 of 449 files, more files were not shown because too many files have changed in this diff. Show more