Skip to content

Invalid BTF produced with IPO globalopts pass #128749

@ayles

Description

@ayles

Consider the following minimal example (https://godbolt.org/z/YqbTb1znd):

// bpf.c
static int foo;

void init() {
    foo = 1000;
}

int get() {
    return foo;
}

When it is compiled with globalopts pass enabled (clang -g -c bpf.c -O1 -target bpf), foo converts to one-byte bool

static bool TryToShrinkGlobalToBoolean(GlobalVariable *GV, Constant *OtherVal) {

and its new size propagates through all of meta information, including BTF.
Verifier rejects such BTF after checking entry size inside DATASEC against referred type size.

I believe that this is not intended behavior for BTF, but not so sure about generated DWARF/symtab.

$ bpftool btf dump file ./result/bpf.o
[1] FUNC_PROTO '(anon)' ret_type_id=0 vlen=0
[2] FUNC 'init' type_id=1 linkage=global
[3] FUNC_PROTO '(anon)' ret_type_id=4 vlen=0
[4] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
[5] FUNC 'get' type_id=3 linkage=global
[6] VAR 'foo' type_id=4, linkage=static
[7] DATASEC '.bss' size=0 vlen=1
	type_id=6 offset=0 size=1 (VAR 'foo')
$ readelf --syms ./result/bpf.o 

Symbol table '.symtab' contains 14 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
...
     3: 0000000000000000     1 OBJECT  LOCAL  DEFAULT    4 foo
...
$ llvm-dwarfdump ./result/bpf.o
...
0x00000023:   DW_TAG_variable
                DW_AT_name	("foo")
                DW_AT_type	(0x00000037 "int")
                DW_AT_decl_file	("/build/source/bpf.c")
                DW_AT_decl_line	(1)
                DW_AT_location	(DW_OP_addrx 0x0, DW_OP_deref_size 0x1, DW_OP_constu 0x3e8, DW_OP_mul, DW_OP_lit0, DW_OP_plus, DW_OP_stack_value)
...

Metadata

Metadata

Assignees

No one assigned

    Labels

    ipoInterprocedural optimizationswrong-debug

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions