[llvm] r212054 - Add the -arch flag support to llvm-nm to select the slice out of a Mach-O
Kevin Enderby
enderby at apple.com
Mon Jun 30 11:45:24 PDT 2014
Author: enderby
Date: Mon Jun 30 13:45:23 2014
New Revision: 212054
URL: http://llvm.org/viewvc/llvm-project?rev=212054&view=rev
Log:
Add the -arch flag support to llvm-nm to select the slice out of a Mach-O
universal file. This also includes support for -arch all, selecting the host
architecture by default from a universal file and checking if -arch is used
with a standard Mach-O it matches that architecture.
Modified:
llvm/trunk/include/llvm/Object/MachO.h
llvm/trunk/include/llvm/Object/MachOUniversal.h
llvm/trunk/include/llvm/Support/MachO.h
llvm/trunk/lib/Object/MachOObjectFile.cpp
llvm/trunk/test/Object/nm-universal-binary.test
llvm/trunk/tools/llvm-nm/llvm-nm.cpp
Modified: llvm/trunk/include/llvm/Object/MachO.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/MachO.h?rev=212054&r1=212053&r2=212054&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Object/MachO.h (original)
+++ llvm/trunk/include/llvm/Object/MachO.h Mon Jun 30 13:45:23 2014
@@ -225,6 +225,9 @@ public:
StringRef &Suffix);
static Triple::ArchType getArch(uint32_t CPUType);
+ static Triple getArch(uint32_t CPUType, uint32_t CPUSubType);
+ static Triple getArch(StringRef ArchFlag);
+ static Triple getHostArch();
static bool classof(const Binary *v) {
return v->isMachO();
Modified: llvm/trunk/include/llvm/Object/MachOUniversal.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/MachOUniversal.h?rev=212054&r1=212053&r2=212054&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Object/MachOUniversal.h (original)
+++ llvm/trunk/include/llvm/Object/MachOUniversal.h Mon Jun 30 13:45:23 2014
@@ -54,7 +54,8 @@ public:
ObjectForArch getNext() const { return ObjectForArch(Parent, Index + 1); }
uint32_t getCPUType() const { return Header.cputype; }
std::string getArchTypeName() const {
- return Triple::getArchTypeName(MachOObjectFile::getArch(Header.cputype));
+ Triple T = MachOObjectFile::getArch(Header.cputype, Header.cpusubtype);
+ return T.getArchName();
}
ErrorOr<std::unique_ptr<ObjectFile>> getAsObjectFile() const;
Modified: llvm/trunk/include/llvm/Support/MachO.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/MachO.h?rev=212054&r1=212053&r2=212054&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Support/MachO.h (original)
+++ llvm/trunk/include/llvm/Support/MachO.h Mon Jun 30 13:45:23 2014
@@ -1015,8 +1015,8 @@ namespace llvm {
enum : uint32_t {
// Capability bits used in the definition of cpusubtype.
- CPU_SUB_TYPE_MASK = 0xff000000, // Mask for architecture bits
- CPU_SUB_TYPE_LIB64 = 0x80000000, // 64 bit libraries
+ CPU_SUBTYPE_MASK = 0xff000000, // Mask for architecture bits
+ CPU_SUBTYPE_LIB64 = 0x80000000, // 64 bit libraries
// Special CPU subtype constants.
CPU_SUBTYPE_MULTIPLE = ~0u
Modified: llvm/trunk/lib/Object/MachOObjectFile.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/MachOObjectFile.cpp?rev=212054&r1=212053&r2=212054&view=diff
==============================================================================
--- llvm/trunk/lib/Object/MachOObjectFile.cpp (original)
+++ llvm/trunk/lib/Object/MachOObjectFile.cpp Mon Jun 30 13:45:23 2014
@@ -1511,6 +1511,108 @@ Triple::ArchType MachOObjectFile::getArc
}
}
+Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType) {
+ switch (CPUType) {
+ case MachO::CPU_TYPE_I386:
+ switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
+ case MachO::CPU_SUBTYPE_I386_ALL:
+ return Triple("i386-apple-darwin");
+ default:
+ return Triple();
+ }
+ case MachO::CPU_TYPE_X86_64:
+ switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
+ case MachO::CPU_SUBTYPE_X86_64_ALL:
+ return Triple("x86_64-apple-darwin");
+ case MachO::CPU_SUBTYPE_X86_64_H:
+ return Triple("x86_64h-apple-darwin");
+ default:
+ return Triple();
+ }
+ case MachO::CPU_TYPE_ARM:
+ switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
+ case MachO::CPU_SUBTYPE_ARM_V4T:
+ return Triple("armv4t-apple-darwin");
+ case MachO::CPU_SUBTYPE_ARM_V5TEJ:
+ return Triple("armv5e-apple-darwin");
+ case MachO::CPU_SUBTYPE_ARM_V6:
+ return Triple("armv6-apple-darwin");
+ case MachO::CPU_SUBTYPE_ARM_V6M:
+ return Triple("armv6m-apple-darwin");
+ case MachO::CPU_SUBTYPE_ARM_V7EM:
+ return Triple("armv7em-apple-darwin");
+ case MachO::CPU_SUBTYPE_ARM_V7K:
+ return Triple("armv7k-apple-darwin");
+ case MachO::CPU_SUBTYPE_ARM_V7M:
+ return Triple("armv7m-apple-darwin");
+ case MachO::CPU_SUBTYPE_ARM_V7S:
+ return Triple("armv7s-apple-darwin");
+ default:
+ return Triple();
+ }
+ case MachO::CPU_TYPE_ARM64:
+ switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
+ case MachO::CPU_SUBTYPE_ARM64_ALL:
+ return Triple("arm64-apple-darwin");
+ default:
+ return Triple();
+ }
+ case MachO::CPU_TYPE_POWERPC:
+ switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
+ case MachO::CPU_SUBTYPE_POWERPC_ALL:
+ return Triple("ppc-apple-darwin");
+ default:
+ return Triple();
+ }
+ case MachO::CPU_TYPE_POWERPC64:
+ case MachO::CPU_SUBTYPE_POWERPC_ALL:
+ return Triple("ppc64-apple-darwin");
+ switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
+ default:
+ return Triple();
+ }
+ default:
+ return Triple();
+ }
+}
+
+Triple MachOObjectFile::getHostArch() {
+ return Triple(sys::getDefaultTargetTriple());
+}
+
+Triple MachOObjectFile::getArch(StringRef ArchFlag) {
+ if (ArchFlag == "i386")
+ return Triple("i386-apple-darwin");
+ else if (ArchFlag == "x86_64")
+ return Triple("x86_64-apple-darwin");
+ else if (ArchFlag == "x86_64h")
+ return Triple("x86_64h-apple-darwin");
+ else if (ArchFlag == "armv4t" || ArchFlag == "arm")
+ return Triple("armv4t-apple-darwin");
+ else if (ArchFlag == "armv5e")
+ return Triple("armv5e-apple-darwin");
+ else if (ArchFlag == "armv6")
+ return Triple("armv6-apple-darwin");
+ else if (ArchFlag == "armv6m")
+ return Triple("armv6m-apple-darwin");
+ else if (ArchFlag == "armv7em")
+ return Triple("armv7em-apple-darwin");
+ else if (ArchFlag == "armv7k")
+ return Triple("armv7k-apple-darwin");
+ else if (ArchFlag == "armv7k")
+ return Triple("armv7m-apple-darwin");
+ else if (ArchFlag == "armv7s")
+ return Triple("armv7s-apple-darwin");
+ else if (ArchFlag == "arm64")
+ return Triple("arm64-apple-darwin");
+ else if (ArchFlag == "ppc")
+ return Triple("ppc-apple-darwin");
+ else if (ArchFlag == "ppc64")
+ return Triple("ppc64-apple-darwin");
+ else
+ return Triple();
+}
+
unsigned MachOObjectFile::getArch() const {
return getArch(getCPUType(this));
}
Modified: llvm/trunk/test/Object/nm-universal-binary.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Object/nm-universal-binary.test?rev=212054&r1=212053&r2=212054&view=diff
==============================================================================
--- llvm/trunk/test/Object/nm-universal-binary.test (original)
+++ llvm/trunk/test/Object/nm-universal-binary.test Mon Jun 30 13:45:23 2014
@@ -1,13 +1,21 @@
-RUN: llvm-nm %p/Inputs/macho-universal.x86_64.i386 \
+RUN: llvm-nm -arch all %p/Inputs/macho-universal.x86_64.i386 \
RUN: | FileCheck %s -check-prefix CHECK-OBJ
-RUN: llvm-nm %p/Inputs/macho-universal-archive.x86_64.i386 \
+RUN: llvm-nm -arch x86_64 %p/Inputs/macho-universal.x86_64.i386 \
+RUN: | FileCheck %s -check-prefix CHECK-OBJ-x86_64
+RUN: llvm-nm -arch all %p/Inputs/macho-universal-archive.x86_64.i386 \
RUN: | FileCheck %s -check-prefix CHECK-AR
+RUN: llvm-nm -arch i386 %p/Inputs/macho-universal-archive.x86_64.i386 \
+RUN: | FileCheck %s -check-prefix CHECK-AR-i386
CHECK-OBJ: macho-universal.x86_64.i386 (for architecture x86_64):
CHECK-OBJ: 0000000100000f60 T _main
CHECK-OBJ: macho-universal.x86_64.i386 (for architecture i386):
CHECK-OBJ: 00001fa0 T _main
+CHECK-OBJ-x86_64: 0000000100000000 T __mh_execute_header
+CHECK-OBJ-x86_64: 0000000100000f60 T _main
+CHECK-OBJ-x86_64: U dyld_stub_binder
+
CHECK-AR: macho-universal-archive.x86_64.i386(hello.o) (for architecture x86_64):
CHECK-AR: 0000000000000068 s EH_frame0
CHECK-AR: 000000000000003b s L_.str
@@ -17,3 +25,7 @@ CHECK-AR: U _printf
CHECK-AR: macho-universal-archive.x86_64.i386(foo.o) (for architecture i386):
CHECK-AR: 00000008 D _bar
CHECK-AR: 00000000 T _foo
+
+CHECK-AR-i386: macho-universal-archive.x86_64.i386(foo.o):
+CHECK-AR-i386: 00000008 D _bar
+CHECK-AR-i386: 00000000 T _foo
Modified: llvm/trunk/tools/llvm-nm/llvm-nm.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-nm/llvm-nm.cpp?rev=212054&r1=212053&r2=212054&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-nm/llvm-nm.cpp (original)
+++ llvm/trunk/tools/llvm-nm/llvm-nm.cpp Mon Jun 30 13:45:23 2014
@@ -83,6 +83,11 @@ cl::opt<bool> BSDFormat("B", cl::desc("A
cl::opt<bool> POSIXFormat("P", cl::desc("Alias for --format=posix"));
cl::opt<bool> DarwinFormat("m", cl::desc("Alias for --format=darwin"));
+static cl::list<std::string> ArchFlags("arch",
+ cl::desc("architecture(s) from a Mach-O file to dump"),
+ cl::ZeroOrMore);
+bool ArchAll = false;
+
cl::opt<bool> PrintFileName(
"print-file-name",
cl::desc("Precede each symbol with the object file it came from"));
@@ -720,6 +725,40 @@ static void dumpSymbolNamesFromObject(Sy
sortAndPrintSymbolList(Obj, printName);
}
+// checkMachOAndArchFlags() checks to see if the SymbolicFile is a Mach-O file
+// and if it is and there is a list of architecture flags is specified then
+// check to make sure this Mach-O file is one of those architectures or all
+// architectures was specificed. If not then an error is generated and this
+// routine returns false. Else it returns true.
+static bool checkMachOAndArchFlags(SymbolicFile *O, std::string &Filename) {
+ if (isa<MachOObjectFile>(O) && !ArchAll && ArchFlags.size() != 0) {
+ MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(O);
+ bool ArchFound = false;
+ MachO::mach_header H;
+ MachO::mach_header_64 H_64;
+ Triple T;
+ if (MachO->is64Bit()) {
+ H_64 = MachO->MachOObjectFile::getHeader64();
+ T = MachOObjectFile::getArch(H_64.cputype, H_64.cpusubtype);
+ } else {
+ H = MachO->MachOObjectFile::getHeader();
+ T = MachOObjectFile::getArch(H.cputype, H.cpusubtype);
+ }
+ unsigned i;
+ for (i = 0; i < ArchFlags.size(); ++i){
+ if (ArchFlags[i] == T.getArchName())
+ ArchFound = true;
+ break;
+ }
+ if (!ArchFound) {
+ error(ArchFlags[i],
+ "file: " + Filename + " does not contain architecture");
+ return false;
+ }
+ }
+ return true;
+}
+
static void dumpSymbolNamesFromFile(std::string &Filename) {
std::unique_ptr<MemoryBuffer> Buffer;
if (error(MemoryBuffer::getFileOrSTDIN(Filename, Buffer), Filename))
@@ -758,6 +797,8 @@ static void dumpSymbolNamesFromFile(std:
if (ChildOrErr.getError())
continue;
if (SymbolicFile *O = dyn_cast<SymbolicFile>(&*ChildOrErr.get())) {
+ if (!checkMachOAndArchFlags(O, Filename))
+ return;
outs() << "\n";
if (isa<MachOObjectFile>(O)) {
outs() << Filename << "(" << O->getFileName() << ")";
@@ -770,6 +811,98 @@ static void dumpSymbolNamesFromFile(std:
return;
}
if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(Bin.get())) {
+ // If we have a list of architecture flags specified dump only those.
+ if (!ArchAll && ArchFlags.size() != 0) {
+ // Look for a slice in the universal binary that matches each ArchFlag.
+ bool ArchFound;
+ for (unsigned i = 0; i < ArchFlags.size(); ++i){
+ ArchFound = false;
+ for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
+ E = UB->end_objects();
+ I != E; ++I) {
+ if (ArchFlags[i] == I->getArchTypeName()){
+ ArchFound = true;
+ ErrorOr<std::unique_ptr<ObjectFile>> ObjOrErr =
+ I->getAsObjectFile();
+ std::unique_ptr<Archive> A;
+ if (ObjOrErr) {
+ std::unique_ptr<ObjectFile> Obj = std::move(ObjOrErr.get());
+ if (ArchFlags.size() > 1) {
+ outs() << "\n" << Obj->getFileName()
+ << " (for architecture " << I->getArchTypeName() << ")"
+ << ":\n";
+ }
+ dumpSymbolNamesFromObject(Obj.get(), false);
+ }
+ else if (!I->getAsArchive(A)) {
+ for (Archive::child_iterator AI = A->child_begin(),
+ AE = A->child_end();
+ AI != AE; ++AI) {
+ ErrorOr<std::unique_ptr<Binary>> ChildOrErr =
+ AI->getAsBinary(&Context);
+ if (ChildOrErr.getError())
+ continue;
+ if (SymbolicFile *O = dyn_cast<SymbolicFile>
+ (&*ChildOrErr.get())) {
+ outs() << "\n" << A->getFileName();
+ outs() << "(" << O->getFileName() << ")";
+ if (ArchFlags.size() > 1) {
+ outs() << " (for architecture " << I->getArchTypeName()
+ << ")";
+ }
+ outs() << ":\n";
+ dumpSymbolNamesFromObject(O, false);
+ }
+ }
+ }
+ }
+ }
+ if (!ArchFound) {
+ error(ArchFlags[i],
+ "file: " + Filename + " does not contain architecture");
+ return;
+ }
+ }
+ return;
+ }
+ // No architecture flags were specified so if this contains a slice that
+ // matches the host architecture dump only that.
+ if (!ArchAll) {
+ StringRef HostArchName =
+ MachOObjectFile::getHostArch().getArchName();
+ for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
+ E = UB->end_objects();
+ I != E; ++I) {
+ if (HostArchName == I->getArchTypeName()){
+ ErrorOr<std::unique_ptr<ObjectFile>> ObjOrErr =
+ I->getAsObjectFile();
+ std::unique_ptr<Archive> A;
+ if (ObjOrErr) {
+ std::unique_ptr<ObjectFile> Obj = std::move(ObjOrErr.get());
+ dumpSymbolNamesFromObject(Obj.get(), false);
+ }
+ else if (!I->getAsArchive(A)) {
+ for (Archive::child_iterator AI = A->child_begin(),
+ AE = A->child_end();
+ AI != AE; ++AI) {
+ ErrorOr<std::unique_ptr<Binary>> ChildOrErr =
+ AI->getAsBinary(&Context);
+ if (ChildOrErr.getError())
+ continue;
+ if (SymbolicFile *O = dyn_cast<SymbolicFile>
+ (&*ChildOrErr.get())) {
+ outs() << "\n" << A->getFileName()
+ << "(" << O->getFileName() << ")" << ":\n";
+ dumpSymbolNamesFromObject(O, false);
+ }
+ }
+ }
+ return;
+ }
+ }
+ }
+ // Either all architectures have been specified or none have been specified
+ // and this does not contain the host architecture so dump all the slices.
bool moreThanOneArch = UB->getNumberOfObjects() > 1;
for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
E = UB->end_objects();
@@ -810,6 +943,8 @@ static void dumpSymbolNamesFromFile(std:
return;
}
if (SymbolicFile *O = dyn_cast<SymbolicFile>(Bin.get())) {
+ if (!checkMachOAndArchFlags(O, Filename))
+ return;
dumpSymbolNamesFromObject(O, true);
return;
}
@@ -854,6 +989,18 @@ int main(int argc, char **argv) {
MultipleFiles = true;
}
+ for (unsigned i = 0; i < ArchFlags.size(); ++i){
+ if (ArchFlags[i] == "all") {
+ ArchAll = true;
+ }
+ else {
+ Triple T = MachOObjectFile::getArch(ArchFlags[i]);
+ if (T.getArch() == Triple::UnknownArch)
+ error("Unknown architecture named '" + ArchFlags[i] + "'",
+ "for the -arch option");
+ }
+ }
+
std::for_each(InputFilenames.begin(), InputFilenames.end(),
dumpSymbolNamesFromFile);
More information about the llvm-commits
mailing list