| ... | @@ -53,26 +53,10 @@ shdr_table_offset: ?u64 = null, | ... | @@ -53,26 +53,10 @@ shdr_table_offset: ?u64 = null, |
| 53 | | 53 | |
| 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. |
| 56 | phdrs: std.ArrayListUnmanaged(elf.Elf64_Phdr) = .empty, | 56 | phdrs: ProgramHeaderList = .empty, |
| 57 | | 57 | |
| 58 | /// Special program headers | 58 | /// Special program headers. |
| 59 | /// PT_PHDR | 59 | phdr_indexes: ProgramHeaderIndexes = .{}, |
| 60 | phdr_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. | | |
| 64 | phdr_table_load_index: ?u16 = null, | | |
| 65 | /// PT_INTERP | | |
| 66 | phdr_interp_index: ?u16 = null, | | |
| 67 | /// PT_DYNAMIC | | |
| 68 | phdr_dynamic_index: ?u16 = null, | | |
| 69 | /// PT_GNU_EH_FRAME | | |
| 70 | phdr_gnu_eh_frame_index: ?u16 = null, | | |
| 71 | /// PT_GNU_STACK | | |
| 72 | phdr_gnu_stack_index: ?u16 = null, | | |
| 73 | /// PT_TLS | | |
| 74 | /// TODO I think ELF permits multiple TLS segments but for now, assume one per file. | | |
| 75 | phdr_tls_index: ?u16 = null, | | |
| 76 | | 60 | |
| 77 | page_size: u32, | 61 | page_size: u32, |
| 78 | default_sym_version: elf.Elf64_Versym, | 62 | default_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, |
| 152 | | 136 | |
| 153 | first_eflags: ?elf.Elf64_Word = null, | 137 | first_eflags: ?elf.Elf64_Word = null, |
| 154 | | 138 | |
| | 139 | const ProgramHeaderList = std.ArrayListUnmanaged(elf.Elf64_Phdr); |
| | 140 | |
| | 141 | const 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 | |
| | 156 | const 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 | |
| | 170 | const 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 by | 190 | /// When allocating, the ideal_capacity is calculated by |
| 156 | /// actual_capacity + (actual_capacity / ideal_factor) | 191 | /// actual_capacity + (actual_capacity / ideal_factor) |
| 157 | const ideal_factor = 3; | 192 | const 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 | } |
| 380 | | 415 | |
| 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().?]; |
| 2465 | | 2500 | |
| 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; |
| 2581 | | 2616 | |
| 2582 | // e_phoff | 2617 | // 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; |
| 2585 | | 2620 | |
| 2586 | // e_shoff | 2621 | // 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; |
| 2633 | | 2668 | |
| 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; |
| 2637 | | 2672 | |
| ... | @@ -3081,43 +3116,43 @@ pub fn initShStrtab(self: *Elf) !void { | ... | @@ -3081,43 +3116,43 @@ pub fn initShStrtab(self: *Elf) !void { |
| 3081 | fn initSpecialPhdrs(self: *Elf) !void { | 3116 | fn initSpecialPhdrs(self: *Elf) !void { |
| 3082 | comptime assert(max_number_of_special_phdrs == 5); | 3117 | comptime assert(max_number_of_special_phdrs == 5); |
| 3083 | | 3118 | |
| 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 | } |
| 3111 | | 3146 | |
| 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 | } |
| 3123 | | 3158 | |
| ... | @@ -3251,25 +3286,30 @@ fn setHashSections(self: *Elf) !void { | ... | @@ -3251,25 +3286,30 @@ fn setHashSections(self: *Elf) !void { |
| 3251 | } | 3286 | } |
| 3252 | | 3287 | |
| 3253 | fn phdrRank(phdr: elf.Elf64_Phdr) u8 { | 3288 | fn 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 | } |
| 3265 | | 3300 | |
| 3266 | fn sortPhdrs(self: *Elf) error{OutOfMemory}!void { | 3301 | fn 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, |
| 3269 | | 3309 | |
| 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 | }; |
| 3279 | | 3319 | |
| 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 | } |
| 3286 | | 3325 | |
| 3287 | mem.sort(Entry, entries.items, self, Entry.lessThan); | 3326 | mem.sort(Entry, entries, phdrs.items, Entry.lessThan); |
| 3288 | | 3327 | |
| 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); |
| 3297 | | 3333 | |
| 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 | } |
| 3302 | | 3338 | |
| 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 | } |
| 3315 | | 3344 | |
| 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 { |
| 3664 | | 3693 | |
| 3665 | /// Allocates PHDR table in virtual memory and in file. | 3694 | /// Allocates PHDR table in virtual memory and in file. |
| 3666 | fn allocatePhdrTable(self: *Elf) error{OutOfMemory}!void { | 3695 | fn 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().?]; |
| 3669 | | 3698 | |
| 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 alignment | 3786 | // When allocating we first find the largest required alignment |
| 3758 | // of any section that is contained in a cover and use it to align | 3787 | // 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; |
| 3762 | | 3791 | |
| 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 | } |
| 3818 | | 3847 | |
| 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 { |
| 3830 | | 3859 | |
| 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 { |
| 3906 | fn allocateSpecialPhdrs(self: *Elf) void { | 3935 | fn allocateSpecialPhdrs(self: *Elf) void { |
| 3907 | const slice = self.sections.slice(); | 3936 | const slice = self.sections.slice(); |
| 3908 | | 3937 | |
| 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 is | 3956 | // 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 { |
| 4482 | fn getPhdr(self: *Elf, opts: struct { | 4511 | fn 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 | } |
| 4494 | | 4524 | |
| 4495 | fn addPhdr(self: *Elf, opts: struct { | 4525 | fn 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 | } |
| 4757 | | 4787 | |
| 4758 | pub fn tpAddress(self: *Elf) i64 { | 4788 | pub 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 | } |
| 4769 | | 4799 | |
| 4770 | pub fn dtpAddress(self: *Elf) i64 { | 4800 | pub 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 | } |
| 4775 | | 4805 | |
| 4776 | pub fn tlsAddress(self: *Elf) i64 { | 4806 | pub 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, |
| 5394 | | 5424 | |
| 5395 | /// Assigned program header index if any. | 5425 | /// Assigned program header index if any. |
| 5396 | phndx: ?u32 = null, | 5426 | phndx: OptionalProgramHeaderIndex = .none, |
| 5397 | | 5427 | |
| 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 mode | 5429 | /// TODO currently this is only used for relocations tracking in relocatable mode |