Commit 5fad683791

Jakub Konka <kubkon@jakubkonka.com>
2023-10-13 23:01:48
elf: emit (broken) debug sections
1 parent 85d451f
Changed files (1)
src
link
src/link/Elf.zig
@@ -1515,6 +1515,47 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
     // Scan and create missing synthetic entries such as GOT indirection.
     try self.scanRelocs();
 
+    // TODO I need to re-think how to handle ZigModule's debug sections AND debug sections
+    // extracted from input object files correctly.
+    if (self.dwarf) |*dw| {
+        if (self.debug_abbrev_section_dirty) {
+            try dw.writeDbgAbbrev();
+            self.debug_abbrev_section_dirty = false;
+        }
+
+        if (self.debug_info_header_dirty) {
+            // Currently only one compilation unit is supported, so the address range is simply
+            // identical to the main program header virtual address and memory size.
+            const text_phdr = &self.phdrs.items[self.phdr_zig_load_re_index.?];
+            const low_pc = text_phdr.p_vaddr;
+            const high_pc = text_phdr.p_vaddr + text_phdr.p_memsz;
+            try dw.writeDbgInfoHeader(self.base.options.module.?, low_pc, high_pc);
+            self.debug_info_header_dirty = false;
+        }
+
+        if (self.debug_aranges_section_dirty) {
+            // Currently only one compilation unit is supported, so the address range is simply
+            // identical to the main program header virtual address and memory size.
+            const text_phdr = &self.phdrs.items[self.phdr_zig_load_re_index.?];
+            try dw.writeDbgAranges(text_phdr.p_vaddr, text_phdr.p_memsz);
+            self.debug_aranges_section_dirty = false;
+        }
+
+        if (self.debug_line_header_dirty) {
+            try dw.writeDbgLineHeader();
+            self.debug_line_header_dirty = false;
+        }
+
+        if (self.debug_str_section_index) |shndx| {
+            if (self.debug_strtab_dirty or dw.strtab.buffer.items.len != self.shdrs.items[shndx].sh_size) {
+                try self.growNonAllocSection(shndx, dw.strtab.buffer.items.len, 1, false);
+                const shdr = self.shdrs.items[shndx];
+                try self.base.file.?.pwriteAll(dw.strtab.buffer.items, shdr.sh_offset);
+                self.debug_strtab_dirty = false;
+            }
+        }
+    }
+
     // Generate and emit non-incremental sections.
     try self.initSections();
     try self.initSpecialPhdrs();
@@ -1531,7 +1572,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
 
     self.allocatePhdrTable();
     try self.allocateAllocSections();
-    self.allocateNonAllocSections();
+    try self.allocateNonAllocSections();
     self.allocateSpecialPhdrs();
     self.allocateAtoms();
     self.allocateLinkerDefinedSymbols();
@@ -1574,45 +1615,6 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
             };
             try self.base.file.?.pwriteAll(code, file_offset);
         }
-
-        if (self.dwarf) |*dw| {
-            if (self.debug_abbrev_section_dirty) {
-                try dw.writeDbgAbbrev();
-                self.debug_abbrev_section_dirty = false;
-            }
-
-            if (self.debug_info_header_dirty) {
-                // Currently only one compilation unit is supported, so the address range is simply
-                // identical to the main program header virtual address and memory size.
-                const text_phdr = &self.phdrs.items[self.phdr_zig_load_re_index.?];
-                const low_pc = text_phdr.p_vaddr;
-                const high_pc = text_phdr.p_vaddr + text_phdr.p_memsz;
-                try dw.writeDbgInfoHeader(self.base.options.module.?, low_pc, high_pc);
-                self.debug_info_header_dirty = false;
-            }
-
-            if (self.debug_aranges_section_dirty) {
-                // Currently only one compilation unit is supported, so the address range is simply
-                // identical to the main program header virtual address and memory size.
-                const text_phdr = &self.phdrs.items[self.phdr_zig_load_re_index.?];
-                try dw.writeDbgAranges(text_phdr.p_vaddr, text_phdr.p_memsz);
-                self.debug_aranges_section_dirty = false;
-            }
-
-            if (self.debug_line_header_dirty) {
-                try dw.writeDbgLineHeader();
-                self.debug_line_header_dirty = false;
-            }
-
-            if (self.debug_str_section_index) |shndx| {
-                if (self.debug_strtab_dirty or dw.strtab.buffer.items.len != self.shdrs.items[shndx].sh_size) {
-                    try self.growNonAllocSection(shndx, dw.strtab.buffer.items.len, 1, false);
-                    const shdr = self.shdrs.items[shndx];
-                    try self.base.file.?.pwriteAll(dw.strtab.buffer.items, shdr.sh_offset);
-                    self.debug_strtab_dirty = false;
-                }
-            }
-        }
     }
 
     try self.writePhdrTable();
@@ -4601,14 +4603,26 @@ fn allocateAllocSections(self: *Elf) error{OutOfMemory}!void {
 }
 
 /// Allocates non-alloc sections (debug info, symtabs, etc.).
-fn allocateNonAllocSections(self: *Elf) void {
-    for (self.shdrs.items) |*shdr| {
+fn allocateNonAllocSections(self: *Elf) !void {
+    for (self.shdrs.items, 0..) |*shdr, shndx| {
         if (shdr.sh_type == elf.SHT_NULL) continue;
         if (shdr.sh_flags & elf.SHF_ALLOC != 0) continue;
         const needed_size = shdr.sh_size;
         if (needed_size > self.allocatedSize(shdr.sh_offset)) {
             shdr.sh_size = 0;
-            shdr.sh_offset = self.findFreeSpace(needed_size, shdr.sh_addralign);
+            const new_offset = self.findFreeSpace(needed_size, shdr.sh_addralign);
+
+            if (self.isDebugSection(@intCast(shndx))) {
+                const amt = try self.base.file.?.copyRangeAll(
+                    shdr.sh_offset,
+                    self.base.file.?,
+                    new_offset,
+                    needed_size, // TODO this will copy too much but ah well
+                );
+                if (amt != needed_size) return error.InputOutput;
+            }
+
+            shdr.sh_offset = new_offset;
         }
         shdr.sh_size = needed_size;
     }
@@ -5354,6 +5368,21 @@ pub fn isZigSection(self: Elf, shndx: u16) bool {
     return false;
 }
 
+pub fn isDebugSection(self: Elf, shndx: u16) bool {
+    inline for (&[_]?u16{
+        self.debug_info_section_index,
+        self.debug_abbrev_section_index,
+        self.debug_str_section_index,
+        self.debug_aranges_section_index,
+        self.debug_line_section_index,
+    }) |maybe_index| {
+        if (maybe_index) |index| {
+            if (index == shndx) return true;
+        }
+    }
+    return false;
+}
+
 fn addPhdr(self: *Elf, opts: struct {
     type: u32 = 0,
     flags: u32 = 0,