https://llvm.org/bugs/show_bug.cgi?id=26243
Bug ID: 26243 Summary: BPF target: relocation records generated for non-map data Product: new-bugs Version: unspecified Hardware: PC OS: Linux Status: NEW Severity: normal Priority: P Component: new bugs Assignee: unassignedb...@nondot.org Reporter: dan...@iogearbox.net CC: llvm-bugs@lists.llvm.org Classification: Unclassified I've noticed tc loader inserting map relocations where there are actually none. I believe also other loaders might be affected (libbpf, etc). Debugging this issue further shows that the ELF file I was working with had couple of other relocations besides maps. I have some test cases attached below. # llc --version LLVM (http://llvm.org/): LLVM version 3.8.0svn Optimized build. Built Jan 9 2016 (02:08:10). Default target: x86_64-unknown-linux-gnu Host CPU: ivybridge Registered Targets: bpf - BPF (host endian) bpfeb - BPF (big endian) bpfel - BPF (little endian) x86 - 32-bit X86: Pentium-Pro and above x86-64 - 64-bit X86: EM64T and AMD64 *** Test case: #include <iproute2/bpf_api.h> union v6addr { struct { __u32 p1; __u32 p2; __u32 p3; __u32 p4; }; __u8 addr[16]; }; static void (*data_barrier)(void *key) = (void *) 42; #define X { .addr = { 0xef, 0xab, 0xef, 0xab, 0xef, 0xab, 0xef, 0xab, 0xef, 0xcb, 0, 0, 0, 0, 0, 0xff } } __section("foo") int bar(struct __sk_buff *skb) { union v6addr x = X; data_barrier(&x); return -1; } BPF_LICENSE("GPL"); *** Disassembly: The code generated the relocation record of .Lbar.x: # clang -O2 -target bpf -c foo.c -S -o - .text .section foo,"ax",@progbits .globl bar .align 8 bar: # @bar # BB#0: ld_64 r1, <MCOperand Expr:(.Lbar.x)> ldw r2, 0(r1) ldw r1, 4(r1) slli r1, 32 or r1, r2 std -8(r10), r1 std -16(r10), r1 mov r1, r10 addi r1, -16 call 42 ld_64 r0, 4294967295 ret .section .rodata.cst16,"aM",@progbits,16 .align 4 # @bar.x .Lbar.x: .ascii "\357\253\357\253\357\253\357\253\357\313\000\000\000\000\000\377" .section license,"aw",@progbits .globl ____license # @____license ____license: .asciz "GPL" *** ELF data: # readelf -a foo.o [...] Section Headers: [Nr] Name Type Address Offset Size EntSize Flags Link Info Align [ 0] NULL 0000000000000000 00000000 0000000000000000 0000000000000000 0 0 0 [ 1] .strtab STRTAB 0000000000000000 00000138 0000000000000045 0000000000000000 0 0 1 [ 2] .text PROGBITS 0000000000000000 00000040 0000000000000000 0000000000000000 AX 0 0 4 [ 3] foo PROGBITS 0000000000000000 00000040 0000000000000070 0000000000000000 AX 0 0 8 [ 4] .relfoo REL 0000000000000000 00000128 0000000000000010 0000000000000010 7 3 8 [ 5] .rodata.cst16 PROGBITS 0000000000000000 000000b0 0000000000000010 0000000000000010 AM 0 0 4 [ 6] license PROGBITS 0000000000000000 000000c0 0000000000000004 0000000000000000 WA 0 0 1 [ 7] .symtab SYMTAB 0000000000000000 000000c8 0000000000000060 0000000000000018 1 2 8 [...] Relocation section '.relfoo' at offset 0x128 contains 1 entries: Offset Info Type Sym. Value Sym. Name 000000000000 000100000001 unrecognized: 1 0000000000000000 .Lbar.x The decoding of unwind sections for machine type None is not currently supported. Symbol table '.symtab' contains 4 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000000000000000 0 NOTYPE LOCAL DEFAULT 5 .Lbar.x 2: 0000000000000000 0 NOTYPE GLOBAL DEFAULT 6 ____license 3: 0000000000000000 0 NOTYPE GLOBAL DEFAULT 3 bar # readelf -x 5 foo.o Hex dump of section '.rodata.cst16': 0x00000000 efabefab efabefab efcb0000 000000ff ................ I could probably change the tc loader to handle such cases and fix up the ld_64 instruction from the relocation information. But something else seems still odd to me, if I do: #include <iproute2/bpf_api.h> union v6addr { struct { __u32 p1; __u32 p2; __u32 p3; __u32 p4; }; __u8 addr[16]; }; static void (*data_barrier)(void *key) = (void *) 42; #define X { .addr = { 0xef, 0xab, 0xef, 0xab, 0xef, 0xab, 0xef, 0xab, 0xef, 0xcb, 0, 0, 0, 0, 0, 0xff } } __section("foo") int bar(struct __sk_buff *skb) { char fmt[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; union v6addr x = X; data_barrier(&x); data_barrier(fmt); return -1; } BPF_LICENSE("GPL"); Then the disassembly looks: # clang -O2 -target bpf -c test.c -S -o - .text .section foo,"ax",@progbits .globl bar .align 8 bar: # @bar # BB#0: mov r1, 97 sth -4(r10), r1 mov r1, 1633771873 stw -8(r10), r1 ld_64 r1, 7016996765293437281 std -16(r10), r1 std -24(r10), r1 std -32(r10), r1 std -40(r10), r1 std -48(r10), r1 std -56(r10), r1 std -64(r10), r1 ld_64 r1, <MCOperand Expr:(.Lbar.x)> ldw r2, 0(r1) ldw r1, 4(r1) slli r1, 32 or r1, r2 std -72(r10), r1 std -80(r10), r1 mov r1, r10 addi r1, -80 call 42 mov r1, r10 addi r1, -64 call 42 ld_64 r0, 4294967295 ret .section .rodata.str1.1,"aMS",@progbits,1 .Lbar.fmt: # @bar.fmt .asciz "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" .section .rodata.cst16,"aM",@progbits,16 .align 4 # @bar.x .Lbar.x: .ascii "\357\253\357\253\357\253\357\253\357\313\000\000\000\000\000\377" .section license,"aw",@progbits .globl ____license # @____license ____license: .asciz "GPL" So, Lbar.fmt doesn't seem to be referenced. It seems this is a bug? There's just one relocation record, which is for Lbar.x: Section Headers: [Nr] Name Type Address Offset Size EntSize Flags Link Info Align [ 0] NULL 0000000000000000 00000000 0000000000000000 0000000000000000 0 0 0 [ 1] .strtab STRTAB 0000000000000000 000001f8 0000000000000054 0000000000000000 0 0 1 [ 2] .text PROGBITS 0000000000000000 00000040 0000000000000000 0000000000000000 AX 0 0 4 [ 3] foo PROGBITS 0000000000000000 00000040 00000000000000f0 0000000000000000 AX 0 0 8 [ 4] .relfoo REL 0000000000000000 000001e8 0000000000000010 0000000000000010 8 3 8 [ 5] .rodata.str1.1 PROGBITS 0000000000000000 00000130 000000000000003e 0000000000000001 AMS 0 0 1 [ 6] .rodata.cst16 PROGBITS 0000000000000000 00000170 0000000000000010 0000000000000010 AM 0 0 4 [ 7] license PROGBITS 0000000000000000 00000180 0000000000000004 0000000000000000 WA 0 0 1 [ 8] .symtab SYMTAB 0000000000000000 00000188 0000000000000060 0000000000000018 1 2 8 Key to Flags: W (write), A (alloc), X (execute), M (merge), S (strings) I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown) O (extra OS processing required) o (OS specific), p (processor specific) There are no section groups in this file. There are no program headers in this file. Relocation section '.relfoo' at offset 0x1e8 contains 1 entries: Offset Info Type Sym. Value Sym. Name 000000000068 000100000001 unrecognized: 1 0000000000000000 .Lbar.x The decoding of unwind sections for machine type None is not currently supported. Symbol table '.symtab' contains 4 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000000000000000 0 NOTYPE LOCAL DEFAULT 6 .Lbar.x 2: 0000000000000000 0 NOTYPE GLOBAL DEFAULT 7 ____license 3: 0000000000000000 0 NOTYPE GLOBAL DEFAULT 3 bar But nevertheless, .Lbar.fmt shouldn't be a relocation record, because fixing this up in the loader seems like a huge headache. That data can only be stored in the eBPF stack, so the loader would need to start dissecting this string data into eBPF instructions and mess with the actual eBPF program code to place this into the stack manually. While it could work for ld_64 relocs, I believe this seems not intended for strings at least. There seems to be even stranger stuff (or, perhaps it's expected and I only haven't seen it before): I have another object file generated by clang which is similar to union v6addr x = X; kind of initialization, where we get a .rodata section without postfix name, it looks like: [...] Section Headers: [Nr] Name Type Address Offset Size EntSize Flags Link Info Align [ 0] NULL 0000000000000000 00000000 0000000000000000 0000000000000000 0 0 0 [ 1] .strtab STRTAB 0000000000000000 000008e8 000000000000009b 0000000000000000 0 0 1 [ 2] .text PROGBITS 0000000000000000 00000040 0000000000000000 0000000000000000 AX 0 0 4 [ 3] from-p1 PROGBITS 0000000000000000 00000040 0000000000000728 0000000000000000 AX 0 0 8 [ 4] .relfrom-p1 REL 0000000000000000 000008c8 0000000000000020 0000000000000010 8 3 8 [ 5] maps PROGBITS 0000000000000000 00000768 0000000000000018 0000000000000000 WA 0 0 4 [ 6] license PROGBITS 0000000000000000 00000780 0000000000000004 0000000000000000 WA 0 0 1 [ 7] .rodata PROGBITS 0000000000000000 00000784 0000000000000006 0000000000000000 A 0 0 1 [ 8] .symtab SYMTAB 0000000000000000 00000790 0000000000000138 0000000000000018 1 10 8 Key to Flags: W (write), A (alloc), X (execute), M (merge), S (strings) I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown) O (extra OS processing required) o (OS specific), p (processor specific) There are no section groups in this file. There are no program headers in this file. Relocation section '.relfrom-p1' at offset 0x8c8 contains 2 entries: Offset Info Type Sym. Value Sym. Name 000000000070 000900000001 unrecognized: 1 0000000000000000 .rodata 000000000628 000b00000001 unrecognized: 1 0000000000000000 mymap The decoding of unwind sections for machine type None is not currently supported. Symbol table '.symtab' contains 13 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 00000000000004b8 0 NOTYPE LOCAL DEFAULT 3 LBB0_10 2: 00000000000004e8 0 NOTYPE LOCAL DEFAULT 3 LBB0_12 3: 0000000000000588 0 NOTYPE LOCAL DEFAULT 3 LBB0_15 4: 0000000000000708 0 NOTYPE LOCAL DEFAULT 3 LBB0_20 5: 0000000000000358 0 NOTYPE LOCAL DEFAULT 3 LBB0_21 6: 0000000000000718 0 NOTYPE LOCAL DEFAULT 3 LBB0_22 7: 0000000000000378 0 NOTYPE LOCAL DEFAULT 3 LBB0_4 8: 0000000000000410 0 NOTYPE LOCAL DEFAULT 3 LBB0_6 9: 0000000000000000 0 SECTION LOCAL DEFAULT 7 10: 0000000000000000 0 NOTYPE GLOBAL DEFAULT 6 ____license 11: 0000000000000000 0 NOTYPE GLOBAL DEFAULT 5 mymap 12: 0000000000000000 0 NOTYPE GLOBAL DEFAULT 3 handle_ingress # readelf -x 7 foo.o Hex dump of section '.rodata': 0x00000000 deadbeef c0de ...... Note, the deadbeef c0de is not part of the C program itself, so this seems to come from llvm somehow. -- You are receiving this mail because: You are on the CC list for the bug.
_______________________________________________ llvm-bugs mailing list llvm-bugs@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs