forked from OSchip/llvm-project
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. llvm-svn: 215931
This commit is contained in:
parent
a2d4b09a55
commit
ec5ca03674
|
@ -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();
|
||||
|
||||
|
|
|
@ -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) { }
|
||||
|
|
|
@ -439,6 +439,9 @@ uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
|
|||
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::getArch(uint32_t CPUType) {
|
|||
}
|
||||
}
|
||||
|
||||
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 CPUType, uint32_t CPUSubType) {
|
|||
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 CPUType, uint32_t CPUSubType) {
|
|||
}
|
||||
}
|
||||
|
||||
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() const {
|
|||
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;
|
||||
|
|
|
@ -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
|
|
@ -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;
|
||||
|
||||
errs() << "llvm-objdump: error: unable to get target for '" << TripleName
|
||||
<< "', see --version and --triple.\n";
|
||||
*ThumbTarget = TargetRegistry::lookupTarget(ThumbTripleName, Error);
|
||||
if (*ThumbTarget)
|
||||
return TheTarget;
|
||||
|
||||
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;
|
||||
|
@ -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,9 +480,18 @@ 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));
|
||||
if (isThumb)
|
||||
ThumbIP->printInst(&Inst, outs(), "");
|
||||
else
|
||||
IP->printInst(&Inst, outs(), "");
|
||||
|
||||
// Print debug info.
|
||||
|
|
Loading…
Reference in New Issue