| ... | @@ -108,12 +108,21 @@ zig_rodata_section_index: ?u16 = null, | ... | @@ -108,12 +108,21 @@ zig_rodata_section_index: ?u16 = null, |
| 108 | zig_data_section_index: ?u16 = null, | 108 | zig_data_section_index: ?u16 = null, |
| 109 | zig_bss_section_index: ?u16 = null, | 109 | zig_bss_section_index: ?u16 = null, |
| 110 | zig_got_section_index: ?u16 = null, | 110 | zig_got_section_index: ?u16 = null, |
| | 111 | |
| 111 | debug_info_section_index: ?u16 = null, | 112 | debug_info_section_index: ?u16 = null, |
| 112 | debug_abbrev_section_index: ?u16 = null, | 113 | debug_abbrev_section_index: ?u16 = null, |
| 113 | debug_str_section_index: ?u16 = null, | 114 | debug_str_section_index: ?u16 = null, |
| 114 | debug_aranges_section_index: ?u16 = null, | 115 | debug_aranges_section_index: ?u16 = null, |
| 115 | debug_line_section_index: ?u16 = null, | 116 | debug_line_section_index: ?u16 = null, |
| 116 | | 117 | |
| | 118 | /// Size contribution of Zig's metadata to each debug section. |
| | 119 | /// Used to track start of metadata from input object files. |
| | 120 | debug_info_section_zig_size: u64 = 0, |
| | 121 | debug_abbrev_section_zig_size: u64 = 0, |
| | 122 | debug_str_section_zig_size: u64 = 0, |
| | 123 | debug_aranges_section_zig_size: u64 = 0, |
| | 124 | debug_line_section_zig_size: u64 = 0, |
| | 125 | |
| 117 | copy_rel_section_index: ?u16 = null, | 126 | copy_rel_section_index: ?u16 = null, |
| 118 | dynamic_section_index: ?u16 = null, | 127 | dynamic_section_index: ?u16 = null, |
| 119 | dynstrtab_section_index: ?u16 = null, | 128 | dynstrtab_section_index: ?u16 = null, |
| ... | @@ -924,7 +933,7 @@ pub fn growNonAllocSection( | ... | @@ -924,7 +933,7 @@ pub fn growNonAllocSection( |
| 924 | shdr.sh_offset = new_offset; | 933 | shdr.sh_offset = new_offset; |
| 925 | } | 934 | } |
| 926 | | 935 | |
| 927 | shdr.sh_size = needed_size; // anticipating adding the global symbols later | 936 | shdr.sh_size = needed_size; |
| 928 | | 937 | |
| 929 | self.markDirty(shdr_index); | 938 | self.markDirty(shdr_index); |
| 930 | } | 939 | } |
| ... | @@ -1522,8 +1531,6 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node | ... | @@ -1522,8 +1531,6 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 1522 | } | 1531 | } |
| 1523 | | 1532 | |
| 1524 | if (self.debug_info_header_dirty) { | 1533 | if (self.debug_info_header_dirty) { |
| 1525 | // Currently only one compilation unit is supported, so the address range is simply | | |
| 1526 | // identical to the main program header virtual address and memory size. | | |
| 1527 | const text_phdr = &self.phdrs.items[self.phdr_zig_load_re_index.?]; | 1534 | const text_phdr = &self.phdrs.items[self.phdr_zig_load_re_index.?]; |
| 1528 | const low_pc = text_phdr.p_vaddr; | 1535 | const low_pc = text_phdr.p_vaddr; |
| 1529 | const high_pc = text_phdr.p_vaddr + text_phdr.p_memsz; | 1536 | const high_pc = text_phdr.p_vaddr + text_phdr.p_memsz; |
| ... | @@ -1532,8 +1539,6 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node | ... | @@ -1532,8 +1539,6 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 1532 | } | 1539 | } |
| 1533 | | 1540 | |
| 1534 | if (self.debug_aranges_section_dirty) { | 1541 | if (self.debug_aranges_section_dirty) { |
| 1535 | // Currently only one compilation unit is supported, so the address range is simply | | |
| 1536 | // identical to the main program header virtual address and memory size. | | |
| 1537 | const text_phdr = &self.phdrs.items[self.phdr_zig_load_re_index.?]; | 1542 | const text_phdr = &self.phdrs.items[self.phdr_zig_load_re_index.?]; |
| 1538 | try dw.writeDbgAranges(text_phdr.p_vaddr, text_phdr.p_memsz); | 1543 | try dw.writeDbgAranges(text_phdr.p_vaddr, text_phdr.p_memsz); |
| 1539 | self.debug_aranges_section_dirty = false; | 1544 | self.debug_aranges_section_dirty = false; |
| ... | @@ -1552,6 +1557,8 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node | ... | @@ -1552,6 +1557,8 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 1552 | self.debug_strtab_dirty = false; | 1557 | self.debug_strtab_dirty = false; |
| 1553 | } | 1558 | } |
| 1554 | } | 1559 | } |
| | 1560 | |
| | 1561 | self.saveDebugSectionsSizes(); |
| 1555 | } | 1562 | } |
| 1556 | | 1563 | |
| 1557 | // Generate and emit non-incremental sections. | 1564 | // Generate and emit non-incremental sections. |
| ... | @@ -4345,6 +4352,24 @@ fn sortShdrs(self: *Elf) !void { | ... | @@ -4345,6 +4352,24 @@ fn sortShdrs(self: *Elf) !void { |
| 4345 | } | 4352 | } |
| 4346 | } | 4353 | } |
| 4347 | | 4354 | |
| | 4355 | fn saveDebugSectionsSizes(self: *Elf) void { |
| | 4356 | if (self.debug_info_section_index) |shndx| { |
| | 4357 | self.debug_info_section_zig_size = self.shdrs.items[shndx].sh_size; |
| | 4358 | } |
| | 4359 | if (self.debug_abbrev_section_index) |shndx| { |
| | 4360 | self.debug_abbrev_section_zig_size = self.shdrs.items[shndx].sh_size; |
| | 4361 | } |
| | 4362 | if (self.debug_str_section_index) |shndx| { |
| | 4363 | self.debug_str_section_zig_size = self.shdrs.items[shndx].sh_size; |
| | 4364 | } |
| | 4365 | if (self.debug_aranges_section_index) |shndx| { |
| | 4366 | self.debug_aranges_section_zig_size = self.shdrs.items[shndx].sh_size; |
| | 4367 | } |
| | 4368 | if (self.debug_line_section_index) |shndx| { |
| | 4369 | self.debug_line_section_zig_size = self.shdrs.items[shndx].sh_size; |
| | 4370 | } |
| | 4371 | } |
| | 4372 | |
| 4348 | fn updateSectionSizes(self: *Elf) !void { | 4373 | fn updateSectionSizes(self: *Elf) !void { |
| 4349 | for (self.output_sections.keys(), self.output_sections.values()) |shndx, atom_list| { | 4374 | for (self.output_sections.keys(), self.output_sections.values()) |shndx, atom_list| { |
| 4350 | if (atom_list.items.len == 0) continue; | 4375 | if (atom_list.items.len == 0) continue; |
| ... | @@ -4675,18 +4700,31 @@ fn allocateNonAllocSections(self: *Elf) !void { | ... | @@ -4675,18 +4700,31 @@ fn allocateNonAllocSections(self: *Elf) !void { |
| 4675 | const new_offset = self.findFreeSpace(needed_size, shdr.sh_addralign); | 4700 | const new_offset = self.findFreeSpace(needed_size, shdr.sh_addralign); |
| 4676 | | 4701 | |
| 4677 | if (self.isDebugSection(@intCast(shndx))) { | 4702 | if (self.isDebugSection(@intCast(shndx))) { |
| | 4703 | log.debug("moving {s} from 0x{x} to 0x{x}", .{ |
| | 4704 | self.shstrtab.getAssumeExists(shdr.sh_name), |
| | 4705 | shdr.sh_offset, |
| | 4706 | new_offset, |
| | 4707 | }); |
| | 4708 | const existing_size = blk: { |
| | 4709 | if (shndx == self.debug_info_section_index.?) break :blk self.debug_info_section_zig_size; |
| | 4710 | if (shndx == self.debug_abbrev_section_index.?) break :blk self.debug_abbrev_section_zig_size; |
| | 4711 | if (shndx == self.debug_str_section_index.?) break :blk self.debug_str_section_zig_size; |
| | 4712 | if (shndx == self.debug_aranges_section_index.?) break :blk self.debug_aranges_section_zig_size; |
| | 4713 | if (shndx == self.debug_line_section_index.?) break :blk self.debug_line_section_zig_size; |
| | 4714 | unreachable; |
| | 4715 | }; |
| 4678 | const amt = try self.base.file.?.copyRangeAll( | 4716 | const amt = try self.base.file.?.copyRangeAll( |
| 4679 | shdr.sh_offset, | 4717 | shdr.sh_offset, |
| 4680 | self.base.file.?, | 4718 | self.base.file.?, |
| 4681 | new_offset, | 4719 | new_offset, |
| 4682 | needed_size, // TODO this will copy too much but ah well | 4720 | existing_size, |
| 4683 | ); | 4721 | ); |
| 4684 | if (amt != needed_size) return error.InputOutput; | 4722 | if (amt != existing_size) return error.InputOutput; |
| 4685 | } | 4723 | } |
| 4686 | | 4724 | |
| 4687 | shdr.sh_offset = new_offset; | 4725 | shdr.sh_offset = new_offset; |
| | 4726 | shdr.sh_size = needed_size; |
| 4688 | } | 4727 | } |
| 4689 | shdr.sh_size = needed_size; | | |
| 4690 | } | 4728 | } |
| 4691 | } | 4729 | } |
| 4692 | | 4730 | |
| ... | @@ -4771,7 +4809,19 @@ fn writeAtoms(self: *Elf) !void { | ... | @@ -4771,7 +4809,19 @@ fn writeAtoms(self: *Elf) !void { |
| 4771 | | 4809 | |
| 4772 | log.debug("writing atoms in '{s}' section", .{self.shstrtab.getAssumeExists(shdr.sh_name)}); | 4810 | log.debug("writing atoms in '{s}' section", .{self.shstrtab.getAssumeExists(shdr.sh_name)}); |
| 4773 | | 4811 | |
| 4774 | const buffer = try gpa.alloc(u8, shdr.sh_size); | 4812 | // TODO really, really handle debug section separately |
| | 4813 | const base_offset = if (self.isDebugSection(@intCast(shndx))) blk: { |
| | 4814 | if (shndx == self.debug_info_section_index.?) break :blk self.debug_info_section_zig_size; |
| | 4815 | if (shndx == self.debug_abbrev_section_index.?) break :blk self.debug_abbrev_section_zig_size; |
| | 4816 | if (shndx == self.debug_str_section_index.?) break :blk self.debug_str_section_zig_size; |
| | 4817 | if (shndx == self.debug_aranges_section_index.?) break :blk self.debug_aranges_section_zig_size; |
| | 4818 | if (shndx == self.debug_line_section_index.?) break :blk self.debug_line_section_zig_size; |
| | 4819 | unreachable; |
| | 4820 | } else 0; |
| | 4821 | const sh_offset = shdr.sh_offset + base_offset; |
| | 4822 | const sh_size = shdr.sh_size - base_offset; |
| | 4823 | |
| | 4824 | const buffer = try gpa.alloc(u8, sh_size); |
| 4775 | defer gpa.free(buffer); | 4825 | defer gpa.free(buffer); |
| 4776 | const padding_byte: u8 = if (shdr.sh_type == elf.SHT_PROGBITS and | 4826 | const padding_byte: u8 = if (shdr.sh_type == elf.SHT_PROGBITS and |
| 4777 | shdr.sh_flags & elf.SHF_EXECINSTR != 0) | 4827 | shdr.sh_flags & elf.SHF_EXECINSTR != 0) |
| ... | @@ -4785,9 +4835,9 @@ fn writeAtoms(self: *Elf) !void { | ... | @@ -4785,9 +4835,9 @@ fn writeAtoms(self: *Elf) !void { |
| 4785 | assert(atom_ptr.flags.alive); | 4835 | assert(atom_ptr.flags.alive); |
| 4786 | | 4836 | |
| 4787 | const object = atom_ptr.file(self).?.object; | 4837 | const object = atom_ptr.file(self).?.object; |
| 4788 | const offset = atom_ptr.value - shdr.sh_addr; | 4838 | const offset = atom_ptr.value - shdr.sh_addr - base_offset; |
| 4789 | | 4839 | |
| 4790 | log.debug("writing atom({d}) at 0x{x}", .{ atom_index, shdr.sh_offset + offset }); | 4840 | log.debug("writing atom({d}) at 0x{x}", .{ atom_index, sh_offset + offset }); |
| 4791 | | 4841 | |
| 4792 | // TODO decompress directly into provided buffer | 4842 | // TODO decompress directly into provided buffer |
| 4793 | const out_code = buffer[offset..][0..atom_ptr.size]; | 4843 | const out_code = buffer[offset..][0..atom_ptr.size]; |
| ... | @@ -4808,7 +4858,7 @@ fn writeAtoms(self: *Elf) !void { | ... | @@ -4808,7 +4858,7 @@ fn writeAtoms(self: *Elf) !void { |
| 4808 | } | 4858 | } |
| 4809 | } | 4859 | } |
| 4810 | | 4860 | |
| 4811 | try self.base.file.?.pwriteAll(buffer, shdr.sh_offset); | 4861 | try self.base.file.?.pwriteAll(buffer, sh_offset); |
| 4812 | } | 4862 | } |
| 4813 | | 4863 | |
| 4814 | try self.reportUndefined(&undefs); | 4864 | try self.reportUndefined(&undefs); |