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
992992 // Generate and emit synthetic sections.
993993 try self.initSyntheticSections();
994994 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
9971006 try self.setDynamicSection(self.rpath_table.keys());
9981007 self.sortDynamicSymtab();
......@@ -3354,9 +3363,8 @@ fn sortPhdrs(
33543363 }
33553364}
33563365
3357fn shdrRank(self: *Elf, shndx: u32) u8 {
3358 const shdr = self.sections.items(.shdr)[shndx];
3359 const name = self.getShString(shdr.sh_name);
3366fn shdrRank(shdr: elf.Elf64_Shdr, shstrtab: []const u8) u8 {
3367 const name = shString(shstrtab, shdr.sh_name);
33603368 const flags = shdr.sh_flags;
33613369
33623370 switch (shdr.sh_type) {
......@@ -3405,120 +3413,138 @@ fn shdrRank(self: *Elf, shndx: u32) u8 {
34053413 }
34063414}
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 {
34093426 const Entry = struct {
34103427 shndx: u32,
34113428
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);
34143437 }
34153438 };
34163439
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) };
34223446 }
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);
34273455 defer gpa.free(backlinks);
34283456 {
3429 var slice = self.sections.toOwnedSlice();
3457 var slice = sections.toOwnedSlice();
34303458 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| {
34343462 backlinks[entry.shndx] = @intCast(i);
3435 self.sections.set(i, slice.get(entry.shndx));
3463 sections.set(i, slice.get(entry.shndx));
34363464 }
34373465 }
34383466
3439 const special_indexes = &self.section_indexes;
3440
34413467 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];
34443470 }
34453471 }
34463472
3447 for (self.merge_sections.items) |*msec| {
3473 for (merge_sections) |*msec| {
34483474 msec.output_section_index = backlinks[msec.output_section_index];
34493475 }
34503476
3451 const slice = self.sections.slice();
3477 const slice = sections.slice();
34523478 for (slice.items(.shdr), slice.items(.atom_list_2)) |*shdr, *atom_list| {
34533479 atom_list.output_section_index = backlinks[atom_list.output_section_index];
34543480 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;
34563482 }
34573483 if (shdr.sh_type == elf.SHT_RELA) {
34583484 // FIXME:JK we should spin up .symtab potentially earlier, or set all non-dynamic RELA sections
34593485 // to point at symtab
34603486 // shdr.sh_link = backlinks[shdr.sh_link];
3461 shdr.sh_link = self.section_indexes.symtab.?;
3487 shdr.sh_link = section_indexes.symtab.?;
34623488 shdr.sh_info = backlinks[shdr.sh_info];
34633489 }
34643490 }
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| {
34693495 cg.shndx = backlinks[cg.shndx];
34703496 }
34713497
3472 if (self.section_indexes.symtab) |index| {
3498 if (section_indexes.symtab) |index| {
34733499 const shdr = &slice.items(.shdr)[index];
3474 shdr.sh_link = self.section_indexes.strtab.?;
3500 shdr.sh_link = section_indexes.strtab.?;
34753501 }
34763502
3477 if (self.section_indexes.dynamic) |index| {
3503 if (section_indexes.dynamic) |index| {
34783504 const shdr = &slice.items(.shdr)[index];
3479 shdr.sh_link = self.section_indexes.dynstrtab.?;
3505 shdr.sh_link = section_indexes.dynstrtab.?;
34803506 }
34813507
3482 if (self.section_indexes.dynsymtab) |index| {
3508 if (section_indexes.dynsymtab) |index| {
34833509 const shdr = &slice.items(.shdr)[index];
3484 shdr.sh_link = self.section_indexes.dynstrtab.?;
3510 shdr.sh_link = section_indexes.dynstrtab.?;
34853511 }
34863512
3487 if (self.section_indexes.hash) |index| {
3513 if (section_indexes.hash) |index| {
34883514 const shdr = &slice.items(.shdr)[index];
3489 shdr.sh_link = self.section_indexes.dynsymtab.?;
3515 shdr.sh_link = section_indexes.dynsymtab.?;
34903516 }
34913517
3492 if (self.section_indexes.gnu_hash) |index| {
3518 if (section_indexes.gnu_hash) |index| {
34933519 const shdr = &slice.items(.shdr)[index];
3494 shdr.sh_link = self.section_indexes.dynsymtab.?;
3520 shdr.sh_link = section_indexes.dynsymtab.?;
34953521 }
34963522
3497 if (self.section_indexes.versym) |index| {
3523 if (section_indexes.versym) |index| {
34983524 const shdr = &slice.items(.shdr)[index];
3499 shdr.sh_link = self.section_indexes.dynsymtab.?;
3525 shdr.sh_link = section_indexes.dynsymtab.?;
35003526 }
35013527
3502 if (self.section_indexes.verneed) |index| {
3528 if (section_indexes.verneed) |index| {
35033529 const shdr = &slice.items(.shdr)[index];
3504 shdr.sh_link = self.section_indexes.dynstrtab.?;
3530 shdr.sh_link = section_indexes.dynstrtab.?;
35053531 }
35063532
3507 if (self.section_indexes.rela_dyn) |index| {
3533 if (section_indexes.rela_dyn) |index| {
35083534 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;
35103536 }
35113537
3512 if (self.section_indexes.rela_plt) |index| {
3538 if (section_indexes.rela_plt) |index| {
35133539 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.?;
35163542 }
35173543
3518 if (self.section_indexes.eh_frame_rela) |index| {
3544 if (section_indexes.eh_frame_rela) |index| {
35193545 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.?;
35223548 }
35233549}
35243550
......@@ -4677,13 +4703,17 @@ pub fn thunk(self: *Elf, index: Thunk.Index) *Thunk {
46774703}
46784704
46794705pub 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];
46814711 return switch (tag) {
46824712 .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 },
46874717 };
46884718}
46894719
......@@ -4790,8 +4820,15 @@ pub fn tlsAddress(self: *Elf) i64 {
47904820}
47914821
47924822pub 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
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];
47954832}
47964833
47974834pub 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
3232 zig_object.claimUnresolvedRelocatable(elf_file);
3333
3434 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 );
3645 try zig_object.addAtomsToRelaSections(elf_file);
3746 try elf_file.updateMergeSectionSizes();
3847 try updateSectionSizes(elf_file);
......@@ -171,7 +180,16 @@ pub fn flushObject(elf_file: *Elf, comp: *Compilation, module_obj_path: ?Path) l
171180 claimUnresolved(elf_file);
172181
173182 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 );
175193 if (elf_file.zigObjectPtr()) |zig_object| {
176194 try zig_object.addAtomsToRelaSections(elf_file);
177195 }