Hi everyone, I've just got around to playing with Roc, but I can't run hello-world or rocLovesRust/rocLovesZig/rocLovesC without getting a segfault. I've tried running different versions of the nightly build as well as installing nix and building roc from source. I'm running Manjaro (an Arch Linux derivative) on an x86-64 laptop.
Any ideas?
maybe try cargo run -- run --linker=legacy examples/platformSwitching/rocLovesZig.roc
if nothing else that should give better debug info, my next step would be to see what a debugger says about that segfault
Oh that worked, thanks @Folkert de Vries! It seems -- run --linker=legacy
is what I needed. Do you know why?
it uses your system linker, rather than our custom surgical linker. Your OS must do/expect something that our linker does not currently support
@Brendan Hansknecht what should we do in this case? open an issue for later? collect the elf files that cause issues, or is this a known issue?
Yeah, an issue with elf files would be great as a starting point. Might have to get them to run the surgical linker in verbose mode as well (though I don't think we currently have a way to toggle that without editing source code)
ok, let's see if we can do this. To get verbose output, find in crates/linker/src/lib.rs
preprocess(
target,
dynhost.to_str().unwrap(),
metadata.to_str().unwrap(),
preprocessed_host_path.to_str().unwrap(),
&dummy_lib,
false,
false,
)
}
pub fn link_preprocessed_host(
target: &Triple,
host_input_path: &Path,
roc_app_obj: &Path,
binary_path: &Path,
) {
let metadata = host_input_path.with_file_name("metadata");
surgery(
roc_app_obj.to_str().unwrap(),
metadata.to_str().unwrap(),
binary_path.to_str().unwrap(),
false,
false,
target,
)
}
and just change those 4 false
bools to true
. Then do cargo run -- run examples/platformSwitching/rocLovesZig.roc
again, without the linker=legacy
this time. It should print a lot of stuff related to linking. Can you put that in a gist and share it here?
here we go: https://gist.github.com/nickgravgaard/fddeecf3b34d4d05d93404e3463aa8d6
thanks, I made https://github.com/roc-lang/roc/issues/4042. Can you maybe add there the files
examples/platform-switching/rocLovesZig
examples/platform-switching/zig-platform/preprocessedhost
Done :smile:
Now I have another problem. I can run various command line examples by specifying the linker as you suggested above, but I have a problem with the GUI example. Here's what I get from inside a nix shell:
$ cargo run -- run --linker=legacy examples/gui/Hello.roc
Finished dev [unoptimized + debuginfo] target(s) in 0.31s
Running `target/debug/roc run --linker=legacy examples/gui/Hello.roc`
π¨ Rebuilding platform...
/nix/store/vhf2cr6immz4qdxd83y025fnxim8mmfg-binutils-2.38/bin/ld: examples/gui/platform/host.o:(.data._rust_extern_with_linkage___dso_handle+0x0): undefined reference to `__dso_handle'
/nix/store/vhf2cr6immz4qdxd83y025fnxim8mmfg-binutils-2.38/bin/ld: /nix/store/6f66prpgx1qx4n6k450sxs3d157ia1ps-glibc-2.35-163/lib/libc_nonshared.a(pthread_atfork.oS): in function `__pthread_atfork':
(.text+0x7): undefined reference to `__dso_handle'
/nix/store/vhf2cr6immz4qdxd83y025fnxim8mmfg-binutils-2.38/bin/ld: examples/gui/hello-gui: hidden symbol `__dso_handle' isn't defined
/nix/store/vhf2cr6immz4qdxd83y025fnxim8mmfg-binutils-2.38/bin/ld: final link failed: bad value
1 error and 0 warnings found in 37699 ms.
Running program anywayβ¦
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Os { code: 2, kind: NotFound, message: "No such file or directory" }', crates/cli/src/lib.rs:639:61
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace```
thanks. Clearly something is not right with the linker on your system. @Anton does this look familiar at all?
I wonder if it might be easier to fix the surgical linking bug than to debug what's wrong with ld
:thinking:
maybe with a pair programming session?
I've got to go now, but I'll be around tomorrow from 9am to 4pm UK time if you need me
The undefined reference to __dso_handle
is a known issue when we use a GUI and the legacy linker, we always ended up using the surgical linker instead. I will write up an issue.
Here's the new issue: https://github.com/roc-lang/roc/issues/4049
Can anyone give me some pointers about how I might try to fix it? I'm happy to pair as @Richard Feldman suggested.
I'm going to take a look today, but pointers around fixing may be hard. Just a lot of potential problems. Likely starting with objdump and gdb to see what they say.
Yeah #4049 may be difficult and since the surgical linker is the default it may be best to attempt to fix #4042 first.
For #4042 it would be helpful to add the output of valgrind --leak-check=full --track-origins=yes ./examples/hello-world/helloWorld
to the issue.
Oh, i just realized this is a different issue than #4042....oops. I guess I mixed up the threads.
This is strange. It looks like the helloWorld binary works when run through valgrind but not when run directly:
[nick@nick-x270 roc]$ cargo run examples/hello-world/main.roc
<lots of debug info snipped>
Segmentation fault
[nick@nick-x270 roc]$ ./examples/hello-world/helloWorld
Segmentation fault
[nick@nick-x270 roc]$ valgrind --leak-check=full --track-origins=yes ./examples/hello-world/helloWorld
==60130== Memcheck, a memory error detector
==60130== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
==60130== Using Valgrind-3.19.0 and LibVEX; rerun with -h for copyright info
==60130== Command: ./examples/hello-world/helloWorld
==60130==
Hello, World!
==60130==
==60130== HEAP SUMMARY:
==60130== in use at exit: 0 bytes in 0 blocks
==60130== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==60130==
==60130== All heap blocks were freed -- no leaks are possible
==60130==
==60130== For lists of detected and suppressed errors, rerun with: -s
==60130== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Am I doing something wrong?
The executable by itself will also work, we've seen this stuff before, I'll write up an issue.
@Anton what do you mean by "The executable by itself will also work". Isn't that what I'm doing when I run "./examples/hello-world/helloWorld"? (which segfaults when I do it on line 4 of the console output above)
Oops, yes this is different
Yeah, this makes no sense :p
Yeah, i was just doing some testing and realized the same. Executable is valid
What happens if you run directly? What is the actual output?
[nick@nick-x270 roc]$ ./examples/hello-world/helloWorld
Segmentation fault
If I run it using cargo run -- run examples/hello-world/main.roc
I get this output: https://gist.github.com/nickgravgaard/56f1bb23ff088df8aaada11930cbf90a
so the "running" part produces no output whatsoever?
that gist mostly shows the verbose surgical linker output
That's right, I don't see anything except the Segmentation fault
text
Can you run it with gdb or lldb?
Also, could you share the output of ldd <segfaulting executable>
Here's the output from ldd
:
[nick@nick-x270 roc]$ ldd ./examples/hello-world/helloWorld
linux-vdso.so.1 (0x00007f44fd90f000)
libm.so.6 => /nix/store/6f66prpgx1qx4n6k450sxs3d157ia1ps-glibc-2.35-163/lib/libm.so.6 (0x00007f44fd7ec000)
libpthread.so.0 => /nix/store/6f66prpgx1qx4n6k450sxs3d157ia1ps-glibc-2.35-163/lib/libpthread.so.0 (0x00007f44fd7e7000)
libdl.so.2 => /nix/store/6f66prpgx1qx4n6k450sxs3d157ia1ps-glibc-2.35-163/lib/libdl.so.2 (0x00007f44fd7e0000)
librt.so.1 => /nix/store/6f66prpgx1qx4n6k450sxs3d157ia1ps-glibc-2.35-163/lib/librt.so.1 (0x00007f44fd7db000)
libutil.so.1 => /nix/store/6f66prpgx1qx4n6k450sxs3d157ia1ps-glibc-2.35-163/lib/libutil.so.1 (0x00007f44fd7d6000)
libc.so.6 => /nix/store/6f66prpgx1qx4n6k450sxs3d157ia1ps-glibc-2.35-163/lib/libc.so.6 (0x00007f44fd5cc000)
/nix/store/6f66prpgx1qx4n6k450sxs3d157ia1ps-glibc-2.35-163/lib/ld-linux-x86-64.so.2 => /nix/store/6f66prpgx1qx4n6k450sxs3d157ia1ps-glibc-2.35-163/lib64/ld-linux-x86-64.so.2 (0x00007f44fd911000)
gdb
complains, and I don't have lldb
installed in this nix shell:
[nick@nick-x270 roc]$ gdb
gdb: /nix/store/cs16l9whsq2mgydlg0j4x517z4qr861k-gcc-11.3.0-lib/lib/libstdc++.so.6: version `GLIBCXX_3.4.30' not found (required by gdb)
gdb: /nix/store/cs16l9whsq2mgydlg0j4x517z4qr861k-gcc-11.3.0-lib/lib/libstdc++.so.6: version `GLIBCXX_3.4.30' not found (required by /usr/lib/libsource-highlight.so.4)
gdb: /nix/store/cs16l9whsq2mgydlg0j4x517z4qr861k-gcc-11.3.0-lib/lib/libstdc++.so.6: version `GLIBCXX_3.4.30' not found (required by /usr/lib/libboost_regex.so.1.79.0)
[nick@nick-x270 roc]$ lldb
bash: lldb: command not found
I'm available to pair now if it helps
I'm installing lldb now
I am going to guess that it is a versioning issue between nix versions of those libraries and your system versions of the libraries. Not sure a fix at the moment, but that is my base guess.
Also, sadly can't pair now.
As in, the platform is pulling in system libraries when it builds, but when the app runs the dynamic library resolution pulls in the nix versions. Some libc call or setup or something has versioning issues that lead to the segfault.
One test would be: completely out of anything nix, run the precompiled nightly build of roc on a cleaned hello world.
No, that doesn't work. I had segfaults running hello-world using the precompiled nightly build before I installed nix.
Interesting. Can you run ldd
outside of nix on that? It shouldn't point to nix store stuff.
$ ldd examples/hello-world/helloWorld
linux-vdso.so.1 => linux-vdso.so.1 (0x00007ffccad5c000)
libm.so.6 => /usr/lib/libm.so.6 (0x00007f11fbae3000)
libc.so.6 => /usr/lib/libc.so.6 (0x00007f11fb8fc000)
/lib64/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007f11fbc37000)
Here's lldb too
$ lldb examples/hello-world/helloWorld
/home/nick/.nix-profile/bin/lldb: error while loading shared libraries: liblzma.so.5: cannot open shared object file: No such file or directory
Wait...error loading a shared library that the executable didn't even request?
I guess you can try seeing what it takes to install liblzma on arch?
Last updated: Jul 06 2025 at 12:14 UTC