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
+
1
7
const Atom = @This ();
2
8
3
9
const std = @import ("std" );
@@ -17,33 +23,38 @@ const Object = @import("Object.zig");
17
23
const SymbolWithLoc = @import ("zld.zig" ).SymbolWithLoc ;
18
24
const Zld = @import ("zld.zig" ).Zld ;
19
25
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.
26
30
sym_index : u32 ,
27
31
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.
31
- inner_sym_index : u32 ,
32
- inner_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.
35
33
/// 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.
36
36
file : i32 ,
37
37
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.
44
+ inner_sym_index : u32 ,
45
+ inner_nsyms_trailing : u32 ,
46
+
47
+ /// Size of this atom.
41
48
size : u64 ,
42
49
43
50
/// Alignment of this atom as a power of 2.
44
51
/// For instance, aligmment of 0 should be read as 2^0 = 1 byte aligned.
45
52
alignment : u32 ,
46
53
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.
47
58
cached_relocs_start : i32 ,
48
59
cached_relocs_len : u32 ,
49
60
@@ -64,6 +75,8 @@ pub const empty = Atom{
64
75
.next_index = null ,
65
76
};
66
77
78
+ /// Returns `null` if the Atom is a synthetic Atom.
79
+ /// Otherwise, returns an index into an array of Objects.
67
80
pub inline fn getFile (self : Atom ) ? u31 {
68
81
if (self .file == -1 ) return null ;
69
82
return @intCast (u31 , self .file );
@@ -90,6 +103,8 @@ const InnerSymIterator = struct {
90
103
}
91
104
};
92
105
106
+ /// Returns an iterator over potentially contained symbols.
107
+ /// Panics when called on a synthetic Atom.
93
108
pub fn getInnerSymbolsIterator (zld : * Zld , atom_index : AtomIndex ) InnerSymIterator {
94
109
const atom = zld .getAtom (atom_index );
95
110
assert (atom .getFile () != null );
@@ -100,6 +115,10 @@ pub fn getInnerSymbolsIterator(zld: *Zld, atom_index: AtomIndex) InnerSymIterato
100
115
};
101
116
}
102
117
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.
103
122
pub fn getSectionAlias (zld : * Zld , atom_index : AtomIndex ) ? SymbolWithLoc {
104
123
const atom = zld .getAtom (atom_index );
105
124
assert (atom .getFile () != null );
@@ -119,6 +138,8 @@ pub fn getSectionAlias(zld: *Zld, atom_index: AtomIndex) ?SymbolWithLoc {
119
138
return null ;
120
139
}
121
140
141
+ /// Given an index into a contained symbol within, calculates an offset wrt
142
+ /// the start of this Atom.
122
143
pub fn calcInnerSymbolOffset (zld : * Zld , atom_index : AtomIndex , sym_index : u32 ) u64 {
123
144
const atom = zld .getAtom (atom_index );
124
145
assert (atom .getFile () != null );
0 commit comments