authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-10-22 14:53:53+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-10-22 14:53:53+02:00
log593b75b109f49e7afbe2fe6fa1d519dc5799a3fb
tree935861f05ad31b73b1edddbe330e76d7aebdec1f
parent086cee844a082bab82dba9e7422067f644930309

macho: some docs


4 files changed, 54 insertions(+), 16 deletions(-)

src/link/MachO/Object.zig+8
......@@ -1,3 +1,7 @@
1//! Represents an input relocatable Object file.
2//! Each Object is fully loaded into memory for easier
3//! access into different data within.
4
15const Object = @This();
26
37const std = @import("std");
......@@ -278,6 +282,9 @@ fn sectionLessThanByAddress(ctx: void, lhs: SortedSection, rhs: SortedSection) b
278282 return lhs.header.addr < rhs.header.addr;
279283}
280284
285/// Splits input sections into Atoms.
286/// If the Object was compiled with `MH_SUBSECTIONS_VIA_SYMBOLS`, splits section
287/// into subsections where each subsection then represents an Atom.
281288pub fn splitIntoAtoms(self: *Object, zld: *Zld, object_id: u31) !void {
282289 const gpa = zld.gpa;
283290
......@@ -514,6 +521,7 @@ pub fn getSourceSymbol(self: Object, index: u32) ?macho.nlist_64 {
514521 return symtab[mapped_index];
515522}
516523
524/// Expects an arena allocator.
517525/// Caller owns memory.
518526pub fn createReverseSymbolLookup(self: Object, arena: Allocator) ![]u32 {
519527 const symtab = self.in_symtab orelse return &[0]u32{};
src/link/MachO/ZldAtom.zig+37-16
......@@ -1,3 +1,9 @@
1//! An atom is a single smallest unit of measure that will get an
2//! allocated virtual memory address in the final linked image.
3//! For example, we parse each input section within an input relocatable
4//! object file into a set of atoms which are then laid out contiguously
5//! as they were defined in the input file.
6
17const Atom = @This();
28
39const std = @import("std");
......@@ -17,33 +23,38 @@ const Object = @import("Object.zig");
1723const SymbolWithLoc = @import("zld.zig").SymbolWithLoc;
1824const Zld = @import("zld.zig").Zld;
1925
20/// Each decl always gets a local symbol with the fully qualified name.
21/// The vaddr and size are found here directly.
22/// The file offset is found by computing the vaddr offset from the section vaddr
23/// the symbol references, and adding that to the file offset of the section.
24/// If this field is 0, it means the codegen size = 0 and there is no symbol or
25/// offset table entry.
26/// Each Atom always gets a symbol with the fully qualified name.
27/// The symbol can reside in any object file context structure in `symtab` array
28/// (see `Object`), or if the symbol is a synthetic symbol such as a GOT cell or
29/// a stub trampoline, it can be found in the linkers `locals` arraylist.
2630sym_index: u32,
2731
28/// If this Atom references a subsection in an Object file, `nsyms_trailing`
29/// tells how many symbols trailing `sym_index` fall within this Atom's address
30/// range.
31inner_sym_index: u32,
32inner_nsyms_trailing: u32,
33
34/// -1 means symbol defined by the linker.
32/// -1 means an Atom is a synthetic Atom such as a GOT cell defined by the linker.
3533/// Otherwise, it is the index into appropriate object file.
34/// Prefer using `getFile()` helper to get the file index out rather than using
35/// the field directly.
3636file: i32,
3737
38/// Size and alignment of this atom
39/// Unlike in Elf, we need to store the size of this symbol as part of
40/// the atom since macho.nlist_64 lacks this information.
38/// If this Atom is not a synthetic Atom, i.e., references a subsection in an
39/// Object file, `inner_sym_index` and `inner_nsyms_trailing` tell where and if
40/// this Atom contains any additional symbol references that fall within this Atom's
41/// address range. These could for example be an alias symbol which can be used
42/// internally by the relocation records, or if the Object file couldn't be split
43/// into subsections, this Atom may encompass an entire input section.
44inner_sym_index: u32,
45inner_nsyms_trailing: u32,
46
47/// Size of this atom.
4148size: u64,
4249
4350/// Alignment of this atom as a power of 2.
4451/// For instance, aligmment of 0 should be read as 2^0 = 1 byte aligned.
4552alignment: u32,
4653
54/// Cached index and length into the relocations records array that correspond to
55/// this Atom and need to be resolved before the Atom can be committed into the
56/// final linked image.
57/// Do not use these fields directly. Instead, use `getAtomRelocs()` helper.
4758cached_relocs_start: i32,
4859cached_relocs_len: u32,
4960
......@@ -64,6 +75,8 @@ pub const empty = Atom{
6475 .next_index = null,
6576};
6677
78/// Returns `null` if the Atom is a synthetic Atom.
79/// Otherwise, returns an index into an array of Objects.
6780pub inline fn getFile(self: Atom) ?u31 {
6881 if (self.file == -1) return null;
6982 return @intCast(u31, self.file);
......@@ -90,6 +103,8 @@ const InnerSymIterator = struct {
90103 }
91104};
92105
106/// Returns an iterator over potentially contained symbols.
107/// Panics when called on a synthetic Atom.
93108pub fn getInnerSymbolsIterator(zld: *Zld, atom_index: AtomIndex) InnerSymIterator {
94109 const atom = zld.getAtom(atom_index);
95110 assert(atom.getFile() != null);
......@@ -100,6 +115,10 @@ pub fn getInnerSymbolsIterator(zld: *Zld, atom_index: AtomIndex) InnerSymIterato
100115 };
101116}
102117
118/// Returns a section alias symbol if one is defined.
119/// An alias symbol is used to represent the start of an input section
120/// if there were no symbols defined within that range.
121/// Alias symbols are only used on x86_64.
103122pub fn getSectionAlias(zld: *Zld, atom_index: AtomIndex) ?SymbolWithLoc {
104123 const atom = zld.getAtom(atom_index);
105124 assert(atom.getFile() != null);
......@@ -119,6 +138,8 @@ pub fn getSectionAlias(zld: *Zld, atom_index: AtomIndex) ?SymbolWithLoc {
119138 return null;
120139}
121140
141/// Given an index into a contained symbol within, calculates an offset wrt
142/// the start of this Atom.
122143pub fn calcInnerSymbolOffset(zld: *Zld, atom_index: AtomIndex, sym_index: u32) u64 {
123144 const atom = zld.getAtom(atom_index);
124145 assert(atom.getFile() != null);
src/link/MachO/dead_strip.zig+2
......@@ -1,3 +1,5 @@
1//! An algorithm for dead stripping of unreferenced Atoms.
2
13const std = @import("std");
24const assert = std.debug.assert;
35const log = std.log.scoped(.dead_strip);
src/link/MachO/thunks.zig+7
......@@ -1,3 +1,10 @@
1//! An algorithm for allocating output machine code section (aka `__TEXT,__text`),
2//! and insertion of range extending thunks. As such, this algorithm is only run
3//! for a target that requires range extenders such as arm64.
4//!
5//! The algorithm works pessimistically and assumes that any reference to an Atom in
6//! another output section is out of range.
7
18const std = @import("std");
29const assert = std.debug.assert;
310const log = std.log.scoped(.thunks);