authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-10-11 10:34:17-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-10-11 10:34:17-07:00
log5e53203e82bdeb0273160db156050164c5c69267
tree9a4d6065238993c49299e16fbdbab420822cc35b
parent41dbd0d0da0989495a97e99fb9269a49ac302768
parent38458c6f70322c7eb0ac1434019f1bbdc3c89a57
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #21666 from ziglang/reduce-flush

link.Elf: fix phdr_gnu_stack_index not included in sortPhdrs

12 files changed, 818 insertions(+), 749 deletions(-)

CMakeLists.txt+2-2
......@@ -603,18 +603,18 @@ set(ZIG_STAGE2_SOURCES
603603 src/link/Elf/AtomList.zig
604604 src/link/Elf/LdScript.zig
605605 src/link/Elf/LinkerDefined.zig
606 src/link/Elf/Merge.zig
606607 src/link/Elf/Object.zig
607608 src/link/Elf/SharedObject.zig
608609 src/link/Elf/Symbol.zig
610 src/link/Elf/Thunk.zig
609611 src/link/Elf/ZigObject.zig
610612 src/link/Elf/eh_frame.zig
611613 src/link/Elf/file.zig
612614 src/link/Elf/gc.zig
613 src/link/Elf/merge_section.zig
614615 src/link/Elf/relocatable.zig
615616 src/link/Elf/relocation.zig
616617 src/link/Elf/synthetic_sections.zig
617 src/link/Elf/Thunk.zig
618618 src/link/MachO.zig
619619 src/link/MachO/Archive.zig
620620 src/link/MachO/Atom.zig
lib/std/multi_array_list.zig+7-1
......@@ -23,6 +23,12 @@ pub fn MultiArrayList(comptime T: type) type {
2323 len: usize = 0,
2424 capacity: usize = 0,
2525
26 pub const empty: Self = .{
27 .bytes = undefined,
28 .len = 0,
29 .capacity = 0,
30 };
31
2632 const Elem = switch (@typeInfo(T)) {
2733 .@"struct" => T,
2834 .@"union" => |u| struct {
......@@ -474,7 +480,7 @@ pub fn MultiArrayList(comptime T: type) type {
474480 pub fn swap(sc: @This(), a_index: usize, b_index: usize) void {
475481 inline for (fields, 0..) |field_info, i| {
476482 if (@sizeOf(field_info.type) != 0) {
477 const field = @as(Field, @enumFromInt(i));
483 const field: Field = @enumFromInt(i);
478484 const ptr = sc.slice.items(field);
479485 mem.swap(field_info.type, &ptr[a_index], &ptr[b_index]);
480486 }
src/link/Elf.zig+377-333
......@@ -1,3 +1,5 @@
1pub const Atom = @import("Elf/Atom.zig");
2
13base: link.File,
24rpath_table: std.StringArrayHashMapUnmanaged(void),
35image_base: u64,
......@@ -53,26 +55,11 @@ shdr_table_offset: ?u64 = null,
5355
5456/// Stored in native-endian format, depending on target endianness needs to be bswapped on read/write.
5557/// Same order as in the file.
56phdrs: std.ArrayListUnmanaged(elf.Elf64_Phdr) = .empty,
57
58/// Special program headers
59/// PT_PHDR
60phdr_table_index: ?u16 = null,
61/// PT_LOAD for PHDR table
62/// We add this special load segment to ensure the EHDR and PHDR table are always
63/// loaded into memory.
64phdr_table_load_index: ?u16 = null,
65/// PT_INTERP
66phdr_interp_index: ?u16 = null,
67/// PT_DYNAMIC
68phdr_dynamic_index: ?u16 = null,
69/// PT_GNU_EH_FRAME
70phdr_gnu_eh_frame_index: ?u16 = null,
71/// PT_GNU_STACK
72phdr_gnu_stack_index: ?u16 = null,
73/// PT_TLS
74/// TODO I think ELF permits multiple TLS segments but for now, assume one per file.
75phdr_tls_index: ?u16 = null,
58phdrs: ProgramHeaderList = .empty,
59
60/// Special program headers.
61phdr_indexes: ProgramHeaderIndexes = .{},
62section_indexes: SectionIndexes = .{},
7663
7764page_size: u32,
7865default_sym_version: elf.Elf64_Versym,
......@@ -115,29 +102,6 @@ rela_plt: std.ArrayListUnmanaged(elf.Elf64_Rela) = .empty,
115102/// Applies only to a relocatable.
116103comdat_group_sections: std.ArrayListUnmanaged(ComdatGroupSection) = .empty,
117104
118copy_rel_section_index: ?u32 = null,
119dynamic_section_index: ?u32 = null,
120dynstrtab_section_index: ?u32 = null,
121dynsymtab_section_index: ?u32 = null,
122eh_frame_section_index: ?u32 = null,
123eh_frame_rela_section_index: ?u32 = null,
124eh_frame_hdr_section_index: ?u32 = null,
125hash_section_index: ?u32 = null,
126gnu_hash_section_index: ?u32 = null,
127got_section_index: ?u32 = null,
128got_plt_section_index: ?u32 = null,
129interp_section_index: ?u32 = null,
130plt_section_index: ?u32 = null,
131plt_got_section_index: ?u32 = null,
132rela_dyn_section_index: ?u32 = null,
133rela_plt_section_index: ?u32 = null,
134versym_section_index: ?u32 = null,
135verneed_section_index: ?u32 = null,
136
137shstrtab_section_index: ?u32 = null,
138strtab_section_index: ?u32 = null,
139symtab_section_index: ?u32 = null,
140
141105resolver: SymbolResolver = .{},
142106
143107has_text_reloc: bool = false,
......@@ -147,11 +111,87 @@ num_ifunc_dynrelocs: usize = 0,
147111thunks: std.ArrayListUnmanaged(Thunk) = .empty,
148112
149113/// List of output merge sections with deduped contents.
150merge_sections: std.ArrayListUnmanaged(MergeSection) = .empty,
151comment_merge_section_index: ?MergeSection.Index = null,
114merge_sections: std.ArrayListUnmanaged(Merge.Section) = .empty,
115comment_merge_section_index: ?Merge.Section.Index = null,
152116
153117first_eflags: ?elf.Elf64_Word = null,
154118
119const SectionIndexes = struct {
120 copy_rel: ?u32 = null,
121 dynamic: ?u32 = null,
122 dynstrtab: ?u32 = null,
123 dynsymtab: ?u32 = null,
124 eh_frame: ?u32 = null,
125 eh_frame_rela: ?u32 = null,
126 eh_frame_hdr: ?u32 = null,
127 hash: ?u32 = null,
128 gnu_hash: ?u32 = null,
129 got: ?u32 = null,
130 got_plt: ?u32 = null,
131 interp: ?u32 = null,
132 plt: ?u32 = null,
133 plt_got: ?u32 = null,
134 rela_dyn: ?u32 = null,
135 rela_plt: ?u32 = null,
136 versym: ?u32 = null,
137 verneed: ?u32 = null,
138
139 shstrtab: ?u32 = null,
140 strtab: ?u32 = null,
141 symtab: ?u32 = null,
142};
143
144const ProgramHeaderList = std.ArrayListUnmanaged(elf.Elf64_Phdr);
145
146const OptionalProgramHeaderIndex = enum(u16) {
147 none = std.math.maxInt(u16),
148 _,
149
150 fn unwrap(i: OptionalProgramHeaderIndex) ?ProgramHeaderIndex {
151 if (i == .none) return null;
152 return @enumFromInt(@intFromEnum(i));
153 }
154
155 fn int(i: OptionalProgramHeaderIndex) ?u16 {
156 if (i == .none) return null;
157 return @intFromEnum(i);
158 }
159};
160
161const ProgramHeaderIndex = enum(u16) {
162 _,
163
164 fn toOptional(i: ProgramHeaderIndex) OptionalProgramHeaderIndex {
165 const result: OptionalProgramHeaderIndex = @enumFromInt(@intFromEnum(i));
166 assert(result != .none);
167 return result;
168 }
169
170 fn int(i: ProgramHeaderIndex) u16 {
171 return @intFromEnum(i);
172 }
173};
174
175const ProgramHeaderIndexes = struct {
176 /// PT_PHDR
177 table: OptionalProgramHeaderIndex = .none,
178 /// PT_LOAD for PHDR table
179 /// We add this special load segment to ensure the EHDR and PHDR table are always
180 /// loaded into memory.
181 table_load: OptionalProgramHeaderIndex = .none,
182 /// PT_INTERP
183 interp: OptionalProgramHeaderIndex = .none,
184 /// PT_DYNAMIC
185 dynamic: OptionalProgramHeaderIndex = .none,
186 /// PT_GNU_EH_FRAME
187 gnu_eh_frame: OptionalProgramHeaderIndex = .none,
188 /// PT_GNU_STACK
189 gnu_stack: OptionalProgramHeaderIndex = .none,
190 /// PT_TLS
191 /// TODO I think ELF permits multiple TLS segments but for now, assume one per file.
192 tls: OptionalProgramHeaderIndex = .none,
193};
194
155195/// When allocating, the ideal_capacity is calculated by
156196/// actual_capacity + (actual_capacity / ideal_factor)
157197const ideal_factor = 3;
......@@ -358,7 +398,7 @@ pub fn createEmpty(
358398 };
359399 const max_nphdrs = comptime getMaxNumberOfPhdrs();
360400 const reserved: u64 = mem.alignForward(u64, padToIdeal(max_nphdrs * phsize), self.page_size);
361 self.phdr_table_index = try self.addPhdr(.{
401 self.phdr_indexes.table = (try self.addPhdr(.{
362402 .type = elf.PT_PHDR,
363403 .flags = elf.PF_R,
364404 .@"align" = p_align,
......@@ -366,8 +406,8 @@ pub fn createEmpty(
366406 .offset = ehsize,
367407 .filesz = reserved,
368408 .memsz = reserved,
369 });
370 self.phdr_table_load_index = try self.addPhdr(.{
409 })).toOptional();
410 self.phdr_indexes.table_load = (try self.addPhdr(.{
371411 .type = elf.PT_LOAD,
372412 .flags = elf.PF_R,
373413 .@"align" = self.page_size,
......@@ -375,7 +415,7 @@ pub fn createEmpty(
375415 .offset = 0,
376416 .filesz = reserved + ehsize,
377417 .memsz = reserved + ehsize,
378 });
418 })).toOptional();
379419 }
380420
381421 if (opt_zcu) |zcu| {
......@@ -952,7 +992,16 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod
952992 // Generate and emit synthetic sections.
953993 try self.initSyntheticSections();
954994 try self.initSpecialPhdrs();
955 try self.sortShdrs();
995 try sortShdrs(
996 gpa,
997 &self.section_indexes,
998 &self.sections,
999 self.shstrtab.items,
1000 self.merge_sections.items,
1001 self.comdat_group_sections.items,
1002 self.zigObjectPtr(),
1003 self.files,
1004 );
9561005
9571006 try self.setDynamicSection(self.rpath_table.keys());
9581007 self.sortDynamicSymtab();
......@@ -966,7 +1015,7 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod
9661015 try self.addLoadPhdrs();
9671016 try self.allocatePhdrTable();
9681017 try self.allocateAllocSections();
969 try self.sortPhdrs();
1018 try sortPhdrs(gpa, &self.phdrs, &self.phdr_indexes, self.sections.items(.phndx));
9701019 try self.allocateNonAllocSections();
9711020 self.allocateSpecialPhdrs();
9721021 if (self.linkerDefinedPtr()) |obj| {
......@@ -2461,7 +2510,7 @@ fn writePhdrTable(self: *Elf) !void {
24612510 const gpa = self.base.comp.gpa;
24622511 const target_endian = self.getTarget().cpu.arch.endian();
24632512 const foreign_endian = target_endian != builtin.cpu.arch.endian();
2464 const phdr_table = &self.phdrs.items[self.phdr_table_index.?];
2513 const phdr_table = &self.phdrs.items[self.phdr_indexes.table.int().?];
24652514
24662515 log.debug("writing program headers from 0x{x} to 0x{x}", .{
24672516 phdr_table.p_offset,
......@@ -2573,18 +2622,18 @@ pub fn writeElfHeader(self: *Elf) !void {
25732622 const entry_sym = obj.entrySymbol(self) orelse break :blk 0;
25742623 break :blk @intCast(entry_sym.address(.{}, self));
25752624 } else 0;
2576 const phdr_table_offset = if (self.phdr_table_index) |phndx| self.phdrs.items[phndx].p_offset else 0;
2625 const phdr_table_offset = if (self.phdr_indexes.table.int()) |phndx| self.phdrs.items[phndx].p_offset else 0;
25772626 switch (self.ptr_width) {
25782627 .p32 => {
2579 mem.writeInt(u32, hdr_buf[index..][0..4], @as(u32, @intCast(e_entry)), endian);
2628 mem.writeInt(u32, hdr_buf[index..][0..4], @intCast(e_entry), endian);
25802629 index += 4;
25812630
25822631 // e_phoff
2583 mem.writeInt(u32, hdr_buf[index..][0..4], @as(u32, @intCast(phdr_table_offset)), endian);
2632 mem.writeInt(u32, hdr_buf[index..][0..4], @intCast(phdr_table_offset), endian);
25842633 index += 4;
25852634
25862635 // e_shoff
2587 mem.writeInt(u32, hdr_buf[index..][0..4], @as(u32, @intCast(self.shdr_table_offset.?)), endian);
2636 mem.writeInt(u32, hdr_buf[index..][0..4], @intCast(self.shdr_table_offset.?), endian);
25882637 index += 4;
25892638 },
25902639 .p64 => {
......@@ -2631,11 +2680,11 @@ pub fn writeElfHeader(self: *Elf) !void {
26312680 mem.writeInt(u16, hdr_buf[index..][0..2], e_shentsize, endian);
26322681 index += 2;
26332682
2634 const e_shnum = @as(u16, @intCast(self.sections.items(.shdr).len));
2683 const e_shnum: u16 = @intCast(self.sections.items(.shdr).len);
26352684 mem.writeInt(u16, hdr_buf[index..][0..2], e_shnum, endian);
26362685 index += 2;
26372686
2638 mem.writeInt(u16, hdr_buf[index..][0..2], @intCast(self.shstrtab_section_index.?), endian);
2687 mem.writeInt(u16, hdr_buf[index..][0..2], @intCast(self.section_indexes.shstrtab.?), endian);
26392688 index += 2;
26402689
26412690 assert(index == e_ehsize);
......@@ -2853,8 +2902,8 @@ fn initSyntheticSections(self: *Elf) !void {
28532902 } else false;
28542903 };
28552904 if (needs_eh_frame) {
2856 if (self.eh_frame_section_index == null) {
2857 self.eh_frame_section_index = self.sectionByName(".eh_frame") orelse try self.addSection(.{
2905 if (self.section_indexes.eh_frame == null) {
2906 self.section_indexes.eh_frame = self.sectionByName(".eh_frame") orelse try self.addSection(.{
28582907 .name = try self.insertShString(".eh_frame"),
28592908 .type = if (target.cpu.arch == .x86_64)
28602909 elf.SHT_X86_64_UNWIND
......@@ -2864,8 +2913,8 @@ fn initSyntheticSections(self: *Elf) !void {
28642913 .addralign = ptr_size,
28652914 });
28662915 }
2867 if (comp.link_eh_frame_hdr and self.eh_frame_hdr_section_index == null) {
2868 self.eh_frame_hdr_section_index = try self.addSection(.{
2916 if (comp.link_eh_frame_hdr and self.section_indexes.eh_frame_hdr == null) {
2917 self.section_indexes.eh_frame_hdr = try self.addSection(.{
28692918 .name = try self.insertShString(".eh_frame_hdr"),
28702919 .type = elf.SHT_PROGBITS,
28712920 .flags = elf.SHF_ALLOC,
......@@ -2874,8 +2923,8 @@ fn initSyntheticSections(self: *Elf) !void {
28742923 }
28752924 }
28762925
2877 if (self.got.entries.items.len > 0 and self.got_section_index == null) {
2878 self.got_section_index = try self.addSection(.{
2926 if (self.got.entries.items.len > 0 and self.section_indexes.got == null) {
2927 self.section_indexes.got = try self.addSection(.{
28792928 .name = try self.insertShString(".got"),
28802929 .type = elf.SHT_PROGBITS,
28812930 .flags = elf.SHF_ALLOC | elf.SHF_WRITE,
......@@ -2883,8 +2932,8 @@ fn initSyntheticSections(self: *Elf) !void {
28832932 });
28842933 }
28852934
2886 if (self.got_plt_section_index == null) {
2887 self.got_plt_section_index = try self.addSection(.{
2935 if (self.section_indexes.got_plt == null) {
2936 self.section_indexes.got_plt = try self.addSection(.{
28882937 .name = try self.insertShString(".got.plt"),
28892938 .type = elf.SHT_PROGBITS,
28902939 .flags = elf.SHF_ALLOC | elf.SHF_WRITE,
......@@ -2903,8 +2952,8 @@ fn initSyntheticSections(self: *Elf) !void {
29032952 }
29042953 break :blk false;
29052954 };
2906 if (needs_rela_dyn and self.rela_dyn_section_index == null) {
2907 self.rela_dyn_section_index = try self.addSection(.{
2955 if (needs_rela_dyn and self.section_indexes.rela_dyn == null) {
2956 self.section_indexes.rela_dyn = try self.addSection(.{
29082957 .name = try self.insertShString(".rela.dyn"),
29092958 .type = elf.SHT_RELA,
29102959 .flags = elf.SHF_ALLOC,
......@@ -2914,16 +2963,16 @@ fn initSyntheticSections(self: *Elf) !void {
29142963 }
29152964
29162965 if (self.plt.symbols.items.len > 0) {
2917 if (self.plt_section_index == null) {
2918 self.plt_section_index = try self.addSection(.{
2966 if (self.section_indexes.plt == null) {
2967 self.section_indexes.plt = try self.addSection(.{
29192968 .name = try self.insertShString(".plt"),
29202969 .type = elf.SHT_PROGBITS,
29212970 .flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR,
29222971 .addralign = 16,
29232972 });
29242973 }
2925 if (self.rela_plt_section_index == null) {
2926 self.rela_plt_section_index = try self.addSection(.{
2974 if (self.section_indexes.rela_plt == null) {
2975 self.section_indexes.rela_plt = try self.addSection(.{
29272976 .name = try self.insertShString(".rela.plt"),
29282977 .type = elf.SHT_RELA,
29292978 .flags = elf.SHF_ALLOC,
......@@ -2933,8 +2982,8 @@ fn initSyntheticSections(self: *Elf) !void {
29332982 }
29342983 }
29352984
2936 if (self.plt_got.symbols.items.len > 0 and self.plt_got_section_index == null) {
2937 self.plt_got_section_index = try self.addSection(.{
2985 if (self.plt_got.symbols.items.len > 0 and self.section_indexes.plt_got == null) {
2986 self.section_indexes.plt_got = try self.addSection(.{
29382987 .name = try self.insertShString(".plt.got"),
29392988 .type = elf.SHT_PROGBITS,
29402989 .flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR,
......@@ -2942,8 +2991,8 @@ fn initSyntheticSections(self: *Elf) !void {
29422991 });
29432992 }
29442993
2945 if (self.copy_rel.symbols.items.len > 0 and self.copy_rel_section_index == null) {
2946 self.copy_rel_section_index = try self.addSection(.{
2994 if (self.copy_rel.symbols.items.len > 0 and self.section_indexes.copy_rel == null) {
2995 self.section_indexes.copy_rel = try self.addSection(.{
29472996 .name = try self.insertShString(".copyrel"),
29482997 .type = elf.SHT_NOBITS,
29492998 .flags = elf.SHF_ALLOC | elf.SHF_WRITE,
......@@ -2959,8 +3008,8 @@ fn initSyntheticSections(self: *Elf) !void {
29593008 if (self.base.isStatic() and !comp.config.pie) break :blk false;
29603009 break :blk target.dynamic_linker.get() != null;
29613010 };
2962 if (needs_interp and self.interp_section_index == null) {
2963 self.interp_section_index = try self.addSection(.{
3011 if (needs_interp and self.section_indexes.interp == null) {
3012 self.section_indexes.interp = try self.addSection(.{
29643013 .name = try self.insertShString(".interp"),
29653014 .type = elf.SHT_PROGBITS,
29663015 .flags = elf.SHF_ALLOC,
......@@ -2969,8 +3018,8 @@ fn initSyntheticSections(self: *Elf) !void {
29693018 }
29703019
29713020 if (self.isEffectivelyDynLib() or self.shared_objects.items.len > 0 or comp.config.pie) {
2972 if (self.dynstrtab_section_index == null) {
2973 self.dynstrtab_section_index = try self.addSection(.{
3021 if (self.section_indexes.dynstrtab == null) {
3022 self.section_indexes.dynstrtab = try self.addSection(.{
29743023 .name = try self.insertShString(".dynstr"),
29753024 .flags = elf.SHF_ALLOC,
29763025 .type = elf.SHT_STRTAB,
......@@ -2978,8 +3027,8 @@ fn initSyntheticSections(self: *Elf) !void {
29783027 .addralign = 1,
29793028 });
29803029 }
2981 if (self.dynamic_section_index == null) {
2982 self.dynamic_section_index = try self.addSection(.{
3030 if (self.section_indexes.dynamic == null) {
3031 self.section_indexes.dynamic = try self.addSection(.{
29833032 .name = try self.insertShString(".dynamic"),
29843033 .flags = elf.SHF_ALLOC | elf.SHF_WRITE,
29853034 .type = elf.SHT_DYNAMIC,
......@@ -2987,8 +3036,8 @@ fn initSyntheticSections(self: *Elf) !void {
29873036 .addralign = @alignOf(elf.Elf64_Dyn),
29883037 });
29893038 }
2990 if (self.dynsymtab_section_index == null) {
2991 self.dynsymtab_section_index = try self.addSection(.{
3039 if (self.section_indexes.dynsymtab == null) {
3040 self.section_indexes.dynsymtab = try self.addSection(.{
29923041 .name = try self.insertShString(".dynsym"),
29933042 .flags = elf.SHF_ALLOC,
29943043 .type = elf.SHT_DYNSYM,
......@@ -2997,8 +3046,8 @@ fn initSyntheticSections(self: *Elf) !void {
29973046 .info = 1,
29983047 });
29993048 }
3000 if (self.hash_section_index == null) {
3001 self.hash_section_index = try self.addSection(.{
3049 if (self.section_indexes.hash == null) {
3050 self.section_indexes.hash = try self.addSection(.{
30023051 .name = try self.insertShString(".hash"),
30033052 .flags = elf.SHF_ALLOC,
30043053 .type = elf.SHT_HASH,
......@@ -3006,8 +3055,8 @@ fn initSyntheticSections(self: *Elf) !void {
30063055 .entsize = 4,
30073056 });
30083057 }
3009 if (self.gnu_hash_section_index == null) {
3010 self.gnu_hash_section_index = try self.addSection(.{
3058 if (self.section_indexes.gnu_hash == null) {
3059 self.section_indexes.gnu_hash = try self.addSection(.{
30113060 .name = try self.insertShString(".gnu.hash"),
30123061 .flags = elf.SHF_ALLOC,
30133062 .type = elf.SHT_GNU_HASH,
......@@ -3020,8 +3069,8 @@ fn initSyntheticSections(self: *Elf) !void {
30203069 if (sym.flags.import and sym.version_index & elf.VERSYM_VERSION > elf.VER_NDX_GLOBAL) break true;
30213070 } else false;
30223071 if (needs_versions) {
3023 if (self.versym_section_index == null) {
3024 self.versym_section_index = try self.addSection(.{
3072 if (self.section_indexes.versym == null) {
3073 self.section_indexes.versym = try self.addSection(.{
30253074 .name = try self.insertShString(".gnu.version"),
30263075 .flags = elf.SHF_ALLOC,
30273076 .type = elf.SHT_GNU_VERSYM,
......@@ -3029,8 +3078,8 @@ fn initSyntheticSections(self: *Elf) !void {
30293078 .entsize = @sizeOf(elf.Elf64_Versym),
30303079 });
30313080 }
3032 if (self.verneed_section_index == null) {
3033 self.verneed_section_index = try self.addSection(.{
3081 if (self.section_indexes.verneed == null) {
3082 self.section_indexes.verneed = try self.addSection(.{
30343083 .name = try self.insertShString(".gnu.version_r"),
30353084 .flags = elf.SHF_ALLOC,
30363085 .type = elf.SHT_GNU_VERNEED,
......@@ -3049,16 +3098,16 @@ pub fn initSymtab(self: *Elf) !void {
30493098 .p32 => true,
30503099 .p64 => false,
30513100 };
3052 if (self.symtab_section_index == null) {
3053 self.symtab_section_index = try self.addSection(.{
3101 if (self.section_indexes.symtab == null) {
3102 self.section_indexes.symtab = try self.addSection(.{
30543103 .name = try self.insertShString(".symtab"),
30553104 .type = elf.SHT_SYMTAB,
30563105 .addralign = if (small_ptr) @alignOf(elf.Elf32_Sym) else @alignOf(elf.Elf64_Sym),
30573106 .entsize = if (small_ptr) @sizeOf(elf.Elf32_Sym) else @sizeOf(elf.Elf64_Sym),
30583107 });
30593108 }
3060 if (self.strtab_section_index == null) {
3061 self.strtab_section_index = try self.addSection(.{
3109 if (self.section_indexes.strtab == null) {
3110 self.section_indexes.strtab = try self.addSection(.{
30623111 .name = try self.insertShString(".strtab"),
30633112 .type = elf.SHT_STRTAB,
30643113 .entsize = 1,
......@@ -3068,8 +3117,8 @@ pub fn initSymtab(self: *Elf) !void {
30683117}
30693118
30703119pub fn initShStrtab(self: *Elf) !void {
3071 if (self.shstrtab_section_index == null) {
3072 self.shstrtab_section_index = try self.addSection(.{
3120 if (self.section_indexes.shstrtab == null) {
3121 self.section_indexes.shstrtab = try self.addSection(.{
30733122 .name = try self.insertShString(".shstrtab"),
30743123 .type = elf.SHT_STRTAB,
30753124 .entsize = 1,
......@@ -3081,43 +3130,43 @@ pub fn initShStrtab(self: *Elf) !void {
30813130fn initSpecialPhdrs(self: *Elf) !void {
30823131 comptime assert(max_number_of_special_phdrs == 5);
30833132
3084 if (self.interp_section_index != null and self.phdr_interp_index == null) {
3085 self.phdr_interp_index = try self.addPhdr(.{
3133 if (self.section_indexes.interp != null and self.phdr_indexes.interp == .none) {
3134 self.phdr_indexes.interp = (try self.addPhdr(.{
30863135 .type = elf.PT_INTERP,
30873136 .flags = elf.PF_R,
30883137 .@"align" = 1,
3089 });
3138 })).toOptional();
30903139 }
3091 if (self.dynamic_section_index != null and self.phdr_dynamic_index == null) {
3092 self.phdr_dynamic_index = try self.addPhdr(.{
3140 if (self.section_indexes.dynamic != null and self.phdr_indexes.dynamic == .none) {
3141 self.phdr_indexes.dynamic = (try self.addPhdr(.{
30933142 .type = elf.PT_DYNAMIC,
30943143 .flags = elf.PF_R | elf.PF_W,
3095 });
3144 })).toOptional();
30963145 }
3097 if (self.eh_frame_hdr_section_index != null and self.phdr_gnu_eh_frame_index == null) {
3098 self.phdr_gnu_eh_frame_index = try self.addPhdr(.{
3146 if (self.section_indexes.eh_frame_hdr != null and self.phdr_indexes.gnu_eh_frame == .none) {
3147 self.phdr_indexes.gnu_eh_frame = (try self.addPhdr(.{
30993148 .type = elf.PT_GNU_EH_FRAME,
31003149 .flags = elf.PF_R,
3101 });
3150 })).toOptional();
31023151 }
3103 if (self.phdr_gnu_stack_index == null) {
3104 self.phdr_gnu_stack_index = try self.addPhdr(.{
3152 if (self.phdr_indexes.gnu_stack == .none) {
3153 self.phdr_indexes.gnu_stack = (try self.addPhdr(.{
31053154 .type = elf.PT_GNU_STACK,
31063155 .flags = elf.PF_W | elf.PF_R,
31073156 .memsz = self.base.stack_size,
31083157 .@"align" = 1,
3109 });
3158 })).toOptional();
31103159 }
31113160
31123161 const has_tls = for (self.sections.items(.shdr)) |shdr| {
31133162 if (shdr.sh_flags & elf.SHF_TLS != 0) break true;
31143163 } else false;
3115 if (has_tls and self.phdr_tls_index == null) {
3116 self.phdr_tls_index = try self.addPhdr(.{
3164 if (has_tls and self.phdr_indexes.tls == .none) {
3165 self.phdr_indexes.tls = (try self.addPhdr(.{
31173166 .type = elf.PT_TLS,
31183167 .flags = elf.PF_R,
31193168 .@"align" = 1,
3120 });
3169 })).toOptional();
31213170 }
31223171}
31233172
......@@ -3202,7 +3251,7 @@ fn sortInitFini(self: *Elf) !void {
32023251}
32033252
32043253fn setDynamicSection(self: *Elf, rpaths: []const []const u8) !void {
3205 if (self.dynamic_section_index == null) return;
3254 if (self.section_indexes.dynamic == null) return;
32063255
32073256 for (self.shared_objects.items) |index| {
32083257 const shared_object = self.file(index).?.shared_object;
......@@ -3220,13 +3269,13 @@ fn setDynamicSection(self: *Elf, rpaths: []const []const u8) !void {
32203269}
32213270
32223271fn sortDynamicSymtab(self: *Elf) void {
3223 if (self.gnu_hash_section_index == null) return;
3272 if (self.section_indexes.gnu_hash == null) return;
32243273 self.dynsym.sort(self);
32253274}
32263275
32273276fn setVersionSymtab(self: *Elf) !void {
32283277 const gpa = self.base.comp.gpa;
3229 if (self.versym_section_index == null) return;
3278 if (self.section_indexes.versym == null) return;
32303279 try self.versym.resize(gpa, self.dynsym.count());
32313280 self.versym.items[0] = elf.VER_NDX_LOCAL;
32323281 for (self.dynsym.entries.items, 1..) |entry, i| {
......@@ -3234,7 +3283,7 @@ fn setVersionSymtab(self: *Elf) !void {
32343283 self.versym.items[i] = sym.version_index;
32353284 }
32363285
3237 if (self.verneed_section_index) |shndx| {
3286 if (self.section_indexes.verneed) |shndx| {
32383287 try self.verneed.generate(self);
32393288 const shdr = &self.sections.items(.shdr)[shndx];
32403289 shdr.sh_info = @as(u32, @intCast(self.verneed.verneed.items.len));
......@@ -3242,34 +3291,39 @@ fn setVersionSymtab(self: *Elf) !void {
32423291}
32433292
32443293fn setHashSections(self: *Elf) !void {
3245 if (self.hash_section_index != null) {
3294 if (self.section_indexes.hash != null) {
32463295 try self.hash.generate(self);
32473296 }
3248 if (self.gnu_hash_section_index != null) {
3297 if (self.section_indexes.gnu_hash != null) {
32493298 try self.gnu_hash.calcSize(self);
32503299 }
32513300}
32523301
32533302fn phdrRank(phdr: elf.Elf64_Phdr) u8 {
3254 switch (phdr.p_type) {
3255 elf.PT_NULL => return 0,
3256 elf.PT_PHDR => return 1,
3257 elf.PT_INTERP => return 2,
3258 elf.PT_LOAD => return 3,
3259 elf.PT_DYNAMIC, elf.PT_TLS => return 4,
3260 elf.PT_GNU_EH_FRAME => return 5,
3261 elf.PT_GNU_STACK => return 6,
3262 else => return 7,
3263 }
3303 return switch (phdr.p_type) {
3304 elf.PT_NULL => 0,
3305 elf.PT_PHDR => 1,
3306 elf.PT_INTERP => 2,
3307 elf.PT_LOAD => 3,
3308 elf.PT_DYNAMIC, elf.PT_TLS => 4,
3309 elf.PT_GNU_EH_FRAME => 5,
3310 elf.PT_GNU_STACK => 6,
3311 else => 7,
3312 };
32643313}
32653314
3266fn sortPhdrs(self: *Elf) error{OutOfMemory}!void {
3315fn sortPhdrs(
3316 gpa: Allocator,
3317 phdrs: *ProgramHeaderList,
3318 special_indexes: *ProgramHeaderIndexes,
3319 section_indexes: []OptionalProgramHeaderIndex,
3320) error{OutOfMemory}!void {
32673321 const Entry = struct {
32683322 phndx: u16,
32693323
3270 pub fn lessThan(elf_file: *Elf, lhs: @This(), rhs: @This()) bool {
3271 const lhs_phdr = elf_file.phdrs.items[lhs.phndx];
3272 const rhs_phdr = elf_file.phdrs.items[rhs.phndx];
3324 pub fn lessThan(program_headers: []const elf.Elf64_Phdr, lhs: @This(), rhs: @This()) bool {
3325 const lhs_phdr = program_headers[lhs.phndx];
3326 const rhs_phdr = program_headers[rhs.phndx];
32733327 const lhs_rank = phdrRank(lhs_phdr);
32743328 const rhs_rank = phdrRank(rhs_phdr);
32753329 if (lhs_rank == rhs_rank) return lhs_phdr.p_vaddr < rhs_phdr.p_vaddr;
......@@ -3277,52 +3331,41 @@ fn sortPhdrs(self: *Elf) error{OutOfMemory}!void {
32773331 }
32783332 };
32793333
3280 const gpa = self.base.comp.gpa;
3281 var entries = try std.ArrayList(Entry).initCapacity(gpa, self.phdrs.items.len);
3282 defer entries.deinit();
3283 for (0..self.phdrs.items.len) |phndx| {
3284 entries.appendAssumeCapacity(.{ .phndx = @as(u16, @intCast(phndx)) });
3334 const entries = try gpa.alloc(Entry, phdrs.items.len);
3335 defer gpa.free(entries);
3336 for (entries, 0..) |*entry, phndx| {
3337 entry.* = .{ .phndx = @intCast(phndx) };
32853338 }
32863339
3287 mem.sort(Entry, entries.items, self, Entry.lessThan);
3340 // The `@as` here works around a bug in the C backend.
3341 mem.sort(Entry, entries, @as([]const elf.Elf64_Phdr, phdrs.items), Entry.lessThan);
32883342
3289 const backlinks = try gpa.alloc(u16, entries.items.len);
3343 const backlinks = try gpa.alloc(u16, entries.len);
32903344 defer gpa.free(backlinks);
3291 for (entries.items, 0..) |entry, i| {
3292 backlinks[entry.phndx] = @as(u16, @intCast(i));
3293 }
3294
3295 const slice = try self.phdrs.toOwnedSlice(gpa);
3345 const slice = try phdrs.toOwnedSlice(gpa);
32963346 defer gpa.free(slice);
3347 try phdrs.resize(gpa, slice.len);
32973348
3298 try self.phdrs.ensureTotalCapacityPrecise(gpa, slice.len);
3299 for (entries.items) |sorted| {
3300 self.phdrs.appendAssumeCapacity(slice[sorted.phndx]);
3349 for (entries, phdrs.items, 0..) |entry, *phdr, i| {
3350 backlinks[entry.phndx] = @intCast(i);
3351 phdr.* = slice[entry.phndx];
33013352 }
33023353
3303 for (&[_]*?u16{
3304 &self.phdr_table_index,
3305 &self.phdr_table_load_index,
3306 &self.phdr_interp_index,
3307 &self.phdr_dynamic_index,
3308 &self.phdr_gnu_eh_frame_index,
3309 &self.phdr_tls_index,
3310 }) |maybe_index| {
3311 if (maybe_index.*) |*index| {
3312 index.* = backlinks[index.*];
3354 inline for (@typeInfo(ProgramHeaderIndexes).@"struct".fields) |field| {
3355 if (@field(special_indexes, field.name).int()) |special_index| {
3356 @field(special_indexes, field.name) = @enumFromInt(backlinks[special_index]);
33133357 }
33143358 }
33153359
3316 for (self.sections.items(.phndx)) |*maybe_phndx| {
3317 if (maybe_phndx.*) |*index| {
3318 index.* = backlinks[index.*];
3360 for (section_indexes) |*opt_phndx| {
3361 if (opt_phndx.int()) |index| {
3362 opt_phndx.* = @enumFromInt(backlinks[index]);
33193363 }
33203364 }
33213365}
33223366
3323fn shdrRank(self: *Elf, shndx: u32) u8 {
3324 const shdr = self.sections.items(.shdr)[shndx];
3325 const name = self.getShString(shdr.sh_name);
3367fn shdrRank(shdr: elf.Elf64_Shdr, shstrtab: []const u8) u8 {
3368 const name = shString(shstrtab, shdr.sh_name);
33263369 const flags = shdr.sh_flags;
33273370
33283371 switch (shdr.sh_type) {
......@@ -3371,145 +3414,138 @@ fn shdrRank(self: *Elf, shndx: u32) u8 {
33713414 }
33723415}
33733416
3374pub fn sortShdrs(self: *Elf) !void {
3417pub fn sortShdrs(
3418 gpa: Allocator,
3419 section_indexes: *SectionIndexes,
3420 sections: *std.MultiArrayList(Section),
3421 shstrtab: []const u8,
3422 merge_sections: []Merge.Section,
3423 comdat_group_sections: []ComdatGroupSection,
3424 zig_object_ptr: ?*ZigObject,
3425 files: std.MultiArrayList(File.Entry),
3426) !void {
33753427 const Entry = struct {
33763428 shndx: u32,
33773429
3378 pub fn lessThan(elf_file: *Elf, lhs: @This(), rhs: @This()) bool {
3379 return elf_file.shdrRank(lhs.shndx) < elf_file.shdrRank(rhs.shndx);
3430 const Context = struct {
3431 shdrs: []const elf.Elf64_Shdr,
3432 shstrtab: []const u8,
3433 };
3434
3435 pub fn lessThan(ctx: Context, lhs: @This(), rhs: @This()) bool {
3436 return shdrRank(ctx.shdrs[lhs.shndx], ctx.shstrtab) <
3437 shdrRank(ctx.shdrs[rhs.shndx], ctx.shstrtab);
33803438 }
33813439 };
33823440
3383 const gpa = self.base.comp.gpa;
3384 var entries = try std.ArrayList(Entry).initCapacity(gpa, self.sections.items(.shdr).len);
3385 defer entries.deinit();
3386 for (0..self.sections.items(.shdr).len) |shndx| {
3387 entries.appendAssumeCapacity(.{ .shndx = @intCast(shndx) });
3441 const shdrs = sections.items(.shdr);
3442
3443 const entries = try gpa.alloc(Entry, shdrs.len);
3444 defer gpa.free(entries);
3445 for (entries, 0..shdrs.len) |*entry, shndx| {
3446 entry.* = .{ .shndx = @intCast(shndx) };
33883447 }
33893448
3390 mem.sort(Entry, entries.items, self, Entry.lessThan);
3449 const sort_context: Entry.Context = .{
3450 .shdrs = shdrs,
3451 .shstrtab = shstrtab,
3452 };
3453 mem.sort(Entry, entries, sort_context, Entry.lessThan);
33913454
3392 const backlinks = try gpa.alloc(u32, entries.items.len);
3455 const backlinks = try gpa.alloc(u32, entries.len);
33933456 defer gpa.free(backlinks);
3394 for (entries.items, 0..) |entry, i| {
3395 backlinks[entry.shndx] = @intCast(i);
3396 }
3397
3398 var slice = self.sections.toOwnedSlice();
3399 defer slice.deinit(gpa);
3400
3401 try self.sections.ensureTotalCapacity(gpa, slice.len);
3402 for (entries.items) |sorted| {
3403 self.sections.appendAssumeCapacity(slice.get(sorted.shndx));
3404 }
3405
3406 self.resetShdrIndexes(backlinks);
3407}
3408
3409fn resetShdrIndexes(self: *Elf, backlinks: []const u32) void {
3410 for (&[_]*?u32{
3411 &self.eh_frame_section_index,
3412 &self.eh_frame_rela_section_index,
3413 &self.eh_frame_hdr_section_index,
3414 &self.got_section_index,
3415 &self.symtab_section_index,
3416 &self.strtab_section_index,
3417 &self.shstrtab_section_index,
3418 &self.interp_section_index,
3419 &self.dynamic_section_index,
3420 &self.dynsymtab_section_index,
3421 &self.dynstrtab_section_index,
3422 &self.hash_section_index,
3423 &self.gnu_hash_section_index,
3424 &self.plt_section_index,
3425 &self.got_plt_section_index,
3426 &self.plt_got_section_index,
3427 &self.rela_dyn_section_index,
3428 &self.rela_plt_section_index,
3429 &self.copy_rel_section_index,
3430 &self.versym_section_index,
3431 &self.verneed_section_index,
3432 }) |maybe_index| {
3433 if (maybe_index.*) |*index| {
3434 index.* = backlinks[index.*];
3457 {
3458 var slice = sections.toOwnedSlice();
3459 defer slice.deinit(gpa);
3460 try sections.resize(gpa, slice.len);
3461
3462 for (entries, 0..) |entry, i| {
3463 backlinks[entry.shndx] = @intCast(i);
3464 sections.set(i, slice.get(entry.shndx));
34353465 }
34363466 }
34373467
3438 for (self.merge_sections.items) |*msec| {
3468 inline for (@typeInfo(SectionIndexes).@"struct".fields) |field| {
3469 if (@field(section_indexes, field.name)) |special_index| {
3470 @field(section_indexes, field.name) = backlinks[special_index];
3471 }
3472 }
3473
3474 for (merge_sections) |*msec| {
34393475 msec.output_section_index = backlinks[msec.output_section_index];
34403476 }
34413477
3442 const slice = self.sections.slice();
3478 const slice = sections.slice();
34433479 for (slice.items(.shdr), slice.items(.atom_list_2)) |*shdr, *atom_list| {
34443480 atom_list.output_section_index = backlinks[atom_list.output_section_index];
34453481 for (atom_list.atoms.keys()) |ref| {
3446 self.atom(ref).?.output_section_index = atom_list.output_section_index;
3482 fileLookup(files, ref.file).?.atom(ref.index).?.output_section_index = atom_list.output_section_index;
34473483 }
34483484 if (shdr.sh_type == elf.SHT_RELA) {
34493485 // FIXME:JK we should spin up .symtab potentially earlier, or set all non-dynamic RELA sections
34503486 // to point at symtab
34513487 // shdr.sh_link = backlinks[shdr.sh_link];
3452 shdr.sh_link = self.symtab_section_index.?;
3488 shdr.sh_link = section_indexes.symtab.?;
34533489 shdr.sh_info = backlinks[shdr.sh_info];
34543490 }
34553491 }
34563492
3457 if (self.zigObjectPtr()) |zo| zo.resetShdrIndexes(backlinks);
3493 if (zig_object_ptr) |zo| zo.resetShdrIndexes(backlinks);
34583494
3459 for (self.comdat_group_sections.items) |*cg| {
3495 for (comdat_group_sections) |*cg| {
34603496 cg.shndx = backlinks[cg.shndx];
34613497 }
34623498
3463 if (self.symtab_section_index) |index| {
3499 if (section_indexes.symtab) |index| {
34643500 const shdr = &slice.items(.shdr)[index];
3465 shdr.sh_link = self.strtab_section_index.?;
3501 shdr.sh_link = section_indexes.strtab.?;
34663502 }
34673503
3468 if (self.dynamic_section_index) |index| {
3504 if (section_indexes.dynamic) |index| {
34693505 const shdr = &slice.items(.shdr)[index];
3470 shdr.sh_link = self.dynstrtab_section_index.?;
3506 shdr.sh_link = section_indexes.dynstrtab.?;
34713507 }
34723508
3473 if (self.dynsymtab_section_index) |index| {
3509 if (section_indexes.dynsymtab) |index| {
34743510 const shdr = &slice.items(.shdr)[index];
3475 shdr.sh_link = self.dynstrtab_section_index.?;
3511 shdr.sh_link = section_indexes.dynstrtab.?;
34763512 }
34773513
3478 if (self.hash_section_index) |index| {
3514 if (section_indexes.hash) |index| {
34793515 const shdr = &slice.items(.shdr)[index];
3480 shdr.sh_link = self.dynsymtab_section_index.?;
3516 shdr.sh_link = section_indexes.dynsymtab.?;
34813517 }
34823518
3483 if (self.gnu_hash_section_index) |index| {
3519 if (section_indexes.gnu_hash) |index| {
34843520 const shdr = &slice.items(.shdr)[index];
3485 shdr.sh_link = self.dynsymtab_section_index.?;
3521 shdr.sh_link = section_indexes.dynsymtab.?;
34863522 }
34873523
3488 if (self.versym_section_index) |index| {
3524 if (section_indexes.versym) |index| {
34893525 const shdr = &slice.items(.shdr)[index];
3490 shdr.sh_link = self.dynsymtab_section_index.?;
3526 shdr.sh_link = section_indexes.dynsymtab.?;
34913527 }
34923528
3493 if (self.verneed_section_index) |index| {
3529 if (section_indexes.verneed) |index| {
34943530 const shdr = &slice.items(.shdr)[index];
3495 shdr.sh_link = self.dynstrtab_section_index.?;
3531 shdr.sh_link = section_indexes.dynstrtab.?;
34963532 }
34973533
3498 if (self.rela_dyn_section_index) |index| {
3534 if (section_indexes.rela_dyn) |index| {
34993535 const shdr = &slice.items(.shdr)[index];
3500 shdr.sh_link = self.dynsymtab_section_index orelse 0;
3536 shdr.sh_link = section_indexes.dynsymtab orelse 0;
35013537 }
35023538
3503 if (self.rela_plt_section_index) |index| {
3539 if (section_indexes.rela_plt) |index| {
35043540 const shdr = &slice.items(.shdr)[index];
3505 shdr.sh_link = self.dynsymtab_section_index.?;
3506 shdr.sh_info = self.plt_section_index.?;
3541 shdr.sh_link = section_indexes.dynsymtab.?;
3542 shdr.sh_info = section_indexes.plt.?;
35073543 }
35083544
3509 if (self.eh_frame_rela_section_index) |index| {
3545 if (section_indexes.eh_frame_rela) |index| {
35103546 const shdr = &slice.items(.shdr)[index];
3511 shdr.sh_link = self.symtab_section_index.?;
3512 shdr.sh_info = self.eh_frame_section_index.?;
3547 shdr.sh_link = section_indexes.symtab.?;
3548 shdr.sh_info = section_indexes.eh_frame.?;
35133549 }
35143550}
35153551
......@@ -3543,31 +3579,31 @@ fn updateSectionSizes(self: *Elf) !void {
35433579 }
35443580
35453581 const shdrs = slice.items(.shdr);
3546 if (self.eh_frame_section_index) |index| {
3582 if (self.section_indexes.eh_frame) |index| {
35473583 shdrs[index].sh_size = try eh_frame.calcEhFrameSize(self);
35483584 }
35493585
3550 if (self.eh_frame_hdr_section_index) |index| {
3586 if (self.section_indexes.eh_frame_hdr) |index| {
35513587 shdrs[index].sh_size = eh_frame.calcEhFrameHdrSize(self);
35523588 }
35533589
3554 if (self.got_section_index) |index| {
3590 if (self.section_indexes.got) |index| {
35553591 shdrs[index].sh_size = self.got.size(self);
35563592 }
35573593
3558 if (self.plt_section_index) |index| {
3594 if (self.section_indexes.plt) |index| {
35593595 shdrs[index].sh_size = self.plt.size(self);
35603596 }
35613597
3562 if (self.got_plt_section_index) |index| {
3598 if (self.section_indexes.got_plt) |index| {
35633599 shdrs[index].sh_size = self.got_plt.size(self);
35643600 }
35653601
3566 if (self.plt_got_section_index) |index| {
3602 if (self.section_indexes.plt_got) |index| {
35673603 shdrs[index].sh_size = self.plt_got.size(self);
35683604 }
35693605
3570 if (self.rela_dyn_section_index) |shndx| {
3606 if (self.section_indexes.rela_dyn) |shndx| {
35713607 var num = self.got.numRela(self) + self.copy_rel.numRela();
35723608 if (self.zigObjectPtr()) |zig_object| {
35733609 num += zig_object.num_dynrelocs;
......@@ -3578,43 +3614,43 @@ fn updateSectionSizes(self: *Elf) !void {
35783614 shdrs[shndx].sh_size = num * @sizeOf(elf.Elf64_Rela);
35793615 }
35803616
3581 if (self.rela_plt_section_index) |index| {
3617 if (self.section_indexes.rela_plt) |index| {
35823618 shdrs[index].sh_size = self.plt.numRela() * @sizeOf(elf.Elf64_Rela);
35833619 }
35843620
3585 if (self.copy_rel_section_index) |index| {
3621 if (self.section_indexes.copy_rel) |index| {
35863622 try self.copy_rel.updateSectionSize(index, self);
35873623 }
35883624
3589 if (self.interp_section_index) |index| {
3625 if (self.section_indexes.interp) |index| {
35903626 shdrs[index].sh_size = self.getTarget().dynamic_linker.get().?.len + 1;
35913627 }
35923628
3593 if (self.hash_section_index) |index| {
3629 if (self.section_indexes.hash) |index| {
35943630 shdrs[index].sh_size = self.hash.size();
35953631 }
35963632
3597 if (self.gnu_hash_section_index) |index| {
3633 if (self.section_indexes.gnu_hash) |index| {
35983634 shdrs[index].sh_size = self.gnu_hash.size();
35993635 }
36003636
3601 if (self.dynamic_section_index) |index| {
3637 if (self.section_indexes.dynamic) |index| {
36023638 shdrs[index].sh_size = self.dynamic.size(self);
36033639 }
36043640
3605 if (self.dynsymtab_section_index) |index| {
3641 if (self.section_indexes.dynsymtab) |index| {
36063642 shdrs[index].sh_size = self.dynsym.size();
36073643 }
36083644
3609 if (self.dynstrtab_section_index) |index| {
3645 if (self.section_indexes.dynstrtab) |index| {
36103646 shdrs[index].sh_size = self.dynstrtab.items.len;
36113647 }
36123648
3613 if (self.versym_section_index) |index| {
3649 if (self.section_indexes.versym) |index| {
36143650 shdrs[index].sh_size = self.versym.items.len * @sizeOf(elf.Elf64_Versym);
36153651 }
36163652
3617 if (self.verneed_section_index) |index| {
3653 if (self.section_indexes.verneed) |index| {
36183654 shdrs[index].sh_size = self.verneed.size();
36193655 }
36203656
......@@ -3624,7 +3660,7 @@ fn updateSectionSizes(self: *Elf) !void {
36243660
36253661// FIXME:JK this is very much obsolete, remove!
36263662pub fn updateShStrtabSize(self: *Elf) void {
3627 if (self.shstrtab_section_index) |index| {
3663 if (self.section_indexes.shstrtab) |index| {
36283664 self.sections.items(.shdr)[index].sh_size = self.shstrtab.items.len;
36293665 }
36303666}
......@@ -3656,7 +3692,7 @@ fn addLoadPhdrs(self: *Elf) error{OutOfMemory}!void {
36563692 if (shdr.sh_type == elf.SHT_NULL) continue;
36573693 if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue;
36583694 const flags = shdrToPhdrFlags(shdr.sh_flags);
3659 if (self.getPhdr(.{ .flags = flags, .type = elf.PT_LOAD }) == null) {
3695 if (self.getPhdr(.{ .flags = flags, .type = elf.PT_LOAD }) == .none) {
36603696 _ = try self.addPhdr(.{ .flags = flags, .type = elf.PT_LOAD });
36613697 }
36623698 }
......@@ -3664,8 +3700,8 @@ fn addLoadPhdrs(self: *Elf) error{OutOfMemory}!void {
36643700
36653701/// Allocates PHDR table in virtual memory and in file.
36663702fn allocatePhdrTable(self: *Elf) error{OutOfMemory}!void {
3667 const phdr_table = &self.phdrs.items[self.phdr_table_index.?];
3668 const phdr_table_load = &self.phdrs.items[self.phdr_table_load_index.?];
3703 const phdr_table = &self.phdrs.items[self.phdr_indexes.table.int().?];
3704 const phdr_table_load = &self.phdrs.items[self.phdr_indexes.table_load.int().?];
36693705
36703706 const ehsize: u64 = switch (self.ptr_width) {
36713707 .p32 => @sizeOf(elf.Elf32_Ehdr),
......@@ -3757,7 +3793,7 @@ pub fn allocateAllocSections(self: *Elf) !void {
37573793 // When allocating we first find the largest required alignment
37583794 // of any section that is contained in a cover and use it to align
37593795 // the start address of the segement (and first section).
3760 const phdr_table = &self.phdrs.items[self.phdr_table_load_index.?];
3796 const phdr_table = &self.phdrs.items[self.phdr_indexes.table_load.int().?];
37613797 var addr = phdr_table.p_vaddr + phdr_table.p_memsz;
37623798
37633799 for (covers) |cover| {
......@@ -3817,8 +3853,8 @@ pub fn allocateAllocSections(self: *Elf) !void {
38173853 }
38183854
38193855 const first = slice.items(.shdr)[cover.items[0]];
3820 const phndx = self.getPhdr(.{ .type = elf.PT_LOAD, .flags = shdrToPhdrFlags(first.sh_flags) }).?;
3821 const phdr = &self.phdrs.items[phndx];
3856 const phndx = self.getPhdr(.{ .type = elf.PT_LOAD, .flags = shdrToPhdrFlags(first.sh_flags) }).unwrap().?;
3857 const phdr = &self.phdrs.items[phndx.int()];
38223858 const allocated_size = self.allocatedSize(phdr.p_offset);
38233859 if (filesz > allocated_size) {
38243860 const old_offset = phdr.p_offset;
......@@ -3830,7 +3866,7 @@ pub fn allocateAllocSections(self: *Elf) !void {
38303866
38313867 for (cover.items) |shndx| {
38323868 const shdr = &slice.items(.shdr)[shndx];
3833 slice.items(.phndx)[shndx] = phndx;
3869 slice.items(.phndx)[shndx] = phndx.toOptional();
38343870 if (shdr.sh_type == elf.SHT_NOBITS) {
38353871 shdr.sh_offset = 0;
38363872 continue;
......@@ -3906,12 +3942,12 @@ pub fn allocateNonAllocSections(self: *Elf) !void {
39063942fn allocateSpecialPhdrs(self: *Elf) void {
39073943 const slice = self.sections.slice();
39083944
3909 for (&[_]struct { ?u16, ?u32 }{
3910 .{ self.phdr_interp_index, self.interp_section_index },
3911 .{ self.phdr_dynamic_index, self.dynamic_section_index },
3912 .{ self.phdr_gnu_eh_frame_index, self.eh_frame_hdr_section_index },
3945 for (&[_]struct { OptionalProgramHeaderIndex, ?u32 }{
3946 .{ self.phdr_indexes.interp, self.section_indexes.interp },
3947 .{ self.phdr_indexes.dynamic, self.section_indexes.dynamic },
3948 .{ self.phdr_indexes.gnu_eh_frame, self.section_indexes.eh_frame_hdr },
39133949 }) |pair| {
3914 if (pair[0]) |index| {
3950 if (pair[0].int()) |index| {
39153951 const shdr = slice.items(.shdr)[pair[1].?];
39163952 const phdr = &self.phdrs.items[index];
39173953 phdr.p_align = shdr.sh_addralign;
......@@ -3926,7 +3962,7 @@ fn allocateSpecialPhdrs(self: *Elf) void {
39263962 // Set the TLS segment boundaries.
39273963 // We assume TLS sections are laid out contiguously and that there is
39283964 // a single TLS segment.
3929 if (self.phdr_tls_index) |index| {
3965 if (self.phdr_indexes.tls.int()) |index| {
39303966 const shdrs = slice.items(.shdr);
39313967 const phdr = &self.phdrs.items[index];
39323968 var shndx: u32 = 0;
......@@ -4046,7 +4082,7 @@ pub fn updateSymtabSize(self: *Elf) !void {
40464082 strsize += ctx.strsize;
40474083 }
40484084
4049 if (self.got_section_index) |_| {
4085 if (self.section_indexes.got) |_| {
40504086 self.got.output_symtab_ctx.reset();
40514087 self.got.output_symtab_ctx.ilocal = nlocals;
40524088 self.got.updateSymtabSize(self);
......@@ -4054,7 +4090,7 @@ pub fn updateSymtabSize(self: *Elf) !void {
40544090 strsize += self.got.output_symtab_ctx.strsize;
40554091 }
40564092
4057 if (self.plt_section_index) |_| {
4093 if (self.section_indexes.plt) |_| {
40584094 self.plt.output_symtab_ctx.reset();
40594095 self.plt.output_symtab_ctx.ilocal = nlocals;
40604096 self.plt.updateSymtabSize(self);
......@@ -4062,7 +4098,7 @@ pub fn updateSymtabSize(self: *Elf) !void {
40624098 strsize += self.plt.output_symtab_ctx.strsize;
40634099 }
40644100
4065 if (self.plt_got_section_index) |_| {
4101 if (self.section_indexes.plt_got) |_| {
40664102 self.plt_got.output_symtab_ctx.reset();
40674103 self.plt_got.output_symtab_ctx.ilocal = nlocals;
40684104 self.plt_got.updateSymtabSize(self);
......@@ -4079,9 +4115,9 @@ pub fn updateSymtabSize(self: *Elf) !void {
40794115 }
40804116
40814117 const slice = self.sections.slice();
4082 const symtab_shdr = &slice.items(.shdr)[self.symtab_section_index.?];
4118 const symtab_shdr = &slice.items(.shdr)[self.section_indexes.symtab.?];
40834119 symtab_shdr.sh_info = nlocals;
4084 symtab_shdr.sh_link = self.strtab_section_index.?;
4120 symtab_shdr.sh_link = self.section_indexes.strtab.?;
40854121
40864122 const sym_size: u64 = switch (self.ptr_width) {
40874123 .p32 => @sizeOf(elf.Elf32_Sym),
......@@ -4090,7 +4126,7 @@ pub fn updateSymtabSize(self: *Elf) !void {
40904126 const needed_size = (nlocals + nglobals) * sym_size;
40914127 symtab_shdr.sh_size = needed_size;
40924128
4093 const strtab = &slice.items(.shdr)[self.strtab_section_index.?];
4129 const strtab = &slice.items(.shdr)[self.section_indexes.strtab.?];
40944130 strtab.sh_size = strsize + 1;
40954131}
40964132
......@@ -4098,7 +4134,7 @@ fn writeSyntheticSections(self: *Elf) !void {
40984134 const gpa = self.base.comp.gpa;
40994135 const slice = self.sections.slice();
41004136
4101 if (self.interp_section_index) |shndx| {
4137 if (self.section_indexes.interp) |shndx| {
41024138 var buffer: [256]u8 = undefined;
41034139 const interp = self.getTarget().dynamic_linker.get().?;
41044140 @memcpy(buffer[0..interp.len], interp);
......@@ -4109,12 +4145,12 @@ fn writeSyntheticSections(self: *Elf) !void {
41094145 try self.base.file.?.pwriteAll(contents, shdr.sh_offset);
41104146 }
41114147
4112 if (self.hash_section_index) |shndx| {
4148 if (self.section_indexes.hash) |shndx| {
41134149 const shdr = slice.items(.shdr)[shndx];
41144150 try self.base.file.?.pwriteAll(self.hash.buffer.items, shdr.sh_offset);
41154151 }
41164152
4117 if (self.gnu_hash_section_index) |shndx| {
4153 if (self.section_indexes.gnu_hash) |shndx| {
41184154 const shdr = slice.items(.shdr)[shndx];
41194155 var buffer = try std.ArrayList(u8).initCapacity(gpa, self.gnu_hash.size());
41204156 defer buffer.deinit();
......@@ -4122,12 +4158,12 @@ fn writeSyntheticSections(self: *Elf) !void {
41224158 try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);
41234159 }
41244160
4125 if (self.versym_section_index) |shndx| {
4161 if (self.section_indexes.versym) |shndx| {
41264162 const shdr = slice.items(.shdr)[shndx];
41274163 try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.versym.items), shdr.sh_offset);
41284164 }
41294165
4130 if (self.verneed_section_index) |shndx| {
4166 if (self.section_indexes.verneed) |shndx| {
41314167 const shdr = slice.items(.shdr)[shndx];
41324168 var buffer = try std.ArrayList(u8).initCapacity(gpa, self.verneed.size());
41334169 defer buffer.deinit();
......@@ -4135,7 +4171,7 @@ fn writeSyntheticSections(self: *Elf) !void {
41354171 try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);
41364172 }
41374173
4138 if (self.dynamic_section_index) |shndx| {
4174 if (self.section_indexes.dynamic) |shndx| {
41394175 const shdr = slice.items(.shdr)[shndx];
41404176 var buffer = try std.ArrayList(u8).initCapacity(gpa, self.dynamic.size(self));
41414177 defer buffer.deinit();
......@@ -4143,7 +4179,7 @@ fn writeSyntheticSections(self: *Elf) !void {
41434179 try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);
41444180 }
41454181
4146 if (self.dynsymtab_section_index) |shndx| {
4182 if (self.section_indexes.dynsymtab) |shndx| {
41474183 const shdr = slice.items(.shdr)[shndx];
41484184 var buffer = try std.ArrayList(u8).initCapacity(gpa, self.dynsym.size());
41494185 defer buffer.deinit();
......@@ -4151,12 +4187,12 @@ fn writeSyntheticSections(self: *Elf) !void {
41514187 try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);
41524188 }
41534189
4154 if (self.dynstrtab_section_index) |shndx| {
4190 if (self.section_indexes.dynstrtab) |shndx| {
41554191 const shdr = slice.items(.shdr)[shndx];
41564192 try self.base.file.?.pwriteAll(self.dynstrtab.items, shdr.sh_offset);
41574193 }
41584194
4159 if (self.eh_frame_section_index) |shndx| {
4195 if (self.section_indexes.eh_frame) |shndx| {
41604196 const existing_size = existing_size: {
41614197 const zo = self.zigObjectPtr() orelse break :existing_size 0;
41624198 const sym = zo.symbol(zo.eh_frame_index orelse break :existing_size 0);
......@@ -4171,7 +4207,7 @@ fn writeSyntheticSections(self: *Elf) !void {
41714207 try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset + existing_size);
41724208 }
41734209
4174 if (self.eh_frame_hdr_section_index) |shndx| {
4210 if (self.section_indexes.eh_frame_hdr) |shndx| {
41754211 const shdr = slice.items(.shdr)[shndx];
41764212 const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow;
41774213 var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size);
......@@ -4180,7 +4216,7 @@ fn writeSyntheticSections(self: *Elf) !void {
41804216 try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);
41814217 }
41824218
4183 if (self.got_section_index) |index| {
4219 if (self.section_indexes.got) |index| {
41844220 const shdr = slice.items(.shdr)[index];
41854221 var buffer = try std.ArrayList(u8).initCapacity(gpa, self.got.size(self));
41864222 defer buffer.deinit();
......@@ -4188,7 +4224,7 @@ fn writeSyntheticSections(self: *Elf) !void {
41884224 try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);
41894225 }
41904226
4191 if (self.rela_dyn_section_index) |shndx| {
4227 if (self.section_indexes.rela_dyn) |shndx| {
41924228 const shdr = slice.items(.shdr)[shndx];
41934229 try self.got.addRela(self);
41944230 try self.copy_rel.addRela(self);
......@@ -4196,7 +4232,7 @@ fn writeSyntheticSections(self: *Elf) !void {
41964232 try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.rela_dyn.items), shdr.sh_offset);
41974233 }
41984234
4199 if (self.plt_section_index) |shndx| {
4235 if (self.section_indexes.plt) |shndx| {
42004236 const shdr = slice.items(.shdr)[shndx];
42014237 var buffer = try std.ArrayList(u8).initCapacity(gpa, self.plt.size(self));
42024238 defer buffer.deinit();
......@@ -4204,7 +4240,7 @@ fn writeSyntheticSections(self: *Elf) !void {
42044240 try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);
42054241 }
42064242
4207 if (self.got_plt_section_index) |shndx| {
4243 if (self.section_indexes.got_plt) |shndx| {
42084244 const shdr = slice.items(.shdr)[shndx];
42094245 var buffer = try std.ArrayList(u8).initCapacity(gpa, self.got_plt.size(self));
42104246 defer buffer.deinit();
......@@ -4212,7 +4248,7 @@ fn writeSyntheticSections(self: *Elf) !void {
42124248 try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);
42134249 }
42144250
4215 if (self.plt_got_section_index) |shndx| {
4251 if (self.section_indexes.plt_got) |shndx| {
42164252 const shdr = slice.items(.shdr)[shndx];
42174253 var buffer = try std.ArrayList(u8).initCapacity(gpa, self.plt_got.size(self));
42184254 defer buffer.deinit();
......@@ -4220,7 +4256,7 @@ fn writeSyntheticSections(self: *Elf) !void {
42204256 try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);
42214257 }
42224258
4223 if (self.rela_plt_section_index) |shndx| {
4259 if (self.section_indexes.rela_plt) |shndx| {
42244260 const shdr = slice.items(.shdr)[shndx];
42254261 try self.plt.addRela(self);
42264262 try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.rela_plt.items), shdr.sh_offset);
......@@ -4232,7 +4268,7 @@ fn writeSyntheticSections(self: *Elf) !void {
42324268
42334269// FIXME:JK again, why is this needed?
42344270pub fn writeShStrtab(self: *Elf) !void {
4235 if (self.shstrtab_section_index) |index| {
4271 if (self.section_indexes.shstrtab) |index| {
42364272 const shdr = self.sections.items(.shdr)[index];
42374273 log.debug("writing .shstrtab from 0x{x} to 0x{x}", .{ shdr.sh_offset, shdr.sh_offset + shdr.sh_size });
42384274 try self.base.file.?.pwriteAll(self.shstrtab.items, shdr.sh_offset);
......@@ -4242,8 +4278,8 @@ pub fn writeShStrtab(self: *Elf) !void {
42424278pub fn writeSymtab(self: *Elf) !void {
42434279 const gpa = self.base.comp.gpa;
42444280 const slice = self.sections.slice();
4245 const symtab_shdr = slice.items(.shdr)[self.symtab_section_index.?];
4246 const strtab_shdr = slice.items(.shdr)[self.strtab_section_index.?];
4281 const symtab_shdr = slice.items(.shdr)[self.section_indexes.symtab.?];
4282 const strtab_shdr = slice.items(.shdr)[self.section_indexes.strtab.?];
42474283 const sym_size: u64 = switch (self.ptr_width) {
42484284 .p32 => @sizeOf(elf.Elf32_Sym),
42494285 .p64 => @sizeOf(elf.Elf64_Sym),
......@@ -4301,15 +4337,15 @@ pub fn writeSymtab(self: *Elf) !void {
43014337 obj.asFile().writeSymtab(self);
43024338 }
43034339
4304 if (self.got_section_index) |_| {
4340 if (self.section_indexes.got) |_| {
43054341 self.got.writeSymtab(self);
43064342 }
43074343
4308 if (self.plt_section_index) |_| {
4344 if (self.section_indexes.plt) |_| {
43094345 self.plt.writeSymtab(self);
43104346 }
43114347
4312 if (self.plt_got_section_index) |_| {
4348 if (self.section_indexes.plt_got) |_| {
43134349 self.plt_got.writeSymtab(self);
43144350 }
43154351
......@@ -4482,14 +4518,15 @@ pub fn isEffectivelyDynLib(self: Elf) bool {
44824518fn getPhdr(self: *Elf, opts: struct {
44834519 type: u32 = 0,
44844520 flags: u32 = 0,
4485}) ?u16 {
4521}) OptionalProgramHeaderIndex {
44864522 for (self.phdrs.items, 0..) |phdr, phndx| {
4487 if (self.phdr_table_load_index) |index| {
4523 if (self.phdr_indexes.table_load.int()) |index| {
44884524 if (phndx == index) continue;
44894525 }
4490 if (phdr.p_type == opts.type and phdr.p_flags == opts.flags) return @intCast(phndx);
4526 if (phdr.p_type == opts.type and phdr.p_flags == opts.flags)
4527 return @enumFromInt(phndx);
44914528 }
4492 return null;
4529 return .none;
44934530}
44944531
44954532fn addPhdr(self: *Elf, opts: struct {
......@@ -4500,9 +4537,9 @@ fn addPhdr(self: *Elf, opts: struct {
45004537 addr: u64 = 0,
45014538 filesz: u64 = 0,
45024539 memsz: u64 = 0,
4503}) error{OutOfMemory}!u16 {
4540}) error{OutOfMemory}!ProgramHeaderIndex {
45044541 const gpa = self.base.comp.gpa;
4505 const index = @as(u16, @intCast(self.phdrs.items.len));
4542 const index: ProgramHeaderIndex = @enumFromInt(self.phdrs.items.len);
45064543 try self.phdrs.append(gpa, .{
45074544 .p_type = opts.type,
45084545 .p_flags = opts.flags,
......@@ -4667,13 +4704,17 @@ pub fn thunk(self: *Elf, index: Thunk.Index) *Thunk {
46674704}
46684705
46694706pub fn file(self: *Elf, index: File.Index) ?File {
4670 const tag = self.files.items(.tags)[index];
4707 return fileLookup(self.files, index);
4708}
4709
4710fn fileLookup(files: std.MultiArrayList(File.Entry), index: File.Index) ?File {
4711 const tag = files.items(.tags)[index];
46714712 return switch (tag) {
46724713 .null => null,
4673 .linker_defined => .{ .linker_defined = &self.files.items(.data)[index].linker_defined },
4674 .zig_object => .{ .zig_object = &self.files.items(.data)[index].zig_object },
4675 .object => .{ .object = &self.files.items(.data)[index].object },
4676 .shared_object => .{ .shared_object = &self.files.items(.data)[index].shared_object },
4714 .linker_defined => .{ .linker_defined = &files.items(.data)[index].linker_defined },
4715 .zig_object => .{ .zig_object = &files.items(.data)[index].zig_object },
4716 .object => .{ .object = &files.items(.data)[index].object },
4717 .shared_object => .{ .shared_object = &files.items(.data)[index].shared_object },
46774718 };
46784719}
46794720
......@@ -4718,7 +4759,7 @@ pub fn linkerDefinedPtr(self: *Elf) ?*LinkerDefined {
47184759 return self.file(index).?.linker_defined;
47194760}
47204761
4721pub fn getOrCreateMergeSection(self: *Elf, name: [:0]const u8, flags: u64, @"type": u32) !MergeSection.Index {
4762pub fn getOrCreateMergeSection(self: *Elf, name: [:0]const u8, flags: u64, @"type": u32) !Merge.Section.Index {
47224763 const gpa = self.base.comp.gpa;
47234764 const out_name = name: {
47244765 if (self.base.isRelocatable()) break :name name;
......@@ -4731,7 +4772,7 @@ pub fn getOrCreateMergeSection(self: *Elf, name: [:0]const u8, flags: u64, @"typ
47314772 }
47324773 const out_off = try self.insertShString(out_name);
47334774 const out_flags = flags & ~@as(u64, elf.SHF_COMPRESSED | elf.SHF_GROUP);
4734 const index = @as(MergeSection.Index, @intCast(self.merge_sections.items.len));
4775 const index: Merge.Section.Index = @intCast(self.merge_sections.items.len);
47354776 const msec = try self.merge_sections.addOne(gpa);
47364777 msec.* = .{
47374778 .name_offset = out_off,
......@@ -4741,22 +4782,22 @@ pub fn getOrCreateMergeSection(self: *Elf, name: [:0]const u8, flags: u64, @"typ
47414782 return index;
47424783}
47434784
4744pub fn mergeSection(self: *Elf, index: MergeSection.Index) *MergeSection {
4785pub fn mergeSection(self: *Elf, index: Merge.Section.Index) *Merge.Section {
47454786 assert(index < self.merge_sections.items.len);
47464787 return &self.merge_sections.items[index];
47474788}
47484789
47494790pub fn gotAddress(self: *Elf) i64 {
47504791 const shndx = blk: {
4751 if (self.getTarget().cpu.arch == .x86_64 and self.got_plt_section_index != null)
4752 break :blk self.got_plt_section_index.?;
4753 break :blk if (self.got_section_index) |shndx| shndx else null;
4792 if (self.getTarget().cpu.arch == .x86_64 and self.section_indexes.got_plt != null)
4793 break :blk self.section_indexes.got_plt.?;
4794 break :blk if (self.section_indexes.got) |shndx| shndx else null;
47544795 };
47554796 return if (shndx) |index| @intCast(self.sections.items(.shdr)[index].sh_addr) else 0;
47564797}
47574798
47584799pub fn tpAddress(self: *Elf) i64 {
4759 const index = self.phdr_tls_index orelse return 0;
4800 const index = self.phdr_indexes.tls.int() orelse return 0;
47604801 const phdr = self.phdrs.items[index];
47614802 const addr = switch (self.getTarget().cpu.arch) {
47624803 .x86_64 => mem.alignForward(u64, phdr.p_vaddr + phdr.p_memsz, phdr.p_align),
......@@ -4768,20 +4809,27 @@ pub fn tpAddress(self: *Elf) i64 {
47684809}
47694810
47704811pub fn dtpAddress(self: *Elf) i64 {
4771 const index = self.phdr_tls_index orelse return 0;
4812 const index = self.phdr_indexes.tls.int() orelse return 0;
47724813 const phdr = self.phdrs.items[index];
47734814 return @intCast(phdr.p_vaddr);
47744815}
47754816
47764817pub fn tlsAddress(self: *Elf) i64 {
4777 const index = self.phdr_tls_index orelse return 0;
4818 const index = self.phdr_indexes.tls.int() orelse return 0;
47784819 const phdr = self.phdrs.items[index];
47794820 return @intCast(phdr.p_vaddr);
47804821}
47814822
47824823pub fn getShString(self: Elf, off: u32) [:0]const u8 {
4783 assert(off < self.shstrtab.items.len);
4784 return mem.sliceTo(@as([*:0]const u8, @ptrCast(self.shstrtab.items.ptr + off)), 0);
4824 return shString(self.shstrtab.items, off);
4825}
4826
4827fn shString(
4828 shstrtab: []const u8,
4829 off: u32,
4830) [:0]const u8 {
4831 const slice = shstrtab[off..];
4832 return slice[0..std.mem.indexOfScalar(u8, slice, 0).? :0];
47854833}
47864834
47874835pub fn insertShString(self: *Elf, name: [:0]const u8) error{OutOfMemory}!u32 {
......@@ -5393,7 +5441,7 @@ const Section = struct {
53935441 shdr: elf.Elf64_Shdr,
53945442
53955443 /// Assigned program header index if any.
5396 phndx: ?u32 = null,
5444 phndx: OptionalProgramHeaderIndex = .none,
53975445
53985446 /// List of atoms contributing to this section.
53995447 /// TODO currently this is only used for relocations tracking in relocatable mode
......@@ -5533,6 +5581,9 @@ const relocs_log = std.log.scoped(.link_relocs);
55335581const state_log = std.log.scoped(.link_state);
55345582const math = std.math;
55355583const mem = std.mem;
5584const Allocator = std.mem.Allocator;
5585const Cache = std.Build.Cache;
5586const Hash = std.hash.Wyhash;
55365587
55375588const codegen = @import("../codegen.zig");
55385589const dev = @import("../dev.zig");
......@@ -5540,7 +5591,6 @@ const eh_frame = @import("Elf/eh_frame.zig");
55405591const gc = @import("Elf/gc.zig");
55415592const glibc = @import("../glibc.zig");
55425593const link = @import("../link.zig");
5543const merge_section = @import("Elf/merge_section.zig");
55445594const musl = @import("../musl.zig");
55455595const relocatable = @import("Elf/relocatable.zig");
55465596const relocation = @import("Elf/relocation.zig");
......@@ -5548,12 +5598,10 @@ const target_util = @import("../target.zig");
55485598const trace = @import("../tracy.zig").trace;
55495599const synthetic_sections = @import("Elf/synthetic_sections.zig");
55505600
5601const Merge = @import("Elf/Merge.zig");
55515602const Air = @import("../Air.zig");
5552const Allocator = std.mem.Allocator;
55535603const Archive = @import("Elf/Archive.zig");
5554pub const Atom = @import("Elf/Atom.zig");
55555604const AtomList = @import("Elf/AtomList.zig");
5556const Cache = std.Build.Cache;
55575605const Path = Cache.Path;
55585606const Compilation = @import("../Compilation.zig");
55595607const ComdatGroupSection = synthetic_sections.ComdatGroupSection;
......@@ -5566,15 +5614,11 @@ const File = @import("Elf/file.zig").File;
55665614const GnuHashSection = synthetic_sections.GnuHashSection;
55675615const GotSection = synthetic_sections.GotSection;
55685616const GotPltSection = synthetic_sections.GotPltSection;
5569const Hash = std.hash.Wyhash;
55705617const HashSection = synthetic_sections.HashSection;
5571const InputMergeSection = merge_section.InputMergeSection;
55725618const LdScript = @import("Elf/LdScript.zig");
55735619const LinkerDefined = @import("Elf/LinkerDefined.zig");
55745620const Liveness = @import("../Liveness.zig");
55755621const LlvmObject = @import("../codegen/llvm.zig").Object;
5576const MergeSection = merge_section.MergeSection;
5577const MergeSubsection = merge_section.MergeSubsection;
55785622const Zcu = @import("../Zcu.zig");
55795623const Object = @import("Elf/Object.zig");
55805624const InternPool = @import("../InternPool.zig");
src/link/Elf/LinkerDefined.zig+6-6
......@@ -205,7 +205,7 @@ pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void {
205205 }.allocSymbol;
206206
207207 // _DYNAMIC
208 if (elf_file.dynamic_section_index) |shndx| {
208 if (elf_file.section_indexes.dynamic) |shndx| {
209209 const shdr = shdrs[shndx];
210210 allocSymbol(self, self.dynamic_index.?, shdr.sh_addr, shndx, elf_file);
211211 }
......@@ -236,19 +236,19 @@ pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void {
236236
237237 // _GLOBAL_OFFSET_TABLE_
238238 if (elf_file.getTarget().cpu.arch == .x86_64) {
239 if (elf_file.got_plt_section_index) |shndx| {
239 if (elf_file.section_indexes.got_plt) |shndx| {
240240 const shdr = shdrs[shndx];
241241 allocSymbol(self, self.got_index.?, shdr.sh_addr, shndx, elf_file);
242242 }
243243 } else {
244 if (elf_file.got_section_index) |shndx| {
244 if (elf_file.section_indexes.got) |shndx| {
245245 const shdr = shdrs[shndx];
246246 allocSymbol(self, self.got_index.?, shdr.sh_addr, shndx, elf_file);
247247 }
248248 }
249249
250250 // _PROCEDURE_LINKAGE_TABLE_
251 if (elf_file.plt_section_index) |shndx| {
251 if (elf_file.section_indexes.plt) |shndx| {
252252 const shdr = shdrs[shndx];
253253 allocSymbol(self, self.plt_index.?, shdr.sh_addr, shndx, elf_file);
254254 }
......@@ -262,13 +262,13 @@ pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void {
262262 }
263263
264264 // __GNU_EH_FRAME_HDR
265 if (elf_file.eh_frame_hdr_section_index) |shndx| {
265 if (elf_file.section_indexes.eh_frame_hdr) |shndx| {
266266 const shdr = shdrs[shndx];
267267 allocSymbol(self, self.gnu_eh_frame_hdr_index.?, shdr.sh_addr, shndx, elf_file);
268268 }
269269
270270 // __rela_iplt_start, __rela_iplt_end
271 if (elf_file.rela_dyn_section_index) |shndx| blk: {
271 if (elf_file.section_indexes.rela_dyn) |shndx| blk: {
272272 if (link_mode != .static or comp.config.pie) break :blk;
273273 const shdr = shdrs[shndx];
274274 const end_addr = shdr.sh_addr + shdr.sh_size;
src/link/Elf/Merge.zig created+341
......@@ -0,0 +1,341 @@
1pub const Section = struct {
2 value: u64 = 0,
3 size: u64 = 0,
4 alignment: Atom.Alignment = .@"1",
5 entsize: u32 = 0,
6 name_offset: u32 = 0,
7 type: u32 = 0,
8 flags: u64 = 0,
9 output_section_index: u32 = 0,
10 bytes: std.ArrayListUnmanaged(u8) = .empty,
11 table: std.HashMapUnmanaged(
12 String,
13 Subsection.Index,
14 IndexContext,
15 std.hash_map.default_max_load_percentage,
16 ) = .{},
17 subsections: std.ArrayListUnmanaged(Subsection) = .empty,
18 finalized_subsections: std.ArrayListUnmanaged(Subsection.Index) = .empty,
19
20 pub fn deinit(msec: *Section, allocator: Allocator) void {
21 msec.bytes.deinit(allocator);
22 msec.table.deinit(allocator);
23 msec.subsections.deinit(allocator);
24 msec.finalized_subsections.deinit(allocator);
25 }
26
27 pub fn name(msec: Section, elf_file: *Elf) [:0]const u8 {
28 return elf_file.getShString(msec.name_offset);
29 }
30
31 pub fn address(msec: Section, elf_file: *Elf) i64 {
32 const shdr = elf_file.sections.items(.shdr)[msec.output_section_index];
33 return @intCast(shdr.sh_addr + msec.value);
34 }
35
36 const InsertResult = struct {
37 found_existing: bool,
38 key: String,
39 sub: *Subsection.Index,
40 };
41
42 pub fn insert(msec: *Section, allocator: Allocator, string: []const u8) !InsertResult {
43 const gop = try msec.table.getOrPutContextAdapted(
44 allocator,
45 string,
46 IndexAdapter{ .bytes = msec.bytes.items },
47 IndexContext{ .bytes = msec.bytes.items },
48 );
49 if (!gop.found_existing) {
50 const index: u32 = @intCast(msec.bytes.items.len);
51 try msec.bytes.appendSlice(allocator, string);
52 gop.key_ptr.* = .{ .pos = index, .len = @intCast(string.len) };
53 }
54 return .{ .found_existing = gop.found_existing, .key = gop.key_ptr.*, .sub = gop.value_ptr };
55 }
56
57 pub fn insertZ(msec: *Section, allocator: Allocator, string: []const u8) !InsertResult {
58 const with_null = try allocator.alloc(u8, string.len + 1);
59 defer allocator.free(with_null);
60 @memcpy(with_null[0..string.len], string);
61 with_null[string.len] = 0;
62 return msec.insert(allocator, with_null);
63 }
64
65 /// Finalizes the merge section and clears hash table.
66 /// Sorts all owned subsections.
67 pub fn finalize(msec: *Section, allocator: Allocator) !void {
68 try msec.finalized_subsections.ensureTotalCapacityPrecise(allocator, msec.subsections.items.len);
69
70 var it = msec.table.iterator();
71 while (it.next()) |entry| {
72 const msub = msec.mergeSubsection(entry.value_ptr.*);
73 if (!msub.alive) continue;
74 msec.finalized_subsections.appendAssumeCapacity(entry.value_ptr.*);
75 }
76 msec.table.clearAndFree(allocator);
77
78 const sortFn = struct {
79 pub fn sortFn(ctx: *Section, lhs: Subsection.Index, rhs: Subsection.Index) bool {
80 const lhs_msub = ctx.mergeSubsection(lhs);
81 const rhs_msub = ctx.mergeSubsection(rhs);
82 if (lhs_msub.alignment.compareStrict(.eq, rhs_msub.alignment)) {
83 if (lhs_msub.size == rhs_msub.size) {
84 const lhs_string = ctx.bytes.items[lhs_msub.string_index..][0..lhs_msub.size];
85 const rhs_string = ctx.bytes.items[rhs_msub.string_index..][0..rhs_msub.size];
86 return mem.order(u8, lhs_string, rhs_string) == .lt;
87 }
88 return lhs_msub.size < rhs_msub.size;
89 }
90 return lhs_msub.alignment.compareStrict(.lt, rhs_msub.alignment);
91 }
92 }.sortFn;
93
94 std.mem.sort(Subsection.Index, msec.finalized_subsections.items, msec, sortFn);
95 }
96
97 pub fn updateSize(msec: *Section) void {
98 // TODO a 'stale' flag would be better here perhaps?
99 msec.size = 0;
100 msec.alignment = .@"1";
101 msec.entsize = 0;
102 for (msec.finalized_subsections.items) |msub_index| {
103 const msub = msec.mergeSubsection(msub_index);
104 assert(msub.alive);
105 const offset = msub.alignment.forward(msec.size);
106 const padding = offset - msec.size;
107 msub.value = @intCast(offset);
108 msec.size += padding + msub.size;
109 msec.alignment = msec.alignment.max(msub.alignment);
110 msec.entsize = if (msec.entsize == 0) msub.entsize else @min(msec.entsize, msub.entsize);
111 }
112 }
113
114 pub fn initOutputSection(msec: *Section, elf_file: *Elf) !void {
115 msec.output_section_index = elf_file.sectionByName(msec.name(elf_file)) orelse try elf_file.addSection(.{
116 .name = msec.name_offset,
117 .type = msec.type,
118 .flags = msec.flags,
119 });
120 }
121
122 pub fn addMergeSubsection(msec: *Section, allocator: Allocator) !Subsection.Index {
123 const index: Subsection.Index = @intCast(msec.subsections.items.len);
124 const msub = try msec.subsections.addOne(allocator);
125 msub.* = .{};
126 return index;
127 }
128
129 pub fn mergeSubsection(msec: *Section, index: Subsection.Index) *Subsection {
130 assert(index < msec.subsections.items.len);
131 return &msec.subsections.items[index];
132 }
133
134 pub const IndexContext = struct {
135 bytes: []const u8,
136
137 pub fn eql(_: @This(), a: String, b: String) bool {
138 return a.pos == b.pos;
139 }
140
141 pub fn hash(ctx: @This(), key: String) u64 {
142 const str = ctx.bytes[key.pos..][0..key.len];
143 return std.hash_map.hashString(str);
144 }
145 };
146
147 pub const IndexAdapter = struct {
148 bytes: []const u8,
149
150 pub fn eql(ctx: @This(), a: []const u8, b: String) bool {
151 const str = ctx.bytes[b.pos..][0..b.len];
152 return mem.eql(u8, a, str);
153 }
154
155 pub fn hash(_: @This(), adapted_key: []const u8) u64 {
156 return std.hash_map.hashString(adapted_key);
157 }
158 };
159
160 pub fn format(
161 msec: Section,
162 comptime unused_fmt_string: []const u8,
163 options: std.fmt.FormatOptions,
164 writer: anytype,
165 ) !void {
166 _ = msec;
167 _ = unused_fmt_string;
168 _ = options;
169 _ = writer;
170 @compileError("do not format directly");
171 }
172
173 pub fn fmt(msec: Section, elf_file: *Elf) std.fmt.Formatter(format2) {
174 return .{ .data = .{
175 .msec = msec,
176 .elf_file = elf_file,
177 } };
178 }
179
180 const FormatContext = struct {
181 msec: Section,
182 elf_file: *Elf,
183 };
184
185 pub fn format2(
186 ctx: FormatContext,
187 comptime unused_fmt_string: []const u8,
188 options: std.fmt.FormatOptions,
189 writer: anytype,
190 ) !void {
191 _ = options;
192 _ = unused_fmt_string;
193 const msec = ctx.msec;
194 const elf_file = ctx.elf_file;
195 try writer.print("{s} : @{x} : size({x}) : align({x}) : entsize({x}) : type({x}) : flags({x})\n", .{
196 msec.name(elf_file),
197 msec.address(elf_file),
198 msec.size,
199 msec.alignment.toByteUnits() orelse 0,
200 msec.entsize,
201 msec.type,
202 msec.flags,
203 });
204 for (msec.subsections.items) |msub| {
205 try writer.print(" {}\n", .{msub.fmt(elf_file)});
206 }
207 }
208
209 pub const Index = u32;
210};
211
212pub const Subsection = struct {
213 value: i64 = 0,
214 merge_section_index: Section.Index = 0,
215 string_index: u32 = 0,
216 size: u32 = 0,
217 alignment: Atom.Alignment = .@"1",
218 entsize: u32 = 0,
219 alive: bool = false,
220
221 pub fn address(msub: Subsection, elf_file: *Elf) i64 {
222 return msub.mergeSection(elf_file).address(elf_file) + msub.value;
223 }
224
225 pub fn mergeSection(msub: Subsection, elf_file: *Elf) *Section {
226 return elf_file.mergeSection(msub.merge_section_index);
227 }
228
229 pub fn getString(msub: Subsection, elf_file: *Elf) []const u8 {
230 const msec = msub.mergeSection(elf_file);
231 return msec.bytes.items[msub.string_index..][0..msub.size];
232 }
233
234 pub fn format(
235 msub: Subsection,
236 comptime unused_fmt_string: []const u8,
237 options: std.fmt.FormatOptions,
238 writer: anytype,
239 ) !void {
240 _ = msub;
241 _ = unused_fmt_string;
242 _ = options;
243 _ = writer;
244 @compileError("do not format directly");
245 }
246
247 pub fn fmt(msub: Subsection, elf_file: *Elf) std.fmt.Formatter(format2) {
248 return .{ .data = .{
249 .msub = msub,
250 .elf_file = elf_file,
251 } };
252 }
253
254 const FormatContext = struct {
255 msub: Subsection,
256 elf_file: *Elf,
257 };
258
259 pub fn format2(
260 ctx: FormatContext,
261 comptime unused_fmt_string: []const u8,
262 options: std.fmt.FormatOptions,
263 writer: anytype,
264 ) !void {
265 _ = options;
266 _ = unused_fmt_string;
267 const msub = ctx.msub;
268 const elf_file = ctx.elf_file;
269 try writer.print("@{x} : align({x}) : size({x})", .{
270 msub.address(elf_file),
271 msub.alignment,
272 msub.size,
273 });
274 if (!msub.alive) try writer.writeAll(" : [*]");
275 }
276
277 pub const Index = u32;
278};
279
280pub const InputSection = struct {
281 merge_section_index: Section.Index = 0,
282 atom_index: Atom.Index = 0,
283 offsets: std.ArrayListUnmanaged(u32) = .empty,
284 subsections: std.ArrayListUnmanaged(Subsection.Index) = .empty,
285 bytes: std.ArrayListUnmanaged(u8) = .empty,
286 strings: std.ArrayListUnmanaged(String) = .empty,
287
288 pub fn deinit(imsec: *InputSection, allocator: Allocator) void {
289 imsec.offsets.deinit(allocator);
290 imsec.subsections.deinit(allocator);
291 imsec.bytes.deinit(allocator);
292 imsec.strings.deinit(allocator);
293 }
294
295 pub fn clearAndFree(imsec: *InputSection, allocator: Allocator) void {
296 imsec.bytes.clearAndFree(allocator);
297 // TODO: imsec.strings.clearAndFree(allocator);
298 }
299
300 const FindSubsectionResult = struct {
301 msub_index: Subsection.Index,
302 offset: u32,
303 };
304
305 pub fn findSubsection(imsec: InputSection, offset: u32) ?FindSubsectionResult {
306 // TODO: binary search
307 for (imsec.offsets.items, 0..) |off, index| {
308 if (offset < off) return .{
309 .msub_index = imsec.subsections.items[index - 1],
310 .offset = offset - imsec.offsets.items[index - 1],
311 };
312 }
313 const last = imsec.offsets.items.len - 1;
314 const last_off = imsec.offsets.items[last];
315 const last_len = imsec.strings.items[last].len;
316 if (offset < last_off + last_len) return .{
317 .msub_index = imsec.subsections.items[last],
318 .offset = offset - last_off,
319 };
320 return null;
321 }
322
323 pub fn insert(imsec: *InputSection, allocator: Allocator, string: []const u8) !void {
324 const index: u32 = @intCast(imsec.bytes.items.len);
325 try imsec.bytes.appendSlice(allocator, string);
326 try imsec.strings.append(allocator, .{ .pos = index, .len = @intCast(string.len) });
327 }
328
329 pub const Index = u32;
330};
331
332const String = struct { pos: u32, len: u32 };
333
334const assert = std.debug.assert;
335const mem = std.mem;
336const std = @import("std");
337
338const Allocator = mem.Allocator;
339const Atom = @import("Atom.zig");
340const Elf = @import("../Elf.zig");
341const Merge = @This();
src/link/Elf/Object.zig+9-9
......@@ -23,8 +23,8 @@ atoms_extra: std.ArrayListUnmanaged(u32) = .empty,
2323comdat_groups: std.ArrayListUnmanaged(Elf.ComdatGroup) = .empty,
2424comdat_group_data: std.ArrayListUnmanaged(u32) = .empty,
2525
26input_merge_sections: std.ArrayListUnmanaged(InputMergeSection) = .empty,
27input_merge_sections_indexes: std.ArrayListUnmanaged(InputMergeSection.Index) = .empty,
26input_merge_sections: std.ArrayListUnmanaged(Merge.InputSection) = .empty,
27input_merge_sections_indexes: std.ArrayListUnmanaged(Merge.InputSection.Index) = .empty,
2828
2929fdes: std.ArrayListUnmanaged(Fde) = .empty,
3030cies: std.ArrayListUnmanaged(Cie) = .empty,
......@@ -927,7 +927,7 @@ pub fn initRelaSections(self: *Object, elf_file: *Elf) !void {
927927 for (self.atoms_indexes.items) |atom_index| {
928928 const atom_ptr = self.atom(atom_index) orelse continue;
929929 if (!atom_ptr.alive) continue;
930 if (atom_ptr.output_section_index == elf_file.eh_frame_section_index) continue;
930 if (atom_ptr.output_section_index == elf_file.section_indexes.eh_frame) continue;
931931 const shndx = atom_ptr.relocsShndx() orelse continue;
932932 const shdr = self.shdrs.items[shndx];
933933 const out_shndx = try elf_file.initOutputSection(.{
......@@ -947,7 +947,7 @@ pub fn addAtomsToRelaSections(self: *Object, elf_file: *Elf) !void {
947947 for (self.atoms_indexes.items) |atom_index| {
948948 const atom_ptr = self.atom(atom_index) orelse continue;
949949 if (!atom_ptr.alive) continue;
950 if (atom_ptr.output_section_index == elf_file.eh_frame_section_index) continue;
950 if (atom_ptr.output_section_index == elf_file.section_indexes.eh_frame) continue;
951951 const shndx = blk: {
952952 const shndx = atom_ptr.relocsShndx() orelse continue;
953953 const shdr = self.shdrs.items[shndx];
......@@ -960,7 +960,7 @@ pub fn addAtomsToRelaSections(self: *Object, elf_file: *Elf) !void {
960960 const slice = elf_file.sections.slice();
961961 const shdr = &slice.items(.shdr)[shndx];
962962 shdr.sh_info = atom_ptr.output_section_index;
963 shdr.sh_link = elf_file.symtab_section_index.?;
963 shdr.sh_link = elf_file.section_indexes.symtab.?;
964964 const gpa = elf_file.base.comp.gpa;
965965 const atom_list = &elf_file.sections.items(.atom_list)[shndx];
966966 try atom_list.append(gpa, .{ .index = atom_index, .file = self.index });
......@@ -1305,14 +1305,14 @@ fn setAtomFields(o: *Object, atom_ptr: *Atom, opts: Atom.Extra.AsOptionals) void
13051305 o.setAtomExtra(atom_ptr.extra_index, extras);
13061306}
13071307
1308fn addInputMergeSection(self: *Object, allocator: Allocator) !InputMergeSection.Index {
1309 const index: InputMergeSection.Index = @intCast(self.input_merge_sections.items.len);
1308fn addInputMergeSection(self: *Object, allocator: Allocator) !Merge.InputSection.Index {
1309 const index: Merge.InputSection.Index = @intCast(self.input_merge_sections.items.len);
13101310 const msec = try self.input_merge_sections.addOne(allocator);
13111311 msec.* = .{};
13121312 return index;
13131313}
13141314
1315fn inputMergeSection(self: *Object, index: InputMergeSection.Index) ?*InputMergeSection {
1315fn inputMergeSection(self: *Object, index: Merge.InputSection.Index) ?*Merge.InputSection {
13161316 if (index == 0) return null;
13171317 return &self.input_merge_sections.items[index];
13181318}
......@@ -1522,6 +1522,6 @@ const Cie = eh_frame.Cie;
15221522const Elf = @import("../Elf.zig");
15231523const Fde = eh_frame.Fde;
15241524const File = @import("file.zig").File;
1525const InputMergeSection = @import("merge_section.zig").InputMergeSection;
1525const Merge = @import("Merge.zig");
15261526const Symbol = @import("Symbol.zig");
15271527const Alignment = Atom.Alignment;
src/link/Elf/Symbol.zig+8-8
......@@ -74,7 +74,7 @@ pub fn atom(symbol: Symbol, elf_file: *Elf) ?*Atom {
7474 return file_ptr.atom(symbol.ref.index);
7575}
7676
77pub fn mergeSubsection(symbol: Symbol, elf_file: *Elf) ?*MergeSubsection {
77pub fn mergeSubsection(symbol: Symbol, elf_file: *Elf) ?*Merge.Subsection {
7878 if (!symbol.flags.merge_subsection) return null;
7979 const msec = elf_file.mergeSection(symbol.ref.file);
8080 return msec.mergeSubsection(symbol.ref.index);
......@@ -128,7 +128,7 @@ pub fn address(symbol: Symbol, opts: struct { plt: bool = true, trampoline: bool
128128 if (mem.eql(u8, atom_ptr.name(elf_file), ".eh_frame")) {
129129 const sym_name = symbol.name(elf_file);
130130 const sh_addr, const sh_size = blk: {
131 const shndx = elf_file.eh_frame_section_index orelse break :blk .{ 0, 0 };
131 const shndx = elf_file.section_indexes.eh_frame orelse break :blk .{ 0, 0 };
132132 const shdr = elf_file.sections.items(.shdr)[shndx];
133133 break :blk .{ shdr.sh_addr, shdr.sh_size };
134134 };
......@@ -176,7 +176,7 @@ pub fn gotAddress(symbol: Symbol, elf_file: *Elf) i64 {
176176pub fn pltGotAddress(symbol: Symbol, elf_file: *Elf) i64 {
177177 if (!symbol.flags.has_pltgot) return 0;
178178 const extras = symbol.extra(elf_file);
179 const shdr = elf_file.sections.items(.shdr)[elf_file.plt_got_section_index.?];
179 const shdr = elf_file.sections.items(.shdr)[elf_file.section_indexes.plt_got.?];
180180 const cpu_arch = elf_file.getTarget().cpu.arch;
181181 return @intCast(shdr.sh_addr + extras.plt_got * PltGotSection.entrySize(cpu_arch));
182182}
......@@ -184,7 +184,7 @@ pub fn pltGotAddress(symbol: Symbol, elf_file: *Elf) i64 {
184184pub fn pltAddress(symbol: Symbol, elf_file: *Elf) i64 {
185185 if (!symbol.flags.has_plt) return 0;
186186 const extras = symbol.extra(elf_file);
187 const shdr = elf_file.sections.items(.shdr)[elf_file.plt_section_index.?];
187 const shdr = elf_file.sections.items(.shdr)[elf_file.section_indexes.plt.?];
188188 const cpu_arch = elf_file.getTarget().cpu.arch;
189189 return @intCast(shdr.sh_addr + extras.plt * PltSection.entrySize(cpu_arch) + PltSection.preambleSize(cpu_arch));
190190}
......@@ -192,13 +192,13 @@ pub fn pltAddress(symbol: Symbol, elf_file: *Elf) i64 {
192192pub fn gotPltAddress(symbol: Symbol, elf_file: *Elf) i64 {
193193 if (!symbol.flags.has_plt) return 0;
194194 const extras = symbol.extra(elf_file);
195 const shdr = elf_file.sections.items(.shdr)[elf_file.got_plt_section_index.?];
195 const shdr = elf_file.sections.items(.shdr)[elf_file.section_indexes.got_plt.?];
196196 return @intCast(shdr.sh_addr + extras.plt * 8 + GotPltSection.preamble_size);
197197}
198198
199199pub fn copyRelAddress(symbol: Symbol, elf_file: *Elf) i64 {
200200 if (!symbol.flags.has_copy_rel) return 0;
201 const shdr = elf_file.sections.items(.shdr)[elf_file.copy_rel_section_index.?];
201 const shdr = elf_file.sections.items(.shdr)[elf_file.section_indexes.copy_rel.?];
202202 return @as(i64, @intCast(shdr.sh_addr)) + symbol.value;
203203}
204204
......@@ -289,7 +289,7 @@ pub fn setOutputSym(symbol: Symbol, elf_file: *Elf, out: *elf.Elf64_Sym) void {
289289 break :blk esym.st_bind();
290290 };
291291 const st_shndx: u16 = blk: {
292 if (symbol.flags.has_copy_rel) break :blk @intCast(elf_file.copy_rel_section_index.?);
292 if (symbol.flags.has_copy_rel) break :blk @intCast(elf_file.section_indexes.copy_rel.?);
293293 if (file_ptr == .shared_object or esym.st_shndx == elf.SHN_UNDEF) break :blk elf.SHN_UNDEF;
294294 if (elf_file.base.isRelocatable() and esym.st_shndx == elf.SHN_COMMON) break :blk elf.SHN_COMMON;
295295 if (symbol.mergeSubsection(elf_file)) |msub| break :blk @intCast(msub.mergeSection(elf_file).output_section_index);
......@@ -493,7 +493,7 @@ const File = @import("file.zig").File;
493493const GotSection = synthetic_sections.GotSection;
494494const GotPltSection = synthetic_sections.GotPltSection;
495495const LinkerDefined = @import("LinkerDefined.zig");
496const MergeSubsection = @import("merge_section.zig").MergeSubsection;
496const Merge = @import("Merge.zig");
497497const Object = @import("Object.zig");
498498const PltSection = synthetic_sections.PltSection;
499499const PltGotSection = synthetic_sections.PltGotSection;
src/link/Elf/ZigObject.zig+4-4
......@@ -791,7 +791,7 @@ pub fn initRelaSections(self: *ZigObject, elf_file: *Elf) !void {
791791 for (self.atoms_indexes.items) |atom_index| {
792792 const atom_ptr = self.atom(atom_index) orelse continue;
793793 if (!atom_ptr.alive) continue;
794 if (atom_ptr.output_section_index == elf_file.eh_frame_section_index) continue;
794 if (atom_ptr.output_section_index == elf_file.section_indexes.eh_frame) continue;
795795 const rela_shndx = atom_ptr.relocsShndx() orelse continue;
796796 // TODO this check will become obsolete when we rework our relocs mechanism at the ZigObject level
797797 if (self.relocs.items[rela_shndx].items.len == 0) continue;
......@@ -812,7 +812,7 @@ pub fn addAtomsToRelaSections(self: *ZigObject, elf_file: *Elf) !void {
812812 for (self.atoms_indexes.items) |atom_index| {
813813 const atom_ptr = self.atom(atom_index) orelse continue;
814814 if (!atom_ptr.alive) continue;
815 if (atom_ptr.output_section_index == elf_file.eh_frame_section_index) continue;
815 if (atom_ptr.output_section_index == elf_file.section_indexes.eh_frame) continue;
816816 const rela_shndx = atom_ptr.relocsShndx() orelse continue;
817817 // TODO this check will become obsolete when we rework our relocs mechanism at the ZigObject level
818818 if (self.relocs.items[rela_shndx].items.len == 0) continue;
......@@ -826,7 +826,7 @@ pub fn addAtomsToRelaSections(self: *ZigObject, elf_file: *Elf) !void {
826826 const out_rela_shndx = elf_file.sectionByName(rela_sect_name).?;
827827 const out_rela_shdr = &elf_file.sections.items(.shdr)[out_rela_shndx];
828828 out_rela_shdr.sh_info = out_shndx;
829 out_rela_shdr.sh_link = elf_file.symtab_section_index.?;
829 out_rela_shdr.sh_link = elf_file.section_indexes.symtab.?;
830830 const atom_list = &elf_file.sections.items(.atom_list)[out_rela_shndx];
831831 try atom_list.append(gpa, .{ .index = atom_index, .file = self.index });
832832 }
......@@ -2027,7 +2027,7 @@ pub fn allocateAtom(self: *ZigObject, atom_ptr: *Atom, requires_padding: bool, e
20272027 log.debug(" prev {?}, next {?}", .{ atom_ptr.prev_atom_ref, atom_ptr.next_atom_ref });
20282028}
20292029
2030pub fn resetShdrIndexes(self: *ZigObject, backlinks: anytype) void {
2030pub fn resetShdrIndexes(self: *ZigObject, backlinks: []const u32) void {
20312031 for (self.atoms_indexes.items) |atom_index| {
20322032 const atom_ptr = self.atom(atom_index) orelse continue;
20332033 atom_ptr.output_section_index = backlinks[atom_ptr.output_section_index];
src/link/Elf/eh_frame.zig+6-6
......@@ -12,7 +12,7 @@ pub const Fde = struct {
1212 out_offset: u64 = 0,
1313
1414 pub fn address(fde: Fde, elf_file: *Elf) u64 {
15 const base: u64 = if (elf_file.eh_frame_section_index) |shndx|
15 const base: u64 = if (elf_file.section_indexes.eh_frame) |shndx|
1616 elf_file.sections.items(.shdr)[shndx].sh_addr
1717 else
1818 0;
......@@ -111,7 +111,7 @@ pub const Cie = struct {
111111 alive: bool = false,
112112
113113 pub fn address(cie: Cie, elf_file: *Elf) u64 {
114 const base: u64 = if (elf_file.eh_frame_section_index) |shndx|
114 const base: u64 = if (elf_file.section_indexes.eh_frame) |shndx|
115115 elf_file.sections.items(.shdr)[shndx].sh_addr
116116 else
117117 0;
......@@ -337,7 +337,7 @@ fn resolveReloc(rec: anytype, sym: *const Symbol, rel: elf.Elf64_Rela, elf_file:
337337
338338pub fn writeEhFrame(elf_file: *Elf, writer: anytype) !void {
339339 relocs_log.debug("{x}: .eh_frame", .{
340 elf_file.sections.items(.shdr)[elf_file.eh_frame_section_index.?].sh_addr,
340 elf_file.sections.items(.shdr)[elf_file.section_indexes.eh_frame.?].sh_addr,
341341 });
342342
343343 var has_reloc_errors = false;
......@@ -458,7 +458,7 @@ fn emitReloc(elf_file: *Elf, r_offset: u64, sym: *const Symbol, rel: elf.Elf64_R
458458
459459pub fn writeEhFrameRelocs(elf_file: *Elf, writer: anytype) !void {
460460 relocs_log.debug("{x}: .eh_frame", .{
461 elf_file.sections.items(.shdr)[elf_file.eh_frame_section_index.?].sh_addr,
461 elf_file.sections.items(.shdr)[elf_file.section_indexes.eh_frame.?].sh_addr,
462462 });
463463
464464 if (elf_file.zigObjectPtr()) |zo| zo: {
......@@ -511,8 +511,8 @@ pub fn writeEhFrameHdr(elf_file: *Elf, writer: anytype) !void {
511511 try writer.writeByte(DW_EH_PE.datarel | DW_EH_PE.sdata4);
512512
513513 const shdrs = elf_file.sections.items(.shdr);
514 const eh_frame_shdr = shdrs[elf_file.eh_frame_section_index.?];
515 const eh_frame_hdr_shdr = shdrs[elf_file.eh_frame_hdr_section_index.?];
514 const eh_frame_shdr = shdrs[elf_file.section_indexes.eh_frame.?];
515 const eh_frame_hdr_shdr = shdrs[elf_file.section_indexes.eh_frame_hdr.?];
516516 const num_fdes = @as(u32, @intCast(@divExact(eh_frame_hdr_shdr.sh_size - eh_frame_hdr_header_size, 8)));
517517 const existing_size = existing_size: {
518518 const zo = elf_file.zigObjectPtr() orelse break :existing_size 0;
src/link/Elf/merge_section.zig deleted-340
......@@ -1,340 +0,0 @@
1pub const MergeSection = struct {
2 value: u64 = 0,
3 size: u64 = 0,
4 alignment: Atom.Alignment = .@"1",
5 entsize: u32 = 0,
6 name_offset: u32 = 0,
7 type: u32 = 0,
8 flags: u64 = 0,
9 output_section_index: u32 = 0,
10 bytes: std.ArrayListUnmanaged(u8) = .empty,
11 table: std.HashMapUnmanaged(
12 String,
13 MergeSubsection.Index,
14 IndexContext,
15 std.hash_map.default_max_load_percentage,
16 ) = .{},
17 subsections: std.ArrayListUnmanaged(MergeSubsection) = .empty,
18 finalized_subsections: std.ArrayListUnmanaged(MergeSubsection.Index) = .empty,
19
20 pub fn deinit(msec: *MergeSection, allocator: Allocator) void {
21 msec.bytes.deinit(allocator);
22 msec.table.deinit(allocator);
23 msec.subsections.deinit(allocator);
24 msec.finalized_subsections.deinit(allocator);
25 }
26
27 pub fn name(msec: MergeSection, elf_file: *Elf) [:0]const u8 {
28 return elf_file.getShString(msec.name_offset);
29 }
30
31 pub fn address(msec: MergeSection, elf_file: *Elf) i64 {
32 const shdr = elf_file.sections.items(.shdr)[msec.output_section_index];
33 return @intCast(shdr.sh_addr + msec.value);
34 }
35
36 const InsertResult = struct {
37 found_existing: bool,
38 key: String,
39 sub: *MergeSubsection.Index,
40 };
41
42 pub fn insert(msec: *MergeSection, allocator: Allocator, string: []const u8) !InsertResult {
43 const gop = try msec.table.getOrPutContextAdapted(
44 allocator,
45 string,
46 IndexAdapter{ .bytes = msec.bytes.items },
47 IndexContext{ .bytes = msec.bytes.items },
48 );
49 if (!gop.found_existing) {
50 const index: u32 = @intCast(msec.bytes.items.len);
51 try msec.bytes.appendSlice(allocator, string);
52 gop.key_ptr.* = .{ .pos = index, .len = @intCast(string.len) };
53 }
54 return .{ .found_existing = gop.found_existing, .key = gop.key_ptr.*, .sub = gop.value_ptr };
55 }
56
57 pub fn insertZ(msec: *MergeSection, allocator: Allocator, string: []const u8) !InsertResult {
58 const with_null = try allocator.alloc(u8, string.len + 1);
59 defer allocator.free(with_null);
60 @memcpy(with_null[0..string.len], string);
61 with_null[string.len] = 0;
62 return msec.insert(allocator, with_null);
63 }
64
65 /// Finalizes the merge section and clears hash table.
66 /// Sorts all owned subsections.
67 pub fn finalize(msec: *MergeSection, allocator: Allocator) !void {
68 try msec.finalized_subsections.ensureTotalCapacityPrecise(allocator, msec.subsections.items.len);
69
70 var it = msec.table.iterator();
71 while (it.next()) |entry| {
72 const msub = msec.mergeSubsection(entry.value_ptr.*);
73 if (!msub.alive) continue;
74 msec.finalized_subsections.appendAssumeCapacity(entry.value_ptr.*);
75 }
76 msec.table.clearAndFree(allocator);
77
78 const sortFn = struct {
79 pub fn sortFn(ctx: *MergeSection, lhs: MergeSubsection.Index, rhs: MergeSubsection.Index) bool {
80 const lhs_msub = ctx.mergeSubsection(lhs);
81 const rhs_msub = ctx.mergeSubsection(rhs);
82 if (lhs_msub.alignment.compareStrict(.eq, rhs_msub.alignment)) {
83 if (lhs_msub.size == rhs_msub.size) {
84 const lhs_string = ctx.bytes.items[lhs_msub.string_index..][0..lhs_msub.size];
85 const rhs_string = ctx.bytes.items[rhs_msub.string_index..][0..rhs_msub.size];
86 return mem.order(u8, lhs_string, rhs_string) == .lt;
87 }
88 return lhs_msub.size < rhs_msub.size;
89 }
90 return lhs_msub.alignment.compareStrict(.lt, rhs_msub.alignment);
91 }
92 }.sortFn;
93
94 std.mem.sort(MergeSubsection.Index, msec.finalized_subsections.items, msec, sortFn);
95 }
96
97 pub fn updateSize(msec: *MergeSection) void {
98 // TODO a 'stale' flag would be better here perhaps?
99 msec.size = 0;
100 msec.alignment = .@"1";
101 msec.entsize = 0;
102 for (msec.finalized_subsections.items) |msub_index| {
103 const msub = msec.mergeSubsection(msub_index);
104 assert(msub.alive);
105 const offset = msub.alignment.forward(msec.size);
106 const padding = offset - msec.size;
107 msub.value = @intCast(offset);
108 msec.size += padding + msub.size;
109 msec.alignment = msec.alignment.max(msub.alignment);
110 msec.entsize = if (msec.entsize == 0) msub.entsize else @min(msec.entsize, msub.entsize);
111 }
112 }
113
114 pub fn initOutputSection(msec: *MergeSection, elf_file: *Elf) !void {
115 msec.output_section_index = elf_file.sectionByName(msec.name(elf_file)) orelse try elf_file.addSection(.{
116 .name = msec.name_offset,
117 .type = msec.type,
118 .flags = msec.flags,
119 });
120 }
121
122 pub fn addMergeSubsection(msec: *MergeSection, allocator: Allocator) !MergeSubsection.Index {
123 const index: MergeSubsection.Index = @intCast(msec.subsections.items.len);
124 const msub = try msec.subsections.addOne(allocator);
125 msub.* = .{};
126 return index;
127 }
128
129 pub fn mergeSubsection(msec: *MergeSection, index: MergeSubsection.Index) *MergeSubsection {
130 assert(index < msec.subsections.items.len);
131 return &msec.subsections.items[index];
132 }
133
134 pub const IndexContext = struct {
135 bytes: []const u8,
136
137 pub fn eql(_: @This(), a: String, b: String) bool {
138 return a.pos == b.pos;
139 }
140
141 pub fn hash(ctx: @This(), key: String) u64 {
142 const str = ctx.bytes[key.pos..][0..key.len];
143 return std.hash_map.hashString(str);
144 }
145 };
146
147 pub const IndexAdapter = struct {
148 bytes: []const u8,
149
150 pub fn eql(ctx: @This(), a: []const u8, b: String) bool {
151 const str = ctx.bytes[b.pos..][0..b.len];
152 return mem.eql(u8, a, str);
153 }
154
155 pub fn hash(_: @This(), adapted_key: []const u8) u64 {
156 return std.hash_map.hashString(adapted_key);
157 }
158 };
159
160 pub fn format(
161 msec: MergeSection,
162 comptime unused_fmt_string: []const u8,
163 options: std.fmt.FormatOptions,
164 writer: anytype,
165 ) !void {
166 _ = msec;
167 _ = unused_fmt_string;
168 _ = options;
169 _ = writer;
170 @compileError("do not format MergeSection directly");
171 }
172
173 pub fn fmt(msec: MergeSection, elf_file: *Elf) std.fmt.Formatter(format2) {
174 return .{ .data = .{
175 .msec = msec,
176 .elf_file = elf_file,
177 } };
178 }
179
180 const FormatContext = struct {
181 msec: MergeSection,
182 elf_file: *Elf,
183 };
184
185 pub fn format2(
186 ctx: FormatContext,
187 comptime unused_fmt_string: []const u8,
188 options: std.fmt.FormatOptions,
189 writer: anytype,
190 ) !void {
191 _ = options;
192 _ = unused_fmt_string;
193 const msec = ctx.msec;
194 const elf_file = ctx.elf_file;
195 try writer.print("{s} : @{x} : size({x}) : align({x}) : entsize({x}) : type({x}) : flags({x})\n", .{
196 msec.name(elf_file),
197 msec.address(elf_file),
198 msec.size,
199 msec.alignment.toByteUnits() orelse 0,
200 msec.entsize,
201 msec.type,
202 msec.flags,
203 });
204 for (msec.subsections.items) |msub| {
205 try writer.print(" {}\n", .{msub.fmt(elf_file)});
206 }
207 }
208
209 pub const Index = u32;
210};
211
212pub const MergeSubsection = struct {
213 value: i64 = 0,
214 merge_section_index: MergeSection.Index = 0,
215 string_index: u32 = 0,
216 size: u32 = 0,
217 alignment: Atom.Alignment = .@"1",
218 entsize: u32 = 0,
219 alive: bool = false,
220
221 pub fn address(msub: MergeSubsection, elf_file: *Elf) i64 {
222 return msub.mergeSection(elf_file).address(elf_file) + msub.value;
223 }
224
225 pub fn mergeSection(msub: MergeSubsection, elf_file: *Elf) *MergeSection {
226 return elf_file.mergeSection(msub.merge_section_index);
227 }
228
229 pub fn getString(msub: MergeSubsection, elf_file: *Elf) []const u8 {
230 const msec = msub.mergeSection(elf_file);
231 return msec.bytes.items[msub.string_index..][0..msub.size];
232 }
233
234 pub fn format(
235 msub: MergeSubsection,
236 comptime unused_fmt_string: []const u8,
237 options: std.fmt.FormatOptions,
238 writer: anytype,
239 ) !void {
240 _ = msub;
241 _ = unused_fmt_string;
242 _ = options;
243 _ = writer;
244 @compileError("do not format MergeSubsection directly");
245 }
246
247 pub fn fmt(msub: MergeSubsection, elf_file: *Elf) std.fmt.Formatter(format2) {
248 return .{ .data = .{
249 .msub = msub,
250 .elf_file = elf_file,
251 } };
252 }
253
254 const FormatContext = struct {
255 msub: MergeSubsection,
256 elf_file: *Elf,
257 };
258
259 pub fn format2(
260 ctx: FormatContext,
261 comptime unused_fmt_string: []const u8,
262 options: std.fmt.FormatOptions,
263 writer: anytype,
264 ) !void {
265 _ = options;
266 _ = unused_fmt_string;
267 const msub = ctx.msub;
268 const elf_file = ctx.elf_file;
269 try writer.print("@{x} : align({x}) : size({x})", .{
270 msub.address(elf_file),
271 msub.alignment,
272 msub.size,
273 });
274 if (!msub.alive) try writer.writeAll(" : [*]");
275 }
276
277 pub const Index = u32;
278};
279
280pub const InputMergeSection = struct {
281 merge_section_index: MergeSection.Index = 0,
282 atom_index: Atom.Index = 0,
283 offsets: std.ArrayListUnmanaged(u32) = .empty,
284 subsections: std.ArrayListUnmanaged(MergeSubsection.Index) = .empty,
285 bytes: std.ArrayListUnmanaged(u8) = .empty,
286 strings: std.ArrayListUnmanaged(String) = .empty,
287
288 pub fn deinit(imsec: *InputMergeSection, allocator: Allocator) void {
289 imsec.offsets.deinit(allocator);
290 imsec.subsections.deinit(allocator);
291 imsec.bytes.deinit(allocator);
292 imsec.strings.deinit(allocator);
293 }
294
295 pub fn clearAndFree(imsec: *InputMergeSection, allocator: Allocator) void {
296 imsec.bytes.clearAndFree(allocator);
297 // TODO: imsec.strings.clearAndFree(allocator);
298 }
299
300 const FindSubsectionResult = struct {
301 msub_index: MergeSubsection.Index,
302 offset: u32,
303 };
304
305 pub fn findSubsection(imsec: InputMergeSection, offset: u32) ?FindSubsectionResult {
306 // TODO: binary search
307 for (imsec.offsets.items, 0..) |off, index| {
308 if (offset < off) return .{
309 .msub_index = imsec.subsections.items[index - 1],
310 .offset = offset - imsec.offsets.items[index - 1],
311 };
312 }
313 const last = imsec.offsets.items.len - 1;
314 const last_off = imsec.offsets.items[last];
315 const last_len = imsec.strings.items[last].len;
316 if (offset < last_off + last_len) return .{
317 .msub_index = imsec.subsections.items[last],
318 .offset = offset - last_off,
319 };
320 return null;
321 }
322
323 pub fn insert(imsec: *InputMergeSection, allocator: Allocator, string: []const u8) !void {
324 const index: u32 = @intCast(imsec.bytes.items.len);
325 try imsec.bytes.appendSlice(allocator, string);
326 try imsec.strings.append(allocator, .{ .pos = index, .len = @intCast(string.len) });
327 }
328
329 pub const Index = u32;
330};
331
332const String = struct { pos: u32, len: u32 };
333
334const assert = std.debug.assert;
335const mem = std.mem;
336const std = @import("std");
337
338const Allocator = mem.Allocator;
339const Atom = @import("Atom.zig");
340const Elf = @import("../Elf.zig");
src/link/Elf/relocatable.zig+31-13
......@@ -32,7 +32,16 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation, module_obj_path: ?Path
3232 zig_object.claimUnresolvedRelocatable(elf_file);
3333
3434 try initSections(elf_file);
35 try elf_file.sortShdrs();
35 try Elf.sortShdrs(
36 gpa,
37 &elf_file.section_indexes,
38 &elf_file.sections,
39 elf_file.shstrtab.items,
40 elf_file.merge_sections.items,
41 elf_file.comdat_group_sections.items,
42 elf_file.zigObjectPtr(),
43 elf_file.files,
44 );
3645 try zig_object.addAtomsToRelaSections(elf_file);
3746 try elf_file.updateMergeSectionSizes();
3847 try updateSectionSizes(elf_file);
......@@ -171,7 +180,16 @@ pub fn flushObject(elf_file: *Elf, comp: *Compilation, module_obj_path: ?Path) l
171180 claimUnresolved(elf_file);
172181
173182 try initSections(elf_file);
174 try elf_file.sortShdrs();
183 try Elf.sortShdrs(
184 comp.gpa,
185 &elf_file.section_indexes,
186 &elf_file.sections,
187 elf_file.shstrtab.items,
188 elf_file.merge_sections.items,
189 elf_file.comdat_group_sections.items,
190 elf_file.zigObjectPtr(),
191 elf_file.files,
192 );
175193 if (elf_file.zigObjectPtr()) |zig_object| {
176194 try zig_object.addAtomsToRelaSections(elf_file);
177195 }
......@@ -288,8 +306,8 @@ fn initSections(elf_file: *Elf) !void {
288306 } else false;
289307 };
290308 if (needs_eh_frame) {
291 if (elf_file.eh_frame_section_index == null) {
292 elf_file.eh_frame_section_index = elf_file.sectionByName(".eh_frame") orelse
309 if (elf_file.section_indexes.eh_frame == null) {
310 elf_file.section_indexes.eh_frame = elf_file.sectionByName(".eh_frame") orelse
293311 try elf_file.addSection(.{
294312 .name = try elf_file.insertShString(".eh_frame"),
295313 .type = if (elf_file.getTarget().cpu.arch == .x86_64)
......@@ -300,10 +318,10 @@ fn initSections(elf_file: *Elf) !void {
300318 .addralign = elf_file.ptrWidthBytes(),
301319 });
302320 }
303 elf_file.eh_frame_rela_section_index = elf_file.sectionByName(".rela.eh_frame") orelse
321 elf_file.section_indexes.eh_frame_rela = elf_file.sectionByName(".rela.eh_frame") orelse
304322 try elf_file.addRelaShdr(
305323 try elf_file.insertShString(".rela.eh_frame"),
306 elf_file.eh_frame_section_index.?,
324 elf_file.section_indexes.eh_frame.?,
307325 );
308326 }
309327
......@@ -346,7 +364,7 @@ fn updateSectionSizes(elf_file: *Elf) !void {
346364 for (slice.items(.shdr), 0..) |*shdr, shndx| {
347365 const atom_list = slice.items(.atom_list)[shndx];
348366 if (shdr.sh_type != elf.SHT_RELA) continue;
349 if (@as(u32, @intCast(shndx)) == elf_file.eh_frame_section_index) continue;
367 if (@as(u32, @intCast(shndx)) == elf_file.section_indexes.eh_frame) continue;
350368 for (atom_list.items) |ref| {
351369 const atom_ptr = elf_file.atom(ref) orelse continue;
352370 if (!atom_ptr.alive) continue;
......@@ -357,10 +375,10 @@ fn updateSectionSizes(elf_file: *Elf) !void {
357375 if (shdr.sh_size == 0) shdr.sh_offset = 0;
358376 }
359377
360 if (elf_file.eh_frame_section_index) |index| {
378 if (elf_file.section_indexes.eh_frame) |index| {
361379 slice.items(.shdr)[index].sh_size = try eh_frame.calcEhFrameSize(elf_file);
362380 }
363 if (elf_file.eh_frame_rela_section_index) |index| {
381 if (elf_file.section_indexes.eh_frame_rela) |index| {
364382 const shdr = &slice.items(.shdr)[index];
365383 shdr.sh_size = eh_frame.calcEhFrameRelocs(elf_file) * shdr.sh_entsize;
366384 }
......@@ -374,7 +392,7 @@ fn updateComdatGroupsSizes(elf_file: *Elf) void {
374392 for (elf_file.comdat_group_sections.items) |cg| {
375393 const shdr = &elf_file.sections.items(.shdr)[cg.shndx];
376394 shdr.sh_size = cg.size(elf_file);
377 shdr.sh_link = elf_file.symtab_section_index.?;
395 shdr.sh_link = elf_file.section_indexes.symtab.?;
378396
379397 const sym = cg.symbol(elf_file);
380398 shdr.sh_info = sym.outputSymtabIndex(elf_file) orelse sym.outputShndx(elf_file).?;
......@@ -439,7 +457,7 @@ fn writeSyntheticSections(elf_file: *Elf) !void {
439457 for (slice.items(.shdr), slice.items(.atom_list), 0..) |shdr, atom_list, shndx| {
440458 if (shdr.sh_type != elf.SHT_RELA) continue;
441459 if (atom_list.items.len == 0) continue;
442 if (@as(u32, @intCast(shndx)) == elf_file.eh_frame_section_index) continue;
460 if (@as(u32, @intCast(shndx)) == elf_file.section_indexes.eh_frame) continue;
443461
444462 const num_relocs = math.cast(usize, @divExact(shdr.sh_size, shdr.sh_entsize)) orelse
445463 return error.Overflow;
......@@ -471,7 +489,7 @@ fn writeSyntheticSections(elf_file: *Elf) !void {
471489 try elf_file.base.file.?.pwriteAll(mem.sliceAsBytes(relocs.items), shdr.sh_offset);
472490 }
473491
474 if (elf_file.eh_frame_section_index) |shndx| {
492 if (elf_file.section_indexes.eh_frame) |shndx| {
475493 const existing_size = existing_size: {
476494 const zo = elf_file.zigObjectPtr() orelse break :existing_size 0;
477495 const sym = zo.symbol(zo.eh_frame_index orelse break :existing_size 0);
......@@ -489,7 +507,7 @@ fn writeSyntheticSections(elf_file: *Elf) !void {
489507 assert(buffer.items.len == sh_size - existing_size);
490508 try elf_file.base.file.?.pwriteAll(buffer.items, shdr.sh_offset + existing_size);
491509 }
492 if (elf_file.eh_frame_rela_section_index) |shndx| {
510 if (elf_file.section_indexes.eh_frame_rela) |shndx| {
493511 const shdr = slice.items(.shdr)[shndx];
494512 const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow;
495513 var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size);
src/link/Elf/synthetic_sections.zig+27-27
......@@ -75,18 +75,18 @@ pub const DynamicSection = struct {
7575 if (elf_file.sectionByName(".fini") != null) nentries += 1; // FINI
7676 if (elf_file.sectionByName(".init_array") != null) nentries += 2; // INIT_ARRAY
7777 if (elf_file.sectionByName(".fini_array") != null) nentries += 2; // FINI_ARRAY
78 if (elf_file.rela_dyn_section_index != null) nentries += 3; // RELA
79 if (elf_file.rela_plt_section_index != null) nentries += 3; // JMPREL
80 if (elf_file.got_plt_section_index != null) nentries += 1; // PLTGOT
78 if (elf_file.section_indexes.rela_dyn != null) nentries += 3; // RELA
79 if (elf_file.section_indexes.rela_plt != null) nentries += 3; // JMPREL
80 if (elf_file.section_indexes.got_plt != null) nentries += 1; // PLTGOT
8181 nentries += 1; // HASH
82 if (elf_file.gnu_hash_section_index != null) nentries += 1; // GNU_HASH
82 if (elf_file.section_indexes.gnu_hash != null) nentries += 1; // GNU_HASH
8383 if (elf_file.has_text_reloc) nentries += 1; // TEXTREL
8484 nentries += 1; // SYMTAB
8585 nentries += 1; // SYMENT
8686 nentries += 1; // STRTAB
8787 nentries += 1; // STRSZ
88 if (elf_file.versym_section_index != null) nentries += 1; // VERSYM
89 if (elf_file.verneed_section_index != null) nentries += 2; // VERNEED
88 if (elf_file.section_indexes.versym != null) nentries += 1; // VERSYM
89 if (elf_file.section_indexes.verneed != null) nentries += 2; // VERNEED
9090 if (dt.getFlags(elf_file) != null) nentries += 1; // FLAGS
9191 if (dt.getFlags1(elf_file) != null) nentries += 1; // FLAGS_1
9292 if (!elf_file.isEffectivelyDynLib()) nentries += 1; // DEBUG
......@@ -139,7 +139,7 @@ pub const DynamicSection = struct {
139139 }
140140
141141 // RELA
142 if (elf_file.rela_dyn_section_index) |shndx| {
142 if (elf_file.section_indexes.rela_dyn) |shndx| {
143143 const shdr = shdrs[shndx];
144144 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_RELA, .d_val = shdr.sh_addr });
145145 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_RELASZ, .d_val = shdr.sh_size });
......@@ -147,7 +147,7 @@ pub const DynamicSection = struct {
147147 }
148148
149149 // JMPREL
150 if (elf_file.rela_plt_section_index) |shndx| {
150 if (elf_file.section_indexes.rela_plt) |shndx| {
151151 const shdr = shdrs[shndx];
152152 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_JMPREL, .d_val = shdr.sh_addr });
153153 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_PLTRELSZ, .d_val = shdr.sh_size });
......@@ -155,18 +155,18 @@ pub const DynamicSection = struct {
155155 }
156156
157157 // PLTGOT
158 if (elf_file.got_plt_section_index) |shndx| {
158 if (elf_file.section_indexes.got_plt) |shndx| {
159159 const addr = shdrs[shndx].sh_addr;
160160 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_PLTGOT, .d_val = addr });
161161 }
162162
163163 {
164 assert(elf_file.hash_section_index != null);
165 const addr = shdrs[elf_file.hash_section_index.?].sh_addr;
164 assert(elf_file.section_indexes.hash != null);
165 const addr = shdrs[elf_file.section_indexes.hash.?].sh_addr;
166166 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_HASH, .d_val = addr });
167167 }
168168
169 if (elf_file.gnu_hash_section_index) |shndx| {
169 if (elf_file.section_indexes.gnu_hash) |shndx| {
170170 const addr = shdrs[shndx].sh_addr;
171171 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_GNU_HASH, .d_val = addr });
172172 }
......@@ -178,28 +178,28 @@ pub const DynamicSection = struct {
178178
179179 // SYMTAB + SYMENT
180180 {
181 assert(elf_file.dynsymtab_section_index != null);
182 const shdr = shdrs[elf_file.dynsymtab_section_index.?];
181 assert(elf_file.section_indexes.dynsymtab != null);
182 const shdr = shdrs[elf_file.section_indexes.dynsymtab.?];
183183 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_SYMTAB, .d_val = shdr.sh_addr });
184184 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_SYMENT, .d_val = shdr.sh_entsize });
185185 }
186186
187187 // STRTAB + STRSZ
188188 {
189 assert(elf_file.dynstrtab_section_index != null);
190 const shdr = shdrs[elf_file.dynstrtab_section_index.?];
189 assert(elf_file.section_indexes.dynstrtab != null);
190 const shdr = shdrs[elf_file.section_indexes.dynstrtab.?];
191191 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_STRTAB, .d_val = shdr.sh_addr });
192192 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_STRSZ, .d_val = shdr.sh_size });
193193 }
194194
195195 // VERSYM
196 if (elf_file.versym_section_index) |shndx| {
196 if (elf_file.section_indexes.versym) |shndx| {
197197 const addr = shdrs[shndx].sh_addr;
198198 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_VERSYM, .d_val = addr });
199199 }
200200
201201 // VERNEED + VERNEEDNUM
202 if (elf_file.verneed_section_index) |shndx| {
202 if (elf_file.section_indexes.verneed) |shndx| {
203203 const addr = shdrs[shndx].sh_addr;
204204 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_VERNEED, .d_val = addr });
205205 try writer.writeStruct(elf.Elf64_Dyn{
......@@ -261,7 +261,7 @@ pub const GotSection = struct {
261261
262262 pub fn address(entry: Entry, elf_file: *Elf) i64 {
263263 const ptr_bytes = elf_file.archPtrWidthBytes();
264 const shdr = &elf_file.sections.items(.shdr)[elf_file.got_section_index.?];
264 const shdr = &elf_file.sections.items(.shdr)[elf_file.section_indexes.got.?];
265265 return @as(i64, @intCast(shdr.sh_addr)) + entry.cell_index * ptr_bytes;
266266 }
267267 };
......@@ -599,7 +599,7 @@ pub const GotSection = struct {
599599 .st_name = st_name,
600600 .st_info = elf.STT_OBJECT,
601601 .st_other = 0,
602 .st_shndx = @intCast(elf_file.got_section_index.?),
602 .st_shndx = @intCast(elf_file.section_indexes.got.?),
603603 .st_value = @intCast(st_value),
604604 .st_size = st_size,
605605 };
......@@ -742,7 +742,7 @@ pub const PltSection = struct {
742742 .st_name = st_name,
743743 .st_info = elf.STT_FUNC,
744744 .st_other = 0,
745 .st_shndx = @intCast(elf_file.plt_section_index.?),
745 .st_shndx = @intCast(elf_file.section_indexes.plt.?),
746746 .st_value = @intCast(sym.pltAddress(elf_file)),
747747 .st_size = entrySize(cpu_arch),
748748 };
......@@ -784,8 +784,8 @@ pub const PltSection = struct {
784784 const x86_64 = struct {
785785 fn write(plt: PltSection, elf_file: *Elf, writer: anytype) !void {
786786 const shdrs = elf_file.sections.items(.shdr);
787 const plt_addr = shdrs[elf_file.plt_section_index.?].sh_addr;
788 const got_plt_addr = shdrs[elf_file.got_plt_section_index.?].sh_addr;
787 const plt_addr = shdrs[elf_file.section_indexes.plt.?].sh_addr;
788 const got_plt_addr = shdrs[elf_file.section_indexes.got_plt.?].sh_addr;
789789 var preamble = [_]u8{
790790 0xf3, 0x0f, 0x1e, 0xfa, // endbr64
791791 0x41, 0x53, // push r11
......@@ -820,8 +820,8 @@ pub const PltSection = struct {
820820 fn write(plt: PltSection, elf_file: *Elf, writer: anytype) !void {
821821 {
822822 const shdrs = elf_file.sections.items(.shdr);
823 const plt_addr: i64 = @intCast(shdrs[elf_file.plt_section_index.?].sh_addr);
824 const got_plt_addr: i64 = @intCast(shdrs[elf_file.got_plt_section_index.?].sh_addr);
823 const plt_addr: i64 = @intCast(shdrs[elf_file.section_indexes.plt.?].sh_addr);
824 const got_plt_addr: i64 = @intCast(shdrs[elf_file.section_indexes.got_plt.?].sh_addr);
825825 // TODO: relax if possible
826826 // .got.plt[2]
827827 const pages = try aarch64_util.calcNumberOfPages(plt_addr + 4, got_plt_addr + 16);
......@@ -894,7 +894,7 @@ pub const GotPltSection = struct {
894894 // [2]: 0x0
895895 try writer.writeInt(u64, 0x0, .little);
896896 try writer.writeInt(u64, 0x0, .little);
897 if (elf_file.plt_section_index) |shndx| {
897 if (elf_file.section_indexes.plt) |shndx| {
898898 const plt_addr = elf_file.sections.items(.shdr)[shndx].sh_addr;
899899 for (0..elf_file.plt.symbols.items.len) |_| {
900900 // [N]: .plt
......@@ -962,7 +962,7 @@ pub const PltGotSection = struct {
962962 .st_name = st_name,
963963 .st_info = elf.STT_FUNC,
964964 .st_other = 0,
965 .st_shndx = @intCast(elf_file.plt_got_section_index.?),
965 .st_shndx = @intCast(elf_file.section_indexes.plt_got.?),
966966 .st_value = @intCast(sym.pltGotAddress(elf_file)),
967967 .st_size = 16,
968968 };