| ... | ... | @@ -100,11 +100,11 @@ offset_table: std.ArrayListUnmanaged(u64) = .{}, |
| 100 | 100 | phdr_table_dirty: bool = false, |
| 101 | 101 | shdr_table_dirty: bool = false, |
| 102 | 102 | shstrtab_dirty: bool = false, |
| 103 | | debug_strtab_dirty: bool = false, |
| 104 | 103 | offset_table_count_dirty: bool = false, |
| 104 | |
| 105 | debug_strtab_dirty: bool = false, |
| 105 | 106 | debug_abbrev_section_dirty: bool = false, |
| 106 | 107 | debug_aranges_section_dirty: bool = false, |
| 107 | | |
| 108 | 108 | debug_info_header_dirty: bool = false, |
| 109 | 109 | debug_line_header_dirty: bool = false, |
| 110 | 110 | |
| ... | ... | @@ -749,127 +749,129 @@ pub fn populateMissingMetadata(self: *Elf) !void { |
| 749 | 749 | try self.writeSymbol(0); |
| 750 | 750 | } |
| 751 | 751 | |
| 752 | | if (self.debug_str_section_index == null) { |
| 753 | | self.debug_str_section_index = @intCast(u16, self.sections.items.len); |
| 754 | | assert(self.dwarf.?.strtab.items.len == 0); |
| 755 | | try self.sections.append(self.base.allocator, .{ |
| 756 | | .sh_name = try self.makeString(".debug_str"), |
| 757 | | .sh_type = elf.SHT_PROGBITS, |
| 758 | | .sh_flags = elf.SHF_MERGE | elf.SHF_STRINGS, |
| 759 | | .sh_addr = 0, |
| 760 | | .sh_offset = 0, |
| 761 | | .sh_size = 0, |
| 762 | | .sh_link = 0, |
| 763 | | .sh_info = 0, |
| 764 | | .sh_addralign = 1, |
| 765 | | .sh_entsize = 1, |
| 766 | | }); |
| 767 | | self.debug_strtab_dirty = true; |
| 768 | | self.shdr_table_dirty = true; |
| 769 | | } |
| 752 | if (self.dwarf) |dw| { |
| 753 | if (self.debug_str_section_index == null) { |
| 754 | self.debug_str_section_index = @intCast(u16, self.sections.items.len); |
| 755 | assert(dw.strtab.items.len == 0); |
| 756 | try self.sections.append(self.base.allocator, .{ |
| 757 | .sh_name = try self.makeString(".debug_str"), |
| 758 | .sh_type = elf.SHT_PROGBITS, |
| 759 | .sh_flags = elf.SHF_MERGE | elf.SHF_STRINGS, |
| 760 | .sh_addr = 0, |
| 761 | .sh_offset = 0, |
| 762 | .sh_size = 0, |
| 763 | .sh_link = 0, |
| 764 | .sh_info = 0, |
| 765 | .sh_addralign = 1, |
| 766 | .sh_entsize = 1, |
| 767 | }); |
| 768 | self.debug_strtab_dirty = true; |
| 769 | self.shdr_table_dirty = true; |
| 770 | } |
| 770 | 771 | |
| 771 | | if (self.debug_info_section_index == null) { |
| 772 | | self.debug_info_section_index = @intCast(u16, self.sections.items.len); |
| 772 | if (self.debug_info_section_index == null) { |
| 773 | self.debug_info_section_index = @intCast(u16, self.sections.items.len); |
| 773 | 774 | |
| 774 | | const file_size_hint = 200; |
| 775 | | const p_align = 1; |
| 776 | | const off = self.findFreeSpace(file_size_hint, p_align); |
| 777 | | log.debug("found .debug_info free space 0x{x} to 0x{x}", .{ |
| 778 | | off, |
| 779 | | off + file_size_hint, |
| 780 | | }); |
| 781 | | try self.sections.append(self.base.allocator, .{ |
| 782 | | .sh_name = try self.makeString(".debug_info"), |
| 783 | | .sh_type = elf.SHT_PROGBITS, |
| 784 | | .sh_flags = 0, |
| 785 | | .sh_addr = 0, |
| 786 | | .sh_offset = off, |
| 787 | | .sh_size = file_size_hint, |
| 788 | | .sh_link = 0, |
| 789 | | .sh_info = 0, |
| 790 | | .sh_addralign = p_align, |
| 791 | | .sh_entsize = 0, |
| 792 | | }); |
| 793 | | self.shdr_table_dirty = true; |
| 794 | | self.debug_info_header_dirty = true; |
| 795 | | } |
| 775 | const file_size_hint = 200; |
| 776 | const p_align = 1; |
| 777 | const off = self.findFreeSpace(file_size_hint, p_align); |
| 778 | log.debug("found .debug_info free space 0x{x} to 0x{x}", .{ |
| 779 | off, |
| 780 | off + file_size_hint, |
| 781 | }); |
| 782 | try self.sections.append(self.base.allocator, .{ |
| 783 | .sh_name = try self.makeString(".debug_info"), |
| 784 | .sh_type = elf.SHT_PROGBITS, |
| 785 | .sh_flags = 0, |
| 786 | .sh_addr = 0, |
| 787 | .sh_offset = off, |
| 788 | .sh_size = file_size_hint, |
| 789 | .sh_link = 0, |
| 790 | .sh_info = 0, |
| 791 | .sh_addralign = p_align, |
| 792 | .sh_entsize = 0, |
| 793 | }); |
| 794 | self.shdr_table_dirty = true; |
| 795 | self.debug_info_header_dirty = true; |
| 796 | } |
| 796 | 797 | |
| 797 | | if (self.debug_abbrev_section_index == null) { |
| 798 | | self.debug_abbrev_section_index = @intCast(u16, self.sections.items.len); |
| 798 | if (self.debug_abbrev_section_index == null) { |
| 799 | self.debug_abbrev_section_index = @intCast(u16, self.sections.items.len); |
| 799 | 800 | |
| 800 | | const file_size_hint = 128; |
| 801 | | const p_align = 1; |
| 802 | | const off = self.findFreeSpace(file_size_hint, p_align); |
| 803 | | log.debug("found .debug_abbrev free space 0x{x} to 0x{x}", .{ |
| 804 | | off, |
| 805 | | off + file_size_hint, |
| 806 | | }); |
| 807 | | try self.sections.append(self.base.allocator, .{ |
| 808 | | .sh_name = try self.makeString(".debug_abbrev"), |
| 809 | | .sh_type = elf.SHT_PROGBITS, |
| 810 | | .sh_flags = 0, |
| 811 | | .sh_addr = 0, |
| 812 | | .sh_offset = off, |
| 813 | | .sh_size = file_size_hint, |
| 814 | | .sh_link = 0, |
| 815 | | .sh_info = 0, |
| 816 | | .sh_addralign = p_align, |
| 817 | | .sh_entsize = 0, |
| 818 | | }); |
| 819 | | self.shdr_table_dirty = true; |
| 820 | | self.debug_abbrev_section_dirty = true; |
| 821 | | } |
| 801 | const file_size_hint = 128; |
| 802 | const p_align = 1; |
| 803 | const off = self.findFreeSpace(file_size_hint, p_align); |
| 804 | log.debug("found .debug_abbrev free space 0x{x} to 0x{x}", .{ |
| 805 | off, |
| 806 | off + file_size_hint, |
| 807 | }); |
| 808 | try self.sections.append(self.base.allocator, .{ |
| 809 | .sh_name = try self.makeString(".debug_abbrev"), |
| 810 | .sh_type = elf.SHT_PROGBITS, |
| 811 | .sh_flags = 0, |
| 812 | .sh_addr = 0, |
| 813 | .sh_offset = off, |
| 814 | .sh_size = file_size_hint, |
| 815 | .sh_link = 0, |
| 816 | .sh_info = 0, |
| 817 | .sh_addralign = p_align, |
| 818 | .sh_entsize = 0, |
| 819 | }); |
| 820 | self.shdr_table_dirty = true; |
| 821 | self.debug_abbrev_section_dirty = true; |
| 822 | } |
| 822 | 823 | |
| 823 | | if (self.debug_aranges_section_index == null) { |
| 824 | | self.debug_aranges_section_index = @intCast(u16, self.sections.items.len); |
| 824 | if (self.debug_aranges_section_index == null) { |
| 825 | self.debug_aranges_section_index = @intCast(u16, self.sections.items.len); |
| 825 | 826 | |
| 826 | | const file_size_hint = 160; |
| 827 | | const p_align = 16; |
| 828 | | const off = self.findFreeSpace(file_size_hint, p_align); |
| 829 | | log.debug("found .debug_aranges free space 0x{x} to 0x{x}", .{ |
| 830 | | off, |
| 831 | | off + file_size_hint, |
| 832 | | }); |
| 833 | | try self.sections.append(self.base.allocator, .{ |
| 834 | | .sh_name = try self.makeString(".debug_aranges"), |
| 835 | | .sh_type = elf.SHT_PROGBITS, |
| 836 | | .sh_flags = 0, |
| 837 | | .sh_addr = 0, |
| 838 | | .sh_offset = off, |
| 839 | | .sh_size = file_size_hint, |
| 840 | | .sh_link = 0, |
| 841 | | .sh_info = 0, |
| 842 | | .sh_addralign = p_align, |
| 843 | | .sh_entsize = 0, |
| 844 | | }); |
| 845 | | self.shdr_table_dirty = true; |
| 846 | | self.debug_aranges_section_dirty = true; |
| 847 | | } |
| 827 | const file_size_hint = 160; |
| 828 | const p_align = 16; |
| 829 | const off = self.findFreeSpace(file_size_hint, p_align); |
| 830 | log.debug("found .debug_aranges free space 0x{x} to 0x{x}", .{ |
| 831 | off, |
| 832 | off + file_size_hint, |
| 833 | }); |
| 834 | try self.sections.append(self.base.allocator, .{ |
| 835 | .sh_name = try self.makeString(".debug_aranges"), |
| 836 | .sh_type = elf.SHT_PROGBITS, |
| 837 | .sh_flags = 0, |
| 838 | .sh_addr = 0, |
| 839 | .sh_offset = off, |
| 840 | .sh_size = file_size_hint, |
| 841 | .sh_link = 0, |
| 842 | .sh_info = 0, |
| 843 | .sh_addralign = p_align, |
| 844 | .sh_entsize = 0, |
| 845 | }); |
| 846 | self.shdr_table_dirty = true; |
| 847 | self.debug_aranges_section_dirty = true; |
| 848 | } |
| 848 | 849 | |
| 849 | | if (self.debug_line_section_index == null) { |
| 850 | | self.debug_line_section_index = @intCast(u16, self.sections.items.len); |
| 850 | if (self.debug_line_section_index == null) { |
| 851 | self.debug_line_section_index = @intCast(u16, self.sections.items.len); |
| 851 | 852 | |
| 852 | | const file_size_hint = 250; |
| 853 | | const p_align = 1; |
| 854 | | const off = self.findFreeSpace(file_size_hint, p_align); |
| 855 | | log.debug("found .debug_line free space 0x{x} to 0x{x}", .{ |
| 856 | | off, |
| 857 | | off + file_size_hint, |
| 858 | | }); |
| 859 | | try self.sections.append(self.base.allocator, .{ |
| 860 | | .sh_name = try self.makeString(".debug_line"), |
| 861 | | .sh_type = elf.SHT_PROGBITS, |
| 862 | | .sh_flags = 0, |
| 863 | | .sh_addr = 0, |
| 864 | | .sh_offset = off, |
| 865 | | .sh_size = file_size_hint, |
| 866 | | .sh_link = 0, |
| 867 | | .sh_info = 0, |
| 868 | | .sh_addralign = p_align, |
| 869 | | .sh_entsize = 0, |
| 870 | | }); |
| 871 | | self.shdr_table_dirty = true; |
| 872 | | self.debug_line_header_dirty = true; |
| 853 | const file_size_hint = 250; |
| 854 | const p_align = 1; |
| 855 | const off = self.findFreeSpace(file_size_hint, p_align); |
| 856 | log.debug("found .debug_line free space 0x{x} to 0x{x}", .{ |
| 857 | off, |
| 858 | off + file_size_hint, |
| 859 | }); |
| 860 | try self.sections.append(self.base.allocator, .{ |
| 861 | .sh_name = try self.makeString(".debug_line"), |
| 862 | .sh_type = elf.SHT_PROGBITS, |
| 863 | .sh_flags = 0, |
| 864 | .sh_addr = 0, |
| 865 | .sh_offset = off, |
| 866 | .sh_size = file_size_hint, |
| 867 | .sh_link = 0, |
| 868 | .sh_info = 0, |
| 869 | .sh_addralign = p_align, |
| 870 | .sh_entsize = 0, |
| 871 | }); |
| 872 | self.shdr_table_dirty = true; |
| 873 | self.debug_line_header_dirty = true; |
| 874 | } |
| 873 | 875 | } |
| 874 | 876 | |
| 875 | 877 | const shsize: u64 = switch (self.ptr_width) { |
| ... | ... | @@ -1001,40 +1003,42 @@ pub fn flushModule(self: *Elf, comp: *Compilation) !void { |
| 1001 | 1003 | // mixing local and global symbols within a symbol table. |
| 1002 | 1004 | try self.writeAllGlobalSymbols(); |
| 1003 | 1005 | |
| 1004 | | if (self.debug_abbrev_section_dirty) { |
| 1005 | | try self.dwarf.?.writeDbgAbbrev(&self.base); |
| 1006 | | if (!self.shdr_table_dirty) { |
| 1007 | | // Then it won't get written with the others and we need to do it. |
| 1008 | | try self.writeSectHeader(self.debug_abbrev_section_index.?); |
| 1006 | if (self.dwarf) |*dw| { |
| 1007 | if (self.debug_abbrev_section_dirty) { |
| 1008 | try dw.writeDbgAbbrev(&self.base); |
| 1009 | if (!self.shdr_table_dirty) { |
| 1010 | // Then it won't get written with the others and we need to do it. |
| 1011 | try self.writeSectHeader(self.debug_abbrev_section_index.?); |
| 1012 | } |
| 1013 | self.debug_abbrev_section_dirty = false; |
| 1009 | 1014 | } |
| 1010 | | self.debug_abbrev_section_dirty = false; |
| 1011 | | } |
| 1012 | 1015 | |
| 1013 | | if (self.debug_info_header_dirty) { |
| 1014 | | // Currently only one compilation unit is supported, so the address range is simply |
| 1015 | | // identical to the main program header virtual address and memory size. |
| 1016 | | const text_phdr = &self.program_headers.items[self.phdr_load_re_index.?]; |
| 1017 | | const low_pc = text_phdr.p_vaddr; |
| 1018 | | const high_pc = text_phdr.p_vaddr + text_phdr.p_memsz; |
| 1019 | | try self.dwarf.?.writeDbgInfoHeader(&self.base, module, low_pc, high_pc); |
| 1020 | | self.debug_info_header_dirty = false; |
| 1021 | | } |
| 1016 | if (self.debug_info_header_dirty) { |
| 1017 | // Currently only one compilation unit is supported, so the address range is simply |
| 1018 | // identical to the main program header virtual address and memory size. |
| 1019 | const text_phdr = &self.program_headers.items[self.phdr_load_re_index.?]; |
| 1020 | const low_pc = text_phdr.p_vaddr; |
| 1021 | const high_pc = text_phdr.p_vaddr + text_phdr.p_memsz; |
| 1022 | try dw.writeDbgInfoHeader(&self.base, module, low_pc, high_pc); |
| 1023 | self.debug_info_header_dirty = false; |
| 1024 | } |
| 1022 | 1025 | |
| 1023 | | if (self.debug_aranges_section_dirty) { |
| 1024 | | // Currently only one compilation unit is supported, so the address range is simply |
| 1025 | | // identical to the main program header virtual address and memory size. |
| 1026 | | const text_phdr = &self.program_headers.items[self.phdr_load_re_index.?]; |
| 1027 | | try self.dwarf.?.writeDbgAranges(&self.base, text_phdr.p_vaddr, text_phdr.p_memsz); |
| 1028 | | if (!self.shdr_table_dirty) { |
| 1029 | | // Then it won't get written with the others and we need to do it. |
| 1030 | | try self.writeSectHeader(self.debug_aranges_section_index.?); |
| 1026 | if (self.debug_aranges_section_dirty) { |
| 1027 | // Currently only one compilation unit is supported, so the address range is simply |
| 1028 | // identical to the main program header virtual address and memory size. |
| 1029 | const text_phdr = &self.program_headers.items[self.phdr_load_re_index.?]; |
| 1030 | try dw.writeDbgAranges(&self.base, text_phdr.p_vaddr, text_phdr.p_memsz); |
| 1031 | if (!self.shdr_table_dirty) { |
| 1032 | // Then it won't get written with the others and we need to do it. |
| 1033 | try self.writeSectHeader(self.debug_aranges_section_index.?); |
| 1034 | } |
| 1035 | self.debug_aranges_section_dirty = false; |
| 1031 | 1036 | } |
| 1032 | | self.debug_aranges_section_dirty = false; |
| 1033 | | } |
| 1034 | 1037 | |
| 1035 | | if (self.debug_line_header_dirty) { |
| 1036 | | try self.dwarf.?.writeDbgLineHeader(&self.base, module); |
| 1037 | | self.debug_line_header_dirty = false; |
| 1038 | if (self.debug_line_header_dirty) { |
| 1039 | try dw.writeDbgLineHeader(&self.base, module); |
| 1040 | self.debug_line_header_dirty = false; |
| 1041 | } |
| 1038 | 1042 | } |
| 1039 | 1043 | |
| 1040 | 1044 | if (self.phdr_table_dirty) { |
| ... | ... | @@ -1105,9 +1109,8 @@ pub fn flushModule(self: *Elf, comp: *Compilation) !void { |
| 1105 | 1109 | } |
| 1106 | 1110 | } |
| 1107 | 1111 | |
| 1108 | | { |
| 1112 | if (self.dwarf) |dwarf| { |
| 1109 | 1113 | const debug_strtab_sect = &self.sections.items[self.debug_str_section_index.?]; |
| 1110 | | const dwarf = self.dwarf.?; |
| 1111 | 1114 | if (self.debug_strtab_dirty or dwarf.strtab.items.len != debug_strtab_sect.sh_size) { |
| 1112 | 1115 | const allocated_size = self.allocatedSize(debug_strtab_sect.sh_offset); |
| 1113 | 1116 | const needed_size = dwarf.strtab.items.len; |
| ... | ... | @@ -2105,14 +2108,16 @@ fn allocateTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, al |
| 2105 | 2108 | phdr.p_memsz = needed_size; |
| 2106 | 2109 | phdr.p_filesz = needed_size; |
| 2107 | 2110 | |
| 2108 | | // The .debug_info section has `low_pc` and `high_pc` values which is the virtual address |
| 2109 | | // range of the compilation unit. When we expand the text section, this range changes, |
| 2110 | | // so the DW_TAG.compile_unit tag of the .debug_info section becomes dirty. |
| 2111 | | self.debug_info_header_dirty = true; |
| 2112 | | // This becomes dirty for the same reason. We could potentially make this more |
| 2113 | | // fine-grained with the addition of support for more compilation units. It is planned to |
| 2114 | | // model each package as a different compilation unit. |
| 2115 | | self.debug_aranges_section_dirty = true; |
| 2111 | if (self.dwarf) |_| { |
| 2112 | // The .debug_info section has `low_pc` and `high_pc` values which is the virtual address |
| 2113 | // range of the compilation unit. When we expand the text section, this range changes, |
| 2114 | // so the DW_TAG.compile_unit tag of the .debug_info section becomes dirty. |
| 2115 | self.debug_info_header_dirty = true; |
| 2116 | // This becomes dirty for the same reason. We could potentially make this more |
| 2117 | // fine-grained with the addition of support for more compilation units. It is planned to |
| 2118 | // model each package as a different compilation unit. |
| 2119 | self.debug_aranges_section_dirty = true; |
| 2120 | } |
| 2116 | 2121 | |
| 2117 | 2122 | self.phdr_table_dirty = true; // TODO look into making only the one program header dirty |
| 2118 | 2123 | self.shdr_table_dirty = true; // TODO look into making only the one section dirty |
| ... | ... | @@ -2794,6 +2799,22 @@ fn writeAllGlobalSymbols(self: *Elf) !void { |
| 2794 | 2799 | .p32 => @sizeOf(elf.Elf32_Sym), |
| 2795 | 2800 | .p64 => @sizeOf(elf.Elf64_Sym), |
| 2796 | 2801 | }; |
| 2802 | const sym_align: u16 = switch (self.ptr_width) { |
| 2803 | .p32 => @alignOf(elf.Elf32_Sym), |
| 2804 | .p64 => @alignOf(elf.Elf64_Sym), |
| 2805 | }; |
| 2806 | const needed_size = (self.local_symbols.items.len + self.global_symbols.items.len) * sym_size; |
| 2807 | if (needed_size > self.allocatedSize(syms_sect.sh_offset)) { |
| 2808 | // Move all the symbols to a new file location. |
| 2809 | const new_offset = self.findFreeSpace(needed_size, sym_align); |
| 2810 | const existing_size = @as(u64, syms_sect.sh_info) * sym_size; |
| 2811 | const amt = try self.base.file.?.copyRangeAll(syms_sect.sh_offset, self.base.file.?, new_offset, existing_size); |
| 2812 | if (amt != existing_size) return error.InputOutput; |
| 2813 | syms_sect.sh_offset = new_offset; |
| 2814 | } |
| 2815 | syms_sect.sh_size = needed_size; // anticipating adding the global symbols later |
| 2816 | self.shdr_table_dirty = true; // TODO look into only writing one section |
| 2817 | |
| 2797 | 2818 | const foreign_endian = self.base.options.target.cpu.arch.endian() != builtin.cpu.arch.endian(); |
| 2798 | 2819 | const global_syms_off = syms_sect.sh_offset + self.local_symbols.items.len * sym_size; |
| 2799 | 2820 | switch (self.ptr_width) { |