authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-10-10 20:34:17-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-10-11 10:33:54-07:00
log05157e820a9fcc3a2a63c785c13c1bbde155c868
tree677e08de231dbe4d4883b6d559b062efdcf535df
parent7b69738a060c738d0f389365bf748dd7321b723c

link.Elf.sortShdrs: tease out data dependencies

In order to reduce the logic that happens in flush() we need to see which data is being accessed by all this logic, so we can see which operations depend on each other.

2 files changed, 114 insertions(+), 59 deletions(-)

src/link/Elf.zig+94-57
...@@ -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 );
9961005
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}
33563365
3357fn shdrRank(self: *Elf, shndx: u32) u8 {3366fn 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;
33613369
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}
34073415
3408pub fn sortShdrs(self: *Elf) !void {3416pub 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,
34113428
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 };
34163439
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 }
34233447
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);
34253453
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);
34323460
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 }
34383466
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 }
34463472
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 }
34503476
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 sections3484 // FIXME:JK we should spin up .symtab potentially earlier, or set all non-dynamic RELA sections
3459 // to point at symtab3485 // 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 }
34653491
3466 if (self.zigObjectPtr()) |zo| zo.resetShdrIndexes(backlinks);3492 if (zig_object_ptr) |zo| zo.resetShdrIndexes(backlinks);
34673493
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 }
34713497
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 }
34763502
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 }
34813507
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 }
34863512
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 }
34913517
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 }
34963522
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 }
35013527
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 }
35063532
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 }
35113537
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 }
35173543
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}
35243550
...@@ -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}
46784704
4679pub fn file(self: *Elf, index: File.Index) ?File {4705pub fn file(self: *Elf, index: File.Index) ?File {
4680 const tag = self.files.items(.tags)[index];4706 return fileLookup(self.files, index);
4707}
4708
4709fn 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}
46894719
...@@ -4790,8 +4820,15 @@ pub fn tlsAddress(self: *Elf) i64 {...@@ -4790,8 +4820,15 @@ pub fn tlsAddress(self: *Elf) i64 {
4790}4820}
47914821
4792pub fn getShString(self: Elf, off: u32) [:0]const u8 {4822pub 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
4826fn 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}
47964833
4797pub fn insertShString(self: *Elf, name: [:0]const u8) error{OutOfMemory}!u32 {4834pub fn insertShString(self: *Elf, name: [:0]const u8) error{OutOfMemory}!u32 {
src/link/Elf/relocatable.zig+20-2
...@@ -32,7 +32,16 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation, module_obj_path: ?Path...@@ -32,7 +32,16 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation, module_obj_path: ?Path
32 zig_object.claimUnresolvedRelocatable(elf_file);32 zig_object.claimUnresolvedRelocatable(elf_file);
3333
34 try initSections(elf_file);34 try initSections(elf_file);
35 try elf_file.sortShdrs();35 try Elf.sortShdrs(
36 gpa,
37 &elf_file.section_indexes,
38 &elf_file.sections,
39 elf_file.shstrtab.items,
40 elf_file.merge_sections.items,
41 elf_file.comdat_group_sections.items,
42 elf_file.zigObjectPtr(),
43 elf_file.files,
44 );
36 try zig_object.addAtomsToRelaSections(elf_file);45 try zig_object.addAtomsToRelaSections(elf_file);
37 try elf_file.updateMergeSectionSizes();46 try elf_file.updateMergeSectionSizes();
38 try updateSectionSizes(elf_file);47 try updateSectionSizes(elf_file);
...@@ -171,7 +180,16 @@ pub fn flushObject(elf_file: *Elf, comp: *Compilation, module_obj_path: ?Path) l...@@ -171,7 +180,16 @@ pub fn flushObject(elf_file: *Elf, comp: *Compilation, module_obj_path: ?Path) l
171 claimUnresolved(elf_file);180 claimUnresolved(elf_file);
172181
173 try initSections(elf_file);182 try initSections(elf_file);
174 try elf_file.sortShdrs();183 try Elf.sortShdrs(
184 comp.gpa,
185 &elf_file.section_indexes,
186 &elf_file.sections,
187 elf_file.shstrtab.items,
188 elf_file.merge_sections.items,
189 elf_file.comdat_group_sections.items,
190 elf_file.zigObjectPtr(),
191 elf_file.files,
192 );
175 if (elf_file.zigObjectPtr()) |zig_object| {193 if (elf_file.zigObjectPtr()) |zig_object| {
176 try zig_object.addAtomsToRelaSections(elf_file);194 try zig_object.addAtomsToRelaSections(elf_file);
177 }195 }