[llvm] r215931 - Make llvm-objdump handle both arm and thumb disassembly from the same Mach-O
Kevin Enderby
enderby at apple.com
Mon Aug 18 13:21:02 PDT 2014
Author: enderby
Date: Mon Aug 18 15:21:02 2014
New Revision: 215931
URL: http://llvm.org/viewvc/llvm-project?rev=215931&view=rev
Log:
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.
Added:
llvm/trunk/test/tools/llvm-objdump/ARM/macho-arm-and-thumb.test
Modified:
llvm/trunk/include/llvm/Object/MachO.h
llvm/trunk/include/llvm/Object/SymbolicFile.h
llvm/trunk/lib/Object/MachOObjectFile.cpp
llvm/trunk/tools/llvm-objdump/MachODump.cpp
Modified: llvm/trunk/include/llvm/Object/MachO.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/MachO.h?rev=215931&r1=215930&r2=215931&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Object/MachO.h (original)
+++ llvm/trunk/include/llvm/Object/MachO.h Mon Aug 18 15:21:02 2014
@@ -137,6 +137,7 @@ public:
StringRef getFileFormatName() const override;
unsigned getArch() const override;
+ Triple getArch(const char **McpuDefault, Triple *ThumbTriple) const;
relocation_iterator section_rel_begin(unsigned Index) const;
relocation_iterator section_rel_end(unsigned Index) const;
@@ -215,7 +216,12 @@ public:
StringRef &Suffix);
static Triple::ArchType getArch(uint32_t CPUType);
- static Triple getArch(uint32_t CPUType, uint32_t CPUSubType);
+ static Triple getArch(uint32_t CPUType, uint32_t CPUSubType,
+ const char **McpuDefault = nullptr);
+ static Triple getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
+ const char **McpuDefault = nullptr);
+ static Triple getArch(uint32_t CPUType, uint32_t CPUSubType,
+ const char **McpuDefault, Triple *ThumbTriple);
static bool isValidArch(StringRef ArchFlag);
static Triple getHostArch();
Modified: llvm/trunk/include/llvm/Object/SymbolicFile.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/SymbolicFile.h?rev=215931&r1=215930&r2=215931&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Object/SymbolicFile.h (original)
+++ llvm/trunk/include/llvm/Object/SymbolicFile.h Mon Aug 18 15:21:02 2014
@@ -87,8 +87,9 @@ public:
SF_Absolute = 1U << 3, // Absolute symbol
SF_Common = 1U << 4, // Symbol has common linkage
SF_Indirect = 1U << 5, // Symbol is an alias to another symbol
- SF_FormatSpecific = 1U << 6 // Specific to the object file format
+ SF_FormatSpecific = 1U << 6, // Specific to the object file format
// (e.g. section symbols)
+ SF_Thumb = 1U << 7 // Thumb symbol in a 32-bit ARM binary
};
BasicSymbolRef() : OwningObject(nullptr) { }
Modified: llvm/trunk/lib/Object/MachOObjectFile.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/MachOObjectFile.cpp?rev=215931&r1=215930&r2=215931&view=diff
==============================================================================
--- llvm/trunk/lib/Object/MachOObjectFile.cpp (original)
+++ llvm/trunk/lib/Object/MachOObjectFile.cpp Mon Aug 18 15:21:02 2014
@@ -439,6 +439,9 @@ uint32_t MachOObjectFile::getSymbolFlags
if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
Result |= SymbolRef::SF_Weak;
+ if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
+ Result |= SymbolRef::SF_Thumb;
+
if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
Result |= SymbolRef::SF_Absolute;
@@ -1293,7 +1296,11 @@ Triple::ArchType MachOObjectFile::getArc
}
}
-Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType) {
+Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
+ const char **McpuDefault) {
+ if (McpuDefault)
+ *McpuDefault = nullptr;
+
switch (CPUType) {
case MachO::CPU_TYPE_I386:
switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
@@ -1322,14 +1329,20 @@ Triple MachOObjectFile::getArch(uint32_t
case MachO::CPU_SUBTYPE_ARM_V6:
return Triple("armv6-apple-darwin");
case MachO::CPU_SUBTYPE_ARM_V6M:
+ if (McpuDefault)
+ *McpuDefault = "cortex-m0";
return Triple("armv6m-apple-darwin");
case MachO::CPU_SUBTYPE_ARM_V7:
return Triple("armv7-apple-darwin");
case MachO::CPU_SUBTYPE_ARM_V7EM:
+ if (McpuDefault)
+ *McpuDefault = "cortex-m4";
return Triple("armv7em-apple-darwin");
case MachO::CPU_SUBTYPE_ARM_V7K:
return Triple("armv7k-apple-darwin");
case MachO::CPU_SUBTYPE_ARM_V7M:
+ if (McpuDefault)
+ *McpuDefault = "cortex-m3";
return Triple("armv7m-apple-darwin");
case MachO::CPU_SUBTYPE_ARM_V7S:
return Triple("armv7s-apple-darwin");
@@ -1362,6 +1375,57 @@ Triple MachOObjectFile::getArch(uint32_t
}
}
+Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType,
+ const char **McpuDefault) {
+ if (McpuDefault)
+ *McpuDefault = nullptr;
+
+ switch (CPUType) {
+ case MachO::CPU_TYPE_ARM:
+ switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
+ case MachO::CPU_SUBTYPE_ARM_V4T:
+ return Triple("thumbv4t-apple-darwin");
+ case MachO::CPU_SUBTYPE_ARM_V5TEJ:
+ return Triple("thumbv5e-apple-darwin");
+ case MachO::CPU_SUBTYPE_ARM_XSCALE:
+ return Triple("xscale-apple-darwin");
+ case MachO::CPU_SUBTYPE_ARM_V6:
+ return Triple("thumbv6-apple-darwin");
+ case MachO::CPU_SUBTYPE_ARM_V6M:
+ if (McpuDefault)
+ *McpuDefault = "cortex-m0";
+ return Triple("thumbv6m-apple-darwin");
+ case MachO::CPU_SUBTYPE_ARM_V7:
+ return Triple("thumbv7-apple-darwin");
+ case MachO::CPU_SUBTYPE_ARM_V7EM:
+ if (McpuDefault)
+ *McpuDefault = "cortex-m4";
+ return Triple("thumbv7em-apple-darwin");
+ case MachO::CPU_SUBTYPE_ARM_V7K:
+ return Triple("thumbv7k-apple-darwin");
+ case MachO::CPU_SUBTYPE_ARM_V7M:
+ if (McpuDefault)
+ *McpuDefault = "cortex-m3";
+ return Triple("thumbv7m-apple-darwin");
+ case MachO::CPU_SUBTYPE_ARM_V7S:
+ return Triple("thumbv7s-apple-darwin");
+ default:
+ return Triple();
+ }
+ default:
+ return Triple();
+ }
+}
+
+Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType,
+ const char **McpuDefault,
+ Triple *ThumbTriple) {
+ Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault);
+ *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType,
+ McpuDefault);
+ return T;
+}
+
Triple MachOObjectFile::getHostArch() {
return Triple(sys::getDefaultTargetTriple());
}
@@ -1390,6 +1454,25 @@ unsigned MachOObjectFile::getArch() cons
return getArch(getCPUType(this));
}
+Triple MachOObjectFile::getArch(const char **McpuDefault,
+ Triple *ThumbTriple) const {
+ Triple T;
+ if (is64Bit()) {
+ MachO::mach_header_64 H_64;
+ H_64 = getHeader64();
+ T = MachOObjectFile::getArch(H_64.cputype, H_64.cpusubtype, McpuDefault);
+ *ThumbTriple = MachOObjectFile::getThumbArch(H_64.cputype, H_64.cpusubtype,
+ McpuDefault);
+ } else {
+ MachO::mach_header H;
+ H = getHeader();
+ T = MachOObjectFile::getArch(H.cputype, H.cpusubtype, McpuDefault);
+ *ThumbTriple = MachOObjectFile::getThumbArch(H.cputype, H.cpusubtype,
+ McpuDefault);
+ }
+ return T;
+}
+
relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
DataRefImpl DRI;
DRI.d.a = Index;
Added: llvm/trunk/test/tools/llvm-objdump/ARM/macho-arm-and-thumb.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-objdump/ARM/macho-arm-and-thumb.test?rev=215931&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-objdump/ARM/macho-arm-and-thumb.test (added)
+++ llvm/trunk/test/tools/llvm-objdump/ARM/macho-arm-and-thumb.test Mon Aug 18 15:21:02 2014
@@ -0,0 +1,15 @@
+@ RUN: llvm-mc < %s -triple armv7-apple-darwin -filetype=obj | llvm-objdump -m -d - | FileCheck %s
+
+.thumb
+.thumb_func _t
+_t:
+nop
+nop
+.align 2
+.arm
+_a:
+nop
+
+@ CHECK: 00 bf nop
+@ CHECK-NEXT: 00 bf nop
+@ CHECK: 00 f0 20 e3 nop
Modified: llvm/trunk/tools/llvm-objdump/MachODump.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-objdump/MachODump.cpp?rev=215931&r1=215930&r2=215931&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-objdump/MachODump.cpp (original)
+++ llvm/trunk/tools/llvm-objdump/MachODump.cpp Mon Aug 18 15:21:02 2014
@@ -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(StringR
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(Strin
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(Strin
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(Strin
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(Strin
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) {
More information about the llvm-commits
mailing list