| ... | @@ -156,8 +156,6 @@ symbols_free_list: std.ArrayListUnmanaged(Symbol.Index) = .{}, | ... | @@ -156,8 +156,6 @@ symbols_free_list: std.ArrayListUnmanaged(Symbol.Index) = .{}, |
| 156 | has_text_reloc: bool = false, | 156 | has_text_reloc: bool = false, |
| 157 | num_ifunc_dynrelocs: usize = 0, | 157 | num_ifunc_dynrelocs: usize = 0, |
| 158 | | 158 | |
| 159 | shdr_table_dirty: bool = false, | | |
| 160 | | | |
| 161 | debug_strtab_dirty: bool = false, | 159 | debug_strtab_dirty: bool = false, |
| 162 | debug_abbrev_section_dirty: bool = false, | 160 | debug_abbrev_section_dirty: bool = false, |
| 163 | debug_aranges_section_dirty: bool = false, | 161 | debug_aranges_section_dirty: bool = false, |
| ... | @@ -245,8 +243,6 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option | ... | @@ -245,8 +243,6 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option |
| 245 | .mode = link.determineMode(options), | 243 | .mode = link.determineMode(options), |
| 246 | }); | 244 | }); |
| 247 | | 245 | |
| 248 | self.shdr_table_dirty = true; | | |
| 249 | | | |
| 250 | // Index 0 is always a null symbol. | 246 | // Index 0 is always a null symbol. |
| 251 | try self.symbols.append(allocator, .{}); | 247 | try self.symbols.append(allocator, .{}); |
| 252 | // Index 0 is always a null symbol. | 248 | // Index 0 is always a null symbol. |
| ... | @@ -523,16 +519,6 @@ fn detectAllocCollision(self: *Elf, start: u64, size: u64) ?u64 { | ... | @@ -523,16 +519,6 @@ fn detectAllocCollision(self: *Elf, start: u64, size: u64) ?u64 { |
| 523 | | 519 | |
| 524 | const end = start + padToIdeal(size); | 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 | for (self.shdrs.items) |shdr| { | 522 | for (self.shdrs.items) |shdr| { |
| 537 | // SHT_NOBITS takes no physical space in the output file so set its size to 0. | 523 | // SHT_NOBITS takes no physical space in the output file so set its size to 0. |
| 538 | const sh_size = if (shdr.sh_type == elf.SHT_NOBITS) 0 else shdr.sh_size; | 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,9 +541,6 @@ fn detectAllocCollision(self: *Elf, start: u64, size: u64) ?u64 { |
| 555 | fn allocatedSize(self: *Elf, start: u64) u64 { | 541 | fn allocatedSize(self: *Elf, start: u64) u64 { |
| 556 | if (start == 0) return 0; | 542 | if (start == 0) return 0; |
| 557 | var min_pos: u64 = std.math.maxInt(u64); | 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 | for (self.shdrs.items) |section| { | 544 | for (self.shdrs.items) |section| { |
| 562 | if (section.sh_offset <= start) continue; | 545 | if (section.sh_offset <= start) continue; |
| 563 | if (section.sh_offset < min_pos) min_pos = section.sh_offset; | 546 | if (section.sh_offset < min_pos) min_pos = section.sh_offset; |
| ... | @@ -1012,8 +995,6 @@ pub fn growNonAllocSection( | ... | @@ -1012,8 +995,6 @@ pub fn growNonAllocSection( |
| 1012 | } | 995 | } |
| 1013 | | 996 | |
| 1014 | pub fn markDirty(self: *Elf, shdr_index: u16) void { | 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 | if (self.dwarf) |_| { | 998 | if (self.dwarf) |_| { |
| 1018 | if (self.debug_info_section_index.? == shdr_index) { | 999 | if (self.debug_info_section_index.? == shdr_index) { |
| 1019 | self.debug_info_header_dirty = true; | 1000 | self.debug_info_header_dirty = true; |
| ... | @@ -1533,9 +1514,6 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node | ... | @@ -1533,9 +1514,6 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 1533 | if (metadata.rodata_state != .unused) metadata.rodata_state = .flushed; | 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 | if (self.dwarf) |*dw| { | 1517 | if (self.dwarf) |*dw| { |
| 1540 | try dw.flushModule(self.base.options.module.?); | 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,10 +1638,6 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 1660 | if (self.dwarf) |*dw| { | 1638 | if (self.dwarf) |*dw| { |
| 1661 | if (self.debug_abbrev_section_dirty) { | 1639 | if (self.debug_abbrev_section_dirty) { |
| 1662 | try dw.writeDbgAbbrev(); | 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 | self.debug_abbrev_section_dirty = false; | 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,10 +1656,6 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 1682 | // identical to the main program header virtual address and memory size. | 1656 | // identical to the main program header virtual address and memory size. |
| 1683 | const text_phdr = &self.phdrs.items[self.phdr_load_re_zig_index.?]; | 1657 | const text_phdr = &self.phdrs.items[self.phdr_load_re_zig_index.?]; |
| 1684 | try dw.writeDbgAranges(text_phdr.p_vaddr, text_phdr.p_memsz); | 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 | self.debug_aranges_section_dirty = false; | 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,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) { | 1678 | try self.writeShdrTable(); |
| 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 | | | |
| 1758 | try self.writePhdrTable(); | 1679 | try self.writePhdrTable(); |
| 1759 | try self.writeAtoms(); | 1680 | try self.writeAtoms(); |
| 1760 | try self.writeSyntheticSections(); | 1681 | try self.writeSyntheticSections(); |
| ... | @@ -1780,7 +1701,6 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node | ... | @@ -1780,7 +1701,6 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 1780 | // such as debug_line_header_dirty and debug_info_header_dirty. | 1701 | // such as debug_line_header_dirty and debug_info_header_dirty. |
| 1781 | assert(!self.debug_abbrev_section_dirty); | 1702 | assert(!self.debug_abbrev_section_dirty); |
| 1782 | assert(!self.debug_aranges_section_dirty); | 1703 | assert(!self.debug_aranges_section_dirty); |
| 1783 | assert(!self.shdr_table_dirty); | | |
| 1784 | assert(!self.debug_strtab_dirty); | 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,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 | fn writePhdrTable(self: *Elf) !void { | 2814 | fn writePhdrTable(self: *Elf) !void { |
| 2847 | const gpa = self.base.allocator; | 2815 | const gpa = self.base.allocator; |
| 2848 | const target_endian = self.base.options.target.cpu.arch.endian(); | 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,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 | fn shdrTo32(shdr: elf.Elf64_Shdr) elf.Elf32_Shdr { | 5055 | fn shdrTo32(shdr: elf.Elf64_Shdr) elf.Elf32_Shdr { |
| 5111 | return .{ | 5056 | return .{ |
| 5112 | .sh_name = shdr.sh_name, | 5057 | .sh_name = shdr.sh_name, |
| ... | @@ -5437,7 +5382,6 @@ pub fn addSection(self: *Elf, opts: AddSectionOpts) !u16 { | ... | @@ -5437,7 +5382,6 @@ pub fn addSection(self: *Elf, opts: AddSectionOpts) !u16 { |
| 5437 | .sh_addralign = opts.addralign, | 5382 | .sh_addralign = opts.addralign, |
| 5438 | .sh_entsize = opts.entsize, | 5383 | .sh_entsize = opts.entsize, |
| 5439 | }; | 5384 | }; |
| 5440 | self.shdr_table_dirty = true; | | |
| 5441 | return index; | 5385 | return index; |
| 5442 | } | 5386 | } |
| 5443 | | 5387 | |