authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-04-18 17:11:27+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-04-21 22:44:27+02:00
log8e3100ae02fef20ce08a679f6212b3d673a5c8f0
tree899bb927fc750896681134079364610c4843ed20
parent8a3ad3f6204747b5621e14cae0564ee7929a7cd8

elf: make TableSection a generic construct


2 files changed, 68 insertions(+), 84 deletions(-)

src/link/Elf.zig+3-84
...@@ -30,6 +30,7 @@ const LlvmObject = @import("../codegen/llvm.zig").Object;...@@ -30,6 +30,7 @@ const LlvmObject = @import("../codegen/llvm.zig").Object;
30const Module = @import("../Module.zig");30const Module = @import("../Module.zig");
31const Package = @import("../Package.zig");31const Package = @import("../Package.zig");
32const StringTable = @import("strtab.zig").StringTable;32const StringTable = @import("strtab.zig").StringTable;
33const TableSection = @import("table_section.zig").TableSection;
33const Type = @import("../type.zig").Type;34const Type = @import("../type.zig").Type;
34const TypedValue = @import("../TypedValue.zig");35const TypedValue = @import("../TypedValue.zig");
35const Value = @import("../value.zig").Value;36const Value = @import("../value.zig").Value;
...@@ -63,88 +64,6 @@ const Section = struct {...@@ -63,88 +64,6 @@ const Section = struct {
63 free_list: std.ArrayListUnmanaged(Atom.Index) = .{},64 free_list: std.ArrayListUnmanaged(Atom.Index) = .{},
64};65};
6566
66const SectionTable = struct {
67 entries: std.ArrayListUnmanaged(SymIndex) = .{},
68 free_list: std.ArrayListUnmanaged(Index) = .{},
69 lookup: std.AutoHashMapUnmanaged(SymIndex, Index) = .{},
70
71 const SymIndex = u32;
72 const Index = u32;
73
74 pub fn deinit(st: *ST, allocator: Allocator) void {
75 st.entries.deinit(allocator);
76 st.free_list.deinit(allocator);
77 st.lookup.deinit(allocator);
78 }
79
80 pub fn allocateEntry(st: *ST, allocator: Allocator, target: SymIndex) !Index {
81 try st.entries.ensureUnusedCapacity(allocator, 1);
82 const index = blk: {
83 if (st.free_list.popOrNull()) |index| {
84 log.debug(" (reusing entry index {d})", .{index});
85 break :blk index;
86 } else {
87 log.debug(" (allocating entry at index {d})", .{st.entries.items.len});
88 const index = @intCast(u32, st.entries.items.len);
89 _ = st.entries.addOneAssumeCapacity();
90 break :blk index;
91 }
92 };
93 st.entries.items[index] = target;
94 try st.lookup.putNoClobber(allocator, target, index);
95 return index;
96 }
97
98 pub fn freeEntry(st: *ST, allocator: Allocator, target: SymIndex) void {
99 const index = st.lookup.get(target) orelse return;
100 st.free_list.append(allocator, index) catch {};
101 st.entries.items[index] = 0;
102 _ = st.lookup.remove(target);
103 }
104
105 const FormatContext = struct {
106 ctx: *Elf,
107 st: *const ST,
108 };
109
110 fn fmt(
111 ctx: FormatContext,
112 comptime unused_format_string: []const u8,
113 options: std.fmt.FormatOptions,
114 writer: anytype,
115 ) @TypeOf(writer).Error!void {
116 _ = options;
117 comptime assert(unused_format_string.len == 0);
118
119 const base_addr = ctx.ctx.program_headers.items[ctx.ctx.phdr_got_index.?].p_vaddr;
120 const target = ctx.ctx.base.options.target;
121 const ptr_bits = target.cpu.arch.ptrBitWidth();
122 const ptr_bytes: u64 = @divExact(ptr_bits, 8);
123
124 try writer.writeAll("SectionTable:\n");
125 for (ctx.st.entries.items, 0..) |entry, i| {
126 try writer.print(" {d}@{x} => local(%{d})\n", .{ i, base_addr + i * ptr_bytes, entry });
127 }
128 }
129
130 fn format(st: ST, comptime unused_format_string: []const u8, options: std.fmt.FormatOptions, writer: anytype) !void {
131 _ = st;
132 _ = unused_format_string;
133 _ = options;
134 _ = writer;
135 @compileError("do not format SectionTable directly; use st.fmtDebug()");
136 }
137
138 pub fn fmtDebug(st: ST, ctx: *Elf) std.fmt.Formatter(fmt) {
139 return .{ .data = .{
140 .ctx = ctx,
141 .st = st,
142 } };
143 }
144
145 const ST = @This();
146};
147
148const LazySymbolMetadata = struct {67const LazySymbolMetadata = struct {
149 text_atom: ?Atom.Index = null,68 text_atom: ?Atom.Index = null,
150 rodata_atom: ?Atom.Index = null,69 rodata_atom: ?Atom.Index = null,
...@@ -231,7 +150,7 @@ global_symbols: std.ArrayListUnmanaged(elf.Elf64_Sym) = .{},...@@ -231,7 +150,7 @@ global_symbols: std.ArrayListUnmanaged(elf.Elf64_Sym) = .{},
231local_symbol_free_list: std.ArrayListUnmanaged(u32) = .{},150local_symbol_free_list: std.ArrayListUnmanaged(u32) = .{},
232global_symbol_free_list: std.ArrayListUnmanaged(u32) = .{},151global_symbol_free_list: std.ArrayListUnmanaged(u32) = .{},
233152
234got_table: SectionTable = .{},153got_table: TableSection(u32) = .{},
235154
236phdr_table_dirty: bool = false,155phdr_table_dirty: bool = false,
237shdr_table_dirty: bool = false,156shdr_table_dirty: bool = false,
...@@ -3047,7 +2966,7 @@ fn writeSectHeader(self: *Elf, index: usize) !void {...@@ -3047,7 +2966,7 @@ fn writeSectHeader(self: *Elf, index: usize) !void {
3047 }2966 }
3048}2967}
30492968
3050fn writeOffsetTableEntry(self: *Elf, index: usize) !void {2969fn writeOffsetTableEntry(self: *Elf, index: @TypeOf(self.got_table).Index) !void {
3051 const entry_size: u16 = self.archPtrWidthBytes();2970 const entry_size: u16 = self.archPtrWidthBytes();
3052 if (self.got_table_count_dirty) {2971 if (self.got_table_count_dirty) {
3053 const needed_size = self.got_table.entries.items.len * entry_size;2972 const needed_size = self.got_table.entries.items.len * entry_size;
src/link/table_section.zig created+65
...@@ -0,0 +1,65 @@
1pub fn TableSection(comptime Entry: type) type {
2 return struct {
3 entries: std.ArrayListUnmanaged(Entry) = .{},
4 free_list: std.ArrayListUnmanaged(Index) = .{},
5 lookup: std.AutoHashMapUnmanaged(Entry, Index) = .{},
6
7 pub fn deinit(self: *Self, allocator: Allocator) void {
8 self.entries.deinit(allocator);
9 self.free_list.deinit(allocator);
10 self.lookup.deinit(allocator);
11 }
12
13 pub fn allocateEntry(self: *Self, allocator: Allocator, entry: Entry) Allocator.Error!Index {
14 try self.entries.ensureUnusedCapacity(allocator, 1);
15 const index = blk: {
16 if (self.free_list.popOrNull()) |index| {
17 log.debug(" (reusing entry index {d})", .{index});
18 break :blk index;
19 } else {
20 log.debug(" (allocating entry at index {d})", .{self.entries.items.len});
21 const index = @intCast(u32, self.entries.items.len);
22 _ = self.entries.addOneAssumeCapacity();
23 break :blk index;
24 }
25 };
26 self.entries.items[index] = entry;
27 try self.lookup.putNoClobber(allocator, entry, index);
28 return index;
29 }
30
31 pub fn freeEntry(self: *Self, allocator: Allocator, entry: Entry) void {
32 const index = self.lookup.get(entry) orelse return;
33 self.free_list.append(allocator, index) catch {};
34 self.entries.items[index] = undefined;
35 _ = self.lookup.remove(entry);
36 }
37
38 pub fn count(self: Self) usize {
39 return self.entries.items.len;
40 }
41
42 pub fn format(
43 self: Self,
44 comptime unused_format_string: []const u8,
45 options: std.fmt.FormatOptions,
46 writer: anytype,
47 ) !void {
48 _ = options;
49 comptime assert(unused_format_string.len == 0);
50 try writer.writeAll("SectionTable:\n");
51 for (self.entries.items, 0..) |entry, i| {
52 try writer.print(" {d} => {}\n", .{ i, entry });
53 }
54 }
55
56 const Self = @This();
57 pub const Index = u32;
58 };
59}
60
61const std = @import("std");
62const assert = std.debug.assert;
63const log = std.log.scoped(.link);
64
65const Allocator = std.mem.Allocator;