mirror of
https://github.com/radareorg/radare2-extras.git
synced 2026-11-10 17:42:29 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
73960d34df | ||
|
|
2afaceab6a | ||
|
|
a29ce917c1 | ||
|
|
8c738204dd | ||
|
|
031b077f2c | ||
|
|
2a44edead6 | ||
|
|
ee031a7021 | ||
|
|
0a0327aa45 | ||
|
|
9870775224 | ||
|
|
d5e7a28186 | ||
|
|
c9571534b9 | ||
|
|
5fff0016a3 | ||
|
|
f2199032a7 | ||
|
|
5d28dc6de4 | ||
|
|
645f4154ff | ||
|
|
899e3344ff | ||
|
|
6493987c72 | ||
|
|
ba096f3546 | ||
|
|
bfab794507 | ||
|
|
619f60a7df | ||
|
|
f4f11b90c3 | ||
|
|
f58de93399 | ||
|
|
58a5ac18e6 | ||
|
|
9b0adabca8 | ||
|
|
219b1f7c07 | ||
|
|
a1b8861f9d | ||
|
|
85f40b5d6c | ||
|
|
a8d4a6a520 | ||
|
|
e108f90f79 | ||
|
|
5b9a32f8c4 | ||
|
|
71ab77c46b | ||
|
|
b6da363492 | ||
|
|
4932f31af9 | ||
|
|
cdd0753019 | ||
|
|
8b98f544d7 | ||
|
|
4ad1a62408 | ||
|
|
39458c3b5b | ||
|
|
b07fcf44b1 | ||
|
|
58536ef4e9 | ||
|
|
3dfb0180d0 | ||
|
|
73831a1ee2 | ||
|
|
68e9f6dfe3 | ||
|
|
2c54fda563 | ||
|
|
a0ccecf534 | ||
|
|
e94cc3060d | ||
|
|
ac1af9c612 | ||
|
|
94bccea25c | ||
|
|
3f8dada173 | ||
|
|
a21d29689b | ||
|
|
099cb94abf | ||
|
|
de674fbeb0 | ||
|
|
f81d48eaca | ||
|
|
610dd48707 | ||
|
|
c6663b87e9 | ||
|
|
f7dca9d52b | ||
|
|
f2a4b1dfa0 | ||
|
|
b5b1101110 | ||
|
|
445c6a5a57 | ||
|
|
5ab2c6aa7d | ||
|
|
1e989215d9 | ||
|
|
a2692a2380 | ||
|
|
614d94959e | ||
|
|
7a0269097b | ||
|
|
c8f032c01d | ||
|
|
188d102f6b | ||
|
|
3275d32127 | ||
|
|
f4218097d2 | ||
|
|
96dbf53b1c | ||
|
|
e3111fcba3 | ||
|
|
5b0ea473f9 | ||
|
|
f28a2ec94c | ||
|
|
80925aeba6 | ||
|
|
45f9bc841c | ||
|
|
69f93467a1 | ||
|
|
67b24be239 | ||
|
|
cd9cc5c190 | ||
|
|
568a7fd146 | ||
|
|
d276feb5e8 | ||
|
|
c3b9864f1d | ||
|
|
7a6e3737c8 | ||
|
|
430b6fa559 | ||
|
|
1cf58513ad | ||
|
|
da8623bdbe | ||
|
|
43057468c6 | ||
|
|
7ed4cb393f | ||
|
|
031b7c20c0 | ||
|
|
9edd5e922b | ||
|
|
dea1f62f8f | ||
|
|
e9306ef9fe | ||
|
|
941e0e8f81 | ||
|
|
fdcf847944 | ||
|
|
e9035eda1c | ||
|
|
f2d4e0d371 | ||
|
|
f06bef6f21 | ||
|
|
aac87e940d | ||
|
|
6c0afb35c2 | ||
|
|
1b276095d4 | ||
|
|
e90d99b9f4 | ||
|
|
e0bb03cdd1 | ||
|
|
6c9df38c66 | ||
|
|
38e79b50b1 | ||
|
|
b03125fc99 | ||
|
|
36f9503eda | ||
|
|
3a25b7f345 | ||
|
|
b91c295be3 | ||
|
|
9e4c70872e | ||
|
|
94f8d2dc94 | ||
|
|
89624cc37c | ||
|
|
42aed83113 | ||
|
|
4d944cce9a | ||
|
|
49a91651d2 | ||
|
|
3596e7f1a5 | ||
|
|
54ff412976 | ||
|
|
3d2fa7985b | ||
|
|
3064bbcb7f | ||
|
|
97d8b87bf5 | ||
|
|
26450ea9b9 | ||
|
|
14d385082c | ||
|
|
3a92956545 | ||
|
|
5ef0b34d57 | ||
|
|
57f3c159e0 | ||
|
|
991ee0f685 | ||
|
|
4e72a04103 | ||
|
|
9a61bb6f7d | ||
|
|
9c22aa709d | ||
|
|
ccefb4237d | ||
|
|
ef93ab4c91 | ||
|
|
496b46918b | ||
|
|
82b3a8e97d | ||
|
|
0350bec1e7 | ||
|
|
6e06bcd365 | ||
|
|
b170500a27 | ||
|
|
ece2da866a | ||
|
|
fecf53943b | ||
|
|
dda5cb2d70 | ||
|
|
ebe772353a | ||
|
|
d6f4f63aca | ||
|
|
343dce1014 | ||
|
|
3bb3fbf753 | ||
|
|
42131f6bd6 | ||
|
|
663b25a8fc | ||
|
|
b0f48b0194 | ||
|
|
6e4ece2732 | ||
|
|
628a9d20d0 |
No files matched your search
+15
-35
@@ -12,24 +12,17 @@ jobs:
|
||||
name: Build radare2 extras and r2pipe
|
||||
runs-on: ubuntu-22.04
|
||||
env:
|
||||
BUILDS: 'asahi blackfin blessr2 keystone-lib keystone r2svd unicorn-lib vc4 x86iced'
|
||||
TESTS: 'keystone vc4'
|
||||
R2PIPE_TESTS: 'r2pipe-js r2pipe-py'
|
||||
EXTERNAL_BUILDS: 'keystone-lib unicorn-lib'
|
||||
LOCAL_BUILDS: 'asahi blackfin blessr2 keystone microblaze ppcdisasm r2svd vc4 x86iced'
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
repository: radareorg/radare2
|
||||
ref: master
|
||||
path: ./radare2
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get --assume-yes update
|
||||
sudo apt-get --assume-yes install libjansson-dev libboost-dev libcurl4-openssl-dev python3-wheel python3-setuptools && sudo pip3 install meson ninja
|
||||
- name: Install radare2
|
||||
run: |
|
||||
export PATH=$PATH:/usr/local/bin
|
||||
meson --prefix=/usr --buildtype=release build && ninja -C build && sudo ninja -C build install
|
||||
working-directory: radare2
|
||||
- uses: radareorg/github-actions@v3
|
||||
with:
|
||||
from-git: true
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
@@ -39,32 +32,19 @@ jobs:
|
||||
- name: Compile and install plugins
|
||||
run: |
|
||||
set -e
|
||||
export R2PM_GITDIR=`pwd`
|
||||
export R2PM_GITSKIP=1
|
||||
for p in $BUILDS ; do
|
||||
for p in $EXTERNAL_BUILDS ; do
|
||||
echo $p
|
||||
r2pm -i $p
|
||||
done
|
||||
set +e
|
||||
R2PM_GITDIR="$(r2pm -H R2PM_GITDIR)"
|
||||
for p in $LOCAL_BUILDS ; do
|
||||
echo $p
|
||||
ln -s "$GITHUB_WORKSPACE/radare2-extras" "$R2PM_GITDIR/$p"
|
||||
R2PM_OFFLINE=1 r2pm -i $p
|
||||
done
|
||||
make -C radare2-extras/mn103 install
|
||||
- name: Test plugins
|
||||
working-directory: radare2/test
|
||||
run: |
|
||||
set -e
|
||||
export R2PM_GITDIR=`pwd`
|
||||
export R2PM_GITSKIP=1
|
||||
for p in $TESTS ; do
|
||||
echo $p
|
||||
make $p
|
||||
done
|
||||
set +e
|
||||
- name: Compile and install r2pipe
|
||||
run: |
|
||||
set -e
|
||||
export R2PM_GITDIR=`pwd`
|
||||
export R2PM_GITSKIP=1
|
||||
for p in $R2PIPE_TESTS ; do
|
||||
echo $p
|
||||
r2pm -i $p
|
||||
done
|
||||
set +e
|
||||
|
||||
make keystone
|
||||
r2r -u "$GITHUB_WORKSPACE/radare2-extras/test/db/extras"
|
||||
@@ -1,6 +1,7 @@
|
||||
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.
|
||||
|
||||
@@ -14,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.
|
||||
|
||||
@@ -29,8 +23,16 @@ repository to be as concise as possible, and reduce the
|
||||
amount of unnecessary plugins to shrink the install size and
|
||||
keep it usable for 99% of users.
|
||||
|
||||
Building
|
||||
========
|
||||
## Building
|
||||
|
||||
The recommended way to build and install those plugins for users
|
||||
is to use r2pm. See the [radare2 plugins](https://github.com/radareorg/radare2#plugins) documentation for details.
|
||||
|
||||
## Notable plugins
|
||||
|
||||
* [`msl`](msl/) — Memory Slice (`.msl`) support: open/emulate process memory
|
||||
dumps (`io`/`bin`/`debug` plugins, with ESIL reverse execution) and produce
|
||||
them from a live debug session (`dgm`/`dgma`, `core` plugin).
|
||||
|
||||
* [`r2gg`](r2gg/) — Game Gear emulation through Z80 ESIL, with color terminal
|
||||
display, controls, Sega cartridge banking, interrupts, and stereo PSG audio.
|
||||
+3
-3
@@ -13,15 +13,15 @@ to any text, thus enabling a creation of variables from expressions.
|
||||
|
||||
Build:
|
||||
|
||||
r2pm -r meson build
|
||||
r2pm -r meson setup build
|
||||
|
||||
Install:
|
||||
|
||||
meson install -C build
|
||||
|
||||
## Running:
|
||||
## Run:
|
||||
|
||||
r2 -e asm.pseudo=true <file>
|
||||
r2 -e asm.parser=afen -e asm.pseudo=true <file>
|
||||
|
||||
## Usage:
|
||||
|
||||
|
||||
+221
-46
@@ -4,74 +4,246 @@
|
||||
|
||||
#include <r_core.h>
|
||||
|
||||
static RList *old_names;
|
||||
static RList *new_names;
|
||||
typedef struct RAfenRepl {
|
||||
char *old_name;
|
||||
char *new_name;
|
||||
} RAfenRepl;
|
||||
|
||||
// afen parser
|
||||
static int r_afen_parse(RParse *p, const char *data, char *str) {
|
||||
int res = true;
|
||||
char *input = strdup (data);
|
||||
#if R2_VERSION_NUMBER >= 50909
|
||||
#else
|
||||
static R_TH_LOCAL HtUP *ht; // hash table
|
||||
#endif
|
||||
|
||||
int n = r_list_length(old_names);
|
||||
#if R2_VERSION_NUMBER >= 50909
|
||||
static void fini(RAsmPluginSession *aps) {
|
||||
RParse *p = aps->rasm->parse;
|
||||
R_FREE (p->retleave_asm);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (n){
|
||||
RListIter *s_iter_old = NULL;
|
||||
RListIter *s_iter_new = NULL;
|
||||
|
||||
s_iter_old = old_names->head;
|
||||
s_iter_new = new_names->head;
|
||||
|
||||
for (int i = 0; i < n; ++i) {
|
||||
input = r_str_replace_all (input, s_iter_old->data, s_iter_new->data);
|
||||
|
||||
s_iter_old = r_list_iter_get_next(s_iter_old);
|
||||
s_iter_new = r_list_iter_get_next(s_iter_new);
|
||||
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;
|
||||
}
|
||||
|
||||
strcpy (str, input);
|
||||
return res;
|
||||
}
|
||||
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;
|
||||
|
||||
// sets afen parser
|
||||
static int r_cmd_init(void *user, const char *input) {
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
static bool r_core_init_afen(void *user, const char *input) {
|
||||
RCmd *rcmd = (RCmd *) user;
|
||||
RCore *core = (RCore *) rcmd->data;
|
||||
old_names = r_list_new ();
|
||||
new_names = r_list_new ();
|
||||
|
||||
core->parser->cur->parse = r_afen_parse;
|
||||
|
||||
return true;
|
||||
}
|
||||
r_parse_plugin_add (core->parser, &r_parse_plugin_afen);
|
||||
|
||||
static int r_cmd_fini(void *user, const char *input) {
|
||||
r_list_free(old_names);
|
||||
r_list_free(new_names);
|
||||
/*<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
|
||||
|
||||
static int r_cmd_afen_client(void *user, const char *input) {
|
||||
if (r_str_startswith (input, "afen")) {
|
||||
int *argc = (int*) malloc(sizeof(int));
|
||||
char **argv = r_str_argv(input, argc);
|
||||
#if R2_VERSION_NUMBER >= 50909
|
||||
static bool r_core_fini_afen(RCorePluginSession *cps) {
|
||||
HtUP *ht = cps->data;
|
||||
ht_up_free (ht);
|
||||
ht = NULL;
|
||||
|
||||
if (*argc != 3) {
|
||||
r_cons_printf("Usage: afen new_name old_name\n");
|
||||
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;
|
||||
}
|
||||
|
||||
r_list_append(new_names, argv[1]);
|
||||
r_list_append(old_names, argv[2]);
|
||||
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;
|
||||
}
|
||||
|
||||
// PLUGIN Definition Info
|
||||
#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",
|
||||
@@ -79,9 +251,9 @@ RCorePlugin r_core_plugin_afen = {
|
||||
.author = "satk0",
|
||||
.license = "GPLv3",
|
||||
},
|
||||
.call = r_cmd_afen_client,
|
||||
.init = r_cmd_init,
|
||||
.fini = r_cmd_fini
|
||||
.call = r_core_call_afen,
|
||||
.init = r_core_init_afen,
|
||||
.fini = r_core_fini_afen
|
||||
};
|
||||
|
||||
|
||||
@@ -89,6 +261,9 @@ RCorePlugin r_core_plugin_afen = {
|
||||
R_API RLibStruct radare_plugin = {
|
||||
.type = R_LIB_TYPE_CORE,
|
||||
.data = &r_core_plugin_afen,
|
||||
.version = R2_VERSION
|
||||
.version = R2_VERSION,
|
||||
#if R2_VERSION_NUMBER >= 50909
|
||||
.abiversion = R2_ABIVERSION,
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/bin/sh
|
||||
# This script was automatically generated by ACR v2.1.4
|
||||
# This script was automatically generated by ACR v2.2.4
|
||||
# @author: pancake <nopcode.org>
|
||||
# @url: http://www.nopcode.org
|
||||
# @repo: git clone https://github.com/radare/acr
|
||||
@@ -67,13 +67,27 @@ if [ -e "${VPATH}/config.guess" ]; then
|
||||
sh ${VPATH}/config.guess
|
||||
return
|
||||
fi
|
||||
CPU="`uname -m|sed -e 's, ,,g'|cut -d - -f 1`"
|
||||
CPU="`uname -m | tr 'A-Z' 'a-z' | sed -e 's, ,,g' | cut -d - -f 1`"
|
||||
OS="`uname -s|tr A-Z a-z`"
|
||||
uname -r | grep -qE "(Microsoft|WSL)" 2>/dev/null && OS="wsl"
|
||||
GNU="`uname --help 2>&1 | grep gnu`"
|
||||
[ "${GNU}" ] && OS="${OS}-gnu"
|
||||
[ "${CPU}" = ppc ] && CPU="powerpc"
|
||||
echo "${CPU}-unknown-${OS}"
|
||||
# normalize CPU
|
||||
case "${CPU}" in
|
||||
ppc*|powermac*|powermacintosh*|powerpc*)
|
||||
if echo "${CPU}" | grep -q '64'; then
|
||||
CPU=powerpc64
|
||||
else
|
||||
CPU=powerpc
|
||||
fi
|
||||
;;
|
||||
*) ;;
|
||||
esac
|
||||
VENDOR="unknown"
|
||||
if [ "${OS}" = "darwin" ]; then
|
||||
VENDOR=apple
|
||||
fi
|
||||
echo "${CPU}-${VENDOR}-${OS}"
|
||||
}
|
||||
|
||||
SEARCHPATH="/usr /usr/local /usr/pkg /sw"
|
||||
@@ -114,12 +128,12 @@ done
|
||||
: ${INSTALL_PROGRAM_STRIP:=${INSTALL} -m 755 -s}
|
||||
: ${INSTALL_MAN:=${INSTALL} -m 444}
|
||||
: ${INSTALL_LIB:=${INSTALL} -m 755 -c}
|
||||
PKGNAME='radare2-extras' ; VERSION='5.9.0' ; VERSION_MAJOR=5; VERSION_MINOR=9; VERSION_PATCH=0; VERSION_NUMBER=50900; CONTACT_MAIL="[email protected]" ; CONTACT_NAME="pancake" ; CONTACT="pancake <[email protected]>" ;
|
||||
PKGNAME='radare2-extras' ; VERSION='6.0.0' ; VERSION_MAJOR=6; VERSION_MINOR=0; VERSION_PATCH=0; VERSION_NUMBER=60000; CONTACT_MAIL="[email protected]" ; CONTACT_NAME="pancake" ; CONTACT="pancake <[email protected]>" ;
|
||||
}
|
||||
|
||||
show_usage() {
|
||||
cat <<EOF2
|
||||
'configure' configures radare2-extras-5.9.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]...
|
||||
|
||||
@@ -201,10 +215,10 @@ ocho() {
|
||||
|
||||
show_version() {
|
||||
if [ "$QUIET" = 1 ]; then
|
||||
echo "5.9.0"
|
||||
echo "6.0.0"
|
||||
exit 0
|
||||
fi
|
||||
echo "radare2-extras-5.9.0 configuration script done with acr v2.1.4.
|
||||
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
|
||||
@@ -233,7 +247,7 @@ case $flag in
|
||||
show_version ; ;;
|
||||
-r|--r|--report)
|
||||
echo "PKGNAME: radare2-extras"
|
||||
echo "VERSION: 5.9.0"
|
||||
echo "VERSION: 6.0.0"
|
||||
echo "AUTHOR: pancake"
|
||||
echo "EMAIL: [email protected]"
|
||||
echo "LANGS: c"
|
||||
@@ -455,7 +469,14 @@ for A in ${ENVWORDS} ; do
|
||||
[ "${A}" = VPATH ] && continue
|
||||
[ "${A}" = srcdir ] && continue
|
||||
eval "VAR=\$${A}"
|
||||
VAR="`echo ${VAR} | sed -e 's/\,/\\\,/g'`"
|
||||
case "" in
|
||||
mingw*|cygwin*|msys*)
|
||||
VAR="`echo ${VAR} | sed -e 's/\\/\\\\/g' -e 's/\,/\\\,/g'`"
|
||||
;;
|
||||
*)
|
||||
VAR="`echo ${VAR} | sed -e 's/\,/\\\,/g'`"
|
||||
;;
|
||||
esac
|
||||
[ $COUNT = 10 ] && COUNT=0 && SEDFLAGS="${SEDFLAGS}' -e '"
|
||||
COUNT=$(($COUNT+1))
|
||||
SEDFLAGS="${SEDFLAGS}s,@${A}@,${VAR},g;"
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
PKGNAME radare2-extras
|
||||
VERSION 5.9.0
|
||||
VERSION 6.0.0
|
||||
CONTACT pancake ; [email protected]
|
||||
|
||||
USE_PKGCONFIG!
|
||||
|
||||
Vendored
+27
-6
@@ -1,5 +1,5 @@
|
||||
#!/bin/sh
|
||||
# This script was automatically generated by ACR v2.1.4
|
||||
# This script was automatically generated by ACR v2.2.4
|
||||
# @author: pancake <nopcode.org>
|
||||
# @url: http://www.nopcode.org
|
||||
# @repo: git clone https://github.com/radare/acr
|
||||
@@ -65,13 +65,27 @@ if [ -e "${VPATH}/config.guess" ]; then
|
||||
sh ${VPATH}/config.guess
|
||||
return
|
||||
fi
|
||||
CPU="`uname -m|sed -e 's, ,,g'|cut -d - -f 1`"
|
||||
CPU="`uname -m | tr 'A-Z' 'a-z' | sed -e 's, ,,g' | cut -d - -f 1`"
|
||||
OS="`uname -s|tr A-Z a-z`"
|
||||
uname -r | grep -qE "(Microsoft|WSL)" 2>/dev/null && OS="wsl"
|
||||
GNU="`uname --help 2>&1 | grep gnu`"
|
||||
[ "${GNU}" ] && OS="${OS}-gnu"
|
||||
[ "${CPU}" = ppc ] && CPU="powerpc"
|
||||
echo "${CPU}-unknown-${OS}"
|
||||
# normalize CPU
|
||||
case "${CPU}" in
|
||||
ppc*|powermac*|powermacintosh*|powerpc*)
|
||||
if echo "${CPU}" | grep -q '64'; then
|
||||
CPU=powerpc64
|
||||
else
|
||||
CPU=powerpc
|
||||
fi
|
||||
;;
|
||||
*) ;;
|
||||
esac
|
||||
VENDOR="unknown"
|
||||
if [ "${OS}" = "darwin" ]; then
|
||||
VENDOR=apple
|
||||
fi
|
||||
echo "${CPU}-${VENDOR}-${OS}"
|
||||
}
|
||||
|
||||
SEARCHPATH="/usr /usr/local /usr/pkg /sw"
|
||||
@@ -201,7 +215,7 @@ if [ "$QUIET" = 1 ]; then
|
||||
echo "0.2"
|
||||
exit 0
|
||||
fi
|
||||
echo "radare2-keystone-0.2 configuration script done with acr v2.1.4.
|
||||
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
|
||||
@@ -415,7 +429,14 @@ for A in ${ENVWORDS} ; do
|
||||
[ "${A}" = VPATH ] && continue
|
||||
[ "${A}" = srcdir ] && continue
|
||||
eval "VAR=\$${A}"
|
||||
VAR="`echo ${VAR} | sed -e 's/\,/\\\,/g'`"
|
||||
case "" in
|
||||
mingw*|cygwin*|msys*)
|
||||
VAR="`echo ${VAR} | sed -e 's/\\/\\\\/g' -e 's/\,/\\\,/g'`"
|
||||
;;
|
||||
*)
|
||||
VAR="`echo ${VAR} | sed -e 's/\,/\\\,/g'`"
|
||||
;;
|
||||
esac
|
||||
[ $COUNT = 10 ] && COUNT=0 && SEDFLAGS="${SEDFLAGS}' -e '"
|
||||
COUNT=$(($COUNT+1))
|
||||
SEDFLAGS="${SEDFLAGS}s,@${A}@,${VAR},g;"
|
||||
|
||||
@@ -16,6 +16,7 @@ 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:
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
R2PM_PLUGDIR ?=$(HOME)/.config/radare2/plugins
|
||||
|
||||
all:
|
||||
@echo
|
||||
|
||||
atombios:
|
||||
cd p ; $(MAKE) asm_atombios.$(LIBEXT)
|
||||
|
||||
|
||||
@@ -90,7 +90,7 @@ static int m32c_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *b, int len, R
|
||||
RAnalPlugin r_anal_plugin_m32c = {
|
||||
.name = "m32c",
|
||||
.desc = "m32c analysis plugin",
|
||||
.license = "LGPL3",
|
||||
.license = "LGPL-3.0-only",
|
||||
.arch = "m32c",
|
||||
.esil = false,
|
||||
.bits = 32,
|
||||
|
||||
@@ -94,7 +94,7 @@ RAsmPlugin r_asm_plugin_m32c_gnu = {
|
||||
.name = "m32c.gnu",
|
||||
.arch = "m32c",
|
||||
.author = "pancake",
|
||||
.license = "GPL3",
|
||||
.license = "GPL-3.0-only",
|
||||
.bits = 16 | 32,
|
||||
.endian = R_SYS_ENDIAN_LITTLE,
|
||||
.desc = "M32C CPU",
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
# build artifacts
|
||||
*.o
|
||||
*.dylib
|
||||
*.so
|
||||
*.a
|
||||
|
||||
# editor / assistant caches
|
||||
.pmai/
|
||||
.DS_Store
|
||||
build/
|
||||
@@ -0,0 +1,68 @@
|
||||
# Build the r2 vc4 asm/anal plugin straight from this directory.
|
||||
# Mirrors libr/asm/p/vc4.mk + libr/plugs.mk but works standalone.
|
||||
|
||||
CC?=cc
|
||||
VC4DIR=$(shell pwd)
|
||||
PLUGDIR=$(abspath $(VC4DIR)/../../p)
|
||||
PLUGSRC=$(PLUGDIR)/arch_vc4.c
|
||||
|
||||
R2_CFLAGS?=$(shell pkg-config --cflags r_arch r_asm r_util 2>/dev/null || pkg-config --cflags r_asm r_util 2>/dev/null || echo -I$(shell r2 -H R2_INCDIR 2>/dev/null))
|
||||
R2_LDFLAGS?=$(shell pkg-config --libs r_arch r_asm r_util 2>/dev/null || pkg-config --libs r_asm r_util 2>/dev/null || echo -L$(shell r2 -H R2_LIBDIR 2>/dev/null) -lr_anal -lr_arch -lr_asm -lr_util)
|
||||
|
||||
R2HOME?=$(shell r2 -H R2_USER_PLUGINS 2>/dev/null || echo $(HOME)/.local/share/radare2/plugins)
|
||||
UNAME_S?=$(shell uname -s)
|
||||
ifeq ($(UNAME_S),Darwin)
|
||||
LIBEXT?=dylib
|
||||
else
|
||||
LIBEXT?=so
|
||||
endif
|
||||
|
||||
TARGET=arch_vc4.$(LIBEXT)
|
||||
PSEUDO=asm_vc4.$(LIBEXT)
|
||||
|
||||
CFLAGS+=$(R2_CFLAGS)
|
||||
CFLAGS+=-g -O2 -Wall -fPIC
|
||||
CFLAGS+=-I$(VC4DIR) -I$(VC4DIR)/include -I$(VC4DIR)/include/opcode
|
||||
CFLAGS+=-I$(VC4DIR)/../include
|
||||
|
||||
LDFLAGS+=$(R2_LDFLAGS) -lr_anal
|
||||
LDFLAGS+=-shared
|
||||
|
||||
OBJ=arch_vc4.o \
|
||||
vc4-dis.o vc4-asm.o vc4-desc.o vc4-ibld.o vc4-opc.o \
|
||||
cgen-bitset.o cgen-dis.o cgen-asm.o cgen-opc.o
|
||||
|
||||
all: $(TARGET) $(PSEUDO)
|
||||
|
||||
%.o: %.c
|
||||
$(CC) -c $(CFLAGS) $< -o $@
|
||||
|
||||
# binutils/cgen generated sources use the dashes in their names
|
||||
vc4-%.o: vc4-%.c
|
||||
$(CC) -c $(CFLAGS) $< -o $@
|
||||
|
||||
# the r2 glue lives in libr/asm/p/
|
||||
arch_vc4.o: $(PLUGSRC) vc4_anal.inc.c
|
||||
$(CC) -c $(CFLAGS) $(PLUGSRC) -o $@
|
||||
|
||||
$(TARGET): $(OBJ)
|
||||
$(CC) -o $(TARGET) $(OBJ) $(LDFLAGS)
|
||||
|
||||
$(PSEUDO): pseudo.o
|
||||
$(CC) -o $(PSEUDO) pseudo.o $(LDFLAGS)
|
||||
|
||||
install: $(TARGET) $(PSEUDO)
|
||||
mkdir -p $(R2HOME)
|
||||
cp -f $(TARGET) $(R2HOME)
|
||||
-codesign -f -s - $(R2HOME)/$(TARGET) 2>/dev/null || true
|
||||
|
||||
uninstall:
|
||||
rm -f $(R2HOME)/$(TARGET) $(R2HOME)/$(PSEUDO)
|
||||
|
||||
clean:
|
||||
rm -f $(OBJ) $(TARGET) pseudo.o $(PSEUDO)
|
||||
|
||||
mrproper: clean
|
||||
$(MAKE) -C libvc4 clean 2>/dev/null || true
|
||||
|
||||
.PHONY: all install uninstall clean mrproper
|
||||
@@ -0,0 +1,16 @@
|
||||
/* Minimal safe-ctype.h for the vc4 cgen sources, avoids depending on
|
||||
libiberty's _sch_istable. */
|
||||
|
||||
#ifndef SAFE_CTYPE_H
|
||||
#define SAFE_CTYPE_H
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#define ISALNUM(c) isalnum ((unsigned char) (c))
|
||||
#define ISALPHA(c) isalpha ((unsigned char) (c))
|
||||
#define ISDIGIT(c) isdigit ((unsigned char) (c))
|
||||
#define ISSPACE(c) isspace ((unsigned char) (c))
|
||||
#define TOLOWER(c) tolower ((unsigned char) (c))
|
||||
#define TOUPPER(c) toupper ((unsigned char) (c))
|
||||
|
||||
#endif
|
||||
@@ -28,6 +28,8 @@
|
||||
file (check in a non-ANSI environment!), it should be. */
|
||||
|
||||
#include "ansidecl.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef HAVE_STDLIB_H
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -0,0 +1,291 @@
|
||||
/* radare - LGPL - Copyright 2026 - pancake */
|
||||
|
||||
#include <r_asm.h>
|
||||
|
||||
static const char *pseudo_rules[] = {
|
||||
"mov/2/$1 = $2",
|
||||
"add/2/$1 += $2",
|
||||
"add/3/$1 = $2 + $3",
|
||||
"sub/2/$1 -= $2",
|
||||
"sub/3/$1 = $2 - $3",
|
||||
"rsub/2/$1 = $2 - $1",
|
||||
"rsub/3/$1 = $3 - $2",
|
||||
"mul/2/$1 *= $2",
|
||||
"mul/3/$1 = $2 * $3",
|
||||
"div/3/$1 = $2 / $3",
|
||||
"mulhd/3/$1 = ($2 * $3) >> 32",
|
||||
"and/2/$1 &= $2",
|
||||
"and/3/$1 = $2 & $3",
|
||||
"or/2/$1 |= $2",
|
||||
"or/3/$1 = $2 | $3",
|
||||
"eor/2/$1 ^= $2",
|
||||
"eor/3/$1 = $2 ^ $3",
|
||||
"bic/2/$1 &= ~$2",
|
||||
"bic/3/$1 = $2 & ~$3",
|
||||
"not/2/$1 = ~$2",
|
||||
"neg/2/$1 = -$2",
|
||||
"abs/2/$1 = abs ($2)",
|
||||
"shl/2/$1 <<= $2",
|
||||
"shl/3/$1 = $2 << $3",
|
||||
"lsr/2/$1 >>= $2",
|
||||
"lsr/3/$1 = $2 >> $3",
|
||||
"asr/2/$1 = (st32)$1 >> $2",
|
||||
"asr/3/$1 = (st32)$2 >> $3",
|
||||
"ror/2/$1 = ror ($1, $2)",
|
||||
"ror/3/$1 = ror ($2, $3)",
|
||||
"min/2/$1 = min ($1, $2)",
|
||||
"min/3/$1 = min ($2, $3)",
|
||||
"max/2/$1 = max ($1, $2)",
|
||||
"max/3/$1 = max ($2, $3)",
|
||||
"bitset/2/$1 |= 1 << $2",
|
||||
"bitset/3/$1 = $2 | (1 << $3)",
|
||||
"bitclear/2/$1 &= ~(1 << $2)",
|
||||
"bitclear/3/$1 = $2 & ~(1 << $3)",
|
||||
"bitflip/2/$1 ^= 1 << $2",
|
||||
"bitflip/3/$1 = $2 ^ (1 << $3)",
|
||||
"btest/2/flags = $1 & (1 << $2)",
|
||||
"bmask/2/$1 &= (1 << $2) - 1",
|
||||
"bmask/3/$1 = $2 & ((1 << $3) - 1)",
|
||||
"signext/2/$1 = signext ($1, $2)",
|
||||
"signext/3/$1 = signext ($2, $3)",
|
||||
"addscale/2/$1 += $2",
|
||||
"addscale/3/$1 = $2 + $3",
|
||||
"subscale/2/$1 -= $2",
|
||||
"subscale/3/$1 = $2 - $3",
|
||||
"adds/3/$1 = sat ($2 + $3)",
|
||||
"subs/3/$1 = sat ($2 - $3)",
|
||||
"msb/2/$1 = msb ($2)",
|
||||
"count/2/$1 = popcount ($2)",
|
||||
"brev/2/$1 = bitreverse ($2)",
|
||||
"clamp16/2/$1 = clamp16 ($2)",
|
||||
"cmp/2/flags = $1 - $2",
|
||||
"cmn/2/flags = $1 + $2",
|
||||
"fadd/3/$1 = $2 + $3",
|
||||
"fsub/3/$1 = $2 - $3",
|
||||
"frsub/3/$1 = $3 - $2",
|
||||
"fmul/3/$1 = $2 * $3",
|
||||
"fnmul/3/$1 = -($2 * $3)",
|
||||
"fdiv/3/$1 = $2 / $3",
|
||||
"fmax/3/$1 = fmax ($2, $3)",
|
||||
"fmin/3/$1 = fmin ($2, $3)",
|
||||
"fabs/2/$1 = fabs ($2)",
|
||||
"frcp/2/$1 = 1 / $2",
|
||||
"frsqrt/2/$1 = 1 / sqrt ($2)",
|
||||
"fceil/2/$1 = ceil ($2)",
|
||||
"ffloor/2/$1 = floor ($2)",
|
||||
"flog2/2/$1 = log2 ($2)",
|
||||
"fexp2/2/$1 = exp2 ($2)",
|
||||
"fcmp/2/flags = $1 - $2",
|
||||
"ftrunc/3/$1 = (int)($2 $3)",
|
||||
"floor/3/$1 = (int)floor ($2 $3)",
|
||||
"flts/3/$1 = (float)($2 $3)",
|
||||
"fltu/3/$1 = (float)(unsigned)($2 $3)",
|
||||
"lea/2/$1 = &$2",
|
||||
"ld/2/$1 = (ut32)$2",
|
||||
"ldh/2/$1 = (ut16)$2",
|
||||
"ldsh/2/$1 = (st16)$2",
|
||||
"ldb/2/$1 = (ut8)$2",
|
||||
"ldsb/2/$1 = (st8)$2",
|
||||
"st/2/(ut32)$2 = $1",
|
||||
"sth/2/(ut16)$2 = $1",
|
||||
"stb/2/(ut8)$2 = $1",
|
||||
"b/1/goto $1",
|
||||
"j/1/goto $1",
|
||||
"bl/1/$1 ()",
|
||||
"jl/1/$1 ()",
|
||||
"tbb/1/goto table8[$1]",
|
||||
"tbh/1/goto table16[$1]",
|
||||
"version/1/$1 = cpuid",
|
||||
"rts/0/return",
|
||||
"rti/0/return from interrupt",
|
||||
"swi/1/syscall ($1)",
|
||||
"bkpt/0/breakpoint",
|
||||
"ei/0/enable interrupts",
|
||||
"di/0/disable interrupts",
|
||||
"nop/0/",
|
||||
NULL
|
||||
};
|
||||
|
||||
// condition suffix and the operator used by compare and branch forms
|
||||
static const char *conds[][2] = {
|
||||
{ "eq", "==" }, { "ne", "!=" }, { "lt", "<" }, { "le", "<=" },
|
||||
{ "gt", ">" }, { "ge", ">=" }, { "hi", ">u" }, { "ls", "<=u" },
|
||||
{ "cs", "<u" }, { "lo", "<u" }, { "cc", ">=u" }, { "hs", ">=u" },
|
||||
{ "mi", NULL }, { "pl", NULL }, { "vs", NULL }, { "vc", NULL },
|
||||
{ "f", NULL }, { NULL, NULL }
|
||||
};
|
||||
|
||||
static int cond_index(const char *s) {
|
||||
int i;
|
||||
for (i = 0; conds[i][0]; i++) {
|
||||
if (!strcmp (s, conds[i][0])) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// "(r1+8)" -> "[r1 + 8]", "(r1)" -> "[r1]", "#imm" -> "imm"
|
||||
static char *normalize(const char *data) {
|
||||
RStrBuf *sb = r_strbuf_new ("");
|
||||
const char *p;
|
||||
for (p = data; *p; p++) {
|
||||
if (*p == '#') {
|
||||
continue;
|
||||
}
|
||||
if (*p == '(' && p > data && (p[-1] == ',' || p[-1] == ' ')) {
|
||||
const char *close = strchr (p, ')');
|
||||
if (close) {
|
||||
char *in = r_str_ndup (p + 1, close - p - 1);
|
||||
in = r_str_replace (in, "+-", " - ", 1);
|
||||
in = r_str_replace (in, "+", " + ", 1);
|
||||
in = r_str_replace (in, " + + ", "++", 1);
|
||||
r_strbuf_appendf (sb, "[%s]", in);
|
||||
free (in);
|
||||
p = close;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
r_strbuf_append_n (sb, p, 1);
|
||||
}
|
||||
return r_strbuf_drain (sb);
|
||||
}
|
||||
|
||||
static char *transform(const char *data) {
|
||||
char *res = r_str_pseudo_transform (pseudo_rules, data);
|
||||
if (res && strcmp (res, data)) {
|
||||
return res;
|
||||
}
|
||||
free (res);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// "addcmpb<cond> a,b,c,dst" and "b<cond> a,b,dst" compare after the add
|
||||
static char *cmpbranch(const char *str, const char *cond, const char *op, bool add) {
|
||||
char *rule;
|
||||
if (!strcmp (cond, "f")) {
|
||||
rule = add? strdup ("x/4/$1 += $2"): strdup ("x/3/");
|
||||
} else if (add) {
|
||||
rule = op? r_str_newf ("x/4/$1 += $2; if ($1 %s $3) goto $4", op)
|
||||
: r_str_newf ("x/4/$1 += $2; if (%s ($1 - $3)) goto $4", cond);
|
||||
} else {
|
||||
rule = op? r_str_newf ("x/3/if ($1 %s $2) goto $3", op)
|
||||
: r_str_newf ("x/3/if (%s ($1 - $2)) goto $3", cond);
|
||||
}
|
||||
const char *rules[] = { rule, NULL };
|
||||
const char *args = strchr (str, ' ');
|
||||
char *s = r_str_newf ("x%s", args? args: "");
|
||||
char *res = r_str_pseudo_transform (rules, s);
|
||||
free (s);
|
||||
free (rule);
|
||||
return res;
|
||||
}
|
||||
|
||||
// r_str_pseudo_transform turns "a + -1" into "a -1", make it "a - 1"
|
||||
static char *fix_minus(char *s) {
|
||||
RStrBuf *sb = r_strbuf_new ("");
|
||||
char *p;
|
||||
for (p = s; *p; p++) {
|
||||
r_strbuf_append_n (sb, p, 1);
|
||||
if (p > s && p[0] == ' ' && p[1] == '-' && isdigit ((ut8)p[2]) && isalnum ((ut8)p[-1])) {
|
||||
r_strbuf_append (sb, "- ");
|
||||
p++;
|
||||
}
|
||||
}
|
||||
free (s);
|
||||
return r_strbuf_drain (sb);
|
||||
}
|
||||
|
||||
static char *parse(RAsmPluginSession *aps, const char *data) {
|
||||
char *str = normalize (data);
|
||||
char *sp = strchr (str, ' ');
|
||||
char *args = sp? sp: "";
|
||||
char *mn = r_str_ndup (str, sp? sp - str: strlen (str));
|
||||
// mnemonic: base[.cond][.m|.s][.ss|.su|.us|.uu]
|
||||
int cond = -1;
|
||||
char *dot = strchr (mn, '.');
|
||||
if (dot) {
|
||||
char *t = dot;
|
||||
*dot = 0;
|
||||
while (t) {
|
||||
char *part = t + 1;
|
||||
t = strchr (part, '.');
|
||||
if (t) {
|
||||
*t = 0;
|
||||
}
|
||||
int c = cond_index (part);
|
||||
if (c >= 0) {
|
||||
cond = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
char *res = NULL;
|
||||
int ci = -1;
|
||||
int nargs = *args? (int)r_str_char_count (args, ',') + 1: 0;
|
||||
if (r_str_startswith (mn, "addcmpb")) {
|
||||
ci = mn[7]? cond_index (mn + 7): -1;
|
||||
if (!mn[7]) {
|
||||
char *s = r_str_newf ("x%s", args);
|
||||
const char *rules[] = { "x/4/$1 += $2; goto $4", NULL };
|
||||
res = r_str_pseudo_transform (rules, s);
|
||||
free (s);
|
||||
} else if (ci >= 0) {
|
||||
res = cmpbranch (str, conds[ci][0], conds[ci][1], true);
|
||||
}
|
||||
} else if (mn[0] == 'b' && mn[1] && (ci = cond_index (mn + 1)) >= 0) {
|
||||
if (nargs == 3) {
|
||||
res = cmpbranch (str, conds[ci][0], conds[ci][1], false);
|
||||
} else if (strcmp (conds[ci][0], "f")) {
|
||||
res = r_str_newf ("if (%s) goto%s", conds[ci][0], args);
|
||||
}
|
||||
} else if (!strcmp (mn, "ldm") || !strcmp (mn, "stm")) {
|
||||
// ldm r6-r7,pc,(sp++) / stm r6-r7,lr,(--sp)
|
||||
char *regs = r_str_trim_dup (args);
|
||||
char *last = (char *)r_str_rchr (regs, NULL, ',');
|
||||
if (last) {
|
||||
*last = 0;
|
||||
}
|
||||
bool ret = strstr (regs, ",pc") || !strcmp (regs, "pc");
|
||||
res = r_str_newf ("%s %s%s", (*mn == 'l')? "pop": "push", regs, ret? "; return": "");
|
||||
free (regs);
|
||||
} else {
|
||||
char *s = r_str_newf ("%s%s", mn, args);
|
||||
char *body = transform (s);
|
||||
free (s);
|
||||
if (body) {
|
||||
if (cond >= 0 && strcmp (conds[cond][0], "f")) {
|
||||
res = r_str_newf ("if (%s) %s", conds[cond][0], body);
|
||||
free (body);
|
||||
} else if (cond >= 0) {
|
||||
free (body);
|
||||
} else {
|
||||
res = body;
|
||||
}
|
||||
}
|
||||
}
|
||||
free (mn);
|
||||
free (str);
|
||||
if (!res) {
|
||||
return strdup (data);
|
||||
}
|
||||
res = r_str_replace (res, "+= -", "-= ", 1);
|
||||
return fix_minus (res);
|
||||
}
|
||||
|
||||
RAsmPlugin r_asm_plugin_vc4 = {
|
||||
.meta = {
|
||||
.name = "vc4",
|
||||
.desc = "VideoCore IV pseudo syntax",
|
||||
.author = "pancake",
|
||||
.license = "LGPL-3.0-only",
|
||||
},
|
||||
.parse = parse,
|
||||
};
|
||||
|
||||
#ifndef R2_PLUGIN_INCORE
|
||||
R_API RLibStruct radare_plugin = {
|
||||
.type = R_LIB_TYPE_ASM,
|
||||
.data = &r_asm_plugin_vc4,
|
||||
.version = R2_VERSION
|
||||
};
|
||||
#endif
|
||||
@@ -0,0 +1,49 @@
|
||||
# r2plugin
|
||||
|
||||
This directory contains the make and meson files required to link the
|
||||
vc4 (VideoCore IV) plugins statically inside radare2, using the XPS
|
||||
(static external plugins) mechanism. See `libr/xps/README.md` in the
|
||||
radare2 source tree for the full details.
|
||||
|
||||
Two plugins are registered directly, without a core wrapper, so both
|
||||
`rasm2` and `r2` get them:
|
||||
|
||||
- `arch.vc4`: cgen based disassembler and analysis, linked into libr_arch
|
||||
- `asm.vc4`: pseudo syntax (`e asm.pseudo=true`), linked into libr_asm
|
||||
|
||||
## Usage
|
||||
|
||||
Run these commands from the radare2 source tree:
|
||||
|
||||
```console
|
||||
mkdir -p libr/xps/p
|
||||
ln -s ../../../../radare2-extras/libr/asm/arch/vc4 libr/xps/p/vc4
|
||||
echo 'EXTERNAL_PLUGINS+=vc4' >> libr/xps/config.mk
|
||||
make -C libr/xps clean all
|
||||
```
|
||||
|
||||
Then build radare2 as usual:
|
||||
|
||||
```console
|
||||
./configure && make -j
|
||||
# or
|
||||
meson setup build --reconfigure && meson compile -C build
|
||||
```
|
||||
|
||||
The meson build needs a radare2 that provides `xps_arch_plugins`,
|
||||
`xps_asm_plugins` and `r_{arch,asm}_additional_{sources,inc}`.
|
||||
|
||||
Verify the plugins are linked in:
|
||||
|
||||
```console
|
||||
rasm2 -L | grep vc4
|
||||
rasm2 -a vc4 -d 01000200
|
||||
r2 -NN -qc 'La~vc4;Lp~vc4' --
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- `libvc4/` is not linked: the plugin only uses the cgen disassembler.
|
||||
- `r2plugin/arch/arch_vc4.c` includes `libr/asm/p/arch_vc4.c`, which
|
||||
lives outside this directory.
|
||||
- Object files for the make build are stored under `build/r2plugin/`.
|
||||
@@ -0,0 +1,4 @@
|
||||
/* radare - LGPL - Copyright 2026 - pancake */
|
||||
|
||||
/* the r2 glue lives in libr/asm/p, outside the XPS directory */
|
||||
#include "../../../../p/arch_vc4.c"
|
||||
@@ -0,0 +1,5 @@
|
||||
/* radare - LGPL - Copyright 2026 - pancake */
|
||||
|
||||
#ifdef R2_ARCH_H
|
||||
extern RArchPlugin r_arch_plugin_vc4;
|
||||
#endif
|
||||
@@ -0,0 +1,22 @@
|
||||
VC4_ARCH_WD=$(LIBR)/xps/p/vc4
|
||||
VC4_ARCH_BUILD=$(VC4_ARCH_WD)/build/r2plugin/arch
|
||||
VC4_ARCH_SRC=\
|
||||
vc4-dis.c vc4-asm.c vc4-desc.c vc4-ibld.c vc4-opc.c \
|
||||
cgen-bitset.c cgen-dis.c cgen-asm.c cgen-opc.c
|
||||
VC4_ARCH_OBJ=$(addprefix $(VC4_ARCH_BUILD)/,$(VC4_ARCH_SRC:.c=.o))
|
||||
VC4_ARCH_OBJ+=$(VC4_ARCH_BUILD)/arch_vc4.o
|
||||
EXTERNAL_STATIC_OBJS+=$(VC4_ARCH_OBJ)
|
||||
|
||||
# must come before r2's libr/arch/include, which ships its own sysdep.h, mybfd.h..
|
||||
VC4_ARCH_CFLAGS=-I$(VC4_ARCH_WD) -I$(VC4_ARCH_WD)/include \
|
||||
-I$(VC4_ARCH_WD)/include/opcode -I$(VC4_ARCH_WD)/../include
|
||||
|
||||
$(VC4_ARCH_BUILD)/arch_vc4.o: $(VC4_ARCH_WD)/r2plugin/arch/arch_vc4.c $(VC4_ARCH_WD)/../../p/arch_vc4.c
|
||||
@mkdir -p $(dir $@)
|
||||
$(CC) -c $(VC4_ARCH_CFLAGS) $(CFLAGS) -o $@ $<
|
||||
|
||||
$(VC4_ARCH_BUILD)/%.o: $(VC4_ARCH_WD)/%.c
|
||||
@mkdir -p $(dir $@)
|
||||
$(CC) -c $(VC4_ARCH_CFLAGS) $(CFLAGS) -o $@ $<
|
||||
|
||||
-include $(VC4_ARCH_OBJ:.o=.d)
|
||||
@@ -0,0 +1,5 @@
|
||||
/* radare - LGPL - Copyright 2026 - pancake */
|
||||
|
||||
#ifdef R2_ASM_H
|
||||
extern RAsmPlugin r_asm_plugin_vc4;
|
||||
#endif
|
||||
@@ -0,0 +1,9 @@
|
||||
VC4_ASM_WD=$(LIBR)/xps/p/vc4
|
||||
VC4_ASM_OBJ=$(VC4_ASM_WD)/build/r2plugin/asm/pseudo.o
|
||||
EXTERNAL_STATIC_OBJS+=$(VC4_ASM_OBJ)
|
||||
|
||||
$(VC4_ASM_OBJ): $(VC4_ASM_WD)/pseudo.c
|
||||
@mkdir -p $(dir $@)
|
||||
$(CC) -c $(CFLAGS) -o $@ $<
|
||||
|
||||
-include $(VC4_ASM_OBJ:.o=.d)
|
||||
@@ -0,0 +1,9 @@
|
||||
EXTERNAL_PLUGINS+=vc4
|
||||
|
||||
.PHONY: vc4
|
||||
|
||||
vc4: p/vc4
|
||||
|
||||
p/vc4:
|
||||
cd p && git clone --depth 1 https://github.com/radareorg/radare2-extras
|
||||
ln -fs radare2-extras/libr/asm/arch/vc4 p/vc4
|
||||
@@ -0,0 +1,35 @@
|
||||
# vc4 XPS integration for radare2.
|
||||
# Included from libr/xps/meson.build when this directory lives under
|
||||
# libr/xps/p/vc4/. Links the arch plugin into libr_arch and the pseudo
|
||||
# plugin into libr_asm, so rasm2 and r2 get vc4 without external files.
|
||||
|
||||
xps_arch_plugins += ['vc4']
|
||||
|
||||
# p/vc4 is usually a symlink, resolve it before going above this directory
|
||||
vc4_shared_inc = run_command('realpath',
|
||||
join_paths(meson.current_source_dir(), '..', '..', 'include'),
|
||||
check: true).stdout().strip()
|
||||
|
||||
r_arch_additional_inc += include_directories(
|
||||
'..',
|
||||
'../include',
|
||||
'../include/opcode',
|
||||
vc4_shared_inc,
|
||||
)
|
||||
|
||||
r_arch_additional_sources += files(
|
||||
'../vc4-dis.c',
|
||||
'../vc4-asm.c',
|
||||
'../vc4-desc.c',
|
||||
'../vc4-ibld.c',
|
||||
'../vc4-opc.c',
|
||||
'../cgen-bitset.c',
|
||||
'../cgen-dis.c',
|
||||
'../cgen-asm.c',
|
||||
'../cgen-opc.c',
|
||||
'arch/arch_vc4.c',
|
||||
)
|
||||
|
||||
xps_asm_plugins += ['vc4']
|
||||
|
||||
r_asm_additional_sources += files('../pseudo.c')
|
||||
@@ -0,0 +1,8 @@
|
||||
/* radare - LGPL - Copyright 2026 - pancake */
|
||||
|
||||
#ifdef R2_ARCH_H
|
||||
#include "arch/deps.h"
|
||||
#endif
|
||||
#ifdef R2_ASM_H
|
||||
#include "asm/deps.h"
|
||||
#endif
|
||||
@@ -0,0 +1,2 @@
|
||||
arch.vc4
|
||||
asm.vc4
|
||||
+1347
-52
File diff suppressed because it is too large.
Load diff
+52977
-655
File diff suppressed because it is too large.
Load diff
+128
-32
@@ -42,12 +42,12 @@ This file is part of the GNU Binutils and/or GDB, the GNU debugger.
|
||||
/* Maximum size of any insn (in bytes). */
|
||||
#define CGEN_MAX_INSN_SIZE 10
|
||||
|
||||
#define CGEN_MAX_EXTRA_OPCODE_OPERANDS 2
|
||||
#define CGEN_MAX_EXTRA_OPCODE_OPERANDS 3
|
||||
|
||||
#define CGEN_INT_INSN_P 0
|
||||
|
||||
/* Maximum number of syntax elements in an instruction. */
|
||||
#define CGEN_ACTUAL_MAX_SYNTAX_ELEMENTS 20
|
||||
#define CGEN_ACTUAL_MAX_SYNTAX_ELEMENTS 26
|
||||
|
||||
/* CGEN_MNEMONIC_OPERANDS is defined if mnemonics have operands.
|
||||
e.g. In "b,a foo" the ",a" is an operand. If mnemonics have operands
|
||||
@@ -55,7 +55,7 @@ This file is part of the GNU Binutils and/or GDB, the GNU debugger.
|
||||
#define CGEN_MNEMONIC_OPERANDS
|
||||
|
||||
/* Maximum number of fields in an instruction. */
|
||||
#define CGEN_ACTUAL_MAX_IFMT_OPERANDS 9
|
||||
#define CGEN_ACTUAL_MAX_IFMT_OPERANDS 15
|
||||
|
||||
/* Enums. */
|
||||
|
||||
@@ -76,7 +76,7 @@ typedef enum insn_op15_13 {
|
||||
/* Enum declaration for insn float ops. */
|
||||
typedef enum insn_floatops {
|
||||
ALUFOP_FADD, ALUFOP_FSUB, ALUFOP_FMUL, ALUFOP_FDIV
|
||||
, ALUFOP_FCMP, ALUFOP_FABS, ALUFOP_FRSB, ALUFOP_FMAX
|
||||
, ALUFOP_FCMP, ALUFOP_FABS, ALUFOP_FRSUB, ALUFOP_FMAX
|
||||
, ALUFOP_FRCP, ALUFOP_FRSQRT, ALUFOP_FNMUL, ALUFOP_FMIN
|
||||
, ALUFOP_FCEIL, ALUFOP_FFLOOR, ALUFOP_FLOG2, ALUFOP_FEXP2
|
||||
} INSN_FLOATOPS;
|
||||
@@ -86,7 +86,7 @@ typedef enum insn_alu16op {
|
||||
ALU16OP_MOV, ALU16OP_CMN, ALU16OP_ADD, ALU16OP_BIC
|
||||
, ALU16OP_MUL, ALU16OP_EOR, ALU16OP_SUB, ALU16OP_AND
|
||||
, ALU16OP_NOT, ALU16OP_ROR, ALU16OP_CMP, ALU16OP_RSUB
|
||||
, ALU16OP_BTST, ALU16OP_OR, ALU16OP_BMASK, ALU16OP_MAX
|
||||
, ALU16OP_BTEST, ALU16OP_OR, ALU16OP_BMASK, ALU16OP_MAX
|
||||
, ALU16OP_BSET, ALU16OP_MIN, ALU16OP_BCLR, ALU16OP_ADDS2
|
||||
, ALU16OP_BCHG, ALU16OP_ADDS4, ALU16OP_ADDS8, ALU16OP_ADDS16
|
||||
, ALU16OP_SIGNEXT, ALU16OP_NEG, ALU16OP_LSR, ALU16OP_MSB
|
||||
@@ -96,7 +96,7 @@ typedef enum insn_alu16op {
|
||||
/* Enum declaration for insn alu16 imm ops. */
|
||||
typedef enum insn_alu16opi {
|
||||
ALU16OPI_MOV, ALU16OPI_ADD, ALU16OPI_MUL, ALU16OPI_SUB
|
||||
, ALU16OPI_NOT, ALU16OPI_CMP, ALU16OPI_BTST, ALU16OPI_BMASK
|
||||
, ALU16OPI_NOT, ALU16OPI_CMP, ALU16OPI_BTEST, ALU16OPI_BMASK
|
||||
, ALU16OPI_BSET, ALU16OPI_BCLR, ALU16OPI_BCHG, ALU16OPI_ADDS8
|
||||
, ALU16OPI_SIGNEXT, ALU16OPI_LSR, ALU16OPI_SHL, ALU16OPI_ASR
|
||||
} INSN_ALU16OPI;
|
||||
@@ -106,7 +106,7 @@ typedef enum insn_alu32op {
|
||||
ALU32OP_MOV, ALU32OP_CMN, ALU32OP_ADD, ALU32OP_BIC
|
||||
, ALU32OP_MUL, ALU32OP_EOR, ALU32OP_SUB, ALU32OP_AND
|
||||
, ALU32OP_NOT, ALU32OP_ROR, ALU32OP_CMP, ALU32OP_RSUB
|
||||
, ALU32OP_BTST, ALU32OP_OR, ALU32OP_BMASK, ALU32OP_MAX
|
||||
, ALU32OP_BTEST, ALU32OP_OR, ALU32OP_BMASK, ALU32OP_MAX
|
||||
, ALU32OP_BSET, ALU32OP_MIN, ALU32OP_BCLR, ALU32OP_ADDS2
|
||||
, ALU32OP_BCHG, ALU32OP_ADDS4, ALU32OP_ADDS8, ALU32OP_ADDS16
|
||||
, ALU32OP_SIGNEXT, ALU32OP_NEG, ALU32OP_LSR, ALU32OP_MSB
|
||||
@@ -141,10 +141,17 @@ typedef enum insn_op7_6 {
|
||||
OP7_6_0, OP7_6_1, OP7_6_2, OP7_6_3
|
||||
} INSN_OP7_6;
|
||||
|
||||
/* Enum declaration for access sizes. */
|
||||
typedef enum accsz_op7_6 {
|
||||
ACCSZ7_6_, ACCSZ7_6_H, ACCSZ7_6_B, ACCSZ7_6_SH
|
||||
} ACCSZ_OP7_6;
|
||||
/* Enum declaration for access size. */
|
||||
typedef enum accsz_10_8 {
|
||||
ACCSZ10_8_LD, ACCSZ10_8_ST, ACCSZ10_8_LDH, ACCSZ10_8_STH
|
||||
, ACCSZ10_8_LDB, ACCSZ10_8_STB, ACCSZ10_8_LDSH, ACCSZ10_8_LDSB
|
||||
} ACCSZ_10_8;
|
||||
|
||||
/* Enum declaration for access size (32 bit insns). */
|
||||
typedef enum accsz_7_5 {
|
||||
ACCSZ7_5_LD, ACCSZ7_5_ST, ACCSZ7_5_LDH, ACCSZ7_5_STH
|
||||
, ACCSZ7_5_LDB, ACCSZ7_5_STB, ACCSZ7_5_LDSH, ACCSZ7_5_LDSB
|
||||
} ACCSZ_7_5;
|
||||
|
||||
/* Enum declaration for insn bits 7-5. */
|
||||
typedef enum insn_op7_5 {
|
||||
@@ -205,6 +212,67 @@ typedef enum insn_op22_21 {
|
||||
OP22_21_0, OP22_21_1, OP22_21_2, OP22_21_3
|
||||
} INSN_OP22_21;
|
||||
|
||||
/* Enum declaration for Vector ops (< 48). */
|
||||
typedef enum insn_vecops {
|
||||
VECOP_MOV, VECOP_BITPLANES, VECOP_EVEN, VECOP_ODD
|
||||
, VECOP_INTERL, VECOP_INTERH, VECOP_BITREV, VECOP_ROR
|
||||
, VECOP_SHL, VECOP_SHLS, VECOP_LSR, VECOP_ASR
|
||||
, VECOP_SIGNSHL, VECOP_OP13, VECOP_SIGNASL, VECOP_SIGNASLS
|
||||
, VECOP_AND, VECOP_OR, VECOP_EOR, VECOP_BIC
|
||||
, VECOP_COUNT, VECOP_MSB, VECOP_OP22, VECOP_OP23
|
||||
, VECOP_MIN, VECOP_MAX, VECOP_DIST, VECOP_DISTS
|
||||
, VECOP_CLIP, VECOP_SIGN, VECOP_CLIPS, VECOP_TESTMAG
|
||||
, VECOP_ADD, VECOP_ADDS, VECOP_ADDC, VECOP_ADDSC
|
||||
, VECOP_SUB, VECOP_SUBS, VECOP_SUBC, VECOP_SUBSC
|
||||
, VECOP_RSUB, VECOP_RSUBS, VECOP_RSUBC, VECOP_RSUBSC
|
||||
, VECOP_OP44, VECOP_OP45, VECOP_OP46, VECOP_OP47
|
||||
} INSN_VECOPS;
|
||||
|
||||
/* Enum declaration for Vector memory ops. */
|
||||
typedef enum insn_vecmemops {
|
||||
VMEMOP_LD, VMEMOP_LOOKUPM, VMEMOP_LOOKUPML, VMEMOP_MEM03
|
||||
, VMEMOP_ST, VMEMOP_INDEXWRITEM, VMEMOP_INDEXWRITEML, VMEMOP_MEM07
|
||||
, VMEMOP_MEMREAD, VMEMOP_MEMWRITE, VMEMOP_MEM10, VMEMOP_MEM11
|
||||
, VMEMOP_MEM12, VMEMOP_MEM13, VMEMOP_MEM14, VMEMOP_MEM15
|
||||
, VMEMOP_MEM16, VMEMOP_MEM17, VMEMOP_MEM18, VMEMOP_MEM19
|
||||
, VMEMOP_MEM20, VMEMOP_MEM21, VMEMOP_MEM22, VMEMOP_MEM23
|
||||
, VMEMOP_GETACC, VMEMOP_MEM25, VMEMOP_MEM26, VMEMOP_MEM27
|
||||
, VMEMOP_MEM28, VMEMOP_MEM29, VMEMOP_MEM30, VMEMOP_MEM31
|
||||
} INSN_VECMEMOPS;
|
||||
|
||||
/* Enum declaration for Vector memory op width. */
|
||||
typedef enum insn_memwidth {
|
||||
VMEMWIDTH_8, VMEMWIDTH_16, VMEMWIDTH_32, VMEMWIDTH_UNK
|
||||
} INSN_MEMWIDTH;
|
||||
|
||||
/* Enum declaration for Vector memory op saturation. */
|
||||
typedef enum insn_memsat {
|
||||
VMEMSAT_, VMEMSAT_S32, VMEMSAT_UNK, VMEMSAT_S16
|
||||
} INSN_MEMSAT;
|
||||
|
||||
/* Enum declaration for Multiply operations. */
|
||||
typedef enum insn_mulop {
|
||||
VMULXOP_MULLSS = 48, VMULXOP_OP481 = 48, VMULXOP_MULLSSS = 49, VMULXOP_OP491 = 49
|
||||
, VMULXOP_MULMSS = 50, VMULXOP_OP501 = 50, VMULXOP_MULMSSS = 51, VMULXOP_OP511 = 51
|
||||
, VMULXOP_MULHDSS = 52, VMULXOP_MUL32SS = 52, VMULXOP_MULHDSU = 53, VMULXOP_MUL32SU = 53
|
||||
, VMULXOP_MULHDUS = 54, VMULXOP_MUL32US = 54, VMULXOP_MULHDUU = 55, VMULXOP_MUL32UU = 55
|
||||
, VMULXOP_MULHNSS = 56, VMULXOP_OP561 = 56, VMULXOP_MULHNSU = 57, VMULXOP_OP571 = 57
|
||||
, VMULXOP_MULHNUS = 58, VMULXOP_OP581 = 58, VMULXOP_MULHNUU = 59, VMULXOP_OP591 = 59
|
||||
, VMULXOP_MULHDTSS = 60, VMULXOP_OP601 = 60, VMULXOP_MULHDTSU = 61, VMULXOP_OP611 = 61
|
||||
, VMULXOP_OP620 = 62, VMULXOP_OP621 = 62, VMULXOP_OP630 = 63, VMULXOP_OP631 = 63
|
||||
} INSN_MULOP;
|
||||
|
||||
/* Enum declaration for SREG setting for 48-bit ops. */
|
||||
typedef enum insn_sreg {
|
||||
SREG_R0, SREG_R1, SREG_R2, SREG_R3
|
||||
, SREG_R4, SREG_R5, SREG_R6, SREG_R7
|
||||
} INSN_SREG;
|
||||
|
||||
/* Enum declaration for Vector direction bit for 48-bit ops. */
|
||||
typedef enum insn_vec48dir {
|
||||
VECDIR_H, VECDIR_V
|
||||
} INSN_VEC48DIR;
|
||||
|
||||
/* Attributes. */
|
||||
|
||||
/* Enum declaration for machine type selection. */
|
||||
@@ -248,7 +316,7 @@ typedef enum cgen_ifld_attr {
|
||||
typedef enum ifield_type {
|
||||
VC4_F_NIL, VC4_F_ANYOF, VC4_F_OPLEN, VC4_F_OP15_13
|
||||
, VC4_F_OP15_11, VC4_F_OP11_8, VC4_F_LDSTOFF, VC4_F_OP11_9
|
||||
, VC4_F_OP11_10, VC4_F_OP11, VC4_F_OP10_9, VC4_F_OP10_7
|
||||
, VC4_F_OP11_10, VC4_F_OP11, VC4_F_OP10_8, VC4_F_OP10_7
|
||||
, VC4_F_ADDSPOFFSET, VC4_F_OP10_0, VC4_F_ALU16OP, VC4_F_ALU16OPI
|
||||
, VC4_F_OP9_8, VC4_F_OP9_5, VC4_F_SPOFFSET, VC4_F_OP8_5
|
||||
, VC4_F_OP8_4, VC4_F_OP8_4_SHL3, VC4_F_OP8, VC4_F_OP7_4
|
||||
@@ -265,7 +333,18 @@ typedef enum ifield_type {
|
||||
, VC4_F_OP21_16S_SHL6, VC4_F_OP21_16S_SHL7, VC4_F_OP21_16S_SHL8, VC4_F_OP20_16
|
||||
, VC4_F_OP47_16, VC4_F_PCREL32_48, VC4_F_OP47_43, VC4_F_OFFSET27_48
|
||||
, VC4_F_PCREL27_48, VC4_F_OP79_48, VC4_F_OFFSET23BITS, VC4_F_OFFSET27BITS
|
||||
, VC4_F_OFFSET12, VC4_F_MAX
|
||||
, VC4_F_OFFSET12, VC4_F_OP15_10, VC4_F_OP9, VC4_F_OP8_3
|
||||
, VC4_F_OP2_0, VC4_F_OP4_3, VC4_F_OP31_22, VC4_F_OP31_28
|
||||
, VC4_F_OP31_29, VC4_F_OP28, VC4_F_OP27_22, VC4_F_OP21_19
|
||||
, VC4_F_OP21_18, VC4_F_OP18, VC4_F_OP17_16, VC4_F_OP37_32
|
||||
, VC4_F_OP38, VC4_F_OP41_32, VC4_F_OP42, VC4_F_OP43
|
||||
, VC4_F_OP47_44, VC4_F_OP38_32, VC4_F_OP41_39, VC4_F_OP41_38
|
||||
, VC4_F_OP51_48, VC4_F_OP57_52, VC4_F_OP63_58, VC4_F_OP69_64
|
||||
, VC4_F_OP76_70, VC4_F_OP79_77, VC4_F_OP65_64, VC4_F_OP69_66
|
||||
, VC4_F_VEC80DREG, VC4_F_VEC80AREG, VC4_F_VEC80BREG, VC4_F_VEC80MODS
|
||||
, VC4_F_VEC80MODS_MEM, VC4_F_VEC80IMM, VC4_F_VEC80LDADDR, VC4_F_VEC80STADDR
|
||||
, VC4_F_DUMMYABITS, VC4_F_VEC48DREG, VC4_F_VEC48AREG, VC4_F_VEC48BREG
|
||||
, VC4_F_MAX
|
||||
} IFIELD_TYPE;
|
||||
|
||||
#define MAX_IFLD ((int) VC4_F_MAX)
|
||||
@@ -291,9 +370,9 @@ typedef enum cgen_hw_attr {
|
||||
/* Enum declaration for vc4 hardware types. */
|
||||
typedef enum cgen_hw_type {
|
||||
HW_H_MEMORY, HW_H_SINT, HW_H_UINT, HW_H_ADDR
|
||||
, HW_H_IADDR, HW_H_REG, HW_H_FASTREG, HW_H_PPREG
|
||||
, HW_H_BASEREG, HW_H_COND, HW_H_ACCSZ, HW_H_PC
|
||||
, HW_MAX
|
||||
, HW_H_IADDR, HW_H_REG, HW_H_FASTREG, HW_H_PREG
|
||||
, HW_H_PPREG, HW_H_BASEREG, HW_H_COND, HW_H_DOTCOND
|
||||
, HW_H_PC, HW_H_ELTSIZE, HW_MAX
|
||||
} CGEN_HW_TYPE;
|
||||
|
||||
#define MAX_HW ((int) HW_MAX)
|
||||
@@ -325,23 +404,37 @@ typedef enum cgen_operand_attr {
|
||||
typedef enum cgen_operand_type {
|
||||
VC4_OPERAND_PC, VC4_OPERAND_CONDCODE, VC4_OPERAND_PCRELCC, VC4_OPERAND_LDSTOFF
|
||||
, VC4_OPERAND_ALU16SREG, VC4_OPERAND_ALU16IMM, VC4_OPERAND_ALU16IMM_SHL3, VC4_OPERAND_ALU16DREG
|
||||
, VC4_OPERAND_ALU32DREG, VC4_OPERAND_IMM6, VC4_OPERAND_FLOATIMM6, VC4_OPERAND_IMM6_SHL1
|
||||
, VC4_OPERAND_IMM6_SHL2, VC4_OPERAND_IMM6_SHL3, VC4_OPERAND_IMM6_SHL4, VC4_OPERAND_IMM6_SHL5
|
||||
, VC4_OPERAND_IMM6_SHL6, VC4_OPERAND_IMM6_SHL7, VC4_OPERAND_IMM6_SHL8, VC4_OPERAND_ALU32BREG
|
||||
, VC4_OPERAND_PPSTARTREG, VC4_OPERAND_PPENDREG0, VC4_OPERAND_PPENDREG6, VC4_OPERAND_PPENDREG16
|
||||
, VC4_OPERAND_PPENDREG24, VC4_OPERAND_SWI_IMM, VC4_OPERAND_SPOFFSET, VC4_OPERAND_ADDSPOFFSET
|
||||
, VC4_OPERAND_ALU32AREG, VC4_OPERAND_ALU32COND, VC4_OPERAND_ALU48ISREG, VC4_OPERAND_ALU48IDREG
|
||||
, VC4_OPERAND_ALU32DREG, VC4_OPERAND_PREGDST, VC4_OPERAND_PREGSRC, VC4_OPERAND_DISP5
|
||||
, VC4_OPERAND_IMM6, VC4_OPERAND_FLOATIMM6, VC4_OPERAND_IMM6_SHL1, VC4_OPERAND_IMM6_SHL2
|
||||
, VC4_OPERAND_IMM6_SHL3, VC4_OPERAND_IMM6_SHL4, VC4_OPERAND_IMM6_SHL5, VC4_OPERAND_IMM6_SHL6
|
||||
, VC4_OPERAND_IMM6_SHL7, VC4_OPERAND_IMM6_SHL8, VC4_OPERAND_ALU32BREG, VC4_OPERAND_PPSTARTREG
|
||||
, VC4_OPERAND_PPENDREG0, VC4_OPERAND_PPENDREG6, VC4_OPERAND_PPENDREG16, VC4_OPERAND_PPENDREG24
|
||||
, VC4_OPERAND_SWI_IMM, VC4_OPERAND_SPOFFSET, VC4_OPERAND_ADDSPOFFSET, VC4_OPERAND_ALU32AREG
|
||||
, VC4_OPERAND_ALU32MISSINGAREG, VC4_OPERAND_ALU32COND, VC4_OPERAND_ALU48ISREG, VC4_OPERAND_ALU48IDREG
|
||||
, VC4_OPERAND_MEM48SREG, VC4_OPERAND_ALU48IMMU, VC4_OPERAND_ALU48PCREL, VC4_OPERAND_MEM48OFFSET27
|
||||
, VC4_OPERAND_MEM48PCREL27, VC4_OPERAND_ACCSZ, VC4_OPERAND_ACCSZ32, VC4_OPERAND_CONDCODEBCC32
|
||||
, VC4_OPERAND_BCC32SREG, VC4_OPERAND_PCREL10BITS, VC4_OPERAND_PCREL8BITS, VC4_OPERAND_BCC32IMM
|
||||
, VC4_OPERAND_ADDCMPBAREG, VC4_OPERAND_ADDCMPBIMM, VC4_OPERAND_OFFSET23BITS, VC4_OPERAND_OFFSET27BITS
|
||||
, VC4_OPERAND_OFFSET12, VC4_OPERAND_OFFSET16, VC4_OPERAND_OFFSET16_SHL1, VC4_OPERAND_OFFSET16_SHL2
|
||||
, VC4_OPERAND_OFFSET16_SHL3, VC4_OPERAND_OFFSET16_SHL4, VC4_OPERAND_PCREL16, VC4_OPERAND_OFF16BASEREG
|
||||
, VC4_OPERAND_OPERAND10_0, VC4_OPERAND_OPERAND47_16, VC4_OPERAND_OPERAND79_48, VC4_OPERAND_MAX
|
||||
, VC4_OPERAND_MEM48PCREL27, VC4_OPERAND_CONDCODEBCC32, VC4_OPERAND_BCC32SREG, VC4_OPERAND_PCREL10BITS
|
||||
, VC4_OPERAND_PCREL8BITS, VC4_OPERAND_BCC32IMM, VC4_OPERAND_ADDCMPBAREG, VC4_OPERAND_ADDCMPBIMM
|
||||
, VC4_OPERAND_OFFSET23BITS, VC4_OPERAND_OFFSET27BITS, VC4_OPERAND_OFFSET12, VC4_OPERAND_OFFSET16
|
||||
, VC4_OPERAND_OFFSET16_SHL1, VC4_OPERAND_OFFSET16_SHL2, VC4_OPERAND_OFFSET16_SHL3, VC4_OPERAND_OFFSET16_SHL4
|
||||
, VC4_OPERAND_PCREL16, VC4_OPERAND_OFF16BASEREG, VC4_OPERAND_OPERAND10_0, VC4_OPERAND_OPERAND47_16
|
||||
, VC4_OPERAND_OPERAND79_48, VC4_OPERAND_SHL1, VC4_OPERAND_SHL2, VC4_OPERAND_SHL3
|
||||
, VC4_OPERAND_SHL4, VC4_OPERAND_SHL5, VC4_OPERAND_SHL6, VC4_OPERAND_SHL7
|
||||
, VC4_OPERAND_SHL8, VC4_OPERAND_V80D32REG, VC4_OPERAND_V80A32REG, VC4_OPERAND_V80B32REG
|
||||
, VC4_OPERAND_V80IMM, VC4_OPERAND_V80MODS, VC4_OPERAND_V80MODS_MEM, VC4_OPERAND_SETF_MOD
|
||||
, VC4_OPERAND_V48IMM_MODS, VC4_OPERAND_VMEMWIDTH, VC4_OPERAND_VEC_LDADDR, VC4_OPERAND_VEC_STADDR
|
||||
, VC4_OPERAND_DUMMYABITS, VC4_OPERAND_DUMMYDBITS, VC4_OPERAND_V48SCLR, VC4_OPERAND_V48IMM
|
||||
, VC4_OPERAND_V48DREG_H, VC4_OPERAND_V48DREG_V, VC4_OPERAND_V48AREG_H, VC4_OPERAND_V48AREG_V
|
||||
, VC4_OPERAND_V48BREG_H, VC4_OPERAND_V48BREG_V, VC4_OPERAND_DPLUS_SR0, VC4_OPERAND_APLUS_SR0
|
||||
, VC4_OPERAND_BPLUS_SR0, VC4_OPERAND_DPLUS_SR1, VC4_OPERAND_APLUS_SR1, VC4_OPERAND_BPLUS_SR1
|
||||
, VC4_OPERAND_DPLUS_SR2, VC4_OPERAND_APLUS_SR2, VC4_OPERAND_BPLUS_SR2, VC4_OPERAND_DPLUS_SR3
|
||||
, VC4_OPERAND_APLUS_SR3, VC4_OPERAND_BPLUS_SR3, VC4_OPERAND_DPLUS_SR4, VC4_OPERAND_APLUS_SR4
|
||||
, VC4_OPERAND_BPLUS_SR4, VC4_OPERAND_DPLUS_SR5, VC4_OPERAND_APLUS_SR5, VC4_OPERAND_BPLUS_SR5
|
||||
, VC4_OPERAND_DPLUS_SR6, VC4_OPERAND_APLUS_SR6, VC4_OPERAND_BPLUS_SR6, VC4_OPERAND_DPLUS_SR7
|
||||
, VC4_OPERAND_APLUS_SR7, VC4_OPERAND_BPLUS_SR7, VC4_OPERAND_MAX
|
||||
} CGEN_OPERAND_TYPE;
|
||||
|
||||
/* Number of operands types. */
|
||||
#define MAX_OPERANDS 59
|
||||
#define MAX_OPERANDS 114
|
||||
|
||||
/* Maximum number of operands referenced by any insn. */
|
||||
#define MAX_OPERAND_INSTANCES 8
|
||||
@@ -352,8 +445,8 @@ typedef enum cgen_operand_type {
|
||||
typedef enum cgen_insn_attr {
|
||||
CGEN_INSN_ALIAS, CGEN_INSN_VIRTUAL, CGEN_INSN_UNCOND_CTI, CGEN_INSN_COND_CTI
|
||||
, CGEN_INSN_SKIP_CTI, CGEN_INSN_DELAY_SLOT, CGEN_INSN_RELAXABLE, CGEN_INSN_RELAXED
|
||||
, CGEN_INSN_NO_DIS, CGEN_INSN_PBB, CGEN_INSN_END_BOOLS, CGEN_INSN_START_NBOOLS = 31
|
||||
, CGEN_INSN_MACH, CGEN_INSN_END_NBOOLS
|
||||
, CGEN_INSN_NO_DIS, CGEN_INSN_PBB, CGEN_INSN_SWITCH, CGEN_INSN_END_BOOLS
|
||||
, CGEN_INSN_START_NBOOLS = 31, CGEN_INSN_MACH, CGEN_INSN_END_NBOOLS
|
||||
} CGEN_INSN_ATTR;
|
||||
|
||||
/* Number of non-boolean elements in cgen_insn_attr. */
|
||||
@@ -371,6 +464,7 @@ typedef enum cgen_insn_attr {
|
||||
#define CGEN_ATTR_CGEN_INSN_RELAXED_VALUE(attrs) (((attrs)->bool_ & (1 << CGEN_INSN_RELAXED)) != 0)
|
||||
#define CGEN_ATTR_CGEN_INSN_NO_DIS_VALUE(attrs) (((attrs)->bool_ & (1 << CGEN_INSN_NO_DIS)) != 0)
|
||||
#define CGEN_ATTR_CGEN_INSN_PBB_VALUE(attrs) (((attrs)->bool_ & (1 << CGEN_INSN_PBB)) != 0)
|
||||
#define CGEN_ATTR_CGEN_INSN_SWITCH_VALUE(attrs) (((attrs)->bool_ & (1 << CGEN_INSN_SWITCH)) != 0)
|
||||
|
||||
/* cgen.h uses things we just defined. */
|
||||
#include "opcode/cgen.h"
|
||||
@@ -387,10 +481,12 @@ extern const CGEN_ATTR_TABLE vc4_cgen_insn_attr_table[];
|
||||
|
||||
extern CGEN_KEYWORD vc4_cgen_opval_h_reg;
|
||||
extern CGEN_KEYWORD vc4_cgen_opval_h_fastreg;
|
||||
extern CGEN_KEYWORD vc4_cgen_opval_h_preg;
|
||||
extern CGEN_KEYWORD vc4_cgen_opval_h_ppreg;
|
||||
extern CGEN_KEYWORD vc4_cgen_opval_h_basereg;
|
||||
extern CGEN_KEYWORD vc4_cgen_opval_h_cond;
|
||||
extern CGEN_KEYWORD vc4_cgen_opval_h_accsz;
|
||||
extern CGEN_KEYWORD vc4_cgen_opval_h_dotcond;
|
||||
extern CGEN_KEYWORD vc4_cgen_opval_h_eltsize;
|
||||
|
||||
extern const CGEN_HW_ENTRY vc4_cgen_hw_table[];
|
||||
|
||||
|
||||
+825
-85
File diff suppressed because it is too large.
Load diff
+1379
-48
File diff suppressed because it is too large.
Load diff
+68136
-870
File diff suppressed because it is too large.
Load diff
+2702
-37
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
+2
-1
@@ -1,5 +1,7 @@
|
||||
ARCHS=
|
||||
|
||||
ARCHS=
|
||||
|
||||
ARCHS+=x86_udis.mk
|
||||
ARCHS+=spc700.mk
|
||||
ARCHS+=ba2.mk
|
||||
@@ -21,4 +23,3 @@ ARCHS+=atombios.mk
|
||||
|
||||
|
||||
include ../../plugs.mk
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
#include <r_lib.h>
|
||||
#include <r_arch.h>
|
||||
#include "../arch/arm/arm.h"
|
||||
|
||||
static bool decode(RArchSession *as, RAnalOp *op, RArchDecodeMask mask) {
|
||||
int *p = (int*)op->bytes; // thumb is 16-bit, using host endianness assumption here
|
||||
char buf_asm[64] = {0};
|
||||
int len = armthumb_disassemble(buf_asm, (ut32)op->addr, *p);
|
||||
if (len <= 0) {
|
||||
op->type = R_ANAL_OP_TYPE_UNK;
|
||||
op->size = 0;
|
||||
if (mask & R_ARCH_OP_MASK_DISASM) op->mnemonic = strdup("(data)");
|
||||
return false;
|
||||
}
|
||||
op->size = len;
|
||||
if (mask & R_ARCH_OP_MASK_DISASM) op->mnemonic = strdup(buf_asm);
|
||||
return true;
|
||||
}
|
||||
|
||||
static int info(RArchSession *s, ut32 q) {
|
||||
switch (q) {
|
||||
case R_ARCH_INFO_MINOP_SIZE: return 2;
|
||||
case R_ARCH_INFO_MAXOP_SIZE: return 4;
|
||||
default: return 2;
|
||||
}
|
||||
}
|
||||
|
||||
RArchPlugin r_arch_plugin_armthumb = {
|
||||
.meta = {
|
||||
.name = "arm.thumb",
|
||||
.desc = "ARM THUMB disassembler",
|
||||
.author = "pancake",
|
||||
.version = R2_VERSION,
|
||||
.license = "LGPL3",
|
||||
.status = R_PLUGIN_STATUS_OK,
|
||||
},
|
||||
.arch = "arm",
|
||||
.bits = R_SYS_BITS_PACK1(16),
|
||||
.endian = R_SYS_ENDIAN_LITTLE,
|
||||
.info = &info,
|
||||
.decode = &decode,
|
||||
};
|
||||
|
||||
#ifndef R2_PLUGIN_INCORE
|
||||
R_API RLibStruct radare_plugin = {
|
||||
.type = R_LIB_TYPE_ARCH,
|
||||
.data = &r_arch_plugin_armthumb,
|
||||
.version = R2_VERSION
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
#include <r_lib.h>
|
||||
#include <r_arch.h>
|
||||
#include <r_util.h>
|
||||
#include "../arch/atombios/atombios.h"
|
||||
|
||||
static bool decode(RArchSession *as, RAnalOp *op, RArchDecodeMask mask) {
|
||||
if (!(mask & R_ARCH_OP_MASK_DISASM)) {
|
||||
op->size = 0;
|
||||
return true;
|
||||
}
|
||||
char out[1024];
|
||||
out[0] = 0;
|
||||
int sz = atombios_disassemble(op->bytes, op->size, out);
|
||||
if (sz <= 0) {
|
||||
op->mnemonic = strdup("invalid");
|
||||
op->size = 0;
|
||||
return false;
|
||||
}
|
||||
op->mnemonic = strdup(out);
|
||||
op->size = sz;
|
||||
return true;
|
||||
}
|
||||
|
||||
static int info(RArchSession *s, ut32 q) {
|
||||
switch (q) {
|
||||
case R_ARCH_INFO_MINOP_SIZE: return 1;
|
||||
case R_ARCH_INFO_MAXOP_SIZE: return 8;
|
||||
default: return 1;
|
||||
}
|
||||
}
|
||||
|
||||
RArchPlugin r_arch_plugin_atombios = {
|
||||
.meta = {
|
||||
.name = "atombios",
|
||||
.desc = "AtomBIOS",
|
||||
.author = "damo22",
|
||||
.version = R2_VERSION,
|
||||
.license = "LGPL3",
|
||||
.status = R_PLUGIN_STATUS_OK,
|
||||
},
|
||||
.arch = "atombios",
|
||||
.bits = R_SYS_BITS_PACK3(16, 32, 64),
|
||||
.endian = R_SYS_ENDIAN_NONE,
|
||||
.info = &info,
|
||||
.decode = &decode,
|
||||
};
|
||||
|
||||
#ifndef R2_PLUGIN_INCORE
|
||||
R_API RLibStruct radare_plugin = {
|
||||
.type = R_LIB_TYPE_ARCH,
|
||||
.data = &r_arch_plugin_atombios,
|
||||
.version = R2_VERSION
|
||||
};
|
||||
#endif
|
||||
@@ -0,0 +1,64 @@
|
||||
/* RArch plugin for BA2 using local disassembler */
|
||||
#include <r_lib.h>
|
||||
#include <r_arch.h>
|
||||
#include <r_util.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../arch/ba2/ba2_disas.c"
|
||||
|
||||
static bool decode(RArchSession *as, RAnalOp *op, RArchDecodeMask mask) {
|
||||
struct op_cmd cmd = { .instr = "", .operands = "" };
|
||||
int ret = ba2_decode_opcode(op->addr, op->bytes, op->size, &cmd, NULL, NULL);
|
||||
if ((op->size < ret) || (!ret && op->size < 6)) {
|
||||
if (mask & R_ARCH_OP_MASK_DISASM) op->mnemonic = strdup("truncated");
|
||||
op->size = 0;
|
||||
op->type = R_ANAL_OP_TYPE_ILL;
|
||||
return false;
|
||||
}
|
||||
if (ret > 0) {
|
||||
if (mask & R_ARCH_OP_MASK_DISASM) {
|
||||
char buf[128];
|
||||
if (*cmd.operands) snprintf(buf, sizeof(buf), "%s %s", cmd.instr, cmd.operands);
|
||||
else snprintf(buf, sizeof(buf), "%s", cmd.instr);
|
||||
op->mnemonic = strdup(buf);
|
||||
}
|
||||
op->size = ret;
|
||||
return true;
|
||||
}
|
||||
if (mask & R_ARCH_OP_MASK_DISASM) op->mnemonic = strdup("invalid");
|
||||
op->size = 0;
|
||||
op->type = R_ANAL_OP_TYPE_ILL;
|
||||
return false;
|
||||
}
|
||||
|
||||
static int info(RArchSession *s, ut32 q) {
|
||||
switch (q) {
|
||||
case R_ARCH_INFO_MINOP_SIZE: return 2;
|
||||
case R_ARCH_INFO_MAXOP_SIZE: return 8;
|
||||
default: return 2;
|
||||
}
|
||||
}
|
||||
|
||||
RArchPlugin r_arch_plugin_ba2 = {
|
||||
.meta = {
|
||||
.name = "ba2",
|
||||
.desc = "Beyond Architecture 2 disassembler",
|
||||
.author = "radare2-extras",
|
||||
.version = R2_VERSION,
|
||||
.license = "LGPL3",
|
||||
.status = R_PLUGIN_STATUS_OK,
|
||||
},
|
||||
.arch = "ba2",
|
||||
.bits = R_SYS_BITS_PACK1(32),
|
||||
.endian = R_SYS_ENDIAN_LITTLE,
|
||||
.info = &info,
|
||||
.decode = &decode,
|
||||
};
|
||||
|
||||
#ifndef R2_PLUGIN_INCORE
|
||||
R_API RLibStruct radare_plugin = {
|
||||
.type = R_LIB_TYPE_ARCH,
|
||||
.data = &r_arch_plugin_ba2,
|
||||
.version = R2_VERSION
|
||||
};
|
||||
#endif
|
||||
@@ -1,4 +1,4 @@
|
||||
/* radare - LGPL - Copyright 2015-2023 - pancake */
|
||||
/* radare - LGPL - Copyright 2015-2024 - pancake */
|
||||
|
||||
#include <r_lib.h>
|
||||
#include <r_asm.h>
|
||||
@@ -207,11 +207,19 @@ static char *getregs(RArchSession *as) {
|
||||
|
||||
static int info(RArchSession *s, ut32 q) {
|
||||
switch (q) {
|
||||
#if R2_VERSION_NUMBER >= 50909
|
||||
case R_ARCH_INFO_MINOP_SIZE:
|
||||
return 2;
|
||||
case R_ARCH_INFO_MAXOP_SIZE:
|
||||
return 4;
|
||||
}
|
||||
#else
|
||||
case R_ARCH_INFO_MIN_OP_SIZE:
|
||||
return 2;
|
||||
case R_ARCH_INFO_MAX_OP_SIZE:
|
||||
return 4;
|
||||
}
|
||||
#endif
|
||||
// i think data align is 4
|
||||
return 2;
|
||||
}
|
||||
@@ -227,9 +235,9 @@ RArchPlugin r_arch_plugin_blackfin = {
|
||||
.meta = {
|
||||
.name = "blackfin",
|
||||
.desc = "BlackFIN architecture plugin",
|
||||
.author = "",
|
||||
.version = "",
|
||||
.license = "GPL",
|
||||
.author = "pancake",
|
||||
.version = "0.2",
|
||||
.license = "GPL-3.0-only",
|
||||
.status = R_PLUGIN_STATUS_OK,
|
||||
},
|
||||
.arch = "blackfin",
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
#include <r_lib.h>
|
||||
#include <r_arch.h>
|
||||
|
||||
static bool decode(RArchSession *as, RAnalOp *op, RArchDecodeMask mask) {
|
||||
op->type = R_ANAL_OP_TYPE_UNK;
|
||||
if (mask & R_ARCH_OP_MASK_DISASM) op->mnemonic = strdup("(dcpu16: unimplemented)");
|
||||
op->size = 2;
|
||||
return true;
|
||||
}
|
||||
|
||||
static int info(RArchSession *s, ut32 q) {
|
||||
switch (q) {
|
||||
case R_ARCH_INFO_MINOP_SIZE: return 2;
|
||||
case R_ARCH_INFO_MAXOP_SIZE: return 4;
|
||||
default: return 2;
|
||||
}
|
||||
}
|
||||
|
||||
RArchPlugin r_arch_plugin_dcpu16 = {
|
||||
.meta = {
|
||||
.name = "dcpu16",
|
||||
.desc = "DCPU-16 (stub)",
|
||||
.author = "radare2-extras",
|
||||
.version = R2_VERSION,
|
||||
.license = "LGPL3",
|
||||
.status = R_PLUGIN_STATUS_BETA,
|
||||
},
|
||||
.arch = "dcpu16",
|
||||
.bits = R_SYS_BITS_PACK1(16),
|
||||
.endian = R_SYS_ENDIAN_LITTLE,
|
||||
.info = &info,
|
||||
.decode = &decode,
|
||||
};
|
||||
|
||||
#ifndef R2_PLUGIN_INCORE
|
||||
R_API RLibStruct radare_plugin = {
|
||||
.type = R_LIB_TYPE_ARCH,
|
||||
.data = &r_arch_plugin_dcpu16,
|
||||
.version = R2_VERSION
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -26,11 +26,13 @@ static int assemble(RAsm *a, RAsmOp *op, const char *buf) {
|
||||
}
|
||||
|
||||
RAsmPlugin r_a_plugin_evm = {
|
||||
.name = "evm",
|
||||
.author = "pancake",
|
||||
.version = "0.0.1",
|
||||
.meta = {
|
||||
.name = "evm",
|
||||
.author = "pancake",
|
||||
.version = "0.0.1",
|
||||
.license = "MIT",
|
||||
},
|
||||
.arch = "evm",
|
||||
.license = "MIT",
|
||||
.bits = 32,
|
||||
.endian = R_SYS_ENDIAN_BIG,
|
||||
.desc = "evm",
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
#include <r_lib.h>
|
||||
#include <r_arch.h>
|
||||
#include <r_util.h>
|
||||
#include "m68k/m68k_disasm/m68k_disasm.h"
|
||||
|
||||
static bool decode(RArchSession *as, RAnalOp *op, RArchDecodeMask mask) {
|
||||
m68k_word bof[8] = {0};
|
||||
int iaddr = (int)op->addr;
|
||||
char opcode[256] = {0};
|
||||
char operands[256] = {0};
|
||||
const unsigned char *buf2;
|
||||
static struct DisasmPara_68k dp;
|
||||
int ilen;
|
||||
|
||||
memcpy(bof, op->bytes, R_MIN(op->size, sizeof(bof)));
|
||||
dp.opcode = opcode;
|
||||
dp.operands = operands;
|
||||
dp.iaddr = (m68k_word *)(size_t)iaddr;
|
||||
dp.instr = bof;
|
||||
buf2 = (const ut8*)M68k_Disassemble(&dp);
|
||||
if (!buf2) {
|
||||
op->size = 2; // invalid, assume 2
|
||||
if (mask & R_ARCH_OP_MASK_DISASM) op->mnemonic = strdup("invalid");
|
||||
op->type = R_ANAL_OP_TYPE_ILL;
|
||||
return false;
|
||||
}
|
||||
ilen = (int)(buf2 - (const ut8*)bof);
|
||||
if (mask & R_ARCH_OP_MASK_DISASM) {
|
||||
char buf[512];
|
||||
if (*operands) snprintf(buf, sizeof(buf), "%s %s", opcode, operands);
|
||||
else snprintf(buf, sizeof(buf), "%s", opcode);
|
||||
r_str_replace_ch(buf, '#', 0, 1);
|
||||
op->mnemonic = strdup(buf);
|
||||
}
|
||||
op->size = ilen;
|
||||
return true;
|
||||
}
|
||||
|
||||
static int info(RArchSession *s, ut32 q) {
|
||||
switch (q) {
|
||||
case R_ARCH_INFO_MINOP_SIZE: return 2;
|
||||
case R_ARCH_INFO_MAXOP_SIZE: return 10;
|
||||
default: return 2;
|
||||
}
|
||||
}
|
||||
|
||||
RArchPlugin r_arch_plugin_m68k_net = {
|
||||
.meta = {
|
||||
.name = "m68k.net",
|
||||
.desc = "Motorola 68000",
|
||||
.author = "nibble",
|
||||
.version = R2_VERSION,
|
||||
.license = "BSD",
|
||||
.status = R_PLUGIN_STATUS_OK,
|
||||
},
|
||||
.arch = "m68k",
|
||||
.bits = R_SYS_BITS_PACK2(16, 32),
|
||||
.endian = R_SYS_ENDIAN_BIG,
|
||||
.info = &info,
|
||||
.decode = &decode,
|
||||
};
|
||||
|
||||
#ifndef R2_PLUGIN_INCORE
|
||||
R_API RLibStruct radare_plugin = {
|
||||
.type = R_LIB_TYPE_ARCH,
|
||||
.data = &r_arch_plugin_m68k_net,
|
||||
.version = R2_VERSION
|
||||
};
|
||||
#endif
|
||||
@@ -0,0 +1,41 @@
|
||||
#include <r_lib.h>
|
||||
#include <r_arch.h>
|
||||
|
||||
static bool decode(RArchSession *as, RAnalOp *op, RArchDecodeMask mask) {
|
||||
op->type = R_ANAL_OP_TYPE_UNK;
|
||||
if (mask & R_ARCH_OP_MASK_DISASM) op->mnemonic = strdup("(mc6809: unimplemented)");
|
||||
op->size = 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
static int info(RArchSession *s, ut32 q) {
|
||||
switch (q) {
|
||||
case R_ARCH_INFO_MINOP_SIZE: return 1;
|
||||
case R_ARCH_INFO_MAXOP_SIZE: return 3;
|
||||
default: return 1;
|
||||
}
|
||||
}
|
||||
|
||||
RArchPlugin r_arch_plugin_mc6809 = {
|
||||
.meta = {
|
||||
.name = "mc6809",
|
||||
.desc = "Motorola 6809 (stub)",
|
||||
.author = "radare2-extras",
|
||||
.version = R2_VERSION,
|
||||
.license = "LGPL3",
|
||||
.status = R_PLUGIN_STATUS_BASIC,
|
||||
},
|
||||
.arch = "mc6809",
|
||||
.bits = R_SYS_BITS_PACK1(8),
|
||||
.endian = R_SYS_ENDIAN_BIG,
|
||||
.info = &info,
|
||||
.decode = &decode,
|
||||
};
|
||||
|
||||
#ifndef R2_PLUGIN_INCORE
|
||||
R_API RLibStruct radare_plugin = {
|
||||
.type = R_LIB_TYPE_ARCH,
|
||||
.data = &r_arch_plugin_mc6809,
|
||||
.version = R2_VERSION
|
||||
};
|
||||
#endif
|
||||
@@ -0,0 +1,56 @@
|
||||
#include <r_lib.h>
|
||||
#include <r_arch.h>
|
||||
#include <r_util.h>
|
||||
#include "msil/demsil.c"
|
||||
|
||||
static bool decode(RArchSession *as, RAnalOp *op, RArchDecodeMask mask) {
|
||||
if (!(mask & R_ARCH_OP_MASK_DISASM)) {
|
||||
op->size = 0;
|
||||
return true;
|
||||
}
|
||||
ut32 n;
|
||||
ILOPCODE_STRUCT ilopar[8];
|
||||
int o = DisasMSIL(op->bytes, op->size, op->addr, ilopar, 8, &n);
|
||||
if (o <= 0) {
|
||||
op->type = R_ANAL_OP_TYPE_ILL;
|
||||
op->size = 0;
|
||||
op->mnemonic = strdup("invalid");
|
||||
return false;
|
||||
}
|
||||
op->size = o;
|
||||
op->mnemonic = strdup(ilopar[0].Mnemonic);
|
||||
return true;
|
||||
}
|
||||
|
||||
static int info(RArchSession *s, ut32 q) {
|
||||
switch (q) {
|
||||
case R_ARCH_INFO_MINOP_SIZE: return 1;
|
||||
case R_ARCH_INFO_MAXOP_SIZE: return 8;
|
||||
default: return 1;
|
||||
}
|
||||
}
|
||||
|
||||
RArchPlugin r_arch_plugin_msil = {
|
||||
.meta = {
|
||||
.name = "msil",
|
||||
.desc = "Microsoft IL",
|
||||
.author = "capi_x, pancake",
|
||||
.version = R2_VERSION,
|
||||
.license = "PD",
|
||||
.status = R_PLUGIN_STATUS_OK,
|
||||
},
|
||||
.arch = "msil",
|
||||
.bits = R_SYS_BITS_PACK3(16, 32, 64),
|
||||
.endian = R_SYS_ENDIAN_LITTLE,
|
||||
.info = &info,
|
||||
.decode = &decode,
|
||||
};
|
||||
|
||||
#ifndef R2_PLUGIN_INCORE
|
||||
R_API RLibStruct radare_plugin = {
|
||||
.type = R_LIB_TYPE_ARCH,
|
||||
.data = &r_arch_plugin_msil,
|
||||
.version = R2_VERSION
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
#include <r_lib.h>
|
||||
#include <r_arch.h>
|
||||
#include <r_util.h>
|
||||
#include "ppc/ppc_disasm/ppc_disasm.h"
|
||||
|
||||
static bool decode(RArchSession *as, RAnalOp *op, RArchDecodeMask mask) {
|
||||
if (!op->bytes || op->size < 4) {
|
||||
return false;
|
||||
}
|
||||
ppc_word iaddr = (ppc_word)op->addr;
|
||||
ppc_word instr = R_ARCH_CONFIG_IS_BIG_ENDIAN(as->config)
|
||||
? r_read_be32(op->bytes) : r_read_le32(op->bytes);
|
||||
char opcode[128] = {0};
|
||||
char operands[128] = {0};
|
||||
struct DisasmPara_PPC dp = {0};
|
||||
dp.opcode = opcode;
|
||||
dp.operands = operands;
|
||||
dp.iaddr = &iaddr;
|
||||
dp.instr = &instr;
|
||||
PPC_Disassemble(&dp, 1);
|
||||
op->size = 4;
|
||||
if (dp.type == PPCINSTR_BRANCH && !(instr & 2)) {
|
||||
char *target = strstr(operands, "0x");
|
||||
if (target) {
|
||||
snprintf(target, sizeof(operands) - (target - operands), "0x%x",
|
||||
(unsigned int)(ppc_word)(op->addr + dp.displacement));
|
||||
}
|
||||
}
|
||||
if (dp.flags & PPCF_ILLEGAL) {
|
||||
op->type = R_ANAL_OP_TYPE_ILL;
|
||||
return false;
|
||||
}
|
||||
if (mask & R_ARCH_OP_MASK_DISASM) {
|
||||
op->mnemonic = r_str_newf("%s%s%s", opcode, *operands ? " " : "", operands);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static int info(RArchSession *s, ut32 q) {
|
||||
switch (q) {
|
||||
case R_ARCH_INFO_MINOP_SIZE:
|
||||
case R_ARCH_INFO_MAXOP_SIZE:
|
||||
case R_ARCH_INFO_INVOP_SIZE:
|
||||
case R_ARCH_INFO_CODE_ALIGN:
|
||||
return 4;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
RArchPlugin r_arch_plugin_ppc_disasm = {
|
||||
.meta = {
|
||||
.name = "ppc.disasm",
|
||||
.desc = "Tiny PowerPC disassembly",
|
||||
.author = "pancake, nibble",
|
||||
.version = R2_VERSION,
|
||||
.license = "GPL3",
|
||||
.status = R_PLUGIN_STATUS_OK,
|
||||
},
|
||||
.arch = "ppc",
|
||||
.bits = R_SYS_BITS_PACK1(32),
|
||||
.endian = R_SYS_ENDIAN_BIG | R_SYS_ENDIAN_LITTLE,
|
||||
.info = &info,
|
||||
.decode = &decode,
|
||||
};
|
||||
|
||||
#ifndef R2_PLUGIN_INCORE
|
||||
R_API RLibStruct radare_plugin = {
|
||||
.type = R_LIB_TYPE_ARCH,
|
||||
.data = &r_arch_plugin_ppc_disasm,
|
||||
.version = R2_VERSION
|
||||
};
|
||||
#endif
|
||||
@@ -0,0 +1,50 @@
|
||||
#include <r_lib.h>
|
||||
#include <r_arch.h>
|
||||
#include <r_util.h>
|
||||
#include <psosvm/vmas/vmas.h>
|
||||
|
||||
static bool decode(RArchSession *as, RAnalOp *op, RArchDecodeMask mask) {
|
||||
char buf_asm[64] = {0};
|
||||
psosvmasm_init();
|
||||
int sz = psosvm_disasm(op->bytes, buf_asm);
|
||||
if (sz > 0) {
|
||||
if (mask & R_ARCH_OP_MASK_DISASM) op->mnemonic = strdup(buf_asm);
|
||||
op->size = sz;
|
||||
return true;
|
||||
}
|
||||
if (mask & R_ARCH_OP_MASK_DISASM) op->mnemonic = strdup("(data)");
|
||||
op->size = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
static int info(RArchSession *s, ut32 q) {
|
||||
switch (q) {
|
||||
case R_ARCH_INFO_MINOP_SIZE: return 1;
|
||||
case R_ARCH_INFO_MAXOP_SIZE: return 4;
|
||||
default: return 1;
|
||||
}
|
||||
}
|
||||
|
||||
RArchPlugin r_arch_plugin_psosvm = {
|
||||
.meta = {
|
||||
.name = "psosvm",
|
||||
.desc = "Smartcard PSOSVM",
|
||||
.author = "nibble",
|
||||
.version = R2_VERSION,
|
||||
.license = "BSD",
|
||||
.status = R_PLUGIN_STATUS_OK,
|
||||
},
|
||||
.arch = "psosvm",
|
||||
.bits = R_SYS_BITS_PACK2(8, 16),
|
||||
.endian = R_SYS_ENDIAN_LITTLE,
|
||||
.info = &info,
|
||||
.decode = &decode,
|
||||
};
|
||||
|
||||
#ifndef R2_PLUGIN_INCORE
|
||||
R_API RLibStruct radare_plugin = {
|
||||
.type = R_LIB_TYPE_ARCH,
|
||||
.data = &r_arch_plugin_psosvm,
|
||||
.version = R2_VERSION
|
||||
};
|
||||
#endif
|
||||
@@ -0,0 +1,94 @@
|
||||
/* RArch port of SPC700 disassembler (minimal text-only) */
|
||||
#include <r_lib.h>
|
||||
#include <r_arch.h>
|
||||
#include <r_util.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../arch/spc700/spc700_opcode_table.h"
|
||||
|
||||
static int op_len(int t) {
|
||||
switch (t) {
|
||||
case SPC_OP: return 1;
|
||||
case SPC_ARG8_1: return 2;
|
||||
case SPC_ARG8_2: return 3;
|
||||
case SPC_ARG16: return 3;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool decode(RArchSession *as, RAnalOp *op, RArchDecodeMask mask) {
|
||||
if (op->size < 1) {
|
||||
op->type = R_ANAL_OP_TYPE_ILL;
|
||||
if (mask & R_ARCH_OP_MASK_DISASM) {
|
||||
op->mnemonic = strdup("invalid");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
int t = spc_op_table[op->bytes[0]].type;
|
||||
int len = op_len(t);
|
||||
if (op->size < len) {
|
||||
op->type = R_ANAL_OP_TYPE_UNK;
|
||||
op->size = 0;
|
||||
if (mask & R_ARCH_OP_MASK_DISASM) {
|
||||
op->mnemonic = strdup("(truncated)");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (mask & R_ARCH_OP_MASK_DISASM) {
|
||||
const char *fmt = spc_op_table[op->bytes[0]].name;
|
||||
char buf[64];
|
||||
switch (t) {
|
||||
case SPC_OP:
|
||||
r_str_ncpy(buf, fmt, sizeof(buf));
|
||||
break;
|
||||
case SPC_ARG8_1:
|
||||
snprintf(buf, sizeof(buf), fmt, op->bytes[1]);
|
||||
break;
|
||||
case SPC_ARG8_2:
|
||||
snprintf(buf, sizeof(buf), fmt, op->bytes[1], op->bytes[2]);
|
||||
break;
|
||||
case SPC_ARG16:
|
||||
snprintf(buf, sizeof(buf), fmt, (int)(op->bytes[1] + 0x100 * op->bytes[2]));
|
||||
break;
|
||||
default:
|
||||
r_str_ncpy(buf, "invalid", sizeof(buf));
|
||||
break;
|
||||
}
|
||||
op->mnemonic = strdup(buf);
|
||||
}
|
||||
op->size = len;
|
||||
return true;
|
||||
}
|
||||
|
||||
static int info(RArchSession *s, ut32 q) {
|
||||
switch (q) {
|
||||
case R_ARCH_INFO_MINOP_SIZE: return 1;
|
||||
case R_ARCH_INFO_MAXOP_SIZE: return 3;
|
||||
default: return 1;
|
||||
}
|
||||
}
|
||||
|
||||
RArchPlugin r_arch_plugin_spc700 = {
|
||||
.meta = {
|
||||
.name = "spc700",
|
||||
.desc = "SPC700, SNES sound chip",
|
||||
.author = "condret, pancake",
|
||||
.version = R2_VERSION,
|
||||
.license = "LGPL3",
|
||||
.status = R_PLUGIN_STATUS_OK,
|
||||
},
|
||||
.arch = "spc700",
|
||||
.bits = R_SYS_BITS_PACK1(16),
|
||||
.endian = R_SYS_ENDIAN_NONE,
|
||||
.info = &info,
|
||||
.decode = &decode,
|
||||
};
|
||||
|
||||
#ifndef R2_PLUGIN_INCORE
|
||||
R_API RLibStruct radare_plugin = {
|
||||
.type = R_LIB_TYPE_ARCH,
|
||||
.data = &r_arch_plugin_spc700,
|
||||
.version = R2_VERSION
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
#include <r_lib.h>
|
||||
#include <r_arch.h>
|
||||
#include <r_util.h>
|
||||
#include "../arch/swf/swfdis.h"
|
||||
|
||||
static bool decode(RArchSession *as, RAnalOp *op, RArchDecodeMask mask) {
|
||||
if (!(mask & R_ARCH_OP_MASK_DISASM)) {
|
||||
op->size = 0;
|
||||
return true;
|
||||
}
|
||||
if (!as || !as->arch || !as->arch->binb.bin || !as->arch->binb.bin->cur) {
|
||||
op->mnemonic = strdup("invalid");
|
||||
op->type = R_ANAL_OP_TYPE_ILL;
|
||||
return false;
|
||||
}
|
||||
RBin *bin = as->arch->binb.bin;
|
||||
RBinObject *obj = bin->cur ? bin->cur->bo : NULL;
|
||||
if (!obj) {
|
||||
op->mnemonic = strdup("invalid");
|
||||
op->size = 0;
|
||||
return false;
|
||||
}
|
||||
RStrBuf sb;
|
||||
r_strbuf_init(&sb);
|
||||
int dlen = r_asm_swf_disass(obj, &sb, op->bytes, op->size, op->addr);
|
||||
op->size = dlen > 0 ? dlen : 0;
|
||||
op->mnemonic = r_strbuf_drain(&sb);
|
||||
return dlen > 0;
|
||||
}
|
||||
|
||||
static int info(RArchSession *s, ut32 q) {
|
||||
switch (q) {
|
||||
case R_ARCH_INFO_MINOP_SIZE: return 1;
|
||||
case R_ARCH_INFO_MAXOP_SIZE: return 8;
|
||||
default: return 1;
|
||||
}
|
||||
}
|
||||
|
||||
RArchPlugin r_arch_plugin_swf = {
|
||||
.meta = {
|
||||
.name = "swf",
|
||||
.desc = "SWF",
|
||||
.author = "xarkes, pancake",
|
||||
.version = R2_VERSION,
|
||||
.license = "LGPL3",
|
||||
.status = R_PLUGIN_STATUS_OK,
|
||||
},
|
||||
.arch = "swf",
|
||||
.bits = R_SYS_BITS_PACK1(32),
|
||||
.endian = R_SYS_ENDIAN_LITTLE,
|
||||
.info = &info,
|
||||
.decode = &decode,
|
||||
};
|
||||
|
||||
#ifndef R2_PLUGIN_INCORE
|
||||
R_API RLibStruct radare_plugin = {
|
||||
.type = R_LIB_TYPE_ARCH,
|
||||
.data = &r_arch_plugin_swf,
|
||||
.version = R2_VERSION
|
||||
};
|
||||
#endif
|
||||
+248
-895
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,53 @@
|
||||
#include <r_lib.h>
|
||||
#include <r_arch.h>
|
||||
#include <r_util.h>
|
||||
#include "x86/bea/BeaEngine.h"
|
||||
|
||||
static bool decode(RArchSession *as, RAnalOp *op, RArchDecodeMask mask) {
|
||||
DISASM dis = {0};
|
||||
dis.EIP = (long long)op->bytes;
|
||||
dis.VirtualAddr = op->addr;
|
||||
dis.Archi = ((as && as->config && as->config->bits == 64) ? 64 : 0);
|
||||
dis.SecurityBlock = op->size;
|
||||
if (as && as->config && as->config->syntax == R_ARCH_SYNTAX_ATT) {
|
||||
dis.Options = 0x400;
|
||||
}
|
||||
int sz = Disasm(&dis);
|
||||
op->size = (sz > 0)? sz: 0;
|
||||
if (mask & R_ARCH_OP_MASK_DISASM) {
|
||||
op->mnemonic = strdup(dis.CompleteInstr ? dis.CompleteInstr : "invalid");
|
||||
}
|
||||
return sz > 0;
|
||||
}
|
||||
|
||||
static int info(RArchSession *s, ut32 q) {
|
||||
switch (q) {
|
||||
case R_ARCH_INFO_MINOP_SIZE: return 1;
|
||||
case R_ARCH_INFO_MAXOP_SIZE: return 15;
|
||||
default: return 1;
|
||||
}
|
||||
}
|
||||
|
||||
RArchPlugin r_arch_plugin_x86_bea = {
|
||||
.meta = {
|
||||
.name = "x86.bea",
|
||||
.desc = "x86 BeaEngine disassembler",
|
||||
.author = "pancake, nibble",
|
||||
.version = R2_VERSION,
|
||||
.license = "LGPL",
|
||||
.status = R_PLUGIN_STATUS_OK,
|
||||
},
|
||||
.arch = "x86",
|
||||
.bits = R_SYS_BITS_PACK3(16, 32, 64),
|
||||
.endian = R_SYS_ENDIAN_LITTLE,
|
||||
.info = &info,
|
||||
.decode = &decode,
|
||||
};
|
||||
|
||||
#ifndef R2_PLUGIN_INCORE
|
||||
R_API RLibStruct radare_plugin = {
|
||||
.type = R_LIB_TYPE_ARCH,
|
||||
.data = &r_arch_plugin_x86_bea,
|
||||
.version = R2_VERSION
|
||||
};
|
||||
#endif
|
||||
@@ -0,0 +1,50 @@
|
||||
/* RArch plugin for x86 Olly disassembler */
|
||||
#include <r_lib.h>
|
||||
#include <r_arch.h>
|
||||
#include <r_util.h>
|
||||
#include "x86/ollyasm/disasm.h"
|
||||
|
||||
static bool decode(RArchSession *as, RAnalOp *op, RArchDecodeMask mask) {
|
||||
t_disasm d = {0};
|
||||
int sz = Disasm_olly(op->bytes, op->size, op->addr, &d, DISASM_FILE);
|
||||
if (sz <= 0) {
|
||||
if (mask & R_ARCH_OP_MASK_DISASM) op->mnemonic = strdup("invalid");
|
||||
op->size = 0;
|
||||
return false;
|
||||
}
|
||||
if (mask & R_ARCH_OP_MASK_DISASM) op->mnemonic = strdup(d.result ? d.result : "");
|
||||
op->size = sz;
|
||||
return true;
|
||||
}
|
||||
|
||||
static int info(RArchSession *s, ut32 q) {
|
||||
switch (q) {
|
||||
case R_ARCH_INFO_MINOP_SIZE: return 1;
|
||||
case R_ARCH_INFO_MAXOP_SIZE: return 15;
|
||||
default: return 1;
|
||||
}
|
||||
}
|
||||
|
||||
RArchPlugin r_arch_plugin_x86_olly = {
|
||||
.meta = {
|
||||
.name = "x86.olly",
|
||||
.desc = "OllyDBG x86 disassembler",
|
||||
.author = "pancake, nibble",
|
||||
.version = R2_VERSION,
|
||||
.license = "GPL2",
|
||||
.status = R_PLUGIN_STATUS_OK,
|
||||
},
|
||||
.arch = "x86",
|
||||
.bits = R_SYS_BITS_PACK3(16, 32, 64),
|
||||
.endian = R_SYS_ENDIAN_LITTLE,
|
||||
.info = &info,
|
||||
.decode = &decode,
|
||||
};
|
||||
|
||||
#ifndef R2_PLUGIN_INCORE
|
||||
R_API RLibStruct radare_plugin = {
|
||||
.type = R_LIB_TYPE_ARCH,
|
||||
.data = &r_arch_plugin_x86_olly,
|
||||
.version = R2_VERSION
|
||||
};
|
||||
#endif
|
||||
@@ -0,0 +1,41 @@
|
||||
#include <r_lib.h>
|
||||
#include <r_arch.h>
|
||||
|
||||
static bool decode(RArchSession *as, RAnalOp *op, RArchDecodeMask mask) {
|
||||
op->type = R_ANAL_OP_TYPE_UNK;
|
||||
if (mask & R_ARCH_OP_MASK_DISASM) op->mnemonic = strdup("(x86.tab: unimplemented)");
|
||||
op->size = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
static int info(RArchSession *s, ut32 q) {
|
||||
switch (q) {
|
||||
case R_ARCH_INFO_MINOP_SIZE: return 1;
|
||||
case R_ARCH_INFO_MAXOP_SIZE: return 15;
|
||||
default: return 1;
|
||||
}
|
||||
}
|
||||
|
||||
RArchPlugin r_arch_plugin_x86_tab = {
|
||||
.meta = {
|
||||
.name = "x86.tab",
|
||||
.desc = "x86 table disassembler (stub)",
|
||||
.author = "radare2-extras",
|
||||
.version = R2_VERSION,
|
||||
.license = "LGPL3",
|
||||
.status = R_PLUGIN_STATUS_BASIC,
|
||||
},
|
||||
.arch = "x86",
|
||||
.bits = R_SYS_BITS_PACK3(16, 32, 64),
|
||||
.endian = R_SYS_ENDIAN_LITTLE,
|
||||
.info = &info,
|
||||
.decode = &decode,
|
||||
};
|
||||
|
||||
#ifndef R2_PLUGIN_INCORE
|
||||
R_API RLibStruct radare_plugin = {
|
||||
.type = R_LIB_TYPE_ARCH,
|
||||
.data = &r_arch_plugin_x86_tab,
|
||||
.version = R2_VERSION
|
||||
};
|
||||
#endif
|
||||
@@ -0,0 +1,98 @@
|
||||
/* radare2-extras: RArch plugin wrapping udis86 for x86 */
|
||||
|
||||
#include <r_lib.h>
|
||||
#include <r_arch.h>
|
||||
#include <r_asm.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "udis86/types.h"
|
||||
#include "udis86/extern.h"
|
||||
|
||||
static bool decode(RArchSession *as, RAnalOp *op, RArchDecodeMask mask) {
|
||||
ud_t d;
|
||||
ud_init(&d);
|
||||
|
||||
/* set syntax based on session config */
|
||||
if (as && as->config) {
|
||||
switch (as->config->syntax) {
|
||||
case R_ARCH_SYNTAX_ATT:
|
||||
ud_set_syntax(&d, UD_SYN_ATT);
|
||||
break;
|
||||
default:
|
||||
ud_set_syntax(&d, UD_SYN_INTEL);
|
||||
break;
|
||||
}
|
||||
ud_set_mode(&d, as->config->bits);
|
||||
} else {
|
||||
ud_set_syntax(&d, UD_SYN_INTEL);
|
||||
ud_set_mode(&d, 32);
|
||||
}
|
||||
|
||||
ud_set_input_buffer(&d, (uint8_t *)op->bytes, op->size);
|
||||
ud_set_pc(&d, op->addr);
|
||||
|
||||
int opsize = ud_disassemble(&d);
|
||||
if (opsize < 1) {
|
||||
op->type = R_ANAL_OP_TYPE_ILL;
|
||||
op->size = 0;
|
||||
if (mask & R_ARCH_OP_MASK_DISASM) {
|
||||
op->mnemonic = strdup("invalid");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mask & R_ARCH_OP_MASK_DISASM) {
|
||||
const char *asmstr = ud_insn_asm(&d);
|
||||
if (!asmstr) {
|
||||
asmstr = "";
|
||||
}
|
||||
char *out = strdup(asmstr);
|
||||
if (as && as->config && as->config->syntax == R_ARCH_SYNTAX_JZ) {
|
||||
if (!strncmp(out, "je ", 3)) {
|
||||
memcpy(out, "jz", 2);
|
||||
} else if (!strncmp(out, "jne ", 4)) {
|
||||
memcpy(out, "jnz", 3);
|
||||
}
|
||||
}
|
||||
op->mnemonic = out;
|
||||
}
|
||||
|
||||
op->size = opsize;
|
||||
return true;
|
||||
}
|
||||
|
||||
static int info(RArchSession *s, ut32 q) {
|
||||
switch (q) {
|
||||
case R_ARCH_INFO_MINOP_SIZE:
|
||||
return 1;
|
||||
case R_ARCH_INFO_MAXOP_SIZE:
|
||||
return 15;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
RArchPlugin r_arch_plugin_x86_udis = {
|
||||
.meta = {
|
||||
.name = "x86.udis",
|
||||
.desc = "udis86 x86-16,32,64",
|
||||
.author = "pancake, nibble",
|
||||
.version = R2_VERSION,
|
||||
.license = "BSD",
|
||||
.status = R_PLUGIN_STATUS_OK,
|
||||
},
|
||||
.arch = "x86",
|
||||
.bits = R_SYS_BITS_PACK3(16, 32, 64),
|
||||
.endian = R_SYS_ENDIAN_LITTLE,
|
||||
.info = &info,
|
||||
.decode = &decode,
|
||||
};
|
||||
|
||||
#ifndef R2_PLUGIN_INCORE
|
||||
R_API RLibStruct radare_plugin = {
|
||||
.type = R_LIB_TYPE_ARCH,
|
||||
.data = &r_arch_plugin_x86_udis,
|
||||
.version = R2_VERSION
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
#include <r_lib.h>
|
||||
#include <r_arch.h>
|
||||
|
||||
static bool decode(RArchSession *as, RAnalOp *op, RArchDecodeMask mask) {
|
||||
if (mask & R_ARCH_OP_MASK_DISASM) op->mnemonic = strdup("(zydis: unavailable on this host)");
|
||||
op->size = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
static int info(RArchSession *s, ut32 q) {
|
||||
switch (q) {
|
||||
case R_ARCH_INFO_MINOP_SIZE: return 1;
|
||||
case R_ARCH_INFO_MAXOP_SIZE: return 15;
|
||||
default: return 1;
|
||||
}
|
||||
}
|
||||
|
||||
RArchPlugin r_arch_plugin_x86_zyan = {
|
||||
.meta = {
|
||||
.name = "x86.zyan",
|
||||
.desc = "x86 Zydis disassembler (stub on non-x86)",
|
||||
.author = "mrexodia",
|
||||
.version = R2_VERSION,
|
||||
.license = "MIT",
|
||||
.status = R_PLUGIN_STATUS_BASIC,
|
||||
},
|
||||
.arch = "x86",
|
||||
.bits = R_SYS_BITS_PACK3(16, 32, 64),
|
||||
.endian = R_SYS_ENDIAN_LITTLE,
|
||||
.info = &info,
|
||||
.decode = &decode,
|
||||
};
|
||||
|
||||
#ifndef R2_PLUGIN_INCORE
|
||||
R_API RLibStruct radare_plugin = {
|
||||
.type = R_LIB_TYPE_ARCH,
|
||||
.data = &r_arch_plugin_x86_zyan,
|
||||
.version = R2_VERSION
|
||||
};
|
||||
#endif
|
||||
@@ -0,0 +1,49 @@
|
||||
#include <r_lib.h>
|
||||
#include <r_arch.h>
|
||||
#include <r_util.h>
|
||||
|
||||
#include "../arch/z80/z80.c"
|
||||
|
||||
static bool decode(RArchSession *as, RAnalOp *op, RArchDecodeMask mask) {
|
||||
if (mask & R_ARCH_OP_MASK_DISASM) {
|
||||
char out[128];
|
||||
int dlen = z80dis(0, op->bytes, out, op->size);
|
||||
if (dlen < 0) dlen = 0;
|
||||
op->size = dlen;
|
||||
op->mnemonic = strdup(out);
|
||||
return dlen > 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static int info(RArchSession *s, ut32 q) {
|
||||
switch (q) {
|
||||
case R_ARCH_INFO_MINOP_SIZE: return 1;
|
||||
case R_ARCH_INFO_MAXOP_SIZE: return 4;
|
||||
default: return 1;
|
||||
}
|
||||
}
|
||||
|
||||
RArchPlugin r_arch_plugin_z80 = {
|
||||
.meta = {
|
||||
.name = "z80",
|
||||
.desc = "Zilog Z80",
|
||||
.author = "pancake",
|
||||
.version = R2_VERSION,
|
||||
.license = "NC-GPL2",
|
||||
.status = R_PLUGIN_STATUS_OK,
|
||||
},
|
||||
.arch = "z80",
|
||||
.bits = R_SYS_BITS_PACK1(8),
|
||||
.endian = R_SYS_ENDIAN_NONE,
|
||||
.info = &info,
|
||||
.decode = &decode,
|
||||
};
|
||||
|
||||
#ifndef R2_PLUGIN_INCORE
|
||||
R_API RLibStruct radare_plugin = {
|
||||
.type = R_LIB_TYPE_ARCH,
|
||||
.data = &r_arch_plugin_z80,
|
||||
.version = R2_VERSION
|
||||
};
|
||||
#endif
|
||||
@@ -0,0 +1,49 @@
|
||||
#include <r_lib.h>
|
||||
#include <r_arch.h>
|
||||
#include <r_util.h>
|
||||
|
||||
#include "../arch/z80_nc/disasm.c"
|
||||
|
||||
static bool decode(RArchSession *as, RAnalOp *op, RArchDecodeMask mask) {
|
||||
if (mask & R_ARCH_OP_MASK_DISASM) {
|
||||
char out[128];
|
||||
int dlen = z80dis(0, op->bytes, out, op->size);
|
||||
if (dlen < 0) dlen = 0;
|
||||
op->size = dlen;
|
||||
op->mnemonic = strdup(out);
|
||||
return dlen > 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static int info(RArchSession *s, ut32 q) {
|
||||
switch (q) {
|
||||
case R_ARCH_INFO_MINOP_SIZE: return 1;
|
||||
case R_ARCH_INFO_MAXOP_SIZE: return 4;
|
||||
default: return 1;
|
||||
}
|
||||
}
|
||||
|
||||
RArchPlugin r_arch_plugin_z80_nc = {
|
||||
.meta = {
|
||||
.name = "z80.nc",
|
||||
.desc = "Zilog Z80 non-commercial",
|
||||
.author = "pancake",
|
||||
.version = R2_VERSION,
|
||||
.license = "NC-GPL2",
|
||||
.status = R_PLUGIN_STATUS_OK,
|
||||
},
|
||||
.arch = "z80",
|
||||
.bits = R_SYS_BITS_PACK1(8),
|
||||
.endian = R_SYS_ENDIAN_NONE,
|
||||
.info = &info,
|
||||
.decode = &decode,
|
||||
};
|
||||
|
||||
#ifndef R2_PLUGIN_INCORE
|
||||
R_API RLibStruct radare_plugin = {
|
||||
.type = R_LIB_TYPE_ARCH,
|
||||
.data = &r_arch_plugin_z80_nc,
|
||||
.version = R2_VERSION
|
||||
};
|
||||
#endif
|
||||
@@ -1,14 +1,17 @@
|
||||
OBJ_ARMTHUMB=asm_armthumb.o
|
||||
OBJ_ARMTHUMB+=../arch/arm/armthumb.o
|
||||
OBJ_ARMTHUMB=arch_armthumb.o
|
||||
OBJ_ARMTHUMB+=armthumb_src.o
|
||||
|
||||
STATIC_OBJ+=${OBJ_ARMTHUMB}
|
||||
TARGET_ARMTHUMB=asm_armthumb.${LIBEXT}
|
||||
TARGET_ARMTHUMB=arch_armthumb.${LIBEXT}
|
||||
|
||||
ALL_TARGETS+=${TARGET_ARMTHUMB}
|
||||
|
||||
$(OBJ_ARMTHUMB): %.o : %.c
|
||||
arch_armthumb.o: arch_armthumb.c
|
||||
$(CC) -c $(CFLAGS) $< -o $@
|
||||
|
||||
armthumb_src.o: ../arch/arm/armthumb.c
|
||||
$(CC) -c $(CFLAGS) -I../arch/arm -o $@ $<
|
||||
|
||||
${TARGET_ARMTHUMB}: ${OBJ_ARMTHUMB}
|
||||
${CC} $(call libname,asm_armthumb) ${LDFLAGS} \
|
||||
${CFLAGS} -o asm_armthumb.${LIBEXT} ${OBJ_ARMTHUMB}
|
||||
${CC} $(call libname,arch_armthumb) ${LDFLAGS} \
|
||||
${CFLAGS} -o ${TARGET_ARMTHUMB} ${OBJ_ARMTHUMB}
|
||||
@@ -1,49 +0,0 @@
|
||||
/* radare - LGPL - Copyright 2010-2018 - pancake */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <r_types.h>
|
||||
#include <r_util.h>
|
||||
#include <r_lib.h>
|
||||
#include <r_asm.h>
|
||||
#include "../arch/arm/arm.h"
|
||||
|
||||
static int disassemble(RAsm *a, RAsmOp *op, const ut8 *buf, int len) {
|
||||
int *p = (int*)buf; // TODO : endian
|
||||
char buf_asm[64] = {0};
|
||||
op->size = armthumb_disassemble (buf_asm, (ut32)a->pc, *p);
|
||||
if (op->size > 0) {
|
||||
r_strbuf_set (&op->buf_asm, buf_asm);
|
||||
} else {
|
||||
r_strbuf_set (&op->buf_asm, " (data)");
|
||||
}
|
||||
return op->size;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int assemble(RAsm *a, RAsmOp *op, const char *buf) {
|
||||
int opcode = armass_assemble (buf, a->pc, true);
|
||||
if (opcode==-1)
|
||||
return -1;
|
||||
r_mem_copyendian (op->buf, (void *)&opcode, 2, a->big_endian);
|
||||
return armthumb_length (opcode);
|
||||
}
|
||||
#endif
|
||||
|
||||
RAsmPlugin r_asm_plugin_armthumb = {
|
||||
.name = "arm.thumb",
|
||||
.arch = "arm",
|
||||
.bits = 16,
|
||||
.desc = "ARM THUMB disassembly plugin",
|
||||
.disassemble = &disassemble,
|
||||
// .assemble = &assemble
|
||||
};
|
||||
|
||||
#ifndef R2_PLUGIN_INCORE
|
||||
RLibStruct radare_plugin = {
|
||||
.type = R_LIB_TYPE_ASM,
|
||||
.data = &r_asm_plugin_armthumb,
|
||||
.version = R2_VERSION
|
||||
};
|
||||
#endif
|
||||
@@ -1,40 +0,0 @@
|
||||
/* radare - LGPL - Copyright 2018 - damo22 */
|
||||
|
||||
#include <r_types.h>
|
||||
#include <r_lib.h>
|
||||
#include <r_asm.h>
|
||||
|
||||
#include "../arch/atombios/atombios.h"
|
||||
|
||||
static int disassemble(RAsm *a, RAsmOp *op, const ut8 *buf, int len) {
|
||||
char res[1024];
|
||||
res[0] = 0;
|
||||
op->size = atombios_disassemble (buf, len, res);
|
||||
r_strbuf_set (&op->buf_asm, res);
|
||||
return op->size;
|
||||
}
|
||||
|
||||
static int assemble(RAsm *a, RAsmOp *op, const char *buf) {
|
||||
return 0; // n
|
||||
}
|
||||
|
||||
RAsmPlugin r_asm_plugin_atombios = {
|
||||
.name = "atombios",
|
||||
.author = "damo22",
|
||||
.version = "0.0.1",
|
||||
.arch = "atombios",
|
||||
.license = "LGPL3",
|
||||
.bits = 32 | 64,
|
||||
.endian = R_SYS_ENDIAN_NONE,
|
||||
.desc = "AtomBIOS",
|
||||
.disassemble = &disassemble,
|
||||
.assemble = &assemble
|
||||
};
|
||||
|
||||
#ifndef CORELIB
|
||||
RLibStruct radare_plugin = {
|
||||
.type = R_LIB_TYPE_ASM,
|
||||
.data = &r_asm_plugin_atombios,
|
||||
.version = R2_VERSION
|
||||
};
|
||||
#endif
|
||||
@@ -1,47 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <r_types.h>
|
||||
#include <r_lib.h>
|
||||
#include <r_util.h>
|
||||
#include <r_asm.h>
|
||||
|
||||
#include "../../asm/arch/ba2/ba2_disas.c"
|
||||
|
||||
static int disassemble(RAsm *a, RAsmOp *op, const ut8 *buf, int len) {
|
||||
struct op_cmd cmd = {
|
||||
.instr = "",
|
||||
.operands = ""
|
||||
};
|
||||
int ret = ba2_decode_opcode (a->pc, buf, len, &cmd, NULL, NULL);
|
||||
if((len < ret) || (!ret && len<6)){
|
||||
r_strbuf_set (&op->buf_asm, "truncated");
|
||||
op->size = 0;
|
||||
return 0;
|
||||
}
|
||||
if (ret > 0) {
|
||||
snprintf (op->buf_asm.buf, sizeof(op->buf_asm.buf), "%s %s", cmd.instr, cmd.operands);
|
||||
}else{
|
||||
r_strbuf_set (&op->buf_asm, "invalid");
|
||||
return -1;
|
||||
}
|
||||
return op->size = ret;
|
||||
}
|
||||
|
||||
RAsmPlugin r_asm_plugin_ba2 = {
|
||||
.name = "ba2",
|
||||
.license = "LGPL3",
|
||||
.desc = "Beyond Architecture 2 disassembly plugin",
|
||||
.arch = "ba2",
|
||||
.bits = 32,
|
||||
.endian = R_SYS_ENDIAN_LITTLE,
|
||||
.disassemble = &disassemble
|
||||
};
|
||||
|
||||
#ifndef R2_PLUGIN_INCORE
|
||||
R_API RLibStruct radare_plugin = {
|
||||
.type = R_LIB_TYPE_ASM,
|
||||
.data = &r_asm_plugin_ba2,
|
||||
.version = R2_VERSION
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
/* radare2 - LGPL - Copyright 2012-2021 pancake */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <r_types.h>
|
||||
#include <r_util.h>
|
||||
#include <r_lib.h>
|
||||
#include <r_asm.h>
|
||||
#include "../arch/dcpu16/dcpu16.h"
|
||||
#include "../arch/dcpu16/dis.c"
|
||||
#include "../arch/dcpu16/asm.c"
|
||||
|
||||
static int disassemble(RAsm *a, RAsmOp *op, const ut8 *buf, int len) {
|
||||
char buf_asm[96];
|
||||
if (len < 2) {
|
||||
return -1; // at least 2 bytes!
|
||||
}
|
||||
op->size = dcpu16_disasm (buf_asm, sizeof (buf_asm), (const ut16*)buf, len, NULL);
|
||||
r_strbuf_set (&op->buf_asm, (op->size > 0) ? buf_asm: "(data)");
|
||||
return op->size;
|
||||
}
|
||||
|
||||
static int assemble(RAsm *a, RAsmOp *op, const char *buf) {
|
||||
int len = dcpu16_assemble ((ut8*)r_strbuf_get (&op->buf), buf);
|
||||
op->buf.len = len;
|
||||
return len;
|
||||
}
|
||||
|
||||
RAsmPlugin r_asm_plugin_dcpu16 = {
|
||||
.name = "dcpu16",
|
||||
.arch = "dpcu",
|
||||
.bits = 16,
|
||||
.endian = R_SYS_ENDIAN_LITTLE,
|
||||
.desc = "Mojang's DCPU-16",
|
||||
.license = "PD",
|
||||
.disassemble = &disassemble,
|
||||
.assemble = &assemble
|
||||
};
|
||||
|
||||
#ifndef R2_PLUGIN_INCORE
|
||||
R_API RLibStruct radare_plugin = {
|
||||
.type = R_LIB_TYPE_ASM,
|
||||
.data = &r_asm_plugin_dcpu16,
|
||||
.version = R2_VERSION
|
||||
};
|
||||
#endif
|
||||
@@ -1,63 +0,0 @@
|
||||
/* radare - GPL3 - Copyright 2009-2015 - nibble */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <r_types.h>
|
||||
#include <r_lib.h>
|
||||
#include <r_util.h>
|
||||
#include <r_asm.h>
|
||||
|
||||
#include "m68k/m68k_disasm/m68k_disasm.h"
|
||||
|
||||
static int disassemble(RAsm *a, RAsmOp *aop, const ut8 *buf, int len) {
|
||||
m68k_word bof[8] = {0};
|
||||
int iaddr = (int)a->pc;
|
||||
char opcode[256], operands[256];
|
||||
const unsigned char *buf2;
|
||||
int ilen ;
|
||||
static struct DisasmPara_68k dp;
|
||||
char *buf_asm;
|
||||
r_strf_buffer (256);
|
||||
|
||||
/* initialize DisasmPara */
|
||||
*operands = *opcode = 0;
|
||||
memcpy (bof, buf, R_MIN(len, sizeof(bof)));
|
||||
dp.opcode = opcode;
|
||||
dp.operands = operands;
|
||||
dp.iaddr = (m68k_word *) (size_t)iaddr;
|
||||
dp.instr = bof;
|
||||
buf2 = (const ut8*)M68k_Disassemble (&dp);
|
||||
if (!buf2) {
|
||||
// invalid instruction
|
||||
return aop->size = 2;
|
||||
}
|
||||
ilen = buf2 - (const ut8*)bof;
|
||||
if (*operands) {
|
||||
buf_asm = r_strf ("%s %s", opcode, operands);
|
||||
} else {
|
||||
buf_asm = r_strf ("%s", opcode);
|
||||
}
|
||||
r_str_replace_ch (buf_asm, '#', 0, 1);
|
||||
r_asm_op_set_asm (aop, buf_asm);
|
||||
aop->size = ilen;
|
||||
return aop->size;
|
||||
}
|
||||
|
||||
RAsmPlugin r_asm_plugin_m68k = {
|
||||
.name = "m68k.net",
|
||||
.arch = "m68k",
|
||||
.license = "BSD",
|
||||
.bits = 16|32,
|
||||
.endian = R_SYS_ENDIAN_BIG,
|
||||
.desc = "Motorola 68000",
|
||||
.disassemble = &disassemble,
|
||||
};
|
||||
|
||||
#ifndef CORELIB
|
||||
RLibStruct radare_plugin = {
|
||||
.type = R_LIB_TYPE_ASM,
|
||||
.data = &r_asm_plugin_m68k,
|
||||
.version = R2_VERSION
|
||||
};
|
||||
#endif
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,43 +0,0 @@
|
||||
/* radare - Public Domain - Copyright 2011-2015 - capi_x, pancake */
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <r_types.h>
|
||||
#include <r_lib.h>
|
||||
#include <r_util.h>
|
||||
#include <r_asm.h>
|
||||
#include "msil/demsil.c"
|
||||
|
||||
static int arch_msil_disasm(RStrBuf *buf_asm, const ut8 *buf, ut64 seek) {
|
||||
ut32 n;
|
||||
int o;
|
||||
DISASMSIL_OFFSET CodeBase = seek;
|
||||
ILOPCODE_STRUCT ilopar[8];
|
||||
o = DisasMSIL (buf, 16, CodeBase, ilopar, 8, &n);
|
||||
r_strbuf_setf (buf_asm, "%s", ilopar[0].Mnemonic);
|
||||
return o;
|
||||
}
|
||||
|
||||
static int disassemble(RAsm *a, RAsmOp *op, const ut8 *buf, int len) {
|
||||
return (op->size = arch_msil_disasm (&op->buf_asm, buf, a->pc));
|
||||
}
|
||||
|
||||
RAsmPlugin r_asm_plugin_msil = {
|
||||
.name = "msil",
|
||||
.arch = "msil",
|
||||
.license = "PD",
|
||||
.bits = 16|32|64,
|
||||
.desc = ".NET Microsoft Intermediate Language",
|
||||
.init = NULL,
|
||||
.fini = NULL,
|
||||
.disassemble = &disassemble,
|
||||
.assemble = NULL
|
||||
};
|
||||
|
||||
#ifndef CORELIB
|
||||
RLibStruct radare_plugin = {
|
||||
.type = R_LIB_TYPE_ASM,
|
||||
.data = &r_asm_plugin_msil,
|
||||
.version = R2_VERSION
|
||||
};
|
||||
#endif
|
||||
@@ -1,48 +0,0 @@
|
||||
/* radare - GPL3 - Copyright 2009-2018 pancake, nibble */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <r_types.h>
|
||||
#include <r_lib.h>
|
||||
#include <r_util.h>
|
||||
#include <r_asm.h>
|
||||
|
||||
#include "ppc/ppc_disasm/ppc_disasm.h"
|
||||
|
||||
static int disassemble(RAsm *a, RAsmOp *aop, const ut8 *buf, int len) {
|
||||
ppc_word iaddr = (ppc_word)a->pc;
|
||||
ppc_word bof[4];
|
||||
char opcode[128];
|
||||
char operands[128];
|
||||
|
||||
static struct DisasmPara_PPC dp;
|
||||
/* initialize DisasmPara */
|
||||
memcpy (bof, buf, 4);
|
||||
dp.opcode = opcode;
|
||||
dp.operands = operands;
|
||||
dp.iaddr = &iaddr;
|
||||
dp.instr = bof;
|
||||
PPC_Disassemble (&dp, a->config->big_endian);
|
||||
char res[64] = {0};
|
||||
snprintf (res, sizeof (res), "%s %s", opcode, operands);
|
||||
r_strbuf_set (&aop->buf_asm, res);
|
||||
aop->size = 4;
|
||||
return aop->size;
|
||||
}
|
||||
|
||||
RAsmPlugin r_asm_plugin_ppc_disasm = {
|
||||
.name = "ppc.disasm",
|
||||
.arch = "ppc",
|
||||
.bits = 32,
|
||||
.desc = "Tiny PowerPC disassembly plugin",
|
||||
.disassemble = &disassemble,
|
||||
};
|
||||
|
||||
#ifndef CORELIB
|
||||
RLibStruct radare_plugin = {
|
||||
.type = R_LIB_TYPE_ASM,
|
||||
.data = &r_asm_plugin_ppc_disasm,
|
||||
.version = R2_VERSION
|
||||
};
|
||||
#endif
|
||||
@@ -1,44 +0,0 @@
|
||||
/* radare - LGPL - Copyright 2009-2013 - nibble */
|
||||
|
||||
#include <r_types.h>
|
||||
#include <r_util.h>
|
||||
#include <r_lib.h>
|
||||
#include <r_asm.h>
|
||||
#include <psosvm/vmas/vmas.h>
|
||||
|
||||
static int disassemble(RAsm *a, struct r_asm_op_t *op, const ut8 *buf, int len) {
|
||||
char buf_asm[64] = {0};
|
||||
psosvmasm_init();
|
||||
op->size = psosvm_disasm(buf, buf_asm);
|
||||
if (op->size > 0) {
|
||||
r_asm_op_set_asm (op, buf_asm);
|
||||
} else {
|
||||
r_asm_op_set_asm (op, " (data)");
|
||||
}
|
||||
return op->size;
|
||||
}
|
||||
|
||||
static int assemble(RAsm *a, RAsmOp *op, const char *buf) {
|
||||
op->size = psosvm_assemble((ut8*)r_strbuf_get (&op->buf), buf);
|
||||
return op->size;
|
||||
}
|
||||
|
||||
RAsmPlugin r_asm_plugin_psosvm = {
|
||||
.name = "psosvm",
|
||||
.desc = "Smartcard PSOS Virtual Machine",
|
||||
.license = "BSD",
|
||||
.arch = "psosvm",
|
||||
.bits = 8|16,
|
||||
.init = NULL,
|
||||
.fini = NULL,
|
||||
.disassemble = &disassemble,
|
||||
.assemble = &assemble
|
||||
};
|
||||
|
||||
#ifndef CORELIB
|
||||
struct r_lib_struct_t radare_plugin = {
|
||||
.type = R_LIB_TYPE_ASM,
|
||||
.data = &r_asm_plugin_psosvm,
|
||||
.version = R2_VERSION
|
||||
};
|
||||
#endif
|
||||
@@ -1,35 +0,0 @@
|
||||
/* radare - LGPL - Copyright 2012-2020 - pancake, condret */
|
||||
|
||||
#include <r_types.h>
|
||||
#include <r_util.h>
|
||||
#include <r_asm.h>
|
||||
#include <sdb.h>
|
||||
#include <r_lib.h>
|
||||
#include "../arch/spc700/spc700dis.c"
|
||||
|
||||
static int disassemble(RAsm *a, RAsmOp *r_op, const ut8 *buf, int len) {
|
||||
int dlen = spc700Disass (r_op, buf, len);
|
||||
if (dlen < 0) {
|
||||
dlen = 0;
|
||||
}
|
||||
r_op->size = dlen;
|
||||
return dlen;
|
||||
}
|
||||
|
||||
RAsmPlugin r_asm_plugin_spc700 = {
|
||||
.name = "spc700",
|
||||
.desc = "spc700, snes' sound-chip",
|
||||
.arch = "spc700",
|
||||
.license = "LGPL3",
|
||||
.bits = 16,
|
||||
.endian = R_SYS_ENDIAN_NONE, // is this LE?
|
||||
.disassemble = &disassemble,
|
||||
};
|
||||
|
||||
#ifndef R2_PLUGIN_INCORE
|
||||
R_API RLibStruct radare_plugin = {
|
||||
.type = R_LIB_TYPE_ASM,
|
||||
.data = &r_asm_plugin_spc700,
|
||||
.version = R2_VERSION
|
||||
};
|
||||
#endif
|
||||
@@ -1,33 +0,0 @@
|
||||
/* radare - LGPL3 - Copyright 2016-2021 - xarkes, pancake */
|
||||
|
||||
#include <r_types.h>
|
||||
#include <r_lib.h>
|
||||
#include <r_util.h>
|
||||
#include <r_asm.h>
|
||||
|
||||
#include "../arch/swf/swfdis.h"
|
||||
|
||||
static int disassemble(RAsm *a, RAsmOp *op, const ut8 *buf, int len) {
|
||||
RBin *bin = a->binb.bin;
|
||||
RBinObject *obj = bin->cur->o;
|
||||
int dlen = r_asm_swf_disass (obj, &op->buf_asm, buf, len, a->pc);
|
||||
op->size = dlen;
|
||||
return dlen;
|
||||
}
|
||||
|
||||
RAsmPlugin r_asm_plugin_swf = {
|
||||
.name = "swf",
|
||||
.arch = "swf",
|
||||
.license = "LGPL3",
|
||||
.bits = 32,
|
||||
.desc = "SWF",
|
||||
.disassemble = &disassemble,
|
||||
};
|
||||
|
||||
#ifndef CORELIB
|
||||
struct r_lib_struct_t radare_plugin = {
|
||||
.type = R_LIB_TYPE_ASM,
|
||||
.data = &r_asm_plugin_swf,
|
||||
.version = R2_VERSION
|
||||
};
|
||||
#endif
|
||||
@@ -1,47 +0,0 @@
|
||||
/* radare - GPL3 - Copyright 2009-2015 - pancake, nibble */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <r_types.h>
|
||||
#include <r_lib.h>
|
||||
#include <r_util.h>
|
||||
#include <r_asm.h>
|
||||
|
||||
#include "x86/bea/BeaEngine.h"
|
||||
//#include "fastcall_x86.h"
|
||||
|
||||
static int disassemble(RAsm *a, RAsmOp *aop, const ut8 *buf, int len) {
|
||||
static DISASM disasm_obj;
|
||||
|
||||
memset (&disasm_obj, '\0', sizeof (DISASM));
|
||||
disasm_obj.EIP = (long long)buf;
|
||||
disasm_obj.VirtualAddr = a->pc;
|
||||
disasm_obj.Archi = ((a->config->bits == 64) ? 64 : 0);
|
||||
disasm_obj.SecurityBlock = len;
|
||||
if (a->config->syntax == R_ASM_SYNTAX_ATT)
|
||||
disasm_obj.Options = 0x400;
|
||||
else disasm_obj.Options = 0;
|
||||
|
||||
aop->size = Disasm (&disasm_obj);
|
||||
r_asm_op_set_asm (aop, disasm_obj.CompleteInstr);
|
||||
|
||||
return aop->size;
|
||||
}
|
||||
|
||||
static RAsmPlugin r_asm_plugin_x86_bea = {
|
||||
.name = "x86.bea",
|
||||
.desc = "x86 BeaEngine disassembler plugin",
|
||||
.arch = "x86",
|
||||
.bits = 16 | 32 | 64,
|
||||
.disassemble = &disassemble,
|
||||
.license = "LGPL"
|
||||
};
|
||||
|
||||
#ifndef CORELIB
|
||||
struct r_lib_struct_t radare_plugin = {
|
||||
.type = R_LIB_TYPE_ASM,
|
||||
.data = &r_asm_plugin_x86_bea,
|
||||
.version = R2_VERSION
|
||||
};
|
||||
#endif
|
||||
@@ -1,60 +0,0 @@
|
||||
/* radare - LGPL - Copyright 2009-2018 - pancake, nibble */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <r_types.h>
|
||||
#include <r_lib.h>
|
||||
#include <r_asm.h>
|
||||
|
||||
#include "x86/ollyasm/disasm.h"
|
||||
|
||||
static int disassemble(RAsm *a, RAsmOp *op, const ut8 *buf, int len) {
|
||||
t_disasm disasm_obj;
|
||||
op->size = Disasm_olly (buf, len, a->pc, &disasm_obj, DISASM_FILE);
|
||||
r_asm_op_set_asm (op, disasm_obj.result);
|
||||
return op->size;
|
||||
}
|
||||
|
||||
static int assemble(RAsm *a, RAsmOp *op, const char *buf) {
|
||||
char buf_err[128];
|
||||
static t_asmmodel asm_obj;
|
||||
int attempt, constsize, oattempt = 0, oconstsize = 0, ret = 0, oret = 0xCAFE;
|
||||
|
||||
/* attempt == 0: First attempt */
|
||||
/* constsize == 0: Address constants and inmediate data of 16/32b */
|
||||
for (constsize = 0; constsize < 4; constsize++) {
|
||||
for (attempt = 0; ret > 0; attempt++) {
|
||||
ret = Assemble ((char*)buf, a->pc, &asm_obj, attempt, constsize, buf_err);
|
||||
if (ret > 0 && ret < oret) {
|
||||
oret = ret;
|
||||
oattempt = attempt;
|
||||
oconstsize = constsize;
|
||||
}
|
||||
}
|
||||
}
|
||||
op->size = R_MAX (0, Assemble ((char*)buf, a->pc, &asm_obj, oattempt, oconstsize, buf_err));
|
||||
if (op->size > 0) {
|
||||
r_asm_op_set_buf (op, (const ut8*)asm_obj.code, R_MIN (16, op->size));
|
||||
}
|
||||
return op->size;
|
||||
}
|
||||
|
||||
RAsmPlugin r_asm_plugin_x86_olly = {
|
||||
.name = "x86.olly",
|
||||
.license = "GPL2",
|
||||
.desc = "OllyDBG X86 disassembler",
|
||||
.arch = "x86",
|
||||
.bits = 32,
|
||||
.endian = R_SYS_ENDIAN_LITTLE,
|
||||
.disassemble = &disassemble,
|
||||
.assemble = &assemble,
|
||||
};
|
||||
|
||||
#ifndef CORELIB
|
||||
RLibStruct radare_plugin = {
|
||||
.type = R_LIB_TYPE_ASM,
|
||||
.data = &r_asm_plugin_x86_olly,
|
||||
.version = R2_VERSION
|
||||
};
|
||||
#endif
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,91 +0,0 @@
|
||||
/* radare - LGPL - Copyright 2009-2018 - pancake, nibble */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <r_types.h>
|
||||
#include <r_lib.h>
|
||||
#include <r_asm.h>
|
||||
#include "udis86/types.h"
|
||||
#include "udis86/extern.h"
|
||||
|
||||
// TODO : split into get/set... we need a way to create binary masks from asm buffers
|
||||
// -- move this shit into r_anal.. ??
|
||||
// -- delta, size, mode.. mode is for a->pc-5, register handling and things like this
|
||||
static bool modify(RAsm *a, ut8 *buf, int field, ut64 val) {
|
||||
ut32 val32 = (ut32)val;
|
||||
switch (buf[0]) {
|
||||
case 0x68: // push dword
|
||||
if (field == R_ASM_MOD_RAWVALUE || field == R_ASM_MOD_VALUE) {
|
||||
memcpy (buf+1, &val, sizeof (val32));
|
||||
}
|
||||
return 5;
|
||||
case 0xe8: // call
|
||||
if (field == R_ASM_MOD_RAWVALUE) {
|
||||
memcpy (buf+1, &val32, sizeof (val32));
|
||||
} else
|
||||
if (field == R_ASM_MOD_VALUE) {
|
||||
val32 = (ut32)(val-a->pc-5);
|
||||
memcpy (buf+1, &val32, sizeof (val32));
|
||||
}
|
||||
return 5;
|
||||
case 0xeb: // jmp short
|
||||
case 0x73: // jnz
|
||||
if (field == R_ASM_MOD_RAWVALUE) {
|
||||
buf[1] = (char)val;
|
||||
} else
|
||||
if (field == R_ASM_MOD_VALUE) {
|
||||
buf[1] = (char)(val-a->pc);
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int disassemble(RAsm *a, RAsmOp *op, const ut8 *buf, int len) {
|
||||
int opsize;
|
||||
static ud_t d = {0};
|
||||
static int osyntax = 0;
|
||||
if (!d.dis_mode)
|
||||
ud_init (&d);
|
||||
if (osyntax != a->config->syntax) {
|
||||
ud_set_syntax (&d, (a->config->syntax==R_ASM_SYNTAX_ATT)?
|
||||
UD_SYN_ATT: UD_SYN_INTEL);
|
||||
osyntax = a->config->syntax;
|
||||
}
|
||||
ud_set_input_buffer (&d, (uint8_t*) buf, len);
|
||||
ud_set_pc (&d, a->pc);
|
||||
ud_set_mode (&d, a->config->bits);
|
||||
opsize = ud_disassemble (&d);
|
||||
r_strbuf_set (&op->buf_asm, ud_insn_asm (&d));
|
||||
char *buf_asm = r_strbuf_get (&op->buf_asm);
|
||||
if (opsize<1 || strstr (buf_asm, "invalid"))
|
||||
opsize = 0;
|
||||
op->size = opsize;
|
||||
if (a->config->syntax == R_ASM_SYNTAX_JZ) {
|
||||
if (!strncmp (buf_asm, "je ", 3)) {
|
||||
memcpy (buf_asm, "jz", 2);
|
||||
} else if (!strncmp (buf_asm, "jne ", 4)) {
|
||||
memcpy (buf_asm, "jnz", 3);
|
||||
}
|
||||
}
|
||||
return opsize;
|
||||
}
|
||||
|
||||
RAsmPlugin r_asm_plugin_x86_udis = {
|
||||
.name = "x86.udis",
|
||||
.desc = "udis86 x86-16,32,64",
|
||||
.arch = "x86",
|
||||
.license = "BSD",
|
||||
.bits = 16 | 32 | 64,
|
||||
.endian = R_SYS_ENDIAN_LITTLE,
|
||||
.disassemble = &disassemble,
|
||||
.modify = &modify,
|
||||
};
|
||||
|
||||
#ifndef CORELIB
|
||||
RLibStruct radare_plugin = {
|
||||
.type = R_LIB_TYPE_ASM,
|
||||
.data = &r_asm_plugin_x86_udis,
|
||||
.version = R2_VERSION
|
||||
};
|
||||
#endif
|
||||
@@ -1,47 +0,0 @@
|
||||
/* radare - GPL3 - Copyright 2017 - mrexodia */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <r_types.h>
|
||||
#include <r_lib.h>
|
||||
#include <r_util.h>
|
||||
#include <r_asm.h>
|
||||
|
||||
#include "x86/zyan/include/Zydis/Zydis.h"
|
||||
|
||||
static int disassemble(RAsm *a, RAsmOp *aop, const ut8 *buf, int len) {
|
||||
static ZydisInstructionDecoder decr;
|
||||
static ZydisInstructionInfo info;
|
||||
static ZydisInstructionFormatter fmtr;
|
||||
|
||||
ZydisDecoderInitInstructionDecoder (&decr, a->config->bits);
|
||||
memset (&info, 0, sizeof (info));
|
||||
ZydisStatus st = ZydisDecoderDecodeInstruction (&decr, buf, len, a->pc, &info);
|
||||
if (ZYDIS_SUCCESS (st)) {
|
||||
ZydisFormatterInitInstructionFormatter (&fmtr, ZYDIS_FORMATTER_STYLE_INTEL);
|
||||
char str[128];
|
||||
str[0] = 0;
|
||||
ZydisFormatterFormatInstruction (&fmtr, &info, str, sizeof (str));
|
||||
r_strbuf_set (&aop->buf_asm, str);
|
||||
}
|
||||
|
||||
return aop->size = info.length;
|
||||
}
|
||||
|
||||
static RAsmPlugin r_asm_plugin_x86_zyan = {
|
||||
.name = "x86.zyan",
|
||||
.desc = "x86 Zyan Disassembler Engine plugin",
|
||||
.arch = "x86",
|
||||
.bits = 16 | 32 | 64,
|
||||
.disassemble = &disassemble,
|
||||
.license = "MIT"
|
||||
};
|
||||
|
||||
#ifndef CORELIB
|
||||
RLibStruct radare_plugin = {
|
||||
.type = R_LIB_TYPE_ASM,
|
||||
.data = &r_asm_plugin_x86_zyan,
|
||||
.version = R2_VERSION
|
||||
};
|
||||
#endif
|
||||
@@ -1,38 +0,0 @@
|
||||
/* radare - LGPL - Copyright 2012-2013 - pancake */
|
||||
|
||||
#include <r_types.h>
|
||||
#include <r_util.h>
|
||||
#include <r_lib.h>
|
||||
#include <r_asm.h>
|
||||
|
||||
#include "../arch/z80/z80.c"
|
||||
|
||||
static int do_assemble(RAsm *a, RAsmOp *op, const char *buf) {
|
||||
return op->size = z80asm (op->buf, buf);
|
||||
}
|
||||
|
||||
static int do_disassemble(RAsm *a, RAsmOp *op, const ut8 *buf, int len) {
|
||||
int dlen = z80dis (0, buf, op->buf_asm, len);
|
||||
if (dlen<0) dlen = 0;
|
||||
op->size = dlen;
|
||||
return op->size;
|
||||
}
|
||||
|
||||
RAsmPlugin r_asm_plugin_z80 = {
|
||||
.name = "z80",
|
||||
.desc = "Zilog Z80",
|
||||
.license = "NC-GPL2", //NON-COMMERCIAL",
|
||||
.arch = "z80",
|
||||
.bits = 8,
|
||||
.endian = R_SYS_ENDIAN_NONE,
|
||||
.disassemble = &do_disassemble,
|
||||
.assemble = &do_assemble,
|
||||
};
|
||||
|
||||
#ifndef CORELIB
|
||||
struct r_lib_struct_t radare_plugin = {
|
||||
.type = R_LIB_TYPE_ASM,
|
||||
.data = &r_asm_plugin_z80,
|
||||
.version = R2_VERSION
|
||||
};
|
||||
#endif
|
||||
@@ -1,34 +0,0 @@
|
||||
/* radare - LGPL - Copyright 2012-2020 - pancake */
|
||||
|
||||
#include <r_types.h>
|
||||
#include <r_util.h>
|
||||
#include <r_lib.h>
|
||||
#include <r_asm.h>
|
||||
#include "../arch/z80_nc/disasm.c"
|
||||
|
||||
static int do_disassemble(RAsm *a, RAsmOp *op, const ut8 *buf, int len) {
|
||||
char str[128];
|
||||
int dlen = z80dis (0, buf, str, len);
|
||||
r_strbuf_set (&op->buf_asm, str);
|
||||
if (dlen<0) dlen = 0;
|
||||
op->size = dlen;
|
||||
return op->size;
|
||||
}
|
||||
|
||||
RAsmPlugin r_asm_plugin_z80 = {
|
||||
.name = "z80.nc",
|
||||
.desc = "Zilog Z80 non-commerical",
|
||||
.license = "NC-GPL2", //NON-COMMERCIAL",
|
||||
.arch = "z80",
|
||||
.bits = 8,
|
||||
.endian = R_SYS_ENDIAN_NONE,
|
||||
.disassemble = &do_disassemble,
|
||||
};
|
||||
|
||||
#ifndef CORELIB
|
||||
RLibStruct radare_plugin = {
|
||||
.type = R_LIB_TYPE_ASM,
|
||||
.data = &r_asm_plugin_z80,
|
||||
.version = R2_VERSION
|
||||
};
|
||||
#endif
|
||||
@@ -1,12 +1,12 @@
|
||||
OBJ_ATOMBIOS=asm_atombios.o
|
||||
OBJ_ATOMBIOS=arch_atombios.o
|
||||
OBJ_ATOMBIOS+=../arch/atombios/atombios.o
|
||||
|
||||
TARGET_ATOMBIOS=asm_atombios.${LIBEXT}
|
||||
TARGET_ATOMBIOS=arch_atombios.${LIBEXT}
|
||||
STATIC_OBJ+=${OBJ_ATOMBIOS}
|
||||
|
||||
$(OBJ_ATOMBIOS): %.o : %.c
|
||||
arch_atombios.o: arch_atombios.c
|
||||
$(CC) -c $(CFLAGS) $< -o $@
|
||||
|
||||
ALL_TARGETS+=${TARGET_ATOMBIOS}
|
||||
${TARGET_ATOMBIOS}: ${OBJ_ATOMBIOS}
|
||||
${CC} -g $(call libname,asm_atombios) ${LDFLAGS} ${CFLAGS} -o ${TARGET_ATOMBIOS} ${OBJ_ATOMBIOS} -lr_util
|
||||
${CC} -g $(call libname,arch_atombios) ${LDFLAGS} ${CFLAGS} -o ${TARGET_ATOMBIOS} ${OBJ_ATOMBIOS}
|
||||
+3
-3
@@ -1,9 +1,9 @@
|
||||
OBJ_BA2=asm_ba2.o
|
||||
OBJ_BA2=arch_ba2.o
|
||||
CFLAGS_BA2=$(CFLAGS)
|
||||
CFLAGS_BA2+=-I../arch/ba2/
|
||||
|
||||
STATIC_OBJ+=${OBJ_BA2}
|
||||
TARGET_BA2=asm_ba2.${LIBEXT}
|
||||
TARGET_BA2=arch_ba2.${LIBEXT}
|
||||
|
||||
ALL_TARGETS+=${TARGET_BA2}
|
||||
|
||||
@@ -11,4 +11,4 @@ $(OBJ_BA2): %.o : %.c
|
||||
$(CC) -c $(CFLAGS_BA2) $< -o $@
|
||||
|
||||
${TARGET_BA2}: ${OBJ_BA2}
|
||||
${CC} -lr_util ${CFLAGS_BA2} -o ${TARGET_BA2} ${OBJ_BA2}
|
||||
${CC} ${LDFLAGS} ${CFLAGS_BA2} -o ${TARGET_BA2} ${OBJ_BA2}
|
||||
@@ -1,13 +1,13 @@
|
||||
OBJ_DCPU16=asm_dcpu16.o
|
||||
OBJ_DCPU16=arch_dcpu16.o
|
||||
#OBJ_DCPU16+=../arch/dcpu16/asm.o
|
||||
#OBJ_DCPU16+=../arch/dcpu16/dis.o
|
||||
|
||||
STATIC_OBJ+=${OBJ_DCPU16}
|
||||
TARGET_DCPU16=asm_dcpu16.${EXT_SO}
|
||||
TARGET_DCPU16=arch_dcpu16.${EXT_SO}
|
||||
|
||||
ifeq ($(WITHPIC),1)
|
||||
ALL_TARGETS+=${TARGET_DCPU16}
|
||||
|
||||
${TARGET_DCPU16}: ${OBJ_DCPU16}
|
||||
${CC} $(call libname,asm_dcpu16) ${LDFLAGS} ${CFLAGS} -o asm_dcpu16.${EXT_SO} ${OBJ_DCPU16}
|
||||
${CC} $(call libname,arch_dcpu16) ${LDFLAGS} ${CFLAGS} -o ${TARGET_DCPU16} ${OBJ_DCPU16}
|
||||
endif
|
||||
@@ -1,10 +1,10 @@
|
||||
OBJ_M68K=asm_m68k_net.o
|
||||
OBJ_M68K=arch_m68k_net.o
|
||||
OBJ_M68K+=../arch/m68k/m68k_disasm/m68k_disasm.o
|
||||
|
||||
STATIC_OBJ+=${OBJ_M68K}
|
||||
TARGET_M68K=asm_m68k_net.${LIBEXT}
|
||||
TARGET_M68K=arch_m68k_net.${LIBEXT}
|
||||
|
||||
ALL_TARGETS+=${TARGET_M68K}
|
||||
|
||||
${TARGET_M68K}: ${OBJ_M68K}
|
||||
${CC} -shared ${CFLAGS} -o asm_m68k_net.${LIBEXT} ${OBJ_M68K} ${LDFLAGS}
|
||||
${CC} -shared ${CFLAGS} -o ${TARGET_M68K} ${OBJ_M68K} ${LDFLAGS}
|
||||
@@ -1,8 +1,8 @@
|
||||
OBJ_MC6809=asm_mc6809.o
|
||||
OBJ_MC6809=arch_mc6809.o
|
||||
|
||||
STATIC_OBJ+=${OBJ_MC6809}
|
||||
|
||||
TARGET_MC6809=asm_mc6809.${LIBEXT}
|
||||
TARGET_MC6809=arch_mc6809.${LIBEXT}
|
||||
|
||||
ALL_TARGETS+=${TARGET_MC6809}
|
||||
|
||||
@@ -10,5 +10,5 @@ $(OBJ_MC6809): %.o : %.c
|
||||
$(CC) -c $(CFLAGS) $< -o $@
|
||||
|
||||
${TARGET_MC6809}: ${OBJ_MC6809}
|
||||
${CC} $(call libname,asm_mc6809) ${LDFLAGS} \
|
||||
${CFLAGS} -o asm_mc6809.${LIBEXT} ${OBJ_MC6809}
|
||||
${CC} $(call libname,arch_mc6809) ${LDFLAGS} \
|
||||
${CFLAGS} -o ${TARGET_MC6809} ${OBJ_MC6809}
|
||||
+3
-5
@@ -1,15 +1,13 @@
|
||||
OBJ_MSIL=asm_msil.o
|
||||
OBJ_MSIL=arch_msil.o
|
||||
#OBJ_MSIL+=../arch/msil/demsil.o
|
||||
|
||||
STATIC_OBJ+=${OBJ_MSIL}
|
||||
TARGET_MSIL=asm_msil.${LIBEXT}
|
||||
TARGET_MSIL=arch_msil.${LIBEXT}
|
||||
|
||||
#ifeq ($(WITHPIC),1)
|
||||
ALL_TARGETS+=${TARGET_MSIL}
|
||||
|
||||
$(OBJ_MSIL): %.o : %.c
|
||||
$(CC) -c $(CFLAGS) $< -o $@
|
||||
|
||||
${TARGET_MSIL}: ${OBJ_MSIL}
|
||||
${CC} $(call libname,asm_msil) ${LDFLAGS} ${CFLAGS} -o asm_msil.${LIBEXT} ${OBJ_MSIL}
|
||||
#endif
|
||||
${CC} $(call libname,arch_msil) ${LDFLAGS} ${CFLAGS} -o ${TARGET_MSIL} ${OBJ_MSIL}
|
||||
@@ -1,9 +1,14 @@
|
||||
OBJ_PPC_DISASM+=../arch/ppc/ppc_disasm/ppc_disasm.o asm_ppc_disasm.o
|
||||
OBJ_PPC_DISASM=arch_ppc_disasm.o
|
||||
OBJ_PPC_DISASM+=../arch/ppc/ppc_disasm/ppc_disasm.o
|
||||
|
||||
STATIC_OBJ+=${OBJ_PPC_DISASM}
|
||||
TARGET_PPC_DISASM=asm_ppc_disasm.${LIBEXT}
|
||||
TARGET_PPC_DISASM=arch_ppc_disasm.${LIBEXT}
|
||||
|
||||
ALL_TARGETS+=${TARGET_PPC_DISASM}
|
||||
|
||||
${TARGET_PPC_DISASM}: ${OBJ_PPC_DISASM}
|
||||
${CC} ${CFLAGS} -o asm_ppc_disasm.${LIBEXT} ${OBJ_PPC_DISASM} ${LDFLAGS}
|
||||
${CC} ${CFLAGS} -o ${TARGET_PPC_DISASM} ${OBJ_PPC_DISASM} ${LDFLAGS}
|
||||
|
||||
# Keep older r2pm recipes working until they use the arch_ target.
|
||||
asm_ppc_disasm.${LIBEXT}: ${TARGET_PPC_DISASM}
|
||||
cp -f ${TARGET_PPC_DISASM} $@
|
||||
@@ -1,10 +1,10 @@
|
||||
OBJ_PSOSVM=asm_psosvm.o
|
||||
OBJ_PSOSVM=arch_psosvm.o
|
||||
OBJ_PSOSVM+=../arch/psosvm/vmas/vmas.o
|
||||
|
||||
STATIC_OBJ+=${OBJ_PSOSVM}
|
||||
TARGET_PSOSVM=asm_psosvm.${LIBEXT}
|
||||
TARGET_PSOSVM=arch_psosvm.${LIBEXT}
|
||||
|
||||
ALL_TARGETS+=${TARGET_PSOSVM}
|
||||
|
||||
${TARGET_PSOSVM}: ${OBJ_PSOSVM}
|
||||
${CC} $(call libname,asm_psosvm) ${LDFLAGS} ${CFLAGS} -o asm_psosvm.${LIBEXT} ${OBJ_PSOSVM}
|
||||
${CC} $(call libname,arch_psosvm) ${LDFLAGS} ${CFLAGS} -o ${TARGET_PSOSVM} ${OBJ_PSOSVM}
|
||||
@@ -1,9 +1,9 @@
|
||||
OBJ_SPC700=asm_spc700.o
|
||||
OBJ_SPC700=arch_spc700.o
|
||||
|
||||
STATIC_OBJ+=${OBJ_SPC700}
|
||||
TARGET_SPC700=asm_spc700.${LIBEXT}
|
||||
TARGET_SPC700=arch_spc700.${LIBEXT}
|
||||
|
||||
ALL_TARGETS+=${TARGET_SPC700}
|
||||
|
||||
${TARGET_SPC700}: ${OBJ_SPC700}
|
||||
${CC} $(call libname,asm_spc700) ${CFLAGS} -o ${TARGET_SPC700} ${OBJ_SPC700} -lr_asm -lr_util
|
||||
${CC} $(call libname,arch_spc700) ${LDFLAGS} ${CFLAGS} -o ${TARGET_SPC700} ${OBJ_SPC700}
|
||||
+3
-3
@@ -1,11 +1,11 @@
|
||||
OBJ_SWF=asm_swf.o
|
||||
OBJ_SWF=arch_swf.o
|
||||
OBJ_SWF+=../arch/swf/swfdis.o
|
||||
|
||||
STATIC_OBJ+=${OBJ_SWF}
|
||||
TARGET_SWF=asm_swf.$(LIBEXT)
|
||||
TARGET_SWF=arch_swf.$(LIBEXT)
|
||||
|
||||
ALL_TARGETS+=${TARGET_SWF}
|
||||
CFLAGS_SWF=-I../arch/swf
|
||||
|
||||
${TARGET_SWF}: ${OBJ_SWF}
|
||||
${CC} ${CFLAGS} ${CFLAGS_SWF} $(LDFLAGS) -o ${TARGET_SWF} ${OBJ_SWF} -lr_util
|
||||
${CC} ${CFLAGS} ${CFLAGS_SWF} $(LDFLAGS) -o ${TARGET_SWF} ${OBJ_SWF}
|
||||
+28
-16
@@ -1,18 +1,13 @@
|
||||
OBJ_VC4=arch_vc4.o
|
||||
OBJ_VC4+=../arch/vc4/vc4-dis.o
|
||||
OBJ_VC4+=../arch/vc4/vc4-asm.o
|
||||
OBJ_VC4+=../arch/vc4/vc4-desc.o
|
||||
OBJ_VC4+=../arch/vc4/vc4-ibld.o
|
||||
OBJ_VC4+=../arch/vc4/vc4-opc.o
|
||||
OBJ_VC4+=../arch/vc4/cgen-bitset.o
|
||||
OBJ_VC4+=../arch/vc4/cgen-dis.o
|
||||
OBJ_VC4+=../arch/vc4/cgen-asm.o
|
||||
OBJ_VC4+=../arch/vc4/cgen-opc.o
|
||||
OBJ_VC4+=../arch/vc4/libvc4/eval.o
|
||||
OBJ_VC4+=../arch/vc4/libvc4/decode.o
|
||||
OBJ_VC4+=../arch/vc4/libvc4/vc4_decode.o
|
||||
OBJ_VC4+=../arch/vc4/libvc4/vc4_arch.o
|
||||
OBJ_VC4+=../arch/vc4/libvc4/vc4_util.o
|
||||
OBJ_VC4+=vc4-dis.o
|
||||
OBJ_VC4+=vc4-asm.o
|
||||
OBJ_VC4+=vc4-desc.o
|
||||
OBJ_VC4+=vc4-ibld.o
|
||||
OBJ_VC4+=vc4-opc.o
|
||||
OBJ_VC4+=cgen-bitset.o
|
||||
OBJ_VC4+=cgen-dis.o
|
||||
OBJ_VC4+=cgen-asm.o
|
||||
OBJ_VC4+=cgen-opc.o
|
||||
|
||||
SRC_VC4=$(patsubst %.o, %.c, $(OBJ_VC4))
|
||||
|
||||
@@ -20,14 +15,31 @@ CFLAGS_VC4=$(R2_CFLAGS)
|
||||
CFLAGS_VC4+=-g -I$(TOP)/shlr
|
||||
CFLAGS_VC4+=-Wall -shared -fPIC ${LDFLAGS_LIB}
|
||||
|
||||
CFLAGS_VC4+=-I../arch/vc4/ -I../arch/vc4/libvc4/ -I../arch/vc4/include/ -I../arch/vc4/include/opcode/ -I../arch/include/
|
||||
CFLAGS_VC4+=-I../arch/vc4/ -I../arch/vc4/include/ -I../arch/vc4/include/opcode/ -I../arch/include/
|
||||
CFLAGS+=$(CFLAGS_VC4)
|
||||
|
||||
STATIC_OBJ+=${OBJ_VC4}
|
||||
TARGET_VC4=arch_vc4.${LIBEXT}
|
||||
|
||||
ALL_TARGETS+=${TARGET_VC4}
|
||||
|
||||
$(OBJ_VC4): %.o : %.c
|
||||
vc4-dis.o: ../arch/vc4/vc4-dis.c
|
||||
$(CC) -c $(CFLAGS_VC4) $< -o $@
|
||||
vc4-asm.o: ../arch/vc4/vc4-asm.c
|
||||
$(CC) -c $(CFLAGS_VC4) $< -o $@
|
||||
vc4-desc.o: ../arch/vc4/vc4-desc.c
|
||||
$(CC) -c $(CFLAGS_VC4) $< -o $@
|
||||
vc4-ibld.o: ../arch/vc4/vc4-ibld.c
|
||||
$(CC) -c $(CFLAGS_VC4) $< -o $@
|
||||
vc4-opc.o: ../arch/vc4/vc4-opc.c
|
||||
$(CC) -c $(CFLAGS_VC4) $< -o $@
|
||||
cgen-bitset.o: ../arch/vc4/cgen-bitset.c
|
||||
$(CC) -c $(CFLAGS_VC4) $< -o $@
|
||||
cgen-dis.o: ../arch/vc4/cgen-dis.c
|
||||
$(CC) -c $(CFLAGS_VC4) $< -o $@
|
||||
cgen-asm.o: ../arch/vc4/cgen-asm.c
|
||||
$(CC) -c $(CFLAGS_VC4) $< -o $@
|
||||
cgen-opc.o: ../arch/vc4/cgen-opc.c
|
||||
$(CC) -c $(CFLAGS_VC4) $< -o $@
|
||||
|
||||
${TARGET_VC4}: ${OBJ_VC4}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
OBJ_X86_BEA=asm_x86_bea.o
|
||||
OBJ_X86_BEA=arch_x86_bea.o
|
||||
OBJ_X86_BEA+=../arch/x86/bea/BeaEngine.o
|
||||
|
||||
STATIC_OBJ+=${OBJ_X86_BEA}
|
||||
TARGET_X86_BEA=asm_x86_bea.$(LIBEXT)
|
||||
TARGET_X86_BEA=arch_x86_bea.$(LIBEXT)
|
||||
|
||||
ALL_TARGETS+=${TARGET_X86_BEA}
|
||||
CFLAGS_BEA=$(CFLAGS)
|
||||
@@ -11,7 +11,7 @@ CFLAGS_BEA+=-I../arch/x86/bea/src
|
||||
CFLAGS_BEA+=-I../arch/x86/bea/include
|
||||
CFLAGS_BEA+=-DUint64=uint64_t
|
||||
|
||||
$(OBJ_X86_BEA): %.o : %.c
|
||||
arch_x86_bea.o: arch_x86_bea.c
|
||||
$(CC) -c $(CFLAGS_BEA) $< -o $@
|
||||
|
||||
${TARGET_X86_BEA}: ${OBJ_X86_BEA}
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
OBJ_X86_OLLY=asm_x86_olly.o
|
||||
OBJ_X86_OLLY=arch_x86_olly.o
|
||||
OBJ_X86_OLLY+=../arch/x86/ollyasm/disasm.o
|
||||
OBJ_X86_OLLY+=../arch/x86/ollyasm/asmserv.o
|
||||
OBJ_X86_OLLY+=../arch/x86/ollyasm/assembl.o
|
||||
|
||||
STATIC_OBJ+=${OBJ_X86_OLLY}
|
||||
TARGET_X86_OLLY=asm_x86_olly.${LIBEXT}
|
||||
TARGET_X86_OLLY=arch_x86_olly.${LIBEXT}
|
||||
|
||||
ALL_TARGETS+=${TARGET_X86_OLLY}
|
||||
|
||||
$(OBJ_X86_OLLY): %.o : %.c
|
||||
arch_x86_olly.o: arch_x86_olly.c
|
||||
$(CC) -c $(CFLAGS) $< -o $@
|
||||
|
||||
${TARGET_X86_OLLY}: ${OBJ_X86_OLLY}
|
||||
${CC} $(call libname,asm_x86_olly) ${LDFLAGS} ${CFLAGS} -o ${TARGET_X86_OLLY} ${OBJ_X86_OLLY}
|
||||
${CC} $(call libname,arch_x86_olly) ${LDFLAGS} ${CFLAGS} -o ${TARGET_X86_OLLY} ${OBJ_X86_OLLY}
|
||||
@@ -1,7 +1,7 @@
|
||||
OBJ_X86_TAB=asm_x86_tab.o
|
||||
OBJ_X86_TAB=arch_x86_tab.o
|
||||
|
||||
STATIC_OBJ+=${OBJ_X86_TAB}
|
||||
TARGET_X86_TAB=asm_x86_tab.$(LIBEXT)
|
||||
TARGET_X86_TAB=arch_x86_tab.$(LIBEXT)
|
||||
|
||||
ALL_TARGETS+=${TARGET_X86_TAB}
|
||||
|
||||
@@ -9,4 +9,4 @@ $(OBJ_X86_TAB): %.o : %.c
|
||||
$(CC) -c $(CFLAGS) $< -o $@
|
||||
|
||||
${TARGET_X86_TAB}: ${OBJ_X86_TAB}
|
||||
${CC} $(call libname,asm_x86_tab) ${LDFLAGS} ${CFLAGS} -o ${TARGET_X86_TAB} ${OBJ_X86_TAB}
|
||||
${CC} $(call libname,arch_x86_tab) ${LDFLAGS} ${CFLAGS} -o ${TARGET_X86_TAB} ${OBJ_X86_TAB}
|
||||
@@ -1,12 +1,11 @@
|
||||
CFLAGS_UDIS86=$(CFLAGS)
|
||||
CFLAGS_UDIS86+=-I../arch/x86
|
||||
|
||||
|
||||
OBJ_X86_UDIS86=asm_x86_udis.o
|
||||
OBJ_X86_UDIS86=arch_x86_udis.o
|
||||
SRC_X86_UDIS86=../arch/x86/udis86/*.c
|
||||
|
||||
STATIC_OBJ+=${OBJ_X86_UDIS86}
|
||||
TARGET_X86_UDIS86=asm_x86_udis.${LIBEXT}
|
||||
TARGET_X86_UDIS86=arch_x86_udis.${LIBEXT}
|
||||
|
||||
ALL_TARGETS+=${TARGET_X86_UDIS86}
|
||||
|
||||
@@ -14,4 +13,4 @@ $(OBJ_X86_UDIS86): %.o : %.c
|
||||
$(CC) -c $(CFLAGS_UDIS86) $< -o $@
|
||||
|
||||
${TARGET_X86_UDIS86}: ${OBJ_X86_UDIS86}
|
||||
${CC} $(call libname,asm_x86_udis) ${LDFLAGS} ${CFLAGS_UDIS86} -o ${TARGET_X86_UDIS86} ${OBJ_X86_UDIS86} ${SRC_X86_UDIS86}
|
||||
${CC} $(call libname,arch_x86_udis) ${LDFLAGS} ${CFLAGS_UDIS86} -o ${TARGET_X86_UDIS86} ${OBJ_X86_UDIS86} ${SRC_X86_UDIS86}
|
||||
+25
-10
@@ -1,21 +1,36 @@
|
||||
CFLAGS_ZYAN=$(CFLAGS)
|
||||
CFLAGS_ZYAN+=-I../arch/x86/zyan/include
|
||||
|
||||
OBJ_X86_ZYAN=asm_x86_zyan.o
|
||||
OBJ_X86_ZYAN+=../arch/x86/zyan/src/Decoder.o
|
||||
OBJ_X86_ZYAN+=../arch/x86/zyan/src/Formatter.o
|
||||
OBJ_X86_ZYAN+=../arch/x86/zyan/src/InstructionTable.o
|
||||
OBJ_X86_ZYAN+=../arch/x86/zyan/src/Mnemonic.o
|
||||
OBJ_X86_ZYAN+=../arch/x86/zyan/src/Register.o
|
||||
OBJ_X86_ZYAN+=../arch/x86/zyan/src/Utils.o
|
||||
OBJ_X86_ZYAN+=../arch/x86/zyan/src/Zydis.o
|
||||
OBJ_X86_ZYAN=arch_x86_zyan.o
|
||||
OBJ_X86_ZYAN+=zyan_Decoder.o
|
||||
OBJ_X86_ZYAN+=zyan_Formatter.o
|
||||
OBJ_X86_ZYAN+=zyan_InstructionTable.o
|
||||
OBJ_X86_ZYAN+=zyan_Mnemonic.o
|
||||
OBJ_X86_ZYAN+=zyan_Register.o
|
||||
OBJ_X86_ZYAN+=zyan_Utils.o
|
||||
OBJ_X86_ZYAN+=zyan_Zydis.o
|
||||
|
||||
STATIC_OBJ+=${OBJ_X86_ZYAN}
|
||||
TARGET_X86_ZYAN=asm_x86_zyan.$(LIBEXT)
|
||||
TARGET_X86_ZYAN=arch_x86_zyan.$(LIBEXT)
|
||||
ALL_TARGETS+=${TARGET_X86_ZYAN}
|
||||
|
||||
$(OBJ_X86_ZYAN): %.o : %.c
|
||||
arch_x86_zyan.o: arch_x86_zyan.c
|
||||
$(CC) -c $(CFLAGS_ZYAN) $< -o $@
|
||||
|
||||
${TARGET_X86_ZYAN}: ${OBJ_X86_ZYAN}
|
||||
${CC} ${LDFLAGS} ${CFLAGS_ZYAN} -o ${TARGET_X86_ZYAN} ${OBJ_X86_ZYAN}
|
||||
|
||||
zyan_Decoder.o: ../arch/x86/zyan/src/Decoder.c
|
||||
$(CC) -c $(CFLAGS_ZYAN) -o $@ $<
|
||||
zyan_Formatter.o: ../arch/x86/zyan/src/Formatter.c
|
||||
$(CC) -c $(CFLAGS_ZYAN) -o $@ $<
|
||||
zyan_InstructionTable.o: ../arch/x86/zyan/src/InstructionTable.c
|
||||
$(CC) -c $(CFLAGS_ZYAN) -o $@ $<
|
||||
zyan_Mnemonic.o: ../arch/x86/zyan/src/Mnemonic.c
|
||||
$(CC) -c $(CFLAGS_ZYAN) -o $@ $<
|
||||
zyan_Register.o: ../arch/x86/zyan/src/Register.c
|
||||
$(CC) -c $(CFLAGS_ZYAN) -o $@ $<
|
||||
zyan_Utils.o: ../arch/x86/zyan/src/Utils.c
|
||||
$(CC) -c $(CFLAGS_ZYAN) -o $@ $<
|
||||
zyan_Zydis.o: ../arch/x86/zyan/src/Zydis.c
|
||||
$(CC) -c $(CFLAGS_ZYAN) -o $@ $<
|
||||
+3
-3
@@ -1,11 +1,11 @@
|
||||
OBJ_Z80=asm_z80.o
|
||||
OBJ_Z80=arch_z80.o
|
||||
|
||||
STATIC_OBJ+=${OBJ_Z80}
|
||||
TARGET_Z80=asm_z80.${LIBEXT}
|
||||
TARGET_Z80=arch_z80.${LIBEXT}
|
||||
|
||||
ifeq ($(WITHPIC),1)
|
||||
ALL_TARGETS+=${TARGET_Z80}
|
||||
|
||||
${TARGET_Z80}: ${OBJ_Z80}
|
||||
${CC} $(call libname,asm_z80) ${LDFLAGS} ${CFLAGS} -o ${TARGET_Z80} ${OBJ_Z80} -lr_util
|
||||
${CC} $(call libname,arch_z80) ${LDFLAGS} ${CFLAGS} -o ${TARGET_Z80} ${OBJ_Z80}
|
||||
endif
|
||||
@@ -1,7 +1,7 @@
|
||||
OBJ_Z80=asm_z80_nc.o
|
||||
OBJ_Z80=arch_z80_nc.o
|
||||
|
||||
STATIC_OBJ+=${OBJ_Z80}
|
||||
TARGET_Z80=asm_z80_nc.${LIBEXT}
|
||||
TARGET_Z80=arch_z80_nc.${LIBEXT}
|
||||
|
||||
ALL_TARGETS+=${TARGET_Z80}
|
||||
|
||||
@@ -9,4 +9,4 @@ $(OBJ_Z80): %.o : %.c
|
||||
$(CC) -c $(CFLAGS) $< -o $@
|
||||
|
||||
${TARGET_Z80}: ${OBJ_Z80}
|
||||
${CC} $(call libname,asm_z80_nc) ${CFLAGS} -o ${TARGET_Z80} ${OBJ_Z80} -lr_util
|
||||
${CC} $(call libname,arch_z80_nc) ${CFLAGS} -o ${TARGET_Z80} ${OBJ_Z80}
|
||||
@@ -1,4 +1,4 @@
|
||||
/* radare - LGPL - Copyright 2023 - pancake */
|
||||
/* radare - LGPL - Copyright 2023-2025 - pancake */
|
||||
|
||||
#include <r_bin.h>
|
||||
enum {
|
||||
@@ -52,7 +52,9 @@ static RBinInfo *info(RBinFile *bf) {
|
||||
}
|
||||
|
||||
static bool check(RBinFile *hello, RBuffer *buf) {
|
||||
r_return_val_if_fail (buf, false);
|
||||
if (!buf) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ut8 tmp[64] = {0};
|
||||
int read_length = r_buf_read_at (buf, 0, tmp, sizeof (tmp));
|
||||
@@ -82,7 +84,7 @@ static bool check(RBinFile *hello, RBuffer *buf) {
|
||||
break;
|
||||
}
|
||||
R_LOG_DEBUG ("KeyNameLen: %d", textlen);
|
||||
char *text = r_str_ndup (data + 8, textlen);
|
||||
char *text = r_str_ndup ((const char *)(data + 8), textlen);
|
||||
R_LOG_INFO ("KeyName: %s", text);
|
||||
free (text);
|
||||
pos += textlen;
|
||||
@@ -95,7 +97,7 @@ static bool check(RBinFile *hello, RBuffer *buf) {
|
||||
ut64 vlen = r_read_le64 (data + 8 + textlen + 4);
|
||||
R_LOG_DEBUG ("KeyValueSize: %d", vlen);
|
||||
vlen = R_MIN (vlen, sizeof (data) - 16 + textlen + 4);
|
||||
char *text = r_str_ndup (data + 8 + textlen + 4 + 8, vlen);
|
||||
char *text = r_str_ndup ((const char *)(data + 8 + textlen + 4 + 8), vlen);
|
||||
R_LOG_INFO ("KeyValue: %s", text);
|
||||
free (text);
|
||||
pos += vlen + 8;
|
||||
@@ -140,7 +142,7 @@ static bool check(RBinFile *hello, RBuffer *buf) {
|
||||
R_LOG_ERROR ("Invalid tensor name");
|
||||
break;
|
||||
}
|
||||
char *text = r_str_ndup (data + 8, textlen);
|
||||
char *text = r_str_ndup ((const char *)(data + 8), textlen);
|
||||
R_LOG_INFO ("Tensor[%d]: %s", i, text);
|
||||
free (text);
|
||||
pos += textlen;
|
||||
@@ -152,23 +154,23 @@ static bool check(RBinFile *hello, RBuffer *buf) {
|
||||
}
|
||||
|
||||
static RList *entries(RBinFile *hello) {
|
||||
r_return_val_if_fail (hello, NULL);
|
||||
if (!hello) {
|
||||
return NULL;
|
||||
}
|
||||
RList *ret = r_list_newf (free);
|
||||
if (ret) {
|
||||
RBinAddr *ptr = R_NEW0 (RBinAddr);
|
||||
if (ptr) {
|
||||
ptr->paddr = ptr->vaddr = 0;
|
||||
r_list_append (ret, ptr);
|
||||
}
|
||||
ptr->paddr = ptr->vaddr = 0;
|
||||
r_list_append (ret, ptr);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
RBinPlugin r_bin_plugin_hello = {
|
||||
.meta = {
|
||||
.name = "hello",
|
||||
.desc = "hello world for rbin",
|
||||
.license = "LGPL3",
|
||||
.name = "gguf",
|
||||
.desc = "GGUF bin parser",
|
||||
.license = "MIT",
|
||||
},
|
||||
.load = &load,
|
||||
.destroy = &destroy,
|
||||
|
||||
@@ -9,7 +9,7 @@ int sq_mount(RFSRoot *root, ut64 delta);
|
||||
int sq_dir(const char *path, SquashDirCallback cb, void *user);
|
||||
unsigned char *sq_cat(const char *path, int *len);
|
||||
|
||||
static RFSFile *fs_squash_open(RFSRoot *root, const char *path) {
|
||||
static RFSFile *fs_squash_open(RFSRoot *root, const char *path, bool create) {
|
||||
int size = 0;
|
||||
unsigned char *buf = sq_cat (path, &size);
|
||||
if (buf) {
|
||||
@@ -27,15 +27,15 @@ static RFSFile *fs_squash_open(RFSRoot *root, const char *path) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool fs_squash_read(RFSFile *file, ut64 addr, int len) {
|
||||
static int fs_squash_read(RFSFile *file, ut64 addr, int len) {
|
||||
int size = 0;
|
||||
unsigned char *buf = sq_cat (file->path, &size);
|
||||
if (buf) {
|
||||
file->data = buf;
|
||||
// file->size = size;
|
||||
return file;
|
||||
return size;
|
||||
}
|
||||
return NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void fs_squash_close(RFSFile *file) {
|
||||
@@ -88,7 +88,7 @@ static RList *fs_squash_dir(RFSRoot *root, const char *path, int view /*ignored*
|
||||
return list;
|
||||
}
|
||||
|
||||
static int fs_squash_mount(RFSRoot *root) {
|
||||
static bool fs_squash_mount(RFSRoot *root) {
|
||||
root->ptr = NULL;
|
||||
return sq_mount (root, root->delta);
|
||||
}
|
||||
@@ -98,9 +98,17 @@ static void fs_squash_umount(RFSRoot *root) {
|
||||
}
|
||||
|
||||
RFSPlugin r_fs_plugin_io = {
|
||||
#if 1
|
||||
.meta = {
|
||||
.name = "squashfs",
|
||||
.desc = "SquashFS filesystem (XZ + LZMA)",
|
||||
.license = "LGPL-3.0-only",
|
||||
},
|
||||
#else
|
||||
.name = "squashfs",
|
||||
.desc = "SquashFS filesystem (XZ + LZMA)",
|
||||
.license = "GPL",
|
||||
.license = "LGPL-3.0-only",
|
||||
#endif
|
||||
.open = fs_squash_open,
|
||||
.read = fs_squash_read,
|
||||
.close = fs_squash_close,
|
||||
|
||||
@@ -1571,8 +1571,7 @@ int read_super(char *source) {
|
||||
memcpy(&sBlk_3, &sblk, sizeof(squashfs_super_block_3));
|
||||
swap = 1;
|
||||
} else {
|
||||
ERROR("Can't find a SQUASHFS superblock on %s\n",
|
||||
source);
|
||||
// ERROR("Can't find a SQUASHFS superblock on %s\n", source);
|
||||
goto failed_mount;
|
||||
}
|
||||
}
|
||||
@@ -1649,23 +1648,6 @@ failed_mount:
|
||||
}
|
||||
|
||||
|
||||
struct pathname *process_extract_files(struct pathname *path, char *filename)
|
||||
{
|
||||
FILE *fd;
|
||||
char name[16384];
|
||||
|
||||
fd = fopen(filename, "r");
|
||||
if(fd == NULL)
|
||||
EXIT_UNSQUASH("Could not open %s, because %s\n", filename,
|
||||
strerror(errno));
|
||||
|
||||
while(fscanf(fd, "%16384[^\n]\n", name) != EOF)
|
||||
path = add_path(path, name, name);
|
||||
|
||||
fclose(fd);
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* reader thread. This thread processes read requests queued by the
|
||||
@@ -2043,14 +2025,6 @@ int main(int argc, char *argv[])
|
||||
strcmp(argv[i], "-li") == 0) {
|
||||
info = TRUE;
|
||||
short_ls = FALSE;
|
||||
} else if(strcmp(argv[i], "-ef") == 0 ||
|
||||
strcmp(argv[i], "-e") == 0) {
|
||||
if(++i == argc) {
|
||||
fprintf(stderr, "%s: -ef missing filename\n",
|
||||
argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
path = process_extract_files(path, argv[i]);
|
||||
} else if(strcmp(argv[i], "-regex") == 0 ||
|
||||
strcmp(argv[i], "-r") == 0)
|
||||
use_regex = TRUE;
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
*.so
|
||||
*.dylib
|
||||
*.dSYM/
|
||||
__pycache__/
|
||||
test/test_md32
|
||||
test/test_parse
|
||||
tools/md32-run
|
||||
|
||||
.pmai/
|
||||
usipdata/
|
||||
@@ -0,0 +1,489 @@
|
||||
# Changelog
|
||||
|
||||
## Unreleased
|
||||
|
||||
### SCQ16 table update (229 forms), the open-reading marker, the broadcast ports, the confidence levels and the public test vectors
|
||||
|
||||
* `isa/scq16_isa.json` / `scq16_opcodes.h`: 229 forms / 402 bit alternatives.
|
||||
`jr rn` (6f ec) reads a 5-bit register field (r0-r31); `btst rd, rd, #pos`
|
||||
(67 f8-fb) has a 5-bit position; `ctz` is its own form without the
|
||||
hypothetical flag, `sqr?` belongs to the `op41` placeholder (hypothetical);
|
||||
`and rd, rs, #0x1|#0x3|#0xf` (2 bytes), `add rd, rs, #-1` (2 bytes) and the
|
||||
4-byte `sb rd, off(rb)` are `high`, the 4-byte `btst rd, rs, #pos` is `medium`
|
||||
(settled by execution results).
|
||||
* `tools/gen_scq16_tables.py`: the flag `SCQ16_FL_OPEN` (an open reading: a
|
||||
family placeholder or a provisional name) and, for an open alternative
|
||||
without a template, the uniform ESIL marker `REF,ALT,open`; `export --hyp`
|
||||
applies the declared plugin hypotheses of `isa/scq16_hyp.json` and records
|
||||
the file's sha256 in the JSON meta and in the header. The file is empty:
|
||||
the packing ESIL / p-code of `op41.fld rd, rs, rt, #pos` is carried by the
|
||||
ISA source (still flagged hypothetical), so every ESIL the plugin emits
|
||||
comes from the source.
|
||||
* `scq16_vu.inc.c` / `scq16_arch.inc.c`: the scalar ports `v0-v31` are the
|
||||
broadcast ports of the vector register file: a write by `vbcast` /
|
||||
`vbcast.i` / `vbcast.i?` reaches the 64 lanes of `vr_k` (an ESIL register-
|
||||
write voyeur); the custom op `open` (no effect); `aoj` reports `open`,
|
||||
`reading`, `hypothetical` and `confidence` per unit.
|
||||
* `ctz` of a zero operand: -1 under the table ESIL (`31 - clz(0)`); documented
|
||||
as an open question against the hardware (32).
|
||||
* `asm_md32.c`: pseudo rule of `op41.fld`.
|
||||
* `test/scq16_vectors.json` + `test/test_scq16_vectors.py`: 195 public
|
||||
bytes-only vectors with the expected result in the big-endian regime of the
|
||||
harness and in the little-endian regime of the core data memory;
|
||||
`test/test_scq16.py` (267 checks) and `test/test_md32.c`: the new forms, the
|
||||
marker, the broadcast, the confidence levels, `ctz(0)`.
|
||||
* `doc/scq16.md`, README: the new forms, the open marker, the broadcast ports,
|
||||
the declared limits of the vector unit model, the hypothesis file, the
|
||||
confidence levels, `ctz(0)`.
|
||||
|
||||
### SCQ16 table update (402 bit alternatives), the `.post` convention and the vector unit model
|
||||
|
||||
* `isa/scq16_isa.json` / `scq16_opcodes.h`: 228 forms / 402 bit alternatives.
|
||||
`ctz rd, rs` (41 f3 0x22) is an established operation; new provisional
|
||||
readings: `sqr? rd, rs` (41 f3 0x23), `sra? rd, rd, #pos` (67 fc-fd),
|
||||
`vrd? rd, vb1[x]` (1a xy), `and? #0xf000?` (67 98-9b and the 2-byte 00/01 with
|
||||
k = 6), `and? #0xc000?` (67 b4-b7); `op41.fld rd, rs, rt, #pos` reads its third
|
||||
field as a register; `lw.post rd, [rb] += 4` (21) has a 4-bit destination;
|
||||
the 3-bit post-increment of the `6e` `.post` family is signed; `sra rd, rd, #imm`
|
||||
(09) is established; the load templates with a post-increment write rd last
|
||||
(with `rd == rb` the loaded value wins).
|
||||
* `scq16_vu.inc.c` (new) / `scq16_arch.inc.c`: the vector unit model of the ESIL:
|
||||
the register file `vr0-vr31` (128 bytes each, four 256-bit quarters in the
|
||||
profile), `vp0-vp7` and `va0-va7`; `vop` models `v.mem.ld`, `v.mem.st` and
|
||||
`v.move.mv` (loads/stores through the VU pointers with the count of `va[A]`
|
||||
and a post-increment, register copies) and leaves every other op9 without effect.
|
||||
* `asm_md32.c`: pseudo rule of `sqr`.
|
||||
* `doc/scq16.md`, README: the new forms, the VU model, the `.post`
|
||||
convention, the callee-saved profile (r16-r31).
|
||||
* `test/test_scq16.py`, `test/test_md32.c`: the new forms and the VU model.
|
||||
|
||||
### SCQ16 table update (228 forms), the `j.d1` target rule and the vector names
|
||||
|
||||
* `isa/scq16_isa.json` / `scq16_opcodes.h`: 228 forms / 400 bit alternatives.
|
||||
The exporter (`tools/gen_scq16_tables.py export`) takes the ESIL, the delayed
|
||||
transfers (SETJT/SETD) and the hypothetical flag from the form-description
|
||||
module itself (its HYP table) and applies no overlay of its own. Vector
|
||||
names: the established operations `v.move.mv`, `v.mem.ld` and `v.mem.st`
|
||||
print without the `?` (`vector.firm_op9`), the provisional ones keep it in
|
||||
the table string.
|
||||
New or renamed: `cmov.ge rd, rs, #imm, ra`, `cmov.eq rd, rs, rx, ra` (the
|
||||
register form), the provisional `cmov.leu?` / `cmov.ltu?` / `cmov.lt?` /
|
||||
`cmov.le?`, `mv rd, rs` (67 c8), `bset` / `btst rd, rd, #pos` (3 bytes),
|
||||
`lbu.post rd, [rb] += inc` with 5-bit registers (6e q2) and the 23 page as
|
||||
`lbu.post rd, [rb] += simm3` (-4..-1), `and rd, rs, #0x3fff` (67 a4-a7), the
|
||||
6-byte `and rd, rs, #imm16` (74 sub 1), the provisional `ctz?` / `clb?` (41 f3),
|
||||
`vcfg4c? v, rs, #0xc` with the hypothetical `p_k <- rs`, `ld46?` as a
|
||||
hypothetical byte load with a post-increment, `lbu? rd, off(sp)` (ex `lb?`),
|
||||
`addsp sp, #imm` (14 8x-fx), `fxts` without the `?`; `halt` and `sys41` carry
|
||||
the empty ESIL (no modelled effect); `5c 40-6f` is the 4-byte `beq rA, rB`.
|
||||
* `scq16_decode.c`: `j.d1 56 0x-3x` decided by its target (stand-alone units
|
||||
and B slots); every ESIL memory access cuts its address to 32 bits (negative
|
||||
frame offsets wrapped in the 64-bit ESIL machine); the `?` of a vector name
|
||||
comes with the table string.
|
||||
* `scq16_arch.inc.c`: a unit with the empty ESIL no longer blocks the ESIL of
|
||||
its packet; opex `named` / `provisional` of vector ops follow the table name.
|
||||
* `asm_md32.c`: pseudo rules of `cmov.ge`/`cmov.leu`/`cmov.le`, `sys41`, `ctz`/`clb`.
|
||||
* `tools/scq16_flags.r2`: the data-space bases (DM, I/O window, DM2) as flags.
|
||||
* `test/test_scq16.py`, `test/test_md32.c`: the new forms, `j.d1` by target,
|
||||
`.d2` across two `aes` steps, negative stack offsets, the vector names.
|
||||
|
||||
### SCQ16 mode (cpu=scq16): the table (218 forms), the byte-granular packet decoder, analysis and ESIL
|
||||
|
||||
* `isa/scq16_isa.json` / `tools/gen_scq16_tables.py` / `scq16_opcodes.h` /
|
||||
`scq16_decode.c`: the SCQ16 (MD32 family, byte-granular packet variant) as
|
||||
a third cpu of the plugin: 218 forms / 389 bit alternatives generated from
|
||||
the ISA table, which carries the plugin semantics (the VU ports as
|
||||
registers, delayed transfers as SETJT/SETD, the hypothetical readings
|
||||
flagged), the length rule by first-byte leaves, packets `{ A ‖ B }` with
|
||||
the head shifted by the borrowed bit, masked orphans, 4-byte vector ops by
|
||||
op9 class (v.<class>[.<name>?]) and 8-byte bundles.
|
||||
* `arch_md32.c` / `scq16_arch.inc.c`: analysis (types, targets relative to the
|
||||
packet start, delay slots counted in instructions, `do` as a loop
|
||||
reference, opex with the unit/packet/bundle structure), ESIL for the scalar
|
||||
forms with parallel packet semantics (temporaries t0-t3), delayed transfers
|
||||
via SETJT/SETD, the VU scalar ports as registers (vu*, v*, va*, vp*, vs*,
|
||||
vb1_/vb3_/vb5_*, udf*) and vector ops as the custom op `vop`; register
|
||||
profile with sp/lr as csr14/csr15, a0 and the loop registers; byte alignment,
|
||||
MAXOP 12.
|
||||
* `asm_md32.c`: SCQ16 pseudo-syntax (packets as `parallel { ...; ...; }`).
|
||||
* `test/test_scq16.py`, `test/test_md32.c`: bytes-only checks of cpu=scq16.
|
||||
* `doc/scq16.md`, README "SCQ16 mode".
|
||||
|
||||
### uSIP table update (760 forms), the parallel packet, the 22-bit branches and the slot pairs
|
||||
|
||||
* `isa/usip_isa.json` / `usip_opcodes.h`: 760 forms (46 added, 12 retired,
|
||||
41 modified). The packet executes in parallel and every read sees the
|
||||
state before the packet (`structure.packet.execution`,
|
||||
`USIP_PACKET_EXEC_PARALLEL`; no decoding rule depends on an intra-packet
|
||||
order). New: `movi rB, #imm17` (the op 7 head with the null-field tail, a
|
||||
17-bit rotated immediate; `movi_min16` / `movi_m32767` retired: with m = 0
|
||||
their value was -65536 / -65535), `movhi` with the small F' = 0 tails
|
||||
(`c001` = 0x10000000, even f12 = 0x1000..0x7000), the 16-bit `ld.w rB,
|
||||
[rA -/+ 4]` of the first slot and the one-unit `st.w rB, [rA -/+ 4]`,
|
||||
`addi rA, #-4 / -2 / -1` of the class-E cell, `loop rX, last, x16` (B = 1,
|
||||
the former `loop.b1?`), the guard `loop_b4_straddle16` on the twelve
|
||||
`loop #N` entries (bit 4 of the head must agree with "the packet at the end
|
||||
crosses a 16-byte line") and the `loop #N?` rule
|
||||
(`structure.packet.loop_imm_q`: N = 0 or the end at pc + 2^k), the m = 1
|
||||
`loop #N` without the `?`, the 22-bit displacement of every `b<cond>.l`
|
||||
(`U1[7:0] : T[13:12] : T[11:0]`: backward and +4096..+8191 cells) and the
|
||||
fifteen `bcc48_*_64x` entries (the 64-bit variant whose extension unit is
|
||||
any 16-bit unit X, with the guard `not_over_validated_call32`), the op c
|
||||
F = 1 branches with the F' = 0 tail exactly at +2 (`beqz_F0c` / `bnez_F0c` /
|
||||
`bleu_rr_F0c` / `bltu_rr_F0c`, `ctx:tail_at_plus2`) and the op 9 F = S = 0
|
||||
cell of >= 4 units (`bne_imm8_F0s0` / `blt_imm8_F0s0`), `bz.s` with the P4
|
||||
cell F = 0 in 2- and 3-unit packets (`bz_s_P4_F0`), the slot pairs
|
||||
(`stslot_F0_k16`, the op c pairs `stslot_slotc_h / _t` and their `stslot?`
|
||||
twins, `ctx:slotc_pair` / `ctx:call_within_2_packets`, `ctx:op4imm_head` on
|
||||
`stslot_F0_q`, `ldslot_S0_pos1` without the `?`), the fusion at distance 2
|
||||
`add rB, rA, #rot12` (`add2_rot12`, `fuse_pair` + `tail_adjacency` 2),
|
||||
`ld.h / ld.hu` with the F' = 0 tail at +2 and any base (`rf0dall_ld_h /
|
||||
ld_hu`, `ctx:rf0dall_guards`), `saturate`, `mfacc` of the C cell and
|
||||
`sext16 / zext16` with S = 0 without the `?`; the CSR names `ag0-ag3.{base?,
|
||||
len?, idx?}` for 0x30-0x3e; the score rules lr32 / rr7 / spodd / rf0dall
|
||||
nowaw in `structure.packet.tie_breaks`.
|
||||
* `tools/gen_usip_tables.py`: the guards `loop_b4_straddle16` (exported with
|
||||
the head field `b4`) and `not_over_validated_call32`, seven new context
|
||||
conditions, `FUSE | ADJ2` for the fusion at distance 2, the constants of the
|
||||
packet model and of the `loop #N?` rule.
|
||||
* `usip_decode.c`: slotpair0 before the layout, the 22-bit prefix
|
||||
displacement and the 64-bit X variant (the branch keeps U0 U1 T, X is the
|
||||
first instruction of the delay slot; the guard against a validated 32-bit
|
||||
call / b of U0 + X), the straddle guard of `loop #N`
|
||||
(`UsipGuardCtx.packet_units`) and the `loop #N?` text, `ctx:tail_at_plus2`
|
||||
(fall-through, never `.word`; the fallback pairs carry their distance),
|
||||
the rf0dall guardians in the f0ctx pass, `bz.s` of the P4 cell F = 0, the
|
||||
post rules R-add2 (`.hword` heads only) / R-fslot0c before the split pass
|
||||
and after the prefix paths, R-slotc in the split pass and `slotc_mark`
|
||||
after the packet (the two following packets through `packet_at`), the
|
||||
F-slot0 readings by rule, the score rules lr32 / rr7 / spodd / rf0dall
|
||||
nowaw. Unverified policy: the `loop_imm_F1S0` reading is no longer
|
||||
accepted (wrong too often), the R-F0c / R-F0s0 branches are (right in
|
||||
nearly every case), the `b<cond>.l` prefix forms only in their forward cell
|
||||
below 4096 units (the 22-bit cells and the X variant need the target
|
||||
validated), the x16 loops as the other `loop rX`.
|
||||
* `arch_md32.c`: the `packet_units` callback (the units of the packet at the
|
||||
loop end, from the bytes at hand or the session's cache; an eight-unit run
|
||||
without a closer is unknown).
|
||||
* `asm_md32.c`: pseudo syntax for `loop rX, last, x16` and `saturate`.
|
||||
* Tests: `test/test_plugin.py` vectors for the parallel packet, `movi #imm17`,
|
||||
the small `movhi` cells, the 16-bit `ld.w` / `st.w` with +-4, the class-E
|
||||
`addi`, `loop x16`, `loop #N` with the straddle guard (accepted and
|
||||
rejected), `loop #N?` (validated and unverified), the backward 22-bit
|
||||
`b<cond>.l` (validated and `.word`), the 64-bit X variant (validated and
|
||||
fallback), `beqz` of R-F0c (validated and unverified), `blt.d` of R-F0s0
|
||||
(validated and fallback), `bz.s` of the P4 cell F = 0 (2 and 3 units,
|
||||
validated and unknown), slotpair0, the op c slot pairs with and without a
|
||||
call, R-fslot0c, R-add2 and rf0dall; the `loop`, `asr16`, `ld_h_Fp0`,
|
||||
`movi #-32768 / #-32767`, `loop.b1?`, `loop #256?`, `ldslot?`, `stslot?`
|
||||
and `saturate?` vectors updated to the new readings; `test/test_parse.c`
|
||||
vectors for the new pseudo rules.
|
||||
|
||||
### uSIP table update (726 forms), the loop cells and the slot splits
|
||||
|
||||
* `isa/usip_isa.json` / `usip_opcodes.h`: 726 forms (52 added, 13 retired,
|
||||
14 modified). New: the `loop #N` count is the collected head field (bits
|
||||
13:5, no +1), `loop #N` with the F' = 0 tail exactly at +2
|
||||
(`loop_imm_*_F1_Fp0`), with h = 1 (N >= 128) and with m = 1 (N >= 256,
|
||||
printed `loop #N?`), `bz.s` in 4- and 3-unit packets (`bz_s_P4_u4` /
|
||||
`bz_s_P4_u3`), the split entries of the slot family `stslot` / `stslot?` /
|
||||
`ldslot?` (F-slot0, S0-slot, the S3 cells `ldslot/stslot #48-63`;
|
||||
`split_role`), the fusion entry `op72? rA, #k, asr#b` (`fuse_pair`),
|
||||
`op2z? rA`, `lsl/asr r8-r15, #B`, the W6 cells `ld.h/st.h rB, [r8+rrr]` and
|
||||
`[rA]+` with h = 1, `sub r14, #f12/2` with any F/F' (`spfix_sub_sp`
|
||||
retired), `st.w [sp], #imm14`, `st.abs` with the hi F' = 0, `add rB, rB,
|
||||
#imm27` / `st.h? [rB], #sat` selected by the immediate value (also the
|
||||
cell-E triples), `add? rB, r15, #rot12` and `ld.h? / ld.hu? rB, [r15+off]`
|
||||
with the F' = 0 tail, `saturate? rd, rs1`, `movi #simm6` in the delay slot
|
||||
of a validated branch, `mtcsr #0x30-0x3e`, `ld.h / ld.hu / lea / movi
|
||||
#-32768 / #-32767 / ld.hu [rA+rB]` without the `?` (twelve `*_q` ids
|
||||
replaced); the constraints `any(rA != 14, m == 1, tail_adjacent == false)`
|
||||
on `beq_imm8_d` (the op 9 `beq.d` with base sp and the adjacent tail is
|
||||
not a branch) and `any(m == 1, rA >= 8, x == 0, rB != 15)` on the seven
|
||||
op a `*_s0f1` / `*_imm8_F0` entries (the `bgt rA, #-1` head class takes
|
||||
only the adjacent S = 1 tail); the ABI passes eight arguments in r0-r7.
|
||||
* `tools/gen_usip_tables.py`: the flags `FUSE`, `SPLIT` / `SPLITBARE` (with a
|
||||
`USIP_FORM_*` index for every split and fusion entry), the constraint op
|
||||
`instr_index`, `any` with up to four alternatives that may be a context
|
||||
condition or an instruction position, six new context conditions; the
|
||||
`loopn` operand type is the collected field.
|
||||
* `usip_decode.c`: the score in twentieths (al1 = 0.3), the explicit
|
||||
candidates loopcand / R-brHHTT / R-b111pre / R-b111ctl with the
|
||||
`b111_layout` context extended to them, the `bz.s` rules of 4- and 3-unit
|
||||
packets (the rest re-parsed as the delay slot, the 3-unit one with the
|
||||
target beyond the packet and no write of rA), the S3 renames and the split
|
||||
pass of the slot family with the split-tail reading and the nowaw guardian,
|
||||
the fusion after the renames, R-movi6d, the R-w6h1 loop guard evaluated
|
||||
with the packet being parsed, the R-loopA adjacency (`.word` at any
|
||||
distance but +2), rf0dmidwaw, the score rules R-waw / al1 / R-bsnext /
|
||||
P2W-P2H prefix / sat40 H H T T / rf0dpen, the instruction position of the
|
||||
renames. Unverified fallback: the loop entries with the F' = 0 tail at +2
|
||||
and the h = 1 heads with the S = 1 tail (and the adjacent F = 0 tail) are
|
||||
accepted; the m = 1 (`loop #N?`) and the other h = 1 entries are not (wrong
|
||||
too often when unverified).
|
||||
* `arch_md32.c`: the stores of an immediate (`[rB]` / `[sp], #imm`) carry the
|
||||
value in `val` and `[sp]` the stack access; the new mnemonics keep their
|
||||
kinds (`op2z?` / `op72?` / `saturate?` are unknown operations).
|
||||
* `asm_md32.c`: pseudo syntax for the stores of an immediate (also to `[sp]`),
|
||||
the absolute `st.abs` / `ld.abs`, the `?` of a count (`loop#? #256?`).
|
||||
* Tests: `test/test_plugin.py` vectors for the loop count, the F' = 0 / h = 1 /
|
||||
m = 1 loops (validated and unverified), the 4- and 3-unit `bz.s` (validated
|
||||
and unknown), beq9sp, the `bgt rA, #-1` cell, the W6 h = 1 cells and the
|
||||
loop guard, `op2z?`, the h = 1 shifts, the 16-bit `lea`, the splits
|
||||
(R-slot4n, R-op4imm in 2 and more units, S0-slot, S3), `op72?`,
|
||||
`saturate?`, sat40 H H T T, R-waw with the P2W prefix, R-b111pre,
|
||||
R-b111ctl, R-bsnext, the omitted weak cell of R-brHHTT, `sub r14`,
|
||||
`st.w [sp]`, `st.abs` hi F' = 0, addq / cell E by value, `mtcsr` of the
|
||||
accumulator CSRs, R-1eX0F0, R-movi6d; the `lea`, `loop#`, `mtcsr`, `movi
|
||||
#-32768 / #-32767`, `ld.h` / `ld.hu` of R-1eX0 / R-ldF0 / R-hhttF0 / R-F0d,
|
||||
`op2z?` and two R-waw vectors updated to the new readings;
|
||||
`test/test_parse.c` vectors for the new pseudo rules.
|
||||
|
||||
### uSIP table update (687 forms), the target filter and the F = 0 branch cells
|
||||
|
||||
* `isa/usip_isa.json` / `usip_opcodes.h`: 687 forms (56 added, 3 retired,
|
||||
71 modified). New: the `b<cond>.d` cells with head F = 0 (`bne.d`, `ble.d`,
|
||||
`bgeu.d`, `bge.d`, `bne.u8.d`, `beq.u8.d`, `bleu.d`, read only in the
|
||||
(B class, tail distance) cells of `usip_br0_cells[]`; the five weak cells of
|
||||
`usip_br0_cells_weak[]` are never taken), `bgt.d` of the F = S = 0 cell back
|
||||
in the table, `ret.s.d`, `loop.b1? rX, last=` and the `?ss=N` loops, `bz.s`
|
||||
with bit 3 = 0, the ld/st type 111 `ld.bu` / `st.b` (`st.b?` retired) with
|
||||
the byte displacement `sext12(f[0]:f[10:1]:f[11])` (`USIP_A_OFFB`, also on
|
||||
`ld.b`), `ld.b` / `st.h` with F != S of op 1 exactly at +2, `ld.h?` / `ld.hu?`
|
||||
with the F' = 0 tail as the second head of H H T T and by the deferred tail
|
||||
of a head with base sp (context group `f0ctx`), the bit-field pair
|
||||
`fxtu`/`fxts`/`fup` in H H T T and the BF_SEL cells
|
||||
`fup`/`fup?`/`fxtu`/`fxtu?`/`fxts?` (renamed from `.bf?` with the nowaw
|
||||
guardian), the 16-bit op 2 shifts `lsl`/`lsl?`/`asr`/`asr? rA, #B` (`addi4`
|
||||
retired), `ldslot`/`stslot` with m = 1, `.stimm16?`, `ld.w?`/`st.w?` for the
|
||||
`f12 = 1 / 3 mod 4` word classes, `add r14` / `sub r14` (spfix),
|
||||
`movi? #-32767`, `movi rA, #-1` with F = 0, `mtcsr?` of the accumulator CSRs
|
||||
with a named 16-bit tail; the known target as a validation filter on the
|
||||
F = S = 0 cells, `bne.d #-1`, the loops with the F' = 1 tail, the open `b.s`
|
||||
(also a function start) and the near `b` (any packet start of the image or a
|
||||
function start), with fall-through on failure for the F = S = 0 cells
|
||||
(`USIP_F_GUARDFT`); the operand conventions of six families revised
|
||||
(`mul`/`divs`/`divu`/`mulu64 A<k>, r<rrr>, rB`, the op 7f bit ops,
|
||||
`cls1`/`clz`/`ctz`, the op 6 compare-immediates, the 48-bit `add`, `asr16`);
|
||||
`known16 = false` on the four h = 0 word slots. Thirty-one entries are
|
||||
post-layout renames.
|
||||
* `tools/gen_usip_tables.py`: the operand type `offb`, the flags `GUARDFT` /
|
||||
`B111` / `F0CTX` (`flags` is `ut32`), the constraint ops `br0_cells` /
|
||||
`br0_cells_live` (cell masks), `bf_valid`, the guards `tail_named16` and
|
||||
`target_packet_start_any_or_function_start`, the `any` sub-operations
|
||||
`packet_len`, `guard`, `range`, `br0_cells`, large value sets
|
||||
(`usip_value_sets[]`), the new context conditions, the tables
|
||||
`usip_br0_cells[]`, `usip_br0_cells_weak[]`, `usip_c48sym_table[]`; form
|
||||
names sanitised into C identifiers.
|
||||
* `usip_decode.c`: the fall-through guards, the fifth guard kind with the
|
||||
optional `UsipGuardCtx.packet_start_any` callback, the R-br0 cells by B class
|
||||
and tail distance, the `b111` group in the 2-unit packet and in H H T T (which
|
||||
now takes tt = 11 tails), the context conditions `b111_layout` /
|
||||
`hhtt_second_head` / `f0d_triple` / `bfpair` / `bf_dst_not_written` /
|
||||
`rest_named_no_q`, the `f0ctx` pass on the `.word` pairs and the re-read of
|
||||
the R-F0d middle unit, R-op1fs (a ld/st entry with `ADJ2` undoes the pair at
|
||||
any other distance), the `bz_s_P5` context rule, the m = 1 R7 slots, P2H,
|
||||
R-lr16, R-align48 and R-c48sym in the score, the `b.s` guard admitting a
|
||||
function start, the loop F' = 0 rule by field; immediates glued to a letter
|
||||
or `=` (`A0`, `?ss=2`, `w=0`) printed in decimal. Unverified fallback: the
|
||||
forms whose guard is a validation filter keep their reading when the target
|
||||
is unknown (`b.s?`, `b?`, `loop?`, `bne.d?` ...; conditional branches only
|
||||
forward), a definite "not a packet start" rejects them.
|
||||
* `arch_md32.c`: `UsipGuardCtx` with designated initialisers; the lowest packet
|
||||
start decoded in the session separates "not a packet start" from "unknown"
|
||||
for backward targets; `offb` as a `disp` operand in `opex`; stack deltas for
|
||||
`addsp` and the `add r14, r14, #imm` / `sub r14, #imm` pairs.
|
||||
* `asm_md32.c`: pseudo syntax for the 2-operand `lsl` / `asr`.
|
||||
* Tests: `test/test_plugin.py` vectors for the F = S = 0 and R-br0 cells
|
||||
(validated by the session, rejected with fall-through, unknown backward,
|
||||
unverified forward), `ret.s.d`, `movi #-1` F = 0, the op 2 shifts, the open
|
||||
`b.s` rejected / unverified, `bz.s` P5 (2-unit, validated, unknown), the m = 1
|
||||
slots, `loop.b1?` and the `?ss=N` loops, `movi? #-32767`, the `asr16` clamp,
|
||||
the bit-field pair and the BF_SEL cells, `ld.bu`/`st.b` with the byte
|
||||
displacement (plain, 2-unit b111, H H T T), `ld.b`/`st.h` F != S at +2 and
|
||||
the undo at +1, `ld.h?`/`ld.hu?` of R-hhttF0 / R-F0d, spfix, NEGQ,
|
||||
`.stimm16?`, `mtcsr?` with a named tail; the `loop`, open `b.s`, `mtcsr`,
|
||||
`movhi` tt = 10 and `save w=` vectors updated; `test/test_parse.c` vectors
|
||||
for the new pseudo rules.
|
||||
|
||||
### uSIP table update (634 forms), decoder rules and the K-tie cascade
|
||||
|
||||
* `isa/usip_isa.json` / `usip_opcodes.h`: 634 forms (52 added, 12 retired,
|
||||
103 modified). New: the 14-bit word displacement of the two-unit
|
||||
`ld.w`/`st.w` (W14: `f12 = 2 mod 4` is `+0x1000 + (f12 & ~3)`), `nop.ctl`
|
||||
for `5e0d`/`1e0d`/`de0d` (never a tail, never a head with a tail), the
|
||||
bit-field family `fxtu`/`fxts`/`fup`/`fup? rB, rs1, #w, #pos`,
|
||||
`movi? rB, #-32768`, the register forms `bset`/`bext rd, rs1, rB`, `mtacc?
|
||||
Ak, rs1:rB` (was `clr.a?`), `sgt rB, rA, #-1` with F = S = 1, `addi rA,
|
||||
#32` next to `cop rA`, the 16-bit `lsl`/`lsl?`/`sext16`/`zext16` variants,
|
||||
`ld.w?`/`ld.h?`/`ld.hu? rB, [r15+off]`, `.ldF0?` and the F' = 0 `ld.h?`/
|
||||
`ld.hu?`, `.3eX0?`, the 20 `b<cond>.d` cells with the `[0][1][tt]` tail at
|
||||
+2, `movhi` with the tt = 10 tail (IEEE test), 16 non-canonical 48-bit
|
||||
constants admitted by a value table, the double-class split (`.op4t0`,
|
||||
`.movi6?`, `.st.h?`/`.st.b?`/`.ld.h?`/`.ld.b?`, `ld.sp`); retired the
|
||||
`.hi`/`.hilo` pair entries and every `not_hi1010` constraint (H1: a
|
||||
hi(1010)-shaped unit is an ordinary head unless a 48-bit instruction claims
|
||||
it), `osl_0_15_2`, `clr.a?`. Twenty entries are post-layout renames
|
||||
(`rename_from`).
|
||||
* `tools/gen_usip_tables.py`: `rename_from` lists per entry, the constraint
|
||||
ops `tail_adjacent`, `ieee_short` and the 48-bit value table membership, the
|
||||
`any` sub-operation `tail_adjacent`, the context conditions
|
||||
`cop_rA_in_packet` / `not_c48_lo_follows`, `USIP_MAXVALS` 12, the tables
|
||||
`usip_never_tail`, `usip_never_head_with_tail` and `usip_c48_table`; the
|
||||
rename entries are exempt from the 16-bit position-class checks.
|
||||
* `usip_decode.c`: W14, the never-tail and never-head-with-tail units from the
|
||||
tables, H1 (the forced hi(1010) decode is gone; `.hi`/`.lo` only after a
|
||||
48-bit-family head in the packet), the 48-bit value table in the partial
|
||||
admission, P2W (no alignment penalty for the `= 2 mod 4` word offsets in the
|
||||
H H T T layout), callin (`UsipGuardCtx.inside_function`), the post-layout
|
||||
renames (`apply_renames`), the K-tie cascade (`dedup` and `nowaw` over the
|
||||
tied readings of the packet; `du2` over the neighbouring packets the caller
|
||||
supplies through `UsipGuardCtx.packet_at` / `branch_target`, first-pass
|
||||
readings with `USIP_GUARD_NO_CASCADE`), `UsipPacket.tiebreak`; the failed op
|
||||
C compare-and-branch guard is printed `.dsp` (unnamed data either way).
|
||||
Unverified fallback extended to the S0F1 cells whose unverified readings are
|
||||
right in nearly every case (`bne`/`blt`/`bgeu`/`bgtu`/`bge` with immediate,
|
||||
`beqz.d`/`bnez.d`, `bleu` register) and to `loop rX` with the F' = 0 tail
|
||||
when the head has F = 1 and the S = 1 tail sits at +2.
|
||||
* `arch_md32.c`: the cascade context (packets decoded earlier in the session,
|
||||
first-pass readings of the packets inside the bytes at hand, the branch
|
||||
targets seen so far), `opex.packet.tiebreak`, `ireg` = `r15` for the r15-based
|
||||
loads, types for `fxtu`/`fxts` (`cast`) and `fup` (`or`).
|
||||
* `asm_md32.c`: pseudo syntax for `fxtu`/`fxts`/`fup`, `mtacc`, the 2-operand
|
||||
`addi`, `sext16`/`zext16`, `asr16`; `nop.ctl` reads `nop`.
|
||||
* Tests: `test/test_plugin.py` vectors for W14, `nop.ctl`, the bit-field
|
||||
family, `mtacc?`, `movi? #-32768`, `sgt #-1`, the register `bset`/`bext`, the
|
||||
S0F1 branches (unverified, validated by the session, not validated), the
|
||||
r15-based loads, `.ldF0?`, the F' = 0 `ld.h?`, the 48-bit value table,
|
||||
`.3eX0?`, the `lsl`/`sext16`/`zext16` renames, `cop ‖ addi`, `.hi`, `movhi`
|
||||
tt = 10, `.op4t0`; the op8 slot split vector updated; `test/test_parse.c`
|
||||
vectors for the new pseudo rules.
|
||||
|
||||
### uSIP table update (594 forms) and the prior-free packet parser
|
||||
|
||||
* `isa/usip_isa.json` / `usip_opcodes.h`: 594 forms (137 added, 18 retired,
|
||||
76 modified). New: the 48/64-bit compare-and-branch prefix forms
|
||||
`b<cond>.l rB, #imm9 / rA, target` (complete condition table incl. the
|
||||
unsigned cells and the 64-bit twin with the `1e0d` unit), `loop# #N, last`,
|
||||
the op 6 set-on-compare family `seq`/`sle`/`slt` and `sgt rB, rA, #rot10`,
|
||||
`movhi` with the 20-bit value and the small cell, `movi?` for the op b class,
|
||||
the 48-bit `mov32`/`add` constants by one formula, `st.w`/`st.h [rB], #imm`,
|
||||
the cell-E triple by position, `ld.d`/`st.d` with the signed offset, the
|
||||
closed negative half-word (`f12 - 0x1001`) and word (`4*sext10(f12 >> 2)`)
|
||||
offsets, `add rB, rA, #rot12` for the odd f12 cell, `st.h` with the F' = 0
|
||||
tail (deferred), the 16-bit first-slot `ld.h`/`st.h`, `movi rA!, #imm5`,
|
||||
`xor rA, rB` alone, the position cells `ld.w?` (k = 0) / `mfacc?` (k >= 2),
|
||||
6-bit `ldslot`/`stslot` and the `.op8?` split, `bset`/`bclr?`/`binv?`/`bext?
|
||||
rd!`, `osl`, `jr rB`, the `sys` twins with F = S = 0, the H H T T loads/
|
||||
stores, the bank bit of the compared register of the 32-bit branches;
|
||||
retired `trap?`, `beqz.l`, `jr?`, `movhi?`, `ld.d?/st.d?` (now `ld.d`/`st.d`),
|
||||
`.ld.abs`, `movi_max32`/`movi_sext27`/`add_r15_imm27` (now `mov32`/`add`),
|
||||
`sgn?`/`scmp?` (now `sgt`), `bgt.d` of op a.
|
||||
* `tools/gen_usip_tables.py`: operand types `offh`/`offw`/`loopn` and the
|
||||
redefined `movhi`, flags `USIP_F_ADJDEF`/`PREFIX`/`RENAME`/`HHTT`, 8 bit
|
||||
ranges per field, 64-bit entries, constraints `gt`, `odd`, `packet_len_ge`,
|
||||
`head_index`/`head_pos_ge`, `ctx`, the guard `head_not_validated_bs`, `any`
|
||||
with up to three alternatives incl. set membership, the `bcc48` condition
|
||||
table, `save w=4` = `{LR, r8}`.
|
||||
* `usip_decode.c`: the prefix forms matched on the first units before the
|
||||
layout (failing guard = not taken), the prior-free total order
|
||||
`(s0, I, Fv, -A, K)` replacing the enumeration order and the group count,
|
||||
the grammar rules (`5e0d` never a tail, the deferred `st.h` tail with its undo
|
||||
and the validated-`b.s` guard, the `.d` SP-negative rejection, the 3-unit and
|
||||
H H T T explicit candidates with the forced decode of hi(1010) heads, the
|
||||
`0e10 3fc0 c000` trio, the `loop #N` F = 1 adjacency, the op8 slot split), the
|
||||
alignment exception `f12 = 3 mod 4 >= 0xf00`, the +0.5 add relabel, +1.0
|
||||
identical units, +0.75 store-of-immediate triples and +0.5 mfcsr pair
|
||||
penalties, the position cells (deferred `head_index`/`packet_len`/`ctx`
|
||||
constraints with fall-through), the late guard evaluation with the undo of a
|
||||
pair, three tails for the 64-bit forms. Unverified fallback extended to the
|
||||
prefix forms and to `loop #N` (F = S = 1, F = 0 with the tail adjacent, F = 1
|
||||
with the S = 0 tail at +2).
|
||||
* `arch_md32.c`: conditions `bequ`/`bneu`, types for `sle` (`cmp`) and `osl`
|
||||
(`shl`), `val` = N for `loop #N`, the signed offsets as `disp` operands in
|
||||
`opex`.
|
||||
* `asm_md32.c`: pseudo syntax for `loop#`, `sle`, `bequ`/`bneu`, the 2-operand
|
||||
`xor`, `mfacc`, `bset`/`bclr`/`binv`/`bext`, `osl`; the `?` marker stripped
|
||||
repeatedly (`ble.l??`); `ld.d`/`ld.w` no longer sign-extended.
|
||||
* Tests: `test/test_plugin.py` vectors for `loop#` (validated at +1 and +2,
|
||||
unverified), `b<cond>.l` (validated, unverified, not taken, 64-bit),
|
||||
`ld.d`/`st.d` with a negative offset, the negative half-word and word offsets,
|
||||
`seq`/`sle`/`sgt`, `movhi`, the 16-bit first-slot `st.h`, the deferred `st.h`
|
||||
and its undo by a validated `b.s`, H H T T, the op8 split, the `0e10` trio,
|
||||
`cop` with F = S = 0, `xor`, `movi rA!`, `bset rd!`, `osl`; the `jr`, `ld.d`,
|
||||
`movhi` and bank-bit (`bnez r15!`, `beqz.d r2!`) vectors updated;
|
||||
`test/test_parse.c` vectors for the new pseudo rules.
|
||||
|
||||
### MS15E30: `cmulr16`/`cmuli16` names
|
||||
|
||||
* `md32_opcodes.h`: the names of 0xDA00 (`cmulr16`, a*c - b*d) and 0xDC00
|
||||
(`cmuli16`, a*d + b*c) follow the little-endian layout of the data memory (the
|
||||
high half of a 32-bit complex word is at +2 and holds the real part); the
|
||||
earlier assignment assumed a big-endian data memory. Vectors in
|
||||
`test/test_md32.c` and `test/test_plugin.py`.
|
||||
|
||||
### uSIP table update (475 forms) and decoder rules
|
||||
|
||||
* `isa/usip_isa.json` / `usip_opcodes.h`: 475 forms (110 added, 24 retired,
|
||||
140 modified). Port I/O `ior`/`iow` replace `mfcr`/`mtcr`; `mtcsr` is back and
|
||||
`mfcsr` accepts F' = 0; the `sys` shape is split by its tail field (`cop`,
|
||||
`rti`, `lpexit?`, `isync?`, `ieon`, `ieoff`, `trap?`, `sys?`, `ret`, `ret?`,
|
||||
`jr?`, `call rB`); `nop32`, `cmov r15`, `add rB, rA, #rot12` for the whole
|
||||
op 0 cell, `sne`, `scmp?`, `movhi?`, `extu`, `movi #-1`, `addsp`, `lea?`,
|
||||
`st.w [sp+4/12/20]`, `ld.d?`/`st.d?` (64-bit pairs), `st.b?`, the stack-slot
|
||||
closers (`ldslot`/`stslot`, `.slot?`, `lsl #1/#2`, `movi #simm6`, `.bit4?`,
|
||||
`.ext8?`), `ld.hu` for type 110, unsigned 12-bit ld/st offsets, `ld.bu` in
|
||||
the class-E cells, per-operand bank bits (`rB!` by `x`, `rA!` by `m`, `rs1!`
|
||||
by `ss`), `save w=2` = four words; the 48-bit `call` with the far tail is
|
||||
retired (those packets are `call`/`b` with the F' = 0 tail at +2).
|
||||
* `tools/gen_usip_tables.py`: `movhi` operand type, `base` as a constant added
|
||||
to register/immediate fields, `scale` on immediates, `ge` and `any`
|
||||
constraints, membership masks for the large CSR sets, the target guards as
|
||||
constraint records, flag `USIP_F_ADJ2`, kinds `io`/`jr`, the `sys` name
|
||||
table, extended CSR names, kind names; the header stays reproducible.
|
||||
* `usip_decode.c`: F' = 0 control tails exactly at +2, target guards evaluated
|
||||
after the match (32-bit: failure = `.word`; 16-bit `call.s`: fall-through),
|
||||
`packet_len` constraints with the real packet length (stand-alone closers),
|
||||
16-bit closers matched with bit 15, rules R0 (the final closer may be its own
|
||||
group) and R7 (first-slot `ldslot`/`stslot`/`lea?` when the rest of the
|
||||
packet is named), the `1dX6 + named tail` and validated-guard tie-breaks;
|
||||
`UsipGuardCtx` lets the caller answer the guards.
|
||||
* `arch_md32.c`: packet starts for the guards from the session (packets seen)
|
||||
and from the bytes at hand (64 bytes of lookahead); function starts are not
|
||||
available to an arch plugin, the documented fallback applies (`call?`,
|
||||
`beqz.d?`... = unverified, `opex.target_guard`, confidence `medium`); types
|
||||
`io`, `rjmp` (`jr?`), `ret` for `rti`, `trap`, `refptr` 8 for the 64-bit
|
||||
pairs, `cast` for `extu`; CSR names in `opex`.
|
||||
* `asm_md32.c`: pseudo syntax for the new mnemonics (`ior`/`iow`, `mfcsr`/
|
||||
`mtcsr`, `addsp`, `ldslot`/`stslot`, `jr`, `nop32`, `sne`, `scmp`, `movhi`,
|
||||
`extu`, the system ops, 64-bit loads/stores, the `?` marker).
|
||||
* Tests: `test/test_plugin.py` vectors for `ior`/`iow`, `nop32`, the 32-bit
|
||||
`ret`, `jr?`, `addsp`, `ld.d?`, the first-slot slot/`lea?` forms, `movhi?`
|
||||
and the guarded 3-unit control packets (validated, failed and unverified);
|
||||
`test/test_parse.c` vectors for the new pseudo rules; the `mov32`/`ld.b`
|
||||
vectors now show the bank bit of the register it applies to (`r15!`).
|
||||
|
||||
### uSIP mode rewritten as a table-driven VLIW packet decoder
|
||||
|
||||
* `isa/usip_isa.json`: the instruction table (386 forms with masks, operand
|
||||
fields, constraints and a confidence level) and the packet model;
|
||||
`tools/gen_usip_tables.py` generates `usip_opcodes.h` from it.
|
||||
* `usip_decode.c`/`.h`: packet decoder (16-bit unit scan, packets closed by
|
||||
bit 15, heads-first/round-robin head-tail pairing per group, slot-0-only
|
||||
control flow, delay slot = rest of the packet, 48-bit forms with hi/lo units,
|
||||
documented tie-breaks and context rules).
|
||||
* `arch_md32.c` (`cpu=usip`): one op per run of adjacent units of the same
|
||||
instruction, `.unit` ops for displaced tails, packet cache in the session,
|
||||
analysis types/conditions/targets/delay/fail for the whole control-flow
|
||||
family, loads/stores and immediates, `opex` with form/confidence/packet info,
|
||||
a register profile with the ABI, `MAXOP_SIZE` 16 in this mode. The previous
|
||||
five hard-coded patterns (`b0`-`b7`, `save16`, two call shapes) are replaced
|
||||
by named conditions and the table.
|
||||
* `asm_md32.c`: pseudo syntax for the uSIP mnemonics (`#` immediates, `[base+off]`
|
||||
memory operands, compare-and-branch, `save`/`restore`, `loop`).
|
||||
* `test/test_plugin.py`: uSIP packet vectors (control flow in slot 0, delay
|
||||
slots, interleaved `S S O O` layout, 48-bit forms, hardware loop, context
|
||||
rule, truncated packet); `test/test_parse.c` updated for the new mnemonics.
|
||||
* `test/test_emulator.py`: in usip mode the probe `5ef9 901a` is a delayed return,
|
||||
so the strict stop is `unsupported_delay_slot_execution` (still zero steps).
|
||||
* Documentation: README "uSIP mode", `doc/usip.md`.
|
||||
@@ -0,0 +1,61 @@
|
||||
R2 ?= r2
|
||||
PKG_CONFIG ?= pkg-config
|
||||
PYTHON ?= python3
|
||||
CC ?= cc
|
||||
SO_EXT := $(shell $(R2) -H R2_LIBEXT)
|
||||
PLUGIN = arch_md32.$(SO_EXT)
|
||||
ASM_PLUGIN = asm_md32.$(SO_EXT)
|
||||
R2_PLUGIN_PATH ?= $(shell $(R2) -H R2_USER_PLUGINS)
|
||||
CPPFLAGS += $(shell $(PKG_CONFIG) --cflags r_arch)
|
||||
CFLAGS += -Wall -Wextra -Wno-unused-parameter -fPIC -O2
|
||||
LDLIBS += $(shell $(PKG_CONFIG) --libs r_arch)
|
||||
|
||||
all: $(PLUGIN) $(ASM_PLUGIN) tools/md32-run
|
||||
|
||||
USIP_SRC = usip_decode.c
|
||||
USIP_HDR = usip_decode.h usip_opcodes.h
|
||||
# the SCQ16 decoder is included by scq16_arch.inc.c (one table instance): dependencies only
|
||||
SCQ16_HDR = scq16_arch.inc.c scq16_vu.inc.c scq16_decode.c scq16_decode.h scq16_opcodes.h
|
||||
|
||||
$(PLUGIN): arch_md32.c md32_opcodes.h $(USIP_SRC) $(USIP_HDR) $(SCQ16_HDR)
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -shared -o $@ arch_md32.c $(USIP_SRC) $(LDLIBS)
|
||||
|
||||
$(ASM_PLUGIN): asm_md32.c
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -shared -o $@ asm_md32.c $(shell $(PKG_CONFIG) --libs r_asm)
|
||||
|
||||
install: $(PLUGIN) $(ASM_PLUGIN) tools/md32-run
|
||||
mkdir -p "$(DESTDIR)$(R2_PLUGIN_PATH)"
|
||||
cp -f $(PLUGIN) $(ASM_PLUGIN) "$(DESTDIR)$(R2_PLUGIN_PATH)/"
|
||||
|
||||
uninstall:
|
||||
rm -f "$(DESTDIR)$(R2_PLUGIN_PATH)/$(PLUGIN)"
|
||||
rm -f "$(DESTDIR)$(R2_PLUGIN_PATH)/$(ASM_PLUGIN)"
|
||||
|
||||
tools/md32-run: tools/md32-run.c arch_md32.c md32_opcodes.h $(USIP_SRC) $(USIP_HDR) $(SCQ16_HDR)
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ tools/md32-run.c $(USIP_SRC) $(shell $(PKG_CONFIG) --libs r_anal)
|
||||
|
||||
test/test_md32: test/test_md32.c arch_md32.c md32_opcodes.h $(USIP_SRC) $(USIP_HDR) $(SCQ16_HDR)
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ test/test_md32.c $(USIP_SRC) $(LDLIBS)
|
||||
|
||||
test/test_parse: test/test_parse.c asm_md32.c
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ test/test_parse.c $(shell $(PKG_CONFIG) --libs r_asm)
|
||||
|
||||
test: $(PLUGIN) $(ASM_PLUGIN) tools/md32-run test/test_md32 test/test_parse
|
||||
./test/test_md32
|
||||
./test/test_parse
|
||||
$(PYTHON) test/test_plugin.py
|
||||
$(PYTHON) test/test_emulator.py
|
||||
$(PYTHON) test/test_firmware.py
|
||||
$(PYTHON) test/test_scq16.py
|
||||
$(PYTHON) test/test_scq16_vectors.py
|
||||
|
||||
usip_opcodes.h: isa/usip_isa.json tools/gen_usip_tables.py
|
||||
$(PYTHON) tools/gen_usip_tables.py $< -o $@
|
||||
|
||||
scq16_opcodes.h: isa/scq16_isa.json tools/gen_scq16_tables.py
|
||||
$(PYTHON) tools/gen_scq16_tables.py $< -o $@
|
||||
|
||||
clean:
|
||||
rm -f arch_md32.so arch_md32.dylib asm_md32.so asm_md32.dylib test/test_md32 test/test_parse tools/md32-run
|
||||
|
||||
.PHONY: all install uninstall test clean
|
||||
+491
@@ -0,0 +1,491 @@
|
||||
# MD32 architecture plugin
|
||||
|
||||
Native radare2 `RArchPlugin` for the MediaTek MD32 **MS15E30** ISA. The decoder
|
||||
covers all **258 encoding forms** in the public vendor disassembler, including
|
||||
16/32-bit instructions, packed instruction pairs, DSP operations, control
|
||||
registers, and hardware-loop setup. It has no runtime dependency on Python,
|
||||
Ghidra, Capstone, or vendor binutils.
|
||||
|
||||
The plugin serves three encodings of the same modem DSP line, selected with
|
||||
`asm.cpu`:
|
||||
|
||||
* **MS15E30** (the default): the public MD32 ISA, 16/32-bit instructions.
|
||||
* **uSIP** (`e asm.cpu=usip`): a later MD32 variant that packs 16-bit units into
|
||||
VLIW packets. Same register model and much of the same vocabulary as MS15E30,
|
||||
but a different encoding; see [uSIP mode](#usip-mode).
|
||||
* **SCQ16** (`e asm.cpu=scq16`): a byte-granular, big-endian packet encoding
|
||||
that is **not** an MD32 encoding. It is served by this plugin because its
|
||||
scalar programming model (32 general registers, `sp`/`lr` as control
|
||||
registers, calling convention, the scalar operations and their ESIL) follows
|
||||
MD32 closely; its instruction table is its own. See [SCQ16 mode](#scq16-mode).
|
||||
|
||||
The remaining DSP cores of the same modem use an unrelated SIMD ISA
|
||||
(byte-granular, little-endian) and are out of this plugin's scope.
|
||||
|
||||
## Build and use
|
||||
|
||||
Requires radare2 development headers/libraries, `pkg-config`, a C compiler, and
|
||||
make. Tested with radare2 6.2.5 on macOS arm64 and on Linux x86-64 (`make test`),
|
||||
and 6.2.2 on Linux x86-64 (against 6.2.2 the optional `tools/md32-run` runner does not build because
|
||||
`r_esil_set_fault` is missing from that release: build the two plugins with
|
||||
`make arch_md32.so asm_md32.so`).
|
||||
|
||||
```sh
|
||||
make
|
||||
make install
|
||||
r2 -a md32 -b 32 -e cfg.bigendian=true firmware.be.bin
|
||||
```
|
||||
|
||||
`make install` copies the architecture and assembly parse plugins to
|
||||
`r2 -H R2_USER_PLUGINS`. Override `R2_PLUGIN_PATH` to choose another location.
|
||||
`make uninstall` removes both.
|
||||
Without installation, load the built library using `L /absolute/path/arch_md32.dylib`
|
||||
inside r2 (`.so` on Linux), then set `e asm.arch=md32`.
|
||||
|
||||
For pseudocode display, enable `e asm.pseudo=true`. The `md32` assembly parser
|
||||
is selected automatically with `asm.arch=md32`; select it explicitly with
|
||||
`e asm.parser=md32` if needed. Without installation, load `asm_md32.dylib`
|
||||
alongside `arch_md32.dylib` before selecting the architecture.
|
||||
|
||||
The parser covers scalar moves, arithmetic, bit operations, signed/unsigned
|
||||
comparisons, calls, jumps and Harvard data-memory accesses. For example,
|
||||
`lw r2, (r1+=0x8)` becomes `r2 = dmem32[r1]; r1 += 0x8`. Signed byte/halfword
|
||||
loads use `sext8`/`sext16`; packed pairs display as `parallel { ...; ...; }`.
|
||||
Delayed control flow and unresolved DSP operations retain their assembly text.
|
||||
In `usip` mode the same rules apply to the uSIP mnemonics (`ld.w r0, [r8+0x4]`
|
||||
becomes `r0 = dmem32[r8 + 0x4]`, `bnez r15, 0x418` becomes
|
||||
`if (r15 != 0) goto 0x418`); format-only `.xxx` forms and `.unit` tails keep
|
||||
their text. This is a display parser; it does not add instruction encodings or
|
||||
ESIL semantics.
|
||||
|
||||
Instructions use big-endian byte order and two-byte alignment. Older VPU/DSP
|
||||
blobs store the instruction stream in reversed **four-byte storage words**.
|
||||
Normalize those files before opening them:
|
||||
|
||||
```sh
|
||||
python3 tools/swap_words.py vpu_p.bin firmware.be.bin
|
||||
```
|
||||
|
||||
This is not ordinary per-instruction byte swapping: a four-byte storage word
|
||||
may contain two instructions or part of an instruction crossing its boundary.
|
||||
Do not apply this conversion to the already big-endian uSIP samples.
|
||||
|
||||
## Supplied uSIP samples
|
||||
|
||||
```sh
|
||||
r2 -a md32 -b 32 -e cfg.bigendian=true -c 'e asm.cpu=usip' \
|
||||
-m 0x400e0000 third_party/r2pkg/bin/usip_sec0.bin
|
||||
r2 -a md32 -b 32 -e cfg.bigendian=true -c 'e asm.cpu=usip' \
|
||||
-m 0x1ca34000 third_party/r2pkg/bin/usip_ddr.bin
|
||||
```
|
||||
|
||||
Optional symbol flags, generated directly from the supplied inventory:
|
||||
|
||||
```sh
|
||||
python3 tools/usip_symbols.py --section sec0 > /tmp/usip-sec0.r2
|
||||
python3 tools/usip_symbols.py --section ddr > /tmp/usip-ddr.r2
|
||||
```
|
||||
|
||||
Load the corresponding script with `. /tmp/usip-sec0.r2` or
|
||||
`. /tmp/usip-ddr.r2`. The first 0x400 bytes of sec0 are the vector table;
|
||||
use the symbol inventory to choose code entry points. These are supplied load
|
||||
aliases; the reset-vector conflict reported by `tools/analyze_firmware.py`
|
||||
means they are not a validated boot memory map.
|
||||
|
||||
## uSIP mode
|
||||
|
||||
`e asm.cpu=usip` selects the decoder for the **uSIP** variant of the MD32 family
|
||||
(VLIW execute packets of 16-bit units). The instruction set is described by the
|
||||
table `isa/usip_isa.json` (760 forms, generated into `usip_opcodes.h` by
|
||||
`tools/gen_usip_tables.py`) and by the packet model implemented in
|
||||
`usip_decode.c`. The table is an empirical description, not a vendor
|
||||
specification: every form carries a confidence level (`high`, `medium`, `low`,
|
||||
`format-only`) that the `aoj` output reports under `opex.confidence`.
|
||||
|
||||
### The packet model
|
||||
|
||||
* The unit is the 16-bit big-endian halfword. A **packet** is the run of units up
|
||||
to and including the first one with bit 15 set (at most 8 units); packets start
|
||||
at 2-byte alignment and the units of a packet execute in parallel.
|
||||
* An **instruction** is a *head* (bit 15 = 0) plus 0, 1 or 2 *tails*
|
||||
(16/32/48 bits; the 64-bit `b<cond>.l` prefix forms have three). Tails are not
|
||||
necessarily adjacent to their head: a packet is a sequence of groups laid out
|
||||
*heads first, then tails round-robin* (`S S O O` is two 32-bit instructions
|
||||
interleaved; `x008 X hi lo hi' lo'` a 48-bit call interleaved with another
|
||||
48-bit op). No bit selects the layout. The decoder enumerates every group split
|
||||
and head/tail assignment the table allows, adds the explicit candidates of the
|
||||
packet grammar (the 3-unit `[head][op16][F' = 0 tail]`, the 4-unit `H H T T`
|
||||
pair of loads/stores) and keeps the smallest reading in the **prior-free total
|
||||
order** `(s0, I, Fv, -A, K)`: unknown units plus the documented tie-break
|
||||
penalties, then the number of instructions, then the heads whose tail
|
||||
adjacency contradicts the F pattern (head F = 0 and next unit bit 14 = 1 means
|
||||
an adjacent tail, otherwise a deferred one), then minus the number of adjacent
|
||||
tails, then the lexicographic key of the assignment. Readings tied on the first
|
||||
four go through the **K-tie cascade**: `dedup` (identical instruction texts),
|
||||
`nowaw` (the only reading without a double register write) and `du2` (a
|
||||
differential use-definition score over the neighbouring packets); a tie the
|
||||
cascade decides is reported as `opex.packet.tiebreak`, one it cannot decide is
|
||||
left to the key and reported as `opex.packet.ambiguous`.
|
||||
* The **prefix forms**: a packet whose first three (four) units are a 48-bit
|
||||
(64-bit, with the `1e0d` extension unit) `b<cond>.l rB, #imm9 / rA, target`
|
||||
whose target is a packet start of the same function is that instruction plus
|
||||
its delay slot (the rest of the packet); a failing guard just means the normal
|
||||
layout. The absolute `call.abs`/`b.abs` prefix (`x008 + hi + lo`) is the other
|
||||
prefix rule.
|
||||
* Only **slot 0** (the first unit) can be control flow: `b<cond>`, `b`, `call`,
|
||||
`loop rX`/`loop #N`, `ret`, the 16-bit `bz.s`/`bnz.s`/`b.s`/`call.s`,
|
||||
`call.abs`/`b.abs`, the `b<cond>.l` prefix forms (the 32-bit `ret`/`ret?`,
|
||||
`jr rB` and `call rB` of the `sys` shape may sit anywhere). The tail of a
|
||||
branch/call/loop is at +1 or +2; the control tails with F' = 0 (`call`/`b`/
|
||||
`b<cond>` with a 16-bit op in between) and `loop #N` with F = 1 and an S = 0
|
||||
tail sit exactly at +2. When the control instruction does not close the
|
||||
packet, the **rest of the packet is its delay slot** (both paths execute it).
|
||||
The plugin reports `delay` = number of ops that follow in the packet and
|
||||
`fail` = the next packet.
|
||||
* Grammar rules of the layout: `5e0d` is never a tail and `5e0d`/`1e0d` never
|
||||
take one (they are the structural no-op `nop.ctl`); a unit with bits 12:9 =
|
||||
1010 is a `hi` syllable only inside a formed 48-bit instruction, otherwise an
|
||||
ordinary head (a lone `.hi`/`.lo` only after a 48-bit-family head in the
|
||||
packet); the `st.h` with the F' = 0 tail takes it at +2 or farther (an
|
||||
adjacent tail is two 16-bit ops) and in the first slot loses against a `b.s`
|
||||
head whose target is a packet start; an op 5 head on SP never takes a negative
|
||||
`ld.d`/`st.d` tail; the immediate set-on-compare forms need an adjacent tail;
|
||||
an `.op8?` pair of two slot-family units is two `ldslot`/`stslot` ops; an op 0
|
||||
head takes `hi + lo` as one of 16 non-canonical 48-bit constants admitted by
|
||||
value; the identical-bit cells `mfacc?` (k >= 2) and `add?`/`st.h?` (cell E)
|
||||
are selected by the position of the head inside the packet. Once the layout
|
||||
is decided, twenty **post-layout renames** relabel the instructions they
|
||||
match (`nop.ctl`, the 16-bit `lsl`/`lsl?`/`sext16`/`zext16` variants, `addi
|
||||
rA, #32` next to `cop rA`, `ld.w?` of cell A, the r15-based loads, the
|
||||
register `bset`/`bext`, `.ldF0?` and the F' = 0 `ld.h?`/`ld.hu?`, `.3eX0?`).
|
||||
* Some control forms carry a **target guard**: `loop`, `loop #N`, `b<cond>` and
|
||||
`beqz.d`/`bnez.d` with the F' = 0 tail, the `b<cond>.d` with the `[0][1][tt]`
|
||||
tail at +2 and the `b<cond>.l` prefix forms need a target at a packet start of
|
||||
the same function, `call` with the F' = 0 tail and the open-packet `call.s`
|
||||
need a function start, far `b` either. A 32-bit pair whose guard fails is data
|
||||
(`.word`; the op C compare-and-branch cell leaves a `.dsp` pair); the 16-bit
|
||||
`call.s` falls through to the plain reading; a prefix form is simply not
|
||||
taken. A relative `call` into the middle of a known function pays a tie-break
|
||||
penalty (`callin`) when the embedder can tell. See
|
||||
[target guards](#target-guards) for what the plugin can check.
|
||||
* Hardware loops: `loop rX, last=ADDR` / `loop# #N, last=ADDR` repeat the
|
||||
following instructions up to `ADDR` (inclusive) `rX` / `N` times; they are
|
||||
reported as a reference (`ptr`), not a branch (`val` = N).
|
||||
|
||||
### What one `pd` line is
|
||||
|
||||
A decode is one **op per run of adjacent units that belong to the same
|
||||
instruction**: an instruction whose tails are adjacent is one op of 4, 6 or 8
|
||||
bytes; an interleaved instruction shows its head as a 2-byte op with the full
|
||||
operands and its displaced tails as `.unit 0xNNNN (mnemonic @ head)` ops, so that
|
||||
every address of the stream is covered exactly once and the sizes add up. The
|
||||
decoder needs the packet context: the decode at a packet start parses the whole
|
||||
packet and caches it in the session, the following decodes inside the packet
|
||||
(linear disassembly, function analysis) reuse that reading, and a decode at an
|
||||
address that is not cached is treated as a packet start — true for branch
|
||||
targets and function starts, not for an arbitrary mid-packet address, which may
|
||||
then read differently than in the linear listing. `R_ARCH_INFO_MAXOP_SIZE` is
|
||||
16 in this mode so that `ao`/analysis see the whole packet.
|
||||
|
||||
### Mnemonics and operands
|
||||
|
||||
Registers `r0-r15` (`r14` = SP, `r15` = LR); the second bank is written `rN!`
|
||||
on the operand it applies to (bit `x` = the data/destination register, bit `m` =
|
||||
the source/base register, also the compared register of the 32-bit branches and
|
||||
the destination of `movi rA!, #imm5`, `ss & 2` = the first source of the
|
||||
three-register ALU forms). Accumulators `A0-A3` (`mfacc rA, Ak.{lo,hi,ext}`),
|
||||
port I/O `ior rB, [rA]`/`iow rB, [rA]` (`rA` holds the port number; there is no
|
||||
classic CSR bank on this core), extended CSRs by number (`mfcsr rB, #nn`,
|
||||
`mtcsr #nn, rA`), the system shape by name (`cop rA`, `rti`, `ieon`, `ieoff`,
|
||||
`idle`, `lpexit?`, `isync?`, `sys #n`; with the F = S = 0 tail the packet stays
|
||||
open), `nop32`, `addsp #imm` (SP adjust), `lea rA, [sp+off]`,
|
||||
`ldslot`/`stslot rB, #k` (stack-slot access, 6-bit slot: the stack arguments
|
||||
from the ninth on; `stslot?`/`ldslot?` where the slot or the role is open),
|
||||
`sub r14, #imm` (frame allocation), `st.w [sp], #imm` (the ninth stack argument),
|
||||
`ld.d`/`st.d rB:rB+1, [rA+off]` (64-bit pairs, signed offset multiple of 4),
|
||||
`st.w`/`st.h [rB], #imm` (store of an immediate), `mov32 rB, #imm32` /
|
||||
`add rB, rB, #imm32` (48-bit constants, by formula or by the value table),
|
||||
`movhi rB, #imm` (20 bits << 12), `movi? rB, #imm20` / `movi? rB, #-32768`, the
|
||||
set-on-compare family `seq`/`sne`/`sle`/`slt`/`sgt rB, rA, #imm`, `osl rB, rs1,
|
||||
#1` (funnel shift), `bset`/`bclr?`/`binv?`/`bext? rd!, rs1, #imm5` and the
|
||||
register forms `bset`/`bext rd, rs1, rB`, the bit-field family
|
||||
`fxtu`/`fxts`/`fup rB, rs1, #w, #pos` (extract unsigned / signed, insert; `extu`,
|
||||
`asr16`, `osl` keep their names), `mtacc? Ak, rs1:rB`, `nop.ctl`, `jr rB`.
|
||||
Immediates carry a `#`; memory operands are `[rA+off]`, `[rA-off]` (the closed
|
||||
negative bands of the half-word and word offsets; the word offsets have 14 bits:
|
||||
`[rA+0x1xxx]`), `[rA]+`, `[rA+rB]`, `[sp+off]`, `[r15+off]`, `[#addr]`. Branch
|
||||
targets and `loop` ends are printed absolute; the 48/64-bit compare-and-branch
|
||||
forms are `b<cond>.l rB, #imm9, target` / `b<cond>.l rB, rA, target` (`bne beq
|
||||
ble blt bge bgt bgeu bgtu`, the open cells `ble.l?`, `bneu.l?`, `bequ.l?`,
|
||||
`bcc48?`), the delayed 32-bit ones `b<cond>.d` (also with the `[0][1][tt]` tail
|
||||
at +2). Forms whose operation is unknown but whose grouping is established are
|
||||
**format-only** and start with `.` (`.hword`, `.word`, `.w48`, `.dsp`, `.op4imm`,
|
||||
`.op4t0`, `.ldF0?`, `.3eX0?`, `.slot?`, `.hi`/`.lo`/`.ext` ...) or end with `?`
|
||||
(`ld.w?`, `mtacc?`, `fup?`): they are grouped correctly so that the packet and
|
||||
delay slot model stays right, and reported with the `unk` type. `.hi`, `.lo`,
|
||||
`.ext`, `.be79`, the 2- to 4-unit `bz.s`, the first-slot `ldslot`/`stslot`/`lea`, the
|
||||
split `ldslot`/`stslot` halves (the `.op8?` pairs and the post-layout splits of the
|
||||
slot family), the fused `op72?` pair, `movi #simm6` in a delay slot and the
|
||||
`H H T T` loads/stores come from context rules, not plain table entries.
|
||||
A control instruction printed with a trailing `?` (`call?`, `beqz.d?`, `bne.l?`,
|
||||
`loop#?`, `bne.d?`) is one whose target guard could not be evaluated (see below).
|
||||
|
||||
### Target guards
|
||||
|
||||
The guarded forms need to know whether the target is a packet start of the
|
||||
current function or a function start. The plugin derives **packet starts from
|
||||
the stream**: the packets decoded earlier in the session (backward targets, and
|
||||
forward targets of a region already decoded, e.g. after `aa` or on a second
|
||||
`pd`) and a scan of the bytes radare2 hands the decoder past the current packet
|
||||
(at most 64 bytes of lookahead). A forward target farther away is unknown.
|
||||
**Function starts are not available** to an arch plugin (radare2 gives it no
|
||||
typed access to RAnal). When a guard cannot be evaluated the plugin applies a
|
||||
fallback measured on the sample the table was built from: the forms whose
|
||||
unverified readings are right in nearly every case are read anyway, printed
|
||||
with a trailing `?`, confidence `medium` and `opex.target_guard = "unverified"`
|
||||
(`call` with the F' = 0 tail at +2, `b` with the F' = 0 tail, `b<cond> rA, #imm`
|
||||
with the F' = 0 tail, `beqz.d`, the `b<cond>.l` prefix forms with a forward
|
||||
target, `loop #N` with F = S = 1, with F = 0 and the tail adjacent, with F = 1
|
||||
and the S = 0 tail at +2, with the F' = 0 tail at +2 and with h = 1 (N >= 128)
|
||||
and the S = 1 tail or the adjacent F = 0 tail, `loop rX` with F = 1 and the
|
||||
S = 1 F' = 0 tail at +2, and the `b<cond>.d` cells with the `[0][1][tt]` tail
|
||||
`bne`/`blt`/`bgeu`/`bgtu`/`bge` with immediate, `beqz.d`/`bnez.d` and `bleu`
|
||||
with registers); the others are treated as a failed guard (`loop rX` with the
|
||||
other F' = 0 tails, `loop #N` with F = 0 and the tail at +2, the m = 1
|
||||
`loop #N?` heads and the other h = 1 loop cells, far `b`, `bnez.d` of the
|
||||
F = S = 0 cell, the register `b<cond>` with the F' = 0 tail, the other
|
||||
`b<cond>.d` cells, the open-packet `call.s`), i.e. `.word`, the plain 16-bit
|
||||
reading or the normal layout. The forms whose guard is a validation filter (the
|
||||
F = S = 0 and the F = 0 `b<cond>.d` cells, `bne.d #-1`, the hardware loops with
|
||||
the F' = 1 tail, the near `b`, the open `b.s`) keep their reading when the
|
||||
target is unknown (printed with the `?` too) and are rejected by a known target
|
||||
that is not a packet start; a conditional branch whose unknown target lies
|
||||
backward is not read. A validated guard reports `opex.target_guard =
|
||||
"validated"`. The K-tie cascade sees the packets decoded earlier in the session
|
||||
and the ones inside the same lookahead (see `doc/usip.md` §7 for what is
|
||||
approximated).
|
||||
|
||||
### Analysis
|
||||
|
||||
Operation types: `cjmp` with `cond` for the compare-and-branch forms (there are
|
||||
no flags on this core; `bequ`/`bneu` are the unsigned equality cells of the
|
||||
48-bit forms), `jmp`, `call`/`rcall`, `ret` (also `rti`), `rjmp` for `jr rB`,
|
||||
`io` for `ior`/`iow` (`ireg` = the port register), `load`/`store` with
|
||||
`refptr`/`ireg`/`disp` (`stackop` on `r14`; `refptr` 8 for `ld.d`/`st.d`; the
|
||||
signed offsets also appear as the `off` operand of `opex`), `mov` with `val` for
|
||||
the immediate moves (`movi`, `movi?`, `mov32`, `movhi`),
|
||||
`add`/`sub`/`and`/`or`/`xor`/`shl`/`shr`/`sar`/`mul`/`div`/`cmp`/`cmov`/`cast`
|
||||
(`osl` is a `shl`, the set-on-compare family `cmp`, `fxtu`/`fxts` `cast`, `fup`
|
||||
`or`), `lea` for `lea`/`lea?`, `nop` for `nop32`/`nop.ctl`, `rpush`/`pop` for
|
||||
`save`/`restore`, `trap` for `trap?`, `swi` for the other system ops; `loop #N`
|
||||
carries the count in `val`. `opex` carries the form id, confidence, kind, slot,
|
||||
unit addresses, the delay-slot flag, the target-guard status, the packet's
|
||||
ambiguity / tie-break and the operands.
|
||||
The register profile exposes the ABI (`SP=r14`, `LR=r15`, arguments `r0-r7`,
|
||||
return `r0`). No ESIL is produced for uSIP.
|
||||
|
||||
### Limitations
|
||||
|
||||
* The reading is table-driven, deterministic and prior-free. Four kinds of
|
||||
packets can read differently from the intended one: packets where several
|
||||
head/tail assignments tie on the first four keys of the layout order and the
|
||||
K-tie cascade cannot decide (flagged by `opex.packet.ambiguous`) or decides
|
||||
them with a shorter context than a whole-function scan would give (`du2`),
|
||||
control flow in open packets (`call`/`b`/`loop`/`loop #N`/`b.s` followed by
|
||||
delay-slot ops) when the branch reading is not the cheapest one (a `loop #N`
|
||||
reading with a 16-bit middle unit often writes a register twice with the
|
||||
stolen tail, which the R-waw rule charges), the guarded forms whose
|
||||
target the plugin cannot check (far `b` to another function or beyond the
|
||||
lookahead, the open-packet `call.s`, `loop`/`bnez.d`, the `b<cond>.d` register
|
||||
cells and the `bz.s` of 3-unit and longer packets with a forward target
|
||||
beyond the lookahead), and the `call` pairs whose tail choice depends on the
|
||||
`callin` tie-break. A disassembler that knows the function table can prefer
|
||||
the reading whose target is a function start or a packet boundary and answer
|
||||
`callin`; `UsipGuardCtx` in `usip_decode.h` is the hook for that knowledge.
|
||||
* Open points of the ISA: the remaining layout ties, the sign and width of the
|
||||
`?` forms (`ld.d?`/`st.d?` with b10, `ld.w?`/`st.w?` in the 0x800-0xeff band,
|
||||
`seq?`/`sle?` with large immediates, `mov32?`, `lea?`, `mfacc?`, `add?`/`st.h?`
|
||||
of cell E, `bcc48?`, `movi?`, `mtacc?`, `fup?`, `.ldF0?`), the `f12 = 1 / 3
|
||||
mod 4` word displacements below 0x800, `.op4t0` (a stolen tail), `.3eX0?`,
|
||||
`ld.w` vs `add` in the op 0 F = S = 1 cell, the exact
|
||||
`save w` frame size, `sys #2/#4/#8`, `L_mult` vs `L_mult.e`, why the scheduler
|
||||
inserts `nop.ctl`, the `?ss=N` loops, the sign of the
|
||||
`ld.w?`/`st.w?` word classes, `.stimm16?`, the `lsl?`/`asr?` cells without an
|
||||
idiom.
|
||||
* A decode in the middle of a packet without the packet cached (e.g. `ao` at an
|
||||
arbitrary address) sees a different packet than the linear listing.
|
||||
* At the end of a map, `ao` pads the read with `0xff`, which is a legal closing
|
||||
unit; the disassembly path (`pd`) gets the exact bytes and marks the packet
|
||||
`truncated`.
|
||||
|
||||
See [doc/usip.md](doc/usip.md) for the table format and the constraint and
|
||||
context-rule semantics.
|
||||
|
||||
## SCQ16 mode
|
||||
|
||||
`e asm.cpu=scq16` selects the decoder for the **SCQ16**, a byte-granular
|
||||
encoding of the same modem DSP line (not an MD32 encoding; it shares the
|
||||
scalar programming model, see the introduction) whose instruction stream is byte-granular: units of 2 to 6
|
||||
bytes (vector operations are 4 bytes, bundles 8), optionally paired in a
|
||||
**packet** `{ A ‖ B }` whose two units execute in parallel. The table is an
|
||||
empirical description, not a vendor specification: every form carries a
|
||||
confidence level (`high`, `medium`, `low`, `format-only`) that the `aoj` output
|
||||
reports under `opex.units[].confidence`. Select it with
|
||||
|
||||
```sh
|
||||
r2 -a md32 -b 32 -e cfg.bigendian=true -e asm.cpu=scq16 firmware.be.bin
|
||||
```
|
||||
|
||||
Functions may start at odd addresses (`asm.cpu=scq16` sets the code and
|
||||
function alignment to 1). Inside a session set `e asm.cpu=scq16` before
|
||||
`e asm.arch=md32` (or re-select `asm.arch` afterwards): the register profile
|
||||
of the SCQ16 (`sp`/`lr` as csr14/csr15, the VU ports) is read when the arch
|
||||
session is created. The table is `isa/scq16_isa.json`, compiled into
|
||||
`scq16_opcodes.h` by `tools/gen_scq16_tables.py`. See
|
||||
[doc/scq16.md](doc/scq16.md) for the encoding model, the length rule and the
|
||||
form families.
|
||||
|
||||
### What one `pd` line is
|
||||
|
||||
* a stand-alone unit: `lw r5, 0x4(r1)`, `jal.d1 0x00001010`;
|
||||
* a packet: `{ mv r1, r3 ‖ beqz r5, #0, 0x0000100e }`: the first
|
||||
byte of the head has its bit 7 set, the head is read shifted left by one bit
|
||||
with the top bit of the second unit borrowed in (the `transformed` field of
|
||||
`aoj` shows the head as decoded); control flow only lives in the second
|
||||
slot, and its targets are relative to the packet start;
|
||||
* a vector operation: `v.alu3 op9=0x1c1 A0 B0 F1,F2,F3`: the op9 code is
|
||||
printed with its class (`v.<class>`), with an established operation name
|
||||
when there is one (`v.move.mv`, `v.mem.ld`, `v.mem.st`) and with a
|
||||
provisional name as `v.<class>.<name>?`; the fields A/B/F1-F3 are shown raw;
|
||||
* a bundle: `vbundle v.mem.ld op9=0x00a … ‖ add r2, r6 ‖ add r3, r1`: a
|
||||
32-bit vector operation and two 15-bit scalar slots in 8 bytes.
|
||||
|
||||
Provisional mnemonics carry a `?` (`sel?`, `cmov.leu?`, `vrd?`, `vwr?`,
|
||||
`vpmem?`, `lhu.post?`, `ld46?`, `sqr?`, `sra?`, `vwait?`…): the encoding is fixed, the
|
||||
operation is not. Family placeholders (`op41`, `op43`, `op67`, `op6f`, `alu41`…) print
|
||||
their fields and are not named. Both are OPEN readings: `aoj` reports them with
|
||||
`open: true` and `reading: provisional | placeholder` (`established` otherwise, and
|
||||
`hypothetical: true` when the ESIL is the reading of a hypothesis), and an open
|
||||
reading without semantics has the uniform ESIL marker `REF,ALT,open` (no effect).
|
||||
|
||||
### Analysis and ESIL
|
||||
|
||||
`aoj` gives the type, `jump`/`fail` (fall-through after the delay slots,
|
||||
which are counted in instructions: `.d1` one, `.d2` two), `delay`, the loop
|
||||
end of `do` as a reference (`ptr`) with the count in `reg`/`val`, loads and
|
||||
stores with `refptr`/`ireg`/`disp`, the stack ops, and an `opex` with the
|
||||
`shape` (unit/packet/bundle), the `units[]` (slot, address, size, mnemonic,
|
||||
form, confidence, operands) and `parallel`.
|
||||
|
||||
The ESIL covers the scalar forms: a packet is emitted as A followed by B with
|
||||
the registers that B reads and A writes copied to the temporaries `t0-t3`
|
||||
first (parallel semantics), delayed transfers use `SETJT`/`SETD` so that `aes`
|
||||
executes the slot before the jump (a `.d2` transfer takes two `aes` steps),
|
||||
memory addresses are cut to 32 bits, `do` writes `lc0/le0/ls0`, division fills
|
||||
`a0l`/`a0h`. The VU scalar ports are registers (`vu0-vu31` for `vget`,
|
||||
`v0-v31` as the scalar shadow of `vbcast`, `va0-va7`, `vp0-vp7`, `vs0-vs15`,
|
||||
`vb1_*`/`vb3_*`/`vb5_*`, `udf0-udf31`) and every vector operation is the custom
|
||||
op `vop` (op9, A, B, F1, F2, F3). `vop` models the three established vector
|
||||
operations on a vector register file `vr0-vr31` (128 bytes each, shown as the
|
||||
256-bit quarters `vrK_0..vrK_3`): `v.mem.ld` loads `va[A]` halves from the
|
||||
pointer `vp[2*F2 + F3[4]]` into `vr[F1 >> 2]`, `v.mem.st` stores them from `vr0`,
|
||||
both post-incrementing the pointer, and `v.move.mv` copies `vr[F3]` into
|
||||
`vr[F1]`; every other vector op has no effect. `vbcast v_k, rs` / `vbcast.i`
|
||||
write the scalar port `v_k` and the plugin broadcasts the low 16 bits to the 64
|
||||
lanes of `vr_k`. Forms without an established operation have the marker ESIL
|
||||
`REF,ALT,open`, except the hypothetical readings flagged in the table (among them
|
||||
the packing of `op41.fld`, carried by the ISA source; the file of
|
||||
plugin hypotheses `isa/scq16_hyp.json` is empty). `ctz` of a zero operand gives
|
||||
-1 in the ESIL (`31 - clz(0)`); whether the hardware returns 32 is open.
|
||||
|
||||
Registers: `r0-r31`, `pc`, `sr`/`ipc`/`isr`/`lf`, the loop registers
|
||||
`ls0-2`/`le0-2`/`lc0-2`, `sp` and `lr` as the special registers csr14/csr15
|
||||
(the public MD32 ABI: arguments r3-r6, return r1; r16-r31 are callee-saved,
|
||||
r0-r15 caller-saved), the accumulator `a0` (`a0l`/`a0h`), the VU state.
|
||||
|
||||
The data-space bases (main data memory at 0, the I/O window at 0x8000, the
|
||||
second data memory at 0x40000) can be added as flags with
|
||||
`. tools/scq16_flags.r2`; the data memory is little-endian while the code is
|
||||
big-endian. `j.d1 56` with the top bits of its second byte clear is decided by
|
||||
its target (see doc/scq16.md).
|
||||
|
||||
## Analysis and emulation
|
||||
|
||||
The MS15E30 decoder provides operation types, direct targets, register-indirect
|
||||
jumps/calls, returns, condition codes, delay counts, memory widths and signedness,
|
||||
operand values, JSON operands, and the register profile. Relative targets wrap
|
||||
at 32 bits. Delay-slot counts are in decoded instructions/bundles; the
|
||||
fallthrough address is computed from their actual lengths when lookahead is
|
||||
available. If lookahead is insufficient, delayed fallthrough remains unknown.
|
||||
|
||||
ESIL covers register/immediate moves, ordinary integer arithmetic and logic,
|
||||
logical/arithmetic shifts, leading-bit counts, scalar min/max, conditional
|
||||
inversion, multiplication, loads/stores, and immediate control flow,
|
||||
including signed/unsigned comparisons. It does not model carry/borrow flags,
|
||||
DSP saturation/rounding, interrupt status restoration, delayed control-flow
|
||||
execution, hardware-loop execution, or parallel bundle execution. These
|
||||
instructions still disassemble. Hardware-loop setup reports the loop-end
|
||||
reference; automatic loop back edges are not inferred.
|
||||
|
||||
A packed pair is one four-byte decode unit, displayed as `slot0 | slot1`.
|
||||
Control flow in its second slot is retained. Other pairs have `unk` as their
|
||||
aggregate operation type, and operand JSON records their slot numbers. This
|
||||
preserves decode boundaries without inventing a sequential execution model.
|
||||
Program and data memory are separate on MD32; r2's usual flat memory view needs
|
||||
appropriate maps for your firmware before memory emulation is useful.
|
||||
|
||||
## Verification
|
||||
|
||||
```sh
|
||||
make test
|
||||
```
|
||||
|
||||
This runs native decoder/parser tests, exhaustive halfword/truncation checks, actual r2
|
||||
plugin/analysis/ESIL tests, and checks all **1,128 functions / 100,275 instruction
|
||||
lengths** against the supplied uSIP inventory. The original private `dsp.bin` and
|
||||
`DbgInfo` files are not required.
|
||||
|
||||
Optional independent vendor comparison (see [research notes](doc/research.md)
|
||||
for downloads and checksums):
|
||||
|
||||
```sh
|
||||
python3 -m venv /tmp/md32-verify
|
||||
/tmp/md32-verify/bin/pip install unicorn
|
||||
/tmp/md32-verify/bin/python test/test_oracle.py /tmp/md32-objdump
|
||||
```
|
||||
|
||||
The test emulates the vendor's original x86-64 disassembly function using
|
||||
Unicorn and compares decoded text, operands, validity, and lengths. Use
|
||||
`--quick` for a smaller run or `--firmware firmware.be.bin` to add a firmware
|
||||
image. The checked run included **141,924 cases with zero mismatches**, including
|
||||
all halfword patterns, randomized operands for every vendor instruction form,
|
||||
packed pairs, and the MT8173 VPU program image.
|
||||
|
||||
See [doc/research.md](doc/research.md) for provenance, the binutils findings,
|
||||
MD380 distinction, and remaining research questions.
|
||||
|
||||
## Firmware exploration and strict ESIL execution
|
||||
|
||||
The newer `third_party/v2/r2pkg` bundle adds BRP and a CSV inventory covering
|
||||
1,301 functions. `tools/analyze_firmware.py` reports the startup probes,
|
||||
purpose/structure, points of interest, missing encodings, string scan, mapping
|
||||
conflicts and plugin fixes, and writes the complete listings plus the
|
||||
three-image loader script into a local `usipdata/` directory. Those artifacts
|
||||
are derived from the third-party firmware, so the directory is gitignored and
|
||||
not shipped.
|
||||
|
||||
```sh
|
||||
make test
|
||||
python3 tools/analyze_firmware.py
|
||||
r2 -a md32 -c '. usipdata/load-usip.r2' malloc://1
|
||||
|
||||
tools/md32-run --cpu usip \
|
||||
--image third_party/v2/r2pkg/bin/usip_sec0.bin@0x400e0000 --vector
|
||||
```
|
||||
|
||||
The runner uses separate code/data maps. Add `--data FILE@BASE` for known data,
|
||||
`--ram BASE:SIZE` for uninitialized RAM, `--zero BASE:SIZE` for deliberately
|
||||
zeroed RAM, and `--reg NAME=VALUE` for known register state. It reports JSON and
|
||||
stops on unresolved semantics, unknown memory/register state or unmodeled MMIO.
|
||||
A reported stop is an analysis result, not a successful firmware boot. The
|
||||
supplied uSIP reset/startup probes currently complete zero instructions.
|
||||
Loaded 100 of 311 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user