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...@@ -1515,6 +1515,47 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
1515 // Scan and create missing synthetic entries such as GOT indirection.1515 // Scan and create missing synthetic entries such as GOT indirection.
1516 try self.scanRelocs();1516 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
1518 // Generate and emit non-incremental sections.1559 // Generate and emit non-incremental sections.
1519 try self.initSections();1560 try self.initSections();
1520 try self.initSpecialPhdrs();1561 try self.initSpecialPhdrs();
...@@ -1531,7 +1572,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node...@@ -1531,7 +1572,7 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
15311572
1532 self.allocatePhdrTable();1573 self.allocatePhdrTable();
1533 try self.allocateAllocSections();1574 try self.allocateAllocSections();
1534 self.allocateNonAllocSections();1575 try self.allocateNonAllocSections();
1535 self.allocateSpecialPhdrs();1576 self.allocateSpecialPhdrs();
1536 self.allocateAtoms();1577 self.allocateAtoms();
1537 self.allocateLinkerDefinedSymbols();1578 self.allocateLinkerDefinedSymbols();
...@@ -1574,45 +1615,6 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node...@@ -1574,45 +1615,6 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
1574 };1615 };
1575 try self.base.file.?.pwriteAll(code, file_offset);1616 try self.base.file.?.pwriteAll(code, file_offset);
1576 }1617 }
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 }
1616 }1618 }
16171619
1618 try self.writePhdrTable();1620 try self.writePhdrTable();
...@@ -4601,14 +4603,26 @@ fn allocateAllocSections(self: *Elf) error{OutOfMemory}!void {...@@ -4601,14 +4603,26 @@ fn allocateAllocSections(self: *Elf) error{OutOfMemory}!void {
4601}4603}
46024604
4603/// Allocates non-alloc sections (debug info, symtabs, etc.).4605/// Allocates non-alloc sections (debug info, symtabs, etc.).
4604fn allocateNonAllocSections(self: *Elf) void {4606fn allocateNonAllocSections(self: *Elf) !void {
4605 for (self.shdrs.items) |*shdr| {4607 for (self.shdrs.items, 0..) |*shdr, shndx| {
4606 if (shdr.sh_type == elf.SHT_NULL) continue;4608 if (shdr.sh_type == elf.SHT_NULL) continue;
4607 if (shdr.sh_flags & elf.SHF_ALLOC != 0) continue;4609 if (shdr.sh_flags & elf.SHF_ALLOC != 0) continue;
4608 const needed_size = shdr.sh_size;4610 const needed_size = shdr.sh_size;
4609 if (needed_size > self.allocatedSize(shdr.sh_offset)) {4611 if (needed_size > self.allocatedSize(shdr.sh_offset)) {
4610 shdr.sh_size = 0;4612 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;
4612 }4626 }
4613 shdr.sh_size = needed_size;4627 shdr.sh_size = needed_size;
4614 }4628 }
...@@ -5354,6 +5368,21 @@ pub fn isZigSection(self: Elf, shndx: u16) bool {...@@ -5354,6 +5368,21 @@ pub fn isZigSection(self: Elf, shndx: u16) bool {
5354 return false;5368 return false;
5355}5369}
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
5357fn addPhdr(self: *Elf, opts: struct {5386fn addPhdr(self: *Elf, opts: struct {
5358 type: u32 = 0,5387 type: u32 = 0,
5359 flags: u32 = 0,5388 flags: u32 = 0,