| ... | @@ -18,13 +18,13 @@ shared_objects: std.ArrayListUnmanaged(File.Index) = .{}, | ... | @@ -18,13 +18,13 @@ shared_objects: std.ArrayListUnmanaged(File.Index) = .{}, |
| 18 | /// Same order as in the file. | 18 | /// Same order as in the file. |
| 19 | shdrs: std.ArrayListUnmanaged(elf.Elf64_Shdr) = .{}, | 19 | shdrs: std.ArrayListUnmanaged(elf.Elf64_Shdr) = .{}, |
| 20 | /// Given index to a section, pulls index of containing phdr if any. | 20 | /// Given index to a section, pulls index of containing phdr if any. |
| 21 | phdr_to_shdr_table: std.AutoHashMapUnmanaged(u16, u16) = .{}, | 21 | phdr_to_shdr_table: std.AutoHashMapUnmanaged(u32, u32) = .{}, |
| 22 | /// File offset into the shdr table. | 22 | /// File offset into the shdr table. |
| 23 | shdr_table_offset: ?u64 = null, | 23 | 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. |
| 26 | output_sections: std.AutoArrayHashMapUnmanaged(u16, std.ArrayListUnmanaged(Atom.Index)) = .{}, | 26 | output_sections: std.AutoArrayHashMapUnmanaged(u32, std.ArrayListUnmanaged(Atom.Index)) = .{}, |
| 27 | output_rela_sections: std.AutoArrayHashMapUnmanaged(u16, std.ArrayListUnmanaged(Atom.Index)) = .{}, | 27 | output_rela_sections: std.AutoArrayHashMapUnmanaged(u32, RelaSection) = .{}, |
| 28 | | 28 | |
| 29 | /// 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. |
| 30 | /// Same order as in the file. | 30 | /// Same order as in the file. |
| ... | @@ -355,8 +355,8 @@ pub fn deinit(self: *Elf) void { | ... | @@ -355,8 +355,8 @@ pub fn deinit(self: *Elf) void { |
| 355 | list.deinit(gpa); | 355 | list.deinit(gpa); |
| 356 | } | 356 | } |
| 357 | self.output_sections.deinit(gpa); | 357 | self.output_sections.deinit(gpa); |
| 358 | for (self.output_rela_sections.values()) |*list| { | 358 | for (self.output_rela_sections.values()) |*sec| { |
| 359 | list.deinit(gpa); | 359 | sec.atom_list.deinit(gpa); |
| 360 | } | 360 | } |
| 361 | self.output_rela_sections.deinit(gpa); | 361 | self.output_rela_sections.deinit(gpa); |
| 362 | self.shstrtab.deinit(gpa); | 362 | self.shstrtab.deinit(gpa); |
| ... | @@ -600,7 +600,9 @@ pub fn initMetadata(self: *Elf) !void { | ... | @@ -600,7 +600,9 @@ pub fn initMetadata(self: *Elf) !void { |
| 600 | 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); |
| 601 | if (self.isRelocatable()) { | 601 | if (self.isRelocatable()) { |
| 602 | const rela_shndx = try self.addRelaShdr(".rela.text.zig", self.zig_text_section_index.?); | 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, .{}); | 603 | try self.output_rela_sections.putNoClobber(gpa, self.zig_text_section_index.?, .{ |
| | 604 | .shndx = rela_shndx, |
| | 605 | }); |
| 604 | } else { | 606 | } else { |
| 605 | try self.phdr_to_shdr_table.putNoClobber( | 607 | try self.phdr_to_shdr_table.putNoClobber( |
| 606 | gpa, | 608 | gpa, |
| ... | @@ -648,7 +650,9 @@ pub fn initMetadata(self: *Elf) !void { | ... | @@ -648,7 +650,9 @@ pub fn initMetadata(self: *Elf) !void { |
| 648 | ".rela.data.rel.ro.zig", | 650 | ".rela.data.rel.ro.zig", |
| 649 | self.zig_data_rel_ro_section_index.?, | 651 | self.zig_data_rel_ro_section_index.?, |
| 650 | ); | 652 | ); |
| 651 | try self.output_rela_sections.putNoClobber(gpa, rela_shndx, .{}); | 653 | try self.output_rela_sections.putNoClobber(gpa, self.zig_data_rel_ro_section_index.?, .{ |
| | 654 | .shndx = rela_shndx, |
| | 655 | }); |
| 652 | } else { | 656 | } else { |
| 653 | try self.phdr_to_shdr_table.putNoClobber( | 657 | try self.phdr_to_shdr_table.putNoClobber( |
| 654 | gpa, | 658 | gpa, |
| ... | @@ -675,7 +679,9 @@ pub fn initMetadata(self: *Elf) !void { | ... | @@ -675,7 +679,9 @@ pub fn initMetadata(self: *Elf) !void { |
| 675 | ".rela.data.zig", | 679 | ".rela.data.zig", |
| 676 | self.zig_data_section_index.?, | 680 | self.zig_data_section_index.?, |
| 677 | ); | 681 | ); |
| 678 | try self.output_rela_sections.putNoClobber(gpa, rela_shndx, .{}); | 682 | try self.output_rela_sections.putNoClobber(gpa, self.zig_data_section_index.?, .{ |
| | 683 | .shndx = rela_shndx, |
| | 684 | }); |
| 679 | } else { | 685 | } else { |
| 680 | try self.phdr_to_shdr_table.putNoClobber( | 686 | try self.phdr_to_shdr_table.putNoClobber( |
| 681 | gpa, | 687 | gpa, |
| ... | @@ -793,6 +799,14 @@ pub fn initMetadata(self: *Elf) !void { | ... | @@ -793,6 +799,14 @@ pub fn initMetadata(self: *Elf) !void { |
| 793 | try self.output_sections.putNoClobber(gpa, self.debug_line_section_index.?, .{}); | 799 | try self.output_sections.putNoClobber(gpa, self.debug_line_section_index.?, .{}); |
| 794 | } | 800 | } |
| 795 | } | 801 | } |
| | 802 | |
| | 803 | // We need to find current max assumed file offset, and actually write to file to make it a reality. |
| | 804 | var end_pos: u64 = 0; |
| | 805 | for (self.shdrs.items) |shdr| { |
| | 806 | if (shdr.sh_offset == std.math.maxInt(u64)) continue; |
| | 807 | end_pos = @max(end_pos, shdr.sh_offset + shdr.sh_size); |
| | 808 | } |
| | 809 | try self.base.file.?.pwriteAll(&[1]u8{0}, end_pos); |
| 796 | } | 810 | } |
| 797 | | 811 | |
| 798 | pub fn growAllocSection(self: *Elf, shdr_index: u16, needed_size: u64) !void { | 812 | pub fn growAllocSection(self: *Elf, shdr_index: u16, needed_size: u64) !void { |
| ... | @@ -1521,8 +1535,12 @@ pub fn flushStaticLib(self: *Elf) link.File.FlushError!void { | ... | @@ -1521,8 +1535,12 @@ pub fn flushStaticLib(self: *Elf) link.File.FlushError!void { |
| 1521 | | 1535 | |
| 1522 | try self.allocateNonAllocSections(); | 1536 | try self.allocateNonAllocSections(); |
| 1523 | | 1537 | |
| 1524 | try self.writeShdrTable(); | 1538 | if (build_options.enable_logging) { |
| | 1539 | state_log.debug("{}", .{self.dumpState()}); |
| | 1540 | } |
| | 1541 | |
| 1525 | try self.writeSyntheticSectionsObject(); | 1542 | try self.writeSyntheticSectionsObject(); |
| | 1543 | try self.writeShdrTable(); |
| 1526 | try self.writeElfHeader(); | 1544 | try self.writeElfHeader(); |
| 1527 | } | 1545 | } |
| 1528 | | 1546 | |
| ... | @@ -1618,6 +1636,9 @@ pub fn flushObject(self: *Elf) link.File.FlushError!void { | ... | @@ -1618,6 +1636,9 @@ pub fn flushObject(self: *Elf) link.File.FlushError!void { |
| 1618 | | 1636 | |
| 1619 | try self.initSectionsObject(); | 1637 | try self.initSectionsObject(); |
| 1620 | try self.sortShdrs(); | 1638 | try self.sortShdrs(); |
| | 1639 | if (self.zigObjectPtr()) |zig_object| { |
| | 1640 | try zig_object.addAtomsToRelaSections(self); |
| | 1641 | } |
| 1621 | for (self.objects.items) |index| { | 1642 | for (self.objects.items) |index| { |
| 1622 | const object = self.file(index).?.object; | 1643 | const object = self.file(index).?.object; |
| 1623 | try object.addAtomsToOutputSections(self); | 1644 | try object.addAtomsToOutputSections(self); |
| ... | @@ -3924,6 +3945,21 @@ fn sortShdrs(self: *Elf) !void { | ... | @@ -3924,6 +3945,21 @@ fn sortShdrs(self: *Elf) !void { |
| 3924 | } | 3945 | } |
| 3925 | } | 3946 | } |
| 3926 | | 3947 | |
| | 3948 | { |
| | 3949 | var output_rela_sections = try self.output_rela_sections.clone(gpa); |
| | 3950 | defer output_rela_sections.deinit(gpa); |
| | 3951 | |
| | 3952 | self.output_rela_sections.clearRetainingCapacity(); |
| | 3953 | |
| | 3954 | var it = output_rela_sections.iterator(); |
| | 3955 | while (it.next()) |entry| { |
| | 3956 | const shndx = entry.key_ptr.*; |
| | 3957 | var meta = entry.value_ptr.*; |
| | 3958 | meta.shndx = backlinks[meta.shndx]; |
| | 3959 | self.output_rela_sections.putAssumeCapacityNoClobber(backlinks[shndx], meta); |
| | 3960 | } |
| | 3961 | } |
| | 3962 | |
| 3927 | { | 3963 | { |
| 3928 | var last_atom_and_free_list_table = try self.last_atom_and_free_list_table.clone(gpa); | 3964 | var last_atom_and_free_list_table = try self.last_atom_and_free_list_table.clone(gpa); |
| 3929 | defer last_atom_and_free_list_table.deinit(gpa); | 3965 | defer last_atom_and_free_list_table.deinit(gpa); |
| ... | @@ -4082,14 +4118,16 @@ fn updateSectionSizesObject(self: *Elf) !void { | ... | @@ -4082,14 +4118,16 @@ fn updateSectionSizesObject(self: *Elf) !void { |
| 4082 | } | 4118 | } |
| 4083 | } | 4119 | } |
| 4084 | | 4120 | |
| 4085 | for (self.output_rela_sections.keys(), self.output_rela_sections.values()) |shndx, atom_list| { | 4121 | for (self.output_rela_sections.values()) |sec| { |
| 4086 | const shdr = &self.shdrs.items[shndx]; | 4122 | const shdr = &self.shdrs.items[sec.shndx]; |
| 4087 | for (atom_list.items) |atom_index| { | 4123 | for (sec.atom_list.items) |atom_index| { |
| 4088 | const atom_ptr = self.atom(atom_index) orelse continue; | 4124 | const atom_ptr = self.atom(atom_index) orelse continue; |
| 4089 | if (!atom_ptr.flags.alive) continue; | 4125 | if (!atom_ptr.flags.alive) continue; |
| 4090 | const relocs = atom_ptr.relocs(self); | 4126 | const relocs = atom_ptr.relocs(self); |
| 4091 | shdr.sh_size += shdr.sh_entsize * relocs.len; | 4127 | shdr.sh_size += shdr.sh_entsize * relocs.len; |
| 4092 | } | 4128 | } |
| | 4129 | |
| | 4130 | if (shdr.sh_size == 0) shdr.sh_offset = 0; |
| 4093 | } | 4131 | } |
| 4094 | | 4132 | |
| 4095 | if (self.eh_frame_section_index) |index| { | 4133 | if (self.eh_frame_section_index) |index| { |
| ... | @@ -4849,16 +4887,16 @@ fn writeSyntheticSections(self: *Elf) !void { | ... | @@ -4849,16 +4887,16 @@ fn writeSyntheticSections(self: *Elf) !void { |
| 4849 | fn writeSyntheticSectionsObject(self: *Elf) !void { | 4887 | fn writeSyntheticSectionsObject(self: *Elf) !void { |
| 4850 | const gpa = self.base.allocator; | 4888 | const gpa = self.base.allocator; |
| 4851 | | 4889 | |
| 4852 | for (self.output_rela_sections.keys(), self.output_rela_sections.values()) |shndx, atom_list| { | 4890 | for (self.output_rela_sections.values()) |sec| { |
| 4853 | if (atom_list.items.len == 0) continue; | 4891 | if (sec.atom_list.items.len == 0) continue; |
| 4854 | | 4892 | |
| 4855 | const shdr = self.shdrs.items[shndx]; | 4893 | const shdr = self.shdrs.items[sec.shndx]; |
| 4856 | | 4894 | |
| 4857 | const num_relocs = @divExact(shdr.sh_size, shdr.sh_entsize); | 4895 | const num_relocs = @divExact(shdr.sh_size, shdr.sh_entsize); |
| 4858 | var relocs = try std.ArrayList(elf.Elf64_Rela).initCapacity(gpa, num_relocs); | 4896 | var relocs = try std.ArrayList(elf.Elf64_Rela).initCapacity(gpa, num_relocs); |
| 4859 | defer relocs.deinit(); | 4897 | defer relocs.deinit(); |
| 4860 | | 4898 | |
| 4861 | for (atom_list.items) |atom_index| { | 4899 | for (sec.atom_list.items) |atom_index| { |
| 4862 | const atom_ptr = self.atom(atom_index) orelse continue; | 4900 | const atom_ptr = self.atom(atom_index) orelse continue; |
| 4863 | if (!atom_ptr.flags.alive) continue; | 4901 | if (!atom_ptr.flags.alive) continue; |
| 4864 | try atom_ptr.writeRelocs(self, &relocs); | 4902 | try atom_ptr.writeRelocs(self, &relocs); |
| ... | @@ -6127,8 +6165,13 @@ const LastAtomAndFreeList = struct { | ... | @@ -6127,8 +6165,13 @@ const LastAtomAndFreeList = struct { |
| 6127 | /// by 1 byte. It will then have -1 overcapacity. | 6165 | /// by 1 byte. It will then have -1 overcapacity. |
| 6128 | free_list: std.ArrayListUnmanaged(Atom.Index) = .{}, | 6166 | free_list: std.ArrayListUnmanaged(Atom.Index) = .{}, |
| 6129 | }; | 6167 | }; |
| | 6168 | const LastAtomAndFreeListTable = std.AutoArrayHashMapUnmanaged(u32, LastAtomAndFreeList); |
| 6130 | | 6169 | |
| 6131 | const LastAtomAndFreeListTable = std.AutoArrayHashMapUnmanaged(u16, LastAtomAndFreeList); | 6170 | const RelaSection = struct { |
| | 6171 | shndx: u32, |
| | 6172 | atom_list: std.ArrayListUnmanaged(Atom.Index) = .{}, |
| | 6173 | }; |
| | 6174 | const RelaSectionTable = std.AutoArrayHashMapUnmanaged(u32, RelaSection); |
| 6132 | | 6175 | |
| 6133 | pub const R_X86_64_ZIG_GOT32 = elf.R_X86_64_NUM + 1; | 6176 | pub const R_X86_64_ZIG_GOT32 = elf.R_X86_64_NUM + 1; |
| 6134 | pub const R_X86_64_ZIG_GOTPCREL = elf.R_X86_64_NUM + 2; | 6177 | pub const R_X86_64_ZIG_GOTPCREL = elf.R_X86_64_NUM + 2; |