llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
28.03k stars 11.58k forks source link

BPF target: relocation records generated for non-map data #26617

Closed llvmbot closed 7 years ago

llvmbot commented 8 years ago
Bugzilla Link 26243
Resolution FIXED
Resolved on Jul 22, 2017 23:25
Version unspecified
OS Linux
Reporter LLVM Bugzilla Contributor
CC @4ast,@yonghong-song

Extended Description

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                       # @&#8203;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             # @&#8203;____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                       # @&#8203;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             # @&#8203;____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.

yonghong-song commented 7 years ago

Fix in 5.0 now.

yonghong-song commented 7 years ago

I am working on this bug now. The idea is during insn selection DAG2DAG translation, recognizing loads which read from read-only session and turns those loads into constants. In BPF backend DAG2DAG translation, a byte array will be constructed when first access to a readonly section (mostly a ConstantStruct data structure) and later references to the global readonly section can get data from the constructed byte array.

yonghong-song commented 8 years ago

The sanity.ll test case does not address the read-only section issue. The code is clean as it is indeed accessing the readonly string from the stack by copying, but it does not eliminate readonly section.

A simple example: yhs@ubuntu:~/tmp$ cat bar.c

include

int bar() { char str[] = "aaaaaaaaaaaaa\n";
printf(str); return -1; } yhs@ubuntu:~/tmp$ clang -O2 -target bpf -c bar.c -S -o - bar.c:4:11: warning: format string is not a string literal (potentially insecure) [-Wformat-security] printf(str); ^~~ bar.c:4:11: note: treat the string as an argument to avoid this printf(str); ^ "%s", .text .globl bar .p2align 3 bar: # @​bar

BB#0:

mov r1, 0
stb -2(r10), r1
mov r1, 2657
sth -4(r10), r1
mov r1, 1633771873
stw -8(r10), r1
ld_64   r1, 7016996765293437281
std -16(r10), r1
mov r1, r10
addi    r1, -16
call    printf
ld_64   r0, 4294967295
ret

.section    .rodata.str1.1,"aMS",@progbits,1

.Lbar.str: # @​bar.str .asciz "aaaaaaaaaaaaa\n"

1 warning generated. yhs@ubuntu:~/tmp$

The IR dump before pre instruction selection.

IR Dump Before Pre-ISel Intrinsic Lowering ; ModuleID = 'bar.ll' source_filename = "bar.c" target datalayout = "e-m:e-p:64:64-i64:64-n32:64-S128" target triple = "bpf"

@​bar.str = private unnamed_addr constant [15 x i8] c"aaaaaaaaaaaaa\0A\00", align 1

; Function Attrs: nounwind define i32 @​bar() local_unnamed_addr #​0 { %1 = alloca [15 x i8], align 1 %2 = getelementptr inbounds [15 x i8], [15 x i8] %1, i64 0, i64 0 call void @​llvm.lifetime.start(i64 15, i8 %2) #​3 call void @​llvm.memcpy.p0i8.p0i8.i64(i8 %2, i8 getelementptr inbounds ([15 x i8], [15 x i8] @​bar.str, i64 0, i64 0), i64 15, i32 1, i1 false) %3 = call i32 (i8, ...) @​printf(i8 %2) call void @​llvm.lifetime.end(i64 15, i8 %2) #​3 ret i32 -1 }

Later on, @​bar.str is turned into a readonly section string and become global. (see a similar example at http://llvm.org/releases/3.3/docs/LangRef.html)

Since all these readonly strings become global, LLVM does not try to remove them at all.

To really fix the issue, interprocedural analysis will be needed to ensure in the module, there is no reference to @​bar.str, and the payoff for non-BPF program may be small (just a few bytes in readonly section).

llvmbot commented 8 years ago

For this test the following should not be generated: ld_64 r1, <MCOperand Expr:(.Lbar.x)> ldw r2, 0(r1) ldw r1, 4(r1)

I fixed similar bug before and there is a test for it: test/CodeGen/BPF/sanity.ll foo_printf is checking that constants are not stored in memory and instead loaded directly into registers. This must be some corner case.

Do you happen to have some progress on this array initialization bug as this occurs from time to time and we have to use ugly workarounds? Thanks!

llvmbot commented 8 years ago

So, Lbar.fmt doesn't seem to be referenced. It seems this is a bug?

How data_barrier is implemented? Looks like "Lbar.fmt" is referenced and that is why a relocation record is generated?

In the code above it was:

static void (data_barrier)(void key) = (void *) 42;

I think main issue here is that there are a couple of ways where such entries can be generated (another one on the top of my head is when you declare your format string as 'const' and pass that to trace printk).

The only reloc records allowed in eBPF context would be in relation to maps, otherwise loaders cannot handle such programs.

yonghong-song commented 8 years ago

So, Lbar.fmt doesn't seem to be referenced. It seems this is a bug?

How data_barrier is implemented? Looks like "Lbar.fmt" is referenced and that is why a relocation record is generated?

Hex dump of section '.rodata': 0x00000000 deadbeef c0de ......

I have not seen this. Maybe just because I did not try a lot :-)

