diff --git a/llvm/docs/CommandGuide/llvm-strip.rst b/llvm/docs/CommandGuide/llvm-strip.rst --- a/llvm/docs/CommandGuide/llvm-strip.rst +++ b/llvm/docs/CommandGuide/llvm-strip.rst @@ -181,6 +181,10 @@ segments. Note that many tools will not be able to use an object without section headers. +.. option:: -T + + Remove Swift symbols. + EXIT STATUS ----------- diff --git a/llvm/test/tools/llvm-objcopy/MachO/remove-swift-symbols.test b/llvm/test/tools/llvm-objcopy/MachO/remove-swift-symbols.test new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-objcopy/MachO/remove-swift-symbols.test @@ -0,0 +1,221 @@ +## Verify that -T removes Swift symbols. +# RUN: yaml2obj -D FLAGS=0x00200085 -D SEGMENT_NAME=__DATA \ +# RUN: -D SECTION_NAME=__objc_imageinfo -D SECTION_SIZE=8 \ +# RUN: -D SECTION_CONTENT=0000000040070105 %s -o %t1 +# RUN: llvm-strip -x -T %t1 +# RUN: llvm-readobj -symbols %t1 | FileCheck --check-prefix=NO-SWIFT-SYMBOLS %s + +# RUN: yaml2obj -D FLAGS=0x00200085 -D SEGMENT_NAME=__DATA_CONST \ +# RUN: -D SECTION_NAME=__objc_imageinfo -D SECTION_SIZE=8 \ +# RUN: -D SECTION_CONTENT=0000000040070105 %s -o %t2 +# RUN: llvm-strip -x -T %t2 +# RUN: llvm-readobj -symbols %t2 | FileCheck --check-prefix=NO-SWIFT-SYMBOLS %s + +# RUN: yaml2obj -D FLAGS=0x00200085 -D SEGMENT_NAME=__DATA_DIRTY \ +# RUN: -D SECTION_NAME=__objc_imageinfo -D SECTION_SIZE=8 \ +# RUN: -D SECTION_CONTENT=0000000040070105 %s -o %t3 +# RUN: llvm-strip -x -T %t3 +# RUN: llvm-readobj -symbols %t3 | FileCheck --check-prefix=NO-SWIFT-SYMBOLS %s + +# NO-SWIFT-SYMBOLS: Symbols [ +# NO-SWIFT-SYMBOLS-NEXT: Symbol { +# NO-SWIFT-SYMBOLS-NEXT: Name: _main (1) +# NO-SWIFT-SYMBOLS-NEXT: Extern +# NO-SWIFT-SYMBOLS-NEXT: Type: Section (0xE) +# NO-SWIFT-SYMBOLS-NEXT: Section: __text (0x1) +# NO-SWIFT-SYMBOLS-NEXT: RefType: UndefinedNonLazy (0x0) +# NO-SWIFT-SYMBOLS-NEXT: Flags [ (0x0) +# NO-SWIFT-SYMBOLS-NEXT: ] +# NO-SWIFT-SYMBOLS-NEXT: Value: 0x100000B70 +# NO-SWIFT-SYMBOLS-NEXT: } +# NO-SWIFT-SYMBOLS-NEXT: ] + +## Verify that -T does not remove (public) Swift symbols when the binary +## does not contain __objc_imageinfo in one of the expected segments. + +# RUN: yaml2obj -D FLAGS=0x00200085 -D SEGMENT_NAME=__DATA \ +# RUN: -D SECTION_NAME=__not_objc_imageinfo -D SECTION_SIZE=8 \ +# RUN: -D SECTION_CONTENT=0000000040070105 %s -o %t4 +# RUN: llvm-strip -x -T %t4 +# RUN: llvm-readobj -symbols %t4 | FileCheck --check-prefix=SWIFT-SYMBOLS %s + +# RUN: yaml2obj -D FLAGS=0x00200085 -D SEGMENT_NAME=__NOT_DATA \ +# RUN: -D SECTION_NAME=__objc_imageinfo -D SECTION_SIZE=8 \ +# RUN: -D SECTION_CONTENT=0000000040070105 %s -o %t5 +# RUN: llvm-strip -x -T %t5 +# RUN: llvm-readobj -symbols %t5 | FileCheck --check-prefix=SWIFT-SYMBOLS %s + +## Verify that -T does not remove (public) Swift symbols when swift_version is zero. + +# RUN: yaml2obj -D FLAGS=0x00200085 -D SEGMENT_NAME=__DATA \ +# RUN: -D SECTION_NAME=__objc_imageinfo -D SECTION_SIZE=8 \ +# RUN: -D SECTION_CONTENT=0000000000000000 %s -o %t6 +# RUN: llvm-strip -x -T %t6 +# RUN: llvm-readobj -symbols %t6 | FileCheck --check-prefix=SWIFT-SYMBOLS %s + +## Verify that -T does not remove (public) Swift symbols when the binary +## contains invalid (too small) __objc_imageinfo. + +# RUN: yaml2obj -D FLAGS=0x00200085 -D SEGMENT_NAME=__DATA \ +# RUN: -D SECTION_NAME=__objc_imageinfo -D SECTION_SIZE=4 \ +# RUN: -D SECTION_CONTENT=00000000 %s -o %t7 +# RUN: llvm-strip -x -T %t7 +# RUN: llvm-readobj -symbols %t7 | FileCheck --check-prefix=SWIFT-SYMBOLS %s + +## Verify that -T does not remove (public) Swift symbols +## when the flag MH_DYLDLINK is not set. + +# RUN: yaml2obj -D FLAGS=0x00200000 -D SEGMENT_NAME=__DATA \ +# RUN: -D SECTION_NAME=__objc_imageinfo -D SECTION_SIZE=8 \ +# RUN: -D SECTION_CONTENT=0000000040070105 %s -o %t8 +# RUN: llvm-strip -x -T %t8 +# RUN: llvm-readobj -symbols %t8 | FileCheck --check-prefix=SWIFT-SYMBOLS %s + +# SWIFT-SYMBOLS: Symbols [ +# SWIFT-SYMBOLS-NEXT: Symbol { +# SWIFT-SYMBOLS-NEXT: Name: _$S1a13PublicSymbol1Sivp (26) +# SWIFT-SYMBOLS-NEXT: Extern +# SWIFT-SYMBOLS-NEXT: Type: Section (0xE) +# SWIFT-SYMBOLS-NEXT: Section: __text (0x1) +# SWIFT-SYMBOLS-NEXT: RefType: UndefinedNonLazy (0x0) +# SWIFT-SYMBOLS-NEXT: Flags [ (0x0) +# SWIFT-SYMBOLS-NEXT: ] +# SWIFT-SYMBOLS-NEXT: Value: 0x100001160 +# SWIFT-SYMBOLS-NEXT: } +# SWIFT-SYMBOLS-NEXT: Symbol { +# SWIFT-SYMBOLS-NEXT: Name: _$s1a13PublicSymbol2Sivp (1) +# SWIFT-SYMBOLS-NEXT: Extern +# SWIFT-SYMBOLS-NEXT: Type: Section (0xE) +# SWIFT-SYMBOLS-NEXT: Section: __text (0x1) +# SWIFT-SYMBOLS-NEXT: RefType: UndefinedNonLazy (0x0) +# SWIFT-SYMBOLS-NEXT: Flags [ (0x0) +# SWIFT-SYMBOLS-NEXT: ] +# SWIFT-SYMBOLS-NEXT: Value: 0x100001168 +# SWIFT-SYMBOLS-NEXT: } +# SWIFT-SYMBOLS-NEXT: Symbol { +# SWIFT-SYMBOLS-NEXT: Name: _main (51) +# SWIFT-SYMBOLS-NEXT: Extern +# SWIFT-SYMBOLS-NEXT: Type: Section (0xE) +# SWIFT-SYMBOLS-NEXT: Section: __text (0x1) +# SWIFT-SYMBOLS-NEXT: RefType: UndefinedNonLazy (0x0) +# SWIFT-SYMBOLS-NEXT: Flags [ (0x0) +# SWIFT-SYMBOLS-NEXT: ] +# SWIFT-SYMBOLS-NEXT: Value: 0x100000B70 +# SWIFT-SYMBOLS-NEXT: } +# SWIFT-SYMBOLS-NEXT: ] + +--- !mach-o +FileHeader: + magic: 0xFEEDFACF + cputype: 0x01000007 + cpusubtype: 0x80000003 + filetype: 0x00000002 + ncmds: 4 + sizeofcmds: 400 + flags: [[FLAGS]] + reserved: 0x00000000 +LoadCommands: + - cmd: LC_SEGMENT_64 + cmdsize: 152 + segname: __TEXT + vmaddr: 4294967296 + vmsize: 4096 + fileoff: 0 + filesize: 4096 + maxprot: 5 + initprot: 5 + nsects: 1 + flags: 0 + Sections: + - sectname: __text + segname: __TEXT + addr: 0x0000000100000B70 + size: 845 + offset: 0x00000B70 + align: 4 + reloff: 0x00000000 + nreloc: 0 + flags: 0x80000400 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + - cmd: LC_SEGMENT_64 + cmdsize: 152 + segname: [[SEGMENT_NAME]] + vmaddr: 4294971392 + vmsize: 4096 + fileoff: 4096 + filesize: 4096 + maxprot: 3 + initprot: 3 + nsects: 1 + flags: 0 + Sections: + - sectname: [[SECTION_NAME]] + segname: [[SEGMENT_NAME]] + addr: 0x0000000100001090 + size: [[SECTION_SIZE]] + offset: 0x00001090 + align: 2 + reloff: 0x00000000 + nreloc: 0 + flags: 0x00000000 + reserved1: 0x00000000 + reserved2: 0x00000000 + reserved3: 0x00000000 + content: "[[SECTION_CONTENT]]" + - cmd: LC_SEGMENT_64 + cmdsize: 72 + segname: __LINKEDIT + vmaddr: 4294975488 + vmsize: 4096 + fileoff: 8192 + filesize: 188 + maxprot: 1 + initprot: 1 + nsects: 0 + flags: 0 + - cmd: LC_SYMTAB + cmdsize: 24 + symoff: 8192 + nsyms: 5 + stroff: 8272 + strsize: 108 +LinkEditData: + NameList: + - n_strx: 50 + n_type: 0x1E + n_sect: 1 + n_desc: 0 + n_value: 4294971760 + - n_strx: 1 + n_type: 0x1E + n_sect: 1 + n_desc: 0 + n_value: 4294971768 + - n_strx: 74 + n_type: 0x0F + n_sect: 1 + n_desc: 0 + n_value: 4294971744 + - n_strx: 25 + n_type: 0x0F + n_sect: 1 + n_desc: 0 + n_value: 4294971752 + - n_strx: 99 + n_type: 0x0F + n_sect: 1 + n_desc: 0 + n_value: 4294970224 + StringTable: + - '' + - '_$s1a12LocalSymbol2Sivp' + - '_$s1a13PublicSymbol2Sivp' + - '_$S1a12LocalSymbol1Sivp' + - '_$S1a13PublicSymbol1Sivp' + - _main + - '' + - '' + - '' +... diff --git a/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp b/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp --- a/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp +++ b/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp @@ -251,7 +251,8 @@ !Config.SymbolsToKeepGlobal.empty() || !Config.SectionsToRename.empty() || !Config.SetSectionAlignment.empty() || Config.ExtractDWO || Config.LocalizeHidden || Config.PreserveDates || Config.StripDWO || - Config.StripNonAlloc || Config.StripSections || Config.Weaken || + Config.StripNonAlloc || Config.StripSections || + Config.StripSwiftSymbols || Config.Weaken || Config.DecompressDebugSections || Config.DiscardMode == DiscardType::Locals || !Config.SymbolsToAdd.empty() || Config.EntryExpr) { 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 @@ -219,6 +219,7 @@ bool StripDebug = false; bool StripNonAlloc = false; bool StripSections = false; + bool StripSwiftSymbols = false; bool StripUnneeded = false; bool Weaken = false; bool DecompressDebugSections = false; diff --git a/llvm/tools/llvm-objcopy/CopyConfig.cpp b/llvm/tools/llvm-objcopy/CopyConfig.cpp --- a/llvm/tools/llvm-objcopy/CopyConfig.cpp +++ b/llvm/tools/llvm-objcopy/CopyConfig.cpp @@ -912,6 +912,7 @@ if (auto Arg = InputArgs.getLastArg(STRIP_strip_all, STRIP_no_strip_all)) Config.StripAll = Arg->getOption().getID() == STRIP_strip_all; Config.StripAllGNU = InputArgs.hasArg(STRIP_strip_all_gnu); + Config.StripSwiftSymbols = InputArgs.hasArg(STRIP_strip_swift_symbols); Config.OnlyKeepDebug = InputArgs.hasArg(STRIP_only_keep_debug); Config.KeepFileSymbols = InputArgs.hasArg(STRIP_keep_file_symbols); diff --git a/llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp b/llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp --- a/llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp +++ b/llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp @@ -604,7 +604,9 @@ // system. The only priority is that keeps/copies overrule removes. static Error handleArgs(const CopyConfig &Config, Object &Obj, const Reader &Reader, ElfType OutputElfType) { - + if (Config.StripSwiftSymbols) + return createStringError(llvm::errc::invalid_argument, + "option not supported by llvm-objcopy for ELF"); if (!Config.SplitDWO.empty()) if (Error E = splitDWOToFile(Config, Reader, Config.SplitDWO, OutputElfType)) 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 @@ -65,13 +65,17 @@ Sym.Name = std::string(I->getValue()); } - auto RemovePred = [Config](const std::unique_ptr &N) { + auto RemovePred = [Config, &Obj](const std::unique_ptr &N) { if (N->Referenced) return false; if (Config.StripAll) return true; if (Config.DiscardMode == DiscardType::All && !(N->n_type & MachO::N_EXT)) return true; + // This behavior is consistent with cctools' strip. + if (Config.StripSwiftSymbols && (Obj.Header.Flags & MachO::MH_DYLDLINK) && + Obj.SwiftVersion && *Obj.SwiftVersion && N->isSwiftSymbol()) + return true; return false; }; diff --git a/llvm/tools/llvm-objcopy/MachO/MachOReader.h b/llvm/tools/llvm-objcopy/MachO/MachOReader.h --- a/llvm/tools/llvm-objcopy/MachO/MachOReader.h +++ b/llvm/tools/llvm-objcopy/MachO/MachOReader.h @@ -39,6 +39,7 @@ void readDataInCodeData(Object &O) const; void readFunctionStartsData(Object &O) const; void readIndirectSymbolTable(Object &O) const; + void readSwiftVersion(Object &O) const; public: explicit MachOReader(const object::MachOObjectFile &Obj) : MachOObj(Obj) {} 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 @@ -283,6 +283,28 @@ } } +void MachOReader::readSwiftVersion(Object &O) const { + struct ObjCImageInfo { + uint32_t Version; + uint32_t Flags; + } ImageInfo; + + for (const LoadCommand &LC : O.LoadCommands) + for (const std::unique_ptr
&Sec : LC.Sections) + if (Sec->Sectname == "__objc_imageinfo" && + (Sec->Segname == "__DATA" || Sec->Segname == "__DATA_CONST" || + Sec->Segname == "__DATA_DIRTY") && + Sec->Content.size() >= sizeof(ObjCImageInfo)) { + memcpy(&ImageInfo, Sec->Content.data(), sizeof(ObjCImageInfo)); + if (MachOObj.isLittleEndian() != sys::IsLittleEndianHost) { + sys::swapByteOrder(ImageInfo.Version); + sys::swapByteOrder(ImageInfo.Flags); + } + O.SwiftVersion = (ImageInfo.Flags >> 8) & 0xff; + return; + } +} + std::unique_ptr MachOReader::create() const { auto Obj = std::make_unique(); readHeader(*Obj); @@ -297,6 +319,7 @@ readDataInCodeData(*Obj); readFunctionStartsData(*Obj); readIndirectSymbolTable(*Obj); + readSwiftVersion(*Obj); return Obj; } 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 @@ -115,6 +115,11 @@ return (n_type & MachO::N_TYPE) == MachO::N_UNDF; } + bool isSwiftSymbol() const { + return StringRef(Name).startswith("_$s") || + StringRef(Name).startswith("_$S"); + } + Optional section() const { return n_sect == MachO::NO_SECT ? None : Optional(n_sect); } @@ -298,6 +303,8 @@ LinkData DataInCode; LinkData FunctionStarts; + Optional SwiftVersion; + /// The index of LC_SYMTAB load command if present. Optional SymTabCommandIndex; /// The index of LC_DYLD_INFO or LC_DYLD_INFO_ONLY load command if present. diff --git a/llvm/tools/llvm-objcopy/StripOpts.td b/llvm/tools/llvm-objcopy/StripOpts.td --- a/llvm/tools/llvm-objcopy/StripOpts.td +++ b/llvm/tools/llvm-objcopy/StripOpts.td @@ -15,3 +15,6 @@ def S : Flag<["-"], "S">, Alias, HelpText<"Alias for --strip-debug">; + +def strip_swift_symbols : Flag<["-"], "T">, + HelpText<"Remove Swift symbols">;