diff options
author | Kevin Enderby <enderby@apple.com> | 2014-08-18 20:21:02 +0000 |
---|---|---|
committer | Kevin Enderby <enderby@apple.com> | 2014-08-18 20:21:02 +0000 |
commit | f759032ccd3709dcd7362b0ed51760ee4e47025a (patch) | |
tree | 26328022c53f9bc7afb240358e5fa47f9ff831ef /tools | |
parent | 0526d167a9f8fcd476f4382d933dda208a4eb5c8 (diff) |
Make llvm-objdump handle both arm and thumb disassembly from the same Mach-O
file with -macho, the Mach-O specific object file parser option.
After some discussion I chose to do this implementation contained in the logic
of llvm-objdump’s MachODump.cpp using a second disassembler for thumb when
needed and with updates mostly contained in the MachOObjectFile class.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@215931 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'tools')
-rw-r--r-- | tools/llvm-objdump/MachODump.cpp | 87 |
1 files changed, 77 insertions, 10 deletions
diff --git a/tools/llvm-objdump/MachODump.cpp b/tools/llvm-objdump/MachODump.cpp index e6c505d1b3b..1cf92360054 100644 --- a/tools/llvm-objdump/MachODump.cpp +++ b/tools/llvm-objdump/MachODump.cpp @@ -50,22 +50,36 @@ static cl::opt<bool> static cl::opt<std::string> DSYMFile("dsym", cl::desc("Use .dSYM file for debug info")); -static const Target *GetTarget(const MachOObjectFile *MachOObj) { +static std::string ThumbTripleName; + +static const Target *GetTarget(const MachOObjectFile *MachOObj, + const char **McpuDefault, + const Target **ThumbTarget) { // Figure out the target triple. if (TripleName.empty()) { llvm::Triple TT("unknown-unknown-unknown"); - TT.setArch(Triple::ArchType(MachOObj->getArch())); + llvm::Triple ThumbTriple = Triple(); + TT = MachOObj->getArch(McpuDefault, &ThumbTriple); TripleName = TT.str(); + ThumbTripleName = ThumbTriple.str(); } // Get the target specific parser. std::string Error; const Target *TheTarget = TargetRegistry::lookupTarget(TripleName, Error); - if (TheTarget) + if (TheTarget && ThumbTripleName.empty()) + return TheTarget; + + *ThumbTarget = TargetRegistry::lookupTarget(ThumbTripleName, Error); + if (*ThumbTarget) return TheTarget; - errs() << "llvm-objdump: error: unable to get target for '" << TripleName - << "', see --version and --triple.\n"; + errs() << "llvm-objdump: error: unable to get target for '"; + if (!TheTarget) + errs() << TripleName; + else + errs() << ThumbTripleName; + errs() << "', see --version and --triple.\n"; return nullptr; } @@ -211,14 +225,26 @@ void llvm::DisassembleInputMachO(StringRef Filename) { static void DisassembleInputMachO2(StringRef Filename, MachOObjectFile *MachOOF) { - const Target *TheTarget = GetTarget(MachOOF); + const char *McpuDefault = nullptr; + const Target *ThumbTarget = nullptr; + const Target *TheTarget = GetTarget(MachOOF, &McpuDefault, &ThumbTarget); if (!TheTarget) { // GetTarget prints out stuff. return; } + if (MCPU.empty() && McpuDefault) + MCPU = McpuDefault; + std::unique_ptr<const MCInstrInfo> InstrInfo(TheTarget->createMCInstrInfo()); std::unique_ptr<MCInstrAnalysis> InstrAnalysis( TheTarget->createMCInstrAnalysis(InstrInfo.get())); + std::unique_ptr<const MCInstrInfo> ThumbInstrInfo; + std::unique_ptr<MCInstrAnalysis> ThumbInstrAnalysis; + if (ThumbTarget) { + ThumbInstrInfo.reset(ThumbTarget->createMCInstrInfo()); + ThumbInstrAnalysis.reset( + ThumbTarget->createMCInstrAnalysis(ThumbInstrInfo.get())); + } // Package up features to be passed to target/subtarget std::string FeaturesStr; @@ -238,7 +264,7 @@ static void DisassembleInputMachO2(StringRef Filename, TheTarget->createMCSubtargetInfo(TripleName, MCPU, FeaturesStr)); MCContext Ctx(AsmInfo.get(), MRI.get(), nullptr); std::unique_ptr<const MCDisassembler> DisAsm( - TheTarget->createMCDisassembler(*STI, Ctx)); + TheTarget->createMCDisassembler(*STI, Ctx)); int AsmPrinterVariant = AsmInfo->getAssemblerDialect(); std::unique_ptr<MCInstPrinter> IP(TheTarget->createMCInstPrinter( AsmPrinterVariant, *AsmInfo, *InstrInfo, *MRI, *STI)); @@ -249,6 +275,34 @@ static void DisassembleInputMachO2(StringRef Filename, return; } + // Set up thumb disassembler. + std::unique_ptr<const MCRegisterInfo> ThumbMRI; + std::unique_ptr<const MCAsmInfo> ThumbAsmInfo; + std::unique_ptr<const MCSubtargetInfo> ThumbSTI; + std::unique_ptr<const MCDisassembler> ThumbDisAsm; + std::unique_ptr<MCInstPrinter> ThumbIP; + std::unique_ptr<MCContext> ThumbCtx; + if (ThumbTarget) { + ThumbMRI.reset(ThumbTarget->createMCRegInfo(ThumbTripleName)); + ThumbAsmInfo.reset( + ThumbTarget->createMCAsmInfo(*ThumbMRI, ThumbTripleName)); + ThumbSTI.reset( + ThumbTarget->createMCSubtargetInfo(ThumbTripleName, MCPU, FeaturesStr)); + ThumbCtx.reset(new MCContext(ThumbAsmInfo.get(), ThumbMRI.get(), nullptr)); + ThumbDisAsm.reset(ThumbTarget->createMCDisassembler(*ThumbSTI, *ThumbCtx)); + int ThumbAsmPrinterVariant = ThumbAsmInfo->getAssemblerDialect(); + ThumbIP.reset(ThumbTarget->createMCInstPrinter( + ThumbAsmPrinterVariant, *ThumbAsmInfo, *ThumbInstrInfo, *ThumbMRI, + *ThumbSTI)); + } + + if (ThumbTarget && (!ThumbInstrAnalysis || !ThumbAsmInfo || !ThumbSTI || + !ThumbDisAsm || !ThumbIP)) { + errs() << "error: couldn't initialize disassembler for target " + << ThumbTripleName << '\n'; + return; + } + outs() << '\n' << Filename << ":\n\n"; MachO::mach_header Header = MachOOF->getHeader(); @@ -396,6 +450,10 @@ static void DisassembleInputMachO2(StringRef Filename, symbolTableWorked = true; + DataRefImpl Symb = Symbols[SymIdx].getRawDataRefImpl(); + bool isThumb = + (MachOOF->getSymbolFlags(Symb) & SymbolRef::SF_Thumb) && ThumbTarget; + outs() << SymName << ":\n"; DILineInfo lastLine; for (uint64_t Index = Start; Index < End; Index += Size) { @@ -422,10 +480,19 @@ static void DisassembleInputMachO2(StringRef Filename, continue; } - if (DisAsm->getInstruction(Inst, Size, memoryObject, Index, - DebugOut, nulls())) { + bool gotInst; + if (isThumb) + gotInst = ThumbDisAsm->getInstruction(Inst, Size, memoryObject, Index, + DebugOut, nulls()); + else + gotInst = DisAsm->getInstruction(Inst, Size, memoryObject, Index, + DebugOut, nulls()); + if (gotInst) { DumpBytes(StringRef(Bytes.data() + Index, Size)); - IP->printInst(&Inst, outs(), ""); + if (isThumb) + ThumbIP->printInst(&Inst, outs(), ""); + else + IP->printInst(&Inst, outs(), ""); // Print debug info. if (diContext) { |