diff --git a/llvm/test/tools/llvm-objcopy/MachO/Inputs/only-section.yaml b/llvm/test/tools/llvm-objcopy/MachO/Inputs/only-section.yaml new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-objcopy/MachO/Inputs/only-section.yaml @@ -0,0 +1,416 @@ +--- !mach-o +FileHeader: + magic: 0xFEEDFACF + cputype: 0x01000007 + cpusubtype: 0x00000003 + filetype: 0x00000001 + ncmds: 4 + sizeofcmds: 1160 + flags: 0x00002000 + reserved: 0x00000000 +LoadCommands: + - cmd: LC_SEGMENT_64 + cmdsize: 1032 + segname: '' + vmaddr: 0 + vmsize: 765 + fileoff: 1192 + filesize: 765 + maxprot: 7 + initprot: 7 + nsects: 12 + flags: 0 + Sections: + - sectname: __text + segname: __TEXT + addr: 0x0000000000000000 + size: 26 + offset: 0x000004A8 + align: 4 + reloff: 0x000007A8 + nreloc: 2 + flags: 0x80000400 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __debug_str + segname: __DWARF + addr: 0x000000000000001A + size: 114 + offset: 0x000004C2 + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x02000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __debug_abbrev + segname: __DWARF + addr: 0x000000000000008C + size: 69 + offset: 0x00000534 + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x02000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __debug_info + segname: __DWARF + addr: 0x00000000000000D1 + size: 117 + offset: 0x00000579 + align: 0 + reloff: 0x000007B8 + nreloc: 4 + flags: 0x02000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __debug_macinfo + segname: __DWARF + addr: 0x0000000000000146 + size: 1 + offset: 0x000005EE + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x02000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __apple_names + segname: __DWARF + addr: 0x0000000000000147 + size: 116 + offset: 0x000005EF + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x02000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __apple_objc + segname: __DWARF + addr: 0x00000000000001BB + size: 36 + offset: 0x00000663 + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x02000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __apple_namespac + segname: __DWARF + addr: 0x00000000000001DF + size: 36 + offset: 0x00000687 + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x02000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __apple_types + segname: __DWARF + addr: 0x0000000000000203 + size: 71 + offset: 0x000006AB + align: 0 + reloff: 0x00000000 + nreloc: 0 + flags: 0x02000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __compact_unwind + segname: __LD + addr: 0x0000000000000250 + size: 32 + offset: 0x000006F8 + align: 3 + reloff: 0x000007D8 + nreloc: 1 + flags: 0x02000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __eh_frame + segname: __TEXT + addr: 0x0000000000000270 + size: 64 + offset: 0x00000718 + align: 3 + reloff: 0x00000000 + nreloc: 0 + flags: 0x6800000B + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - sectname: __debug_line + segname: __DWARF + addr: 0x00000000000002B0 + size: 77 + offset: 0x00000758 + align: 0 + reloff: 0x000007E0 + nreloc: 1 + flags: 0x02000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - cmd: LC_BUILD_VERSION + cmdsize: 24 + platform: 1 + minos: 658944 + sdk: 0 + ntools: 0 + - cmd: LC_SYMTAB + cmdsize: 24 + symoff: 2024 + nsyms: 3 + stroff: 2072 + strsize: 12 + - cmd: LC_DYSYMTAB + cmdsize: 80 + ilocalsym: 0 + nlocalsym: 0 + iextdefsym: 0 + nextdefsym: 1 + iundefsym: 1 + nundefsym: 2 + tocoff: 0 + ntoc: 0 + modtaboff: 0 + nmodtab: 0 + extrefsymoff: 0 + nextrefsyms: 0 + indirectsymoff: 0 + nindirectsyms: 0 + extreloff: 0 + nextrel: 0 + locreloff: 0 + nlocrel: 0 +LinkEditData: + NameList: + - n_strx: 1 + n_type: 0x0F + n_sect: 1 + n_desc: 0 + n_value: 0 + - n_strx: 9 + n_type: 0x01 + n_sect: 0 + n_desc: 512 + n_value: 4 + - n_strx: 6 + n_type: 0x01 + n_sect: 0 + n_desc: 512 + n_value: 4 + StringTable: + - '' + - _foo + - _b + - _a +DWARF: + debug_str: + - 'Apple LLVM version 10.0.1 (clang-1001.0.46.4)' + - only-section.c + - '/Users/seiya/dev/llvm-project/llvm/build' + - a + - int + - b + - foo + debug_abbrev: + - Code: 0x00000001 + Tag: DW_TAG_compile_unit + Children: DW_CHILDREN_yes + Attributes: + - Attribute: DW_AT_producer + Form: DW_FORM_strp + - Attribute: DW_AT_language + Form: DW_FORM_data2 + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_stmt_list + Form: DW_FORM_sec_offset + - Attribute: DW_AT_comp_dir + Form: DW_FORM_strp + - Attribute: DW_AT_low_pc + Form: DW_FORM_addr + - Attribute: DW_AT_high_pc + Form: DW_FORM_data4 + - Code: 0x00000002 + Tag: DW_TAG_variable + Children: DW_CHILDREN_no + Attributes: + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_type + Form: DW_FORM_ref4 + - Attribute: DW_AT_external + Form: DW_FORM_flag_present + - Attribute: DW_AT_decl_file + Form: DW_FORM_data1 + - Attribute: DW_AT_decl_line + Form: DW_FORM_data1 + - Attribute: DW_AT_location + Form: DW_FORM_exprloc + - Code: 0x00000003 + Tag: DW_TAG_base_type + Children: DW_CHILDREN_no + Attributes: + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_encoding + Form: DW_FORM_data1 + - Attribute: DW_AT_byte_size + Form: DW_FORM_data1 + - Code: 0x00000004 + Tag: DW_TAG_subprogram + Children: DW_CHILDREN_no + Attributes: + - Attribute: DW_AT_low_pc + Form: DW_FORM_addr + - Attribute: DW_AT_high_pc + Form: DW_FORM_data4 + - Attribute: DW_AT_frame_base + Form: DW_FORM_exprloc + - Attribute: DW_AT_name + Form: DW_FORM_strp + - Attribute: DW_AT_decl_file + Form: DW_FORM_data1 + - Attribute: DW_AT_decl_line + Form: DW_FORM_data1 + - Attribute: DW_AT_type + Form: DW_FORM_ref4 + - Attribute: DW_AT_external + Form: DW_FORM_flag_present + debug_info: + - Length: + TotalLength: 113 + Version: 4 + AbbrOffset: 0 + AddrSize: 8 + Entries: + - AbbrCode: 0x00000001 + Values: + - Value: 0x0000000000000000 + - Value: 0x000000000000000C + - Value: 0x000000000000002E + - Value: 0x0000000000000000 + - Value: 0x000000000000003D + - Value: 0x0000000000000000 + - Value: 0x000000000000001A + - AbbrCode: 0x00000002 + Values: + - Value: 0x0000000000000066 + - Value: 0x000000000000003F + - Value: 0x0000000000000001 + - Value: 0x0000000000000001 + - Value: 0x0000000000000001 + - Value: 0x0000000000000009 + BlockData: + - 0x03 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - AbbrCode: 0x00000003 + Values: + - Value: 0x0000000000000068 + - Value: 0x0000000000000005 + - Value: 0x0000000000000004 + - AbbrCode: 0x00000002 + Values: + - Value: 0x000000000000006C + - Value: 0x000000000000003F + - Value: 0x0000000000000001 + - Value: 0x0000000000000001 + - Value: 0x0000000000000001 + - Value: 0x0000000000000009 + BlockData: + - 0x03 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - 0x00 + - AbbrCode: 0x00000004 + Values: + - Value: 0x0000000000000000 + - Value: 0x000000000000001A + - Value: 0x0000000000000001 + BlockData: + - 0x56 + - Value: 0x000000000000006E + - Value: 0x0000000000000001 + - Value: 0x0000000000000002 + - Value: 0x000000000000003F + - Value: 0x0000000000000001 + - AbbrCode: 0x00000000 + Values: [] + debug_line: + - Length: + TotalLength: 73 + Version: 4 + PrologueLength: 38 + MinInstLength: 1 + MaxOpsPerInst: 1 + DefaultIsStmt: 1 + LineBase: 251 + LineRange: 14 + OpcodeBase: 13 + StandardOpcodeLengths: [ 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1 ] + IncludeDirs: [] + Files: + - Name: only-section.c + DirIdx: 0 + ModTime: 0 + Length: 0 + Opcodes: + - Opcode: DW_LNS_extended_op + ExtLen: 9 + SubOpcode: DW_LNE_set_address + Data: 0 + - Opcode: 0x13 + Data: 0 + - Opcode: DW_LNS_set_column + Data: 20 + - Opcode: DW_LNS_set_prologue_end + Data: 20 + - Opcode: DW_LNS_const_add_pc + Data: 20 + - Opcode: 0x20 + Data: 20 + - Opcode: DW_LNS_set_column + Data: 22 + - Opcode: DW_LNS_negate_stmt + Data: 22 + - Opcode: 0x2E + Data: 22 + - Opcode: DW_LNS_set_column + Data: 13 + - Opcode: 0x2E + Data: 13 + - Opcode: DW_LNS_advance_pc + Data: 4 + - Opcode: DW_LNS_extended_op + ExtLen: 1 + SubOpcode: DW_LNE_end_sequence + Data: 4 +... diff --git a/llvm/test/tools/llvm-objcopy/MachO/only-section.test b/llvm/test/tools/llvm-objcopy/MachO/only-section.test new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-objcopy/MachO/only-section.test @@ -0,0 +1,16 @@ +RUN: yaml2obj %p/Inputs/only-section.yaml > %t +RUN: llvm-objcopy --only-section __TEXT,__text --only-section __TEXT,__eh_frame %t %t2 +RUN: llvm-readobj --sections %t2 | FileCheck %s + +CHECK: Name: __text +CHECK-NOT: Name: __debug_str +CHECK-NOT: Name: __debug_abbrev +CHECK-NOT: Name: __debug_info +CHECK-NOT: Name: __debug_macinfo +CHECK-NOT: Name: __apple_names +CHECK-NOT: Name: __apple_objc +CHECK-NOT: Name: __apple_namespac +CHECK-NOT: Name: __apple_types +CHECK-NOT: Name: __compact_unwind +CHECK: Name: __eh_frame +CHECK-NOT: Name: __debug_line diff --git a/llvm/tools/llvm-objcopy/CopyConfig.h b/llvm/tools/llvm-objcopy/CopyConfig.h --- a/llvm/tools/llvm-objcopy/CopyConfig.h +++ b/llvm/tools/llvm-objcopy/CopyConfig.h @@ -96,6 +96,11 @@ NameOrRegex(StringRef Pattern, bool IsRegex); bool operator==(StringRef S) const { return R ? R->match(S) : Name == S; } bool operator!=(StringRef S) const { return !operator==(S); } + + // Checks if this is a cannonical name (",
"). + bool isMachOCannonicalName() const { + return R ? true : is_contained(Name, ','); + } }; struct NewSymbolInfo { diff --git a/llvm/tools/llvm-objcopy/MachO/MachOObjcopy.cpp b/llvm/tools/llvm-objcopy/MachO/MachOObjcopy.cpp --- a/llvm/tools/llvm-objcopy/MachO/MachOObjcopy.cpp +++ b/llvm/tools/llvm-objcopy/MachO/MachOObjcopy.cpp @@ -18,6 +18,37 @@ namespace macho { using namespace object; +using SectionPred = std::function; + +static void removeSections(const CopyConfig &Config, Object &Obj) { + SectionPred RemovePred = [](const Section &) { return false; }; + + if (!Config.OnlySection.empty()) { + RemovePred = [&Config, RemovePred](const Section &Sec) { + if (is_contained(Config.OnlySection, Sec.CannonicalName)) + return false; + + return true; + }; + } + + return Obj.removeSections(RemovePred); +} + +static Error validateOptions(const CopyConfig &Config) { + // TODO: Support section renaming in GNU objcopy for compatibility (see + // http://lists.llvm.org/pipermail/llvm-dev/2019-May/132570.html). + + if (!Config.OnlySection.empty()) { + for (const NameOrRegex &NR : Config.OnlySection) + if (!NR.isMachOCannonicalName()) + return createStringError(errc::invalid_argument, + "Invalid section name (should be formatted as " + "\",
\")"); + } + + return Error::success(); +} static Error handleArgs(const CopyConfig &Config, Object &Obj) { if (Config.AllowBrokenLinks || !Config.BuildIdLinkDir.empty() || @@ -25,10 +56,10 @@ !Config.SplitDWO.empty() || !Config.SymbolsPrefix.empty() || !Config.AllocSectionsPrefix.empty() || !Config.AddSection.empty() || !Config.DumpSection.empty() || !Config.KeepSection.empty() || - !Config.OnlySection.empty() || !Config.SymbolsToGlobalize.empty() || - !Config.SymbolsToKeep.empty() || !Config.SymbolsToLocalize.empty() || - !Config.SymbolsToWeaken.empty() || !Config.SymbolsToKeepGlobal.empty() || - !Config.SectionsToRename.empty() || !Config.SymbolsToRename.empty() || + !Config.SymbolsToGlobalize.empty() || !Config.SymbolsToKeep.empty() || + !Config.SymbolsToLocalize.empty() || !Config.SymbolsToWeaken.empty() || + !Config.SymbolsToKeepGlobal.empty() || !Config.SectionsToRename.empty() || + !Config.SymbolsToRename.empty() || !Config.UnneededSymbolsToRemove.empty() || !Config.SetSectionFlags.empty() || !Config.ToRemove.empty() || Config.ExtractDWO || Config.KeepFileSymbols || Config.LocalizeHidden || @@ -41,6 +72,10 @@ "option not supported by llvm-objcopy for MachO"); } + if (auto E = validateOptions(Config)) + return E; + + removeSections(Config, Obj); return Error::success(); } diff --git a/llvm/tools/llvm-objcopy/MachO/MachOReader.cpp b/llvm/tools/llvm-objcopy/MachO/MachOReader.cpp --- a/llvm/tools/llvm-objcopy/MachO/MachOReader.cpp +++ b/llvm/tools/llvm-objcopy/MachO/MachOReader.cpp @@ -35,6 +35,7 @@ .str(); S.Segname = StringRef(Sec.segname, strnlen(Sec.segname, sizeof(Sec.sectname))).str(); + S.CannonicalName = (Twine(S.Segname) + "," + S.Sectname).str(); S.Addr = Sec.addr; S.Size = Sec.size; S.Offset = Sec.offset; diff --git a/llvm/tools/llvm-objcopy/MachO/Object.h b/llvm/tools/llvm-objcopy/MachO/Object.h --- a/llvm/tools/llvm-objcopy/MachO/Object.h +++ b/llvm/tools/llvm-objcopy/MachO/Object.h @@ -38,6 +38,8 @@ struct Section { std::string Sectname; std::string Segname; + // CannonicalName is a string formatted as “,". + std::string CannonicalName; uint64_t Addr; uint64_t Size; uint32_t Offset; @@ -250,6 +252,8 @@ Optional DataInCodeCommandIndex; /// The index LC_FUNCTION_STARTS load comamnd if present. Optional FunctionStartsCommandIndex; + + void removeSections(function_ref ToRemove); }; } // end namespace macho diff --git a/llvm/tools/llvm-objcopy/MachO/Object.cpp b/llvm/tools/llvm-objcopy/MachO/Object.cpp --- a/llvm/tools/llvm-objcopy/MachO/Object.cpp +++ b/llvm/tools/llvm-objcopy/MachO/Object.cpp @@ -10,6 +10,13 @@ return Symbols[Index].get(); } +void Object::removeSections(function_ref ToRemove) { + for (LoadCommand &LC : LoadCommands) + LC.Sections.erase(std::remove_if(std::begin(LC.Sections), + std::end(LC.Sections), ToRemove), + std::end(LC.Sections)); +} + } // end namespace macho } // end namespace objcopy } // end namespace llvm