Skip to content

Commit d414eed

Browse files
committed
Implement support for bpf pseudocode (alias sbpf) ##arch
1 parent 8399775 commit d414eed

File tree

3 files changed

+97
-73
lines changed

3 files changed

+97
-73
lines changed

doc/fortunes.fun

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,3 +358,4 @@ You are offline. Some functionality may be unavailable.
358358
Patching instructions should be illegal
359359
Are you still watching?
360360
Downloading update 1 of 1 ...
361+
Embrace the failure

libr/arch/p/bpf/pseudo.c

Lines changed: 93 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1,85 +1,105 @@
1-
/* radare - LGPL - Copyright 2022-2024 - pancake */
1+
/* radare - LGPL - Copyright 2022-2025 - pancake */
22

33
#include <r_asm.h>
44

5-
#define MAXARGS 4
6-
#define BUFSIZE 64
7-
8-
static void concat(char *buf, size_t len, const char** args) {
9-
const char *arg;
10-
char *dest = buf;
11-
int arg_len;
12-
13-
while ((arg = *args++)) {
14-
if (snprintf (dest, len, "%s", arg) >= len) {
15-
break;
16-
}
17-
arg_len = strlen (arg);
18-
dest += arg_len;
19-
len -= arg_len;
20-
}
21-
}
5+
/* Pseudo rules for classic and extended BPF (eBPF/sBPF) */
6+
static const char *pseudo_rules[] = {
7+
/* moves / immediates */
8+
"mov/2/$1 = $2",
9+
"mov64/2/$1 = $2",
10+
"lddw/2/$1 = $2",
2211

23-
static int replace(int argc, char *argv[], char *newstr, size_t len) {
24-
int i;
25-
struct {
26-
const char *op;
27-
const char **res;
28-
} ops[] = {
29-
{ "add", (const char*[]){ argv[1], " += ", argv[2], NULL } },
30-
#if 0
31-
{ "subn", (const char*[]){ argv[1], " = ", argv[2], " - ", argv[1], NULL } },
32-
{ "xor", (const char*[]){ argv[1], " ^= ", argv[2], NULL } },
33-
#endif
34-
{ NULL }
35-
};
12+
/* arithmetic */
13+
"add/2/$1 += $2",
14+
"add64/2/$1 += $2",
15+
"sub/2/$1 -= $2",
16+
"sub64/2/$1 -= $2",
17+
"mul/2/$1 *= $2",
18+
"mul64/2/$1 *= $2",
19+
"div/2/$1 /= $2",
20+
"div64/2/$1 /= $2",
21+
"mod/2/$1 %= $2",
22+
"mod64/2/$1 %= $2",
23+
"neg/1/$1 = -$1",
24+
"neg64/1/$1 = -$1",
3625

37-
for (i = 0; ops[i].op; i++) {
38-
if (!strcmp (ops[i].op, argv[0]) && newstr) {
39-
concat (newstr, len, ops[i].res);
40-
return true;
41-
}
42-
}
26+
/* bitwise */
27+
"and/2/$1 &= $2",
28+
"and64/2/$1 &= $2",
29+
"or/2/$1 |= $2",
30+
"or64/2/$1 |= $2",
31+
"xor/2/$1 ^= $2",
32+
"xor64/2/$1 ^= $2",
4333

44-
return false;
45-
}
34+
/* shifts */
35+
"lsh/2/$1 <<= $2",
36+
"lsh64/2/$1 <<= $2",
37+
"rsh/2/$1 >>= $2",
38+
"rsh64/2/$1 >>= $2",
39+
"arsh/2/$1 >>= $2",
40+
"arsh64/2/$1 >>= $2",
4641

47-
static int tokenize(const char* in, char* out[]) {
48-
int len = strlen (in), count = 0, i = 0, tokenlen = 0, seplen = 0;
49-
char *token, *buf = (char*) in;
50-
const char* tokcharset = ", \t\n";
51-
52-
while (i < len) {
53-
tokenlen = strcspn (buf, tokcharset);
54-
token = calloc (tokenlen + 1, sizeof (char));
55-
memcpy (token, buf, tokenlen);
56-
out[count] = token;
57-
i += tokenlen;
58-
buf += tokenlen;
59-
count++;
60-
61-
seplen = strspn (buf, tokcharset);
62-
i += seplen;
63-
buf += seplen;
64-
}
65-
66-
return count;
67-
}
42+
/* byteswaps */
43+
"be16/1/$1 = bswap16($1)",
44+
"be32/1/$1 = bswap32($1)",
45+
"be64/1/$1 = bswap64($1)",
46+
"le16/1/$1 = (ut16)$1",
47+
"le32/1/$1 = (ut32)$1",
48+
"le64/1/$1 = (ut64)$1",
49+
50+
/* classic BPF xfers */
51+
"tax/0/x = a",
52+
"txa/0/a = x",
53+
54+
/* loads */
55+
"ldxw/2/$1 = $2",
56+
"ldxh/2/$1 = $2",
57+
"ldxb/2/$1 = $2",
58+
"ldxdw/2/$1 = $2",
59+
"ldw/2/$1 = $2",
60+
"ldh/2/$1 = $2",
61+
"ldb/2/$1 = $2",
62+
63+
/* stores */
64+
"stxw/2/$1 = $2",
65+
"stxh/2/$1 = $2",
66+
"stxb/2/$1 = $2",
67+
"stxdw/2/$1 = $2",
68+
"stw/2/$1 = $2",
69+
"sth/2/$1 = $2",
70+
"stb/2/$1 = $2",
71+
72+
/* atomics */
73+
"xaddw/2/$1 += $2",
74+
"xadddw/2/$1 += $2",
75+
76+
/* control flow */
77+
"call/1/$1 ()",
78+
"exit/0/return",
79+
"ret/0/return",
80+
"ja/1/goto $1",
81+
"jmp/1/goto $1",
82+
"goto/1/goto $1",
83+
84+
/* conditional branches */
85+
"jeq/3/if ($1 == $2) goto $3",
86+
"jne/3/if ($1 != $2) goto $3",
87+
"jgt/3/if ($1 > $2) goto $3",
88+
"jge/3/if ($1 >= $2) goto $3",
89+
"jlt/3/if ($1 < $2) goto $3",
90+
"jle/3/if ($1 <= $2) goto $3",
91+
"jset/3/if ($1 & $2) goto $3",
92+
/* signed variants */
93+
"jsgt/3/if ($1 > $2) goto $3",
94+
"jsge/3/if ($1 >= $2) goto $3",
95+
"jslt/3/if ($1 < $2) goto $3",
96+
"jsle/3/if ($1 <= $2) goto $3",
97+
98+
NULL
99+
};
68100

69101
static char *parse(RAsmPluginSession *aps, const char *data) {
70-
int i;
71-
char *argv[MAXARGS] = { NULL, NULL, NULL, NULL };
72-
int argc = tokenize (data, argv);
73-
74-
char *str = malloc (strlen (data) + 128);
75-
strcpy (str, data);
76-
if (!replace (argc, argv, str, BUFSIZE)) {
77-
strcpy (str, data);
78-
}
79-
for (i = 0; i < MAXARGS; i++) {
80-
free (argv[i]);
81-
}
82-
return r_str_fixspaces (str);
102+
return r_str_pseudo_transform (pseudo_rules, data);
83103
}
84104

85105
RAsmPlugin r_asm_plugin_bpf = {

libr/asm/asm.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,9 @@ R_API bool r_asm_use_parser(RAsm *a, const char *name) {
265265
name = "mips";
266266
} else if (r_str_startswith (name, "blackfin")) {
267267
name = "arm";
268+
} else if (r_str_startswith (name, "sbpf")) {
269+
// Use BPF pseudo parser for sBPF as fallback
270+
name = "bpf";
268271
}
269272

270273
RListIter *iter;

0 commit comments

Comments
 (0)