[llvm][llvm-nm] add TextAPI/MachO support

Summary:
This completes the needed glueing to support reading tbd files from nm.
This includes specifying which slice filtering with `--arch` and a new
option specifically for tbd files `--add-inlinedinfo` which will show
the reexported libraries that are appended in the tbd file.

Reviewers: ributzka, steven_wu, JDevlieghere, jhenderson

Reviewed By: JDevlieghere

Subscribers: hiraditya, MaskRay, dexonsmith, rupprecht, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D81614
This commit is contained in:
Cyndy Ishida 2020-06-11 18:32:45 -07:00
parent 519b019a0a
commit 28fefcc83c
19 changed files with 352 additions and 33 deletions

View File

@ -246,6 +246,10 @@ MACH-O SPECIFIC OPTIONS
Add symbols from the dyldinfo, if they are not already in the symbol table. Add symbols from the dyldinfo, if they are not already in the symbol table.
This is the default. This is the default.
.. option:: --add-inlinedinfo
Add symbols from the inlined libraries, TBD file inputs only.
.. option:: --arch=<arch1[,arch2,...]> .. option:: --arch=<arch1[,arch2,...]>
Dump the symbols from the specified architecture(s). Dump the symbols from the specified architecture(s).

View File

@ -41,6 +41,8 @@ public:
static bool classof(const Binary *v) { return v->isTapiFile(); } static bool classof(const Binary *v) { return v->isTapiFile(); }
bool is64Bit() { return MachO::is64Bit(Arch); }
private: private:
struct Symbol { struct Symbol {
StringRef Prefix; StringRef Prefix;
@ -52,6 +54,7 @@ private:
}; };
std::vector<Symbol> Symbols; std::vector<Symbol> Symbols;
MachO::Architecture Arch;
}; };
} // end namespace object. } // end namespace object.

View File

@ -41,18 +41,26 @@ public:
uint32_t getCPUType() const { uint32_t getCPUType() const {
auto Result = auto Result =
MachO::getCPUTypeFromArchitecture(Parent->Architectures[Index]); MachO::getCPUTypeFromArchitecture(Parent->Libraries[Index].Arch);
return Result.first; return Result.first;
} }
uint32_t getCPUSubType() const { uint32_t getCPUSubType() const {
auto Result = auto Result =
MachO::getCPUTypeFromArchitecture(Parent->Architectures[Index]); MachO::getCPUTypeFromArchitecture(Parent->Libraries[Index].Arch);
return Result.second; return Result.second;
} }
StringRef getArchFlagName() const { StringRef getArchFlagName() const {
return MachO::getArchitectureName(Parent->Architectures[Index]); return MachO::getArchitectureName(Parent->Libraries[Index].Arch);
}
std::string getInstallName() const {
return std::string(Parent->Libraries[Index].InstallName);
}
bool isTopLevelLib() const {
return Parent->ParsedFile->getInstallName() == getInstallName();
} }
Expected<std::unique_ptr<TapiFile>> getAsObjectFile() const; Expected<std::unique_ptr<TapiFile>> getAsObjectFile() const;
@ -86,21 +94,25 @@ public:
object_iterator begin_objects() const { return ObjectForArch(this, 0); } object_iterator begin_objects() const { return ObjectForArch(this, 0); }
object_iterator end_objects() const { object_iterator end_objects() const {
return ObjectForArch(this, Architectures.size()); return ObjectForArch(this, Libraries.size());
} }
iterator_range<object_iterator> objects() const { iterator_range<object_iterator> objects() const {
return make_range(begin_objects(), end_objects()); return make_range(begin_objects(), end_objects());
} }
uint32_t getNumberOfObjects() const { return Architectures.size(); } uint32_t getNumberOfObjects() const { return Libraries.size(); }
// Cast methods.
static bool classof(const Binary *v) { return v->isTapiUniversal(); } static bool classof(const Binary *v) { return v->isTapiUniversal(); }
private: private:
struct Library {
StringRef InstallName;
MachO::Architecture Arch;
};
std::unique_ptr<MachO::InterfaceFile> ParsedFile; std::unique_ptr<MachO::InterfaceFile> ParsedFile;
std::vector<MachO::Architecture> Architectures; std::vector<Library> Libraries;
}; };
} // end namespace object. } // end namespace object.

