authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-04-14 20:04:29+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-04-14 20:04:29+02:00
log35171dd3dbb92a0a22733f40f2a1f81daf510409
tree40aeaeab396c629ee56d9aac62e2a75c1f21dc95
parent25874747174da2b0e77b3b888d0f5a13aa1a317e
parent4d77ef25f948cac32e4d5fd3f9df019e728fcb45
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #11433 from ziglang/elf-fixes

elf: support `--strip` option and set symtab size when writing globals

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

src/link/Elf.zig+175-154
......@@ -100,11 +100,11 @@ offset_table: std.ArrayListUnmanaged(u64) = .{},
100100phdr_table_dirty: bool = false,
101101shdr_table_dirty: bool = false,
102102shstrtab_dirty: bool = false,
103debug_strtab_dirty: bool = false,
104103offset_table_count_dirty: bool = false,
104
105debug_strtab_dirty: bool = false,
105106debug_abbrev_section_dirty: bool = false,
106107debug_aranges_section_dirty: bool = false,
107
108108debug_info_header_dirty: bool = false,
109109debug_line_header_dirty: bool = false,
110110
......@@ -749,127 +749,129 @@ pub fn populateMissingMetadata(self: *Elf) !void {
749749 try self.writeSymbol(0);
750750 }
751751
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 }
770771
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);
773774
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 }
796797
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);
799800
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 }
822823
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);
825826
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 }
848849
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);
851852
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 }
873875 }
874876
875877 const shsize: u64 = switch (self.ptr_width) {
......@@ -1001,40 +1003,42 @@ pub fn flushModule(self: *Elf, comp: *Compilation) !void {
10011003 // mixing local and global symbols within a symbol table.
10021004 try self.writeAllGlobalSymbols();
10031005
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;
10091014 }
1010 self.debug_abbrev_section_dirty = false;
1011 }
10121015
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 }
10221025
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;
10311036 }
1032 self.debug_aranges_section_dirty = false;
1033 }
10341037
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 }
10381042 }
10391043
10401044 if (self.phdr_table_dirty) {
......@@ -1105,9 +1109,8 @@ pub fn flushModule(self: *Elf, comp: *Compilation) !void {
11051109 }
11061110 }
11071111
1108 {
1112 if (self.dwarf) |dwarf| {
11091113 const debug_strtab_sect = &self.sections.items[self.debug_str_section_index.?];
1110 const dwarf = self.dwarf.?;
11111114 if (self.debug_strtab_dirty or dwarf.strtab.items.len != debug_strtab_sect.sh_size) {
11121115 const allocated_size = self.allocatedSize(debug_strtab_sect.sh_offset);
11131116 const needed_size = dwarf.strtab.items.len;
......@@ -2105,14 +2108,16 @@ fn allocateTextBlock(self: *Elf, text_block: *TextBlock, new_block_size: u64, al
21052108 phdr.p_memsz = needed_size;
21062109 phdr.p_filesz = needed_size;
21072110
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 }
21162121
21172122 self.phdr_table_dirty = true; // TODO look into making only the one program header dirty
21182123 self.shdr_table_dirty = true; // TODO look into making only the one section dirty
......@@ -2794,6 +2799,22 @@ fn writeAllGlobalSymbols(self: *Elf) !void {
27942799 .p32 => @sizeOf(elf.Elf32_Sym),
27952800 .p64 => @sizeOf(elf.Elf64_Sym),
27962801 };
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
27972818 const foreign_endian = self.base.options.target.cpu.arch.endian() != builtin.cpu.arch.endian();
27982819 const global_syms_off = syms_sect.sh_offset + self.local_symbols.items.len * sym_size;
27992820 switch (self.ptr_width) {