Add the option, -universal-headers, used with -macho to print the Mach-O universal headers to llvm-objdump.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@225537 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Kevin Enderby 2015-01-09 19:22:37 +00:00
parent 8cd39a2630
commit 6248d1b153
5 changed files with 230 additions and 13 deletions

View File

@ -51,6 +51,10 @@ public:
ObjectForArch getNext() const { return ObjectForArch(Parent, Index + 1); }
uint32_t getCPUType() const { return Header.cputype; }
uint32_t getCPUSubType() const { return Header.cpusubtype; }
uint32_t getOffset() const { return Header.offset; }
uint32_t getSize() const { return Header.size; }
uint32_t getAlign() const { return Header.align; }
std::string getArchTypeName() const {
Triple T = MachOObjectFile::getArch(Header.cputype, Header.cpusubtype);
return T.getArchName();

View File

@ -2,6 +2,8 @@ RUN: llvm-objdump %p/Inputs/macho-universal.x86_64.i386 -d -m -no-show-raw-insn
RUN: | FileCheck %s -check-prefix UEXE-all
RUN: llvm-objdump %p/Inputs/macho-universal-archive.x86_64.i386 -d -m -no-show-raw-insn -full-leading-addr -print-imm-hex -arch i386 \
RUN: | FileCheck %s -check-prefix UArchive-i386
RUN: llvm-objdump %p/Inputs/macho-universal.x86_64.i386 -universal-headers -m \
RUN: | FileCheck %s -check-prefix FAT
UEXE-all: macho-universal.x86_64.i386 (architecture x86_64):
UEXE-all: (__TEXT,__text) section
@ -23,3 +25,20 @@ UArchive-i386: 00000001 movl %esp, %ebp
UArchive-i386: 00000003 popl %ebp
UArchive-i386: 00000004 retl
FAT: Fat headers
FAT: fat_magic FAT_MAGIC
FAT: nfat_arch 2
FAT: architecture x86_64
FAT: cputype CPU_TYPE_X86_64
FAT: cpusubtype CPU_SUBTYPE_X86_64_ALL
FAT: capabilities CPU_SUBTYPE_LIB64
FAT: offset 4096
FAT: size 4360
FAT: align 2^12 (4096)
FAT: architecture i386
FAT: cputype CPU_TYPE_I386
FAT: cpusubtype CPU_SUBTYPE_I386_ALL
FAT: capabilities 0x0
FAT: offset 12288
FAT: size 4336
FAT: align 2^12 (4096)

View File

@ -66,6 +66,10 @@ static cl::opt<bool>
PrintImmHex("print-imm-hex",
cl::desc("Use hex format for immediate values"));
cl::opt<bool>
llvm::UniversalHeaders("universal-headers",
cl::desc("Print Mach-O universal headers"));
static cl::list<std::string>
ArchFlags("arch", cl::desc("architecture(s) from a Mach-O file to dump"),
cl::ZeroOrMore);
@ -294,12 +298,18 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF);
static void ProcessMachO(StringRef Filename, MachOObjectFile *MachOOF,
StringRef ArchiveMemberName = StringRef(),
StringRef ArchitectureName = StringRef()) {
outs() << Filename;
if (!ArchiveMemberName.empty())
outs() << '(' << ArchiveMemberName << ')';
if (!ArchitectureName.empty())
outs() << " (architecture " << ArchitectureName << ")";
outs() << ":\n";
// If we are doing some processing here on the Mach-O file print the header
// info. And don't print it otherwise like in the case of printing the
// UniversalHeaders.
if (Disassemble || PrivateHeaders || ExportsTrie || Rebase || Bind ||
LazyBind || WeakBind) {
outs() << Filename;
if (!ArchiveMemberName.empty())
outs() << '(' << ArchiveMemberName << ')';
if (!ArchitectureName.empty())
outs() << " (architecture " << ArchitectureName << ")";
outs() << ":\n";
}
if (Disassemble)
DisassembleMachO(Filename, MachOOF);
@ -331,6 +341,179 @@ static void ProcessMachO(StringRef Filename, MachOObjectFile *MachOOF,
printWeakBindTable(MachOOF);
}
// printUnknownCPUType() helps print_fat_headers for unknown CPU's.
static void printUnknownCPUType(uint32_t cputype, uint32_t cpusubtype) {
outs() << " cputype (" << cputype << ")\n";
outs() << " cpusubtype (" << cpusubtype << ")\n";
}
// printCPUType() helps print_fat_headers by printing the cputype and
// pusubtype (symbolically for the one's it knows about).
static void printCPUType(uint32_t cputype, uint32_t cpusubtype) {
switch (cputype) {
case MachO::CPU_TYPE_I386:
switch (cpusubtype) {
case MachO::CPU_SUBTYPE_I386_ALL:
outs() << " cputype CPU_TYPE_I386\n";
outs() << " cpusubtype CPU_SUBTYPE_I386_ALL\n";
break;
default:
printUnknownCPUType(cputype, cpusubtype);
break;
}
break;
case MachO::CPU_TYPE_X86_64:
switch (cpusubtype) {
case MachO::CPU_SUBTYPE_X86_64_ALL:
outs() << " cputype CPU_TYPE_X86_64\n";
outs() << " cpusubtype CPU_SUBTYPE_X86_64_ALL\n";
break;
case MachO::CPU_SUBTYPE_X86_64_H:
outs() << " cputype CPU_TYPE_X86_64\n";
outs() << " cpusubtype CPU_SUBTYPE_X86_64_H\n";
break;
default:
printUnknownCPUType(cputype, cpusubtype);
break;
}
break;
case MachO::CPU_TYPE_ARM:
switch (cpusubtype) {
case MachO::CPU_SUBTYPE_ARM_ALL:
outs() << " cputype CPU_TYPE_ARM\n";
outs() << " cpusubtype CPU_SUBTYPE_ARM_ALL\n";
break;
case MachO::CPU_SUBTYPE_ARM_V4T:
outs() << " cputype CPU_TYPE_ARM\n";
outs() << " cpusubtype CPU_SUBTYPE_ARM_V4T\n";
break;
case MachO::CPU_SUBTYPE_ARM_V5TEJ:
outs() << " cputype CPU_TYPE_ARM\n";
outs() << " cpusubtype CPU_SUBTYPE_ARM_V5TEJ\n";
break;
case MachO::CPU_SUBTYPE_ARM_XSCALE:
outs() << " cputype CPU_TYPE_ARM\n";
outs() << " cpusubtype CPU_SUBTYPE_ARM_XSCALE\n";
break;
case MachO::CPU_SUBTYPE_ARM_V6:
outs() << " cputype CPU_TYPE_ARM\n";
outs() << " cpusubtype CPU_SUBTYPE_ARM_V6\n";
break;
case MachO::CPU_SUBTYPE_ARM_V6M:
outs() << " cputype CPU_TYPE_ARM\n";
outs() << " cpusubtype CPU_SUBTYPE_ARM_V6M\n";
break;
case MachO::CPU_SUBTYPE_ARM_V7:
outs() << " cputype CPU_TYPE_ARM\n";
outs() << " cpusubtype CPU_SUBTYPE_ARM_V7\n";
break;
case MachO::CPU_SUBTYPE_ARM_V7EM:
outs() << " cputype CPU_TYPE_ARM\n";
outs() << " cpusubtype CPU_SUBTYPE_ARM_V7EM\n";
break;
case MachO::CPU_SUBTYPE_ARM_V7K:
outs() << " cputype CPU_TYPE_ARM\n";
outs() << " cpusubtype CPU_SUBTYPE_ARM_V7K\n";
break;
case MachO::CPU_SUBTYPE_ARM_V7M:
outs() << " cputype CPU_TYPE_ARM\n";
outs() << " cpusubtype CPU_SUBTYPE_ARM_V7M\n";
break;
case MachO::CPU_SUBTYPE_ARM_V7S:
outs() << " cputype CPU_TYPE_ARM\n";
outs() << " cpusubtype CPU_SUBTYPE_ARM_V7S\n";
break;
default:
printUnknownCPUType(cputype, cpusubtype);
break;
}
break;
case MachO::CPU_TYPE_ARM64:
switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
case MachO::CPU_SUBTYPE_ARM64_ALL:
outs() << " cputype CPU_TYPE_ARM64\n";
outs() << " cpusubtype CPU_SUBTYPE_ARM64_ALL\n";
break;
default:
printUnknownCPUType(cputype, cpusubtype);
break;
}
break;
default:
printUnknownCPUType(cputype, cpusubtype);
break;
}
}
static void printMachOUniversalHeaders(const object::MachOUniversalBinary *UB,
bool verbose) {
outs() << "Fat headers\n";
if (verbose)
outs() << "fat_magic FAT_MAGIC\n";
else
outs() << "fat_magic " << format("0x%" PRIx32, MachO::FAT_MAGIC) << "\n";
uint32_t nfat_arch = UB->getNumberOfObjects();
StringRef Buf = UB->getData();
uint64_t size = Buf.size();
uint64_t big_size = sizeof(struct MachO::fat_header) +
nfat_arch * sizeof(struct MachO::fat_arch);
outs() << "nfat_arch " << UB->getNumberOfObjects();
if (nfat_arch == 0)
outs() << " (malformed, contains zero architecture types)\n";
else if (big_size > size)
outs() << " (malformed, architectures past end of file)\n";
else
outs() << "\n";
for (uint32_t i = 0; i < nfat_arch; ++i) {
MachOUniversalBinary::ObjectForArch OFA(UB, i);
uint32_t cputype = OFA.getCPUType();
uint32_t cpusubtype = OFA.getCPUSubType();
outs() << "architecture ";
for (uint32_t j = 0; i != 0 && j <= i - 1; j++) {
MachOUniversalBinary::ObjectForArch other_OFA(UB, j);
uint32_t other_cputype = other_OFA.getCPUType();
uint32_t other_cpusubtype = other_OFA.getCPUSubType();
if (cputype != 0 && cpusubtype != 0 &&
cputype == other_cputype &&
(cpusubtype & ~MachO::CPU_SUBTYPE_MASK) ==
(other_cpusubtype & ~MachO::CPU_SUBTYPE_MASK))
outs() << "(illegal duplicate architecture) ";
break;
}
if (verbose) {
outs() << OFA.getArchTypeName() << "\n";
printCPUType(cputype, cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
} else {
outs() << i << "\n";
outs() << " cputype " << cputype << "\n";
outs() << " cpusubtype " << (cpusubtype & ~MachO::CPU_SUBTYPE_MASK)
<< "\n";
}
if (verbose &&
(cpusubtype & MachO::CPU_SUBTYPE_MASK) == MachO::CPU_SUBTYPE_LIB64)
outs() << " capabilities CPU_SUBTYPE_LIB64\n";
else
outs() << " capabilities "
<< format("0x%" PRIx32,
(cpusubtype & MachO::CPU_SUBTYPE_MASK) >> 24) << "\n";
outs() << " offset " << OFA.getOffset();
if (OFA.getOffset() > size)
outs() << " (past end of file)";
if (OFA.getOffset() % (1 << OFA.getAlign()) != 0)
outs() << " (not aligned on it's alignment (2^" << OFA.getAlign() << ")";
outs() << "\n";
outs() << " size " << OFA.getSize();
big_size = OFA.getOffset() + OFA.getSize();
if (big_size > size)
outs() << " (past end of file)";
outs() << "\n";
outs() << " align 2^" << OFA.getAlign() << " (" << (1 << OFA.getAlign())
<< ")\n";
}
}
// ParseInputMachO() parses the named Mach-O file in Filename and handles the
// -arch flags selecting just those slices as specified by them and also parses
// archive files. Then for each individual Mach-O file ProcessMachO() is
@ -372,6 +555,10 @@ void llvm::ParseInputMachO(StringRef Filename) {
}
return;
}
if (UniversalHeaders) {
if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(&Bin))
printMachOUniversalHeaders(UB, true);
}
if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(&Bin)) {
// If we have a list of architecture flags specified dump only those.
if (!ArchAll && ArchFlags.size() != 0) {
@ -2765,12 +2952,17 @@ static void PrintMachHeader(uint32_t magic, uint32_t cputype,
break;
case MachO::CPU_TYPE_X86_64:
outs() << " X86_64";
case MachO::CPU_SUBTYPE_X86_64_ALL:
outs() << " ALL";
break;
case MachO::CPU_SUBTYPE_X86_64_H:
outs() << " Haswell";
outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
switch (cpusubtype & ~MachO::CPU_SUBTYPE_MASK) {
case MachO::CPU_SUBTYPE_X86_64_ALL:
outs() << " ALL";
break;
case MachO::CPU_SUBTYPE_X86_64_H:
outs() << " Haswell";
break;
default:
outs() << format(" %10d", cpusubtype & ~MachO::CPU_SUBTYPE_MASK);
break;
}
break;
case MachO::CPU_TYPE_ARM:
outs() << " ARM";

View File

@ -891,7 +891,8 @@ int main(int argc, char **argv) {
&& !Rebase
&& !Bind
&& !LazyBind
&& !WeakBind) {
&& !WeakBind
&& !(UniversalHeaders && MachOOpt)) {
cl::PrintHelpMessage();
return 2;
}

View File

@ -34,6 +34,7 @@ extern cl::opt<bool> Rebase;
extern cl::opt<bool> Bind;
extern cl::opt<bool> LazyBind;
extern cl::opt<bool> WeakBind;
extern cl::opt<bool> UniversalHeaders;
// Various helper functions.
bool error(std::error_code ec);