[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