Stream: git-cranelift

Topic: cranelift / Issue #1354 Read only relocations should go i...


view this post on Zulip GitHub (Jan 17 2020 at 17:15):

jyn514 edited Issue #1354:

This code works fine on Ubuntu 18.04. Note that the segfault comes before main.

I am using cranelift, cranelift-object, cranelift-module 0.54.

function u0:0() -> i32 system_v {
    gv0 = symbol colocated u1:0
    sig0 = (i64) -> i32 system_v
    fn0 = u0:0 sig0

ebb0:
    v0 = global_value.i64 gv0
    v1 = load.i64 v0
    v2 = call fn0(v1)
    v3 = iconst.i32 0
    return v3
}
$ target/debug/rcc
int puts(const char *s);
static const char *index_page = "index.html";
int main() {
    puts(index_page);
}
$ ./a.out
Segmentation fault
$ gdb
(gdb) break main
Breakpoint 1 at 0x119a
(gdb) run
Starting program: /home/joshua/src/rcc/a.out

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7fc408c in ?? () from /lib/ld-musl-x86_64.so.1
(gdb) where
#0  0x00007ffff7fc408c in ?? () from /lib/ld-musl-x86_64.so.1
#1  0x0000000000000000 in ?? ()
$ target/debug/rcc -c -o a.o  # this means compile to object file but don't link
int puts(const char *s);
static const char *index_page = "index.html";
int main() {
    puts(index_page);
}
$ objdump -rd a.o

a.o:     file format elf64-x86-64


Disassembly of section .text:

0000000000000000 <main>:
   0:   40 55                   rex push %rbp
   2:   48 89 e5                mov    %rsp,%rbp
   5:   48 8d 05 00 00 00 00    lea    0x0(%rip),%rax        # c <main+0xc>
            8: R_X86_64_PC32    index_page-0x4
   c:   48 8b 00                mov    (%rax),%rax
   f:   48 89 c7                mov    %rax,%rdi
  12:   e8 00 00 00 00          callq  17 <main+0x17>
            13: R_X86_64_PLT32  puts-0x4
  17:   40 b8 00 00 00 00       rex mov $0x0,%eax
  1d:   40 5d                   rex pop %rbp
  1f:   c3                      retq

cc @philipc

view this post on Zulip GitHub (Jan 20 2020 at 13:25):

bnjbvr commented on Issue #1354:

So this is probably a bug in object. For ELF, it selects .rodata for StandardSection::ReadOnlyDataWithRel. I think that should be .data. Not sure why it works on ubuntu though, something I need to look into more.

Considering this comment, can we close the issue here, and report one on the object crate instead?

view this post on Zulip GitHub (Jan 20 2020 at 14:00):

jyn514 commented on Issue #1354:

Well, I'm worried the Cranelift API doesn't provide the backend enough information to know whether the data is a relocation or not. declare_data() only has a writable bool, which doesn't let the backend tell between read only data and read only data with relocations until you call define_data().

@philipc , @m4b you would know more than me here.

view this post on Zulip GitHub (Jan 20 2020 at 21:02):

m4b commented on Issue #1354:

@jyn514 you said static doesn't affect the miscompile/segfault, yes?

I'm wondering because we specifically added tests for this in faerie a while back, as global pointer relocations were crashing @bjorn3 's work on rust backend for rustc.

If I change the prototype STATIC_REF to no longer be writable here, it correctly places it in rodata, which you can see here:

2040    GLOBAL     OBJECT      STATIC_REF                               0x8     .rodata(15)             0x0

Can you share your code where you tested this in faerie?

I'll play around with your rcc to look at it's output

view this post on Zulip GitHub (Jan 20 2020 at 21:13):

m4b commented on Issue #1354:

Also can you provide your linkline? I can link on my machine, archlinux, it prints "index_page", and then segfaults (because it retqs itself into a non-existent libc _start)

view this post on Zulip GitHub (Jan 20 2020 at 21:15):

m4b edited a comment on Issue #1354:

Also can you provide your linkline? I can link on my machine archlinux:

m4b@efrit ::  [ ~/git/rcc ] ld -e _start -I/usr/lib/ld-linux-x86-64.so.2 -L/usr/lib/ -lc rodata.o -o rodata
ld: warning: cannot find entry symbol _start; defaulting to 0000000000401020
m4b@efrit ::  [ ~/git/rcc ] ./rodata
index.html
Segmentation fault (core dumped)

it prints "index_page", and then segfaults (because it retqs itself into a non-existent libc _start)