View File

@ -13,27 +13,27 @@
/// ///
/// X86 architectures sorted by cpu type and sub type id. /// X86 architectures sorted by cpu type and sub type id.
/// ///
ARCHINFO(i386, MachO::CPU_TYPE_I386, MachO::CPU_SUBTYPE_I386_ALL) ARCHINFO(i386, MachO::CPU_TYPE_I386, MachO::CPU_SUBTYPE_I386_ALL, 32)
ARCHINFO(x86_64, MachO::CPU_TYPE_X86_64, MachO::CPU_SUBTYPE_X86_64_ALL) ARCHINFO(x86_64, MachO::CPU_TYPE_X86_64, MachO::CPU_SUBTYPE_X86_64_ALL, 64)
ARCHINFO(x86_64h, MachO::CPU_TYPE_X86_64, MachO::CPU_SUBTYPE_X86_64_H) ARCHINFO(x86_64h, MachO::CPU_TYPE_X86_64, MachO::CPU_SUBTYPE_X86_64_H, 64)
/// ///
/// ARM architectures sorted by cpu sub type id. /// ARM architectures sorted by cpu sub type id.
/// ///
ARCHINFO(armv4t, MachO::CPU_TYPE_ARM, MachO::CPU_SUBTYPE_ARM_V4T) ARCHINFO(armv4t, MachO::CPU_TYPE_ARM, MachO::CPU_SUBTYPE_ARM_V4T, 32)
ARCHINFO(armv6, MachO::CPU_TYPE_ARM, MachO::CPU_SUBTYPE_ARM_V6) ARCHINFO(armv6, MachO::CPU_TYPE_ARM, MachO::CPU_SUBTYPE_ARM_V6, 32)
ARCHINFO(armv5, MachO::CPU_TYPE_ARM, MachO::CPU_SUBTYPE_ARM_V5TEJ) ARCHINFO(armv5, MachO::CPU_TYPE_ARM, MachO::CPU_SUBTYPE_ARM_V5TEJ, 32)
ARCHINFO(armv7, MachO::CPU_TYPE_ARM, MachO::CPU_SUBTYPE_ARM_V7) ARCHINFO(armv7, MachO::CPU_TYPE_ARM, MachO::CPU_SUBTYPE_ARM_V7, 32)
ARCHINFO(armv7s, MachO::CPU_TYPE_ARM, MachO::CPU_SUBTYPE_ARM_V7S) ARCHINFO(armv7s, MachO::CPU_TYPE_ARM, MachO::CPU_SUBTYPE_ARM_V7S, 32)
ARCHINFO(armv7k, MachO::CPU_TYPE_ARM, MachO::CPU_SUBTYPE_ARM_V7K) ARCHINFO(armv7k, MachO::CPU_TYPE_ARM, MachO::CPU_SUBTYPE_ARM_V7K, 32)
ARCHINFO(armv6m, MachO::CPU_TYPE_ARM, MachO::CPU_SUBTYPE_ARM_V6M) ARCHINFO(armv6m, MachO::CPU_TYPE_ARM, MachO::CPU_SUBTYPE_ARM_V6M, 32)
ARCHINFO(armv7m, MachO::CPU_TYPE_ARM, MachO::CPU_SUBTYPE_ARM_V7M) ARCHINFO(armv7m, MachO::CPU_TYPE_ARM, MachO::CPU_SUBTYPE_ARM_V7M, 32)
ARCHINFO(armv7em, MachO::CPU_TYPE_ARM, MachO::CPU_SUBTYPE_ARM_V7EM) ARCHINFO(armv7em, MachO::CPU_TYPE_ARM, MachO::CPU_SUBTYPE_ARM_V7EM, 32)
/// ///
/// ARM64 architectures sorted by cpu sub type id. /// ARM64 architectures sorted by cpu sub type id.
/// ///
ARCHINFO(arm64, MachO::CPU_TYPE_ARM64, MachO::CPU_SUBTYPE_ARM64_ALL) ARCHINFO(arm64, MachO::CPU_TYPE_ARM64, MachO::CPU_SUBTYPE_ARM64_ALL, 64)
ARCHINFO(arm64e, MachO::CPU_TYPE_ARM64, MachO::CPU_SUBTYPE_ARM64E) ARCHINFO(arm64e, MachO::CPU_TYPE_ARM64, MachO::CPU_SUBTYPE_ARM64E, 64)

