Skip to content

Miscalulation of offset with consecutive bitfields #4890

@shunghsiyu

Description

@shunghsiyu

With latest bcc v0.29.1 and LLVM 17.0.6. bcc will produce a BPF program with incorrect offset for struct my_struct.ptr in the following (incomplete) snipped:

struct my_struct
{
    long: 64;
    long: 64;
    long: 64;
    void* ptr;
};

int kprobe__netif_rx(struct pt_regs *ctx)
{
    struct event_t event = {};
    void* p1 = (void*)ctx->di;
    void* p2 = NULL;

    event.offset1 = ((long)&((struct my_struct*)p1)->ptr) - (long)p1;
    event.offset2 = ((long)&((struct my_struct*)p2)->ptr) - (long)p2;
    events.perf_submit(ctx, &event, sizeof(event));
    return 0;
}

where the produced BPF program is

Disassembly of function kprobe__netif_rx
; { // Line  34
   0:   b7 02 00 00 18 00 00 00 r2 = 24
; event.offset2 = (long)&((struct my_struct*)p2)->ptr - (long)p2; // Line  41
   1:   7b 2a f8 ff 00 00 00 00 *(u64 *)(r10 - 8) = r2
   2:   b7 02 00 00 20 00 00 00 r2 = 32
; event.offset1 = (long)&((struct my_struct*)p1)->ptr - (long)p1; // Line  40
   3:   7b 2a f0 ff 00 00 00 00 *(u64 *)(r10 - 16) = r2
; bpf_perf_event_output(ctx, (void *)bpf_pseudo_fd(1, -1), CUR_CPU_IDENTIFIER, &event, sizeof(event)); // Line  42
   ...

In the above we can see offset1 == 32 while offset2 == 24 despite both are calculating the offset of ptr.

Bisect landed me on f35dae07 (merged in #2863) which was meant to address #2827 by introducing i128 type to the BPF layout spec (supported since LLVM 11); but I don't know what's the proper fix here.

To my best knowledge this has to do with the consecutive bitfields merging together and become a singe i192 type, which will use the alignment of the largest defined type (i64:64/8 bytes before and i128:128/16 bytes after f35dae07).

%struct.my_struct = type { i192, ptr }

Note: LLVM release 18.1.0-rc1 has llvm/llvm-project@a21abc7 that made the issue go away for me. However, I cannot judge whether it is the proper fix in this case.

(CC @yonghong-song)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions