authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-10-13 23:01:48+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-10-16 19:33:05+02:00
log5fad6837919c683b48d11987e55948b7f25d67cd
tree78f0a5cd88927aa9ecded84cfe24ed10a6356d58
parent85d451f96cd8f2854fa6a092625b8a2f3c474a73

elf: emit (broken) debug sections


1 files changed, 72 insertions(+), 43 deletions(-)

src/link/Elf.zig+72-43
......@@ -1515,6 +1515,47 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
15151515 // Scan and create missing synthetic entries such as GOT indirection.
15161516 try self.scanRelocs();
15171517
1518 // TODO I need to re-think how to handle ZigModule's debug sections AND debug sections
1519 // extracted from input object files correctly.
1520 if (self.dwarf) |*dw| {
1521 if (self.debug_abbrev_section_dirty) {
1522 try dw.writeDbgAbbrev();
1523 self.debug_abbrev_section_dirty = false;
1524 }
1525
1526 if (self.debug_info_header_dirty) {
1527 // Currently only one compilation unit is supported, so the address range is simply
1528 // identical to the main program header virtual address and memory size.
1529 const text_phdr = &self.phdrs.items[self.phdr_zig_load_re_index.?];
1530 const low_pc = text_phdr.p_vaddr;
1531 const high_pc = text_phdr.p_vaddr + text_phdr.p_memsz;
1532 try dw.writeDbgInfoHeader(self.base.options.module.?, low_pc, high_pc);
1533 self.debug_info_header_dirty = false;
1534 }
1535
1536 if (self.debug_aranges_section_dirty) {
1537 // Currently only one compilation unit is supported, so the address range is simply
1538 // identical to the main program header virtual address and memory size.
1539 const text_phdr = &self.phdrs.items[self.phdr_zig_load_re_index.?];
1540 try dw.writeDbgAranges(text_phdr.p_vaddr, text_phdr.p_memsz);
1541 self.debug_aranges_section_dirty = false;
1542 }
1543
1544 if (self.debug_line_header_dirty) {
1545 try dw.writeDbgLineHeader();
1546 self.debug_line_header_dirty = false;
1547 }
1548
1549 if (self.debug_str_section_index) |shndx| {
1550 if (self.debug_strtab_dirty or dw.strtab.buffer.items.len != self.shdrs.items[shndx].sh_size) {
1551 try self.growNonAllocSection(shndx, dw.strtab.buffer.items.len, 1, false);
1552 const shdr = self.shdrs.items[shndx];
1553 try self.base.file.?.pwriteAll(dw.strtab.buffer.items, shdr.sh_offset);
1554 self.debug_strtab_dirty = false;
1555 }
1556 }
1557 }
1558
15181559 // Generate and emit non-incremental sections.
15191560 try self.initSections();
15201561 try self.initSpecialPhdrs();
......@@ -1531,7 +1572,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
15311572
15321573 self.allocatePhdrTable();
15331574 try self.allocateAllocSections();
1534 self.allocateNonAllocSections();
1575 try self.allocateNonAllocSections();
15351576 self.allocateSpecialPhdrs();
15361577 self.allocateAtoms();
15371578 self.allocateLinkerDefinedSymbols();
......@@ -1574,45 +1615,6 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
15741615 };
15751616 try self.base.file.?.pwriteAll(code, file_offset);
15761617 }
1577
1578 if (self.dwarf) |*dw| {
1579 if (self.debug_abbrev_section_dirty) {
1580 try dw.writeDbgAbbrev();
1581 self.debug_abbrev_section_dirty = false;
1582 }
1583
1584 if (self.debug_info_header_dirty) {
1585 // Currently only one compilation unit is supported, so the address range is simply
1586 // identical to the main program header virtual address and memory size.
1587 const text_phdr = &self.phdrs.items[self.phdr_zig_load_re_index.?];
1588 const low_pc = text_phdr.p_vaddr;
1589 const high_pc = text_phdr.p_vaddr + text_phdr.p_memsz;
1590 try dw.writeDbgInfoHeader(self.base.options.module.?, low_pc, high_pc);
1591 self.debug_info_header_dirty = false;
1592 }
1593
1594 if (self.debug_aranges_section_dirty) {
1595 // Currently only one compilation unit is supported, so the address range is simply
1596 // identical to the main program header virtual address and memory size.
1597 const text_phdr = &self.phdrs.items[self.phdr_zig_load_re_index.?];
1598 try dw.writeDbgAranges(text_phdr.p_vaddr, text_phdr.p_memsz);
1599 self.debug_aranges_section_dirty = false;
1600 }
1601
1602 if (self.debug_line_header_dirty) {
1603 try dw.writeDbgLineHeader();
1604 self.debug_line_header_dirty = false;
1605 }
1606
1607 if (self.debug_str_section_index) |shndx| {
1608 if (self.debug_strtab_dirty or dw.strtab.buffer.items.len != self.shdrs.items[shndx].sh_size) {
1609 try self.growNonAllocSection(shndx, dw.strtab.buffer.items.len, 1, false);
1610 const shdr = self.shdrs.items[shndx];
1611 try self.base.file.?.pwriteAll(dw.strtab.buffer.items, shdr.sh_offset);
1612 self.debug_strtab_dirty = false;
1613 }
1614 }
1615 }
16161618 }
16171619
16181620 try self.writePhdrTable();
......@@ -4601,14 +4603,26 @@ fn allocateAllocSections(self: *Elf) error{OutOfMemory}!void {
46014603}
46024604
46034605/// Allocates non-alloc sections (debug info, symtabs, etc.).
4604fn allocateNonAllocSections(self: *Elf) void {
4605 for (self.shdrs.items) |*shdr| {
4606fn allocateNonAllocSections(self: *Elf) !void {
4607 for (self.shdrs.items, 0..) |*shdr, shndx| {
46064608 if (shdr.sh_type == elf.SHT_NULL) continue;
46074609 if (shdr.sh_flags & elf.SHF_ALLOC != 0) continue;
46084610 const needed_size = shdr.sh_size;
46094611 if (needed_size > self.allocatedSize(shdr.sh_offset)) {
46104612 shdr.sh_size = 0;
4611 shdr.sh_offset = self.findFreeSpace(needed_size, shdr.sh_addralign);
4613 const new_offset = self.findFreeSpace(needed_size, shdr.sh_addralign);
4614
4615 if (self.isDebugSection(@intCast(shndx))) {
4616 const amt = try self.base.file.?.copyRangeAll(
4617 shdr.sh_offset,
4618 self.base.file.?,
4619 new_offset,
4620 needed_size, // TODO this will copy too much but ah well
4621 );
4622 if (amt != needed_size) return error.InputOutput;
4623 }
4624
4625 shdr.sh_offset = new_offset;
46124626 }
46134627 shdr.sh_size = needed_size;
46144628 }
......@@ -5354,6 +5368,21 @@ pub fn isZigSection(self: Elf, shndx: u16) bool {
53545368 return false;
53555369}
53565370
5371pub fn isDebugSection(self: Elf, shndx: u16) bool {
5372 inline for (&[_]?u16{
5373 self.debug_info_section_index,
5374 self.debug_abbrev_section_index,
5375 self.debug_str_section_index,
5376 self.debug_aranges_section_index,
5377 self.debug_line_section_index,
5378 }) |maybe_index| {
5379 if (maybe_index) |index| {
5380 if (index == shndx) return true;
5381 }
5382 }
5383 return false;
5384}
5385
53575386fn addPhdr(self: *Elf, opts: struct {
53585387 type: u32 = 0,
53595388 flags: u32 = 0,