mirror of
https://github.com/radareorg/radare2-extras.git
synced 2026-11-07 17:48:16 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
d034b2769a | ||
|
|
0cea6e28e4 | ||
|
|
9689796965 | ||
|
|
8fe16da993 | ||
|
|
52439a5845 | ||
|
|
e27b7bfe3c | ||
|
|
9962027deb | ||
|
|
79bf9fa5ba | ||
|
|
b74faa00f2 | ||
|
|
88a5de0331 | ||
|
|
fe805b5781 | ||
|
|
33cc031b38 | ||
|
|
39d6a3e9c9 | ||
|
|
5cda6a599e | ||
|
|
245716be19 | ||
|
|
f8137fd314 | ||
|
|
fe4e54b50e | ||
|
|
790c02b9ce | ||
|
|
acbb8a7c0f | ||
|
|
b557dc24a0 | ||
|
|
c4594ce486 | ||
|
|
40a6d34bea | ||
|
|
38e369a367 | ||
|
|
af3214df2c | ||
|
|
88aaebc6ee | ||
|
|
9d82adef43 | ||
|
|
4779456cd6 | ||
|
|
4a795e0b30 | ||
|
|
bec354d82c | ||
|
|
0ab8603f0c | ||
|
|
d5add35cd5 | ||
|
|
15b05687ae | ||
|
|
14f68e9388 | ||
|
|
a4f8842bd8 | ||
|
|
55cc028778 | ||
|
|
baa29e633a | ||
|
|
165b565eb2 | ||
|
|
053f774462 | ||
|
|
002b26d5e9 | ||
|
|
2dd9a63faa | ||
|
|
5af97a31d2 | ||
|
|
e8099c7b14 | ||
|
|
5a78bcb402 | ||
|
|
8a0da3c5b7 | ||
|
|
ed8e9d96d7 | ||
|
|
a1bc103782 | ||
|
|
c56286efdb | ||
|
|
adb999852e | ||
|
|
3254c72bc6 | ||
|
|
575bfec497 | ||
|
|
6a3d97082b | ||
|
|
5c172dcb55 | ||
|
|
64b81544bd | ||
|
|
caee604777 | ||
|
|
71c938d827 | ||
|
|
5c9126d2d8 | ||
|
|
df747eba95 | ||
|
|
b50ce706ea | ||
|
|
2eb8d24357 | ||
|
|
3f0adee8a9 | ||
|
|
283554e8fd | ||
|
|
45d4483161 | ||
|
|
e30d193d28 | ||
|
|
e8c9895354 | ||
|
|
b5b7ddf7c5 | ||
|
|
83bcd0ef38 | ||
|
|
ea07e3fc43 | ||
|
|
e158c1bbdc | ||
|
|
679046a6c0 | ||
|
|
1d9f052001 | ||
|
|
bdb9416300 | ||
|
|
158169099e | ||
|
|
a4c71ac354 | ||
|
|
2aee0cb6d8 | ||
|
|
903bbe6c70 | ||
|
|
5db084ce75 | ||
|
|
b49e51aefb | ||
|
|
393d2f573a | ||
|
|
5efc8aac3c | ||
|
|
4d44a7abea | ||
|
|
25e895800e | ||
|
|
eea5e126ae | ||
|
|
9e30411db8 | ||
|
|
0b1bc17ec4 | ||
|
|
f5763dcae7 | ||
|
|
035c0ff594 | ||
|
|
32152f2ec2 | ||
|
|
b44d25e0e2 | ||
|
|
e25b59fe2e | ||
|
|
ac57ab34a7 | ||
|
|
24072c986e | ||
|
|
5877128009 | ||
|
|
29894cabdc | ||
|
|
eb27602a8e | ||
|
|
5b020c3796 | ||
|
|
457a8bf1ea | ||
|
|
f2b8a6aa40 | ||
|
|
0a09545ce0 | ||
|
|
3b29d305ab | ||
|
|
184a769b90 | ||
|
|
5a14def4af | ||
|
|
c8cb79e175 | ||
|
|
e40dd90bb9 | ||
|
|
ae8872e121 | ||
|
|
1943c6793a | ||
|
|
d3faa7e8a6 | ||
|
|
7c0287d0e7 | ||
|
|
ef6b08214f | ||
|
|
6ec77c12b6 | ||
|
|
644ee622c5 | ||
|
|
34719628b9 |
No files matched your search
@@ -0,0 +1,6 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "cargo"
|
||||
directory: "/x86iced"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
+25
-25
@@ -10,47 +10,47 @@ jobs:
|
||||
|
||||
build-extras:
|
||||
name: Build radare2 extras and r2pipe
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-22.04
|
||||
env:
|
||||
TESTS: 'armthumb atombios baleful bcl ba2 blackfin blessr2 keystone-lib keystone lang-duktape mc6809 microblaze msil pcap ppcdisasm psosvm swf unicorn-lib unicorn vc4 x86udis x86bea x86tab x86olly x86zyan z80-nc'
|
||||
R2PIPE_TESTS: 'r2pipe-go r2pipe-js r2pipe-py'
|
||||
EXTERNAL_BUILDS: 'keystone-lib unicorn-lib'
|
||||
LOCAL_BUILDS: 'asahi blackfin blessr2 keystone microblaze ppcdisasm r2svd vc4 x86iced'
|
||||
TESTS: 'keystone vc4'
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
repository: zamaudio/radare2
|
||||
ref: r2pm-gitmaster
|
||||
repository: radareorg/radare2
|
||||
ref: master
|
||||
path: ./radare2
|
||||
- name: Install dependencies
|
||||
run: sudo apt-get --assume-yes install wget unzip python3-wheel python3-setuptools build-essential python3-pip && 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=./
|
||||
export R2PM_GITMASTER=`cd radare2-extras; git describe --always --all`
|
||||
for p in $TESTS ; do
|
||||
for p in $EXTERNAL_BUILDS ; do
|
||||
echo $p
|
||||
r2pm -i $p
|
||||
done
|
||||
set +e
|
||||
- name: Compile and install r2pipe
|
||||
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
|
||||
- name: Test plugins
|
||||
working-directory: radare2/test
|
||||
run: |
|
||||
set -e
|
||||
export R2PM_GITDIR=./
|
||||
export R2PM_GITMASTER=`cd radare2-extras; git describe --always --all`
|
||||
for p in $R2PIPE_TESTS ; do
|
||||
for p in $TESTS ; do
|
||||
echo $p
|
||||
r2pm -i $p
|
||||
make $p
|
||||
done
|
||||
r2r -u "$GITHUB_WORKSPACE/radare2-extras/test/db/extras/microblaze"
|
||||
r2r -u "$GITHUB_WORKSPACE/radare2-extras/test/db/extras/ppcdisasm"
|
||||
set +e
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
name: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "master" ]
|
||||
pull_request:
|
||||
branches: [ "master" ]
|
||||
schedule:
|
||||
- cron: "30 16 * * 1"
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
actions: read
|
||||
contents: read
|
||||
security-events: write
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
language: [ javascript, python ]
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
queries: +security-and-quality
|
||||
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v2
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
with:
|
||||
category: "/language:${{ matrix.language }}"
|
||||
@@ -17,6 +17,7 @@
|
||||
*.swo
|
||||
*.un~
|
||||
/Makefile
|
||||
r2yara/Makefile
|
||||
/options.mk
|
||||
|
||||
# misc
|
||||
|
||||
-118
@@ -1,118 +0,0 @@
|
||||
dist:
|
||||
- trusty
|
||||
sudo:
|
||||
- false
|
||||
os:
|
||||
- linux
|
||||
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- gcc-7
|
||||
- llvm-dev
|
||||
- libatomic-ops-dev
|
||||
- mono-xbuild
|
||||
- curl
|
||||
- make
|
||||
- tcc
|
||||
- libboost-dev
|
||||
- libqt4-dev
|
||||
- cmake
|
||||
- cmake-data
|
||||
- ninja-build
|
||||
- libboost-dev
|
||||
- libqt4-dev
|
||||
- exuberant-ctags
|
||||
- libelf-dev
|
||||
- libgmp-dev
|
||||
- zlib1g-dev
|
||||
- swig
|
||||
env:
|
||||
- TESTS="r2pm -i armthumb"
|
||||
- TESTS="r2pm -i baleful"
|
||||
- TESTS="r2pm -i bcl"
|
||||
- TESTS="r2pm -i ba2"
|
||||
- TESTS="r2pm -i blackfin"
|
||||
- TESTS="r2pm -i blessr2"
|
||||
# - TESTS="r2pm -i bpf" [BR] https://travis-ci.org/radareorg/radare2-extras/builds/157522362
|
||||
# - TESTS="r2pm -i dlang" [BR] https://travis-ci.org/radareorg/radare2-extras/builds/157522362
|
||||
# ONLY FOR LINUX - TESTS="r2pm -i dirtycow"
|
||||
- TESTS="r2pm -i lang-duktape"
|
||||
# - TESTS="git clone git://git.code.sf.net/p/libdwarf/code libdwarf-code && cd libdwarf-code && ./configure && make && cd .. && r2pm -i dwarf-parser && cd radare2-regressions && ./r2r dwarf && cd .. && r2pm -u libdwarf && rm -rf libdwarf-code" #need to remove libdwarf? or travis destroys the vm so no issue in that?
|
||||
# - TESTS="r2pm -i r2frida"
|
||||
# - TESTS="r2pm -i io-ewf" # https://github.com/travis-ci/apt-package-whitelist/issues/3205
|
||||
# - TESTS="r2pm -i keystone-lib && r2pm -i keystone && cd radare2-regressions && make keystone && cd .." [BR] https://travis-ci.org/radareorg/radare2-extras/builds/157522362
|
||||
- TESTS="r2pm -i mc6809"
|
||||
- TESTS="r2pm -i microblaze && cd radare2/test && make microblaze && cd ../.."
|
||||
- TESTS="r2pm -i msil"
|
||||
- TESTS="r2pm -i nios"
|
||||
- TESTS="r2pm -i pcap"
|
||||
- TESTS="r2pm -i ppcdisasm"
|
||||
- TESTS="r2pm -i psosvm"
|
||||
# - TESTS="r2pm -i vala && r2pm -i valabind && r2pm -i r2api-python" [BR] https://travis-ci.org/radareorg/radare2-extras/builds/387043680
|
||||
# - TESTS="r2pm -i r2pipe-cs" [BR] https://travis-ci.org/radareorg/radare2-extras/builds/157522362
|
||||
# - TESTS="r2pm -i r2pipe-go" [BR] https://travis-ci.org/radareorg/radare2-extras/builds/387043680
|
||||
- TESTS="r2pm -i r2pipe-js"
|
||||
- TESTS="r2pm -i r2pipe-py"
|
||||
- TESTS="r2pm -i r2pipe-rb"
|
||||
# - TESTS="r2pm -i r2pipe-vala" https://travis-ci.org/radareorg/radare2-extras/builds/157522362
|
||||
- TESTS="r2pm -i radare2"
|
||||
# - TESTS="r2pm -i r2snow" https://travis-ci.org/radareorg/radare2-extras/jobs/199500082
|
||||
# - TESTS="r2pm -i radeco" [BR] https://travis-ci.org/radare/radare2-extras/builds/157522362
|
||||
# - TESTS="r2pm -i retdec"
|
||||
- TESTS="r2pm -i swf && make -C radare2/test swf"
|
||||
# - TESTS="r2pm -i m68k-net && cd radare2-regressions && make m68k-extras && cd .." [BR] https://travis-ci.org/radare/radare2-extras/builds/387043680
|
||||
# - TESTS="r2pm -i swig" Sorry. This package cannot be installed in your home.
|
||||
- TESTS="r2pm -i syms2elf"
|
||||
# - TESTS="r2pm -i tcc" [BR] https://travis-ci.org/radare/radare2-extras/builds/157522362
|
||||
- TESTS="r2pm -i unicorn-lib && r2pm -i unicorn" # need to do this properly
|
||||
- TESTS="r2pm -i vala"
|
||||
# - TESTS="r2pm -i valabind" [BR] https://travis-ci.org/radare/radare2-extras/builds/387043680
|
||||
# - TESTS="r2pm -i vapi" [BR] https://travis-ci.org/radare/radare2-extras/builds/387043680
|
||||
- TESTS="r2pm -i vc4"
|
||||
- TESTS="r2pm -i winapi"
|
||||
- TESTS="r2pm -i www-enyo"
|
||||
# - TESTS="r2pm -i www-m" [BR] https://travis-ci.org/radare/radare2-extras/builds/157522362
|
||||
- TESTS="r2pm -i www-p"
|
||||
- TESTS="r2pm -i www-t"
|
||||
- TESTS="r2pm -i x86udis"
|
||||
- TESTS="r2pm -i x86bea"
|
||||
- TESTS="r2pm -i x86tab"
|
||||
- TESTS="r2pm -i x86olly && cd radare2/test && make olly-extras && cd ../.."
|
||||
- TESTS="r2pm -i z80-nc"
|
||||
- TESTS="r2pm -i yara && r2pm -i yara-r2 && cd radare2/test && make yara && cd ../.."
|
||||
- TESTS="r2pm -i x86zyan"
|
||||
language:
|
||||
- rust
|
||||
rust:
|
||||
- stable
|
||||
cache:
|
||||
- ccache
|
||||
- apt
|
||||
|
||||
before_script:
|
||||
- export WORKING_DIR=${TRAVIS_BUILD_DIR}/..
|
||||
- cd ${WORKING_DIR}
|
||||
- rm -rf ~/.nvm && git clone https://github.com/creationix/nvm.git ~/.nvm && (cd ~/.nvm && git checkout `git describe --abbrev=0 --tags`) && source ~/.nvm/nvm.sh && nvm install 10
|
||||
- git clone https://github.com/radareorg/radare2 && cd radare2
|
||||
- export CC=gcc-7
|
||||
- ./configure --prefix=${WORKING_DIR}/install > /dev/null
|
||||
- make -s -j2 > /dev/null
|
||||
- make install > /dev/null
|
||||
- cd ..
|
||||
- export PATH=${WORKING_DIR}/install/bin:${PATH}
|
||||
- export LD_LIBRARY_PATH=${WORKING_DIR}/install/lib:${LD_LIBRARY_PATH}
|
||||
- export LIBR_INCLUDE=${WORKING_DIR}/radare2/libr/include
|
||||
- export LIBR_UTIL=${WORKING_DIR}/radare2/libr/util
|
||||
- export PKG_CONFIG_PATH=${WORKING_DIR}/radare2/pkgcfg
|
||||
- export GOPATH=${WORKING_DIR}/
|
||||
- r2pm init
|
||||
- export R2PM_GITDIR=${WORKING_DIR}
|
||||
- cd radare2-extras
|
||||
- ./configure --prefix=${WORKING_DIR}/install
|
||||
- cd ..
|
||||
|
||||
script:
|
||||
- eval $TESTS
|
||||
+6
-2
@@ -12,9 +12,10 @@ DIRS+=libr/anal/p
|
||||
endif
|
||||
|
||||
help:
|
||||
@echo "Usage make [target] .. Targets:"
|
||||
@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)"
|
||||
@@ -24,9 +25,10 @@ help:
|
||||
@echo " (target)-install - install given plugin"
|
||||
@echo " (target)-clean - clean given plugin"
|
||||
|
||||
|
||||
# @echo " install-yara{2,3} - install Yara 2 or 3 from Git"
|
||||
|
||||
afen:
|
||||
$(MAKE) -C afen
|
||||
baleful:
|
||||
$(MAKE) -C baleful
|
||||
debug unicorn:
|
||||
@@ -54,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,5 +1,8 @@
|
||||
radare2-extras [](https://travis-ci.org/radareorg/radare2-extras)
|
||||
==============
|
||||
# radare2-extras
|
||||
|
||||
[](https://github.com/radareorg/radare2-extras/actions?query=workflow%3A%22ci%22)
|
||||
[](https://github.com/radareorg/radare2)
|
||||
|
||||
This repository contains extra plugins for radare2.
|
||||
|
||||
The reasons why those plugins are distributed in a separate
|
||||
@@ -12,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.
|
||||
|
||||
@@ -27,10 +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-pm repository for details:
|
||||
is to use r2pm. See the [radare2 plugins](https://github.com/radareorg/radare2#plugins) documentation for details.
|
||||
|
||||
https://github.com/radareorg/radare2-pm
|
||||
## 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
|
||||
@@ -0,0 +1,22 @@
|
||||
R2_LIBEXT=$(shell r2 -H R2_LIBEXT)
|
||||
R2_USER_PLUGINS=$(shell r2 -H R2_USER_PLUGINS)
|
||||
|
||||
CFLAGS+=$(shell pkg-config --cflags r_core)
|
||||
LDFLAGS+=$(shell pkg-config --libs r_core)
|
||||
CFLAGS+=-Igpu/wrap
|
||||
|
||||
all: gpu
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -shared -fPIC arch_asahi.c -o arch_asahi.$(R2_LIBEXT)
|
||||
|
||||
mrproper clean:
|
||||
rm -f *.$(R2_LIBEXT)
|
||||
|
||||
gpu:
|
||||
git clone https://github.com/AsahiLinux/gpu
|
||||
|
||||
install:
|
||||
mkdir -p "$(R2_USER_PLUGINS)"
|
||||
cp -f arch_asahi.$(R2_LIBEXT) $(R2_USER_PLUGINS)
|
||||
|
||||
uninstall:
|
||||
rm -f $(R2_USER_PLUGINS)/arch_asahi.$(R2_LIBEXT)
|
||||
@@ -0,0 +1,14 @@
|
||||
ASAHI
|
||||
=====
|
||||
|
||||
This is the r2 disassembler plugin for
|
||||
the ASAHI GPU shipped in the Apple M1.
|
||||
|
||||
This plugin is just a shim on top of [AsahiLinux](https://github.com/AsahiLinux/gpu)
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
* Install r2 from git and then type `make; make install`
|
||||
|
||||
Alternatively you can just `r2pm -ci asahi`
|
||||
@@ -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
|
||||
|
||||
+30
-1
@@ -5,10 +5,39 @@
|
||||
# git clone https://github.com/radare/acr
|
||||
#
|
||||
# -- pancake
|
||||
#!/bin/sh
|
||||
#
|
||||
# Look for the 'acr' tool here: https://github.com/radare/acr
|
||||
# Clone last version of ACR from here:
|
||||
# git clone https://github.com/radare/acr
|
||||
#
|
||||
# -- pancake
|
||||
|
||||
r2pm -h >/dev/null 2>&1
|
||||
if [ $? = 0 ]; then
|
||||
echo "Installing the last version of 'acr'..."
|
||||
r2pm -i acr > /dev/null
|
||||
r2pm -r acr -h > /dev/null 2>&1
|
||||
if [ $? = 0 ]; then
|
||||
echo "Running 'acr -p'..."
|
||||
r2pm -r acr -p
|
||||
else
|
||||
echo "Cannot find 'acr' in PATH"
|
||||
fi
|
||||
else
|
||||
echo "Running acr..."
|
||||
acr -p
|
||||
fi
|
||||
V=`./configure -qV | cut -d - -f -1`
|
||||
if [ -n "$1" ]; then
|
||||
echo "./configure $*"
|
||||
./configure $*
|
||||
fi
|
||||
|
||||
files=`find . -name configure.acr`
|
||||
for a in ${files}; do
|
||||
echo "[+] $a"
|
||||
( cd `dirname $a` ; acr -p )
|
||||
( cd `dirname $a` ; r2pm -r acr -p )
|
||||
done
|
||||
if [ -n "$1" ]; then
|
||||
echo "./configure $@"
|
||||
|
||||
+17
-33
@@ -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,31 +547,9 @@ 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);
|
||||
}
|
||||
|
||||
RAnalEsilInterruptHandler bale_intr_handler00 = {
|
||||
.num = 0x00, //interrupt number
|
||||
.cb = esil_bale_interrupt_wrapper_cb, //the actual handler
|
||||
};
|
||||
|
||||
RAnalEsilInterruptHandler bale_intr_handler04 = {
|
||||
.num = 0x04, //interrupt number
|
||||
.cb = esil_bale_interrupt_wrapper_cb, //the actual handler
|
||||
};
|
||||
|
||||
RAnalEsilInterruptHandler bale_intr_handler11 = {
|
||||
.num = 0x11, //interrupt number
|
||||
.cb = esil_bale_interrupt_wrapper_cb, //the actual handler
|
||||
};
|
||||
|
||||
RAnalEsilInterruptHandler *bale_intr_handlers[] = {
|
||||
&bale_intr_handler00,
|
||||
&bale_intr_handler04,
|
||||
&bale_intr_handler11,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static int set_reg_profile(RAnal *anal) {
|
||||
const char *p = \
|
||||
"=PC pc\n"
|
||||
@@ -627,7 +608,10 @@ static int esil_baleful_init (RAnalEsil *esil) {
|
||||
if (!esil) {
|
||||
return false;
|
||||
}
|
||||
return r_anal_esil_load_interrupts (esil, bale_intr_handlers, 0);
|
||||
r_anal_esil_set_interrupt(esil,0,esil_bale_interrupt_wrapper_cb, NULL);
|
||||
r_anal_esil_set_interrupt(esil,4,esil_bale_interrupt_wrapper_cb, NULL);
|
||||
r_anal_esil_set_interrupt(esil,11,esil_bale_interrupt_wrapper_cb, NULL);
|
||||
return true;
|
||||
/*
|
||||
internalMemory=malloc(4096);
|
||||
if (!internalMemory) {
|
||||
|
||||
+3
-3
@@ -76,7 +76,7 @@ static int bcl_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *buf, int len,
|
||||
return op->size;
|
||||
}
|
||||
|
||||
static int set_reg_profile(RAnal *anal) {
|
||||
static bool set_reg_profile(RAnal *anal) {
|
||||
const char *p = \
|
||||
"=PC pc\n"
|
||||
"=SP sp\n"
|
||||
@@ -93,7 +93,7 @@ static int set_reg_profile(RAnal *anal) {
|
||||
return r_reg_set_profile_string (anal->reg, p);
|
||||
}
|
||||
|
||||
struct r_anal_plugin_t r_anal_plugin_bcl = {
|
||||
RAnalPlugin r_anal_plugin_bcl = {
|
||||
.name = "bcl",
|
||||
.desc = "Base Call DNA Illumina records",
|
||||
.license = "BSD",
|
||||
@@ -101,7 +101,7 @@ struct r_anal_plugin_t r_anal_plugin_bcl = {
|
||||
.bits = 8,
|
||||
.esil = true,
|
||||
.op = &bcl_op,
|
||||
.set_reg_profile = set_reg_profile,
|
||||
.set_reg_profile = &set_reg_profile
|
||||
};
|
||||
|
||||
#ifndef CORELIB
|
||||
|
||||
+2
-2
@@ -5,7 +5,7 @@
|
||||
#include <r_lib.h>
|
||||
#include <r_bin.h>
|
||||
|
||||
static bool __check_buffer(RBuffer *b) {
|
||||
static bool __check_buffer(RBinFile *bf, RBuffer *b) {
|
||||
ut8 buf[8];
|
||||
int length = r_buf_size (b);
|
||||
int r = r_buf_read_at (b, 0, buf, sizeof (buf));
|
||||
@@ -20,7 +20,7 @@ static bool __check_buffer(RBuffer *b) {
|
||||
}
|
||||
|
||||
static bool load_buffer(RBinFile *bf, void **bin_obj, RBuffer *buf, ut64 loadaddr, Sdb *sdb) {
|
||||
return __check_buffer (buf);
|
||||
return __check_buffer (bf, buf);
|
||||
}
|
||||
|
||||
static ut64 baddr(RBinFile *bf) {
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
R2_PLUGIN_PATH=$(shell r2 -hh|grep LIBR_PLUGINS|awk '{print $$2}')
|
||||
R2_INCLUDE_PATH=$(shell r2 -hh|grep INCDIR|awk '{print $$2}')
|
||||
R2_LIB_PATH=$(shell r2 -hh|grep LIBDIR|awk '{print $$2}')
|
||||
CFLAGS=-g -fPIC
|
||||
CFLAGS+=-I$(R2_INCLUDE_PATH)
|
||||
SUDO=sudo
|
||||
|
||||
LDFLAGS=-shared -L$(R2_LIB_PATH) -lr_util -lr_parse -lr_syscall
|
||||
|
||||
EXT_SO=$(shell r2 -hh|grep LIBEXT|awk '{print $$2}')
|
||||
|
||||
CC_ASM=$(CC) $(CFLAGS) $(LDFLAGS) $(shell pkg-config --libs r_asm)
|
||||
CC_ANA=$(CC) $(CFLAGS) $(LDFLAGS) $(shell pkg-config --libs r_anal)
|
||||
CC_BIN=$(CC) $(CFLAGS) $(LDFLAGS) $(shell pkg-config --libs r_bin) -lr_magic
|
||||
CC_COR=$(CC) $(CFLAGS) $(LDFLAGS) $(shell pkg-config --libs r_core)
|
||||
|
||||
all:
|
||||
$(CC_ASM) -o asm_bpf.$(EXT_SO) asm_bpf.c
|
||||
$(CC_ANA) -o anal_bpf.$(EXT_SO) anal_bpf.c
|
||||
$(CC_BIN) -o bin_bpf.$(EXT_SO) bin_bpf.c
|
||||
# $(CC_COR) -o bpf_core.$(EXT_SO) bpf_core.c
|
||||
|
||||
install: all
|
||||
$(SUDO) cp -f *.$(EXT_SO) $(R2_PLUGIN_PATH)
|
||||
|
||||
uninstall:
|
||||
for a in *.$(EXT_SO) ; do rm -f $(R2_PLUGIN_PATH)/$$a ; done
|
||||
|
||||
clean:
|
||||
rm -f *.$(EXT_SO)
|
||||
rm -rf *.$(EXT_SO).dSYM
|
||||
@@ -1,54 +0,0 @@
|
||||
#BPF architecture for radare2
|
||||
|
||||
This is meant to add support for Berkeley Packet Filter in radare2, with full [ESIL](https://radare.gitbooks.io/radare2book/content/esil.html) emulation. The main purpose is to ease the analysis of existing filters encountered in reverse engineering, but can also aid filter development through ESIL emulation.
|
||||
|
||||
## Components
|
||||
|
||||
It is composed by three plugins:
|
||||
|
||||
* **asm_bpf** is the disassembler, i'm planning to add also assembler functionality, but for now it's only disassembler - it is mostly ripped from bpf_dbg.c in the Linux kernel
|
||||
* **anal_bpf** this is the major contribution of this package, i.e. the analysis plugin which translates everything to ESIL and permits to emulate it completely
|
||||
* **bin_bpf** is a placeholder, not sure if it's useful at all since there isn't a specific file format - i'm using it just to remember that data is represented big endian by enforcing this information
|
||||
|
||||
## Installing using r2pm
|
||||
|
||||
This plugin is available in latest r2pm, therefore can be installed simply by:
|
||||
|
||||
```
|
||||
r2pm -i bpf
|
||||
```
|
||||
|
||||
## Building manually
|
||||
|
||||
In unix system (tested on mac, but should work in Linux or *BSD out of the box) it should be as easy as doing:
|
||||
|
||||
```bash
|
||||
make install
|
||||
```
|
||||
|
||||
There are two known warnings:
|
||||
|
||||
* be sure to have the latest [radare2 from git](https://github.com/radareorg/radare2)
|
||||
* on mac systems radare2 should be installed with sys/install.sh (and not sys/user.sh) because the Makefile relies on a properly working `pkg-config`
|
||||
|
||||
## Example
|
||||
|
||||
The provided [bpf.bin](bpf.bin) is ripped from the [berkeley crackme](http://crackmes.de/users/kwisatz_haderach/berkeley/), here is an example session:
|
||||
|
||||
[](https://asciinema.org/a/1q8oq25bjpp00aut5v5sd4sez)
|
||||
|
||||
Moreover, i wrote an [r2pipe script](https://github.com/mrmacete/r2scripts/tree/master/bpf-test/bpftest.py) able to read a pcap file, iterate packets, and test them against the filter by using ESIL emulation.
|
||||
|
||||
Here is a not-so-clear live action trying to explain the steps of the above python script:
|
||||
|
||||
[](https://asciinema.org/a/e22kxl5wncmcnqfvseq0k6dxj)
|
||||
|
||||
## Testing
|
||||
|
||||
There's a [python script](https://github.com/mrmacete/r2scripts/tree/master/bpf-test/testtool.py) which parses the Linux kernel's BPF test suite and runs it on radare2's emulated BPF using r2pipe. Until now, all the test which doesn't involve kernel emulation are passing (for the CLASSIC bpf test category only).
|
||||
|
||||
If you have collections of test cases you can disclose they're welcome, please open an issue or just PR a test script.
|
||||
|
||||
## License
|
||||
|
||||
Since most of asm_bpf.c is ripped from Linux kernel, it's licensed on GPLv2.
|
||||
-538
@@ -1,538 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2015 - mrmacete <[email protected]>
|
||||
* Licensed under the GNU General Public License, version 2.0 (GPLv2)
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <r_types.h>
|
||||
#include <r_lib.h>
|
||||
#include <r_asm.h>
|
||||
#include <r_anal.h>
|
||||
#include "bpf.h"
|
||||
|
||||
#define EMIT_CJMP(op, addr, f)\
|
||||
(op)->type = R_ANAL_OP_TYPE_CJMP;\
|
||||
(op)->jump = (addr) + 8 + (st8) (f)->jt * 8;\
|
||||
(op)->fail = (addr) + 8 + (st8) (f)->jf * 8;
|
||||
|
||||
#define EMIT_LOAD(op, addr, size)\
|
||||
(op)->type = R_ANAL_OP_TYPE_LOAD;\
|
||||
(op)->ptr = (addr);\
|
||||
(op)->ptrsize = (size);
|
||||
|
||||
#define NEW_SRC_DST(op)\
|
||||
(op)->src[0] = r_anal_value_new ();\
|
||||
(op)->dst = r_anal_value_new ();
|
||||
|
||||
#define SET_REG_SRC_DST(op, _src, _dst)\
|
||||
NEW_SRC_DST ((op));\
|
||||
(op)->src[0]->reg = r_reg_get (anal->reg, (_src), R_REG_TYPE_GPR);\
|
||||
(op)->dst->reg = r_reg_get (anal->reg, (_dst), R_REG_TYPE_GPR);
|
||||
|
||||
#define SET_REG_DST_IMM(op, _dst, _imm)\
|
||||
NEW_SRC_DST ((op));\
|
||||
(op)->dst->reg = r_reg_get (anal->reg, (_dst), R_REG_TYPE_GPR);\
|
||||
(op)->src[0]->imm = (_imm);
|
||||
|
||||
#define SET_A_SRC(op)\
|
||||
(op)->src[0] = r_anal_value_new ();\
|
||||
(op)->src[0]->reg = r_reg_get (anal->reg, "A", R_REG_TYPE_GPR);
|
||||
|
||||
#define SET_A_DST(op)\
|
||||
(op)->dst = r_anal_value_new ();\
|
||||
(op)->dst->reg = r_reg_get (anal->reg, "A", R_REG_TYPE_GPR);
|
||||
|
||||
#define INSIDE_M(k) ((k) >= 0 && (k) <= 16)
|
||||
|
||||
static bool bpf_int_exit(RAnalEsil *esil, ut32 interrupt, void *user);
|
||||
RAnalEsilInterruptHandler ih = { 0, NULL, NULL, &bpf_int_exit, NULL };
|
||||
|
||||
static const char *M[] = {
|
||||
"M[0]",
|
||||
"M[1]",
|
||||
"M[2]",
|
||||
"M[3]",
|
||||
"M[4]",
|
||||
"M[5]",
|
||||
"M[6]",
|
||||
"M[7]",
|
||||
"M[8]",
|
||||
"M[9]",
|
||||
"M[10]",
|
||||
"M[11]",
|
||||
"M[12]",
|
||||
"M[13]",
|
||||
"M[14]",
|
||||
"M[15]"
|
||||
};
|
||||
|
||||
static int bpf_anal(RAnal *anal, RAnalOp *op, ut64 addr,
|
||||
const ut8 *data, int len) {
|
||||
RBpfSockFilter *f = (RBpfSockFilter *)data;
|
||||
memset (op, '\0', sizeof (RAnalOp));
|
||||
op->jump = UT64_MAX;
|
||||
op->fail = UT64_MAX;
|
||||
op->ptr = op->val = UT64_MAX;
|
||||
op->type = R_ANAL_OP_TYPE_UNK;
|
||||
op->size = 8;
|
||||
op->addr = addr;
|
||||
|
||||
r_strbuf_init (&op->esil);
|
||||
|
||||
switch (f->code) {
|
||||
case BPF_RET | BPF_A:
|
||||
op->type = R_ANAL_OP_TYPE_RET;
|
||||
esilprintf (op, "A,R0,=,0,$");
|
||||
break;
|
||||
case BPF_RET | BPF_K:
|
||||
case BPF_RET | BPF_X:
|
||||
op->type = R_ANAL_OP_TYPE_RET;
|
||||
if (BPF_SRC (f->code) == BPF_K) {
|
||||
esilprintf (op, "%" PFMT64d ",R0,=,0,$", f->k);
|
||||
} else if (BPF_SRC (f->code) == BPF_X) {
|
||||
esilprintf (op, "X,R0,=,0,$");
|
||||
}
|
||||
break;
|
||||
case BPF_MISC_TAX:
|
||||
op->type = R_ANAL_OP_TYPE_MOV;
|
||||
SET_REG_SRC_DST (op, "A", "X");
|
||||
esilprintf (op, "A,X,=");
|
||||
break;
|
||||
case BPF_MISC_TXA:
|
||||
op->type = R_ANAL_OP_TYPE_MOV;
|
||||
SET_REG_SRC_DST (op, "X", "A");
|
||||
esilprintf (op, "X,A,=");
|
||||
break;
|
||||
case BPF_ST:
|
||||
if (INSIDE_M (f->k)) {
|
||||
op->type = R_ANAL_OP_TYPE_MOV;
|
||||
SET_REG_SRC_DST (op, "A", M[f->k]);
|
||||
esilprintf (op, "A,M[%" PFMT64d "],=", f->k);
|
||||
} else {
|
||||
op->type = R_ANAL_OP_TYPE_ILL;
|
||||
}
|
||||
break;
|
||||
case BPF_STX:
|
||||
if (INSIDE_M (f->k)) {
|
||||
op->type = R_ANAL_OP_TYPE_MOV;
|
||||
SET_REG_SRC_DST (op, "X", M[f->k]);
|
||||
esilprintf (op, "X,M[%" PFMT64d "],=", f->k);
|
||||
} else {
|
||||
op->type = R_ANAL_OP_TYPE_ILL;
|
||||
}
|
||||
break;
|
||||
case BPF_LD_W | BPF_LEN:
|
||||
op->type = R_ANAL_OP_TYPE_MOV;
|
||||
SET_REG_SRC_DST (op, "len", "A");
|
||||
esilprintf (op, "len,A,=", f->k);
|
||||
break;
|
||||
case BPF_LDX | BPF_LEN:
|
||||
op->type = R_ANAL_OP_TYPE_MOV;
|
||||
SET_REG_SRC_DST (op, "len", "X");
|
||||
esilprintf (op, "len,X,=", f->k);
|
||||
break;
|
||||
case BPF_LD_W | BPF_ABS:
|
||||
EMIT_LOAD (op, anal->gp + f->k, 4);
|
||||
SET_A_DST (op);
|
||||
esilprintf (op,
|
||||
"len,%" PFMT64d ",>,?{,0,R0,=,0,$,BREAK,},%" PFMT64d ",[4],A,=",
|
||||
f->k + 4, op->ptr);
|
||||
break;
|
||||
case BPF_LD_H | BPF_ABS:
|
||||
EMIT_LOAD (op, anal->gp + f->k, 2);
|
||||
SET_A_DST (op);
|
||||
esilprintf (op,
|
||||
"len,%" PFMT64d ",>,?{,0,R0,=,0,$,BREAK,},"
|
||||
"%" PFMT64d ",[2],A,=",
|
||||
f->k + 2, op->ptr);
|
||||
break;
|
||||
case BPF_LD_B | BPF_ABS:
|
||||
EMIT_LOAD (op, anal->gp + f->k, 1);
|
||||
SET_A_DST (op);
|
||||
esilprintf (op,
|
||||
"len,%" PFMT64d ",>,?{,0,R0,=,0,$,BREAK,},"
|
||||
"%" PFMT64d ",[1],A,=",
|
||||
f->k + 1, op->ptr);
|
||||
break;
|
||||
case BPF_LD_W | BPF_IND:
|
||||
op->type = R_ANAL_OP_TYPE_LOAD;
|
||||
op->ptrsize = 4;
|
||||
SET_A_DST (op);
|
||||
esilprintf (op,
|
||||
"len,%" PFMT64d ",X,+,0xffffffff,&,>,?{,0,R0,=,0,$,BREAK,},"
|
||||
"%" PFMT64d ",X,+,0xffffffff,&,[4],A,=",
|
||||
(st32)f->k + 4, anal->gp + (st32)f->k);
|
||||
break;
|
||||
case BPF_LD_H | BPF_IND:
|
||||
op->type = R_ANAL_OP_TYPE_LOAD;
|
||||
op->ptrsize = 2;
|
||||
SET_A_DST (op);
|
||||
esilprintf (op,
|
||||
"len,%" PFMT64d ",X,+,0xffffffff,&,>,?{,0,R0,=,0,$,BREAK,},"
|
||||
"%" PFMT64d ",X,+,0xffffffff,&,[2],A,=",
|
||||
(st32)f->k + 2, anal->gp + (st32)f->k);
|
||||
break;
|
||||
case BPF_LD_B | BPF_IND:
|
||||
op->type = R_ANAL_OP_TYPE_LOAD;
|
||||
op->ptrsize = 1;
|
||||
SET_A_DST (op);
|
||||
esilprintf (op,
|
||||
"len,%" PFMT64d ",X,+,0xffffffff,&,>,?{,0,R0,=,0,$,BREAK,},"
|
||||
"%" PFMT64d ",X,+,0xffffffff,&,[1],A,=",
|
||||
(st32)f->k + 1, anal->gp + (st32)f->k);
|
||||
break;
|
||||
case BPF_LD | BPF_IMM:
|
||||
op->type = R_ANAL_OP_TYPE_MOV;
|
||||
op->val = f->k;
|
||||
SET_REG_DST_IMM (op, "A", f->k);
|
||||
esilprintf (op, "0x%08" PFMT64x ",A,=", f->k);
|
||||
break;
|
||||
case BPF_LDX | BPF_IMM:
|
||||
op->type = R_ANAL_OP_TYPE_MOV;
|
||||
op->val = f->k;
|
||||
SET_REG_DST_IMM (op, "X", f->k);
|
||||
esilprintf (op, "0x%08" PFMT64x ",X,=", f->k);
|
||||
break;
|
||||
case BPF_LDX_B | BPF_MSH:
|
||||
op->type = R_ANAL_OP_TYPE_LOAD;
|
||||
op->ptrsize = 1;
|
||||
op->ptr = anal->gp + f->k;
|
||||
SET_A_DST (op);
|
||||
esilprintf (op, "%" PFMT64d ",[1],0xf,&,4,*,X,=", op->ptr);
|
||||
break;
|
||||
case BPF_LD | BPF_MEM:
|
||||
op->type = R_ANAL_OP_TYPE_MOV;
|
||||
if (INSIDE_M (f->k)) {
|
||||
SET_REG_SRC_DST (op, M[f->k], "A");
|
||||
esilprintf (op, "M[%" PFMT64d "],A,=", f->k);
|
||||
} else {
|
||||
op->type = R_ANAL_OP_TYPE_ILL;
|
||||
}
|
||||
break;
|
||||
case BPF_LDX | BPF_MEM:
|
||||
op->type = R_ANAL_OP_TYPE_MOV;
|
||||
if (INSIDE_M (f->k)) {
|
||||
SET_REG_SRC_DST (op, M[f->k], "X");
|
||||
esilprintf (op, "M[%" PFMT64d "],X,=", f->k);
|
||||
} else {
|
||||
op->type = R_ANAL_OP_TYPE_ILL;
|
||||
}
|
||||
break;
|
||||
case BPF_JMP_JA:
|
||||
op->type = R_ANAL_OP_TYPE_JMP;
|
||||
op->jump = addr + 8 + f->k * 8;
|
||||
esilprintf (op, "%" PFMT64d ",pc,=", op->jump);
|
||||
|
||||
break;
|
||||
case BPF_JMP_JGT | BPF_X:
|
||||
case BPF_JMP_JGT | BPF_K:
|
||||
EMIT_CJMP (op, addr, f);
|
||||
op->cond = R_ANAL_COND_GT;
|
||||
if (BPF_SRC (f->code) == BPF_K) {
|
||||
op->val = f->k;
|
||||
esilprintf (op,
|
||||
"%" PFMT64d ",A,>,?{,%" PFMT64d ",pc,=,BREAK,},%" PFMT64d ",pc,=",
|
||||
op->val, op->jump, op->fail);
|
||||
} else if (BPF_SRC (f->code) == BPF_X) {
|
||||
esilprintf (op,
|
||||
"X,A,>,?{,%" PFMT64d ",pc,=,BREAK,},%" PFMT64d ",pc,=",
|
||||
op->jump, op->fail);
|
||||
} else {
|
||||
op->type = R_ANAL_OP_TYPE_ILL;
|
||||
}
|
||||
break;
|
||||
case BPF_JMP_JGE | BPF_X:
|
||||
case BPF_JMP_JGE | BPF_K:
|
||||
EMIT_CJMP (op, addr, f);
|
||||
op->cond = R_ANAL_COND_GE;
|
||||
if (BPF_SRC (f->code) == BPF_K) {
|
||||
op->val = f->k;
|
||||
esilprintf (op,
|
||||
"%" PFMT64d ",A,>=,?{,%" PFMT64d ",pc,=,BREAK,},%" PFMT64d ",pc,=",
|
||||
op->val, op->jump, op->fail);
|
||||
} else {
|
||||
esilprintf (op,
|
||||
"X,A,>=,?{,%" PFMT64d ",pc,=,BREAK,},%" PFMT64d ",pc,=",
|
||||
op->jump, op->fail);
|
||||
}
|
||||
break;
|
||||
case BPF_JMP_JEQ | BPF_X:
|
||||
case BPF_JMP_JEQ | BPF_K:
|
||||
EMIT_CJMP (op, addr, f);
|
||||
op->cond = R_ANAL_COND_EQ;
|
||||
if (BPF_SRC (f->code) == BPF_K) {
|
||||
op->val = f->k;
|
||||
esilprintf (op,
|
||||
"%" PFMT64d ",A,==,$z,?{,%" PFMT64d ",pc,=,BREAK,},%" PFMT64d ",pc,=",
|
||||
op->val, op->jump, op->fail);
|
||||
} else {
|
||||
esilprintf (op,
|
||||
"X,A,==,$z,?{,%" PFMT64d ",pc,=,BREAK,},%" PFMT64d ",pc,=",
|
||||
op->jump, op->fail);
|
||||
}
|
||||
break;
|
||||
case BPF_JMP_JSET | BPF_X:
|
||||
case BPF_JMP_JSET | BPF_K:
|
||||
EMIT_CJMP (op, addr, f);
|
||||
if (BPF_SRC (f->code) == BPF_K) {
|
||||
op->val = f->k;
|
||||
esilprintf (op,
|
||||
"%" PFMT64d ",A,&,?{,%" PFMT64d ",pc,=,BREAK,},%" PFMT64d ",pc,=",
|
||||
op->val, op->jump, op->fail);
|
||||
} else {
|
||||
esilprintf (op,
|
||||
"X,A,&,!,?{,%" PFMT64d ",pc,=,BREAK,},%" PFMT64d ",pc,=",
|
||||
op->val, op->jump, op->fail);
|
||||
}
|
||||
break;
|
||||
case BPF_ALU_NEG:
|
||||
op->type = R_ANAL_OP_TYPE_NOT;
|
||||
esilprintf (op, "A,0,-,A,=");
|
||||
SET_REG_SRC_DST (op, "A", "A");
|
||||
break;
|
||||
case BPF_ALU_LSH | BPF_X:
|
||||
case BPF_ALU_LSH | BPF_K:
|
||||
op->type = R_ANAL_OP_TYPE_SHL;
|
||||
if (BPF_SRC (f->code) == BPF_K) {
|
||||
op->val = f->k;
|
||||
SET_REG_DST_IMM (op, "A", f->k);
|
||||
esilprintf (op, "%" PFMT64d ",A,<<=", f->k);
|
||||
} else {
|
||||
SET_REG_SRC_DST (op, "X", "A");
|
||||
esilprintf (op, "X,A,<<=");
|
||||
}
|
||||
break;
|
||||
case BPF_ALU_RSH | BPF_X:
|
||||
case BPF_ALU_RSH | BPF_K:
|
||||
op->type = R_ANAL_OP_TYPE_SHR;
|
||||
if (BPF_SRC (f->code) == BPF_K) {
|
||||
op->val = f->k;
|
||||
SET_REG_DST_IMM (op, "A", f->k);
|
||||
esilprintf (op, "%" PFMT64d ",A,>>=", f->k);
|
||||
} else {
|
||||
SET_REG_SRC_DST (op, "X", "A");
|
||||
esilprintf (op, "X,A,>>=");
|
||||
}
|
||||
break;
|
||||
case BPF_ALU_ADD | BPF_X:
|
||||
case BPF_ALU_ADD | BPF_K:
|
||||
op->type = R_ANAL_OP_TYPE_ADD;
|
||||
if (BPF_SRC (f->code) == BPF_K) {
|
||||
op->val = f->k;
|
||||
SET_REG_DST_IMM (op, "A", op->val);
|
||||
esilprintf (op, "%" PFMT64d ",A,+=", op->val);
|
||||
} else {
|
||||
SET_REG_SRC_DST (op, "X", "A");
|
||||
esilprintf (op, "X,A,+=");
|
||||
}
|
||||
break;
|
||||
case BPF_ALU_SUB | BPF_X:
|
||||
case BPF_ALU_SUB | BPF_K:
|
||||
op->type = R_ANAL_OP_TYPE_SUB;
|
||||
if (BPF_SRC (f->code) == BPF_K) {
|
||||
op->val = f->k;
|
||||
SET_REG_DST_IMM (op, "A", op->val);
|
||||
esilprintf (op, "%" PFMT64d ",A,-=", op->val);
|
||||
|
||||
} else {
|
||||
SET_REG_SRC_DST (op, "X", "A");
|
||||
esilprintf (op, "X,A,-=");
|
||||
}
|
||||
break;
|
||||
case BPF_ALU_MUL | BPF_X:
|
||||
case BPF_ALU_MUL | BPF_K:
|
||||
op->type = R_ANAL_OP_TYPE_MUL;
|
||||
if (BPF_SRC (f->code) == BPF_K) {
|
||||
op->val = f->k;
|
||||
SET_REG_DST_IMM (op, "A", f->k);
|
||||
esilprintf (op, "%" PFMT64d ",A,*=", f->k);
|
||||
} else {
|
||||
SET_REG_SRC_DST (op, "X", "A");
|
||||
esilprintf (op, "X,A,*=");
|
||||
}
|
||||
break;
|
||||
case BPF_ALU_DIV | BPF_X:
|
||||
case BPF_ALU_DIV | BPF_K:
|
||||
op->type = R_ANAL_OP_TYPE_DIV;
|
||||
if (BPF_SRC (f->code) == BPF_K) {
|
||||
op->val = f->k;
|
||||
SET_REG_DST_IMM (op, "A", f->k);
|
||||
if (f->k == 0) {
|
||||
esilprintf (op, "0,R0,=,0,$");
|
||||
} else {
|
||||
esilprintf (op, "%" PFMT64d ",A,/=", f->k);
|
||||
}
|
||||
} else {
|
||||
SET_REG_SRC_DST (op, "X", "A");
|
||||
esilprintf (op, "0,X,==,$z,?{,0,R0,=,0,$,BREAK,},X,A,/=");
|
||||
}
|
||||
break;
|
||||
case BPF_ALU_MOD | BPF_X:
|
||||
case BPF_ALU_MOD | BPF_K:
|
||||
op->type = R_ANAL_OP_TYPE_MOD;
|
||||
if (BPF_SRC (f->code) == BPF_K) {
|
||||
op->val = f->k;
|
||||
SET_REG_DST_IMM (op, "A", f->k);
|
||||
if (f->k == 0) {
|
||||
esilprintf (op, "0,R0,=,0,$");
|
||||
} else {
|
||||
esilprintf (op, "%" PFMT64d ",A,%%=", f->k);
|
||||
}
|
||||
} else {
|
||||
SET_REG_SRC_DST (op, "X", "A");
|
||||
esilprintf (op, "0,X,==,$z,?{,0,R0,=,0,$,BREAK,},X,A,%%=");
|
||||
}
|
||||
break;
|
||||
case BPF_ALU_AND | BPF_X:
|
||||
case BPF_ALU_AND | BPF_K:
|
||||
op->type = R_ANAL_OP_TYPE_AND;
|
||||
if (BPF_SRC (f->code) == BPF_K) {
|
||||
op->val = f->k;
|
||||
SET_REG_DST_IMM (op, "A", f->k);
|
||||
esilprintf (op, "%" PFMT64d ",A,&=", f->k);
|
||||
} else {
|
||||
SET_REG_SRC_DST (op, "X", "A");
|
||||
esilprintf (op, "X,A,&=");
|
||||
}
|
||||
break;
|
||||
case BPF_ALU_OR | BPF_X:
|
||||
case BPF_ALU_OR | BPF_K:
|
||||
op->type = R_ANAL_OP_TYPE_OR;
|
||||
if (BPF_SRC (f->code) == BPF_K) {
|
||||
op->val = f->k;
|
||||
SET_REG_DST_IMM (op, "A", f->k);
|
||||
esilprintf (op, "%" PFMT64d ",A,|=", f->k);
|
||||
} else {
|
||||
SET_REG_SRC_DST (op, "X", "A");
|
||||
esilprintf (op, "X,A,|,A,=");
|
||||
}
|
||||
break;
|
||||
case BPF_ALU_XOR | BPF_X:
|
||||
case BPF_ALU_XOR | BPF_K:
|
||||
op->type = R_ANAL_OP_TYPE_XOR;
|
||||
if (BPF_SRC (f->code) == BPF_K) {
|
||||
op->val = f->k;
|
||||
SET_REG_DST_IMM (op, "A", f->k);
|
||||
esilprintf (op, "%" PFMT64d ",A,^=", f->k);
|
||||
} else {
|
||||
SET_REG_SRC_DST (op, "X", "A");
|
||||
esilprintf (op, "X,A,^=");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
op->type = R_ANAL_OP_TYPE_ILL;
|
||||
break;
|
||||
}
|
||||
|
||||
return op->size;
|
||||
}
|
||||
|
||||
static int set_reg_profile(RAnal *anal) {
|
||||
const char *p =
|
||||
"=PC pc\n"
|
||||
"gpr A .32 0 0\n"
|
||||
"gpr X .32 4 0\n"
|
||||
"gpr M[0] .32 8 0\n"
|
||||
"gpr M[1] .32 12 0\n"
|
||||
"gpr M[2] .32 16 0\n"
|
||||
"gpr M[3] .32 20 0\n"
|
||||
"gpr M[4] .32 24 0\n"
|
||||
"gpr M[5] .32 28 0\n"
|
||||
"gpr M[6] .32 32 0\n"
|
||||
"gpr M[7] .32 36 0\n"
|
||||
"gpr M[8] .32 40 0\n"
|
||||
"gpr M[9] .32 44 0\n"
|
||||
"gpr M[10] .32 48 0\n"
|
||||
"gpr M[11] .32 52 0\n"
|
||||
"gpr M[12] .32 56 0\n"
|
||||
"gpr M[13] .32 60 0\n"
|
||||
"gpr M[14] .32 64 0\n"
|
||||
"gpr M[15] .32 68 0\n"
|
||||
"gpr pc .32 72 0\n"
|
||||
"gpr len .32 76 0\n"
|
||||
"gpr R0 .32 80 0\n"
|
||||
"gpr R1 .32 84 0\n"
|
||||
"gpr R2 .32 88 0\n"
|
||||
"gpr R3 .32 92 0\n"
|
||||
"gpr R4 .32 96 0\n"
|
||||
"gpr R5 .32 100 0\n";
|
||||
return r_reg_set_profile_string (anal->reg, p);
|
||||
}
|
||||
|
||||
static bool bpf_int_exit(RAnalEsil *esil, ut32 interrupt, void *user) {
|
||||
int syscall;
|
||||
ut64 r0;
|
||||
if (!esil || (interrupt != 0x0))
|
||||
return false;
|
||||
r_anal_esil_reg_read (esil, "R0", &r0, NULL);
|
||||
if (r0 == 0) {
|
||||
esil->anal->cb_printf ("; BPF result: DROP value: %d\n", (int)r0);
|
||||
eprintf ("BPF result: DROP value: %d\n", (int)r0);
|
||||
} else {
|
||||
esil->anal->cb_printf ("; BPF result: ACCEPT value: %d\n", (int)r0);
|
||||
eprintf ("BPF result: ACCEPT value: %d\n", (int)r0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static int esil_bpf_init(RAnalEsil *esil) {
|
||||
if (!esil)
|
||||
return false;
|
||||
RAnalEsilInterrupt *intr = r_anal_esil_interrupt_new (esil, 0, &ih);
|
||||
r_anal_esil_set_interrupt (esil, intr);
|
||||
return true;
|
||||
}
|
||||
|
||||
static int esil_bpf_fini(RAnalEsil *esil) {
|
||||
return true;
|
||||
}
|
||||
|
||||
struct r_anal_plugin_t r_anal_plugin_bpf = {
|
||||
.name = "bpf",
|
||||
.desc = "Berkely packet filter analysis plugin",
|
||||
.license = "GPLv2",
|
||||
.arch = "bpf",
|
||||
.bits = 32,
|
||||
.esil = true,
|
||||
.init = NULL,
|
||||
.fini = NULL,
|
||||
.reset_counter = NULL,
|
||||
.archinfo = NULL,
|
||||
.op = &bpf_anal,
|
||||
.bb = NULL,
|
||||
.fcn = NULL,
|
||||
.analyze_fns = NULL,
|
||||
.op_from_buffer = NULL,
|
||||
.bb_from_buffer = NULL,
|
||||
.fn_from_buffer = NULL,
|
||||
.analysis_algorithm = NULL,
|
||||
.set_reg_profile = &set_reg_profile,
|
||||
.fingerprint_bb = NULL,
|
||||
.fingerprint_fcn = NULL,
|
||||
.diff_bb = NULL,
|
||||
.diff_fcn = NULL,
|
||||
.diff_eval = NULL,
|
||||
.pre_anal = NULL,
|
||||
.pre_anal_fn_cb = NULL,
|
||||
.pre_anal_op_cb = NULL,
|
||||
.post_anal_op_cb = NULL,
|
||||
.pre_anal_bb_cb = NULL,
|
||||
.post_anal_bb_cb = NULL,
|
||||
.post_anal_fn_cb = NULL,
|
||||
.post_anal = NULL,
|
||||
.revisit_bb_anal = NULL,
|
||||
.cmd_ext = NULL,
|
||||
.esil_init = &esil_bpf_init,
|
||||
.esil_post_loop = NULL,
|
||||
.esil_trap = NULL,
|
||||
.esil_fini = &esil_bpf_fini
|
||||
};
|
||||
|
||||
#ifndef CORELIB
|
||||
struct r_lib_struct_t radare_plugin = {
|
||||
.type = R_LIB_TYPE_ANAL,
|
||||
.data = &r_anal_plugin_bpf,
|
||||
.version = R2_VERSION
|
||||
};
|
||||
#endif
|
||||
-767
@@ -1,767 +0,0 @@
|
||||
/*
|
||||
* Most of this is copied and pasted from linux source (except
|
||||
* for the assembler part).
|
||||
*
|
||||
* Copyright 2015 - mrmacete <[email protected]>
|
||||
* Licensed under the GNU General Public License, version 2.0 (GPLv2)
|
||||
*/
|
||||
|
||||
#include <r_types.h>
|
||||
#include <r_util.h>
|
||||
#include <r_lib.h>
|
||||
#include <r_asm.h>
|
||||
#include "bpf.h"
|
||||
|
||||
static int disassemble(RAsm *a, RAsmOp *r_op, const ut8 *buf, int len) {
|
||||
const char *op, *fmt;
|
||||
RBpfSockFilter *f = (RBpfSockFilter *)buf;
|
||||
int val = f->k;
|
||||
char vbuf[256];
|
||||
|
||||
switch (f->code) {
|
||||
case BPF_RET | BPF_K:
|
||||
op = r_bpf_op_table[BPF_RET];
|
||||
fmt = "%#x";
|
||||
break;
|
||||
case BPF_RET | BPF_A:
|
||||
op = r_bpf_op_table[BPF_RET];
|
||||
fmt = "a";
|
||||
break;
|
||||
case BPF_RET | BPF_X:
|
||||
op = r_bpf_op_table[BPF_RET];
|
||||
fmt = "x";
|
||||
break;
|
||||
case BPF_MISC_TAX:
|
||||
op = r_bpf_op_table[BPF_MISC_TAX];
|
||||
fmt = "";
|
||||
break;
|
||||
case BPF_MISC_TXA:
|
||||
op = r_bpf_op_table[BPF_MISC_TXA];
|
||||
fmt = "";
|
||||
break;
|
||||
case BPF_ST:
|
||||
op = r_bpf_op_table[BPF_ST];
|
||||
fmt = "M[%d]";
|
||||
break;
|
||||
case BPF_STX:
|
||||
op = r_bpf_op_table[BPF_STX];
|
||||
fmt = "M[%d]";
|
||||
break;
|
||||
case BPF_LD_W | BPF_ABS:
|
||||
op = r_bpf_op_table[BPF_LD_W];
|
||||
fmt = "[%d]";
|
||||
break;
|
||||
case BPF_LD_H | BPF_ABS:
|
||||
op = r_bpf_op_table[BPF_LD_H];
|
||||
fmt = "[%d]";
|
||||
break;
|
||||
case BPF_LD_B | BPF_ABS:
|
||||
op = r_bpf_op_table[BPF_LD_B];
|
||||
fmt = "[%d]";
|
||||
break;
|
||||
case BPF_LD_W | BPF_LEN:
|
||||
op = r_bpf_op_table[BPF_LD_W];
|
||||
fmt = "len";
|
||||
break;
|
||||
case BPF_LD_W | BPF_IND:
|
||||
op = r_bpf_op_table[BPF_LD_W];
|
||||
fmt = "[x+%d]";
|
||||
break;
|
||||
case BPF_LD_H | BPF_IND:
|
||||
op = r_bpf_op_table[BPF_LD_H];
|
||||
fmt = "[x+%d]";
|
||||
break;
|
||||
case BPF_LD_B | BPF_IND:
|
||||
op = r_bpf_op_table[BPF_LD_B];
|
||||
fmt = "[x+%d]";
|
||||
break;
|
||||
case BPF_LD | BPF_IMM:
|
||||
op = r_bpf_op_table[BPF_LD_W];
|
||||
fmt = "%#x";
|
||||
break;
|
||||
case BPF_LDX | BPF_IMM:
|
||||
op = r_bpf_op_table[BPF_LDX];
|
||||
fmt = "%#x";
|
||||
break;
|
||||
case BPF_LDX | BPF_LEN:
|
||||
op = r_bpf_op_table[BPF_LDX];
|
||||
fmt = "len";
|
||||
break;
|
||||
case BPF_LDX | BPF_ABS:
|
||||
op = r_bpf_op_table[BPF_LDX];
|
||||
fmt = "[%d]";
|
||||
break;
|
||||
case BPF_LDX_B | BPF_MSH:
|
||||
op = r_bpf_op_table[BPF_LDX_B];
|
||||
fmt = "4*([%d]&0xf)";
|
||||
break;
|
||||
case BPF_LD | BPF_MEM:
|
||||
op = r_bpf_op_table[BPF_LD_W];
|
||||
fmt = "M[%d]";
|
||||
break;
|
||||
case BPF_LDX | BPF_MEM:
|
||||
op = r_bpf_op_table[BPF_LDX];
|
||||
fmt = "M[%d]";
|
||||
break;
|
||||
case BPF_JMP_JA:
|
||||
op = r_bpf_op_table[BPF_JMP_JA];
|
||||
fmt = "%d";
|
||||
val = a->pc + 8 + f->k * 8;
|
||||
break;
|
||||
case BPF_JMP_JGT | BPF_X:
|
||||
op = r_bpf_op_table[BPF_JMP_JGT];
|
||||
fmt = "x";
|
||||
break;
|
||||
case BPF_JMP_JGT | BPF_K:
|
||||
op = r_bpf_op_table[BPF_JMP_JGT];
|
||||
fmt = "%#x";
|
||||
break;
|
||||
case BPF_JMP_JGE | BPF_X:
|
||||
op = r_bpf_op_table[BPF_JMP_JGE];
|
||||
fmt = "x";
|
||||
break;
|
||||
case BPF_JMP_JGE | BPF_K:
|
||||
op = r_bpf_op_table[BPF_JMP_JGE];
|
||||
fmt = "%#x";
|
||||
break;
|
||||
case BPF_JMP_JEQ | BPF_X:
|
||||
op = r_bpf_op_table[BPF_JMP_JEQ];
|
||||
fmt = "x";
|
||||
break;
|
||||
case BPF_JMP_JEQ | BPF_K:
|
||||
op = r_bpf_op_table[BPF_JMP_JEQ];
|
||||
fmt = "%#x";
|
||||
break;
|
||||
case BPF_JMP_JSET | BPF_X:
|
||||
op = r_bpf_op_table[BPF_JMP_JSET];
|
||||
fmt = "x";
|
||||
break;
|
||||
case BPF_JMP_JSET | BPF_K:
|
||||
op = r_bpf_op_table[BPF_JMP_JSET];
|
||||
fmt = "%#x";
|
||||
break;
|
||||
case BPF_ALU_NEG:
|
||||
op = r_bpf_op_table[BPF_ALU_NEG];
|
||||
fmt = "";
|
||||
break;
|
||||
case BPF_ALU_LSH | BPF_X:
|
||||
op = r_bpf_op_table[BPF_ALU_LSH];
|
||||
fmt = "x";
|
||||
break;
|
||||
case BPF_ALU_LSH | BPF_K:
|
||||
op = r_bpf_op_table[BPF_ALU_LSH];
|
||||
fmt = "%d";
|
||||
break;
|
||||
case BPF_ALU_RSH | BPF_X:
|
||||
op = r_bpf_op_table[BPF_ALU_RSH];
|
||||
fmt = "x";
|
||||
break;
|
||||
case BPF_ALU_RSH | BPF_K:
|
||||
op = r_bpf_op_table[BPF_ALU_RSH];
|
||||
fmt = "%d";
|
||||
break;
|
||||
case BPF_ALU_ADD | BPF_X:
|
||||
op = r_bpf_op_table[BPF_ALU_ADD];
|
||||
fmt = "x";
|
||||
break;
|
||||
case BPF_ALU_ADD | BPF_K:
|
||||
op = r_bpf_op_table[BPF_ALU_ADD];
|
||||
fmt = "%d";
|
||||
break;
|
||||
case BPF_ALU_SUB | BPF_X:
|
||||
op = r_bpf_op_table[BPF_ALU_SUB];
|
||||
fmt = "x";
|
||||
break;
|
||||
case BPF_ALU_SUB | BPF_K:
|
||||
op = r_bpf_op_table[BPF_ALU_SUB];
|
||||
fmt = "%d";
|
||||
break;
|
||||
case BPF_ALU_MUL | BPF_X:
|
||||
op = r_bpf_op_table[BPF_ALU_MUL];
|
||||
fmt = "x";
|
||||
break;
|
||||
case BPF_ALU_MUL | BPF_K:
|
||||
op = r_bpf_op_table[BPF_ALU_MUL];
|
||||
fmt = "%d";
|
||||
break;
|
||||
case BPF_ALU_DIV | BPF_X:
|
||||
op = r_bpf_op_table[BPF_ALU_DIV];
|
||||
fmt = "x";
|
||||
break;
|
||||
case BPF_ALU_DIV | BPF_K:
|
||||
op = r_bpf_op_table[BPF_ALU_DIV];
|
||||
fmt = "%d";
|
||||
break;
|
||||
case BPF_ALU_MOD | BPF_X:
|
||||
op = r_bpf_op_table[BPF_ALU_MOD];
|
||||
fmt = "x";
|
||||
break;
|
||||
case BPF_ALU_MOD | BPF_K:
|
||||
op = r_bpf_op_table[BPF_ALU_MOD];
|
||||
fmt = "%d";
|
||||
break;
|
||||
case BPF_ALU_AND | BPF_X:
|
||||
op = r_bpf_op_table[BPF_ALU_AND];
|
||||
fmt = "x";
|
||||
break;
|
||||
case BPF_ALU_AND | BPF_K:
|
||||
op = r_bpf_op_table[BPF_ALU_AND];
|
||||
fmt = "%#x";
|
||||
break;
|
||||
case BPF_ALU_OR | BPF_X:
|
||||
op = r_bpf_op_table[BPF_ALU_OR];
|
||||
fmt = "x";
|
||||
break;
|
||||
case BPF_ALU_OR | BPF_K:
|
||||
op = r_bpf_op_table[BPF_ALU_OR];
|
||||
fmt = "%#x";
|
||||
break;
|
||||
case BPF_ALU_XOR | BPF_X:
|
||||
op = r_bpf_op_table[BPF_ALU_XOR];
|
||||
fmt = "x";
|
||||
break;
|
||||
case BPF_ALU_XOR | BPF_K:
|
||||
op = r_bpf_op_table[BPF_ALU_XOR];
|
||||
fmt = "%#x";
|
||||
break;
|
||||
default:
|
||||
op = "invalid";
|
||||
fmt = "%#x";
|
||||
val = f->code;
|
||||
break;
|
||||
}
|
||||
|
||||
memset (vbuf, 0, sizeof (vbuf));
|
||||
snprintf (vbuf, sizeof (vbuf), fmt, val);
|
||||
vbuf[sizeof (vbuf) - 1] = 0;
|
||||
|
||||
if ((BPF_CLASS (f->code) == BPF_JMP && BPF_OP (f->code) != BPF_JA))
|
||||
r_strbuf_setf (&r_op->buf_asm, "%s %s, 0x%08" PFMT64x ", 0x%08" PFMT64x "", op, vbuf,
|
||||
a->pc + 8 + f->jt * 8, a->pc + 8 + f->jf * 8);
|
||||
else r_strbuf_setf (&r_op->buf_asm, "%s %s", op, vbuf);
|
||||
|
||||
return r_op->size = 8;
|
||||
}
|
||||
|
||||
/* start of ASSEMBLER code */
|
||||
|
||||
#define PARSER_MAX_TOKENS 4
|
||||
|
||||
#define COPY_AND_RET(a, b)\
|
||||
r_strbuf_setbin (&a, (const ut8 *)b, sizeof (*b) + 1);\
|
||||
return 0;
|
||||
|
||||
#define PARSE_FAILURE(message, arg...)\
|
||||
{\
|
||||
eprintf ("PARSE FAILURE: " message "\n", ##arg);\
|
||||
return -1;\
|
||||
}
|
||||
|
||||
#define CMP4(tok, n, x, y, z, w)\
|
||||
(tok[n][0] == x && tok[n][1] == y && tok[n][2] == z && tok[n][3] == w)
|
||||
|
||||
#define CMP3(tok, n, x, y, z)\
|
||||
(tok[n][0] == x && tok[n][1] == y && tok[n][2] == z)
|
||||
|
||||
#define CMP2(tok, n, x, y)\
|
||||
(tok[n][0] == x && tok[n][1] == y)
|
||||
|
||||
#define IS_K_TOK(tok, n)\
|
||||
(tok[n][0] == '-' || R_BETWEEN ('0', tok[n][0], '9'))
|
||||
|
||||
#define IS_LEN(tok, n)\
|
||||
CMP4 (tok, n, 'l', 'e', 'n', '\0')
|
||||
|
||||
#define PARSE_K_OR_FAIL(dst, tok, n)\
|
||||
dst = strtol (&tok[n][0], &end, 0);\
|
||||
if (*end != '\0' && *end != ',')\
|
||||
PARSE_FAILURE ("could not parse k");
|
||||
|
||||
#define PARSE_LABEL_OR_FAIL(dst, tok, n)\
|
||||
dst = strtoul (&tok[n][0], &end, 0);\
|
||||
if (*end != '\0' && *end != ',') {\
|
||||
return -1;\
|
||||
}
|
||||
|
||||
#define PARSE_OFFSET_OR_FAIL(dst, tok, n, off)\
|
||||
dst = strtoul (&tok[n][off], &end, 10);\
|
||||
if (*end != ']')\
|
||||
PARSE_FAILURE ("could not parse offset value");
|
||||
|
||||
#define PARSE_IND_ABS_OR_FAIL(f, tok, n)\
|
||||
if (CMP3 (tok, 1, '[', 'x', '+')) {\
|
||||
f->code = f->code | BPF_IND;\
|
||||
PARSE_OFFSET_OR_FAIL (f->k, tok, 1, 3);\
|
||||
return 0;\
|
||||
} else if (tok[1][0] == '[') {\
|
||||
f->code = f->code | BPF_ABS;\
|
||||
PARSE_OFFSET_OR_FAIL (f->k, tok, 1, 1);\
|
||||
return 0;\
|
||||
}\
|
||||
PARSE_FAILURE ("could not parse addressing mode");
|
||||
|
||||
#define PARSE_K_OR_X_OR_FAIL(f, tok)\
|
||||
if (IS_K_TOK (tok, 1)) {\
|
||||
PARSE_K_OR_FAIL (f->k, tok, 1);\
|
||||
f->code = f->code | BPF_K;\
|
||||
} else if (tok[1][0] == 'x' && (tok[1][1] == '\0' || tok[1][1] == ',')) {\
|
||||
f->code = f->code | BPF_X;\
|
||||
} else {\
|
||||
PARSE_FAILURE ("could not parse k or x: %s", tok[1]);\
|
||||
}
|
||||
|
||||
#define PARSE_A_OR_X_OR_FAIL(f, tok)\
|
||||
if (tok[1][0] == 'x' && (tok[1][1] == '\0' || tok[1][1] == ',')) {\
|
||||
f->code = f->code | BPF_X;\
|
||||
} else if (tok[1][0] == 'a' && (tok[1][1] == '\0' || tok[1][1] == ',')) {\
|
||||
f->code = f->code | BPF_A;\
|
||||
} else {\
|
||||
PARSE_FAILURE ("could not parse a or x");\
|
||||
}
|
||||
|
||||
#define PARSE_JUMP_TARGETS(a, f, tok, count)\
|
||||
PARSE_K_OR_X_OR_FAIL (f, tok);\
|
||||
if (count >= 3) {\
|
||||
PARSE_LABEL_OR_FAIL (label, tok, 2);\
|
||||
f->jt = (st64) (label - a->pc - 8) / 8;\
|
||||
f->jf = (a->pc >> 3) + 1;\
|
||||
}\
|
||||
if (count == 4) {\
|
||||
PARSE_LABEL_OR_FAIL (label, tok, 3);\
|
||||
f->jf = (st64) (label - a->pc - 8) / 8;\
|
||||
}
|
||||
|
||||
#define SWAP_JUMP_TARGETS(f)\
|
||||
temp = f->jt;\
|
||||
f->jt = f->jf;\
|
||||
f->jf = temp;
|
||||
|
||||
#define ENFORCE_COUNT(count, n)\
|
||||
if (count != n)\
|
||||
PARSE_FAILURE ("invalid argument count, try to omit '#'");
|
||||
|
||||
#define ENFORCE_COUNT_GE(count, n)\
|
||||
if (count < n)\
|
||||
PARSE_FAILURE ("invalid argument count, try to omit '#'");
|
||||
|
||||
static int assemble_ld(RAsm *a, RAsmOp *op,
|
||||
char *tok[PARSER_MAX_TOKENS], int count, RBpfSockFilter *f) {
|
||||
char *end;
|
||||
|
||||
switch (tok[0][2]) {
|
||||
case '\0':
|
||||
if (CMP2 (tok, 1, 'm', '[')) {
|
||||
f->code = BPF_LD | BPF_MEM;
|
||||
PARSE_OFFSET_OR_FAIL (f->k, tok, 1, 2);
|
||||
} else if (IS_K_TOK (tok, 1)) {
|
||||
f->code = BPF_LD | BPF_IMM;
|
||||
PARSE_K_OR_FAIL (f->k, tok, 1);
|
||||
} else if (IS_LEN (tok, 1)) {
|
||||
f->code = BPF_LD | BPF_LEN;
|
||||
} else {
|
||||
f->code = BPF_LD_W;
|
||||
PARSE_IND_ABS_OR_FAIL (f, tok, 1);
|
||||
}
|
||||
break;
|
||||
case 'i':
|
||||
if (IS_K_TOK (tok, 1)) {
|
||||
f->code = BPF_LD | BPF_IMM;
|
||||
PARSE_K_OR_FAIL (f->k, tok, 1);
|
||||
} else {
|
||||
PARSE_FAILURE ("ldi without k");
|
||||
}
|
||||
break;
|
||||
case 'b':
|
||||
f->code = BPF_LD_B;
|
||||
PARSE_IND_ABS_OR_FAIL (f, tok, 1);
|
||||
break;
|
||||
case 'h':
|
||||
f->code = BPF_LD_H;
|
||||
PARSE_IND_ABS_OR_FAIL (f, tok, 1);
|
||||
break;
|
||||
case 'x':
|
||||
switch (tok[0][3]) {
|
||||
case '\0':
|
||||
if (CMP2 (tok, 1, 'm', '[')) {
|
||||
f->code = BPF_LDX | BPF_MEM;
|
||||
PARSE_OFFSET_OR_FAIL (f->k, tok, 1, 2);
|
||||
} else if (IS_K_TOK (tok, 1)) {
|
||||
f->code = BPF_LDX | BPF_IMM;
|
||||
PARSE_K_OR_FAIL (f->k, tok, 1);
|
||||
} else if (IS_LEN (tok, 1)) {
|
||||
f->code = BPF_LDX | BPF_LEN;
|
||||
} else {
|
||||
f->code = BPF_LDX_W;
|
||||
PARSE_IND_ABS_OR_FAIL (f, tok, 1);
|
||||
}
|
||||
break;
|
||||
case 'i':
|
||||
if (IS_K_TOK (tok, 1)) {
|
||||
f->code = BPF_LDX | BPF_IMM;
|
||||
PARSE_K_OR_FAIL (f->k, tok, 1);
|
||||
} else {
|
||||
PARSE_FAILURE ("ldxi without k");
|
||||
}
|
||||
break;
|
||||
case 'b':
|
||||
f->code = BPF_LDX_B | BPF_MSH;
|
||||
if (sscanf (tok[1], "4*([%d]&0xf)", &f->k) != 1) {
|
||||
PARSE_FAILURE ("invalid nibble addressing");
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
PARSE_FAILURE ("unsupported load instruction");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int assemble_j(RAsm *a, RAsmOp *op, char *tok[PARSER_MAX_TOKENS],
|
||||
int count, RBpfSockFilter *f) {
|
||||
int label;
|
||||
ut8 temp;
|
||||
char *end;
|
||||
|
||||
if (CMP4 (tok, 0, 'j', 'm', 'p', '\0') ||
|
||||
CMP3 (tok, 0, 'j', 'a', '\0')) {
|
||||
ENFORCE_COUNT (count, 2);
|
||||
f->code = BPF_JMP_JA;
|
||||
PARSE_LABEL_OR_FAIL (f->k, tok, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (CMP4 (tok, 0, 'j', 'n', 'e', '\0') ||
|
||||
CMP4 (tok, 0, 'j', 'n', 'e', 'q')) {
|
||||
ENFORCE_COUNT_GE (count, 3);
|
||||
f->code = BPF_JMP_JEQ;
|
||||
PARSE_JUMP_TARGETS (a, f, tok, count);
|
||||
SWAP_JUMP_TARGETS (f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (CMP4 (tok, 0, 'j', 'e', 'q', '\0')) {
|
||||
ENFORCE_COUNT_GE (count, 3);
|
||||
f->code = BPF_JMP_JEQ;
|
||||
PARSE_JUMP_TARGETS (a, f, tok, count);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (CMP4 (tok, 0, 'j', 'l', 't', '\0')) {
|
||||
ENFORCE_COUNT_GE (count, 3);
|
||||
f->code = BPF_JMP_JGE;
|
||||
PARSE_JUMP_TARGETS (a, f, tok, count);
|
||||
SWAP_JUMP_TARGETS (f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (CMP4 (tok, 0, 'j', 'l', 'e', '\0')) {
|
||||
ENFORCE_COUNT_GE (count, 3);
|
||||
f->code = BPF_JMP_JGT;
|
||||
PARSE_JUMP_TARGETS (a, f, tok, count);
|
||||
SWAP_JUMP_TARGETS (f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (CMP4 (tok, 0, 'j', 'g', 't', '\0')) {
|
||||
ENFORCE_COUNT_GE (count, 3);
|
||||
f->code = BPF_JMP_JGT;
|
||||
PARSE_JUMP_TARGETS (a, f, tok, count);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (CMP4 (tok, 0, 'j', 'g', 'e', '\0')) {
|
||||
ENFORCE_COUNT_GE (count, 3);
|
||||
f->code = BPF_JMP_JGE;
|
||||
PARSE_JUMP_TARGETS (a, f, tok, count);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (CMP4 (tok, 0, 'j', 's', 'e', 't')) {
|
||||
ENFORCE_COUNT_GE (count, 3);
|
||||
f->code = BPF_JMP_JSET;
|
||||
PARSE_JUMP_TARGETS (a, f, tok, count);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int assemble_alu(RAsm *a, RAsmOp *op, char *tok[PARSER_MAX_TOKENS],
|
||||
int count, RBpfSockFilter *f) {
|
||||
char *end;
|
||||
|
||||
if (CMP4 (tok, 0, 'a', 'd', 'd', '\0')) {
|
||||
ENFORCE_COUNT (count, 2);
|
||||
f->code = BPF_ALU_ADD;
|
||||
PARSE_K_OR_X_OR_FAIL (f, tok);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (CMP4 (tok, 0, 's', 'u', 'b', '\0')) {
|
||||
ENFORCE_COUNT (count, 2);
|
||||
f->code = BPF_ALU_SUB;
|
||||
PARSE_K_OR_X_OR_FAIL (f, tok);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (CMP4 (tok, 0, 'm', 'u', 'l', '\0')) {
|
||||
ENFORCE_COUNT (count, 2);
|
||||
f->code = BPF_ALU_MUL;
|
||||
PARSE_K_OR_X_OR_FAIL (f, tok);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (CMP4 (tok, 0, 'd', 'i', 'v', '\0')) {
|
||||
ENFORCE_COUNT (count, 2);
|
||||
f->code = BPF_ALU_DIV;
|
||||
PARSE_K_OR_X_OR_FAIL (f, tok);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (CMP4 (tok, 0, 'm', 'o', 'd', '\0')) {
|
||||
ENFORCE_COUNT (count, 2);
|
||||
f->code = BPF_ALU_MOD;
|
||||
PARSE_K_OR_X_OR_FAIL (f, tok);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (CMP4 (tok, 0, 'n', 'e', 'g', '\0')) {
|
||||
ENFORCE_COUNT (count, 1);
|
||||
f->code = BPF_ALU_NEG;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (CMP4 (tok, 0, 'a', 'n', 'd', '\0')) {
|
||||
ENFORCE_COUNT (count, 2);
|
||||
f->code = BPF_ALU_AND;
|
||||
PARSE_K_OR_X_OR_FAIL (f, tok);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (CMP3 (tok, 0, 'o', 'r', '\0')) {
|
||||
ENFORCE_COUNT (count, 2);
|
||||
f->code = BPF_ALU_OR;
|
||||
PARSE_K_OR_X_OR_FAIL (f, tok);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (CMP4 (tok, 0, 'x', 'o', 'r', '\0')) {
|
||||
ENFORCE_COUNT (count, 2);
|
||||
f->code = BPF_ALU_XOR;
|
||||
PARSE_K_OR_X_OR_FAIL (f, tok);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (CMP4 (tok, 0, 'l', 's', 'h', '\0')) {
|
||||
ENFORCE_COUNT (count, 2);
|
||||
f->code = BPF_ALU_LSH;
|
||||
PARSE_K_OR_X_OR_FAIL (f, tok);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (CMP4 (tok, 0, 'r', 's', 'h', '\0')) {
|
||||
ENFORCE_COUNT (count, 2);
|
||||
f->code = BPF_ALU_RSH;
|
||||
PARSE_K_OR_X_OR_FAIL (f, tok);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int assemble_tok(RAsm *a, RAsmOp *op,
|
||||
char *tok[PARSER_MAX_TOKENS], int count) {
|
||||
char *end;
|
||||
int oplen = 0;
|
||||
RBpfSockFilter f = { 0, 0, 0, 0 };
|
||||
oplen = strnlen (tok[0], 5);
|
||||
|
||||
if (oplen < 2 || oplen > 4) {
|
||||
PARSE_FAILURE ("mnemonic length not valid");
|
||||
}
|
||||
|
||||
if (CMP4 (tok, 0, 't', 'x', 'a', '\0')) {
|
||||
ENFORCE_COUNT (count, 1);
|
||||
f.code = BPF_MISC_TXA;
|
||||
COPY_AND_RET (op->buf, &f);
|
||||
}
|
||||
|
||||
if (CMP4 (tok, 0, 't', 'a', 'x', '\0')) {
|
||||
ENFORCE_COUNT (count, 1);
|
||||
f.code = BPF_MISC_TAX;
|
||||
COPY_AND_RET (op->buf, &f);
|
||||
}
|
||||
|
||||
if (CMP4 (tok, 0, 'r', 'e', 't', '\0')) {
|
||||
ENFORCE_COUNT (count, 2);
|
||||
if (IS_K_TOK (tok, 1)) {
|
||||
f.code = BPF_RET | BPF_K;
|
||||
PARSE_K_OR_FAIL (f.k, tok, 1);
|
||||
} else if (tok[1][0] == 'x') {
|
||||
f.code = BPF_RET | BPF_X;
|
||||
} else if (tok[1][0] == 'a') {
|
||||
f.code = BPF_RET | BPF_A;
|
||||
} else {
|
||||
PARSE_FAILURE ("unsupported ret instruction");
|
||||
}
|
||||
COPY_AND_RET (op->buf, &f);
|
||||
}
|
||||
|
||||
if (CMP2 (tok, 0, 'l', 'd')) {
|
||||
ENFORCE_COUNT (count, 2);
|
||||
if (assemble_ld (a, op, tok, count, &f) == 0) {
|
||||
COPY_AND_RET (op->buf, &f);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (CMP2 (tok, 0, 's', 't')) {
|
||||
ENFORCE_COUNT (count, 2);
|
||||
if (tok[0][2] == '\0') {
|
||||
f.code = BPF_ST;
|
||||
} else if (tok[0][2] == 'x') {
|
||||
f.code = BPF_STX;
|
||||
}
|
||||
|
||||
if (CMP2 (tok, 1, 'm', '[')) {
|
||||
PARSE_OFFSET_OR_FAIL (f.k, tok, 1, 2);
|
||||
if (f.k > 15) {
|
||||
PARSE_FAILURE ("mem addressing out of bounds");
|
||||
}
|
||||
COPY_AND_RET (op->buf, &f);
|
||||
} else {
|
||||
PARSE_FAILURE ("invalid store addressing");
|
||||
}
|
||||
}
|
||||
|
||||
if (tok[0][0] == 'j') {
|
||||
if (assemble_j (a, op, tok, count, &f) == 0) {
|
||||
COPY_AND_RET (op->buf, &f);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (assemble_alu (a, op, tok, count, &f) == 0) {
|
||||
COPY_AND_RET (op->buf, &f);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static void lower_op(char *c) {
|
||||
if ((c[0] <= 'Z') && (c[0] >= 'A')) {
|
||||
c[0] += 0x20;
|
||||
}
|
||||
}
|
||||
#define R_TRUE 1
|
||||
static void normalize(RStrBuf *buf) {
|
||||
int i;
|
||||
char *buf_asm;
|
||||
if (!buf)
|
||||
return;
|
||||
buf_asm = r_strbuf_get (buf);
|
||||
|
||||
/* this normalization step is largely sub-optimal */
|
||||
|
||||
i = strlen (buf_asm);
|
||||
while (strstr (buf_asm, " ")) {
|
||||
r_str_replace_in (buf_asm, (ut32)i, " ", " ", R_TRUE);
|
||||
}
|
||||
r_str_replace_in (buf_asm, (ut32)i, " ,", ",", R_TRUE);
|
||||
r_str_replace_in (buf_asm, (ut32)i, "[ ", "[", R_TRUE);
|
||||
r_str_replace_in (buf_asm, (ut32)i, " ]", "]", R_TRUE);
|
||||
r_str_replace_in (buf_asm, (ut32)i, "( ", "(", R_TRUE);
|
||||
r_str_replace_in (buf_asm, (ut32)i, " )", ")", R_TRUE);
|
||||
r_str_replace_in (buf_asm, (ut32)i, "+ ", "+", R_TRUE);
|
||||
r_str_replace_in (buf_asm, (ut32)i, " +", "+", R_TRUE);
|
||||
r_str_replace_in (buf_asm, (ut32)i, "* ", "*", R_TRUE);
|
||||
r_str_replace_in (buf_asm, (ut32)i, " *", "*", R_TRUE);
|
||||
r_str_replace_in (buf_asm, (ut32)i, "& ", "&", R_TRUE);
|
||||
r_str_replace_in (buf_asm, (ut32)i, " &", "&", R_TRUE);
|
||||
r_str_replace_in (buf_asm, (ut32)i, "%", "", R_TRUE);
|
||||
r_str_replace_in (buf_asm, (ut32)i, "#", "", R_TRUE);
|
||||
r_str_do_until_token (lower_op, buf_asm, '\0');
|
||||
r_strbuf_set (buf, buf_asm);
|
||||
}
|
||||
|
||||
static int assemble(RAsm *a, RAsmOp *op, const char *buf) {
|
||||
char *tok[PARSER_MAX_TOKENS];
|
||||
char tmp[128];
|
||||
int i, j, l;
|
||||
const char *p = NULL;
|
||||
if (!a || !op || !buf) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
r_strbuf_set (&op->buf_asm, buf);
|
||||
normalize (&op->buf_asm);
|
||||
|
||||
// tokenization, copied from profile.c
|
||||
j = 0;
|
||||
p = r_strbuf_get (&op->buf_asm);
|
||||
|
||||
// For every word
|
||||
while (*p) {
|
||||
// Skip the whitespace
|
||||
while (*p == ' ' || *p == '\t') {
|
||||
p++;
|
||||
}
|
||||
// Skip the rest of the line is a comment is encountered
|
||||
if (*p == ';') {
|
||||
while (*p != '\0') {
|
||||
p++;
|
||||
}
|
||||
}
|
||||
// EOL ?
|
||||
if (*p == '\0') {
|
||||
break;
|
||||
}
|
||||
// Gather a handful of chars
|
||||
// Use isgraph instead of isprint because the latter considers ' ' printable
|
||||
for (i = 0; isgraph ((const unsigned char)*p) && i < sizeof (tmp) - 1;) {
|
||||
tmp[i++] = *p++;
|
||||
}
|
||||
tmp[i] = '\0';
|
||||
// Limit the number of tokens
|
||||
if (j > PARSER_MAX_TOKENS - 1) {
|
||||
break;
|
||||
}
|
||||
// Save the token
|
||||
tok[j++] = strdup (tmp);
|
||||
}
|
||||
|
||||
if (j) {
|
||||
if (assemble_tok (a, op, tok, j) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Clean up
|
||||
for (i = 0; i < j; i++) {
|
||||
free (tok[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return op->size = 8;
|
||||
}
|
||||
|
||||
RAsmPlugin r_asm_plugin_bpf = {
|
||||
.name = "bpf",
|
||||
.desc = "Berkeley Packet Filter disassembler",
|
||||
.license = "GPLv2",
|
||||
.arch = "bpf",
|
||||
.bits = 32,
|
||||
.disassemble = &disassemble,
|
||||
.assemble = &assemble
|
||||
};
|
||||
|
||||
#ifndef CORELIB
|
||||
struct r_lib_struct_t radare_plugin = {
|
||||
.type = R_LIB_TYPE_ASM,
|
||||
.data = &r_asm_plugin_bpf,
|
||||
.version = R2_VERSION
|
||||
};
|
||||
#endif
|
||||
@@ -1,98 +0,0 @@
|
||||
/* LGPL3 - Copyright 2015 - mrmacete */
|
||||
/* it's a blatant copy of "any" bin plugin from radare, big_endian = 1 */
|
||||
|
||||
#include <r_types.h>
|
||||
#include <r_util.h>
|
||||
#include <r_lib.h>
|
||||
#include <r_bin.h>
|
||||
#include <r_magic.h>
|
||||
|
||||
static char *get_filetype(RBinFile *arch) {
|
||||
ut8 buf[4096] = { 0 };
|
||||
char *res = NULL;
|
||||
RMagic *ck;
|
||||
if (!arch)
|
||||
return NULL;
|
||||
ck = r_magic_new (0);
|
||||
if (ck && arch && arch->buf) {
|
||||
const char *tmp = NULL;
|
||||
r_magic_load (ck, R2_SDB_MAGIC);
|
||||
r_buf_read_at (arch->buf, 0, buf, sizeof (buf));
|
||||
tmp = r_magic_buffer (ck, buf, sizeof (buf));
|
||||
if (tmp)
|
||||
res = strdup (tmp);
|
||||
}
|
||||
r_magic_free (ck);
|
||||
return res;
|
||||
}
|
||||
|
||||
static RBinInfo *info(RBinFile *arch) {
|
||||
RBinInfo *ret = R_NEW0 (RBinInfo);
|
||||
if (!ret)
|
||||
return NULL;
|
||||
ret->lang = "";
|
||||
ret->file = arch->file ? strdup (arch->file) : NULL;
|
||||
ret->type = get_filetype (arch);
|
||||
ret->has_pi = 0;
|
||||
ret->has_canary = 0;
|
||||
if (R_SYS_BITS & R_SYS_BITS_64) {
|
||||
ret->bits = 64;
|
||||
} else {
|
||||
ret->bits = 32;
|
||||
}
|
||||
ret->big_endian = 1;
|
||||
ret->has_va = 0;
|
||||
ret->has_nx = 0;
|
||||
ret->dbg_info = 0;
|
||||
ret->dbg_info = 0;
|
||||
ret->dbg_info = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool load(RBinFile *arch) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static int destroy(RBinFile *arch) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static ut64 baddr(RBinFile *arch) {
|
||||
return 0LL;
|
||||
}
|
||||
|
||||
struct r_bin_plugin_t r_bin_plugin_bpf = {
|
||||
.name = "bpf",
|
||||
.desc = "Berkeley Packet Filter - raw binary",
|
||||
.license = "LGPL3",
|
||||
.init = NULL,
|
||||
.fini = NULL,
|
||||
.get_sdb = NULL,
|
||||
.load = &load,
|
||||
.load_bytes = NULL,
|
||||
.destroy = &destroy,
|
||||
.baddr = &baddr,
|
||||
.boffset = NULL,
|
||||
.binsym = NULL,
|
||||
.entries = NULL,
|
||||
.sections = NULL,
|
||||
.symbols = NULL,
|
||||
.imports = NULL,
|
||||
.strings = NULL,
|
||||
.info = info,
|
||||
.fields = NULL,
|
||||
.libs = NULL,
|
||||
.relocs = NULL,
|
||||
.dbginfo = NULL,
|
||||
.create = NULL,
|
||||
.write = NULL,
|
||||
.minstrlen = 0,
|
||||
};
|
||||
|
||||
#ifndef CORELIB
|
||||
struct r_lib_struct_t radare_plugin = {
|
||||
.type = R_LIB_TYPE_BIN,
|
||||
.data = &r_bin_plugin_bpf,
|
||||
.version = R2_VERSION
|
||||
};
|
||||
#endif
|
||||
BIN
Binary file not shown.
@@ -1,82 +0,0 @@
|
||||
/*
|
||||
* Most of this is copied and pasted from linux kernel source
|
||||
*
|
||||
* Copyright 2015 - mrmacete <[email protected]>
|
||||
* Licensed under the GNU General Public License, version 2.0 (GPLv2)
|
||||
*/
|
||||
|
||||
#ifndef _BPF_H_
|
||||
#define _BPF_H_
|
||||
|
||||
#include "bpf_common.h"
|
||||
|
||||
/* defines ripped from linux/filter.h : */
|
||||
|
||||
#define BPF_A 0x10
|
||||
#define BPF_TAX 0x00
|
||||
#define BPF_TXA 0x80
|
||||
|
||||
/* defines ripped from bpf_dbg.c : */
|
||||
|
||||
#define BPF_LDX_B (BPF_LDX | BPF_B)
|
||||
#define BPF_LDX_W (BPF_LDX | BPF_W)
|
||||
#define BPF_JMP_JA (BPF_JMP | BPF_JA)
|
||||
#define BPF_JMP_JEQ (BPF_JMP | BPF_JEQ)
|
||||
#define BPF_JMP_JGT (BPF_JMP | BPF_JGT)
|
||||
#define BPF_JMP_JGE (BPF_JMP | BPF_JGE)
|
||||
#define BPF_JMP_JSET (BPF_JMP | BPF_JSET)
|
||||
#define BPF_ALU_ADD (BPF_ALU | BPF_ADD)
|
||||
#define BPF_ALU_SUB (BPF_ALU | BPF_SUB)
|
||||
#define BPF_ALU_MUL (BPF_ALU | BPF_MUL)
|
||||
#define BPF_ALU_DIV (BPF_ALU | BPF_DIV)
|
||||
#define BPF_ALU_MOD (BPF_ALU | BPF_MOD)
|
||||
#define BPF_ALU_NEG (BPF_ALU | BPF_NEG)
|
||||
#define BPF_ALU_AND (BPF_ALU | BPF_AND)
|
||||
#define BPF_ALU_OR (BPF_ALU | BPF_OR)
|
||||
#define BPF_ALU_XOR (BPF_ALU | BPF_XOR)
|
||||
#define BPF_ALU_LSH (BPF_ALU | BPF_LSH)
|
||||
#define BPF_ALU_RSH (BPF_ALU | BPF_RSH)
|
||||
#define BPF_MISC_TAX (BPF_MISC | BPF_TAX)
|
||||
#define BPF_MISC_TXA (BPF_MISC | BPF_TXA)
|
||||
#define BPF_LD_B (BPF_LD | BPF_B)
|
||||
#define BPF_LD_H (BPF_LD | BPF_H)
|
||||
#define BPF_LD_W (BPF_LD | BPF_W)
|
||||
|
||||
static const char * const r_bpf_op_table[] = {
|
||||
[BPF_ST] = "st",
|
||||
[BPF_STX] = "stx",
|
||||
[BPF_LD_B] = "ldb",
|
||||
[BPF_LD_H] = "ldh",
|
||||
[BPF_LD_W] = "ld",
|
||||
[BPF_LDX] = "ldx",
|
||||
[BPF_LDX_B] = "ldxb",
|
||||
[BPF_JMP_JA] = "ja",
|
||||
[BPF_JMP_JEQ] = "jeq",
|
||||
[BPF_JMP_JGT] = "jgt",
|
||||
[BPF_JMP_JGE] = "jge",
|
||||
[BPF_JMP_JSET] = "jset",
|
||||
[BPF_ALU_ADD] = "add",
|
||||
[BPF_ALU_SUB] = "sub",
|
||||
[BPF_ALU_MUL] = "mul",
|
||||
[BPF_ALU_DIV] = "div",
|
||||
[BPF_ALU_MOD] = "mod",
|
||||
[BPF_ALU_NEG] = "neg",
|
||||
[BPF_ALU_AND] = "and",
|
||||
[BPF_ALU_OR] = "or",
|
||||
[BPF_ALU_XOR] = "xor",
|
||||
[BPF_ALU_LSH] = "lsh",
|
||||
[BPF_ALU_RSH] = "rsh",
|
||||
[BPF_MISC_TAX] = "tax",
|
||||
[BPF_MISC_TXA] = "txa",
|
||||
[BPF_RET] = "ret",
|
||||
};
|
||||
|
||||
|
||||
typedef struct r_bpf_sock_filter { /* Filter block */
|
||||
ut16 code; /* Actual filter code */
|
||||
st8 jt; /* Jump true */
|
||||
st8 jf; /* Jump false */
|
||||
ut32 k; /* Generic multiuse field */
|
||||
} RBpfSockFilter;
|
||||
|
||||
#endif
|
||||
@@ -1,60 +0,0 @@
|
||||
/*
|
||||
* this file is directly copied from linux source
|
||||
* Licensed under the GNU General Public License, version 2.0 (GPLv2)
|
||||
*/
|
||||
|
||||
#ifndef _UAPI__LINUX_BPF_COMMON_H__
|
||||
#define _UAPI__LINUX_BPF_COMMON_H__
|
||||
|
||||
/* Instruction classes */
|
||||
#define BPF_CLASS(code) ((code) & 0x07)
|
||||
#define BPF_LD 0x00
|
||||
#define BPF_LDX 0x01
|
||||
#define BPF_ST 0x02
|
||||
#define BPF_STX 0x03
|
||||
#define BPF_ALU 0x04
|
||||
#define BPF_JMP 0x05
|
||||
#define BPF_RET 0x06
|
||||
#define BPF_MISC 0x07
|
||||
|
||||
/* ld/ldx fields */
|
||||
#define BPF_SIZE(code) ((code) & 0x18)
|
||||
#define BPF_W 0x00
|
||||
#define BPF_H 0x08
|
||||
#define BPF_B 0x10
|
||||
#define BPF_MODE(code) ((code) & 0xe0)
|
||||
#define BPF_IMM 0x00
|
||||
#define BPF_ABS 0x20
|
||||
#define BPF_IND 0x40
|
||||
#define BPF_MEM 0x60
|
||||
#define BPF_LEN 0x80
|
||||
#define BPF_MSH 0xa0
|
||||
|
||||
/* alu/jmp fields */
|
||||
#define BPF_OP(code) ((code) & 0xf0)
|
||||
#define BPF_ADD 0x00
|
||||
#define BPF_SUB 0x10
|
||||
#define BPF_MUL 0x20
|
||||
#define BPF_DIV 0x30
|
||||
#define BPF_OR 0x40
|
||||
#define BPF_AND 0x50
|
||||
#define BPF_LSH 0x60
|
||||
#define BPF_RSH 0x70
|
||||
#define BPF_NEG 0x80
|
||||
#define BPF_MOD 0x90
|
||||
#define BPF_XOR 0xa0
|
||||
|
||||
#define BPF_JA 0x00
|
||||
#define BPF_JEQ 0x10
|
||||
#define BPF_JGT 0x20
|
||||
#define BPF_JGE 0x30
|
||||
#define BPF_JSET 0x40
|
||||
#define BPF_SRC(code) ((code) & 0x08)
|
||||
#define BPF_K 0x00
|
||||
#define BPF_X 0x08
|
||||
|
||||
#ifndef BPF_MAXINSNS
|
||||
#define BPF_MAXINSNS 4096
|
||||
#endif
|
||||
|
||||
#endif /* _UAPI__LINUX_BPF_COMMON_H__ */
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/bin/sh
|
||||
# This script was automatically generated by ACR v1.8.1
|
||||
# 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
|
||||
@@ -41,6 +41,11 @@ shift
|
||||
done
|
||||
}
|
||||
|
||||
QUIET=0
|
||||
be_quiet() {
|
||||
QUIET=1
|
||||
}
|
||||
|
||||
VPATH=`dirname ${0}`
|
||||
if [ "${VPATH}" = "." ]; then
|
||||
WODIS=current
|
||||
@@ -62,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"
|
||||
@@ -78,15 +97,19 @@ CROSSBUILD=0
|
||||
BUILD=`guess_os`
|
||||
HOST="${BUILD}"
|
||||
TARGET="${HOST}"
|
||||
ETCDIR="/etc"
|
||||
SYSCONFDIR=""
|
||||
DESCRIPTION=""
|
||||
|
||||
create_environ() {
|
||||
: ${EPREFIX:="${PREFIX}"}
|
||||
: ${SPREFIX:="${PREFIX}"}
|
||||
: ${BINDIR:="${SPREFIX}/bin"}
|
||||
: ${SBINDIR:="${PREFIX}/sbin"}
|
||||
: ${SYSCONFDIR:="${SPREFIX}/etc"}
|
||||
: ${ETCDIR:="${SPREFIX}/etc"}
|
||||
: ${LIBDIR:="${SPREFIX}/lib"}
|
||||
: ${PKGCFG_LIBDIR:='${exec_prefix}/lib'}
|
||||
: ${PKGCFG_INCDIR:='${prefix}/include'}
|
||||
: ${LIBEXECDIR:="${SPREFIX}/libexec"}
|
||||
: ${INCLUDEDIR:="${SPREFIX}/include"}
|
||||
: ${DATADIR:="${SPREFIX}/share"}
|
||||
@@ -105,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='4.4.0' ; VERSION_MAJOR=4; VERSION_MINOR=4; VERSION_PATCH=0; VERSION_NUMBER=40400; 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-4.4.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]...
|
||||
|
||||
@@ -122,6 +145,7 @@ Defaults for the options are specified in brackets.
|
||||
Configuration:
|
||||
-h, --help display this help and exit
|
||||
-r, --report show what libs/programs require to work
|
||||
-q, --quiet be quiet, less verbose (see ./configure -qV)
|
||||
-V, --version display version information and exit
|
||||
|
||||
Installation directories:
|
||||
@@ -141,6 +165,7 @@ Fine tuning of the installation directories:
|
||||
--localstatedir=DIR modifiable single-machine data [PREFIX/var]
|
||||
--mandir=DIR man documentation [DATADIR/man]
|
||||
--sbindir=DIR system admin executables [EPREFIX/sbin]
|
||||
--etcdir=DIR same as --sysconfdir (/etc)
|
||||
--sysconfdir=DIR read-only single-machine data [PREFIX/etc]
|
||||
--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
|
||||
|
||||
@@ -159,7 +184,6 @@ printf "
|
||||
Some influential environment variables:
|
||||
CC C compiler command
|
||||
CFLAGS C compiler flags
|
||||
CPPFLAGS C preprocessor flags
|
||||
LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
|
||||
nonstandard directory <lib dir>
|
||||
CPPFLAGS C/C++ preprocessor flags, e.g. -I<include dir> if you have
|
||||
@@ -179,8 +203,22 @@ take_environ() {
|
||||
: ${PREFIX:=/usr/local/}
|
||||
}
|
||||
|
||||
ochof() {
|
||||
[ "$QUIET" = 1 ] && return
|
||||
printf "$*"
|
||||
}
|
||||
|
||||
ocho() {
|
||||
[ "$QUIET" = 1 ] && return
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
show_version() {
|
||||
echo "radare2-extras-4.4.0 configuration script done with acr v1.8.1.
|
||||
if [ "$QUIET" = 1 ]; then
|
||||
echo "6.0.0"
|
||||
exit 0
|
||||
fi
|
||||
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
|
||||
@@ -200,15 +238,22 @@ fi
|
||||
case $flag in
|
||||
-h|--help|--hel|--h|--he|-help)
|
||||
show_usage ; ;;
|
||||
-qV|-quiet-version|--quiet-version)
|
||||
be_quiet
|
||||
show_version ; ;;
|
||||
-q|-quiet|--quiet)
|
||||
be_quiet ; ;;
|
||||
-V|-version|--version)
|
||||
show_version ; ;;
|
||||
-r|--r|--report)
|
||||
echo "PKGNAME: radare2-extras"
|
||||
echo "VERSION: 4.4.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)
|
||||
@@ -238,16 +283,22 @@ echo "FLAGS: --with-ostype=auto --without-ewf"
|
||||
--datadir)
|
||||
DATADIR="$value"; ;;
|
||||
--sysconfdir)
|
||||
SYSCONFDIR="$value"; ;;
|
||||
SYSCONFDIR="$value"
|
||||
ETCDIR="$value"; ;;
|
||||
--etcdir)
|
||||
SYSCONFDIR="$value"
|
||||
ETCDIR="$value"; ;;
|
||||
--sharedstatedir)
|
||||
SHAREDSTATEDIR="$value"; ;;
|
||||
--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"; ;;
|
||||
@@ -273,38 +324,68 @@ parse_options "$1"
|
||||
shift
|
||||
done
|
||||
|
||||
ENVWORDS="MANDIR INFODIR LIBDIR INCLUDEDIR LOCALSTATEDIR 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 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
|
||||
|
||||
echo "checking build system type... ${BUILD}"
|
||||
echo "checking host system type... ${HOST}"
|
||||
echo "checking target system type... ${TARGET}"
|
||||
ocho "checking build system type... ${BUILD}"
|
||||
ocho "checking host system type... ${HOST}"
|
||||
ocho "checking target system type... ${TARGET}"
|
||||
[ "${CROSSBUILD}" = 1 ] && echo "using crosscompilation mode."
|
||||
|
||||
#split_host BUILD HOST TARGET
|
||||
[ -n "${prefix}" ] && PREFIX="${prefix}"
|
||||
echo "checking for working directories... ${WODIS}"
|
||||
echo "using prefix '${PREFIX}'"
|
||||
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}"
|
||||
else
|
||||
ocho "PKGCONFIG env is not executable"
|
||||
PKGCONFIG=""
|
||||
fi
|
||||
else
|
||||
IFS=:
|
||||
for A in ${PATH} ; do
|
||||
if [ -x "${A}/pkg-config" ]; then
|
||||
PKGCONFIG="${A}/pkg-config"
|
||||
elif [ -x "${A}/pkgconf" ]; then
|
||||
PKGCONFIG="${A}/pkgconf"
|
||||
else
|
||||
continue
|
||||
fi
|
||||
break
|
||||
done
|
||||
unset IFS
|
||||
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
|
||||
COMPILER=CC
|
||||
printf "checking for c compiler... "
|
||||
ochof "checking for c compiler... "
|
||||
HAVE_LANG_C=1
|
||||
if [ "${CROSSBUILD}" = 1 ]; then
|
||||
(command -v ${HOST}-${CC} >/dev/null 2>&1)
|
||||
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
|
||||
echo "ERROR: ${CC} cannot create executables" >&2 ;
|
||||
exit 1 ; fi
|
||||
[ -z "${PKGCONFIG}" ] && PKGCONFIG=pkg-config
|
||||
type ${PKGCONFIG} > /dev/null 2>&1 || echo "ERROR: Cannot find PKGCONFIG ${PKGCONFIG}"
|
||||
if [ -z "${PKGCONFIG}" ]; then pkg-config --version >/dev/null 2>&1 ; if [ 0 = 0 ]; then PKGCONFIG=pkg-config ; else PKGCONFIG=pkgconf ; fi; fi
|
||||
type ${PKGCONFIG} > /dev/null 2>&1 || echo "ERROR: Cannot find valid PKGCONFIG, pkg-config or pkgconf in PATH"
|
||||
echo 'Using PKGCONFIG: '${PKGCONFIG}
|
||||
printf 'checking pkg-config flags for r_core... '
|
||||
tmp=`${PKGCONFIG} --cflags r_core 2>/dev/null`
|
||||
@@ -324,7 +405,7 @@ S="$"
|
||||
_REQUIRED=$3
|
||||
_CHKLIB_NAME=$2
|
||||
_CHKLIB_LIBS=$(echo "-l${_CHKLIB_NAME}" | sed 's,+, -l,g')
|
||||
printf "checking for lib${_CHKLIB_NAME} ... "
|
||||
ochof "checking for lib${_CHKLIB_NAME} ... "
|
||||
echo "int main(int ac, char **av){return 0;}" > test.c
|
||||
eval ${S}${COMPILER} ${CFLAGS} ${CPPFLAGS} ${CXXFLAGS} ${LDFLAGS} ${_CHKLIB_LIBS} test.c >/dev/null 2>&1
|
||||
if [ $? = 0 ]; then
|
||||
@@ -342,7 +423,7 @@ fi
|
||||
}
|
||||
|
||||
check_library HAVE_LIB_EWF ewf 0
|
||||
[ -z "${PKGCONFIG}" ] && PKGCONFIG=pkg-config
|
||||
if [ -z "${PKGCONFIG}" ]; then pkg-config --version >/dev/null 2>&1 ; if [ 0 = 0 ]; then PKGCONFIG=pkg-config ; else PKGCONFIG=pkgconf ; fi; fi
|
||||
printf 'checking pkg-config flags for libewf... '
|
||||
tmp=`${PKGCONFIG} --cflags libewf 2>/dev/null`
|
||||
if [ $? != 0 ]; then echo no ; HAVE_PKGCFG_LIBEWF=0;
|
||||
@@ -359,7 +440,7 @@ else
|
||||
HAVE_LIB_EWF="0"; fi
|
||||
if [ "$WANT_EWF" = "0" ]; then
|
||||
HAVE_LIB_EWF="0"; fi
|
||||
[ -z "${PKGCONFIG}" ] && PKGCONFIG=pkg-config
|
||||
if [ -z "${PKGCONFIG}" ]; then pkg-config --version >/dev/null 2>&1 ; if [ 0 = 0 ]; then PKGCONFIG=pkg-config ; else PKGCONFIG=pkgconf ; fi; fi
|
||||
printf 'checking pkg-config flags for unicorn... '
|
||||
tmp=`${PKGCONFIG} --cflags unicorn 2>/dev/null`
|
||||
if [ $? != 0 ]; then echo no ; HAVE_PKGCFG_UNICORN=0;
|
||||
@@ -371,7 +452,7 @@ if [ $? = 0 ]; then
|
||||
echo yes; HAVE_PKGCFG_UNICORN=1;
|
||||
UC_LDFLAGS=$tmp; fi; fi
|
||||
check_library HAVE_LIB_YARA yara 0
|
||||
[ -z "${PKGCONFIG}" ] && PKGCONFIG=pkg-config
|
||||
if [ -z "${PKGCONFIG}" ]; then pkg-config --version >/dev/null 2>&1 ; if [ 0 = 0 ]; then PKGCONFIG=pkg-config ; else PKGCONFIG=pkgconf ; fi; fi
|
||||
printf 'checking pkg-config flags for yara... '
|
||||
tmp=`${PKGCONFIG} --cflags yara 2>/dev/null`
|
||||
if [ $? != 0 ]; then echo no ; HAVE_PKGCFG_YARA=0;
|
||||
@@ -388,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;"
|
||||
@@ -406,8 +494,8 @@ if [ -f "${VPATH}/${A}.acr" ]; then
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
echo "creating ${SD_TARGET}"
|
||||
mkdir -p $(echo ${A} | sed -e "s,/`basename ${A}`$,,g")
|
||||
ocho "creating ${SD_TARGET}"
|
||||
[ "${VPATH}" != '.' ] && mkdir -p $(echo ${A} | sed -e "s,/`basename ${A}`$,,g")
|
||||
cat ${VPATH}/${SD_TARGET}.acr | \
|
||||
eval sed -e "s,@VPATH@,${VPATH}/${A},g" ${SEDFLAGS} > ${SD_TARGET}.tmp
|
||||
|
||||
@@ -426,10 +514,12 @@ done
|
||||
done
|
||||
|
||||
do_remove
|
||||
if [ "$QUIET" = 0 ]; then
|
||||
echo
|
||||
echo "Final report:"
|
||||
for A in PREFIX ; do # REPORT
|
||||
for A in PREFIX ; do
|
||||
eval VAL="\$${A}"
|
||||
[ -z "${VAL}" ] && VAL="(null)"
|
||||
[ -z "${VAL}" ] && VAL="\"\""
|
||||
echo " - ${A} = ${VAL}"
|
||||
done
|
||||
fi
|
||||
+3
-1
@@ -1,7 +1,9 @@
|
||||
PKGNAME radare2-extras
|
||||
VERSION 4.4.0
|
||||
VERSION 6.0.0
|
||||
CONTACT pancake ; [email protected]
|
||||
|
||||
USE_PKGCONFIG!
|
||||
|
||||
REPORT PREFIX ;
|
||||
|
||||
LANG_C!
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
#!/bin/sh
|
||||
FILE=$1
|
||||
type addr2line > /dev/null 2>&1
|
||||
if [ $? = 0 ]; then
|
||||
ADDRS=`objdump -d "$FILE" |grep :| grep -v 0000000| grep -v Disas|cut -d : -f1`
|
||||
addr2line -pa -e "$FILE" $ADDRS | sed -e 's,:,,' -e 's,^,CL ,' | grep -v '?'
|
||||
else
|
||||
echo "Unable to find 'addr2line' executable in PATH"
|
||||
exit 1
|
||||
fi
|
||||
@@ -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']
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
D=$(DESTDIR)/$(shell r2 -H R2_USER_PLUGINS)/iref-db
|
||||
BINDIR=$(shell r2pm -H R2PM_BINDIR)
|
||||
B=$(DESTDIR)/$(BINDIR)/
|
||||
|
||||
all:
|
||||
|
||||
clean:
|
||||
|
||||
install: user-install
|
||||
|
||||
user-uninstall uninstall:
|
||||
rm -f "$(B)/iref"
|
||||
rm -rf "$(D)"
|
||||
|
||||
user-install:
|
||||
mkdir -p "$(B)"
|
||||
cp iref.sh $(B)/iref
|
||||
chmod +x $(B)/iref
|
||||
mkdir -p "$(D)"
|
||||
tar xJvf iref-db.txz -C $(D)
|
||||
|
||||
sync: cutterref
|
||||
rm -rf iref-db
|
||||
cd cutterref/archs && tar cJvf ../../iref-db.txz *.sql
|
||||
|
||||
cutterref:
|
||||
git clone https://github.com/yossizap/cutterref
|
||||
|
||||
.PHONY: sync all install user-install user-uninstall uninstall clean
|
||||
@@ -0,0 +1,24 @@
|
||||
iref
|
||||
====
|
||||
|
||||
This is a commandline version of the cutterref tool.
|
||||
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
```
|
||||
$ r2pm -ci iref
|
||||
```
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
See this video demo: [https://youtu.be/jne9e_kBS8E](https://youtu.be/jne9e_kBS8E)
|
||||
|
||||
```
|
||||
$ r2 /bin/ls
|
||||
> "$a=!!iref x86-64 `ao~mnemonic[1]`"
|
||||
> $a
|
||||
> !iref x86-64 nop
|
||||
```
|
||||
Binary file not shown.
@@ -0,0 +1,28 @@
|
||||
#!/bin/sh
|
||||
|
||||
A="$1"
|
||||
M="`echo $2 |tr '[a-z]' '[A-Z]'`"
|
||||
|
||||
R2_USER_PLUGINS=$(r2 -H R2_USER_PLUGINS)
|
||||
if [ -z "$A" ]; then
|
||||
echo "Usage: iref [arch] ([insn])"
|
||||
if [ ! -d iref-db ]; then
|
||||
cd "$R2_USER_PLUGINS" || exit 1
|
||||
fi
|
||||
cd iref-db
|
||||
ls |sed -e 's,.sql,,'
|
||||
exit 1
|
||||
fi
|
||||
if [ ! -f "iref-db/$A.sql" ]; then
|
||||
cd "$R2_USER_PLUGINS" || exit 1
|
||||
if [ ! -f "iref-db/$A.sql" ]; then
|
||||
echo "Cannot load $A"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$M" ]; then
|
||||
echo "select mnem from instructions" | sqlite3 -init iref-db/$A.sql | tr 'A-Z' 'a-z'
|
||||
else
|
||||
echo "select description from instructions where mnem = '$M'" | sqlite3 -init iref-db/$A.sql
|
||||
fi
|
||||
+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:
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
/* radare2-keystone - GPL - Copyright 2016-2023 - pancake */
|
||||
|
||||
#include <r_arch.h>
|
||||
#include <r_lib.h>
|
||||
#include <keystone/keystone.h>
|
||||
#include <keystone/arm.h>
|
||||
#include "keystone.c"
|
||||
|
||||
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) {
|
||||
case 16:
|
||||
mode = KS_MODE_THUMB;
|
||||
break;
|
||||
case 64:
|
||||
arch = KS_ARCH_ARM64;
|
||||
mode = KS_MODE_LITTLE_ENDIAN;
|
||||
a->config->big_endian = false;
|
||||
break;
|
||||
}
|
||||
if (a->config->big_endian) {
|
||||
mode = (ks_mode)((int)mode | KS_MODE_BIG_ENDIAN);
|
||||
}
|
||||
return keystone_assemble (a, ao, ao->mnemonic, arch, mode);
|
||||
}
|
||||
|
||||
RArchPlugin r_arch_plugin_arm_ks = {
|
||||
.meta = {
|
||||
.name = "arm.ks",
|
||||
.desc = "ARM keystone assembler",
|
||||
.license = "GPL",
|
||||
},
|
||||
.arch = "arm",
|
||||
.bits = R_SYS_BITS_PACK3 (16, 32, 64),
|
||||
.encode = &assemble,
|
||||
.decode = NULL,
|
||||
};
|
||||
|
||||
#ifndef CORELIB
|
||||
RLibStruct radare_plugin = {
|
||||
.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
|
||||
@@ -0,0 +1,45 @@
|
||||
/* radare2-keystone - GPL - Copyright 2016-2023 - pancake */
|
||||
|
||||
#include <r_arch.h>
|
||||
#include <r_lib.h>
|
||||
#include <keystone/keystone.h>
|
||||
#include <keystone/mips.h>
|
||||
#include "keystone.c"
|
||||
|
||||
static bool assemble(RArchSession *a, RAnalOp *ao, RArchEncodeMask mask) {
|
||||
ks_mode mode;
|
||||
switch (a->config->bits) {
|
||||
case 16:
|
||||
mode = KS_MODE_MICRO; // micromips mode
|
||||
break;
|
||||
case 32:
|
||||
mode = KS_MODE_MIPS32;
|
||||
break;
|
||||
case 64:
|
||||
mode = KS_MODE_MIPS64;
|
||||
break;
|
||||
}
|
||||
if (a->config->big_endian) {
|
||||
mode = (ks_mode)((int)mode | KS_MODE_BIG_ENDIAN);
|
||||
}
|
||||
return keystone_assemble (a, ao, ao->mnemonic, KS_ARCH_MIPS, mode);
|
||||
}
|
||||
|
||||
RArchPlugin r_arch_plugin_mips_ks = {
|
||||
.meta = {
|
||||
.name = "mips.ks",
|
||||
.desc = "MIPS keystone assembler",
|
||||
.license = "GPL",
|
||||
},
|
||||
.arch = "mips",
|
||||
.bits = R_SYS_BITS_PACK3 (16, 32, 64),
|
||||
.encode = &assemble,
|
||||
};
|
||||
|
||||
#ifndef CORELIB
|
||||
struct r_lib_struct_t radare_plugin = {
|
||||
.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
|
||||
@@ -0,0 +1,42 @@
|
||||
/* radare2-keystone - GPL - Copyright 2016 - pancake */
|
||||
|
||||
#include <r_arch.h>
|
||||
#include <r_lib.h>
|
||||
#include <keystone/keystone.h>
|
||||
#include <keystone/sparc.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_SPARC32;
|
||||
break;
|
||||
case 64:
|
||||
mode = KS_MODE_SPARC64;
|
||||
break;
|
||||
}
|
||||
if (a->config->big_endian) {
|
||||
mode = (ks_mode)((int)mode | KS_MODE_BIG_ENDIAN);
|
||||
}
|
||||
return keystone_assemble (a, ao, ao->mnemonic, KS_ARCH_SPARC, mode);
|
||||
}
|
||||
|
||||
RArchPlugin r_arch_plugin_sparc_ks = {
|
||||
.meta = {
|
||||
.name = "sparc.ks",
|
||||
.desc = "sparc keystone assembler",
|
||||
.license = "GPL",
|
||||
},
|
||||
.arch = "sparc",
|
||||
.bits = R_SYS_BITS_PACK2 (32, 64),
|
||||
.encode = &assemble,
|
||||
};
|
||||
|
||||
#ifndef CORELIB
|
||||
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,43 +0,0 @@
|
||||
/* radare2-keystone - GPL - Copyright 2016 - pancake */
|
||||
|
||||
#include <r_asm.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) {
|
||||
ks_arch arch = KS_ARCH_ARM;
|
||||
ks_mode mode = KS_MODE_ARM;
|
||||
switch (a->bits) {
|
||||
case 16:
|
||||
mode = KS_MODE_THUMB;
|
||||
break;
|
||||
case 64:
|
||||
arch = KS_ARCH_ARM64;
|
||||
mode = KS_MODE_LITTLE_ENDIAN;
|
||||
a->big_endian = false;
|
||||
break;
|
||||
}
|
||||
if (a->big_endian) {
|
||||
mode = (ks_mode)((int)mode | KS_MODE_BIG_ENDIAN);
|
||||
}
|
||||
return keystone_assemble (a, ao, str, arch, mode);
|
||||
}
|
||||
|
||||
RAsmPlugin r_asm_plugin_arm_ks = {
|
||||
.name = "arm.ks",
|
||||
.desc = "ARM keystone assembler",
|
||||
.license = "GPL",
|
||||
.arch = "arm",
|
||||
.bits = 16|32|64,
|
||||
.assemble = &assemble,
|
||||
};
|
||||
|
||||
#ifndef CORELIB
|
||||
RLibStruct radare_plugin = {
|
||||
.type = R_LIB_TYPE_ASM,
|
||||
.data = &r_asm_plugin_arm_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->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,43 +0,0 @@
|
||||
/* radare2-keystone - GPL - Copyright 2016 - pancake */
|
||||
|
||||
#include <r_asm.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) {
|
||||
ks_mode mode;
|
||||
switch (a->bits) {
|
||||
case 16:
|
||||
mode = KS_MODE_MICRO; // micromips mode
|
||||
break;
|
||||
case 32:
|
||||
mode = KS_MODE_MIPS32;
|
||||
break;
|
||||
case 64:
|
||||
mode = KS_MODE_MIPS64;
|
||||
break;
|
||||
}
|
||||
if (a->big_endian) {
|
||||
mode = (ks_mode)((int)mode | KS_MODE_BIG_ENDIAN);
|
||||
}
|
||||
return keystone_assemble (a, ao, str, KS_ARCH_MIPS, mode);
|
||||
}
|
||||
|
||||
RAsmPlugin r_asm_plugin_mips_ks = {
|
||||
.name = "mips.ks",
|
||||
.desc = "MIPS keystone assembler",
|
||||
.license = "GPL",
|
||||
.arch = "mips",
|
||||
.bits = 16|32|64,
|
||||
.assemble = &assemble,
|
||||
};
|
||||
|
||||
#ifndef CORELIB
|
||||
struct r_lib_struct_t radare_plugin = {
|
||||
.type = R_LIB_TYPE_ASM,
|
||||
.data = &r_asm_plugin_mips_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->bits) {
|
||||
case 32:
|
||||
mode = KS_MODE_PPC32;
|
||||
break;
|
||||
case 64:
|
||||
mode = KS_MODE_PPC64;
|
||||
break;
|
||||
}
|
||||
if (a->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,40 +0,0 @@
|
||||
/* radare2-keystone - GPL - Copyright 2016 - pancake */
|
||||
|
||||
#include <r_asm.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) {
|
||||
ks_mode mode = (ks_mode)0;
|
||||
switch (a->bits) {
|
||||
case 32:
|
||||
mode = KS_MODE_SPARC32;
|
||||
break;
|
||||
case 64:
|
||||
mode = KS_MODE_SPARC64;
|
||||
break;
|
||||
}
|
||||
if (a->big_endian) {
|
||||
mode = (ks_mode)((int)mode | KS_MODE_BIG_ENDIAN);
|
||||
}
|
||||
return keystone_assemble (a, ao, str, KS_ARCH_SPARC, mode);
|
||||
}
|
||||
|
||||
RAsmPlugin r_asm_plugin_sparc_ks = {
|
||||
.name = "sparc.ks",
|
||||
.desc = "sparc keystone assembler",
|
||||
.license = "GPL",
|
||||
.arch = "sparc",
|
||||
.bits = 32|64,
|
||||
.assemble = &assemble,
|
||||
};
|
||||
|
||||
#ifndef CORELIB
|
||||
struct r_lib_struct_t radare_plugin = {
|
||||
.type = R_LIB_TYPE_ASM,
|
||||
.data = &r_asm_plugin_sparc_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->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->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
|
||||
@@ -4,8 +4,8 @@ LDFLAGS=@LDFLAGS@
|
||||
|
||||
R2_CFLAGS=@R2_CFLAGS@
|
||||
R2_LDFLAGS=@R2_LDFLAGS@
|
||||
|
||||
HAVE_LIB_KEYSTONE=@HAVE_LIB_KEYSTONE@
|
||||
KS_CFLAGS=@KS_CFLAGS@
|
||||
KS_LDFLAGS=@KS_LDFLAGS@
|
||||
|
||||
BUILD_OS=@BUILD_OS@
|
||||
|
||||
|
||||
Vendored
+130
-56
@@ -1,5 +1,5 @@
|
||||
#!/bin/sh
|
||||
# This script was automatically generated by ACR v1.8.1
|
||||
# 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
|
||||
@@ -39,6 +39,11 @@ shift
|
||||
done
|
||||
}
|
||||
|
||||
QUIET=0
|
||||
be_quiet() {
|
||||
QUIET=1
|
||||
}
|
||||
|
||||
VPATH=`dirname ${0}`
|
||||
if [ "${VPATH}" = "." ]; then
|
||||
WODIS=current
|
||||
@@ -60,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"
|
||||
@@ -76,15 +95,19 @@ CROSSBUILD=0
|
||||
BUILD=`guess_os`
|
||||
HOST="${BUILD}"
|
||||
TARGET="${HOST}"
|
||||
ETCDIR="/etc"
|
||||
SYSCONFDIR=""
|
||||
DESCRIPTION=""
|
||||
|
||||
create_environ() {
|
||||
: ${EPREFIX:="${PREFIX}"}
|
||||
: ${SPREFIX:="${PREFIX}"}
|
||||
: ${BINDIR:="${SPREFIX}/bin"}
|
||||
: ${SBINDIR:="${PREFIX}/sbin"}
|
||||
: ${SYSCONFDIR:="${SPREFIX}/etc"}
|
||||
: ${ETCDIR:="${SPREFIX}/etc"}
|
||||
: ${LIBDIR:="${SPREFIX}/lib"}
|
||||
: ${PKGCFG_LIBDIR:='${exec_prefix}/lib'}
|
||||
: ${PKGCFG_INCDIR:='${prefix}/include'}
|
||||
: ${LIBEXECDIR:="${SPREFIX}/libexec"}
|
||||
: ${INCLUDEDIR:="${SPREFIX}/include"}
|
||||
: ${DATADIR:="${SPREFIX}/share"}
|
||||
@@ -103,12 +126,12 @@ done
|
||||
: ${INSTALL_PROGRAM_STRIP:=${INSTALL} -m 755 -s}
|
||||
: ${INSTALL_MAN:=${INSTALL} -m 444}
|
||||
: ${INSTALL_LIB:=${INSTALL} -m 755 -c}
|
||||
PKGNAME='radare2-keystone' ; VERSION='0.1' ; VERSION_MAJOR=0; VERSION_MINOR=1; VERSION_PATCH=0; VERSION_NUMBER=00100; CONTACT_MAIL="[email protected]" ; CONTACT_NAME="pancake" ; CONTACT="pancake <[email protected]>" ;
|
||||
PKGNAME='radare2-keystone' ; VERSION='0.2' ; VERSION_MAJOR=0; VERSION_MINOR=2; VERSION_PATCH=0; VERSION_NUMBER=00200; CONTACT_MAIL="[email protected]" ; CONTACT_NAME="pancake" ; CONTACT="pancake <[email protected]>" ;
|
||||
}
|
||||
|
||||
show_usage() {
|
||||
cat <<EOF2
|
||||
'configure' configures radare2-keystone-0.1 to adapt to many kinds of systems.
|
||||
'configure' configures radare2-keystone-0.2 to adapt to many kinds of systems.
|
||||
|
||||
Usage: ./configure [OPTION]... [VAR=VALUE]...
|
||||
|
||||
@@ -120,6 +143,7 @@ Defaults for the options are specified in brackets.
|
||||
Configuration:
|
||||
-h, --help display this help and exit
|
||||
-r, --report show what libs/programs require to work
|
||||
-q, --quiet be quiet, less verbose (see ./configure -qV)
|
||||
-V, --version display version information and exit
|
||||
|
||||
Installation directories:
|
||||
@@ -139,6 +163,7 @@ Fine tuning of the installation directories:
|
||||
--localstatedir=DIR modifiable single-machine data [PREFIX/var]
|
||||
--mandir=DIR man documentation [DATADIR/man]
|
||||
--sbindir=DIR system admin executables [EPREFIX/sbin]
|
||||
--etcdir=DIR same as --sysconfdir (/etc)
|
||||
--sysconfdir=DIR read-only single-machine data [PREFIX/etc]
|
||||
--sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
|
||||
|
||||
@@ -152,7 +177,6 @@ printf "
|
||||
Some influential environment variables:
|
||||
CC C compiler command
|
||||
CFLAGS C compiler flags
|
||||
CPPFLAGS C preprocessor flags
|
||||
LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
|
||||
nonstandard directory <lib dir>
|
||||
CPPFLAGS C/C++ preprocessor flags, e.g. -I<include dir> if you have
|
||||
@@ -172,12 +196,26 @@ take_environ() {
|
||||
: ${CPP:=cpp}
|
||||
: ${CC:=gcc}
|
||||
: ${CPP:=cpp}
|
||||
: ${CXX:=g++}
|
||||
: ${CXX:=c++}
|
||||
: ${PREFIX:=/usr/local/}
|
||||
}
|
||||
|
||||
ochof() {
|
||||
[ "$QUIET" = 1 ] && return
|
||||
printf "$*"
|
||||
}
|
||||
|
||||
ocho() {
|
||||
[ "$QUIET" = 1 ] && return
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
show_version() {
|
||||
echo "radare2-keystone-0.1 configuration script done with acr v1.8.1.
|
||||
if [ "$QUIET" = 1 ]; then
|
||||
echo "0.2"
|
||||
exit 0
|
||||
fi
|
||||
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
|
||||
@@ -197,14 +235,20 @@ fi
|
||||
case $flag in
|
||||
-h|--help|--hel|--h|--he|-help)
|
||||
show_usage ; ;;
|
||||
-qV|-quiet-version|--quiet-version)
|
||||
be_quiet
|
||||
show_version ; ;;
|
||||
-q|-quiet|--quiet)
|
||||
be_quiet ; ;;
|
||||
-V|-version|--version)
|
||||
show_version ; ;;
|
||||
-r|--r|--report)
|
||||
echo "PKGNAME: radare2-keystone"
|
||||
echo "VERSION: 0.1"
|
||||
echo "LANGS: c c++"
|
||||
echo "REQUIRED: libkeystone"
|
||||
echo "PKG-CONFIG: r_asm"
|
||||
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)
|
||||
@@ -234,16 +278,22 @@ echo "PKG-CONFIG: r_asm"
|
||||
--datadir)
|
||||
DATADIR="$value"; ;;
|
||||
--sysconfdir)
|
||||
SYSCONFDIR="$value"; ;;
|
||||
SYSCONFDIR="$value"
|
||||
ETCDIR="$value"; ;;
|
||||
--etcdir)
|
||||
SYSCONFDIR="$value"
|
||||
ETCDIR="$value"; ;;
|
||||
--sharedstatedir)
|
||||
SHAREDSTATEDIR="$value"; ;;
|
||||
--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"; ;;
|
||||
@@ -267,33 +317,30 @@ parse_options "$1"
|
||||
shift
|
||||
done
|
||||
|
||||
ENVWORDS="MANDIR INFODIR LIBDIR INCLUDEDIR LOCALSTATEDIR 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 HAVE_LIB_KEYSTONE R2_CFLAGS R2_LDFLAGS HAVE_PKGCFG_R_ASM"
|
||||
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
|
||||
|
||||
echo "checking build system type... ${BUILD}"
|
||||
echo "checking host system type... ${HOST}"
|
||||
echo "checking target system type... ${TARGET}"
|
||||
ocho "checking build system type... ${BUILD}"
|
||||
ocho "checking host system type... ${HOST}"
|
||||
ocho "checking target system type... ${TARGET}"
|
||||
[ "${CROSSBUILD}" = 1 ] && echo "using crosscompilation mode."
|
||||
|
||||
#split_host BUILD HOST TARGET
|
||||
[ -n "${prefix}" ] && PREFIX="${prefix}"
|
||||
echo "checking for working directories... ${WODIS}"
|
||||
echo "using prefix '${PREFIX}'"
|
||||
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
|
||||
printf "checking for c compiler... "
|
||||
ochof "checking for c compiler... "
|
||||
HAVE_LANG_C=1
|
||||
if [ "${CROSSBUILD}" = 1 ]; then
|
||||
(command -v ${HOST}-${CC} >/dev/null 2>&1)
|
||||
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
|
||||
@@ -301,7 +348,7 @@ echo "ERROR: ${CC} cannot create executables" >&2 ;
|
||||
exit 1 ; fi
|
||||
COMPILER=CXX
|
||||
HAVE_LANG_CXX=1
|
||||
printf "checking for c++ compiler... "
|
||||
ochof "checking for c++ compiler... "
|
||||
if [ "${CROSSBUILD}" = 1 ]; then
|
||||
(command -v ${HOST}-${CXX} 2>&1 >/dev/null)
|
||||
if [ "$?" = 0 ]; then CXX="${HOST}-${CXX}"; fi
|
||||
@@ -317,32 +364,39 @@ echo "ERROR: ${CXX} cannot create executables" >&2 ;
|
||||
do_remove
|
||||
exit 1
|
||||
fi
|
||||
check_library() {
|
||||
VAR=$1
|
||||
S="$"
|
||||
_REQUIRED=$3
|
||||
_CHKLIB_NAME=$2
|
||||
_CHKLIB_LIBS=$(echo "-l${_CHKLIB_NAME}" | sed 's,+, -l,g')
|
||||
printf "checking for lib${_CHKLIB_NAME} ... "
|
||||
echo "int main(int ac, char **av){return 0;}" > test.c
|
||||
eval ${S}${COMPILER} ${CFLAGS} ${CPPFLAGS} ${CXXFLAGS} ${LDFLAGS} ${_CHKLIB_LIBS} test.c >/dev/null 2>&1
|
||||
if [ $? = 0 ]; then
|
||||
eval ${VAR}=1
|
||||
echo yes
|
||||
else
|
||||
eval ${VAR}=0
|
||||
echo no
|
||||
if [ "${_REQUIRED}" = 1 ]; then
|
||||
echo "this library is required."
|
||||
do_remove
|
||||
exit 1
|
||||
ochof "checking for pkg-config... "
|
||||
ENVWORDS="${ENVWORDS} HAVE_PKGCONFIG"
|
||||
if [ -n "$PKGCONFIG" ]; then
|
||||
if [ -x "$PKGCONFIG" ]; then
|
||||
_HAVE_PKGCONFIG="${PKGCONFIG}"
|
||||
else
|
||||
ocho "PKGCONFIG env is not executable"
|
||||
PKGCONFIG=""
|
||||
fi
|
||||
else
|
||||
IFS=:
|
||||
for A in ${PATH} ; do
|
||||
if [ -x "${A}/pkg-config" ]; then
|
||||
PKGCONFIG="${A}/pkg-config"
|
||||
elif [ -x "${A}/pkgconf" ]; then
|
||||
PKGCONFIG="${A}/pkgconf"
|
||||
else
|
||||
continue
|
||||
fi
|
||||
break
|
||||
done
|
||||
unset IFS
|
||||
fi
|
||||
}
|
||||
|
||||
check_library HAVE_LIB_KEYSTONE keystone 1
|
||||
[ -z "${PKGCONFIG}" ] && PKGCONFIG=pkg-config
|
||||
type ${PKGCONFIG} > /dev/null 2>&1 || echo "ERROR: Cannot find PKGCONFIG ${PKGCONFIG}"
|
||||
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
|
||||
if [ -z "${PKGCONFIG}" ]; then pkg-config --version >/dev/null 2>&1 ; if [ 0 = 0 ]; then PKGCONFIG=pkg-config ; else PKGCONFIG=pkgconf ; fi; fi
|
||||
type ${PKGCONFIG} > /dev/null 2>&1 || echo "ERROR: Cannot find valid PKGCONFIG, pkg-config or pkgconf in PATH"
|
||||
echo 'Using PKGCONFIG: '${PKGCONFIG}
|
||||
printf 'checking pkg-config flags for r_asm... '
|
||||
tmp=`${PKGCONFIG} --cflags r_asm 2>/dev/null`
|
||||
@@ -356,13 +410,33 @@ tmp=`${PKGCONFIG} --libs r_asm 2>/dev/null`
|
||||
if [ $? = 0 ]; then
|
||||
echo yes; HAVE_PKGCFG_R_ASM=1;
|
||||
R2_LDFLAGS=$tmp; fi; fi
|
||||
if [ -z "${PKGCONFIG}" ]; then pkg-config --version >/dev/null 2>&1 ; if [ 0 = 0 ]; then PKGCONFIG=pkg-config ; else PKGCONFIG=pkgconf ; fi; fi
|
||||
printf 'checking pkg-config flags for keystone... '
|
||||
tmp=`${PKGCONFIG} --cflags keystone 2>/dev/null`
|
||||
if [ $? != 0 ]; then echo no ; HAVE_PKGCFG_KEYSTONE=0;
|
||||
KS_CFLAGS='';KS_LDFLAGS='';
|
||||
echo 'This package is required'
|
||||
exit 1
|
||||
else
|
||||
KS_CFLAGS=$tmp;
|
||||
tmp=`${PKGCONFIG} --libs keystone 2>/dev/null`
|
||||
if [ $? = 0 ]; then
|
||||
echo yes; HAVE_PKGCFG_KEYSTONE=1;
|
||||
KS_LDFLAGS=$tmp; fi; fi
|
||||
SEDFLAGS=" -e '"
|
||||
COUNT=0
|
||||
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;"
|
||||
@@ -380,8 +454,8 @@ if [ -f "${VPATH}/${A}.acr" ]; then
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
echo "creating ${SD_TARGET}"
|
||||
mkdir -p $(echo ${A} | sed -e "s,/`basename ${A}`$,,g")
|
||||
ocho "creating ${SD_TARGET}"
|
||||
[ "${VPATH}" != '.' ] && mkdir -p $(echo ${A} | sed -e "s,/`basename ${A}`$,,g")
|
||||
cat ${VPATH}/${SD_TARGET}.acr | \
|
||||
eval sed -e "s,@VPATH@,${VPATH}/${A},g" ${SEDFLAGS} > ${SD_TARGET}.tmp
|
||||
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
PKGNAME radare2-keystone
|
||||
VERSION 0.1
|
||||
VERSION 0.2
|
||||
CONTACT pancake ; [email protected]
|
||||
|
||||
LANG_C!
|
||||
LANG_CXX!
|
||||
USE_PKGCONFIG!
|
||||
|
||||
|
||||
CHKLIB! keystone
|
||||
(( CHKLIB! keystone ))
|
||||
PKGCFG! R2_CFLAGS R2_LDFLAGS r_asm
|
||||
PKGCFG! KS_CFLAGS KS_LDFLAGS keystone
|
||||
|
||||
SUBDIRS ./config.mk ;
|
||||
+24
-15
@@ -1,22 +1,30 @@
|
||||
/* radare2-keystone - GPL - Copyright 2016 - pancake */
|
||||
|
||||
static void *oldcur = NULL;
|
||||
static ks_engine *ks = NULL;
|
||||
static int oldbit = 0;
|
||||
#if R2_VERSION_NUMBER >= 50709
|
||||
#define ATTSYNTAX R_ARCH_SYNTAX_ATT
|
||||
#else
|
||||
#define ATTSYNTAX R_ASM_SYNTAX_ATT
|
||||
#endif
|
||||
|
||||
static int keystone_assemble(RAsm *a, RAsmOp *ao, const char *str, ks_arch arch, ks_mode mode) {
|
||||
#include <r_th.h>
|
||||
|
||||
static R_TH_LOCAL void *oldcur = NULL;
|
||||
static R_TH_LOCAL ks_engine *ks = NULL;
|
||||
static R_TH_LOCAL int oldbit = 0;
|
||||
|
||||
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;
|
||||
oldbit = a->bits;
|
||||
// oldcur = a->cur;
|
||||
oldbit = a->config->bits;
|
||||
|
||||
if (must_init) {
|
||||
if (ks) {
|
||||
@@ -25,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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,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->syntax == R_ASM_SYNTAX_ATT) {
|
||||
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);
|
||||
@@ -56,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,13 +34,8 @@ 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 asm nios
|
||||
$(MAKE) -C anal nios
|
||||
|
||||
clean:
|
||||
@@ -78,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)
|
||||
|
||||
+4
-3
@@ -1,3 +1,7 @@
|
||||
rl78:
|
||||
$(MAKE) -C p anal_rl78.$(LIBEXT)
|
||||
cp -f p/anal_rl78.$(LIBEXT) $(shell r2 -H R2_USER_PLUGINS)
|
||||
|
||||
ba2:
|
||||
cd p ; $(MAKE) anal_ba2.$(LIBEXT)
|
||||
|
||||
@@ -13,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)
|
||||
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,433 @@
|
||||
/* Disassembler code for Renesas RL78.
|
||||
Copyright (C) 2011-2022 Free Software Foundation, Inc.
|
||||
Contributed by Red Hat.
|
||||
Written by DJ Delorie.
|
||||
|
||||
This file is part of the GNU opcodes library.
|
||||
|
||||
This library is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
It is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
|
||||
MA 02110-1301, USA. */
|
||||
|
||||
#include "sysdep.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#include "bfd.h"
|
||||
#include "elf-bfd.h"
|
||||
#include "dis-asm.h"
|
||||
#include "opcode/rl78.h"
|
||||
// #include "elf/rl78.h"
|
||||
|
||||
#include <setjmp.h>
|
||||
|
||||
#define DEBUG_SEMANTICS 0
|
||||
|
||||
typedef struct
|
||||
{
|
||||
bfd_vma pc;
|
||||
disassemble_info * dis;
|
||||
} RL78_Data;
|
||||
|
||||
#if 0
|
||||
struct private
|
||||
{
|
||||
OPCODES_SIGJMP_BUF bailout;
|
||||
};
|
||||
#endif
|
||||
|
||||
static int
|
||||
rl78_get_byte (void * vdata)
|
||||
{
|
||||
bfd_byte buf[1];
|
||||
RL78_Data *rl78_data = (RL78_Data *) vdata;
|
||||
int status;
|
||||
|
||||
status = rl78_data->dis->read_memory_func (rl78_data->pc,
|
||||
buf,
|
||||
1,
|
||||
rl78_data->dis);
|
||||
#if 0
|
||||
if (status != 0)
|
||||
{
|
||||
struct private *priv = (struct private *) rl78_data->dis->private_data;
|
||||
|
||||
rl78_data->dis->memory_error_func (status, rl78_data->pc,
|
||||
rl78_data->dis);
|
||||
OPCODES_SIGLONGJMP (priv->bailout, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
rl78_data->pc ++;
|
||||
return buf[0];
|
||||
}
|
||||
|
||||
static char const *
|
||||
register_names[] =
|
||||
{
|
||||
"",
|
||||
"x", "a", "c", "b", "e", "d", "l", "h",
|
||||
"ax", "bc", "de", "hl",
|
||||
"sp", "psw", "cs", "es", "pmc", "mem"
|
||||
};
|
||||
|
||||
static char const *
|
||||
condition_names[] =
|
||||
{
|
||||
"t", "f", "c", "nc", "h", "nh", "z", "nz"
|
||||
};
|
||||
|
||||
static int
|
||||
indirect_type (int t)
|
||||
{
|
||||
switch (t)
|
||||
{
|
||||
case RL78_Operand_Indirect:
|
||||
case RL78_Operand_BitIndirect:
|
||||
case RL78_Operand_PostInc:
|
||||
case RL78_Operand_PreDec:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
print_insn_rl78_common (bfd_vma addr, disassemble_info * dis, RL78_Dis_Isa isa)
|
||||
{
|
||||
int rv;
|
||||
RL78_Data rl78_data;
|
||||
RL78_Opcode_Decoded opcode;
|
||||
const char * s;
|
||||
#if DEBUG_SEMANTICS
|
||||
static char buf[200];
|
||||
#endif
|
||||
// struct private priv;
|
||||
|
||||
// dis->private_data = (PTR) &priv;
|
||||
rl78_data.pc = addr;
|
||||
rl78_data.dis = dis;
|
||||
|
||||
#if 0
|
||||
if (OPCODES_SIGSETJMP (priv.bailout) != 0)
|
||||
{
|
||||
/* Error return. */
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
rv = rl78_decode_opcode (addr, &opcode, rl78_get_byte, &rl78_data, isa);
|
||||
|
||||
dis->bytes_per_line = 10;
|
||||
|
||||
#define PR (dis->fprintf_func)
|
||||
#define PS (dis->stream)
|
||||
#define PC(c) PR (PS, "%c", c)
|
||||
|
||||
s = opcode.syntax;
|
||||
|
||||
#if DEBUG_SEMANTICS
|
||||
|
||||
switch (opcode.id)
|
||||
{
|
||||
case RLO_unknown: s = "uknown"; break;
|
||||
case RLO_add: s = "add: %e0%0 += %e1%1"; break;
|
||||
case RLO_addc: s = "addc: %e0%0 += %e1%1 + CY"; break;
|
||||
case RLO_and: s = "and: %e0%0 &= %e1%1"; break;
|
||||
case RLO_branch: s = "branch: pc = %e0%0"; break;
|
||||
case RLO_branch_cond: s = "branch_cond: pc = %e0%0 if %c1 / %e1%1"; break;
|
||||
case RLO_branch_cond_clear: s = "branch_cond_clear: pc = %e0%0 if %c1 / %e1%1, %e1%1 = 0"; break;
|
||||
case RLO_call: s = "call: pc = %e1%0"; break;
|
||||
case RLO_cmp: s = "cmp: %e0%0 - %e1%1"; break;
|
||||
case RLO_mov: s = "mov: %e0%0 = %e1%1"; break;
|
||||
case RLO_or: s = "or: %e0%0 |= %e1%1"; break;
|
||||
case RLO_rol: s = "rol: %e0%0 <<= %e1%1"; break;
|
||||
case RLO_rolc: s = "rol: %e0%0 <<= %e1%1,CY"; break;
|
||||
case RLO_ror: s = "ror: %e0%0 >>= %e1%1"; break;
|
||||
case RLO_rorc: s = "ror: %e0%0 >>= %e1%1,CY"; break;
|
||||
case RLO_sar: s = "sar: %e0%0 >>= %e1%1 signed"; break;
|
||||
case RLO_sel: s = "sel: rb = %1"; break;
|
||||
case RLO_shr: s = "shr: %e0%0 >>= %e1%1 unsigned"; break;
|
||||
case RLO_shl: s = "shl: %e0%0 <<= %e1%1"; break;
|
||||
case RLO_skip: s = "skip: if %c1"; break;
|
||||
case RLO_sub: s = "sub: %e0%0 -= %e1%1"; break;
|
||||
case RLO_subc: s = "subc: %e0%0 -= %e1%1 - CY"; break;
|
||||
case RLO_xch: s = "xch: %e0%0 <-> %e1%1"; break;
|
||||
case RLO_xor: s = "xor: %e0%0 ^= %e1%1"; break;
|
||||
}
|
||||
|
||||
sprintf(buf, "%s%%W%%f\t\033[32m%s\033[0m", s, opcode.syntax);
|
||||
s = buf;
|
||||
|
||||
#endif
|
||||
|
||||
for (; *s; s++)
|
||||
{
|
||||
if (*s != '%')
|
||||
{
|
||||
PC (*s);
|
||||
}
|
||||
else
|
||||
{
|
||||
RL78_Opcode_Operand * oper;
|
||||
int do_hex = 0;
|
||||
int do_addr = 0;
|
||||
int do_es = 0;
|
||||
int do_sfr = 0;
|
||||
int do_cond = 0;
|
||||
int do_bang = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
s ++;
|
||||
switch (*s)
|
||||
{
|
||||
case 'x':
|
||||
do_hex = 1;
|
||||
break;
|
||||
case '!':
|
||||
do_bang = 1;
|
||||
break;
|
||||
case 'e':
|
||||
do_es = 1;
|
||||
break;
|
||||
case 'a':
|
||||
do_addr = 1;
|
||||
break;
|
||||
case 's':
|
||||
do_sfr = 1;
|
||||
break;
|
||||
case 'c':
|
||||
do_cond = 1;
|
||||
break;
|
||||
default:
|
||||
goto no_more_modifiers;
|
||||
}
|
||||
}
|
||||
no_more_modifiers:;
|
||||
|
||||
switch (*s)
|
||||
{
|
||||
case '%':
|
||||
PC ('%');
|
||||
break;
|
||||
|
||||
#if DEBUG_SEMANTICS
|
||||
|
||||
case 'W':
|
||||
if (opcode.size == RL78_Word)
|
||||
PR (PS, " \033[33mW\033[0m");
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
if (opcode.flags)
|
||||
{
|
||||
char *comma = "";
|
||||
PR (PS, " \033[35m");
|
||||
|
||||
if (opcode.flags & RL78_PSW_Z)
|
||||
{ PR (PS, "Z"); comma = ","; }
|
||||
if (opcode.flags & RL78_PSW_AC)
|
||||
{ PR (PS, "%sAC", comma); comma = ","; }
|
||||
if (opcode.flags & RL78_PSW_CY)
|
||||
{ PR (PS, "%sCY", comma); comma = ","; }
|
||||
PR (PS, "\033[0m");
|
||||
}
|
||||
break;
|
||||
|
||||
#endif
|
||||
|
||||
case '0':
|
||||
case '1':
|
||||
oper = *s == '0' ? &opcode.op[0] : &opcode.op[1];
|
||||
if (do_es)
|
||||
{
|
||||
if (oper->use_es && indirect_type (oper->type))
|
||||
PR (PS, "es:");
|
||||
}
|
||||
|
||||
if (do_bang)
|
||||
{
|
||||
/* If we are going to display SP by name, we must omit the bang. */
|
||||
if ((oper->type == RL78_Operand_Indirect
|
||||
|| oper->type == RL78_Operand_BitIndirect)
|
||||
&& oper->reg == RL78_Reg_None
|
||||
&& do_sfr
|
||||
&& ((oper->addend == 0xffff8 && opcode.size == RL78_Word)
|
||||
|| (oper->addend == 0x0fff8 && do_es && opcode.size == RL78_Word)))
|
||||
;
|
||||
else
|
||||
PC ('!');
|
||||
}
|
||||
|
||||
if (do_cond)
|
||||
{
|
||||
PR (PS, "%s", condition_names[oper->condition]);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (oper->type)
|
||||
{
|
||||
case RL78_Operand_Immediate:
|
||||
if (do_addr)
|
||||
dis->print_address_func (oper->addend, dis);
|
||||
else if (do_hex
|
||||
|| oper->addend > 999
|
||||
|| oper->addend < -999)
|
||||
PR (PS, "%#x", oper->addend);
|
||||
else
|
||||
PR (PS, "%d", oper->addend);
|
||||
break;
|
||||
|
||||
case RL78_Operand_Register:
|
||||
PR (PS, "%s", register_names[oper->reg]);
|
||||
break;
|
||||
|
||||
case RL78_Operand_Bit:
|
||||
PR (PS, "%s.%d", register_names[oper->reg], oper->bit_number);
|
||||
break;
|
||||
|
||||
case RL78_Operand_Indirect:
|
||||
case RL78_Operand_BitIndirect:
|
||||
switch (oper->reg)
|
||||
{
|
||||
case RL78_Reg_None:
|
||||
if (oper->addend == 0xffffa && do_sfr && opcode.size == RL78_Byte)
|
||||
PR (PS, "psw");
|
||||
else if (oper->addend == 0xffff8 && do_sfr && opcode.size == RL78_Word)
|
||||
PR (PS, "sp");
|
||||
else if (oper->addend == 0x0fff8 && do_sfr && do_es && opcode.size == RL78_Word)
|
||||
PR (PS, "sp");
|
||||
else if (oper->addend == 0xffff8 && do_sfr && opcode.size == RL78_Byte)
|
||||
PR (PS, "spl");
|
||||
else if (oper->addend == 0xffff9 && do_sfr && opcode.size == RL78_Byte)
|
||||
PR (PS, "sph");
|
||||
else if (oper->addend == 0xffffc && do_sfr && opcode.size == RL78_Byte)
|
||||
PR (PS, "cs");
|
||||
else if (oper->addend == 0xffffd && do_sfr && opcode.size == RL78_Byte)
|
||||
PR (PS, "es");
|
||||
else if (oper->addend == 0xffffe && do_sfr && opcode.size == RL78_Byte)
|
||||
PR (PS, "pmc");
|
||||
else if (oper->addend == 0xfffff && do_sfr && opcode.size == RL78_Byte)
|
||||
PR (PS, "mem");
|
||||
else if (oper->addend >= 0xffe20)
|
||||
PR (PS, "%#x", oper->addend);
|
||||
else
|
||||
{
|
||||
int faddr = oper->addend;
|
||||
if (do_es && ! oper->use_es)
|
||||
faddr += 0xf0000;
|
||||
dis->print_address_func (faddr, dis);
|
||||
}
|
||||
break;
|
||||
|
||||
case RL78_Reg_B:
|
||||
case RL78_Reg_C:
|
||||
case RL78_Reg_BC:
|
||||
PR (PS, "%d[%s]", oper->addend, register_names[oper->reg]);
|
||||
break;
|
||||
|
||||
default:
|
||||
PR (PS, "[%s", register_names[oper->reg]);
|
||||
if (oper->reg2 != RL78_Reg_None)
|
||||
PR (PS, "+%s", register_names[oper->reg2]);
|
||||
if (oper->addend || do_addr)
|
||||
PR (PS, "+%d", oper->addend);
|
||||
PC (']');
|
||||
break;
|
||||
|
||||
}
|
||||
if (oper->type == RL78_Operand_BitIndirect)
|
||||
PR (PS, ".%d", oper->bit_number);
|
||||
break;
|
||||
|
||||
#if DEBUG_SEMANTICS
|
||||
/* Shouldn't happen - push and pop don't print
|
||||
[SP] directly. But we *do* use them for
|
||||
semantic debugging. */
|
||||
case RL78_Operand_PostInc:
|
||||
PR (PS, "[%s++]", register_names[oper->reg]);
|
||||
break;
|
||||
case RL78_Operand_PreDec:
|
||||
PR (PS, "[--%s]", register_names[oper->reg]);
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
/* If we ever print this, that means the
|
||||
programmer tried to print an operand with a
|
||||
type we don't expect. Print the line and
|
||||
operand number from rl78-decode.opc for
|
||||
them. */
|
||||
PR (PS, "???%d.%d", opcode.lineno, *s - '0');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG_SEMANTICS
|
||||
|
||||
PR (PS, "\t\033[34m(line %d)\033[0m", opcode.lineno);
|
||||
|
||||
#endif
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
int
|
||||
print_insn_rl78 (bfd_vma addr, disassemble_info * dis)
|
||||
{
|
||||
return print_insn_rl78_common (addr, dis, RL78_ISA_DEFAULT);
|
||||
}
|
||||
|
||||
int
|
||||
print_insn_rl78_g10 (bfd_vma addr, disassemble_info * dis)
|
||||
{
|
||||
return print_insn_rl78_common (addr, dis, RL78_ISA_G10);
|
||||
}
|
||||
|
||||
int
|
||||
print_insn_rl78_g13 (bfd_vma addr, disassemble_info * dis)
|
||||
{
|
||||
return print_insn_rl78_common (addr, dis, RL78_ISA_G13);
|
||||
}
|
||||
|
||||
int
|
||||
print_insn_rl78_g14 (bfd_vma addr, disassemble_info * dis)
|
||||
{
|
||||
return print_insn_rl78_common (addr, dis, RL78_ISA_G14);
|
||||
}
|
||||
|
||||
#if 0
|
||||
disassembler_ftype
|
||||
rl78_get_disassembler (bfd *abfd)
|
||||
{
|
||||
int cpu = E_FLAG_RL78_ANY_CPU;
|
||||
|
||||
if (abfd != NULL)
|
||||
cpu = abfd->tdata.elf_obj_data->elf_header->e_flags & E_FLAG_RL78_CPU_MASK;
|
||||
|
||||
switch (cpu)
|
||||
{
|
||||
case E_FLAG_RL78_G10:
|
||||
return print_insn_rl78_g10;
|
||||
case E_FLAG_RL78_G13:
|
||||
return print_insn_rl78_g13;
|
||||
case E_FLAG_RL78_G14:
|
||||
return print_insn_rl78_g14;
|
||||
default:
|
||||
return print_insn_rl78;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -6,8 +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
|
||||
|
||||
include ../../plugs.mk
|
||||
@@ -399,7 +399,7 @@ static int atombios_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *b, int le
|
||||
op->cond = R_ANAL_COND_AL;
|
||||
op->jump = sect->paddr;
|
||||
op->eob = true;
|
||||
esilprintf (op, "0x%08x,pc,4,sp,-=,sp,=[],pc,=", op->jump);
|
||||
esilprintf (op, "0x%" PFMT64d ",pc,4,sp,-=,sp,=[],pc,=", op->jump);
|
||||
} break;
|
||||
|
||||
// jmp imm16
|
||||
@@ -413,7 +413,7 @@ static int atombios_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *b, int le
|
||||
op->cond = R_ANAL_COND_AL;
|
||||
op->jump = cursect->paddr + r_read_at_le16(b, 1);
|
||||
op->eob = true;
|
||||
esilprintf (op, "0x%08x,pc,=", op->jump);
|
||||
esilprintf (op, "0x%" PFMT64d ",pc,=", op->jump);
|
||||
} break;
|
||||
case 0x44:
|
||||
{
|
||||
@@ -426,7 +426,7 @@ static int atombios_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *b, int le
|
||||
op->jump = cursect->paddr + r_read_at_le16(b, 1);
|
||||
op->fail = addr + op->size;
|
||||
op->eob = true;
|
||||
esilprintf (op, "$z,?{,0x%08x,pc,=,}", op->jump);
|
||||
esilprintf (op, "$z,?{,0x%" PFMT64d ",pc,=,}", op->jump);
|
||||
} break;
|
||||
case 0x45:
|
||||
{
|
||||
@@ -439,7 +439,7 @@ static int atombios_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *b, int le
|
||||
op->jump = cursect->paddr + r_read_at_le16(b, 1);
|
||||
op->fail = addr + op->size;
|
||||
op->eob = true;
|
||||
esilprintf (op, "$of,$sf,!=,?{,0x%08x,pc,=,}", op->jump);
|
||||
esilprintf (op, "$of,$sf,!=,?{,0x%" PFMT64d ",pc,=,}", op->jump);
|
||||
} break;
|
||||
case 0x46:
|
||||
{
|
||||
@@ -452,7 +452,7 @@ static int atombios_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *b, int le
|
||||
op->jump = cursect->paddr + r_read_at_le16(b, 1);
|
||||
op->fail = addr + op->size;
|
||||
op->eob = true;
|
||||
esilprintf (op, "$z,!,$of,$sf,==,&,?{,0x%08x,pc,=,}", op->jump);
|
||||
esilprintf (op, "$z,!,$of,$sf,==,&,?{,0x%" PFMT64d ",pc,=,}", op->jump);
|
||||
} break;
|
||||
case 0x47:
|
||||
{
|
||||
@@ -465,7 +465,7 @@ static int atombios_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *b, int le
|
||||
op->jump = cursect->paddr + r_read_at_le16(b, 1);
|
||||
op->fail = addr + op->size;
|
||||
op->eob = true;
|
||||
esilprintf (op, "$z,$of,$sf,!=,|,?{,0x%08x,pc,=,}", op->jump);
|
||||
esilprintf (op, "$z,$of,$sf,!=,|,?{,0x%" PFMT64d ",pc,=,}", op->jump);
|
||||
} break;
|
||||
case 0x48:
|
||||
{
|
||||
@@ -478,7 +478,7 @@ static int atombios_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *b, int le
|
||||
op->jump = cursect->paddr + r_read_at_le16(b, 1);
|
||||
op->fail = addr + op->size;
|
||||
op->eob = true;
|
||||
esilprintf (op, "$of,$sf,==,?{,0x%08x,pc,=,}", op->jump);
|
||||
esilprintf (op, "$of,$sf,==,?{,0x%" PFMT64d ",pc,=,}", op->jump);
|
||||
} break;
|
||||
case 0x49:
|
||||
{
|
||||
@@ -491,7 +491,7 @@ static int atombios_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *b, int le
|
||||
op->jump = cursect->paddr + r_read_at_le16(b, 1);
|
||||
op->fail = addr + op->size;
|
||||
op->eob = true;
|
||||
esilprintf (op, "$z,!,?{,0x%08x,pc,=,}", op->jump);
|
||||
esilprintf (op, "$z,!,?{,0x%" PFMT64d ",pc,=,}", op->jump);
|
||||
} break;
|
||||
|
||||
// SET DATA BLOCK imm8 dataptr = &data[datatable[imm8]]
|
||||
|
||||
@@ -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
|
||||
@@ -376,7 +376,7 @@ static int parse_insn(enum mach_attr mach, ut16 insn, struct insn_op **op, struc
|
||||
int opcode;
|
||||
|
||||
for (int type = TYPE_OP6; type < TYPE_OPS; type++) {
|
||||
const char *key = sdb_fmt("%d %d %d", mach, type, insns[type]);
|
||||
r_strf_var (key, 128, "%d %d %d", mach, type, insns[type]);
|
||||
*op = ht_pp_find(nios->ops, key, &found);
|
||||
|
||||
if (found) {
|
||||
@@ -756,7 +756,7 @@ static int nios_init(void *user) {
|
||||
|
||||
for (int i = 0; i < INSN_OPS_MAX; i++) {
|
||||
const struct insn_op *op = &insn_ops[i];
|
||||
const char *key = sdb_fmt("%d %d %d", op->mach, op->type, op->opcode);
|
||||
r_strf_var (key, 64, "%d %d %d", op->mach, op->type, op->opcode);
|
||||
ht_pp_insert(nios->ops, key, (void *) op);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,207 @@
|
||||
/* rl78 plugin by pancake, using binutils ripped code from 2022 */
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <r_types.h>
|
||||
#include <r_lib.h>
|
||||
#include <r_asm.h>
|
||||
#include <r_anal.h>
|
||||
#include <sdb.h>
|
||||
|
||||
#include "disas-asm.h"
|
||||
#include "../arch/rl78/rl78-decode.c"
|
||||
#include "../arch/rl78/rl78-dis.c"
|
||||
|
||||
|
||||
static const char *rl78_reg_profile = \
|
||||
"=SR ctl0\n"
|
||||
"=PC pc\n"
|
||||
"=SP r14\n"
|
||||
"=LR r15\n"
|
||||
"=BP r30\n"
|
||||
/* control registers */
|
||||
"gpr ctl0 .16 0 0\n"
|
||||
"gpr ctl1 .16 2 0\n"
|
||||
"gpr ctl2 .16 4 0\n"
|
||||
"gpr ctl3 .16 6 0\n"
|
||||
"gpr ctl4 .16 8 0\n"
|
||||
"gpr ctl5 .16 10 0\n"
|
||||
"gpr ctl6 .16 12 0\n"
|
||||
"gpr ctl7 .16 14 0\n"
|
||||
"gpr ctl8 .16 16 0\n"
|
||||
"gpr ctl9 .16 18 0\n"
|
||||
"gpr pc .16 20 0\n"
|
||||
"gpr k .16 22 0\n"
|
||||
/* r0-r7 are global (g0-g7) */
|
||||
"gpr r0 .16 24 0\n"
|
||||
"gpr r1 .16 26 0\n"
|
||||
"gpr r2 .16 28 0\n"
|
||||
"gpr r3 .16 30 0\n"
|
||||
"gpr r4 .16 32 0\n"
|
||||
"gpr r5 .16 34 0\n"
|
||||
"gpr r6 .16 36 0\n"
|
||||
"gpr r7 .16 38 0\n"
|
||||
/* r8-15 are out (o0-o7) */
|
||||
"gpr r8 .16 40 0\n"
|
||||
"gpr r9 .16 42 0\n"
|
||||
"gpr r10 .16 44 0\n"
|
||||
"gpr r11 .16 46 0\n"
|
||||
"gpr r12 .16 48 0\n"
|
||||
"gpr r13 .16 50 0\n"
|
||||
"gpr r14 .16 52 0\n"
|
||||
"gpr r15 .16 54 0\n"
|
||||
/* r16-23 are local (l0-l7) */
|
||||
"gpr r16 .16 56 0\n"
|
||||
"gpr r17 .16 58 0\n"
|
||||
"gpr r18 .16 60 0\n"
|
||||
"gpr r19 .16 62 0\n"
|
||||
"gpr r20 .16 64 0\n"
|
||||
"gpr r21 .16 66 0\n"
|
||||
"gpr r22 .16 68 0\n"
|
||||
"gpr r23 .16 70 0\n"
|
||||
/* r24-31 are in (i0-i7) */
|
||||
"gpr r24 .16 72 0\n"
|
||||
"gpr r25 .16 74 0\n"
|
||||
"gpr r26 .16 76 0\n"
|
||||
"gpr r27 .16 78 0\n"
|
||||
"gpr r28 .16 80 0\n"
|
||||
"gpr r29 .16 82 0\n"
|
||||
"gpr r30 .16 84 0\n"
|
||||
"gpr r31 .16 86 0\n";
|
||||
|
||||
static const char *rl7832_reg_profile = \
|
||||
"=SR ctl0\n"
|
||||
"=PC pc\n"
|
||||
"=SP r14\n"
|
||||
"=LR r15\n"
|
||||
"=BP r30\n"
|
||||
/* control registers */
|
||||
"gpr ctl0 .32 0 0\n"
|
||||
"gpr ctl1 .32 4 0\n"
|
||||
"gpr ctl2 .32 8 0\n"
|
||||
"gpr ctl3 .32 12 0\n"
|
||||
"gpr ctl4 .32 16 0\n"
|
||||
"gpr ctl5 .32 20 0\n"
|
||||
"gpr ctl6 .32 24 0\n"
|
||||
"gpr ctl7 .32 28 0\n"
|
||||
"gpr ctl8 .32 32 0\n"
|
||||
"gpr ctl9 .32 36 0\n"
|
||||
"gpr pc .32 40 0\n"
|
||||
"gpr k .16 44 0\n"
|
||||
/* r0-r7 are global (g0-g7) */
|
||||
"gpr r0 .32 48 0\n"
|
||||
"gpr r1 .32 52 0\n"
|
||||
"gpr r2 .32 56 0\n"
|
||||
"gpr r3 .32 60 0\n"
|
||||
"gpr r4 .32 64 0\n"
|
||||
"gpr r5 .32 68 0\n"
|
||||
"gpr r6 .32 72 0\n"
|
||||
"gpr r7 .32 76 0\n"
|
||||
/* r8-15 are out (o0-o7) */
|
||||
"gpr r8 .32 80 0\n"
|
||||
"gpr r9 .32 84 0\n"
|
||||
"gpr r10 .32 88 0\n"
|
||||
"gpr r11 .32 92 0\n"
|
||||
"gpr r12 .32 96 0\n"
|
||||
"gpr r13 .32 100 0\n"
|
||||
"gpr r14 .32 104 0\n"
|
||||
"gpr r15 .32 108 0\n"
|
||||
/* r16-23 are local (l0-l7) */
|
||||
"gpr r16 .32 112 0\n"
|
||||
"gpr r17 .32 116 0\n"
|
||||
"gpr r18 .32 120 0\n"
|
||||
"gpr r19 .32 124 0\n"
|
||||
"gpr r20 .32 128 0\n"
|
||||
"gpr r21 .32 132 0\n"
|
||||
"gpr r22 .32 136 0\n"
|
||||
"gpr r23 .32 140 0\n"
|
||||
/* r24-31 are in (i0-i7) */
|
||||
"gpr r24 .32 144 0\n"
|
||||
"gpr r25 .32 148 0\n"
|
||||
"gpr r26 .32 152 0\n"
|
||||
"gpr r27 .32 156 0\n"
|
||||
"gpr r28 .32 160 0\n"
|
||||
"gpr r29 .32 164 0\n"
|
||||
"gpr r30 .32 168 0\n"
|
||||
"gpr r31 .32 172 0\n";
|
||||
|
||||
static unsigned long Offset = 0;
|
||||
static RStrBuf *buf_global = NULL;
|
||||
static const ut8 *bytes = NULL;
|
||||
static int bytes_size = 0;
|
||||
|
||||
static int rl78_buffer_read_memory(bfd_vma memaddr, bfd_byte *myaddr, ut32 length, struct disassemble_info *info) {
|
||||
int delta = (memaddr - Offset);
|
||||
if (delta < 0) {
|
||||
return -1; // disable backward reads
|
||||
}
|
||||
memcpy (myaddr, bytes + delta, R_MIN (length, bytes_size));
|
||||
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 rl78_op(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *data, int len, RAnalOpMask mask) {
|
||||
if (!op) {
|
||||
return -1;
|
||||
}
|
||||
memset (op, 0, sizeof (RAnalOp));
|
||||
// RL78_ISA_G10
|
||||
// RL78_ISA_G13
|
||||
// RL78_ISA_G14
|
||||
disassemble_info disasm_obj = {0};
|
||||
memset (&disasm_obj, '\0', sizeof (struct disassemble_info));
|
||||
buf_global = r_strbuf_new ("");
|
||||
bytes = data;
|
||||
bytes_size = len;
|
||||
Offset = 0; // a->pc;
|
||||
disasm_obj.buffer = (ut8*)bytes;
|
||||
disasm_obj.read_memory_func = &rl78_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 = BFD_ENDIAN_LITTLE;
|
||||
disasm_obj.fprintf_func = &generic_fprintf_func;
|
||||
disasm_obj.stream = stdout;
|
||||
op->size = print_insn_rl78 ((bfd_vma)Offset, &disasm_obj);
|
||||
int res = print_insn_rl78_common (addr, &disasm_obj, RL78_ISA_DEFAULT);
|
||||
if (mask & R_ANAL_OP_MASK_DISASM) {
|
||||
op->mnemonic = r_strbuf_drain (buf_global);
|
||||
}
|
||||
|
||||
op->size = 1; // CGEN_MAX_INSN_SIZE;
|
||||
op->addr = addr;
|
||||
op->type = R_ANAL_OP_TYPE_UNK;
|
||||
|
||||
return op->size;
|
||||
}
|
||||
|
||||
RAnalPlugin r_anal_plugin_rl78 = {
|
||||
.name = "rl78",
|
||||
.desc = "Renesas RL78 8 bit CPU",
|
||||
.license = "LGPL3",
|
||||
.arch = "rl78",
|
||||
.bits = 8,
|
||||
.esil = false,
|
||||
.op = &rl78_op,
|
||||
// .set_reg_profile = &set_reg_profile,
|
||||
};
|
||||
|
||||
#ifndef CORELIB
|
||||
RLibStruct radare_plugin = {
|
||||
.type = R_LIB_TYPE_ANAL,
|
||||
.data = &r_anal_plugin_rl78,
|
||||
.version = R2_VERSION
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -19,7 +19,7 @@ static int aop(RAnal *anal, RAnalOp *aop, ut64 addr, const ut8 *data, int len) {
|
||||
memset(&disasm_obj, '\0', sizeof(DISASM));
|
||||
disasm_obj.EIP = (long long)(data);
|
||||
disasm_obj.VirtualAddr = addr;
|
||||
disasm_obj.Archi = ((anal->bits == 64) ? 64 : 0);
|
||||
disasm_obj.Archi = ((anal->config->bits == 64) ? 64 : 0);
|
||||
disasm_obj.SecurityBlock = 128;
|
||||
|
||||
memset(aop, 0, sizeof(RAnalOp));
|
||||
|
||||
@@ -161,13 +161,13 @@ static st64 getval(ud_operand_t *op) {
|
||||
}
|
||||
|
||||
int x86_udis86_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *data, int len) {
|
||||
const char *pc = anal->bits==64? "rip": anal->bits==32? "eip": "ip";
|
||||
const char *sp = anal->bits==64? "rsp": anal->bits==32? "esp": "sp";
|
||||
const char *bp = anal->bits==64? "rbp": anal->bits==32? "ebp": "bp";
|
||||
const char *pc = anal->config->bits==64? "rip": anal->config->bits==32? "eip": "ip";
|
||||
const char *sp = anal->config->bits==64? "rsp": anal->config->bits==32? "esp": "sp";
|
||||
const char *bp = anal->config->bits==64? "rbp": anal->config->bits==32? "ebp": "bp";
|
||||
int delta, oplen, regsz = 4;
|
||||
char str[64], src[32], dst[32];
|
||||
struct ud u;
|
||||
switch (anal->bits) {
|
||||
switch (anal->config->bits) {
|
||||
case 64: regsz = 8; break;
|
||||
case 16: regsz = 2; break;
|
||||
default:
|
||||
@@ -175,7 +175,7 @@ int x86_udis86_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *data, int len)
|
||||
}
|
||||
|
||||
UDis86Esil *handler;
|
||||
UDis86OPInfo info = {0, anal->bits, (1LL << anal->bits) - 1, regsz, 0, pc, sp, bp};
|
||||
UDis86OPInfo info = {0, anal->config->bits, (1LL << anal->config->bits) - 1, regsz, 0, pc, sp, bp};
|
||||
memset (op, '\0', sizeof (RAnalOp));
|
||||
op->addr = addr;
|
||||
op->jump = op->fail = -1;
|
||||
@@ -183,7 +183,7 @@ int x86_udis86_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *data, int len)
|
||||
|
||||
ud_init (&u);
|
||||
ud_set_pc (&u, addr);
|
||||
ud_set_mode (&u, anal->bits);
|
||||
ud_set_mode (&u, anal->config->bits);
|
||||
ud_set_syntax (&u, NULL);
|
||||
ud_set_input_buffer (&u, data, len);
|
||||
ud_disassemble (&u);
|
||||
@@ -479,7 +479,7 @@ int x86_udis86_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *data, int len)
|
||||
if (u.operand[0].type==UD_OP_PTR) {
|
||||
op->jump = getval (&u.operand[0]);
|
||||
} else {
|
||||
if (anal->bits==16) {
|
||||
if (anal->config->bits==16) {
|
||||
// honor segment
|
||||
op->jump = (addr&0xf0000) + oplen + \
|
||||
((((addr&0xffff)+getval (&u.operand[0]))&0xffff));
|
||||
@@ -557,7 +557,7 @@ int x86_udis86_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *data, int len)
|
||||
|
||||
static int set_reg_profile(RAnal *anal) {
|
||||
const char *p = NULL;
|
||||
switch (anal->bits) {
|
||||
switch (anal->config->bits) {
|
||||
case 16: p =
|
||||
"=PC ip\n"
|
||||
"=SP sp\n"
|
||||
|
||||
+8
-2
@@ -1,10 +1,16 @@
|
||||
OBJ_BA2=anal_ba2.o
|
||||
CFLAGS+=-I../asm/arch/ba2
|
||||
|
||||
STATIC_OBJ+=${OBJ_BA2}
|
||||
TARGET_BA2=anal_ba2.${LIBEXT}
|
||||
|
||||
ALL_TARGETS+=${TARGET_BA2}
|
||||
|
||||
CFLAGS_BA2=$(R2_CFLAGS)
|
||||
CFLAGS_BA2+=-I../../asm/arch/ba2
|
||||
CFLAGS_BA2+=-Wall -shared -fPIC ${LDFLAGS_LIB}
|
||||
|
||||
$(OBJ_BA2): %.o : %.c
|
||||
$(CC) -c $(CFLAGS_BA2) $< -o $@
|
||||
|
||||
${TARGET_BA2}: ${OBJ_BA2}
|
||||
${CC} $(call libname,anal_ba2) ${LDFLAGS} ${CFLAGS} -o ${TARGET_BA2} ${OBJ_BA2}
|
||||
${CC} $(call libname,anal_ba2) ${LDFLAGS} ${CFLAGS_BA2} -o ${TARGET_BA2} ${OBJ_BA2}
|
||||
@@ -1,12 +0,0 @@
|
||||
OBJ_evm=anal_evm.o
|
||||
OBJ_evm+=../../asm/arch/evm/evm.o
|
||||
CFLAGS+=-I../../asm/arch/evm/
|
||||
|
||||
STATIC_OBJ+=${OBJ_evm}
|
||||
TARGET_evm=anal_evm.${LIBEXT}
|
||||
|
||||
ALL_TARGETS+=${TARGET_evm}
|
||||
LINKFLAGS+=-ljansson
|
||||
|
||||
${TARGET_evm}: ${OBJ_evm} ${SHARED_OBJ}
|
||||
${CC} $(call libname,anal_evm) ${LDFLAGS} ${CFLAGS} -o ${TARGET_evm} ${OBJ_evm} ${LINKFLAGS}
|
||||
@@ -0,0 +1,14 @@
|
||||
OBJ_RL78=anal_rl78.o
|
||||
|
||||
STATIC_OBJ+=${OBJ_RL78}
|
||||
TARGET_RL78=anal_rl78.${LIBEXT}
|
||||
|
||||
ALL_TARGETS+=${TARGET_RL78}
|
||||
|
||||
CFLAGS+=-I../../asm/arch
|
||||
CFLAGS+=-I../../asm/arch/include
|
||||
|
||||
${TARGET_RL78}: ${OBJ_RL78}
|
||||
${CC} $(call libname,anal_rl78) ${LDFLAGS} ${CFLAGS} \
|
||||
-o anal_rl78.${LIBEXT} ${OBJ_RL78}
|
||||
|
||||
+10
-5
@@ -5,11 +5,16 @@ STATIC_OBJ+=${OBJ_X86_BEA}
|
||||
TARGET_X86_BEA=anal_x86_bea.${LIBEXT}
|
||||
|
||||
ALL_TARGETS+=${TARGET_X86_BEA}
|
||||
CFLAGS+=-I../../asm/arch/x86/bea/
|
||||
CFLAGS+=-I../../asm/arch/x86/bea/src
|
||||
CFLAGS+=-I../../asm/arch/x86/bea/include
|
||||
CFLAGS+=-DUint64=uint64_t
|
||||
|
||||
CFLAGS_BEA=$(CFLAGS)
|
||||
CFLAGS_BEA+=-I../../asm/arch/x86/bea/
|
||||
CFLAGS_BEA+=-I../../asm/arch/x86/bea/src
|
||||
CFLAGS_BEA+=-I../../asm/arch/x86/bea/include
|
||||
CFLAGS_BEA+=-DUint64=uint64_t
|
||||
|
||||
$(OBJ_X86_BEA): %.o : %.c
|
||||
$(CC) -c $(CFLAGS_BEA) $< -o $@
|
||||
|
||||
${TARGET_X86_BEA}: ${OBJ_X86_BEA}
|
||||
${CC} ${CFLAGS} -o anal_x86_bea.${LIBEXT} ${OBJ_X86_BEA}
|
||||
${CC} ${CFLAGS_BEA} -o anal_x86_bea.${LIBEXT} ${OBJ_X86_BEA}
|
||||
@#strip -s anal_x86_bea.${LIBEXT}
|
||||
@@ -1,5 +1,5 @@
|
||||
OBJ_X86_UDIS86=anal_x86_udis.o
|
||||
OBJ_ESIL_UDIS86=esil_x86_udis.o
|
||||
OBJ_X86_UDIS86+=esil_x86_udis.o
|
||||
SHARED_X86_UDIS86=../../asm/arch/x86/udis86/decode.o
|
||||
SHARED_X86_UDIS86+=../../asm/arch/x86/udis86/itab.o
|
||||
SHARED_X86_UDIS86+=../../asm/arch/x86/udis86/syn-att.o
|
||||
@@ -16,8 +16,12 @@ SHARED_OBJ+=${SHARED_X86_UDIS86}
|
||||
TARGET_X86_UDIS86=anal_x86_udis.${EXT_SO}
|
||||
|
||||
ALL_TARGETS+=${TARGET_X86_UDIS86}
|
||||
CFLAGS+=-I../../asm/arch/x86 -I../../asm/arch/x86/udis86 -DHAVE_STRING_H=1
|
||||
CFLAGS_UDIS86=$(CFLAGS)
|
||||
CFLAGS_UDIS86+=-I../../asm/arch/x86 -I../../asm/arch/x86/udis86 -DHAVE_STRING_H=1
|
||||
|
||||
$(OBJ_X86_UDIS86): %.o : %.c
|
||||
$(CC) -c $(CFLAGS_UDIS86) $< -o $@
|
||||
|
||||
${TARGET_X86_UDIS86}: ${OBJ_X86_UDIS86} ${OBJ_ESIL_UDIS86}
|
||||
${CC} ${CFLAGS} ${LDFLAGS} $(call libname,anal_x86) -lr_reg -lr_anal -lr_util \
|
||||
$(SRC_X86_UDIS86) -o anal_x86_udis.${EXT_SO} ${OBJ_X86_UDIS86} ${OBJ_ESIL_UDIS86}
|
||||
${CC} ${CFLAGS_UDIS86} ${LDFLAGS} $(call libname,anal_x86) -lr_reg -lr_anal -lr_util \
|
||||
$(SRC_X86_UDIS86) -o anal_x86_udis.${EXT_SO} ${OBJ_X86_UDIS86}
|
||||
@@ -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)
|
||||
@@ -0,0 +1,116 @@
|
||||
#if 0
|
||||
/* radare - LGPL - Copyright 2018-2021 - xvilka, pancake */
|
||||
|
||||
#include <r_types.h>
|
||||
#include <r_util.h>
|
||||
#include <r_asm.h>
|
||||
#include <r_anal.h>
|
||||
#include <r_lib.h>
|
||||
#include "hexagon.h"
|
||||
#include "hexagon_insn.h"
|
||||
#include "hexagon_anal.h"
|
||||
|
||||
static int hexagon_v6_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *buf, int len, RAnalOpMask mask) {
|
||||
if (len < 4) {
|
||||
return 0;
|
||||
}
|
||||
ut32 data = r_read_le32 (buf);
|
||||
HexInsn hi = {0};
|
||||
int size = hexagon_disasm_instruction (data, &hi, (ut32) addr);
|
||||
if (size > 0 && mask & R_ANAL_OP_MASK_DISASM) {
|
||||
op->mnemonic = strdup (hi.mnem);
|
||||
}
|
||||
op->size = size;
|
||||
if (size < 1) {
|
||||
return size;
|
||||
}
|
||||
op->vliw = hi.op_count;
|
||||
op->addr = addr;
|
||||
return hexagon_anal_instruction (&hi, op);
|
||||
}
|
||||
|
||||
static bool set_reg_profile(RAnal *anal) {
|
||||
// TODO: Add missing registers
|
||||
const char *p =
|
||||
"=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";
|
||||
|
||||
return r_reg_set_profile_string (anal->reg, p);
|
||||
}
|
||||
|
||||
RAnalPlugin r_anal_plugin_hexagon = {
|
||||
.name = "hexagon",
|
||||
.desc = "Qualcomm Hexagon (QDSP6) V6",
|
||||
.license = "LGPL3",
|
||||
.arch = "hexagon",
|
||||
.bits = 32,
|
||||
.op = hexagon_v6_op,
|
||||
.esil = false,
|
||||
.set_reg_profile = set_reg_profile,
|
||||
};
|
||||
|
||||
#ifndef R2_PLUGIN_INCORE
|
||||
R_API RLibStruct radare_plugin = {
|
||||
.type = R_LIB_TYPE_ANAL,
|
||||
.data = &r_anal_plugin_hexagon,
|
||||
.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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,282 @@
|
||||
// Predicates - declare the predicate state
|
||||
|
||||
#ifndef HEXAGON_H
|
||||
#define HEXAGON_H
|
||||
|
||||
typedef enum {
|
||||
HEX_NOPRED, // no conditional execution
|
||||
HEX_PRED_TRUE, // if (Pd) ...
|
||||
HEX_PRED_FALSE, // if (!Pd) ...
|
||||
HEX_PRED_TRUE_NEW, // if (Pd.new) ...
|
||||
HEX_PRED_FALSE_NEW, // if (!Pd.new) ...
|
||||
} HexPred;
|
||||
|
||||
// Pre/post-fixes, different types
|
||||
typedef enum {
|
||||
HEX_PF_RND = 1, // :rnd
|
||||
HEX_PF_CRND = 1<<1, // :crnd
|
||||
HEX_PF_RAW = 1<<2, // :raw
|
||||
HEX_PF_CHOP = 1<<3, // :chop
|
||||
HEX_PF_SAT = 1<<4, // :sat
|
||||
HEX_PF_HI = 1<<5, // :hi
|
||||
HEX_PF_LO = 1<<6, // :lo
|
||||
HEX_PF_LSH1 = 1<<7, // :<<1
|
||||
HEX_PF_LSH16 = 1<<8, // :<<16
|
||||
HEX_PF_RSH1 = 1<<9, // :>>1
|
||||
HEX_PF_NEG = 1<<10, // :neg
|
||||
HEX_PF_POS = 1<<11, // :pos
|
||||
HEX_PF_SCALE = 1<<12, // :scale, for FMA instructions
|
||||
HEX_PF_DEPRECATED = 1<<15, // :deprecated
|
||||
} HexPf;
|
||||
|
||||
typedef enum {
|
||||
HEX_OP_TYPE_IMM,
|
||||
HEX_OP_TYPE_REG,
|
||||
HEX_OP_TYPE_PREDICATE,
|
||||
HEX_OP_TYPE_CONTROL,
|
||||
HEX_OP_TYPE_SYSTEM,
|
||||
HEX_OP_TYPE_OPT, // Do not really use in the C code
|
||||
} HexOpType;
|
||||
|
||||
// Attributes - .H/.L, const extender
|
||||
typedef enum {
|
||||
HEX_OP_CONST_EXT = 1 << 0, // Constant extender marker for Immediate
|
||||
HEX_OP_REG_HI = 1 << 1, // Rn.H marker
|
||||
HEX_OP_REG_LO = 1 << 2, // Rn.L marker
|
||||
HEX_OP_REG_PAIR = 1 << 3, // Is this a register pair?
|
||||
} HexOpAttr;
|
||||
|
||||
typedef struct {
|
||||
ut8 type;
|
||||
union {
|
||||
ut8 reg; // + additional Hi or Lo selector // + additional shift // + additional :brev //
|
||||
ut32 imm;
|
||||
ut8 pred; // predicates - P0-P3 registers
|
||||
ut8 cr; // control register
|
||||
ut8 sys; // system control register
|
||||
} op;
|
||||
ut8 attr;
|
||||
} HexOp;
|
||||
|
||||
typedef struct {
|
||||
int instruction;
|
||||
ut32 mask;
|
||||
HexPred predicate; // predicate set if set
|
||||
ut16 pf; // additional prefixes (bitmap)
|
||||
bool duplex; // is part of duplex container?
|
||||
bool compound; // is part of compound instruction?
|
||||
bool last; // is last in instruction packet?
|
||||
int shift; // Optional shift left is it true?
|
||||
ut8 op_count;
|
||||
HexOp ops[8];
|
||||
char mnem[128]; // Instruction mnemonic
|
||||
} HexInsn;
|
||||
|
||||
// Instruction container (currently only 2 instructions)
|
||||
// Can handle duplexes
|
||||
typedef struct {
|
||||
bool duplex;
|
||||
HexInsn ins[2]; // Or make it pointer + size?
|
||||
} HexInsnCont;
|
||||
|
||||
// Instruction packet (Maximum - 4 instructions)
|
||||
// Can handle up to 4 instructions or 1 duplex + 2 instructions
|
||||
// Can have a loop marks
|
||||
typedef struct {
|
||||
bool loop0; // :endloop0 marker
|
||||
bool loop1; // :endloop1 marker
|
||||
int cont_cnt;
|
||||
HexInsnCont ins[4]; // Or make it pointer + size?
|
||||
} HexInsnPkt;
|
||||
|
||||
typedef enum {
|
||||
HEX_INSN_CLASS_CEXT = 0, // Constant extender
|
||||
HEX_INSN_CLASS_J1 = 1, // Jump
|
||||
HEX_INSN_CLASS_J2 = 2, // Jump
|
||||
HEX_INSN_CLASS_LD_ST = 3, // Load/Store
|
||||
HEX_INSN_CLASS_LD_ST_COND_GP = 4, // Load/Store conditional or GP relative
|
||||
HEX_INSN_CLASS_J3 = 5, // Jump
|
||||
HEX_INSN_CLASS_CR = 6, // Control register instructions
|
||||
HEX_INSN_CLASS_ALU32 = 7, // ALU32
|
||||
HEX_INSN_CLASS_XTYPE = 8, // XTYPE
|
||||
HEX_INSN_CLASS_LD = 9, // Just load instructions
|
||||
HEX_INSN_CLASS_ST = 10, // Just store instructions
|
||||
HEX_INSN_CLASS_ALU32_1 = 11, // ALU32
|
||||
HEX_INSN_CLASS_XTYPE_1 = 12, // XTYPE again
|
||||
HEX_INSN_CLASS_XTYPE_2 = 13, // XTYPE one more time
|
||||
HEX_INSN_CLASS_XTYPE_3 = 14, // And again, XTYPE
|
||||
HEX_INSN_CLASS_ALU32_2 = 12, // ALU32 again
|
||||
} HEX_INSN_CLASS;
|
||||
|
||||
typedef enum {
|
||||
HEX_REG_R0 = 0,
|
||||
HEX_REG_R1 = 1,
|
||||
HEX_REG_R2 = 2,
|
||||
HEX_REG_R3 = 3,
|
||||
HEX_REG_R4 = 4,
|
||||
HEX_REG_R5 = 5,
|
||||
HEX_REG_R6 = 6,
|
||||
HEX_REG_R7 = 7,
|
||||
HEX_REG_R8 = 8,
|
||||
HEX_REG_R9 = 9,
|
||||
HEX_REG_R10 = 10,
|
||||
HEX_REG_R11 = 11,
|
||||
HEX_REG_R12 = 12,
|
||||
HEX_REG_R13 = 13,
|
||||
HEX_REG_R14 = 14,
|
||||
HEX_REG_R15 = 15,
|
||||
HEX_REG_R16 = 16,
|
||||
HEX_REG_R17 = 17,
|
||||
HEX_REG_R18 = 18,
|
||||
HEX_REG_R19 = 19,
|
||||
HEX_REG_R20 = 20,
|
||||
HEX_REG_R21 = 21,
|
||||
HEX_REG_R22 = 22,
|
||||
HEX_REG_R23 = 23,
|
||||
HEX_REG_R24 = 24,
|
||||
HEX_REG_R25 = 25,
|
||||
HEX_REG_R26 = 26,
|
||||
HEX_REG_R27 = 27,
|
||||
HEX_REG_R28 = 28,
|
||||
HEX_REG_R29 = 29,
|
||||
HEX_REG_R30 = 30,
|
||||
HEX_REG_R31 = 31,
|
||||
} HEX_REG;
|
||||
|
||||
// TODO: Also add regpair values
|
||||
|
||||
// Control registers
|
||||
typedef enum {
|
||||
// Loop registers
|
||||
HEX_REG_SA0 = 0, // C0
|
||||
HEX_REG_LC0 = 1, // C1
|
||||
HEX_REG_SA1 = 2, // C2
|
||||
HEX_REG_LC1 = 3, // C3
|
||||
HEX_REG_P = 4, // C4 - 4 of 8bit registers
|
||||
// C5 is reserved
|
||||
// Modifier registers
|
||||
HEX_REG_M0 = 6, // C6
|
||||
HEX_REG_M1 = 7, // C7
|
||||
HEX_REG_USR = 8, // C8 // User Status Register
|
||||
HEX_REG_PC = 9, // C9 // Program counter
|
||||
HEX_REG_UGP = 10, // C10 // User General Pointer
|
||||
HEX_REG_GP = 11, // C11 // Global Pointer
|
||||
// Circular Start registers
|
||||
HEX_REG_CS0 = 12, // C12
|
||||
HEX_REG_CS1 = 13, // C13
|
||||
// Cycle Count registers
|
||||
HEX_REG_UPCYCLELO = 14, // C14
|
||||
HEX_REG_UPCYCLEHI = 15, // C15
|
||||
HEX_REG_FRAMELIMIT = 16, // C16 // Stack Bounds register
|
||||
HEX_REG_FRAMEKEY = 17, // C17 // Stack Smash register
|
||||
// Packet Count registers
|
||||
HEX_REG_PKTCOUNTLO = 18, // C18
|
||||
HEX_REG_PKTCOUNTHI = 19, // C19
|
||||
// C20 - C29 are reserved
|
||||
// Qtimer registers
|
||||
HEX_REG_UTIMERLO = 30, // C30
|
||||
HEX_REG_UTIMERHI = 31, // C31
|
||||
} HEX_CR_REG;
|
||||
|
||||
// Supervisor control registers
|
||||
typedef enum {
|
||||
HEX_REG_SGP0 = 0, // S0
|
||||
HEX_REG_SGP1 = 1, // S1
|
||||
HEX_REG_STID = 2, // S2
|
||||
HEX_REG_ELR = 3, // S3
|
||||
HEX_REG_BADVA0 = 4, // S4
|
||||
HEX_REG_BADVA1 = 5, // S5
|
||||
HEX_REG_SSR = 6, // S6
|
||||
HEX_REG_CCR = 7, // S7
|
||||
HEX_REG_HTID = 8, // S8
|
||||
HEX_REG_BADVA = 9, // S9
|
||||
HEX_REG_IMASK = 10, // S10
|
||||
// S11 - S15 are reserved
|
||||
HEX_REG_EVB = 16, // S16
|
||||
HEX_REG_MODECTL = 17, // S17
|
||||
HEX_REG_SYSCFG = 18, // S18
|
||||
// S19 is reserved
|
||||
HEX_REG_IPEND = 20, // S20
|
||||
HEX_REG_VID = 21, // S21
|
||||
HEX_REG_IAD = 22, // S22
|
||||
// S23 is reserved
|
||||
HEX_REG_IEL = 24, // S24
|
||||
// S25 is reserved
|
||||
HEX_REG_IAHL = 26, // S26
|
||||
HEX_REG_CFGBASE = 27, // S27
|
||||
HEX_REG_DIAG = 28, // S28
|
||||
HEX_REG_REV = 29, // S29
|
||||
HEX_REG_PCYCLELO = 30, // S30
|
||||
HEX_REG_PCYCLEHI = 31, // S31
|
||||
HEX_REG_ISDBST = 32, // S32
|
||||
HEX_REG_ISDBCFG0 = 33, // S33
|
||||
HEX_REG_ISDBCFG1 = 34, // S34
|
||||
// S35 is reserved
|
||||
HEX_REG_BRKPTPC0 = 36, // S36
|
||||
HEX_REG_BRKPTCFG0 = 37, // S37
|
||||
HEX_REG_BRKPTPC1 = 38, // S38
|
||||
HEX_REG_BRKPTCFG1 = 39, // S39
|
||||
HEX_REG_ISDBMBXIN = 40, // S40
|
||||
HEX_REG_ISDBMBXOUT = 41, // S41
|
||||
HEX_REG_ISDBEN = 42, // S42
|
||||
HEX_REG_ISDBGPR = 43, // S43
|
||||
// S44 - S47 are reserved
|
||||
HEX_REG_PMUCNT0 = 48, // S48
|
||||
HEX_REG_PMUCNT1 = 49, // S49
|
||||
HEX_REG_PMUCNT2 = 50, // S50
|
||||
HEX_REG_PMUCNT3 = 51, // S51
|
||||
HEX_REG_PMUEVTCFG = 52, // S52
|
||||
HEX_REG_PMUCFG = 53, // S53
|
||||
// S54 - S63 are reserved
|
||||
} HEX_SYSCR_REG;
|
||||
|
||||
// Here are the register field values for subinstructions
|
||||
|
||||
typedef enum {
|
||||
HEX_SUB_REG_R0 = 0, // 0b0000
|
||||
HEX_SUB_REG_R1 = 1, // 0b0001
|
||||
HEX_SUB_REG_R2 = 2, // 0b0010
|
||||
HEX_SUB_REG_R3 = 3, // 0b0011
|
||||
HEX_SUB_REG_R4 = 4, // 0b0100
|
||||
HEX_SUB_REG_R5 = 5, // 0b0101
|
||||
HEX_SUB_REG_R6 = 6, // 0b0110
|
||||
HEX_SUB_REG_R7 = 7, // 0b0111
|
||||
HEX_SUB_REG_R16 = 8, // 0b1000
|
||||
HEX_SUB_REG_R17 = 9, // 0b1001
|
||||
HEX_SUB_REG_R18 = 10, // 0b1010
|
||||
HEX_SUB_REG_R19 = 11, // 0b1011
|
||||
HEX_SUB_REG_R20 = 12, // 0b1100
|
||||
HEX_SUB_REG_R21 = 13, // 0b1101
|
||||
HEX_SUB_REG_R22 = 14, // 0b1110
|
||||
HEX_SUB_REG_R23 = 15, // 0b1111
|
||||
} HEX_SUB_REG;
|
||||
|
||||
|
||||
typedef enum {
|
||||
HEX_SUB_REGPAIR_R1_R0 = 0, // 0b000
|
||||
HEX_SUB_REGPAIR_R3_R2 = 1, // 0b001
|
||||
HEX_SUB_REGPAIR_R5_R4 = 2, // 0b010
|
||||
HEX_SUB_REGPAIR_R7_R6 = 3, // 0b011
|
||||
HEX_SUB_REGPAIR_R17_R16 = 4, // 0b100
|
||||
HEX_SUB_REGPAIR_R19_R18 = 5, // 0b101
|
||||
HEX_SUB_REGPAIR_R21_R20 = 6, // 0b110
|
||||
HEX_SUB_REGPAIR_R23_R22 = 7, // 0b111
|
||||
} HEX_SUB_REGPAIR;
|
||||
|
||||
|
||||
#define BIT_MASK(len) (BIT(len)-1)
|
||||
#define BF_MASK(start, len) (BIT_MASK(len)<<(start))
|
||||
#define BF_PREP(x, start, len) (((x)&BIT_MASK(len))<<(start))
|
||||
#define BF_GET(y, start, len) (((y)>>(start)) & BIT_MASK(len))
|
||||
#define BF_GETB(y, start, end) (BF_GET((y), (start), (end) - (start) + 1)
|
||||
|
||||
char* hex_get_cntl_reg(int opreg);
|
||||
char* hex_get_sys_reg(int opreg);
|
||||
char* hex_get_sub_reg(int opreg);
|
||||
char* hex_get_sub_regpair(int opreg);
|
||||
bool hex_if_duplex(ut32 insn_word);
|
||||
void hex_op_extend(HexOp *op);
|
||||
void hex_op_extend_off(HexOp *op, int offset);
|
||||
int hexagon_disasm_instruction(ut32 hi_u32, HexInsn *hi, ut32 addr);
|
||||
|
||||
#endif
|
||||
@@ -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 diff suppressed because it is too large.
Load diff
@@ -0,0 +1,2 @@
|
||||
int hexagon_anal_instruction(HexInsn *hi, RAnalOp *op);
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,83 @@
|
||||
/* radare - LGPL - Copyright 2015-2022 - condret */
|
||||
|
||||
#include <r_anal.h>
|
||||
#include <r_lib.h>
|
||||
|
||||
static bool mal_decode(RArchSession *s, RAnalOp *op, RArchEncodeMask mask) {
|
||||
if (op->size < 1 || !op->bytes) {
|
||||
return false;
|
||||
}
|
||||
const ut8 *data = op->bytes;
|
||||
switch ((data[0] + op->addr) % 94) {
|
||||
case 4:
|
||||
op->type = R_ANAL_OP_TYPE_UJMP;
|
||||
if (mask & R_ARCH_OP_MASK_DISASM) {
|
||||
op->mnemonic = strdup ("jmp [d]");
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
op->type = R_ANAL_OP_TYPE_IO;
|
||||
if (mask & R_ARCH_OP_MASK_DISASM) {
|
||||
op->mnemonic = strdup ("out a");
|
||||
}
|
||||
break;
|
||||
case 23:
|
||||
op->type = R_ANAL_OP_TYPE_IO;
|
||||
if (mask & R_ARCH_OP_MASK_DISASM) {
|
||||
op->mnemonic = strdup ("in a");
|
||||
}
|
||||
break;
|
||||
case 39:
|
||||
op->type = R_ANAL_OP_TYPE_ROR;
|
||||
op->type2 = R_ANAL_OP_TYPE_LOAD;
|
||||
if (mask & R_ARCH_OP_MASK_DISASM) {
|
||||
op->mnemonic = strdup ("rotr [d], mov a, [d]");
|
||||
}
|
||||
break;
|
||||
case 40:
|
||||
op->type = R_ANAL_OP_TYPE_LOAD;
|
||||
if (mask & R_ARCH_OP_MASK_DISASM) {
|
||||
op->mnemonic = strdup ("mov d, [d]");
|
||||
}
|
||||
break;
|
||||
case 62:
|
||||
op->type = R_ANAL_OP_TYPE_XOR;
|
||||
op->type2 = R_ANAL_OP_TYPE_LOAD;
|
||||
if (mask & R_ARCH_OP_MASK_DISASM) {
|
||||
op->mnemonic = strdup ("crz [d], a, mov a, [d]");
|
||||
}
|
||||
break;
|
||||
case 81:
|
||||
op->type = R_ANAL_OP_TYPE_TRAP;
|
||||
if (mask & R_ARCH_OP_MASK_DISASM) {
|
||||
op->mnemonic = strdup ("end");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
op->type = R_ANAL_OP_TYPE_NOP;
|
||||
if (mask & R_ARCH_OP_MASK_DISASM) {
|
||||
op->mnemonic = strdup ("nop");
|
||||
}
|
||||
}
|
||||
op->size = 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
RArchPlugin r_arch_plugin_malbolge = {
|
||||
.meta = {
|
||||
.name = "malbolge",
|
||||
.desc = "Malbolge analysis plugin",
|
||||
.license = "LGPL3",
|
||||
},
|
||||
.arch = "malbolge",
|
||||
.bits = 32,
|
||||
.decode = &mal_decode,
|
||||
};
|
||||
|
||||
#ifndef R2_PLUGIN_INCORE
|
||||
R_API RLibStruct radare_plugin = {
|
||||
.type = R_LIB_TYPE_ARCH,
|
||||
.data = &r_arch_plugin_malbolge,
|
||||
.version = R2_VERSION
|
||||
};
|
||||
#endif
|
||||
@@ -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
|
||||
+3
-6
@@ -1,5 +1,8 @@
|
||||
R2PM_PLUGDIR ?=$(HOME)/.config/radare2/plugins
|
||||
|
||||
all:
|
||||
@echo
|
||||
|
||||
atombios:
|
||||
cd p ; $(MAKE) asm_atombios.$(LIBEXT)
|
||||
|
||||
@@ -39,12 +42,6 @@ m68k_net:
|
||||
zyan:
|
||||
$(MAKE) -C p asm_x86_zyan.$(LIBEXT)
|
||||
|
||||
evm:
|
||||
$(MAKE) -C p asm_evm.$(LIBEXT)
|
||||
|
||||
nios:
|
||||
$(MAKE) -C p asm_nios.$(LIBEXT)
|
||||
|
||||
zyan-install: zyan
|
||||
mkdir -p $(R2PM_PLUGDIR)
|
||||
cp -f p/asm_x86_zyan.$(LIBEXT) $(R2PM_PLUGDIR)
|
||||
|
||||
@@ -433,7 +433,7 @@ static int ba2_decode_opcode(ut64 pc, const ut8 *bytes, int len, struct op_cmd *
|
||||
strcpy (cmd->instr, "b.exthz");
|
||||
snprintf (cmd->operands, sizeof (cmd->operands), "r%d, r%d", d, a);
|
||||
if (esil) {
|
||||
r_strbuf_appendf (esil, "0xffff,r{A},&,r{D},=,", a, d);
|
||||
r_strbuf_appendf (esil, "0xffff,r%d,&,r%d,=,", a, d);
|
||||
}
|
||||
return 3;
|
||||
|
||||
@@ -623,7 +623,7 @@ static int ba2_decode_opcode(ut64 pc, const ut8 *bytes, int len, struct op_cmd *
|
||||
}
|
||||
snprintf (cmd->operands, sizeof (cmd->operands), "%x", (unsigned int)(pc + s));
|
||||
if (esil) {
|
||||
r_strbuf_appendf (esil, "fl,1,==,?{,3,{S},-,pc,+=,}", s);
|
||||
r_strbuf_appendf (esil, "fl,1,==,?{,3,%d,-,pc,+=,}", s);
|
||||
}
|
||||
return 3;
|
||||
|
||||
@@ -1315,7 +1315,7 @@ static int ba2_decode_opcode(ut64 pc, const ut8 *bytes, int len, struct op_cmd *
|
||||
strcpy (cmd->instr, "b.sh");
|
||||
snprintf (cmd->operands, sizeof (cmd->operands), "0x%x(r%d), r%d", x, a, b);
|
||||
if (esil) {
|
||||
r_strbuf_appendf (esil, "r%d,0x&x,r%d,+,=[2]", b, x, a);
|
||||
r_strbuf_appendf (esil, "r%d,0x%x,r%d,+,=[2]", b, x, a);
|
||||
}
|
||||
return 4;
|
||||
|
||||
|
||||
+974
-730
File diff suppressed because it is too large.
Load diff
Loaded 100 of 590 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user