mirror of
https://github.com/radareorg/radare2-extras.git
synced 2026-11-11 04:11:24 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
73960d34df | ||
|
|
2afaceab6a | ||
|
|
a29ce917c1 | ||
|
|
8c738204dd | ||
|
|
031b077f2c | ||
|
|
2a44edead6 | ||
|
|
ee031a7021 | ||
|
|
0a0327aa45 | ||
|
|
9870775224 | ||
|
|
d5e7a28186 | ||
|
|
c9571534b9 | ||
|
|
5fff0016a3 | ||
|
|
f2199032a7 | ||
|
|
5d28dc6de4 | ||
|
|
645f4154ff | ||
|
|
899e3344ff | ||
|
|
6493987c72 | ||
|
|
ba096f3546 | ||
|
|
bfab794507 | ||
|
|
619f60a7df | ||
|
|
f4f11b90c3 | ||
|
|
f58de93399 | ||
|
|
58a5ac18e6 | ||
|
|
9b0adabca8 | ||
|
|
219b1f7c07 | ||
|
|
a1b8861f9d | ||
|
|
85f40b5d6c | ||
|
|
a8d4a6a520 | ||
|
|
e108f90f79 | ||
|
|
5b9a32f8c4 | ||
|
|
71ab77c46b | ||
|
|
b6da363492 | ||
|
|
4932f31af9 | ||
|
|
cdd0753019 | ||
|
|
8b98f544d7 | ||
|
|
4ad1a62408 | ||
|
|
39458c3b5b | ||
|
|
b07fcf44b1 | ||
|
|
58536ef4e9 | ||
|
|
3dfb0180d0 | ||
|
|
73831a1ee2 | ||
|
|
68e9f6dfe3 | ||
|
|
2c54fda563 | ||
|
|
a0ccecf534 | ||
|
|
e94cc3060d | ||
|
|
ac1af9c612 | ||
|
|
94bccea25c | ||
|
|
3f8dada173 | ||
|
|
a21d29689b | ||
|
|
099cb94abf | ||
|
|
de674fbeb0 | ||
|
|
f81d48eaca | ||
|
|
610dd48707 | ||
|
|
c6663b87e9 | ||
|
|
f7dca9d52b | ||
|
|
f2a4b1dfa0 | ||
|
|
b5b1101110 | ||
|
|
445c6a5a57 | ||
|
|
5ab2c6aa7d | ||
|
|
1e989215d9 | ||
|
|
a2692a2380 | ||
|
|
614d94959e | ||
|
|
7a0269097b | ||
|
|
c8f032c01d | ||
|
|
188d102f6b | ||
|
|
3275d32127 | ||
|
|
f4218097d2 | ||
|
|
96dbf53b1c | ||
|
|
e3111fcba3 | ||
|
|
5b0ea473f9 | ||
|
|
f28a2ec94c | ||
|
|
80925aeba6 | ||
|
|
45f9bc841c | ||
|
|
69f93467a1 | ||
|
|
67b24be239 | ||
|
|
cd9cc5c190 | ||
|
|
568a7fd146 | ||
|
|
d276feb5e8 | ||
|
|
c3b9864f1d | ||
|
|
7a6e3737c8 | ||
|
|
430b6fa559 | ||
|
|
1cf58513ad | ||
|
|
da8623bdbe | ||
|
|
43057468c6 | ||
|
|
7ed4cb393f | ||
|
|
031b7c20c0 | ||
|
|
9edd5e922b | ||
|
|
dea1f62f8f | ||
|
|
e9306ef9fe | ||
|
|
941e0e8f81 | ||
|
|
fdcf847944 | ||
|
|
e9035eda1c | ||
|
|
f2d4e0d371 | ||
|
|
f06bef6f21 | ||
|
|
aac87e940d | ||
|
|
6c0afb35c2 | ||
|
|
1b276095d4 | ||
|
|
e90d99b9f4 | ||
|
|
e0bb03cdd1 | ||
|
|
6c9df38c66 | ||
|
|
38e79b50b1 | ||
|
|
b03125fc99 | ||
|
|
36f9503eda | ||
|
|
3a25b7f345 | ||
|
|
b91c295be3 | ||
|
|
9e4c70872e | ||
|
|
94f8d2dc94 | ||
|
|
89624cc37c | ||
|
|
42aed83113 | ||
|
|
4d944cce9a | ||
|
|
49a91651d2 | ||
|
|
3596e7f1a5 | ||
|
|
54ff412976 | ||
|
|
3d2fa7985b | ||
|
|
3064bbcb7f | ||
|
|
97d8b87bf5 | ||
|
|
26450ea9b9 | ||
|
|
14d385082c | ||
|
|
3a92956545 | ||
|
|
5ef0b34d57 | ||
|
|
57f3c159e0 | ||
|
|
991ee0f685 | ||
|
|
4e72a04103 | ||
|
|
9a61bb6f7d | ||
|
|
9c22aa709d | ||
|
|
ccefb4237d | ||
|
|
ef93ab4c91 | ||
|
|
496b46918b | ||
|
|
82b3a8e97d | ||
|
|
0350bec1e7 | ||
|
|
6e06bcd365 | ||
|
|
b170500a27 | ||
|
|
ece2da866a | ||
|
|
fecf53943b | ||
|
|
dda5cb2d70 | ||
|
|
ebe772353a | ||
|
|
d6f4f63aca | ||
|
|
343dce1014 | ||
|
|
3bb3fbf753 | ||
|
|
42131f6bd6 | ||
|
|
663b25a8fc | ||
|
|
b0f48b0194 | ||
|
|
6e4ece2732 | ||
|
|
628a9d20d0 | ||
|
|
315256b0ef | ||
|
|
eef6f4a39f | ||
|
|
306cc36d80 | ||
|
|
39f897acfe | ||
|
|
33c681dadf | ||
|
|
fd6d8979ea | ||
|
|
167e5c48b2 | ||
|
|
82d0276127 | ||
|
|
d9273fc53e | ||
|
|
26d8b75ffe | ||
|
|
fc38eb7862 | ||
|
|
da11f75c73 | ||
|
|
7be547f648 | ||
|
|
31fba0eafd | ||
|
|
77269480b3 | ||
|
|
8903ddf7ef | ||
|
|
a88eecf962 | ||
|
|
f912df64a2 | ||
|
|
6dd7921729 | ||
|
|
ae05525a78 | ||
|
|
78f4e70ca7 | ||
|
|
ec94bfcd50 | ||
|
|
6de9a49e88 | ||
|
|
a36564eaa9 | ||
|
|
ccc7d46e92 | ||
|
|
6c21ca2a7d | ||
|
|
adf9e7aca8 | ||
|
|
d1f90741b0 | ||
|
|
bb15dc4562 | ||
|
|
90567f4c80 | ||
|
|
e8d1cb20b2 | ||
|
|
98e6d29133 | ||
|
|
e5ef780da8 | ||
|
|
6f8c8f0836 | ||
|
|
c28cf25f7a | ||
|
|
6a7a636ebe | ||
|
|
e3b6897bda | ||
|
|
209c82d674 | ||
|
|
e68f98a223 | ||
|
|
84aa166231 | ||
|
|
a005f0402b | ||
|
|
1a1e68a882 | ||
|
|
68a8e3d4e5 | ||
|
|
7d6afc0855 | ||
|
|
a0fd4013b0 | ||
|
|
dd78a53a1a | ||
|
|
5a13ac3032 | ||
|
|
d3fe9b7223 | ||
|
|
90b782e683 | ||
|
|
36feb1733c | ||
|
|
0fd38b8121 | ||
|
|
229188050e | ||
|
|
31a841c561 | ||
|
|
5469876cfa | ||
|
|
8c90086fc2 | ||
|
|
82734d3371 | ||
|
|
edeadec44c | ||
|
|
d5a88f6b41 | ||
|
|
4f67e1af9a | ||
|
|
e1ace49642 | ||
|
|
046db11e95 | ||
|
|
e1edea1405 | ||
|
|
a5a042cecc | ||
|
|
d91308a818 | ||
|
|
bb205b2607 | ||
|
|
3636cc53ff | ||
|
|
b652ff1305 | ||
|
|
e50cfcc008 | ||
|
|
7044515214 | ||
|
|
1c83c693ba | ||
|
|
d3f44531c7 | ||
|
|
9a2cd79b6c | ||
|
|
44ae4f46c5 | ||
|
|
296ff27e42 | ||
|
|
400d67c472 | ||
|
|
01ef784858 | ||
|
|
8a2c686105 | ||
|
|
d12ef02a13 | ||
|
|
3fcb7ecf9b | ||
|
|
e7c8f4e7e5 | ||
|
|
848a1b2eeb | ||
|
|
1947df56fd | ||
|
|
c12d4badff | ||
|
|
fd3871893a | ||
|
|
0a7590f748 | ||
|
|
9ae0981f5a | ||
|
|
bdb04b54fa | ||
|
|
1318082a67 | ||
|
|
e72b5010c8 | ||
|
|
9b5b0013f9 | ||
|
|
c4b7f76081 | ||
|
|
71eb56d619 | ||
|
|
d3911fa5a5 | ||
|
|
5cf30b4af2 | ||
|
|
0b983e477e | ||
|
|
822a45ab18 | ||
|
|
cd4e396bcd | ||
|
|
22f196cecc | ||
|
|
f8dea3b7e2 | ||
|
|
3a7484b467 | ||
|
|
4901c49c4e | ||
|
|
90765cc641 | ||
|
|
f665a9eb11 | ||
|
|
e0a8b8b3e3 | ||
|
|
3584dee33b | ||
|
|
0c113bdea8 | ||
|
|
23fc638c27 | ||
|
|
7d67e6343d | ||
|
|
ad95329c1e | ||
|
|
d10a5257cd | ||
|
|
9896414afb | ||
|
|
a599c6c2d6 | ||
|
|
ba754bed7b | ||
|
|
a745e3cd65 | ||
|
|
4235786fab | ||
|
|
6fc39af6e2 | ||
|
|
6a0781ab3f | ||
|
|
c31f8fb226 | ||
|
|
831b8579ee | ||
|
|
6bd03e5642 | ||
|
|
77c8e95061 | ||
|
|
730aff1b19 | ||
|
|
eba95758d2 | ||
|
|
9836aa3b73 | ||
|
|
ab97757ada | ||
|
|
ad856dee2d | ||
|
|
07c8150329 | ||
|
|
913874da41 | ||
|
|
75a4f63391 | ||
|
|
d834af469c | ||
|
|
7e0235ea45 | ||
|
|
e49a1bb2e3 | ||
|
|
c563cdd8f8 | ||
|
|
bb4a2bdb6d | ||
|
|
97070385b4 | ||
|
|
18d26928e6 | ||
|
|
5baebd4620 |
No files matched your search
@@ -0,0 +1,6 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "cargo"
|
||||
directory: "/x86iced"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
+19
-37
@@ -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"
|
||||
@@ -17,6 +17,7 @@
|
||||
*.swo
|
||||
*.un~
|
||||
/Makefile
|
||||
r2yara/Makefile
|
||||
/options.mk
|
||||
|
||||
# misc
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
radare2-extras
|
||||
==============
|
||||
# radare2-extras
|
||||
|
||||
[](https://github.com/radareorg/radare2-extras/actions?query=workflow%3A%22ci%22)|
|
||||
[](https://github.com/radareorg/radare2-extras/actions?query=workflow%3A%22ci%22)
|
||||
[](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.
|
||||
@@ -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)
|
||||
@@ -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"
|
||||
@@ -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
@@ -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
@@ -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)
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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) {
|
||||
|
||||
@@ -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
@@ -1,5 +1,5 @@
|
||||
PKGNAME radare2-extras
|
||||
VERSION 5.8.0
|
||||
VERSION 6.0.0
|
||||
CONTACT pancake ; [email protected]
|
||||
|
||||
USE_PKGCONFIG!
|
||||
|
||||
@@ -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
|
||||
@@ -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()
|
||||
}
|
||||
```
|
||||
@@ -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
@@ -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
@@ -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()
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
@@ -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
@@ -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
|
||||
}
|
||||
Executable
BIN
Binary file not shown.
@@ -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;
|
||||
}
|
||||
Executable
BIN
Binary file not shown.
@@ -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
@@ -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
|
||||
Executable
+34
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
Vendored
+44
-15
@@ -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
@@ -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;
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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}
|
||||
@@ -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)
|
||||
@@ -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
|
||||
@@ -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.
@@ -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;
|
||||
|
||||
@@ -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}
|
||||
@@ -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.
@@ -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
@@ -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)
|
||||
|
||||
+974
-730
File diff suppressed because it is too large.
Load diff
@@ -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
|
||||
@@ -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 */
|
||||
@@ -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) */
|
||||
@@ -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.......|
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
@@ -0,0 +1,10 @@
|
||||
# build artifacts
|
||||
*.o
|
||||
*.dylib
|
||||
*.so
|
||||
*.a
|
||||
|
||||
# editor / assistant caches
|
||||
.pmai/
|
||||
.DS_Store
|
||||
build/
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
@@ -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"
|
||||
@@ -0,0 +1,5 @@
|
||||
/* radare - LGPL - Copyright 2026 - pancake */
|
||||
|
||||
#ifdef R2_ARCH_H
|
||||
extern RArchPlugin r_arch_plugin_vc4;
|
||||
#endif
|
||||
@@ -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)
|
||||
@@ -0,0 +1,5 @@
|
||||
/* radare - LGPL - Copyright 2026 - pancake */
|
||||
|
||||
#ifdef R2_ASM_H
|
||||
extern RAsmPlugin r_asm_plugin_vc4;
|
||||
#endif
|
||||
@@ -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)
|
||||
@@ -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
|
||||
@@ -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')
|
||||
@@ -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
|
||||
@@ -0,0 +1,2 @@
|
||||
arch.vc4
|
||||
asm.vc4
|
||||
+1347
-52
File diff suppressed because it is too large.
Load diff
+52977
-655
File diff suppressed because it is too large.
Load diff
+128
-32
@@ -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[];
|
||||
|
||||
|
||||
+825
-88
File diff suppressed because it is too large.
Load diff
+1378
-47
File diff suppressed because it is too large.
Load diff
+68136
-870
File diff suppressed because it is too large.
Load diff
+2702
-37
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
+2
-2
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
Reference in new issue
Block a user