This makes sense due to the warning; i didn't give it a proper crt start symbol afaik.

view this post on Zulip GitHub (Jan 20 2020 at 21:16):

m4b edited a comment on Issue #1354:

Also can you provide your linkline? I can link on my machine archlinux:

m4b@efrit ::  [ ~/git/rcc ] ld -e _start -I/usr/lib/ld-linux-x86-64.so.2 -L/usr/lib/ -lc rodata.o -o rodata
ld: warning: cannot find entry symbol _start; defaulting to 0000000000401020
m4b@efrit ::  [ ~/git/rcc ] ./rodata
index.html
Segmentation fault (core dumped)

it prints "index.html", and then segfaults (because it retqs itself into a non-existent libc _start)

This makes sense due to the warning; i didn't give it a proper crt start symbol afaik.

view this post on Zulip GitHub (Jan 20 2020 at 21:18):

m4b commented on Issue #1354:

and as per @bnjbvr comment, this might not be appropriate issue tracker; iiuc, the question is whether cranelift api provides enough granularity to correctly emit relocations for read only pointers in the rodata section.

I think the answer is yes? Though I don't really know the api of cranelift at all, so I'll defer to others (though I'd be surprised if not, since bjorn3 has gotten most tests passing at this point)

view this post on Zulip GitHub (Jan 20 2020 at 21:22):

m4b edited a comment on Issue #1354:

Also can you provide your linkline? I can link on my machine archlinux:

m4b@efrit ::  [ ~/git/rcc ] ld -e _start -I/usr/lib/ld-linux-x86-64.so.2 -L/usr/lib/ -lc rodata.o -o rodata
ld: warning: cannot find entry symbol _start; defaulting to 0000000000401020
m4b@efrit ::  [ ~/git/rcc ] ./rodata
index.html
Segmentation fault (core dumped)

it prints "index.html", and then segfaults (because it retqs itself into a non-existent libc _start)

This makes sense due to the warning; i didn't give it a proper crt start symbol afaik.

EDIT

Here is a linkline that works for me, resulting binary does not segfault:

m4b@efrit ::  [ ~/git/rcc ] ld -e _start -I/usr/lib/ld-linux-x86-64.so.2 -L/usr/lib/ /usr/lib/crti.o /usr/lib/Scrt1.o /usr/lib/crtn.o -lc rodata.o -o rodata
m4b@efrit ::  [ ~/git/rcc ] ./rodata
index.html
m4b@efrit ::  [ ~/git/rcc ] echo $?
0

view this post on Zulip GitHub (Jan 20 2020 at 21:23):

m4b edited a comment on Issue #1354:

@jyn514 you said static doesn't affect the miscompile/segfault, yes?

I'm wondering because we specifically added tests for this in faerie a while back, as global pointer relocations were crashing @bjorn3 's work on rust backend for rustc.

If I change the prototype STATIC_REF to no longer be writable here, it correctly places it in rodata, which you can see here:

2040    GLOBAL     OBJECT      STATIC_REF                               0x8     .rodata(15)             0x0

Can you share your code where you tested this in faerie?

I'll play around with your rcc to look at it's output

EDIT

Btw, your C program is technically undefined; you declare it returning a int, but you return nothing from main :)

view this post on Zulip GitHub (Jan 20 2020 at 21:37):

philipc commented on Issue #1354:

I'm worried the Cranelift API doesn't provide the backend enough information to know whether the data is a relocation or not.

The API already provides this via DataContext::write_function_addr/write_data_addr, cranelift-object already uses that info, and cranelift-faerie would probably let faerie handle this instead. So yes this should be moved to an object issue, and it's trivial enough that you could patch object and test it fixes it yourself (the problem doesn't occur on my system).

view this post on Zulip GitHub (Jan 20 2020 at 23:24):

jyn514 commented on Issue #1354:

Can you share your code where you tested this in faerie?

Checkout the faerie branch on rcc: https://github.com/jyn514/rcc/tree/faerie

Also can you provide your linkline? I can link on my machine archlinux:

Interesting - if I use a linkline similar to yours, it works fine, but if I use gcc to link it segfaults:

(-bash@build-server) ~/src/rcc ▶️ ld -e _start -L/usr/lib/ /usr/lib/crti.o /usr/lib/Scrt1.o /usr/lib/crtn.o -I/lib/ld-musl-x86_64.so.1 -lc faerie.o -o faerie
(-bash@build-server) ~/src/rcc ▶️ ./faerie
(-bash@build-server) ~/src/rcc ▶️ echo $?
0
(-bash@build-server) ~/src/rcc ▶️ gcc -v faerie.o -o faerie-gcc
... truncated ...
COLLECT_GCC_OPTIONS='-v' '-o' 'faerie-gcc' '-mtune=generic' '-march=x86-64'
 /usr/libexec/gcc/x86_64-alpine-linux-musl/8.3.0/collect2 -plugin /usr/libexec/gcc/x86_64-alpine-linux-musl/8.3.0/liblto_plugin.so -plugin-opt=/usr/libexec/gcc/x86_64-alpine-linux-musl/8.3.0/lto-wrapper -plugin-opt=-fresolution=/tmp/ccNcloDj.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s --eh-frame-hdr --hash-style=gnu -m elf_x86_64 --as-needed -dynamic-linker /lib/ld-musl-x86_64.so.1 -pie -z relro -z now -o faerie-gcc /usr/lib/gcc/x86_64-alpine-linux-musl/8.3.0/../../../../lib/Scrt1.o /usr/lib/gcc/x86_64-alpine-linux-musl/8.3.0/../../../../lib/crti.o /usr/lib/gcc/x86_64-alpine-linux-musl/8.3.0/crtbeginS.o -L/usr/lib/gcc/x86_64-alpine-linux-musl/8.3.0 -L/usr/lib/gcc/x86_64-alpine-linux-musl/8.3.0/../../../../x86_64-alpine-linux-musl/lib/../lib -L/usr/lib/gcc/x86_64-alpine-linux-musl/8.3.0/../../../../lib -L/lib/../lib -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-alpine-linux-musl/8.3.0/../../../../x86_64-alpine-linux-musl/lib -L/usr/lib/gcc/x86_64-alpine-linux-musl/8.3.0/../../.. faerie.o -lssp_nonshared -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-alpine-linux-musl/8.3.0/crtendS.o /usr/lib/gcc/x86_64-alpine-linux-musl/8.3.0/../../../../lib/crtn.o
COLLECT_GCC_OPTIONS='-v' '-o' 'faerie-gcc' '-mtune=generic' '-march=x86-64'
(-bash@build-server) ~/src/rcc ▶️ ./faerie-gcc
Segmentation fault

The same is true of object.

Btw, your C program is technically undefined; you declare it returning a int, but you return nothing from main :)

For main only, returning no value is the same as returning 0: http://port70.net/~nsz/c/c11/n1570.html#5.1.2.2.3.