llvmbot commented 8 years ago

Not inlining 'inline' functions is a different 'problem'. BCC already adds 'always_inline' when it's ok to do so. backend cannot do such things, since it's too late.

Hmm yeah, that's rather unfortunate. We're not using bcc and 'normal' users that work with clang directly might have hard time debugging this ... would be nice if this works out of the box and users don't need to worry about this.

Best one could do right now is probably to point out in the loader to use __always_inline annotation when such relocs are found. :/

4ast commented 8 years ago

Not inlining 'inline' functions is a different 'problem'. BCC already adds 'always_inline' when it's ok to do so. backend cannot do such things, since it's too late.

llvmbot commented 8 years ago

Btw, the same happens with functions, too.

Simplified test case to demonstrate the issue is below. A workaround here is to annotate all functions with attribute((always_inline)).

I'd see this part here as an enhancement, maybe there's a possibility in the backend to make everything always inline w/o any annotation in the program at all? Would be nice if so.

Thanks a lot!


include <iproute2/bpf_api.h>

static int (data_barrier)(void key) = (void *) 42;

static inline int bar(struct __sk_buff *skb) { int ret = 0;

    ret += data_barrier(skb);
    ret += data_barrier(skb);
    ret += data_barrier(skb);
    ret += data_barrier(skb);
    ret += data_barrier(skb);
    ret += data_barrier(skb);
    ret += data_barrier(skb);
    ret += data_barrier(skb);
    ret += data_barrier(skb);
    ret += data_barrier(skb);
    ret += data_barrier(skb);
    ret += data_barrier(skb);
    ret += data_barrier(skb);
    ret += data_barrier(skb);
    ret += data_barrier(skb);
    ret += data_barrier(skb);
    ret += data_barrier(skb);
    ret += data_barrier(skb);
    ret += data_barrier(skb);
    ret += data_barrier(skb);
    ret += data_barrier(skb);
    ret += data_barrier(skb);
    ret += data_barrier(skb);
    ret += data_barrier(skb);
    ret += data_barrier(skb);
    ret += data_barrier(skb);
    ret += data_barrier(skb);
    ret += data_barrier(skb);
    ret += data_barrier(skb);
    ret += data_barrier(skb);
    ret += data_barrier(skb);
    ret += data_barrier(skb);
    ret += data_barrier(skb);
    ret += data_barrier(skb);
    ret += data_barrier(skb);
    ret += data_barrier(skb);
    ret += data_barrier(skb);
    ret += data_barrier(skb);
    ret += data_barrier(skb);
    ret += data_barrier(skb);
    ret += data_barrier(skb);
    ret += data_barrier(skb);
    ret += data_barrier(skb);
    ret += data_barrier(skb);
    ret += data_barrier(skb);

    return ret;

}

static inline int blb(struct __sk_buff *skb) { switch (skb->mark) { case 123: case 124: case 222: bar(skb); case 223: return -1; default: break; }

    return 0;

}

section("entry") int foo(struct sk_buff *skb) { int ret;

    if (skb->priority == 42)
            ret = blb(skb);
    else
            ret = bar(skb);

    return ret;

}

BPF_LICENSE("GPL");


clang -O2 -target bpf -c out.c -o out.o

readelf -a out.o

