Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 45 additions & 1 deletion content/this-month/2026-06/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,53 @@ In this section, we describe updates to Rust OS projects that are not directly r
...<<your project updates>>...
-->

<span class="gray">No projects updates were submitted this month.</span>
### [`mkroening/elf-symbols`](https://github.com/mkroening/elf-symbols)
<span class="maintainers">(Section written by [@mkroening](https://github.com/mkroening))</span>

When developing an OS, you often need some information about the loaded kernel image:

- Where has the loader loaded the kernel to?
- How large is the loaded kernel?
- Where do the text segment and the data segment end?
- How do I get the kernel TLS image?

These questions can be answered by building non-relocatable images, by writing custom linker scripts, or by having a custom loader that provides this information somehow.

But there is another way!
In fact, the main ELF linkers that I am aware of ([BFD], [gold], [LLD], [mold], and [Wild]) all have built-in ELF symbols that answer these questions when not using custom linker scripts.
Unfortunately, many are poorly documented, so I created the [elf-symbols] crate that exposes and documents them.
All symbols are tested on the aforementioned linkers.
The documentation shows when each linker gained support for the respective symbol.

The following symbols are straightforward:

- `__executable_start` (`executable_start()`) is the start of the executable.
- `_etext` (`text_end()`) is the end of the text segment.
- `_edata` (`data_end()`) is the end of the data segment.
- `_end` (`executable_end()`) is the end of the executable.

`__ehdr_start` (`elf_header()`) is especially interesting.
It allows programs to examine themselves by reading their ELF headers (file headers and program headers).
This can be used to get TLS image information, for example.

Note that these symbols are ELF specific, though, so they cannot be used when linking to something else, such as a PE32+ UEFI executable.

#### Examples

```rust
println!("Executable start: {:p}", elf_symbols::executable_start());
println!("ELF header: {:p}", elf_symbols::elf_header());
println!("Text segment end: {:p}", elf_symbols::text_end());
println!("Data segment end: {:p}", elf_symbols::data_end());
println!("Executable end: {:p}", elf_symbols::executable_end());
```

[BFD]: https://sourceware.org/git/?p=binutils-gdb.git;a=tree;f=ld;h=b1662159cdd15bb857e04e42bd26361c0d406099;hb=5e56594815854de5eca35c7c04b11705d0f19c02
[gold]: https://sourceware.org/git/?p=binutils-gdb.git;a=tree;f=gold;h=ac6272c7bb3ad02524b2ca86a2cf9b68e9ca30ca;hb=5e56594815854de5eca35c7c04b11705d0f19c02
[LLD]: https://github.com/llvm/llvm-project/tree/llvmorg-22.1.8/lld
[mold]: https://github.com/rui314/mold/tree/v2.41.0
[Wild]: https://github.com/wild-linker/wild/tree/0.9.0
[elf-symbols]: https://crates.io/crates/elf-symbols

## Join Us?

Expand Down
Loading