Re: [PATCH bpf-next v3 5/8] selftests/bpf: utility function to get program disassembly after jit

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, Aug 20, 2024 at 3:24 AM Eduard Zingerman <eddyz87@xxxxxxxxx> wrote:
> +
> +struct local_labels {
> +       bool print_phase;
> +       __u32 prog_len;
> +       __u32 cnt;
> +       __u32 pcs[MAX_LOCAL_LABELS];
> +       char names[MAX_LOCAL_LABELS][4];
> +};
> +
> +static const char *lookup_symbol(void *data, uint64_t ref_value, uint64_t *ref_type,
> +                                uint64_t ref_pc, const char **ref_name)
> +{
> +       struct local_labels *labels = data;
> +       uint64_t type = *ref_type;
> +       int i;
> +
> +       *ref_type = LLVMDisassembler_ReferenceType_InOut_None;
> +       *ref_name = NULL;
> +       if (type != LLVMDisassembler_ReferenceType_In_Branch)
> +               return NULL;
> +       /* Depending on labels->print_phase either discover local labels or
> +        * return a name assigned with local jump target:
> +        * - if print_phase is true and ref_value is in labels->pcs,
> +        *   return corresponding labels->name.
> +        * - if print_phase is false, save program-local jump targets
> +        *   in labels->pcs;
> +        */
> +       if (labels->print_phase) {
> +               for (i = 0; i < labels->cnt; ++i)
> +                       if (labels->pcs[i] == ref_value)
> +                               return labels->names[i];
> +       } else {
> +               if (labels->cnt < MAX_LOCAL_LABELS && ref_value < labels->prog_len)
> +                       labels->pcs[labels->cnt++] = ref_value;
> +       }
> +       return NULL;
> +}

bpftool should probably adopt similar logic
just to be consistent?


> +
> +static int disasm_insn(LLVMDisasmContextRef ctx, uint8_t *image, __u32 len, __u32 pc,
> +                      char *buf, __u32 buf_sz)
> +{
> +       int i, cnt;
> +
> +       cnt = LLVMDisasmInstruction(ctx, image + pc, len - pc, pc,
> +                                   buf, buf_sz);
> +       if (cnt > 0)
> +               return cnt;
> +       PRINT_FAIL("Can't disasm instruction at offset %d:", pc);
> +       for (i = 0; i < 16 && pc + i < len; ++i)
> +               printf(" %02x", image[pc + i]);
> +       printf("\n");
> +       return -EINVAL;
> +}
> +
> +static int cmp_u32(const void *_a, const void *_b)
> +{
> +       __u32 a = *(__u32 *)_a;
> +       __u32 b = *(__u32 *)_b;
> +
> +       if (a < b)
> +               return -1;
> +       if (a > b)
> +               return 1;
> +       return 0;
> +}
> +
> +static int disasm_one_func(FILE *text_out, uint8_t *image, __u32 len)
> +{
> +       char *label, *colon, *triple = NULL;
> +       LLVMDisasmContextRef ctx = NULL;
> +       struct local_labels labels = {};
> +       __u32 *label_pc, pc;
> +       int i, cnt, err = 0;
> +       char buf[64];
> +
> +       triple = LLVMGetDefaultTargetTriple();
> +       ctx = LLVMCreateDisasm(triple, &labels, 0, NULL, lookup_symbol);
> +       if (!ASSERT_OK_PTR(ctx, "LLVMCreateDisasm")) {
> +               err = -EINVAL;
> +               goto out;
> +       }
> +
> +       cnt = LLVMSetDisasmOptions(ctx, LLVMDisassembler_Option_PrintImmHex);
> +       if (!ASSERT_EQ(cnt, 1, "LLVMSetDisasmOptions")) {
> +               err = -EINVAL;
> +               goto out;
> +       }
> +
> +       /* discover labels */
> +       labels.prog_len = len;
> +       pc = 0;
> +       while (pc < len) {
> +               cnt = disasm_insn(ctx, image, len, pc, buf, 1);
> +               if (cnt < 0) {
> +                       err = cnt;
> +                       goto out;
> +               }
> +               pc += cnt;
> +       }
> +       qsort(labels.pcs, labels.cnt, sizeof(*labels.pcs), cmp_u32);
> +       for (i = 0; i < labels.cnt; ++i)
> +               /* use (i % 100) to avoid format truncation warning */
> +               snprintf(labels.names[i], sizeof(labels.names[i]), "L%d", i % 100);

100 here and names[..][4] are a bit of magic.
Pls add some #define and comments to clarify in the follow up.

Overall it looks to be a great improvement to selftests.
Applied.

Pls add necessary packages to bpf CI.





[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux