authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-07-31 16:30:45+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-08-07 10:21:02+02:00
logde80e4fec2a29c5aac70c8d72b11a90cb96feeaf
treea5f0015e29bec5c87a75c1c3e2a1c6404aeca946
parent9fe69cc0b588ff96075854d687f3fce3d4457258

elf: move symbol ownership to LinkerDefined


2 files changed, 237 insertions(+), 142 deletions(-)

src/link/Elf/LinkerDefined.zig+235-140
...@@ -2,7 +2,10 @@ index: File.Index,...@@ -2,7 +2,10 @@ index: File.Index,
22
3symtab: std.ArrayListUnmanaged(elf.Elf64_Sym) = .{},3symtab: std.ArrayListUnmanaged(elf.Elf64_Sym) = .{},
4strtab: std.ArrayListUnmanaged(u8) = .{},4strtab: std.ArrayListUnmanaged(u8) = .{},
5symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},5
6symbols: std.ArrayListUnmanaged(Symbol) = .{},
7symbols_extra: std.ArrayListUnmanaged(u32) = .{},
8symbols_resolver: std.ArrayListUnmanaged(Elf.SymbolResolver.Index) = .{},
69
7entry_index: ?Symbol.Index = null,10entry_index: ?Symbol.Index = null,
8dynamic_index: ?Symbol.Index = null,11dynamic_index: ?Symbol.Index = null,
...@@ -29,6 +32,8 @@ pub fn deinit(self: *LinkerDefined, allocator: Allocator) void {...@@ -29,6 +32,8 @@ pub fn deinit(self: *LinkerDefined, allocator: Allocator) void {
29 self.symtab.deinit(allocator);32 self.symtab.deinit(allocator);
30 self.strtab.deinit(allocator);33 self.strtab.deinit(allocator);
31 self.symbols.deinit(allocator);34 self.symbols.deinit(allocator);
35 self.symbols_extra.deinit(allocator);
36 self.symbols_resolver.deinit(allocator);
32 self.start_stop_indexes.deinit(allocator);37 self.start_stop_indexes.deinit(allocator);
33}38}
3439
...@@ -38,85 +43,137 @@ pub fn init(self: *LinkerDefined, allocator: Allocator) !void {...@@ -38,85 +43,137 @@ pub fn init(self: *LinkerDefined, allocator: Allocator) !void {
38}43}
3944
40pub fn initSymbols(self: *LinkerDefined, elf_file: *Elf) !void {45pub fn initSymbols(self: *LinkerDefined, elf_file: *Elf) !void {
46 const newSymbolAssumeCapacity = struct {
47 fn newSymbolAssumeCapacity(ld: *LinkerDefined, name_off: u32) Symbol.Index {
48 const esym_index: u32 = @intCast(ld.symtab.items.len);
49 const esym = ld.symtab.addOneAssumeCapacity();
50 esym.* = .{
51 .st_name = name_off,
52 .st_info = elf.STB_GLOBAL << 4,
53 .st_other = @intFromEnum(elf.STV.HIDDEN),
54 .st_shndx = elf.SHN_ABS,
55 .st_value = 0,
56 .st_size = 0,
57 };
58 const index = ld.addSymbolAssumeCapacity();
59 const symbol = &ld.symbols.items[index];
60 symbol.name_offset = name_off;
61 symbol.extra_index = ld.addSymbolExtraAssumeCapacity(.{});
62 symbol.ref = .{ .index = 0, .file = 0 };
63 symbol.esym_index = esym_index;
64 symbol.version_index = elf_file.default_sym_version;
65 }
66 }.newSymbolAssumeCapacity;
67
41 const gpa = elf_file.base.comp.gpa;68 const gpa = elf_file.base.comp.gpa;
4269
43 if (elf_file.entry_name) |name| {70 var nsyms: usize = 0;
44 self.entry_index = try self.addGlobal(name, elf_file);71 if (elf_file.entry_name) |_| {
72 nsyms += 1; // entry
45 }73 }
4674 nsyms += 1; // _DYNAMIC
47 self.dynamic_index = try self.addGlobal("_DYNAMIC", elf_file);75 nsyms += 1; // __ehdr_start
48 self.ehdr_start_index = try self.addGlobal("__ehdr_start", elf_file);76 nsyms += 1; // __init_array_start
49 self.init_array_start_index = try self.addGlobal("__init_array_start", elf_file);77 nsyms += 1; // __init_array_end
50 self.init_array_end_index = try self.addGlobal("__init_array_end", elf_file);78 nsyms += 1; // __fini_array_start
51 self.fini_array_start_index = try self.addGlobal("__fini_array_start", elf_file);79 nsyms += 1; // __fini_array_end
52 self.fini_array_end_index = try self.addGlobal("__fini_array_end", elf_file);80 nsyms += 1; // __preinit_array_start
53 self.preinit_array_start_index = try self.addGlobal("__preinit_array_start", elf_file);81 nsyms += 1; // __preinit_array_end
54 self.preinit_array_end_index = try self.addGlobal("__preinit_array_end", elf_file);82 nsyms += 1; // _GLOBAL_OFFSET_TABLE_
55 self.got_index = try self.addGlobal("_GLOBAL_OFFSET_TABLE_", elf_file);83 nsyms += 1; // _PROCEDURE_LINKAGE_TABLE_
56 self.plt_index = try self.addGlobal("_PROCEDURE_LINKAGE_TABLE_", elf_file);84 nsyms += 1; // _end
57 self.end_index = try self.addGlobal("_end", elf_file);
58
59 if (elf_file.base.comp.link_eh_frame_hdr) {85 if (elf_file.base.comp.link_eh_frame_hdr) {
60 self.gnu_eh_frame_hdr_index = try self.addGlobal("__GNU_EH_FRAME_HDR", elf_file);86 nsyms += 1; // __GNU_EH_FRAME_HDR
87 }
88 nsyms += 1; // __dso_handle
89 nsyms += 1; // __rela_iplt_start
90 nsyms += 1; // __rela_iplt_end
91 if (elf_file.getTarget().cpu.arch.isRISCV() and elf_file.isEffectivelyDynLib()) {
92 nsyms += 1; // __global_pointer$
61 }93 }
6294
63 self.dso_handle_index = try self.addGlobal("__dso_handle", elf_file);95 var start_stop_count: usize = 0;
64 self.rela_iplt_start_index = try self.addGlobal("__rela_iplt_start", elf_file);96 for (elf_file.objects.items) |index| {
65 self.rela_iplt_end_index = try self.addGlobal("__rela_iplt_end", elf_file);97 for (elf_file.file(index).?.object.shdrs.items) |shdr| {
98 if (elf_file.getStartStopBasename(shdr)) |_| {
99 start_stop_count += 2; // __start_, __stop_
100 }
101 }
102 }
103 nsyms += start_stop_count;
66104
67 for (elf_file.shdrs.items) |shdr| {105 try self.start_stop_indexes.ensureTotalCapacityPrecise(gpa, start_stop_count);
68 if (elf_file.getStartStopBasename(shdr)) |name| {106 try self.symtab.ensureTotalCapacityPrecise(gpa, nsyms);
69 try self.start_stop_indexes.ensureUnusedCapacity(gpa, 2);107 try self.symbols.ensureTotalCapacityPrecise(gpa, nsyms);
108 try self.symbols_extra.ensureTotalCapacityPrecise(gpa, nsyms * @sizeOf(Symbol.Extra));
109 try self.symbols_resolver.ensureTotalCapacityPrecise(gpa, nsyms);
110 self.symbols_resolver.resize(gpa, nsyms) catch unreachable;
111 @memset(self.symbols_resolver.items, 0);
70112
71 const start = try std.fmt.allocPrintZ(gpa, "__start_{s}", .{name});113 if (elf_file.entry_name) |name| {
72 defer gpa.free(start);114 self.entry_index = newSymbolAssumeCapacity(self, try self.addString(gpa, name));
73 const stop = try std.fmt.allocPrintZ(gpa, "__stop_{s}", .{name});115 }
74 defer gpa.free(stop);
75116
76 self.start_stop_indexes.appendAssumeCapacity(try self.addGlobal(start, elf_file));117 self.dynamic_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "_DYNAMIC"));
77 self.start_stop_indexes.appendAssumeCapacity(try self.addGlobal(stop, elf_file));118 self.ehdr_start_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__ehdr_start"));
78 }119 self.init_array_start_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__init_array_start"));
120 self.init_array_end_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__init_array_end"));
121 self.fini_array_start_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__fini_array_start"));
122 self.fini_array_end_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__fini_array_end"));
123 self.preinit_array_start_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__preinit_array_start"));
124 self.preinit_array_end_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__preinit_array_end"));
125 self.got_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "_GLOBAL_OFFSET_TABLE_"));
126 self.plt_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "_PROCEDURE_LINKAGE_TABLE_"));
127 self.end_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "_end"));
128
129 if (elf_file.base.comp.link_eh_frame_hdr) {
130 self.gnu_eh_frame_hdr_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__GNU_EH_FRAME_HDR"));
79 }131 }
80132
133 self.dso_handle_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__dso_handle"));
134 self.rela_iplt_start_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__rela_iplt_start"));
135 self.rela_iplt_end_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__rela_iplt_end"));
136
81 if (elf_file.getTarget().cpu.arch.isRISCV() and elf_file.isEffectivelyDynLib()) {137 if (elf_file.getTarget().cpu.arch.isRISCV() and elf_file.isEffectivelyDynLib()) {
82 self.global_pointer_index = try self.addGlobal("__global_pointer$", elf_file);138 self.global_pointer_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__global_pointer$"));
83 }139 }
84}
85140
86fn addGlobal(self: *LinkerDefined, name: []const u8, elf_file: *Elf) !u32 {141 for (elf_file.objects.items) |index| {
87 const comp = elf_file.base.comp;142 for (elf_file.file(index).?.object.shdrs.items) |shdr| {
88 const gpa = comp.gpa;143 if (elf_file.getStartStopBasename(shdr)) |name| {
89 try self.symtab.ensureUnusedCapacity(gpa, 1);144 const start_name = try std.fmt.allocPrintZ(gpa, "__start_{s}", .{name});
90 try self.symbols.ensureUnusedCapacity(gpa, 1);145 defer gpa.free(start_name);
91 const name_off = @as(u32, @intCast(self.strtab.items.len));146 const stop_name = try std.fmt.allocPrintZ(gpa, "__stop_{s}", .{name});
92 try self.strtab.writer(gpa).print("{s}\x00", .{name});147 defer gpa.free(stop_name);
93 self.symtab.appendAssumeCapacity(.{148 const start = newSymbolAssumeCapacity(self, try self.addString(gpa, start_name));
94 .st_name = name_off,149 const stop = newSymbolAssumeCapacity(self, try self.addString(gpa, stop_name));
95 .st_info = elf.STB_GLOBAL << 4,150 self.start_stop_indexes.appendSliceAssumeCapacity(&.{ start, stop });
96 .st_other = @intFromEnum(elf.STV.HIDDEN),151 }
97 .st_shndx = elf.SHN_ABS,152 }
98 .st_value = 0,153 }
99 .st_size = 0,
100 });
101 const gop = try elf_file.getOrPutGlobal(name);
102 self.symbols.addOneAssumeCapacity().* = gop.index;
103 return gop.index;
104}154}
105155
106pub fn resolveSymbols(self: *LinkerDefined, elf_file: *Elf) void {156pub fn resolveSymbols(self: *LinkerDefined, elf_file: *Elf) !void {
107 for (self.symbols.items, 0..) |index, i| {157 const gpa = elf_file.base.comp.gpa;
108 const sym_idx = @as(Symbol.Index, @intCast(i));158
109 const this_sym = self.symtab.items[sym_idx];159 for (self.symtab.items, self.symbols_resolver.items, 0..) |esym, *resolv, i| {
160 const gop = try elf_file.resolver.getOrPut(gpa, .{
161 .index = @intCast(i),
162 .file = self.index,
163 }, elf_file);
164 if (!gop.found_existing) {
165 gop.ref.* = .{ .index = 0, .file = 0 };
166 }
167 resolv.* = gop.index;
110168
111 if (this_sym.st_shndx == elf.SHN_UNDEF) continue;169 if (esym.st_shndx == elf.SHN_UNDEF) continue;
170 if (elf_file.symbol(gop.ref.*) == null) {
171 gop.ref.* = .{ .index = @intCast(i), .file = self.index };
172 continue;
173 }
112174
113 const global = elf_file.symbol(index);175 if (self.asFile().symbolRank(esym, false) < elf_file.symbol(gop.ref.*).?.symbolRank(elf_file)) {
114 if (self.asFile().symbolRank(this_sym, false) < global.symbolRank(elf_file)) {176 gop.ref.* = .{ .index = @intCast(i), .file = self.index };
115 global.value = 0;
116 global.ref = .{ .index = 0, .file = 0 };
117 global.file_index = self.index;
118 global.esym_index = sym_idx;
119 global.version_index = elf_file.default_sym_version;
120 }177 }
121 }178 }
122}179}
...@@ -125,93 +182,73 @@ pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void {...@@ -125,93 +182,73 @@ pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void {
125 const comp = elf_file.base.comp;182 const comp = elf_file.base.comp;
126 const link_mode = comp.config.link_mode;183 const link_mode = comp.config.link_mode;
127184
185 const allocSymbol = struct {
186 fn allocSymbol(ld: *LinkerDefined, index: Symbol.Index, value: u64, osec: u32, ef: *Elf) void {
187 const sym = ef.symbol(ld.resolveSymbol(index, ef)).?;
188 sym.value = @intCast(value);
189 sym.output_section_index = osec;
190 }
191 }.allocSymbol;
192
128 // _DYNAMIC193 // _DYNAMIC
129 if (elf_file.dynamic_section_index) |shndx| {194 if (elf_file.dynamic_section_index) |shndx| {
130 const shdr = &elf_file.shdrs.items[shndx];195 const shdr = &elf_file.shdrs.items[shndx];
131 const symbol_ptr = elf_file.symbol(self.dynamic_index.?);196 allocSymbol(self, self.dynamic_index.?, shdr.sh_addr, shndx, elf_file);
132 symbol_ptr.value = @intCast(shdr.sh_addr);
133 symbol_ptr.output_section_index = shndx;
134 }197 }
135198
136 // __ehdr_start199 // __ehdr_start
137 {200 allocSymbol(self, self.ehdr_start_index.?, elf_file.image_base, 1, elf_file);
138 const symbol_ptr = elf_file.symbol(self.ehdr_start_index.?);
139 symbol_ptr.value = @intCast(elf_file.image_base);
140 symbol_ptr.output_section_index = 1;
141 }
142201
143 // __init_array_start, __init_array_end202 // __init_array_start, __init_array_end
144 if (elf_file.sectionByName(".init_array")) |shndx| {203 if (elf_file.sectionByName(".init_array")) |shndx| {
145 const start_sym = elf_file.symbol(self.init_array_start_index.?);
146 const end_sym = elf_file.symbol(self.init_array_end_index.?);
147 const shdr = &elf_file.shdrs.items[shndx];204 const shdr = &elf_file.shdrs.items[shndx];
148 start_sym.output_section_index = shndx;205 allocSymbol(self, self.init_array_start_index.?, shdr.sh_addr, shndx, elf_file);
149 start_sym.value = @intCast(shdr.sh_addr);206 allocSymbol(self, self.init_array_end_index.?, shdr.sh_addr + shdr.sh_size, shndx, elf_file);
150 end_sym.output_section_index = shndx;
151 end_sym.value = @intCast(shdr.sh_addr + shdr.sh_size);
152 }207 }
153208
154 // __fini_array_start, __fini_array_end209 // __fini_array_start, __fini_array_end
155 if (elf_file.sectionByName(".fini_array")) |shndx| {210 if (elf_file.sectionByName(".fini_array")) |shndx| {
156 const start_sym = elf_file.symbol(self.fini_array_start_index.?);
157 const end_sym = elf_file.symbol(self.fini_array_end_index.?);
158 const shdr = &elf_file.shdrs.items[shndx];211 const shdr = &elf_file.shdrs.items[shndx];
159 start_sym.output_section_index = shndx;212 allocSymbol(self, self.fini_array_start_index.?, shdr.sh_addr, shndx, elf_file);
160 start_sym.value = @intCast(shdr.sh_addr);213 allocSymbol(self, self.fini_array_end_index.?, shdr.sh_addr + shdr.sh_size, shndx, elf_file);
161 end_sym.output_section_index = shndx;
162 end_sym.value = @intCast(shdr.sh_addr + shdr.sh_size);
163 }214 }
164215
165 // __preinit_array_start, __preinit_array_end216 // __preinit_array_start, __preinit_array_end
166 if (elf_file.sectionByName(".preinit_array")) |shndx| {217 if (elf_file.sectionByName(".preinit_array")) |shndx| {
167 const start_sym = elf_file.symbol(self.preinit_array_start_index.?);
168 const end_sym = elf_file.symbol(self.preinit_array_end_index.?);
169 const shdr = &elf_file.shdrs.items[shndx];218 const shdr = &elf_file.shdrs.items[shndx];
170 start_sym.output_section_index = shndx;219 allocSymbol(self, self.preinit_array_start_index.?, shdr.sh_addr, shndx, elf_file);
171 start_sym.value = @intCast(shdr.sh_addr);220 allocSymbol(self, self.preinit_array_end_index.?, shdr.sh_addr + shdr.sh_size, shndx, elf_file);
172 end_sym.output_section_index = shndx;
173 end_sym.value = @intCast(shdr.sh_addr + shdr.sh_size);
174 }221 }
175222
176 // _GLOBAL_OFFSET_TABLE_223 // _GLOBAL_OFFSET_TABLE_
177 if (elf_file.getTarget().cpu.arch == .x86_64) {224 if (elf_file.getTarget().cpu.arch == .x86_64) {
178 if (elf_file.got_plt_section_index) |shndx| {225 if (elf_file.got_plt_section_index) |shndx| {
179 const shdr = elf_file.shdrs.items[shndx];226 const shdr = elf_file.shdrs.items[shndx];
180 const sym = elf_file.symbol(self.got_index.?);227 allocSymbol(self, self.got_index.?, shdr.sh_addr, shndx, elf_file);
181 sym.value = @intCast(shdr.sh_addr);
182 sym.output_section_index = shndx;
183 }228 }
184 } else {229 } else {
185 if (elf_file.got_section_index) |shndx| {230 if (elf_file.got_section_index) |shndx| {
186 const shdr = elf_file.shdrs.items[shndx];231 const shdr = elf_file.shdrs.items[shndx];
187 const sym = elf_file.symbol(self.got_index.?);232 allocSymbol(self, self.got_index.?, shdr.sh_addr, shndx, elf_file);
188 sym.value = @intCast(shdr.sh_addr);
189 sym.output_section_index = shndx;
190 }233 }
191 }234 }
192235
193 // _PROCEDURE_LINKAGE_TABLE_236 // _PROCEDURE_LINKAGE_TABLE_
194 if (elf_file.plt_section_index) |shndx| {237 if (elf_file.plt_section_index) |shndx| {
195 const shdr = &elf_file.shdrs.items[shndx];238 const shdr = &elf_file.shdrs.items[shndx];
196 const symbol_ptr = elf_file.symbol(self.plt_index.?);239 allocSymbol(self, self.plt_index.?, shdr.sh_addr, shndx, elf_file);
197 symbol_ptr.value = @intCast(shdr.sh_addr);
198 symbol_ptr.output_section_index = shndx;
199 }240 }
200241
201 // __dso_handle242 // __dso_handle
202 if (self.dso_handle_index) |index| {243 if (self.dso_handle_index) |index| {
203 const shdr = &elf_file.shdrs.items[1];244 const shdr = &elf_file.shdrs.items[1];
204 const symbol_ptr = elf_file.symbol(index);245 allocSymbol(self, index, shdr.sh_addr, 0, elf_file);
205 symbol_ptr.value = @intCast(shdr.sh_addr);
206 symbol_ptr.output_section_index = 0;
207 }246 }
208247
209 // __GNU_EH_FRAME_HDR248 // __GNU_EH_FRAME_HDR
210 if (elf_file.eh_frame_hdr_section_index) |shndx| {249 if (elf_file.eh_frame_hdr_section_index) |shndx| {
211 const shdr = &elf_file.shdrs.items[shndx];250 const shdr = &elf_file.shdrs.items[shndx];
212 const symbol_ptr = elf_file.symbol(self.gnu_eh_frame_hdr_index.?);251 allocSymbol(self, self.gnu_eh_frame_hdr_index.?, shdr.sh_addr, shndx, elf_file);
213 symbol_ptr.value = @intCast(shdr.sh_addr);
214 symbol_ptr.output_section_index = shndx;
215 }252 }
216253
217 // __rela_iplt_start, __rela_iplt_end254 // __rela_iplt_start, __rela_iplt_end
...@@ -220,32 +257,41 @@ pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void {...@@ -220,32 +257,41 @@ pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void {
220 const shdr = &elf_file.shdrs.items[shndx];257 const shdr = &elf_file.shdrs.items[shndx];
221 const end_addr = shdr.sh_addr + shdr.sh_size;258 const end_addr = shdr.sh_addr + shdr.sh_size;
222 const start_addr = end_addr - elf_file.calcNumIRelativeRelocs() * @sizeOf(elf.Elf64_Rela);259 const start_addr = end_addr - elf_file.calcNumIRelativeRelocs() * @sizeOf(elf.Elf64_Rela);
223 const start_sym = elf_file.symbol(self.rela_iplt_start_index.?);260 allocSymbol(self, self.rela_iplt_start_index.?, start_addr, shndx, elf_file);
224 const end_sym = elf_file.symbol(self.rela_iplt_end_index.?);261 allocSymbol(self, self.rela_iplt_end_index.?, end_addr, shndx, elf_file);
225 start_sym.value = @intCast(start_addr);
226 start_sym.output_section_index = shndx;
227 end_sym.value = @intCast(end_addr);
228 end_sym.output_section_index = shndx;
229 }262 }
230263
231 // _end264 // _end
232 {265 {
233 const end_symbol = elf_file.symbol(self.end_index.?);266 var value: u64 = 0;
267 var osec: u32 = 0;
234 for (elf_file.shdrs.items, 0..) |shdr, shndx| {268 for (elf_file.shdrs.items, 0..) |shdr, shndx| {
235 if (shdr.sh_flags & elf.SHF_ALLOC != 0) {269 if (shdr.sh_flags & elf.SHF_ALLOC != 0) {
236 end_symbol.value = @intCast(shdr.sh_addr + shdr.sh_size);270 value = shdr.sh_addr + shdr.sh_size;
237 end_symbol.output_section_index = @intCast(shndx);271 osec = shndx;
238 }272 }
239 }273 }
274 allocSymbol(self, self.end_index.?, value, osec, elf_file);
275 }
276
277 // __global_pointer$
278 if (self.global_pointer_index) |index| {
279 const value, const osec = if (elf_file.sectionByName(".sdata")) |shndx| .{
280 elf_file.shdrs.items[shndx].sh_addr + 0x800,
281 shndx,
282 } else .{ 0, 0 };
283 allocSymbol(self, index, value, osec, elf_file);
240 }284 }
241285
242 // __start_*, __stop_*286 // __start_*, __stop_*
243 {287 {
244 var index: usize = 0;288 var index: usize = 0;
245 while (index < self.start_stop_indexes.items.len) : (index += 2) {289 while (index < self.start_stop_indexes.items.len) : (index += 2) {
246 const start = elf_file.symbol(self.start_stop_indexes.items[index]);290 const start_ref = self.resolveSymbol(self.start_stop_indexes.items[index]);
291 const start = elf_file.symbol(start_ref).?;
247 const name = start.name(elf_file);292 const name = start.name(elf_file);
248 const stop = elf_file.symbol(self.start_stop_indexes.items[index + 1]);293 const stop_ref = self.resolveSymbol(self.start_stop_indexes.items[index + 1]);
294 const stop = elf_file.symbol(stop_ref).?;
249 const shndx = elf_file.sectionByName(name["__start_".len..]).?;295 const shndx = elf_file.sectionByName(name["__start_".len..]).?;
250 const shdr = &elf_file.shdrs.items[shndx];296 const shdr = &elf_file.shdrs.items[shndx];
251 start.value = @intCast(shdr.sh_addr);297 start.value = @intCast(shdr.sh_addr);
...@@ -254,47 +300,34 @@ pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void {...@@ -254,47 +300,34 @@ pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void {
254 stop.output_section_index = shndx;300 stop.output_section_index = shndx;
255 }301 }
256 }302 }
257
258 // __global_pointer$
259 if (self.global_pointer_index) |index| {
260 const sym = elf_file.symbol(index);
261 if (elf_file.sectionByName(".sdata")) |shndx| {
262 const shdr = elf_file.shdrs.items[shndx];
263 sym.value = @intCast(shdr.sh_addr + 0x800);
264 sym.output_section_index = shndx;
265 } else {
266 sym.value = 0;
267 sym.output_section_index = 0;
268 }
269 }
270}303}
271304
272pub fn globals(self: LinkerDefined) []const Symbol.Index {305pub fn globals(self: *LinkerDefined) []Symbol {
273 return self.symbols.items;306 return self.symbols.items;
274}307}
275308
276pub fn updateSymtabSize(self: *LinkerDefined, elf_file: *Elf) !void {309pub fn updateSymtabSize(self: *LinkerDefined, elf_file: *Elf) void {
277 for (self.globals()) |global_index| {310 for (self.globals(), self.symbols_resolver.items) |*global, resolv| {
278 const global = elf_file.symbol(global_index);311 const ref = elf_file.resolver.get(resolv).?;
279 const file_ptr = global.file(elf_file) orelse continue;312 const ref_sym = elf_file.symbol(ref) orelse continue;
280 if (file_ptr.index() != self.index) continue;313 if (ref_sym.file(elf_file).?.index() != self.index) continue;
281 global.flags.output_symtab = true;314 global.flags.output_symtab = true;
282 if (global.isLocal(elf_file)) {315 if (global.isLocal(elf_file)) {
283 try global.addExtra(.{ .symtab = self.output_symtab_ctx.nlocals }, elf_file);316 global.addExtra(.{ .symtab = self.output_symtab_ctx.nlocals }, elf_file);
284 self.output_symtab_ctx.nlocals += 1;317 self.output_symtab_ctx.nlocals += 1;
285 } else {318 } else {
286 try global.addExtra(.{ .symtab = self.output_symtab_ctx.nglobals }, elf_file);319 global.addExtra(.{ .symtab = self.output_symtab_ctx.nglobals }, elf_file);
287 self.output_symtab_ctx.nglobals += 1;320 self.output_symtab_ctx.nglobals += 1;
288 }321 }
289 self.output_symtab_ctx.strsize += @as(u32, @intCast(global.name(elf_file).len)) + 1;322 self.output_symtab_ctx.strsize += @as(u32, @intCast(global.name(elf_file).len)) + 1;
290 }323 }
291}324}
292325
293pub fn writeSymtab(self: LinkerDefined, elf_file: *Elf) void {326pub fn writeSymtab(self: *LinkerDefined, elf_file: *Elf) void {
294 for (self.globals()) |global_index| {327 for (self.globals(), self.symbols_resolver.items) |global, resolv| {
295 const global = elf_file.symbol(global_index);328 const ref = elf_file.resolver.get(resolv).?;
296 const file_ptr = global.file(elf_file) orelse continue;329 const ref_sym = elf_file.symbol(ref) orelse continue;
297 if (file_ptr.index() != self.index) continue;330 if (ref_sym.file(elf_file).?.index() != self.index) continue;
298 const idx = global.outputSymtabIndex(elf_file) orelse continue;331 const idx = global.outputSymtabIndex(elf_file) orelse continue;
299 const st_name = @as(u32, @intCast(elf_file.strtab.items.len));332 const st_name = @as(u32, @intCast(elf_file.strtab.items.len));
300 elf_file.strtab.appendSliceAssumeCapacity(global.name(elf_file));333 elf_file.strtab.appendSliceAssumeCapacity(global.name(elf_file));
...@@ -309,11 +342,73 @@ pub fn asFile(self: *LinkerDefined) File {...@@ -309,11 +342,73 @@ pub fn asFile(self: *LinkerDefined) File {
309 return .{ .linker_defined = self };342 return .{ .linker_defined = self };
310}343}
311344
345fn addString(self: *LinkerDefined, allocator: Allocator, str: []const u8) !u32 {
346 const off: u32 = @intCast(self.strtab.items.len);
347 try self.strtab.ensureUnusedCapacity(allocator, str.len + 1);
348 self.strtab.appendSliceAssumeCapacity(str);
349 self.strtab.appendAssumeCapacity(0);
350 return off;
351}
352
312pub fn getString(self: LinkerDefined, off: u32) [:0]const u8 {353pub fn getString(self: LinkerDefined, off: u32) [:0]const u8 {
313 assert(off < self.strtab.items.len);354 assert(off < self.strtab.items.len);
314 return mem.sliceTo(@as([*:0]const u8, @ptrCast(self.strtab.items.ptr + off)), 0);355 return mem.sliceTo(@as([*:0]const u8, @ptrCast(self.strtab.items.ptr + off)), 0);
315}356}
316357
358pub fn resolveSymbol(self: LinkerDefined, index: Symbol.Index, elf_file: *Elf) Elf.Ref {
359 const resolv = self.symbols_resolver.items[index];
360 return elf_file.resolver.get(resolv).?;
361}
362
363pub fn addSymbol(self: *LinkerDefined, allocator: Allocator) !Symbol.Index {
364 try self.symbols.ensureUnusedCapacity(allocator, 1);
365 const index: Symbol.Index = @intCast(self.symbols.items.len);
366 self.symbols.appendAssumeCapacity(.{ .file_index = self.index });
367 return index;
368}
369
370pub fn addSymbolExtra(self: *LinkerDefined, allocator: Allocator, extra: Symbol.Extra) !u32 {
371 const fields = @typeInfo(Symbol.Extra).Struct.fields;
372 try self.symbols_extra.ensureUnusedCapacity(allocator, fields.len);
373 return self.addSymbolExtraAssumeCapacity(extra);
374}
375
376pub fn addSymbolExtraAssumeCapacity(self: *LinkerDefined, extra: Symbol.Extra) u32 {
377 const index = @as(u32, @intCast(self.symbols_extra.items.len));
378 const fields = @typeInfo(Symbol.Extra).Struct.fields;
379 inline for (fields) |field| {
380 self.symbols_extra.appendAssumeCapacity(switch (field.type) {
381 u32 => @field(extra, field.name),
382 else => @compileError("bad field type"),
383 });
384 }
385 return index;
386}
387
388pub fn symbolExtra(self: *LinkerDefined, index: u32) Symbol.Extra {
389 const fields = @typeInfo(Symbol.Extra).Struct.fields;
390 var i: usize = index;
391 var result: Symbol.Extra = undefined;
392 inline for (fields) |field| {
393 @field(result, field.name) = switch (field.type) {
394 u32 => self.symbols_extra.items[i],
395 else => @compileError("bad field type"),
396 };
397 i += 1;
398 }
399 return result;
400}
401
402pub fn setSymbolExtra(self: *LinkerDefined, index: u32, extra: Symbol.Extra) void {
403 const fields = @typeInfo(Symbol.Extra).Struct.fields;
404 inline for (fields, 0..) |field, i| {
405 self.symbols_extra.items[index + i] = switch (field.type) {
406 u32 => @field(extra, field.name),
407 else => @compileError("bad field type"),
408 };
409 }
410}
411
317pub fn fmtSymtab(self: *LinkerDefined, elf_file: *Elf) std.fmt.Formatter(formatSymtab) {412pub fn fmtSymtab(self: *LinkerDefined, elf_file: *Elf) std.fmt.Formatter(formatSymtab) {
318 return .{ .data = .{413 return .{ .data = .{
319 .self = self,414 .self = self,
src/link/Elf/SharedObject.zig+2-2
...@@ -282,7 +282,7 @@ pub fn markLive(self: *SharedObject, elf_file: *Elf) void {...@@ -282,7 +282,7 @@ pub fn markLive(self: *SharedObject, elf_file: *Elf) void {
282 }282 }
283}283}
284284
285pub fn globals(self: SharedObject) []const Symbol.Index {285pub fn globals(self: *SharedObject) []Symbol {
286 return self.symbols.items;286 return self.symbols.items;
287}287}
288288
...@@ -299,7 +299,7 @@ pub fn updateSymtabSize(self: *SharedObject, elf_file: *Elf) void {...@@ -299,7 +299,7 @@ pub fn updateSymtabSize(self: *SharedObject, elf_file: *Elf) void {
299 }299 }
300}300}
301301
302pub fn writeSymtab(self: SharedObject, elf_file: *Elf) void {302pub fn writeSymtab(self: *SharedObject, elf_file: *Elf) void {
303 for (self.globals(), self.symbols_resolver.items) |global, resolv| {303 for (self.globals(), self.symbols_resolver.items) |global, resolv| {
304 const ref = elf_file.resolver.get(resolv).?;304 const ref = elf_file.resolver.get(resolv).?;
305 const ref_sym = elf_file.symbol(ref) orelse continue;305 const ref_sym = elf_file.symbol(ref) orelse continue;