mirror of
https://github.com/radareorg/radare2-extras.git
synced 2026-11-07 22:42:19 -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 | ||
|
|
e45ff06e70 | ||
|
|
6f726e0f68 | ||
|
|
c4d27a8e94 | ||
|
|
fb7ed81025 | ||
|
|
a9b4f2be6f | ||
|
|
dd59385722 | ||
|
|
440147b930 | ||
|
|
7d2cdb43dc | ||
|
|
70907f1ee4 | ||
|
|
d7fc41424b | ||
|
|
1d54839979 | ||
|
|
5561fe99c3 | ||
|
|
e74a93c4ad | ||
|
|
374fa1646f | ||
|
|
8069025044 | ||
|
|
d818dba15e | ||
|
|
010a1e39b1 | ||
|
|
3167bed57f | ||
|
|
b6acfeef45 | ||
|
|
3fd5cd76cb | ||
|
|
86f8c56be8 | ||
|
|
a015f9fe7e | ||
|
|
792d43b3ba | ||
|
|
8d1c02121a | ||
|
|
dc5887818e | ||
|
|
ac22c81ada | ||
|
|
859c307cb5 | ||
|
|
249e782a2e | ||
|
|
097a5f56e4 | ||
|
|
d65bb20b65 | ||
|
|
e9993f8fdf | ||
|
|
db29d60aa9 | ||
|
|
e9a74be52c | ||
|
|
72a43824b1 | ||
|
|
8a5936eb64 | ||
|
|
e4a73ccf07 | ||
|
|
fc564166bd | ||
|
|
7cc5d343af | ||
|
|
854e6f38ed | ||
|
|
8da191d171 | ||
|
|
2749dedb1e | ||
|
|
327898bac1 | ||
|
|
046efbdae8 | ||
|
|
cc4a103ff3 | ||
|
|
b9723c5629 | ||
|
|
ae90621fe0 | ||
|
|
2e53b36308 | ||
|
|
26838fc56f | ||
|
|
986b99a6fe | ||
|
|
4c9a552d06 | ||
|
|
ef5771f7ce | ||
|
|
8ba3432f5c | ||
|
|
271369f8ee | ||
|
|
145e685c60 | ||
|
|
730433360e | ||
|
|
f1f617f791 | ||
|
|
c3d8e433bd | ||
|
|
934c08364f | ||
|
|
6e8b2ed5db | ||
|
|
2434f97937 | ||
|
|
3319911179 | ||
|
|
5eb18b3e3b | ||
|
|
91eeb7b154 | ||
|
|
b01f0180ea | ||
|
|
16e27dc9e9 | ||
|
|
5f6f945498 |
No files matched your search
@@ -0,0 +1,6 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "cargo"
|
||||
directory: "/x86iced"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
@@ -0,0 +1,56 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
|
||||
pull_request:
|
||||
|
||||
|
||||
jobs:
|
||||
|
||||
build-extras:
|
||||
name: Build radare2 extras and r2pipe
|
||||
runs-on: ubuntu-22.04
|
||||
env:
|
||||
EXTERNAL_BUILDS: 'keystone-lib unicorn-lib'
|
||||
LOCAL_BUILDS: 'asahi blackfin blessr2 keystone microblaze ppcdisasm r2svd vc4 x86iced'
|
||||
TESTS: 'keystone vc4'
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
repository: radareorg/radare2
|
||||
ref: master
|
||||
path: ./radare2
|
||||
- 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 -U
|
||||
- name: Compile and install plugins
|
||||
run: |
|
||||
set -e
|
||||
for p in $EXTERNAL_BUILDS ; do
|
||||
echo $p
|
||||
r2pm -i $p
|
||||
done
|
||||
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
|
||||
for p in $TESTS ; do
|
||||
echo $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,4 +17,10 @@
|
||||
*.swo
|
||||
*.un~
|
||||
/Makefile
|
||||
r2yara/Makefile
|
||||
/options.mk
|
||||
|
||||
# misc
|
||||
tags
|
||||
|
||||
node_modules
|
||||
-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" [BR] https://travis-ci.org/radareorg/radare2-extras/builds/157522362
|
||||
- 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
|
||||
- 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-regressions && make microblaze"
|
||||
- TESTS="r2pm -i msil"
|
||||
- TESTS="r2pm -i pcap"
|
||||
- TESTS="r2pm -i ppcdisasm"
|
||||
- TESTS="r2pm -i psosvm"
|
||||
- TESTS="r2pm -i pyc"
|
||||
# - 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 && cd radare2-regressions && make swf && cd .."
|
||||
# - 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-regressions && make olly-extras && cd .."
|
||||
- TESTS="r2pm -i z80-nc"
|
||||
- TESTS="r2pm -i yara && r2pm -i yara-r2"
|
||||
- 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-regressions
|
||||
- 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) {
|
||||
|
||||
+4
-4
@@ -37,7 +37,7 @@ static int findpair(ut64 addr, const ut8 *buf, int len, int base) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bcl_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *buf, int len) {
|
||||
static int bcl_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *buf, int len, RAnalOpMask mask) {
|
||||
int i;
|
||||
char cache[256] = {0};
|
||||
ut64 dst = 0LL;
|
||||
@@ -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
|
||||
|
||||
+6
-3
@@ -9,21 +9,23 @@ static int disassemble(RAsm *a, RAsmOp *op, const ut8 *buf, int len) {
|
||||
const char *bases = "ACGT";
|
||||
if (a->pc == 0) {
|
||||
ut32 *clusters = (ut32*)buf;
|
||||
snprintf (op->buf_asm, sizeof (op->buf_asm), "clusters %d\n", *clusters);
|
||||
r_strbuf_setf (&op->buf_asm, "clusters %d", *clusters);
|
||||
// snprintf (op->buf_asm, sizeof (op->buf_asm), "clusters %d\n", *clusters);
|
||||
return op->size = 4;
|
||||
}
|
||||
if (*buf != 0) {
|
||||
char base = bases[*buf & 3];
|
||||
int qual = *buf >> 2;
|
||||
snprintf (op->buf_asm, sizeof (op->buf_asm), "%c ; %d", base, qual);
|
||||
r_strbuf_setf (&op->buf_asm, "%c ; %d", base, qual);
|
||||
op->size = 1;
|
||||
return 1;
|
||||
}
|
||||
strcpy (op->buf_asm, ".");
|
||||
r_strbuf_setf (&op->buf_asm, ".");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int assemble(RAsm *a, RAsmOp *op, const char *buf) {
|
||||
#if 0
|
||||
bool qmode = false;
|
||||
int quality = 0;
|
||||
int outsz = 128;
|
||||
@@ -76,6 +78,7 @@ static int assemble(RAsm *a, RAsmOp *op, const char *buf) {
|
||||
out[op->size] = (quality<<2) | base;
|
||||
op->size ++;
|
||||
}
|
||||
#endif
|
||||
return op->size;
|
||||
}
|
||||
|
||||
|
||||
+65
-90
@@ -5,8 +5,11 @@
|
||||
#include <r_lib.h>
|
||||
#include <r_bin.h>
|
||||
|
||||
static int check_bytes(const ut8 *buf, ut64 length) {
|
||||
if (buf && length >= 4) {
|
||||
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));
|
||||
if (r == sizeof (buf)) {
|
||||
ut32 cls = r_mem_get_num (buf, 4);
|
||||
ut32 cls2 = r_mem_get_num (buf + 4, 4);
|
||||
if (cls + 4 == length && !cls2) {
|
||||
@@ -16,64 +19,49 @@ static int check_bytes(const ut8 *buf, ut64 length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static int check(RBinFile *arch) {
|
||||
const ut8 *bytes = arch ? r_buf_buffer (arch->buf) : NULL;
|
||||
ut64 sz = arch ? r_buf_size (arch->buf): 0;
|
||||
return check_bytes (bytes, sz);
|
||||
static bool load_buffer(RBinFile *bf, void **bin_obj, RBuffer *buf, ut64 loadaddr, Sdb *sdb) {
|
||||
return __check_buffer (bf, buf);
|
||||
}
|
||||
|
||||
static Sdb* get_sdb (RBinObject *o) {
|
||||
if (!o) return NULL;
|
||||
//struct r_bin_[NAME]_obj_t *bin = (struct r_bin_r_bin_[NAME]_obj_t *) o->bin_obj;
|
||||
//if (bin->kv) return kv;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void * load_bytes(RBinFile *arch, const ut8 *buf, ut64 sz, ut64 loadaddr, Sdb *sdb){
|
||||
return (void*)(size_t)check_bytes (buf, sz);
|
||||
}
|
||||
|
||||
static int load(RBinFile *arch) {
|
||||
return check(arch);
|
||||
}
|
||||
|
||||
static int destroy (RBinFile *arch) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static ut64 baddr(RBinFile *arch) {
|
||||
static ut64 baddr(RBinFile *bf) {
|
||||
return 4;
|
||||
}
|
||||
|
||||
static RBinAddr* binsym(RBinFile *arch, int type) {
|
||||
static RBinAddr* binsym(RBinFile *bf, int type) {
|
||||
return NULL; // TODO
|
||||
}
|
||||
|
||||
static ut64 findEntry(RBuffer *buf, int n) {
|
||||
ut8 b;
|
||||
ut64 buf_size = r_buf_size (buf);
|
||||
int i;
|
||||
for (i=4;i<buf->length; i++) {
|
||||
if (buf->buf[i] != 0) {
|
||||
for (i = 4; i < buf_size; i++) {
|
||||
if (r_buf_read_at (buf, i, &b, 1) != 1) {
|
||||
break;
|
||||
}
|
||||
if (b != 0) {
|
||||
if (n == 0) {
|
||||
return i;
|
||||
}
|
||||
n--;
|
||||
for (++i; i<buf->length; i++) {
|
||||
if (!buf->buf[i])
|
||||
for (++i; i < buf_size && b; i++) {
|
||||
if (r_buf_read_at (buf, i, &b, 1) != 1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static RList* entries(RBinFile *arch) {
|
||||
static RList* entries(RBinFile *bf) {
|
||||
RList* ret = r_list_newf (free);
|
||||
RBinAddr *ptr = NULL;
|
||||
if (ret) {
|
||||
if ((ptr = R_NEW0 (RBinAddr))) {
|
||||
ut64 entry = findEntry (arch->buf, 2);
|
||||
if (!entry) entry = findEntry (arch->buf, 1);
|
||||
if (!entry) entry = findEntry (arch->buf, 0);
|
||||
ut64 entry = findEntry (bf->buf, 2);
|
||||
if (!entry) entry = findEntry (bf->buf, 1);
|
||||
if (!entry) entry = findEntry (bf->buf, 0);
|
||||
if (!entry) entry = 4;
|
||||
ptr->paddr = entry;
|
||||
ptr->vaddr = entry;
|
||||
@@ -86,79 +74,74 @@ static RList* entries(RBinFile *arch) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static RList* sections(RBinFile *arch) {
|
||||
static RList* sections(RBinFile *bf) {
|
||||
RList *ret = NULL;
|
||||
RBinSection *ptr = NULL;
|
||||
ut64 textsize, datasize, symssize, spszsize, pcszsize;
|
||||
ut64 entry0 = findEntry (arch->buf, 0);
|
||||
ut64 entry1 = findEntry (arch->buf, 1);
|
||||
ut64 entry2 = findEntry (arch->buf, 2);
|
||||
ut64 entry0 = findEntry (bf->buf, 0);
|
||||
ut64 entry1 = findEntry (bf->buf, 1);
|
||||
ut64 entry2 = findEntry (bf->buf, 2);
|
||||
|
||||
if (!(ret = r_list_newf (free))) {
|
||||
return NULL;
|
||||
}
|
||||
// add text segment
|
||||
textsize = r_mem_get_num (arch->buf->buf + 4, 4);
|
||||
ut8 str[4] = {0};
|
||||
r_buf_read_at (bf->buf, 4, str, 4);
|
||||
textsize = r_mem_get_num (str, 4);
|
||||
if (!(ptr = R_NEW0 (RBinSection))) {
|
||||
return ret;
|
||||
}
|
||||
if (!entry1) {
|
||||
entry1 = arch->buf->length;
|
||||
entry1 = r_buf_size (bf->buf);
|
||||
}
|
||||
strncpy (ptr->name, "init", R_BIN_SIZEOF_STRINGS);
|
||||
ptr->size = entry1-entry0;
|
||||
ptr->vsize = entry1-entry0;
|
||||
ptr->name = strdup ("init");
|
||||
ptr->size = entry1 - entry0;
|
||||
ptr->vsize = entry1 - entry0;
|
||||
ptr->paddr = entry0 + 4;
|
||||
ptr->vaddr = entry0;
|
||||
ptr->srwx = R_BIN_SCN_READABLE | R_BIN_SCN_EXECUTABLE | R_BIN_SCN_MAP; // r-x
|
||||
ptr->add = true;
|
||||
ptr->perm = R_PERM_RX;
|
||||
r_list_append (ret, ptr);
|
||||
|
||||
if (entry1) {
|
||||
if (entry2) {
|
||||
if (!(ptr = R_NEW0 (RBinSection)))
|
||||
if (!(ptr = R_NEW0 (RBinSection))) {
|
||||
return ret;
|
||||
strncpy (ptr->name, "fini", R_BIN_SIZEOF_STRINGS);
|
||||
ptr->size = entry2-entry1;
|
||||
ptr->vsize = entry2-entry1;
|
||||
}
|
||||
ptr->name = strdup ("fini");
|
||||
ptr->size = entry2 - entry1;
|
||||
ptr->vsize = entry2 - entry1;
|
||||
ptr->paddr = entry1 + 4;
|
||||
ptr->vaddr = entry1;
|
||||
ptr->srwx = R_BIN_SCN_READABLE | R_BIN_SCN_EXECUTABLE | R_BIN_SCN_MAP; // r-x
|
||||
ptr->perm = R_PERM_RX;
|
||||
ptr->add = true;
|
||||
r_list_append (ret, ptr);
|
||||
} else {
|
||||
entry2 = entry1;
|
||||
}
|
||||
}
|
||||
if (entry2) {
|
||||
if (!(ptr = R_NEW0 (RBinSection)))
|
||||
if (!(ptr = R_NEW0 (RBinSection))) {
|
||||
return ret;
|
||||
strncpy (ptr->name, "text", R_BIN_SIZEOF_STRINGS);
|
||||
ptr->size = arch->buf->length - entry2;
|
||||
ptr->vsize = arch->buf->length - entry2;
|
||||
}
|
||||
ptr->name = strdup ("text");
|
||||
ut64 filesize = r_buf_size (bf->buf);
|
||||
ptr->size = filesize - entry2;
|
||||
ptr->vsize = filesize - entry2;
|
||||
ptr->paddr = entry2 + 4;
|
||||
ptr->vaddr = entry2;
|
||||
ptr->srwx = R_BIN_SCN_READABLE | R_BIN_SCN_EXECUTABLE | R_BIN_SCN_MAP; // r-x
|
||||
ptr->perm = R_PERM_RX;
|
||||
ptr->add = true;
|
||||
r_list_append (ret, ptr);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static RList* symbols(RBinFile *arch) {
|
||||
// TODO: parse symbol table
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static RList* imports(RBinFile *arch) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static RList* libs(RBinFile *arch) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static RBinInfo* info(RBinFile *arch) {
|
||||
static RBinInfo* info(RBinFile *bf) {
|
||||
RBinInfo *ret = R_NEW0 (RBinInfo);
|
||||
if (ret) {
|
||||
ret->file = strdup (arch->file);
|
||||
ret->file = strdup (bf->file);
|
||||
ret->bclass = strdup ("dna");
|
||||
ret->rclass = strdup ("bcl");
|
||||
ret->os = strdup ("Illumina DNA Sequences");
|
||||
@@ -174,18 +157,17 @@ static RBinInfo* info(RBinFile *arch) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ut64 size(RBinFile *arch) {
|
||||
ut64 text, data, syms, spsz;
|
||||
int big_endian;
|
||||
if (!arch->o->info) {
|
||||
arch->o->info = info (arch);
|
||||
static ut64 size(RBinFile *bf) {
|
||||
if (!bf->o->info) {
|
||||
bf->o->info = info (bf);
|
||||
}
|
||||
big_endian = arch->o->info->big_endian;
|
||||
ut8 str[32] = {0};
|
||||
r_buf_read_at (bf->buf, 0, str, 32);
|
||||
// TODO: reuse section list
|
||||
text = r_mem_get_num (arch->buf->buf + 4, 4);
|
||||
data = r_mem_get_num (arch->buf->buf + 8, 4);
|
||||
syms = r_mem_get_num (arch->buf->buf + 16, 4);
|
||||
spsz = r_mem_get_num (arch->buf->buf + 24, 4);
|
||||
ut64 text = r_mem_get_num (str + 4, 4);
|
||||
ut64 data = r_mem_get_num (str + 8, 4);
|
||||
ut64 syms = r_mem_get_num (str + 16, 4);
|
||||
ut64 spsz = r_mem_get_num (str + 24, 4);
|
||||
return text + data + syms + spsz + (6 * 4);
|
||||
}
|
||||
|
||||
@@ -193,25 +175,18 @@ RBinPlugin r_bin_plugin_bcl = {
|
||||
.name = "bcl",
|
||||
.desc = "Base Call DNA Illumina",
|
||||
.license = "BSD",
|
||||
.get_sdb = &get_sdb,
|
||||
.load = &load,
|
||||
.load_bytes = &load_bytes,
|
||||
.load_buffer = &load_buffer,
|
||||
.check_buffer = &__check_buffer,
|
||||
.size = &size,
|
||||
.destroy = &destroy,
|
||||
.check = &check,
|
||||
.check_bytes = &check_bytes,
|
||||
.baddr = &baddr,
|
||||
.binsym = &binsym,
|
||||
.entries = &entries,
|
||||
.sections = §ions,
|
||||
.symbols = &symbols,
|
||||
.imports = &imports,
|
||||
.info = &info,
|
||||
.libs = &libs,
|
||||
};
|
||||
|
||||
#ifndef CORELIB
|
||||
struct r_lib_struct_t radare_plugin = {
|
||||
RLibStruct radare_plugin = {
|
||||
.type = R_LIB_TYPE_BIN,
|
||||
.data = &r_bin_plugin_bcl,
|
||||
.version = R2_VERSION
|
||||
|
||||
@@ -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.7.2
|
||||
# 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.0.0' ; 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.0.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.0.0 configuration script done with acr v1.7.2.
|
||||
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.0.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 PKGNAME VPATH VERSION 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.0.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.7.2
|
||||
# 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' ; 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.7.2.
|
||||
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 PKGNAME VPATH VERSION 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;
|
||||
}
|
||||
+10
-8
@@ -9,6 +9,10 @@ atombios:
|
||||
$(MAKE) -C anal atombios
|
||||
$(MAKE) -C bin atombios
|
||||
|
||||
ba2:
|
||||
$(MAKE) -C asm ba2
|
||||
$(MAKE) -C anal ba2
|
||||
|
||||
blackfin:
|
||||
$(MAKE) -C asm blackfin
|
||||
|
||||
@@ -30,13 +34,9 @@ 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:
|
||||
$(MAKE) -C asm clean
|
||||
@@ -47,6 +47,10 @@ atombios-install:
|
||||
cp -f anal/p/anal_atombios.$(LIBEXT) $(R2PM_PLUGDIR)
|
||||
cp -f bin/p/bin_atombios.$(LIBEXT) $(R2PM_PLUGDIR)
|
||||
|
||||
ba2-install:
|
||||
cp -f asm/p/asm_ba2.$(LIBEXT) $(R2PM_PLUGDIR)
|
||||
cp -f anal/p/anal_ba2.$(LIBEXT) $(R2PM_PLUGDIR)
|
||||
|
||||
bea-install:
|
||||
cp -f asm/p/asm_x86_bea.$(LIBEXT) $(R2PM_PLUGDIR)
|
||||
cp -f anal/p/anal_x86_bea.$(LIBEXT) $(R2PM_PLUGDIR)
|
||||
@@ -69,12 +73,10 @@ 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)
|
||||
cp -f anal/p/anal_nios.$(LIBEXT) $(R2PM_PLUGDIR)
|
||||
|
||||
include ../options.mk
|
||||
+11
-2
@@ -1,3 +1,10 @@
|
||||
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)
|
||||
|
||||
bea:
|
||||
cd p ; $(MAKE) anal_x86_bea.$(LIBEXT)
|
||||
|
||||
@@ -10,12 +17,14 @@ m68k_net:
|
||||
atombios:
|
||||
cd p ; $(MAKE) anal_atombios.$(LIBEXT)
|
||||
|
||||
evm:
|
||||
cd p ; $(MAKE) anal_evm.$(LIBEXT)
|
||||
nios:
|
||||
cd p ; $(MAKE) anal_nios.$(LIBEXT)
|
||||
|
||||
clean:
|
||||
rm -f p/anal_ba2.$(LIBEXT)
|
||||
rm -f p/anal_x86_bea.$(LIBEXT)
|
||||
rm -f p/anal_m68k_net.$(LIBEXT)
|
||||
rm -f p/anal_atombios.{$(LIBEXT),o}
|
||||
rm -f p/anal_nios.$(LIBEXT)
|
||||
|
||||
include ../../options.mk
|
||||
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
|
||||
@@ -1,11 +1,13 @@
|
||||
ARCHS=
|
||||
|
||||
ARCHS+=ba2.mk
|
||||
ARCHS+=x86_bea.mk
|
||||
#ARCHS+=x86_im.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
|
||||
+24
-77
@@ -8,8 +8,6 @@
|
||||
|
||||
#include "../../asm/arch/atombios/atombios.h"
|
||||
|
||||
#define R_IPI static
|
||||
|
||||
typedef struct {
|
||||
_RAnalOpType optype;
|
||||
const char *reg;
|
||||
@@ -155,66 +153,17 @@ atombios_ops_t atombios_ops[256] = {
|
||||
[0xff] = { R_ANAL_OP_TYPE_ILL, NULL }, // not implemented (reserved)
|
||||
};
|
||||
|
||||
static int atombios_analyze_fns(RAnal *anal, ut64 start, ut64 end, int reftype, int depth) {
|
||||
ut8 i;
|
||||
const RList *sects;
|
||||
char name[256] = {0};
|
||||
char namesym[256] = {0};
|
||||
|
||||
if (!(sects = r_bin_get_sections(anal->binb.bin))) {
|
||||
return 0;
|
||||
}
|
||||
for (i = 0; i < N_TABLES_CMD; i++) {
|
||||
RBinSection *sect = (RBinSection *)r_list_get_n(sects, i);
|
||||
|
||||
if (!sect)
|
||||
continue;
|
||||
else if (!sect->paddr)
|
||||
continue;
|
||||
|
||||
sprintf (name, "fcn.%s", index_command_table[i]);
|
||||
r_anal_fcn_add(anal, sect->paddr, sect->size, name, R_ANAL_FCN_TYPE_FCN, NULL);
|
||||
|
||||
// Add locs for local data blocks:
|
||||
// eg:
|
||||
// 0x0000c236 5b ret
|
||||
// 0x0000c237 7a2600000000. bindata 38 bytes
|
||||
// ;end section
|
||||
|
||||
ut32 paddr = 0;
|
||||
ut32 size = 0;
|
||||
ut8 *buf = r_buf_get_at (anal->binb.bin->cur->buf, sect->paddr + sect->size - 1, NULL);
|
||||
ut8 *orig = r_buf_get_at (anal->binb.bin->cur->buf, 0, NULL);
|
||||
if (*buf == 0x5b) {
|
||||
// No data here
|
||||
continue;
|
||||
} else {
|
||||
// We have a data block at the end of the fcn.
|
||||
while (r_read_le16(buf) != 0x7a5b) {
|
||||
--buf;
|
||||
++size;
|
||||
}
|
||||
if (buf - orig < sect->paddr) {
|
||||
// WTF not in function
|
||||
continue;
|
||||
}
|
||||
buf += 2;
|
||||
--size;
|
||||
paddr = buf - orig;
|
||||
sprintf (namesym, "sym.%s", index_command_table[i]);
|
||||
r_anal_fcn_add (anal, paddr, size, namesym, R_ANAL_FCN_TYPE_SYM, NULL);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int atombios_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *b, int len) {
|
||||
static int atombios_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *b, int len, RAnalOpMask unused) {
|
||||
if (!op)
|
||||
return 1;
|
||||
return -1;
|
||||
memset (op, 0, sizeof (RAnalOp));
|
||||
op->nopcode = 1;
|
||||
op->size = atombios_inst_len (b);
|
||||
op->type = atombios_ops[*b].optype;
|
||||
if (len < op->size) {
|
||||
op->type = R_ANAL_OP_TYPE_ILL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (*b > 0x7a) {
|
||||
op->type = R_ANAL_OP_TYPE_ILL;
|
||||
@@ -418,9 +367,8 @@ static int atombios_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *b, int le
|
||||
|
||||
// op ds (imm data table)
|
||||
case 0x7a:
|
||||
{
|
||||
|
||||
} break;
|
||||
op->size = 3;// + r_read_at_le16(b, 1);
|
||||
break;
|
||||
|
||||
// op imm8
|
||||
case 0x50:
|
||||
@@ -451,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
|
||||
@@ -463,9 +411,9 @@ static int atombios_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *b, int le
|
||||
return op->size;
|
||||
}
|
||||
op->cond = R_ANAL_COND_AL;
|
||||
op->jump = cursect->paddr - 6 + r_read_at_le16(b, 1);
|
||||
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:
|
||||
{
|
||||
@@ -475,10 +423,10 @@ static int atombios_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *b, int le
|
||||
return op->size;
|
||||
}
|
||||
op->cond = R_ANAL_COND_EQ;
|
||||
op->jump = cursect->paddr - 6 + r_read_at_le16(b, 1);
|
||||
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:
|
||||
{
|
||||
@@ -488,10 +436,10 @@ static int atombios_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *b, int le
|
||||
return op->size;
|
||||
}
|
||||
op->cond = R_ANAL_COND_LT;
|
||||
op->jump = cursect->paddr - 6 + r_read_at_le16(b, 1);
|
||||
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:
|
||||
{
|
||||
@@ -501,10 +449,10 @@ static int atombios_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *b, int le
|
||||
return op->size;
|
||||
}
|
||||
op->cond = R_ANAL_COND_GT;
|
||||
op->jump = cursect->paddr - 6 + r_read_at_le16(b, 1);
|
||||
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:
|
||||
{
|
||||
@@ -514,10 +462,10 @@ static int atombios_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *b, int le
|
||||
return op->size;
|
||||
}
|
||||
op->cond = R_ANAL_COND_LE;
|
||||
op->jump = cursect->paddr - 6 + r_read_at_le16(b, 1);
|
||||
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:
|
||||
{
|
||||
@@ -527,10 +475,10 @@ static int atombios_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *b, int le
|
||||
return op->size;
|
||||
}
|
||||
op->cond = R_ANAL_COND_GE;
|
||||
op->jump = cursect->paddr - 6 + r_read_at_le16(b, 1);
|
||||
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:
|
||||
{
|
||||
@@ -540,10 +488,10 @@ static int atombios_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *b, int le
|
||||
return op->size;
|
||||
}
|
||||
op->cond = R_ANAL_COND_NE;
|
||||
op->jump = cursect->paddr - 6 + r_read_at_le16(b, 1);
|
||||
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]]
|
||||
@@ -892,7 +840,7 @@ static int archinfo(RAnal *anal, int query) {
|
||||
}
|
||||
}
|
||||
|
||||
static int set_reg_profile(RAnal *anal) {
|
||||
static bool set_reg_profile(RAnal *anal) {
|
||||
const char *p =
|
||||
"=PC pc\n"
|
||||
"=SP sp\n"
|
||||
@@ -1114,7 +1062,6 @@ RAnalPlugin r_anal_plugin_atombios = {
|
||||
.arch = "atombios",
|
||||
.bits = 32 | 64,
|
||||
.op = &atombios_op,
|
||||
.analyze_fns = atombios_analyze_fns,
|
||||
.archinfo = archinfo,
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
/* radare - LGPL - Copyright 2020 - Jerome-PS */
|
||||
|
||||
#include <r_lib.h>
|
||||
#include <r_anal.h>
|
||||
|
||||
#include "../../asm/arch/ba2/ba2_disas.c"
|
||||
|
||||
|
||||
static int ba2_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *buf, int len, RAnalOpMask mask) {
|
||||
struct op_cmd cmd = {
|
||||
.instr = "",
|
||||
.operands = ""
|
||||
};
|
||||
|
||||
op->cycles = 0;
|
||||
op->failcycles = 0;
|
||||
op->nopcode = 1;
|
||||
// op->size = ;
|
||||
// op->type = ;
|
||||
op->family = R_ANAL_OP_FAMILY_CPU; // maybe also FAMILY_IO...
|
||||
// op->id = ;
|
||||
|
||||
int ret = ba2_decode_opcode (addr, buf, len, &cmd, &op->esil, op);
|
||||
if((len < ret) || (!ret && len<6)){
|
||||
op->size = 0;
|
||||
return 0;
|
||||
}
|
||||
if (ret <= 0) {
|
||||
return -1;
|
||||
}
|
||||
return op->size = ret;
|
||||
}
|
||||
|
||||
static bool set_reg_profile(RAnal *anal) {
|
||||
const char *p =
|
||||
"=PC pc\n"
|
||||
"=SP r1\n"
|
||||
"=BP r2\n"
|
||||
"=A0 r0\n"
|
||||
"=A1 r1\n"
|
||||
"=A2 r2\n"
|
||||
"=A3 r3\n"
|
||||
"=A4 r4\n"
|
||||
"=A5 r5\n"
|
||||
"=A6 r6\n"
|
||||
"=A7 r7\n"
|
||||
"=A8 r8\n"
|
||||
"=SN r8\n" ///! TODO: ??? Which register ???
|
||||
"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 sp .32 4 0\n"
|
||||
"gpr fp .32 8 0\n"
|
||||
"gpr lr .32 36 0\n"
|
||||
"gpr pc .32 128 0\n"
|
||||
"gpr fl .1 132 0\n"
|
||||
"gpr mac .64 136 0\n";
|
||||
|
||||
return r_reg_set_profile_string (anal->reg, p);
|
||||
}
|
||||
|
||||
static int archinfo(RAnal *anal, int q) {
|
||||
// fprintf(stderr, "archinfo:%d\r\n", q);
|
||||
if (q == R_ANAL_ARCHINFO_ALIGN) {
|
||||
return 0;
|
||||
}
|
||||
if (q == R_ANAL_ARCHINFO_MAX_OP_SIZE) {
|
||||
return 6;
|
||||
}
|
||||
if (q == R_ANAL_ARCHINFO_MIN_OP_SIZE) {
|
||||
return 2;
|
||||
}
|
||||
// if (q == R_ANAL_ARCHINFO_DATA_ALIGN) {
|
||||
// return 0;
|
||||
// }
|
||||
return 0; // XXX
|
||||
}
|
||||
|
||||
RAnalPlugin r_anal_plugin_ba2 = {
|
||||
.name = "ba2",
|
||||
.arch = "ba2",
|
||||
.esil = true,
|
||||
.bits = 32,
|
||||
.desc = "Beyond Architecture 2 CPU code analysis plugin",
|
||||
.license = "LGPL3",
|
||||
.archinfo = archinfo,
|
||||
.op = &ba2_op,
|
||||
.set_reg_profile = &set_reg_profile,
|
||||
// .esil_init = esil_ba2_init,
|
||||
// .esil_fini = esil_ba2_fini
|
||||
};
|
||||
|
||||
#ifndef R2_PLUGIN_INCORE
|
||||
R_API RLibStruct radare_plugin = {
|
||||
.type = R_LIB_TYPE_ANAL,
|
||||
.data = &r_anal_plugin_ba2,
|
||||
.version = R2_VERSION
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -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
|
||||
@@ -0,0 +1,799 @@
|
||||
/* nios plugin by hewittc at 2018-2020 */
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <r_types.h>
|
||||
#include <r_lib.h>
|
||||
#include <r_asm.h>
|
||||
#include <r_anal.h>
|
||||
#include <sdb.h>
|
||||
|
||||
#include "dis-asm.h"
|
||||
|
||||
#include "nios/gnu/nios-desc.h"
|
||||
|
||||
#define f_op11(i) ((i >> 5))
|
||||
#define f_op9(i) ((i >> 7))
|
||||
#define f_op8(i) ((i >> 8))
|
||||
#define f_op6(i) ((i >> 10))
|
||||
#define f_op5w(i) ((i >> 5) & 0x001f)
|
||||
#define f_op5(i) ((i >> 11))
|
||||
#define f_op4(i) ((i >> 12))
|
||||
#define f_op3u(i) ((i >> 7) & 0x0007)
|
||||
#define f_op3(i) ((i >> 13))
|
||||
#define f_op2v(i) ((i >> 8) & 0x0003)
|
||||
|
||||
#define f_IMM11(i) ((i >> 0) & 0x07ff)
|
||||
#define f_IMM10(i) ((i >> 0) & 0x03ff)
|
||||
#define f_IMM9(i) ((i >> 1) & 0x01ff)
|
||||
#define f_IMM8v(i) ((i >> 0) & 0x00ff)
|
||||
#define f_IMM8(i) ((i >> 5) & 0x00ff)
|
||||
#define f_IMM6v(i) ((i >> 0) & 0x003f)
|
||||
#define f_IMM6(i) ((i >> 5) & 0x003f)
|
||||
#define f_IMM5(i) ((i >> 5) & 0x001f)
|
||||
#define f_IMM4w(i) ((i >> 0) & 0x00ff)
|
||||
#define f_IMM4(i) ((i >> 5) & 0x000f)
|
||||
#define f_IMM2u(i) ((i >> 5) & 0x0003)
|
||||
#define f_IMM1u(i) ((i >> 6) & 0x0001)
|
||||
|
||||
#define f_P(i) ((i >> 10) & 0x0003)
|
||||
#define f_B(i) ((i >> 5) & 0x001f)
|
||||
#define f_A(i) ((i >> 0) & 0x001f)
|
||||
|
||||
enum insn_format {
|
||||
FMT_RR,
|
||||
FMT_Ri5,
|
||||
FMT_Ri4,
|
||||
FMT_RPi5,
|
||||
FMT_Ri6,
|
||||
FMT_Ri8,
|
||||
FMT_i9,
|
||||
FMT_i10,
|
||||
FMT_i11,
|
||||
FMT_Ri1u,
|
||||
FMT_Ri2u,
|
||||
FMT_i8v,
|
||||
FMT_i6v,
|
||||
FMT_Rw,
|
||||
FMT_i4w,
|
||||
FMT_w
|
||||
};
|
||||
|
||||
enum insn_type {
|
||||
TYPE_OP6,
|
||||
TYPE_OP9,
|
||||
TYPE_OP8,
|
||||
TYPE_OP11,
|
||||
TYPE_OP5,
|
||||
TYPE_OP4,
|
||||
TYPE_OP3,
|
||||
TYPE_OPS
|
||||
};
|
||||
|
||||
struct insn_fields {
|
||||
ut16 op11 : 11;
|
||||
ut16 op9 : 9;
|
||||
ut16 op8 : 8;
|
||||
ut16 op6 : 6;
|
||||
ut16 op5w : 5;
|
||||
ut16 op5 : 5;
|
||||
ut16 op4 : 4;
|
||||
ut16 op3u : 3;
|
||||
ut16 op3 : 3;
|
||||
ut16 op2v : 2;
|
||||
|
||||
st16 IMM11 : 11;
|
||||
st16 IMM10 : 10;
|
||||
st16 IMM9 : 9;
|
||||
st16 IMM8v : 8;
|
||||
st16 IMM8 : 8;
|
||||
st16 IMM6v : 6;
|
||||
st16 IMM6 : 6;
|
||||
st16 IMM5 : 5;
|
||||
st16 IMM4w : 4;
|
||||
st16 IMM4 : 4;
|
||||
st16 IMM2u : 2;
|
||||
st16 IMM1u : 1;
|
||||
|
||||
st16 P : 2;
|
||||
st16 B : 5;
|
||||
st16 A : 5;
|
||||
};
|
||||
|
||||
struct insn_op {
|
||||
enum mach_attr mach;
|
||||
enum insn_type type;
|
||||
ut16 opcode;
|
||||
enum insn_format format;
|
||||
_RAnalOpType r_op_type;
|
||||
};
|
||||
|
||||
#define INSN_OPS_MAX 131
|
||||
static const struct insn_op insn_ops[INSN_OPS_MAX] = {
|
||||
{ MACH_NIOS16, TYPE_OP6, OP_ADD, FMT_RR, R_ANAL_OP_TYPE_ADD },
|
||||
{ MACH_NIOS16, TYPE_OP6, OP_ADDI, FMT_Ri5, R_ANAL_OP_TYPE_ADD },
|
||||
{ MACH_NIOS16, TYPE_OP6, OP_SUB, FMT_RR, R_ANAL_OP_TYPE_SUB },
|
||||
{ MACH_NIOS16, TYPE_OP6, OP_SUBI, FMT_Ri5, R_ANAL_OP_TYPE_SUB },
|
||||
{ MACH_NIOS16, TYPE_OP6, OP_CMP, FMT_RR, R_ANAL_OP_TYPE_CMP },
|
||||
{ MACH_NIOS16, TYPE_OP6, OP_CMPI, FMT_Ri5, R_ANAL_OP_TYPE_CMP },
|
||||
{ MACH_NIOS16, TYPE_OP6, OP_LSL, FMT_RR, R_ANAL_OP_TYPE_SHL },
|
||||
{ MACH_NIOS16, TYPE_OP6, OP_LSLI, FMT_Ri4, R_ANAL_OP_TYPE_SHL },
|
||||
{ MACH_NIOS16, TYPE_OP6, OP_LSR, FMT_RR, R_ANAL_OP_TYPE_SHR },
|
||||
{ MACH_NIOS16, TYPE_OP6, OP_LSRI, FMT_Ri4, R_ANAL_OP_TYPE_SHR },
|
||||
{ MACH_NIOS16, TYPE_OP6, OP_ASR, FMT_RR, R_ANAL_OP_TYPE_SAR },
|
||||
{ MACH_NIOS16, TYPE_OP6, OP_ASRI, FMT_Ri4, R_ANAL_OP_TYPE_SAR },
|
||||
{ MACH_NIOS16, TYPE_OP6, OP_MOV, FMT_RR, R_ANAL_OP_TYPE_MOV },
|
||||
{ MACH_NIOS16, TYPE_OP6, OP_MOVI, FMT_Ri5, R_ANAL_OP_TYPE_MOV },
|
||||
{ MACH_NIOS16, TYPE_OP6, OP_AND, FMT_RR, R_ANAL_OP_TYPE_AND },
|
||||
{ MACH_NIOS16, TYPE_OP6, OP_ANDN, FMT_RR, R_ANAL_OP_TYPE_AND },
|
||||
{ MACH_NIOS16, TYPE_OP6, OP_OR, FMT_RR, R_ANAL_OP_TYPE_OR },
|
||||
{ MACH_NIOS16, TYPE_OP6, OP_XOR, FMT_RR, R_ANAL_OP_TYPE_XOR },
|
||||
{ MACH_NIOS16, TYPE_OP6, OP_BGEN, FMT_Ri4, R_ANAL_OP_TYPE_MUL },
|
||||
{ MACH_NIOS16, TYPE_OP6, OP_EXT8D, FMT_RR, R_ANAL_OP_TYPE_MOV },
|
||||
{ MACH_NIOS16, TYPE_OP6, OP_SKP0, FMT_Ri4, R_ANAL_OP_TYPE_CJMP },
|
||||
{ MACH_NIOS16, TYPE_OP6, OP_SKP1, FMT_Ri4, R_ANAL_OP_TYPE_CJMP },
|
||||
{ MACH_NIOS16, TYPE_OP6, OP_LD, FMT_RR, R_ANAL_OP_TYPE_LOAD },
|
||||
{ MACH_NIOS16, TYPE_OP6, OP_ST, FMT_RR, R_ANAL_OP_TYPE_STORE },
|
||||
{ MACH_NIOS16, TYPE_OP6, OP_STS8S, FMT_i10, R_ANAL_OP_TYPE_STORE },
|
||||
{ MACH_NIOS16, TYPE_OP6, OP_ADDC, FMT_RR, R_ANAL_OP_TYPE_MOV },
|
||||
{ MACH_NIOS16, TYPE_OP6, OP_SUBC, FMT_Ri5, R_ANAL_OP_TYPE_MOV },
|
||||
{ MACH_NIOS16, TYPE_OP6, OP_USR0, FMT_RR, R_ANAL_OP_TYPE_IO },
|
||||
{ MACH_NIOS16, TYPE_OP3, OP_STS, FMT_Ri8, R_ANAL_OP_TYPE_STORE },
|
||||
{ MACH_NIOS16, TYPE_OP3, OP_LDS, FMT_Ri8, R_ANAL_OP_TYPE_LOAD },
|
||||
{ MACH_NIOS16, TYPE_OP4, OP_STP, FMT_RPi5, R_ANAL_OP_TYPE_STORE },
|
||||
{ MACH_NIOS16, TYPE_OP4, OP_LDP, FMT_RPi5, R_ANAL_OP_TYPE_LOAD },
|
||||
{ MACH_NIOS16, TYPE_OP5, OP_BR, FMT_i11, R_ANAL_OP_TYPE_JMP },
|
||||
{ MACH_NIOS16, TYPE_OP5, OP_BSR, FMT_i11, R_ANAL_OP_TYPE_JMP },
|
||||
{ MACH_NIOS16, TYPE_OP5, OP_PFX, FMT_i11, R_ANAL_OP_TYPE_MOV },
|
||||
{ MACH_NIOS16, TYPE_OP8, OP_SAVE, FMT_i8v, R_ANAL_OP_TYPE_PUSH },
|
||||
{ MACH_NIOS16, TYPE_OP8, OP_TRAP, FMT_i6v, R_ANAL_OP_TYPE_TRAP },
|
||||
{ MACH_NIOS16, TYPE_OP9, OP_EXT8S, FMT_Ri1u, R_ANAL_OP_TYPE_MOV },
|
||||
{ MACH_NIOS16, TYPE_OP9, OP_ST8S, FMT_Ri1u, R_ANAL_OP_TYPE_STORE },
|
||||
{ MACH_NIOS16, TYPE_OP11, OP_NOT, FMT_Rw, R_ANAL_OP_TYPE_NOT },
|
||||
{ MACH_NIOS16, TYPE_OP11, OP_NEG, FMT_Rw, R_ANAL_OP_TYPE_SUB },
|
||||
{ MACH_NIOS16, TYPE_OP11, OP_ABS, FMT_Rw, R_ANAL_OP_TYPE_ABS },
|
||||
{ MACH_NIOS16, TYPE_OP11, OP_SEXT8, FMT_Rw, R_ANAL_OP_TYPE_MOV },
|
||||
{ MACH_NIOS16, TYPE_OP11, OP_RLC, FMT_Rw, R_ANAL_OP_TYPE_ROL },
|
||||
{ MACH_NIOS16, TYPE_OP11, OP_RRC, FMT_Rw, R_ANAL_OP_TYPE_ROR },
|
||||
{ MACH_NIOS16, TYPE_OP11, OP_TRET, FMT_Rw, R_ANAL_OP_TYPE_UJMP },
|
||||
{ MACH_NIOS16, TYPE_OP11, OP_RESTORE, FMT_w, R_ANAL_OP_TYPE_POP },
|
||||
{ MACH_NIOS16, TYPE_OP11, OP_ST8D, FMT_Rw, R_ANAL_OP_TYPE_STORE },
|
||||
{ MACH_NIOS16, TYPE_OP11, OP_FILL8, FMT_Rw, R_ANAL_OP_TYPE_MOV },
|
||||
{ MACH_NIOS16, TYPE_OP11, OP_SKPRZ, FMT_Rw, R_ANAL_OP_TYPE_CJMP },
|
||||
{ MACH_NIOS16, TYPE_OP11, OP_SKPS, FMT_Rw, R_ANAL_OP_TYPE_CJMP },
|
||||
{ MACH_NIOS16, TYPE_OP11, OP_WRCTL, FMT_Rw, R_ANAL_OP_TYPE_MOV },
|
||||
{ MACH_NIOS16, TYPE_OP11, OP_RDCTL, FMT_Rw, R_ANAL_OP_TYPE_MOV },
|
||||
{ MACH_NIOS16, TYPE_OP11, OP_SKPRNZ, FMT_Rw, R_ANAL_OP_TYPE_CJMP },
|
||||
{ MACH_NIOS16, TYPE_OP11, OP_JMP, FMT_Rw, R_ANAL_OP_TYPE_JMP },
|
||||
{ MACH_NIOS16, TYPE_OP11, OP_CALL, FMT_Rw, R_ANAL_OP_TYPE_CALL },
|
||||
{ MACH_NIOS16, TYPE_OP11, OP_SWAP, FMT_Rw, R_ANAL_OP_TYPE_MOV },
|
||||
{ MACH_NIOS16, TYPE_OP11, OP_USR1, FMT_Rw, R_ANAL_OP_TYPE_IO },
|
||||
{ MACH_NIOS16, TYPE_OP11, OP_USR2, FMT_Rw, R_ANAL_OP_TYPE_IO },
|
||||
{ MACH_NIOS16, TYPE_OP11, OP_USR3, FMT_Rw, R_ANAL_OP_TYPE_IO },
|
||||
{ MACH_NIOS16, TYPE_OP11, OP_USR4, FMT_Rw, R_ANAL_OP_TYPE_IO },
|
||||
{ MACH_NIOS32, TYPE_OP6, OP_ADD, FMT_RR, R_ANAL_OP_TYPE_ADD },
|
||||
{ MACH_NIOS32, TYPE_OP6, OP_ADDI, FMT_Ri5, R_ANAL_OP_TYPE_ADD },
|
||||
{ MACH_NIOS32, TYPE_OP6, OP_SUB, FMT_RR, R_ANAL_OP_TYPE_SUB },
|
||||
{ MACH_NIOS32, TYPE_OP6, OP_SUBI, FMT_Ri5, R_ANAL_OP_TYPE_SUB },
|
||||
{ MACH_NIOS32, TYPE_OP6, OP_CMP, FMT_RR, R_ANAL_OP_TYPE_CMP },
|
||||
{ MACH_NIOS32, TYPE_OP6, OP_CMPI, FMT_Ri5, R_ANAL_OP_TYPE_CMP },
|
||||
{ MACH_NIOS32, TYPE_OP6, OP_LSL, FMT_RR, R_ANAL_OP_TYPE_SHL },
|
||||
{ MACH_NIOS32, TYPE_OP6, OP_LSLI, FMT_Ri5, R_ANAL_OP_TYPE_SHL },
|
||||
{ MACH_NIOS32, TYPE_OP6, OP_LSR, FMT_RR, R_ANAL_OP_TYPE_SHR },
|
||||
{ MACH_NIOS32, TYPE_OP6, OP_LSRI, FMT_Ri5, R_ANAL_OP_TYPE_SHR },
|
||||
{ MACH_NIOS32, TYPE_OP6, OP_ASR, FMT_RR, R_ANAL_OP_TYPE_SAR },
|
||||
{ MACH_NIOS32, TYPE_OP6, OP_ASRI, FMT_Ri5, R_ANAL_OP_TYPE_SAR },
|
||||
{ MACH_NIOS32, TYPE_OP6, OP_MOV, FMT_RR, R_ANAL_OP_TYPE_MOV },
|
||||
{ MACH_NIOS32, TYPE_OP6, OP_MOVI, FMT_Ri5, R_ANAL_OP_TYPE_MOV },
|
||||
{ MACH_NIOS32, TYPE_OP6, OP_AND, FMT_RR, R_ANAL_OP_TYPE_AND },
|
||||
{ MACH_NIOS32, TYPE_OP6, OP_ANDN, FMT_RR, R_ANAL_OP_TYPE_AND },
|
||||
{ MACH_NIOS32, TYPE_OP6, OP_OR, FMT_RR, R_ANAL_OP_TYPE_OR },
|
||||
{ MACH_NIOS32, TYPE_OP6, OP_XOR, FMT_RR, R_ANAL_OP_TYPE_XOR },
|
||||
{ MACH_NIOS32, TYPE_OP6, OP_BGEN, FMT_Ri5, R_ANAL_OP_TYPE_MUL },
|
||||
{ MACH_NIOS32, TYPE_OP6, OP_EXT8D, FMT_RR, R_ANAL_OP_TYPE_MOV },
|
||||
{ MACH_NIOS32, TYPE_OP6, OP_SKP0, FMT_Ri5, R_ANAL_OP_TYPE_CJMP },
|
||||
{ MACH_NIOS32, TYPE_OP6, OP_SKP1, FMT_Ri5, R_ANAL_OP_TYPE_CJMP },
|
||||
{ MACH_NIOS32, TYPE_OP6, OP_LD, FMT_RR, R_ANAL_OP_TYPE_LOAD },
|
||||
{ MACH_NIOS32, TYPE_OP6, OP_ST, FMT_RR, R_ANAL_OP_TYPE_STORE },
|
||||
{ MACH_NIOS32, TYPE_OP6, OP_STS8S, FMT_i10, R_ANAL_OP_TYPE_STORE },
|
||||
{ MACH_NIOS32, TYPE_OP6, OP_STS16S, FMT_i9, R_ANAL_OP_TYPE_STORE },
|
||||
{ MACH_NIOS32, TYPE_OP6, OP_EXT16D, FMT_RR, R_ANAL_OP_TYPE_MOV },
|
||||
{ MACH_NIOS32, TYPE_OP6, OP_MOVHI, FMT_Ri5, R_ANAL_OP_TYPE_MOV },
|
||||
{ MACH_NIOS32, TYPE_OP6, OP_USR0, FMT_RR, R_ANAL_OP_TYPE_IO },
|
||||
{ MACH_NIOS32, TYPE_OP3, OP_STS, FMT_Ri8, R_ANAL_OP_TYPE_STORE },
|
||||
{ MACH_NIOS32, TYPE_OP3, OP_LDS, FMT_Ri8, R_ANAL_OP_TYPE_LOAD },
|
||||
{ MACH_NIOS32, TYPE_OP4, OP_STP, FMT_RPi5, R_ANAL_OP_TYPE_STORE },
|
||||
{ MACH_NIOS32, TYPE_OP4, OP_LDP, FMT_RPi5, R_ANAL_OP_TYPE_LOAD },
|
||||
{ MACH_NIOS32, TYPE_OP5, OP_BR, FMT_i11, R_ANAL_OP_TYPE_JMP },
|
||||
{ MACH_NIOS32, TYPE_OP5, OP_BSR, FMT_i11, R_ANAL_OP_TYPE_JMP },
|
||||
{ MACH_NIOS32, TYPE_OP5, OP_PFXIO, FMT_i11, R_ANAL_OP_TYPE_MOV },
|
||||
{ MACH_NIOS32, TYPE_OP5, OP_PFX, FMT_i11, R_ANAL_OP_TYPE_MOV },
|
||||
{ MACH_NIOS32, TYPE_OP8, OP_SAVE, FMT_i8v, R_ANAL_OP_TYPE_PUSH },
|
||||
{ MACH_NIOS32, TYPE_OP8, OP_TRAP, FMT_i6v, R_ANAL_OP_TYPE_TRAP },
|
||||
{ MACH_NIOS32, TYPE_OP9, OP_EXT8S, FMT_Ri1u, R_ANAL_OP_TYPE_MOV },
|
||||
{ MACH_NIOS32, TYPE_OP9, OP_EXT16S, FMT_Ri1u, R_ANAL_OP_TYPE_MOV },
|
||||
{ MACH_NIOS32, TYPE_OP9, OP_ST8S, FMT_Ri1u, R_ANAL_OP_TYPE_STORE },
|
||||
{ MACH_NIOS32, TYPE_OP9, OP_ST16S, FMT_Ri1u, R_ANAL_OP_TYPE_STORE },
|
||||
{ MACH_NIOS32, TYPE_OP11, OP_NOT, FMT_Rw, R_ANAL_OP_TYPE_NOT },
|
||||
{ MACH_NIOS32, TYPE_OP11, OP_NEG, FMT_Rw, R_ANAL_OP_TYPE_SUB },
|
||||
{ MACH_NIOS32, TYPE_OP11, OP_ABS, FMT_Rw, R_ANAL_OP_TYPE_ABS },
|
||||
{ MACH_NIOS32, TYPE_OP11, OP_SEXT8, FMT_Rw, R_ANAL_OP_TYPE_MOV },
|
||||
{ MACH_NIOS32, TYPE_OP11, OP_SEXT16, FMT_Rw, R_ANAL_OP_TYPE_MOV },
|
||||
{ MACH_NIOS32, TYPE_OP11, OP_RLC, FMT_Rw, R_ANAL_OP_TYPE_ROL },
|
||||
{ MACH_NIOS32, TYPE_OP11, OP_RRC, FMT_Rw, R_ANAL_OP_TYPE_ROR },
|
||||
{ MACH_NIOS32, TYPE_OP11, OP_TRET, FMT_Rw, R_ANAL_OP_TYPE_UJMP },
|
||||
{ MACH_NIOS32, TYPE_OP11, OP_RESTORE, FMT_w, R_ANAL_OP_TYPE_POP },
|
||||
{ MACH_NIOS32, TYPE_OP11, OP_ST8D, FMT_Rw, R_ANAL_OP_TYPE_STORE },
|
||||
{ MACH_NIOS32, TYPE_OP11, OP_ST16D, FMT_Rw, R_ANAL_OP_TYPE_STORE },
|
||||
{ MACH_NIOS32, TYPE_OP11, OP_FILL8, FMT_Rw, R_ANAL_OP_TYPE_MOV },
|
||||
{ MACH_NIOS32, TYPE_OP11, OP_FILL16, FMT_Rw, R_ANAL_OP_TYPE_MOV },
|
||||
{ MACH_NIOS32, TYPE_OP11, OP_SKPRZ, FMT_Rw, R_ANAL_OP_TYPE_CJMP },
|
||||
{ MACH_NIOS32, TYPE_OP11, OP_SKPS, FMT_Rw, R_ANAL_OP_TYPE_CJMP },
|
||||
{ MACH_NIOS32, TYPE_OP11, OP_WRCTL, FMT_Rw, R_ANAL_OP_TYPE_MOV },
|
||||
{ MACH_NIOS32, TYPE_OP11, OP_RDCTL, FMT_Rw, R_ANAL_OP_TYPE_MOV },
|
||||
{ MACH_NIOS32, TYPE_OP11, OP_SKPRNZ, FMT_Rw, R_ANAL_OP_TYPE_CJMP },
|
||||
{ MACH_NIOS32, TYPE_OP11, OP_JMP, FMT_Rw, R_ANAL_OP_TYPE_JMP },
|
||||
{ MACH_NIOS32, TYPE_OP11, OP_CALL, FMT_Rw, R_ANAL_OP_TYPE_CALL },
|
||||
{ MACH_NIOS32, TYPE_OP11, OP_SWAP, FMT_Rw, R_ANAL_OP_TYPE_MOV },
|
||||
{ MACH_NIOS32, TYPE_OP11, OP_USR1, FMT_Rw, R_ANAL_OP_TYPE_IO },
|
||||
{ MACH_NIOS32, TYPE_OP11, OP_USR2, FMT_Rw, R_ANAL_OP_TYPE_IO },
|
||||
{ MACH_NIOS32, TYPE_OP11, OP_USR3, FMT_Rw, R_ANAL_OP_TYPE_IO },
|
||||
{ MACH_NIOS32, TYPE_OP11, OP_USR4, FMT_Rw, R_ANAL_OP_TYPE_IO },
|
||||
{ MACH_NIOS32, TYPE_OP11, OP_MSTEP, FMT_Rw, R_ANAL_OP_TYPE_MUL },
|
||||
{ MACH_NIOS32, TYPE_OP11, OP_MUL, FMT_Rw, R_ANAL_OP_TYPE_MUL }
|
||||
};
|
||||
|
||||
struct nios_info {
|
||||
HtPP *ops;
|
||||
};
|
||||
|
||||
static struct nios_info *nios;
|
||||
|
||||
static const char *nios16_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 *nios32_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 int parse_insn(enum mach_attr mach, ut16 insn, struct insn_op **op, struct insn_fields *f) {
|
||||
ut16 insns[TYPE_OPS] = {
|
||||
f_op6(insn),
|
||||
f_op9(insn),
|
||||
f_op8(insn),
|
||||
f_op11(insn),
|
||||
f_op5(insn),
|
||||
f_op4(insn),
|
||||
f_op3(insn),
|
||||
};
|
||||
|
||||
bool found;
|
||||
int opcode;
|
||||
|
||||
for (int type = TYPE_OP6; type < TYPE_OPS; type++) {
|
||||
r_strf_var (key, 128, "%d %d %d", mach, type, insns[type]);
|
||||
*op = ht_pp_find(nios->ops, key, &found);
|
||||
|
||||
if (found) {
|
||||
opcode = (*op)->opcode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch ((*op)->format) {
|
||||
case FMT_RR:
|
||||
f->op6 = f_op6(insn);
|
||||
f->B = f_B(insn);
|
||||
f->A = f_A(insn);
|
||||
break;
|
||||
case FMT_Ri5:
|
||||
f->op6 = f_op6(insn);
|
||||
f->IMM5 = f_IMM5(insn);
|
||||
f->A = f_A(insn);
|
||||
break;
|
||||
case FMT_Ri4:
|
||||
f->op6 = f_op6(insn);
|
||||
f->IMM4 = f_IMM4(insn);
|
||||
f->A = f_A(insn);
|
||||
break;
|
||||
case FMT_RPi5:
|
||||
f->op4 = f_op4(insn);
|
||||
f->P = f_P(insn);
|
||||
f->B = f_B(insn);
|
||||
f->A = f_A(insn);
|
||||
break;
|
||||
case FMT_Ri6:
|
||||
f->op5 = f_op5(insn);
|
||||
f->IMM6 = f_IMM6(insn);
|
||||
f->A = f_A(insn);
|
||||
break;
|
||||
case FMT_Ri8:
|
||||
f->op3 = f_op3(insn);
|
||||
f->IMM8 = f_IMM8(insn);
|
||||
f->A = f_A(insn);
|
||||
break;
|
||||
case FMT_i9:
|
||||
f->op6 = f_op6(insn);
|
||||
f->IMM9 = f_IMM9(insn);
|
||||
break;
|
||||
case FMT_i10:
|
||||
f->op6 = f_op6(insn);
|
||||
f->IMM10 = f_IMM10(insn);
|
||||
break;
|
||||
case FMT_i11:
|
||||
f->op5 = f_op5(insn);
|
||||
f->IMM11 = f_IMM11(insn);
|
||||
break;
|
||||
case FMT_Ri1u:
|
||||
f->op6 = f_op6(insn);
|
||||
f->op3u = f_op3u(insn);
|
||||
f->IMM1u = f_IMM1u(insn);
|
||||
f->A = f_A(insn);
|
||||
break;
|
||||
case FMT_Ri2u:
|
||||
f->op6 = f_op6(insn);
|
||||
f->op3u = f_op3u(insn);
|
||||
f->IMM2u = f_IMM2u(insn);
|
||||
f->A = f_A(insn);
|
||||
break;
|
||||
case FMT_i8v:
|
||||
f->op6 = f_op6(insn);
|
||||
f->op2v = f_op2v(insn);
|
||||
f->IMM8v = f_IMM8v(insn);
|
||||
break;
|
||||
case FMT_i6v:
|
||||
f->op6 = f_op6(insn);
|
||||
f->op2v = f_op2v(insn);
|
||||
f->IMM6v = f_IMM6v(insn);
|
||||
break;
|
||||
case FMT_Rw:
|
||||
f->op6 = f_op6(insn);
|
||||
f->op5w = f_op5w(insn);
|
||||
f->A = f_A(insn);
|
||||
break;
|
||||
case FMT_i4w:
|
||||
f->op6 = f_op6(insn);
|
||||
f->op5w = f_op5w(insn);
|
||||
f->IMM4w = f_IMM4w(insn);
|
||||
break;
|
||||
case FMT_w:
|
||||
f->op6 = f_op6(insn);
|
||||
f->op5w = f_op5w(insn);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return opcode;
|
||||
}
|
||||
|
||||
static void nios16_anal(RAnalOp *op, ut16 opcode, enum insn_type type, struct insn_fields *f) {
|
||||
if (type == TYPE_OP6) {
|
||||
switch (opcode) {
|
||||
case OP_ADD:
|
||||
case OP_ADDI:
|
||||
case OP_SUB:
|
||||
case OP_SUBI:
|
||||
case OP_CMP:
|
||||
case OP_CMPI:
|
||||
case OP_LSL:
|
||||
case OP_LSLI:
|
||||
case OP_LSR:
|
||||
case OP_LSRI:
|
||||
case OP_ASR:
|
||||
case OP_ASRI:
|
||||
case OP_MOV:
|
||||
case OP_MOVI:
|
||||
case OP_AND:
|
||||
case OP_ANDN:
|
||||
case OP_OR:
|
||||
case OP_XOR:
|
||||
case OP_BGEN:
|
||||
case OP_EXT8D:
|
||||
case OP_SKP0:
|
||||
case OP_SKP1:
|
||||
case OP_LD:
|
||||
case OP_ST:
|
||||
case OP_STS8S:
|
||||
case OP_ADDC:
|
||||
case OP_SUBC:
|
||||
case OP_USR0:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (type == TYPE_OP3) {
|
||||
switch (opcode) {
|
||||
case OP_STS:
|
||||
case OP_LDS:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (type == TYPE_OP4) {
|
||||
switch (opcode) {
|
||||
case OP_STP:
|
||||
case OP_LDP:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (type == TYPE_OP5) {
|
||||
switch (opcode) {
|
||||
case OP_BR:
|
||||
case OP_BSR:
|
||||
op->jump = op->addr + ((f->IMM11 + 1) * 2);
|
||||
break;
|
||||
case OP_PFX:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (type == TYPE_OP8) {
|
||||
switch (opcode) {
|
||||
case OP_SAVE:
|
||||
case OP_TRAP:
|
||||
break;
|
||||
}
|
||||
} else if (type == TYPE_OP9) {
|
||||
switch (opcode) {
|
||||
case OP_EXT8S:
|
||||
case OP_ST8S:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (type == TYPE_OP11) {
|
||||
switch (opcode) {
|
||||
case OP_NOT:
|
||||
case OP_NEG:
|
||||
case OP_ABS:
|
||||
case OP_SEXT8:
|
||||
case OP_RLC:
|
||||
case OP_RRC:
|
||||
case OP_TRET:
|
||||
case OP_RESTORE:
|
||||
case OP_ST8D:
|
||||
case OP_FILL8:
|
||||
case OP_SKPRZ:
|
||||
case OP_SKPS:
|
||||
case OP_WRCTL:
|
||||
case OP_RDCTL:
|
||||
case OP_SKPRNZ:
|
||||
case OP_JMP:
|
||||
case OP_CALL:
|
||||
case OP_SWAP:
|
||||
case OP_USR1:
|
||||
case OP_USR2:
|
||||
case OP_USR3:
|
||||
case OP_USR4:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void nios32_anal(RAnalOp *op, ut16 opcode, enum insn_type type, struct insn_fields *f) {
|
||||
if (type == TYPE_OP6) {
|
||||
switch (opcode) {
|
||||
case OP_ADD:
|
||||
case OP_ADDI:
|
||||
case OP_SUB:
|
||||
case OP_SUBI:
|
||||
case OP_CMP:
|
||||
case OP_CMPI:
|
||||
case OP_LSL:
|
||||
case OP_LSLI:
|
||||
case OP_LSR:
|
||||
case OP_LSRI:
|
||||
case OP_ASR:
|
||||
case OP_ASRI:
|
||||
case OP_MOV:
|
||||
case OP_MOVI:
|
||||
case OP_AND:
|
||||
case OP_ANDN:
|
||||
case OP_OR:
|
||||
case OP_XOR:
|
||||
case OP_BGEN:
|
||||
case OP_EXT8D:
|
||||
case OP_SKP0:
|
||||
case OP_SKP1:
|
||||
case OP_LD:
|
||||
case OP_ST:
|
||||
case OP_STS8S:
|
||||
case OP_STS16S:
|
||||
case OP_EXT16D:
|
||||
case OP_MOVHI:
|
||||
case OP_USR0:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (type == TYPE_OP3) {
|
||||
switch (opcode) {
|
||||
case OP_STS:
|
||||
case OP_LDS:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (type == TYPE_OP4) {
|
||||
switch (opcode) {
|
||||
case OP_STP:
|
||||
case OP_LDP:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (type == TYPE_OP5) {
|
||||
switch (opcode) {
|
||||
case OP_BR:
|
||||
case OP_BSR:
|
||||
op->jump = op->addr + ((f->IMM11 + 1) * 2);
|
||||
break;
|
||||
case OP_PFXIO:
|
||||
case OP_PFX:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (type == TYPE_OP8) {
|
||||
switch (opcode) {
|
||||
case OP_SAVE:
|
||||
case OP_TRAP:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (type == TYPE_OP9) {
|
||||
switch (opcode) {
|
||||
case OP_EXT8S:
|
||||
case OP_EXT16S:
|
||||
case OP_ST8S:
|
||||
case OP_ST16S:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (type == TYPE_OP11) {
|
||||
switch (opcode) {
|
||||
case OP_NOT:
|
||||
case OP_NEG:
|
||||
case OP_ABS:
|
||||
case OP_SEXT8:
|
||||
case OP_SEXT16:
|
||||
case OP_RLC:
|
||||
case OP_RRC:
|
||||
case OP_TRET:
|
||||
case OP_RESTORE:
|
||||
case OP_ST8D:
|
||||
case OP_ST16D:
|
||||
case OP_FILL8:
|
||||
case OP_FILL16:
|
||||
case OP_SKPRZ:
|
||||
case OP_SKPS:
|
||||
case OP_WRCTL:
|
||||
case OP_RDCTL:
|
||||
case OP_SKPRNZ:
|
||||
case OP_JMP:
|
||||
case OP_CALL:
|
||||
case OP_SWAP:
|
||||
case OP_USR1:
|
||||
case OP_USR2:
|
||||
case OP_USR3:
|
||||
case OP_USR4:
|
||||
case OP_MSTEP:
|
||||
case OP_MUL:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int nios_op(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *data, int len, RAnalOpMask mask) {
|
||||
if (!op) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(op, 0, sizeof (RAnalOp));
|
||||
|
||||
op->size = CGEN_MAX_INSN_SIZE;
|
||||
op->addr = addr;
|
||||
op->type = R_ANAL_OP_TYPE_UNK;
|
||||
|
||||
enum mach_attr arch;
|
||||
void (*nios_anal)(RAnalOp *, ut16, enum insn_type, struct insn_fields *);
|
||||
|
||||
if (a->bits == 16) {
|
||||
arch = MACH_NIOS16;
|
||||
nios_anal = &nios16_anal;
|
||||
} else {
|
||||
arch = MACH_NIOS32;
|
||||
nios_anal = &nios32_anal;
|
||||
}
|
||||
|
||||
ut16 insn;
|
||||
insn = r_read_ble16(data, a->big_endian);
|
||||
|
||||
struct insn_op *insn_op;
|
||||
struct insn_fields insn_fields = { 0 };
|
||||
|
||||
int opcode;
|
||||
opcode = parse_insn(arch, insn, &insn_op, &insn_fields);
|
||||
|
||||
if (opcode >= 0) {
|
||||
op->type = insn_op->r_op_type;
|
||||
(*nios_anal)(op, opcode, insn_op->type, &insn_fields);
|
||||
}
|
||||
|
||||
return op->size;
|
||||
}
|
||||
|
||||
static bool set_reg_profile(RAnal *a) {
|
||||
const char *nios_reg_profile;
|
||||
|
||||
if (a->bits == 16) {
|
||||
nios_reg_profile = nios16_reg_profile;
|
||||
} else {
|
||||
nios_reg_profile = nios32_reg_profile;
|
||||
}
|
||||
|
||||
return r_reg_set_profile_string(a->reg, nios_reg_profile);
|
||||
}
|
||||
|
||||
static void nios_free_kv(HtPPKv *kv) {
|
||||
if (kv && kv->key) {
|
||||
free(kv->key);
|
||||
}
|
||||
}
|
||||
|
||||
static int nios_init(void *user) {
|
||||
if (!nios) {
|
||||
nios = calloc(1, sizeof (*nios));
|
||||
nios->ops = ht_pp_new(NULL, nios_free_kv, NULL);
|
||||
if (!nios->ops) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < INSN_OPS_MAX; i++) {
|
||||
const struct insn_op *op = &insn_ops[i];
|
||||
r_strf_var (key, 64, "%d %d %d", op->mach, op->type, op->opcode);
|
||||
ht_pp_insert(nios->ops, key, (void *) op);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nios_fini(void *user) {
|
||||
if (nios && nios->ops) {
|
||||
ht_pp_free(nios->ops);
|
||||
}
|
||||
|
||||
if (nios) {
|
||||
free(nios);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
RAnalPlugin r_anal_plugin_nios = {
|
||||
.name = "nios",
|
||||
.desc = "Altera Nios code analysis plugin",
|
||||
.license = "LGPL3",
|
||||
.arch = "nios",
|
||||
.bits = 16 | 32,
|
||||
.esil = false,
|
||||
.init = &nios_init,
|
||||
.fini = &nios_fini,
|
||||
.op = &nios_op,
|
||||
.cmd_ext = NULL,
|
||||
.set_reg_profile = &set_reg_profile,
|
||||
};
|
||||
|
||||
#ifndef CORELIB
|
||||
RLibStruct radare_plugin = {
|
||||
.type = R_LIB_TYPE_ANAL,
|
||||
.data = &r_anal_plugin_nios,
|
||||
.version = R2_VERSION
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
OBJ_BA2=anal_ba2.o
|
||||
|
||||
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_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_NIOS=anal_nios.o
|
||||
|
||||
STATIC_OBJ+=${OBJ_NIOS}
|
||||
TARGET_NIOS=anal_nios.${LIBEXT}
|
||||
|
||||
ALL_TARGETS+=${TARGET_NIOS}
|
||||
|
||||
CFLAGS+=-I../../asm/arch
|
||||
CFLAGS+=-I../../asm/arch/include
|
||||
|
||||
${TARGET_NIOS}: ${OBJ_NIOS}
|
||||
${CC} $(call libname,anal_nios) ${LDFLAGS} ${CFLAGS} \
|
||||
-o anal_nios.${LIBEXT} ${OBJ_NIOS}
|
||||
|
||||
@@ -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
|
||||
@@ -0,0 +1,91 @@
|
||||
/* radare - LGPL - Copyright 2017 - pancake */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <r_types.h>
|
||||
#include <r_lib.h>
|
||||
#include <r_util.h>
|
||||
#include <r_asm.h>
|
||||
#include "disas-asm.h"
|
||||
#include <mybfd.h>
|
||||
|
||||
disassembler_ftype
|
||||
hexagon_get_disassembler_from_mach(
|
||||
unsigned long machine,
|
||||
unsigned long big_p
|
||||
);
|
||||
static unsigned long Offset = 0;
|
||||
static RStrBuf *buf_global = NULL;
|
||||
static unsigned char bytes[4];
|
||||
|
||||
static int hexagon_buffer_read_memory (bfd_vma memaddr, bfd_byte *myaddr, unsigned int length, struct disassemble_info *info) {
|
||||
memcpy (myaddr, bytes, length);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int symbol_at_address(bfd_vma addr, struct disassemble_info * info) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void memory_error_func(int status, bfd_vma memaddr, struct disassemble_info *info) {
|
||||
//--
|
||||
}
|
||||
|
||||
DECLARE_GENERIC_PRINT_ADDRESS_FUNC()
|
||||
DECLARE_GENERIC_FPRINTF_FUNC()
|
||||
|
||||
static int disassemble(RAsm *a, RAsmOp *op, const ut8 *buf, int len) {
|
||||
static int (*print_insn_hexagon)(bfd_vma, struct disassemble_info *);
|
||||
static struct disassemble_info disasm_obj;
|
||||
if (len < 4) {
|
||||
return -1;
|
||||
}
|
||||
buf_global = &op->buf_asm;
|
||||
Offset = a->pc;
|
||||
// disasm inverted
|
||||
r_mem_swapendian (bytes, buf, 4); // TODO handle thumb
|
||||
|
||||
/* prepare disassembler */
|
||||
memset (&disasm_obj,'\0', sizeof (struct disassemble_info));
|
||||
disasm_obj.buffer = bytes;
|
||||
disasm_obj.read_memory_func = &hexagon_buffer_read_memory;
|
||||
disasm_obj.symbol_at_address_func = &symbol_at_address;
|
||||
disasm_obj.memory_error_func = &memory_error_func;
|
||||
disasm_obj.print_address_func = &generic_print_address_func;
|
||||
disasm_obj.endian = a->big_endian;
|
||||
disasm_obj.fprintf_func = &generic_fprintf_func;
|
||||
disasm_obj.stream = stdout;
|
||||
disasm_obj.mach = 0;
|
||||
|
||||
r_strbuf_set (&op->buf_asm, "");
|
||||
print_insn_hexagon = hexagon_get_disassembler_from_mach (0, 0);
|
||||
op->size = print_insn_hexagon ((bfd_vma)Offset, &disasm_obj);
|
||||
|
||||
if (!strncmp ( r_strbuf_get (&op->buf_asm), "unknown", 7)) {
|
||||
r_strbuf_set (&op->buf_asm, "invalid");
|
||||
}
|
||||
|
||||
if (op->size == -1) {
|
||||
r_strbuf_set (&op->buf_asm, "(data)");
|
||||
}
|
||||
return op->size;
|
||||
}
|
||||
|
||||
RAsmPlugin r_asm_plugin_hexagon_gnu = {
|
||||
.name = "hexagon.gnu",
|
||||
.arch = "hexagon.gnu",
|
||||
.bits = 32,
|
||||
.endian = R_SYS_ENDIAN_BIG | R_SYS_ENDIAN_LITTLE,
|
||||
.license = "GPL3",
|
||||
.desc = "Qualcomm DSPv5",
|
||||
.disassemble = &disassemble,
|
||||
};
|
||||
|
||||
#ifndef R2_PLUGIN_INCORE
|
||||
R_API RLibStruct radare_plugin = {
|
||||
.type = R_LIB_TYPE_ASM,
|
||||
.data = &r_asm_plugin_hexagon_gnu,
|
||||
.version = R2_VERSION
|
||||
};
|
||||
#endif
|
||||
@@ -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
|
||||
Loaded 100 of 646 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user