authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-10-10 16:58:11-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-10-11 10:33:54-07:00
log4669269673e0240301699127abb16b3072c5e592
treef41f071ac888c0aebf07bfeea0b213d29d82bdba
parentec67d6e03a05a2d87880d7a97654ae55f4c733a2

link.Elf: fix phdr_gnu_stack_index not included in sortPhdrs

Adds type safety for program header indexes. Reduce the amount of state sortPhdrs has access to, helping make the data dependencies clear.

1 files changed, 141 insertions(+), 111 deletions(-)

src/link/Elf.zig+141-111
...@@ -53,26 +53,10 @@ shdr_table_offset: ?u64 = null,...@@ -53,26 +53,10 @@ shdr_table_offset: ?u64 = null,
5353
54/// Stored in native-endian format, depending on target endianness needs to be bswapped on read/write.54/// Stored in native-endian format, depending on target endianness needs to be bswapped on read/write.
55/// Same order as in the file.55/// Same order as in the file.
56phdrs: std.ArrayListUnmanaged(elf.Elf64_Phdr) = .empty,56phdrs: ProgramHeaderList = .empty,
5757
58/// Special program headers58/// Special program headers.
59/// PT_PHDR59phdr_indexes: ProgramHeaderIndexes = .{},
60phdr_table_index: ?u16 = null,
61/// PT_LOAD for PHDR table
62/// We add this special load segment to ensure the EHDR and PHDR table are always
63/// loaded into memory.
64phdr_table_load_index: ?u16 = null,
65/// PT_INTERP
66phdr_interp_index: ?u16 = null,
67/// PT_DYNAMIC
68phdr_dynamic_index: ?u16 = null,
69/// PT_GNU_EH_FRAME
70phdr_gnu_eh_frame_index: ?u16 = null,
71/// PT_GNU_STACK
72phdr_gnu_stack_index: ?u16 = null,
73/// PT_TLS
74/// TODO I think ELF permits multiple TLS segments but for now, assume one per file.
75phdr_tls_index: ?u16 = null,
7660
77page_size: u32,61page_size: u32,
78default_sym_version: elf.Elf64_Versym,62default_sym_version: elf.Elf64_Versym,
...@@ -152,6 +136,57 @@ comment_merge_section_index: ?MergeSection.Index = null,...@@ -152,6 +136,57 @@ comment_merge_section_index: ?MergeSection.Index = null,
152136
153first_eflags: ?elf.Elf64_Word = null,137first_eflags: ?elf.Elf64_Word = null,
154138
139const ProgramHeaderList = std.ArrayListUnmanaged(elf.Elf64_Phdr);
140
141const OptionalProgramHeaderIndex = enum(u16) {
142 none = std.math.maxInt(u16),
143 _,
144
145 fn unwrap(i: OptionalProgramHeaderIndex) ?ProgramHeaderIndex {
146 if (i == .none) return null;
147 return @enumFromInt(@intFromEnum(i));
148 }
149
150 fn int(i: OptionalProgramHeaderIndex) ?u16 {
151 if (i == .none) return null;
152 return @intFromEnum(i);
153 }
154};
155
156const ProgramHeaderIndex = enum(u16) {
157 _,
158
159 fn toOptional(i: ProgramHeaderIndex) OptionalProgramHeaderIndex {
160 const result: OptionalProgramHeaderIndex = @enumFromInt(@intFromEnum(i));
161 assert(result != .none);
162 return result;
163 }
164
165 fn int(i: ProgramHeaderIndex) u16 {
166 return @intFromEnum(i);
167 }
168};
169
170const ProgramHeaderIndexes = struct {
171 /// PT_PHDR
172 table: OptionalProgramHeaderIndex = .none,
173 /// PT_LOAD for PHDR table
174 /// We add this special load segment to ensure the EHDR and PHDR table are always
175 /// loaded into memory.
176 table_load: OptionalProgramHeaderIndex = .none,
177 /// PT_INTERP
178 interp: OptionalProgramHeaderIndex = .none,
179 /// PT_DYNAMIC
180 dynamic: OptionalProgramHeaderIndex = .none,
181 /// PT_GNU_EH_FRAME
182 gnu_eh_frame: OptionalProgramHeaderIndex = .none,
183 /// PT_GNU_STACK
184 gnu_stack: OptionalProgramHeaderIndex = .none,
185 /// PT_TLS
186 /// TODO I think ELF permits multiple TLS segments but for now, assume one per file.
187 tls: OptionalProgramHeaderIndex = .none,
188};
189
155/// When allocating, the ideal_capacity is calculated by190/// When allocating, the ideal_capacity is calculated by
156/// actual_capacity + (actual_capacity / ideal_factor)191/// actual_capacity + (actual_capacity / ideal_factor)
157const ideal_factor = 3;192const ideal_factor = 3;
...@@ -358,7 +393,7 @@ pub fn createEmpty(...@@ -358,7 +393,7 @@ pub fn createEmpty(
358 };393 };
359 const max_nphdrs = comptime getMaxNumberOfPhdrs();394 const max_nphdrs = comptime getMaxNumberOfPhdrs();
360 const reserved: u64 = mem.alignForward(u64, padToIdeal(max_nphdrs * phsize), self.page_size);395 const reserved: u64 = mem.alignForward(u64, padToIdeal(max_nphdrs * phsize), self.page_size);
361 self.phdr_table_index = try self.addPhdr(.{396 self.phdr_indexes.table = (try self.addPhdr(.{
362 .type = elf.PT_PHDR,397 .type = elf.PT_PHDR,
363 .flags = elf.PF_R,398 .flags = elf.PF_R,
364 .@"align" = p_align,399 .@"align" = p_align,
...@@ -366,8 +401,8 @@ pub fn createEmpty(...@@ -366,8 +401,8 @@ pub fn createEmpty(
366 .offset = ehsize,401 .offset = ehsize,
367 .filesz = reserved,402 .filesz = reserved,
368 .memsz = reserved,403 .memsz = reserved,
369 });404 })).toOptional();
370 self.phdr_table_load_index = try self.addPhdr(.{405 self.phdr_indexes.table_load = (try self.addPhdr(.{
371 .type = elf.PT_LOAD,406 .type = elf.PT_LOAD,
372 .flags = elf.PF_R,407 .flags = elf.PF_R,
373 .@"align" = self.page_size,408 .@"align" = self.page_size,
...@@ -375,7 +410,7 @@ pub fn createEmpty(...@@ -375,7 +410,7 @@ pub fn createEmpty(
375 .offset = 0,410 .offset = 0,
376 .filesz = reserved + ehsize,411 .filesz = reserved + ehsize,
377 .memsz = reserved + ehsize,412 .memsz = reserved + ehsize,
378 });413 })).toOptional();
379 }414 }
380415
381 if (opt_zcu) |zcu| {416 if (opt_zcu) |zcu| {
...@@ -966,7 +1001,7 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod...@@ -966,7 +1001,7 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod
966 try self.addLoadPhdrs();1001 try self.addLoadPhdrs();
967 try self.allocatePhdrTable();1002 try self.allocatePhdrTable();
968 try self.allocateAllocSections();1003 try self.allocateAllocSections();
969 try self.sortPhdrs();1004 try sortPhdrs(gpa, &self.phdrs, &self.phdr_indexes, self.sections.items(.phndx));
970 try self.allocateNonAllocSections();1005 try self.allocateNonAllocSections();
971 self.allocateSpecialPhdrs();1006 self.allocateSpecialPhdrs();
972 if (self.linkerDefinedPtr()) |obj| {1007 if (self.linkerDefinedPtr()) |obj| {
...@@ -2461,7 +2496,7 @@ fn writePhdrTable(self: *Elf) !void {...@@ -2461,7 +2496,7 @@ fn writePhdrTable(self: *Elf) !void {
2461 const gpa = self.base.comp.gpa;2496 const gpa = self.base.comp.gpa;
2462 const target_endian = self.getTarget().cpu.arch.endian();2497 const target_endian = self.getTarget().cpu.arch.endian();
2463 const foreign_endian = target_endian != builtin.cpu.arch.endian();2498 const foreign_endian = target_endian != builtin.cpu.arch.endian();
2464 const phdr_table = &self.phdrs.items[self.phdr_table_index.?];2499 const phdr_table = &self.phdrs.items[self.phdr_indexes.table.int().?];
24652500
2466 log.debug("writing program headers from 0x{x} to 0x{x}", .{2501 log.debug("writing program headers from 0x{x} to 0x{x}", .{
2467 phdr_table.p_offset,2502 phdr_table.p_offset,
...@@ -2573,18 +2608,18 @@ pub fn writeElfHeader(self: *Elf) !void {...@@ -2573,18 +2608,18 @@ pub fn writeElfHeader(self: *Elf) !void {
2573 const entry_sym = obj.entrySymbol(self) orelse break :blk 0;2608 const entry_sym = obj.entrySymbol(self) orelse break :blk 0;
2574 break :blk @intCast(entry_sym.address(.{}, self));2609 break :blk @intCast(entry_sym.address(.{}, self));
2575 } else 0;2610 } else 0;
2576 const phdr_table_offset = if (self.phdr_table_index) |phndx| self.phdrs.items[phndx].p_offset else 0;2611 const phdr_table_offset = if (self.phdr_indexes.table.int()) |phndx| self.phdrs.items[phndx].p_offset else 0;
2577 switch (self.ptr_width) {2612 switch (self.ptr_width) {
2578 .p32 => {2613 .p32 => {
2579 mem.writeInt(u32, hdr_buf[index..][0..4], @as(u32, @intCast(e_entry)), endian);2614 mem.writeInt(u32, hdr_buf[index..][0..4], @intCast(e_entry), endian);
2580 index += 4;2615 index += 4;
25812616
2582 // e_phoff2617 // e_phoff
2583 mem.writeInt(u32, hdr_buf[index..][0..4], @as(u32, @intCast(phdr_table_offset)), endian);2618 mem.writeInt(u32, hdr_buf[index..][0..4], @intCast(phdr_table_offset), endian);
2584 index += 4;2619 index += 4;
25852620
2586 // e_shoff2621 // e_shoff
2587 mem.writeInt(u32, hdr_buf[index..][0..4], @as(u32, @intCast(self.shdr_table_offset.?)), endian);2622 mem.writeInt(u32, hdr_buf[index..][0..4], @intCast(self.shdr_table_offset.?), endian);
2588 index += 4;2623 index += 4;
2589 },2624 },
2590 .p64 => {2625 .p64 => {
...@@ -2631,7 +2666,7 @@ pub fn writeElfHeader(self: *Elf) !void {...@@ -2631,7 +2666,7 @@ pub fn writeElfHeader(self: *Elf) !void {
2631 mem.writeInt(u16, hdr_buf[index..][0..2], e_shentsize, endian);2666 mem.writeInt(u16, hdr_buf[index..][0..2], e_shentsize, endian);
2632 index += 2;2667 index += 2;
26332668
2634 const e_shnum = @as(u16, @intCast(self.sections.items(.shdr).len));2669 const e_shnum: u16 = @intCast(self.sections.items(.shdr).len);
2635 mem.writeInt(u16, hdr_buf[index..][0..2], e_shnum, endian);2670 mem.writeInt(u16, hdr_buf[index..][0..2], e_shnum, endian);
2636 index += 2;2671 index += 2;
26372672
...@@ -3081,43 +3116,43 @@ pub fn initShStrtab(self: *Elf) !void {...@@ -3081,43 +3116,43 @@ pub fn initShStrtab(self: *Elf) !void {
3081fn initSpecialPhdrs(self: *Elf) !void {3116fn initSpecialPhdrs(self: *Elf) !void {
3082 comptime assert(max_number_of_special_phdrs == 5);3117 comptime assert(max_number_of_special_phdrs == 5);
30833118
3084 if (self.interp_section_index != null and self.phdr_interp_index == null) {3119 if (self.interp_section_index != null and self.phdr_indexes.interp == .none) {
3085 self.phdr_interp_index = try self.addPhdr(.{3120 self.phdr_indexes.interp = (try self.addPhdr(.{
3086 .type = elf.PT_INTERP,3121 .type = elf.PT_INTERP,
3087 .flags = elf.PF_R,3122 .flags = elf.PF_R,
3088 .@"align" = 1,3123 .@"align" = 1,
3089 });3124 })).toOptional();
3090 }3125 }
3091 if (self.dynamic_section_index != null and self.phdr_dynamic_index == null) {3126 if (self.dynamic_section_index != null and self.phdr_indexes.dynamic == .none) {
3092 self.phdr_dynamic_index = try self.addPhdr(.{3127 self.phdr_indexes.dynamic = (try self.addPhdr(.{
3093 .type = elf.PT_DYNAMIC,3128 .type = elf.PT_DYNAMIC,
3094 .flags = elf.PF_R | elf.PF_W,3129 .flags = elf.PF_R | elf.PF_W,
3095 });3130 })).toOptional();
3096 }3131 }
3097 if (self.eh_frame_hdr_section_index != null and self.phdr_gnu_eh_frame_index == null) {3132 if (self.eh_frame_hdr_section_index != null and self.phdr_indexes.gnu_eh_frame == .none) {
3098 self.phdr_gnu_eh_frame_index = try self.addPhdr(.{3133 self.phdr_indexes.gnu_eh_frame = (try self.addPhdr(.{
3099 .type = elf.PT_GNU_EH_FRAME,3134 .type = elf.PT_GNU_EH_FRAME,
3100 .flags = elf.PF_R,3135 .flags = elf.PF_R,
3101 });3136 })).toOptional();
3102 }3137 }
3103 if (self.phdr_gnu_stack_index == null) {3138 if (self.phdr_indexes.gnu_stack == .none) {
3104 self.phdr_gnu_stack_index = try self.addPhdr(.{3139 self.phdr_indexes.gnu_stack = (try self.addPhdr(.{
3105 .type = elf.PT_GNU_STACK,3140 .type = elf.PT_GNU_STACK,
3106 .flags = elf.PF_W | elf.PF_R,3141 .flags = elf.PF_W | elf.PF_R,
3107 .memsz = self.base.stack_size,3142 .memsz = self.base.stack_size,
3108 .@"align" = 1,3143 .@"align" = 1,
3109 });3144 })).toOptional();
3110 }3145 }
31113146
3112 const has_tls = for (self.sections.items(.shdr)) |shdr| {3147 const has_tls = for (self.sections.items(.shdr)) |shdr| {
3113 if (shdr.sh_flags & elf.SHF_TLS != 0) break true;3148 if (shdr.sh_flags & elf.SHF_TLS != 0) break true;
3114 } else false;3149 } else false;
3115 if (has_tls and self.phdr_tls_index == null) {3150 if (has_tls and self.phdr_indexes.tls == .none) {
3116 self.phdr_tls_index = try self.addPhdr(.{3151 self.phdr_indexes.tls = (try self.addPhdr(.{
3117 .type = elf.PT_TLS,3152 .type = elf.PT_TLS,
3118 .flags = elf.PF_R,3153 .flags = elf.PF_R,
3119 .@"align" = 1,3154 .@"align" = 1,
3120 });3155 })).toOptional();
3121 }3156 }
3122}3157}
31233158
...@@ -3251,25 +3286,30 @@ fn setHashSections(self: *Elf) !void {...@@ -3251,25 +3286,30 @@ fn setHashSections(self: *Elf) !void {
3251}3286}
32523287
3253fn phdrRank(phdr: elf.Elf64_Phdr) u8 {3288fn phdrRank(phdr: elf.Elf64_Phdr) u8 {
3254 switch (phdr.p_type) {3289 return switch (phdr.p_type) {
3255 elf.PT_NULL => return 0,3290 elf.PT_NULL => 0,
3256 elf.PT_PHDR => return 1,3291 elf.PT_PHDR => 1,
3257 elf.PT_INTERP => return 2,3292 elf.PT_INTERP => 2,
3258 elf.PT_LOAD => return 3,3293 elf.PT_LOAD => 3,
3259 elf.PT_DYNAMIC, elf.PT_TLS => return 4,3294 elf.PT_DYNAMIC, elf.PT_TLS => 4,
3260 elf.PT_GNU_EH_FRAME => return 5,3295 elf.PT_GNU_EH_FRAME => 5,
3261 elf.PT_GNU_STACK => return 6,3296 elf.PT_GNU_STACK => 6,
3262 else => return 7,3297 else => 7,
3263 }3298 };
3264}3299}
32653300
3266fn sortPhdrs(self: *Elf) error{OutOfMemory}!void {3301fn sortPhdrs(
3302 gpa: Allocator,
3303 phdrs: *ProgramHeaderList,
3304 special_indexes: *ProgramHeaderIndexes,
3305 section_indexes: []OptionalProgramHeaderIndex,
3306) error{OutOfMemory}!void {
3267 const Entry = struct {3307 const Entry = struct {
3268 phndx: u16,3308 phndx: u16,
32693309
3270 pub fn lessThan(elf_file: *Elf, lhs: @This(), rhs: @This()) bool {3310 pub fn lessThan(program_headers: []const elf.Elf64_Phdr, lhs: @This(), rhs: @This()) bool {
3271 const lhs_phdr = elf_file.phdrs.items[lhs.phndx];3311 const lhs_phdr = program_headers[lhs.phndx];
3272 const rhs_phdr = elf_file.phdrs.items[rhs.phndx];3312 const rhs_phdr = program_headers[rhs.phndx];
3273 const lhs_rank = phdrRank(lhs_phdr);3313 const lhs_rank = phdrRank(lhs_phdr);
3274 const rhs_rank = phdrRank(rhs_phdr);3314 const rhs_rank = phdrRank(rhs_phdr);
3275 if (lhs_rank == rhs_rank) return lhs_phdr.p_vaddr < rhs_phdr.p_vaddr;3315 if (lhs_rank == rhs_rank) return lhs_phdr.p_vaddr < rhs_phdr.p_vaddr;
...@@ -3277,45 +3317,34 @@ fn sortPhdrs(self: *Elf) error{OutOfMemory}!void {...@@ -3277,45 +3317,34 @@ fn sortPhdrs(self: *Elf) error{OutOfMemory}!void {
3277 }3317 }
3278 };3318 };
32793319
3280 const gpa = self.base.comp.gpa;3320 const entries = try gpa.alloc(Entry, phdrs.items.len);
3281 var entries = try std.ArrayList(Entry).initCapacity(gpa, self.phdrs.items.len);3321 defer gpa.free(entries);
3282 defer entries.deinit();3322 for (entries, 0..) |*entry, phndx| {
3283 for (0..self.phdrs.items.len) |phndx| {3323 entry.* = .{ .phndx = @intCast(phndx) };
3284 entries.appendAssumeCapacity(.{ .phndx = @as(u16, @intCast(phndx)) });
3285 }3324 }
32863325
3287 mem.sort(Entry, entries.items, self, Entry.lessThan);3326 mem.sort(Entry, entries, phdrs.items, Entry.lessThan);
32883327
3289 const backlinks = try gpa.alloc(u16, entries.items.len);3328 const backlinks = try gpa.alloc(u16, entries.len);
3290 defer gpa.free(backlinks);3329 defer gpa.free(backlinks);
3291 for (entries.items, 0..) |entry, i| {3330 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);3331 defer gpa.free(slice);
3332 try phdrs.resize(gpa, slice.len);
32973333
3298 try self.phdrs.ensureTotalCapacityPrecise(gpa, slice.len);3334 for (entries, phdrs.items, 0..) |entry, *phdr, i| {
3299 for (entries.items) |sorted| {3335 backlinks[entry.phndx] = @intCast(i);
3300 self.phdrs.appendAssumeCapacity(slice[sorted.phndx]);3336 phdr.* = slice[entry.phndx];
3301 }3337 }
33023338
3303 for (&[_]*?u16{3339 inline for (@typeInfo(ProgramHeaderIndexes).@"struct".fields) |field| {
3304 &self.phdr_table_index,3340 if (@field(special_indexes, field.name).int()) |special_index| {
3305 &self.phdr_table_load_index,3341 @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 }3342 }
3314 }3343 }
33153344
3316 for (self.sections.items(.phndx)) |*maybe_phndx| {3345 for (section_indexes) |*opt_phndx| {
3317 if (maybe_phndx.*) |*index| {3346 if (opt_phndx.int()) |index| {
3318 index.* = backlinks[index.*];3347 opt_phndx.* = @enumFromInt(backlinks[index]);
3319 }3348 }
3320 }3349 }
3321}3350}
...@@ -3656,7 +3685,7 @@ fn addLoadPhdrs(self: *Elf) error{OutOfMemory}!void {...@@ -3656,7 +3685,7 @@ fn addLoadPhdrs(self: *Elf) error{OutOfMemory}!void {
3656 if (shdr.sh_type == elf.SHT_NULL) continue;3685 if (shdr.sh_type == elf.SHT_NULL) continue;
3657 if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue;3686 if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue;
3658 const flags = shdrToPhdrFlags(shdr.sh_flags);3687 const flags = shdrToPhdrFlags(shdr.sh_flags);
3659 if (self.getPhdr(.{ .flags = flags, .type = elf.PT_LOAD }) == null) {3688 if (self.getPhdr(.{ .flags = flags, .type = elf.PT_LOAD }) == .none) {
3660 _ = try self.addPhdr(.{ .flags = flags, .type = elf.PT_LOAD });3689 _ = try self.addPhdr(.{ .flags = flags, .type = elf.PT_LOAD });
3661 }3690 }
3662 }3691 }
...@@ -3664,8 +3693,8 @@ fn addLoadPhdrs(self: *Elf) error{OutOfMemory}!void {...@@ -3664,8 +3693,8 @@ fn addLoadPhdrs(self: *Elf) error{OutOfMemory}!void {
36643693
3665/// Allocates PHDR table in virtual memory and in file.3694/// Allocates PHDR table in virtual memory and in file.
3666fn allocatePhdrTable(self: *Elf) error{OutOfMemory}!void {3695fn allocatePhdrTable(self: *Elf) error{OutOfMemory}!void {
3667 const phdr_table = &self.phdrs.items[self.phdr_table_index.?];3696 const phdr_table = &self.phdrs.items[self.phdr_indexes.table.int().?];
3668 const phdr_table_load = &self.phdrs.items[self.phdr_table_load_index.?];3697 const phdr_table_load = &self.phdrs.items[self.phdr_indexes.table_load.int().?];
36693698
3670 const ehsize: u64 = switch (self.ptr_width) {3699 const ehsize: u64 = switch (self.ptr_width) {
3671 .p32 => @sizeOf(elf.Elf32_Ehdr),3700 .p32 => @sizeOf(elf.Elf32_Ehdr),
...@@ -3757,7 +3786,7 @@ pub fn allocateAllocSections(self: *Elf) !void {...@@ -3757,7 +3786,7 @@ pub fn allocateAllocSections(self: *Elf) !void {
3757 // When allocating we first find the largest required alignment3786 // When allocating we first find the largest required alignment
3758 // of any section that is contained in a cover and use it to align3787 // of any section that is contained in a cover and use it to align
3759 // the start address of the segement (and first section).3788 // the start address of the segement (and first section).
3760 const phdr_table = &self.phdrs.items[self.phdr_table_load_index.?];3789 const phdr_table = &self.phdrs.items[self.phdr_indexes.table_load.int().?];
3761 var addr = phdr_table.p_vaddr + phdr_table.p_memsz;3790 var addr = phdr_table.p_vaddr + phdr_table.p_memsz;
37623791
3763 for (covers) |cover| {3792 for (covers) |cover| {
...@@ -3817,8 +3846,8 @@ pub fn allocateAllocSections(self: *Elf) !void {...@@ -3817,8 +3846,8 @@ pub fn allocateAllocSections(self: *Elf) !void {
3817 }3846 }
38183847
3819 const first = slice.items(.shdr)[cover.items[0]];3848 const first = slice.items(.shdr)[cover.items[0]];
3820 const phndx = self.getPhdr(.{ .type = elf.PT_LOAD, .flags = shdrToPhdrFlags(first.sh_flags) }).?;3849 const phndx = self.getPhdr(.{ .type = elf.PT_LOAD, .flags = shdrToPhdrFlags(first.sh_flags) }).unwrap().?;
3821 const phdr = &self.phdrs.items[phndx];3850 const phdr = &self.phdrs.items[phndx.int()];
3822 const allocated_size = self.allocatedSize(phdr.p_offset);3851 const allocated_size = self.allocatedSize(phdr.p_offset);
3823 if (filesz > allocated_size) {3852 if (filesz > allocated_size) {
3824 const old_offset = phdr.p_offset;3853 const old_offset = phdr.p_offset;
...@@ -3830,7 +3859,7 @@ pub fn allocateAllocSections(self: *Elf) !void {...@@ -3830,7 +3859,7 @@ pub fn allocateAllocSections(self: *Elf) !void {
38303859
3831 for (cover.items) |shndx| {3860 for (cover.items) |shndx| {
3832 const shdr = &slice.items(.shdr)[shndx];3861 const shdr = &slice.items(.shdr)[shndx];
3833 slice.items(.phndx)[shndx] = phndx;3862 slice.items(.phndx)[shndx] = phndx.toOptional();
3834 if (shdr.sh_type == elf.SHT_NOBITS) {3863 if (shdr.sh_type == elf.SHT_NOBITS) {
3835 shdr.sh_offset = 0;3864 shdr.sh_offset = 0;
3836 continue;3865 continue;
...@@ -3906,12 +3935,12 @@ pub fn allocateNonAllocSections(self: *Elf) !void {...@@ -3906,12 +3935,12 @@ pub fn allocateNonAllocSections(self: *Elf) !void {
3906fn allocateSpecialPhdrs(self: *Elf) void {3935fn allocateSpecialPhdrs(self: *Elf) void {
3907 const slice = self.sections.slice();3936 const slice = self.sections.slice();
39083937
3909 for (&[_]struct { ?u16, ?u32 }{3938 for (&[_]struct { OptionalProgramHeaderIndex, ?u32 }{
3910 .{ self.phdr_interp_index, self.interp_section_index },3939 .{ self.phdr_indexes.interp, self.interp_section_index },
3911 .{ self.phdr_dynamic_index, self.dynamic_section_index },3940 .{ self.phdr_indexes.dynamic, self.dynamic_section_index },
3912 .{ self.phdr_gnu_eh_frame_index, self.eh_frame_hdr_section_index },3941 .{ self.phdr_indexes.gnu_eh_frame, self.eh_frame_hdr_section_index },
3913 }) |pair| {3942 }) |pair| {
3914 if (pair[0]) |index| {3943 if (pair[0].int()) |index| {
3915 const shdr = slice.items(.shdr)[pair[1].?];3944 const shdr = slice.items(.shdr)[pair[1].?];
3916 const phdr = &self.phdrs.items[index];3945 const phdr = &self.phdrs.items[index];
3917 phdr.p_align = shdr.sh_addralign;3946 phdr.p_align = shdr.sh_addralign;
...@@ -3926,7 +3955,7 @@ fn allocateSpecialPhdrs(self: *Elf) void {...@@ -3926,7 +3955,7 @@ fn allocateSpecialPhdrs(self: *Elf) void {
3926 // Set the TLS segment boundaries.3955 // Set the TLS segment boundaries.
3927 // We assume TLS sections are laid out contiguously and that there is3956 // We assume TLS sections are laid out contiguously and that there is
3928 // a single TLS segment.3957 // a single TLS segment.
3929 if (self.phdr_tls_index) |index| {3958 if (self.phdr_indexes.tls.int()) |index| {
3930 const shdrs = slice.items(.shdr);3959 const shdrs = slice.items(.shdr);
3931 const phdr = &self.phdrs.items[index];3960 const phdr = &self.phdrs.items[index];
3932 var shndx: u32 = 0;3961 var shndx: u32 = 0;
...@@ -4482,14 +4511,15 @@ pub fn isEffectivelyDynLib(self: Elf) bool {...@@ -4482,14 +4511,15 @@ pub fn isEffectivelyDynLib(self: Elf) bool {
4482fn getPhdr(self: *Elf, opts: struct {4511fn getPhdr(self: *Elf, opts: struct {
4483 type: u32 = 0,4512 type: u32 = 0,
4484 flags: u32 = 0,4513 flags: u32 = 0,
4485}) ?u16 {4514}) OptionalProgramHeaderIndex {
4486 for (self.phdrs.items, 0..) |phdr, phndx| {4515 for (self.phdrs.items, 0..) |phdr, phndx| {
4487 if (self.phdr_table_load_index) |index| {4516 if (self.phdr_indexes.table_load.int()) |index| {
4488 if (phndx == index) continue;4517 if (phndx == index) continue;
4489 }4518 }
4490 if (phdr.p_type == opts.type and phdr.p_flags == opts.flags) return @intCast(phndx);4519 if (phdr.p_type == opts.type and phdr.p_flags == opts.flags)
4520 return @enumFromInt(phndx);
4491 }4521 }
4492 return null;4522 return .none;
4493}4523}
44944524
4495fn addPhdr(self: *Elf, opts: struct {4525fn addPhdr(self: *Elf, opts: struct {
...@@ -4500,9 +4530,9 @@ fn addPhdr(self: *Elf, opts: struct {...@@ -4500,9 +4530,9 @@ fn addPhdr(self: *Elf, opts: struct {
4500 addr: u64 = 0,4530 addr: u64 = 0,
4501 filesz: u64 = 0,4531 filesz: u64 = 0,
4502 memsz: u64 = 0,4532 memsz: u64 = 0,
4503}) error{OutOfMemory}!u16 {4533}) error{OutOfMemory}!ProgramHeaderIndex {
4504 const gpa = self.base.comp.gpa;4534 const gpa = self.base.comp.gpa;
4505 const index = @as(u16, @intCast(self.phdrs.items.len));4535 const index: ProgramHeaderIndex = @enumFromInt(self.phdrs.items.len);
4506 try self.phdrs.append(gpa, .{4536 try self.phdrs.append(gpa, .{
4507 .p_type = opts.type,4537 .p_type = opts.type,
4508 .p_flags = opts.flags,4538 .p_flags = opts.flags,
...@@ -4756,7 +4786,7 @@ pub fn gotAddress(self: *Elf) i64 {...@@ -4756,7 +4786,7 @@ pub fn gotAddress(self: *Elf) i64 {
4756}4786}
47574787
4758pub fn tpAddress(self: *Elf) i64 {4788pub fn tpAddress(self: *Elf) i64 {
4759 const index = self.phdr_tls_index orelse return 0;4789 const index = self.phdr_indexes.tls.int() orelse return 0;
4760 const phdr = self.phdrs.items[index];4790 const phdr = self.phdrs.items[index];
4761 const addr = switch (self.getTarget().cpu.arch) {4791 const addr = switch (self.getTarget().cpu.arch) {
4762 .x86_64 => mem.alignForward(u64, phdr.p_vaddr + phdr.p_memsz, phdr.p_align),4792 .x86_64 => mem.alignForward(u64, phdr.p_vaddr + phdr.p_memsz, phdr.p_align),
...@@ -4768,13 +4798,13 @@ pub fn tpAddress(self: *Elf) i64 {...@@ -4768,13 +4798,13 @@ pub fn tpAddress(self: *Elf) i64 {
4768}4798}
47694799
4770pub fn dtpAddress(self: *Elf) i64 {4800pub fn dtpAddress(self: *Elf) i64 {
4771 const index = self.phdr_tls_index orelse return 0;4801 const index = self.phdr_indexes.tls.int() orelse return 0;
4772 const phdr = self.phdrs.items[index];4802 const phdr = self.phdrs.items[index];
4773 return @intCast(phdr.p_vaddr);4803 return @intCast(phdr.p_vaddr);
4774}4804}
47754805
4776pub fn tlsAddress(self: *Elf) i64 {4806pub fn tlsAddress(self: *Elf) i64 {
4777 const index = self.phdr_tls_index orelse return 0;4807 const index = self.phdr_indexes.tls.int() orelse return 0;
4778 const phdr = self.phdrs.items[index];4808 const phdr = self.phdrs.items[index];
4779 return @intCast(phdr.p_vaddr);4809 return @intCast(phdr.p_vaddr);
4780}4810}
...@@ -5393,7 +5423,7 @@ const Section = struct {...@@ -5393,7 +5423,7 @@ const Section = struct {
5393 shdr: elf.Elf64_Shdr,5423 shdr: elf.Elf64_Shdr,
53945424
5395 /// Assigned program header index if any.5425 /// Assigned program header index if any.
5396 phndx: ?u32 = null,5426 phndx: OptionalProgramHeaderIndex = .none,
53975427
5398 /// List of atoms contributing to this section.5428 /// List of atoms contributing to this section.
5399 /// TODO currently this is only used for relocations tracking in relocatable mode5429 /// TODO currently this is only used for relocations tracking in relocatable mode