diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2024-08-06 12:36:51 +0200 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2024-08-07 10:21:03 +0200 |
| commit | e99818c602f7e2f75c62be7c4329688c8fa5afe1 (patch) | |
| tree | 8c9e28c717241a1991e996097ded8f26b5463243 /src | |
| parent | 835f1fc03f795663bfd98a768f132bf99168d40f (diff) | |
| download | zig-e99818c602f7e2f75c62be7c4329688c8fa5afe1.tar.gz zig-e99818c602f7e2f75c62be7c4329688c8fa5afe1.zip | |
elf: start-stop resolution has to come after init output sections
Diffstat (limited to 'src')
| -rw-r--r-- | src/link/Elf.zig | 11 | ||||
| -rw-r--r-- | src/link/Elf/LinkerDefined.zig | 135 | ||||
| -rw-r--r-- | src/link/Elf/Object.zig | 8 |
3 files changed, 83 insertions, 71 deletions
diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 4478bb0760..1a3087e8f9 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -1282,6 +1282,9 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod try self.finalizeMergeSections(); try self.initOutputSections(); try self.initMergeSections(); + if (self.linkerDefinedPtr()) |obj| { + try obj.initStartStopSymbols(self); + } self.claimUnresolved(); // Scan and create missing synthetic entries such as GOT indirection. @@ -5247,6 +5250,14 @@ pub fn calcNumIRelativeRelocs(self: *Elf) usize { return count; } +pub fn getStartStopBasename(self: Elf, shdr: elf.Elf64_Shdr) ?[]const u8 { + const name = self.getShString(shdr.sh_name); + if (shdr.sh_flags & elf.SHF_ALLOC != 0 and name.len > 0) { + if (Elf.isCIdentifier(name)) return name; + } + return null; +} + pub fn isCIdentifier(name: []const u8) bool { if (name.len == 0) return false; const first_c = name[0]; diff --git a/src/link/Elf/LinkerDefined.zig b/src/link/Elf/LinkerDefined.zig index 0ead1dba62..0a3a96d95e 100644 --- a/src/link/Elf/LinkerDefined.zig +++ b/src/link/Elf/LinkerDefined.zig @@ -42,30 +42,28 @@ pub fn init(self: *LinkerDefined, allocator: Allocator) !void { try self.strtab.append(allocator, 0); } -pub fn initSymbols(self: *LinkerDefined, elf_file: *Elf) !void { - const newSymbolAssumeCapacity = struct { - fn newSymbolAssumeCapacity(ld: *LinkerDefined, name_off: u32, ef: *Elf) Symbol.Index { - const esym_index: u32 = @intCast(ld.symtab.items.len); - const esym = ld.symtab.addOneAssumeCapacity(); - esym.* = .{ - .st_name = name_off, - .st_info = elf.STB_GLOBAL << 4, - .st_other = @intFromEnum(elf.STV.HIDDEN), - .st_shndx = elf.SHN_ABS, - .st_value = 0, - .st_size = 0, - }; - const index = ld.addSymbolAssumeCapacity(); - const symbol = &ld.symbols.items[index]; - symbol.name_offset = name_off; - symbol.extra_index = ld.addSymbolExtraAssumeCapacity(.{}); - symbol.ref = .{ .index = 0, .file = 0 }; - symbol.esym_index = esym_index; - symbol.version_index = ef.default_sym_version; - return index; - } - }.newSymbolAssumeCapacity; +fn newSymbolAssumeCapacity(self: *LinkerDefined, name_off: u32, elf_file: *Elf) Symbol.Index { + const esym_index: u32 = @intCast(self.symtab.items.len); + const esym = self.symtab.addOneAssumeCapacity(); + esym.* = .{ + .st_name = name_off, + .st_info = elf.STB_GLOBAL << 4, + .st_other = @intFromEnum(elf.STV.HIDDEN), + .st_shndx = elf.SHN_ABS, + .st_value = 0, + .st_size = 0, + }; + const index = self.addSymbolAssumeCapacity(); + const symbol = &self.symbols.items[index]; + symbol.name_offset = name_off; + symbol.extra_index = self.addSymbolExtraAssumeCapacity(.{}); + symbol.ref = .{ .index = 0, .file = 0 }; + symbol.esym_index = esym_index; + symbol.version_index = elf_file.default_sym_version; + return index; +} +pub fn initSymbols(self: *LinkerDefined, elf_file: *Elf) !void { const gpa = elf_file.base.comp.gpa; var nsyms: usize = 0; @@ -93,18 +91,6 @@ pub fn initSymbols(self: *LinkerDefined, elf_file: *Elf) !void { nsyms += 1; // __global_pointer$ } - var start_stop_count: usize = 0; - for (elf_file.objects.items) |index| { - const object = elf_file.file(index).?.object; - for (object.shdrs.items) |shdr| { - if (object.getStartStopBasename(shdr)) |_| { - start_stop_count += 2; // __start_, __stop_ - } - } - } - nsyms += start_stop_count; - - try self.start_stop_indexes.ensureTotalCapacityPrecise(gpa, start_stop_count); try self.symtab.ensureTotalCapacityPrecise(gpa, nsyms); try self.symbols.ensureTotalCapacityPrecise(gpa, nsyms); try self.symbols_extra.ensureTotalCapacityPrecise(gpa, nsyms * @sizeOf(Symbol.Extra)); @@ -113,44 +99,67 @@ pub fn initSymbols(self: *LinkerDefined, elf_file: *Elf) !void { @memset(self.symbols_resolver.items, 0); if (elf_file.entry_name) |name| { - self.entry_index = newSymbolAssumeCapacity(self, try self.addString(gpa, name), elf_file); + self.entry_index = self.newSymbolAssumeCapacity(try self.addString(gpa, name), elf_file); } - self.dynamic_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "_DYNAMIC"), elf_file); - self.ehdr_start_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__ehdr_start"), elf_file); - self.init_array_start_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__init_array_start"), elf_file); - self.init_array_end_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__init_array_end"), elf_file); - self.fini_array_start_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__fini_array_start"), elf_file); - self.fini_array_end_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__fini_array_end"), elf_file); - self.preinit_array_start_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__preinit_array_start"), elf_file); - self.preinit_array_end_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__preinit_array_end"), elf_file); - self.got_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "_GLOBAL_OFFSET_TABLE_"), elf_file); - self.plt_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "_PROCEDURE_LINKAGE_TABLE_"), elf_file); - self.end_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "_end"), elf_file); + self.dynamic_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "_DYNAMIC"), elf_file); + self.ehdr_start_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "__ehdr_start"), elf_file); + self.init_array_start_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "__init_array_start"), elf_file); + self.init_array_end_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "__init_array_end"), elf_file); + self.fini_array_start_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "__fini_array_start"), elf_file); + self.fini_array_end_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "__fini_array_end"), elf_file); + self.preinit_array_start_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "__preinit_array_start"), elf_file); + self.preinit_array_end_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "__preinit_array_end"), elf_file); + self.got_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "_GLOBAL_OFFSET_TABLE_"), elf_file); + self.plt_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "_PROCEDURE_LINKAGE_TABLE_"), elf_file); + self.end_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "_end"), elf_file); if (elf_file.base.comp.link_eh_frame_hdr) { - self.gnu_eh_frame_hdr_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__GNU_EH_FRAME_HDR"), elf_file); + self.gnu_eh_frame_hdr_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "__GNU_EH_FRAME_HDR"), elf_file); } - self.dso_handle_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__dso_handle"), elf_file); - self.rela_iplt_start_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__rela_iplt_start"), elf_file); - self.rela_iplt_end_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__rela_iplt_end"), elf_file); + self.dso_handle_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "__dso_handle"), elf_file); + self.rela_iplt_start_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "__rela_iplt_start"), elf_file); + self.rela_iplt_end_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "__rela_iplt_end"), elf_file); if (elf_file.getTarget().cpu.arch.isRISCV() and elf_file.isEffectivelyDynLib()) { - self.global_pointer_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__global_pointer$"), elf_file); + self.global_pointer_index = self.newSymbolAssumeCapacity(try self.addString(gpa, "__global_pointer$"), elf_file); + } +} + +pub fn initStartStopSymbols(self: *LinkerDefined, elf_file: *Elf) !void { + const gpa = elf_file.base.comp.gpa; + + var nsyms: usize = 0; + for (elf_file.shdrs.items) |shdr| { + if (elf_file.getStartStopBasename(shdr)) |_| { + nsyms += 2; // __start_, __stop_ + } } - for (elf_file.objects.items) |index| { - const object = elf_file.file(index).?.object; - for (object.shdrs.items) |shdr| { - if (object.getStartStopBasename(shdr)) |name| { - const start_name = try std.fmt.allocPrintZ(gpa, "__start_{s}", .{name}); - defer gpa.free(start_name); - const stop_name = try std.fmt.allocPrintZ(gpa, "__stop_{s}", .{name}); - defer gpa.free(stop_name); - const start = newSymbolAssumeCapacity(self, try self.addString(gpa, start_name), elf_file); - const stop = newSymbolAssumeCapacity(self, try self.addString(gpa, stop_name), elf_file); - self.start_stop_indexes.appendSliceAssumeCapacity(&.{ start, stop }); + try self.start_stop_indexes.ensureTotalCapacityPrecise(gpa, nsyms); + try self.symtab.ensureUnusedCapacity(gpa, nsyms); + try self.symbols.ensureUnusedCapacity(gpa, nsyms); + try self.symbols_extra.ensureUnusedCapacity(gpa, nsyms * @sizeOf(Symbol.Extra)); + try self.symbols_resolver.ensureUnusedCapacity(gpa, nsyms); + + for (elf_file.shdrs.items) |shdr| { + if (elf_file.getStartStopBasename(shdr)) |name| { + const start_name = try std.fmt.allocPrintZ(gpa, "__start_{s}", .{name}); + defer gpa.free(start_name); + const stop_name = try std.fmt.allocPrintZ(gpa, "__stop_{s}", .{name}); + defer gpa.free(stop_name); + + for (&[_][]const u8{ start_name, stop_name }) |nn| { + const index = self.newSymbolAssumeCapacity(try self.addString(gpa, nn), elf_file); + self.start_stop_indexes.appendAssumeCapacity(index); + const gop = try elf_file.resolver.getOrPut(gpa, .{ + .index = index, + .file = self.index, + }, elf_file); + assert(!gop.found_existing); + gop.ref.* = .{ .index = index, .file = self.index }; + self.symbols_resolver.appendAssumeCapacity(gop.index); } } } diff --git a/src/link/Elf/Object.zig b/src/link/Elf/Object.zig index b9903e7bbc..a81a6f34f3 100644 --- a/src/link/Elf/Object.zig +++ b/src/link/Elf/Object.zig @@ -1399,14 +1399,6 @@ pub fn comdatGroup(self: *Object, index: Elf.ComdatGroup.Index) *Elf.ComdatGroup return &self.comdat_groups.items[index]; } -pub fn getStartStopBasename(self: Object, shdr: elf.Elf64_Shdr) ?[]const u8 { - const name = self.getString(shdr.sh_name); - if (shdr.sh_flags & elf.SHF_ALLOC != 0 and name.len > 0) { - if (Elf.isCIdentifier(name)) return name; - } - return null; -} - pub fn format( self: *Object, comptime unused_fmt_string: []const u8, |
