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 retqcc @philipc
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?
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 awritable
bool, which doesn't let the backend tell between read only data and read only data with relocations until you calldefine_data()
.@philipc , @m4b you would know more than me here.
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) 0x0Can you share your code where you tested this in faerie?
I'll play around with your rcc to look at it's output
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
)
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.
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.
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)
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
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) 0x0Can 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 :)
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 anobject
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).
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/faerieAlso 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 faultThe 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?)
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
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
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
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
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;
fromint main
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 retqcc @philipc
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