authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-08-06 12:36:51+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-08-07 10:21:03+02:00
loge99818c602f7e2f75c62be7c4329688c8fa5afe1
tree8c9e28c717241a1991e996097ded8f26b5463243
parent835f1fc03f795663bfd98a768f132bf99168d40f

elf: start-stop resolution has to come after init output sections


3 files changed, 83 insertions(+), 71 deletions(-)

src/link/Elf.zig+11
......@@ -1282,6 +1282,9 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod
12821282 try self.finalizeMergeSections();
12831283 try self.initOutputSections();
12841284 try self.initMergeSections();
1285 if (self.linkerDefinedPtr()) |obj| {
1286 try obj.initStartStopSymbols(self);
1287 }
12851288 self.claimUnresolved();
12861289
12871290 // Scan and create missing synthetic entries such as GOT indirection.
......@@ -5247,6 +5250,14 @@ pub fn calcNumIRelativeRelocs(self: *Elf) usize {
52475250 return count;
52485251}
52495252
5253pub fn getStartStopBasename(self: Elf, shdr: elf.Elf64_Shdr) ?[]const u8 {
5254 const name = self.getShString(shdr.sh_name);
5255 if (shdr.sh_flags & elf.SHF_ALLOC != 0 and name.len > 0) {
5256 if (Elf.isCIdentifier(name)) return name;
5257 }
5258 return null;
5259}
5260
52505261pub fn isCIdentifier(name: []const u8) bool {
52515262 if (name.len == 0) return false;
52525263 const first_c = name[0];
src/link/Elf/LinkerDefined.zig+72-63
......@@ -42,30 +42,28 @@ pub fn init(self: *LinkerDefined, allocator: Allocator) !void {
4242 try self.strtab.append(allocator, 0);
4343}
4444
45pub fn initSymbols(self: *LinkerDefined, elf_file: *Elf) !void {
46 const newSymbolAssumeCapacity = struct {
47 fn newSymbolAssumeCapacity(ld: *LinkerDefined, name_off: u32, ef: *Elf) 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 = ef.default_sym_version;
65 return index;
66 }
67 }.newSymbolAssumeCapacity;
45fn newSymbolAssumeCapacity(self: *LinkerDefined, name_off: u32, elf_file: *Elf) Symbol.Index {
46 const esym_index: u32 = @intCast(self.symtab.items.len);
47 const esym = self.symtab.addOneAssumeCapacity();
48 esym.* = .{
49 .st_name = name_off,
50 .st_info = elf.STB_GLOBAL << 4,
51 .st_other = @intFromEnum(elf.STV.HIDDEN),
52 .st_shndx = elf.SHN_ABS,
53 .st_value = 0,
54 .st_size = 0,
55 };
56 const index = self.addSymbolAssumeCapacity();
57 const symbol = &self.symbols.items[index];
58 symbol.name_offset = name_off;
59 symbol.extra_index = self.addSymbolExtraAssumeCapacity(.{});
60 symbol.ref = .{ .index = 0, .file = 0 };
61 symbol.esym_index = esym_index;
62 symbol.version_index = elf_file.default_sym_version;
63 return index;
64}
6865
66pub fn initSymbols(self: *LinkerDefined, elf_file: *Elf) !void {
6967 const gpa = elf_file.base.comp.gpa;
7068
7169 var nsyms: usize = 0;
......@@ -93,18 +91,6 @@ pub fn initSymbols(self: *LinkerDefined, elf_file: *Elf) !void {
9391 nsyms += 1; // __global_pointer$
9492 }
9593
96 var start_stop_count: usize = 0;
97 for (elf_file.objects.items) |index| {
98 const object = elf_file.file(index).?.object;
99 for (object.shdrs.items) |shdr| {
100 if (object.getStartStopBasename(shdr)) |_| {
101 start_stop_count += 2; // __start_, __stop_
102 }
103 }
104 }
105 nsyms += start_stop_count;
106
107 try self.start_stop_indexes.ensureTotalCapacityPrecise(gpa, start_stop_count);
10894 try self.symtab.ensureTotalCapacityPrecise(gpa, nsyms);
10995 try self.symbols.ensureTotalCapacityPrecise(gpa, nsyms);
11096 try self.symbols_extra.ensureTotalCapacityPrecise(gpa, nsyms * @sizeOf(Symbol.Extra));
......@@ -113,44 +99,67 @@ pub fn initSymbols(self: *LinkerDefined, elf_file: *Elf) !void {
11399 @memset(self.symbols_resolver.items, 0);
114100
115101 if (elf_file.entry_name) |name| {
116 self.entry_index = newSymbolAssumeCapacity(self, try self.addString(gpa, name), elf_file);
102 self.entry_index = self.newSymbolAssumeCapacity(try self.addString(gpa, name), elf_file);
117103 }
118104
119 self.dynamic_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "_DYNAMIC"), elf_file);
120 self.ehdr_start_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__ehdr_start"), elf_file);
121 self.init_array_start_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__init_array_start"), elf_file);
122 self.init_array_end_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__init_array_end"), elf_file);
123 self.fini_array_start_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__fini_array_start"), elf_file);
124 self.fini_array_end_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__fini_array_end"), elf_file);
125 self.preinit_array_start_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__preinit_array_start"), elf_file);
126 self.preinit_array_end_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__preinit_array_end"), elf_file);
127 self.got_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "_GLOBAL_OFFSET_TABLE_"), elf_file);
128 self.plt_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "_PROCEDURE_LINKAGE_TABLE_"), elf_file);
129 self.end_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "_end"), elf_file);
105 self.dynamic_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "_DYNAMIC"), elf_file);
106 self.ehdr_start_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "__ehdr_start"), elf_file);
107 self.init_array_start_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "__init_array_start"), elf_file);
108 self.init_array_end_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "__init_array_end"), elf_file);
109 self.fini_array_start_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "__fini_array_start"), elf_file);
110 self.fini_array_end_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "__fini_array_end"), elf_file);
111 self.preinit_array_start_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "__preinit_array_start"), elf_file);
112 self.preinit_array_end_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "__preinit_array_end"), elf_file);
113 self.got_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "_GLOBAL_OFFSET_TABLE_"), elf_file);
114 self.plt_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "_PROCEDURE_LINKAGE_TABLE_"), elf_file);
115 self.end_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "_end"), elf_file);
130116
131117 if (elf_file.base.comp.link_eh_frame_hdr) {
132 self.gnu_eh_frame_hdr_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__GNU_EH_FRAME_HDR"), elf_file);
118 self.gnu_eh_frame_hdr_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "__GNU_EH_FRAME_HDR"), elf_file);
133119 }
134120
135 self.dso_handle_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__dso_handle"), elf_file);
136 self.rela_iplt_start_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__rela_iplt_start"), elf_file);
137 self.rela_iplt_end_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__rela_iplt_end"), elf_file);
121 self.dso_handle_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "__dso_handle"), elf_file);
122 self.rela_iplt_start_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "__rela_iplt_start"), elf_file);
123 self.rela_iplt_end_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "__rela_iplt_end"), elf_file);
138124
139125 if (elf_file.getTarget().cpu.arch.isRISCV() and elf_file.isEffectivelyDynLib()) {
140 self.global_pointer_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__global_pointer$"), elf_file);
126 self.global_pointer_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "__global_pointer$"), elf_file);
127 }
128}
129
130pub fn initStartStopSymbols(self: *LinkerDefined, elf_file: *Elf) !void {
131 const gpa = elf_file.base.comp.gpa;
132
133 var nsyms: usize = 0;
134 for (elf_file.shdrs.items) |shdr| {
135 if (elf_file.getStartStopBasename(shdr)) |_| {
136 nsyms += 2; // __start_, __stop_
137 }
141138 }
142139
143 for (elf_file.objects.items) |index| {
144 const object = elf_file.file(index).?.object;
145 for (object.shdrs.items) |shdr| {
146 if (object.getStartStopBasename(shdr)) |name| {
147 const start_name = try std.fmt.allocPrintZ(gpa, "__start_{s}", .{name});
148 defer gpa.free(start_name);
149 const stop_name = try std.fmt.allocPrintZ(gpa, "__stop_{s}", .{name});
150 defer gpa.free(stop_name);
151 const start = newSymbolAssumeCapacity(self, try self.addString(gpa, start_name), elf_file);
152 const stop = newSymbolAssumeCapacity(self, try self.addString(gpa, stop_name), elf_file);
153 self.start_stop_indexes.appendSliceAssumeCapacity(&.{ start, stop });
140 try self.start_stop_indexes.ensureTotalCapacityPrecise(gpa, nsyms);
141 try self.symtab.ensureUnusedCapacity(gpa, nsyms);
142 try self.symbols.ensureUnusedCapacity(gpa, nsyms);
143 try self.symbols_extra.ensureUnusedCapacity(gpa, nsyms * @sizeOf(Symbol.Extra));
144 try self.symbols_resolver.ensureUnusedCapacity(gpa, nsyms);
145
146 for (elf_file.shdrs.items) |shdr| {
147 if (elf_file.getStartStopBasename(shdr)) |name| {
148 const start_name = try std.fmt.allocPrintZ(gpa, "__start_{s}", .{name});
149 defer gpa.free(start_name);
150 const stop_name = try std.fmt.allocPrintZ(gpa, "__stop_{s}", .{name});
151 defer gpa.free(stop_name);
152
153 for (&[_][]const u8{ start_name, stop_name }) |nn| {
154 const index = self.newSymbolAssumeCapacity(try self.addString(gpa, nn), elf_file);
155 self.start_stop_indexes.appendAssumeCapacity(index);
156 const gop = try elf_file.resolver.getOrPut(gpa, .{
157 .index = index,
158 .file = self.index,
159 }, elf_file);
160 assert(!gop.found_existing);
161 gop.ref.* = .{ .index = index, .file = self.index };
162 self.symbols_resolver.appendAssumeCapacity(gop.index);
154163 }
155164 }
156165 }
src/link/Elf/Object.zig-8
......@@ -1399,14 +1399,6 @@ pub fn comdatGroup(self: *Object, index: Elf.ComdatGroup.Index) *Elf.ComdatGroup
13991399 return &self.comdat_groups.items[index];
14001400}
14011401
1402pub fn getStartStopBasename(self: Object, shdr: elf.Elf64_Shdr) ?[]const u8 {
1403 const name = self.getString(shdr.sh_name);
1404 if (shdr.sh_flags & elf.SHF_ALLOC != 0 and name.len > 0) {
1405 if (Elf.isCIdentifier(name)) return name;
1406 }
1407 return null;
1408}
1409
14101402pub fn format(
14111403 self: *Object,
14121404 comptime unused_fmt_string: []const u8,