authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-04-14 15:15:09+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-04-14 15:15:13+02:00
log7a0022725342be8d3ea555a635da51f0e8c47b25
tree5304e08d711e5918cc690c18d25c63f52b4c6c94
parent2a00df9c091498268b58dd671f646a5590439b7a

elf: support --strip option

When the user passes `--strip` option on the command line, we do not emit any debug info by skipping initializing the internal `Dwarf` module.

1 files changed, 159 insertions(+), 154 deletions(-)

src/link/Elf.zig+159-154
...@@ -100,11 +100,11 @@ offset_table: std.ArrayListUnmanaged(u64) = .{},...@@ -100,11 +100,11 @@ offset_table: std.ArrayListUnmanaged(u64) = .{},
100phdr_table_dirty: bool = false,100phdr_table_dirty: bool = false,
101shdr_table_dirty: bool = false,101shdr_table_dirty: bool = false,
102shstrtab_dirty: bool = false,102shstrtab_dirty: bool = false,
103debug_strtab_dirty: bool = false,
104offset_table_count_dirty: bool = false,103offset_table_count_dirty: bool = false,
104
105debug_strtab_dirty: bool = false,
105debug_abbrev_section_dirty: bool = false,106debug_abbrev_section_dirty: bool = false,
106debug_aranges_section_dirty: bool = false,107debug_aranges_section_dirty: bool = false,
107
108debug_info_header_dirty: bool = false,108debug_info_header_dirty: bool = false,
109debug_line_header_dirty: bool = false,109debug_line_header_dirty: bool = false,
110110
...@@ -749,127 +749,129 @@ pub fn populateMissingMetadata(self: *Elf) !void {...@@ -749,127 +749,129 @@ pub fn populateMissingMetadata(self: *Elf) !void {
749 try self.writeSymbol(0);749 try self.writeSymbol(0);
750 }750 }
751751
752 if (self.debug_str_section_index == null) {752 if (self.dwarf) |dw| {
753 self.debug_str_section_index = @intCast(u16, self.sections.items.len);753 if (self.debug_str_section_index == null) {
754 assert(self.dwarf.?.strtab.items.len == 0);754 self.debug_str_section_index = @intCast(u16, self.sections.items.len);
755 try self.sections.append(self.base.allocator, .{755 assert(dw.strtab.items.len == 0);
756 .sh_name = try self.makeString(".debug_str"),756 try self.sections.append(self.base.allocator, .{
757 .sh_type = elf.SHT_PROGBITS,757 .sh_name = try self.makeString(".debug_str"),
758 .sh_flags = elf.SHF_MERGE | elf.SHF_STRINGS,758 .sh_type = elf.SHT_PROGBITS,
759 .sh_addr = 0,759 .sh_flags = elf.SHF_MERGE | elf.SHF_STRINGS,
760 .sh_offset = 0,760 .sh_addr = 0,
761 .sh_size = 0,761 .sh_offset = 0,
762 .sh_link = 0,762 .sh_size = 0,
763 .sh_info = 0,763 .sh_link = 0,
764 .sh_addralign = 1,764 .sh_info = 0,
765 .sh_entsize = 1,765 .sh_addralign = 1,
766 });766 .sh_entsize = 1,
767 self.debug_strtab_dirty = true;767 });
768 self.shdr_table_dirty = true;768 self.debug_strtab_dirty = true;
769 }769 self.shdr_table_dirty = true;
770 }
770771
771 if (self.debug_info_section_index == null) {772 if (self.debug_info_section_index == null) {
772 self.debug_info_section_index = @intCast(u16, self.sections.items.len);773 self.debug_info_section_index = @intCast(u16, self.sections.items.len);
773774
774 const file_size_hint = 200;775 const file_size_hint = 200;
775 const p_align = 1;776 const p_align = 1;
776 const off = self.findFreeSpace(file_size_hint, p_align);777 const off = self.findFreeSpace(file_size_hint, p_align);
777 log.debug("found .debug_info free space 0x{x} to 0x{x}", .{778 log.debug("found .debug_info free space 0x{x} to 0x{x}", .{
778 off,779 off,
779 off + file_size_hint,780 off + file_size_hint,
780 });781 });
781 try self.sections.append(self.base.allocator, .{782 try self.sections.append(self.base.allocator, .{
782 .sh_name = try self.makeString(".debug_info"),783 .sh_name = try self.makeString(".debug_info"),
783 .sh_type = elf.SHT_PROGBITS,784 .sh_type = elf.SHT_PROGBITS,
784 .sh_flags = 0,785 .sh_flags = 0,
785 .sh_addr = 0,786 .sh_addr = 0,
786 .sh_offset = off,787 .sh_offset = off,
787 .sh_size = file_size_hint,788 .sh_size = file_size_hint,
788 .sh_link = 0,789 .sh_link = 0,
789 .sh_info = 0,790 .sh_info = 0,
790 .sh_addralign = p_align,791 .sh_addralign = p_align,
791 .sh_entsize = 0,792 .sh_entsize = 0,
792 });793 });
793 self.shdr_table_dirty = true;794 self.shdr_table_dirty = true;
794 self.debug_info_header_dirty = true;795 self.debug_info_header_dirty = true;
795 }796 }
796797
797 if (self.debug_abbrev_section_index == null) {798 if (self.debug_abbrev_section_index == null) {
798 self.debug_abbrev_section_index = @intCast(u16, self.sections.items.len);799 self.debug_abbrev_section_index = @intCast(u16, self.sections.items.len);
799800
800 const file_size_hint = 128;801 const file_size_hint = 128;
801 const p_align = 1;802 const p_align = 1;
802 const off = self.findFreeSpace(file_size_hint, p_align);803 const off = self.findFreeSpace(file_size_hint, p_align);
803 log.debug("found .debug_abbrev free space 0x{x} to 0x{x}", .{804 log.debug("found .debug_abbrev free space 0x{x} to 0x{x}", .{
804 off,805 off,
805 off + file_size_hint,806 off + file_size_hint,
806 });807 });
807 try self.sections.append(self.base.allocator, .{808 try self.sections.append(self.base.allocator, .{
808 .sh_name = try self.makeString(".debug_abbrev"),809 .sh_name = try self.makeString(".debug_abbrev"),
809 .sh_type = elf.SHT_PROGBITS,810 .sh_type = elf.SHT_PROGBITS,
810 .sh_flags = 0,811 .sh_flags = 0,
811 .sh_addr = 0,812 .sh_addr = 0,
812 .sh_offset = off,813 .sh_offset = off,
813 .sh_size = file_size_hint,814 .sh_size = file_size_hint,
814 .sh_link = 0,815 .sh_link = 0,
815 .sh_info = 0,816 .sh_info = 0,
816 .sh_addralign = p_align,817 .sh_addralign = p_align,
817 .sh_entsize = 0,818 .sh_entsize = 0,
818 });819 });
819 self.shdr_table_dirty = true;820 self.shdr_table_dirty = true;
820 self.debug_abbrev_section_dirty = true;821 self.debug_abbrev_section_dirty = true;
821 }822 }
822823
823 if (self.debug_aranges_section_index == null) {824 if (self.debug_aranges_section_index == null) {
824 self.debug_aranges_section_index = @intCast(u16, self.sections.items.len);825 self.debug_aranges_section_index = @intCast(u16, self.sections.items.len);
825826
826 const file_size_hint = 160;827 const file_size_hint = 160;
827 const p_align = 16;828 const p_align = 16;
828 const off = self.findFreeSpace(file_size_hint, p_align);829 const off = self.findFreeSpace(file_size_hint, p_align);
829 log.debug("found .debug_aranges free space 0x{x} to 0x{x}", .{830 log.debug("found .debug_aranges free space 0x{x} to 0x{x}", .{
830 off,831 off,
831 off + file_size_hint,832 off + file_size_hint,
832 });833 });
833 try self.sections.append(self.base.allocator, .{834 try self.sections.append(self.base.allocator, .{
834 .sh_name = try self.makeString(".debug_aranges"),835 .sh_name = try self.makeString(".debug_aranges"),
835 .sh_type = elf.SHT_PROGBITS,836 .sh_type = elf.SHT_PROGBITS,
836 .sh_flags = 0,837 .sh_flags = 0,
837 .sh_addr = 0,838 .sh_addr = 0,
838 .sh_offset = off,839 .sh_offset = off,
839 .sh_size = file_size_hint,840 .sh_size = file_size_hint,
840 .sh_link = 0,841 .sh_link = 0,
841 .sh_info = 0,842 .sh_info = 0,
842 .sh_addralign = p_align,843 .sh_addralign = p_align,
843 .sh_entsize = 0,844 .sh_entsize = 0,
844 });845 });
845 self.shdr_table_dirty = true;846 self.shdr_table_dirty = true;
846 self.debug_aranges_section_dirty = true;847 self.debug_aranges_section_dirty = true;
847 }848 }
848849
849 if (self.debug_line_section_index == null) {850 if (self.debug_line_section_index == null) {
850 self.debug_line_section_index = @intCast(u16, self.sections.items.len);851 self.debug_line_section_index = @intCast(u16, self.sections.items.len);
851852
852 const file_size_hint = 250;853 const file_size_hint = 250;
853 const p_align = 1;854 const p_align = 1;
854 const off = self.findFreeSpace(file_size_hint, p_align);855 const off = self.findFreeSpace(file_size_hint, p_align);
855 log.debug("found .debug_line free space 0x{x} to 0x{x}", .{856 log.debug("found .debug_line free space 0x{x} to 0x{x}", .{
856 off,857 off,
857 off + file_size_hint,858 off + file_size_hint,
858 });859 });
859 try self.sections.append(self.base.allocator, .{860 try self.sections.append(self.base.allocator, .{
860 .sh_name = try self.makeString(".debug_line"),861 .sh_name = try self.makeString(".debug_line"),
861 .sh_type = elf.SHT_PROGBITS,862 .sh_type = elf.SHT_PROGBITS,
862 .sh_flags = 0,863 .sh_flags = 0,
863 .sh_addr = 0,864 .sh_addr = 0,
864 .sh_offset = off,865 .sh_offset = off,
865 .sh_size = file_size_hint,866 .sh_size = file_size_hint,
866 .sh_link = 0,867 .sh_link = 0,
867 .sh_info = 0,868 .sh_info = 0,
868 .sh_addralign = p_align,869 .sh_addralign = p_align,
869 .sh_entsize = 0,870 .sh_entsize = 0,
870 });871 });
871 self.shdr_table_dirty = true;872 self.shdr_table_dirty = true;
872 self.debug_line_header_dirty = true;873 self.debug_line_header_dirty = true;
874 }
873 }875 }
874876
875 const shsize: u64 = switch (self.ptr_width) {877 const shsize: u64 = switch (self.ptr_width) {
...@@ -1001,40 +1003,42 @@ pub fn flushModule(self: *Elf, comp: *Compilation) !void {...@@ -1001,40 +1003,42 @@ pub fn flushModule(self: *Elf, comp: *Compilation) !void {
1001 // mixing local and global symbols within a symbol table.1003 // mixing local and global symbols within a symbol table.
1002 try self.writeAllGlobalSymbols();1004 try self.writeAllGlobalSymbols();
10031005
1004 if (self.debug_abbrev_section_dirty) {1006 if (self.dwarf) |*dw| {
1005 try self.dwarf.?.writeDbgAbbrev(&self.base);1007 if (self.debug_abbrev_section_dirty) {
1006 if (!self.shdr_table_dirty) {1008 try dw.writeDbgAbbrev(&self.base);
1007 // Then it won't get written with the others and we need to do it.1009 if (!self.shdr_table_dirty) {
1008 try self.writeSectHeader(self.debug_abbrev_section_index.?);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 }
10121015
1013 if (self.debug_info_header_dirty) {1016 if (self.debug_info_header_dirty) {
1014 // Currently only one compilation unit is supported, so the address range is simply1017 // 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.1018 // identical to the main program header virtual address and memory size.
1016 const text_phdr = &self.program_headers.items[self.phdr_load_re_index.?];1019 const text_phdr = &self.program_headers.items[self.phdr_load_re_index.?];
1017 const low_pc = text_phdr.p_vaddr;1020 const low_pc = text_phdr.p_vaddr;
1018 const high_pc = text_phdr.p_vaddr + text_phdr.p_memsz;1021 const high_pc = text_phdr.p_vaddr + text_phdr.p_memsz;
1019 try self.dwarf.?.writeDbgInfoHeader(&self.base, module, low_pc, high_pc);1022 try dw.writeDbgInfoHeader(&self.base, module, low_pc, high_pc);
1020 self.debug_info_header_dirty = false;1023 self.debug_info_header_dirty = false;
1021 }1024 }
10221025
1023 if (self.debug_aranges_section_dirty) {1026 if (self.debug_aranges_section_dirty) {
1024 // Currently only one compilation unit is supported, so the address range is simply1027 // 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.1028 // identical to the main program header virtual address and memory size.
1026 const text_phdr = &self.program_headers.items[self.phdr_load_re_index.?];1029 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);1030 try dw.writeDbgAranges(&self.base, text_phdr.p_vaddr, text_phdr.p_memsz);
1028 if (!self.shdr_table_dirty) {1031 if (!self.shdr_table_dirty) {
1029 // Then it won't get written with the others and we need to do it.1032 // Then it won't get written with the others and we need to do it.
1030 try self.writeSectHeader(self.debug_aranges_section_index.?);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 }
10341037
1035 if (self.debug_line_header_dirty) {1038 if (self.debug_line_header_dirty) {
1036 try self.dwarf.?.writeDbgLineHeader(&self.base, module);1039 try dw.writeDbgLineHeader(&self.base, module);
1037 self.debug_line_header_dirty = false;1040 self.debug_line_header_dirty = false;
1041 }
1038 }1042 }
10391043
1040 if (self.phdr_table_dirty) {1044 if (self.phdr_table_dirty) {
...@@ -1105,9 +1109,8 @@ pub fn flushModule(self: *Elf, comp: *Compilation) !void {...@@ -1105,9 +1109,8 @@ pub fn flushModule(self: *Elf, comp: *Compilation) !void {
1105 }1109 }
1106 }1110 }
11071111
1108 {1112 if (self.dwarf) |dwarf| {
1109 const debug_strtab_sect = &self.sections.items[self.debug_str_section_index.?];1113 const debug_strtab_sect = &self.sections.items[self.debug_str_section_index.?];
1110 const dwarf = self.dwarf.?;
1111 if (self.debug_strtab_dirty or dwarf.strtab.items.len != debug_strtab_sect.sh_size) {1114 if (self.debug_strtab_dirty or dwarf.strtab.items.len != debug_strtab_sect.sh_size) {
1112 const allocated_size = self.allocatedSize(debug_strtab_sect.sh_offset);1115 const allocated_size = self.allocatedSize(debug_strtab_sect.sh_offset);
1113 const needed_size = dwarf.strtab.items.len;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,14 +2108,16 @@ fn allocateTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, al
2105 phdr.p_memsz = needed_size;2108 phdr.p_memsz = needed_size;
2106 phdr.p_filesz = needed_size;2109 phdr.p_filesz = needed_size;
21072110
2108 // The .debug_info section has `low_pc` and `high_pc` values which is the virtual address2111 if (self.dwarf) |_| {
2109 // range of the compilation unit. When we expand the text section, this range changes,2112 // The .debug_info section has `low_pc` and `high_pc` values which is the virtual address
2110 // so the DW_TAG.compile_unit tag of the .debug_info section becomes dirty.2113 // range of the compilation unit. When we expand the text section, this range changes,
2111 self.debug_info_header_dirty = true;2114 // so the DW_TAG.compile_unit tag of the .debug_info section becomes dirty.
2112 // This becomes dirty for the same reason. We could potentially make this more2115 self.debug_info_header_dirty = true;
2113 // fine-grained with the addition of support for more compilation units. It is planned to2116 // This becomes dirty for the same reason. We could potentially make this more
2114 // model each package as a different compilation unit.2117 // fine-grained with the addition of support for more compilation units. It is planned to
2115 self.debug_aranges_section_dirty = true;2118 // model each package as a different compilation unit.
2119 self.debug_aranges_section_dirty = true;
2120 }
21162121
2117 self.phdr_table_dirty = true; // TODO look into making only the one program header dirty2122 self.phdr_table_dirty = true; // TODO look into making only the one program header dirty
2118 self.shdr_table_dirty = true; // TODO look into making only the one section dirty2123 self.shdr_table_dirty = true; // TODO look into making only the one section dirty