| ... | ... | @@ -992,7 +992,16 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod |
| 992 | 992 | // Generate and emit synthetic sections. |
| 993 | 993 | try self.initSyntheticSections(); |
| 994 | 994 | try self.initSpecialPhdrs(); |
| 995 | | 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 | ); |
| 996 | 1005 | |
| 997 | 1006 | try self.setDynamicSection(self.rpath_table.keys()); |
| 998 | 1007 | self.sortDynamicSymtab(); |
| ... | ... | @@ -3354,9 +3363,8 @@ fn sortPhdrs( |
| 3354 | 3363 | } |
| 3355 | 3364 | } |
| 3356 | 3365 | |
| 3357 | | fn shdrRank(self: *Elf, shndx: u32) u8 { |
| 3358 | | const shdr = self.sections.items(.shdr)[shndx]; |
| 3359 | | const name = self.getShString(shdr.sh_name); |
| 3366 | fn shdrRank(shdr: elf.Elf64_Shdr, shstrtab: []const u8) u8 { |
| 3367 | const name = shString(shstrtab, shdr.sh_name); |
| 3360 | 3368 | const flags = shdr.sh_flags; |
| 3361 | 3369 | |
| 3362 | 3370 | switch (shdr.sh_type) { |
| ... | ... | @@ -3405,120 +3413,138 @@ fn shdrRank(self: *Elf, shndx: u32) u8 { |
| 3405 | 3413 | } |
| 3406 | 3414 | } |
| 3407 | 3415 | |
| 3408 | | pub fn sortShdrs(self: *Elf) !void { |
| 3416 | pub fn sortShdrs( |
| 3417 | gpa: Allocator, |
| 3418 | section_indexes: *SectionIndexes, |
| 3419 | sections: *std.MultiArrayList(Section), |
| 3420 | shstrtab: []const u8, |
| 3421 | merge_sections: []Merge.Section, |
| 3422 | comdat_group_sections: []ComdatGroupSection, |
| 3423 | zig_object_ptr: ?*ZigObject, |
| 3424 | files: std.MultiArrayList(File.Entry), |
| 3425 | ) !void { |
| 3409 | 3426 | const Entry = struct { |
| 3410 | 3427 | shndx: u32, |
| 3411 | 3428 | |
| 3412 | | pub fn lessThan(elf_file: *Elf, lhs: @This(), rhs: @This()) bool { |
| 3413 | | return elf_file.shdrRank(lhs.shndx) < elf_file.shdrRank(rhs.shndx); |
| 3429 | const Context = struct { |
| 3430 | shdrs: []const elf.Elf64_Shdr, |
| 3431 | shstrtab: []const u8, |
| 3432 | }; |
| 3433 | |
| 3434 | pub fn lessThan(ctx: Context, lhs: @This(), rhs: @This()) bool { |
| 3435 | return shdrRank(ctx.shdrs[lhs.shndx], ctx.shstrtab) < |
| 3436 | shdrRank(ctx.shdrs[rhs.shndx], ctx.shstrtab); |
| 3414 | 3437 | } |
| 3415 | 3438 | }; |
| 3416 | 3439 | |
| 3417 | | const gpa = self.base.comp.gpa; |
| 3418 | | var entries = try std.ArrayList(Entry).initCapacity(gpa, self.sections.items(.shdr).len); |
| 3419 | | defer entries.deinit(); |
| 3420 | | for (0..self.sections.items(.shdr).len) |shndx| { |
| 3421 | | entries.appendAssumeCapacity(.{ .shndx = @intCast(shndx) }); |
| 3440 | const shdrs = sections.items(.shdr); |
| 3441 | |
| 3442 | const entries = try gpa.alloc(Entry, shdrs.len); |
| 3443 | defer gpa.free(entries); |
| 3444 | for (entries, 0..shdrs.len) |*entry, shndx| { |
| 3445 | entry.* = .{ .shndx = @intCast(shndx) }; |
| 3422 | 3446 | } |
| 3423 | 3447 | |
| 3424 | | mem.sort(Entry, entries.items, self, Entry.lessThan); |
| 3448 | const sort_context: Entry.Context = .{ |
| 3449 | .shdrs = shdrs, |
| 3450 | .shstrtab = shstrtab, |
| 3451 | }; |
| 3452 | mem.sort(Entry, entries, sort_context, Entry.lessThan); |
| 3425 | 3453 | |
| 3426 | | const backlinks = try gpa.alloc(u32, entries.items.len); |
| 3454 | const backlinks = try gpa.alloc(u32, entries.len); |
| 3427 | 3455 | defer gpa.free(backlinks); |
| 3428 | 3456 | { |
| 3429 | | var slice = self.sections.toOwnedSlice(); |
| 3457 | var slice = sections.toOwnedSlice(); |
| 3430 | 3458 | defer slice.deinit(gpa); |
| 3431 | | try self.sections.resize(gpa, slice.len); |
| 3459 | try sections.resize(gpa, slice.len); |
| 3432 | 3460 | |
| 3433 | | for (entries.items, 0..) |entry, i| { |
| 3461 | for (entries, 0..) |entry, i| { |
| 3434 | 3462 | backlinks[entry.shndx] = @intCast(i); |
| 3435 | | self.sections.set(i, slice.get(entry.shndx)); |
| 3463 | sections.set(i, slice.get(entry.shndx)); |
| 3436 | 3464 | } |
| 3437 | 3465 | } |
| 3438 | 3466 | |
| 3439 | | const special_indexes = &self.section_indexes; |
| 3440 | | |
| 3441 | 3467 | inline for (@typeInfo(SectionIndexes).@"struct".fields) |field| { |
| 3442 | | if (@field(special_indexes, field.name)) |special_index| { |
| 3443 | | @field(special_indexes, field.name) = backlinks[special_index]; |
| 3468 | if (@field(section_indexes, field.name)) |special_index| { |
| 3469 | @field(section_indexes, field.name) = backlinks[special_index]; |
| 3444 | 3470 | } |
| 3445 | 3471 | } |
| 3446 | 3472 | |
| 3447 | | for (self.merge_sections.items) |*msec| { |
| 3473 | for (merge_sections) |*msec| { |
| 3448 | 3474 | msec.output_section_index = backlinks[msec.output_section_index]; |
| 3449 | 3475 | } |
| 3450 | 3476 | |
| 3451 | | const slice = self.sections.slice(); |
| 3477 | const slice = sections.slice(); |
| 3452 | 3478 | for (slice.items(.shdr), slice.items(.atom_list_2)) |*shdr, *atom_list| { |
| 3453 | 3479 | atom_list.output_section_index = backlinks[atom_list.output_section_index]; |
| 3454 | 3480 | for (atom_list.atoms.keys()) |ref| { |
| 3455 | | self.atom(ref).?.output_section_index = atom_list.output_section_index; |
| 3481 | fileLookup(files, ref.file).?.atom(ref.index).?.output_section_index = atom_list.output_section_index; |
| 3456 | 3482 | } |
| 3457 | 3483 | if (shdr.sh_type == elf.SHT_RELA) { |
| 3458 | 3484 | // FIXME:JK we should spin up .symtab potentially earlier, or set all non-dynamic RELA sections |
| 3459 | 3485 | // to point at symtab |
| 3460 | 3486 | // shdr.sh_link = backlinks[shdr.sh_link]; |
| 3461 | | shdr.sh_link = self.section_indexes.symtab.?; |
| 3487 | shdr.sh_link = section_indexes.symtab.?; |
| 3462 | 3488 | shdr.sh_info = backlinks[shdr.sh_info]; |
| 3463 | 3489 | } |
| 3464 | 3490 | } |
| 3465 | 3491 | |
| 3466 | | if (self.zigObjectPtr()) |zo| zo.resetShdrIndexes(backlinks); |
| 3492 | if (zig_object_ptr) |zo| zo.resetShdrIndexes(backlinks); |
| 3467 | 3493 | |
| 3468 | | for (self.comdat_group_sections.items) |*cg| { |
| 3494 | for (comdat_group_sections) |*cg| { |
| 3469 | 3495 | cg.shndx = backlinks[cg.shndx]; |
| 3470 | 3496 | } |
| 3471 | 3497 | |
| 3472 | | if (self.section_indexes.symtab) |index| { |
| 3498 | if (section_indexes.symtab) |index| { |
| 3473 | 3499 | const shdr = &slice.items(.shdr)[index]; |
| 3474 | | shdr.sh_link = self.section_indexes.strtab.?; |
| 3500 | shdr.sh_link = section_indexes.strtab.?; |
| 3475 | 3501 | } |
| 3476 | 3502 | |
| 3477 | | if (self.section_indexes.dynamic) |index| { |
| 3503 | if (section_indexes.dynamic) |index| { |
| 3478 | 3504 | const shdr = &slice.items(.shdr)[index]; |
| 3479 | | shdr.sh_link = self.section_indexes.dynstrtab.?; |
| 3505 | shdr.sh_link = section_indexes.dynstrtab.?; |
| 3480 | 3506 | } |
| 3481 | 3507 | |
| 3482 | | if (self.section_indexes.dynsymtab) |index| { |
| 3508 | if (section_indexes.dynsymtab) |index| { |
| 3483 | 3509 | const shdr = &slice.items(.shdr)[index]; |
| 3484 | | shdr.sh_link = self.section_indexes.dynstrtab.?; |
| 3510 | shdr.sh_link = section_indexes.dynstrtab.?; |
| 3485 | 3511 | } |
| 3486 | 3512 | |
| 3487 | | if (self.section_indexes.hash) |index| { |
| 3513 | if (section_indexes.hash) |index| { |
| 3488 | 3514 | const shdr = &slice.items(.shdr)[index]; |
| 3489 | | shdr.sh_link = self.section_indexes.dynsymtab.?; |
| 3515 | shdr.sh_link = section_indexes.dynsymtab.?; |
| 3490 | 3516 | } |
| 3491 | 3517 | |
| 3492 | | if (self.section_indexes.gnu_hash) |index| { |
| 3518 | if (section_indexes.gnu_hash) |index| { |
| 3493 | 3519 | const shdr = &slice.items(.shdr)[index]; |
| 3494 | | shdr.sh_link = self.section_indexes.dynsymtab.?; |
| 3520 | shdr.sh_link = section_indexes.dynsymtab.?; |
| 3495 | 3521 | } |
| 3496 | 3522 | |
| 3497 | | if (self.section_indexes.versym) |index| { |
| 3523 | if (section_indexes.versym) |index| { |
| 3498 | 3524 | const shdr = &slice.items(.shdr)[index]; |
| 3499 | | shdr.sh_link = self.section_indexes.dynsymtab.?; |
| 3525 | shdr.sh_link = section_indexes.dynsymtab.?; |
| 3500 | 3526 | } |
| 3501 | 3527 | |
| 3502 | | if (self.section_indexes.verneed) |index| { |
| 3528 | if (section_indexes.verneed) |index| { |
| 3503 | 3529 | const shdr = &slice.items(.shdr)[index]; |
| 3504 | | shdr.sh_link = self.section_indexes.dynstrtab.?; |
| 3530 | shdr.sh_link = section_indexes.dynstrtab.?; |
| 3505 | 3531 | } |
| 3506 | 3532 | |
| 3507 | | if (self.section_indexes.rela_dyn) |index| { |
| 3533 | if (section_indexes.rela_dyn) |index| { |
| 3508 | 3534 | const shdr = &slice.items(.shdr)[index]; |
| 3509 | | shdr.sh_link = self.section_indexes.dynsymtab orelse 0; |
| 3535 | shdr.sh_link = section_indexes.dynsymtab orelse 0; |
| 3510 | 3536 | } |
| 3511 | 3537 | |
| 3512 | | if (self.section_indexes.rela_plt) |index| { |
| 3538 | if (section_indexes.rela_plt) |index| { |
| 3513 | 3539 | const shdr = &slice.items(.shdr)[index]; |
| 3514 | | shdr.sh_link = self.section_indexes.dynsymtab.?; |
| 3515 | | shdr.sh_info = self.section_indexes.plt.?; |
| 3540 | shdr.sh_link = section_indexes.dynsymtab.?; |
| 3541 | shdr.sh_info = section_indexes.plt.?; |
| 3516 | 3542 | } |
| 3517 | 3543 | |
| 3518 | | if (self.section_indexes.eh_frame_rela) |index| { |
| 3544 | if (section_indexes.eh_frame_rela) |index| { |
| 3519 | 3545 | const shdr = &slice.items(.shdr)[index]; |
| 3520 | | shdr.sh_link = self.section_indexes.symtab.?; |
| 3521 | | shdr.sh_info = self.section_indexes.eh_frame.?; |
| 3546 | shdr.sh_link = section_indexes.symtab.?; |
| 3547 | shdr.sh_info = section_indexes.eh_frame.?; |
| 3522 | 3548 | } |
| 3523 | 3549 | } |
| 3524 | 3550 | |
| ... | ... | @@ -4677,13 +4703,17 @@ pub fn thunk(self: *Elf, index: Thunk.Index) *Thunk { |
| 4677 | 4703 | } |
| 4678 | 4704 | |
| 4679 | 4705 | pub fn file(self: *Elf, index: File.Index) ?File { |
| 4680 | | const tag = self.files.items(.tags)[index]; |
| 4706 | return fileLookup(self.files, index); |
| 4707 | } |
| 4708 | |
| 4709 | fn fileLookup(files: std.MultiArrayList(File.Entry), index: File.Index) ?File { |
| 4710 | const tag = files.items(.tags)[index]; |
| 4681 | 4711 | return switch (tag) { |
| 4682 | 4712 | .null => null, |
| 4683 | | .linker_defined => .{ .linker_defined = &self.files.items(.data)[index].linker_defined }, |
| 4684 | | .zig_object => .{ .zig_object = &self.files.items(.data)[index].zig_object }, |
| 4685 | | .object => .{ .object = &self.files.items(.data)[index].object }, |
| 4686 | | .shared_object => .{ .shared_object = &self.files.items(.data)[index].shared_object }, |
| 4713 | .linker_defined => .{ .linker_defined = &files.items(.data)[index].linker_defined }, |
| 4714 | .zig_object => .{ .zig_object = &files.items(.data)[index].zig_object }, |
| 4715 | .object => .{ .object = &files.items(.data)[index].object }, |
| 4716 | .shared_object => .{ .shared_object = &files.items(.data)[index].shared_object }, |
| 4687 | 4717 | }; |
| 4688 | 4718 | } |
| 4689 | 4719 | |
| ... | ... | @@ -4790,8 +4820,15 @@ pub fn tlsAddress(self: *Elf) i64 { |
| 4790 | 4820 | } |
| 4791 | 4821 | |
| 4792 | 4822 | pub fn getShString(self: Elf, off: u32) [:0]const u8 { |
| 4793 | | assert(off < self.shstrtab.items.len); |
| 4794 | | return mem.sliceTo(@as([*:0]const u8, @ptrCast(self.shstrtab.items.ptr + off)), 0); |
| 4823 | return shString(self.shstrtab.items, off); |
| 4824 | } |
| 4825 | |
| 4826 | fn shString( |
| 4827 | shstrtab: []const u8, |
| 4828 | off: u32, |
| 4829 | ) [:0]const u8 { |
| 4830 | const slice = shstrtab[off..]; |
| 4831 | return slice[0..std.mem.indexOfScalar(u8, slice, 0).? :0]; |
| 4795 | 4832 | } |
| 4796 | 4833 | |
| 4797 | 4834 | pub fn insertShString(self: *Elf, name: [:0]const u8) error{OutOfMemory}!u32 { |