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 | |
| 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')
| -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 | } |
