From ec67d6e03a05a2d87880d7a97654ae55f4c733a2 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 10 Oct 2024 16:57:41 -0700 Subject: [PATCH 1/7] std.MultiArrayList: add empty initalizer value --- lib/std/multi_array_list.zig | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/std/multi_array_list.zig b/lib/std/multi_array_list.zig index eedc540db27babaab225948a44535bc4f069737e..681fbc3e7e5c03c84832bce42edcc6037ec621fa 100644 --- a/lib/std/multi_array_list.zig +++ b/lib/std/multi_array_list.zig @@ -23,6 +23,12 @@ pub fn MultiArrayList(comptime T: type) type { len: usize = 0, capacity: usize = 0, + pub const empty: Self = .{ + .bytes = undefined, + .len = 0, + .capacity = 0, + }; + const Elem = switch (@typeInfo(T)) { .@"struct" => T, .@"union" => |u| struct { @@ -474,7 +480,7 @@ pub fn MultiArrayList(comptime T: type) type { pub fn swap(sc: @This(), a_index: usize, b_index: usize) void { inline for (fields, 0..) |field_info, i| { if (@sizeOf(field_info.type) != 0) { - const field = @as(Field, @enumFromInt(i)); + const field: Field = @enumFromInt(i); const ptr = sc.slice.items(field); mem.swap(field_info.type, &ptr[a_index], &ptr[b_index]); } -- 2.54.0 From 4669269673e0240301699127abb16b3072c5e592 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 10 Oct 2024 16:58:11 -0700 Subject: [PATCH 2/7] link.Elf: fix phdr_gnu_stack_index not included in sortPhdrs Adds type safety for program header indexes. Reduce the amount of state sortPhdrs has access to, helping make the data dependencies clear. --- src/link/Elf.zig | 250 ++++++++++++++++++++++++++--------------------- 1 file changed, 140 insertions(+), 110 deletions(-) diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 5f6a0738429720ef27dcaee646f3a17e05e9541c..3a3edfff86592aef004992a13594fb53b1a844af 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -53,26 +53,10 @@ shdr_table_offset: ?u64 = null, /// Stored in native-endian format, depending on target endianness needs to be bswapped on read/write. /// Same order as in the file. -phdrs: std.ArrayListUnmanaged(elf.Elf64_Phdr) = .empty, +phdrs: ProgramHeaderList = .empty, -/// Special program headers -/// PT_PHDR -phdr_table_index: ?u16 = null, -/// PT_LOAD for PHDR table -/// We add this special load segment to ensure the EHDR and PHDR table are always -/// loaded into memory. -phdr_table_load_index: ?u16 = null, -/// PT_INTERP -phdr_interp_index: ?u16 = null, -/// PT_DYNAMIC -phdr_dynamic_index: ?u16 = null, -/// PT_GNU_EH_FRAME -phdr_gnu_eh_frame_index: ?u16 = null, -/// PT_GNU_STACK -phdr_gnu_stack_index: ?u16 = null, -/// PT_TLS -/// TODO I think ELF permits multiple TLS segments but for now, assume one per file. -phdr_tls_index: ?u16 = null, +/// Special program headers. +phdr_indexes: ProgramHeaderIndexes = .{}, page_size: u32, default_sym_version: elf.Elf64_Versym, @@ -152,6 +136,57 @@ comment_merge_section_index: ?MergeSection.Index = null, first_eflags: ?elf.Elf64_Word = null, +const ProgramHeaderList = std.ArrayListUnmanaged(elf.Elf64_Phdr); + +const OptionalProgramHeaderIndex = enum(u16) { + none = std.math.maxInt(u16), + _, + + fn unwrap(i: OptionalProgramHeaderIndex) ?ProgramHeaderIndex { + if (i == .none) return null; + return @enumFromInt(@intFromEnum(i)); + } + + fn int(i: OptionalProgramHeaderIndex) ?u16 { + if (i == .none) return null; + return @intFromEnum(i); + } +}; + +const ProgramHeaderIndex = enum(u16) { + _, + + fn toOptional(i: ProgramHeaderIndex) OptionalProgramHeaderIndex { + const result: OptionalProgramHeaderIndex = @enumFromInt(@intFromEnum(i)); + assert(result != .none); + return result; + } + + fn int(i: ProgramHeaderIndex) u16 { + return @intFromEnum(i); + } +}; + +const ProgramHeaderIndexes = struct { + /// PT_PHDR + table: OptionalProgramHeaderIndex = .none, + /// PT_LOAD for PHDR table + /// We add this special load segment to ensure the EHDR and PHDR table are always + /// loaded into memory. + table_load: OptionalProgramHeaderIndex = .none, + /// PT_INTERP + interp: OptionalProgramHeaderIndex = .none, + /// PT_DYNAMIC + dynamic: OptionalProgramHeaderIndex = .none, + /// PT_GNU_EH_FRAME + gnu_eh_frame: OptionalProgramHeaderIndex = .none, + /// PT_GNU_STACK + gnu_stack: OptionalProgramHeaderIndex = .none, + /// PT_TLS + /// TODO I think ELF permits multiple TLS segments but for now, assume one per file. + tls: OptionalProgramHeaderIndex = .none, +}; + /// When allocating, the ideal_capacity is calculated by /// actual_capacity + (actual_capacity / ideal_factor) const ideal_factor = 3; @@ -358,7 +393,7 @@ pub fn createEmpty( }; const max_nphdrs = comptime getMaxNumberOfPhdrs(); const reserved: u64 = mem.alignForward(u64, padToIdeal(max_nphdrs * phsize), self.page_size); - self.phdr_table_index = try self.addPhdr(.{ + self.phdr_indexes.table = (try self.addPhdr(.{ .type = elf.PT_PHDR, .flags = elf.PF_R, .@"align" = p_align, @@ -366,8 +401,8 @@ pub fn createEmpty( .offset = ehsize, .filesz = reserved, .memsz = reserved, - }); - self.phdr_table_load_index = try self.addPhdr(.{ + })).toOptional(); + self.phdr_indexes.table_load = (try self.addPhdr(.{ .type = elf.PT_LOAD, .flags = elf.PF_R, .@"align" = self.page_size, @@ -375,7 +410,7 @@ pub fn createEmpty( .offset = 0, .filesz = reserved + ehsize, .memsz = reserved + ehsize, - }); + })).toOptional(); } if (opt_zcu) |zcu| { @@ -966,7 +1001,7 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod try self.addLoadPhdrs(); try self.allocatePhdrTable(); try self.allocateAllocSections(); - try self.sortPhdrs(); + try sortPhdrs(gpa, &self.phdrs, &self.phdr_indexes, self.sections.items(.phndx)); try self.allocateNonAllocSections(); self.allocateSpecialPhdrs(); if (self.linkerDefinedPtr()) |obj| { @@ -2461,7 +2496,7 @@ fn writePhdrTable(self: *Elf) !void { const gpa = self.base.comp.gpa; const target_endian = self.getTarget().cpu.arch.endian(); const foreign_endian = target_endian != builtin.cpu.arch.endian(); - const phdr_table = &self.phdrs.items[self.phdr_table_index.?]; + const phdr_table = &self.phdrs.items[self.phdr_indexes.table.int().?]; log.debug("writing program headers from 0x{x} to 0x{x}", .{ phdr_table.p_offset, @@ -2573,18 +2608,18 @@ pub fn writeElfHeader(self: *Elf) !void { const entry_sym = obj.entrySymbol(self) orelse break :blk 0; break :blk @intCast(entry_sym.address(.{}, self)); } else 0; - const phdr_table_offset = if (self.phdr_table_index) |phndx| self.phdrs.items[phndx].p_offset else 0; + const phdr_table_offset = if (self.phdr_indexes.table.int()) |phndx| self.phdrs.items[phndx].p_offset else 0; switch (self.ptr_width) { .p32 => { - mem.writeInt(u32, hdr_buf[index..][0..4], @as(u32, @intCast(e_entry)), endian); + mem.writeInt(u32, hdr_buf[index..][0..4], @intCast(e_entry), endian); index += 4; // e_phoff - mem.writeInt(u32, hdr_buf[index..][0..4], @as(u32, @intCast(phdr_table_offset)), endian); + mem.writeInt(u32, hdr_buf[index..][0..4], @intCast(phdr_table_offset), endian); index += 4; // e_shoff - mem.writeInt(u32, hdr_buf[index..][0..4], @as(u32, @intCast(self.shdr_table_offset.?)), endian); + mem.writeInt(u32, hdr_buf[index..][0..4], @intCast(self.shdr_table_offset.?), endian); index += 4; }, .p64 => { @@ -2631,7 +2666,7 @@ pub fn writeElfHeader(self: *Elf) !void { mem.writeInt(u16, hdr_buf[index..][0..2], e_shentsize, endian); index += 2; - const e_shnum = @as(u16, @intCast(self.sections.items(.shdr).len)); + const e_shnum: u16 = @intCast(self.sections.items(.shdr).len); mem.writeInt(u16, hdr_buf[index..][0..2], e_shnum, endian); index += 2; @@ -3081,43 +3116,43 @@ pub fn initShStrtab(self: *Elf) !void { fn initSpecialPhdrs(self: *Elf) !void { comptime assert(max_number_of_special_phdrs == 5); - if (self.interp_section_index != null and self.phdr_interp_index == null) { - self.phdr_interp_index = try self.addPhdr(.{ + if (self.interp_section_index != null and self.phdr_indexes.interp == .none) { + self.phdr_indexes.interp = (try self.addPhdr(.{ .type = elf.PT_INTERP, .flags = elf.PF_R, .@"align" = 1, - }); + })).toOptional(); } - if (self.dynamic_section_index != null and self.phdr_dynamic_index == null) { - self.phdr_dynamic_index = try self.addPhdr(.{ + if (self.dynamic_section_index != null and self.phdr_indexes.dynamic == .none) { + self.phdr_indexes.dynamic = (try self.addPhdr(.{ .type = elf.PT_DYNAMIC, .flags = elf.PF_R | elf.PF_W, - }); + })).toOptional(); } - if (self.eh_frame_hdr_section_index != null and self.phdr_gnu_eh_frame_index == null) { - self.phdr_gnu_eh_frame_index = try self.addPhdr(.{ + if (self.eh_frame_hdr_section_index != null and self.phdr_indexes.gnu_eh_frame == .none) { + self.phdr_indexes.gnu_eh_frame = (try self.addPhdr(.{ .type = elf.PT_GNU_EH_FRAME, .flags = elf.PF_R, - }); + })).toOptional(); } - if (self.phdr_gnu_stack_index == null) { - self.phdr_gnu_stack_index = try self.addPhdr(.{ + if (self.phdr_indexes.gnu_stack == .none) { + self.phdr_indexes.gnu_stack = (try self.addPhdr(.{ .type = elf.PT_GNU_STACK, .flags = elf.PF_W | elf.PF_R, .memsz = self.base.stack_size, .@"align" = 1, - }); + })).toOptional(); } const has_tls = for (self.sections.items(.shdr)) |shdr| { if (shdr.sh_flags & elf.SHF_TLS != 0) break true; } else false; - if (has_tls and self.phdr_tls_index == null) { - self.phdr_tls_index = try self.addPhdr(.{ + if (has_tls and self.phdr_indexes.tls == .none) { + self.phdr_indexes.tls = (try self.addPhdr(.{ .type = elf.PT_TLS, .flags = elf.PF_R, .@"align" = 1, - }); + })).toOptional(); } } @@ -3251,25 +3286,30 @@ fn setHashSections(self: *Elf) !void { } fn phdrRank(phdr: elf.Elf64_Phdr) u8 { - switch (phdr.p_type) { - elf.PT_NULL => return 0, - elf.PT_PHDR => return 1, - elf.PT_INTERP => return 2, - elf.PT_LOAD => return 3, - elf.PT_DYNAMIC, elf.PT_TLS => return 4, - elf.PT_GNU_EH_FRAME => return 5, - elf.PT_GNU_STACK => return 6, - else => return 7, - } + return switch (phdr.p_type) { + elf.PT_NULL => 0, + elf.PT_PHDR => 1, + elf.PT_INTERP => 2, + elf.PT_LOAD => 3, + elf.PT_DYNAMIC, elf.PT_TLS => 4, + elf.PT_GNU_EH_FRAME => 5, + elf.PT_GNU_STACK => 6, + else => 7, + }; } -fn sortPhdrs(self: *Elf) error{OutOfMemory}!void { +fn sortPhdrs( + gpa: Allocator, + phdrs: *ProgramHeaderList, + special_indexes: *ProgramHeaderIndexes, + section_indexes: []OptionalProgramHeaderIndex, +) error{OutOfMemory}!void { const Entry = struct { phndx: u16, - pub fn lessThan(elf_file: *Elf, lhs: @This(), rhs: @This()) bool { - const lhs_phdr = elf_file.phdrs.items[lhs.phndx]; - const rhs_phdr = elf_file.phdrs.items[rhs.phndx]; + pub fn lessThan(program_headers: []const elf.Elf64_Phdr, lhs: @This(), rhs: @This()) bool { + const lhs_phdr = program_headers[lhs.phndx]; + const rhs_phdr = program_headers[rhs.phndx]; const lhs_rank = phdrRank(lhs_phdr); const rhs_rank = phdrRank(rhs_phdr); if (lhs_rank == rhs_rank) return lhs_phdr.p_vaddr < rhs_phdr.p_vaddr; @@ -3277,45 +3317,34 @@ fn sortPhdrs(self: *Elf) error{OutOfMemory}!void { } }; - const gpa = self.base.comp.gpa; - var entries = try std.ArrayList(Entry).initCapacity(gpa, self.phdrs.items.len); - defer entries.deinit(); - for (0..self.phdrs.items.len) |phndx| { - entries.appendAssumeCapacity(.{ .phndx = @as(u16, @intCast(phndx)) }); + const entries = try gpa.alloc(Entry, phdrs.items.len); + defer gpa.free(entries); + for (entries, 0..) |*entry, phndx| { + entry.* = .{ .phndx = @intCast(phndx) }; } - mem.sort(Entry, entries.items, self, Entry.lessThan); + mem.sort(Entry, entries, phdrs.items, Entry.lessThan); - const backlinks = try gpa.alloc(u16, entries.items.len); + const backlinks = try gpa.alloc(u16, entries.len); defer gpa.free(backlinks); - for (entries.items, 0..) |entry, i| { - backlinks[entry.phndx] = @as(u16, @intCast(i)); - } - - const slice = try self.phdrs.toOwnedSlice(gpa); + const slice = try phdrs.toOwnedSlice(gpa); defer gpa.free(slice); + try phdrs.resize(gpa, slice.len); - try self.phdrs.ensureTotalCapacityPrecise(gpa, slice.len); - for (entries.items) |sorted| { - self.phdrs.appendAssumeCapacity(slice[sorted.phndx]); + for (entries, phdrs.items, 0..) |entry, *phdr, i| { + backlinks[entry.phndx] = @intCast(i); + phdr.* = slice[entry.phndx]; } - for (&[_]*?u16{ - &self.phdr_table_index, - &self.phdr_table_load_index, - &self.phdr_interp_index, - &self.phdr_dynamic_index, - &self.phdr_gnu_eh_frame_index, - &self.phdr_tls_index, - }) |maybe_index| { - if (maybe_index.*) |*index| { - index.* = backlinks[index.*]; + inline for (@typeInfo(ProgramHeaderIndexes).@"struct".fields) |field| { + if (@field(special_indexes, field.name).int()) |special_index| { + @field(special_indexes, field.name) = @enumFromInt(backlinks[special_index]); } } - for (self.sections.items(.phndx)) |*maybe_phndx| { - if (maybe_phndx.*) |*index| { - index.* = backlinks[index.*]; + for (section_indexes) |*opt_phndx| { + if (opt_phndx.int()) |index| { + opt_phndx.* = @enumFromInt(backlinks[index]); } } } @@ -3656,7 +3685,7 @@ fn addLoadPhdrs(self: *Elf) error{OutOfMemory}!void { if (shdr.sh_type == elf.SHT_NULL) continue; if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue; const flags = shdrToPhdrFlags(shdr.sh_flags); - if (self.getPhdr(.{ .flags = flags, .type = elf.PT_LOAD }) == null) { + if (self.getPhdr(.{ .flags = flags, .type = elf.PT_LOAD }) == .none) { _ = try self.addPhdr(.{ .flags = flags, .type = elf.PT_LOAD }); } } @@ -3664,8 +3693,8 @@ fn addLoadPhdrs(self: *Elf) error{OutOfMemory}!void { /// Allocates PHDR table in virtual memory and in file. fn allocatePhdrTable(self: *Elf) error{OutOfMemory}!void { - const phdr_table = &self.phdrs.items[self.phdr_table_index.?]; - const phdr_table_load = &self.phdrs.items[self.phdr_table_load_index.?]; + const phdr_table = &self.phdrs.items[self.phdr_indexes.table.int().?]; + const phdr_table_load = &self.phdrs.items[self.phdr_indexes.table_load.int().?]; const ehsize: u64 = switch (self.ptr_width) { .p32 => @sizeOf(elf.Elf32_Ehdr), @@ -3757,7 +3786,7 @@ pub fn allocateAllocSections(self: *Elf) !void { // When allocating we first find the largest required alignment // of any section that is contained in a cover and use it to align // the start address of the segement (and first section). - const phdr_table = &self.phdrs.items[self.phdr_table_load_index.?]; + const phdr_table = &self.phdrs.items[self.phdr_indexes.table_load.int().?]; var addr = phdr_table.p_vaddr + phdr_table.p_memsz; for (covers) |cover| { @@ -3817,8 +3846,8 @@ pub fn allocateAllocSections(self: *Elf) !void { } const first = slice.items(.shdr)[cover.items[0]]; - const phndx = self.getPhdr(.{ .type = elf.PT_LOAD, .flags = shdrToPhdrFlags(first.sh_flags) }).?; - const phdr = &self.phdrs.items[phndx]; + const phndx = self.getPhdr(.{ .type = elf.PT_LOAD, .flags = shdrToPhdrFlags(first.sh_flags) }).unwrap().?; + const phdr = &self.phdrs.items[phndx.int()]; const allocated_size = self.allocatedSize(phdr.p_offset); if (filesz > allocated_size) { const old_offset = phdr.p_offset; @@ -3830,7 +3859,7 @@ pub fn allocateAllocSections(self: *Elf) !void { for (cover.items) |shndx| { const shdr = &slice.items(.shdr)[shndx]; - slice.items(.phndx)[shndx] = phndx; + slice.items(.phndx)[shndx] = phndx.toOptional(); if (shdr.sh_type == elf.SHT_NOBITS) { shdr.sh_offset = 0; continue; @@ -3906,12 +3935,12 @@ pub fn allocateNonAllocSections(self: *Elf) !void { fn allocateSpecialPhdrs(self: *Elf) void { const slice = self.sections.slice(); - for (&[_]struct { ?u16, ?u32 }{ - .{ self.phdr_interp_index, self.interp_section_index }, - .{ self.phdr_dynamic_index, self.dynamic_section_index }, - .{ self.phdr_gnu_eh_frame_index, self.eh_frame_hdr_section_index }, + for (&[_]struct { OptionalProgramHeaderIndex, ?u32 }{ + .{ self.phdr_indexes.interp, self.interp_section_index }, + .{ self.phdr_indexes.dynamic, self.dynamic_section_index }, + .{ self.phdr_indexes.gnu_eh_frame, self.eh_frame_hdr_section_index }, }) |pair| { - if (pair[0]) |index| { + if (pair[0].int()) |index| { const shdr = slice.items(.shdr)[pair[1].?]; const phdr = &self.phdrs.items[index]; phdr.p_align = shdr.sh_addralign; @@ -3926,7 +3955,7 @@ fn allocateSpecialPhdrs(self: *Elf) void { // Set the TLS segment boundaries. // We assume TLS sections are laid out contiguously and that there is // a single TLS segment. - if (self.phdr_tls_index) |index| { + if (self.phdr_indexes.tls.int()) |index| { const shdrs = slice.items(.shdr); const phdr = &self.phdrs.items[index]; var shndx: u32 = 0; @@ -4482,14 +4511,15 @@ pub fn isEffectivelyDynLib(self: Elf) bool { fn getPhdr(self: *Elf, opts: struct { type: u32 = 0, flags: u32 = 0, -}) ?u16 { +}) OptionalProgramHeaderIndex { for (self.phdrs.items, 0..) |phdr, phndx| { - if (self.phdr_table_load_index) |index| { + if (self.phdr_indexes.table_load.int()) |index| { if (phndx == index) continue; } - if (phdr.p_type == opts.type and phdr.p_flags == opts.flags) return @intCast(phndx); + if (phdr.p_type == opts.type and phdr.p_flags == opts.flags) + return @enumFromInt(phndx); } - return null; + return .none; } fn addPhdr(self: *Elf, opts: struct { @@ -4500,9 +4530,9 @@ fn addPhdr(self: *Elf, opts: struct { addr: u64 = 0, filesz: u64 = 0, memsz: u64 = 0, -}) error{OutOfMemory}!u16 { +}) error{OutOfMemory}!ProgramHeaderIndex { const gpa = self.base.comp.gpa; - const index = @as(u16, @intCast(self.phdrs.items.len)); + const index: ProgramHeaderIndex = @enumFromInt(self.phdrs.items.len); try self.phdrs.append(gpa, .{ .p_type = opts.type, .p_flags = opts.flags, @@ -4756,7 +4786,7 @@ pub fn gotAddress(self: *Elf) i64 { } pub fn tpAddress(self: *Elf) i64 { - const index = self.phdr_tls_index orelse return 0; + const index = self.phdr_indexes.tls.int() orelse return 0; const phdr = self.phdrs.items[index]; const addr = switch (self.getTarget().cpu.arch) { .x86_64 => mem.alignForward(u64, phdr.p_vaddr + phdr.p_memsz, phdr.p_align), @@ -4768,13 +4798,13 @@ pub fn tpAddress(self: *Elf) i64 { } pub fn dtpAddress(self: *Elf) i64 { - const index = self.phdr_tls_index orelse return 0; + const index = self.phdr_indexes.tls.int() orelse return 0; const phdr = self.phdrs.items[index]; return @intCast(phdr.p_vaddr); } pub fn tlsAddress(self: *Elf) i64 { - const index = self.phdr_tls_index orelse return 0; + const index = self.phdr_indexes.tls.int() orelse return 0; const phdr = self.phdrs.items[index]; return @intCast(phdr.p_vaddr); } @@ -5393,7 +5423,7 @@ const Section = struct { shdr: elf.Elf64_Shdr, /// Assigned program header index if any. - phndx: ?u32 = null, + phndx: OptionalProgramHeaderIndex = .none, /// List of atoms contributing to this section. /// TODO currently this is only used for relocations tracking in relocatable mode -- 2.54.0 From c3148988a3e1ccbe351b8d51359490eb8258c18f Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 10 Oct 2024 17:08:41 -0700 Subject: [PATCH 3/7] link.Elf.ZigObject: make resetShdrIndexes non generic --- src/link/Elf/ZigObject.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/link/Elf/ZigObject.zig b/src/link/Elf/ZigObject.zig index 54d15297d526fb4c9a7141d55771cfceb75c6239..e8b804e024509d53eb7a1668fb6c7c43aaa624ee 100644 --- a/src/link/Elf/ZigObject.zig +++ b/src/link/Elf/ZigObject.zig @@ -2027,7 +2027,7 @@ pub fn allocateAtom(self: *ZigObject, atom_ptr: *Atom, requires_padding: bool, e log.debug(" prev {?}, next {?}", .{ atom_ptr.prev_atom_ref, atom_ptr.next_atom_ref }); } -pub fn resetShdrIndexes(self: *ZigObject, backlinks: anytype) void { +pub fn resetShdrIndexes(self: *ZigObject, backlinks: []const u32) void { for (self.atoms_indexes.items) |atom_index| { const atom_ptr = self.atom(atom_index) orelse continue; atom_ptr.output_section_index = backlinks[atom_ptr.output_section_index]; -- 2.54.0 From 2c4e05eda7c3b6e27e83f85ca0a7c501c15775e7 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 10 Oct 2024 17:35:04 -0700 Subject: [PATCH 4/7] link.Elf: group section indexes so they cannot be forgotten when updating them after sorting them. --- src/link/Elf.zig | 348 +++++++++++++--------------- src/link/Elf/LinkerDefined.zig | 12 +- src/link/Elf/Object.zig | 6 +- src/link/Elf/Symbol.zig | 12 +- src/link/Elf/ZigObject.zig | 6 +- src/link/Elf/eh_frame.zig | 12 +- src/link/Elf/relocatable.zig | 22 +- src/link/Elf/synthetic_sections.zig | 54 ++--- 8 files changed, 225 insertions(+), 247 deletions(-) diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 3a3edfff86592aef004992a13594fb53b1a844af..a69f5fe18c3425cee25b285d581e0f55d19f7fcf 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -57,6 +57,7 @@ phdrs: ProgramHeaderList = .empty, /// Special program headers. phdr_indexes: ProgramHeaderIndexes = .{}, +section_indexes: SectionIndexes = .{}, page_size: u32, default_sym_version: elf.Elf64_Versym, @@ -99,29 +100,6 @@ rela_plt: std.ArrayListUnmanaged(elf.Elf64_Rela) = .empty, /// Applies only to a relocatable. comdat_group_sections: std.ArrayListUnmanaged(ComdatGroupSection) = .empty, -copy_rel_section_index: ?u32 = null, -dynamic_section_index: ?u32 = null, -dynstrtab_section_index: ?u32 = null, -dynsymtab_section_index: ?u32 = null, -eh_frame_section_index: ?u32 = null, -eh_frame_rela_section_index: ?u32 = null, -eh_frame_hdr_section_index: ?u32 = null, -hash_section_index: ?u32 = null, -gnu_hash_section_index: ?u32 = null, -got_section_index: ?u32 = null, -got_plt_section_index: ?u32 = null, -interp_section_index: ?u32 = null, -plt_section_index: ?u32 = null, -plt_got_section_index: ?u32 = null, -rela_dyn_section_index: ?u32 = null, -rela_plt_section_index: ?u32 = null, -versym_section_index: ?u32 = null, -verneed_section_index: ?u32 = null, - -shstrtab_section_index: ?u32 = null, -strtab_section_index: ?u32 = null, -symtab_section_index: ?u32 = null, - resolver: SymbolResolver = .{}, has_text_reloc: bool = false, @@ -136,6 +114,31 @@ comment_merge_section_index: ?MergeSection.Index = null, first_eflags: ?elf.Elf64_Word = null, +const SectionIndexes = struct { + copy_rel: ?u32 = null, + dynamic: ?u32 = null, + dynstrtab: ?u32 = null, + dynsymtab: ?u32 = null, + eh_frame: ?u32 = null, + eh_frame_rela: ?u32 = null, + eh_frame_hdr: ?u32 = null, + hash: ?u32 = null, + gnu_hash: ?u32 = null, + got: ?u32 = null, + got_plt: ?u32 = null, + interp: ?u32 = null, + plt: ?u32 = null, + plt_got: ?u32 = null, + rela_dyn: ?u32 = null, + rela_plt: ?u32 = null, + versym: ?u32 = null, + verneed: ?u32 = null, + + shstrtab: ?u32 = null, + strtab: ?u32 = null, + symtab: ?u32 = null, +}; + const ProgramHeaderList = std.ArrayListUnmanaged(elf.Elf64_Phdr); const OptionalProgramHeaderIndex = enum(u16) { @@ -2670,7 +2673,7 @@ pub fn writeElfHeader(self: *Elf) !void { mem.writeInt(u16, hdr_buf[index..][0..2], e_shnum, endian); index += 2; - mem.writeInt(u16, hdr_buf[index..][0..2], @intCast(self.shstrtab_section_index.?), endian); + mem.writeInt(u16, hdr_buf[index..][0..2], @intCast(self.section_indexes.shstrtab.?), endian); index += 2; assert(index == e_ehsize); @@ -2888,8 +2891,8 @@ fn initSyntheticSections(self: *Elf) !void { } else false; }; if (needs_eh_frame) { - if (self.eh_frame_section_index == null) { - self.eh_frame_section_index = self.sectionByName(".eh_frame") orelse try self.addSection(.{ + if (self.section_indexes.eh_frame == null) { + self.section_indexes.eh_frame = self.sectionByName(".eh_frame") orelse try self.addSection(.{ .name = try self.insertShString(".eh_frame"), .type = if (target.cpu.arch == .x86_64) elf.SHT_X86_64_UNWIND @@ -2899,8 +2902,8 @@ fn initSyntheticSections(self: *Elf) !void { .addralign = ptr_size, }); } - if (comp.link_eh_frame_hdr and self.eh_frame_hdr_section_index == null) { - self.eh_frame_hdr_section_index = try self.addSection(.{ + if (comp.link_eh_frame_hdr and self.section_indexes.eh_frame_hdr == null) { + self.section_indexes.eh_frame_hdr = try self.addSection(.{ .name = try self.insertShString(".eh_frame_hdr"), .type = elf.SHT_PROGBITS, .flags = elf.SHF_ALLOC, @@ -2909,8 +2912,8 @@ fn initSyntheticSections(self: *Elf) !void { } } - if (self.got.entries.items.len > 0 and self.got_section_index == null) { - self.got_section_index = try self.addSection(.{ + if (self.got.entries.items.len > 0 and self.section_indexes.got == null) { + self.section_indexes.got = try self.addSection(.{ .name = try self.insertShString(".got"), .type = elf.SHT_PROGBITS, .flags = elf.SHF_ALLOC | elf.SHF_WRITE, @@ -2918,8 +2921,8 @@ fn initSyntheticSections(self: *Elf) !void { }); } - if (self.got_plt_section_index == null) { - self.got_plt_section_index = try self.addSection(.{ + if (self.section_indexes.got_plt == null) { + self.section_indexes.got_plt = try self.addSection(.{ .name = try self.insertShString(".got.plt"), .type = elf.SHT_PROGBITS, .flags = elf.SHF_ALLOC | elf.SHF_WRITE, @@ -2938,8 +2941,8 @@ fn initSyntheticSections(self: *Elf) !void { } break :blk false; }; - if (needs_rela_dyn and self.rela_dyn_section_index == null) { - self.rela_dyn_section_index = try self.addSection(.{ + if (needs_rela_dyn and self.section_indexes.rela_dyn == null) { + self.section_indexes.rela_dyn = try self.addSection(.{ .name = try self.insertShString(".rela.dyn"), .type = elf.SHT_RELA, .flags = elf.SHF_ALLOC, @@ -2949,16 +2952,16 @@ fn initSyntheticSections(self: *Elf) !void { } if (self.plt.symbols.items.len > 0) { - if (self.plt_section_index == null) { - self.plt_section_index = try self.addSection(.{ + if (self.section_indexes.plt == null) { + self.section_indexes.plt = try self.addSection(.{ .name = try self.insertShString(".plt"), .type = elf.SHT_PROGBITS, .flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR, .addralign = 16, }); } - if (self.rela_plt_section_index == null) { - self.rela_plt_section_index = try self.addSection(.{ + if (self.section_indexes.rela_plt == null) { + self.section_indexes.rela_plt = try self.addSection(.{ .name = try self.insertShString(".rela.plt"), .type = elf.SHT_RELA, .flags = elf.SHF_ALLOC, @@ -2968,8 +2971,8 @@ fn initSyntheticSections(self: *Elf) !void { } } - if (self.plt_got.symbols.items.len > 0 and self.plt_got_section_index == null) { - self.plt_got_section_index = try self.addSection(.{ + if (self.plt_got.symbols.items.len > 0 and self.section_indexes.plt_got == null) { + self.section_indexes.plt_got = try self.addSection(.{ .name = try self.insertShString(".plt.got"), .type = elf.SHT_PROGBITS, .flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR, @@ -2977,8 +2980,8 @@ fn initSyntheticSections(self: *Elf) !void { }); } - if (self.copy_rel.symbols.items.len > 0 and self.copy_rel_section_index == null) { - self.copy_rel_section_index = try self.addSection(.{ + if (self.copy_rel.symbols.items.len > 0 and self.section_indexes.copy_rel == null) { + self.section_indexes.copy_rel = try self.addSection(.{ .name = try self.insertShString(".copyrel"), .type = elf.SHT_NOBITS, .flags = elf.SHF_ALLOC | elf.SHF_WRITE, @@ -2994,8 +2997,8 @@ fn initSyntheticSections(self: *Elf) !void { if (self.base.isStatic() and !comp.config.pie) break :blk false; break :blk target.dynamic_linker.get() != null; }; - if (needs_interp and self.interp_section_index == null) { - self.interp_section_index = try self.addSection(.{ + if (needs_interp and self.section_indexes.interp == null) { + self.section_indexes.interp = try self.addSection(.{ .name = try self.insertShString(".interp"), .type = elf.SHT_PROGBITS, .flags = elf.SHF_ALLOC, @@ -3004,8 +3007,8 @@ fn initSyntheticSections(self: *Elf) !void { } if (self.isEffectivelyDynLib() or self.shared_objects.items.len > 0 or comp.config.pie) { - if (self.dynstrtab_section_index == null) { - self.dynstrtab_section_index = try self.addSection(.{ + if (self.section_indexes.dynstrtab == null) { + self.section_indexes.dynstrtab = try self.addSection(.{ .name = try self.insertShString(".dynstr"), .flags = elf.SHF_ALLOC, .type = elf.SHT_STRTAB, @@ -3013,8 +3016,8 @@ fn initSyntheticSections(self: *Elf) !void { .addralign = 1, }); } - if (self.dynamic_section_index == null) { - self.dynamic_section_index = try self.addSection(.{ + if (self.section_indexes.dynamic == null) { + self.section_indexes.dynamic = try self.addSection(.{ .name = try self.insertShString(".dynamic"), .flags = elf.SHF_ALLOC | elf.SHF_WRITE, .type = elf.SHT_DYNAMIC, @@ -3022,8 +3025,8 @@ fn initSyntheticSections(self: *Elf) !void { .addralign = @alignOf(elf.Elf64_Dyn), }); } - if (self.dynsymtab_section_index == null) { - self.dynsymtab_section_index = try self.addSection(.{ + if (self.section_indexes.dynsymtab == null) { + self.section_indexes.dynsymtab = try self.addSection(.{ .name = try self.insertShString(".dynsym"), .flags = elf.SHF_ALLOC, .type = elf.SHT_DYNSYM, @@ -3032,8 +3035,8 @@ fn initSyntheticSections(self: *Elf) !void { .info = 1, }); } - if (self.hash_section_index == null) { - self.hash_section_index = try self.addSection(.{ + if (self.section_indexes.hash == null) { + self.section_indexes.hash = try self.addSection(.{ .name = try self.insertShString(".hash"), .flags = elf.SHF_ALLOC, .type = elf.SHT_HASH, @@ -3041,8 +3044,8 @@ fn initSyntheticSections(self: *Elf) !void { .entsize = 4, }); } - if (self.gnu_hash_section_index == null) { - self.gnu_hash_section_index = try self.addSection(.{ + if (self.section_indexes.gnu_hash == null) { + self.section_indexes.gnu_hash = try self.addSection(.{ .name = try self.insertShString(".gnu.hash"), .flags = elf.SHF_ALLOC, .type = elf.SHT_GNU_HASH, @@ -3055,8 +3058,8 @@ fn initSyntheticSections(self: *Elf) !void { if (sym.flags.import and sym.version_index & elf.VERSYM_VERSION > elf.VER_NDX_GLOBAL) break true; } else false; if (needs_versions) { - if (self.versym_section_index == null) { - self.versym_section_index = try self.addSection(.{ + if (self.section_indexes.versym == null) { + self.section_indexes.versym = try self.addSection(.{ .name = try self.insertShString(".gnu.version"), .flags = elf.SHF_ALLOC, .type = elf.SHT_GNU_VERSYM, @@ -3064,8 +3067,8 @@ fn initSyntheticSections(self: *Elf) !void { .entsize = @sizeOf(elf.Elf64_Versym), }); } - if (self.verneed_section_index == null) { - self.verneed_section_index = try self.addSection(.{ + if (self.section_indexes.verneed == null) { + self.section_indexes.verneed = try self.addSection(.{ .name = try self.insertShString(".gnu.version_r"), .flags = elf.SHF_ALLOC, .type = elf.SHT_GNU_VERNEED, @@ -3084,16 +3087,16 @@ pub fn initSymtab(self: *Elf) !void { .p32 => true, .p64 => false, }; - if (self.symtab_section_index == null) { - self.symtab_section_index = try self.addSection(.{ + if (self.section_indexes.symtab == null) { + self.section_indexes.symtab = try self.addSection(.{ .name = try self.insertShString(".symtab"), .type = elf.SHT_SYMTAB, .addralign = if (small_ptr) @alignOf(elf.Elf32_Sym) else @alignOf(elf.Elf64_Sym), .entsize = if (small_ptr) @sizeOf(elf.Elf32_Sym) else @sizeOf(elf.Elf64_Sym), }); } - if (self.strtab_section_index == null) { - self.strtab_section_index = try self.addSection(.{ + if (self.section_indexes.strtab == null) { + self.section_indexes.strtab = try self.addSection(.{ .name = try self.insertShString(".strtab"), .type = elf.SHT_STRTAB, .entsize = 1, @@ -3103,8 +3106,8 @@ pub fn initSymtab(self: *Elf) !void { } pub fn initShStrtab(self: *Elf) !void { - if (self.shstrtab_section_index == null) { - self.shstrtab_section_index = try self.addSection(.{ + if (self.section_indexes.shstrtab == null) { + self.section_indexes.shstrtab = try self.addSection(.{ .name = try self.insertShString(".shstrtab"), .type = elf.SHT_STRTAB, .entsize = 1, @@ -3116,20 +3119,20 @@ pub fn initShStrtab(self: *Elf) !void { fn initSpecialPhdrs(self: *Elf) !void { comptime assert(max_number_of_special_phdrs == 5); - if (self.interp_section_index != null and self.phdr_indexes.interp == .none) { + if (self.section_indexes.interp != null and self.phdr_indexes.interp == .none) { self.phdr_indexes.interp = (try self.addPhdr(.{ .type = elf.PT_INTERP, .flags = elf.PF_R, .@"align" = 1, })).toOptional(); } - if (self.dynamic_section_index != null and self.phdr_indexes.dynamic == .none) { + if (self.section_indexes.dynamic != null and self.phdr_indexes.dynamic == .none) { self.phdr_indexes.dynamic = (try self.addPhdr(.{ .type = elf.PT_DYNAMIC, .flags = elf.PF_R | elf.PF_W, })).toOptional(); } - if (self.eh_frame_hdr_section_index != null and self.phdr_indexes.gnu_eh_frame == .none) { + if (self.section_indexes.eh_frame_hdr != null and self.phdr_indexes.gnu_eh_frame == .none) { self.phdr_indexes.gnu_eh_frame = (try self.addPhdr(.{ .type = elf.PT_GNU_EH_FRAME, .flags = elf.PF_R, @@ -3237,7 +3240,7 @@ fn sortInitFini(self: *Elf) !void { } fn setDynamicSection(self: *Elf, rpaths: []const []const u8) !void { - if (self.dynamic_section_index == null) return; + if (self.section_indexes.dynamic == null) return; for (self.shared_objects.items) |index| { const shared_object = self.file(index).?.shared_object; @@ -3255,13 +3258,13 @@ fn setDynamicSection(self: *Elf, rpaths: []const []const u8) !void { } fn sortDynamicSymtab(self: *Elf) void { - if (self.gnu_hash_section_index == null) return; + if (self.section_indexes.gnu_hash == null) return; self.dynsym.sort(self); } fn setVersionSymtab(self: *Elf) !void { const gpa = self.base.comp.gpa; - if (self.versym_section_index == null) return; + if (self.section_indexes.versym == null) return; try self.versym.resize(gpa, self.dynsym.count()); self.versym.items[0] = elf.VER_NDX_LOCAL; for (self.dynsym.entries.items, 1..) |entry, i| { @@ -3269,7 +3272,7 @@ fn setVersionSymtab(self: *Elf) !void { self.versym.items[i] = sym.version_index; } - if (self.verneed_section_index) |shndx| { + if (self.section_indexes.verneed) |shndx| { try self.verneed.generate(self); const shdr = &self.sections.items(.shdr)[shndx]; shdr.sh_info = @as(u32, @intCast(self.verneed.verneed.items.len)); @@ -3277,10 +3280,10 @@ fn setVersionSymtab(self: *Elf) !void { } fn setHashSections(self: *Elf) !void { - if (self.hash_section_index != null) { + if (self.section_indexes.hash != null) { try self.hash.generate(self); } - if (self.gnu_hash_section_index != null) { + if (self.section_indexes.gnu_hash != null) { try self.gnu_hash.calcSize(self); } } @@ -3420,47 +3423,22 @@ pub fn sortShdrs(self: *Elf) !void { const backlinks = try gpa.alloc(u32, entries.items.len); defer gpa.free(backlinks); - for (entries.items, 0..) |entry, i| { - backlinks[entry.shndx] = @intCast(i); - } - - var slice = self.sections.toOwnedSlice(); - defer slice.deinit(gpa); + { + var slice = self.sections.toOwnedSlice(); + defer slice.deinit(gpa); + try self.sections.resize(gpa, slice.len); - try self.sections.ensureTotalCapacity(gpa, slice.len); - for (entries.items) |sorted| { - self.sections.appendAssumeCapacity(slice.get(sorted.shndx)); + for (entries.items, 0..) |entry, i| { + backlinks[entry.shndx] = @intCast(i); + self.sections.set(i, slice.get(entry.shndx)); + } } - self.resetShdrIndexes(backlinks); -} + const special_indexes = &self.section_indexes; -fn resetShdrIndexes(self: *Elf, backlinks: []const u32) void { - for (&[_]*?u32{ - &self.eh_frame_section_index, - &self.eh_frame_rela_section_index, - &self.eh_frame_hdr_section_index, - &self.got_section_index, - &self.symtab_section_index, - &self.strtab_section_index, - &self.shstrtab_section_index, - &self.interp_section_index, - &self.dynamic_section_index, - &self.dynsymtab_section_index, - &self.dynstrtab_section_index, - &self.hash_section_index, - &self.gnu_hash_section_index, - &self.plt_section_index, - &self.got_plt_section_index, - &self.plt_got_section_index, - &self.rela_dyn_section_index, - &self.rela_plt_section_index, - &self.copy_rel_section_index, - &self.versym_section_index, - &self.verneed_section_index, - }) |maybe_index| { - if (maybe_index.*) |*index| { - index.* = backlinks[index.*]; + inline for (@typeInfo(SectionIndexes).@"struct".fields) |field| { + if (@field(special_indexes, field.name)) |special_index| { + @field(special_indexes, field.name) = backlinks[special_index]; } } @@ -3478,7 +3456,7 @@ fn resetShdrIndexes(self: *Elf, backlinks: []const u32) void { // FIXME:JK we should spin up .symtab potentially earlier, or set all non-dynamic RELA sections // to point at symtab // shdr.sh_link = backlinks[shdr.sh_link]; - shdr.sh_link = self.symtab_section_index.?; + shdr.sh_link = self.section_indexes.symtab.?; shdr.sh_info = backlinks[shdr.sh_info]; } } @@ -3489,56 +3467,56 @@ fn resetShdrIndexes(self: *Elf, backlinks: []const u32) void { cg.shndx = backlinks[cg.shndx]; } - if (self.symtab_section_index) |index| { + if (self.section_indexes.symtab) |index| { const shdr = &slice.items(.shdr)[index]; - shdr.sh_link = self.strtab_section_index.?; + shdr.sh_link = self.section_indexes.strtab.?; } - if (self.dynamic_section_index) |index| { + if (self.section_indexes.dynamic) |index| { const shdr = &slice.items(.shdr)[index]; - shdr.sh_link = self.dynstrtab_section_index.?; + shdr.sh_link = self.section_indexes.dynstrtab.?; } - if (self.dynsymtab_section_index) |index| { + if (self.section_indexes.dynsymtab) |index| { const shdr = &slice.items(.shdr)[index]; - shdr.sh_link = self.dynstrtab_section_index.?; + shdr.sh_link = self.section_indexes.dynstrtab.?; } - if (self.hash_section_index) |index| { + if (self.section_indexes.hash) |index| { const shdr = &slice.items(.shdr)[index]; - shdr.sh_link = self.dynsymtab_section_index.?; + shdr.sh_link = self.section_indexes.dynsymtab.?; } - if (self.gnu_hash_section_index) |index| { + if (self.section_indexes.gnu_hash) |index| { const shdr = &slice.items(.shdr)[index]; - shdr.sh_link = self.dynsymtab_section_index.?; + shdr.sh_link = self.section_indexes.dynsymtab.?; } - if (self.versym_section_index) |index| { + if (self.section_indexes.versym) |index| { const shdr = &slice.items(.shdr)[index]; - shdr.sh_link = self.dynsymtab_section_index.?; + shdr.sh_link = self.section_indexes.dynsymtab.?; } - if (self.verneed_section_index) |index| { + if (self.section_indexes.verneed) |index| { const shdr = &slice.items(.shdr)[index]; - shdr.sh_link = self.dynstrtab_section_index.?; + shdr.sh_link = self.section_indexes.dynstrtab.?; } - if (self.rela_dyn_section_index) |index| { + if (self.section_indexes.rela_dyn) |index| { const shdr = &slice.items(.shdr)[index]; - shdr.sh_link = self.dynsymtab_section_index orelse 0; + shdr.sh_link = self.section_indexes.dynsymtab orelse 0; } - if (self.rela_plt_section_index) |index| { + if (self.section_indexes.rela_plt) |index| { const shdr = &slice.items(.shdr)[index]; - shdr.sh_link = self.dynsymtab_section_index.?; - shdr.sh_info = self.plt_section_index.?; + shdr.sh_link = self.section_indexes.dynsymtab.?; + shdr.sh_info = self.section_indexes.plt.?; } - if (self.eh_frame_rela_section_index) |index| { + if (self.section_indexes.eh_frame_rela) |index| { const shdr = &slice.items(.shdr)[index]; - shdr.sh_link = self.symtab_section_index.?; - shdr.sh_info = self.eh_frame_section_index.?; + shdr.sh_link = self.section_indexes.symtab.?; + shdr.sh_info = self.section_indexes.eh_frame.?; } } @@ -3572,31 +3550,31 @@ fn updateSectionSizes(self: *Elf) !void { } const shdrs = slice.items(.shdr); - if (self.eh_frame_section_index) |index| { + if (self.section_indexes.eh_frame) |index| { shdrs[index].sh_size = try eh_frame.calcEhFrameSize(self); } - if (self.eh_frame_hdr_section_index) |index| { + if (self.section_indexes.eh_frame_hdr) |index| { shdrs[index].sh_size = eh_frame.calcEhFrameHdrSize(self); } - if (self.got_section_index) |index| { + if (self.section_indexes.got) |index| { shdrs[index].sh_size = self.got.size(self); } - if (self.plt_section_index) |index| { + if (self.section_indexes.plt) |index| { shdrs[index].sh_size = self.plt.size(self); } - if (self.got_plt_section_index) |index| { + if (self.section_indexes.got_plt) |index| { shdrs[index].sh_size = self.got_plt.size(self); } - if (self.plt_got_section_index) |index| { + if (self.section_indexes.plt_got) |index| { shdrs[index].sh_size = self.plt_got.size(self); } - if (self.rela_dyn_section_index) |shndx| { + if (self.section_indexes.rela_dyn) |shndx| { var num = self.got.numRela(self) + self.copy_rel.numRela(); if (self.zigObjectPtr()) |zig_object| { num += zig_object.num_dynrelocs; @@ -3607,43 +3585,43 @@ fn updateSectionSizes(self: *Elf) !void { shdrs[shndx].sh_size = num * @sizeOf(elf.Elf64_Rela); } - if (self.rela_plt_section_index) |index| { + if (self.section_indexes.rela_plt) |index| { shdrs[index].sh_size = self.plt.numRela() * @sizeOf(elf.Elf64_Rela); } - if (self.copy_rel_section_index) |index| { + if (self.section_indexes.copy_rel) |index| { try self.copy_rel.updateSectionSize(index, self); } - if (self.interp_section_index) |index| { + if (self.section_indexes.interp) |index| { shdrs[index].sh_size = self.getTarget().dynamic_linker.get().?.len + 1; } - if (self.hash_section_index) |index| { + if (self.section_indexes.hash) |index| { shdrs[index].sh_size = self.hash.size(); } - if (self.gnu_hash_section_index) |index| { + if (self.section_indexes.gnu_hash) |index| { shdrs[index].sh_size = self.gnu_hash.size(); } - if (self.dynamic_section_index) |index| { + if (self.section_indexes.dynamic) |index| { shdrs[index].sh_size = self.dynamic.size(self); } - if (self.dynsymtab_section_index) |index| { + if (self.section_indexes.dynsymtab) |index| { shdrs[index].sh_size = self.dynsym.size(); } - if (self.dynstrtab_section_index) |index| { + if (self.section_indexes.dynstrtab) |index| { shdrs[index].sh_size = self.dynstrtab.items.len; } - if (self.versym_section_index) |index| { + if (self.section_indexes.versym) |index| { shdrs[index].sh_size = self.versym.items.len * @sizeOf(elf.Elf64_Versym); } - if (self.verneed_section_index) |index| { + if (self.section_indexes.verneed) |index| { shdrs[index].sh_size = self.verneed.size(); } @@ -3653,7 +3631,7 @@ fn updateSectionSizes(self: *Elf) !void { // FIXME:JK this is very much obsolete, remove! pub fn updateShStrtabSize(self: *Elf) void { - if (self.shstrtab_section_index) |index| { + if (self.section_indexes.shstrtab) |index| { self.sections.items(.shdr)[index].sh_size = self.shstrtab.items.len; } } @@ -3936,9 +3914,9 @@ fn allocateSpecialPhdrs(self: *Elf) void { const slice = self.sections.slice(); for (&[_]struct { OptionalProgramHeaderIndex, ?u32 }{ - .{ self.phdr_indexes.interp, self.interp_section_index }, - .{ self.phdr_indexes.dynamic, self.dynamic_section_index }, - .{ self.phdr_indexes.gnu_eh_frame, self.eh_frame_hdr_section_index }, + .{ self.phdr_indexes.interp, self.section_indexes.interp }, + .{ self.phdr_indexes.dynamic, self.section_indexes.dynamic }, + .{ self.phdr_indexes.gnu_eh_frame, self.section_indexes.eh_frame_hdr }, }) |pair| { if (pair[0].int()) |index| { const shdr = slice.items(.shdr)[pair[1].?]; @@ -4075,7 +4053,7 @@ pub fn updateSymtabSize(self: *Elf) !void { strsize += ctx.strsize; } - if (self.got_section_index) |_| { + if (self.section_indexes.got) |_| { self.got.output_symtab_ctx.reset(); self.got.output_symtab_ctx.ilocal = nlocals; self.got.updateSymtabSize(self); @@ -4083,7 +4061,7 @@ pub fn updateSymtabSize(self: *Elf) !void { strsize += self.got.output_symtab_ctx.strsize; } - if (self.plt_section_index) |_| { + if (self.section_indexes.plt) |_| { self.plt.output_symtab_ctx.reset(); self.plt.output_symtab_ctx.ilocal = nlocals; self.plt.updateSymtabSize(self); @@ -4091,7 +4069,7 @@ pub fn updateSymtabSize(self: *Elf) !void { strsize += self.plt.output_symtab_ctx.strsize; } - if (self.plt_got_section_index) |_| { + if (self.section_indexes.plt_got) |_| { self.plt_got.output_symtab_ctx.reset(); self.plt_got.output_symtab_ctx.ilocal = nlocals; self.plt_got.updateSymtabSize(self); @@ -4108,9 +4086,9 @@ pub fn updateSymtabSize(self: *Elf) !void { } const slice = self.sections.slice(); - const symtab_shdr = &slice.items(.shdr)[self.symtab_section_index.?]; + const symtab_shdr = &slice.items(.shdr)[self.section_indexes.symtab.?]; symtab_shdr.sh_info = nlocals; - symtab_shdr.sh_link = self.strtab_section_index.?; + symtab_shdr.sh_link = self.section_indexes.strtab.?; const sym_size: u64 = switch (self.ptr_width) { .p32 => @sizeOf(elf.Elf32_Sym), @@ -4119,7 +4097,7 @@ pub fn updateSymtabSize(self: *Elf) !void { const needed_size = (nlocals + nglobals) * sym_size; symtab_shdr.sh_size = needed_size; - const strtab = &slice.items(.shdr)[self.strtab_section_index.?]; + const strtab = &slice.items(.shdr)[self.section_indexes.strtab.?]; strtab.sh_size = strsize + 1; } @@ -4127,7 +4105,7 @@ fn writeSyntheticSections(self: *Elf) !void { const gpa = self.base.comp.gpa; const slice = self.sections.slice(); - if (self.interp_section_index) |shndx| { + if (self.section_indexes.interp) |shndx| { var buffer: [256]u8 = undefined; const interp = self.getTarget().dynamic_linker.get().?; @memcpy(buffer[0..interp.len], interp); @@ -4138,12 +4116,12 @@ fn writeSyntheticSections(self: *Elf) !void { try self.base.file.?.pwriteAll(contents, shdr.sh_offset); } - if (self.hash_section_index) |shndx| { + if (self.section_indexes.hash) |shndx| { const shdr = slice.items(.shdr)[shndx]; try self.base.file.?.pwriteAll(self.hash.buffer.items, shdr.sh_offset); } - if (self.gnu_hash_section_index) |shndx| { + if (self.section_indexes.gnu_hash) |shndx| { const shdr = slice.items(.shdr)[shndx]; var buffer = try std.ArrayList(u8).initCapacity(gpa, self.gnu_hash.size()); defer buffer.deinit(); @@ -4151,12 +4129,12 @@ fn writeSyntheticSections(self: *Elf) !void { try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset); } - if (self.versym_section_index) |shndx| { + if (self.section_indexes.versym) |shndx| { const shdr = slice.items(.shdr)[shndx]; try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.versym.items), shdr.sh_offset); } - if (self.verneed_section_index) |shndx| { + if (self.section_indexes.verneed) |shndx| { const shdr = slice.items(.shdr)[shndx]; var buffer = try std.ArrayList(u8).initCapacity(gpa, self.verneed.size()); defer buffer.deinit(); @@ -4164,7 +4142,7 @@ fn writeSyntheticSections(self: *Elf) !void { try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset); } - if (self.dynamic_section_index) |shndx| { + if (self.section_indexes.dynamic) |shndx| { const shdr = slice.items(.shdr)[shndx]; var buffer = try std.ArrayList(u8).initCapacity(gpa, self.dynamic.size(self)); defer buffer.deinit(); @@ -4172,7 +4150,7 @@ fn writeSyntheticSections(self: *Elf) !void { try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset); } - if (self.dynsymtab_section_index) |shndx| { + if (self.section_indexes.dynsymtab) |shndx| { const shdr = slice.items(.shdr)[shndx]; var buffer = try std.ArrayList(u8).initCapacity(gpa, self.dynsym.size()); defer buffer.deinit(); @@ -4180,12 +4158,12 @@ fn writeSyntheticSections(self: *Elf) !void { try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset); } - if (self.dynstrtab_section_index) |shndx| { + if (self.section_indexes.dynstrtab) |shndx| { const shdr = slice.items(.shdr)[shndx]; try self.base.file.?.pwriteAll(self.dynstrtab.items, shdr.sh_offset); } - if (self.eh_frame_section_index) |shndx| { + if (self.section_indexes.eh_frame) |shndx| { const existing_size = existing_size: { const zo = self.zigObjectPtr() orelse break :existing_size 0; const sym = zo.symbol(zo.eh_frame_index orelse break :existing_size 0); @@ -4200,7 +4178,7 @@ fn writeSyntheticSections(self: *Elf) !void { try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset + existing_size); } - if (self.eh_frame_hdr_section_index) |shndx| { + if (self.section_indexes.eh_frame_hdr) |shndx| { const shdr = slice.items(.shdr)[shndx]; const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow; var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size); @@ -4209,7 +4187,7 @@ fn writeSyntheticSections(self: *Elf) !void { try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset); } - if (self.got_section_index) |index| { + if (self.section_indexes.got) |index| { const shdr = slice.items(.shdr)[index]; var buffer = try std.ArrayList(u8).initCapacity(gpa, self.got.size(self)); defer buffer.deinit(); @@ -4217,7 +4195,7 @@ fn writeSyntheticSections(self: *Elf) !void { try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset); } - if (self.rela_dyn_section_index) |shndx| { + if (self.section_indexes.rela_dyn) |shndx| { const shdr = slice.items(.shdr)[shndx]; try self.got.addRela(self); try self.copy_rel.addRela(self); @@ -4225,7 +4203,7 @@ fn writeSyntheticSections(self: *Elf) !void { try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.rela_dyn.items), shdr.sh_offset); } - if (self.plt_section_index) |shndx| { + if (self.section_indexes.plt) |shndx| { const shdr = slice.items(.shdr)[shndx]; var buffer = try std.ArrayList(u8).initCapacity(gpa, self.plt.size(self)); defer buffer.deinit(); @@ -4233,7 +4211,7 @@ fn writeSyntheticSections(self: *Elf) !void { try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset); } - if (self.got_plt_section_index) |shndx| { + if (self.section_indexes.got_plt) |shndx| { const shdr = slice.items(.shdr)[shndx]; var buffer = try std.ArrayList(u8).initCapacity(gpa, self.got_plt.size(self)); defer buffer.deinit(); @@ -4241,7 +4219,7 @@ fn writeSyntheticSections(self: *Elf) !void { try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset); } - if (self.plt_got_section_index) |shndx| { + if (self.section_indexes.plt_got) |shndx| { const shdr = slice.items(.shdr)[shndx]; var buffer = try std.ArrayList(u8).initCapacity(gpa, self.plt_got.size(self)); defer buffer.deinit(); @@ -4249,7 +4227,7 @@ fn writeSyntheticSections(self: *Elf) !void { try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset); } - if (self.rela_plt_section_index) |shndx| { + if (self.section_indexes.rela_plt) |shndx| { const shdr = slice.items(.shdr)[shndx]; try self.plt.addRela(self); try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.rela_plt.items), shdr.sh_offset); @@ -4261,7 +4239,7 @@ fn writeSyntheticSections(self: *Elf) !void { // FIXME:JK again, why is this needed? pub fn writeShStrtab(self: *Elf) !void { - if (self.shstrtab_section_index) |index| { + if (self.section_indexes.shstrtab) |index| { const shdr = self.sections.items(.shdr)[index]; log.debug("writing .shstrtab from 0x{x} to 0x{x}", .{ shdr.sh_offset, shdr.sh_offset + shdr.sh_size }); try self.base.file.?.pwriteAll(self.shstrtab.items, shdr.sh_offset); @@ -4271,8 +4249,8 @@ pub fn writeShStrtab(self: *Elf) !void { pub fn writeSymtab(self: *Elf) !void { const gpa = self.base.comp.gpa; const slice = self.sections.slice(); - const symtab_shdr = slice.items(.shdr)[self.symtab_section_index.?]; - const strtab_shdr = slice.items(.shdr)[self.strtab_section_index.?]; + const symtab_shdr = slice.items(.shdr)[self.section_indexes.symtab.?]; + const strtab_shdr = slice.items(.shdr)[self.section_indexes.strtab.?]; const sym_size: u64 = switch (self.ptr_width) { .p32 => @sizeOf(elf.Elf32_Sym), .p64 => @sizeOf(elf.Elf64_Sym), @@ -4330,15 +4308,15 @@ pub fn writeSymtab(self: *Elf) !void { obj.asFile().writeSymtab(self); } - if (self.got_section_index) |_| { + if (self.section_indexes.got) |_| { self.got.writeSymtab(self); } - if (self.plt_section_index) |_| { + if (self.section_indexes.plt) |_| { self.plt.writeSymtab(self); } - if (self.plt_got_section_index) |_| { + if (self.section_indexes.plt_got) |_| { self.plt_got.writeSymtab(self); } @@ -4778,9 +4756,9 @@ pub fn mergeSection(self: *Elf, index: MergeSection.Index) *MergeSection { pub fn gotAddress(self: *Elf) i64 { const shndx = blk: { - if (self.getTarget().cpu.arch == .x86_64 and self.got_plt_section_index != null) - break :blk self.got_plt_section_index.?; - break :blk if (self.got_section_index) |shndx| shndx else null; + if (self.getTarget().cpu.arch == .x86_64 and self.section_indexes.got_plt != null) + break :blk self.section_indexes.got_plt.?; + break :blk if (self.section_indexes.got) |shndx| shndx else null; }; return if (shndx) |index| @intCast(self.sections.items(.shdr)[index].sh_addr) else 0; } diff --git a/src/link/Elf/LinkerDefined.zig b/src/link/Elf/LinkerDefined.zig index 9515dfcd432e9f297939a1bdf3bfa58ac4d15d9c..ad02d8d5d9f4606ea56acfb36762c2f5a3db4b9c 100644 --- a/src/link/Elf/LinkerDefined.zig +++ b/src/link/Elf/LinkerDefined.zig @@ -205,7 +205,7 @@ pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void { }.allocSymbol; // _DYNAMIC - if (elf_file.dynamic_section_index) |shndx| { + if (elf_file.section_indexes.dynamic) |shndx| { const shdr = shdrs[shndx]; allocSymbol(self, self.dynamic_index.?, shdr.sh_addr, shndx, elf_file); } @@ -236,19 +236,19 @@ pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void { // _GLOBAL_OFFSET_TABLE_ if (elf_file.getTarget().cpu.arch == .x86_64) { - if (elf_file.got_plt_section_index) |shndx| { + if (elf_file.section_indexes.got_plt) |shndx| { const shdr = shdrs[shndx]; allocSymbol(self, self.got_index.?, shdr.sh_addr, shndx, elf_file); } } else { - if (elf_file.got_section_index) |shndx| { + if (elf_file.section_indexes.got) |shndx| { const shdr = shdrs[shndx]; allocSymbol(self, self.got_index.?, shdr.sh_addr, shndx, elf_file); } } // _PROCEDURE_LINKAGE_TABLE_ - if (elf_file.plt_section_index) |shndx| { + if (elf_file.section_indexes.plt) |shndx| { const shdr = shdrs[shndx]; allocSymbol(self, self.plt_index.?, shdr.sh_addr, shndx, elf_file); } @@ -262,13 +262,13 @@ pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void { } // __GNU_EH_FRAME_HDR - if (elf_file.eh_frame_hdr_section_index) |shndx| { + if (elf_file.section_indexes.eh_frame_hdr) |shndx| { const shdr = shdrs[shndx]; allocSymbol(self, self.gnu_eh_frame_hdr_index.?, shdr.sh_addr, shndx, elf_file); } // __rela_iplt_start, __rela_iplt_end - if (elf_file.rela_dyn_section_index) |shndx| blk: { + if (elf_file.section_indexes.rela_dyn) |shndx| blk: { if (link_mode != .static or comp.config.pie) break :blk; const shdr = shdrs[shndx]; const end_addr = shdr.sh_addr + shdr.sh_size; diff --git a/src/link/Elf/Object.zig b/src/link/Elf/Object.zig index 23216020a628b285c930a66b40cc45abece5f69d..03172efb386a9bca16ba649807c35405b8f79ba5 100644 --- a/src/link/Elf/Object.zig +++ b/src/link/Elf/Object.zig @@ -927,7 +927,7 @@ pub fn initRelaSections(self: *Object, elf_file: *Elf) !void { for (self.atoms_indexes.items) |atom_index| { const atom_ptr = self.atom(atom_index) orelse continue; if (!atom_ptr.alive) continue; - if (atom_ptr.output_section_index == elf_file.eh_frame_section_index) continue; + if (atom_ptr.output_section_index == elf_file.section_indexes.eh_frame) continue; const shndx = atom_ptr.relocsShndx() orelse continue; const shdr = self.shdrs.items[shndx]; const out_shndx = try elf_file.initOutputSection(.{ @@ -947,7 +947,7 @@ pub fn addAtomsToRelaSections(self: *Object, elf_file: *Elf) !void { for (self.atoms_indexes.items) |atom_index| { const atom_ptr = self.atom(atom_index) orelse continue; if (!atom_ptr.alive) continue; - if (atom_ptr.output_section_index == elf_file.eh_frame_section_index) continue; + if (atom_ptr.output_section_index == elf_file.section_indexes.eh_frame) continue; const shndx = blk: { const shndx = atom_ptr.relocsShndx() orelse continue; const shdr = self.shdrs.items[shndx]; @@ -960,7 +960,7 @@ pub fn addAtomsToRelaSections(self: *Object, elf_file: *Elf) !void { const slice = elf_file.sections.slice(); const shdr = &slice.items(.shdr)[shndx]; shdr.sh_info = atom_ptr.output_section_index; - shdr.sh_link = elf_file.symtab_section_index.?; + shdr.sh_link = elf_file.section_indexes.symtab.?; const gpa = elf_file.base.comp.gpa; const atom_list = &elf_file.sections.items(.atom_list)[shndx]; try atom_list.append(gpa, .{ .index = atom_index, .file = self.index }); diff --git a/src/link/Elf/Symbol.zig b/src/link/Elf/Symbol.zig index 6eaaedf28c766dd6324e77fbc60d3f46f75ead66..6fc82474e24fd03423007d0e3078df53a7cae86c 100644 --- a/src/link/Elf/Symbol.zig +++ b/src/link/Elf/Symbol.zig @@ -128,7 +128,7 @@ pub fn address(symbol: Symbol, opts: struct { plt: bool = true, trampoline: bool if (mem.eql(u8, atom_ptr.name(elf_file), ".eh_frame")) { const sym_name = symbol.name(elf_file); const sh_addr, const sh_size = blk: { - const shndx = elf_file.eh_frame_section_index orelse break :blk .{ 0, 0 }; + const shndx = elf_file.section_indexes.eh_frame orelse break :blk .{ 0, 0 }; const shdr = elf_file.sections.items(.shdr)[shndx]; break :blk .{ shdr.sh_addr, shdr.sh_size }; }; @@ -176,7 +176,7 @@ pub fn gotAddress(symbol: Symbol, elf_file: *Elf) i64 { pub fn pltGotAddress(symbol: Symbol, elf_file: *Elf) i64 { if (!symbol.flags.has_pltgot) return 0; const extras = symbol.extra(elf_file); - const shdr = elf_file.sections.items(.shdr)[elf_file.plt_got_section_index.?]; + const shdr = elf_file.sections.items(.shdr)[elf_file.section_indexes.plt_got.?]; const cpu_arch = elf_file.getTarget().cpu.arch; return @intCast(shdr.sh_addr + extras.plt_got * PltGotSection.entrySize(cpu_arch)); } @@ -184,7 +184,7 @@ pub fn pltGotAddress(symbol: Symbol, elf_file: *Elf) i64 { pub fn pltAddress(symbol: Symbol, elf_file: *Elf) i64 { if (!symbol.flags.has_plt) return 0; const extras = symbol.extra(elf_file); - const shdr = elf_file.sections.items(.shdr)[elf_file.plt_section_index.?]; + const shdr = elf_file.sections.items(.shdr)[elf_file.section_indexes.plt.?]; const cpu_arch = elf_file.getTarget().cpu.arch; return @intCast(shdr.sh_addr + extras.plt * PltSection.entrySize(cpu_arch) + PltSection.preambleSize(cpu_arch)); } @@ -192,13 +192,13 @@ pub fn pltAddress(symbol: Symbol, elf_file: *Elf) i64 { pub fn gotPltAddress(symbol: Symbol, elf_file: *Elf) i64 { if (!symbol.flags.has_plt) return 0; const extras = symbol.extra(elf_file); - const shdr = elf_file.sections.items(.shdr)[elf_file.got_plt_section_index.?]; + const shdr = elf_file.sections.items(.shdr)[elf_file.section_indexes.got_plt.?]; return @intCast(shdr.sh_addr + extras.plt * 8 + GotPltSection.preamble_size); } pub fn copyRelAddress(symbol: Symbol, elf_file: *Elf) i64 { if (!symbol.flags.has_copy_rel) return 0; - const shdr = elf_file.sections.items(.shdr)[elf_file.copy_rel_section_index.?]; + const shdr = elf_file.sections.items(.shdr)[elf_file.section_indexes.copy_rel.?]; return @as(i64, @intCast(shdr.sh_addr)) + symbol.value; } @@ -289,7 +289,7 @@ pub fn setOutputSym(symbol: Symbol, elf_file: *Elf, out: *elf.Elf64_Sym) void { break :blk esym.st_bind(); }; const st_shndx: u16 = blk: { - if (symbol.flags.has_copy_rel) break :blk @intCast(elf_file.copy_rel_section_index.?); + if (symbol.flags.has_copy_rel) break :blk @intCast(elf_file.section_indexes.copy_rel.?); if (file_ptr == .shared_object or esym.st_shndx == elf.SHN_UNDEF) break :blk elf.SHN_UNDEF; if (elf_file.base.isRelocatable() and esym.st_shndx == elf.SHN_COMMON) break :blk elf.SHN_COMMON; if (symbol.mergeSubsection(elf_file)) |msub| break :blk @intCast(msub.mergeSection(elf_file).output_section_index); diff --git a/src/link/Elf/ZigObject.zig b/src/link/Elf/ZigObject.zig index e8b804e024509d53eb7a1668fb6c7c43aaa624ee..d97b5699e51317287a3a9e2ce1de4e42e6a95363 100644 --- a/src/link/Elf/ZigObject.zig +++ b/src/link/Elf/ZigObject.zig @@ -791,7 +791,7 @@ pub fn initRelaSections(self: *ZigObject, elf_file: *Elf) !void { for (self.atoms_indexes.items) |atom_index| { const atom_ptr = self.atom(atom_index) orelse continue; if (!atom_ptr.alive) continue; - if (atom_ptr.output_section_index == elf_file.eh_frame_section_index) continue; + if (atom_ptr.output_section_index == elf_file.section_indexes.eh_frame) continue; const rela_shndx = atom_ptr.relocsShndx() orelse continue; // TODO this check will become obsolete when we rework our relocs mechanism at the ZigObject level if (self.relocs.items[rela_shndx].items.len == 0) continue; @@ -812,7 +812,7 @@ pub fn addAtomsToRelaSections(self: *ZigObject, elf_file: *Elf) !void { for (self.atoms_indexes.items) |atom_index| { const atom_ptr = self.atom(atom_index) orelse continue; if (!atom_ptr.alive) continue; - if (atom_ptr.output_section_index == elf_file.eh_frame_section_index) continue; + if (atom_ptr.output_section_index == elf_file.section_indexes.eh_frame) continue; const rela_shndx = atom_ptr.relocsShndx() orelse continue; // TODO this check will become obsolete when we rework our relocs mechanism at the ZigObject level if (self.relocs.items[rela_shndx].items.len == 0) continue; @@ -826,7 +826,7 @@ pub fn addAtomsToRelaSections(self: *ZigObject, elf_file: *Elf) !void { const out_rela_shndx = elf_file.sectionByName(rela_sect_name).?; const out_rela_shdr = &elf_file.sections.items(.shdr)[out_rela_shndx]; out_rela_shdr.sh_info = out_shndx; - out_rela_shdr.sh_link = elf_file.symtab_section_index.?; + out_rela_shdr.sh_link = elf_file.section_indexes.symtab.?; const atom_list = &elf_file.sections.items(.atom_list)[out_rela_shndx]; try atom_list.append(gpa, .{ .index = atom_index, .file = self.index }); } diff --git a/src/link/Elf/eh_frame.zig b/src/link/Elf/eh_frame.zig index b520c94aaf14f45ebfbcdf6ba3df2e14283dc307..0e08677b80dc250c8858ee3bd826c16eb38a9486 100644 --- a/src/link/Elf/eh_frame.zig +++ b/src/link/Elf/eh_frame.zig @@ -12,7 +12,7 @@ pub const Fde = struct { out_offset: u64 = 0, pub fn address(fde: Fde, elf_file: *Elf) u64 { - const base: u64 = if (elf_file.eh_frame_section_index) |shndx| + const base: u64 = if (elf_file.section_indexes.eh_frame) |shndx| elf_file.sections.items(.shdr)[shndx].sh_addr else 0; @@ -111,7 +111,7 @@ pub const Cie = struct { alive: bool = false, pub fn address(cie: Cie, elf_file: *Elf) u64 { - const base: u64 = if (elf_file.eh_frame_section_index) |shndx| + const base: u64 = if (elf_file.section_indexes.eh_frame) |shndx| elf_file.sections.items(.shdr)[shndx].sh_addr else 0; @@ -337,7 +337,7 @@ fn resolveReloc(rec: anytype, sym: *const Symbol, rel: elf.Elf64_Rela, elf_file: pub fn writeEhFrame(elf_file: *Elf, writer: anytype) !void { relocs_log.debug("{x}: .eh_frame", .{ - elf_file.sections.items(.shdr)[elf_file.eh_frame_section_index.?].sh_addr, + elf_file.sections.items(.shdr)[elf_file.section_indexes.eh_frame.?].sh_addr, }); var has_reloc_errors = false; @@ -458,7 +458,7 @@ fn emitReloc(elf_file: *Elf, r_offset: u64, sym: *const Symbol, rel: elf.Elf64_R pub fn writeEhFrameRelocs(elf_file: *Elf, writer: anytype) !void { relocs_log.debug("{x}: .eh_frame", .{ - elf_file.sections.items(.shdr)[elf_file.eh_frame_section_index.?].sh_addr, + elf_file.sections.items(.shdr)[elf_file.section_indexes.eh_frame.?].sh_addr, }); if (elf_file.zigObjectPtr()) |zo| zo: { @@ -511,8 +511,8 @@ pub fn writeEhFrameHdr(elf_file: *Elf, writer: anytype) !void { try writer.writeByte(DW_EH_PE.datarel | DW_EH_PE.sdata4); const shdrs = elf_file.sections.items(.shdr); - const eh_frame_shdr = shdrs[elf_file.eh_frame_section_index.?]; - const eh_frame_hdr_shdr = shdrs[elf_file.eh_frame_hdr_section_index.?]; + const eh_frame_shdr = shdrs[elf_file.section_indexes.eh_frame.?]; + const eh_frame_hdr_shdr = shdrs[elf_file.section_indexes.eh_frame_hdr.?]; const num_fdes = @as(u32, @intCast(@divExact(eh_frame_hdr_shdr.sh_size - eh_frame_hdr_header_size, 8))); const existing_size = existing_size: { const zo = elf_file.zigObjectPtr() orelse break :existing_size 0; diff --git a/src/link/Elf/relocatable.zig b/src/link/Elf/relocatable.zig index bdf0d378ffa1d1d304746f7d89ea6d56b66f597e..73fcf6a44a77cfcb6a6fb8eab84f9ee1bba583fb 100644 --- a/src/link/Elf/relocatable.zig +++ b/src/link/Elf/relocatable.zig @@ -288,8 +288,8 @@ fn initSections(elf_file: *Elf) !void { } else false; }; if (needs_eh_frame) { - if (elf_file.eh_frame_section_index == null) { - elf_file.eh_frame_section_index = elf_file.sectionByName(".eh_frame") orelse + if (elf_file.section_indexes.eh_frame == null) { + elf_file.section_indexes.eh_frame = elf_file.sectionByName(".eh_frame") orelse try elf_file.addSection(.{ .name = try elf_file.insertShString(".eh_frame"), .type = if (elf_file.getTarget().cpu.arch == .x86_64) @@ -300,10 +300,10 @@ fn initSections(elf_file: *Elf) !void { .addralign = elf_file.ptrWidthBytes(), }); } - elf_file.eh_frame_rela_section_index = elf_file.sectionByName(".rela.eh_frame") orelse + elf_file.section_indexes.eh_frame_rela = elf_file.sectionByName(".rela.eh_frame") orelse try elf_file.addRelaShdr( try elf_file.insertShString(".rela.eh_frame"), - elf_file.eh_frame_section_index.?, + elf_file.section_indexes.eh_frame.?, ); } @@ -346,7 +346,7 @@ fn updateSectionSizes(elf_file: *Elf) !void { for (slice.items(.shdr), 0..) |*shdr, shndx| { const atom_list = slice.items(.atom_list)[shndx]; if (shdr.sh_type != elf.SHT_RELA) continue; - if (@as(u32, @intCast(shndx)) == elf_file.eh_frame_section_index) continue; + if (@as(u32, @intCast(shndx)) == elf_file.section_indexes.eh_frame) continue; for (atom_list.items) |ref| { const atom_ptr = elf_file.atom(ref) orelse continue; if (!atom_ptr.alive) continue; @@ -357,10 +357,10 @@ fn updateSectionSizes(elf_file: *Elf) !void { if (shdr.sh_size == 0) shdr.sh_offset = 0; } - if (elf_file.eh_frame_section_index) |index| { + if (elf_file.section_indexes.eh_frame) |index| { slice.items(.shdr)[index].sh_size = try eh_frame.calcEhFrameSize(elf_file); } - if (elf_file.eh_frame_rela_section_index) |index| { + if (elf_file.section_indexes.eh_frame_rela) |index| { const shdr = &slice.items(.shdr)[index]; shdr.sh_size = eh_frame.calcEhFrameRelocs(elf_file) * shdr.sh_entsize; } @@ -374,7 +374,7 @@ fn updateComdatGroupsSizes(elf_file: *Elf) void { for (elf_file.comdat_group_sections.items) |cg| { const shdr = &elf_file.sections.items(.shdr)[cg.shndx]; shdr.sh_size = cg.size(elf_file); - shdr.sh_link = elf_file.symtab_section_index.?; + shdr.sh_link = elf_file.section_indexes.symtab.?; const sym = cg.symbol(elf_file); shdr.sh_info = sym.outputSymtabIndex(elf_file) orelse sym.outputShndx(elf_file).?; @@ -439,7 +439,7 @@ fn writeSyntheticSections(elf_file: *Elf) !void { for (slice.items(.shdr), slice.items(.atom_list), 0..) |shdr, atom_list, shndx| { if (shdr.sh_type != elf.SHT_RELA) continue; if (atom_list.items.len == 0) continue; - if (@as(u32, @intCast(shndx)) == elf_file.eh_frame_section_index) continue; + if (@as(u32, @intCast(shndx)) == elf_file.section_indexes.eh_frame) continue; const num_relocs = math.cast(usize, @divExact(shdr.sh_size, shdr.sh_entsize)) orelse return error.Overflow; @@ -471,7 +471,7 @@ fn writeSyntheticSections(elf_file: *Elf) !void { try elf_file.base.file.?.pwriteAll(mem.sliceAsBytes(relocs.items), shdr.sh_offset); } - if (elf_file.eh_frame_section_index) |shndx| { + if (elf_file.section_indexes.eh_frame) |shndx| { const existing_size = existing_size: { const zo = elf_file.zigObjectPtr() orelse break :existing_size 0; const sym = zo.symbol(zo.eh_frame_index orelse break :existing_size 0); @@ -489,7 +489,7 @@ fn writeSyntheticSections(elf_file: *Elf) !void { assert(buffer.items.len == sh_size - existing_size); try elf_file.base.file.?.pwriteAll(buffer.items, shdr.sh_offset + existing_size); } - if (elf_file.eh_frame_rela_section_index) |shndx| { + if (elf_file.section_indexes.eh_frame_rela) |shndx| { const shdr = slice.items(.shdr)[shndx]; const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow; var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size); diff --git a/src/link/Elf/synthetic_sections.zig b/src/link/Elf/synthetic_sections.zig index 987ee4bf9ad69a416e23cefbf66b99df0869f749..95bcb4c1a0df37f62f16ae7675a33da075b27525 100644 --- a/src/link/Elf/synthetic_sections.zig +++ b/src/link/Elf/synthetic_sections.zig @@ -75,18 +75,18 @@ pub const DynamicSection = struct { if (elf_file.sectionByName(".fini") != null) nentries += 1; // FINI if (elf_file.sectionByName(".init_array") != null) nentries += 2; // INIT_ARRAY if (elf_file.sectionByName(".fini_array") != null) nentries += 2; // FINI_ARRAY - if (elf_file.rela_dyn_section_index != null) nentries += 3; // RELA - if (elf_file.rela_plt_section_index != null) nentries += 3; // JMPREL - if (elf_file.got_plt_section_index != null) nentries += 1; // PLTGOT + if (elf_file.section_indexes.rela_dyn != null) nentries += 3; // RELA + if (elf_file.section_indexes.rela_plt != null) nentries += 3; // JMPREL + if (elf_file.section_indexes.got_plt != null) nentries += 1; // PLTGOT nentries += 1; // HASH - if (elf_file.gnu_hash_section_index != null) nentries += 1; // GNU_HASH + if (elf_file.section_indexes.gnu_hash != null) nentries += 1; // GNU_HASH if (elf_file.has_text_reloc) nentries += 1; // TEXTREL nentries += 1; // SYMTAB nentries += 1; // SYMENT nentries += 1; // STRTAB nentries += 1; // STRSZ - if (elf_file.versym_section_index != null) nentries += 1; // VERSYM - if (elf_file.verneed_section_index != null) nentries += 2; // VERNEED + if (elf_file.section_indexes.versym != null) nentries += 1; // VERSYM + if (elf_file.section_indexes.verneed != null) nentries += 2; // VERNEED if (dt.getFlags(elf_file) != null) nentries += 1; // FLAGS if (dt.getFlags1(elf_file) != null) nentries += 1; // FLAGS_1 if (!elf_file.isEffectivelyDynLib()) nentries += 1; // DEBUG @@ -139,7 +139,7 @@ pub const DynamicSection = struct { } // RELA - if (elf_file.rela_dyn_section_index) |shndx| { + if (elf_file.section_indexes.rela_dyn) |shndx| { const shdr = shdrs[shndx]; try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_RELA, .d_val = shdr.sh_addr }); try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_RELASZ, .d_val = shdr.sh_size }); @@ -147,7 +147,7 @@ pub const DynamicSection = struct { } // JMPREL - if (elf_file.rela_plt_section_index) |shndx| { + if (elf_file.section_indexes.rela_plt) |shndx| { const shdr = shdrs[shndx]; try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_JMPREL, .d_val = shdr.sh_addr }); try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_PLTRELSZ, .d_val = shdr.sh_size }); @@ -155,18 +155,18 @@ pub const DynamicSection = struct { } // PLTGOT - if (elf_file.got_plt_section_index) |shndx| { + if (elf_file.section_indexes.got_plt) |shndx| { const addr = shdrs[shndx].sh_addr; try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_PLTGOT, .d_val = addr }); } { - assert(elf_file.hash_section_index != null); - const addr = shdrs[elf_file.hash_section_index.?].sh_addr; + assert(elf_file.section_indexes.hash != null); + const addr = shdrs[elf_file.section_indexes.hash.?].sh_addr; try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_HASH, .d_val = addr }); } - if (elf_file.gnu_hash_section_index) |shndx| { + if (elf_file.section_indexes.gnu_hash) |shndx| { const addr = shdrs[shndx].sh_addr; try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_GNU_HASH, .d_val = addr }); } @@ -178,28 +178,28 @@ pub const DynamicSection = struct { // SYMTAB + SYMENT { - assert(elf_file.dynsymtab_section_index != null); - const shdr = shdrs[elf_file.dynsymtab_section_index.?]; + assert(elf_file.section_indexes.dynsymtab != null); + const shdr = shdrs[elf_file.section_indexes.dynsymtab.?]; try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_SYMTAB, .d_val = shdr.sh_addr }); try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_SYMENT, .d_val = shdr.sh_entsize }); } // STRTAB + STRSZ { - assert(elf_file.dynstrtab_section_index != null); - const shdr = shdrs[elf_file.dynstrtab_section_index.?]; + assert(elf_file.section_indexes.dynstrtab != null); + const shdr = shdrs[elf_file.section_indexes.dynstrtab.?]; try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_STRTAB, .d_val = shdr.sh_addr }); try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_STRSZ, .d_val = shdr.sh_size }); } // VERSYM - if (elf_file.versym_section_index) |shndx| { + if (elf_file.section_indexes.versym) |shndx| { const addr = shdrs[shndx].sh_addr; try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_VERSYM, .d_val = addr }); } // VERNEED + VERNEEDNUM - if (elf_file.verneed_section_index) |shndx| { + if (elf_file.section_indexes.verneed) |shndx| { const addr = shdrs[shndx].sh_addr; try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_VERNEED, .d_val = addr }); try writer.writeStruct(elf.Elf64_Dyn{ @@ -261,7 +261,7 @@ pub const GotSection = struct { pub fn address(entry: Entry, elf_file: *Elf) i64 { const ptr_bytes = elf_file.archPtrWidthBytes(); - const shdr = &elf_file.sections.items(.shdr)[elf_file.got_section_index.?]; + const shdr = &elf_file.sections.items(.shdr)[elf_file.section_indexes.got.?]; return @as(i64, @intCast(shdr.sh_addr)) + entry.cell_index * ptr_bytes; } }; @@ -599,7 +599,7 @@ pub const GotSection = struct { .st_name = st_name, .st_info = elf.STT_OBJECT, .st_other = 0, - .st_shndx = @intCast(elf_file.got_section_index.?), + .st_shndx = @intCast(elf_file.section_indexes.got.?), .st_value = @intCast(st_value), .st_size = st_size, }; @@ -742,7 +742,7 @@ pub const PltSection = struct { .st_name = st_name, .st_info = elf.STT_FUNC, .st_other = 0, - .st_shndx = @intCast(elf_file.plt_section_index.?), + .st_shndx = @intCast(elf_file.section_indexes.plt.?), .st_value = @intCast(sym.pltAddress(elf_file)), .st_size = entrySize(cpu_arch), }; @@ -784,8 +784,8 @@ pub const PltSection = struct { const x86_64 = struct { fn write(plt: PltSection, elf_file: *Elf, writer: anytype) !void { const shdrs = elf_file.sections.items(.shdr); - const plt_addr = shdrs[elf_file.plt_section_index.?].sh_addr; - const got_plt_addr = shdrs[elf_file.got_plt_section_index.?].sh_addr; + const plt_addr = shdrs[elf_file.section_indexes.plt.?].sh_addr; + const got_plt_addr = shdrs[elf_file.section_indexes.got_plt.?].sh_addr; var preamble = [_]u8{ 0xf3, 0x0f, 0x1e, 0xfa, // endbr64 0x41, 0x53, // push r11 @@ -820,8 +820,8 @@ pub const PltSection = struct { fn write(plt: PltSection, elf_file: *Elf, writer: anytype) !void { { const shdrs = elf_file.sections.items(.shdr); - const plt_addr: i64 = @intCast(shdrs[elf_file.plt_section_index.?].sh_addr); - const got_plt_addr: i64 = @intCast(shdrs[elf_file.got_plt_section_index.?].sh_addr); + const plt_addr: i64 = @intCast(shdrs[elf_file.section_indexes.plt.?].sh_addr); + const got_plt_addr: i64 = @intCast(shdrs[elf_file.section_indexes.got_plt.?].sh_addr); // TODO: relax if possible // .got.plt[2] const pages = try aarch64_util.calcNumberOfPages(plt_addr + 4, got_plt_addr + 16); @@ -894,7 +894,7 @@ pub const GotPltSection = struct { // [2]: 0x0 try writer.writeInt(u64, 0x0, .little); try writer.writeInt(u64, 0x0, .little); - if (elf_file.plt_section_index) |shndx| { + if (elf_file.section_indexes.plt) |shndx| { const plt_addr = elf_file.sections.items(.shdr)[shndx].sh_addr; for (0..elf_file.plt.symbols.items.len) |_| { // [N]: .plt @@ -962,7 +962,7 @@ pub const PltGotSection = struct { .st_name = st_name, .st_info = elf.STT_FUNC, .st_other = 0, - .st_shndx = @intCast(elf_file.plt_got_section_index.?), + .st_shndx = @intCast(elf_file.section_indexes.plt_got.?), .st_value = @intCast(sym.pltGotAddress(elf_file)), .st_size = 16, }; -- 2.54.0 From 7b69738a060c738d0f389365bf748dd7321b723c Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 10 Oct 2024 18:34:54 -0700 Subject: [PATCH 5/7] link.Elf: fix merge sections namespacing `link.Elf.merge_section.MergeSection` -> `link.Elf.Merge.Section` --- CMakeLists.txt | 4 +- src/link/Elf.zig | 24 +++--- src/link/Elf/{merge_section.zig => Merge.zig} | 79 ++++++++++--------- src/link/Elf/Object.zig | 12 +-- src/link/Elf/Symbol.zig | 4 +- 5 files changed, 61 insertions(+), 62 deletions(-) rename src/link/Elf/{merge_section.zig => Merge.zig} (77%) diff --git a/CMakeLists.txt b/CMakeLists.txt index e71f799b549187b51897c1df5870a09c54157e6f..70d1fde6bb5b83d4e13984ee86c8bda84ca6ca8d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -603,18 +603,18 @@ set(ZIG_STAGE2_SOURCES src/link/Elf/AtomList.zig src/link/Elf/LdScript.zig src/link/Elf/LinkerDefined.zig + src/link/Elf/Merge.zig src/link/Elf/Object.zig src/link/Elf/SharedObject.zig src/link/Elf/Symbol.zig + src/link/Elf/Thunk.zig src/link/Elf/ZigObject.zig src/link/Elf/eh_frame.zig src/link/Elf/file.zig src/link/Elf/gc.zig - src/link/Elf/merge_section.zig src/link/Elf/relocatable.zig src/link/Elf/relocation.zig src/link/Elf/synthetic_sections.zig - src/link/Elf/Thunk.zig src/link/MachO.zig src/link/MachO/Archive.zig src/link/MachO/Atom.zig diff --git a/src/link/Elf.zig b/src/link/Elf.zig index a69f5fe18c3425cee25b285d581e0f55d19f7fcf..24a99e567759b33eef48458967e6e159b5c41df4 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -1,3 +1,5 @@ +pub const Atom = @import("Elf/Atom.zig"); + base: link.File, rpath_table: std.StringArrayHashMapUnmanaged(void), image_base: u64, @@ -109,8 +111,8 @@ num_ifunc_dynrelocs: usize = 0, thunks: std.ArrayListUnmanaged(Thunk) = .empty, /// List of output merge sections with deduped contents. -merge_sections: std.ArrayListUnmanaged(MergeSection) = .empty, -comment_merge_section_index: ?MergeSection.Index = null, +merge_sections: std.ArrayListUnmanaged(Merge.Section) = .empty, +comment_merge_section_index: ?Merge.Section.Index = null, first_eflags: ?elf.Elf64_Word = null, @@ -4726,7 +4728,7 @@ pub fn linkerDefinedPtr(self: *Elf) ?*LinkerDefined { return self.file(index).?.linker_defined; } -pub fn getOrCreateMergeSection(self: *Elf, name: [:0]const u8, flags: u64, @"type": u32) !MergeSection.Index { +pub fn getOrCreateMergeSection(self: *Elf, name: [:0]const u8, flags: u64, @"type": u32) !Merge.Section.Index { const gpa = self.base.comp.gpa; const out_name = name: { if (self.base.isRelocatable()) break :name name; @@ -4739,7 +4741,7 @@ pub fn getOrCreateMergeSection(self: *Elf, name: [:0]const u8, flags: u64, @"typ } const out_off = try self.insertShString(out_name); const out_flags = flags & ~@as(u64, elf.SHF_COMPRESSED | elf.SHF_GROUP); - const index = @as(MergeSection.Index, @intCast(self.merge_sections.items.len)); + const index: Merge.Section.Index = @intCast(self.merge_sections.items.len); const msec = try self.merge_sections.addOne(gpa); msec.* = .{ .name_offset = out_off, @@ -4749,7 +4751,7 @@ pub fn getOrCreateMergeSection(self: *Elf, name: [:0]const u8, flags: u64, @"typ return index; } -pub fn mergeSection(self: *Elf, index: MergeSection.Index) *MergeSection { +pub fn mergeSection(self: *Elf, index: Merge.Section.Index) *Merge.Section { assert(index < self.merge_sections.items.len); return &self.merge_sections.items[index]; } @@ -5541,6 +5543,9 @@ const relocs_log = std.log.scoped(.link_relocs); const state_log = std.log.scoped(.link_state); const math = std.math; const mem = std.mem; +const Allocator = std.mem.Allocator; +const Cache = std.Build.Cache; +const Hash = std.hash.Wyhash; const codegen = @import("../codegen.zig"); const dev = @import("../dev.zig"); @@ -5548,7 +5553,6 @@ const eh_frame = @import("Elf/eh_frame.zig"); const gc = @import("Elf/gc.zig"); const glibc = @import("../glibc.zig"); const link = @import("../link.zig"); -const merge_section = @import("Elf/merge_section.zig"); const musl = @import("../musl.zig"); const relocatable = @import("Elf/relocatable.zig"); const relocation = @import("Elf/relocation.zig"); @@ -5556,12 +5560,10 @@ const target_util = @import("../target.zig"); const trace = @import("../tracy.zig").trace; const synthetic_sections = @import("Elf/synthetic_sections.zig"); +const Merge = @import("Elf/Merge.zig"); const Air = @import("../Air.zig"); -const Allocator = std.mem.Allocator; const Archive = @import("Elf/Archive.zig"); -pub const Atom = @import("Elf/Atom.zig"); const AtomList = @import("Elf/AtomList.zig"); -const Cache = std.Build.Cache; const Path = Cache.Path; const Compilation = @import("../Compilation.zig"); const ComdatGroupSection = synthetic_sections.ComdatGroupSection; @@ -5574,15 +5576,11 @@ const File = @import("Elf/file.zig").File; const GnuHashSection = synthetic_sections.GnuHashSection; const GotSection = synthetic_sections.GotSection; const GotPltSection = synthetic_sections.GotPltSection; -const Hash = std.hash.Wyhash; const HashSection = synthetic_sections.HashSection; -const InputMergeSection = merge_section.InputMergeSection; const LdScript = @import("Elf/LdScript.zig"); const LinkerDefined = @import("Elf/LinkerDefined.zig"); const Liveness = @import("../Liveness.zig"); const LlvmObject = @import("../codegen/llvm.zig").Object; -const MergeSection = merge_section.MergeSection; -const MergeSubsection = merge_section.MergeSubsection; const Zcu = @import("../Zcu.zig"); const Object = @import("Elf/Object.zig"); const InternPool = @import("../InternPool.zig"); diff --git a/src/link/Elf/merge_section.zig b/src/link/Elf/Merge.zig similarity index 77% rename from src/link/Elf/merge_section.zig rename to src/link/Elf/Merge.zig index dc6239d738f9cad99b54986c4d99a1b4cc768370..33e4f9c5b29cc220986d9ccb59ce5b8d8a2a5aa2 100644 --- a/src/link/Elf/merge_section.zig +++ b/src/link/Elf/Merge.zig @@ -1,4 +1,4 @@ -pub const MergeSection = struct { +pub const Section = struct { value: u64 = 0, size: u64 = 0, alignment: Atom.Alignment = .@"1", @@ -10,25 +10,25 @@ pub const MergeSection = struct { bytes: std.ArrayListUnmanaged(u8) = .empty, table: std.HashMapUnmanaged( String, - MergeSubsection.Index, + Subsection.Index, IndexContext, std.hash_map.default_max_load_percentage, ) = .{}, - subsections: std.ArrayListUnmanaged(MergeSubsection) = .empty, - finalized_subsections: std.ArrayListUnmanaged(MergeSubsection.Index) = .empty, + subsections: std.ArrayListUnmanaged(Subsection) = .empty, + finalized_subsections: std.ArrayListUnmanaged(Subsection.Index) = .empty, - pub fn deinit(msec: *MergeSection, allocator: Allocator) void { + pub fn deinit(msec: *Section, allocator: Allocator) void { msec.bytes.deinit(allocator); msec.table.deinit(allocator); msec.subsections.deinit(allocator); msec.finalized_subsections.deinit(allocator); } - pub fn name(msec: MergeSection, elf_file: *Elf) [:0]const u8 { + pub fn name(msec: Section, elf_file: *Elf) [:0]const u8 { return elf_file.getShString(msec.name_offset); } - pub fn address(msec: MergeSection, elf_file: *Elf) i64 { + pub fn address(msec: Section, elf_file: *Elf) i64 { const shdr = elf_file.sections.items(.shdr)[msec.output_section_index]; return @intCast(shdr.sh_addr + msec.value); } @@ -36,10 +36,10 @@ pub const MergeSection = struct { const InsertResult = struct { found_existing: bool, key: String, - sub: *MergeSubsection.Index, + sub: *Subsection.Index, }; - pub fn insert(msec: *MergeSection, allocator: Allocator, string: []const u8) !InsertResult { + pub fn insert(msec: *Section, allocator: Allocator, string: []const u8) !InsertResult { const gop = try msec.table.getOrPutContextAdapted( allocator, string, @@ -54,7 +54,7 @@ pub const MergeSection = struct { return .{ .found_existing = gop.found_existing, .key = gop.key_ptr.*, .sub = gop.value_ptr }; } - pub fn insertZ(msec: *MergeSection, allocator: Allocator, string: []const u8) !InsertResult { + pub fn insertZ(msec: *Section, allocator: Allocator, string: []const u8) !InsertResult { const with_null = try allocator.alloc(u8, string.len + 1); defer allocator.free(with_null); @memcpy(with_null[0..string.len], string); @@ -64,7 +64,7 @@ pub const MergeSection = struct { /// Finalizes the merge section and clears hash table. /// Sorts all owned subsections. - pub fn finalize(msec: *MergeSection, allocator: Allocator) !void { + pub fn finalize(msec: *Section, allocator: Allocator) !void { try msec.finalized_subsections.ensureTotalCapacityPrecise(allocator, msec.subsections.items.len); var it = msec.table.iterator(); @@ -76,7 +76,7 @@ pub const MergeSection = struct { msec.table.clearAndFree(allocator); const sortFn = struct { - pub fn sortFn(ctx: *MergeSection, lhs: MergeSubsection.Index, rhs: MergeSubsection.Index) bool { + pub fn sortFn(ctx: *Section, lhs: Subsection.Index, rhs: Subsection.Index) bool { const lhs_msub = ctx.mergeSubsection(lhs); const rhs_msub = ctx.mergeSubsection(rhs); if (lhs_msub.alignment.compareStrict(.eq, rhs_msub.alignment)) { @@ -91,10 +91,10 @@ pub const MergeSection = struct { } }.sortFn; - std.mem.sort(MergeSubsection.Index, msec.finalized_subsections.items, msec, sortFn); + std.mem.sort(Subsection.Index, msec.finalized_subsections.items, msec, sortFn); } - pub fn updateSize(msec: *MergeSection) void { + pub fn updateSize(msec: *Section) void { // TODO a 'stale' flag would be better here perhaps? msec.size = 0; msec.alignment = .@"1"; @@ -111,7 +111,7 @@ pub const MergeSection = struct { } } - pub fn initOutputSection(msec: *MergeSection, elf_file: *Elf) !void { + pub fn initOutputSection(msec: *Section, elf_file: *Elf) !void { msec.output_section_index = elf_file.sectionByName(msec.name(elf_file)) orelse try elf_file.addSection(.{ .name = msec.name_offset, .type = msec.type, @@ -119,14 +119,14 @@ pub const MergeSection = struct { }); } - pub fn addMergeSubsection(msec: *MergeSection, allocator: Allocator) !MergeSubsection.Index { - const index: MergeSubsection.Index = @intCast(msec.subsections.items.len); + pub fn addMergeSubsection(msec: *Section, allocator: Allocator) !Subsection.Index { + const index: Subsection.Index = @intCast(msec.subsections.items.len); const msub = try msec.subsections.addOne(allocator); msub.* = .{}; return index; } - pub fn mergeSubsection(msec: *MergeSection, index: MergeSubsection.Index) *MergeSubsection { + pub fn mergeSubsection(msec: *Section, index: Subsection.Index) *Subsection { assert(index < msec.subsections.items.len); return &msec.subsections.items[index]; } @@ -158,7 +158,7 @@ pub const MergeSection = struct { }; pub fn format( - msec: MergeSection, + msec: Section, comptime unused_fmt_string: []const u8, options: std.fmt.FormatOptions, writer: anytype, @@ -167,10 +167,10 @@ pub const MergeSection = struct { _ = unused_fmt_string; _ = options; _ = writer; - @compileError("do not format MergeSection directly"); + @compileError("do not format directly"); } - pub fn fmt(msec: MergeSection, elf_file: *Elf) std.fmt.Formatter(format2) { + pub fn fmt(msec: Section, elf_file: *Elf) std.fmt.Formatter(format2) { return .{ .data = .{ .msec = msec, .elf_file = elf_file, @@ -178,7 +178,7 @@ pub const MergeSection = struct { } const FormatContext = struct { - msec: MergeSection, + msec: Section, elf_file: *Elf, }; @@ -209,30 +209,30 @@ pub const MergeSection = struct { pub const Index = u32; }; -pub const MergeSubsection = struct { +pub const Subsection = struct { value: i64 = 0, - merge_section_index: MergeSection.Index = 0, + merge_section_index: Section.Index = 0, string_index: u32 = 0, size: u32 = 0, alignment: Atom.Alignment = .@"1", entsize: u32 = 0, alive: bool = false, - pub fn address(msub: MergeSubsection, elf_file: *Elf) i64 { + pub fn address(msub: Subsection, elf_file: *Elf) i64 { return msub.mergeSection(elf_file).address(elf_file) + msub.value; } - pub fn mergeSection(msub: MergeSubsection, elf_file: *Elf) *MergeSection { + pub fn mergeSection(msub: Subsection, elf_file: *Elf) *Section { return elf_file.mergeSection(msub.merge_section_index); } - pub fn getString(msub: MergeSubsection, elf_file: *Elf) []const u8 { + pub fn getString(msub: Subsection, elf_file: *Elf) []const u8 { const msec = msub.mergeSection(elf_file); return msec.bytes.items[msub.string_index..][0..msub.size]; } pub fn format( - msub: MergeSubsection, + msub: Subsection, comptime unused_fmt_string: []const u8, options: std.fmt.FormatOptions, writer: anytype, @@ -241,10 +241,10 @@ pub const MergeSubsection = struct { _ = unused_fmt_string; _ = options; _ = writer; - @compileError("do not format MergeSubsection directly"); + @compileError("do not format directly"); } - pub fn fmt(msub: MergeSubsection, elf_file: *Elf) std.fmt.Formatter(format2) { + pub fn fmt(msub: Subsection, elf_file: *Elf) std.fmt.Formatter(format2) { return .{ .data = .{ .msub = msub, .elf_file = elf_file, @@ -252,7 +252,7 @@ pub const MergeSubsection = struct { } const FormatContext = struct { - msub: MergeSubsection, + msub: Subsection, elf_file: *Elf, }; @@ -277,32 +277,32 @@ pub const MergeSubsection = struct { pub const Index = u32; }; -pub const InputMergeSection = struct { - merge_section_index: MergeSection.Index = 0, +pub const InputSection = struct { + merge_section_index: Section.Index = 0, atom_index: Atom.Index = 0, offsets: std.ArrayListUnmanaged(u32) = .empty, - subsections: std.ArrayListUnmanaged(MergeSubsection.Index) = .empty, + subsections: std.ArrayListUnmanaged(Subsection.Index) = .empty, bytes: std.ArrayListUnmanaged(u8) = .empty, strings: std.ArrayListUnmanaged(String) = .empty, - pub fn deinit(imsec: *InputMergeSection, allocator: Allocator) void { + pub fn deinit(imsec: *InputSection, allocator: Allocator) void { imsec.offsets.deinit(allocator); imsec.subsections.deinit(allocator); imsec.bytes.deinit(allocator); imsec.strings.deinit(allocator); } - pub fn clearAndFree(imsec: *InputMergeSection, allocator: Allocator) void { + pub fn clearAndFree(imsec: *InputSection, allocator: Allocator) void { imsec.bytes.clearAndFree(allocator); // TODO: imsec.strings.clearAndFree(allocator); } const FindSubsectionResult = struct { - msub_index: MergeSubsection.Index, + msub_index: Subsection.Index, offset: u32, }; - pub fn findSubsection(imsec: InputMergeSection, offset: u32) ?FindSubsectionResult { + pub fn findSubsection(imsec: InputSection, offset: u32) ?FindSubsectionResult { // TODO: binary search for (imsec.offsets.items, 0..) |off, index| { if (offset < off) return .{ @@ -320,7 +320,7 @@ pub const InputMergeSection = struct { return null; } - pub fn insert(imsec: *InputMergeSection, allocator: Allocator, string: []const u8) !void { + pub fn insert(imsec: *InputSection, allocator: Allocator, string: []const u8) !void { const index: u32 = @intCast(imsec.bytes.items.len); try imsec.bytes.appendSlice(allocator, string); try imsec.strings.append(allocator, .{ .pos = index, .len = @intCast(string.len) }); @@ -338,3 +338,4 @@ const std = @import("std"); const Allocator = mem.Allocator; const Atom = @import("Atom.zig"); const Elf = @import("../Elf.zig"); +const Merge = @This(); diff --git a/src/link/Elf/Object.zig b/src/link/Elf/Object.zig index 03172efb386a9bca16ba649807c35405b8f79ba5..d1f1870036d5c16752f39b590df4eb966d73e986 100644 --- a/src/link/Elf/Object.zig +++ b/src/link/Elf/Object.zig @@ -23,8 +23,8 @@ atoms_extra: std.ArrayListUnmanaged(u32) = .empty, comdat_groups: std.ArrayListUnmanaged(Elf.ComdatGroup) = .empty, comdat_group_data: std.ArrayListUnmanaged(u32) = .empty, -input_merge_sections: std.ArrayListUnmanaged(InputMergeSection) = .empty, -input_merge_sections_indexes: std.ArrayListUnmanaged(InputMergeSection.Index) = .empty, +input_merge_sections: std.ArrayListUnmanaged(Merge.InputSection) = .empty, +input_merge_sections_indexes: std.ArrayListUnmanaged(Merge.InputSection.Index) = .empty, fdes: std.ArrayListUnmanaged(Fde) = .empty, cies: std.ArrayListUnmanaged(Cie) = .empty, @@ -1305,14 +1305,14 @@ fn setAtomFields(o: *Object, atom_ptr: *Atom, opts: Atom.Extra.AsOptionals) void o.setAtomExtra(atom_ptr.extra_index, extras); } -fn addInputMergeSection(self: *Object, allocator: Allocator) !InputMergeSection.Index { - const index: InputMergeSection.Index = @intCast(self.input_merge_sections.items.len); +fn addInputMergeSection(self: *Object, allocator: Allocator) !Merge.InputSection.Index { + const index: Merge.InputSection.Index = @intCast(self.input_merge_sections.items.len); const msec = try self.input_merge_sections.addOne(allocator); msec.* = .{}; return index; } -fn inputMergeSection(self: *Object, index: InputMergeSection.Index) ?*InputMergeSection { +fn inputMergeSection(self: *Object, index: Merge.InputSection.Index) ?*Merge.InputSection { if (index == 0) return null; return &self.input_merge_sections.items[index]; } @@ -1522,6 +1522,6 @@ const Cie = eh_frame.Cie; const Elf = @import("../Elf.zig"); const Fde = eh_frame.Fde; const File = @import("file.zig").File; -const InputMergeSection = @import("merge_section.zig").InputMergeSection; +const Merge = @import("Merge.zig"); const Symbol = @import("Symbol.zig"); const Alignment = Atom.Alignment; diff --git a/src/link/Elf/Symbol.zig b/src/link/Elf/Symbol.zig index 6fc82474e24fd03423007d0e3078df53a7cae86c..c01fa1988499b25a5b9171a6276e72e9152fd037 100644 --- a/src/link/Elf/Symbol.zig +++ b/src/link/Elf/Symbol.zig @@ -74,7 +74,7 @@ pub fn atom(symbol: Symbol, elf_file: *Elf) ?*Atom { return file_ptr.atom(symbol.ref.index); } -pub fn mergeSubsection(symbol: Symbol, elf_file: *Elf) ?*MergeSubsection { +pub fn mergeSubsection(symbol: Symbol, elf_file: *Elf) ?*Merge.Subsection { if (!symbol.flags.merge_subsection) return null; const msec = elf_file.mergeSection(symbol.ref.file); return msec.mergeSubsection(symbol.ref.index); @@ -493,7 +493,7 @@ const File = @import("file.zig").File; const GotSection = synthetic_sections.GotSection; const GotPltSection = synthetic_sections.GotPltSection; const LinkerDefined = @import("LinkerDefined.zig"); -const MergeSubsection = @import("merge_section.zig").MergeSubsection; +const Merge = @import("Merge.zig"); const Object = @import("Object.zig"); const PltSection = synthetic_sections.PltSection; const PltGotSection = synthetic_sections.PltGotSection; -- 2.54.0 From 05157e820a9fcc3a2a63c785c13c1bbde155c868 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 10 Oct 2024 20:34:17 -0700 Subject: [PATCH 6/7] link.Elf.sortShdrs: tease out data dependencies In order to reduce the logic that happens in flush() we need to see which data is being accessed by all this logic, so we can see which operations depend on each other. --- src/link/Elf.zig | 151 ++++++++++++++++++++++------------- src/link/Elf/relocatable.zig | 22 ++++- 2 files changed, 114 insertions(+), 59 deletions(-) diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 24a99e567759b33eef48458967e6e159b5c41df4..535008e87399cb05f2fb75e315e3bbd2f6c05876 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -992,7 +992,16 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod // Generate and emit synthetic sections. try self.initSyntheticSections(); try self.initSpecialPhdrs(); - try self.sortShdrs(); + try sortShdrs( + gpa, + &self.section_indexes, + &self.sections, + self.shstrtab.items, + self.merge_sections.items, + self.comdat_group_sections.items, + self.zigObjectPtr(), + self.files, + ); try self.setDynamicSection(self.rpath_table.keys()); self.sortDynamicSymtab(); @@ -3354,9 +3363,8 @@ fn sortPhdrs( } } -fn shdrRank(self: *Elf, shndx: u32) u8 { - const shdr = self.sections.items(.shdr)[shndx]; - const name = self.getShString(shdr.sh_name); +fn shdrRank(shdr: elf.Elf64_Shdr, shstrtab: []const u8) u8 { + const name = shString(shstrtab, shdr.sh_name); const flags = shdr.sh_flags; switch (shdr.sh_type) { @@ -3405,120 +3413,138 @@ fn shdrRank(self: *Elf, shndx: u32) u8 { } } -pub fn sortShdrs(self: *Elf) !void { +pub fn sortShdrs( + gpa: Allocator, + section_indexes: *SectionIndexes, + sections: *std.MultiArrayList(Section), + shstrtab: []const u8, + merge_sections: []Merge.Section, + comdat_group_sections: []ComdatGroupSection, + zig_object_ptr: ?*ZigObject, + files: std.MultiArrayList(File.Entry), +) !void { const Entry = struct { shndx: u32, - pub fn lessThan(elf_file: *Elf, lhs: @This(), rhs: @This()) bool { - return elf_file.shdrRank(lhs.shndx) < elf_file.shdrRank(rhs.shndx); + const Context = struct { + shdrs: []const elf.Elf64_Shdr, + shstrtab: []const u8, + }; + + pub fn lessThan(ctx: Context, lhs: @This(), rhs: @This()) bool { + return shdrRank(ctx.shdrs[lhs.shndx], ctx.shstrtab) < + shdrRank(ctx.shdrs[rhs.shndx], ctx.shstrtab); } }; - const gpa = self.base.comp.gpa; - var entries = try std.ArrayList(Entry).initCapacity(gpa, self.sections.items(.shdr).len); - defer entries.deinit(); - for (0..self.sections.items(.shdr).len) |shndx| { - entries.appendAssumeCapacity(.{ .shndx = @intCast(shndx) }); + const shdrs = sections.items(.shdr); + + const entries = try gpa.alloc(Entry, shdrs.len); + defer gpa.free(entries); + for (entries, 0..shdrs.len) |*entry, shndx| { + entry.* = .{ .shndx = @intCast(shndx) }; } - mem.sort(Entry, entries.items, self, Entry.lessThan); + const sort_context: Entry.Context = .{ + .shdrs = shdrs, + .shstrtab = shstrtab, + }; + mem.sort(Entry, entries, sort_context, Entry.lessThan); - const backlinks = try gpa.alloc(u32, entries.items.len); + const backlinks = try gpa.alloc(u32, entries.len); defer gpa.free(backlinks); { - var slice = self.sections.toOwnedSlice(); + var slice = sections.toOwnedSlice(); defer slice.deinit(gpa); - try self.sections.resize(gpa, slice.len); + try sections.resize(gpa, slice.len); - for (entries.items, 0..) |entry, i| { + for (entries, 0..) |entry, i| { backlinks[entry.shndx] = @intCast(i); - self.sections.set(i, slice.get(entry.shndx)); + sections.set(i, slice.get(entry.shndx)); } } - const special_indexes = &self.section_indexes; - inline for (@typeInfo(SectionIndexes).@"struct".fields) |field| { - if (@field(special_indexes, field.name)) |special_index| { - @field(special_indexes, field.name) = backlinks[special_index]; + if (@field(section_indexes, field.name)) |special_index| { + @field(section_indexes, field.name) = backlinks[special_index]; } } - for (self.merge_sections.items) |*msec| { + for (merge_sections) |*msec| { msec.output_section_index = backlinks[msec.output_section_index]; } - const slice = self.sections.slice(); + const slice = sections.slice(); for (slice.items(.shdr), slice.items(.atom_list_2)) |*shdr, *atom_list| { atom_list.output_section_index = backlinks[atom_list.output_section_index]; for (atom_list.atoms.keys()) |ref| { - self.atom(ref).?.output_section_index = atom_list.output_section_index; + fileLookup(files, ref.file).?.atom(ref.index).?.output_section_index = atom_list.output_section_index; } if (shdr.sh_type == elf.SHT_RELA) { // FIXME:JK we should spin up .symtab potentially earlier, or set all non-dynamic RELA sections // to point at symtab // shdr.sh_link = backlinks[shdr.sh_link]; - shdr.sh_link = self.section_indexes.symtab.?; + shdr.sh_link = section_indexes.symtab.?; shdr.sh_info = backlinks[shdr.sh_info]; } } - if (self.zigObjectPtr()) |zo| zo.resetShdrIndexes(backlinks); + if (zig_object_ptr) |zo| zo.resetShdrIndexes(backlinks); - for (self.comdat_group_sections.items) |*cg| { + for (comdat_group_sections) |*cg| { cg.shndx = backlinks[cg.shndx]; } - if (self.section_indexes.symtab) |index| { + if (section_indexes.symtab) |index| { const shdr = &slice.items(.shdr)[index]; - shdr.sh_link = self.section_indexes.strtab.?; + shdr.sh_link = section_indexes.strtab.?; } - if (self.section_indexes.dynamic) |index| { + if (section_indexes.dynamic) |index| { const shdr = &slice.items(.shdr)[index]; - shdr.sh_link = self.section_indexes.dynstrtab.?; + shdr.sh_link = section_indexes.dynstrtab.?; } - if (self.section_indexes.dynsymtab) |index| { + if (section_indexes.dynsymtab) |index| { const shdr = &slice.items(.shdr)[index]; - shdr.sh_link = self.section_indexes.dynstrtab.?; + shdr.sh_link = section_indexes.dynstrtab.?; } - if (self.section_indexes.hash) |index| { + if (section_indexes.hash) |index| { const shdr = &slice.items(.shdr)[index]; - shdr.sh_link = self.section_indexes.dynsymtab.?; + shdr.sh_link = section_indexes.dynsymtab.?; } - if (self.section_indexes.gnu_hash) |index| { + if (section_indexes.gnu_hash) |index| { const shdr = &slice.items(.shdr)[index]; - shdr.sh_link = self.section_indexes.dynsymtab.?; + shdr.sh_link = section_indexes.dynsymtab.?; } - if (self.section_indexes.versym) |index| { + if (section_indexes.versym) |index| { const shdr = &slice.items(.shdr)[index]; - shdr.sh_link = self.section_indexes.dynsymtab.?; + shdr.sh_link = section_indexes.dynsymtab.?; } - if (self.section_indexes.verneed) |index| { + if (section_indexes.verneed) |index| { const shdr = &slice.items(.shdr)[index]; - shdr.sh_link = self.section_indexes.dynstrtab.?; + shdr.sh_link = section_indexes.dynstrtab.?; } - if (self.section_indexes.rela_dyn) |index| { + if (section_indexes.rela_dyn) |index| { const shdr = &slice.items(.shdr)[index]; - shdr.sh_link = self.section_indexes.dynsymtab orelse 0; + shdr.sh_link = section_indexes.dynsymtab orelse 0; } - if (self.section_indexes.rela_plt) |index| { + if (section_indexes.rela_plt) |index| { const shdr = &slice.items(.shdr)[index]; - shdr.sh_link = self.section_indexes.dynsymtab.?; - shdr.sh_info = self.section_indexes.plt.?; + shdr.sh_link = section_indexes.dynsymtab.?; + shdr.sh_info = section_indexes.plt.?; } - if (self.section_indexes.eh_frame_rela) |index| { + if (section_indexes.eh_frame_rela) |index| { const shdr = &slice.items(.shdr)[index]; - shdr.sh_link = self.section_indexes.symtab.?; - shdr.sh_info = self.section_indexes.eh_frame.?; + shdr.sh_link = section_indexes.symtab.?; + shdr.sh_info = section_indexes.eh_frame.?; } } @@ -4677,13 +4703,17 @@ pub fn thunk(self: *Elf, index: Thunk.Index) *Thunk { } pub fn file(self: *Elf, index: File.Index) ?File { - const tag = self.files.items(.tags)[index]; + return fileLookup(self.files, index); +} + +fn fileLookup(files: std.MultiArrayList(File.Entry), index: File.Index) ?File { + const tag = files.items(.tags)[index]; return switch (tag) { .null => null, - .linker_defined => .{ .linker_defined = &self.files.items(.data)[index].linker_defined }, - .zig_object => .{ .zig_object = &self.files.items(.data)[index].zig_object }, - .object => .{ .object = &self.files.items(.data)[index].object }, - .shared_object => .{ .shared_object = &self.files.items(.data)[index].shared_object }, + .linker_defined => .{ .linker_defined = &files.items(.data)[index].linker_defined }, + .zig_object => .{ .zig_object = &files.items(.data)[index].zig_object }, + .object => .{ .object = &files.items(.data)[index].object }, + .shared_object => .{ .shared_object = &files.items(.data)[index].shared_object }, }; } @@ -4790,8 +4820,15 @@ pub fn tlsAddress(self: *Elf) i64 { } pub fn getShString(self: Elf, off: u32) [:0]const u8 { - assert(off < self.shstrtab.items.len); - return mem.sliceTo(@as([*:0]const u8, @ptrCast(self.shstrtab.items.ptr + off)), 0); + return shString(self.shstrtab.items, off); +} + +fn shString( + shstrtab: []const u8, + off: u32, +) [:0]const u8 { + const slice = shstrtab[off..]; + return slice[0..std.mem.indexOfScalar(u8, slice, 0).? :0]; } pub fn insertShString(self: *Elf, name: [:0]const u8) error{OutOfMemory}!u32 { diff --git a/src/link/Elf/relocatable.zig b/src/link/Elf/relocatable.zig index 73fcf6a44a77cfcb6a6fb8eab84f9ee1bba583fb..944a6e0e467c27fc15e17e0b2ea9b04d79b355cc 100644 --- a/src/link/Elf/relocatable.zig +++ b/src/link/Elf/relocatable.zig @@ -32,7 +32,16 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation, module_obj_path: ?Path zig_object.claimUnresolvedRelocatable(elf_file); try initSections(elf_file); - try elf_file.sortShdrs(); + try Elf.sortShdrs( + gpa, + &elf_file.section_indexes, + &elf_file.sections, + elf_file.shstrtab.items, + elf_file.merge_sections.items, + elf_file.comdat_group_sections.items, + elf_file.zigObjectPtr(), + elf_file.files, + ); try zig_object.addAtomsToRelaSections(elf_file); try elf_file.updateMergeSectionSizes(); try updateSectionSizes(elf_file); @@ -171,7 +180,16 @@ pub fn flushObject(elf_file: *Elf, comp: *Compilation, module_obj_path: ?Path) l claimUnresolved(elf_file); try initSections(elf_file); - try elf_file.sortShdrs(); + try Elf.sortShdrs( + comp.gpa, + &elf_file.section_indexes, + &elf_file.sections, + elf_file.shstrtab.items, + elf_file.merge_sections.items, + elf_file.comdat_group_sections.items, + elf_file.zigObjectPtr(), + elf_file.files, + ); if (elf_file.zigObjectPtr()) |zig_object| { try zig_object.addAtomsToRelaSections(elf_file); } -- 2.54.0 From 38458c6f70322c7eb0ac1434019f1bbdc3c89a57 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 10 Oct 2024 21:02:53 -0700 Subject: [PATCH 7/7] work around C backend bug --- src/link/Elf.zig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 535008e87399cb05f2fb75e315e3bbd2f6c05876..47554d2200564b542624802561f199fc0cba1af4 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -3337,7 +3337,8 @@ fn sortPhdrs( entry.* = .{ .phndx = @intCast(phndx) }; } - mem.sort(Entry, entries, phdrs.items, Entry.lessThan); + // The `@as` here works around a bug in the C backend. + mem.sort(Entry, entries, @as([]const elf.Elf64_Phdr, phdrs.items), Entry.lessThan); const backlinks = try gpa.alloc(u16, entries.len); defer gpa.free(backlinks); -- 2.54.0