authorgravatar for xavierb@gmail.comXavier Bouchoux <xavierb@gmail.com> 2023-05-12 21:45:23+02:00
committergravatar for xavierb@gmail.comXavier Bouchoux <xavierb@gmail.com> 2023-06-19 07:29:39+02:00
log5eacddce99c36c6f6ab62e7e7e5cc427c3e2f807
treeb6bf137b19b107d355b2bde41d5e81d7f532f902
parent423d7b848b1953173df99fde1f83166dc68c2a2c

objcopy: support some more elf file variants

"SHT_NOBITS" sections can be easily moved around in the file, they can be anywhere since there is no data... and remove logic about the categorization of symbol tables: I don't understand or remember why it was needed, and, in my tests, it works fine without... It previouly failed to strip an exe linked with `mold`

1 files changed, 7 insertions(+), 28 deletions(-)

src/objcopy.zig+7-28
...@@ -817,7 +817,7 @@ fn ElfFile(comptime is_64: bool) type {...@@ -817,7 +817,7 @@ fn ElfFile(comptime is_64: bool) type {
817 // fill-in sections info:817 // fill-in sections info:
818 // resolve the name818 // resolve the name
819 // find if a program segment uses the section819 // find if a program segment uses the section
820 // categorise sections usage (used by program segments, debug datadase, common metadata, symbol table)820 // categorize sections usage (used by program segments, debug datadase, common metadata, symbol table)
821 for (sections) |*section| {821 for (sections) |*section| {
822 section.segment = for (program_segments) |*seg| {822 section.segment = for (program_segments) |*seg| {
823 if (sectionWithinSegment(section.section, seg.*)) break seg;823 if (sectionWithinSegment(section.section, seg.*)) break seg;
...@@ -836,8 +836,8 @@ fn ElfFile(comptime is_64: bool) type {...@@ -836,8 +836,8 @@ fn ElfFile(comptime is_64: bool) type {
836 if (std.mem.eql(u8, section.name, ".gnu_debuglink")) break :cat .none;836 if (std.mem.eql(u8, section.name, ".gnu_debuglink")) break :cat .none;
837 break :cat category_from_program;837 break :cat category_from_program;
838 },838 },
839 elf.SHT_LOPROC...elf.SHT_HIPROC => .common, // don't strip unkonwn sections839 elf.SHT_LOPROC...elf.SHT_HIPROC => .common, // don't strip unknown sections
840 elf.SHT_LOUSER...elf.SHT_HIUSER => .common, // don't strip unkonwn sections840 elf.SHT_LOUSER...elf.SHT_HIUSER => .common, // don't strip unknown sections
841 else => category_from_program,841 else => category_from_program,
842 };842 };
843 }843 }
...@@ -846,7 +846,7 @@ fn ElfFile(comptime is_64: bool) type {...@@ -846,7 +846,7 @@ fn ElfFile(comptime is_64: bool) type {
846 if (header.shstrndx != elf.SHN_UNDEF)846 if (header.shstrndx != elf.SHN_UNDEF)
847 sections[header.shstrndx].category = .common; // string table for the headers847 sections[header.shstrndx].category = .common; // string table for the headers
848848
849 // recursive dependencies849 // recursively propagate section categories to their linked sections, so that they are kept together
850 var dirty: u1 = 1;850 var dirty: u1 = 1;
851 while (dirty != 0) {851 while (dirty != 0) {
852 dirty = 0;852 dirty = 0;
...@@ -856,29 +856,6 @@ fn ElfFile(comptime is_64: bool) type {...@@ -856,29 +856,6 @@ fn ElfFile(comptime is_64: bool) type {
856 dirty |= ElfFileHelper.propagateCategory(&sections[section.section.sh_link].category, section.category);856 dirty |= ElfFileHelper.propagateCategory(&sections[section.section.sh_link].category, section.category);
857 if ((section.section.sh_flags & elf.SHF_INFO_LINK) != 0 and section.section.sh_info != elf.SHN_UNDEF)857 if ((section.section.sh_flags & elf.SHF_INFO_LINK) != 0 and section.section.sh_info != elf.SHN_UNDEF)
858 dirty |= ElfFileHelper.propagateCategory(&sections[section.section.sh_info].category, section.category);858 dirty |= ElfFileHelper.propagateCategory(&sections[section.section.sh_info].category, section.category);
859
860 if (section.payload) |data| {
861 switch (section.section.sh_type) {
862 elf.DT_VERSYM => {
863 assert(section.section.sh_entsize == @sizeOf(Elf_Verdef));
864 const defs = @ptrCast([*]const Elf_Verdef, data)[0 .. @intCast(usize, section.section.sh_size) / @sizeOf(Elf_Verdef)];
865 for (defs) |def| {
866 if (def.vd_ndx != elf.SHN_UNDEF)
867 dirty |= ElfFileHelper.propagateCategory(&sections[def.vd_ndx].category, section.category);
868 }
869 },
870 elf.SHT_SYMTAB, elf.SHT_DYNSYM => {
871 assert(section.section.sh_entsize == @sizeOf(Elf_Sym));
872 const syms = @ptrCast([*]const Elf_Sym, data)[0 .. @intCast(usize, section.section.sh_size) / @sizeOf(Elf_Sym)];
873
874 for (syms) |sym| {
875 if (sym.st_shndx != elf.SHN_UNDEF and sym.st_shndx < elf.SHN_LORESERVE)
876 dirty |= ElfFileHelper.propagateCategory(&sections[sym.st_shndx].category, section.category);
877 }
878 },
879 else => {},
880 }
881 }
882 }859 }
883 }860 }
884861
...@@ -994,6 +971,8 @@ fn ElfFile(comptime is_64: bool) type {...@@ -994,6 +971,8 @@ fn ElfFile(comptime is_64: bool) type {
994 // this code only supports when they are in increasing file order.971 // this code only supports when they are in increasing file order.
995 var offset: u64 = eof_offset;972 var offset: u64 = eof_offset;
996 for (self.sections[1..]) |section| {973 for (self.sections[1..]) |section| {
974 if (section.section.sh_type == elf.SHT_NOBITS)
975 continue;
997 if (section.section.sh_offset < offset) {976 if (section.section.sh_offset < offset) {
998 fatal("zig objcopy: unsuported ELF file", .{});977 fatal("zig objcopy: unsuported ELF file", .{});
999 }978 }
...@@ -1025,7 +1004,7 @@ fn ElfFile(comptime is_64: bool) type {...@@ -1025,7 +1004,7 @@ fn ElfFile(comptime is_64: bool) type {
10251004
1026 const addralign = if (src.sh_addralign == 0 or dest.sh_type == elf.SHT_NOBITS) 1 else src.sh_addralign;1005 const addralign = if (src.sh_addralign == 0 or dest.sh_type == elf.SHT_NOBITS) 1 else src.sh_addralign;
1027 dest.sh_offset = std.mem.alignForward(Elf_OffSize, eof_offset, addralign);1006 dest.sh_offset = std.mem.alignForward(Elf_OffSize, eof_offset, addralign);
1028 if (src.sh_offset != dest.sh_offset and section.segment != null and update.action != .empty and dest.sh_type != elf.SHT_NOTE) {1007 if (src.sh_offset != dest.sh_offset and section.segment != null and update.action != .empty and dest.sh_type != elf.SHT_NOTE and dest.sh_type != elf.SHT_NOBITS) {
1029 if (src.sh_offset > dest.sh_offset) {1008 if (src.sh_offset > dest.sh_offset) {
1030 dest.sh_offset = src.sh_offset; // add padding to avoid modifing the program segments1009 dest.sh_offset = src.sh_offset; // add padding to avoid modifing the program segments
1031 } else {1010 } else {