| ... | @@ -992,7 +992,16 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod | ... | @@ -992,7 +992,16 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod |
| 992 | // Generate and emit synthetic sections. | 992 | // Generate and emit synthetic sections. |
| 993 | try self.initSyntheticSections(); | 993 | try self.initSyntheticSections(); |
| 994 | try self.initSpecialPhdrs(); | 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 | try self.setDynamicSection(self.rpath_table.keys()); | 1006 | try self.setDynamicSection(self.rpath_table.keys()); |
| 998 | self.sortDynamicSymtab(); | 1007 | self.sortDynamicSymtab(); |
| ... | @@ -3354,9 +3363,8 @@ fn sortPhdrs( | ... | @@ -3354,9 +3363,8 @@ fn sortPhdrs( |
| 3354 | } | 3363 | } |
| 3355 | } | 3364 | } |
| 3356 | | 3365 | |
| 3357 | fn shdrRank(self: *Elf, shndx: u32) u8 { | 3366 | fn shdrRank(shdr: elf.Elf64_Shdr, shstrtab: []const u8) u8 { |
| 3358 | const shdr = self.sections.items(.shdr)[shndx]; | 3367 | const name = shString(shstrtab, shdr.sh_name); |
| 3359 | const name = self.getShString(shdr.sh_name); | | |
| 3360 | const flags = shdr.sh_flags; | 3368 | const flags = shdr.sh_flags; |
| 3361 | | 3369 | |
| 3362 | switch (shdr.sh_type) { | 3370 | switch (shdr.sh_type) { |
| ... | @@ -3405,120 +3413,138 @@ fn shdrRank(self: *Elf, shndx: u32) u8 { | ... | @@ -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 | const Entry = struct { | 3426 | const Entry = struct { |
| 3410 | shndx: u32, | 3427 | shndx: u32, |
| 3411 | | 3428 | |
| 3412 | pub fn lessThan(elf_file: *Elf, lhs: @This(), rhs: @This()) bool { | 3429 | const Context = struct { |
| 3413 | return elf_file.shdrRank(lhs.shndx) < elf_file.shdrRank(rhs.shndx); | 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; | 3440 | const shdrs = sections.items(.shdr); |
| 3418 | var entries = try std.ArrayList(Entry).initCapacity(gpa, self.sections.items(.shdr).len); | 3441 | |
| 3419 | defer entries.deinit(); | 3442 | const entries = try gpa.alloc(Entry, shdrs.len); |
| 3420 | for (0..self.sections.items(.shdr).len) |shndx| { | 3443 | defer gpa.free(entries); |
| 3421 | entries.appendAssumeCapacity(.{ .shndx = @intCast(shndx) }); | 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 | defer gpa.free(backlinks); | 3455 | defer gpa.free(backlinks); |
| 3428 | { | 3456 | { |
| 3429 | var slice = self.sections.toOwnedSlice(); | 3457 | var slice = sections.toOwnedSlice(); |
| 3430 | defer slice.deinit(gpa); | 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 | backlinks[entry.shndx] = @intCast(i); | 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 | inline for (@typeInfo(SectionIndexes).@"struct".fields) |field| { | 3467 | inline for (@typeInfo(SectionIndexes).@"struct".fields) |field| { |
| 3442 | if (@field(special_indexes, field.name)) |special_index| { | 3468 | if (@field(section_indexes, field.name)) |special_index| { |
| 3443 | @field(special_indexes, field.name) = backlinks[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 | msec.output_section_index = backlinks[msec.output_section_index]; | 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 | for (slice.items(.shdr), slice.items(.atom_list_2)) |*shdr, *atom_list| { | 3478 | for (slice.items(.shdr), slice.items(.atom_list_2)) |*shdr, *atom_list| { |
| 3453 | atom_list.output_section_index = backlinks[atom_list.output_section_index]; | 3479 | atom_list.output_section_index = backlinks[atom_list.output_section_index]; |
| 3454 | for (atom_list.atoms.keys()) |ref| { | 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 | if (shdr.sh_type == elf.SHT_RELA) { | 3483 | if (shdr.sh_type == elf.SHT_RELA) { |
| 3458 | // FIXME:JK we should spin up .symtab potentially earlier, or set all non-dynamic RELA sections | 3484 | // FIXME:JK we should spin up .symtab potentially earlier, or set all non-dynamic RELA sections |
| 3459 | // to point at symtab | 3485 | // to point at symtab |
| 3460 | // shdr.sh_link = backlinks[shdr.sh_link]; | 3486 | // shdr.sh_link = backlinks[shdr.sh_link]; |
| 3461 | shdr.sh_link = self.section_indexes.symtab.?; | 3487 | shdr.sh_link = section_indexes.symtab.?; |
| 3462 | shdr.sh_info = backlinks[shdr.sh_info]; | 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 | cg.shndx = backlinks[cg.shndx]; | 3495 | cg.shndx = backlinks[cg.shndx]; |
| 3470 | } | 3496 | } |
| 3471 | | 3497 | |
| 3472 | if (self.section_indexes.symtab) |index| { | 3498 | if (section_indexes.symtab) |index| { |
| 3473 | const shdr = &slice.items(.shdr)[index]; | 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 | const shdr = &slice.items(.shdr)[index]; | 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 | const shdr = &slice.items(.shdr)[index]; | 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 | const shdr = &slice.items(.shdr)[index]; | 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 | const shdr = &slice.items(.shdr)[index]; | 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 | const shdr = &slice.items(.shdr)[index]; | 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 | const shdr = &slice.items(.shdr)[index]; | 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 | const shdr = &slice.items(.shdr)[index]; | 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 | const shdr = &slice.items(.shdr)[index]; | 3539 | const shdr = &slice.items(.shdr)[index]; |
| 3514 | shdr.sh_link = self.section_indexes.dynsymtab.?; | 3540 | shdr.sh_link = section_indexes.dynsymtab.?; |
| 3515 | shdr.sh_info = self.section_indexes.plt.?; | 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 | const shdr = &slice.items(.shdr)[index]; | 3545 | const shdr = &slice.items(.shdr)[index]; |
| 3520 | shdr.sh_link = self.section_indexes.symtab.?; | 3546 | shdr.sh_link = section_indexes.symtab.?; |
| 3521 | shdr.sh_info = self.section_indexes.eh_frame.?; | 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,13 +4703,17 @@ pub fn thunk(self: *Elf, index: Thunk.Index) *Thunk { |
| 4677 | } | 4703 | } |
| 4678 | | 4704 | |
| 4679 | pub fn file(self: *Elf, index: File.Index) ?File { | 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 | return switch (tag) { | 4711 | return switch (tag) { |
| 4682 | .null => null, | 4712 | .null => null, |
| 4683 | .linker_defined => .{ .linker_defined = &self.files.items(.data)[index].linker_defined }, | 4713 | .linker_defined => .{ .linker_defined = &files.items(.data)[index].linker_defined }, |
| 4684 | .zig_object => .{ .zig_object = &self.files.items(.data)[index].zig_object }, | 4714 | .zig_object => .{ .zig_object = &files.items(.data)[index].zig_object }, |
| 4685 | .object => .{ .object = &self.files.items(.data)[index].object }, | 4715 | .object => .{ .object = &files.items(.data)[index].object }, |
| 4686 | .shared_object => .{ .shared_object = &self.files.items(.data)[index].shared_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,8 +4820,15 @@ pub fn tlsAddress(self: *Elf) i64 { |
| 4790 | } | 4820 | } |
| 4791 | | 4821 | |
| 4792 | pub fn getShString(self: Elf, off: u32) [:0]const u8 { | 4822 | pub fn getShString(self: Elf, off: u32) [:0]const u8 { |
| 4793 | assert(off < self.shstrtab.items.len); | 4823 | return shString(self.shstrtab.items, off); |
| 4794 | return mem.sliceTo(@as([*:0]const u8, @ptrCast(self.shstrtab.items.ptr + off)), 0); | 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 | pub fn insertShString(self: *Elf, name: [:0]const u8) error{OutOfMemory}!u32 { | 4834 | pub fn insertShString(self: *Elf, name: [:0]const u8) error{OutOfMemory}!u32 { |