Update llvm-objdump’s Mach-O symbolizer code to demangle C++ names.
[oota-llvm.git] / tools / llvm-objdump / MachODump.cpp
index 378eacb256a288a3a953e0b0afd5bf97277be301..7d7eb80569ca52d294101d181222eb253c8fca24 100644 (file)
@@ -16,6 +16,7 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/Triple.h"
+#include "llvm/Config/config.h"
 #include "llvm/DebugInfo/DIContext.h"
 #include "llvm/MC/MCAsmInfo.h"
 #include "llvm/MC/MCContext.h"
 #include "llvm/Support/GraphWriter.h"
 #include "llvm/Support/MachO.h"
 #include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/FormattedStream.h"
 #include "llvm/Support/TargetRegistry.h"
 #include "llvm/Support/TargetSelect.h"
 #include "llvm/Support/raw_ostream.h"
 #include <algorithm>
 #include <cstring>
 #include <system_error>
+
+#if HAVE_CXXABI_H
+#include <cxxabi.h>
+#endif
+
 using namespace llvm;
 using namespace object;
 
@@ -51,6 +58,14 @@ static cl::opt<bool>
 static cl::opt<std::string>
   DSYMFile("dsym", cl::desc("Use .dSYM file for debug info"));
 
+static cl::opt<bool>
+    FullLeadingAddr("full-leading-addr",
+                    cl::desc("Print full leading address"));
+
+static cl::opt<bool>
+    PrintImmHex("print-imm-hex",
+                cl::desc("Use hex format for immediate values"));
+
 static std::string ThumbTripleName;
 
 static const Target *GetTarget(const MachOObjectFile *MachOObj,
@@ -225,11 +240,23 @@ void llvm::DisassembleInputMachO(StringRef Filename) {
   DisassembleInputMachO2(Filename, MachOOF.get());
 }
 
+typedef DenseMap<uint64_t, StringRef> SymbolAddressMap;
+typedef std::pair<uint64_t, const char *> BindInfoEntry;
+typedef std::vector<BindInfoEntry> BindTable;
+typedef BindTable::iterator bind_table_iterator;
+
 // The block of info used by the Symbolizer call backs.
 struct DisassembleInfo {
   bool verbose;
   MachOObjectFile *O;
   SectionRef S;
+  SymbolAddressMap *AddrMap;
+  std::vector<SectionRef> *Sections;
+  const char *class_name;
+  const char *selector_name;
+  char *method;
+  char *demangled_name;
+  BindTable *bindtable;
 };
 
 // SymbolizerGetOpInfo() is the operand information call back function.
@@ -271,8 +298,7 @@ int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset,
       return 0;
     // First search the section's relocation entries (if any) for an entry
     // for this section offset.
-    uint64_t sect_addr;
-    info->S.getAddress(sect_addr);
+    uint64_t sect_addr = info->S.getAddress();
     uint64_t sect_offset = (Pc + Offset) - sect_addr;
     bool reloc_found = false;
     DataRefImpl Rel;
@@ -301,7 +327,6 @@ int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset,
       // is the offset from the external symbol.
       if (info->O->getAnyRelocationPCRel(RE))
         op_info->Value -= Pc + Offset + Size;
-      // SymbolRef Symbol = (*info->Relocs)[Idx].second;
       StringRef SymName;
       Symbol.getName(SymName);
       const char *name = SymName.data();
@@ -332,7 +357,7 @@ int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset,
     // TODO:
     // Second search the external relocation entries of a fully linked image
     // (if any) for an entry that matches this segment offset.
-    //uint64_t seg_offset = (Pc + Offset);
+    // uint64_t seg_offset = (Pc + Offset);
     return 0;
   } else if (Arch == Triple::arm) {
     return 0;
@@ -343,8 +368,682 @@ int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset,
   }
 }
 
