roc/crates/linker
Jakub Konka fa85fc7e87
linker/macho: warn when headerpad is too small in host executable
Previously, I wrongly assumed that the Roc compiler controls how
the host is being built, but this is not the case. Therefore,
there is no way to automatically enforcing that the host will have
enough headerpad size. It may be possible to re-use the old idea
of shifting everything in file, however, this will necessitate also
shifting everything in memory since we absolutely have to shift
by page size to guarantee original alignment of sections. This then
becomes difficult as we will not only need update segments/sections
with new offsets and virtual addresses but also every rebase and binding
for the dynamic linker (which effectively means parsing the info and
recreating it). There may be even more avenues where updates are
required. Therefore, for the time being, let's nerf the error into
a warning since the linker is still experimental until we investigate
how difficult shifting actually is. If it turns out to be nigh
impossible, we will convert the warning back into a hard error and
the user will have to recompile the host with increased headerpad size.
Boy, this kinda reminds me of how errors are structured when one is
mixing PIC with non-PIC code ("recompile your code with -fPIC" or
similar).
2025-01-16 20:42:28 +01:00
..
src linker/macho: warn when headerpad is too small in host executable 2025-01-16 20:42:28 +01:00
Cargo.toml replace cargo deps with workspace in linker, packaging, repl_* 2024-11-29 10:53:54 +11:00
dynhost_benchmarks_elf64 revert changed binary files 2025-01-05 06:32:49 -08:00
dynhost_benchmarks_windows.exe revert changed binary files 2025-01-05 06:32:49 -08:00
README.md Kevin Gillette: markdown typo fixes 2023-04-10 14:07:03 -06:00

The Roc Surgical Linker

This linker has the goal of being extremely slim lined and fast. It is focused on the scope of only linking platforms to Roc applications. This restriction enables ignoring most of linking.

General Overview

This linker is run in 2 phases: preprocessing and surgical linking.

Platform Preprocessor

  1. Dynamically link the platform to a dummy Roc application dynamic library
  2. Create metadata related to Roc dynamically linked functions
    • Symbols that need to be redefined
    • Call locations that need to be modified for each symbol
    • Locations of special roc functions (roc_alloc, roc_dealloc, builtins, etc)
  3. Modify the main executable to no longer be dynamically link
    • Delete dependency on dynamic library
    • Remove symbols from the dynamic table (maybe add them to the regular table?)
    • Delete GOT and PLT entries
    • Remove relocations from the dynamic table
    • Add extra header information about new text and data section at end of file

Surgical Linker

  1. Build off of preprocessed platform
  2. Append text and data of application, dealing with app relocations
  3. Surgically update all call locations in the platform
  4. Surgically update call information in the application (also dealing with other relocations for builtins)

TODO (In a lightly prioritized order)

  • Add Macho support
    • Honestly should be almost exactly the same code. This means we likely need to do a lot of refactoring to minimize the duplicate code. The fun of almost but not quite the same.
  • Add PE support
    • As a prereq, we need roc building on Windows (I'm not sure it does currently).
    • Definitely a solid bit different than elf, but hopefully after refactoring for Macho, won't be that crazy to add.
  • Look at enabling completely in memory linking that could be used with roc run and/or roc repl
  • Look more into rust hosts and keeping certain functions. Currently I just disabled linker garbage collection. This works but adds 1.2MB (40%) to even a tiny app. It may be a size issue for large rust hosts. Roc, for reference, adds 13MB (20%) when linked without garbage collection.
  • Add a feature to the compiler to make this linker optional.