Skip to content

Commit ad25b69

Browse files
Yonghong Songqmonnet
authored andcommitted
bpf: Add kernel/bpftool asm support for new instructions
Add asm support for new instructions so kernel verifier and bpftool xlated insn dumps can have proper asm syntax for new instructions. Acked-by: Eduard Zingerman <[email protected]> Acked-by: Quentin Monnet <[email protected]> Signed-off-by: Yonghong Song <[email protected]> Signed-off-by: Alexei Starovoitov <[email protected]>
1 parent a3e7b21 commit ad25b69

File tree

1 file changed

+51
-6
lines changed

1 file changed

+51
-6
lines changed

src/kernel/bpf/disasm.c

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,17 @@ const char *const bpf_alu_string[16] = {
8787
[BPF_END >> 4] = "endian",
8888
};
8989

90+
const char *const bpf_alu_sign_string[16] = {
91+
[BPF_DIV >> 4] = "s/=",
92+
[BPF_MOD >> 4] = "s%=",
93+
};
94+
95+
const char *const bpf_movsx_string[4] = {
96+
[0] = "(s8)",
97+
[1] = "(s16)",
98+
[3] = "(s32)",
99+
};
100+
90101
static const char *const bpf_atomic_alu_string[16] = {
91102
[BPF_ADD >> 4] = "add",
92103
[BPF_AND >> 4] = "and",
@@ -101,6 +112,12 @@ static const char *const bpf_ldst_string[] = {
101112
[BPF_DW >> 3] = "u64",
102113
};
103114

115+
static const char *const bpf_ldsx_string[] = {
116+
[BPF_W >> 3] = "s32",
117+
[BPF_H >> 3] = "s16",
118+
[BPF_B >> 3] = "s8",
119+
};
120+
104121
static const char *const bpf_jmp_string[16] = {
105122
[BPF_JA >> 4] = "jmp",
106123
[BPF_JEQ >> 4] = "==",
@@ -128,6 +145,26 @@ static void print_bpf_end_insn(bpf_insn_print_t verbose,
128145
insn->imm, insn->dst_reg);
129146
}
130147

148+
static void print_bpf_bswap_insn(bpf_insn_print_t verbose,
149+
void *private_data,
150+
const struct bpf_insn *insn)
151+
{
152+
verbose(private_data, "(%02x) r%d = bswap%d r%d\n",
153+
insn->code, insn->dst_reg,
154+
insn->imm, insn->dst_reg);
155+
}
156+
157+
static bool is_sdiv_smod(const struct bpf_insn *insn)
158+
{
159+
return (BPF_OP(insn->code) == BPF_DIV || BPF_OP(insn->code) == BPF_MOD) &&
160+
insn->off == 1;
161+
}
162+
163+
static bool is_movsx(const struct bpf_insn *insn)
164+
{
165+
return BPF_OP(insn->code) == BPF_MOV && insn->off != 0;
166+
}
167+
131168
void print_bpf_insn(const struct bpf_insn_cbs *cbs,
132169
const struct bpf_insn *insn,
133170
bool allow_ptr_leaks)
@@ -138,7 +175,7 @@ void print_bpf_insn(const struct bpf_insn_cbs *cbs,
138175
if (class == BPF_ALU || class == BPF_ALU64) {
139176
if (BPF_OP(insn->code) == BPF_END) {
140177
if (class == BPF_ALU64)
141-
verbose(cbs->private_data, "BUG_alu64_%02x\n", insn->code);
178+
print_bpf_bswap_insn(verbose, cbs->private_data, insn);
142179
else
143180
print_bpf_end_insn(verbose, cbs->private_data, insn);
144181
} else if (BPF_OP(insn->code) == BPF_NEG) {
@@ -147,17 +184,20 @@ void print_bpf_insn(const struct bpf_insn_cbs *cbs,
147184
insn->dst_reg, class == BPF_ALU ? 'w' : 'r',
148185
insn->dst_reg);
149186
} else if (BPF_SRC(insn->code) == BPF_X) {
150-
verbose(cbs->private_data, "(%02x) %c%d %s %c%d\n",
187+
verbose(cbs->private_data, "(%02x) %c%d %s %s%c%d\n",
151188
insn->code, class == BPF_ALU ? 'w' : 'r',
152189
insn->dst_reg,
153-
bpf_alu_string[BPF_OP(insn->code) >> 4],
190+
is_sdiv_smod(insn) ? bpf_alu_sign_string[BPF_OP(insn->code) >> 4]
191+
: bpf_alu_string[BPF_OP(insn->code) >> 4],
192+
is_movsx(insn) ? bpf_movsx_string[(insn->off >> 3) - 1] : "",
154193
class == BPF_ALU ? 'w' : 'r',
155194
insn->src_reg);
156195
} else {
157196
verbose(cbs->private_data, "(%02x) %c%d %s %d\n",
158197
insn->code, class == BPF_ALU ? 'w' : 'r',
159198
insn->dst_reg,
160-
bpf_alu_string[BPF_OP(insn->code) >> 4],
199+
is_sdiv_smod(insn) ? bpf_alu_sign_string[BPF_OP(insn->code) >> 4]
200+
: bpf_alu_string[BPF_OP(insn->code) >> 4],
161201
insn->imm);
162202
}
163203
} else if (class == BPF_STX) {
@@ -218,13 +258,15 @@ void print_bpf_insn(const struct bpf_insn_cbs *cbs,
218258
verbose(cbs->private_data, "BUG_st_%02x\n", insn->code);
219259
}
220260
} else if (class == BPF_LDX) {
221-
if (BPF_MODE(insn->code) != BPF_MEM) {
261+
if (BPF_MODE(insn->code) != BPF_MEM && BPF_MODE(insn->code) != BPF_MEMSX) {
222262
verbose(cbs->private_data, "BUG_ldx_%02x\n", insn->code);
223263
return;
224264
}
225265
verbose(cbs->private_data, "(%02x) r%d = *(%s *)(r%d %+d)\n",
226266
insn->code, insn->dst_reg,
227-
bpf_ldst_string[BPF_SIZE(insn->code) >> 3],
267+
BPF_MODE(insn->code) == BPF_MEM ?
268+
bpf_ldst_string[BPF_SIZE(insn->code) >> 3] :
269+
bpf_ldsx_string[BPF_SIZE(insn->code) >> 3],
228270
insn->src_reg, insn->off);
229271
} else if (class == BPF_LD) {
230272
if (BPF_MODE(insn->code) == BPF_ABS) {
@@ -279,6 +321,9 @@ void print_bpf_insn(const struct bpf_insn_cbs *cbs,
279321
} else if (insn->code == (BPF_JMP | BPF_JA)) {
280322
verbose(cbs->private_data, "(%02x) goto pc%+d\n",
281323
insn->code, insn->off);
324+
} else if (insn->code == (BPF_JMP32 | BPF_JA)) {
325+
verbose(cbs->private_data, "(%02x) gotol pc%+d\n",
326+
insn->code, insn->imm);
282327
} else if (insn->code == (BPF_JMP | BPF_EXIT)) {
283328
verbose(cbs->private_data, "(%02x) exit\n", insn->code);
284329
} else if (BPF_SRC(insn->code) == BPF_X) {

0 commit comments

Comments
 (0)