+// GuessCstringPointer is passed the address of what might be a pointer to a
+// literal string in a cstring section.  If that address is in a cstring section
+// it returns a pointer to that string.  Else it returns nullptr.
+const char *GuessCstringPointer(uint64_t ReferenceValue,
+                                struct DisassembleInfo *info) {
+  uint32_t LoadCommandCount = info->O->getHeader().ncmds;
+  MachOObjectFile::LoadCommandInfo Load = info->O->getFirstLoadCommandInfo();
+  for (unsigned I = 0;; ++I) {
+    if (Load.C.cmd == MachO::LC_SEGMENT_64) {
+      MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load);
+      for (unsigned J = 0; J < Seg.nsects; ++J) {
+        MachO::section_64 Sec = info->O->getSection64(Load, J);
+        uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
+        if (section_type == MachO::S_CSTRING_LITERALS &&
+            ReferenceValue >= Sec.addr &&
+            ReferenceValue < Sec.addr + Sec.size) {
+          uint64_t sect_offset = ReferenceValue - Sec.addr;
+          uint64_t object_offset = Sec.offset + sect_offset;
+          StringRef MachOContents = info->O->getData();
+          uint64_t object_size = MachOContents.size();
+          const char *object_addr = (const char *)MachOContents.data();
+          if (object_offset < object_size) {
+            const char *name = object_addr + object_offset;
+            return name;
+          } else {
+            return nullptr;
+          }
+        }
+      }
+    } else if (Load.C.cmd == MachO::LC_SEGMENT) {
+      MachO::segment_command Seg = info->O->getSegmentLoadCommand(Load);
+      for (unsigned J = 0; J < Seg.nsects; ++J) {
+        MachO::section Sec = info->O->getSection(Load, J);
+        uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
+        if (section_type == MachO::S_CSTRING_LITERALS &&
+            ReferenceValue >= Sec.addr &&
+            ReferenceValue < Sec.addr + Sec.size) {
+          uint64_t sect_offset = ReferenceValue - Sec.addr;
+          uint64_t object_offset = Sec.offset + sect_offset;
+          StringRef MachOContents = info->O->getData();
+          uint64_t object_size = MachOContents.size();
+          const char *object_addr = (const char *)MachOContents.data();
+          if (object_offset < object_size) {
+            const char *name = object_addr + object_offset;
+            return name;
+          } else {
+            return nullptr;
+          }
+        }
+      }
+    }
+    if (I == LoadCommandCount - 1)
+      break;
+    else
+      Load = info->O->getNextLoadCommandInfo(Load);
+  }
+  return nullptr;
+}
+
+// GuessIndirectSymbol returns the name of the indirect symbol for the
+// ReferenceValue passed in or nullptr.  This is used when ReferenceValue maybe
+// an address of a symbol stub or a lazy or non-lazy pointer to associate the
+// symbol name being referenced by the stub or pointer.
+static const char *GuessIndirectSymbol(uint64_t ReferenceValue,
+                                       struct DisassembleInfo *info) {
+  uint32_t LoadCommandCount = info->O->getHeader().ncmds;
+  MachOObjectFile::LoadCommandInfo Load = info->O->getFirstLoadCommandInfo();
+  MachO::dysymtab_command Dysymtab = info->O->getDysymtabLoadCommand();
+  MachO::symtab_command Symtab = info->O->getSymtabLoadCommand();
+  for (unsigned I = 0;; ++I) {
+    if (Load.C.cmd == MachO::LC_SEGMENT_64) {
+      MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load);
+      for (unsigned J = 0; J < Seg.nsects; ++J) {
+        MachO::section_64 Sec = info->O->getSection64(Load, J);
+        uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
+        if ((section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
+             section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
+             section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
+             section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS ||
+             section_type == MachO::S_SYMBOL_STUBS) &&
+            ReferenceValue >= Sec.addr &&
+            ReferenceValue < Sec.addr + Sec.size) {
+          uint32_t stride;
+          if (section_type == MachO::S_SYMBOL_STUBS)
+            stride = Sec.reserved2;
+          else
+            stride = 8;
+          if (stride == 0)
+            return nullptr;
+          uint32_t index = Sec.reserved1 + (ReferenceValue - Sec.addr) / stride;
+          if (index < Dysymtab.nindirectsyms) {
+            uint32_t indirect_symbol =
+                info->O->getIndirectSymbolTableEntry(Dysymtab, index);
+            if (indirect_symbol < Symtab.nsyms) {
+              symbol_iterator Sym = info->O->getSymbolByIndex(indirect_symbol);
+              SymbolRef Symbol = *Sym;
+              StringRef SymName;
+              Symbol.getName(SymName);
+              const char *name = SymName.data();
+              return name;
+            }
+          }
+        }
+      }
+    } else if (Load.C.cmd == MachO::LC_SEGMENT) {
+      MachO::segment_command Seg = info->O->getSegmentLoadCommand(Load);
+      for (unsigned J = 0; J < Seg.nsects; ++J) {
+        MachO::section Sec = info->O->getSection(Load, J);
+        uint32_t section_type = Sec.flags & MachO::SECTION_TYPE;
+        if ((section_type == MachO::S_NON_LAZY_SYMBOL_POINTERS ||
+             section_type == MachO::S_LAZY_SYMBOL_POINTERS ||
+             section_type == MachO::S_LAZY_DYLIB_SYMBOL_POINTERS ||
+             section_type == MachO::S_THREAD_LOCAL_VARIABLE_POINTERS ||
+             section_type == MachO::S_SYMBOL_STUBS) &&
+            ReferenceValue >= Sec.addr &&
+            ReferenceValue < Sec.addr + Sec.size) {
+          uint32_t stride;
+          if (section_type == MachO::S_SYMBOL_STUBS)
+            stride = Sec.reserved2;
+          else
+            stride = 4;
+          if (stride == 0)
+            return nullptr;
+          uint32_t index = Sec.reserved1 + (ReferenceValue - Sec.addr) / stride;
+          if (index < Dysymtab.nindirectsyms) {
+            uint32_t indirect_symbol =
+                info->O->getIndirectSymbolTableEntry(Dysymtab, index);
+            if (indirect_symbol < Symtab.nsyms) {
+              symbol_iterator Sym = info->O->getSymbolByIndex(indirect_symbol);
+              SymbolRef Symbol = *Sym;
+              StringRef SymName;
+              Symbol.getName(SymName);
+              const char *name = SymName.data();
+              return name;
+            }
+          }
+        }
+      }
+    }
+    if (I == LoadCommandCount - 1)
+      break;
+    else
+      Load = info->O->getNextLoadCommandInfo(Load);
+  }
+  return nullptr;
+}
+
+// method_reference() is called passing it the ReferenceName that might be
+// a reference it to an Objective-C method call.  If so then it allocates and
+// assembles a method call string with the values last seen and saved in
+// the DisassembleInfo's class_name and selector_name fields.  This is saved
+// into the method field of the info and any previous string is free'ed.
+// Then the class_name field in the info is set to nullptr.  The method call
+// string is set into ReferenceName and ReferenceType is set to
+// LLVMDisassembler_ReferenceType_Out_Objc_Message.  If this not a method call
+// then both ReferenceType and ReferenceName are left unchanged.
+static void method_reference(struct DisassembleInfo *info,
+                             uint64_t *ReferenceType,
+                             const char **ReferenceName) {
+  if (*ReferenceName != nullptr) {
+    if (strcmp(*ReferenceName, "_objc_msgSend") == 0) {
+      if (info->selector_name != NULL) {
+        if (info->method != nullptr)
+          free(info->method);
+        if (info->class_name != nullptr) {
+          info->method = (char *)malloc(5 + strlen(info->class_name) +
+                                        strlen(info->selector_name));
+          if (info->method != nullptr) {
+            strcpy(info->method, "+[");
+            strcat(info->method, info->class_name);
+            strcat(info->method, " ");
+            strcat(info->method, info->selector_name);
+            strcat(info->method, "]");
+            *ReferenceName = info->method;
+            *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message;
+          }
+        } else {
+          info->method = (char *)malloc(9 + strlen(info->selector_name));
+          if (info->method != nullptr) {
+            strcpy(info->method, "-[%rdi ");
+            strcat(info->method, info->selector_name);
+            strcat(info->method, "]");
+            *ReferenceName = info->method;
+            *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message;
+          }
+        }
+        info->class_name = nullptr;
+      }
+    } else if (strcmp(*ReferenceName, "_objc_msgSendSuper2") == 0) {
+      if (info->selector_name != NULL) {
+        if (info->method != nullptr)
+          free(info->method);
+        info->method = (char *)malloc(17 + strlen(info->selector_name));
+        if (info->method != nullptr) {
+          strcpy(info->method, "-[[%rdi super] ");
+          strcat(info->method, info->selector_name);
+          strcat(info->method, "]");
+          *ReferenceName = info->method;
+          *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message;
+        }
+        info->class_name = nullptr;
+      }
+    }
+  }
+}
+
+// GuessPointerPointer() is passed the address of what might be a pointer to
+// a reference to an Objective-C class, selector, message ref or cfstring.
+// If so the value of the pointer is returned and one of the booleans are set
+// to true.  If not zero is returned and all the booleans are set to false.
+static uint64_t GuessPointerPointer(uint64_t ReferenceValue,
+                                    struct DisassembleInfo *info,
+                                    bool &classref, bool &selref, bool &msgref,
+                                    bool &cfstring) {
+  classref = false;
+  selref = false;
+  msgref = false;
+  cfstring = false;
+  uint32_t LoadCommandCount = info->O->getHeader().ncmds;
+  MachOObjectFile::LoadCommandInfo Load = info->O->getFirstLoadCommandInfo();
+  for (unsigned I = 0;; ++I) {
+    if (Load.C.cmd == MachO::LC_SEGMENT_64) {
+      MachO::segment_command_64 Seg = info->O->getSegment64LoadCommand(Load);
+      for (unsigned J = 0; J < Seg.nsects; ++J) {
+        MachO::section_64 Sec = info->O->getSection64(Load, J);
+        if ((strncmp(Sec.sectname, "__objc_selrefs", 16) == 0 ||
+             strncmp(Sec.sectname, "__objc_classrefs", 16) == 0 ||
+             strncmp(Sec.sectname, "__objc_superrefs", 16) == 0 ||
+             strncmp(Sec.sectname, "__objc_msgrefs", 16) == 0 ||
+             strncmp(Sec.sectname, "__cfstring", 16) == 0) &&
+            ReferenceValue >= Sec.addr &&
+            ReferenceValue < Sec.addr + Sec.size) {
+          uint64_t sect_offset = ReferenceValue - Sec.addr;
+          uint64_t object_offset = Sec.offset + sect_offset;
+          StringRef MachOContents = info->O->getData();
+          uint64_t object_size = MachOContents.size();
+          const char *object_addr = (const char *)MachOContents.data();
+          if (object_offset < object_size) {
+            uint64_t pointer_value;
+            memcpy(&pointer_value, object_addr + object_offset,
+                   sizeof(uint64_t));
+            if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
+              sys::swapByteOrder(pointer_value);
+            if (strncmp(Sec.sectname, "__objc_selrefs", 16) == 0)
+              selref = true;
+            else if (strncmp(Sec.sectname, "__objc_classrefs", 16) == 0 ||
+                     strncmp(Sec.sectname, "__objc_superrefs", 16) == 0)
+              classref = true;
+            else if (strncmp(Sec.sectname, "__objc_msgrefs", 16) == 0 &&
+                     ReferenceValue + 8 < Sec.addr + Sec.size) {
+              msgref = true;
+              memcpy(&pointer_value, object_addr + object_offset + 8,
+                     sizeof(uint64_t));
+              if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
+                sys::swapByteOrder(pointer_value);
+            } else if (strncmp(Sec.sectname, "__cfstring", 16) == 0)
+              cfstring = true;
+            return pointer_value;
+          } else {
+            return 0;
+          }
+        }
+      }
+    }
+    // TODO: Look for LC_SEGMENT for 32-bit Mach-O files.
+    if (I == LoadCommandCount - 1)
+      break;
+    else
+      Load = info->O->getNextLoadCommandInfo(Load);
+  }
+  return 0;
+}
+
+// get_pointer_64 returns a pointer to the bytes in the object file at the
+// Address from a section in the Mach-O file.  And indirectly returns the
+// offset into the section, number of bytes left in the section past the offset
+// and which section is was being referenced.  If the Address is not in a
+// section nullptr is returned.
+const char *get_pointer_64(uint64_t Address, uint32_t &offset, uint32_t &left,
+                           SectionRef &S, DisassembleInfo *info) {
+  offset = 0;
+  left = 0;
+  S = SectionRef();
+  for (unsigned SectIdx = 0; SectIdx != info->Sections->size(); SectIdx++) {
+    uint64_t SectAddress = ((*(info->Sections))[SectIdx]).getAddress();
+    uint64_t SectSize = ((*(info->Sections))[SectIdx]).getSize();
+    if (Address >= SectAddress && Address < SectAddress + SectSize) {
+      S = (*(info->Sections))[SectIdx];
+      offset = Address - SectAddress;
+      left = SectSize - offset;
+      StringRef SectContents;
+      ((*(info->Sections))[SectIdx]).getContents(SectContents);
+      return SectContents.data() + offset;
+    }
+  }
+  return nullptr;
+}
+
+// get_symbol_64() returns the name of a symbol (or nullptr) and the address of
+// the symbol indirectly through n_value. Based on the relocation information
+// for the specified section offset in the specified section reference.
+const char *get_symbol_64(uint32_t sect_offset, SectionRef S,
+                          DisassembleInfo *info, uint64_t &n_value) {
+  n_value = 0;
+  if (info->verbose == false)
+    return nullptr;
+
+  // See if there is an external relocation entry at the sect_offset.
+  bool reloc_found = false;
+  DataRefImpl Rel;
+  MachO::any_relocation_info RE;
+  bool isExtern = false;
+  SymbolRef Symbol;
+  for (const RelocationRef &Reloc : S.relocations()) {
+    uint64_t RelocOffset;
+    Reloc.getOffset(RelocOffset);
+    if (RelocOffset == sect_offset) {
+      Rel = Reloc.getRawDataRefImpl();
+      RE = info->O->getRelocation(Rel);
+      if (info->O->isRelocationScattered(RE))
+        continue;
+      isExtern = info->O->getPlainRelocationExternal(RE);
+      if (isExtern) {
+        symbol_iterator RelocSym = Reloc.getSymbol();
+        Symbol = *RelocSym;
+      }
+      reloc_found = true;
+      break;
+    }
+  }
+  // If there is an external relocation entry for a symbol in this section
+  // at this section_offset then use that symbol's value for the n_value
+  // and return its name.
+  const char *SymbolName = nullptr;
+  if (reloc_found && isExtern) {
+    Symbol.getAddress(n_value);
+    StringRef name;
+    Symbol.getName(name);
+    if (!name.empty()) {
+      SymbolName = name.data();
+      return SymbolName;
+    }
+  }
+
+  // TODO: For fully linked images, look through the external relocation
+  // entries off the dynamic symtab command. For these the r_offset is from the
+  // start of the first writeable segment in the Mach-O file.  So the offset
+  // to this section from that segment is passed to this routine by the caller,
+  // as the database_offset. Which is the difference of the section's starting
+  // address and the first writable segment.
+  //
+  // NOTE: need add passing the database_offset to this routine.
+
+  // TODO: We did not find an external relocation entry so look up the
+  // ReferenceValue as an address of a symbol and if found return that symbol's
+  // name.
+  //
+  // NOTE: need add passing the ReferenceValue to this routine.  Then that code
+  // would simply be this:
+  //
+  // if (ReferenceValue != 0xffffffffffffffffLLU &&
+  //     ReferenceValue != 0xfffffffffffffffeLLU) {
+  //   StringRef name = info->AddrMap->lookup(ReferenceValue);
+  //   if (!name.empty())
+  //     SymbolName = name.data();
+  // }
+
+  return SymbolName;
+}
+
+// These are structs in the Objective-C meta data and read to produce the
+// comments for disassembly.  While these are part of the ABI they are no
+// public defintions.  So the are here not in include/llvm/Support/MachO.h .
+
+// The cfstring object in a 64-bit Mach-O file.
+struct cfstring64_t {
+  uint64_t isa;        // class64_t * (64-bit pointer)
+  uint64_t flags;      // flag bits
+  uint64_t characters; // char * (64-bit pointer)
+  uint64_t length;     // number of non-NULL characters in above
+};
+
+// The class object in a 64-bit Mach-O file.
+struct class64_t {
+  uint64_t isa;        // class64_t * (64-bit pointer)
+  uint64_t superclass; // class64_t * (64-bit pointer)
+  uint64_t cache;      // Cache (64-bit pointer)
+  uint64_t vtable;     // IMP * (64-bit pointer)
+  uint64_t data;       // class_ro64_t * (64-bit pointer)
+};
+
+struct class_ro64_t {
+  uint32_t flags;
+  uint32_t instanceStart;
+  uint32_t instanceSize;
+  uint32_t reserved;
+  uint64_t ivarLayout;     // const uint8_t * (64-bit pointer)
+  uint64_t name;           // const char * (64-bit pointer)
+  uint64_t baseMethods;    // const method_list_t * (64-bit pointer)
+  uint64_t baseProtocols;  // const protocol_list_t * (64-bit pointer)
+  uint64_t ivars;          // const ivar_list_t * (64-bit pointer)
+  uint64_t weakIvarLayout; // const uint8_t * (64-bit pointer)
+  uint64_t baseProperties; // const struct objc_property_list (64-bit pointer)
+};
+
+inline void swapStruct(struct cfstring64_t &cfs) {
+  sys::swapByteOrder(cfs.isa);
+  sys::swapByteOrder(cfs.flags);
+  sys::swapByteOrder(cfs.characters);
+  sys::swapByteOrder(cfs.length);
+}
+
+inline void swapStruct(struct class64_t &c) {
+  sys::swapByteOrder(c.isa);
+  sys::swapByteOrder(c.superclass);
+  sys::swapByteOrder(c.cache);
+  sys::swapByteOrder(c.vtable);
+  sys::swapByteOrder(c.data);
+}
+
+inline void swapStruct(struct class_ro64_t &cro) {
+  sys::swapByteOrder(cro.flags);
+  sys::swapByteOrder(cro.instanceStart);
+  sys::swapByteOrder(cro.instanceSize);
+  sys::swapByteOrder(cro.reserved);
+  sys::swapByteOrder(cro.ivarLayout);
+  sys::swapByteOrder(cro.name);
+  sys::swapByteOrder(cro.baseMethods);
+  sys::swapByteOrder(cro.baseProtocols);
+  sys::swapByteOrder(cro.ivars);
+  sys::swapByteOrder(cro.weakIvarLayout);
+  sys::swapByteOrder(cro.baseProperties);
+}
+
+static const char *get_dyld_bind_info_symbolname(uint64_t ReferenceValue,
+                                                 struct DisassembleInfo *info);
+
+// get_objc2_64bit_class_name() is used for disassembly and is passed a pointer
+// to an Objective-C class and returns the class name.  It is also passed the
+// address of the pointer, so when the pointer is zero as it can be in an .o
+// file, that is used to look for an external relocation entry with a symbol
+// name.
+const char *get_objc2_64bit_class_name(uint64_t pointer_value,
+                                       uint64_t ReferenceValue,
+                                       struct DisassembleInfo *info) {
+  const char *r;
+  uint32_t offset, left;
+  SectionRef S;
+
+  // The pointer_value can be 0 in an object file and have a relocation
+  // entry for the class symbol at the ReferenceValue (the address of the
+  // pointer).
+  if (pointer_value == 0) {
+    r = get_pointer_64(ReferenceValue, offset, left, S, info);
+    if (r == nullptr || left < sizeof(uint64_t))
+      return nullptr;
+    uint64_t n_value;
+    const char *symbol_name = get_symbol_64(offset, S, info, n_value);
+    if (symbol_name == nullptr)
+      return nullptr;
+    const char *class_name = strrchr(symbol_name, '$');
+    if (class_name != nullptr && class_name[1] == '_' && class_name[2] != '\0')
+      return class_name + 2;
+    else
+      return nullptr;
+  }
+
+  // The case were the pointer_value is non-zero and points to a class defined
+  // in this Mach-O file.
+  r = get_pointer_64(pointer_value, offset, left, S, info);
+  if (r == nullptr || left < sizeof(struct class64_t))
+    return nullptr;
+  struct class64_t c;
+  memcpy(&c, r, sizeof(struct class64_t));
+  if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
+    swapStruct(c);
+  if (c.data == 0)
+    return nullptr;
+  r = get_pointer_64(c.data, offset, left, S, info);
+  if (r == nullptr || left < sizeof(struct class_ro64_t))
+    return nullptr;
+  struct class_ro64_t cro;
+  memcpy(&cro, r, sizeof(struct class_ro64_t));
+  if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
+    swapStruct(cro);
+  if (cro.name == 0)
+    return nullptr;
+  const char *name = get_pointer_64(cro.name, offset, left, S, info);
+  return name;
+}
+
+// get_objc2_64bit_cfstring_name is used for disassembly and is passed a
+// pointer to a cfstring and returns its name or nullptr.
+const char *get_objc2_64bit_cfstring_name(uint64_t ReferenceValue,
+                                          struct DisassembleInfo *info) {
+  const char *r, *name;
+  uint32_t offset, left;
+  SectionRef S;
+  struct cfstring64_t cfs;
+  uint64_t cfs_characters;
+
+  r = get_pointer_64(ReferenceValue, offset, left, S, info);
+  if (r == nullptr || left < sizeof(struct cfstring64_t))
+    return nullptr;
+  memcpy(&cfs, r, sizeof(struct cfstring64_t));
+  if (info->O->isLittleEndian() != sys::IsLittleEndianHost)
+    swapStruct(cfs);
+  if (cfs.characters == 0) {
+    uint64_t n_value;
+    const char *symbol_name = get_symbol_64(
+        offset + offsetof(struct cfstring64_t, characters), S, info, n_value);
+    if (symbol_name == nullptr)
+      return nullptr;
+    cfs_characters = n_value;
+  } else
+    cfs_characters = cfs.characters;
+  name = get_pointer_64(cfs_characters, offset, left, S, info);
+
+  return name;
+}
+
+// get_objc2_64bit_selref() is used for disassembly and is passed a the address
+// of a pointer to an Objective-C selector reference when the pointer value is
+// zero as in a .o file and is likely to have a external relocation entry with
+// who's symbol's n_value is the real pointer to the selector name.  If that is
+// the case the real pointer to the selector name is returned else 0 is
+// returned
+uint64_t get_objc2_64bit_selref(uint64_t ReferenceValue,
+                                struct DisassembleInfo *info) {
+  uint32_t offset, left;
+  SectionRef S;
+
+  const char *r = get_pointer_64(ReferenceValue, offset, left, S, info);
+  if (r == nullptr || left < sizeof(uint64_t))
+    return 0;
+  uint64_t n_value;
+  const char *symbol_name = get_symbol_64(offset, S, info, n_value);
+  if (symbol_name == nullptr)
+    return 0;
+  return n_value;
+}
+
+// GuessLiteralPointer returns a string which for the item in the Mach-O file
+// for the address passed in as ReferenceValue for printing as a comment with
+// the instruction and also returns the corresponding type of that item
+// indirectly through ReferenceType.
+//
+// If ReferenceValue is an address of literal cstring then a pointer to the
+// cstring is returned and ReferenceType is set to
+// LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr .
+//
+// If ReferenceValue is an address of an Objective-C CFString, Selector ref or
+// Class ref that name is returned and the ReferenceType is set accordingly.
+//
+// Lastly, literals which are Symbol address in a literal pool are looked for
+// and if found the symbol name is returned and ReferenceType is set to
+// LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr .
+//
+// If there is no item in the Mach-O file for the address passed in as
+// ReferenceValue nullptr is returned and ReferenceType is unchanged.
+const char *GuessLiteralPointer(uint64_t ReferenceValue, uint64_t ReferencePC,
+                                uint64_t *ReferenceType,
+                                struct DisassembleInfo *info) {
+  // TODO: This rouine's code and the routines it calls are only work with
+  // x86_64 Mach-O files for now.
+  unsigned int Arch = info->O->getArch();
+  if (Arch != Triple::x86_64)
+    return nullptr;
+
+  // First see if there is an external relocation entry at the ReferencePC.
+  uint64_t sect_addr = info->S.getAddress();
+  uint64_t sect_offset = ReferencePC - sect_addr;
+  bool reloc_found = false;
+  DataRefImpl Rel;
+  MachO::any_relocation_info RE;
+  bool isExtern = false;
+  SymbolRef Symbol;
+  for (const RelocationRef &Reloc : info->S.relocations()) {
+    uint64_t RelocOffset;
+    Reloc.getOffset(RelocOffset);
+    if (RelocOffset == sect_offset) {
+      Rel = Reloc.getRawDataRefImpl();
+      RE = info->O->getRelocation(Rel);
+      if (info->O->isRelocationScattered(RE))
+        continue;
+      isExtern = info->O->getPlainRelocationExternal(RE);
+      if (isExtern) {
+        symbol_iterator RelocSym = Reloc.getSymbol();
+        Symbol = *RelocSym;
+      }
+      reloc_found = true;
+      break;
+    }
+  }
+  // If there is an external relocation entry for a symbol in a section
+  // then used that symbol's value for the value of the reference.
+  if (reloc_found && isExtern) {
+    if (info->O->getAnyRelocationPCRel(RE)) {
+      unsigned Type = info->O->getAnyRelocationType(RE);
+      if (Type == MachO::X86_64_RELOC_SIGNED) {
+        Symbol.getAddress(ReferenceValue);
+      }
+    }
+  }
+
+  // Look for literals such as Objective-C CFStrings refs, Selector refs,
+  // Message refs and Class refs.
+  bool classref, selref, msgref, cfstring;
+  uint64_t pointer_value = GuessPointerPointer(ReferenceValue, info, classref,
+                                               selref, msgref, cfstring);
+  if (classref == true && pointer_value == 0) {
+    // Note the ReferenceValue is a pointer into the __objc_classrefs section.
+    // And the pointer_value in that section is typically zero as it will be
+    // set by dyld as part of the "bind information".
+    const char *name = get_dyld_bind_info_symbolname(ReferenceValue, info);
+    if (name != nullptr) {
+      *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref;
+      const char *class_name = strrchr(name, '$');
+      if (class_name != nullptr && class_name[1] == '_' &&
+          class_name[2] != '\0') {
+        info->class_name = class_name + 2;
+        return name;
+      }
+    }
+  }
+
+  if (classref == true) {
+    *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Class_Ref;
+    const char *name =
+        get_objc2_64bit_class_name(pointer_value, ReferenceValue, info);
+    if (name != nullptr)
+      info->class_name = name;
+    else
+      name = "bad class ref";
+    return name;
+  }
+
+  if (cfstring == true) {
+    *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_CFString_Ref;
+    const char *name = get_objc2_64bit_cfstring_name(ReferenceValue, info);
+    return name;
+  }
+
+  if (selref == true && pointer_value == 0)
+    pointer_value = get_objc2_64bit_selref(ReferenceValue, info);
+
+  if (pointer_value != 0)
+    ReferenceValue = pointer_value;
+
+  const char *name = GuessCstringPointer(ReferenceValue, info);
+  if (name) {
+    if (pointer_value != 0 && selref == true) {
+      *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Selector_Ref;
+      info->selector_name = name;
+    } else if (pointer_value != 0 && msgref == true) {
+      info->class_name = nullptr;
+      *ReferenceType = LLVMDisassembler_ReferenceType_Out_Objc_Message_Ref;
+      info->selector_name = name;
+    } else
+      *ReferenceType = LLVMDisassembler_ReferenceType_Out_LitPool_CstrAddr;
+    return name;
+  }
+
+  // Lastly look for an indirect symbol with this ReferenceValue which is in
+  // a literal pool.  If found return that symbol name.
+  name = GuessIndirectSymbol(ReferenceValue, info);
+  if (name) {
+    *ReferenceType = LLVMDisassembler_ReferenceType_Out_LitPool_SymAddr;
+    return name;
+  }
+
+  return nullptr;
+}
+
 // SymbolizerSymbolLookUp is the symbol lookup function passed when creating
