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,...@@ -24,6 +24,7 @@ shdr_table_offset: ?u64 = null,
24/// Table of lists of atoms per output section.24/// Table of lists of atoms per output section.
25/// This table is not used to track incrementally generated atoms.25/// This table is not used to track incrementally generated atoms.
26output_sections: std.AutoArrayHashMapUnmanaged(u16, std.ArrayListUnmanaged(Atom.Index)) = .{},26output_sections: std.AutoArrayHashMapUnmanaged(u16, std.ArrayListUnmanaged(Atom.Index)) = .{},
27output_rela_sections: std.AutoArrayHashMapUnmanaged(u16, std.ArrayListUnmanaged(Atom.Index)) = .{},
2728
28/// Stored in native-endian format, depending on target endianness needs to be bswapped on read/write.29/// Stored in native-endian format, depending on target endianness needs to be bswapped on read/write.
29/// Same order as in the file.30/// Same order as in the file.
...@@ -105,11 +106,8 @@ zig_got: ZigGotSection = .{},...@@ -105,11 +106,8 @@ zig_got: ZigGotSection = .{},
105/// Tracked section headers with incremental updates to Zig object.106/// Tracked section headers with incremental updates to Zig object.
106/// .rela.* sections are only used when emitting a relocatable object file.107/// .rela.* sections are only used when emitting a relocatable object file.
107zig_text_section_index: ?u16 = null,108zig_text_section_index: ?u16 = null,
108zig_text_rela_section_index: ?u16 = null,
109zig_data_rel_ro_section_index: ?u16 = null,109zig_data_rel_ro_section_index: ?u16 = null,
110zig_data_rel_ro_rela_section_index: ?u16 = null,
111zig_data_section_index: ?u16 = null,110zig_data_section_index: ?u16 = null,
112zig_data_rela_section_index: ?u16 = null,
113zig_bss_section_index: ?u16 = null,111zig_bss_section_index: ?u16 = null,
114zig_got_section_index: ?u16 = null,112zig_got_section_index: ?u16 = null,
115113
...@@ -357,6 +355,10 @@ pub fn deinit(self: *Elf) void {...@@ -357,6 +355,10 @@ pub fn deinit(self: *Elf) void {
357 list.deinit(gpa);355 list.deinit(gpa);
358 }356 }
359 self.output_sections.deinit(gpa);357 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);
360 self.shstrtab.deinit(gpa);362 self.shstrtab.deinit(gpa);
361 self.symtab.deinit(gpa);363 self.symtab.deinit(gpa);
362 self.strtab.deinit(gpa);364 self.strtab.deinit(gpa);
...@@ -597,10 +599,8 @@ pub fn initMetadata(self: *Elf) !void {...@@ -597,10 +599,8 @@ pub fn initMetadata(self: *Elf) !void {
597 const shdr = &self.shdrs.items[self.zig_text_section_index.?];599 const shdr = &self.shdrs.items[self.zig_text_section_index.?];
598 fillSection(self, shdr, self.base.options.program_code_size_hint, self.phdr_zig_load_re_index);600 fillSection(self, shdr, self.base.options.program_code_size_hint, self.phdr_zig_load_re_index);
599 if (self.isRelocatable()) {601 if (self.isRelocatable()) {
600 self.zig_text_rela_section_index = try self.addRelaShdr(602 const rela_shndx = try self.addRelaShdr(".rela.text.zig", self.zig_text_section_index.?);
601 ".rela.text.zig",603 try self.output_rela_sections.putNoClobber(gpa, rela_shndx, .{});
602 self.zig_text_section_index.?,
603 );
604 } else {604 } else {
605 try self.phdr_to_shdr_table.putNoClobber(605 try self.phdr_to_shdr_table.putNoClobber(
606 gpa,606 gpa,
...@@ -644,10 +644,11 @@ pub fn initMetadata(self: *Elf) !void {...@@ -644,10 +644,11 @@ pub fn initMetadata(self: *Elf) !void {
644 const shdr = &self.shdrs.items[self.zig_data_rel_ro_section_index.?];644 const shdr = &self.shdrs.items[self.zig_data_rel_ro_section_index.?];
645 fillSection(self, shdr, 1024, self.phdr_zig_load_ro_index);645 fillSection(self, shdr, 1024, self.phdr_zig_load_ro_index);
646 if (self.isRelocatable()) {646 if (self.isRelocatable()) {
647 self.zig_data_rel_ro_rela_section_index = try self.addRelaShdr(647 const rela_shndx = try self.addRelaShdr(
648 ".rela.data.rel.ro.zig",648 ".rela.data.rel.ro.zig",
649 self.zig_data_rel_ro_section_index.?,649 self.zig_data_rel_ro_section_index.?,
650 );650 );
651 try self.output_rela_sections.putNoClobber(gpa, rela_shndx, .{});
651 } else {652 } else {
652 try self.phdr_to_shdr_table.putNoClobber(653 try self.phdr_to_shdr_table.putNoClobber(
653 gpa,654 gpa,
...@@ -670,10 +671,11 @@ pub fn initMetadata(self: *Elf) !void {...@@ -670,10 +671,11 @@ pub fn initMetadata(self: *Elf) !void {
670 const shdr = &self.shdrs.items[self.zig_data_section_index.?];671 const shdr = &self.shdrs.items[self.zig_data_section_index.?];
671 fillSection(self, shdr, 1024, self.phdr_zig_load_rw_index);672 fillSection(self, shdr, 1024, self.phdr_zig_load_rw_index);
672 if (self.isRelocatable()) {673 if (self.isRelocatable()) {
673 self.zig_data_rela_section_index = try self.addRelaShdr(674 const rela_shndx = try self.addRelaShdr(
674 ".rela.data.zig",675 ".rela.data.zig",
675 self.zig_data_section_index.?,676 self.zig_data_section_index.?,
676 );677 );
678 try self.output_rela_sections.putNoClobber(gpa, rela_shndx, .{});
677 } else {679 } else {
678 try self.phdr_to_shdr_table.putNoClobber(680 try self.phdr_to_shdr_table.putNoClobber(
679 gpa,681 gpa,
...@@ -1514,16 +1516,13 @@ pub fn flushStaticLib(self: *Elf) link.File.FlushError!void {...@@ -1514,16 +1516,13 @@ pub fn flushStaticLib(self: *Elf) link.File.FlushError!void {
1514 try self.initSymtab();1516 try self.initSymtab();
1515 try self.initShStrtab();1517 try self.initShStrtab();
1516 try self.sortShdrs();1518 try self.sortShdrs();
1517 zig_object.updateRelaSectionsSizes(self);1519 try zig_object.addAtomsToRelaSections(self);
1518 self.updateSymtabSizeZigObject(zig_object);1520 try self.updateSectionSizesObject();
1519 self.updateShStrtabSize();
15201521
1521 try self.allocateNonAllocSections();1522 try self.allocateNonAllocSections();
15221523
1523 try self.writeShdrTable();1524 try self.writeShdrTable();
1524 try zig_object.writeRelaSections(self);1525 try self.writeSyntheticSectionsObject();
1525 try self.writeSymtabZigObject(zig_object);
1526 try self.writeShStrtab();
1527 try self.writeElfHeader();1526 try self.writeElfHeader();
1528 }1527 }
15291528
...@@ -1620,7 +1619,9 @@ pub fn flushObject(self: *Elf) link.File.FlushError!void {...@@ -1620,7 +1619,9 @@ pub fn flushObject(self: *Elf) link.File.FlushError!void {
1620 try self.initSectionsObject();1619 try self.initSectionsObject();
1621 try self.sortShdrs();1620 try self.sortShdrs();
1622 for (self.objects.items) |index| {1621 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);
1624 }1625 }
1625 try self.updateSectionSizesObject();1626 try self.updateSectionSizesObject();
16261627
...@@ -3452,7 +3453,7 @@ fn initSectionsObject(self: *Elf) !void {...@@ -3452,7 +3453,7 @@ fn initSectionsObject(self: *Elf) !void {
3452 .addralign = ptr_size,3453 .addralign = ptr_size,
3453 .offset = std.math.maxInt(u64),3454 .offset = std.math.maxInt(u64),
3454 });3455 });
3455 _ = try self.addRelaShdr(".rela.eh_frame", self.eh_frame_section_index.?);3456 // _ = try self.addRelaShdr(".rela.eh_frame", self.eh_frame_section_index.?);
3456 }3457 }
34573458
3458 try self.initSymtab();3459 try self.initSymtab();
...@@ -3841,12 +3842,9 @@ fn sortShdrs(self: *Elf) !void {...@@ -3841,12 +3842,9 @@ fn sortShdrs(self: *Elf) !void {
3841 &self.versym_section_index,3842 &self.versym_section_index,
3842 &self.verneed_section_index,3843 &self.verneed_section_index,
3843 &self.zig_text_section_index,3844 &self.zig_text_section_index,
3844 &self.zig_text_rela_section_index,
3845 &self.zig_got_section_index,3845 &self.zig_got_section_index,
3846 &self.zig_data_rel_ro_section_index,3846 &self.zig_data_rel_ro_section_index,
3847 &self.zig_data_rel_ro_rela_section_index,
3848 &self.zig_data_section_index,3847 &self.zig_data_section_index,
3849 &self.zig_data_rela_section_index,
3850 &self.zig_bss_section_index,3848 &self.zig_bss_section_index,
3851 &self.debug_str_section_index,3849 &self.debug_str_section_index,
3852 &self.debug_info_section_index,3850 &self.debug_info_section_index,
...@@ -4066,7 +4064,7 @@ fn updateSectionSizes(self: *Elf) !void {...@@ -4066,7 +4064,7 @@ fn updateSectionSizes(self: *Elf) !void {
4066 self.shdrs.items[index].sh_size = self.verneed.size();4064 self.shdrs.items[index].sh_size = self.verneed.size();
4067 }4065 }
40684066
4069 self.updateSymtabSize();4067 try self.updateSymtabSize();
4070 self.updateShStrtabSize();4068 self.updateShStrtabSize();
4071}4069}
40724070
...@@ -4084,19 +4082,21 @@ fn updateSectionSizesObject(self: *Elf) !void {...@@ -4084,19 +4082,21 @@ fn updateSectionSizesObject(self: *Elf) !void {
4084 }4082 }
4085 }4083 }
40864084
4087 if (self.zigObjectPtr()) |zig_object| {4085 for (self.output_rela_sections.keys(), self.output_rela_sections.values()) |shndx, atom_list| {
4088 zig_object.updateRelaSectionsSizes(self);4086 const shdr = &self.shdrs.items[shndx];
4089 }4087 for (atom_list.items) |atom_index| {
40904088 const atom_ptr = self.atom(atom_index) orelse continue;
4091 for (self.objects.items) |index| {4089 if (!atom_ptr.flags.alive) continue;
4092 self.file(index).?.object.updateRelaSectionsSizes(self);4090 const relocs = atom_ptr.relocs(self);
4091 shdr.sh_size += shdr.sh_entsize * relocs.len;
4092 }
4093 }4093 }
40944094
4095 if (self.eh_frame_section_index) |index| {4095 if (self.eh_frame_section_index) |index| {
4096 self.shdrs.items[index].sh_size = try eh_frame.calcEhFrameSize(self);4096 self.shdrs.items[index].sh_size = try eh_frame.calcEhFrameSize(self);
4097 }4097 }
40984098
4099 self.updateSymtabSize();4099 try self.updateSymtabSize();
4100 self.updateShStrtabSize();4100 self.updateShStrtabSize();
4101}4101}
41024102
...@@ -4597,96 +4597,123 @@ fn writeAtomsObject(self: *Elf) !void {...@@ -4597,96 +4597,123 @@ fn writeAtomsObject(self: *Elf) !void {
4597 }4597 }
4598}4598}
45994599
4600fn updateSymtabSize(self: *Elf) void {4600fn updateSymtabSize(self: *Elf) !void {
4601 var sizes = SymtabSize{};4601 var nlocals: u32 = 0;
4602 var nglobals: u32 = 0;
4603 var strsize: u32 = 0;
46024604
4603 if (self.zigObjectPtr()) |zig_object| {4605 const gpa = self.base.allocator;
4604 zig_object.asFile().updateSymtabSize(self);4606 var files = std.ArrayList(File.Index).init(gpa);
4605 sizes.add(zig_object.output_symtab_size);4607 defer files.deinit();
4606 }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);
4608 for (self.objects.items) |index| {4611 for (self.objects.items) |index| {
4609 const file_ptr = self.file(index).?;4612 files.appendAssumeCapacity(index);
4610 file_ptr.updateSymtabSize(self);
4611 sizes.add(file_ptr.object.output_symtab_size);
4612 }4613 }
4613
4614 for (self.shared_objects.items) |index| {4614 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| {
4615 const file_ptr = self.file(index).?;4624 const file_ptr = self.file(index).?;
4616 file_ptr.updateSymtabSize(self);4625 const ctx = switch (file_ptr) {
4617 sizes.add(file_ptr.shared_object.output_symtab_size);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;
4618 }4634 }
46194635
4620 if (self.zig_got_section_index) |_| {4636 if (self.zig_got_section_index) |_| {
4637 self.zig_got.output_symtab_ctx.ilocal = nlocals + 1;
4621 self.zig_got.updateSymtabSize(self);4638 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;
4623 }4641 }
46244642
4625 if (self.got_section_index) |_| {4643 if (self.got_section_index) |_| {
4644 self.got.output_symtab_ctx.ilocal = nlocals + 1;
4626 self.got.updateSymtabSize(self);4645 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;
4628 }4648 }
46294649
4630 if (self.plt_section_index) |_| {4650 if (self.plt_section_index) |_| {
4651 self.plt.output_symtab_ctx.ilocal = nlocals + 1;
4631 self.plt.updateSymtabSize(self);4652 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;
4633 }4655 }
46344656
4635 if (self.plt_got_section_index) |_| {4657 if (self.plt_got_section_index) |_| {
4658 self.plt_got.output_symtab_ctx.ilocal = nlocals + 1;
4636 self.plt_got.updateSymtabSize(self);4659 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;
4638 }4662 }
46394663
4640 if (self.linker_defined_index) |index| {4664 for (files.items) |index| {
4641 const file_ptr = self.file(index).?;4665 const file_ptr = self.file(index).?;
4642 file_ptr.updateSymtabSize(self);4666 const ctx = switch (file_ptr) {
4643 sizes.add(file_ptr.linker_defined.output_symtab_size);4667 inline else => |x| &x.output_symtab_ctx,
4644 }4668 };
46454669 ctx.iglobal += nlocals;
4646 // Section symbols
4647 for (self.output_sections.keys()) |_| {
4648 sizes.nlocals += 1;
4649 }4670 }
46504671
4651 const symtab_shdr = &self.shdrs.items[self.symtab_section_index.?];4672 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;
4653 symtab_shdr.sh_link = self.strtab_section_index.?;4674 symtab_shdr.sh_link = self.strtab_section_index.?;
46544675
4655 const sym_size: u64 = switch (self.ptr_width) {4676 const sym_size: u64 = switch (self.ptr_width) {
4656 .p32 => @sizeOf(elf.Elf32_Sym),4677 .p32 => @sizeOf(elf.Elf32_Sym),
4657 .p64 => @sizeOf(elf.Elf64_Sym),4678 .p64 => @sizeOf(elf.Elf64_Sym),
4658 };4679 };
4659 const needed_size = (sizes.nlocals + sizes.nglobals + 1) * sym_size;4680 const needed_size = (nlocals + nglobals + 1) * sym_size;
4660 symtab_shdr.sh_size = needed_size;4681 symtab_shdr.sh_size = needed_size;
46614682
4662 const strtab = &self.shdrs.items[self.strtab_section_index.?];4683 const strtab = &self.shdrs.items[self.strtab_section_index.?];
4663 strtab.sh_size = sizes.strsize + 1;4684 strtab.sh_size = strsize + 1;
4664}4685}
46654686
4666fn updateSymtabSizeZigObject(self: *Elf, zig_object: *ZigObject) void {4687fn updateSymtabSizeZigObject(self: *Elf, zig_object: *ZigObject) void {
4667 var sizes = SymtabSize{};4688 var nlocals: u32 = 0;
46684689 var nglobals: u32 = 0;
4669 zig_object.asFile().updateSymtabSize(self);4690 var strsize: u32 = 0;
4670 sizes.add(zig_object.output_symtab_size);
46714691
4672 // Section symbols4692 // Section symbols
4673 for (self.output_sections.keys()) |_| {4693 for (self.output_sections.keys()) |_| {
4674 sizes.nlocals += 1;4694 nlocals += 1;
4675 }4695 }
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
4677 const symtab_shdr = &self.shdrs.items[self.symtab_section_index.?];4704 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;
4679 symtab_shdr.sh_link = self.strtab_section_index.?;4706 symtab_shdr.sh_link = self.strtab_section_index.?;
46804707
4681 const sym_size: u64 = switch (self.ptr_width) {4708 const sym_size: u64 = switch (self.ptr_width) {
4682 .p32 => @sizeOf(elf.Elf32_Sym),4709 .p32 => @sizeOf(elf.Elf32_Sym),
4683 .p64 => @sizeOf(elf.Elf64_Sym),4710 .p64 => @sizeOf(elf.Elf64_Sym),
4684 };4711 };
4685 const needed_size = (sizes.nlocals + sizes.nglobals + 1) * sym_size;4712 const needed_size = (nlocals + nglobals + 1) * sym_size;
4686 symtab_shdr.sh_size = needed_size;4713 symtab_shdr.sh_size = needed_size;
46874714
4688 const strtab = &self.shdrs.items[self.strtab_section_index.?];4715 const strtab = &self.shdrs.items[self.strtab_section_index.?];
4689 strtab.sh_size = sizes.strsize + 1;4716 strtab.sh_size = strsize + 1;
4690}4717}
46914718
4692fn writeSyntheticSections(self: *Elf) !void {4719fn writeSyntheticSections(self: *Elf) !void {
...@@ -4822,12 +4849,31 @@ fn writeSyntheticSections(self: *Elf) !void {...@@ -4822,12 +4849,31 @@ fn writeSyntheticSections(self: *Elf) !void {
4822fn writeSyntheticSectionsObject(self: *Elf) !void {4849fn writeSyntheticSectionsObject(self: *Elf) !void {
4823 const gpa = self.base.allocator;4850 const gpa = self.base.allocator;
48244851
4825 if (self.zigObjectPtr()) |zig_object| {4852 for (self.output_rela_sections.keys(), self.output_rela_sections.values()) |shndx, atom_list| {
4826 try zig_object.writeRelaSections(self);4853 if (atom_list.items.len == 0) continue;
4827 }
48284854
4829 for (self.objects.items) |index| {4855 const shdr = self.shdrs.items[shndx];
4830 try self.file(index).?.object.writeRelaSections(self);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);
4831 }4877 }
48324878
4833 if (self.eh_frame_section_index) |shndx| {4879 if (self.eh_frame_section_index) |shndx| {
...@@ -4836,7 +4882,7 @@ fn writeSyntheticSectionsObject(self: *Elf) !void {...@@ -4836,7 +4882,7 @@ fn writeSyntheticSectionsObject(self: *Elf) !void {
4836 var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size);4882 var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size);
4837 defer buffer.deinit();4883 defer buffer.deinit();
4838 try eh_frame.writeEhFrame(self, buffer.writer());4884 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);
4840 }4886 }
48414887
4842 try self.writeSymtab();4888 try self.writeSymtab();
...@@ -4850,16 +4896,6 @@ fn writeShStrtab(self: *Elf) !void {...@@ -4850,16 +4896,6 @@ fn writeShStrtab(self: *Elf) !void {
4850 }4896 }
4851}4897}
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
4863fn writeSymtab(self: *Elf) !void {4899fn writeSymtab(self: *Elf) !void {
4864 const gpa = self.base.allocator;4900 const gpa = self.base.allocator;
4865 const symtab_shdr = self.shdrs.items[self.symtab_section_index.?];4901 const symtab_shdr = self.shdrs.items[self.symtab_section_index.?];
...@@ -4876,54 +4912,41 @@ fn writeSymtab(self: *Elf) !void {...@@ -4876,54 +4912,41 @@ fn writeSymtab(self: *Elf) !void {
4876 const needed_strtab_size = math.cast(usize, strtab_shdr.sh_size - 1) orelse return error.Overflow;4912 const needed_strtab_size = math.cast(usize, strtab_shdr.sh_size - 1) orelse return error.Overflow;
4877 try self.strtab.ensureUnusedCapacity(gpa, needed_strtab_size);4913 try self.strtab.ensureUnusedCapacity(gpa, needed_strtab_size);
48784914
4879 var ctx: WriteSymtabCtx = .{4915 self.writeSectionSymbols();
4880 .ilocal = 1,
4881 .iglobal = symtab_shdr.sh_info,
4882 };
4883
4884 ctx.incr(self.writeSectionSymbols(ctx));
48854916
4886 if (self.zigObjectPtr()) |zig_object| {4917 if (self.zigObjectPtr()) |zig_object| {
4887 zig_object.asFile().writeSymtab(self, ctx);4918 zig_object.asFile().writeSymtab(self);
4888 ctx.incr(zig_object.output_symtab_size);
4889 }4919 }
48904920
4891 for (self.objects.items) |index| {4921 for (self.objects.items) |index| {
4892 const file_ptr = self.file(index).?;4922 const file_ptr = self.file(index).?;
4893 file_ptr.writeSymtab(self, ctx);4923 file_ptr.writeSymtab(self);
4894 ctx.incr(file_ptr.object.output_symtab_size);
4895 }4924 }
48964925
4897 for (self.shared_objects.items) |index| {4926 for (self.shared_objects.items) |index| {
4898 const file_ptr = self.file(index).?;4927 const file_ptr = self.file(index).?;
4899 file_ptr.writeSymtab(self, ctx);4928 file_ptr.writeSymtab(self);
4900 ctx.incr(file_ptr.shared_object.output_symtab_size);
4901 }4929 }
49024930
4903 if (self.zig_got_section_index) |_| {4931 if (self.zig_got_section_index) |_| {
4904 self.zig_got.writeSymtab(self, ctx);4932 self.zig_got.writeSymtab(self);
4905 ctx.incr(self.zig_got.output_symtab_size);
4906 }4933 }
49074934
4908 if (self.got_section_index) |_| {4935 if (self.got_section_index) |_| {
4909 self.got.writeSymtab(self, ctx);4936 self.got.writeSymtab(self);
4910 ctx.incr(self.got.output_symtab_size);
4911 }4937 }
49124938
4913 if (self.plt_section_index) |_| {4939 if (self.plt_section_index) |_| {
4914 self.plt.writeSymtab(self, ctx);4940 self.plt.writeSymtab(self);
4915 ctx.incr(self.plt.output_symtab_size);
4916 }4941 }
49174942
4918 if (self.plt_got_section_index) |_| {4943 if (self.plt_got_section_index) |_| {
4919 self.plt_got.writeSymtab(self, ctx);4944 self.plt_got.writeSymtab(self);
4920 ctx.incr(self.plt_got.output_symtab_size);
4921 }4945 }
49224946
4923 if (self.linker_defined_index) |index| {4947 if (self.linker_defined_index) |index| {
4924 const file_ptr = self.file(index).?;4948 const file_ptr = self.file(index).?;
4925 file_ptr.writeSymtab(self, ctx);4949 file_ptr.writeSymtab(self);
4926 ctx.incr(file_ptr.linker_defined.output_symtab_size);
4927 }4950 }
49284951
4929 const foreign_endian = self.base.options.target.cpu.arch.endian() != builtin.cpu.arch.endian();4952 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 {...@@ -4972,15 +4995,8 @@ fn writeSymtabZigObject(self: *Elf, zig_object: *ZigObject) !void {
4972 const needed_strtab_size = math.cast(usize, strtab_shdr.sh_size - 1) orelse return error.Overflow;4995 const needed_strtab_size = math.cast(usize, strtab_shdr.sh_size - 1) orelse return error.Overflow;
4973 try self.strtab.ensureUnusedCapacity(gpa, needed_strtab_size);4996 try self.strtab.ensureUnusedCapacity(gpa, needed_strtab_size);
49744997
4975 var ctx: WriteSymtabCtx = .{4998 self.writeSectionSymbols();
4976 .ilocal = 1,4999 zig_object.asFile().writeSymtab(self);
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);
49845000
4985 const foreign_endian = self.base.options.target.cpu.arch.endian() != builtin.cpu.arch.endian();5001 const foreign_endian = self.base.options.target.cpu.arch.endian() != builtin.cpu.arch.endian();
4986 switch (self.ptr_width) {5002 switch (self.ptr_width) {
...@@ -5012,8 +5028,8 @@ fn writeSymtabZigObject(self: *Elf, zig_object: *ZigObject) !void {...@@ -5012,8 +5028,8 @@ fn writeSymtabZigObject(self: *Elf, zig_object: *ZigObject) !void {
5012 try self.base.file.?.pwriteAll(self.strtab.items, strtab_shdr.sh_offset);5028 try self.base.file.?.pwriteAll(self.strtab.items, strtab_shdr.sh_offset);
5013}5029}
50145030
5015fn writeSectionSymbols(self: *Elf, ctx: WriteSymtabCtx) SymtabSize {5031fn writeSectionSymbols(self: *Elf) void {
5016 var ilocal = ctx.ilocal;5032 var ilocal: u32 = 1;
5017 for (self.output_sections.keys()) |shndx| {5033 for (self.output_sections.keys()) |shndx| {
5018 const shdr = self.shdrs.items[shndx];5034 const shdr = self.shdrs.items[shndx];
5019 const out_sym = &self.symtab.items[ilocal];5035 const out_sym = &self.symtab.items[ilocal];
...@@ -5027,7 +5043,6 @@ fn writeSectionSymbols(self: *Elf, ctx: WriteSymtabCtx) SymtabSize {...@@ -5027,7 +5043,6 @@ fn writeSectionSymbols(self: *Elf, ctx: WriteSymtabCtx) SymtabSize {
5027 };5043 };
5028 ilocal += 1;5044 ilocal += 1;
5029 }5045 }
5030 return .{ .nlocals = @intCast(ilocal - ctx.ilocal) };
5031}5046}
50325047
5033/// Always 4 or 8 depending on whether this is 32-bit ELF or 64-bit ELF.5048/// Always 4 or 8 depending on whether this is 32-bit ELF or 64-bit ELF.
...@@ -6056,16 +6071,12 @@ pub const ComdatGroup = struct {...@@ -6056,16 +6071,12 @@ pub const ComdatGroup = struct {
6056 pub const Index = u32;6071 pub const Index = u32;
6057};6072};
60586073
6059pub const SymtabSize = struct {6074pub const SymtabCtx = struct {
6075 ilocal: u32 = 0,
6076 iglobal: u32 = 0,
6060 nlocals: u32 = 0,6077 nlocals: u32 = 0,
6061 nglobals: u32 = 0,6078 nglobals: u32 = 0,
6062 strsize: u32 = 0,6079 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 }
6069};6080};
60706081
6071pub const null_sym = elf.Elf64_Sym{6082pub 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 {...@@ -293,6 +293,32 @@ pub fn relocs(self: Atom, elf_file: *Elf) []align(1) const elf.Elf64_Rela {
293 };293 };
294}294}
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
296pub fn fdes(self: Atom, elf_file: *Elf) []Fde {322pub fn fdes(self: Atom, elf_file: *Elf) []Fde {
297 if (self.fde_start == self.fde_end) return &[0]Fde{};323 if (self.fde_start == self.fde_end) return &[0]Fde{};
298 const object = self.file(elf_file).?.object;324 const object = self.file(elf_file).?.object;
src/link/Elf/LinkerDefined.zig+1-1
...@@ -3,7 +3,7 @@ symtab: std.ArrayListUnmanaged(elf.Elf64_Sym) = .{},...@@ -3,7 +3,7 @@ symtab: std.ArrayListUnmanaged(elf.Elf64_Sym) = .{},
3strtab: std.ArrayListUnmanaged(u8) = .{},3strtab: std.ArrayListUnmanaged(u8) = .{},
4symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},4symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},
55
6output_symtab_size: Elf.SymtabSize = .{},6output_symtab_ctx: Elf.SymtabCtx = .{},
77
8pub fn deinit(self: *LinkerDefined, allocator: Allocator) void {8pub fn deinit(self: *LinkerDefined, allocator: Allocator) void {
9 self.symtab.deinit(allocator);9 self.symtab.deinit(allocator);
src/link/Elf/Object.zig+7-10
...@@ -19,7 +19,7 @@ cies: std.ArrayListUnmanaged(Cie) = .{},...@@ -19,7 +19,7 @@ cies: std.ArrayListUnmanaged(Cie) = .{},
19alive: bool = true,19alive: bool = true,
20num_dynrelocs: u32 = 0,20num_dynrelocs: u32 = 0,
2121
22output_symtab_size: Elf.SymtabSize = .{},22output_symtab_ctx: Elf.SymtabCtx = .{},
23output_ar_state: Archive.ArState = .{},23output_ar_state: Archive.ArState = .{},
2424
25pub fn isObject(path: []const u8) !bool {25pub fn isObject(path: []const u8) !bool {
...@@ -672,22 +672,19 @@ pub fn initRelaSections(self: Object, elf_file: *Elf) !void {...@@ -672,22 +672,19 @@ pub fn initRelaSections(self: Object, elf_file: *Elf) !void {
672 }672 }
673}673}
674674
675pub fn updateRelaSectionsSizes(self: Object, elf_file: *Elf) void {675pub fn addAtomsToRelaSections(self: Object, elf_file: *Elf) !void {
676 for (self.atoms.items) |atom_index| {676 for (self.atoms.items) |atom_index| {
677 const atom = elf_file.atom(atom_index) orelse continue;677 const atom = elf_file.atom(atom_index) orelse continue;
678 if (!atom.flags.alive) continue;678 if (!atom.flags.alive) continue;
679 const shndx = atom.relocsShndx() orelse continue;679 const shndx = atom.relocsShndx() orelse continue;
680 const shdr = self.shdrs.items[shndx];680 const shdr = self.shdrs.items[shndx];
681 const out_shndx = self.initOutputSection(elf_file, shdr) catch unreachable;681 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 {683 const gpa = elf_file.base.allocator;
689 _ = self;684 const gop = try elf_file.output_rela_sections.getOrPut(gpa, out_shndx);
690 _ = elf_file;685 if (!gop.found_existing) gop.value_ptr.* = .{};
686 try gop.value_ptr.append(gpa, atom_index);
687 }
691}688}
692689
693pub fn updateArSymtab(self: Object, ar_symtab: *Archive.ArSymtab, elf_file: *Elf) !void {690pub 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,...@@ -21,7 +21,7 @@ verdef_sect_index: ?u16 = null,
21needed: bool,21needed: bool,
22alive: bool,22alive: bool,
2323
24output_symtab_size: Elf.SymtabSize = .{},24output_symtab_ctx: Elf.SymtabCtx = .{},
2525
26pub fn isSharedObject(path: []const u8) !bool {26pub fn isSharedObject(path: []const u8) !bool {
27 const file = try std.fs.cwd().openFile(path, .{});27 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...@@ -107,6 +107,24 @@ pub fn address(symbol: Symbol, opts: struct { plt: bool = true }, elf_file: *Elf
107 return symbol.value;107 return symbol.value;
108}108}
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
110pub fn gotAddress(symbol: Symbol, elf_file: *Elf) u64 {128pub fn gotAddress(symbol: Symbol, elf_file: *Elf) u64 {
111 if (!symbol.flags.has_got) return 0;129 if (!symbol.flags.has_got) return 0;
112 const extras = symbol.extra(elf_file).?;130 const extras = symbol.extra(elf_file).?;
...@@ -388,6 +406,7 @@ pub const Extra = struct {...@@ -388,6 +406,7 @@ pub const Extra = struct {
388 plt: u32 = 0,406 plt: u32 = 0,
389 plt_got: u32 = 0,407 plt_got: u32 = 0,
390 dynamic: u32 = 0,408 dynamic: u32 = 0,
409 symtab: u32 = 0,
391 copy_rel: u32 = 0,410 copy_rel: u32 = 0,
392 tlsgd: u32 = 0,411 tlsgd: u32 = 0,
393 gottp: u32 = 0,412 gottp: u32 = 0,
src/link/Elf/ZigObject.zig+11-88
...@@ -18,7 +18,7 @@ relocs: std.ArrayListUnmanaged(std.ArrayListUnmanaged(elf.Elf64_Rela)) = .{},...@@ -18,7 +18,7 @@ relocs: std.ArrayListUnmanaged(std.ArrayListUnmanaged(elf.Elf64_Rela)) = .{},
1818
19num_dynrelocs: u32 = 0,19num_dynrelocs: u32 = 0,
2020
21output_symtab_size: Elf.SymtabSize = .{},21output_symtab_ctx: Elf.SymtabCtx = .{},
22output_ar_state: Archive.ArState = .{},22output_ar_state: Archive.ArState = .{},
2323
24dwarf: ?Dwarf = null,24dwarf: ?Dwarf = null,
...@@ -533,94 +533,17 @@ pub fn writeAr(self: ZigObject, elf_file: *Elf, writer: anytype) !void {...@@ -533,94 +533,17 @@ pub fn writeAr(self: ZigObject, elf_file: *Elf, writer: anytype) !void {
533 try writer.writeAll(contents);533 try writer.writeAll(contents);
534}534}
535535
536pub fn updateRelaSectionsSizes(self: ZigObject, elf_file: *Elf) void {536pub fn addAtomsToRelaSections(self: ZigObject, elf_file: *Elf) !void {
537 _ = self;537 for (self.atoms.items) |atom_index| {
538538 const atom = elf_file.atom(atom_index) orelse continue;
539 for (&[_]?u16{539 if (!atom.flags.alive) continue;
540 elf_file.zig_text_rela_section_index,540 _ = atom.relocsShndx() orelse continue;
541 elf_file.zig_data_rel_ro_rela_section_index,541 const out_shndx = atom.outputShndx().?;
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);
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);
624 }547 }
625}548}
626549
src/link/Elf/file.zig+18-24
...@@ -127,9 +127,9 @@ pub const File = union(enum) {...@@ -127,9 +127,9 @@ pub const File = union(enum) {
127 };127 };
128 }128 }
129129
130 pub fn updateSymtabSize(file: File, elf_file: *Elf) void {130 pub fn updateSymtabSize(file: File, elf_file: *Elf) !void {
131 const output_symtab_size = switch (file) {131 const output_symtab_ctx = switch (file) {
132 inline else => |x| &x.output_symtab_size,132 inline else => |x| &x.output_symtab_ctx,
133 };133 };
134 for (file.locals()) |local_index| {134 for (file.locals()) |local_index| {
135 const local = elf_file.symbol(local_index);135 const local = elf_file.symbol(local_index);
...@@ -140,8 +140,9 @@ pub const File = union(enum) {...@@ -140,8 +140,9 @@ pub const File = union(enum) {
140 else => {},140 else => {},
141 }141 }
142 local.flags.output_symtab = true;142 local.flags.output_symtab = true;
143 output_symtab_size.nlocals += 1;143 try local.setOutputSymtabIndex(output_symtab_ctx.nlocals, elf_file);
144 output_symtab_size.strsize += @as(u32, @intCast(local.name(elf_file).len)) + 1;144 output_symtab_ctx.nlocals += 1;
145 output_symtab_ctx.strsize += @as(u32, @intCast(local.name(elf_file).len)) + 1;
145 }146 }
146147
147 for (file.globals()) |global_index| {148 for (file.globals()) |global_index| {
...@@ -151,28 +152,28 @@ pub const File = union(enum) {...@@ -151,28 +152,28 @@ pub const File = union(enum) {
151 if (global.atom(elf_file)) |atom| if (!atom.flags.alive) continue;152 if (global.atom(elf_file)) |atom| if (!atom.flags.alive) continue;
152 global.flags.output_symtab = true;153 global.flags.output_symtab = true;
153 if (global.isLocal(elf_file)) {154 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;
155 } else {157 } else {
156 output_symtab_size.nglobals += 1;158 try global.setOutputSymtabIndex(output_symtab_ctx.nglobals, elf_file);
159 output_symtab_ctx.nglobals += 1;
157 }160 }
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;
159 }162 }
160 }163 }
161164
162 pub fn writeSymtab(file: File, elf_file: *Elf, ctx: anytype) void {165 pub fn writeSymtab(file: File, elf_file: *Elf) void {
163 var ilocal: usize = ctx.ilocal;
164 for (file.locals()) |local_index| {166 for (file.locals()) |local_index| {
165 const local = elf_file.symbol(local_index);167 const local = elf_file.symbol(local_index);
166 if (!local.flags.output_symtab) continue;168 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];
168 out_sym.st_name = @intCast(elf_file.strtab.items.len);171 out_sym.st_name = @intCast(elf_file.strtab.items.len);
169 elf_file.strtab.appendSliceAssumeCapacity(local.name(elf_file));172 elf_file.strtab.appendSliceAssumeCapacity(local.name(elf_file));
170 elf_file.strtab.appendAssumeCapacity(0);173 elf_file.strtab.appendAssumeCapacity(0);
171 local.setOutputSym(elf_file, out_sym);174 local.setOutputSym(elf_file, out_sym);
172 ilocal += 1;
173 }175 }
174176
175 var iglobal: usize = ctx.iglobal;
176 for (file.globals()) |global_index| {177 for (file.globals()) |global_index| {
177 const global = elf_file.symbol(global_index);178 const global = elf_file.symbol(global_index);
178 const file_ptr = global.file(elf_file) orelse continue;179 const file_ptr = global.file(elf_file) orelse continue;
...@@ -181,17 +182,10 @@ pub const File = union(enum) {...@@ -181,17 +182,10 @@ pub const File = union(enum) {
181 const st_name = @as(u32, @intCast(elf_file.strtab.items.len));182 const st_name = @as(u32, @intCast(elf_file.strtab.items.len));
182 elf_file.strtab.appendSliceAssumeCapacity(global.name(elf_file));183 elf_file.strtab.appendSliceAssumeCapacity(global.name(elf_file));
183 elf_file.strtab.appendAssumeCapacity(0);184 elf_file.strtab.appendAssumeCapacity(0);
184 if (global.isLocal(elf_file)) {185 const idx = global.outputSymtabIndex(elf_file);
185 const out_sym = &elf_file.symtab.items[ilocal];186 const out_sym = &elf_file.symtab.items[idx];
186 out_sym.st_name = st_name;187 out_sym.st_name = st_name;
187 global.setOutputSym(elf_file, out_sym);188 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 }
195 }189 }
196 }190 }
197191
src/link/Elf/synthetic_sections.zig+20-20
...@@ -222,7 +222,7 @@ pub const DynamicSection = struct {...@@ -222,7 +222,7 @@ pub const DynamicSection = struct {
222222
223pub const ZigGotSection = struct {223pub const ZigGotSection = struct {
224 entries: std.ArrayListUnmanaged(Symbol.Index) = .{},224 entries: std.ArrayListUnmanaged(Symbol.Index) = .{},
225 output_symtab_size: Elf.SymtabSize = .{},225 output_symtab_ctx: Elf.SymtabCtx = .{},
226 flags: Flags = .{},226 flags: Flags = .{},
227227
228 const Flags = packed struct {228 const Flags = packed struct {
...@@ -359,15 +359,15 @@ pub const ZigGotSection = struct {...@@ -359,15 +359,15 @@ pub const ZigGotSection = struct {
359 }359 }
360360
361 pub fn updateSymtabSize(zig_got: *ZigGotSection, elf_file: *Elf) void {361 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));
363 for (zig_got.entries.items) |entry| {363 for (zig_got.entries.items) |entry| {
364 const name = elf_file.symbol(entry).name(elf_file);364 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;
366 }366 }
367 }367 }
368368
369 pub fn writeSymtab(zig_got: ZigGotSection, elf_file: *Elf, ctx: anytype) void {369 pub fn writeSymtab(zig_got: ZigGotSection, elf_file: *Elf) void {
370 for (zig_got.entries.items, ctx.ilocal.., 0..) |entry, ilocal, index| {370 for (zig_got.entries.items, zig_got.output_symtab_ctx.ilocal.., 0..) |entry, ilocal, index| {
371 const symbol = elf_file.symbol(entry);371 const symbol = elf_file.symbol(entry);
372 const symbol_name = symbol.name(elf_file);372 const symbol_name = symbol.name(elf_file);
373 const st_name = @as(u32, @intCast(elf_file.strtab.items.len));373 const st_name = @as(u32, @intCast(elf_file.strtab.items.len));
...@@ -420,7 +420,7 @@ pub const ZigGotSection = struct {...@@ -420,7 +420,7 @@ pub const ZigGotSection = struct {
420420
421pub const GotSection = struct {421pub const GotSection = struct {
422 entries: std.ArrayListUnmanaged(Entry) = .{},422 entries: std.ArrayListUnmanaged(Entry) = .{},
423 output_symtab_size: Elf.SymtabSize = .{},423 output_symtab_ctx: Elf.SymtabCtx = .{},
424 tlsld_index: ?u32 = null,424 tlsld_index: ?u32 = null,
425 flags: Flags = .{},425 flags: Flags = .{},
426426
...@@ -760,18 +760,18 @@ pub const GotSection = struct {...@@ -760,18 +760,18 @@ pub const GotSection = struct {
760 }760 }
761761
762 pub fn updateSymtabSize(got: *GotSection, elf_file: *Elf) void {762 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));
764 for (got.entries.items) |entry| {764 for (got.entries.items) |entry| {
765 const symbol_name = switch (entry.tag) {765 const symbol_name = switch (entry.tag) {
766 .tlsld => "",766 .tlsld => "",
767 inline else => elf_file.symbol(entry.symbol_index).name(elf_file),767 inline else => elf_file.symbol(entry.symbol_index).name(elf_file),
768 };768 };
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;
770 }770 }
771 }771 }
772772
773 pub fn writeSymtab(got: GotSection, elf_file: *Elf, ctx: anytype) void {773 pub fn writeSymtab(got: GotSection, elf_file: *Elf) void {
774 for (got.entries.items, ctx.ilocal..) |entry, ilocal| {774 for (got.entries.items, got.output_symtab_ctx.ilocal..) |entry, ilocal| {
775 const symbol = switch (entry.tag) {775 const symbol = switch (entry.tag) {
776 .tlsld => null,776 .tlsld => null,
777 inline else => elf_file.symbol(entry.symbol_index),777 inline else => elf_file.symbol(entry.symbol_index),
...@@ -831,7 +831,7 @@ pub const GotSection = struct {...@@ -831,7 +831,7 @@ pub const GotSection = struct {
831831
832pub const PltSection = struct {832pub const PltSection = struct {
833 symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},833 symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},
834 output_symtab_size: Elf.SymtabSize = .{},834 output_symtab_ctx: Elf.SymtabCtx = .{},
835835
836 pub const preamble_size = 32;836 pub const preamble_size = 32;
837837
...@@ -909,15 +909,15 @@ pub const PltSection = struct {...@@ -909,15 +909,15 @@ pub const PltSection = struct {
909 }909 }
910910
911 pub fn updateSymtabSize(plt: *PltSection, elf_file: *Elf) void {911 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));
913 for (plt.symbols.items) |sym_index| {913 for (plt.symbols.items) |sym_index| {
914 const name = elf_file.symbol(sym_index).name(elf_file);914 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;
916 }916 }
917 }917 }
918918
919 pub fn writeSymtab(plt: PltSection, elf_file: *Elf, ctx: anytype) void {919 pub fn writeSymtab(plt: PltSection, elf_file: *Elf) void {
920 var ilocal = ctx.ilocal;920 var ilocal = plt.output_symtab_ctx.ilocal;
921 for (plt.symbols.items) |sym_index| {921 for (plt.symbols.items) |sym_index| {
922 const sym = elf_file.symbol(sym_index);922 const sym = elf_file.symbol(sym_index);
923 const st_name = @as(u32, @intCast(elf_file.strtab.items.len));923 const st_name = @as(u32, @intCast(elf_file.strtab.items.len));
...@@ -968,7 +968,7 @@ pub const GotPltSection = struct {...@@ -968,7 +968,7 @@ pub const GotPltSection = struct {
968968
969pub const PltGotSection = struct {969pub const PltGotSection = struct {
970 symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},970 symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},
971 output_symtab_size: Elf.SymtabSize = .{},971 output_symtab_ctx: Elf.SymtabCtx = .{},
972972
973 pub fn deinit(plt_got: *PltGotSection, allocator: Allocator) void {973 pub fn deinit(plt_got: *PltGotSection, allocator: Allocator) void {
974 plt_got.symbols.deinit(allocator);974 plt_got.symbols.deinit(allocator);
...@@ -1008,15 +1008,15 @@ pub const PltGotSection = struct {...@@ -1008,15 +1008,15 @@ pub const PltGotSection = struct {
1008 }1008 }
10091009
1010 pub fn updateSymtabSize(plt_got: *PltGotSection, elf_file: *Elf) void {1010 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));
1012 for (plt_got.symbols.items) |sym_index| {1012 for (plt_got.symbols.items) |sym_index| {
1013 const name = elf_file.symbol(sym_index).name(elf_file);1013 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;
1015 }1015 }
1016 }1016 }
10171017
1018 pub fn writeSymtab(plt_got: PltGotSection, elf_file: *Elf, ctx: anytype) void {1018 pub fn writeSymtab(plt_got: PltGotSection, elf_file: *Elf) void {
1019 var ilocal = ctx.ilocal;1019 var ilocal = plt_got.output_symtab_ctx.ilocal;
1020 for (plt_got.symbols.items) |sym_index| {1020 for (plt_got.symbols.items) |sym_index| {
1021 const sym = elf_file.symbol(sym_index);1021 const sym = elf_file.symbol(sym_index);
1022 const st_name = @as(u32, @intCast(elf_file.strtab.items.len));1022 const st_name = @as(u32, @intCast(elf_file.strtab.items.len));