Addends in relocations are signed integers as theoretically it could
be a negative number. As Atom's offsets are relative to their parent
section, the relocation value should still result in a postive number.
For this reason, the final result is stored as an unsigned integer.
Also, rather than using `null` for relocations that do not support
addends. We set the value to 0 for those that do not support addends,
and have to call `addendIsPresent` to determine if an addend exists
or not. This means each Relocation costs 4 bytes less than before,
saving memory while linking.
The `producers` section contains meta data of the binary and/or
object file. It *can* contain the source language, the tool it
was processed by, and/or the SDK that was used to produce the file.
For now, we always set the language and processed-by fields to Zig.
In the future we will parse linked object files to detect their
producers sections and append (if different) their language, SDK
and processed-by fields.
For example, building stage2 requires an empty `empty.cc` source file
compiling which generates a valid translation unit with no symtab/strtab.
In this case, we cannot simply assume that every translation unit will
have a valid symtab; instead, we cautiously default the input symtab
and strtab fields to optional `null` to signal symtab's presence or its lack of.
In case the symtab is not present, we catch this fact when splitting
input sections into subsections and create a synthetic symbol per every
suitable section.
On each invocation of `flush()` the file pointer is moved.
This means that rather than overwriting the binary file,
we're appending to the file. With this commit, we're resetting
said pointer to '0' and overwrite the existing binary in incremental
mode.
Rather than writing to the file using a writer, we now first write to
an arraylist and store the binary in memory. Once the full binary
data was written, we write all data to disk at once. This reduces
the amount of syscalls tremendously, increasing the performance of
the linker in exchange for increased memory usage during flush.
By writing them at the very end, we can easily detect
where the writing of the binary went wrong as tools will
indicate the missing of the magic bytes.
This adds the following for passthrough to lld:
- `--print-gc-sections`
- `--print-icf-sections`
- `--print-map`
I am not adding these to the cache manifest, since it does not change
the produced artifacts.
Tested with an example from #11398: it successfully prints the resulting
map and the GC'd sections.
If there are zerofill sections, the loader may copy the contents of
the physical space in file directly into memory and attach that to
the zerofill section. This is a performance optimisation in the loader
but requires us, the linker, to properly zero-out any space between
__DATA and __LINKEDIT segments in file. This is of course completely
skipped if there are no zerofill sections present.
This is a temporary workaround to an unclear platform-dependence
behavior we have in libstd for `std.fs.File` abstraction. See
https://github.com/ziglang/zig/issues/12783 for more information.