authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-01-26 00:03:42+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-01-26 14:29:14+01:00
logfb8d754a4bf823b66bcf3fa281c469af8be6f923
tree6768702887d95e5f097634fd4085ea12240be2dc
parent2b5d0ca73b6b0ae96f3362aabe92b792ece2ae63

elf: move TextBlock into its own module and rename to Atom


2 files changed, 61 insertions(+), 54 deletions(-)

src/link/Elf.zig+5-54
...@@ -10,6 +10,7 @@ const fs = std.fs;...@@ -10,6 +10,7 @@ const fs = std.fs;
10const elf = std.elf;10const elf = std.elf;
11const log = std.log.scoped(.link);11const log = std.log.scoped(.link);
1212
13const Atom = @import("Elf/Atom.zig");
13const Module = @import("../Module.zig");14const Module = @import("../Module.zig");
14const Compilation = @import("../Compilation.zig");15const Compilation = @import("../Compilation.zig");
15const Dwarf = @import("Dwarf.zig");16const Dwarf = @import("Dwarf.zig");
...@@ -31,6 +32,8 @@ const Air = @import("../Air.zig");...@@ -31,6 +32,8 @@ const Air = @import("../Air.zig");
31const Liveness = @import("../Liveness.zig");32const Liveness = @import("../Liveness.zig");
32const LlvmObject = @import("../codegen/llvm.zig").Object;33const LlvmObject = @import("../codegen/llvm.zig").Object;
3334
35pub const TextBlock = Atom;
36
34const default_entry_addr = 0x8000000;37const default_entry_addr = 0x8000000;
3538
36pub const base_tag: File.Tag = .elf;39pub const base_tag: File.Tag = .elf;
...@@ -188,62 +191,10 @@ const ideal_factor = 3;...@@ -188,62 +191,10 @@ const ideal_factor = 3;
188/// it as a possible place to put new symbols, it must have enough room for this many bytes191/// it as a possible place to put new symbols, it must have enough room for this many bytes
189/// (plus extra for reserved capacity).192/// (plus extra for reserved capacity).
190const minimum_text_block_size = 64;193const minimum_text_block_size = 64;
191const min_text_capacity = padToIdeal(minimum_text_block_size);194pub const min_text_capacity = padToIdeal(minimum_text_block_size);
192195
193pub const PtrWidth = enum { p32, p64 };196pub const PtrWidth = enum { p32, p64 };
194197
195pub const TextBlock = struct {
196 /// Each decl always gets a local symbol with the fully qualified name.
197 /// The vaddr and size are found here directly.
198 /// The file offset is found by computing the vaddr offset from the section vaddr
199 /// the symbol references, and adding that to the file offset of the section.
200 /// If this field is 0, it means the codegen size = 0 and there is no symbol or
201 /// offset table entry.
202 local_sym_index: u32,
203 /// This field is undefined for symbols with size = 0.
204 offset_table_index: u32,
205 /// Points to the previous and next neighbors, based on the `text_offset`.
206 /// This can be used to find, for example, the capacity of this `TextBlock`.
207 prev: ?*TextBlock,
208 next: ?*TextBlock,
209
210 dbg_info_atom: Dwarf.Atom,
211
212 pub const empty = TextBlock{
213 .local_sym_index = 0,
214 .offset_table_index = undefined,
215 .prev = null,
216 .next = null,
217 .dbg_info_atom = undefined,
218 };
219
220 /// Returns how much room there is to grow in virtual address space.
221 /// File offset relocation happens transparently, so it is not included in
222 /// this calculation.
223 fn capacity(self: TextBlock, elf_file: Elf) u64 {
224 const self_sym = elf_file.local_symbols.items[self.local_sym_index];
225 if (self.next) |next| {
226 const next_sym = elf_file.local_symbols.items[next.local_sym_index];
227 return next_sym.st_value - self_sym.st_value;
228 } else {
229 // We are the last block. The capacity is limited only by virtual address space.
230 return std.math.maxInt(u32) - self_sym.st_value;
231 }
232 }
233
234 fn freeListEligible(self: TextBlock, elf_file: Elf) bool {
235 // No need to keep a free list node for the last block.
236 const next = self.next orelse return false;
237 const self_sym = elf_file.local_symbols.items[self.local_sym_index];
238 const next_sym = elf_file.local_symbols.items[next.local_sym_index];
239 const cap = next_sym.st_value - self_sym.st_value;
240 const ideal_cap = padToIdeal(self_sym.st_size);
241 if (cap <= ideal_cap) return false;
242 const surplus = cap - ideal_cap;
243 return surplus >= min_text_capacity;
244 }
245};
246
247pub const Export = struct {198pub const Export = struct {
248 sym_index: ?u32 = null,199 sym_index: ?u32 = null,
249};200};
...@@ -3052,7 +3003,7 @@ fn getLDMOption(target: std.Target) ?[]const u8 {...@@ -3052,7 +3003,7 @@ fn getLDMOption(target: std.Target) ?[]const u8 {
3052 }3003 }
3053}3004}
30543005
3055fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) {3006pub fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) {
3056 return actual_size +| (actual_size / ideal_factor);3007 return actual_size +| (actual_size / ideal_factor);
3057}3008}
30583009
src/link/Elf/Atom.zig created+56
...@@ -0,0 +1,56 @@
1const Atom = @This();
2
3const std = @import("std");
4
5const Dwarf = @import("../Dwarf.zig");
6const Elf = @import("../Elf.zig");
7
8/// Each decl always gets a local symbol with the fully qualified name.
9/// The vaddr and size are found here directly.
10/// The file offset is found by computing the vaddr offset from the section vaddr
11/// the symbol references, and adding that to the file offset of the section.
12/// If this field is 0, it means the codegen size = 0 and there is no symbol or
13/// offset table entry.
14local_sym_index: u32,
15/// This field is undefined for symbols with size = 0.
16offset_table_index: u32,
17/// Points to the previous and next neighbors, based on the `text_offset`.
18/// This can be used to find, for example, the capacity of this `TextBlock`.
19prev: ?*Atom,
20next: ?*Atom,
21
22dbg_info_atom: Dwarf.Atom,
23
24pub const empty = Atom{
25 .local_sym_index = 0,
26 .offset_table_index = undefined,
27 .prev = null,
28 .next = null,
29 .dbg_info_atom = undefined,
30};
31
32/// Returns how much room there is to grow in virtual address space.
33/// File offset relocation happens transparently, so it is not included in
34/// this calculation.
35pub fn capacity(self: Atom, elf_file: Elf) u64 {
36 const self_sym = elf_file.local_symbols.items[self.local_sym_index];
37 if (self.next) |next| {
38 const next_sym = elf_file.local_symbols.items[next.local_sym_index];
39 return next_sym.st_value - self_sym.st_value;
40 } else {
41 // We are the last block. The capacity is limited only by virtual address space.
42 return std.math.maxInt(u32) - self_sym.st_value;
43 }
44}
45
46pub fn freeListEligible(self: Atom, elf_file: Elf) bool {
47 // No need to keep a free list node for the last block.
48 const next = self.next orelse return false;
49 const self_sym = elf_file.local_symbols.items[self.local_sym_index];
50 const next_sym = elf_file.local_symbols.items[next.local_sym_index];
51 const cap = next_sym.st_value - self_sym.st_value;
52 const ideal_cap = Elf.padToIdeal(self_sym.st_size);
53 if (cap <= ideal_cap) return false;
54 const surplus = cap - ideal_cap;
55 return surplus >= Elf.min_text_capacity;
56}