diff options
author | Jiong Wang <jiong.wang@netronome.com> | 2019-01-26 12:26:02 -0500 |
---|---|---|
committer | Alexei Starovoitov <ast@kernel.org> | 2019-01-26 16:33:01 -0500 |
commit | 56cbd82ef0b3dc47a16beeebc8d9a9a9269093dc (patch) | |
tree | d4dd6f2a9bf40d89b471fcd2cb47feb81e4e6126 /kernel/bpf/disasm.c | |
parent | 092ed0968bb648cd18e8a0430cd0a8a71727315c (diff) |
bpf: disassembler support JMP32
This patch teaches disassembler about JMP32. There are two places to
update:
- Class 0x6 now used by BPF_JMP32, not "unused".
- BPF_JMP32 need to show comparison operands properly.
The disassemble format is to add an extra "(32)" before the operands if
it is a sub-register. A better disassemble format for both JMP32 and
ALU32 just show the register prefix as "w" instead of "r", this is the
format using by LLVM assembler.
Reviewed-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Signed-off-by: Jiong Wang <jiong.wang@netronome.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Diffstat (limited to 'kernel/bpf/disasm.c')
-rw-r--r-- | kernel/bpf/disasm.c | 34 |
1 files changed, 19 insertions, 15 deletions
diff --git a/kernel/bpf/disasm.c b/kernel/bpf/disasm.c index d6b76377cb6e..de73f55e42fd 100644 --- a/kernel/bpf/disasm.c +++ b/kernel/bpf/disasm.c | |||
@@ -67,7 +67,7 @@ const char *const bpf_class_string[8] = { | |||
67 | [BPF_STX] = "stx", | 67 | [BPF_STX] = "stx", |
68 | [BPF_ALU] = "alu", | 68 | [BPF_ALU] = "alu", |
69 | [BPF_JMP] = "jmp", | 69 | [BPF_JMP] = "jmp", |
70 | [BPF_RET] = "BUG", | 70 | [BPF_JMP32] = "jmp32", |
71 | [BPF_ALU64] = "alu64", | 71 | [BPF_ALU64] = "alu64", |
72 | }; | 72 | }; |
73 | 73 | ||
@@ -136,23 +136,22 @@ void print_bpf_insn(const struct bpf_insn_cbs *cbs, | |||
136 | else | 136 | else |
137 | print_bpf_end_insn(verbose, cbs->private_data, insn); | 137 | print_bpf_end_insn(verbose, cbs->private_data, insn); |
138 | } else if (BPF_OP(insn->code) == BPF_NEG) { | 138 | } else if (BPF_OP(insn->code) == BPF_NEG) { |
139 | verbose(cbs->private_data, "(%02x) r%d = %s-r%d\n", | 139 | verbose(cbs->private_data, "(%02x) %c%d = -%c%d\n", |
140 | insn->code, insn->dst_reg, | 140 | insn->code, class == BPF_ALU ? 'w' : 'r', |
141 | class == BPF_ALU ? "(u32) " : "", | 141 | insn->dst_reg, class == BPF_ALU ? 'w' : 'r', |
142 | insn->dst_reg); | 142 | insn->dst_reg); |
143 | } else if (BPF_SRC(insn->code) == BPF_X) { | 143 | } else if (BPF_SRC(insn->code) == BPF_X) { |
144 | verbose(cbs->private_data, "(%02x) %sr%d %s %sr%d\n", | 144 | verbose(cbs->private_data, "(%02x) %c%d %s %c%d\n", |
145 | insn->code, class == BPF_ALU ? "(u32) " : "", | 145 | insn->code, class == BPF_ALU ? 'w' : 'r', |
146 | insn->dst_reg, | 146 | insn->dst_reg, |
147 | bpf_alu_string[BPF_OP(insn->code) >> 4], | 147 | bpf_alu_string[BPF_OP(insn->code) >> 4], |
148 | class == BPF_ALU ? "(u32) " : "", | 148 | class == BPF_ALU ? 'w' : 'r', |
149 | insn->src_reg); | 149 | insn->src_reg); |
150 | } else { | 150 | } else { |
151 | verbose(cbs->private_data, "(%02x) %sr%d %s %s%d\n", | 151 | verbose(cbs->private_data, "(%02x) %c%d %s %d\n", |
152 | insn->code, class == BPF_ALU ? "(u32) " : "", | 152 | insn->code, class == BPF_ALU ? 'w' : 'r', |
153 | insn->dst_reg, | 153 | insn->dst_reg, |
154 | bpf_alu_string[BPF_OP(insn->code) >> 4], | 154 | bpf_alu_string[BPF_OP(insn->code) >> 4], |
155 | class == BPF_ALU ? "(u32) " : "", | ||
156 | insn->imm); | 155 | insn->imm); |
157 | } | 156 | } |
158 | } else if (class == BPF_STX) { | 157 | } else if (class == BPF_STX) { |
@@ -220,7 +219,7 @@ void print_bpf_insn(const struct bpf_insn_cbs *cbs, | |||
220 | verbose(cbs->private_data, "BUG_ld_%02x\n", insn->code); | 219 | verbose(cbs->private_data, "BUG_ld_%02x\n", insn->code); |
221 | return; | 220 | return; |
222 | } | 221 | } |
223 | } else if (class == BPF_JMP) { | 222 | } else if (class == BPF_JMP32 || class == BPF_JMP) { |
224 | u8 opcode = BPF_OP(insn->code); | 223 | u8 opcode = BPF_OP(insn->code); |
225 | 224 | ||
226 | if (opcode == BPF_CALL) { | 225 | if (opcode == BPF_CALL) { |
@@ -244,13 +243,18 @@ void print_bpf_insn(const struct bpf_insn_cbs *cbs, | |||
244 | } else if (insn->code == (BPF_JMP | BPF_EXIT)) { | 243 | } else if (insn->code == (BPF_JMP | BPF_EXIT)) { |
245 | verbose(cbs->private_data, "(%02x) exit\n", insn->code); | 244 | verbose(cbs->private_data, "(%02x) exit\n", insn->code); |
246 | } else if (BPF_SRC(insn->code) == BPF_X) { | 245 | } else if (BPF_SRC(insn->code) == BPF_X) { |
247 | verbose(cbs->private_data, "(%02x) if r%d %s r%d goto pc%+d\n", | 246 | verbose(cbs->private_data, |
248 | insn->code, insn->dst_reg, | 247 | "(%02x) if %c%d %s %c%d goto pc%+d\n", |
248 | insn->code, class == BPF_JMP32 ? 'w' : 'r', | ||
249 | insn->dst_reg, | ||
249 | bpf_jmp_string[BPF_OP(insn->code) >> 4], | 250 | bpf_jmp_string[BPF_OP(insn->code) >> 4], |
251 | class == BPF_JMP32 ? 'w' : 'r', | ||
250 | insn->src_reg, insn->off); | 252 | insn->src_reg, insn->off); |
251 | } else { | 253 | } else { |
252 | verbose(cbs->private_data, "(%02x) if r%d %s 0x%x goto pc%+d\n", | 254 | verbose(cbs->private_data, |
253 | insn->code, insn->dst_reg, | 255 | "(%02x) if %c%d %s 0x%x goto pc%+d\n", |
256 | insn->code, class == BPF_JMP32 ? 'w' : 'r', | ||
257 | insn->dst_reg, | ||
254 | bpf_jmp_string[BPF_OP(insn->code) >> 4], | 258 | bpf_jmp_string[BPF_OP(insn->code) >> 4], |
255 | insn->imm, insn->off); | 259 | insn->imm, insn->off); |
256 | } | 260 | } |