ELF Header: Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 Class: ELF64 Data: 2's complement, little endian Version: 1 (current) OS/ABI: UNIX - System V ABI Version: 0 Type: REL (Relocatable file) Machine: None Version: 0x1 Entry point address: 0x0 Start of program headers: 0 (bytes into file) Start of section headers: 1664 (bytes into file) Flags: 0x0 Size of this header: 64 (bytes) Size of program headers: 0 (bytes) Number of program headers: 0 Size of section headers: 64 (bytes) Number of section headers: 7 Section header string table index: 1

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 00000628 0000000000000051 0000000000000000 0 0 1 [ 2] .text PROGBITS 0000000000000000 00000040 0000000000000450 0000000000000000 AX 0 0 8 [ 3] entry PROGBITS 0000000000000000 00000490 0000000000000098 0000000000000000 AX 0 0 8 [ 4] .relentry REL 0000000000000000 00000608 0000000000000020 0000000000000010 6 3 8 [ 5] license PROGBITS 0000000000000000 00000528 0000000000000004 0000000000000000 WA 0 0 1 [ 6] .symtab SYMTAB 0000000000000000 00000530 00000000000000d8 0000000000000018 1 7 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 '.relentry' at offset 0x608 contains 2 entries: Offset Info Type Sym. Value Sym. Name 000000000058 000600000002 unrecognized: 2 0000000000000000 .text 000000000068 000600000002 unrecognized: 2 0000000000000000 .text

The decoding of unwind sections for machine type None is not currently supported.

Symbol table '.symtab' contains 9 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000000000000058 0 NOTYPE LOCAL DEFAULT 3 LBB0_4 2: 0000000000000080 0 NOTYPE LOCAL DEFAULT 3 LBB0_5 3: 0000000000000068 0 NOTYPE LOCAL DEFAULT 3 LBB0_6 4: 0000000000000088 0 NOTYPE LOCAL DEFAULT 3 LBB0_7 5: 0000000000000000 0 NOTYPE LOCAL DEFAULT 2 bar 6: 0000000000000000 0 SECTION LOCAL DEFAULT 2 7: 0000000000000000 0 NOTYPE GLOBAL DEFAULT 5 ____license 8: 0000000000000000 0 NOTYPE GLOBAL DEFAULT 3 foo

No version information found in this file.

tc filter ... bpf da obj ./out.o sec entry

Prog section 'entry' (type:3 insns:19 license:'GPL') rejected: Invalid argument (22)!

0: (61) r2 = (u32 )(r1 +32) 1: (55) if r2 != 0x2a goto pc+11 R1=ctx R2=imm42 R10=fp 2: (18) r6 = 0xffffffff 4: (61) r2 = (u32 )(r1 +8) 5: (bf) r3 = r2 6: (07) r3 += -123 7: (b7) r4 = 2 8: (2d) if r4 > r3 goto pc+2 R1=ctx R2=inv R3=inv R4=imm2 R6=inv R10=fp 9: (15) if r2 == 0xdf goto pc+7 R1=ctx R2=inv R3=inv R4=imm2 R6=inv R10=fp 10: (55) if r2 != 0xde goto pc+5 R1=ctx R2=imm222 R3=inv R4=imm2 R6=inv R10=fp 11: (85) call 0 unknown func 0

Error fetching program/map! Failed to retrieve (e)BPF data!

4ast commented 8 years ago

For this test the following should not be generated: ld_64 r1, <MCOperand Expr:(.Lbar.x)> ldw r2, 0(r1) ldw r1, 4(r1)

I fixed similar bug before and there is a test for it: test/CodeGen/BPF/sanity.ll foo_printf is checking that constants are not stored in memory and instead loaded directly into registers. This must be some corner case.

llvmbot commented 8 years ago

Hmm, thinking more about this, even for that the code should rather generate two ld_64 instructions. Fixing this up in the loader seems to be fragile as well, both ldw instructions would need to be replaced by a 2nd ld_64, and it would kind of require to mess around with registers in the loader code.

So, I think llvm backend needs to be taught if possible to not generate such relocations (but only map-related ones that were already explicitly present from the C program).

    [...]
    ld_64   r1, <MCOperand Expr:(.Lbar.x)>
    ldw     r2, 0(r1)
    ldw     r1, 4(r1)
    [...]

    .section   .rodata.cst16,"aM",@progbits,16
    .align   4                # @&#8203;bar.x

.Lbar.x: .ascii "\357\253\357\253\357\253\357\253\357\313\000\000\000\000\000\377"

llvmbot commented 8 years ago

assigned to @yonghong-song