Expand description
ELF, Mach-O and COFF object writers.
Design: spec/11-asm-objects-debug.md. Layer rank 9, see spec/18-package-layout.md.
§Status
ELF, which is what Linux and the freestanding targets want and what M3 needs. A text section, the symbols that say where each function in it is and how long it is, the names it wanted that are not in it, the relocations that ask a linker to find them, and the marker whose absence makes the stack executable. An object this writes links with the system linker and runs.
The variables a file defines are written too: the section each one goes in, the symbol that says where it is and how long it is, the binding that says who can see it, and the relocations an image asks for when it holds the address of something. A tentative definition is asked of the linker rather than put in a section, which is the one case where a variable has a symbol and no bytes anywhere.
An Alias is written as a second symbol at the first one’s section, value and size, with a
binding of its own and no second copy of the bytes, which is what a file gets from
__attribute__((alias("target"))) and what makes one name reach another at no cost.
Sections says whether each function and each variable gets a section to itself, which is
what -ffunction-sections and -fdata-sections ask for and what makes --gc-sections able to
drop anything: a linker can leave out a section nothing reaches and cannot leave out half of
one. The names and the offsets are the same either way, so the only thing that moves is which
section header a symbol points at.
Array is what a section of function addresses for the startup code to call is, which is what
the constructor and destructor attributes produce. ELF has a section type for each of the
three kinds, and a section of the ordinary type under one of those names is gathered by the
linker in the same run and called by nobody, so the type is written out rather than left to the
default.
Property is what the file says it was built to have checked, which is what
-fcf-protection= asks for. It is written as a note the linker keeps only the agreed part of
and the loader reads out of the result, which is why a file that says nothing about it turns
the check off for the whole program rather than only for itself.
defines says which names a linker can find in what write() wrote, which is what the symbol
index of an archive is built from. It is here rather than worked out by whoever writes the
archive because the index has to agree with the member, and the writer is the only thing that
knows what it put in one.
What it is given is Text, Data and the aliases between them, which are here rather than
beside the assembler that fills them in because they are what an object file is made of and
because a writer cannot depend on the thing that produces its input without the layer graph
going the wrong way round.
assembled is the other way in, for an object written from a file of assembly rather than
from a compilation. It takes Assembled, which is a list of sections that each carry their
own name and flags and a flat list of names that point into them at offsets. That is a different
shape from Text and Data because a file of assembly says things neither of them can hold:
which section something is in, a name at an offset that no variable covers, and a name that is a
number rather than a place. Both go through the same writer underneath, so there is still one
place that knows how an ELF file is laid out.
Mach-O and COFF are not written yet. Both wait on the target that needs them.
Every crate in the workspace is published, and publishing implies a promise. This one is
tier 3: its Rust API is explicitly unstable and will change without a major version bump.
Depend on the rucc binary’s behaviour, not on this.
Structs§
- Alias
- A second name for something the same file defines.
- Assembled
- Everything an assembled file holds: its sections, and the names that point into them.
- Data
- The variables a file defines, and what the linker has to be told about them.
- Extent
- Where one function ended up.
- Marker
- Where a place inside a function that has a name of its own ended up.
- Name
- One name in the symbol table, as a file of assembly defines one.
- Object
- One global variable, laid out.
- Output
- What the command line decided about the file being written, as against what the code in it decided.
- Part
- One section, as a file of assembly describes one.
- Patch
- Where the room a patcher was promised at the top of a function ended up.
- Property
- What a file says it was built to have checked, which is what
-fcf-protection=asks for. - Reloc
- One reference to something this file does not contain.
- Sections
- Whether each function and each variable gets a section to itself.
- Shape
- What a section is, which on ELF is a handful of flag letters and a type.
- Text
- A text section, and what the linker has to be told about it.
- Unwind
- The unwind table, as the bytes of its own section and what the linker has to be told about them.
Enums§
- Array
- A section holding function addresses for a C runtime to call rather than data for the program to read.
- Binding
- How the linker sees a name.
- Error
- Why an object file could not be written.
- Held
- Where a name is, which is four different things and not an offset with special cases.
- Place
- Which section a variable goes in.
- Reference
- What kind of thing a relocation is asking the linker for.
- Sort
- What kind of thing a name names, which is what
.typesays. - Visibility
- How far outside a shared library a name reaches.
Constants§
- FUNC_
ALIGN - What a function is aligned to when nothing asked for more.
- MILESTONE
- The milestone in
spec/17-milestones.mdthat fills this crate in.
Functions§
- assembled
- That, as a relocatable ELF object.
- assembled_
defines - Every name in it a linker can find, which is what an archive’s symbol index is built from.
- defines
- Every name a linker can find in the object
write()would write from the same input. - write
- One text section and the variables beside it, as a relocatable ELF object.