authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-11-07 22:48:02+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-11-07 23:18:41+01:00
log5e78600f0f5e790c0429817d8249020fd65b49f8
treef3715b5e5999e44f09a65a7793a40ae4a155a18d
parentecf6ed7d9bc9bcd61d619fae985ce9ebdc4d5562

elf: actually track output symtab index of symbols


9 files changed, 234 insertions(+), 264 deletions(-)

src/link/Elf.zig+131-120
......@@ -24,6 +24,7 @@ shdr_table_offset: ?u64 = null,
2424/// Table of lists of atoms per output section.
2525/// This table is not used to track incrementally generated atoms.
2626output_sections: std.AutoArrayHashMapUnmanaged(u16, std.ArrayListUnmanaged(Atom.Index)) = .{},
27output_rela_sections: std.AutoArrayHashMapUnmanaged(u16, std.ArrayListUnmanaged(Atom.Index)) = .{},
2728
2829/// Stored in native-endian format, depending on target endianness needs to be bswapped on read/write.
2930/// Same order as in the file.
......@@ -105,11 +106,8 @@ zig_got: ZigGotSection = .{},
105106/// Tracked section headers with incremental updates to Zig object.
106107/// .rela.* sections are only used when emitting a relocatable object file.
107108zig_text_section_index: ?u16 = null,
108zig_text_rela_section_index: ?u16 = null,
109109zig_data_rel_ro_section_index: ?u16 = null,
110zig_data_rel_ro_rela_section_index: ?u16 = null,
111110zig_data_section_index: ?u16 = null,
112zig_data_rela_section_index: ?u16 = null,
113111zig_bss_section_index: ?u16 = null,
114112zig_got_section_index: ?u16 = null,
115113
......@@ -357,6 +355,10 @@ pub fn deinit(self: *Elf) void {
357355 list.deinit(gpa);
358356 }
359357 self.output_sections.deinit(gpa);
358 for (self.output_rela_sections.values()) |*list| {
359 list.deinit(gpa);
360 }
361 self.output_rela_sections.deinit(gpa);
360362 self.shstrtab.deinit(gpa);
361363 self.symtab.deinit(gpa);
362364 self.strtab.deinit(gpa);
......@@ -597,10 +599,8 @@ pub fn initMetadata(self: *Elf) !void {
597599 const shdr = &self.shdrs.items[self.zig_text_section_index.?];
598600 fillSection(self, shdr, self.base.options.program_code_size_hint, self.phdr_zig_load_re_index);
599601 if (self.isRelocatable()) {
600 self.zig_text_rela_section_index = try self.addRelaShdr(
601 ".rela.text.zig",
602 self.zig_text_section_index.?,
603 );
602 const rela_shndx = try self.addRelaShdr(".rela.text.zig", self.zig_text_section_index.?);
603 try self.output_rela_sections.putNoClobber(gpa, rela_shndx, .{});
604604 } else {
605605 try self.phdr_to_shdr_table.putNoClobber(
606606 gpa,
......@@ -644,10 +644,11 @@ pub fn initMetadata(self: *Elf) !void {
644644 const shdr = &self.shdrs.items[self.zig_data_rel_ro_section_index.?];
645645 fillSection(self, shdr, 1024, self.phdr_zig_load_ro_index);
646646 if (self.isRelocatable()) {
647 self.zig_data_rel_ro_rela_section_index = try self.addRelaShdr(
647 const rela_shndx = try self.addRelaShdr(
648648 ".rela.data.rel.ro.zig",
649649 self.zig_data_rel_ro_section_index.?,
650650 );
651 try self.output_rela_sections.putNoClobber(gpa, rela_shndx, .{});
651652 } else {
652653 try self.phdr_to_shdr_table.putNoClobber(
653654 gpa,
......@@ -670,10 +671,11 @@ pub fn initMetadata(self: *Elf) !void {
670671 const shdr = &self.shdrs.items[self.zig_data_section_index.?];
671672 fillSection(self, shdr, 1024, self.phdr_zig_load_rw_index);
672673 if (self.isRelocatable()) {
673 self.zig_data_rela_section_index = try self.addRelaShdr(
674 const rela_shndx = try self.addRelaShdr(
674675 ".rela.data.zig",
675676 self.zig_data_section_index.?,
676677 );
678 try self.output_rela_sections.putNoClobber(gpa, rela_shndx, .{});
677679 } else {
678680 try self.phdr_to_shdr_table.putNoClobber(
679681 gpa,
......@@ -1514,16 +1516,13 @@ pub fn flushStaticLib(self: *Elf) link.File.FlushError!void {
15141516 try self.initSymtab();
15151517 try self.initShStrtab();
15161518 try self.sortShdrs();
1517 zig_object.updateRelaSectionsSizes(self);
1518 self.updateSymtabSizeZigObject(zig_object);
1519 self.updateShStrtabSize();
1519 try zig_object.addAtomsToRelaSections(self);
1520 try self.updateSectionSizesObject();
15201521
15211522 try self.allocateNonAllocSections();
15221523
15231524 try self.writeShdrTable();
1524 try zig_object.writeRelaSections(self);
1525 try self.writeSymtabZigObject(zig_object);
1526 try self.writeShStrtab();
1525 try self.writeSyntheticSectionsObject();
15271526 try self.writeElfHeader();
15281527 }
15291528
......@@ -1620,7 +1619,9 @@ pub fn flushObject(self: *Elf) link.File.FlushError!void {
16201619 try self.initSectionsObject();
16211620 try self.sortShdrs();
16221621 for (self.objects.items) |index| {
1623 try self.file(index).?.object.addAtomsToOutputSections(self);
1622 const object = self.file(index).?.object;
1623 try object.addAtomsToOutputSections(self);
1624 try object.addAtomsToRelaSections(self);
16241625 }
16251626 try self.updateSectionSizesObject();
16261627
......@@ -3452,7 +3453,7 @@ fn initSectionsObject(self: *Elf) !void {
34523453 .addralign = ptr_size,
34533454 .offset = std.math.maxInt(u64),
34543455 });
3455 _ = try self.addRelaShdr(".rela.eh_frame", self.eh_frame_section_index.?);
3456 // _ = try self.addRelaShdr(".rela.eh_frame", self.eh_frame_section_index.?);
34563457 }
34573458
34583459 try self.initSymtab();
......@@ -3841,12 +3842,9 @@ fn sortShdrs(self: *Elf) !void {
38413842 &self.versym_section_index,
38423843 &self.verneed_section_index,
38433844 &self.zig_text_section_index,
3844 &self.zig_text_rela_section_index,
38453845 &self.zig_got_section_index,
38463846 &self.zig_data_rel_ro_section_index,
3847 &self.zig_data_rel_ro_rela_section_index,
38483847 &self.zig_data_section_index,
3849 &self.zig_data_rela_section_index,
38503848 &self.zig_bss_section_index,
38513849 &self.debug_str_section_index,
38523850 &self.debug_info_section_index,
......@@ -4066,7 +4064,7 @@ fn updateSectionSizes(self: *Elf) !void {
40664064 self.shdrs.items[index].sh_size = self.verneed.size();
40674065 }
40684066
4069 self.updateSymtabSize();
4067 try self.updateSymtabSize();
40704068 self.updateShStrtabSize();
40714069}
40724070
......@@ -4084,19 +4082,21 @@ fn updateSectionSizesObject(self: *Elf) !void {
40844082 }
40854083 }
40864084
4087 if (self.zigObjectPtr()) |zig_object| {
4088 zig_object.updateRelaSectionsSizes(self);
4089 }
4090
4091 for (self.objects.items) |index| {
4092 self.file(index).?.object.updateRelaSectionsSizes(self);
4085 for (self.output_rela_sections.keys(), self.output_rela_sections.values()) |shndx, atom_list| {
4086 const shdr = &self.shdrs.items[shndx];
4087 for (atom_list.items) |atom_index| {
4088 const atom_ptr = self.atom(atom_index) orelse continue;
4089 if (!atom_ptr.flags.alive) continue;
4090 const relocs = atom_ptr.relocs(self);
4091 shdr.sh_size += shdr.sh_entsize * relocs.len;
4092 }
40934093 }
40944094
40954095 if (self.eh_frame_section_index) |index| {
40964096 self.shdrs.items[index].sh_size = try eh_frame.calcEhFrameSize(self);
40974097 }
40984098
4099 self.updateSymtabSize();
4099 try self.updateSymtabSize();
41004100 self.updateShStrtabSize();
41014101}
41024102
......@@ -4597,96 +4597,123 @@ fn writeAtomsObject(self: *Elf) !void {
45974597 }
45984598}
45994599
4600fn updateSymtabSize(self: *Elf) void {
4601 var sizes = SymtabSize{};
4600fn updateSymtabSize(self: *Elf) !void {
4601 var nlocals: u32 = 0;
4602 var nglobals: u32 = 0;
4603 var strsize: u32 = 0;
46024604
4603 if (self.zigObjectPtr()) |zig_object| {
4604 zig_object.asFile().updateSymtabSize(self);
4605 sizes.add(zig_object.output_symtab_size);
4606 }
4605 const gpa = self.base.allocator;
4606 var files = std.ArrayList(File.Index).init(gpa);
4607 defer files.deinit();
4608 try files.ensureTotalCapacityPrecise(self.objects.items.len + self.shared_objects.items.len + 1);
46074609
4610 if (self.zig_object_index) |index| files.appendAssumeCapacity(index);
46084611 for (self.objects.items) |index| {
4609 const file_ptr = self.file(index).?;
4610 file_ptr.updateSymtabSize(self);
4611 sizes.add(file_ptr.object.output_symtab_size);
4612 files.appendAssumeCapacity(index);
46124613 }
4613
46144614 for (self.shared_objects.items) |index| {
4615 files.appendAssumeCapacity(index);
4616 }
4617
4618 // Section symbols
4619 for (self.output_sections.keys()) |_| {
4620 nlocals += 1;
4621 }
4622
4623 for (files.items) |index| {
46154624 const file_ptr = self.file(index).?;
4616 file_ptr.updateSymtabSize(self);
4617 sizes.add(file_ptr.shared_object.output_symtab_size);
4625 const ctx = switch (file_ptr) {
4626 inline else => |x| &x.output_symtab_ctx,
4627 };
4628 ctx.ilocal = nlocals + 1;
4629 ctx.iglobal = nglobals + 1;
4630 try file_ptr.updateSymtabSize(self);
4631 nlocals += ctx.nlocals;
4632 nglobals += ctx.nglobals;
4633 strsize += ctx.strsize;
46184634 }
46194635
46204636 if (self.zig_got_section_index) |_| {
4637 self.zig_got.output_symtab_ctx.ilocal = nlocals + 1;
46214638 self.zig_got.updateSymtabSize(self);
4622 sizes.add(self.zig_got.output_symtab_size);
4639 nlocals += self.zig_got.output_symtab_ctx.nlocals;
4640 strsize += self.zig_got.output_symtab_ctx.strsize;
46234641 }
46244642
46254643 if (self.got_section_index) |_| {
4644 self.got.output_symtab_ctx.ilocal = nlocals + 1;
46264645 self.got.updateSymtabSize(self);
4627 sizes.add(self.got.output_symtab_size);
4646 nlocals += self.got.output_symtab_ctx.nlocals;
4647 strsize += self.got.output_symtab_ctx.strsize;
46284648 }
46294649
46304650 if (self.plt_section_index) |_| {
4651 self.plt.output_symtab_ctx.ilocal = nlocals + 1;
46314652 self.plt.updateSymtabSize(self);
4632 sizes.add(self.plt.output_symtab_size);
4653 nlocals += self.plt.output_symtab_ctx.nlocals;
4654 strsize += self.plt.output_symtab_ctx.strsize;
46334655 }
46344656
46354657 if (self.plt_got_section_index) |_| {
4658 self.plt_got.output_symtab_ctx.ilocal = nlocals + 1;
46364659 self.plt_got.updateSymtabSize(self);
4637 sizes.add(self.plt_got.output_symtab_size);
4660 nlocals += self.plt_got.output_symtab_ctx.nlocals;
4661 strsize += self.plt_got.output_symtab_ctx.strsize;
46384662 }
46394663
4640 if (self.linker_defined_index) |index| {
4664 for (files.items) |index| {
46414665 const file_ptr = self.file(index).?;
4642 file_ptr.updateSymtabSize(self);
4643 sizes.add(file_ptr.linker_defined.output_symtab_size);
4644 }
4645
4646 // Section symbols
4647 for (self.output_sections.keys()) |_| {
4648 sizes.nlocals += 1;
4666 const ctx = switch (file_ptr) {
4667 inline else => |x| &x.output_symtab_ctx,
4668 };
4669 ctx.iglobal += nlocals;
46494670 }
46504671
46514672 const symtab_shdr = &self.shdrs.items[self.symtab_section_index.?];
4652 symtab_shdr.sh_info = sizes.nlocals + 1;
4673 symtab_shdr.sh_info = nlocals + 1;
46534674 symtab_shdr.sh_link = self.strtab_section_index.?;
46544675
46554676 const sym_size: u64 = switch (self.ptr_width) {
46564677 .p32 => @sizeOf(elf.Elf32_Sym),
46574678 .p64 => @sizeOf(elf.Elf64_Sym),
46584679 };
4659 const needed_size = (sizes.nlocals + sizes.nglobals + 1) * sym_size;
4680 const needed_size = (nlocals + nglobals + 1) * sym_size;
46604681 symtab_shdr.sh_size = needed_size;
46614682
46624683 const strtab = &self.shdrs.items[self.strtab_section_index.?];
4663 strtab.sh_size = sizes.strsize + 1;
4684 strtab.sh_size = strsize + 1;
46644685}
46654686
46664687fn updateSymtabSizeZigObject(self: *Elf, zig_object: *ZigObject) void {
4667 var sizes = SymtabSize{};
4668
4669 zig_object.asFile().updateSymtabSize(self);
4670 sizes.add(zig_object.output_symtab_size);
4688 var nlocals: u32 = 0;
4689 var nglobals: u32 = 0;
4690 var strsize: u32 = 0;
46714691
46724692 // Section symbols
46734693 for (self.output_sections.keys()) |_| {
4674 sizes.nlocals += 1;
4694 nlocals += 1;
46754695 }
46764696
4697 zig_object.output_symtab_ctx.ilocal = nlocals + 1;
4698 try zig_object.asFile().updateSymtabSize(self);
4699 nlocals += zig_object.output_symtab_ctx.nlocals;
4700 nglobals += zig_object.output_symtab_ctx.nglobals;
4701 strsize += zig_object.output_symtab_ctx.strsize;
4702 zig_object.output_symtab_ctx.iglobal = nlocals + 1;
4703
46774704 const symtab_shdr = &self.shdrs.items[self.symtab_section_index.?];
4678 symtab_shdr.sh_info = sizes.nlocals + 1;
4705 symtab_shdr.sh_info = nlocals + 1;
46794706 symtab_shdr.sh_link = self.strtab_section_index.?;
46804707
46814708 const sym_size: u64 = switch (self.ptr_width) {
46824709 .p32 => @sizeOf(elf.Elf32_Sym),
46834710 .p64 => @sizeOf(elf.Elf64_Sym),
46844711 };
4685 const needed_size = (sizes.nlocals + sizes.nglobals + 1) * sym_size;
4712 const needed_size = (nlocals + nglobals + 1) * sym_size;
46864713 symtab_shdr.sh_size = needed_size;
46874714
46884715 const strtab = &self.shdrs.items[self.strtab_section_index.?];
4689 strtab.sh_size = sizes.strsize + 1;
4716 strtab.sh_size = strsize + 1;
46904717}
46914718
46924719fn writeSyntheticSections(self: *Elf) !void {
......@@ -4822,12 +4849,31 @@ fn writeSyntheticSections(self: *Elf) !void {
48224849fn writeSyntheticSectionsObject(self: *Elf) !void {
48234850 const gpa = self.base.allocator;
48244851
4825 if (self.zigObjectPtr()) |zig_object| {
4826 try zig_object.writeRelaSections(self);
4827 }
4852 for (self.output_rela_sections.keys(), self.output_rela_sections.values()) |shndx, atom_list| {
4853 if (atom_list.items.len == 0) continue;
48284854
4829 for (self.objects.items) |index| {
4830 try self.file(index).?.object.writeRelaSections(self);
4855 const shdr = self.shdrs.items[shndx];
4856
4857 const num_relocs = @divExact(shdr.sh_size, shdr.sh_entsize);
4858 var relocs = try std.ArrayList(elf.Elf64_Rela).initCapacity(gpa, num_relocs);
4859 defer relocs.deinit();
4860
4861 for (atom_list.items) |atom_index| {
4862 const atom_ptr = self.atom(atom_index) orelse continue;
4863 if (!atom_ptr.flags.alive) continue;
4864 try atom_ptr.writeRelocs(self, &relocs);
4865 }
4866
4867 const SortRelocs = struct {
4868 pub fn lessThan(ctx: void, lhs: elf.Elf64_Rela, rhs: elf.Elf64_Rela) bool {
4869 _ = ctx;
4870 return lhs.r_offset < rhs.r_offset;
4871 }
4872 };
4873
4874 mem.sort(elf.Elf64_Rela, relocs.items, {}, SortRelocs.lessThan);
4875
4876 try self.base.file.?.pwriteAll(mem.sliceAsBytes(relocs.items), shdr.sh_offset);
48314877 }
48324878
48334879 if (self.eh_frame_section_index) |shndx| {
......@@ -4836,7 +4882,7 @@ fn writeSyntheticSectionsObject(self: *Elf) !void {
48364882 var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size);
48374883 defer buffer.deinit();
48384884 try eh_frame.writeEhFrame(self, buffer.writer());
4839 // try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);
4885 try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);
48404886 }
48414887
48424888 try self.writeSymtab();
......@@ -4850,16 +4896,6 @@ fn writeShStrtab(self: *Elf) !void {
48504896 }
48514897}
48524898
4853const WriteSymtabCtx = struct {
4854 ilocal: usize,
4855 iglobal: usize,
4856
4857 fn incr(this: *@This(), ss: SymtabSize) void {
4858 this.ilocal += ss.nlocals;
4859 this.iglobal += ss.nglobals;
4860 }
4861};
4862
48634899fn writeSymtab(self: *Elf) !void {
48644900 const gpa = self.base.allocator;
48654901 const symtab_shdr = self.shdrs.items[self.symtab_section_index.?];
......@@ -4876,54 +4912,41 @@ fn writeSymtab(self: *Elf) !void {
48764912 const needed_strtab_size = math.cast(usize, strtab_shdr.sh_size - 1) orelse return error.Overflow;
48774913 try self.strtab.ensureUnusedCapacity(gpa, needed_strtab_size);
48784914
4879 var ctx: WriteSymtabCtx = .{
4880 .ilocal = 1,
4881 .iglobal = symtab_shdr.sh_info,
4882 };
4883
4884 ctx.incr(self.writeSectionSymbols(ctx));
4915 self.writeSectionSymbols();
48854916
48864917 if (self.zigObjectPtr()) |zig_object| {
4887 zig_object.asFile().writeSymtab(self, ctx);
4888 ctx.incr(zig_object.output_symtab_size);
4918 zig_object.asFile().writeSymtab(self);
48894919 }
48904920
48914921 for (self.objects.items) |index| {
48924922 const file_ptr = self.file(index).?;
4893 file_ptr.writeSymtab(self, ctx);
4894 ctx.incr(file_ptr.object.output_symtab_size);
4923 file_ptr.writeSymtab(self);
48954924 }
48964925
48974926 for (self.shared_objects.items) |index| {
48984927 const file_ptr = self.file(index).?;
4899 file_ptr.writeSymtab(self, ctx);
4900 ctx.incr(file_ptr.shared_object.output_symtab_size);
4928 file_ptr.writeSymtab(self);
49014929 }
49024930
49034931 if (self.zig_got_section_index) |_| {
4904 self.zig_got.writeSymtab(self, ctx);
4905 ctx.incr(self.zig_got.output_symtab_size);
4932 self.zig_got.writeSymtab(self);
49064933 }
49074934
49084935 if (self.got_section_index) |_| {
4909 self.got.writeSymtab(self, ctx);
4910 ctx.incr(self.got.output_symtab_size);
4936 self.got.writeSymtab(self);
49114937 }
49124938
49134939 if (self.plt_section_index) |_| {
4914 self.plt.writeSymtab(self, ctx);
4915 ctx.incr(self.plt.output_symtab_size);
4940 self.plt.writeSymtab(self);
49164941 }
49174942
49184943 if (self.plt_got_section_index) |_| {
4919 self.plt_got.writeSymtab(self, ctx);
4920 ctx.incr(self.plt_got.output_symtab_size);
4944 self.plt_got.writeSymtab(self);
49214945 }
49224946
49234947 if (self.linker_defined_index) |index| {
49244948 const file_ptr = self.file(index).?;
4925 file_ptr.writeSymtab(self, ctx);
4926 ctx.incr(file_ptr.linker_defined.output_symtab_size);
4949 file_ptr.writeSymtab(self);
49274950 }
49284951
49294952 const foreign_endian = self.base.options.target.cpu.arch.endian() != builtin.cpu.arch.endian();
......@@ -4972,15 +4995,8 @@ fn writeSymtabZigObject(self: *Elf, zig_object: *ZigObject) !void {
49724995 const needed_strtab_size = math.cast(usize, strtab_shdr.sh_size - 1) orelse return error.Overflow;
49734996 try self.strtab.ensureUnusedCapacity(gpa, needed_strtab_size);
49744997
4975 var ctx: WriteSymtabCtx = .{
4976 .ilocal = 1,
4977 .iglobal = symtab_shdr.sh_info,
4978 };
4979
4980 ctx.incr(self.writeSectionSymbols(ctx));
4981
4982 zig_object.asFile().writeSymtab(self, ctx);
4983 ctx.incr(zig_object.output_symtab_size);
4998 self.writeSectionSymbols();
4999 zig_object.asFile().writeSymtab(self);
49845000
49855001 const foreign_endian = self.base.options.target.cpu.arch.endian() != builtin.cpu.arch.endian();
49865002 switch (self.ptr_width) {
......@@ -5012,8 +5028,8 @@ fn writeSymtabZigObject(self: *Elf, zig_object: *ZigObject) !void {
50125028 try self.base.file.?.pwriteAll(self.strtab.items, strtab_shdr.sh_offset);
50135029}
50145030
5015fn writeSectionSymbols(self: *Elf, ctx: WriteSymtabCtx) SymtabSize {
5016 var ilocal = ctx.ilocal;
5031fn writeSectionSymbols(self: *Elf) void {
5032 var ilocal: u32 = 1;
50175033 for (self.output_sections.keys()) |shndx| {
50185034 const shdr = self.shdrs.items[shndx];
50195035 const out_sym = &self.symtab.items[ilocal];
......@@ -5027,7 +5043,6 @@ fn writeSectionSymbols(self: *Elf, ctx: WriteSymtabCtx) SymtabSize {
50275043 };
50285044 ilocal += 1;
50295045 }
5030 return .{ .nlocals = @intCast(ilocal - ctx.ilocal) };
50315046}
50325047
50335048/// Always 4 or 8 depending on whether this is 32-bit ELF or 64-bit ELF.
......@@ -6056,16 +6071,12 @@ pub const ComdatGroup = struct {
60566071 pub const Index = u32;
60576072};
60586073
6059pub const SymtabSize = struct {
6074pub const SymtabCtx = struct {
6075 ilocal: u32 = 0,
6076 iglobal: u32 = 0,
60606077 nlocals: u32 = 0,
60616078 nglobals: u32 = 0,
60626079 strsize: u32 = 0,
6063
6064 fn add(ss: *SymtabSize, other: SymtabSize) void {
6065 ss.nlocals += other.nlocals;
6066 ss.nglobals += other.nglobals;
6067 ss.strsize += other.strsize;
6068 }
60696080};
60706081
60716082pub const null_sym = elf.Elf64_Sym{
src/link/Elf/Atom.zig+26
......@@ -293,6 +293,32 @@ pub fn relocs(self: Atom, elf_file: *Elf) []align(1) const elf.Elf64_Rela {
293293 };
294294}
295295
296pub fn writeRelocs(self: Atom, elf_file: *Elf, out_relocs: *std.ArrayList(elf.Elf64_Rela)) !void {
297 const file_ptr = self.file(elf_file).?;
298 for (self.relocs(elf_file)) |rel| {
299 const target_index = switch (file_ptr) {
300 .zig_object => |x| x.symbol(rel.r_sym()),
301 .object => |x| x.symbols.items[rel.r_sym()],
302 else => unreachable,
303 };
304 const target = elf_file.symbol(target_index);
305 const r_sym = target.outputSymtabIndex(elf_file);
306 const r_offset = self.value + rel.r_offset;
307 const r_addend = rel.r_addend;
308 const r_type = switch (rel.r_type()) {
309 Elf.R_X86_64_ZIG_GOT32,
310 Elf.R_X86_64_ZIG_GOTPCREL,
311 => unreachable, // Sanity check if we accidentally emitted those.
312 else => |r_type| r_type,
313 };
314 out_relocs.appendAssumeCapacity(.{
315 .r_offset = r_offset,
316 .r_addend = r_addend,
317 .r_info = (@as(u64, @intCast(r_sym)) << 32) | r_type,
318 });
319 }
320}
321
296322pub fn fdes(self: Atom, elf_file: *Elf) []Fde {
297323 if (self.fde_start == self.fde_end) return &[0]Fde{};
298324 const object = self.file(elf_file).?.object;
src/link/Elf/LinkerDefined.zig+1-1
......@@ -3,7 +3,7 @@ symtab: std.ArrayListUnmanaged(elf.Elf64_Sym) = .{},
33strtab: std.ArrayListUnmanaged(u8) = .{},
44symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},
55
6output_symtab_size: Elf.SymtabSize = .{},
6output_symtab_ctx: Elf.SymtabCtx = .{},
77
88pub fn deinit(self: *LinkerDefined, allocator: Allocator) void {
99 self.symtab.deinit(allocator);
src/link/Elf/Object.zig+7-10
......@@ -19,7 +19,7 @@ cies: std.ArrayListUnmanaged(Cie) = .{},
1919alive: bool = true,
2020num_dynrelocs: u32 = 0,
2121
22output_symtab_size: Elf.SymtabSize = .{},
22output_symtab_ctx: Elf.SymtabCtx = .{},
2323output_ar_state: Archive.ArState = .{},
2424
2525pub fn isObject(path: []const u8) !bool {
......@@ -672,22 +672,19 @@ pub fn initRelaSections(self: Object, elf_file: *Elf) !void {
672672 }
673673}
674674
675pub fn updateRelaSectionsSizes(self: Object, elf_file: *Elf) void {
675pub fn addAtomsToRelaSections(self: Object, elf_file: *Elf) !void {
676676 for (self.atoms.items) |atom_index| {
677677 const atom = elf_file.atom(atom_index) orelse continue;
678678 if (!atom.flags.alive) continue;
679679 const shndx = atom.relocsShndx() orelse continue;
680680 const shdr = self.shdrs.items[shndx];
681681 const out_shndx = self.initOutputSection(elf_file, shdr) catch unreachable;
682 const out_shdr = &elf_file.shdrs.items[out_shndx];
683 const relocs = atom.relocs(elf_file);
684 out_shdr.sh_size += out_shdr.sh_entsize * relocs.len;
685 }
686}
687682
688pub fn writeRelaSections(self: Object, elf_file: *Elf) !void {
689 _ = self;
690 _ = elf_file;
683 const gpa = elf_file.base.allocator;
684 const gop = try elf_file.output_rela_sections.getOrPut(gpa, out_shndx);
685 if (!gop.found_existing) gop.value_ptr.* = .{};
686 try gop.value_ptr.append(gpa, atom_index);
687 }
691688}
692689
693690pub fn updateArSymtab(self: Object, ar_symtab: *Archive.ArSymtab, elf_file: *Elf) !void {
src/link/Elf/SharedObject.zig+1-1
......@@ -21,7 +21,7 @@ verdef_sect_index: ?u16 = null,
2121needed: bool,
2222alive: bool,
2323
24output_symtab_size: Elf.SymtabSize = .{},
24output_symtab_ctx: Elf.SymtabCtx = .{},
2525
2626pub fn isSharedObject(path: []const u8) !bool {
2727 const file = try std.fs.cwd().openFile(path, .{});
src/link/Elf/Symbol.zig+19
......@@ -107,6 +107,24 @@ pub fn address(symbol: Symbol, opts: struct { plt: bool = true }, elf_file: *Elf
107107 return symbol.value;
108108}
109109
110pub fn outputSymtabIndex(symbol: Symbol, elf_file: *Elf) u32 {
111 assert(symbol.flags.output_symtab);
112 const file_ptr = symbol.file(elf_file).?;
113 const symtab_ctx = switch (file_ptr) {
114 inline else => |x| x.output_symtab_ctx,
115 };
116 const idx = symbol.extra(elf_file).?.symtab;
117 return if (symbol.isLocal(elf_file)) idx + symtab_ctx.ilocal else idx + symtab_ctx.iglobal;
118}
119
120pub fn setOutputSymtabIndex(symbol: *Symbol, index: u32, elf_file: *Elf) !void {
121 if (symbol.extra(elf_file)) |extras| {
122 var new_extras = extras;
123 new_extras.symtab = index;
124 symbol.setExtra(new_extras, elf_file);
125 } else try symbol.addExtra(.{ .symtab = index }, elf_file);
126}
127
110128pub fn gotAddress(symbol: Symbol, elf_file: *Elf) u64 {
111129 if (!symbol.flags.has_got) return 0;
112130 const extras = symbol.extra(elf_file).?;
......@@ -388,6 +406,7 @@ pub const Extra = struct {
388406 plt: u32 = 0,
389407 plt_got: u32 = 0,
390408 dynamic: u32 = 0,
409 symtab: u32 = 0,
391410 copy_rel: u32 = 0,
392411 tlsgd: u32 = 0,
393412 gottp: u32 = 0,
src/link/Elf/ZigObject.zig+11-88
......@@ -18,7 +18,7 @@ relocs: std.ArrayListUnmanaged(std.ArrayListUnmanaged(elf.Elf64_Rela)) = .{},
1818
1919num_dynrelocs: u32 = 0,
2020
21output_symtab_size: Elf.SymtabSize = .{},
21output_symtab_ctx: Elf.SymtabCtx = .{},
2222output_ar_state: Archive.ArState = .{},
2323
2424dwarf: ?Dwarf = null,
......@@ -533,94 +533,17 @@ pub fn writeAr(self: ZigObject, elf_file: *Elf, writer: anytype) !void {
533533 try writer.writeAll(contents);
534534}
535535
536pub fn updateRelaSectionsSizes(self: ZigObject, elf_file: *Elf) void {
537 _ = self;
538
539 for (&[_]?u16{
540 elf_file.zig_text_rela_section_index,
541 elf_file.zig_data_rel_ro_rela_section_index,
542 elf_file.zig_data_rela_section_index,
543 }) |maybe_index| {
544 const index = maybe_index orelse continue;
545 const shdr = &elf_file.shdrs.items[index];
546 const meta = elf_file.last_atom_and_free_list_table.get(@intCast(shdr.sh_info)).?;
547 const last_atom_index = meta.last_atom_index;
548
549 var atom = elf_file.atom(last_atom_index) orelse continue;
550 while (true) {
551 const relocs = atom.relocs(elf_file);
552 shdr.sh_size += relocs.len * shdr.sh_entsize;
553 if (elf_file.atom(atom.prev_index)) |prev| {
554 atom = prev;
555 } else break;
556 }
557 }
558
559 for (&[_]?u16{
560 elf_file.zig_text_rela_section_index,
561 elf_file.zig_data_rel_ro_rela_section_index,
562 elf_file.zig_data_rela_section_index,
563 }) |maybe_index| {
564 const index = maybe_index orelse continue;
565 const shdr = &elf_file.shdrs.items[index];
566 if (shdr.sh_size == 0) shdr.sh_offset = 0;
567 }
568}
569
570pub fn writeRelaSections(self: ZigObject, elf_file: *Elf) !void {
571 const gpa = elf_file.base.allocator;
572
573 for (&[_]?u16{
574 elf_file.zig_text_rela_section_index,
575 elf_file.zig_data_rel_ro_rela_section_index,
576 elf_file.zig_data_rela_section_index,
577 }) |maybe_index| {
578 const index = maybe_index orelse continue;
579 const shdr = elf_file.shdrs.items[index];
580 const meta = elf_file.last_atom_and_free_list_table.get(@intCast(shdr.sh_info)).?;
581 const last_atom_index = meta.last_atom_index;
582
583 var atom = elf_file.atom(last_atom_index) orelse continue;
584
585 var relocs = std.ArrayList(elf.Elf64_Rela).init(gpa);
586 defer relocs.deinit();
587 try relocs.ensureTotalCapacityPrecise(@intCast(@divExact(shdr.sh_size, shdr.sh_entsize)));
588
589 while (true) {
590 for (atom.relocs(elf_file)) |rel| {
591 const target = elf_file.symbol(self.symbol(rel.r_sym()));
592 const r_offset = atom.value + rel.r_offset;
593 const r_sym: u32 = if (target.flags.global)
594 (target.esym_index & symbol_mask) + @as(u32, @intCast(self.local_esyms.slice().len))
595 else
596 target.esym_index;
597 const r_type = switch (rel.r_type()) {
598 Elf.R_X86_64_ZIG_GOT32,
599 Elf.R_X86_64_ZIG_GOTPCREL,
600 => unreachable, // Sanity check if we accidentally emitted those.
601 else => |r_type| r_type,
602 };
603 relocs.appendAssumeCapacity(.{
604 .r_offset = r_offset,
605 .r_addend = rel.r_addend,
606 .r_info = (@as(u64, @intCast(r_sym + 1)) << 32) | r_type,
607 });
608 }
609 if (elf_file.atom(atom.prev_index)) |prev| {
610 atom = prev;
611 } else break;
612 }
613
614 const SortRelocs = struct {
615 pub fn lessThan(ctx: void, lhs: elf.Elf64_Rela, rhs: elf.Elf64_Rela) bool {
616 _ = ctx;
617 return lhs.r_offset < rhs.r_offset;
618 }
619 };
620
621 mem.sort(elf.Elf64_Rela, relocs.items, {}, SortRelocs.lessThan);
536pub fn addAtomsToRelaSections(self: ZigObject, elf_file: *Elf) !void {
537 for (self.atoms.items) |atom_index| {
538 const atom = elf_file.atom(atom_index) orelse continue;
539 if (!atom.flags.alive) continue;
540 _ = atom.relocsShndx() orelse continue;
541 const out_shndx = atom.outputShndx().?;
622542
623 try elf_file.base.file.?.pwriteAll(mem.sliceAsBytes(relocs.items), shdr.sh_offset);
543 const gpa = elf_file.base.allocator;
544 const gop = try elf_file.output_rela_sections.getOrPut(gpa, out_shndx);
545 if (!gop.found_existing) gop.value_ptr.* = .{};
546 try gop.value_ptr.append(gpa, atom_index);
624547 }
625548}
626549
src/link/Elf/file.zig+18-24
......@@ -127,9 +127,9 @@ pub const File = union(enum) {
127127 };
128128 }
129129
130 pub fn updateSymtabSize(file: File, elf_file: *Elf) void {
131 const output_symtab_size = switch (file) {
132 inline else => |x| &x.output_symtab_size,
130 pub fn updateSymtabSize(file: File, elf_file: *Elf) !void {
131 const output_symtab_ctx = switch (file) {
132 inline else => |x| &x.output_symtab_ctx,
133133 };
134134 for (file.locals()) |local_index| {
135135 const local = elf_file.symbol(local_index);
......@@ -140,8 +140,9 @@ pub const File = union(enum) {
140140 else => {},
141141 }
142142 local.flags.output_symtab = true;
143 output_symtab_size.nlocals += 1;
144 output_symtab_size.strsize += @as(u32, @intCast(local.name(elf_file).len)) + 1;
143 try local.setOutputSymtabIndex(output_symtab_ctx.nlocals, elf_file);
144 output_symtab_ctx.nlocals += 1;
145 output_symtab_ctx.strsize += @as(u32, @intCast(local.name(elf_file).len)) + 1;
145146 }
146147
147148 for (file.globals()) |global_index| {
......@@ -151,28 +152,28 @@ pub const File = union(enum) {
151152 if (global.atom(elf_file)) |atom| if (!atom.flags.alive) continue;
152153 global.flags.output_symtab = true;
153154 if (global.isLocal(elf_file)) {
154 output_symtab_size.nlocals += 1;
155 try global.setOutputSymtabIndex(output_symtab_ctx.nlocals, elf_file);
156 output_symtab_ctx.nlocals += 1;
155157 } else {
156 output_symtab_size.nglobals += 1;
158 try global.setOutputSymtabIndex(output_symtab_ctx.nglobals, elf_file);
159 output_symtab_ctx.nglobals += 1;
157160 }
158 output_symtab_size.strsize += @as(u32, @intCast(global.name(elf_file).len)) + 1;
161 output_symtab_ctx.strsize += @as(u32, @intCast(global.name(elf_file).len)) + 1;
159162 }
160163 }
161164
162 pub fn writeSymtab(file: File, elf_file: *Elf, ctx: anytype) void {
163 var ilocal: usize = ctx.ilocal;
165 pub fn writeSymtab(file: File, elf_file: *Elf) void {
164166 for (file.locals()) |local_index| {
165167 const local = elf_file.symbol(local_index);
166168 if (!local.flags.output_symtab) continue;
167 const out_sym = &elf_file.symtab.items[ilocal];
169 const idx = local.outputSymtabIndex(elf_file);
170 const out_sym = &elf_file.symtab.items[idx];
168171 out_sym.st_name = @intCast(elf_file.strtab.items.len);
169172 elf_file.strtab.appendSliceAssumeCapacity(local.name(elf_file));
170173 elf_file.strtab.appendAssumeCapacity(0);
171174 local.setOutputSym(elf_file, out_sym);
172 ilocal += 1;
173175 }
174176
175 var iglobal: usize = ctx.iglobal;
176177 for (file.globals()) |global_index| {
177178 const global = elf_file.symbol(global_index);
178179 const file_ptr = global.file(elf_file) orelse continue;
......@@ -181,17 +182,10 @@ pub const File = union(enum) {
181182 const st_name = @as(u32, @intCast(elf_file.strtab.items.len));
182183 elf_file.strtab.appendSliceAssumeCapacity(global.name(elf_file));
183184 elf_file.strtab.appendAssumeCapacity(0);
184 if (global.isLocal(elf_file)) {
185 const out_sym = &elf_file.symtab.items[ilocal];
186 out_sym.st_name = st_name;
187 global.setOutputSym(elf_file, out_sym);
188 ilocal += 1;
189 } else {
190 const out_sym = &elf_file.symtab.items[iglobal];
191 out_sym.st_name = st_name;
192 global.setOutputSym(elf_file, out_sym);
193 iglobal += 1;
194 }
185 const idx = global.outputSymtabIndex(elf_file);
186 const out_sym = &elf_file.symtab.items[idx];
187 out_sym.st_name = st_name;
188 global.setOutputSym(elf_file, out_sym);
195189 }
196190 }
197191
src/link/Elf/synthetic_sections.zig+20-20
......@@ -222,7 +222,7 @@ pub const DynamicSection = struct {
222222
223223pub const ZigGotSection = struct {
224224 entries: std.ArrayListUnmanaged(Symbol.Index) = .{},
225 output_symtab_size: Elf.SymtabSize = .{},
225 output_symtab_ctx: Elf.SymtabCtx = .{},
226226 flags: Flags = .{},
227227
228228 const Flags = packed struct {
......@@ -359,15 +359,15 @@ pub const ZigGotSection = struct {
359359 }
360360
361361 pub fn updateSymtabSize(zig_got: *ZigGotSection, elf_file: *Elf) void {
362 zig_got.output_symtab_size.nlocals = @as(u32, @intCast(zig_got.entries.items.len));
362 zig_got.output_symtab_ctx.nlocals = @as(u32, @intCast(zig_got.entries.items.len));
363363 for (zig_got.entries.items) |entry| {
364364 const name = elf_file.symbol(entry).name(elf_file);
365 zig_got.output_symtab_size.strsize += @as(u32, @intCast(name.len + "$ziggot".len)) + 1;
365 zig_got.output_symtab_ctx.strsize += @as(u32, @intCast(name.len + "$ziggot".len)) + 1;
366366 }
367367 }
368368
369 pub fn writeSymtab(zig_got: ZigGotSection, elf_file: *Elf, ctx: anytype) void {
370 for (zig_got.entries.items, ctx.ilocal.., 0..) |entry, ilocal, index| {
369 pub fn writeSymtab(zig_got: ZigGotSection, elf_file: *Elf) void {
370 for (zig_got.entries.items, zig_got.output_symtab_ctx.ilocal.., 0..) |entry, ilocal, index| {
371371 const symbol = elf_file.symbol(entry);
372372 const symbol_name = symbol.name(elf_file);
373373 const st_name = @as(u32, @intCast(elf_file.strtab.items.len));
......@@ -420,7 +420,7 @@ pub const ZigGotSection = struct {
420420
421421pub const GotSection = struct {
422422 entries: std.ArrayListUnmanaged(Entry) = .{},
423 output_symtab_size: Elf.SymtabSize = .{},
423 output_symtab_ctx: Elf.SymtabCtx = .{},
424424 tlsld_index: ?u32 = null,
425425 flags: Flags = .{},
426426
......@@ -760,18 +760,18 @@ pub const GotSection = struct {
760760 }
761761
762762 pub fn updateSymtabSize(got: *GotSection, elf_file: *Elf) void {
763 got.output_symtab_size.nlocals = @as(u32, @intCast(got.entries.items.len));
763 got.output_symtab_ctx.nlocals = @as(u32, @intCast(got.entries.items.len));
764764 for (got.entries.items) |entry| {
765765 const symbol_name = switch (entry.tag) {
766766 .tlsld => "",
767767 inline else => elf_file.symbol(entry.symbol_index).name(elf_file),
768768 };
769 got.output_symtab_size.strsize += @as(u32, @intCast(symbol_name.len + @tagName(entry.tag).len)) + 1 + 1;
769 got.output_symtab_ctx.strsize += @as(u32, @intCast(symbol_name.len + @tagName(entry.tag).len)) + 1 + 1;
770770 }
771771 }
772772
773 pub fn writeSymtab(got: GotSection, elf_file: *Elf, ctx: anytype) void {
774 for (got.entries.items, ctx.ilocal..) |entry, ilocal| {
773 pub fn writeSymtab(got: GotSection, elf_file: *Elf) void {
774 for (got.entries.items, got.output_symtab_ctx.ilocal..) |entry, ilocal| {
775775 const symbol = switch (entry.tag) {
776776 .tlsld => null,
777777 inline else => elf_file.symbol(entry.symbol_index),
......@@ -831,7 +831,7 @@ pub const GotSection = struct {
831831
832832pub const PltSection = struct {
833833 symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},
834 output_symtab_size: Elf.SymtabSize = .{},
834 output_symtab_ctx: Elf.SymtabCtx = .{},
835835
836836 pub const preamble_size = 32;
837837
......@@ -909,15 +909,15 @@ pub const PltSection = struct {
909909 }
910910
911911 pub fn updateSymtabSize(plt: *PltSection, elf_file: *Elf) void {
912 plt.output_symtab_size.nlocals = @as(u32, @intCast(plt.symbols.items.len));
912 plt.output_symtab_ctx.nlocals = @as(u32, @intCast(plt.symbols.items.len));
913913 for (plt.symbols.items) |sym_index| {
914914 const name = elf_file.symbol(sym_index).name(elf_file);
915 plt.output_symtab_size.strsize += @as(u32, @intCast(name.len + "$plt".len)) + 1;
915 plt.output_symtab_ctx.strsize += @as(u32, @intCast(name.len + "$plt".len)) + 1;
916916 }
917917 }
918918
919 pub fn writeSymtab(plt: PltSection, elf_file: *Elf, ctx: anytype) void {
920 var ilocal = ctx.ilocal;
919 pub fn writeSymtab(plt: PltSection, elf_file: *Elf) void {
920 var ilocal = plt.output_symtab_ctx.ilocal;
921921 for (plt.symbols.items) |sym_index| {
922922 const sym = elf_file.symbol(sym_index);
923923 const st_name = @as(u32, @intCast(elf_file.strtab.items.len));
......@@ -968,7 +968,7 @@ pub const GotPltSection = struct {
968968
969969pub const PltGotSection = struct {
970970 symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},
971 output_symtab_size: Elf.SymtabSize = .{},
971 output_symtab_ctx: Elf.SymtabCtx = .{},
972972
973973 pub fn deinit(plt_got: *PltGotSection, allocator: Allocator) void {
974974 plt_got.symbols.deinit(allocator);
......@@ -1008,15 +1008,15 @@ pub const PltGotSection = struct {
10081008 }
10091009
10101010 pub fn updateSymtabSize(plt_got: *PltGotSection, elf_file: *Elf) void {
1011 plt_got.output_symtab_size.nlocals = @as(u32, @intCast(plt_got.symbols.items.len));
1011 plt_got.output_symtab_ctx.nlocals = @as(u32, @intCast(plt_got.symbols.items.len));
10121012 for (plt_got.symbols.items) |sym_index| {
10131013 const name = elf_file.symbol(sym_index).name(elf_file);
1014 plt_got.output_symtab_size.strsize += @as(u32, @intCast(name.len + "$pltgot".len)) + 1;
1014 plt_got.output_symtab_ctx.strsize += @as(u32, @intCast(name.len + "$pltgot".len)) + 1;
10151015 }
10161016 }
10171017
1018 pub fn writeSymtab(plt_got: PltGotSection, elf_file: *Elf, ctx: anytype) void {
1019 var ilocal = ctx.ilocal;
1018 pub fn writeSymtab(plt_got: PltGotSection, elf_file: *Elf) void {
1019 var ilocal = plt_got.output_symtab_ctx.ilocal;
10201020 for (plt_got.symbols.items) |sym_index| {
10211021 const sym = elf_file.symbol(sym_index);
10221022 const st_name = @as(u32, @intCast(elf_file.strtab.items.len));