| ... | ... | @@ -53,26 +53,10 @@ shdr_table_offset: ?u64 = null, |
| 53 | 53 | |
| 54 | 54 | /// Stored in native-endian format, depending on target endianness needs to be bswapped on read/write. |
| 55 | 55 | /// Same order as in the file. |
| 56 | | phdrs: std.ArrayListUnmanaged(elf.Elf64_Phdr) = .empty, |
| 57 | | |
| 58 | | /// Special program headers |
| 59 | | /// PT_PHDR |
| 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, |
| 56 | phdrs: ProgramHeaderList = .empty, |
| 57 | |
| 58 | /// Special program headers. |
| 59 | phdr_indexes: ProgramHeaderIndexes = .{}, |
| 76 | 60 | |
| 77 | 61 | page_size: u32, |
| 78 | 62 | default_sym_version: elf.Elf64_Versym, |
| ... | ... | @@ -152,6 +136,57 @@ comment_merge_section_index: ?MergeSection.Index = null, |
| 152 | 136 | |
| 153 | 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 | 190 | /// When allocating, the ideal_capacity is calculated by |
| 156 | 191 | /// actual_capacity + (actual_capacity / ideal_factor) |
| 157 | 192 | const ideal_factor = 3; |
| ... | ... | @@ -358,7 +393,7 @@ pub fn createEmpty( |
| 358 | 393 | }; |
| 359 | 394 | const max_nphdrs = comptime getMaxNumberOfPhdrs(); |
| 360 | 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 | 397 | .type = elf.PT_PHDR, |
| 363 | 398 | .flags = elf.PF_R, |
| 364 | 399 | .@"align" = p_align, |
| ... | ... | @@ -366,8 +401,8 @@ pub fn createEmpty( |
| 366 | 401 | .offset = ehsize, |
| 367 | 402 | .filesz = reserved, |
| 368 | 403 | .memsz = reserved, |
| 369 | | }); |
| 370 | | self.phdr_table_load_index = try self.addPhdr(.{ |
| 404 | })).toOptional(); |
| 405 | self.phdr_indexes.table_load = (try self.addPhdr(.{ |
| 371 | 406 | .type = elf.PT_LOAD, |
| 372 | 407 | .flags = elf.PF_R, |
| 373 | 408 | .@"align" = self.page_size, |
| ... | ... | @@ -375,7 +410,7 @@ pub fn createEmpty( |
| 375 | 410 | .offset = 0, |
| 376 | 411 | .filesz = reserved + ehsize, |
| 377 | 412 | .memsz = reserved + ehsize, |
| 378 | | }); |
| 413 | })).toOptional(); |
| 379 | 414 | } |
| 380 | 415 | |
| 381 | 416 | if (opt_zcu) |zcu| { |
| ... | ... | @@ -966,7 +1001,7 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod |
| 966 | 1001 | try self.addLoadPhdrs(); |
| 967 | 1002 | try self.allocatePhdrTable(); |
| 968 | 1003 | try self.allocateAllocSections(); |
| 969 | | try self.sortPhdrs(); |
| 1004 | try sortPhdrs(gpa, &self.phdrs, &self.phdr_indexes, self.sections.items(.phndx)); |
| 970 | 1005 | try self.allocateNonAllocSections(); |
| 971 | 1006 | self.allocateSpecialPhdrs(); |
| 972 | 1007 | if (self.linkerDefinedPtr()) |obj| { |
| ... | ... | @@ -2461,7 +2496,7 @@ fn writePhdrTable(self: *Elf) !void { |
| 2461 | 2496 | const gpa = self.base.comp.gpa; |
| 2462 | 2497 | const target_endian = self.getTarget().cpu.arch.endian(); |
| 2463 | 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 | 2501 | log.debug("writing program headers from 0x{x} to 0x{x}", .{ |
| 2467 | 2502 | phdr_table.p_offset, |
| ... | ... | @@ -2573,18 +2608,18 @@ pub fn writeElfHeader(self: *Elf) !void { |
| 2573 | 2608 | const entry_sym = obj.entrySymbol(self) orelse break :blk 0; |
| 2574 | 2609 | break :blk @intCast(entry_sym.address(.{}, self)); |
| 2575 | 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 | 2612 | switch (self.ptr_width) { |
| 2578 | 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 | 2615 | index += 4; |
| 2581 | 2616 | |
| 2582 | 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 | 2619 | index += 4; |
| 2585 | 2620 | |
| 2586 | 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 | 2623 | index += 4; |
| 2589 | 2624 | }, |
| 2590 | 2625 | .p64 => { |
| ... | ... | @@ -2631,7 +2666,7 @@ pub fn writeElfHeader(self: *Elf) !void { |
| 2631 | 2666 | mem.writeInt(u16, hdr_buf[index..][0..2], e_shentsize, endian); |
| 2632 | 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 | 2670 | mem.writeInt(u16, hdr_buf[index..][0..2], e_shnum, endian); |
| 2636 | 2671 | index += 2; |
| 2637 | 2672 | |
| ... | ... | @@ -3081,43 +3116,43 @@ pub fn initShStrtab(self: *Elf) !void { |
| 3081 | 3116 | fn initSpecialPhdrs(self: *Elf) !void { |
| 3082 | 3117 | comptime assert(max_number_of_special_phdrs == 5); |
| 3083 | 3118 | |
| 3084 | | if (self.interp_section_index != null and self.phdr_interp_index == null) { |
| 3085 | | self.phdr_interp_index = try self.addPhdr(.{ |
| 3119 | if (self.interp_section_index != null and self.phdr_indexes.interp == .none) { |
| 3120 | self.phdr_indexes.interp = (try self.addPhdr(.{ |
| 3086 | 3121 | .type = elf.PT_INTERP, |
| 3087 | 3122 | .flags = elf.PF_R, |
| 3088 | 3123 | .@"align" = 1, |
| 3089 | | }); |
| 3124 | })).toOptional(); |
| 3090 | 3125 | } |
| 3091 | | if (self.dynamic_section_index != null and self.phdr_dynamic_index == null) { |
| 3092 | | self.phdr_dynamic_index = try self.addPhdr(.{ |
| 3126 | if (self.dynamic_section_index != null and self.phdr_indexes.dynamic == .none) { |
| 3127 | self.phdr_indexes.dynamic = (try self.addPhdr(.{ |
| 3093 | 3128 | .type = elf.PT_DYNAMIC, |
| 3094 | 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) { |
| 3098 | | self.phdr_gnu_eh_frame_index = try self.addPhdr(.{ |
| 3132 | if (self.eh_frame_hdr_section_index != null and self.phdr_indexes.gnu_eh_frame == .none) { |
| 3133 | self.phdr_indexes.gnu_eh_frame = (try self.addPhdr(.{ |
| 3099 | 3134 | .type = elf.PT_GNU_EH_FRAME, |
| 3100 | 3135 | .flags = elf.PF_R, |
| 3101 | | }); |
| 3136 | })).toOptional(); |
| 3102 | 3137 | } |
| 3103 | | if (self.phdr_gnu_stack_index == null) { |
| 3104 | | self.phdr_gnu_stack_index = try self.addPhdr(.{ |
| 3138 | if (self.phdr_indexes.gnu_stack == .none) { |
| 3139 | self.phdr_indexes.gnu_stack = (try self.addPhdr(.{ |
| 3105 | 3140 | .type = elf.PT_GNU_STACK, |
| 3106 | 3141 | .flags = elf.PF_W | elf.PF_R, |
| 3107 | 3142 | .memsz = self.base.stack_size, |
| 3108 | 3143 | .@"align" = 1, |
| 3109 | | }); |
| 3144 | })).toOptional(); |
| 3110 | 3145 | } |
| 3111 | 3146 | |
| 3112 | 3147 | const has_tls = for (self.sections.items(.shdr)) |shdr| { |
| 3113 | 3148 | if (shdr.sh_flags & elf.SHF_TLS != 0) break true; |
| 3114 | 3149 | } else false; |
| 3115 | | if (has_tls and self.phdr_tls_index == null) { |
| 3116 | | self.phdr_tls_index = try self.addPhdr(.{ |
| 3150 | if (has_tls and self.phdr_indexes.tls == .none) { |
| 3151 | self.phdr_indexes.tls = (try self.addPhdr(.{ |
| 3117 | 3152 | .type = elf.PT_TLS, |
| 3118 | 3153 | .flags = elf.PF_R, |
| 3119 | 3154 | .@"align" = 1, |
| 3120 | | }); |
| 3155 | })).toOptional(); |
| 3121 | 3156 | } |
| 3122 | 3157 | } |
| 3123 | 3158 | |
| ... | ... | @@ -3251,25 +3286,30 @@ fn setHashSections(self: *Elf) !void { |
| 3251 | 3286 | } |
| 3252 | 3287 | |
| 3253 | 3288 | fn phdrRank(phdr: elf.Elf64_Phdr) u8 { |
| 3254 | | switch (phdr.p_type) { |
| 3255 | | elf.PT_NULL => return 0, |
| 3256 | | elf.PT_PHDR => return 1, |
| 3257 | | elf.PT_INTERP => return 2, |
| 3258 | | elf.PT_LOAD => return 3, |
| 3259 | | elf.PT_DYNAMIC, elf.PT_TLS => return 4, |
| 3260 | | elf.PT_GNU_EH_FRAME => return 5, |
| 3261 | | elf.PT_GNU_STACK => return 6, |
| 3262 | | else => return 7, |
| 3263 | | } |
| 3289 | return switch (phdr.p_type) { |
| 3290 | elf.PT_NULL => 0, |
| 3291 | elf.PT_PHDR => 1, |
| 3292 | elf.PT_INTERP => 2, |
| 3293 | elf.PT_LOAD => 3, |
| 3294 | elf.PT_DYNAMIC, elf.PT_TLS => 4, |
| 3295 | elf.PT_GNU_EH_FRAME => 5, |
| 3296 | elf.PT_GNU_STACK => 6, |
| 3297 | else => 7, |
| 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 | 3307 | const Entry = struct { |
| 3268 | 3308 | phndx: u16, |
| 3269 | 3309 | |
| 3270 | | pub fn lessThan(elf_file: *Elf, lhs: @This(), rhs: @This()) bool { |
| 3271 | | const lhs_phdr = elf_file.phdrs.items[lhs.phndx]; |
| 3272 | | const rhs_phdr = elf_file.phdrs.items[rhs.phndx]; |
| 3310 | pub fn lessThan(program_headers: []const elf.Elf64_Phdr, lhs: @This(), rhs: @This()) bool { |
| 3311 | const lhs_phdr = program_headers[lhs.phndx]; |
| 3312 | const rhs_phdr = program_headers[rhs.phndx]; |
| 3273 | 3313 | const lhs_rank = phdrRank(lhs_phdr); |
| 3274 | 3314 | const rhs_rank = phdrRank(rhs_phdr); |
| 3275 | 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 | 3317 | } |
| 3278 | 3318 | }; |
| 3279 | 3319 | |
| 3280 | | const gpa = self.base.comp.gpa; |
| 3281 | | var entries = try std.ArrayList(Entry).initCapacity(gpa, self.phdrs.items.len); |
| 3282 | | defer entries.deinit(); |
| 3283 | | for (0..self.phdrs.items.len) |phndx| { |
| 3284 | | entries.appendAssumeCapacity(.{ .phndx = @as(u16, @intCast(phndx)) }); |
| 3320 | const entries = try gpa.alloc(Entry, phdrs.items.len); |
| 3321 | defer gpa.free(entries); |
| 3322 | for (entries, 0..) |*entry, phndx| { |
| 3323 | entry.* = .{ .phndx = @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 | 3329 | defer gpa.free(backlinks); |
| 3291 | | for (entries.items, 0..) |entry, i| { |
| 3292 | | backlinks[entry.phndx] = @as(u16, @intCast(i)); |
| 3293 | | } |
| 3294 | | |
| 3295 | | const slice = try self.phdrs.toOwnedSlice(gpa); |
| 3330 | const slice = try phdrs.toOwnedSlice(gpa); |
| 3296 | 3331 | defer gpa.free(slice); |
| 3332 | try phdrs.resize(gpa, slice.len); |
| 3297 | 3333 | |
| 3298 | | try self.phdrs.ensureTotalCapacityPrecise(gpa, slice.len); |
| 3299 | | for (entries.items) |sorted| { |
| 3300 | | self.phdrs.appendAssumeCapacity(slice[sorted.phndx]); |
| 3334 | for (entries, phdrs.items, 0..) |entry, *phdr, i| { |
| 3335 | backlinks[entry.phndx] = @intCast(i); |
| 3336 | phdr.* = slice[entry.phndx]; |
| 3301 | 3337 | } |
| 3302 | 3338 | |
| 3303 | | for (&[_]*?u16{ |
| 3304 | | &self.phdr_table_index, |
| 3305 | | &self.phdr_table_load_index, |
| 3306 | | &self.phdr_interp_index, |
| 3307 | | &self.phdr_dynamic_index, |
| 3308 | | &self.phdr_gnu_eh_frame_index, |
| 3309 | | &self.phdr_tls_index, |
| 3310 | | }) |maybe_index| { |
| 3311 | | if (maybe_index.*) |*index| { |
| 3312 | | index.* = backlinks[index.*]; |
| 3339 | inline for (@typeInfo(ProgramHeaderIndexes).@"struct".fields) |field| { |
| 3340 | if (@field(special_indexes, field.name).int()) |special_index| { |
| 3341 | @field(special_indexes, field.name) = @enumFromInt(backlinks[special_index]); |
| 3313 | 3342 | } |
| 3314 | 3343 | } |
| 3315 | 3344 | |
| 3316 | | for (self.sections.items(.phndx)) |*maybe_phndx| { |
| 3317 | | if (maybe_phndx.*) |*index| { |
| 3318 | | index.* = backlinks[index.*]; |
| 3345 | for (section_indexes) |*opt_phndx| { |
| 3346 | if (opt_phndx.int()) |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 | 3685 | if (shdr.sh_type == elf.SHT_NULL) continue; |
| 3657 | 3686 | if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue; |
| 3658 | 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 | 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 | 3693 | |
| 3665 | 3694 | /// Allocates PHDR table in virtual memory and in file. |
| 3666 | 3695 | fn allocatePhdrTable(self: *Elf) error{OutOfMemory}!void { |
| 3667 | | const phdr_table = &self.phdrs.items[self.phdr_table_index.?]; |
| 3668 | | const phdr_table_load = &self.phdrs.items[self.phdr_table_load_index.?]; |
| 3696 | const phdr_table = &self.phdrs.items[self.phdr_indexes.table.int().?]; |
| 3697 | const phdr_table_load = &self.phdrs.items[self.phdr_indexes.table_load.int().?]; |
| 3669 | 3698 | |
| 3670 | 3699 | const ehsize: u64 = switch (self.ptr_width) { |
| 3671 | 3700 | .p32 => @sizeOf(elf.Elf32_Ehdr), |
| ... | ... | @@ -3757,7 +3786,7 @@ pub fn allocateAllocSections(self: *Elf) !void { |
| 3757 | 3786 | // When allocating we first find the largest required alignment |
| 3758 | 3787 | // of any section that is contained in a cover and use it to align |
| 3759 | 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 | 3790 | var addr = phdr_table.p_vaddr + phdr_table.p_memsz; |
| 3762 | 3791 | |
| 3763 | 3792 | for (covers) |cover| { |
| ... | ... | @@ -3817,8 +3846,8 @@ pub fn allocateAllocSections(self: *Elf) !void { |
| 3817 | 3846 | } |
| 3818 | 3847 | |
| 3819 | 3848 | const first = slice.items(.shdr)[cover.items[0]]; |
| 3820 | | const phndx = self.getPhdr(.{ .type = elf.PT_LOAD, .flags = shdrToPhdrFlags(first.sh_flags) }).?; |
| 3821 | | const phdr = &self.phdrs.items[phndx]; |
| 3849 | const phndx = self.getPhdr(.{ .type = elf.PT_LOAD, .flags = shdrToPhdrFlags(first.sh_flags) }).unwrap().?; |
| 3850 | const phdr = &self.phdrs.items[phndx.int()]; |
| 3822 | 3851 | const allocated_size = self.allocatedSize(phdr.p_offset); |
| 3823 | 3852 | if (filesz > allocated_size) { |
| 3824 | 3853 | const old_offset = phdr.p_offset; |
| ... | ... | @@ -3830,7 +3859,7 @@ pub fn allocateAllocSections(self: *Elf) !void { |
| 3830 | 3859 | |
| 3831 | 3860 | for (cover.items) |shndx| { |
| 3832 | 3861 | const shdr = &slice.items(.shdr)[shndx]; |
| 3833 | | slice.items(.phndx)[shndx] = phndx; |
| 3862 | slice.items(.phndx)[shndx] = phndx.toOptional(); |
| 3834 | 3863 | if (shdr.sh_type == elf.SHT_NOBITS) { |
| 3835 | 3864 | shdr.sh_offset = 0; |
| 3836 | 3865 | continue; |
| ... | ... | @@ -3906,12 +3935,12 @@ pub fn allocateNonAllocSections(self: *Elf) !void { |
| 3906 | 3935 | fn allocateSpecialPhdrs(self: *Elf) void { |
| 3907 | 3936 | const slice = self.sections.slice(); |
| 3908 | 3937 | |
| 3909 | | for (&[_]struct { ?u16, ?u32 }{ |
| 3910 | | .{ self.phdr_interp_index, self.interp_section_index }, |
| 3911 | | .{ self.phdr_dynamic_index, self.dynamic_section_index }, |
| 3912 | | .{ self.phdr_gnu_eh_frame_index, self.eh_frame_hdr_section_index }, |
| 3938 | for (&[_]struct { OptionalProgramHeaderIndex, ?u32 }{ |
| 3939 | .{ self.phdr_indexes.interp, self.interp_section_index }, |
| 3940 | .{ self.phdr_indexes.dynamic, self.dynamic_section_index }, |
| 3941 | .{ self.phdr_indexes.gnu_eh_frame, self.eh_frame_hdr_section_index }, |
| 3913 | 3942 | }) |pair| { |
| 3914 | | if (pair[0]) |index| { |
| 3943 | if (pair[0].int()) |index| { |
| 3915 | 3944 | const shdr = slice.items(.shdr)[pair[1].?]; |
| 3916 | 3945 | const phdr = &self.phdrs.items[index]; |
| 3917 | 3946 | phdr.p_align = shdr.sh_addralign; |
| ... | ... | @@ -3926,7 +3955,7 @@ fn allocateSpecialPhdrs(self: *Elf) void { |
| 3926 | 3955 | // Set the TLS segment boundaries. |
| 3927 | 3956 | // We assume TLS sections are laid out contiguously and that there is |
| 3928 | 3957 | // a single TLS segment. |
| 3929 | | if (self.phdr_tls_index) |index| { |
| 3958 | if (self.phdr_indexes.tls.int()) |index| { |
| 3930 | 3959 | const shdrs = slice.items(.shdr); |
| 3931 | 3960 | const phdr = &self.phdrs.items[index]; |
| 3932 | 3961 | var shndx: u32 = 0; |
| ... | ... | @@ -4482,14 +4511,15 @@ pub fn isEffectivelyDynLib(self: Elf) bool { |
| 4482 | 4511 | fn getPhdr(self: *Elf, opts: struct { |
| 4483 | 4512 | type: u32 = 0, |
| 4484 | 4513 | flags: u32 = 0, |
| 4485 | | }) ?u16 { |
| 4514 | }) OptionalProgramHeaderIndex { |
| 4486 | 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 | 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 | 4525 | fn addPhdr(self: *Elf, opts: struct { |
| ... | ... | @@ -4500,9 +4530,9 @@ fn addPhdr(self: *Elf, opts: struct { |
| 4500 | 4530 | addr: u64 = 0, |
| 4501 | 4531 | filesz: u64 = 0, |
| 4502 | 4532 | memsz: u64 = 0, |
| 4503 | | }) error{OutOfMemory}!u16 { |
| 4533 | }) error{OutOfMemory}!ProgramHeaderIndex { |
| 4504 | 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 | 4536 | try self.phdrs.append(gpa, .{ |
| 4507 | 4537 | .p_type = opts.type, |
| 4508 | 4538 | .p_flags = opts.flags, |
| ... | ... | @@ -4756,7 +4786,7 @@ pub fn gotAddress(self: *Elf) i64 { |
| 4756 | 4786 | } |
| 4757 | 4787 | |
| 4758 | 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 | 4790 | const phdr = self.phdrs.items[index]; |
| 4761 | 4791 | const addr = switch (self.getTarget().cpu.arch) { |
| 4762 | 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 | 4798 | } |
| 4769 | 4799 | |
| 4770 | 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 | 4802 | const phdr = self.phdrs.items[index]; |
| 4773 | 4803 | return @intCast(phdr.p_vaddr); |
| 4774 | 4804 | } |
| 4775 | 4805 | |
| 4776 | 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 | 4808 | const phdr = self.phdrs.items[index]; |
| 4779 | 4809 | return @intCast(phdr.p_vaddr); |
| 4780 | 4810 | } |
| ... | ... | @@ -5393,7 +5423,7 @@ const Section = struct { |
| 5393 | 5423 | shdr: elf.Elf64_Shdr, |
| 5394 | 5424 | |
| 5395 | 5425 | /// Assigned program header index if any. |
| 5396 | | phndx: ?u32 = null, |
| 5426 | phndx: OptionalProgramHeaderIndex = .none, |
| 5397 | 5427 | |
| 5398 | 5428 | /// List of atoms contributing to this section. |
| 5399 | 5429 | /// TODO currently this is only used for relocations tracking in relocatable mode |