View File

@ -25,7 +25,7 @@ namespace MachO {
/// Defines the architecture slices that are supported by Text-based Stub files. /// Defines the architecture slices that are supported by Text-based Stub files.
enum Architecture : uint8_t { enum Architecture : uint8_t {
#define ARCHINFO(Arch, Type, SubType) AK_##Arch, #define ARCHINFO(Arch, Type, SubType, NumBits) AK_##Arch,
#include "llvm/TextAPI/MachO/Architecture.def" #include "llvm/TextAPI/MachO/Architecture.def"
#undef ARCHINFO #undef ARCHINFO
AK_unknown, // this has to go last. AK_unknown, // this has to go last.
@ -46,6 +46,9 @@ std::pair<uint32_t, uint32_t> getCPUTypeFromArchitecture(Architecture Arch);
/// Convert a target to an architecture slice. /// Convert a target to an architecture slice.
Architecture mapToArchitecture(const llvm::Triple &Target); Architecture mapToArchitecture(const llvm::Triple &Target);
/// Check if architecture is 64 bit.
bool is64Bit(Architecture);
raw_ostream &operator<<(raw_ostream &OS, Architecture Arch); raw_ostream &operator<<(raw_ostream &OS, Architecture Arch);
} // end namespace MachO. } // end namespace MachO.

View File

@ -40,7 +40,7 @@ static uint32_t getFlags(const Symbol *Sym) {
TapiFile::TapiFile(MemoryBufferRef Source, const InterfaceFile &interface, TapiFile::TapiFile(MemoryBufferRef Source, const InterfaceFile &interface,
Architecture Arch) Architecture Arch)
: SymbolicFile(ID_TapiFile, Source) { : SymbolicFile(ID_TapiFile, Source), Arch(Arch) {
for (const auto *Symbol : interface.symbols()) { for (const auto *Symbol : interface.symbols()) {
if (!Symbol->getArchitectures().has(Arch)) if (!Symbol->getArchitectures().has(Arch))
continue; continue;

View File

@ -22,7 +22,7 @@ using namespace object;
TapiUniversal::TapiUniversal(MemoryBufferRef Source, Error &Err) TapiUniversal::TapiUniversal(MemoryBufferRef Source, Error &Err)
: Binary(ID_TapiUniversal, Source) { : Binary(ID_TapiUniversal, Source) {
auto Result = TextAPIReader::get(Source); Expected<std::unique_ptr<InterfaceFile>> Result = TextAPIReader::get(Source);
ErrorAsOutParameter ErrAsOuParam(&Err); ErrorAsOutParameter ErrAsOuParam(&Err);
if (!Result) { if (!Result) {
Err = Result.takeError(); Err = Result.takeError();
@ -30,9 +30,16 @@ TapiUniversal::TapiUniversal(MemoryBufferRef Source, Error &Err)
} }
ParsedFile = std::move(Result.get()); ParsedFile = std::move(Result.get());
auto Archs = ParsedFile->getArchitectures(); auto FlattenObjectInfo = [this](const auto &File) {
for (auto Arch : Archs) StringRef Name = File->getInstallName();
Architectures.emplace_back(Arch); for (const Architecture Arch : File->getArchitectures())
Libraries.emplace_back(Library({Name, Arch}));
};
FlattenObjectInfo(ParsedFile);
// Get inlined documents from tapi file.
for (const std::shared_ptr<InterfaceFile> &File : ParsedFile->documents())
FlattenObjectInfo(File);
} }
TapiUniversal::~TapiUniversal() = default; TapiUniversal::~TapiUniversal() = default;
@ -41,7 +48,7 @@ Expected<std::unique_ptr<TapiFile>>
TapiUniversal::ObjectForArch::getAsObjectFile() const { TapiUniversal::ObjectForArch::getAsObjectFile() const {
return std::unique_ptr<TapiFile>(new TapiFile(Parent->getMemoryBufferRef(), return std::unique_ptr<TapiFile>(new TapiFile(Parent->getMemoryBufferRef(),
*Parent->ParsedFile.get(), *Parent->ParsedFile.get(),
Parent->Architectures[Index])); Parent->Libraries[Index].Arch));
} }
Expected<std::unique_ptr<TapiUniversal>> Expected<std::unique_ptr<TapiUniversal>>

View File

@ -15,12 +15,13 @@
#include "llvm/ADT/Triple.h" #include "llvm/ADT/Triple.h"
#include "llvm/BinaryFormat/MachO.h" #include "llvm/BinaryFormat/MachO.h"
#include "llvm/Support/raw_ostream.h" #include "llvm/Support/raw_ostream.h"
#include "llvm/TextAPI/MachO/ArchitectureSet.h"
namespace llvm { namespace llvm {
namespace MachO { namespace MachO {
Architecture getArchitectureFromCpuType(uint32_t CPUType, uint32_t CPUSubType) { Architecture getArchitectureFromCpuType(uint32_t CPUType, uint32_t CPUSubType) {
#define ARCHINFO(Arch, Type, Subtype) \ #define ARCHINFO(Arch, Type, Subtype, NumBits) \
if (CPUType == (Type) && \ if (CPUType == (Type) && \
(CPUSubType & ~MachO::CPU_SUBTYPE_MASK) == (Subtype)) \ (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) == (Subtype)) \
return AK_##Arch; return AK_##Arch;
@ -32,7 +33,7 @@ Architecture getArchitectureFromCpuType(uint32_t CPUType, uint32_t CPUSubType) {
Architecture getArchitectureFromName(StringRef Name) { Architecture getArchitectureFromName(StringRef Name) {
return StringSwitch<Architecture>(Name) return StringSwitch<Architecture>(Name)
#define ARCHINFO(Arch, Type, Subtype) .Case(#Arch, AK_##Arch) #define ARCHINFO(Arch, Type, Subtype, NumBits) .Case(#Arch, AK_##Arch)
#include "llvm/TextAPI/MachO/Architecture.def" #include "llvm/TextAPI/MachO/Architecture.def"
#undef ARCHINFO #undef ARCHINFO
.Default(AK_unknown); .Default(AK_unknown);
@ -40,7 +41,7 @@ Architecture getArchitectureFromName(StringRef Name) {
StringRef getArchitectureName(Architecture Arch) { StringRef getArchitectureName(Architecture Arch) {
switch (Arch) { switch (Arch) {
#define ARCHINFO(Arch, Type, Subtype) \ #define ARCHINFO(Arch, Type, Subtype, NumBits) \
case AK_##Arch: \ case AK_##Arch: \
return #Arch; return #Arch;
#include "llvm/TextAPI/MachO/Architecture.def" #include "llvm/TextAPI/MachO/Architecture.def"
@ -56,7 +57,7 @@ StringRef getArchitectureName(Architecture Arch) {
std::pair<uint32_t, uint32_t> getCPUTypeFromArchitecture(Architecture Arch) { std::pair<uint32_t, uint32_t> getCPUTypeFromArchitecture(Architecture Arch) {
switch (Arch) { switch (Arch) {
#define ARCHINFO(Arch, Type, Subtype) \ #define ARCHINFO(Arch, Type, Subtype, NumBits) \
case AK_##Arch: \ case AK_##Arch: \
return std::make_pair(Type, Subtype); return std::make_pair(Type, Subtype);
#include "llvm/TextAPI/MachO/Architecture.def" #include "llvm/TextAPI/MachO/Architecture.def"
@ -74,6 +75,20 @@ Architecture mapToArchitecture(const Triple &Target) {
return getArchitectureFromName(Target.getArchName()); return getArchitectureFromName(Target.getArchName());
} }
bool is64Bit(Architecture Arch) {
switch (Arch) {
#define ARCHINFO(Arch, Type, Subtype, NumBits) \
case AK_##Arch: \
return NumBits == 64;
#include "llvm/TextAPI/MachO/Architecture.def"
#undef ARCHINFO
case AK_unknown:
return false;
}
llvm_unreachable("Fully handled switch case above.");
}
raw_ostream &operator<<(raw_ostream &OS, Architecture Arch) { raw_ostream &operator<<(raw_ostream &OS, Architecture Arch) {
OS << getArchitectureName(Arch); OS << getArchitectureName(Arch);
return OS; return OS;

View File

@ -129,7 +129,7 @@ QuotingType ScalarTraits<PlatformSet>::mustQuote(StringRef) {
void ScalarBitSetTraits<ArchitectureSet>::bitset(IO &IO, void ScalarBitSetTraits<ArchitectureSet>::bitset(IO &IO,
ArchitectureSet &Archs) { ArchitectureSet &Archs) {
#define ARCHINFO(arch, type, subtype) \ #define ARCHINFO(arch, type, subtype, numbits) \
IO.bitSetCase(Archs, #arch, 1U << static_cast<int>(AK_##arch)); IO.bitSetCase(Archs, #arch, 1U << static_cast<int>(AK_##arch));
#include "llvm/TextAPI/MachO/Architecture.def" #include "llvm/TextAPI/MachO/Architecture.def"
#undef ARCHINFO #undef ARCHINFO

View File

@ -0,0 +1,15 @@
--- !tapi-tbd-v1
archs: [ armv7, armv7s, arm64 ]
platform: ios
install-name: /u/l/libfoo.dylib
current-version: 1.2.3
compatibility-version: 1.0
swift-version: 0
objc-constraint: none
expors:
- archs: [ arm64, armv7 ]
allowed-clients: [ client ]
symbols: [ _sym, _test, _a, _b, ]
...

View File

@ -0,0 +1,21 @@
--- !tapi-tbd-v2
uuids: [ "armv7: 00000000-0000-0000-0000-000000000000",
"armv7s: 11111111-1111-1111-1111-111111111111",
"arm64: 22222222-2222-2222-2222-222222222222" ]
platform: ios
flags: [ installapi ]
install-name: /u/l/libfoo.dylib
current-version: 1.2.3
compatibility-version: 1.0
swift-version: 0
objc-constraint: retain_release
parent-umbrella: Umbrella.dylib
exports:
- archs: [ armv7, armv7s, arm64 ]
allowable-clients: [ client ]
re-exports: [ ]
symbols: [ _sym1, _sym2, _sym3 ]
undefineds:
- archs: [ arm64 ]
symbols: [ _sym ]
...

View File

@ -0,0 +1,23 @@
--- !tapi-tbd-v3
archs: [ i386, armv7, armv7s ]
platform: ios
install-name: /usr/lib/libfoo.dylib
swift-abi-version: 3
exports:
- archs: [ i386, armv7, armv7s ]
re-exports: [ /usr/lib/external/liba.dylib ]
symbols: [ _sym1, _sym2 ]
objc-classes: [ NSString, NSBlockPredicate ]
objc-eh-types: [ NSString ]
objc-ivars: [ NSBlockPredicate._block ]
- archs: [ i386 ]
symbols: [ _sym3 ]
--- !tapi-tbd-v3
archs: [ armv7, armv7s ]
platform: ios
install-name: /usr/lib/liba.dylib
swift-version: 3
exports:
- archs: [ armv7, armv7s ]
symbols: [ _sym10, _sym11 ]
...

View File

@ -0,0 +1,15 @@
--- !tapi-tbd-v1
archs: [ armv7, armv7s ]
platform: ios
install-name: /u/l/libfoo.dylib
current-version: 1.2.3
compatibility-version: 1.0
swift-version: 0
objc-constraint: none
exports:
- archs: [ armv7, armv7s ]
allowed-clients: [ client ]
symbols: [ _sym, ]
...

View File

@ -0,0 +1,21 @@
--- !tapi-tbd-v2
archs: [ armv7, armv7s, arm64 ]
uuids: [ "armv7: 00000000-0000-0000-0000-000000000000",
"armv7s: 11111111-1111-1111-1111-111111111111",
"arm64: 22222222-2222-2222-2222-222222222222" ]
platform: ios
flags: [ installapi, flat_namespace ]
install-name: /u/l/libfoo.dylib
current-version: 1.2.3
compatibility-version: 1.0
swift-version: 0
objc-constraint: retain_release
parent-umbrella: Umbrella.dylib
exports:
- archs: [ armv7, armv7s, arm64 ]
symbols: [ _sym1, _sym2, _sym3 ]
undefineds:
- archs: [ arm64 ]
symbols: [ _sym ]
...

View File

@ -0,0 +1,24 @@
--- !tapi-tbd-v3
archs: [ i386, x86_64 ]
platform: ios
install-name: /usr/lib/libfoo.dylib
swift-abi-version: 3
exports:
- archs: [ i386, x86_64 ]
re-exports: [ /usr/lib/external/liba.dylib ]
symbols: [ _sym1, _sym2 ]
objc-classes: [ NSString, NSBlockPredicate ]
objc-eh-types: [ NSString ]
objc-ivars: [ NSBlockPredicate._block ]
- archs: [ i386 ]
symbols: [ _sym3 ]
--- !tapi-tbd-v3
archs: [ x86_64 ]
platform: ios
install-name: /usr/lib/liba.dylib
swift-abi-version: 3
parent-umbrella: foo
exports:
- archs: [ x86_64 ]
symbols: [ _sym10, _sym11 ]
...

View File

@ -0,0 +1,38 @@
--- !tapi-tbd
tbd-version: 4
targets: [ i386-ios-simulator, x86_64-ios-simulator ]
uuids:
- target: i386-ios-simulator
value: 00000000-0000-0000-0000-000000000000
- target: x86_64-ios-simulator
value: 12FF0E69-DD5A-3356-BB9E-24A133D816F0
install-name: '/u/l/libFoo.dylib'
current-version: 1288
reexported-libraries:
- targets: [ i386-ios-simulator, x86_64-ios-simulator ]
libraries: [ '/u/l/s/libPrivate.dylib', '/u/l/libPublic.dylib' ]
exports:
- targets: [ i386-ios-simulator ]
symbols: [ '_sym1' ]
weak-symbols: [ '_sym2' ]
- targets: [ x86_64-ios-simulator, i386-ios-simulator ]
symbols: [ '_sym3', '_sym4' ]
--- !tapi-tbd
tbd-version: 4
targets: [ i386-ios-simulator, x86_64-ios-simulator ]
uuids:
- target: i386-ios-simulator
value: 2E88EC2B-F951-3D76-B114-F6CC635EFE8C
- target: x86_64-ios-simulator
value: 42CD91A1-9824-3FC3-81B2-5355D95C99C7
install-name: '/u/l/s/libPrivate.dylib'
current-version: 60177
parent-umbrella:
- targets: [ i386-ios-simulator, x86_64-ios-simulator ]
umbrella: Foo
exports:
- targets: [ x86_64-ios-simulator ]
symbols: [ '_sym1', '_sym2' ]
- targets: [ x86_64-ios-simulator, i386-ios-simulator ]
symbols: [ '_sym3', '_sym4' ]
...

View File

@ -0,0 +1,20 @@
RUN: not llvm-nm %p/Inputs/tapi-invalid-v1.tbd 2>&1\
RUN: | FileCheck %s -check-prefix V1
RUN: not llvm-nm %p/Inputs/tapi-invalid-v2.tbd 2>&1\
RUN: | FileCheck %s -check-prefix V2
RUN: not llvm-nm %p/Inputs/tapi-invalid-v3.tbd 2>&1\
RUN: | FileCheck %s -check-prefix V3
# Typo Check
V1: tapi-invalid-v1.tbd malformed file
V1-NEXT: tapi-invalid-v1.tbd:12:2: error: unknown key 'expors'
# Missing required key
V2: tapi-invalid-v2.tbd malformed file
V2-NEXT: tapi-invalid-v2.tbd:2:1: error: missing required key 'archs'
# v2 key in v3 specified file
V3: tapi-invalid-v3.tbd malformed file
V3-NEXT: tapi-invalid-v3.tbd:19:16: error: unknown key 'swift-version'

View File

@ -0,0 +1,58 @@
RUN: llvm-nm %p/Inputs/tapi-v1.tbd 2>&1\
RUN: | FileCheck %s -check-prefix V1
RUN: llvm-nm %p/Inputs/tapi-v2.tbd \
RUN: | FileCheck %s -check-prefix V2
RUN: llvm-nm --add-inlinedinfo --arch=x86_64 %p/Inputs/tapi-v3.tbd \
RUN: | FileCheck %s -check-prefix V3
RUN: llvm-nm %p/Inputs/tapi-v4.tbd \
RUN: | FileCheck %s -check-prefix V4
V1: /u/l/libfoo.dylib (for architecture armv7):
V1-NEXT: 00000000 S _sym
V1: /u/l/libfoo.dylib (for architecture armv7s):
V1-NEXT: 00000000 S _sym
V2: /u/l/libfoo.dylib (for architecture armv7):
V2-NEXT: 00000000 S _sym1
V2-NEXT: 00000000 S _sym2
V2-NEXT: 00000000 S _sym3
V2: /u/l/libfoo.dylib (for architecture armv7s):
V2-NEXT: 00000000 S _sym1
V2-NEXT: 00000000 S _sym2
V2-NEXT: 00000000 S _sym3
V2: /u/l/libfoo.dylib (for architecture arm64):
V2-NEXT: U _sym
V2-NEXT: 0000000000000000 S _sym1
V2-NEXT: 0000000000000000 S _sym2
V2-NEXT: 0000000000000000 S _sym3
V3: /usr/lib/libfoo.dylib (for architecture x86_64):
V3-NEXT: 0000000000000000 S _OBJC_CLASS_$_NSBlockPredicate
V3-NEXT: 0000000000000000 S _OBJC_CLASS_$_NSString
V3-NEXT: 0000000000000000 S _OBJC_EHTYPE_$_NSString
V3-NEXT: 0000000000000000 S _OBJC_IVAR_$_NSBlockPredicate._block
V3-NEXT: 0000000000000000 S _OBJC_METACLASS_$_NSBlockPredicate
V3-NEXT: 0000000000000000 S _OBJC_METACLASS_$_NSString
V3-NEXT: 0000000000000000 S _sym1
V3-NEXT: 0000000000000000 S _sym2
V3: /usr/lib/liba.dylib (for architecture x86_64):
V3-NEXT: 0000000000000000 S _OBJC_CLASS_$_NSBlockPredicate
V3-NEXT: 0000000000000000 S _OBJC_CLASS_$_NSString
V3-NEXT: 0000000000000000 S _OBJC_EHTYPE_$_NSString
V3-NEXT: 0000000000000000 S _OBJC_IVAR_$_NSBlockPredicate._block
V3-NEXT: 0000000000000000 S _OBJC_METACLASS_$_NSBlockPredicate
V3-NEXT: 0000000000000000 S _OBJC_METACLASS_$_NSString
V3-NEXT: 0000000000000000 S _sym1
V3-NEXT: 0000000000000000 S _sym2
V4: /u/l/libFoo.dylib (for architecture i386):
V4-NEXT: 00000000 S _sym1
V4-NEXT: 00000000 W _sym2
V4-NEXT: 00000000 S _sym3
V4-NEXT: 00000000 S _sym4
V4: /u/l/libFoo.dylib (for architecture x86_64):
V4-NEXT: 0000000000000000 S _sym3
V4-NEXT: 0000000000000000 S _sym4

View File

@ -28,6 +28,8 @@
#include "llvm/Object/MachO.h" #include "llvm/Object/MachO.h"
#include "llvm/Object/MachOUniversal.h" #include "llvm/Object/MachOUniversal.h"
#include "llvm/Object/ObjectFile.h" #include "llvm/Object/ObjectFile.h"
#include "llvm/Object/TapiFile.h"
#include "llvm/Object/TapiUniversal.h"
#include "llvm/Object/Wasm.h" #include "llvm/Object/Wasm.h"
#include "llvm/Support/CommandLine.h" #include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileSystem.h" #include "llvm/Support/FileSystem.h"
@ -210,6 +212,11 @@ cl::opt<bool> NoLLVMBitcode("no-llvm-bc",
cl::desc("Disable LLVM bitcode reader"), cl::desc("Disable LLVM bitcode reader"),
cl::cat(NMCat)); cl::cat(NMCat));
cl::opt<bool> AddInlinedInfo("add-inlinedinfo",
cl::desc("Add symbols from the inlined libraries, "
"TBD(Mach-O) only"),
cl::cat(NMCat));
cl::extrahelp HelpResponse("\nPass @FILE as argument to read options from FILE.\n"); cl::extrahelp HelpResponse("\nPass @FILE as argument to read options from FILE.\n");
bool PrintAddress = true; bool PrintAddress = true;
@ -340,6 +347,8 @@ static char isSymbolList64Bit(SymbolicFile &Obj) {
return false; return false;
if (isa<WasmObjectFile>(Obj)) if (isa<WasmObjectFile>(Obj))
return false; return false;
if (TapiFile *Tapi = dyn_cast<TapiFile>(&Obj))
return Tapi->is64Bit();
if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(&Obj)) if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(&Obj))
return MachO->is64Bit(); return MachO->is64Bit();
return cast<ELFObjectFileBase>(Obj).getBytesInAddress() == 8; return cast<ELFObjectFileBase>(Obj).getBytesInAddress() == 8;
@ -1046,6 +1055,10 @@ static char getSymbolNMTypeChar(MachOObjectFile &Obj, basic_symbol_iterator I) {
return '?'; return '?';
} }
static char getSymbolNMTypeChar(TapiFile &Obj, basic_symbol_iterator I) {
return 's';
}
static char getSymbolNMTypeChar(WasmObjectFile &Obj, basic_symbol_iterator I) { static char getSymbolNMTypeChar(WasmObjectFile &Obj, basic_symbol_iterator I) {
uint32_t Flags = cantFail(I->getFlags()); uint32_t Flags = cantFail(I->getFlags());
if (Flags & SymbolRef::SF_Executable) if (Flags & SymbolRef::SF_Executable)
@ -1139,6 +1152,8 @@ static char getNMSectionTagAndName(SymbolicFile &Obj, basic_symbol_iterator I,
Ret = getSymbolNMTypeChar(*MachO, I); Ret = getSymbolNMTypeChar(*MachO, I);
else if (WasmObjectFile *Wasm = dyn_cast<WasmObjectFile>(&Obj)) else if (WasmObjectFile *Wasm = dyn_cast<WasmObjectFile>(&Obj))
Ret = getSymbolNMTypeChar(*Wasm, I); Ret = getSymbolNMTypeChar(*Wasm, I);
else if (TapiFile *Tapi = dyn_cast<TapiFile>(&Obj))
Ret = getSymbolNMTypeChar(*Tapi, I);
else if (ELFObjectFileBase *ELF = dyn_cast<ELFObjectFileBase>(&Obj)) { else if (ELFObjectFileBase *ELF = dyn_cast<ELFObjectFileBase>(&Obj)) {
if (ELFSymbolRef(*I).getELFType() == ELF::STT_GNU_IFUNC) if (ELFSymbolRef(*I).getELFType() == ELF::STT_GNU_IFUNC)
return 'i'; return 'i';
@ -2081,6 +2096,31 @@ static void dumpSymbolNamesFromFile(std::string &Filename) {
} }
return; return;
} }
if (TapiUniversal *TU = dyn_cast<TapiUniversal>(&Bin)) {
for (const TapiUniversal::ObjectForArch &I : TU->objects()) {
StringRef ArchName = I.getArchFlagName();
const bool ShowArch =
ArchFlags.empty() ||
any_of(ArchFlags, [&](StringRef Name) { return Name == ArchName; });
if (!ShowArch)
continue;
if (!AddInlinedInfo && !I.isTopLevelLib())
continue;
if (auto ObjOrErr = I.getAsObjectFile()) {
outs() << "\n"
<< I.getInstallName() << " (for architecture " << ArchName << ")"
<< ":\n";
dumpSymbolNamesFromObject(*ObjOrErr.get(), false, {}, ArchName);
} else if (Error E =
isNotObjectErrorInvalidFileType(ObjOrErr.takeError())) {
error(std::move(E), Filename, ArchName);
}
}
return;
}
if (SymbolicFile *O = dyn_cast<SymbolicFile>(&Bin)) { if (SymbolicFile *O = dyn_cast<SymbolicFile>(&Bin)) {
if (!MachOPrintSizeWarning && PrintSize && isa<MachOObjectFile>(O)) { if (!MachOPrintSizeWarning && PrintSize && isa<MachOObjectFile>(O)) {
WithColor::warning(errs(), ToolName) WithColor::warning(errs(), ToolName)