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...@@ -603,18 +603,18 @@ set(ZIG_STAGE2_SOURCES
603 src/link/Elf/AtomList.zig603 src/link/Elf/AtomList.zig
604 src/link/Elf/LdScript.zig604 src/link/Elf/LdScript.zig
605 src/link/Elf/LinkerDefined.zig605 src/link/Elf/LinkerDefined.zig
606 src/link/Elf/Merge.zig
606 src/link/Elf/Object.zig607 src/link/Elf/Object.zig
607 src/link/Elf/SharedObject.zig608 src/link/Elf/SharedObject.zig
608 src/link/Elf/Symbol.zig609 src/link/Elf/Symbol.zig
610 src/link/Elf/Thunk.zig
609 src/link/Elf/ZigObject.zig611 src/link/Elf/ZigObject.zig
610 src/link/Elf/eh_frame.zig612 src/link/Elf/eh_frame.zig
611 src/link/Elf/file.zig613 src/link/Elf/file.zig
612 src/link/Elf/gc.zig614 src/link/Elf/gc.zig
613 src/link/Elf/merge_section.zig
614 src/link/Elf/relocatable.zig615 src/link/Elf/relocatable.zig
615 src/link/Elf/relocation.zig616 src/link/Elf/relocation.zig
616 src/link/Elf/synthetic_sections.zig617 src/link/Elf/synthetic_sections.zig
617 src/link/Elf/Thunk.zig
618 src/link/MachO.zig618 src/link/MachO.zig
619 src/link/MachO/Archive.zig619 src/link/MachO/Archive.zig
620 src/link/MachO/Atom.zig620 src/link/MachO/Atom.zig
lib/std/multi_array_list.zig+7-1
...@@ -23,6 +23,12 @@ pub fn MultiArrayList(comptime T: type) type {...@@ -23,6 +23,12 @@ pub fn MultiArrayList(comptime T: type) type {
23 len: usize = 0,23 len: usize = 0,
24 capacity: usize = 0,24 capacity: usize = 0,
2525
26 pub const empty: Self = .{
27 .bytes = undefined,
28 .len = 0,
29 .capacity = 0,
30 };
31
26 const Elem = switch (@typeInfo(T)) {32 const Elem = switch (@typeInfo(T)) {
27 .@"struct" => T,33 .@"struct" => T,
28 .@"union" => |u| struct {34 .@"union" => |u| struct {
...@@ -474,7 +480,7 @@ pub fn MultiArrayList(comptime T: type) type {...@@ -474,7 +480,7 @@ pub fn MultiArrayList(comptime T: type) type {
474 pub fn swap(sc: @This(), a_index: usize, b_index: usize) void {480 pub fn swap(sc: @This(), a_index: usize, b_index: usize) void {
475 inline for (fields, 0..) |field_info, i| {481 inline for (fields, 0..) |field_info, i| {
476 if (@sizeOf(field_info.type) != 0) {482 if (@sizeOf(field_info.type) != 0) {
477 const field = @as(Field, @enumFromInt(i));483 const field: Field = @enumFromInt(i);
478 const ptr = sc.slice.items(field);484 const ptr = sc.slice.items(field);
479 mem.swap(field_info.type, &ptr[a_index], &ptr[b_index]);485 mem.swap(field_info.type, &ptr[a_index], &ptr[b_index]);
480 }486 }
src/link/Elf.zig+377-333
...@@ -1,3 +1,5 @@...@@ -1,3 +1,5 @@
1pub const Atom = @import("Elf/Atom.zig");
2
1base: link.File,3base: link.File,
2rpath_table: std.StringArrayHashMapUnmanaged(void),4rpath_table: std.StringArrayHashMapUnmanaged(void),
3image_base: u64,5image_base: u64,
...@@ -53,26 +55,11 @@ shdr_table_offset: ?u64 = null,...@@ -53,26 +55,11 @@ shdr_table_offset: ?u64 = null,
5355
54/// Stored in native-endian format, depending on target endianness needs to be bswapped on read/write.56/// Stored in native-endian format, depending on target endianness needs to be bswapped on read/write.
55/// Same order as in the file.57/// Same order as in the file.
56phdrs: std.ArrayListUnmanaged(elf.Elf64_Phdr) = .empty,58phdrs: ProgramHeaderList = .empty,
5759
58/// Special program headers60/// Special program headers.
59/// PT_PHDR61phdr_indexes: ProgramHeaderIndexes = .{},
60phdr_table_index: ?u16 = null,62section_indexes: SectionIndexes = .{},
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,
7663
77page_size: u32,64page_size: u32,
78default_sym_version: elf.Elf64_Versym,65default_sym_version: elf.Elf64_Versym,
...@@ -115,29 +102,6 @@ rela_plt: std.ArrayListUnmanaged(elf.Elf64_Rela) = .empty,...@@ -115,29 +102,6 @@ rela_plt: std.ArrayListUnmanaged(elf.Elf64_Rela) = .empty,
115/// Applies only to a relocatable.102/// Applies only to a relocatable.
116comdat_group_sections: std.ArrayListUnmanaged(ComdatGroupSection) = .empty,103comdat_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
141resolver: SymbolResolver = .{},105resolver: SymbolResolver = .{},
142106
143has_text_reloc: bool = false,107has_text_reloc: bool = false,
...@@ -147,11 +111,87 @@ num_ifunc_dynrelocs: usize = 0,...@@ -147,11 +111,87 @@ num_ifunc_dynrelocs: usize = 0,
147thunks: std.ArrayListUnmanaged(Thunk) = .empty,111thunks: std.ArrayListUnmanaged(Thunk) = .empty,
148112
149/// List of output merge sections with deduped contents.113/// List of output merge sections with deduped contents.
150merge_sections: std.ArrayListUnmanaged(MergeSection) = .empty,114merge_sections: std.ArrayListUnmanaged(Merge.Section) = .empty,
151comment_merge_section_index: ?MergeSection.Index = null,115comment_merge_section_index: ?Merge.Section.Index = null,
152116
153first_eflags: ?elf.Elf64_Word = null,117first_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
155/// When allocating, the ideal_capacity is calculated by195/// When allocating, the ideal_capacity is calculated by
156/// actual_capacity + (actual_capacity / ideal_factor)196/// actual_capacity + (actual_capacity / ideal_factor)
157const ideal_factor = 3;197const ideal_factor = 3;
...@@ -358,7 +398,7 @@ pub fn createEmpty(...@@ -358,7 +398,7 @@ pub fn createEmpty(
358 };398 };
359 const max_nphdrs = comptime getMaxNumberOfPhdrs();399 const max_nphdrs = comptime getMaxNumberOfPhdrs();
360 const reserved: u64 = mem.alignForward(u64, padToIdeal(max_nphdrs * phsize), self.page_size);400 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(.{
362 .type = elf.PT_PHDR,402 .type = elf.PT_PHDR,
363 .flags = elf.PF_R,403 .flags = elf.PF_R,
364 .@"align" = p_align,404 .@"align" = p_align,
...@@ -366,8 +406,8 @@ pub fn createEmpty(...@@ -366,8 +406,8 @@ pub fn createEmpty(
366 .offset = ehsize,406 .offset = ehsize,
367 .filesz = reserved,407 .filesz = reserved,
368 .memsz = reserved,408 .memsz = reserved,
369 });409 })).toOptional();
370 self.phdr_table_load_index = try self.addPhdr(.{410 self.phdr_indexes.table_load = (try self.addPhdr(.{
371 .type = elf.PT_LOAD,411 .type = elf.PT_LOAD,
372 .flags = elf.PF_R,412 .flags = elf.PF_R,
373 .@"align" = self.page_size,413 .@"align" = self.page_size,
...@@ -375,7 +415,7 @@ pub fn createEmpty(...@@ -375,7 +415,7 @@ pub fn createEmpty(
375 .offset = 0,415 .offset = 0,
376 .filesz = reserved + ehsize,416 .filesz = reserved + ehsize,
377 .memsz = reserved + ehsize,417 .memsz = reserved + ehsize,
378 });418 })).toOptional();
379 }419 }
380420
381 if (opt_zcu) |zcu| {421 if (opt_zcu) |zcu| {
...@@ -952,7 +992,16 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod...@@ -952,7 +992,16 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod
952 // Generate and emit synthetic sections.992 // Generate and emit synthetic sections.
953 try self.initSyntheticSections();993 try self.initSyntheticSections();
954 try self.initSpecialPhdrs();994 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
957 try self.setDynamicSection(self.rpath_table.keys());1006 try self.setDynamicSection(self.rpath_table.keys());
958 self.sortDynamicSymtab();1007 self.sortDynamicSymtab();
...@@ -966,7 +1015,7 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod...@@ -966,7 +1015,7 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod
966 try self.addLoadPhdrs();1015 try self.addLoadPhdrs();
967 try self.allocatePhdrTable();1016 try self.allocatePhdrTable();
968 try self.allocateAllocSections();1017 try self.allocateAllocSections();
969 try self.sortPhdrs();1018 try sortPhdrs(gpa, &self.phdrs, &self.phdr_indexes, self.sections.items(.phndx));
970 try self.allocateNonAllocSections();1019 try self.allocateNonAllocSections();
971 self.allocateSpecialPhdrs();1020 self.allocateSpecialPhdrs();
972 if (self.linkerDefinedPtr()) |obj| {1021 if (self.linkerDefinedPtr()) |obj| {
...@@ -2461,7 +2510,7 @@ fn writePhdrTable(self: *Elf) !void {...@@ -2461,7 +2510,7 @@ fn writePhdrTable(self: *Elf) !void {
2461 const gpa = self.base.comp.gpa;2510 const gpa = self.base.comp.gpa;
2462 const target_endian = self.getTarget().cpu.arch.endian();2511 const target_endian = self.getTarget().cpu.arch.endian();
2463 const foreign_endian = target_endian != builtin.cpu.arch.endian();2512 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
2466 log.debug("writing program headers from 0x{x} to 0x{x}", .{2515 log.debug("writing program headers from 0x{x} to 0x{x}", .{
2467 phdr_table.p_offset,2516 phdr_table.p_offset,
...@@ -2573,18 +2622,18 @@ pub fn writeElfHeader(self: *Elf) !void {...@@ -2573,18 +2622,18 @@ pub fn writeElfHeader(self: *Elf) !void {
2573 const entry_sym = obj.entrySymbol(self) orelse break :blk 0;2622 const entry_sym = obj.entrySymbol(self) orelse break :blk 0;
2574 break :blk @intCast(entry_sym.address(.{}, self));2623 break :blk @intCast(entry_sym.address(.{}, self));
2575 } else 0;2624 } 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;
2577 switch (self.ptr_width) {2626 switch (self.ptr_width) {
2578 .p32 => {2627 .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);
2580 index += 4;2629 index += 4;
25812630
2582 // e_phoff2631 // 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);
2584 index += 4;2633 index += 4;
25852634
2586 // e_shoff2635 // 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);
2588 index += 4;2637 index += 4;
2589 },2638 },
2590 .p64 => {2639 .p64 => {
...@@ -2631,11 +2680,11 @@ pub fn writeElfHeader(self: *Elf) !void {...@@ -2631,11 +2680,11 @@ pub fn writeElfHeader(self: *Elf) !void {
2631 mem.writeInt(u16, hdr_buf[index..][0..2], e_shentsize, endian);2680 mem.writeInt(u16, hdr_buf[index..][0..2], e_shentsize, endian);
2632 index += 2;2681 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);
2635 mem.writeInt(u16, hdr_buf[index..][0..2], e_shnum, endian);2684 mem.writeInt(u16, hdr_buf[index..][0..2], e_shnum, endian);
2636 index += 2;2685 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);
2639 index += 2;2688 index += 2;
26402689
2641 assert(index == e_ehsize);2690 assert(index == e_ehsize);
...@@ -2853,8 +2902,8 @@ fn initSyntheticSections(self: *Elf) !void {...@@ -2853,8 +2902,8 @@ fn initSyntheticSections(self: *Elf) !void {
2853 } else false;2902 } else false;
2854 };2903 };
2855 if (needs_eh_frame) {2904 if (needs_eh_frame) {
2856 if (self.eh_frame_section_index == null) {2905 if (self.section_indexes.eh_frame == null) {
2857 self.eh_frame_section_index = self.sectionByName(".eh_frame") orelse try self.addSection(.{2906 self.section_indexes.eh_frame = self.sectionByName(".eh_frame") orelse try self.addSection(.{
2858 .name = try self.insertShString(".eh_frame"),2907 .name = try self.insertShString(".eh_frame"),
2859 .type = if (target.cpu.arch == .x86_64)2908 .type = if (target.cpu.arch == .x86_64)
2860 elf.SHT_X86_64_UNWIND2909 elf.SHT_X86_64_UNWIND
...@@ -2864,8 +2913,8 @@ fn initSyntheticSections(self: *Elf) !void {...@@ -2864,8 +2913,8 @@ fn initSyntheticSections(self: *Elf) !void {
2864 .addralign = ptr_size,2913 .addralign = ptr_size,
2865 });2914 });
2866 }2915 }
2867 if (comp.link_eh_frame_hdr and self.eh_frame_hdr_section_index == null) {2916 if (comp.link_eh_frame_hdr and self.section_indexes.eh_frame_hdr == null) {
2868 self.eh_frame_hdr_section_index = try self.addSection(.{2917 self.section_indexes.eh_frame_hdr = try self.addSection(.{
2869 .name = try self.insertShString(".eh_frame_hdr"),2918 .name = try self.insertShString(".eh_frame_hdr"),
2870 .type = elf.SHT_PROGBITS,2919 .type = elf.SHT_PROGBITS,
2871 .flags = elf.SHF_ALLOC,2920 .flags = elf.SHF_ALLOC,
...@@ -2874,8 +2923,8 @@ fn initSyntheticSections(self: *Elf) !void {...@@ -2874,8 +2923,8 @@ fn initSyntheticSections(self: *Elf) !void {
2874 }2923 }
2875 }2924 }
28762925
2877 if (self.got.entries.items.len > 0 and self.got_section_index == null) {2926 if (self.got.entries.items.len > 0 and self.section_indexes.got == null) {
2878 self.got_section_index = try self.addSection(.{2927 self.section_indexes.got = try self.addSection(.{
2879 .name = try self.insertShString(".got"),2928 .name = try self.insertShString(".got"),
2880 .type = elf.SHT_PROGBITS,2929 .type = elf.SHT_PROGBITS,
2881 .flags = elf.SHF_ALLOC | elf.SHF_WRITE,2930 .flags = elf.SHF_ALLOC | elf.SHF_WRITE,
...@@ -2883,8 +2932,8 @@ fn initSyntheticSections(self: *Elf) !void {...@@ -2883,8 +2932,8 @@ fn initSyntheticSections(self: *Elf) !void {
2883 });2932 });
2884 }2933 }
28852934
2886 if (self.got_plt_section_index == null) {2935 if (self.section_indexes.got_plt == null) {
2887 self.got_plt_section_index = try self.addSection(.{2936 self.section_indexes.got_plt = try self.addSection(.{
2888 .name = try self.insertShString(".got.plt"),2937 .name = try self.insertShString(".got.plt"),
2889 .type = elf.SHT_PROGBITS,2938 .type = elf.SHT_PROGBITS,
2890 .flags = elf.SHF_ALLOC | elf.SHF_WRITE,2939 .flags = elf.SHF_ALLOC | elf.SHF_WRITE,
...@@ -2903,8 +2952,8 @@ fn initSyntheticSections(self: *Elf) !void {...@@ -2903,8 +2952,8 @@ fn initSyntheticSections(self: *Elf) !void {
2903 }2952 }
2904 break :blk false;2953 break :blk false;
2905 };2954 };
2906 if (needs_rela_dyn and self.rela_dyn_section_index == null) {2955 if (needs_rela_dyn and self.section_indexes.rela_dyn == null) {
2907 self.rela_dyn_section_index = try self.addSection(.{2956 self.section_indexes.rela_dyn = try self.addSection(.{
2908 .name = try self.insertShString(".rela.dyn"),2957 .name = try self.insertShString(".rela.dyn"),
2909 .type = elf.SHT_RELA,2958 .type = elf.SHT_RELA,
2910 .flags = elf.SHF_ALLOC,2959 .flags = elf.SHF_ALLOC,
...@@ -2914,16 +2963,16 @@ fn initSyntheticSections(self: *Elf) !void {...@@ -2914,16 +2963,16 @@ fn initSyntheticSections(self: *Elf) !void {
2914 }2963 }
29152964
2916 if (self.plt.symbols.items.len > 0) {2965 if (self.plt.symbols.items.len > 0) {
2917 if (self.plt_section_index == null) {2966 if (self.section_indexes.plt == null) {
2918 self.plt_section_index = try self.addSection(.{2967 self.section_indexes.plt = try self.addSection(.{
2919 .name = try self.insertShString(".plt"),2968 .name = try self.insertShString(".plt"),
2920 .type = elf.SHT_PROGBITS,2969 .type = elf.SHT_PROGBITS,
2921 .flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR,2970 .flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR,
2922 .addralign = 16,2971 .addralign = 16,
2923 });2972 });
2924 }2973 }
2925 if (self.rela_plt_section_index == null) {2974 if (self.section_indexes.rela_plt == null) {
2926 self.rela_plt_section_index = try self.addSection(.{2975 self.section_indexes.rela_plt = try self.addSection(.{
2927 .name = try self.insertShString(".rela.plt"),2976 .name = try self.insertShString(".rela.plt"),
2928 .type = elf.SHT_RELA,2977 .type = elf.SHT_RELA,
2929 .flags = elf.SHF_ALLOC,2978 .flags = elf.SHF_ALLOC,
...@@ -2933,8 +2982,8 @@ fn initSyntheticSections(self: *Elf) !void {...@@ -2933,8 +2982,8 @@ fn initSyntheticSections(self: *Elf) !void {
2933 }2982 }
2934 }2983 }
29352984
2936 if (self.plt_got.symbols.items.len > 0 and self.plt_got_section_index == null) {2985 if (self.plt_got.symbols.items.len > 0 and self.section_indexes.plt_got == null) {
2937 self.plt_got_section_index = try self.addSection(.{2986 self.section_indexes.plt_got = try self.addSection(.{
2938 .name = try self.insertShString(".plt.got"),2987 .name = try self.insertShString(".plt.got"),
2939 .type = elf.SHT_PROGBITS,2988 .type = elf.SHT_PROGBITS,
2940 .flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR,2989 .flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR,
...@@ -2942,8 +2991,8 @@ fn initSyntheticSections(self: *Elf) !void {...@@ -2942,8 +2991,8 @@ fn initSyntheticSections(self: *Elf) !void {
2942 });2991 });
2943 }2992 }
29442993
2945 if (self.copy_rel.symbols.items.len > 0 and self.copy_rel_section_index == null) {2994 if (self.copy_rel.symbols.items.len > 0 and self.section_indexes.copy_rel == null) {
2946 self.copy_rel_section_index = try self.addSection(.{2995 self.section_indexes.copy_rel = try self.addSection(.{
2947 .name = try self.insertShString(".copyrel"),2996 .name = try self.insertShString(".copyrel"),
2948 .type = elf.SHT_NOBITS,2997 .type = elf.SHT_NOBITS,
2949 .flags = elf.SHF_ALLOC | elf.SHF_WRITE,2998 .flags = elf.SHF_ALLOC | elf.SHF_WRITE,
...@@ -2959,8 +3008,8 @@ fn initSyntheticSections(self: *Elf) !void {...@@ -2959,8 +3008,8 @@ fn initSyntheticSections(self: *Elf) !void {
2959 if (self.base.isStatic() and !comp.config.pie) break :blk false;3008 if (self.base.isStatic() and !comp.config.pie) break :blk false;
2960 break :blk target.dynamic_linker.get() != null;3009 break :blk target.dynamic_linker.get() != null;
2961 };3010 };
2962 if (needs_interp and self.interp_section_index == null) {3011 if (needs_interp and self.section_indexes.interp == null) {
2963 self.interp_section_index = try self.addSection(.{3012 self.section_indexes.interp = try self.addSection(.{
2964 .name = try self.insertShString(".interp"),3013 .name = try self.insertShString(".interp"),
2965 .type = elf.SHT_PROGBITS,3014 .type = elf.SHT_PROGBITS,
2966 .flags = elf.SHF_ALLOC,3015 .flags = elf.SHF_ALLOC,
...@@ -2969,8 +3018,8 @@ fn initSyntheticSections(self: *Elf) !void {...@@ -2969,8 +3018,8 @@ fn initSyntheticSections(self: *Elf) !void {
2969 }3018 }
29703019
2971 if (self.isEffectivelyDynLib() or self.shared_objects.items.len > 0 or comp.config.pie) {3020 if (self.isEffectivelyDynLib() or self.shared_objects.items.len > 0 or comp.config.pie) {
2972 if (self.dynstrtab_section_index == null) {3021 if (self.section_indexes.dynstrtab == null) {
2973 self.dynstrtab_section_index = try self.addSection(.{3022 self.section_indexes.dynstrtab = try self.addSection(.{
2974 .name = try self.insertShString(".dynstr"),3023 .name = try self.insertShString(".dynstr"),
2975 .flags = elf.SHF_ALLOC,3024 .flags = elf.SHF_ALLOC,
2976 .type = elf.SHT_STRTAB,3025 .type = elf.SHT_STRTAB,
...@@ -2978,8 +3027,8 @@ fn initSyntheticSections(self: *Elf) !void {...@@ -2978,8 +3027,8 @@ fn initSyntheticSections(self: *Elf) !void {
2978 .addralign = 1,3027 .addralign = 1,
2979 });3028 });
2980 }3029 }
2981 if (self.dynamic_section_index == null) {3030 if (self.section_indexes.dynamic == null) {
2982 self.dynamic_section_index = try self.addSection(.{3031 self.section_indexes.dynamic = try self.addSection(.{
2983 .name = try self.insertShString(".dynamic"),3032 .name = try self.insertShString(".dynamic"),
2984 .flags = elf.SHF_ALLOC | elf.SHF_WRITE,3033 .flags = elf.SHF_ALLOC | elf.SHF_WRITE,
2985 .type = elf.SHT_DYNAMIC,3034 .type = elf.SHT_DYNAMIC,
...@@ -2987,8 +3036,8 @@ fn initSyntheticSections(self: *Elf) !void {...@@ -2987,8 +3036,8 @@ fn initSyntheticSections(self: *Elf) !void {
2987 .addralign = @alignOf(elf.Elf64_Dyn),3036 .addralign = @alignOf(elf.Elf64_Dyn),
2988 });3037 });
2989 }3038 }
2990 if (self.dynsymtab_section_index == null) {3039 if (self.section_indexes.dynsymtab == null) {
2991 self.dynsymtab_section_index = try self.addSection(.{3040 self.section_indexes.dynsymtab = try self.addSection(.{
2992 .name = try self.insertShString(".dynsym"),3041 .name = try self.insertShString(".dynsym"),
2993 .flags = elf.SHF_ALLOC,3042 .flags = elf.SHF_ALLOC,
2994 .type = elf.SHT_DYNSYM,3043 .type = elf.SHT_DYNSYM,
...@@ -2997,8 +3046,8 @@ fn initSyntheticSections(self: *Elf) !void {...@@ -2997,8 +3046,8 @@ fn initSyntheticSections(self: *Elf) !void {
2997 .info = 1,3046 .info = 1,
2998 });3047 });
2999 }3048 }
3000 if (self.hash_section_index == null) {3049 if (self.section_indexes.hash == null) {
3001 self.hash_section_index = try self.addSection(.{3050 self.section_indexes.hash = try self.addSection(.{
3002 .name = try self.insertShString(".hash"),3051 .name = try self.insertShString(".hash"),
3003 .flags = elf.SHF_ALLOC,3052 .flags = elf.SHF_ALLOC,
3004 .type = elf.SHT_HASH,3053 .type = elf.SHT_HASH,
...@@ -3006,8 +3055,8 @@ fn initSyntheticSections(self: *Elf) !void {...@@ -3006,8 +3055,8 @@ fn initSyntheticSections(self: *Elf) !void {
3006 .entsize = 4,3055 .entsize = 4,
3007 });3056 });
3008 }3057 }
3009 if (self.gnu_hash_section_index == null) {3058 if (self.section_indexes.gnu_hash == null) {
3010 self.gnu_hash_section_index = try self.addSection(.{3059 self.section_indexes.gnu_hash = try self.addSection(.{
3011 .name = try self.insertShString(".gnu.hash"),3060 .name = try self.insertShString(".gnu.hash"),
3012 .flags = elf.SHF_ALLOC,3061 .flags = elf.SHF_ALLOC,
3013 .type = elf.SHT_GNU_HASH,3062 .type = elf.SHT_GNU_HASH,
...@@ -3020,8 +3069,8 @@ fn initSyntheticSections(self: *Elf) !void {...@@ -3020,8 +3069,8 @@ fn initSyntheticSections(self: *Elf) !void {
3020 if (sym.flags.import and sym.version_index & elf.VERSYM_VERSION > elf.VER_NDX_GLOBAL) break true;3069 if (sym.flags.import and sym.version_index & elf.VERSYM_VERSION > elf.VER_NDX_GLOBAL) break true;
3021 } else false;3070 } else false;
3022 if (needs_versions) {3071 if (needs_versions) {
3023 if (self.versym_section_index == null) {3072 if (self.section_indexes.versym == null) {
3024 self.versym_section_index = try self.addSection(.{3073 self.section_indexes.versym = try self.addSection(.{
3025 .name = try self.insertShString(".gnu.version"),3074 .name = try self.insertShString(".gnu.version"),
3026 .flags = elf.SHF_ALLOC,3075 .flags = elf.SHF_ALLOC,
3027 .type = elf.SHT_GNU_VERSYM,3076 .type = elf.SHT_GNU_VERSYM,
...@@ -3029,8 +3078,8 @@ fn initSyntheticSections(self: *Elf) !void {...@@ -3029,8 +3078,8 @@ fn initSyntheticSections(self: *Elf) !void {
3029 .entsize = @sizeOf(elf.Elf64_Versym),3078 .entsize = @sizeOf(elf.Elf64_Versym),
3030 });3079 });
3031 }3080 }
3032 if (self.verneed_section_index == null) {3081 if (self.section_indexes.verneed == null) {
3033 self.verneed_section_index = try self.addSection(.{3082 self.section_indexes.verneed = try self.addSection(.{
3034 .name = try self.insertShString(".gnu.version_r"),3083 .name = try self.insertShString(".gnu.version_r"),
3035 .flags = elf.SHF_ALLOC,3084 .flags = elf.SHF_ALLOC,
3036 .type = elf.SHT_GNU_VERNEED,3085 .type = elf.SHT_GNU_VERNEED,
...@@ -3049,16 +3098,16 @@ pub fn initSymtab(self: *Elf) !void {...@@ -3049,16 +3098,16 @@ pub fn initSymtab(self: *Elf) !void {
3049 .p32 => true,3098 .p32 => true,
3050 .p64 => false,3099 .p64 => false,
3051 };3100 };
3052 if (self.symtab_section_index == null) {3101 if (self.section_indexes.symtab == null) {
3053 self.symtab_section_index = try self.addSection(.{3102 self.section_indexes.symtab = try self.addSection(.{
3054 .name = try self.insertShString(".symtab"),3103 .name = try self.insertShString(".symtab"),
3055 .type = elf.SHT_SYMTAB,3104 .type = elf.SHT_SYMTAB,
3056 .addralign = if (small_ptr) @alignOf(elf.Elf32_Sym) else @alignOf(elf.Elf64_Sym),3105 .addralign = if (small_ptr) @alignOf(elf.Elf32_Sym) else @alignOf(elf.Elf64_Sym),
3057 .entsize = if (small_ptr) @sizeOf(elf.Elf32_Sym) else @sizeOf(elf.Elf64_Sym),3106 .entsize = if (small_ptr) @sizeOf(elf.Elf32_Sym) else @sizeOf(elf.Elf64_Sym),
3058 });3107 });
3059 }3108 }
3060 if (self.strtab_section_index == null) {3109 if (self.section_indexes.strtab == null) {
3061 self.strtab_section_index = try self.addSection(.{3110 self.section_indexes.strtab = try self.addSection(.{
3062 .name = try self.insertShString(".strtab"),3111 .name = try self.insertShString(".strtab"),
3063 .type = elf.SHT_STRTAB,3112 .type = elf.SHT_STRTAB,
3064 .entsize = 1,3113 .entsize = 1,
...@@ -3068,8 +3117,8 @@ pub fn initSymtab(self: *Elf) !void {...@@ -3068,8 +3117,8 @@ pub fn initSymtab(self: *Elf) !void {
3068}3117}
30693118
3070pub fn initShStrtab(self: *Elf) !void {3119pub fn initShStrtab(self: *Elf) !void {
3071 if (self.shstrtab_section_index == null) {3120 if (self.section_indexes.shstrtab == null) {
3072 self.shstrtab_section_index = try self.addSection(.{3121 self.section_indexes.shstrtab = try self.addSection(.{
3073 .name = try self.insertShString(".shstrtab"),3122 .name = try self.insertShString(".shstrtab"),
3074 .type = elf.SHT_STRTAB,3123 .type = elf.SHT_STRTAB,
3075 .entsize = 1,3124 .entsize = 1,
...@@ -3081,43 +3130,43 @@ pub fn initShStrtab(self: *Elf) !void {...@@ -3081,43 +3130,43 @@ pub fn initShStrtab(self: *Elf) !void {
3081fn initSpecialPhdrs(self: *Elf) !void {3130fn initSpecialPhdrs(self: *Elf) !void {
3082 comptime assert(max_number_of_special_phdrs == 5);3131 comptime assert(max_number_of_special_phdrs == 5);
30833132
3084 if (self.interp_section_index != null and self.phdr_interp_index == null) {3133 if (self.section_indexes.interp != null and self.phdr_indexes.interp == .none) {
3085 self.phdr_interp_index = try self.addPhdr(.{3134 self.phdr_indexes.interp = (try self.addPhdr(.{
3086 .type = elf.PT_INTERP,3135 .type = elf.PT_INTERP,
3087 .flags = elf.PF_R,3136 .flags = elf.PF_R,
3088 .@"align" = 1,3137 .@"align" = 1,
3089 });3138 })).toOptional();
3090 }3139 }
3091 if (self.dynamic_section_index != null and self.phdr_dynamic_index == null) {3140 if (self.section_indexes.dynamic != null and self.phdr_indexes.dynamic == .none) {
3092 self.phdr_dynamic_index = try self.addPhdr(.{3141 self.phdr_indexes.dynamic = (try self.addPhdr(.{
3093 .type = elf.PT_DYNAMIC,3142 .type = elf.PT_DYNAMIC,
3094 .flags = elf.PF_R | elf.PF_W,3143 .flags = elf.PF_R | elf.PF_W,
3095 });3144 })).toOptional();
3096 }3145 }
3097 if (self.eh_frame_hdr_section_index != null and self.phdr_gnu_eh_frame_index == null) {3146 if (self.section_indexes.eh_frame_hdr != null and self.phdr_indexes.gnu_eh_frame == .none) {
3098 self.phdr_gnu_eh_frame_index = try self.addPhdr(.{3147 self.phdr_indexes.gnu_eh_frame = (try self.addPhdr(.{
3099 .type = elf.PT_GNU_EH_FRAME,3148 .type = elf.PT_GNU_EH_FRAME,
3100 .flags = elf.PF_R,3149 .flags = elf.PF_R,
3101 });3150 })).toOptional();
3102 }3151 }
3103 if (self.phdr_gnu_stack_index == null) {3152 if (self.phdr_indexes.gnu_stack == .none) {
3104 self.phdr_gnu_stack_index = try self.addPhdr(.{3153 self.phdr_indexes.gnu_stack = (try self.addPhdr(.{
3105 .type = elf.PT_GNU_STACK,3154 .type = elf.PT_GNU_STACK,
3106 .flags = elf.PF_W | elf.PF_R,3155 .flags = elf.PF_W | elf.PF_R,
3107 .memsz = self.base.stack_size,3156 .memsz = self.base.stack_size,
3108 .@"align" = 1,3157 .@"align" = 1,
3109 });3158 })).toOptional();
3110 }3159 }
31113160
3112 const has_tls = for (self.sections.items(.shdr)) |shdr| {3161 const has_tls = for (self.sections.items(.shdr)) |shdr| {
3113 if (shdr.sh_flags & elf.SHF_TLS != 0) break true;3162 if (shdr.sh_flags & elf.SHF_TLS != 0) break true;
3114 } else false;3163 } else false;
3115 if (has_tls and self.phdr_tls_index == null) {3164 if (has_tls and self.phdr_indexes.tls == .none) {
3116 self.phdr_tls_index = try self.addPhdr(.{3165 self.phdr_indexes.tls = (try self.addPhdr(.{
3117 .type = elf.PT_TLS,3166 .type = elf.PT_TLS,
3118 .flags = elf.PF_R,3167 .flags = elf.PF_R,
3119 .@"align" = 1,3168 .@"align" = 1,
3120 });3169 })).toOptional();
3121 }3170 }
3122}3171}
31233172
...@@ -3202,7 +3251,7 @@ fn sortInitFini(self: *Elf) !void {...@@ -3202,7 +3251,7 @@ fn sortInitFini(self: *Elf) !void {
3202}3251}
32033252
3204fn setDynamicSection(self: *Elf, rpaths: []const []const u8) !void {3253fn 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
3207 for (self.shared_objects.items) |index| {3256 for (self.shared_objects.items) |index| {
3208 const shared_object = self.file(index).?.shared_object;3257 const shared_object = self.file(index).?.shared_object;
...@@ -3220,13 +3269,13 @@ fn setDynamicSection(self: *Elf, rpaths: []const []const u8) !void {...@@ -3220,13 +3269,13 @@ fn setDynamicSection(self: *Elf, rpaths: []const []const u8) !void {
3220}3269}
32213270
3222fn sortDynamicSymtab(self: *Elf) void {3271fn sortDynamicSymtab(self: *Elf) void {
3223 if (self.gnu_hash_section_index == null) return;3272 if (self.section_indexes.gnu_hash == null) return;
3224 self.dynsym.sort(self);3273 self.dynsym.sort(self);
3225}3274}
32263275
3227fn setVersionSymtab(self: *Elf) !void {3276fn setVersionSymtab(self: *Elf) !void {
3228 const gpa = self.base.comp.gpa;3277 const gpa = self.base.comp.gpa;
3229 if (self.versym_section_index == null) return;3278 if (self.section_indexes.versym == null) return;
3230 try self.versym.resize(gpa, self.dynsym.count());3279 try self.versym.resize(gpa, self.dynsym.count());
3231 self.versym.items[0] = elf.VER_NDX_LOCAL;3280 self.versym.items[0] = elf.VER_NDX_LOCAL;
3232 for (self.dynsym.entries.items, 1..) |entry, i| {3281 for (self.dynsym.entries.items, 1..) |entry, i| {
...@@ -3234,7 +3283,7 @@ fn setVersionSymtab(self: *Elf) !void {...@@ -3234,7 +3283,7 @@ fn setVersionSymtab(self: *Elf) !void {
3234 self.versym.items[i] = sym.version_index;3283 self.versym.items[i] = sym.version_index;
3235 }3284 }
32363285
3237 if (self.verneed_section_index) |shndx| {3286 if (self.section_indexes.verneed) |shndx| {
3238 try self.verneed.generate(self);3287 try self.verneed.generate(self);
3239 const shdr = &self.sections.items(.shdr)[shndx];3288 const shdr = &self.sections.items(.shdr)[shndx];
3240 shdr.sh_info = @as(u32, @intCast(self.verneed.verneed.items.len));3289 shdr.sh_info = @as(u32, @intCast(self.verneed.verneed.items.len));
...@@ -3242,34 +3291,39 @@ fn setVersionSymtab(self: *Elf) !void {...@@ -3242,34 +3291,39 @@ fn setVersionSymtab(self: *Elf) !void {
3242}3291}
32433292
3244fn setHashSections(self: *Elf) !void {3293fn setHashSections(self: *Elf) !void {
3245 if (self.hash_section_index != null) {3294 if (self.section_indexes.hash != null) {
3246 try self.hash.generate(self);3295 try self.hash.generate(self);
3247 }3296 }
3248 if (self.gnu_hash_section_index != null) {3297 if (self.section_indexes.gnu_hash != null) {
3249 try self.gnu_hash.calcSize(self);3298 try self.gnu_hash.calcSize(self);
3250 }3299 }
3251}3300}
32523301
3253fn phdrRank(phdr: elf.Elf64_Phdr) u8 {3302fn phdrRank(phdr: elf.Elf64_Phdr) u8 {
3254 switch (phdr.p_type) {3303 return switch (phdr.p_type) {
3255 elf.PT_NULL => return 0,3304 elf.PT_NULL => 0,
3256 elf.PT_PHDR => return 1,3305 elf.PT_PHDR => 1,
3257 elf.PT_INTERP => return 2,3306 elf.PT_INTERP => 2,
3258 elf.PT_LOAD => return 3,3307 elf.PT_LOAD => 3,
3259 elf.PT_DYNAMIC, elf.PT_TLS => return 4,3308 elf.PT_DYNAMIC, elf.PT_TLS => 4,
3260 elf.PT_GNU_EH_FRAME => return 5,3309 elf.PT_GNU_EH_FRAME => 5,
3261 elf.PT_GNU_STACK => return 6,3310 elf.PT_GNU_STACK => 6,
3262 else => return 7,3311 else => 7,
3263 }3312 };
3264}3313}
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 {
3267 const Entry = struct {3321 const Entry = struct {
3268 phndx: u16,3322 phndx: u16,
32693323
3270 pub fn lessThan(elf_file: *Elf, lhs: @This(), rhs: @This()) bool {3324 pub fn lessThan(program_headers: []const elf.Elf64_Phdr, lhs: @This(), rhs: @This()) bool {
3271 const lhs_phdr = elf_file.phdrs.items[lhs.phndx];3325 const lhs_phdr = program_headers[lhs.phndx];
3272 const rhs_phdr = elf_file.phdrs.items[rhs.phndx];3326 const rhs_phdr = program_headers[rhs.phndx];
3273 const lhs_rank = phdrRank(lhs_phdr);3327 const lhs_rank = phdrRank(lhs_phdr);
3274 const rhs_rank = phdrRank(rhs_phdr);3328 const rhs_rank = phdrRank(rhs_phdr);
3275 if (lhs_rank == rhs_rank) return lhs_phdr.p_vaddr < rhs_phdr.p_vaddr;3329 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 {...@@ -3277,52 +3331,41 @@ fn sortPhdrs(self: *Elf) error{OutOfMemory}!void {
3277 }3331 }
3278 };3332 };
32793333
3280 const gpa = self.base.comp.gpa;3334 const entries = try gpa.alloc(Entry, phdrs.items.len);
3281 var entries = try std.ArrayList(Entry).initCapacity(gpa, self.phdrs.items.len);3335 defer gpa.free(entries);
3282 defer entries.deinit();3336 for (entries, 0..) |*entry, phndx| {
3283 for (0..self.phdrs.items.len) |phndx| {3337 entry.* = .{ .phndx = @intCast(phndx) };
3284 entries.appendAssumeCapacity(.{ .phndx = @as(u16, @intCast(phndx)) });
3285 }3338 }
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);
3290 defer gpa.free(backlinks);3344 defer gpa.free(backlinks);
3291 for (entries.items, 0..) |entry, i| {3345 const slice = try phdrs.toOwnedSlice(gpa);
3292 backlinks[entry.phndx] = @as(u16, @intCast(i));
3293 }
3294
3295 const slice = try self.phdrs.toOwnedSlice(gpa);
3296 defer gpa.free(slice);3346 defer gpa.free(slice);
3347 try phdrs.resize(gpa, slice.len);
32973348
3298 try self.phdrs.ensureTotalCapacityPrecise(gpa, slice.len);3349 for (entries, phdrs.items, 0..) |entry, *phdr, i| {
3299 for (entries.items) |sorted| {3350 backlinks[entry.phndx] = @intCast(i);
3300 self.phdrs.appendAssumeCapacity(slice[sorted.phndx]);3351 phdr.* = slice[entry.phndx];
3301 }3352 }
33023353
3303 for (&[_]*?u16{3354 inline for (@typeInfo(ProgramHeaderIndexes).@"struct".fields) |field| {
3304 &self.phdr_table_index,3355 if (@field(special_indexes, field.name).int()) |special_index| {
3305 &self.phdr_table_load_index,3356 @field(special_indexes, field.name) = @enumFromInt(backlinks[special_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.*];
3313 }3357 }
3314 }3358 }
33153359
3316 for (self.sections.items(.phndx)) |*maybe_phndx| {3360 for (section_indexes) |*opt_phndx| {
3317 if (maybe_phndx.*) |*index| {3361 if (opt_phndx.int()) |index| {
3318 index.* = backlinks[index.*];3362 opt_phndx.* = @enumFromInt(backlinks[index]);
3319 }3363 }
3320 }3364 }
3321}3365}
33223366
3323fn shdrRank(self: *Elf, shndx: u32) u8 {3367fn shdrRank(shdr: elf.Elf64_Shdr, shstrtab: []const u8) u8 {
3324 const shdr = self.sections.items(.shdr)[shndx];3368 const name = shString(shstrtab, shdr.sh_name);
3325 const name = self.getShString(shdr.sh_name);
3326 const flags = shdr.sh_flags;3369 const flags = shdr.sh_flags;
33273370
3328 switch (shdr.sh_type) {3371 switch (shdr.sh_type) {
...@@ -3371,145 +3414,138 @@ fn shdrRank(self: *Elf, shndx: u32) u8 {...@@ -3371,145 +3414,138 @@ fn shdrRank(self: *Elf, shndx: u32) u8 {
3371 }3414 }
3372}3415}
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 {
3375 const Entry = struct {3427 const Entry = struct {
3376 shndx: u32,3428 shndx: u32,
33773429
3378 pub fn lessThan(elf_file: *Elf, lhs: @This(), rhs: @This()) bool {3430 const Context = struct {
3379 return elf_file.shdrRank(lhs.shndx) < elf_file.shdrRank(rhs.shndx);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);
3380 }3438 }
3381 };3439 };
33823440
3383 const gpa = self.base.comp.gpa;3441 const shdrs = sections.items(.shdr);
3384 var entries = try std.ArrayList(Entry).initCapacity(gpa, self.sections.items(.shdr).len);3442
3385 defer entries.deinit();3443 const entries = try gpa.alloc(Entry, shdrs.len);
3386 for (0..self.sections.items(.shdr).len) |shndx| {3444 defer gpa.free(entries);
3387 entries.appendAssumeCapacity(.{ .shndx = @intCast(shndx) });3445 for (entries, 0..shdrs.len) |*entry, shndx| {
3446 entry.* = .{ .shndx = @intCast(shndx) };
3388 }3447 }
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);
3393 defer gpa.free(backlinks);3456 defer gpa.free(backlinks);
3394 for (entries.items, 0..) |entry, i| {3457 {
3395 backlinks[entry.shndx] = @intCast(i);3458 var slice = sections.toOwnedSlice();
3396 }3459 defer slice.deinit(gpa);
33973460 try sections.resize(gpa, slice.len);
3398 var slice = self.sections.toOwnedSlice();3461
3399 defer slice.deinit(gpa);3462 for (entries, 0..) |entry, i| {
34003463 backlinks[entry.shndx] = @intCast(i);
3401 try self.sections.ensureTotalCapacity(gpa, slice.len);3464 sections.set(i, slice.get(entry.shndx));
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.*];
3435 }3465 }
3436 }3466 }
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| {
3439 msec.output_section_index = backlinks[msec.output_section_index];3475 msec.output_section_index = backlinks[msec.output_section_index];
3440 }3476 }
34413477
3442 const slice = self.sections.slice();3478 const slice = sections.slice();
3443 for (slice.items(.shdr), slice.items(.atom_list_2)) |*shdr, *atom_list| {3479 for (slice.items(.shdr), slice.items(.atom_list_2)) |*shdr, *atom_list| {
3444 atom_list.output_section_index = backlinks[atom_list.output_section_index];3480 atom_list.output_section_index = backlinks[atom_list.output_section_index];
3445 for (atom_list.atoms.keys()) |ref| {3481 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;
3447 }3483 }
3448 if (shdr.sh_type == elf.SHT_RELA) {3484 if (shdr.sh_type == elf.SHT_RELA) {
3449 // FIXME:JK we should spin up .symtab potentially earlier, or set all non-dynamic RELA sections3485 // FIXME:JK we should spin up .symtab potentially earlier, or set all non-dynamic RELA sections
3450 // to point at symtab3486 // to point at symtab
3451 // shdr.sh_link = backlinks[shdr.sh_link];3487 // shdr.sh_link = backlinks[shdr.sh_link];
3452 shdr.sh_link = self.symtab_section_index.?;3488 shdr.sh_link = section_indexes.symtab.?;
3453 shdr.sh_info = backlinks[shdr.sh_info];3489 shdr.sh_info = backlinks[shdr.sh_info];
3454 }3490 }
3455 }3491 }
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| {
3460 cg.shndx = backlinks[cg.shndx];3496 cg.shndx = backlinks[cg.shndx];
3461 }3497 }
34623498
3463 if (self.symtab_section_index) |index| {3499 if (section_indexes.symtab) |index| {
3464 const shdr = &slice.items(.shdr)[index];3500 const shdr = &slice.items(.shdr)[index];
3465 shdr.sh_link = self.strtab_section_index.?;3501 shdr.sh_link = section_indexes.strtab.?;
3466 }3502 }
34673503
3468 if (self.dynamic_section_index) |index| {3504 if (section_indexes.dynamic) |index| {
3469 const shdr = &slice.items(.shdr)[index];3505 const shdr = &slice.items(.shdr)[index];
3470 shdr.sh_link = self.dynstrtab_section_index.?;3506 shdr.sh_link = section_indexes.dynstrtab.?;
3471 }3507 }
34723508
3473 if (self.dynsymtab_section_index) |index| {3509 if (section_indexes.dynsymtab) |index| {
3474 const shdr = &slice.items(.shdr)[index];3510 const shdr = &slice.items(.shdr)[index];
3475 shdr.sh_link = self.dynstrtab_section_index.?;3511 shdr.sh_link = section_indexes.dynstrtab.?;
3476 }3512 }
34773513
3478 if (self.hash_section_index) |index| {3514 if (section_indexes.hash) |index| {
3479 const shdr = &slice.items(.shdr)[index];3515 const shdr = &slice.items(.shdr)[index];
3480 shdr.sh_link = self.dynsymtab_section_index.?;3516 shdr.sh_link = section_indexes.dynsymtab.?;
3481 }3517 }
34823518
3483 if (self.gnu_hash_section_index) |index| {3519 if (section_indexes.gnu_hash) |index| {
3484 const shdr = &slice.items(.shdr)[index];3520 const shdr = &slice.items(.shdr)[index];
3485 shdr.sh_link = self.dynsymtab_section_index.?;3521 shdr.sh_link = section_indexes.dynsymtab.?;
3486 }3522 }
34873523
3488 if (self.versym_section_index) |index| {3524 if (section_indexes.versym) |index| {
3489 const shdr = &slice.items(.shdr)[index];3525 const shdr = &slice.items(.shdr)[index];
3490 shdr.sh_link = self.dynsymtab_section_index.?;3526 shdr.sh_link = section_indexes.dynsymtab.?;
3491 }3527 }
34923528
3493 if (self.verneed_section_index) |index| {3529 if (section_indexes.verneed) |index| {
3494 const shdr = &slice.items(.shdr)[index];3530 const shdr = &slice.items(.shdr)[index];
3495 shdr.sh_link = self.dynstrtab_section_index.?;3531 shdr.sh_link = section_indexes.dynstrtab.?;
3496 }3532 }
34973533
3498 if (self.rela_dyn_section_index) |index| {3534 if (section_indexes.rela_dyn) |index| {
3499 const shdr = &slice.items(.shdr)[index];3535 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;
3501 }3537 }
35023538
3503 if (self.rela_plt_section_index) |index| {3539 if (section_indexes.rela_plt) |index| {
3504 const shdr = &slice.items(.shdr)[index];3540 const shdr = &slice.items(.shdr)[index];
3505 shdr.sh_link = self.dynsymtab_section_index.?;3541 shdr.sh_link = section_indexes.dynsymtab.?;
3506 shdr.sh_info = self.plt_section_index.?;3542 shdr.sh_info = section_indexes.plt.?;
3507 }3543 }
35083544
3509 if (self.eh_frame_rela_section_index) |index| {3545 if (section_indexes.eh_frame_rela) |index| {
3510 const shdr = &slice.items(.shdr)[index];3546 const shdr = &slice.items(.shdr)[index];
3511 shdr.sh_link = self.symtab_section_index.?;3547 shdr.sh_link = section_indexes.symtab.?;
3512 shdr.sh_info = self.eh_frame_section_index.?;3548 shdr.sh_info = section_indexes.eh_frame.?;
3513 }3549 }
3514}3550}
35153551
...@@ -3543,31 +3579,31 @@ fn updateSectionSizes(self: *Elf) !void {...@@ -3543,31 +3579,31 @@ fn updateSectionSizes(self: *Elf) !void {
3543 }3579 }
35443580
3545 const shdrs = slice.items(.shdr);3581 const shdrs = slice.items(.shdr);
3546 if (self.eh_frame_section_index) |index| {3582 if (self.section_indexes.eh_frame) |index| {
3547 shdrs[index].sh_size = try eh_frame.calcEhFrameSize(self);3583 shdrs[index].sh_size = try eh_frame.calcEhFrameSize(self);
3548 }3584 }
35493585
3550 if (self.eh_frame_hdr_section_index) |index| {3586 if (self.section_indexes.eh_frame_hdr) |index| {
3551 shdrs[index].sh_size = eh_frame.calcEhFrameHdrSize(self);3587 shdrs[index].sh_size = eh_frame.calcEhFrameHdrSize(self);
3552 }3588 }
35533589
3554 if (self.got_section_index) |index| {3590 if (self.section_indexes.got) |index| {
3555 shdrs[index].sh_size = self.got.size(self);3591 shdrs[index].sh_size = self.got.size(self);
3556 }3592 }
35573593
3558 if (self.plt_section_index) |index| {3594 if (self.section_indexes.plt) |index| {
3559 shdrs[index].sh_size = self.plt.size(self);3595 shdrs[index].sh_size = self.plt.size(self);
3560 }3596 }
35613597
3562 if (self.got_plt_section_index) |index| {3598 if (self.section_indexes.got_plt) |index| {
3563 shdrs[index].sh_size = self.got_plt.size(self);3599 shdrs[index].sh_size = self.got_plt.size(self);
3564 }3600 }
35653601
3566 if (self.plt_got_section_index) |index| {3602 if (self.section_indexes.plt_got) |index| {
3567 shdrs[index].sh_size = self.plt_got.size(self);3603 shdrs[index].sh_size = self.plt_got.size(self);
3568 }3604 }
35693605
3570 if (self.rela_dyn_section_index) |shndx| {3606 if (self.section_indexes.rela_dyn) |shndx| {
3571 var num = self.got.numRela(self) + self.copy_rel.numRela();3607 var num = self.got.numRela(self) + self.copy_rel.numRela();
3572 if (self.zigObjectPtr()) |zig_object| {3608 if (self.zigObjectPtr()) |zig_object| {
3573 num += zig_object.num_dynrelocs;3609 num += zig_object.num_dynrelocs;
...@@ -3578,43 +3614,43 @@ fn updateSectionSizes(self: *Elf) !void {...@@ -3578,43 +3614,43 @@ fn updateSectionSizes(self: *Elf) !void {
3578 shdrs[shndx].sh_size = num * @sizeOf(elf.Elf64_Rela);3614 shdrs[shndx].sh_size = num * @sizeOf(elf.Elf64_Rela);
3579 }3615 }
35803616
3581 if (self.rela_plt_section_index) |index| {3617 if (self.section_indexes.rela_plt) |index| {
3582 shdrs[index].sh_size = self.plt.numRela() * @sizeOf(elf.Elf64_Rela);3618 shdrs[index].sh_size = self.plt.numRela() * @sizeOf(elf.Elf64_Rela);
3583 }3619 }
35843620
3585 if (self.copy_rel_section_index) |index| {3621 if (self.section_indexes.copy_rel) |index| {
3586 try self.copy_rel.updateSectionSize(index, self);3622 try self.copy_rel.updateSectionSize(index, self);
3587 }3623 }
35883624
3589 if (self.interp_section_index) |index| {3625 if (self.section_indexes.interp) |index| {
3590 shdrs[index].sh_size = self.getTarget().dynamic_linker.get().?.len + 1;3626 shdrs[index].sh_size = self.getTarget().dynamic_linker.get().?.len + 1;
3591 }3627 }
35923628
3593 if (self.hash_section_index) |index| {3629 if (self.section_indexes.hash) |index| {
3594 shdrs[index].sh_size = self.hash.size();3630 shdrs[index].sh_size = self.hash.size();
3595 }3631 }
35963632
3597 if (self.gnu_hash_section_index) |index| {3633 if (self.section_indexes.gnu_hash) |index| {
3598 shdrs[index].sh_size = self.gnu_hash.size();3634 shdrs[index].sh_size = self.gnu_hash.size();
3599 }3635 }
36003636
3601 if (self.dynamic_section_index) |index| {3637 if (self.section_indexes.dynamic) |index| {
3602 shdrs[index].sh_size = self.dynamic.size(self);3638 shdrs[index].sh_size = self.dynamic.size(self);
3603 }3639 }
36043640
3605 if (self.dynsymtab_section_index) |index| {3641 if (self.section_indexes.dynsymtab) |index| {
3606 shdrs[index].sh_size = self.dynsym.size();3642 shdrs[index].sh_size = self.dynsym.size();
3607 }3643 }
36083644
3609 if (self.dynstrtab_section_index) |index| {3645 if (self.section_indexes.dynstrtab) |index| {
3610 shdrs[index].sh_size = self.dynstrtab.items.len;3646 shdrs[index].sh_size = self.dynstrtab.items.len;
3611 }3647 }
36123648
3613 if (self.versym_section_index) |index| {3649 if (self.section_indexes.versym) |index| {
3614 shdrs[index].sh_size = self.versym.items.len * @sizeOf(elf.Elf64_Versym);3650 shdrs[index].sh_size = self.versym.items.len * @sizeOf(elf.Elf64_Versym);
3615 }3651 }
36163652
3617 if (self.verneed_section_index) |index| {3653 if (self.section_indexes.verneed) |index| {
3618 shdrs[index].sh_size = self.verneed.size();3654 shdrs[index].sh_size = self.verneed.size();
3619 }3655 }
36203656
...@@ -3624,7 +3660,7 @@ fn updateSectionSizes(self: *Elf) !void {...@@ -3624,7 +3660,7 @@ fn updateSectionSizes(self: *Elf) !void {
36243660
3625// FIXME:JK this is very much obsolete, remove!3661// FIXME:JK this is very much obsolete, remove!
3626pub fn updateShStrtabSize(self: *Elf) void {3662pub fn updateShStrtabSize(self: *Elf) void {
3627 if (self.shstrtab_section_index) |index| {3663 if (self.section_indexes.shstrtab) |index| {
3628 self.sections.items(.shdr)[index].sh_size = self.shstrtab.items.len;3664 self.sections.items(.shdr)[index].sh_size = self.shstrtab.items.len;
3629 }3665 }
3630}3666}
...@@ -3656,7 +3692,7 @@ fn addLoadPhdrs(self: *Elf) error{OutOfMemory}!void {...@@ -3656,7 +3692,7 @@ fn addLoadPhdrs(self: *Elf) error{OutOfMemory}!void {
3656 if (shdr.sh_type == elf.SHT_NULL) continue;3692 if (shdr.sh_type == elf.SHT_NULL) continue;
3657 if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue;3693 if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue;
3658 const flags = shdrToPhdrFlags(shdr.sh_flags);3694 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) {
3660 _ = try self.addPhdr(.{ .flags = flags, .type = elf.PT_LOAD });3696 _ = try self.addPhdr(.{ .flags = flags, .type = elf.PT_LOAD });
3661 }3697 }
3662 }3698 }
...@@ -3664,8 +3700,8 @@ fn addLoadPhdrs(self: *Elf) error{OutOfMemory}!void {...@@ -3664,8 +3700,8 @@ fn addLoadPhdrs(self: *Elf) error{OutOfMemory}!void {
36643700
3665/// Allocates PHDR table in virtual memory and in file.3701/// Allocates PHDR table in virtual memory and in file.
3666fn allocatePhdrTable(self: *Elf) error{OutOfMemory}!void {3702fn allocatePhdrTable(self: *Elf) error{OutOfMemory}!void {
3667 const phdr_table = &self.phdrs.items[self.phdr_table_index.?];3703 const phdr_table = &self.phdrs.items[self.phdr_indexes.table.int().?];
3668 const phdr_table_load = &self.phdrs.items[self.phdr_table_load_index.?];3704 const phdr_table_load = &self.phdrs.items[self.phdr_indexes.table_load.int().?];
36693705
3670 const ehsize: u64 = switch (self.ptr_width) {3706 const ehsize: u64 = switch (self.ptr_width) {
3671 .p32 => @sizeOf(elf.Elf32_Ehdr),3707 .p32 => @sizeOf(elf.Elf32_Ehdr),
...@@ -3757,7 +3793,7 @@ pub fn allocateAllocSections(self: *Elf) !void {...@@ -3757,7 +3793,7 @@ pub fn allocateAllocSections(self: *Elf) !void {
3757 // When allocating we first find the largest required alignment3793 // When allocating we first find the largest required alignment
3758 // of any section that is contained in a cover and use it to align3794 // of any section that is contained in a cover and use it to align
3759 // the start address of the segement (and first section).3795 // 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().?];
3761 var addr = phdr_table.p_vaddr + phdr_table.p_memsz;3797 var addr = phdr_table.p_vaddr + phdr_table.p_memsz;
37623798
3763 for (covers) |cover| {3799 for (covers) |cover| {
...@@ -3817,8 +3853,8 @@ pub fn allocateAllocSections(self: *Elf) !void {...@@ -3817,8 +3853,8 @@ pub fn allocateAllocSections(self: *Elf) !void {
3817 }3853 }
38183854
3819 const first = slice.items(.shdr)[cover.items[0]];3855 const first = slice.items(.shdr)[cover.items[0]];
3820 const phndx = self.getPhdr(.{ .type = elf.PT_LOAD, .flags = shdrToPhdrFlags(first.sh_flags) }).?;3856 const phndx = self.getPhdr(.{ .type = elf.PT_LOAD, .flags = shdrToPhdrFlags(first.sh_flags) }).unwrap().?;
3821 const phdr = &self.phdrs.items[phndx];3857 const phdr = &self.phdrs.items[phndx.int()];
3822 const allocated_size = self.allocatedSize(phdr.p_offset);3858 const allocated_size = self.allocatedSize(phdr.p_offset);
3823 if (filesz > allocated_size) {3859 if (filesz > allocated_size) {
3824 const old_offset = phdr.p_offset;3860 const old_offset = phdr.p_offset;
...@@ -3830,7 +3866,7 @@ pub fn allocateAllocSections(self: *Elf) !void {...@@ -3830,7 +3866,7 @@ pub fn allocateAllocSections(self: *Elf) !void {
38303866
3831 for (cover.items) |shndx| {3867 for (cover.items) |shndx| {
3832 const shdr = &slice.items(.shdr)[shndx];3868 const shdr = &slice.items(.shdr)[shndx];
3833 slice.items(.phndx)[shndx] = phndx;3869 slice.items(.phndx)[shndx] = phndx.toOptional();
3834 if (shdr.sh_type == elf.SHT_NOBITS) {3870 if (shdr.sh_type == elf.SHT_NOBITS) {
3835 shdr.sh_offset = 0;3871 shdr.sh_offset = 0;
3836 continue;3872 continue;
...@@ -3906,12 +3942,12 @@ pub fn allocateNonAllocSections(self: *Elf) !void {...@@ -3906,12 +3942,12 @@ pub fn allocateNonAllocSections(self: *Elf) !void {
3906fn allocateSpecialPhdrs(self: *Elf) void {3942fn allocateSpecialPhdrs(self: *Elf) void {
3907 const slice = self.sections.slice();3943 const slice = self.sections.slice();
39083944
3909 for (&[_]struct { ?u16, ?u32 }{3945 for (&[_]struct { OptionalProgramHeaderIndex, ?u32 }{
3910 .{ self.phdr_interp_index, self.interp_section_index },3946 .{ self.phdr_indexes.interp, self.section_indexes.interp },
3911 .{ self.phdr_dynamic_index, self.dynamic_section_index },3947 .{ self.phdr_indexes.dynamic, self.section_indexes.dynamic },
3912 .{ self.phdr_gnu_eh_frame_index, self.eh_frame_hdr_section_index },3948 .{ self.phdr_indexes.gnu_eh_frame, self.section_indexes.eh_frame_hdr },
3913 }) |pair| {3949 }) |pair| {
3914 if (pair[0]) |index| {3950 if (pair[0].int()) |index| {
3915 const shdr = slice.items(.shdr)[pair[1].?];3951 const shdr = slice.items(.shdr)[pair[1].?];
3916 const phdr = &self.phdrs.items[index];3952 const phdr = &self.phdrs.items[index];
3917 phdr.p_align = shdr.sh_addralign;3953 phdr.p_align = shdr.sh_addralign;
...@@ -3926,7 +3962,7 @@ fn allocateSpecialPhdrs(self: *Elf) void {...@@ -3926,7 +3962,7 @@ fn allocateSpecialPhdrs(self: *Elf) void {
3926 // Set the TLS segment boundaries.3962 // Set the TLS segment boundaries.
3927 // We assume TLS sections are laid out contiguously and that there is3963 // We assume TLS sections are laid out contiguously and that there is
3928 // a single TLS segment.3964 // a single TLS segment.
3929 if (self.phdr_tls_index) |index| {3965 if (self.phdr_indexes.tls.int()) |index| {
3930 const shdrs = slice.items(.shdr);3966 const shdrs = slice.items(.shdr);
3931 const phdr = &self.phdrs.items[index];3967 const phdr = &self.phdrs.items[index];
3932 var shndx: u32 = 0;3968 var shndx: u32 = 0;
...@@ -4046,7 +4082,7 @@ pub fn updateSymtabSize(self: *Elf) !void {...@@ -4046,7 +4082,7 @@ pub fn updateSymtabSize(self: *Elf) !void {
4046 strsize += ctx.strsize;4082 strsize += ctx.strsize;
4047 }4083 }
40484084
4049 if (self.got_section_index) |_| {4085 if (self.section_indexes.got) |_| {
4050 self.got.output_symtab_ctx.reset();4086 self.got.output_symtab_ctx.reset();
4051 self.got.output_symtab_ctx.ilocal = nlocals;4087 self.got.output_symtab_ctx.ilocal = nlocals;
4052 self.got.updateSymtabSize(self);4088 self.got.updateSymtabSize(self);
...@@ -4054,7 +4090,7 @@ pub fn updateSymtabSize(self: *Elf) !void {...@@ -4054,7 +4090,7 @@ pub fn updateSymtabSize(self: *Elf) !void {
4054 strsize += self.got.output_symtab_ctx.strsize;4090 strsize += self.got.output_symtab_ctx.strsize;
4055 }4091 }
40564092
4057 if (self.plt_section_index) |_| {4093 if (self.section_indexes.plt) |_| {
4058 self.plt.output_symtab_ctx.reset();4094 self.plt.output_symtab_ctx.reset();
4059 self.plt.output_symtab_ctx.ilocal = nlocals;4095 self.plt.output_symtab_ctx.ilocal = nlocals;
4060 self.plt.updateSymtabSize(self);4096 self.plt.updateSymtabSize(self);
...@@ -4062,7 +4098,7 @@ pub fn updateSymtabSize(self: *Elf) !void {...@@ -4062,7 +4098,7 @@ pub fn updateSymtabSize(self: *Elf) !void {
4062 strsize += self.plt.output_symtab_ctx.strsize;4098 strsize += self.plt.output_symtab_ctx.strsize;
4063 }4099 }
40644100
4065 if (self.plt_got_section_index) |_| {4101 if (self.section_indexes.plt_got) |_| {
4066 self.plt_got.output_symtab_ctx.reset();4102 self.plt_got.output_symtab_ctx.reset();
4067 self.plt_got.output_symtab_ctx.ilocal = nlocals;4103 self.plt_got.output_symtab_ctx.ilocal = nlocals;
4068 self.plt_got.updateSymtabSize(self);4104 self.plt_got.updateSymtabSize(self);
...@@ -4079,9 +4115,9 @@ pub fn updateSymtabSize(self: *Elf) !void {...@@ -4079,9 +4115,9 @@ pub fn updateSymtabSize(self: *Elf) !void {
4079 }4115 }
40804116
4081 const slice = self.sections.slice();4117 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.?];
4083 symtab_shdr.sh_info = nlocals;4119 symtab_shdr.sh_info = nlocals;
4084 symtab_shdr.sh_link = self.strtab_section_index.?;4120 symtab_shdr.sh_link = self.section_indexes.strtab.?;
40854121
4086 const sym_size: u64 = switch (self.ptr_width) {4122 const sym_size: u64 = switch (self.ptr_width) {
4087 .p32 => @sizeOf(elf.Elf32_Sym),4123 .p32 => @sizeOf(elf.Elf32_Sym),
...@@ -4090,7 +4126,7 @@ pub fn updateSymtabSize(self: *Elf) !void {...@@ -4090,7 +4126,7 @@ pub fn updateSymtabSize(self: *Elf) !void {
4090 const needed_size = (nlocals + nglobals) * sym_size;4126 const needed_size = (nlocals + nglobals) * sym_size;
4091 symtab_shdr.sh_size = needed_size;4127 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.?];
4094 strtab.sh_size = strsize + 1;4130 strtab.sh_size = strsize + 1;
4095}4131}
40964132
...@@ -4098,7 +4134,7 @@ fn writeSyntheticSections(self: *Elf) !void {...@@ -4098,7 +4134,7 @@ fn writeSyntheticSections(self: *Elf) !void {
4098 const gpa = self.base.comp.gpa;4134 const gpa = self.base.comp.gpa;
4099 const slice = self.sections.slice();4135 const slice = self.sections.slice();
41004136
4101 if (self.interp_section_index) |shndx| {4137 if (self.section_indexes.interp) |shndx| {
4102 var buffer: [256]u8 = undefined;4138 var buffer: [256]u8 = undefined;
4103 const interp = self.getTarget().dynamic_linker.get().?;4139 const interp = self.getTarget().dynamic_linker.get().?;
4104 @memcpy(buffer[0..interp.len], interp);4140 @memcpy(buffer[0..interp.len], interp);
...@@ -4109,12 +4145,12 @@ fn writeSyntheticSections(self: *Elf) !void {...@@ -4109,12 +4145,12 @@ fn writeSyntheticSections(self: *Elf) !void {
4109 try self.base.file.?.pwriteAll(contents, shdr.sh_offset);4145 try self.base.file.?.pwriteAll(contents, shdr.sh_offset);
4110 }4146 }
41114147
4112 if (self.hash_section_index) |shndx| {4148 if (self.section_indexes.hash) |shndx| {
4113 const shdr = slice.items(.shdr)[shndx];4149 const shdr = slice.items(.shdr)[shndx];
4114 try self.base.file.?.pwriteAll(self.hash.buffer.items, shdr.sh_offset);4150 try self.base.file.?.pwriteAll(self.hash.buffer.items, shdr.sh_offset);
4115 }4151 }
41164152
4117 if (self.gnu_hash_section_index) |shndx| {4153 if (self.section_indexes.gnu_hash) |shndx| {
4118 const shdr = slice.items(.shdr)[shndx];4154 const shdr = slice.items(.shdr)[shndx];
4119 var buffer = try std.ArrayList(u8).initCapacity(gpa, self.gnu_hash.size());4155 var buffer = try std.ArrayList(u8).initCapacity(gpa, self.gnu_hash.size());
4120 defer buffer.deinit();4156 defer buffer.deinit();
...@@ -4122,12 +4158,12 @@ fn writeSyntheticSections(self: *Elf) !void {...@@ -4122,12 +4158,12 @@ fn writeSyntheticSections(self: *Elf) !void {
4122 try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);4158 try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);
4123 }4159 }
41244160
4125 if (self.versym_section_index) |shndx| {4161 if (self.section_indexes.versym) |shndx| {
4126 const shdr = slice.items(.shdr)[shndx];4162 const shdr = slice.items(.shdr)[shndx];
4127 try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.versym.items), shdr.sh_offset);4163 try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.versym.items), shdr.sh_offset);
4128 }4164 }
41294165
4130 if (self.verneed_section_index) |shndx| {4166 if (self.section_indexes.verneed) |shndx| {
4131 const shdr = slice.items(.shdr)[shndx];4167 const shdr = slice.items(.shdr)[shndx];
4132 var buffer = try std.ArrayList(u8).initCapacity(gpa, self.verneed.size());4168 var buffer = try std.ArrayList(u8).initCapacity(gpa, self.verneed.size());
4133 defer buffer.deinit();4169 defer buffer.deinit();
...@@ -4135,7 +4171,7 @@ fn writeSyntheticSections(self: *Elf) !void {...@@ -4135,7 +4171,7 @@ fn writeSyntheticSections(self: *Elf) !void {
4135 try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);4171 try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);
4136 }4172 }
41374173
4138 if (self.dynamic_section_index) |shndx| {4174 if (self.section_indexes.dynamic) |shndx| {
4139 const shdr = slice.items(.shdr)[shndx];4175 const shdr = slice.items(.shdr)[shndx];
4140 var buffer = try std.ArrayList(u8).initCapacity(gpa, self.dynamic.size(self));4176 var buffer = try std.ArrayList(u8).initCapacity(gpa, self.dynamic.size(self));
4141 defer buffer.deinit();4177 defer buffer.deinit();
...@@ -4143,7 +4179,7 @@ fn writeSyntheticSections(self: *Elf) !void {...@@ -4143,7 +4179,7 @@ fn writeSyntheticSections(self: *Elf) !void {
4143 try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);4179 try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);
4144 }4180 }
41454181
4146 if (self.dynsymtab_section_index) |shndx| {4182 if (self.section_indexes.dynsymtab) |shndx| {
4147 const shdr = slice.items(.shdr)[shndx];4183 const shdr = slice.items(.shdr)[shndx];
4148 var buffer = try std.ArrayList(u8).initCapacity(gpa, self.dynsym.size());4184 var buffer = try std.ArrayList(u8).initCapacity(gpa, self.dynsym.size());
4149 defer buffer.deinit();4185 defer buffer.deinit();
...@@ -4151,12 +4187,12 @@ fn writeSyntheticSections(self: *Elf) !void {...@@ -4151,12 +4187,12 @@ fn writeSyntheticSections(self: *Elf) !void {
4151 try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);4187 try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);
4152 }4188 }
41534189
4154 if (self.dynstrtab_section_index) |shndx| {4190 if (self.section_indexes.dynstrtab) |shndx| {
4155 const shdr = slice.items(.shdr)[shndx];4191 const shdr = slice.items(.shdr)[shndx];
4156 try self.base.file.?.pwriteAll(self.dynstrtab.items, shdr.sh_offset);4192 try self.base.file.?.pwriteAll(self.dynstrtab.items, shdr.sh_offset);
4157 }4193 }
41584194
4159 if (self.eh_frame_section_index) |shndx| {4195 if (self.section_indexes.eh_frame) |shndx| {
4160 const existing_size = existing_size: {4196 const existing_size = existing_size: {
4161 const zo = self.zigObjectPtr() orelse break :existing_size 0;4197 const zo = self.zigObjectPtr() orelse break :existing_size 0;
4162 const sym = zo.symbol(zo.eh_frame_index orelse break :existing_size 0);4198 const sym = zo.symbol(zo.eh_frame_index orelse break :existing_size 0);
...@@ -4171,7 +4207,7 @@ fn writeSyntheticSections(self: *Elf) !void {...@@ -4171,7 +4207,7 @@ fn writeSyntheticSections(self: *Elf) !void {
4171 try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset + existing_size);4207 try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset + existing_size);
4172 }4208 }
41734209
4174 if (self.eh_frame_hdr_section_index) |shndx| {4210 if (self.section_indexes.eh_frame_hdr) |shndx| {
4175 const shdr = slice.items(.shdr)[shndx];4211 const shdr = slice.items(.shdr)[shndx];
4176 const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow;4212 const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow;
4177 var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size);4213 var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size);
...@@ -4180,7 +4216,7 @@ fn writeSyntheticSections(self: *Elf) !void {...@@ -4180,7 +4216,7 @@ fn writeSyntheticSections(self: *Elf) !void {
4180 try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);4216 try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);
4181 }4217 }
41824218
4183 if (self.got_section_index) |index| {4219 if (self.section_indexes.got) |index| {
4184 const shdr = slice.items(.shdr)[index];4220 const shdr = slice.items(.shdr)[index];
4185 var buffer = try std.ArrayList(u8).initCapacity(gpa, self.got.size(self));4221 var buffer = try std.ArrayList(u8).initCapacity(gpa, self.got.size(self));
4186 defer buffer.deinit();4222 defer buffer.deinit();
...@@ -4188,7 +4224,7 @@ fn writeSyntheticSections(self: *Elf) !void {...@@ -4188,7 +4224,7 @@ fn writeSyntheticSections(self: *Elf) !void {
4188 try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);4224 try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);
4189 }4225 }
41904226
4191 if (self.rela_dyn_section_index) |shndx| {4227 if (self.section_indexes.rela_dyn) |shndx| {
4192 const shdr = slice.items(.shdr)[shndx];4228 const shdr = slice.items(.shdr)[shndx];
4193 try self.got.addRela(self);4229 try self.got.addRela(self);
4194 try self.copy_rel.addRela(self);4230 try self.copy_rel.addRela(self);
...@@ -4196,7 +4232,7 @@ fn writeSyntheticSections(self: *Elf) !void {...@@ -4196,7 +4232,7 @@ fn writeSyntheticSections(self: *Elf) !void {
4196 try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.rela_dyn.items), shdr.sh_offset);4232 try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.rela_dyn.items), shdr.sh_offset);
4197 }4233 }
41984234
4199 if (self.plt_section_index) |shndx| {4235 if (self.section_indexes.plt) |shndx| {
4200 const shdr = slice.items(.shdr)[shndx];4236 const shdr = slice.items(.shdr)[shndx];
4201 var buffer = try std.ArrayList(u8).initCapacity(gpa, self.plt.size(self));4237 var buffer = try std.ArrayList(u8).initCapacity(gpa, self.plt.size(self));
4202 defer buffer.deinit();4238 defer buffer.deinit();
...@@ -4204,7 +4240,7 @@ fn writeSyntheticSections(self: *Elf) !void {...@@ -4204,7 +4240,7 @@ fn writeSyntheticSections(self: *Elf) !void {
4204 try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);4240 try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);
4205 }4241 }
42064242
4207 if (self.got_plt_section_index) |shndx| {4243 if (self.section_indexes.got_plt) |shndx| {
4208 const shdr = slice.items(.shdr)[shndx];4244 const shdr = slice.items(.shdr)[shndx];
4209 var buffer = try std.ArrayList(u8).initCapacity(gpa, self.got_plt.size(self));4245 var buffer = try std.ArrayList(u8).initCapacity(gpa, self.got_plt.size(self));
4210 defer buffer.deinit();4246 defer buffer.deinit();
...@@ -4212,7 +4248,7 @@ fn writeSyntheticSections(self: *Elf) !void {...@@ -4212,7 +4248,7 @@ fn writeSyntheticSections(self: *Elf) !void {
4212 try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);4248 try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);
4213 }4249 }
42144250
4215 if (self.plt_got_section_index) |shndx| {4251 if (self.section_indexes.plt_got) |shndx| {
4216 const shdr = slice.items(.shdr)[shndx];4252 const shdr = slice.items(.shdr)[shndx];
4217 var buffer = try std.ArrayList(u8).initCapacity(gpa, self.plt_got.size(self));4253 var buffer = try std.ArrayList(u8).initCapacity(gpa, self.plt_got.size(self));
4218 defer buffer.deinit();4254 defer buffer.deinit();
...@@ -4220,7 +4256,7 @@ fn writeSyntheticSections(self: *Elf) !void {...@@ -4220,7 +4256,7 @@ fn writeSyntheticSections(self: *Elf) !void {
4220 try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);4256 try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);
4221 }4257 }
42224258
4223 if (self.rela_plt_section_index) |shndx| {4259 if (self.section_indexes.rela_plt) |shndx| {
4224 const shdr = slice.items(.shdr)[shndx];4260 const shdr = slice.items(.shdr)[shndx];
4225 try self.plt.addRela(self);4261 try self.plt.addRela(self);
4226 try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.rela_plt.items), shdr.sh_offset);4262 try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.rela_plt.items), shdr.sh_offset);
...@@ -4232,7 +4268,7 @@ fn writeSyntheticSections(self: *Elf) !void {...@@ -4232,7 +4268,7 @@ fn writeSyntheticSections(self: *Elf) !void {
42324268
4233// FIXME:JK again, why is this needed?4269// FIXME:JK again, why is this needed?
4234pub fn writeShStrtab(self: *Elf) !void {4270pub fn writeShStrtab(self: *Elf) !void {
4235 if (self.shstrtab_section_index) |index| {4271 if (self.section_indexes.shstrtab) |index| {
4236 const shdr = self.sections.items(.shdr)[index];4272 const shdr = self.sections.items(.shdr)[index];
4237 log.debug("writing .shstrtab from 0x{x} to 0x{x}", .{ shdr.sh_offset, shdr.sh_offset + shdr.sh_size });4273 log.debug("writing .shstrtab from 0x{x} to 0x{x}", .{ shdr.sh_offset, shdr.sh_offset + shdr.sh_size });
4238 try self.base.file.?.pwriteAll(self.shstrtab.items, shdr.sh_offset);4274 try self.base.file.?.pwriteAll(self.shstrtab.items, shdr.sh_offset);
...@@ -4242,8 +4278,8 @@ pub fn writeShStrtab(self: *Elf) !void {...@@ -4242,8 +4278,8 @@ pub fn writeShStrtab(self: *Elf) !void {
4242pub fn writeSymtab(self: *Elf) !void {4278pub fn writeSymtab(self: *Elf) !void {
4243 const gpa = self.base.comp.gpa;4279 const gpa = self.base.comp.gpa;
4244 const slice = self.sections.slice();4280 const slice = self.sections.slice();
4245 const symtab_shdr = slice.items(.shdr)[self.symtab_section_index.?];4281 const symtab_shdr = slice.items(.shdr)[self.section_indexes.symtab.?];
4246 const strtab_shdr = slice.items(.shdr)[self.strtab_section_index.?];4282 const strtab_shdr = slice.items(.shdr)[self.section_indexes.strtab.?];
4247 const sym_size: u64 = switch (self.ptr_width) {4283 const sym_size: u64 = switch (self.ptr_width) {
4248 .p32 => @sizeOf(elf.Elf32_Sym),4284 .p32 => @sizeOf(elf.Elf32_Sym),
4249 .p64 => @sizeOf(elf.Elf64_Sym),4285 .p64 => @sizeOf(elf.Elf64_Sym),
...@@ -4301,15 +4337,15 @@ pub fn writeSymtab(self: *Elf) !void {...@@ -4301,15 +4337,15 @@ pub fn writeSymtab(self: *Elf) !void {
4301 obj.asFile().writeSymtab(self);4337 obj.asFile().writeSymtab(self);
4302 }4338 }
43034339
4304 if (self.got_section_index) |_| {4340 if (self.section_indexes.got) |_| {
4305 self.got.writeSymtab(self);4341 self.got.writeSymtab(self);
4306 }4342 }
43074343
4308 if (self.plt_section_index) |_| {4344 if (self.section_indexes.plt) |_| {
4309 self.plt.writeSymtab(self);4345 self.plt.writeSymtab(self);
4310 }4346 }
43114347
4312 if (self.plt_got_section_index) |_| {4348 if (self.section_indexes.plt_got) |_| {
4313 self.plt_got.writeSymtab(self);4349 self.plt_got.writeSymtab(self);
4314 }4350 }
43154351
...@@ -4482,14 +4518,15 @@ pub fn isEffectivelyDynLib(self: Elf) bool {...@@ -4482,14 +4518,15 @@ pub fn isEffectivelyDynLib(self: Elf) bool {
4482fn getPhdr(self: *Elf, opts: struct {4518fn getPhdr(self: *Elf, opts: struct {
4483 type: u32 = 0,4519 type: u32 = 0,
4484 flags: u32 = 0,4520 flags: u32 = 0,
4485}) ?u16 {4521}) OptionalProgramHeaderIndex {
4486 for (self.phdrs.items, 0..) |phdr, phndx| {4522 for (self.phdrs.items, 0..) |phdr, phndx| {
4487 if (self.phdr_table_load_index) |index| {4523 if (self.phdr_indexes.table_load.int()) |index| {
4488 if (phndx == index) continue;4524 if (phndx == index) continue;
4489 }4525 }
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);
4491 }4528 }
4492 return null;4529 return .none;
4493}4530}
44944531
4495fn addPhdr(self: *Elf, opts: struct {4532fn addPhdr(self: *Elf, opts: struct {
...@@ -4500,9 +4537,9 @@ fn addPhdr(self: *Elf, opts: struct {...@@ -4500,9 +4537,9 @@ fn addPhdr(self: *Elf, opts: struct {
4500 addr: u64 = 0,4537 addr: u64 = 0,
4501 filesz: u64 = 0,4538 filesz: u64 = 0,
4502 memsz: u64 = 0,4539 memsz: u64 = 0,
4503}) error{OutOfMemory}!u16 {4540}) error{OutOfMemory}!ProgramHeaderIndex {
4504 const gpa = self.base.comp.gpa;4541 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);
4506 try self.phdrs.append(gpa, .{4543 try self.phdrs.append(gpa, .{
4507 .p_type = opts.type,4544 .p_type = opts.type,
4508 .p_flags = opts.flags,4545 .p_flags = opts.flags,
...@@ -4667,13 +4704,17 @@ pub fn thunk(self: *Elf, index: Thunk.Index) *Thunk {...@@ -4667,13 +4704,17 @@ pub fn thunk(self: *Elf, index: Thunk.Index) *Thunk {
4667}4704}
46684705
4669pub fn file(self: *Elf, index: File.Index) ?File {4706pub 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];
4671 return switch (tag) {4712 return switch (tag) {
4672 .null => null,4713 .null => null,
4673 .linker_defined => .{ .linker_defined = &self.files.items(.data)[index].linker_defined },4714 .linker_defined => .{ .linker_defined = &files.items(.data)[index].linker_defined },
4674 .zig_object => .{ .zig_object = &self.files.items(.data)[index].zig_object },4715 .zig_object => .{ .zig_object = &files.items(.data)[index].zig_object },
4675 .object => .{ .object = &self.files.items(.data)[index].object },4716 .object => .{ .object = &files.items(.data)[index].object },
4676 .shared_object => .{ .shared_object = &self.files.items(.data)[index].shared_object },4717 .shared_object => .{ .shared_object = &files.items(.data)[index].shared_object },
4677 };4718 };
4678}4719}
46794720
...@@ -4718,7 +4759,7 @@ pub fn linkerDefinedPtr(self: *Elf) ?*LinkerDefined {...@@ -4718,7 +4759,7 @@ pub fn linkerDefinedPtr(self: *Elf) ?*LinkerDefined {
4718 return self.file(index).?.linker_defined;4759 return self.file(index).?.linker_defined;
4719}4760}
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 {
4722 const gpa = self.base.comp.gpa;4763 const gpa = self.base.comp.gpa;
4723 const out_name = name: {4764 const out_name = name: {
4724 if (self.base.isRelocatable()) break :name name;4765 if (self.base.isRelocatable()) break :name name;
...@@ -4731,7 +4772,7 @@ pub fn getOrCreateMergeSection(self: *Elf, name: [:0]const u8, flags: u64, @"typ...@@ -4731,7 +4772,7 @@ pub fn getOrCreateMergeSection(self: *Elf, name: [:0]const u8, flags: u64, @"typ
4731 }4772 }
4732 const out_off = try self.insertShString(out_name);4773 const out_off = try self.insertShString(out_name);
4733 const out_flags = flags & ~@as(u64, elf.SHF_COMPRESSED | elf.SHF_GROUP);4774 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);
4735 const msec = try self.merge_sections.addOne(gpa);4776 const msec = try self.merge_sections.addOne(gpa);
4736 msec.* = .{4777 msec.* = .{
4737 .name_offset = out_off,4778 .name_offset = out_off,
...@@ -4741,22 +4782,22 @@ pub fn getOrCreateMergeSection(self: *Elf, name: [:0]const u8, flags: u64, @"typ...@@ -4741,22 +4782,22 @@ pub fn getOrCreateMergeSection(self: *Elf, name: [:0]const u8, flags: u64, @"typ
4741 return index;4782 return index;
4742}4783}
47434784
4744pub fn mergeSection(self: *Elf, index: MergeSection.Index) *MergeSection {4785pub fn mergeSection(self: *Elf, index: Merge.Section.Index) *Merge.Section {
4745 assert(index < self.merge_sections.items.len);4786 assert(index < self.merge_sections.items.len);
4746 return &self.merge_sections.items[index];4787 return &self.merge_sections.items[index];
4747}4788}
47484789
4749pub fn gotAddress(self: *Elf) i64 {4790pub fn gotAddress(self: *Elf) i64 {
4750 const shndx = blk: {4791 const shndx = blk: {
4751 if (self.getTarget().cpu.arch == .x86_64 and self.got_plt_section_index != null)4792 if (self.getTarget().cpu.arch == .x86_64 and self.section_indexes.got_plt != null)
4752 break :blk self.got_plt_section_index.?;4793 break :blk self.section_indexes.got_plt.?;
4753 break :blk if (self.got_section_index) |shndx| shndx else null;4794 break :blk if (self.section_indexes.got) |shndx| shndx else null;
4754 };4795 };
4755 return if (shndx) |index| @intCast(self.sections.items(.shdr)[index].sh_addr) else 0;4796 return if (shndx) |index| @intCast(self.sections.items(.shdr)[index].sh_addr) else 0;
4756}4797}
47574798
4758pub fn tpAddress(self: *Elf) i64 {4799pub 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;
4760 const phdr = self.phdrs.items[index];4801 const phdr = self.phdrs.items[index];
4761 const addr = switch (self.getTarget().cpu.arch) {4802 const addr = switch (self.getTarget().cpu.arch) {
4762 .x86_64 => mem.alignForward(u64, phdr.p_vaddr + phdr.p_memsz, phdr.p_align),4803 .x86_64 => mem.alignForward(u64, phdr.p_vaddr + phdr.p_memsz, phdr.p_align),
...@@ -4768,20 +4809,27 @@ pub fn tpAddress(self: *Elf) i64 {...@@ -4768,20 +4809,27 @@ pub fn tpAddress(self: *Elf) i64 {
4768}4809}
47694810
4770pub fn dtpAddress(self: *Elf) i64 {4811pub 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;
4772 const phdr = self.phdrs.items[index];4813 const phdr = self.phdrs.items[index];
4773 return @intCast(phdr.p_vaddr);4814 return @intCast(phdr.p_vaddr);
4774}4815}
47754816
4776pub fn tlsAddress(self: *Elf) i64 {4817pub 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;
4778 const phdr = self.phdrs.items[index];4819 const phdr = self.phdrs.items[index];
4779 return @intCast(phdr.p_vaddr);4820 return @intCast(phdr.p_vaddr);
4780}4821}
47814822
4782pub fn getShString(self: Elf, off: u32) [:0]const u8 {4823pub fn getShString(self: Elf, off: u32) [:0]const u8 {
4783 assert(off < self.shstrtab.items.len);4824 return shString(self.shstrtab.items, off);
4784 return mem.sliceTo(@as([*:0]const u8, @ptrCast(self.shstrtab.items.ptr + off)), 0);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];
4785}4833}
47864834
4787pub fn insertShString(self: *Elf, name: [:0]const u8) error{OutOfMemory}!u32 {4835pub fn insertShString(self: *Elf, name: [:0]const u8) error{OutOfMemory}!u32 {
...@@ -5393,7 +5441,7 @@ const Section = struct {...@@ -5393,7 +5441,7 @@ const Section = struct {
5393 shdr: elf.Elf64_Shdr,5441 shdr: elf.Elf64_Shdr,
53945442
5395 /// Assigned program header index if any.5443 /// Assigned program header index if any.
5396 phndx: ?u32 = null,5444 phndx: OptionalProgramHeaderIndex = .none,
53975445
5398 /// List of atoms contributing to this section.5446 /// List of atoms contributing to this section.
5399 /// TODO currently this is only used for relocations tracking in relocatable mode5447 /// TODO currently this is only used for relocations tracking in relocatable mode
...@@ -5533,6 +5581,9 @@ const relocs_log = std.log.scoped(.link_relocs);...@@ -5533,6 +5581,9 @@ const relocs_log = std.log.scoped(.link_relocs);
5533const state_log = std.log.scoped(.link_state);5581const state_log = std.log.scoped(.link_state);
5534const math = std.math;5582const math = std.math;
5535const mem = std.mem;5583const mem = std.mem;
5584const Allocator = std.mem.Allocator;
5585const Cache = std.Build.Cache;
5586const Hash = std.hash.Wyhash;
55365587
5537const codegen = @import("../codegen.zig");5588const codegen = @import("../codegen.zig");
5538const dev = @import("../dev.zig");5589const dev = @import("../dev.zig");
...@@ -5540,7 +5591,6 @@ const eh_frame = @import("Elf/eh_frame.zig");...@@ -5540,7 +5591,6 @@ const eh_frame = @import("Elf/eh_frame.zig");
5540const gc = @import("Elf/gc.zig");5591const gc = @import("Elf/gc.zig");
5541const glibc = @import("../glibc.zig");5592const glibc = @import("../glibc.zig");
5542const link = @import("../link.zig");5593const link = @import("../link.zig");
5543const merge_section = @import("Elf/merge_section.zig");
5544const musl = @import("../musl.zig");5594const musl = @import("../musl.zig");
5545const relocatable = @import("Elf/relocatable.zig");5595const relocatable = @import("Elf/relocatable.zig");
5546const relocation = @import("Elf/relocation.zig");5596const relocation = @import("Elf/relocation.zig");
...@@ -5548,12 +5598,10 @@ const target_util = @import("../target.zig");...@@ -5548,12 +5598,10 @@ const target_util = @import("../target.zig");
5548const trace = @import("../tracy.zig").trace;5598const trace = @import("../tracy.zig").trace;
5549const synthetic_sections = @import("Elf/synthetic_sections.zig");5599const synthetic_sections = @import("Elf/synthetic_sections.zig");
55505600
5601const Merge = @import("Elf/Merge.zig");
5551const Air = @import("../Air.zig");5602const Air = @import("../Air.zig");
5552const Allocator = std.mem.Allocator;
5553const Archive = @import("Elf/Archive.zig");5603const Archive = @import("Elf/Archive.zig");
5554pub const Atom = @import("Elf/Atom.zig");
5555const AtomList = @import("Elf/AtomList.zig");5604const AtomList = @import("Elf/AtomList.zig");
5556const Cache = std.Build.Cache;
5557const Path = Cache.Path;5605const Path = Cache.Path;
5558const Compilation = @import("../Compilation.zig");5606const Compilation = @import("../Compilation.zig");
5559const ComdatGroupSection = synthetic_sections.ComdatGroupSection;5607const ComdatGroupSection = synthetic_sections.ComdatGroupSection;
...@@ -5566,15 +5614,11 @@ const File = @import("Elf/file.zig").File;...@@ -5566,15 +5614,11 @@ const File = @import("Elf/file.zig").File;
5566const GnuHashSection = synthetic_sections.GnuHashSection;5614const GnuHashSection = synthetic_sections.GnuHashSection;
5567const GotSection = synthetic_sections.GotSection;5615const GotSection = synthetic_sections.GotSection;
5568const GotPltSection = synthetic_sections.GotPltSection;5616const GotPltSection = synthetic_sections.GotPltSection;
5569const Hash = std.hash.Wyhash;
5570const HashSection = synthetic_sections.HashSection;5617const HashSection = synthetic_sections.HashSection;
5571const InputMergeSection = merge_section.InputMergeSection;
5572const LdScript = @import("Elf/LdScript.zig");5618const LdScript = @import("Elf/LdScript.zig");
5573const LinkerDefined = @import("Elf/LinkerDefined.zig");5619const LinkerDefined = @import("Elf/LinkerDefined.zig");
5574const Liveness = @import("../Liveness.zig");5620const Liveness = @import("../Liveness.zig");
5575const LlvmObject = @import("../codegen/llvm.zig").Object;5621const LlvmObject = @import("../codegen/llvm.zig").Object;
5576const MergeSection = merge_section.MergeSection;
5577const MergeSubsection = merge_section.MergeSubsection;
5578const Zcu = @import("../Zcu.zig");5622const Zcu = @import("../Zcu.zig");
5579const Object = @import("Elf/Object.zig");5623const Object = @import("Elf/Object.zig");
5580const InternPool = @import("../InternPool.zig");5624const InternPool = @import("../InternPool.zig");
src/link/Elf/LinkerDefined.zig+6-6
...@@ -205,7 +205,7 @@ pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void {...@@ -205,7 +205,7 @@ pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void {
205 }.allocSymbol;205 }.allocSymbol;
206206
207 // _DYNAMIC207 // _DYNAMIC
208 if (elf_file.dynamic_section_index) |shndx| {208 if (elf_file.section_indexes.dynamic) |shndx| {
209 const shdr = shdrs[shndx];209 const shdr = shdrs[shndx];
210 allocSymbol(self, self.dynamic_index.?, shdr.sh_addr, shndx, elf_file);210 allocSymbol(self, self.dynamic_index.?, shdr.sh_addr, shndx, elf_file);
211 }211 }
...@@ -236,19 +236,19 @@ pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void {...@@ -236,19 +236,19 @@ pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void {
236236
237 // _GLOBAL_OFFSET_TABLE_237 // _GLOBAL_OFFSET_TABLE_
238 if (elf_file.getTarget().cpu.arch == .x86_64) {238 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| {
240 const shdr = shdrs[shndx];240 const shdr = shdrs[shndx];
241 allocSymbol(self, self.got_index.?, shdr.sh_addr, shndx, elf_file);241 allocSymbol(self, self.got_index.?, shdr.sh_addr, shndx, elf_file);
242 }242 }
243 } else {243 } else {
244 if (elf_file.got_section_index) |shndx| {244 if (elf_file.section_indexes.got) |shndx| {
245 const shdr = shdrs[shndx];245 const shdr = shdrs[shndx];
246 allocSymbol(self, self.got_index.?, shdr.sh_addr, shndx, elf_file);246 allocSymbol(self, self.got_index.?, shdr.sh_addr, shndx, elf_file);
247 }247 }
248 }248 }
249249
250 // _PROCEDURE_LINKAGE_TABLE_250 // _PROCEDURE_LINKAGE_TABLE_
251 if (elf_file.plt_section_index) |shndx| {251 if (elf_file.section_indexes.plt) |shndx| {
252 const shdr = shdrs[shndx];252 const shdr = shdrs[shndx];
253 allocSymbol(self, self.plt_index.?, shdr.sh_addr, shndx, elf_file);253 allocSymbol(self, self.plt_index.?, shdr.sh_addr, shndx, elf_file);
254 }254 }
...@@ -262,13 +262,13 @@ pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void {...@@ -262,13 +262,13 @@ pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void {
262 }262 }
263263
264 // __GNU_EH_FRAME_HDR264 // __GNU_EH_FRAME_HDR
265 if (elf_file.eh_frame_hdr_section_index) |shndx| {265 if (elf_file.section_indexes.eh_frame_hdr) |shndx| {
266 const shdr = shdrs[shndx];266 const shdr = shdrs[shndx];
267 allocSymbol(self, self.gnu_eh_frame_hdr_index.?, shdr.sh_addr, shndx, elf_file);267 allocSymbol(self, self.gnu_eh_frame_hdr_index.?, shdr.sh_addr, shndx, elf_file);
268 }268 }
269269
270 // __rela_iplt_start, __rela_iplt_end270 // __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: {
272 if (link_mode != .static or comp.config.pie) break :blk;272 if (link_mode != .static or comp.config.pie) break :blk;
273 const shdr = shdrs[shndx];273 const shdr = shdrs[shndx];
274 const end_addr = shdr.sh_addr + shdr.sh_size;274 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,...@@ -23,8 +23,8 @@ atoms_extra: std.ArrayListUnmanaged(u32) = .empty,
23comdat_groups: std.ArrayListUnmanaged(Elf.ComdatGroup) = .empty,23comdat_groups: std.ArrayListUnmanaged(Elf.ComdatGroup) = .empty,
24comdat_group_data: std.ArrayListUnmanaged(u32) = .empty,24comdat_group_data: std.ArrayListUnmanaged(u32) = .empty,
2525
26input_merge_sections: std.ArrayListUnmanaged(InputMergeSection) = .empty,26input_merge_sections: std.ArrayListUnmanaged(Merge.InputSection) = .empty,
27input_merge_sections_indexes: std.ArrayListUnmanaged(InputMergeSection.Index) = .empty,27input_merge_sections_indexes: std.ArrayListUnmanaged(Merge.InputSection.Index) = .empty,
2828
29fdes: std.ArrayListUnmanaged(Fde) = .empty,29fdes: std.ArrayListUnmanaged(Fde) = .empty,
30cies: std.ArrayListUnmanaged(Cie) = .empty,30cies: std.ArrayListUnmanaged(Cie) = .empty,
...@@ -927,7 +927,7 @@ pub fn initRelaSections(self: *Object, elf_file: *Elf) !void {...@@ -927,7 +927,7 @@ pub fn initRelaSections(self: *Object, elf_file: *Elf) !void {
927 for (self.atoms_indexes.items) |atom_index| {927 for (self.atoms_indexes.items) |atom_index| {
928 const atom_ptr = self.atom(atom_index) orelse continue;928 const atom_ptr = self.atom(atom_index) orelse continue;
929 if (!atom_ptr.alive) continue;929 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;
931 const shndx = atom_ptr.relocsShndx() orelse continue;931 const shndx = atom_ptr.relocsShndx() orelse continue;
932 const shdr = self.shdrs.items[shndx];932 const shdr = self.shdrs.items[shndx];
933 const out_shndx = try elf_file.initOutputSection(.{933 const out_shndx = try elf_file.initOutputSection(.{
...@@ -947,7 +947,7 @@ pub fn addAtomsToRelaSections(self: *Object, elf_file: *Elf) !void {...@@ -947,7 +947,7 @@ pub fn addAtomsToRelaSections(self: *Object, elf_file: *Elf) !void {
947 for (self.atoms_indexes.items) |atom_index| {947 for (self.atoms_indexes.items) |atom_index| {
948 const atom_ptr = self.atom(atom_index) orelse continue;948 const atom_ptr = self.atom(atom_index) orelse continue;
949 if (!atom_ptr.alive) continue;949 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;
951 const shndx = blk: {951 const shndx = blk: {
952 const shndx = atom_ptr.relocsShndx() orelse continue;952 const shndx = atom_ptr.relocsShndx() orelse continue;
953 const shdr = self.shdrs.items[shndx];953 const shdr = self.shdrs.items[shndx];
...@@ -960,7 +960,7 @@ pub fn addAtomsToRelaSections(self: *Object, elf_file: *Elf) !void {...@@ -960,7 +960,7 @@ pub fn addAtomsToRelaSections(self: *Object, elf_file: *Elf) !void {
960 const slice = elf_file.sections.slice();960 const slice = elf_file.sections.slice();
961 const shdr = &slice.items(.shdr)[shndx];961 const shdr = &slice.items(.shdr)[shndx];
962 shdr.sh_info = atom_ptr.output_section_index;962 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.?;
964 const gpa = elf_file.base.comp.gpa;964 const gpa = elf_file.base.comp.gpa;
965 const atom_list = &elf_file.sections.items(.atom_list)[shndx];965 const atom_list = &elf_file.sections.items(.atom_list)[shndx];
966 try atom_list.append(gpa, .{ .index = atom_index, .file = self.index });966 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...@@ -1305,14 +1305,14 @@ fn setAtomFields(o: *Object, atom_ptr: *Atom, opts: Atom.Extra.AsOptionals) void
1305 o.setAtomExtra(atom_ptr.extra_index, extras);1305 o.setAtomExtra(atom_ptr.extra_index, extras);
1306}1306}
13071307
1308fn addInputMergeSection(self: *Object, allocator: Allocator) !InputMergeSection.Index {1308fn addInputMergeSection(self: *Object, allocator: Allocator) !Merge.InputSection.Index {
1309 const index: InputMergeSection.Index = @intCast(self.input_merge_sections.items.len);1309 const index: Merge.InputSection.Index = @intCast(self.input_merge_sections.items.len);
1310 const msec = try self.input_merge_sections.addOne(allocator);1310 const msec = try self.input_merge_sections.addOne(allocator);
1311 msec.* = .{};1311 msec.* = .{};
1312 return index;1312 return index;
1313}1313}
13141314
1315fn inputMergeSection(self: *Object, index: InputMergeSection.Index) ?*InputMergeSection {1315fn inputMergeSection(self: *Object, index: Merge.InputSection.Index) ?*Merge.InputSection {
1316 if (index == 0) return null;1316 if (index == 0) return null;
1317 return &self.input_merge_sections.items[index];1317 return &self.input_merge_sections.items[index];
1318}1318}
...@@ -1522,6 +1522,6 @@ const Cie = eh_frame.Cie;...@@ -1522,6 +1522,6 @@ const Cie = eh_frame.Cie;
1522const Elf = @import("../Elf.zig");1522const Elf = @import("../Elf.zig");
1523const Fde = eh_frame.Fde;1523const Fde = eh_frame.Fde;
1524const File = @import("file.zig").File;1524const File = @import("file.zig").File;
1525const InputMergeSection = @import("merge_section.zig").InputMergeSection;1525const Merge = @import("Merge.zig");
1526const Symbol = @import("Symbol.zig");1526const Symbol = @import("Symbol.zig");
1527const Alignment = Atom.Alignment;1527const Alignment = Atom.Alignment;
src/link/Elf/Symbol.zig+8-8
...@@ -74,7 +74,7 @@ pub fn atom(symbol: Symbol, elf_file: *Elf) ?*Atom {...@@ -74,7 +74,7 @@ pub fn atom(symbol: Symbol, elf_file: *Elf) ?*Atom {
74 return file_ptr.atom(symbol.ref.index);74 return file_ptr.atom(symbol.ref.index);
75}75}
7676
77pub fn mergeSubsection(symbol: Symbol, elf_file: *Elf) ?*MergeSubsection {77pub fn mergeSubsection(symbol: Symbol, elf_file: *Elf) ?*Merge.Subsection {
78 if (!symbol.flags.merge_subsection) return null;78 if (!symbol.flags.merge_subsection) return null;
79 const msec = elf_file.mergeSection(symbol.ref.file);79 const msec = elf_file.mergeSection(symbol.ref.file);
80 return msec.mergeSubsection(symbol.ref.index);80 return msec.mergeSubsection(symbol.ref.index);
...@@ -128,7 +128,7 @@ pub fn address(symbol: Symbol, opts: struct { plt: bool = true, trampoline: bool...@@ -128,7 +128,7 @@ pub fn address(symbol: Symbol, opts: struct { plt: bool = true, trampoline: bool
128 if (mem.eql(u8, atom_ptr.name(elf_file), ".eh_frame")) {128 if (mem.eql(u8, atom_ptr.name(elf_file), ".eh_frame")) {
129 const sym_name = symbol.name(elf_file);129 const sym_name = symbol.name(elf_file);
130 const sh_addr, const sh_size = blk: {130 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 };
132 const shdr = elf_file.sections.items(.shdr)[shndx];132 const shdr = elf_file.sections.items(.shdr)[shndx];
133 break :blk .{ shdr.sh_addr, shdr.sh_size };133 break :blk .{ shdr.sh_addr, shdr.sh_size };
134 };134 };
...@@ -176,7 +176,7 @@ pub fn gotAddress(symbol: Symbol, elf_file: *Elf) i64 {...@@ -176,7 +176,7 @@ pub fn gotAddress(symbol: Symbol, elf_file: *Elf) i64 {
176pub fn pltGotAddress(symbol: Symbol, elf_file: *Elf) i64 {176pub fn pltGotAddress(symbol: Symbol, elf_file: *Elf) i64 {
177 if (!symbol.flags.has_pltgot) return 0;177 if (!symbol.flags.has_pltgot) return 0;
178 const extras = symbol.extra(elf_file);178 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.?];
180 const cpu_arch = elf_file.getTarget().cpu.arch;180 const cpu_arch = elf_file.getTarget().cpu.arch;
181 return @intCast(shdr.sh_addr + extras.plt_got * PltGotSection.entrySize(cpu_arch));181 return @intCast(shdr.sh_addr + extras.plt_got * PltGotSection.entrySize(cpu_arch));
182}182}
...@@ -184,7 +184,7 @@ pub fn pltGotAddress(symbol: Symbol, elf_file: *Elf) i64 {...@@ -184,7 +184,7 @@ pub fn pltGotAddress(symbol: Symbol, elf_file: *Elf) i64 {
184pub fn pltAddress(symbol: Symbol, elf_file: *Elf) i64 {184pub fn pltAddress(symbol: Symbol, elf_file: *Elf) i64 {
185 if (!symbol.flags.has_plt) return 0;185 if (!symbol.flags.has_plt) return 0;
186 const extras = symbol.extra(elf_file);186 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.?];
188 const cpu_arch = elf_file.getTarget().cpu.arch;188 const cpu_arch = elf_file.getTarget().cpu.arch;
189 return @intCast(shdr.sh_addr + extras.plt * PltSection.entrySize(cpu_arch) + PltSection.preambleSize(cpu_arch));189 return @intCast(shdr.sh_addr + extras.plt * PltSection.entrySize(cpu_arch) + PltSection.preambleSize(cpu_arch));
190}190}
...@@ -192,13 +192,13 @@ pub fn pltAddress(symbol: Symbol, elf_file: *Elf) i64 {...@@ -192,13 +192,13 @@ pub fn pltAddress(symbol: Symbol, elf_file: *Elf) i64 {
192pub fn gotPltAddress(symbol: Symbol, elf_file: *Elf) i64 {192pub fn gotPltAddress(symbol: Symbol, elf_file: *Elf) i64 {
193 if (!symbol.flags.has_plt) return 0;193 if (!symbol.flags.has_plt) return 0;
194 const extras = symbol.extra(elf_file);194 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.?];
196 return @intCast(shdr.sh_addr + extras.plt * 8 + GotPltSection.preamble_size);196 return @intCast(shdr.sh_addr + extras.plt * 8 + GotPltSection.preamble_size);
197}197}
198198
199pub fn copyRelAddress(symbol: Symbol, elf_file: *Elf) i64 {199pub fn copyRelAddress(symbol: Symbol, elf_file: *Elf) i64 {
200 if (!symbol.flags.has_copy_rel) return 0;200 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.?];
202 return @as(i64, @intCast(shdr.sh_addr)) + symbol.value;202 return @as(i64, @intCast(shdr.sh_addr)) + symbol.value;
203}203}
204204
...@@ -289,7 +289,7 @@ pub fn setOutputSym(symbol: Symbol, elf_file: *Elf, out: *elf.Elf64_Sym) void {...@@ -289,7 +289,7 @@ pub fn setOutputSym(symbol: Symbol, elf_file: *Elf, out: *elf.Elf64_Sym) void {
289 break :blk esym.st_bind();289 break :blk esym.st_bind();
290 };290 };
291 const st_shndx: u16 = blk: {291 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.?);
293 if (file_ptr == .shared_object or esym.st_shndx == elf.SHN_UNDEF) break :blk elf.SHN_UNDEF;293 if (file_ptr == .shared_object or esym.st_shndx == elf.SHN_UNDEF) break :blk elf.SHN_UNDEF;
294 if (elf_file.base.isRelocatable() and esym.st_shndx == elf.SHN_COMMON) break :blk elf.SHN_COMMON;294 if (elf_file.base.isRelocatable() and esym.st_shndx == elf.SHN_COMMON) break :blk elf.SHN_COMMON;
295 if (symbol.mergeSubsection(elf_file)) |msub| break :blk @intCast(msub.mergeSection(elf_file).output_section_index);295 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;...@@ -493,7 +493,7 @@ const File = @import("file.zig").File;
493const GotSection = synthetic_sections.GotSection;493const GotSection = synthetic_sections.GotSection;
494const GotPltSection = synthetic_sections.GotPltSection;494const GotPltSection = synthetic_sections.GotPltSection;
495const LinkerDefined = @import("LinkerDefined.zig");495const LinkerDefined = @import("LinkerDefined.zig");
496const MergeSubsection = @import("merge_section.zig").MergeSubsection;496const Merge = @import("Merge.zig");
497const Object = @import("Object.zig");497const Object = @import("Object.zig");
498const PltSection = synthetic_sections.PltSection;498const PltSection = synthetic_sections.PltSection;
499const PltGotSection = synthetic_sections.PltGotSection;499const PltGotSection = synthetic_sections.PltGotSection;
src/link/Elf/ZigObject.zig+4-4
...@@ -791,7 +791,7 @@ pub fn initRelaSections(self: *ZigObject, elf_file: *Elf) !void {...@@ -791,7 +791,7 @@ pub fn initRelaSections(self: *ZigObject, elf_file: *Elf) !void {
791 for (self.atoms_indexes.items) |atom_index| {791 for (self.atoms_indexes.items) |atom_index| {
792 const atom_ptr = self.atom(atom_index) orelse continue;792 const atom_ptr = self.atom(atom_index) orelse continue;
793 if (!atom_ptr.alive) continue;793 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;
795 const rela_shndx = atom_ptr.relocsShndx() orelse continue;795 const rela_shndx = atom_ptr.relocsShndx() orelse continue;
796 // TODO this check will become obsolete when we rework our relocs mechanism at the ZigObject level796 // TODO this check will become obsolete when we rework our relocs mechanism at the ZigObject level
797 if (self.relocs.items[rela_shndx].items.len == 0) continue;797 if (self.relocs.items[rela_shndx].items.len == 0) continue;
...@@ -812,7 +812,7 @@ pub fn addAtomsToRelaSections(self: *ZigObject, elf_file: *Elf) !void {...@@ -812,7 +812,7 @@ pub fn addAtomsToRelaSections(self: *ZigObject, elf_file: *Elf) !void {
812 for (self.atoms_indexes.items) |atom_index| {812 for (self.atoms_indexes.items) |atom_index| {
813 const atom_ptr = self.atom(atom_index) orelse continue;813 const atom_ptr = self.atom(atom_index) orelse continue;
814 if (!atom_ptr.alive) continue;814 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;
816 const rela_shndx = atom_ptr.relocsShndx() orelse continue;816 const rela_shndx = atom_ptr.relocsShndx() orelse continue;
817 // TODO this check will become obsolete when we rework our relocs mechanism at the ZigObject level817 // TODO this check will become obsolete when we rework our relocs mechanism at the ZigObject level
818 if (self.relocs.items[rela_shndx].items.len == 0) continue;818 if (self.relocs.items[rela_shndx].items.len == 0) continue;
...@@ -826,7 +826,7 @@ pub fn addAtomsToRelaSections(self: *ZigObject, elf_file: *Elf) !void {...@@ -826,7 +826,7 @@ pub fn addAtomsToRelaSections(self: *ZigObject, elf_file: *Elf) !void {
826 const out_rela_shndx = elf_file.sectionByName(rela_sect_name).?;826 const out_rela_shndx = elf_file.sectionByName(rela_sect_name).?;
827 const out_rela_shdr = &elf_file.sections.items(.shdr)[out_rela_shndx];827 const out_rela_shdr = &elf_file.sections.items(.shdr)[out_rela_shndx];
828 out_rela_shdr.sh_info = out_shndx;828 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.?;
830 const atom_list = &elf_file.sections.items(.atom_list)[out_rela_shndx];830 const atom_list = &elf_file.sections.items(.atom_list)[out_rela_shndx];
831 try atom_list.append(gpa, .{ .index = atom_index, .file = self.index });831 try atom_list.append(gpa, .{ .index = atom_index, .file = self.index });
832 }832 }
...@@ -2027,7 +2027,7 @@ pub fn allocateAtom(self: *ZigObject, atom_ptr: *Atom, requires_padding: bool, e...@@ -2027,7 +2027,7 @@ pub fn allocateAtom(self: *ZigObject, atom_ptr: *Atom, requires_padding: bool, e
2027 log.debug(" prev {?}, next {?}", .{ atom_ptr.prev_atom_ref, atom_ptr.next_atom_ref });2027 log.debug(" prev {?}, next {?}", .{ atom_ptr.prev_atom_ref, atom_ptr.next_atom_ref });
2028}2028}
20292029
2030pub fn resetShdrIndexes(self: *ZigObject, backlinks: anytype) void {2030pub fn resetShdrIndexes(self: *ZigObject, backlinks: []const u32) void {
2031 for (self.atoms_indexes.items) |atom_index| {2031 for (self.atoms_indexes.items) |atom_index| {
2032 const atom_ptr = self.atom(atom_index) orelse continue;2032 const atom_ptr = self.atom(atom_index) orelse continue;
2033 atom_ptr.output_section_index = backlinks[atom_ptr.output_section_index];2033 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 {...@@ -12,7 +12,7 @@ pub const Fde = struct {
12 out_offset: u64 = 0,12 out_offset: u64 = 0,
1313
14 pub fn address(fde: Fde, elf_file: *Elf) u64 {14 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|
16 elf_file.sections.items(.shdr)[shndx].sh_addr16 elf_file.sections.items(.shdr)[shndx].sh_addr
17 else17 else
18 0;18 0;
...@@ -111,7 +111,7 @@ pub const Cie = struct {...@@ -111,7 +111,7 @@ pub const Cie = struct {
111 alive: bool = false,111 alive: bool = false,
112112
113 pub fn address(cie: Cie, elf_file: *Elf) u64 {113 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|
115 elf_file.sections.items(.shdr)[shndx].sh_addr115 elf_file.sections.items(.shdr)[shndx].sh_addr
116 else116 else
117 0;117 0;
...@@ -337,7 +337,7 @@ fn resolveReloc(rec: anytype, sym: *const Symbol, rel: elf.Elf64_Rela, elf_file:...@@ -337,7 +337,7 @@ fn resolveReloc(rec: anytype, sym: *const Symbol, rel: elf.Elf64_Rela, elf_file:
337337
338pub fn writeEhFrame(elf_file: *Elf, writer: anytype) !void {338pub fn writeEhFrame(elf_file: *Elf, writer: anytype) !void {
339 relocs_log.debug("{x}: .eh_frame", .{339 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,
341 });341 });
342342
343 var has_reloc_errors = false;343 var has_reloc_errors = false;
...@@ -458,7 +458,7 @@ fn emitReloc(elf_file: *Elf, r_offset: u64, sym: *const Symbol, rel: elf.Elf64_R...@@ -458,7 +458,7 @@ fn emitReloc(elf_file: *Elf, r_offset: u64, sym: *const Symbol, rel: elf.Elf64_R
458458
459pub fn writeEhFrameRelocs(elf_file: *Elf, writer: anytype) !void {459pub fn writeEhFrameRelocs(elf_file: *Elf, writer: anytype) !void {
460 relocs_log.debug("{x}: .eh_frame", .{460 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,
462 });462 });
463463
464 if (elf_file.zigObjectPtr()) |zo| zo: {464 if (elf_file.zigObjectPtr()) |zo| zo: {
...@@ -511,8 +511,8 @@ pub fn writeEhFrameHdr(elf_file: *Elf, writer: anytype) !void {...@@ -511,8 +511,8 @@ pub fn writeEhFrameHdr(elf_file: *Elf, writer: anytype) !void {
511 try writer.writeByte(DW_EH_PE.datarel | DW_EH_PE.sdata4);511 try writer.writeByte(DW_EH_PE.datarel | DW_EH_PE.sdata4);
512512
513 const shdrs = elf_file.sections.items(.shdr);513 const shdrs = elf_file.sections.items(.shdr);
514 const eh_frame_shdr = shdrs[elf_file.eh_frame_section_index.?];514 const eh_frame_shdr = shdrs[elf_file.section_indexes.eh_frame.?];
515 const eh_frame_hdr_shdr = shdrs[elf_file.eh_frame_hdr_section_index.?];515 const eh_frame_hdr_shdr = shdrs[elf_file.section_indexes.eh_frame_hdr.?];
516 const num_fdes = @as(u32, @intCast(@divExact(eh_frame_hdr_shdr.sh_size - eh_frame_hdr_header_size, 8)));516 const num_fdes = @as(u32, @intCast(@divExact(eh_frame_hdr_shdr.sh_size - eh_frame_hdr_header_size, 8)));
517 const existing_size = existing_size: {517 const existing_size = existing_size: {
518 const zo = elf_file.zigObjectPtr() orelse break :existing_size 0;518 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...@@ -32,7 +32,16 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation, module_obj_path: ?Path
32 zig_object.claimUnresolvedRelocatable(elf_file);32 zig_object.claimUnresolvedRelocatable(elf_file);
3333
34 try initSections(elf_file);34 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 );
36 try zig_object.addAtomsToRelaSections(elf_file);45 try zig_object.addAtomsToRelaSections(elf_file);
37 try elf_file.updateMergeSectionSizes();46 try elf_file.updateMergeSectionSizes();
38 try updateSectionSizes(elf_file);47 try updateSectionSizes(elf_file);
...@@ -171,7 +180,16 @@ pub fn flushObject(elf_file: *Elf, comp: *Compilation, module_obj_path: ?Path) l...@@ -171,7 +180,16 @@ pub fn flushObject(elf_file: *Elf, comp: *Compilation, module_obj_path: ?Path) l
171 claimUnresolved(elf_file);180 claimUnresolved(elf_file);
172181
173 try initSections(elf_file);182 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 );
175 if (elf_file.zigObjectPtr()) |zig_object| {193 if (elf_file.zigObjectPtr()) |zig_object| {
176 try zig_object.addAtomsToRelaSections(elf_file);194 try zig_object.addAtomsToRelaSections(elf_file);
177 }195 }
...@@ -288,8 +306,8 @@ fn initSections(elf_file: *Elf) !void {...@@ -288,8 +306,8 @@ fn initSections(elf_file: *Elf) !void {
288 } else false;306 } else false;
289 };307 };
290 if (needs_eh_frame) {308 if (needs_eh_frame) {
291 if (elf_file.eh_frame_section_index == null) {309 if (elf_file.section_indexes.eh_frame == null) {
292 elf_file.eh_frame_section_index = elf_file.sectionByName(".eh_frame") orelse310 elf_file.section_indexes.eh_frame = elf_file.sectionByName(".eh_frame") orelse
293 try elf_file.addSection(.{311 try elf_file.addSection(.{
294 .name = try elf_file.insertShString(".eh_frame"),312 .name = try elf_file.insertShString(".eh_frame"),
295 .type = if (elf_file.getTarget().cpu.arch == .x86_64)313 .type = if (elf_file.getTarget().cpu.arch == .x86_64)
...@@ -300,10 +318,10 @@ fn initSections(elf_file: *Elf) !void {...@@ -300,10 +318,10 @@ fn initSections(elf_file: *Elf) !void {
300 .addralign = elf_file.ptrWidthBytes(),318 .addralign = elf_file.ptrWidthBytes(),
301 });319 });
302 }320 }
303 elf_file.eh_frame_rela_section_index = elf_file.sectionByName(".rela.eh_frame") orelse321 elf_file.section_indexes.eh_frame_rela = elf_file.sectionByName(".rela.eh_frame") orelse
304 try elf_file.addRelaShdr(322 try elf_file.addRelaShdr(
305 try elf_file.insertShString(".rela.eh_frame"),323 try elf_file.insertShString(".rela.eh_frame"),
306 elf_file.eh_frame_section_index.?,324 elf_file.section_indexes.eh_frame.?,
307 );325 );
308 }326 }
309327
...@@ -346,7 +364,7 @@ fn updateSectionSizes(elf_file: *Elf) !void {...@@ -346,7 +364,7 @@ fn updateSectionSizes(elf_file: *Elf) !void {
346 for (slice.items(.shdr), 0..) |*shdr, shndx| {364 for (slice.items(.shdr), 0..) |*shdr, shndx| {
347 const atom_list = slice.items(.atom_list)[shndx];365 const atom_list = slice.items(.atom_list)[shndx];
348 if (shdr.sh_type != elf.SHT_RELA) continue;366 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;
350 for (atom_list.items) |ref| {368 for (atom_list.items) |ref| {
351 const atom_ptr = elf_file.atom(ref) orelse continue;369 const atom_ptr = elf_file.atom(ref) orelse continue;
352 if (!atom_ptr.alive) continue;370 if (!atom_ptr.alive) continue;
...@@ -357,10 +375,10 @@ fn updateSectionSizes(elf_file: *Elf) !void {...@@ -357,10 +375,10 @@ fn updateSectionSizes(elf_file: *Elf) !void {
357 if (shdr.sh_size == 0) shdr.sh_offset = 0;375 if (shdr.sh_size == 0) shdr.sh_offset = 0;
358 }376 }
359377
360 if (elf_file.eh_frame_section_index) |index| {378 if (elf_file.section_indexes.eh_frame) |index| {
361 slice.items(.shdr)[index].sh_size = try eh_frame.calcEhFrameSize(elf_file);379 slice.items(.shdr)[index].sh_size = try eh_frame.calcEhFrameSize(elf_file);
362 }380 }
363 if (elf_file.eh_frame_rela_section_index) |index| {381 if (elf_file.section_indexes.eh_frame_rela) |index| {
364 const shdr = &slice.items(.shdr)[index];382 const shdr = &slice.items(.shdr)[index];
365 shdr.sh_size = eh_frame.calcEhFrameRelocs(elf_file) * shdr.sh_entsize;383 shdr.sh_size = eh_frame.calcEhFrameRelocs(elf_file) * shdr.sh_entsize;
366 }384 }
...@@ -374,7 +392,7 @@ fn updateComdatGroupsSizes(elf_file: *Elf) void {...@@ -374,7 +392,7 @@ fn updateComdatGroupsSizes(elf_file: *Elf) void {
374 for (elf_file.comdat_group_sections.items) |cg| {392 for (elf_file.comdat_group_sections.items) |cg| {
375 const shdr = &elf_file.sections.items(.shdr)[cg.shndx];393 const shdr = &elf_file.sections.items(.shdr)[cg.shndx];
376 shdr.sh_size = cg.size(elf_file);394 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
379 const sym = cg.symbol(elf_file);397 const sym = cg.symbol(elf_file);
380 shdr.sh_info = sym.outputSymtabIndex(elf_file) orelse sym.outputShndx(elf_file).?;398 shdr.sh_info = sym.outputSymtabIndex(elf_file) orelse sym.outputShndx(elf_file).?;
...@@ -439,7 +457,7 @@ fn writeSyntheticSections(elf_file: *Elf) !void {...@@ -439,7 +457,7 @@ fn writeSyntheticSections(elf_file: *Elf) !void {
439 for (slice.items(.shdr), slice.items(.atom_list), 0..) |shdr, atom_list, shndx| {457 for (slice.items(.shdr), slice.items(.atom_list), 0..) |shdr, atom_list, shndx| {
440 if (shdr.sh_type != elf.SHT_RELA) continue;458 if (shdr.sh_type != elf.SHT_RELA) continue;
441 if (atom_list.items.len == 0) continue;459 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
444 const num_relocs = math.cast(usize, @divExact(shdr.sh_size, shdr.sh_entsize)) orelse462 const num_relocs = math.cast(usize, @divExact(shdr.sh_size, shdr.sh_entsize)) orelse
445 return error.Overflow;463 return error.Overflow;
...@@ -471,7 +489,7 @@ fn writeSyntheticSections(elf_file: *Elf) !void {...@@ -471,7 +489,7 @@ fn writeSyntheticSections(elf_file: *Elf) !void {
471 try elf_file.base.file.?.pwriteAll(mem.sliceAsBytes(relocs.items), shdr.sh_offset);489 try elf_file.base.file.?.pwriteAll(mem.sliceAsBytes(relocs.items), shdr.sh_offset);
472 }490 }
473491
474 if (elf_file.eh_frame_section_index) |shndx| {492 if (elf_file.section_indexes.eh_frame) |shndx| {
475 const existing_size = existing_size: {493 const existing_size = existing_size: {
476 const zo = elf_file.zigObjectPtr() orelse break :existing_size 0;494 const zo = elf_file.zigObjectPtr() orelse break :existing_size 0;
477 const sym = zo.symbol(zo.eh_frame_index orelse break :existing_size 0);495 const sym = zo.symbol(zo.eh_frame_index orelse break :existing_size 0);
...@@ -489,7 +507,7 @@ fn writeSyntheticSections(elf_file: *Elf) !void {...@@ -489,7 +507,7 @@ fn writeSyntheticSections(elf_file: *Elf) !void {
489 assert(buffer.items.len == sh_size - existing_size);507 assert(buffer.items.len == sh_size - existing_size);
490 try elf_file.base.file.?.pwriteAll(buffer.items, shdr.sh_offset + existing_size);508 try elf_file.base.file.?.pwriteAll(buffer.items, shdr.sh_offset + existing_size);
491 }509 }
492 if (elf_file.eh_frame_rela_section_index) |shndx| {510 if (elf_file.section_indexes.eh_frame_rela) |shndx| {
493 const shdr = slice.items(.shdr)[shndx];511 const shdr = slice.items(.shdr)[shndx];
494 const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow;512 const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow;
495 var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size);513 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 {...@@ -75,18 +75,18 @@ pub const DynamicSection = struct {
75 if (elf_file.sectionByName(".fini") != null) nentries += 1; // FINI75 if (elf_file.sectionByName(".fini") != null) nentries += 1; // FINI
76 if (elf_file.sectionByName(".init_array") != null) nentries += 2; // INIT_ARRAY76 if (elf_file.sectionByName(".init_array") != null) nentries += 2; // INIT_ARRAY
77 if (elf_file.sectionByName(".fini_array") != null) nentries += 2; // FINI_ARRAY77 if (elf_file.sectionByName(".fini_array") != null) nentries += 2; // FINI_ARRAY
78 if (elf_file.rela_dyn_section_index != null) nentries += 3; // RELA78 if (elf_file.section_indexes.rela_dyn != null) nentries += 3; // RELA
79 if (elf_file.rela_plt_section_index != null) nentries += 3; // JMPREL79 if (elf_file.section_indexes.rela_plt != null) nentries += 3; // JMPREL
80 if (elf_file.got_plt_section_index != null) nentries += 1; // PLTGOT80 if (elf_file.section_indexes.got_plt != null) nentries += 1; // PLTGOT
81 nentries += 1; // HASH81 nentries += 1; // HASH
82 if (elf_file.gnu_hash_section_index != null) nentries += 1; // GNU_HASH82 if (elf_file.section_indexes.gnu_hash != null) nentries += 1; // GNU_HASH
83 if (elf_file.has_text_reloc) nentries += 1; // TEXTREL83 if (elf_file.has_text_reloc) nentries += 1; // TEXTREL
84 nentries += 1; // SYMTAB84 nentries += 1; // SYMTAB
85 nentries += 1; // SYMENT85 nentries += 1; // SYMENT
86 nentries += 1; // STRTAB86 nentries += 1; // STRTAB
87 nentries += 1; // STRSZ87 nentries += 1; // STRSZ
88 if (elf_file.versym_section_index != null) nentries += 1; // VERSYM88 if (elf_file.section_indexes.versym != null) nentries += 1; // VERSYM
89 if (elf_file.verneed_section_index != null) nentries += 2; // VERNEED89 if (elf_file.section_indexes.verneed != null) nentries += 2; // VERNEED
90 if (dt.getFlags(elf_file) != null) nentries += 1; // FLAGS90 if (dt.getFlags(elf_file) != null) nentries += 1; // FLAGS
91 if (dt.getFlags1(elf_file) != null) nentries += 1; // FLAGS_191 if (dt.getFlags1(elf_file) != null) nentries += 1; // FLAGS_1
92 if (!elf_file.isEffectivelyDynLib()) nentries += 1; // DEBUG92 if (!elf_file.isEffectivelyDynLib()) nentries += 1; // DEBUG
...@@ -139,7 +139,7 @@ pub const DynamicSection = struct {...@@ -139,7 +139,7 @@ pub const DynamicSection = struct {
139 }139 }
140140
141 // RELA141 // RELA
142 if (elf_file.rela_dyn_section_index) |shndx| {142 if (elf_file.section_indexes.rela_dyn) |shndx| {
143 const shdr = shdrs[shndx];143 const shdr = shdrs[shndx];
144 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_RELA, .d_val = shdr.sh_addr });144 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_RELA, .d_val = shdr.sh_addr });
145 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_RELASZ, .d_val = shdr.sh_size });145 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_RELASZ, .d_val = shdr.sh_size });
...@@ -147,7 +147,7 @@ pub const DynamicSection = struct {...@@ -147,7 +147,7 @@ pub const DynamicSection = struct {
147 }147 }
148148
149 // JMPREL149 // JMPREL
150 if (elf_file.rela_plt_section_index) |shndx| {150 if (elf_file.section_indexes.rela_plt) |shndx| {
151 const shdr = shdrs[shndx];151 const shdr = shdrs[shndx];
152 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_JMPREL, .d_val = shdr.sh_addr });152 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_JMPREL, .d_val = shdr.sh_addr });
153 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_PLTRELSZ, .d_val = shdr.sh_size });153 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_PLTRELSZ, .d_val = shdr.sh_size });
...@@ -155,18 +155,18 @@ pub const DynamicSection = struct {...@@ -155,18 +155,18 @@ pub const DynamicSection = struct {
155 }155 }
156156
157 // PLTGOT157 // PLTGOT
158 if (elf_file.got_plt_section_index) |shndx| {158 if (elf_file.section_indexes.got_plt) |shndx| {
159 const addr = shdrs[shndx].sh_addr;159 const addr = shdrs[shndx].sh_addr;
160 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_PLTGOT, .d_val = addr });160 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_PLTGOT, .d_val = addr });
161 }161 }
162162
163 {163 {
164 assert(elf_file.hash_section_index != null);164 assert(elf_file.section_indexes.hash != null);
165 const addr = shdrs[elf_file.hash_section_index.?].sh_addr;165 const addr = shdrs[elf_file.section_indexes.hash.?].sh_addr;
166 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_HASH, .d_val = addr });166 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_HASH, .d_val = addr });
167 }167 }
168168
169 if (elf_file.gnu_hash_section_index) |shndx| {169 if (elf_file.section_indexes.gnu_hash) |shndx| {
170 const addr = shdrs[shndx].sh_addr;170 const addr = shdrs[shndx].sh_addr;
171 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_GNU_HASH, .d_val = addr });171 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_GNU_HASH, .d_val = addr });
172 }172 }
...@@ -178,28 +178,28 @@ pub const DynamicSection = struct {...@@ -178,28 +178,28 @@ pub const DynamicSection = struct {
178178
179 // SYMTAB + SYMENT179 // SYMTAB + SYMENT
180 {180 {
181 assert(elf_file.dynsymtab_section_index != null);181 assert(elf_file.section_indexes.dynsymtab != null);
182 const shdr = shdrs[elf_file.dynsymtab_section_index.?];182 const shdr = shdrs[elf_file.section_indexes.dynsymtab.?];
183 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_SYMTAB, .d_val = shdr.sh_addr });183 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_SYMTAB, .d_val = shdr.sh_addr });
184 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_SYMENT, .d_val = shdr.sh_entsize });184 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_SYMENT, .d_val = shdr.sh_entsize });
185 }185 }
186186
187 // STRTAB + STRSZ187 // STRTAB + STRSZ
188 {188 {
189 assert(elf_file.dynstrtab_section_index != null);189 assert(elf_file.section_indexes.dynstrtab != null);
190 const shdr = shdrs[elf_file.dynstrtab_section_index.?];190 const shdr = shdrs[elf_file.section_indexes.dynstrtab.?];
191 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_STRTAB, .d_val = shdr.sh_addr });191 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_STRTAB, .d_val = shdr.sh_addr });
192 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_STRSZ, .d_val = shdr.sh_size });192 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_STRSZ, .d_val = shdr.sh_size });
193 }193 }
194194
195 // VERSYM195 // VERSYM
196 if (elf_file.versym_section_index) |shndx| {196 if (elf_file.section_indexes.versym) |shndx| {
197 const addr = shdrs[shndx].sh_addr;197 const addr = shdrs[shndx].sh_addr;
198 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_VERSYM, .d_val = addr });198 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_VERSYM, .d_val = addr });
199 }199 }
200200
201 // VERNEED + VERNEEDNUM201 // VERNEED + VERNEEDNUM
202 if (elf_file.verneed_section_index) |shndx| {202 if (elf_file.section_indexes.verneed) |shndx| {
203 const addr = shdrs[shndx].sh_addr;203 const addr = shdrs[shndx].sh_addr;
204 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_VERNEED, .d_val = addr });204 try writer.writeStruct(elf.Elf64_Dyn{ .d_tag = elf.DT_VERNEED, .d_val = addr });
205 try writer.writeStruct(elf.Elf64_Dyn{205 try writer.writeStruct(elf.Elf64_Dyn{
...@@ -261,7 +261,7 @@ pub const GotSection = struct {...@@ -261,7 +261,7 @@ pub const GotSection = struct {
261261
262 pub fn address(entry: Entry, elf_file: *Elf) i64 {262 pub fn address(entry: Entry, elf_file: *Elf) i64 {
263 const ptr_bytes = elf_file.archPtrWidthBytes();263 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.?];
265 return @as(i64, @intCast(shdr.sh_addr)) + entry.cell_index * ptr_bytes;265 return @as(i64, @intCast(shdr.sh_addr)) + entry.cell_index * ptr_bytes;
266 }266 }
267 };267 };
...@@ -599,7 +599,7 @@ pub const GotSection = struct {...@@ -599,7 +599,7 @@ pub const GotSection = struct {
599 .st_name = st_name,599 .st_name = st_name,
600 .st_info = elf.STT_OBJECT,600 .st_info = elf.STT_OBJECT,
601 .st_other = 0,601 .st_other = 0,
602 .st_shndx = @intCast(elf_file.got_section_index.?),602 .st_shndx = @intCast(elf_file.section_indexes.got.?),
603 .st_value = @intCast(st_value),603 .st_value = @intCast(st_value),
604 .st_size = st_size,604 .st_size = st_size,
605 };605 };
...@@ -742,7 +742,7 @@ pub const PltSection = struct {...@@ -742,7 +742,7 @@ pub const PltSection = struct {
742 .st_name = st_name,742 .st_name = st_name,
743 .st_info = elf.STT_FUNC,743 .st_info = elf.STT_FUNC,
744 .st_other = 0,744 .st_other = 0,
745 .st_shndx = @intCast(elf_file.plt_section_index.?),745 .st_shndx = @intCast(elf_file.section_indexes.plt.?),
746 .st_value = @intCast(sym.pltAddress(elf_file)),746 .st_value = @intCast(sym.pltAddress(elf_file)),
747 .st_size = entrySize(cpu_arch),747 .st_size = entrySize(cpu_arch),
748 };748 };
...@@ -784,8 +784,8 @@ pub const PltSection = struct {...@@ -784,8 +784,8 @@ pub const PltSection = struct {
784 const x86_64 = struct {784 const x86_64 = struct {
785 fn write(plt: PltSection, elf_file: *Elf, writer: anytype) !void {785 fn write(plt: PltSection, elf_file: *Elf, writer: anytype) !void {
786 const shdrs = elf_file.sections.items(.shdr);786 const shdrs = elf_file.sections.items(.shdr);
787 const plt_addr = shdrs[elf_file.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.got_plt_section_index.?].sh_addr;788 const got_plt_addr = shdrs[elf_file.section_indexes.got_plt.?].sh_addr;
789 var preamble = [_]u8{789 var preamble = [_]u8{
790 0xf3, 0x0f, 0x1e, 0xfa, // endbr64790 0xf3, 0x0f, 0x1e, 0xfa, // endbr64
791 0x41, 0x53, // push r11791 0x41, 0x53, // push r11
...@@ -820,8 +820,8 @@ pub const PltSection = struct {...@@ -820,8 +820,8 @@ pub const PltSection = struct {
820 fn write(plt: PltSection, elf_file: *Elf, writer: anytype) !void {820 fn write(plt: PltSection, elf_file: *Elf, writer: anytype) !void {
821 {821 {
822 const shdrs = elf_file.sections.items(.shdr);822 const shdrs = elf_file.sections.items(.shdr);
823 const plt_addr: i64 = @intCast(shdrs[elf_file.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.got_plt_section_index.?].sh_addr);824 const got_plt_addr: i64 = @intCast(shdrs[elf_file.section_indexes.got_plt.?].sh_addr);
825 // TODO: relax if possible825 // TODO: relax if possible
826 // .got.plt[2]826 // .got.plt[2]
827 const pages = try aarch64_util.calcNumberOfPages(plt_addr + 4, got_plt_addr + 16);827 const pages = try aarch64_util.calcNumberOfPages(plt_addr + 4, got_plt_addr + 16);
...@@ -894,7 +894,7 @@ pub const GotPltSection = struct {...@@ -894,7 +894,7 @@ pub const GotPltSection = struct {
894 // [2]: 0x0894 // [2]: 0x0
895 try writer.writeInt(u64, 0x0, .little);895 try writer.writeInt(u64, 0x0, .little);
896 try writer.writeInt(u64, 0x0, .little);896 try writer.writeInt(u64, 0x0, .little);
897 if (elf_file.plt_section_index) |shndx| {897 if (elf_file.section_indexes.plt) |shndx| {
898 const plt_addr = elf_file.sections.items(.shdr)[shndx].sh_addr;898 const plt_addr = elf_file.sections.items(.shdr)[shndx].sh_addr;
899 for (0..elf_file.plt.symbols.items.len) |_| {899 for (0..elf_file.plt.symbols.items.len) |_| {
900 // [N]: .plt900 // [N]: .plt
...@@ -962,7 +962,7 @@ pub const PltGotSection = struct {...@@ -962,7 +962,7 @@ pub const PltGotSection = struct {
962 .st_name = st_name,962 .st_name = st_name,
963 .st_info = elf.STT_FUNC,963 .st_info = elf.STT_FUNC,
964 .st_other = 0,964 .st_other = 0,
965 .st_shndx = @intCast(elf_file.plt_got_section_index.?),965 .st_shndx = @intCast(elf_file.section_indexes.plt_got.?),
966 .st_value = @intCast(sym.pltGotAddress(elf_file)),966 .st_value = @intCast(sym.pltGotAddress(elf_file)),
967 .st_size = 16,967 .st_size = 16,
968 };968 };