| ... | ... | @@ -18,13 +18,13 @@ shared_objects: std.ArrayListUnmanaged(File.Index) = .{}, |
| 18 | 18 | /// Same order as in the file. |
| 19 | 19 | shdrs: std.ArrayListUnmanaged(elf.Elf64_Shdr) = .{}, |
| 20 | 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 | 22 | /// File offset into the shdr table. |
| 23 | 23 | shdr_table_offset: ?u64 = null, |
| 24 | 24 | /// Table of lists of atoms per output section. |
| 25 | 25 | /// This table is not used to track incrementally generated atoms. |
| 26 | | output_sections: std.AutoArrayHashMapUnmanaged(u16, std.ArrayListUnmanaged(Atom.Index)) = .{}, |
| 27 | | output_rela_sections: std.AutoArrayHashMapUnmanaged(u16, std.ArrayListUnmanaged(Atom.Index)) = .{}, |
| 26 | output_sections: std.AutoArrayHashMapUnmanaged(u32, std.ArrayListUnmanaged(Atom.Index)) = .{}, |
| 27 | output_rela_sections: std.AutoArrayHashMapUnmanaged(u32, RelaSection) = .{}, |
| 28 | 28 | |
| 29 | 29 | /// Stored in native-endian format, depending on target endianness needs to be bswapped on read/write. |
| 30 | 30 | /// Same order as in the file. |
| ... | ... | @@ -355,8 +355,8 @@ pub fn deinit(self: *Elf) void { |
| 355 | 355 | list.deinit(gpa); |
| 356 | 356 | } |
| 357 | 357 | self.output_sections.deinit(gpa); |
| 358 | | for (self.output_rela_sections.values()) |*list| { |
| 359 | | list.deinit(gpa); |
| 358 | for (self.output_rela_sections.values()) |*sec| { |
| 359 | sec.atom_list.deinit(gpa); |
| 360 | 360 | } |
| 361 | 361 | self.output_rela_sections.deinit(gpa); |
| 362 | 362 | self.shstrtab.deinit(gpa); |
| ... | ... | @@ -600,7 +600,9 @@ pub fn initMetadata(self: *Elf) !void { |
| 600 | 600 | fillSection(self, shdr, self.base.options.program_code_size_hint, self.phdr_zig_load_re_index); |
| 601 | 601 | if (self.isRelocatable()) { |
| 602 | 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 | 606 | } else { |
| 605 | 607 | try self.phdr_to_shdr_table.putNoClobber( |
| 606 | 608 | gpa, |
| ... | ... | @@ -648,7 +650,9 @@ pub fn initMetadata(self: *Elf) !void { |
| 648 | 650 | ".rela.data.rel.ro.zig", |
| 649 | 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 | 656 | } else { |
| 653 | 657 | try self.phdr_to_shdr_table.putNoClobber( |
| 654 | 658 | gpa, |
| ... | ... | @@ -675,7 +679,9 @@ pub fn initMetadata(self: *Elf) !void { |
| 675 | 679 | ".rela.data.zig", |
| 676 | 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 | 685 | } else { |
| 680 | 686 | try self.phdr_to_shdr_table.putNoClobber( |
| 681 | 687 | gpa, |
| ... | ... | @@ -793,6 +799,14 @@ pub fn initMetadata(self: *Elf) !void { |
| 793 | 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 | 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 | 1535 | |
| 1522 | 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 | 1542 | try self.writeSyntheticSectionsObject(); |
| 1543 | try self.writeShdrTable(); |
| 1526 | 1544 | try self.writeElfHeader(); |
| 1527 | 1545 | } |
| 1528 | 1546 | |
| ... | ... | @@ -1618,6 +1636,9 @@ pub fn flushObject(self: *Elf) link.File.FlushError!void { |
| 1618 | 1636 | |
| 1619 | 1637 | try self.initSectionsObject(); |
| 1620 | 1638 | try self.sortShdrs(); |
| 1639 | if (self.zigObjectPtr()) |zig_object| { |
| 1640 | try zig_object.addAtomsToRelaSections(self); |
| 1641 | } |
| 1621 | 1642 | for (self.objects.items) |index| { |
| 1622 | 1643 | const object = self.file(index).?.object; |
| 1623 | 1644 | try object.addAtomsToOutputSections(self); |
| ... | ... | @@ -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 | 3964 | var last_atom_and_free_list_table = try self.last_atom_and_free_list_table.clone(gpa); |
| 3929 | 3965 | defer last_atom_and_free_list_table.deinit(gpa); |
| ... | ... | @@ -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| { |
| 4086 | | const shdr = &self.shdrs.items[shndx]; |
| 4087 | | for (atom_list.items) |atom_index| { |
| 4121 | for (self.output_rela_sections.values()) |sec| { |
| 4122 | const shdr = &self.shdrs.items[sec.shndx]; |
| 4123 | for (sec.atom_list.items) |atom_index| { |
| 4088 | 4124 | const atom_ptr = self.atom(atom_index) orelse continue; |
| 4089 | 4125 | if (!atom_ptr.flags.alive) continue; |
| 4090 | 4126 | const relocs = atom_ptr.relocs(self); |
| 4091 | 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 | 4133 | if (self.eh_frame_section_index) |index| { |
| ... | ... | @@ -4849,16 +4887,16 @@ fn writeSyntheticSections(self: *Elf) !void { |
| 4849 | 4887 | fn writeSyntheticSectionsObject(self: *Elf) !void { |
| 4850 | 4888 | const gpa = self.base.allocator; |
| 4851 | 4889 | |
| 4852 | | for (self.output_rela_sections.keys(), self.output_rela_sections.values()) |shndx, atom_list| { |
| 4853 | | if (atom_list.items.len == 0) continue; |
| 4890 | for (self.output_rela_sections.values()) |sec| { |
| 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 | 4895 | const num_relocs = @divExact(shdr.sh_size, shdr.sh_entsize); |
| 4858 | 4896 | var relocs = try std.ArrayList(elf.Elf64_Rela).initCapacity(gpa, num_relocs); |
| 4859 | 4897 | defer relocs.deinit(); |
| 4860 | 4898 | |
| 4861 | | for (atom_list.items) |atom_index| { |
| 4899 | for (sec.atom_list.items) |atom_index| { |
| 4862 | 4900 | const atom_ptr = self.atom(atom_index) orelse continue; |
| 4863 | 4901 | if (!atom_ptr.flags.alive) continue; |
| 4864 | 4902 | try atom_ptr.writeRelocs(self, &relocs); |
| ... | ... | @@ -6127,8 +6165,13 @@ const LastAtomAndFreeList = struct { |
| 6127 | 6165 | /// by 1 byte. It will then have -1 overcapacity. |
| 6128 | 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 | 6176 | pub const R_X86_64_ZIG_GOT32 = elf.R_X86_64_NUM + 1; |
| 6134 | 6177 | pub const R_X86_64_ZIG_GOTPCREL = elf.R_X86_64_NUM + 2; |