forked from OSchip/llvm-project
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. llvm-svn: 212054
This commit is contained in:
parent
eb606a3c27
commit
4c8dfe4d0f
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1511,6 +1511,108 @@ Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
|
|||
}
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -83,6 +83,11 @@ cl::opt<bool> BSDFormat("B", cl::desc("Alias for --format=bsd"));
|
|||
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(SymbolicFile *Obj, bool printName) {
|
|||
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::string &Filename) {
|
|||
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::string &Filename) {
|
|||
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::string &Filename) {
|
|||
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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue