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