| ... | @@ -1,3 +1,9 @@ | ... | @@ -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 | |
| 1 | const Atom = @This(); | 7 | const Atom = @This(); |
| 2 | | 8 | |
| 3 | const std = @import("std"); | 9 | const std = @import("std"); |
| ... | @@ -17,33 +23,38 @@ const Object = @import("Object.zig"); | ... | @@ -17,33 +23,38 @@ const Object = @import("Object.zig"); |
| 17 | const SymbolWithLoc = @import("zld.zig").SymbolWithLoc; | 23 | const SymbolWithLoc = @import("zld.zig").SymbolWithLoc; |
| 18 | const Zld = @import("zld.zig").Zld; | 24 | const Zld = @import("zld.zig").Zld; |
| 19 | | 25 | |
| 20 | /// Each decl always gets a local symbol with the fully qualified name. | 26 | /// Each Atom always gets a symbol with the fully qualified name. |
| 21 | /// The vaddr and size are found here directly. | 27 | /// The symbol can reside in any object file context structure in `symtab` array |
| 22 | /// The file offset is found by computing the vaddr offset from the section vaddr | 28 | /// (see `Object`), or if the symbol is a synthetic symbol such as a GOT cell or |
| 23 | /// the symbol references, and adding that to the file offset of the section. | 29 | /// a stub trampoline, it can be found in the linkers `locals` arraylist. |
| 24 | /// If this field is 0, it means the codegen size = 0 and there is no symbol or | | |
| 25 | /// offset table entry. | | |
| 26 | sym_index: u32, | 30 | sym_index: u32, |
| 27 | | 31 | |
| 28 | /// If this Atom references a subsection in an Object file, `nsyms_trailing` | 32 | /// -1 means an Atom is a synthetic Atom such as a GOT cell defined by the linker. |
| 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. | | |
| 35 | /// Otherwise, it is the index into appropriate object file. | 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 | file: i32, | 36 | file: i32, |
| 37 | | 37 | |
| 38 | /// Size and alignment of this atom | 38 | /// If this Atom is not a synthetic Atom, i.e., references a subsection in an |
| 39 | /// Unlike in Elf, we need to store the size of this symbol as part of | 39 | /// Object file, `inner_sym_index` and `inner_nsyms_trailing` tell where and if |
| 40 | /// the atom since macho.nlist_64 lacks this information. | 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 | size: u64, | 48 | size: u64, |
| 42 | | 49 | |
| 43 | /// Alignment of this atom as a power of 2. | 50 | /// Alignment of this atom as a power of 2. |
| 44 | /// For instance, aligmment of 0 should be read as 2^0 = 1 byte aligned. | 51 | /// For instance, aligmment of 0 should be read as 2^0 = 1 byte aligned. |
| 45 | alignment: u32, | 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 | cached_relocs_start: i32, | 58 | cached_relocs_start: i32, |
| 48 | cached_relocs_len: u32, | 59 | cached_relocs_len: u32, |
| 49 | | 60 | |
| ... | @@ -64,6 +75,8 @@ pub const empty = Atom{ | ... | @@ -64,6 +75,8 @@ pub const empty = Atom{ |
| 64 | .next_index = null, | 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 | pub inline fn getFile(self: Atom) ?u31 { | 80 | pub inline fn getFile(self: Atom) ?u31 { |
| 68 | if (self.file == -1) return null; | 81 | if (self.file == -1) return null; |
| 69 | return @intCast(u31, self.file); | 82 | return @intCast(u31, self.file); |
| ... | @@ -90,6 +103,8 @@ const InnerSymIterator = struct { | ... | @@ -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 | pub fn getInnerSymbolsIterator(zld: *Zld, atom_index: AtomIndex) InnerSymIterator { | 108 | pub fn getInnerSymbolsIterator(zld: *Zld, atom_index: AtomIndex) InnerSymIterator { |
| 94 | const atom = zld.getAtom(atom_index); | 109 | const atom = zld.getAtom(atom_index); |
| 95 | assert(atom.getFile() != null); | 110 | assert(atom.getFile() != null); |
| ... | @@ -100,6 +115,10 @@ pub fn getInnerSymbolsIterator(zld: *Zld, atom_index: AtomIndex) InnerSymIterato | ... | @@ -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 | pub fn getSectionAlias(zld: *Zld, atom_index: AtomIndex) ?SymbolWithLoc { | 122 | pub fn getSectionAlias(zld: *Zld, atom_index: AtomIndex) ?SymbolWithLoc { |
| 104 | const atom = zld.getAtom(atom_index); | 123 | const atom = zld.getAtom(atom_index); |
| 105 | assert(atom.getFile() != null); | 124 | assert(atom.getFile() != null); |
| ... | @@ -119,6 +138,8 @@ pub fn getSectionAlias(zld: *Zld, atom_index: AtomIndex) ?SymbolWithLoc { | ... | @@ -119,6 +138,8 @@ pub fn getSectionAlias(zld: *Zld, atom_index: AtomIndex) ?SymbolWithLoc { |
| 119 | return null; | 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 | pub fn calcInnerSymbolOffset(zld: *Zld, atom_index: AtomIndex, sym_index: u32) u64 { | 143 | pub fn calcInnerSymbolOffset(zld: *Zld, atom_index: AtomIndex, sym_index: u32) u64 { |
| 123 | const atom = zld.getAtom(atom_index); | 144 | const atom = zld.getAtom(atom_index); |
| 124 | assert(atom.getFile() != null); | 145 | assert(atom.getFile() != null); |