roc: Surgical linker can not link absolute relocations

cargo run examples/platform-switching/main.roc 
    Finished dev [unoptimized + debuginfo] target(s) in 0.14s
     Running `target/debug/roc examples/platform-switching/main.roc`
🔨 Rebuilding host...
An internal compiler expectation was broken.
This is definitely a compiler bug.
Please file an issue here: https://github.com/rtfeldman/roc/issues/new/choose
thread 'main' panicked at 'Undefined Symbol in relocation, (+49b6, Relocation { kind: Relative, encoding: Generic, size: +20, target: Symbol(SymbolIndex(+1e6)), addend: +fffffffffffffffc, implicit_addend: false }): Ok(Symbol { name: "", address: +0, size: +0, kind: Section, section: Section(SectionIndex(+8)), scope: Compilation, weak: false, flags: Elf { st_info: +3, st_other: +0 } })', crates/linker/src/lib.rs:2713:25
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

Cause:

app "rocLovesPlatforms"
    packages { pf: "rust-platform/main.roc" }
    imports []
    provides [main] to pf

main = Num.toStr (Num.sin 0)

This does work with --linker=legacy. Could this be a surgical linker issue @bhansconnect or is the true cause coming from somewhere else?

About this issue

  • Original URL
  • State: open
  • Created 2 years ago
  • Comments: 15 (15 by maintainers)

Commits related to this issue

Most upvoted comments

Made some progress. Got a few apps to compile with a moved dynamic section. Then tried to make it work in the general case and broke things. Probably gonna be a good amount of bit twiddling and minor adjustments before I get this move working for all apps. That said, definitely possible given I had it working for one app for a bit. Hopefully, I can find the right combination quickly to get this all passing and updating each address in the correct way. Once that is done, I think expanding the table should be rather simple.

The main annoyance with this work is that I get a lot of SegEnv where the app doesn’t load at all, and that is not easy to debug.

I am finally looking into this. We shall see how it goes. Currently just looking at moving the .rela.dyn section to the end of the binary. Once that is done, it should be easy to extend the section while appending the application code.

Just have to get past all of the segfaults while loading the modified binary first. I debated just duplicating the section instead of moving it to avoid all of the offset modification pains, but the section can actually get quite large. Don’t want to force extra bloat into all binaries.

Not sure if that is the place for it, but: I saw the message b306c9a when trying to run a different code I wrote. For the code below, it panics similarly as for the original issue:

app "day3"
    packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.2.0/8tCohJeXMBUnjo_zdMq0jSaqdYoCWJkWazBd4wa8cQU.tar.br" }
    imports [pf.Stdout]
    provides [main] to pf


main = 
    dbg (Num.round 5)
    dbg (Num.floor 5)
    Stdout.line "hi"

Adding --linker=legacy solves this. With the surgical linker, roc dev prints:

thread 'main' panicked at 'Undefined Symbol in relocation, (+1f2, Relocation { kind: PltRelative, encoding: Generic, size: +20, target: Symbol(SymbolIndex(+14)), addend: +fffffffffffffffc, implicit_addend: false }): Ok(Symbol { name: "round", address: +0, size: +0, kind: Unknown, section: Undefined, scope: Unknown, weak: false, flags: Elf { st_info: +10, st_other: +0 } })', crates/linker/src/elf.rs:1415:33

Can you add these cases to the error message b306c9a for the sake of future users?

Another update. Zig platforms definitely fully work except for the alignment issue for vector instructions (that said, I am still using zig 9). I was able to get a complex zig platform to work. It runs in debug builds where the alignment just happens to be correct. In release builds, it fails because of alignment issues, but the app runs until hitting a vector instruction.

So I’m not sure what zig does differently than rust and c, but currently I have some zig hosts working with the section moved to the end of the file. I think the ones that don’t work are broken due to shifting of alignment of some data. Which breaks when zig tries to load it using vector instructions. So theoretically zig host could work properly with the change, but they need some vector data alignment based fixes.

As for rust and c, really not sure. They crash before ever getting to any app code. The dynamic linker fails while trying to load them LD_DEBUG=all doesn’t seem to print anything useful for them. It just crashes after initting the shared libraries.