-// the Symbolizer.  It looks up the SymbolValue using the info passed via the
+// the Symbolizer.  It looks up the ReferenceValue using the info passed via the
 // pointer to the struct DisassembleInfo that was passed when MCSymbolizer
 // is created and returns the symbol name that matches the ReferenceValue or
 // nullptr if none.  The ReferenceType is passed in for the IN type of
@@ -353,9 +1052,11 @@ int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset,
 // Out type and the ReferenceName will also be set which is added as a comment
 // to the disassembled instruction.
 //
+#if HAVE_CXXABI_H
 // If the symbol name is a C++ mangled name then the demangled name is
 // returned through ReferenceName and ReferenceType is set to
 // LLVMDisassembler_ReferenceType_DeMangled_Name .
+#endif
 //
 // When this is called to get a symbol name for a branch target then the
 // ReferenceType will be LLVMDisassembler_ReferenceType_In_Branch and then
@@ -364,30 +1065,139 @@ int SymbolizerGetOpInfo(void *DisInfo, uint64_t Pc, uint64_t Offset,
 // stub is returned indirectly through ReferenceName and then ReferenceType is
 // set to LLVMDisassembler_ReferenceType_Out_SymbolStub.
 //
-// When this is called with an value loaded via a PC relative load then 
+// When this is called with an value loaded via a PC relative load then
 // ReferenceType will be LLVMDisassembler_ReferenceType_In_PCrel_Load then the
 // SymbolValue is checked to be an address of literal pointer, symbol pointer,
 // or an Objective-C meta data reference.  If so the output ReferenceType is
-// set to correspond to that as well as ReferenceName.
+// set to correspond to that as well as setting the ReferenceName.
 const char *SymbolizerSymbolLookUp(void *DisInfo, uint64_t ReferenceValue,
                                    uint64_t *ReferenceType,
                                    uint64_t ReferencePC,
                                    const char **ReferenceName) {
   struct DisassembleInfo *info = (struct DisassembleInfo *)DisInfo;
-  *ReferenceName = nullptr;
-  *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
-  unsigned int Arch = info->O->getArch();
-  if (Arch == Triple::x86) {
-    return nullptr;
-  } else if (Arch == Triple::x86_64) {
-    return nullptr;
-  } else if (Arch == Triple::arm) {
-    return nullptr;
-  } else if (Arch == Triple::aarch64) {
-    return nullptr;
-  } else {
+  // If no verbose symbolic information is wanted then just return nullptr.
+  if (info->verbose == false) {
+    *ReferenceName = nullptr;
+    *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
     return nullptr;
   }
+
+  const char *SymbolName = nullptr;
+  if (ReferenceValue != 0xffffffffffffffffULL &&
+      ReferenceValue != 0xfffffffffffffffeULL) {
+    StringRef name = info->AddrMap->lookup(ReferenceValue);
+    if (!name.empty())
+      SymbolName = name.data();
+  }
+
+  if (*ReferenceType == LLVMDisassembler_ReferenceType_In_Branch) {
+    *ReferenceName = GuessIndirectSymbol(ReferenceValue, info);
+    if (*ReferenceName != nullptr) {
+      method_reference(info, ReferenceType, ReferenceName);
+      if (*ReferenceType != LLVMDisassembler_ReferenceType_Out_Objc_Message)
+        *ReferenceType = LLVMDisassembler_ReferenceType_Out_SymbolStub;
+    } else
+#if HAVE_CXXABI_H
+    if (SymbolName != nullptr && strncmp(SymbolName, "__Z", 3) == 0) {
+      if (info->demangled_name != nullptr)
+        free(info->demangled_name);
+      int status;
+      info->demangled_name = abi::__cxa_demangle(SymbolName + 1, nullptr,
+                                                 nullptr, &status);
+      if (info->demangled_name != nullptr) {
+        *ReferenceName = info->demangled_name;
+        *ReferenceType = LLVMDisassembler_ReferenceType_DeMangled_Name;
+      } else
+        *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
+    } else
+#endif
+      *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
+  } else if (*ReferenceType == LLVMDisassembler_ReferenceType_In_PCrel_Load) {
+    *ReferenceName =
+        GuessLiteralPointer(ReferenceValue, ReferencePC, ReferenceType, info);
+    if (*ReferenceName)
+      method_reference(info, ReferenceType, ReferenceName);
+    else
+      *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
+  }
+#if HAVE_CXXABI_H
+  else if (SymbolName != nullptr && strncmp(SymbolName, "__Z", 3) == 0) {
+    if (info->demangled_name != nullptr)
+      free(info->demangled_name);
+    int status;
+    info->demangled_name = abi::__cxa_demangle(SymbolName + 1, nullptr, nullptr,
+                                               &status);
+    if (info->demangled_name != nullptr) {
+      *ReferenceName = info->demangled_name;
+      *ReferenceType = LLVMDisassembler_ReferenceType_DeMangled_Name;
+    }
+  }
+#endif
+  else {
+    *ReferenceName = nullptr;
+    *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
+  }
+
+  return SymbolName;
+}
+
+//
+// This is the memory object used by DisAsm->getInstruction() which has its
+// BasePC.  This then allows the 'address' parameter to getInstruction() to
+// be the actual PC of the instruction.  Then when a branch dispacement is
+// added to the PC of an instruction, the 'ReferenceValue' passed to the
+// SymbolizerSymbolLookUp() routine is the correct target addresses.  As in
+// the case of a fully linked Mach-O file where a section being disassembled
+// generally not linked at address zero.
+//
+class DisasmMemoryObject : public MemoryObject {
+  const uint8_t *Bytes;
+  uint64_t Size;
+  uint64_t BasePC;
+public:
+  DisasmMemoryObject(const uint8_t *bytes, uint64_t size, uint64_t basePC)
+      : Bytes(bytes), Size(size), BasePC(basePC) {}
+
+  uint64_t getBase() const override { return BasePC; }
+  uint64_t getExtent() const override { return Size; }
+
+  int readByte(uint64_t Addr, uint8_t *Byte) const override {
+    if (Addr - BasePC >= Size)
+      return -1;
+    *Byte = Bytes[Addr - BasePC];
+    return 0;
+  }
+};
+
+/// \brief Emits the comments that are stored in the CommentStream.
+/// Each comment in the CommentStream must end with a newline.
+static void emitComments(raw_svector_ostream &CommentStream,
+                         SmallString<128> &CommentsToEmit,
+                         formatted_raw_ostream &FormattedOS,
+                         const MCAsmInfo &MAI) {
+  // Flush the stream before taking its content.
+  CommentStream.flush();
+  StringRef Comments = CommentsToEmit.str();
+  // Get the default information for printing a comment.
+  const char *CommentBegin = MAI.getCommentString();
+  unsigned CommentColumn = MAI.getCommentColumn();
+  bool IsFirst = true;
+  while (!Comments.empty()) {
+    if (!IsFirst)
+      FormattedOS << '\n';
+    // Emit a line of comments.
+    FormattedOS.PadToColumn(CommentColumn);
+    size_t Position = Comments.find('\n');
+    FormattedOS << CommentBegin << ' ' << Comments.substr(0, Position);
+    // Move after the newline character.
+    Comments = Comments.substr(Position + 1);
+    IsFirst = false;
+  }
+  FormattedOS.flush();
+
+  // Tell the comment stream that the vector changed underneath it.
+  CommentsToEmit.clear();
+  CommentStream.resync();
 }
 
 static void DisassembleInputMachO2(StringRef Filename,
@@ -445,6 +1255,12 @@ static void DisassembleInputMachO2(StringRef Filename,
   int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
   std::unique_ptr<MCInstPrinter> IP(TheTarget->createMCInstPrinter(
       AsmPrinterVariant, *AsmInfo, *InstrInfo, *MRI, *STI));
+  // Set the display preference for hex vs. decimal immediates.
+  IP->setPrintImmHex(PrintImmHex);
+  // Comment stream and backing vector.
+  SmallString<128> CommentsToEmit;
+  raw_svector_ostream CommentStream(CommentsToEmit);
+  IP->setCommentStream(CommentStream);
 
   if (!InstrAnalysis || !AsmInfo || !STI || !DisAsm || !IP) {
     errs() << "error: couldn't initialize disassembler for target "
@@ -467,11 +1283,13 @@ static void DisassembleInputMachO2(StringRef Filename,
         ThumbTarget->createMCSubtargetInfo(ThumbTripleName, MCPU, FeaturesStr));
     ThumbCtx.reset(new MCContext(ThumbAsmInfo.get(), ThumbMRI.get(), nullptr));
     ThumbDisAsm.reset(ThumbTarget->createMCDisassembler(*ThumbSTI, *ThumbCtx));
-// TODO: add MCSymbolizer here for the ThumbTarget like above for TheTarget.
+    // TODO: add MCSymbolizer here for the ThumbTarget like above for TheTarget.
     int ThumbAsmPrinterVariant = ThumbAsmInfo->getAssemblerDialect();
     ThumbIP.reset(ThumbTarget->createMCInstPrinter(
         ThumbAsmPrinterVariant, *ThumbAsmInfo, *ThumbInstrInfo, *ThumbMRI,
         *ThumbSTI));
+    // Set the display preference for hex vs. decimal immediates.
+    ThumbIP->setPrintImmHex(PrintImmHex);
   }
 
   if (ThumbTarget && (!ThumbInstrAnalysis || !ThumbAsmInfo || !ThumbSTI ||
@@ -503,7 +1321,7 @@ static void DisassembleInputMachO2(StringRef Filename,
   // Build a data in code table that is sorted on by the address of each entry.
   uint64_t BaseAddress = 0;
   if (Header.filetype == MachO::MH_OBJECT)
-    Sections[0].getAddress(BaseAddress);
+    BaseAddress = Sections[0].getAddress();
   else
     BaseAddress = BaseSegmentAddress;
   DiceTable Dices;
@@ -546,8 +1364,7 @@ static void DisassembleInputMachO2(StringRef Filename,
 
   for (unsigned SectIdx = 0; SectIdx != Sections.size(); SectIdx++) {
 
-    bool SectIsText = false;
-    Sections[SectIdx].isText(SectIsText);
+    bool SectIsText = Sections[SectIdx].isText();
     if (SectIsText == false)
       continue;
 
@@ -564,15 +1381,17 @@ static void DisassembleInputMachO2(StringRef Filename,
 
     StringRef Bytes;
     Sections[SectIdx].getContents(Bytes);
-    StringRefMemoryObject memoryObject(Bytes);
+    uint64_t SectAddress = Sections[SectIdx].getAddress();
+    DisasmMemoryObject MemoryObject((const uint8_t *)Bytes.data(), Bytes.size(),
+                                    SectAddress);
     bool symbolTableWorked = false;
 
     // Parse relocations.
     std::vector<std::pair<uint64_t, SymbolRef>> Relocs;
     for (const RelocationRef &Reloc : Sections[SectIdx].relocations()) {
-      uint64_t RelocOffset, SectionAddress;
+      uint64_t RelocOffset;
       Reloc.getOffset(RelocOffset);
-      Sections[SectIdx].getAddress(SectionAddress);
+      uint64_t SectionAddress = Sections[SectIdx].getAddress();
       RelocOffset -= SectionAddress;
 
       symbol_iterator RelocSym = Reloc.getSymbol();
@@ -581,10 +1400,32 @@ static void DisassembleInputMachO2(StringRef Filename,
     }
     array_pod_sort(Relocs.begin(), Relocs.end());
 
+    // Create a map of symbol addresses to symbol names for use by
+    // the SymbolizerSymbolLookUp() routine.
+    SymbolAddressMap AddrMap;
+    for (const SymbolRef &Symbol : MachOOF->symbols()) {
+      SymbolRef::Type ST;
+      Symbol.getType(ST);
+      if (ST == SymbolRef::ST_Function || ST == SymbolRef::ST_Data ||
+          ST == SymbolRef::ST_Other) {
+        uint64_t Address;
+        Symbol.getAddress(Address);
+        StringRef SymName;
+        Symbol.getName(SymName);
+        AddrMap[Address] = SymName;
+      }
+    }
     // Set up the block of info used by the Symbolizer call backs.
     SymbolizerInfo.verbose = true;
     SymbolizerInfo.O = MachOOF;
     SymbolizerInfo.S = Sections[SectIdx];
+    SymbolizerInfo.AddrMap = &AddrMap;
+    SymbolizerInfo.Sections = &Sections;
+    SymbolizerInfo.class_name = nullptr;
+    SymbolizerInfo.selector_name = nullptr;
+    SymbolizerInfo.method = nullptr;
+    SymbolizerInfo.demangled_name = nullptr;
+    SymbolizerInfo.bindtable = nullptr;
 
     // Disassemble symbol by symbol.
     for (unsigned SymIdx = 0; SymIdx != Symbols.size(); SymIdx++) {
@@ -597,15 +1438,13 @@ static void DisassembleInputMachO2(StringRef Filename,
         continue;
 
       // Make sure the symbol is defined in this section.
-      bool containsSym = false;
-      Sections[SectIdx].containsSymbol(Symbols[SymIdx], containsSym);
+      bool containsSym = Sections[SectIdx].containsSymbol(Symbols[SymIdx]);
       if (!containsSym)
         continue;
 
       // Start at the address of the symbol relative to the section's address.
-      uint64_t SectionAddress = 0;
       uint64_t Start = 0;
-      Sections[SectIdx].getAddress(SectionAddress);
+      uint64_t SectionAddress = Sections[SectIdx].getAddress();
       Symbols[SymIdx].getAddress(Start);
       Start -= SectionAddress;
 
@@ -618,8 +1457,8 @@ static void DisassembleInputMachO2(StringRef Filename,
         SymbolRef::Type NextSymType;
         Symbols[NextSymIdx].getType(NextSymType);
         if (NextSymType == SymbolRef::ST_Function) {
-          Sections[SectIdx].containsSymbol(Symbols[NextSymIdx],
-                                           containsNextSym);
+          containsNextSym =
+              Sections[SectIdx].containsSymbol(Symbols[NextSymIdx]);
           Symbols[NextSymIdx].getAddress(NextSym);
           NextSym -= SectionAddress;
           break;
@@ -627,12 +1466,14 @@ static void DisassembleInputMachO2(StringRef Filename,
         ++NextSymIdx;
       }
 
-      uint64_t SectSize;
-      Sections[SectIdx].getSize(SectSize);
+      uint64_t SectSize = Sections[SectIdx].getSize();
       uint64_t End = containsNextSym ?  NextSym : SectSize;
       uint64_t Size;
 
       symbolTableWorked = true;
+      DisasmMemoryObject SectionMemoryObject((const uint8_t *)Bytes.data() +
+                                                 Start,
+                                             End - Start, SectAddress + Start);
 
       DataRefImpl Symb = Symbols[SymIdx].getRawDataRefImpl();
       bool isThumb =
@@ -643,14 +1484,22 @@ static void DisassembleInputMachO2(StringRef Filename,
       for (uint64_t Index = Start; Index < End; Index += Size) {
         MCInst Inst;
 
-        uint64_t SectAddress = 0;
-        Sections[SectIdx].getAddress(SectAddress);
-        outs() << format("%8" PRIx64 ":\t", SectAddress + Index);
+        uint64_t PC = SectAddress + Index;
+        if (FullLeadingAddr) {
+          if (MachOOF->is64Bit())
+            outs() << format("%016" PRIx64, PC);
+          else
+            outs() << format("%08" PRIx64, PC);
+        } else {
+          outs() << format("%8" PRIx64 ":", PC);
+        }
+        if (!NoShowRawInsn)
+          outs() << "\t";
 
         // Check the data in code table here to see if this is data not an
         // instruction to be disassembled.
         DiceTable Dice;
-        Dice.push_back(std::make_pair(SectAddress + Index, DiceRef()));
+        Dice.push_back(std::make_pair(PC, DiceRef()));
         dice_table_iterator DTI = std::search(Dices.begin(), Dices.end(),
                                               Dice.begin(), Dice.end(),
                                               compareDiceTableEntries);
@@ -664,24 +1513,33 @@ static void DisassembleInputMachO2(StringRef Filename,
           continue;
         }
 
+        SmallVector<char, 64> AnnotationsBytes;
+        raw_svector_ostream Annotations(AnnotationsBytes);
+
         bool gotInst;
         if (isThumb)
-          gotInst = ThumbDisAsm->getInstruction(Inst, Size, memoryObject, Index,
-                                     DebugOut, nulls());
+          gotInst = ThumbDisAsm->getInstruction(Inst, Size, SectionMemoryObject,
+                                                PC, DebugOut, Annotations);
         else
-          gotInst = DisAsm->getInstruction(Inst, Size, memoryObject, Index,
-                                     DebugOut, nulls());
+          gotInst = DisAsm->getInstruction(Inst, Size, SectionMemoryObject, PC,
+                                           DebugOut, Annotations);
         if (gotInst) {
-          DumpBytes(StringRef(Bytes.data() + Index, Size));
+          if (!NoShowRawInsn) {
+            DumpBytes(StringRef(Bytes.data() + Index, Size));
+          }
+          formatted_raw_ostream FormattedOS(outs());
+          Annotations.flush();
+          StringRef AnnotationsStr = Annotations.str();
           if (isThumb)
-            ThumbIP->printInst(&Inst, outs(), "");
+            ThumbIP->printInst(&Inst, FormattedOS, AnnotationsStr);
           else
-            IP->printInst(&Inst, outs(), "");
+            IP->printInst(&Inst, FormattedOS, AnnotationsStr);
+          emitComments(CommentStream, CommentsToEmit, FormattedOS, *AsmInfo);
 
           // Print debug info.
           if (diContext) {
             DILineInfo dli =
-              diContext->getLineInfoForAddress(SectAddress + Index);
+              diContext->getLineInfoForAddress(PC);
             // Print valid line info if it changed.
             if (dli != lastLine && dli.Line != 0)
               outs() << "\t## " << dli.FileName << ':' << dli.Line << ':'
@@ -690,35 +1548,64 @@ static void DisassembleInputMachO2(StringRef Filename,
           }
           outs() << "\n";
         } else {
-          errs() << "llvm-objdump: warning: invalid instruction encoding\n";
-          if (Size == 0)
-            Size = 1; // skip illegible bytes
+          unsigned int Arch = MachOOF->getArch();
+          if (Arch == Triple::x86_64 || Arch == Triple::x86){
+            outs() << format("\t.byte 0x%02x #bad opcode\n",
+                             *(Bytes.data() + Index) & 0xff);
+            Size = 1; // skip exactly one illegible byte and move on.
+          } else {
+            errs() << "llvm-objdump: warning: invalid instruction encoding\n";
+            if (Size == 0)
+              Size = 1; // skip illegible bytes
+          }
         }
       }
     }
     if (!symbolTableWorked) {
-      // Reading the symbol table didn't work, disassemble the whole section. 
-      uint64_t SectAddress;
-      Sections[SectIdx].getAddress(SectAddress);
-      uint64_t SectSize;
-      Sections[SectIdx].getSize(SectSize);
+      // Reading the symbol table didn't work, disassemble the whole section.
+      uint64_t SectAddress = Sections[SectIdx].getAddress();
+      uint64_t SectSize = Sections[SectIdx].getSize();
       uint64_t InstSize;
       for (uint64_t Index = 0; Index < SectSize; Index += InstSize) {
         MCInst Inst;
 
-        if (DisAsm->getInstruction(Inst, InstSize, memoryObject, Index,
-                                   DebugOut, nulls())) {
-          outs() << format("%8" PRIx64 ":\t", SectAddress + Index);
-          DumpBytes(StringRef(Bytes.data() + Index, InstSize));
+        uint64_t PC = SectAddress + Index;
+        if (DisAsm->getInstruction(Inst, InstSize, MemoryObject, PC, DebugOut,
+                                   nulls())) {
+          if (FullLeadingAddr) {
+            if (MachOOF->is64Bit())
+              outs() << format("%016" PRIx64, PC);
+            else
+              outs() << format("%08" PRIx64, PC);
+          } else {
+            outs() << format("%8" PRIx64 ":", PC);
+          }
+          if (!NoShowRawInsn) {
+            outs() << "\t";
+            DumpBytes(StringRef(Bytes.data() + Index, InstSize));
+          }
           IP->printInst(&Inst, outs(), "");
           outs() << "\n";
         } else {
-          errs() << "llvm-objdump: warning: invalid instruction encoding\n";
-          if (InstSize == 0)
-            InstSize = 1; // skip illegible bytes
+          unsigned int Arch = MachOOF->getArch();
+          if (Arch == Triple::x86_64 || Arch == Triple::x86){
+            outs() << format("\t.byte 0x%02x #bad opcode\n",
+                             *(Bytes.data() + Index) & 0xff);
+            InstSize = 1; // skip exactly one illegible byte and move on.
+          } else {
+            errs() << "llvm-objdump: warning: invalid instruction encoding\n";
+            if (InstSize == 0)
+              InstSize = 1; // skip illegible bytes
+          }
         }
       }
     }
+    if (SymbolizerInfo.method != nullptr)
+      free(SymbolizerInfo.method);
+    if (SymbolizerInfo.demangled_name != nullptr)
+      free(SymbolizerInfo.demangled_name);
+    if (SymbolizerInfo.bindtable != nullptr)
+      delete SymbolizerInfo.bindtable;
   }
 }
 
@@ -795,8 +1682,7 @@ static void findUnwindRelocNameAddend(const MachOObjectFile *Obj,
   auto RE = Obj->getRelocation(Reloc.getRawDataRefImpl());
   SectionRef RelocSection = Obj->getRelocationSection(RE);
 
-  uint64_t SectionAddr;
-  RelocSection.getAddress(SectionAddr);
+  uint64_t SectionAddr = RelocSection.getAddress();
 
   auto Sym = Symbols.upper_bound(Addr);
   if (Sym == Symbols.begin()) {
@@ -2212,7 +3098,12 @@ static void PrintLoadCommands(const MachOObjectFile *Obj, uint32_t ncmds,
     } else if (Command.C.cmd == MachO::LC_MAIN) {
       MachO::entry_point_command Ep = Obj->getEntryPointCommand(Command);
       PrintEntryPointCommand(Ep);
-    } else if (Command.C.cmd == MachO::LC_LOAD_DYLIB) {
+    } else if (Command.C.cmd == MachO::LC_LOAD_DYLIB ||
+               Command.C.cmd == MachO::LC_ID_DYLIB ||
+               Command.C.cmd == MachO::LC_LOAD_WEAK_DYLIB ||
+               Command.C.cmd == MachO::LC_REEXPORT_DYLIB ||
+               Command.C.cmd == MachO::LC_LAZY_LOAD_DYLIB ||
+               Command.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
       MachO::dylib_command Dl = Obj->getDylibIDLoadCommand(Command);
       PrintDylibCommand(Dl, Command.Ptr);
     } else if (Command.C.cmd == MachO::LC_CODE_SIGNATURE ||
@@ -2367,10 +3258,8 @@ SegInfo::SegInfo(const object::MachOObjectFile *Obj) {
     SectionInfo Info;
     if (error(Section.getName(Info.SectionName)))
       return;
-    if (error(Section.getAddress(Info.Address)))
-      return;
-    if (error(Section.getSize(Info.Size)))
-      return;
+    Info.Address = Section.getAddress();
+    Info.Size = Section.getSize();
     Info.SegmentName =
         Obj->getSectionFinalSegmentName(Section.getRawDataRefImpl());
     if (!Info.SegmentName.equals(CurSegName)) {
@@ -2450,7 +3339,7 @@ static StringRef ordinalName(const object::MachOObjectFile *Obj, int Ordinal) {
       std::error_code EC = Obj->getLibraryShortNameByIndex(Ordinal-1, 
                                                            DylibName);
       if (EC)
-        return "<<ordinal too big>>";
+        return "<<bad library ordinal>>";
       return DylibName;
     }
   }
@@ -2465,8 +3354,8 @@ void llvm::printMachOBindTable(const object::MachOObjectFile *Obj) {
   // Build table of sections so names can used in final output.
   SegInfo sectionTable(Obj);
 
-  outs() << "segment  section            address     type     "
-            "addend   dylib               symbol\n";
+  outs() << "segment  section            address    type       "
+            "addend dylib            symbol\n";
   for (const llvm::object::MachOBindEntry &Entry : Obj->bindTable()) {
     uint32_t SegIndex = Entry.segmentIndex();
     uint64_t OffsetInSeg = Entry.segmentOffset();
@@ -2476,18 +3365,17 @@ void llvm::printMachOBindTable(const object::MachOObjectFile *Obj) {
 
     // Table lines look like:
     //  __DATA  __got  0x00012010    pointer   0 libSystem ___stack_chk_guard
-    outs() << format("%-8s %-18s 0x%08" PRIX64 "  %-8s %-8" PRId64 " %-20s",
-                     SegmentName.str().c_str(),
-                     SectionName.str().c_str(),
-                     Address,
-                     Entry.typeName().str().c_str(),
-                     Entry.addend(),
-                     ordinalName(Obj, Entry.ordinal()).str().c_str())
-           << Entry.symbolName();
+    StringRef Attr;
     if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_WEAK_IMPORT)
-      outs() << " (weak_import)\n";
-    else
-      outs() << "\n";
+      Attr = " (weak_import)";
+    outs() << left_justify(SegmentName, 8)  << " "
+           << left_justify(SectionName, 18) << " "
+           << format_hex(Address, 10, true) << " "
+           << left_justify(Entry.typeName(), 8) << " "
+           << format_decimal(Entry.addend(), 8)  << " "  
+           << left_justify(ordinalName(Obj, Entry.ordinal()), 16) << " "
+           << Entry.symbolName() 
+           << Attr << "\n";
   }
 }
 
@@ -2499,8 +3387,8 @@ void llvm::printMachOLazyBindTable(const object::MachOObjectFile *Obj) {
   // Build table of sections so names can used in final output.
   SegInfo sectionTable(Obj);
 
-  outs() << "segment  section            address      "
-            "dylib               symbol\n";
+  outs() << "segment  section            address     "
+            "dylib            symbol\n";
   for (const llvm::object::MachOBindEntry &Entry : Obj->lazyBindTable()) {
     uint32_t SegIndex = Entry.segmentIndex();
     uint64_t OffsetInSeg = Entry.segmentOffset();
@@ -2510,11 +3398,10 @@ void llvm::printMachOLazyBindTable(const object::MachOObjectFile *Obj) {
 
     // Table lines look like:
     //  __DATA  __got  0x00012010 libSystem ___stack_chk_guard
-    outs() << format("%-8s %-18s 0x%08" PRIX64 "   %-20s",
-                     SegmentName.str().c_str(),
-                     SectionName.str().c_str(),
-                     Address,
-                     ordinalName(Obj, Entry.ordinal()).str().c_str())
+    outs() << left_justify(SegmentName, 8)  << " "
+           << left_justify(SectionName, 18) << " "
+           << format_hex(Address, 10, true) << " "
+           << left_justify(ordinalName(Obj, Entry.ordinal()), 16) << " "
            << Entry.symbolName() << "\n";
   }
 }
@@ -2528,12 +3415,12 @@ void llvm::printMachOWeakBindTable(const object::MachOObjectFile *Obj) {
   // Build table of sections so names can used in final output.
   SegInfo sectionTable(Obj);
 
-  outs() << "segment  section            address      "
-            "type     addend   symbol\n";
+  outs() << "segment  section            address     "
+            "type       addend   symbol\n";
   for (const llvm::object::MachOBindEntry &Entry : Obj->weakBindTable()) {
     // Strong symbols don't have a location to update.
     if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION) {
-      outs() << "                                          strong            "
+      outs() << "                                        strong              "
              << Entry.symbolName() << "\n";
       continue;
     }
@@ -2545,14 +3432,43 @@ void llvm::printMachOWeakBindTable(const object::MachOObjectFile *Obj) {
 
     // Table lines look like:
     // __DATA  __data  0x00001000  pointer    0   _foo
-    outs() << format("%-8s %-18s 0x%08" PRIX64 "   %-8s %-8" PRId64 " ",
-                     SegmentName.str().c_str(),
-                     SectionName.str().c_str(),
-                     Address,
-                     Entry.typeName().str().c_str(),
-                     Entry.addend())
+    outs() << left_justify(SegmentName, 8)  << " "
+           << left_justify(SectionName, 18) << " "
+           << format_hex(Address, 10, true) << " "
+           << left_justify(Entry.typeName(), 8) << " "
+           << format_decimal(Entry.addend(), 8)  << "   "  
            << Entry.symbolName() << "\n";
   }
 }
 
-
+// get_dyld_bind_info_symbolname() is used for disassembly and passed an
+// address, ReferenceValue, in the Mach-O file and looks in the dyld bind
+// information for that address. If the address is found its binding symbol
+// name is returned.  If not nullptr is returned.
+static const char *get_dyld_bind_info_symbolname(uint64_t ReferenceValue,
+                                                 struct DisassembleInfo *info) {
+  if (info->bindtable == nullptr) {
+    info->bindtable = new (BindTable);
+    SegInfo sectionTable(info->O);
+    for (const llvm::object::MachOBindEntry &Entry : info->O->bindTable()) {
+      uint32_t SegIndex = Entry.segmentIndex();
+      uint64_t OffsetInSeg = Entry.segmentOffset();
+      uint64_t Address = sectionTable.address(SegIndex, OffsetInSeg);
+      const char *SymbolName = nullptr;
+      StringRef name = Entry.symbolName();
+      if (!name.empty())
+        SymbolName = name.data();
+      info->bindtable->push_back(std::make_pair(Address, SymbolName));
+    }
+  }
+  for (bind_table_iterator BI = info->bindtable->begin(),
+                           BE = info->bindtable->end();
+       BI != BE; ++BI) {
+    uint64_t Address = BI->first;
+    if (ReferenceValue == Address) {
+      const char *SymbolName = BI->second;
+      return SymbolName;
+    }
+  }
+  return nullptr;
+}