(the problem doesn't occur on my system)

Yes, as I mentioned this only happens on alpine (not sure why, something to do with musl?)

view this post on Zulip GitHub (Jan 20 2020 at 23:33):

jyn514 commented on Issue #1354:

Minimized gcc linker flags:

(-bash@build-server) ~/src/rcc ▶️ /usr/libexec/gcc/x86_64-alpine-linux-musl/8.3.0/collect2 -m elf_x86_64 -dynamic-linker /lib/ld-musl-x86_64.so.1 -pie -o faerie-gcc /usr/lib/Scrt1.o /usr/lib/gcc/x86_64-alpine-linux-musl/8.3.0/crtbeginS.o -L/lib/ -L/usr/lib faerie.o --no-as-needed -lc /usr/lib/gcc/x86_64-alpine-linux-musl/8.3.0/crtendS.o

view this post on Zulip GitHub (Jan 20 2020 at 23:33):

jyn514 edited a comment on Issue #1354:

Minimized gcc linker flags:

$ /usr/libexec/gcc/x86_64-alpine-linux-musl/8.3.0/collect2 -m elf_x86_64 -dynamic-linker /lib/ld-musl-x86_64.so.1 -pie -o faerie-gcc /usr/lib/Scrt1.o /usr/lib/gcc/x86_64-alpine-linux-musl/8.3.0/crtbeginS.o -L/lib/ -L/usr/lib faerie.o --no-as-needed -lc /usr/lib/gcc/x86_64-alpine-linux-musl/8.3.0/crtendS.o

view this post on Zulip GitHub (Jan 20 2020 at 23:35):

jyn514 edited a comment on Issue #1354:

Minimized gcc linker flags:

$ /usr/libexec/gcc/x86_64-alpine-linux-musl/8.3.0/collect2 -m elf_x86_64 -dynamic-linker /lib/ld-musl-x86_64.so.1 -pie -o faerie-gcc /usr/lib/Scrt1.o /usr/lib/gcc/x86_64-alpine-linux-musl/8.3.0/crtbeginS.o faerie.o -lc /usr/lib/gcc/x86_64-alpine-linux-musl/8.3.0/crtendS.o

view this post on Zulip GitHub (Jan 20 2020 at 23:37):

jyn514 commented on Issue #1354:

Passing -pie is what makes it segfault:

(-bash@build-server) ~/src/rcc ▶️ ld -e _start -L/usr/lib/ /usr/lib/crti.o /usr/lib/Scrt1.o /usr/lib/crtn.o -I/lib/ld-musl-x86_64.so.1 -lc object.o -o object
(-bash@build-server) ~/src/rcc ▶️ ./object ; echo $?
0
(-bash@build-server) ~/src/rcc ▶️ ld -pie -e _start -L/usr/lib/ /usr/lib/crti.o /usr/lib/Scrt1.o /usr/lib/crtn.o -I/lib/ld-musl-x86_64.so.1 -lc object.o -o object
(-bash@build-server) ~/src/rcc ▶️ ./object ; echo $?
Segmentation fault
139
(-bash@build-server) ~/src/rcc ▶️ ld -e _start -L/usr/lib/ /usr/lib/crti.o /usr/lib/Scrt1.o /usr/lib/crtn.o -I/lib/ld-musl-x86_64.so.1 -lc faerie.o -o faerie
(-bash@build-server) ~/src/rcc ▶️ ./faerie ; echo $?
0
(-bash@build-server) ~/src/rcc ▶️ ld -pie -e _start -L/usr/lib/ /usr/lib/crti.o /usr/lib/Scrt1.o /usr/lib/crtn.o -I/lib/ld-musl-x86_64.so.1 -lc faerie.o -o faerie
(-bash@build-server) ~/src/rcc ▶️ ./faerie ; echo $?
Segmentation fault
139

view this post on Zulip GitHub (Jan 20 2020 at 23:56):

m4b commented on Issue #1354:

For main only, returning no value is the same as returning 0: http://port70.net/~nsz/c/c11/n1570.html#5.1.2.2.3.

Ah yes, thank you for correct, you're right :) i always mix this up with return; from int main

view this post on Zulip GitHub (Jan 21 2020 at 14:54):

jyn514 closed Issue #1354:

This code works fine on Ubuntu 18.04. Note that the segfault comes before main.

I am using cranelift, cranelift-object, cranelift-module 0.54.

function u0:0() -> i32 system_v {
    gv0 = symbol colocated u1:0
    sig0 = (i64) -> i32 system_v
    fn0 = u0:0 sig0

ebb0:
    v0 = global_value.i64 gv0
    v1 = load.i64 v0
    v2 = call fn0(v1)
    v3 = iconst.i32 0
    return v3
}
$ target/debug/rcc
int puts(const char *s);
static const char *index_page = "index.html";
int main() {
    puts(index_page);
}
$ ./a.out
Segmentation fault
$ gdb
(gdb) break main
Breakpoint 1 at 0x119a
(gdb) run
Starting program: /home/joshua/src/rcc/a.out

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7fc408c in ?? () from /lib/ld-musl-x86_64.so.1
(gdb) where
#0  0x00007ffff7fc408c in ?? () from /lib/ld-musl-x86_64.so.1
#1  0x0000000000000000 in ?? ()
$ target/debug/rcc -c -o a.o  # this means compile to object file but don't link
int puts(const char *s);
static const char *index_page = "index.html";
int main() {
    puts(index_page);
}
$ objdump -rd a.o

a.o:     file format elf64-x86-64


Disassembly of section .text:

0000000000000000 <main>:
   0:   40 55                   rex push %rbp
   2:   48 89 e5                mov    %rsp,%rbp
   5:   48 8d 05 00 00 00 00    lea    0x0(%rip),%rax        # c <main+0xc>
            8: R_X86_64_PC32    index_page-0x4
   c:   48 8b 00                mov    (%rax),%rax
   f:   48 89 c7                mov    %rax,%rdi
  12:   e8 00 00 00 00          callq  17 <main+0x17>
            13: R_X86_64_PLT32  puts-0x4
  17:   40 b8 00 00 00 00       rex mov $0x0,%eax
  1d:   40 5d                   rex pop %rbp
  1f:   c3                      retq

cc @philipc

view this post on Zulip GitHub (Jan 21 2020 at 14:54):

jyn514 commented on Issue #1354:

This was fixed in object, sorry for the badly placed issue. @m4b feel free to open this in faerie if you are interested but otherwise this is fixed for me.


Last updated: Dec 23 2024 at 13:07 UTC