I have build GitHub - atopia/ripgrep-goa successfully using goa and copied all depot content from /home/user/ripgrep-goa/var/depot to depot on the active *GENODE GPT partition.
The following deploy file for sculpt runs the ripgrep tool successfully as a component with the expected output:
[init -> runtime -> ripgrep] 3: say hello to Genode!
[init -> runtime] child "ripgrep" exited with exit value 0
On the other hand, calling the tool as a binary in the “system shell” scenario gives the following error:
I have successfully ported another more complex rust command line tool, but run into the same error. So I hope the above solves as a minimal reproducable example.
What am I missing in order to run the CLI tool in the “system shell” scenario?
The system shell executes a binary only if located under /bin. This policy is defined by the routing rules in its configuration.
I’d recommend creating a custom shell with the additions and customizations you want, e.g., including the ripgrep tool. The following pointers may hopefully be of help:
Section 5.1 of the Applications book (PDF) explains the inner workings of Unix-like subsystems in great detail. Specifically, on page 80, you can find the ROM-routing covered.
If you want skip reading and jump right into a working example of a customized shell, you may have a look at my unix project, which I use to take as a common basis for tailored Unix-like subsystems. E.g., my m68k-sdk is a much customized version of the unix project where I added a bunch of tools like sed, make, asm56000. You can follow the latter to see the places one needs to touch in order to integrate a custom tool: pkg archives, pkg runtime, and vfs. BTW, I’ve actually expanded the ROM routing rules in this project for allowing /libexec.
When creating a custom shell project besides your existing Goa project, you will need to configure a central depot dir where both projects can meet. For including your program into your shell, first goa export your program (installing it into the depot). Then your shell can incorporate it in its pkg archives.
Following the approach of creating your custom shell gives you three advantages over the ad-hoc attempt of sneaking your custom executable into the system shell. First, you can interactively test your program in its designated environment by running the shell via goa run. Second, as your custom shell is a Goa project you can readily package, publish, and reproduce it. I.e., you can test-drive it on a remote Sculpt machine via the Goa testbed (see Section 4.4 of the Applications book) or install it on Sculpt. Third, creating your own Unix-like environment is great fun.
I followed your advice and read through the applications book, reused the configuration of the m68k-sdk project expanded by the rg.tar (artifact of the atopias ripgrep-goa) providing the rg binary at /bin/rg. After a goa export, the dependencies are available for the VM running Sculpt.
Building a customized shell is fun indeed and executes every other command provided just fine. Upon executing the rust executable, the shell comes to an error though.
Upon executing it, I get the following output in the log component:
[init -> runtime -> m68k-sdk -> /bin/bash -> 1] Warning: unable to allocate linker-area region for binary
[init -> runtime -> m68k-sdk -> /bin/bash -> 1] Error: failed to load RX segment
[init -> runtime -> m68k-sdk -> /bin/bash -> 1] Error: dynamic linker failed to copy RW segment
Error: illegal READ at address 0x0 by pager_object: pd='init -> runtime -> m68k-sdk -> /bin/bash -> 1' thread='ep' ip=0xe4228
I expected the same error as in the first post, since establishing the ROM session was already successful there, but getting a different error here really puzzles me.
Do you or atopia maybe have another hint?
The documentation and blog posts are really great and exiting reads, but for some errors my only approach is to constantly diff my build and configuration with existing examples like yours. I simply have not found an existing configuration for executing a rust binary in a shell on Sculpt/Genode though.
This means that the dynamic linker could not allocate the virtual-area your binary (rg) is linked to. This either means some else is there already, or the binary overlaps with something else.
Given that the rg tool executes fine outside the Unix-like shell environment, I suspect that the problem is related to execve. After forking the new process, execve instructs the dynamic linker to replace all higher-level dynamically loaded parts of the running program by the new program (and its respective libraries). To the lower-level parts (dynamic linker, libc, libm, posix) stay in tact. For this to work, all programs must be linked such that the lower-level parts are loaded first and in the same order. When looking at objdump -p bash I can see that the “Dynamic section” differs from rg in this respect:
The libm is missing from the lower-level part of rg, which makes it incompatible with process it is forked from (bash). To fix this, we need to find out how to tell Goa to link our libm in addition to libc when building a rust executable via cargo.
Looking at the goa build log, I notice the libm.lib.so in the build arguments in the cargo build process: ... -C 'link-arg=-l:libc.lib.so' -C 'link-arg=-l:libm.lib.so' -C 'link-arg=-l:posix.lib.so' ...
Furthermore, I have noticed, that the executable does have libm.so.6 in it’s “Dynamic Section”, if compiled without goa for Linux. Digging in the goa source code, I found an option to garbage collect unreferenced data. Removing it by issuing:
sed -i 's/lappend ldflags -gc-sections//g' /home/user/build/goa/goa-25.04/share/goa/lib/flags.tcl
It doesn’t look like as if there is anything wrong with the binary to me. As @nfeske stated it might be related to fork/execve. We will have to look into this.
@r-freilach: We have found the problem and I just published a new libc with a hotfix for Sculpt 25.04. For your m68k-sdk example it should be sufficient to add ssumpf/src/libc/2025-07-09 to the m68k-sdk/pkg/m68k-sdl/archives file. Let me know how it goes. rg works here in bash.
Thank you again for your help. Sadly the day after my message, I seem to have made a change, that made the same error message reappear. Since you obviously have enough work to do, I did not want to ask for help again right away, but debugged since then.
Copying everything from var/depot to /depot on my Sculpt installation, I can successfully run the terminal component by adding this to the deploy file:
That should not be necessary. Does it work, when you goa run the unix scenario on your Linux host?
Not if the archives are configured correctly (i.e. mention the correct version). You can double-check by looking at the generated routes for the deployed unix scenario in /config/managed/runtime.
Yes, the order actually matters. The mentioned archives are scanned for the the required ROM modules line-by-line. The last match takes precedence.