authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-10-11 07:45:46+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-10-16 19:33:05+02:00
log43397bbdc48ec0d5484a0fc2290fc2feddec7905
treeb8e9a7da152dc36450d1aad7e1d3d419a085480a
parent6a7a20520d02f958e1354636f99fcac53cc9c146

elf: always write SHDR table, at least for now


1 files changed, 49 insertions(+), 105 deletions(-)

src/link/Elf.zig+49-105
...@@ -156,8 +156,6 @@ symbols_free_list: std.ArrayListUnmanaged(Symbol.Index) = .{},...@@ -156,8 +156,6 @@ symbols_free_list: std.ArrayListUnmanaged(Symbol.Index) = .{},
156has_text_reloc: bool = false,156has_text_reloc: bool = false,
157num_ifunc_dynrelocs: usize = 0,157num_ifunc_dynrelocs: usize = 0,
158158
159shdr_table_dirty: bool = false,
160
161debug_strtab_dirty: bool = false,159debug_strtab_dirty: bool = false,
162debug_abbrev_section_dirty: bool = false,160debug_abbrev_section_dirty: bool = false,
163debug_aranges_section_dirty: bool = false,161debug_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 });
247245
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 {
523519
524 const end = start + padToIdeal(size);520 const end = start + padToIdeal(size);
525521
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 {
555fn allocatedSize(self: *Elf, start: u64) u64 {541fn 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}
1013996
1014pub fn markDirty(self: *Elf, shdr_index: u16) void {997pub 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 }
15351516
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 }
16691643
...@@ -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 }
16911661
...@@ -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 }
17071677
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}
17861706
...@@ -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}
28452765
2766fn 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
2846fn writePhdrTable(self: *Elf) !void {2814fn 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}
50865054
5087fn 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
5110fn shdrTo32(shdr: elf.Elf64_Shdr) elf.Elf32_Shdr {5055fn 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}
54435387