| ... | ... | @@ -156,8 +156,6 @@ symbols_free_list: std.ArrayListUnmanaged(Symbol.Index) = .{}, |
| 156 | 156 | has_text_reloc: bool = false, |
| 157 | 157 | num_ifunc_dynrelocs: usize = 0, |
| 158 | 158 | |
| 159 | | shdr_table_dirty: bool = false, |
| 160 | | |
| 161 | 159 | debug_strtab_dirty: bool = false, |
| 162 | 160 | debug_abbrev_section_dirty: bool = false, |
| 163 | 161 | debug_aranges_section_dirty: bool = false, |
| ... | ... | @@ -245,8 +243,6 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option |
| 245 | 243 | .mode = link.determineMode(options), |
| 246 | 244 | }); |
| 247 | 245 | |
| 248 | | self.shdr_table_dirty = true; |
| 249 | | |
| 250 | 246 | // Index 0 is always a null symbol. |
| 251 | 247 | try self.symbols.append(allocator, .{}); |
| 252 | 248 | // Index 0 is always a null symbol. |
| ... | ... | @@ -523,16 +519,6 @@ fn detectAllocCollision(self: *Elf, start: u64, size: u64) ?u64 { |
| 523 | 519 | |
| 524 | 520 | const end = start + padToIdeal(size); |
| 525 | 521 | |
| 526 | | if (self.shdr_table_offset) |off| { |
| 527 | | const shdr_size: u64 = if (small_ptr) @sizeOf(elf.Elf32_Shdr) else @sizeOf(elf.Elf64_Shdr); |
| 528 | | const tight_size = self.shdrs.items.len * shdr_size; |
| 529 | | const increased_size = padToIdeal(tight_size); |
| 530 | | const test_end = off + increased_size; |
| 531 | | if (end > off and start < test_end) { |
| 532 | | return test_end; |
| 533 | | } |
| 534 | | } |
| 535 | | |
| 536 | 522 | for (self.shdrs.items) |shdr| { |
| 537 | 523 | // SHT_NOBITS takes no physical space in the output file so set its size to 0. |
| 538 | 524 | const sh_size = if (shdr.sh_type == elf.SHT_NOBITS) 0 else shdr.sh_size; |
| ... | ... | @@ -555,9 +541,6 @@ fn detectAllocCollision(self: *Elf, start: u64, size: u64) ?u64 { |
| 555 | 541 | fn allocatedSize(self: *Elf, start: u64) u64 { |
| 556 | 542 | if (start == 0) return 0; |
| 557 | 543 | var min_pos: u64 = std.math.maxInt(u64); |
| 558 | | if (self.shdr_table_offset) |off| { |
| 559 | | if (off > start and off < min_pos) min_pos = off; |
| 560 | | } |
| 561 | 544 | for (self.shdrs.items) |section| { |
| 562 | 545 | if (section.sh_offset <= start) continue; |
| 563 | 546 | if (section.sh_offset < min_pos) min_pos = section.sh_offset; |
| ... | ... | @@ -1012,8 +995,6 @@ pub fn growNonAllocSection( |
| 1012 | 995 | } |
| 1013 | 996 | |
| 1014 | 997 | pub fn markDirty(self: *Elf, shdr_index: u16) void { |
| 1015 | | self.shdr_table_dirty = true; // TODO look into only writing one section |
| 1016 | | |
| 1017 | 998 | if (self.dwarf) |_| { |
| 1018 | 999 | if (self.debug_info_section_index.? == shdr_index) { |
| 1019 | 1000 | self.debug_info_header_dirty = true; |
| ... | ... | @@ -1533,9 +1514,6 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 1533 | 1514 | if (metadata.rodata_state != .unused) metadata.rodata_state = .flushed; |
| 1534 | 1515 | } |
| 1535 | 1516 | |
| 1536 | | const target_endian = self.base.options.target.cpu.arch.endian(); |
| 1537 | | const foreign_endian = target_endian != builtin.cpu.arch.endian(); |
| 1538 | | |
| 1539 | 1517 | if (self.dwarf) |*dw| { |
| 1540 | 1518 | try dw.flushModule(self.base.options.module.?); |
| 1541 | 1519 | } |
| ... | ... | @@ -1660,10 +1638,6 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 1660 | 1638 | if (self.dwarf) |*dw| { |
| 1661 | 1639 | if (self.debug_abbrev_section_dirty) { |
| 1662 | 1640 | try dw.writeDbgAbbrev(); |
| 1663 | | if (!self.shdr_table_dirty) { |
| 1664 | | // Then it won't get written with the others and we need to do it. |
| 1665 | | try self.writeShdr(self.debug_abbrev_section_index.?); |
| 1666 | | } |
| 1667 | 1641 | self.debug_abbrev_section_dirty = false; |
| 1668 | 1642 | } |
| 1669 | 1643 | |
| ... | ... | @@ -1682,10 +1656,6 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 1682 | 1656 | // identical to the main program header virtual address and memory size. |
| 1683 | 1657 | const text_phdr = &self.phdrs.items[self.phdr_load_re_zig_index.?]; |
| 1684 | 1658 | try dw.writeDbgAranges(text_phdr.p_vaddr, text_phdr.p_memsz); |
| 1685 | | if (!self.shdr_table_dirty) { |
| 1686 | | // Then it won't get written with the others and we need to do it. |
| 1687 | | try self.writeShdr(self.debug_aranges_section_index.?); |
| 1688 | | } |
| 1689 | 1659 | self.debug_aranges_section_dirty = false; |
| 1690 | 1660 | } |
| 1691 | 1661 | |
| ... | ... | @@ -1705,56 +1675,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 1705 | 1675 | } |
| 1706 | 1676 | } |
| 1707 | 1677 | |
| 1708 | | if (self.shdr_table_dirty) { |
| 1709 | | const shsize: u64 = switch (self.ptr_width) { |
| 1710 | | .p32 => @sizeOf(elf.Elf32_Shdr), |
| 1711 | | .p64 => @sizeOf(elf.Elf64_Shdr), |
| 1712 | | }; |
| 1713 | | const shalign: u16 = switch (self.ptr_width) { |
| 1714 | | .p32 => @alignOf(elf.Elf32_Shdr), |
| 1715 | | .p64 => @alignOf(elf.Elf64_Shdr), |
| 1716 | | }; |
| 1717 | | const needed_size = self.shdrs.items.len * shsize; |
| 1718 | | const allocated_size = if (self.shdr_table_offset) |off| |
| 1719 | | self.allocatedSize(off) |
| 1720 | | else |
| 1721 | | 0; |
| 1722 | | if (needed_size > allocated_size) { |
| 1723 | | self.shdr_table_offset = null; // free the space |
| 1724 | | self.shdr_table_offset = self.findFreeSpace(needed_size, shalign); |
| 1725 | | } |
| 1726 | | |
| 1727 | | switch (self.ptr_width) { |
| 1728 | | .p32 => { |
| 1729 | | const buf = try gpa.alloc(elf.Elf32_Shdr, self.shdrs.items.len); |
| 1730 | | defer gpa.free(buf); |
| 1731 | | |
| 1732 | | for (buf, 0..) |*shdr, i| { |
| 1733 | | shdr.* = shdrTo32(self.shdrs.items[i]); |
| 1734 | | log.debug("writing section {?s}: {}", .{ self.shstrtab.get(shdr.sh_name), shdr.* }); |
| 1735 | | if (foreign_endian) { |
| 1736 | | mem.byteSwapAllFields(elf.Elf32_Shdr, shdr); |
| 1737 | | } |
| 1738 | | } |
| 1739 | | try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), self.shdr_table_offset.?); |
| 1740 | | }, |
| 1741 | | .p64 => { |
| 1742 | | const buf = try gpa.alloc(elf.Elf64_Shdr, self.shdrs.items.len); |
| 1743 | | defer gpa.free(buf); |
| 1744 | | |
| 1745 | | for (buf, 0..) |*shdr, i| { |
| 1746 | | shdr.* = self.shdrs.items[i]; |
| 1747 | | log.debug("writing section {?s}: {}", .{ self.shstrtab.get(shdr.sh_name), shdr.* }); |
| 1748 | | if (foreign_endian) { |
| 1749 | | mem.byteSwapAllFields(elf.Elf64_Shdr, shdr); |
| 1750 | | } |
| 1751 | | } |
| 1752 | | try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), self.shdr_table_offset.?); |
| 1753 | | }, |
| 1754 | | } |
| 1755 | | self.shdr_table_dirty = false; |
| 1756 | | } |
| 1757 | | |
| 1678 | try self.writeShdrTable(); |
| 1758 | 1679 | try self.writePhdrTable(); |
| 1759 | 1680 | try self.writeAtoms(); |
| 1760 | 1681 | try self.writeSyntheticSections(); |
| ... | ... | @@ -1780,7 +1701,6 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 1780 | 1701 | // such as debug_line_header_dirty and debug_info_header_dirty. |
| 1781 | 1702 | assert(!self.debug_abbrev_section_dirty); |
| 1782 | 1703 | assert(!self.debug_aranges_section_dirty); |
| 1783 | | assert(!self.shdr_table_dirty); |
| 1784 | 1704 | assert(!self.debug_strtab_dirty); |
| 1785 | 1705 | } |
| 1786 | 1706 | |
| ... | ... | @@ -2843,6 +2763,54 @@ fn writeDwarfAddrAssumeCapacity(self: *Elf, buf: *std.ArrayList(u8), addr: u64) |
| 2843 | 2763 | } |
| 2844 | 2764 | } |
| 2845 | 2765 | |
| 2766 | fn writeShdrTable(self: *Elf) !void { |
| 2767 | const gpa = self.base.allocator; |
| 2768 | const target_endian = self.base.options.target.cpu.arch.endian(); |
| 2769 | const foreign_endian = target_endian != builtin.cpu.arch.endian(); |
| 2770 | const shsize: u64 = switch (self.ptr_width) { |
| 2771 | .p32 => @sizeOf(elf.Elf32_Shdr), |
| 2772 | .p64 => @sizeOf(elf.Elf64_Shdr), |
| 2773 | }; |
| 2774 | const shalign: u16 = switch (self.ptr_width) { |
| 2775 | .p32 => @alignOf(elf.Elf32_Shdr), |
| 2776 | .p64 => @alignOf(elf.Elf64_Shdr), |
| 2777 | }; |
| 2778 | const needed_size = self.shdrs.items.len * shsize; |
| 2779 | var shoff: u64 = 0; |
| 2780 | for (self.shdrs.items) |shdr| { |
| 2781 | const off = mem.alignForward(u64, shdr.sh_offset + shdr.sh_size, shalign); |
| 2782 | shoff = @max(shoff, off); |
| 2783 | } |
| 2784 | self.shdr_table_offset = shoff; |
| 2785 | log.debug("writing section headers from 0x{x} to 0x{x}", .{ shoff, shoff + needed_size }); |
| 2786 | switch (self.ptr_width) { |
| 2787 | .p32 => { |
| 2788 | const buf = try gpa.alloc(elf.Elf32_Shdr, self.shdrs.items.len); |
| 2789 | defer gpa.free(buf); |
| 2790 | |
| 2791 | for (buf, 0..) |*shdr, i| { |
| 2792 | shdr.* = shdrTo32(self.shdrs.items[i]); |
| 2793 | if (foreign_endian) { |
| 2794 | mem.byteSwapAllFields(elf.Elf32_Shdr, shdr); |
| 2795 | } |
| 2796 | } |
| 2797 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), self.shdr_table_offset.?); |
| 2798 | }, |
| 2799 | .p64 => { |
| 2800 | const buf = try gpa.alloc(elf.Elf64_Shdr, self.shdrs.items.len); |
| 2801 | defer gpa.free(buf); |
| 2802 | |
| 2803 | for (buf, 0..) |*shdr, i| { |
| 2804 | shdr.* = self.shdrs.items[i]; |
| 2805 | if (foreign_endian) { |
| 2806 | mem.byteSwapAllFields(elf.Elf64_Shdr, shdr); |
| 2807 | } |
| 2808 | } |
| 2809 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), self.shdr_table_offset.?); |
| 2810 | }, |
| 2811 | } |
| 2812 | } |
| 2813 | |
| 2846 | 2814 | fn writePhdrTable(self: *Elf) !void { |
| 2847 | 2815 | const gpa = self.base.allocator; |
| 2848 | 2816 | const target_endian = self.base.options.target.cpu.arch.endian(); |
| ... | ... | @@ -5084,29 +5052,6 @@ fn phdrTo32(phdr: elf.Elf64_Phdr) elf.Elf32_Phdr { |
| 5084 | 5052 | }; |
| 5085 | 5053 | } |
| 5086 | 5054 | |
| 5087 | | fn writeShdr(self: *Elf, index: usize) !void { |
| 5088 | | const foreign_endian = self.base.options.target.cpu.arch.endian() != builtin.cpu.arch.endian(); |
| 5089 | | switch (self.ptr_width) { |
| 5090 | | .p32 => { |
| 5091 | | var shdr: [1]elf.Elf32_Shdr = undefined; |
| 5092 | | shdr[0] = shdrTo32(self.shdrs.items[index]); |
| 5093 | | if (foreign_endian) { |
| 5094 | | mem.byteSwapAllFields(elf.Elf32_Shdr, &shdr[0]); |
| 5095 | | } |
| 5096 | | const offset = self.shdr_table_offset.? + index * @sizeOf(elf.Elf32_Shdr); |
| 5097 | | return self.base.file.?.pwriteAll(mem.sliceAsBytes(&shdr), offset); |
| 5098 | | }, |
| 5099 | | .p64 => { |
| 5100 | | var shdr = [1]elf.Elf64_Shdr{self.shdrs.items[index]}; |
| 5101 | | if (foreign_endian) { |
| 5102 | | mem.byteSwapAllFields(elf.Elf64_Shdr, &shdr[0]); |
| 5103 | | } |
| 5104 | | const offset = self.shdr_table_offset.? + index * @sizeOf(elf.Elf64_Shdr); |
| 5105 | | return self.base.file.?.pwriteAll(mem.sliceAsBytes(&shdr), offset); |
| 5106 | | }, |
| 5107 | | } |
| 5108 | | } |
| 5109 | | |
| 5110 | 5055 | fn shdrTo32(shdr: elf.Elf64_Shdr) elf.Elf32_Shdr { |
| 5111 | 5056 | return .{ |
| 5112 | 5057 | .sh_name = shdr.sh_name, |
| ... | ... | @@ -5437,7 +5382,6 @@ pub fn addSection(self: *Elf, opts: AddSectionOpts) !u16 { |
| 5437 | 5382 | .sh_addralign = opts.addralign, |
| 5438 | 5383 | .sh_entsize = opts.entsize, |
| 5439 | 5384 | }; |
| 5440 | | self.shdr_table_dirty = true; |
| 5441 | 5385 | return index; |
| 5442 | 5386 | } |
| 5443 | 5387 | |