<html><head><meta http-equiv="Content-Type" content="text/html charset=windows-1252"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div>Fixed in r216809.</div><br><div><div>On Aug 29, 2014, at 6:54 PM, Sean Silva <<a href="mailto:chisophugis@gmail.com">chisophugis@gmail.com</a>> wrote:</div><blockquote type="cite"><div dir="ltr"><span style="font-family:arial,sans-serif;font-size:13px">+  if (!CumulativeString.str().</span><span style="font-family:arial,sans-serif;font-size:13px">equals(CumulativeString.str())</span><span style="font-family:arial,sans-serif;font-size:13px">)</span><br style="font-family:arial,sans-serif;font-size:13px">
<span style="font-family:arial,sans-serif;font-size:13px">+    return false;</span><br><div><span style="font-family:arial,sans-serif;font-size:13px"><br></span></div><div><span style="font-family:arial,sans-serif;font-size:13px">Bug? Do we have test coverage for this?</span></div></div></blockquote><div>Yes bug.  (Hey, would be great if the compiler had enough insight into that expression to realize it is a self-comparison and issue a warning like it does for “if (x != x)” ).</div><div><br></div><div>In normal for() iterations that code is never exercised because you are just comparing against the end() iterator which has an empty stack and no cumulative string.  </div><div><br></div><br><blockquote type="cite"><div dir="ltr">
<div><span style="font-family:arial,sans-serif;font-size:13px"><br></span></div><div><span style="font-family:arial,sans-serif;font-size:13px"><br></span></div><div><span style="font-family:arial,sans-serif;font-size:13px">+      State.Address = readULEB128(State.Current);</span><br style="font-family:arial,sans-serif;font-size:13px">
<span style="font-family:arial,sans-serif;font-size:13px">+                       if (State.Flags &  MachO::EXPORT_SYMBOL_FLAGS_</span><span style="font-family:arial,sans-serif;font-size:13px">STUB_AND_RESOLVER)</span><br style="font-family:arial,sans-serif;font-size:13px">
<span style="font-family:arial,sans-serif;font-size:13px">+                               State.Other = readULEB128(State.Current);</span><br style="font-family:arial,sans-serif;font-size:13px"><span style="font-family:arial,sans-serif;font-size:13px">+    }</span><span style="font-family:arial,sans-serif;font-size:13px"><br>
</span></div><div><span style="font-family:arial,sans-serif;font-size:13px"><br></span></div><div><span style="font-family:arial,sans-serif;font-size:13px">How did the `if` get all the way over there.</span></div></div></blockquote><div>Some how a TAB slipped in.  Not sure how.</div><div><br></div><div>-Nick</div><div><br></div><div><br></div><blockquote type="cite"><div class="gmail_extra"><br><br><div class="gmail_quote">On Fri, Aug 29, 2014 at 5:20 PM, Nick Kledzik <span dir="ltr"><<a href="mailto:kledzik@apple.com" target="_blank">kledzik@apple.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: kledzik<br>
Date: Fri Aug 29 19:20:14 2014<br>
New Revision: 216808<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=216808&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=216808&view=rev</a><br>
Log:<br>
Object/llvm-objdump: allow dumping of mach-o exports trie<br>
<br>
MachOObjectFile in lib/Object currently has no support for parsing the rebase,<br>
binding, and export information from the LC_DYLD_INFO load command in final<br>
linked mach-o images. This patch adds support for parsing the exports trie data<br>
structure. It also adds an option to llvm-objdump to dump that export info.<br>
<br>
I did the exports parsing first because it is the hardest. The information is<br>
encoded in a trie structure, but the standard ObjectFile way to inspect content<br>
is through iterators. So I needed to make an iterator that would do a<br>
non-recursive walk through the trie and maintain the concatenation of edges<br>
needed for the current string prefix.<br>
<br>
I plan to add similar support in MachOObjectFile and llvm-objdump to<br>
parse/display the rebasing and binding info too.<br>
<br>
Added:<br>
    llvm/trunk/test/tools/llvm-objdump/Inputs/exports-trie.macho-x86_64   (with props)<br>
    llvm/trunk/test/tools/llvm-objdump/macho-exports-trie.test<br>
Modified:<br>
    llvm/trunk/include/llvm/Object/MachO.h<br>
    llvm/trunk/include/llvm/Support/MachO.h<br>
    llvm/trunk/lib/Object/MachOObjectFile.cpp<br>
    llvm/trunk/tools/llvm-objdump/MachODump.cpp<br>
    llvm/trunk/tools/llvm-objdump/llvm-objdump.cpp<br>
    llvm/trunk/tools/llvm-objdump/llvm-objdump.h<br>
<br>
Modified: llvm/trunk/include/llvm/Object/MachO.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/MachO.h?rev=216808&r1=216807&r2=216808&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/MachO.h?rev=216808&r1=216807&r2=216808&view=diff</a><br>

==============================================================================<br>
--- llvm/trunk/include/llvm/Object/MachO.h (original)<br>
+++ llvm/trunk/include/llvm/Object/MachO.h Fri Aug 29 19:20:14 2014<br>
@@ -49,6 +49,57 @@ public:<br>
 };<br>
 typedef content_iterator<DiceRef> dice_iterator;<br>
<br>
+/// ExportEntry encapsulates the current-state-of-the-walk used when doing a<br>
+/// non-recursive walk of the trie data structure.  This allows you to iterate<br>
+/// across all exported symbols using:<br>
+///      for (const llvm::object::ExportEntry &AnExport : Obj->exports()) {<br>
+///      }<br>
+class ExportEntry {<br>
+public:<br>
+  ExportEntry(ArrayRef<uint8_t> Trie);<br>
+<br>
+  StringRef name() const;<br>
+  uint64_t flags() const;<br>
+  uint64_t address() const;<br>
+  uint64_t other() const;<br>
+  StringRef otherName() const;<br>
+  uint32_t nodeOffset() const;<br>
+<br>
+  bool operator==(const ExportEntry &) const;<br>
+<br>
+  void moveNext();<br>
+<br>
+private:<br>
+  friend class MachOObjectFile;<br>
+  void moveToFirst();<br>
+  void moveToEnd();<br>
+  uint64_t readULEB128(const uint8_t *&p);<br>
+  void pushDownUntilBottom();<br>
+  void pushNode(uint64_t Offset);<br>
+<br>
+  // Represents a node in the mach-o exports trie.<br>
+  struct NodeState {<br>
+    NodeState(const uint8_t *Ptr);<br>
+    const uint8_t *Start;<br>
+    const uint8_t *Current;<br>
+    uint64_t Flags;<br>
+    uint64_t Address;<br>
+    uint64_t Other;<br>
+    const char *ImportName;<br>
+    unsigned ChildCount;<br>
+    unsigned NextChildIndex;<br>
+    unsigned ParentStringLength;<br>
+    bool IsExportNode;<br>
+  };<br>
+<br>
+  ArrayRef<uint8_t> Trie;<br>
+  SmallString<256> CumulativeString;<br>
+  SmallVector<NodeState, 16> Stack;<br>
+  bool Malformed;<br>
+  bool Done;<br>
+};<br>
+typedef content_iterator<ExportEntry> export_iterator;<br>
+<br>
 class MachOObjectFile : public ObjectFile {<br>
 public:<br>
   struct LoadCommandInfo {<br>
@@ -119,7 +170,7 @@ public:<br>
                                       bool &Result) const override;<br>
<br>
   // MachO specific.<br>
-  std::error_code getLibraryShortNameByIndex(unsigned Index, StringRef &Res);<br>
+  std::error_code getLibraryShortNameByIndex(unsigned Index, StringRef &) const;<br>
<br>
   // TODO: Would be useful to have an iterator based version<br>
   // of the load command interface too.<br>
@@ -144,6 +195,12 @@ public:<br>
<br>
   dice_iterator begin_dices() const;<br>
   dice_iterator end_dices() const;<br>
+<br>
+  /// For use iterating over all exported symbols.<br>
+  iterator_range<export_iterator> exports() const;<br>
+<br>
+  /// For use examining a trie not in a MachOObjectFile.<br>
+  static iterator_range<export_iterator> exports(ArrayRef<uint8_t> Trie);<br>
<br>
   // In a MachO file, sections have a segment name. This is used in the .o<br>
   // files. They have a single segment, but this field specifies which segment<br>
@@ -207,6 +264,11 @@ public:<br>
   MachO::symtab_command getSymtabLoadCommand() const;<br>
   MachO::dysymtab_command getDysymtabLoadCommand() const;<br>
   MachO::linkedit_data_command getDataInCodeLoadCommand() const;<br>
+  ArrayRef<uint8_t> getDyldInfoRebaseOpcodes() const;<br>
+  ArrayRef<uint8_t> getDyldInfoBindOpcodes() const;<br>
+  ArrayRef<uint8_t> getDyldInfoWeakBindOpcodes() const;<br>
+  ArrayRef<uint8_t> getDyldInfoLazyBindOpcodes() const;<br>
+  ArrayRef<uint8_t> getDyldInfoExportsTrie() const;<br>
<br>
   StringRef getStringTableData() const;<br>
   bool is64Bit() const;<br>
@@ -237,10 +299,11 @@ private:<br>
   typedef SmallVector<const char*, 1> LibraryList;<br>
   LibraryList Libraries;<br>
   typedef SmallVector<StringRef, 1> LibraryShortName;<br>
-  LibraryShortName LibrariesShortNames;<br>
+  mutable LibraryShortName LibrariesShortNames;<br>
   const char *SymtabLoadCmd;<br>
   const char *DysymtabLoadCmd;<br>
   const char *DataInCodeLoadCmd;<br>
+  const char *DyldInfoLoadCmd;<br>
 };<br>
<br>
 /// DiceRef<br>
<br>
Modified: llvm/trunk/include/llvm/Support/MachO.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/MachO.h?rev=216808&r1=216807&r2=216808&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/MachO.h?rev=216808&r1=216807&r2=216808&view=diff</a><br>

==============================================================================<br>
--- llvm/trunk/include/llvm/Support/MachO.h (original)<br>
+++ llvm/trunk/include/llvm/Support/MachO.h Fri Aug 29 19:20:14 2014<br>
@@ -322,13 +322,13 @@ namespace llvm {<br>
     };<br>
<br>
     enum {<br>
+      EXPORT_SYMBOL_FLAGS_KIND_MASK           = 0x03u,<br>
       EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION     = 0x04u,<br>
       EXPORT_SYMBOL_FLAGS_REEXPORT            = 0x08u,<br>
       EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER   = 0x10u<br>
     };<br>
<br>
     enum ExportSymbolKind {<br>
-      EXPORT_SYMBOL_FLAGS_KIND_MASK           = 0x03u,<br>
       EXPORT_SYMBOL_FLAGS_KIND_REGULAR        = 0x00u,<br>
       EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL   = 0x01u,<br>
       EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE       = 0x02u<br>
<br>
Modified: llvm/trunk/lib/Object/MachOObjectFile.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/MachOObjectFile.cpp?rev=216808&r1=216807&r2=216808&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/MachOObjectFile.cpp?rev=216808&r1=216807&r2=216808&view=diff</a><br>

==============================================================================<br>
--- llvm/trunk/lib/Object/MachOObjectFile.cpp (original)<br>
+++ llvm/trunk/lib/Object/MachOObjectFile.cpp Fri Aug 29 19:20:14 2014<br>
@@ -19,6 +19,8 @@<br>
 #include "llvm/Support/DataExtractor.h"<br>
 #include "llvm/Support/Format.h"<br>
 #include "llvm/Support/Host.h"<br>
+#include "llvm/Support/LEB128.h"<br>
+#include "llvm/Support/MachO.h"<br>
 #include "llvm/Support/MemoryBuffer.h"<br>
 #include "llvm/Support/raw_ostream.h"<br>
 #include <cctype><br>
@@ -226,7 +228,7 @@ MachOObjectFile::MachOObjectFile(MemoryB<br>
                                  bool Is64bits, std::error_code &EC)<br>
     : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),<br>
       SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr),<br>
-      DataInCodeLoadCmd(nullptr) {<br>
+      DataInCodeLoadCmd(nullptr), DyldInfoLoadCmd(nullptr) {<br>
   uint32_t LoadCommandCount = this->getHeader().ncmds;<br>
   MachO::LoadCommandType SegmentLoadType = is64Bit() ?<br>
     MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT;<br>
@@ -242,6 +244,10 @@ MachOObjectFile::MachOObjectFile(MemoryB<br>
     } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {<br>
       assert(!DataInCodeLoadCmd && "Multiple data in code tables");<br>
       DataInCodeLoadCmd = Load.Ptr;<br>
+    } else if (Load.C.cmd == MachO::LC_DYLD_INFO ||<br>
+               Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {<br>
+      assert(!DyldInfoLoadCmd && "Multiple dyldinfo load commands");<br>
+      DyldInfoLoadCmd = Load.Ptr;<br>
     } else if (Load.C.cmd == SegmentLoadType) {<br>
       uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load);<br>
       for (unsigned J = 0; J < NumSections; ++J) {<br>
@@ -1159,7 +1165,7 @@ guess_qtx:<br>
 // It is passed the index (0 - based) of the library as translated from<br>
 // GET_LIBRARY_ORDINAL (1 - based).<br>
 std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,<br>
-                                                            StringRef &Res) {<br>
+                                                         StringRef &Res) const {<br>
   if (Index >= Libraries.size())<br>
     return object_error::parse_failed;<br>
<br>
@@ -1505,6 +1511,183 @@ dice_iterator MachOObjectFile::end_dices<br>
   return dice_iterator(DiceRef(DRI, this));<br>
 }<br>
<br>
+ExportEntry::ExportEntry(ArrayRef<uint8_t> T)<br>
+  : Trie(T), Malformed(false), Done(false) { }<br>
+<br>
+void ExportEntry::moveToFirst() {<br>
+  pushNode(0);<br>
+  pushDownUntilBottom();<br>
+}<br>
+<br>
+void ExportEntry::moveToEnd() {<br>
+  Stack.clear();<br>
+  Done = true;<br>
+}<br>
+<br>
+bool ExportEntry::operator==(const ExportEntry &Other) const {<br>
+  // Common case, one at end, other iterating from begin.<br>
+  if (Done || Other.Done)<br>
+    return (Done == Other.Done);<br>
+  // Not equal if different stack sizes.<br>
+  if (Stack.size() != Other.Stack.size())<br>
+    return false;<br>
+  // Not equal if different cumulative strings.<br>
+  if (!CumulativeString.str().equals(CumulativeString.str()))<br>
+    return false;<br>
+  // Equal if all nodes in both stacks match.<br>
+  for (unsigned i=0; i < Stack.size(); ++i) {<br>
+    if (Stack[i].Start != Other.Stack[i].Start)<br>
+      return false;<br>
+  }<br>
+  return true;<br>
+}<br>
+<br>
+uint64_t ExportEntry::readULEB128(const uint8_t *&p) {<br>
+  unsigned count;<br>
+  uint64_t result = decodeULEB128(p, &count);<br>
+  p += count;<br>
+  if (p > Trie.end()) {<br>
+    p = Trie.end();<br>
+    Malformed = true;<br>
+  }<br>
+  return result;<br>
+}<br>
+<br>
+StringRef ExportEntry::name() const {<br>
+  return CumulativeString.str();<br>
+}<br>
+<br>
+uint64_t ExportEntry::flags() const {<br>
+  return Stack.back().Flags;<br>
+}<br>
+<br>
+uint64_t ExportEntry::address() const {<br>
+  return Stack.back().Address;<br>
+}<br>
+<br>
+uint64_t ExportEntry::other() const {<br>
+  return Stack.back().Other;<br>
+}<br>
+<br>
+StringRef ExportEntry::otherName() const {<br>
+  const char* ImportName = Stack.back().ImportName;<br>
+  if (ImportName)<br>
+    return StringRef(ImportName);<br>
+  return StringRef();<br>
+}<br>
+<br>
+uint32_t ExportEntry::nodeOffset() const {<br>
+  return Stack.back().Start - Trie.begin();<br>
+}<br>
+<br>
+ExportEntry::NodeState::NodeState(const uint8_t *Ptr)<br>
+  : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),<br>
+    ImportName(nullptr), ChildCount(0), NextChildIndex(0),<br>
+    ParentStringLength(0), IsExportNode(false) {<br>
+}<br>
+<br>
+void ExportEntry::pushNode(uint64_t offset) {<br>
+  const uint8_t *Ptr = Trie.begin() + offset;<br>
+  NodeState State(Ptr);<br>
+  uint64_t ExportInfoSize = readULEB128(State.Current);<br>
+  State.IsExportNode = (ExportInfoSize != 0);<br>
+  const uint8_t* Children = State.Current + ExportInfoSize;<br>
+  if (State.IsExportNode) {<br>
+    State.Flags = readULEB128(State.Current);<br>
+    if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {<br>
+      State.Address = 0;<br>
+      State.Other = readULEB128(State.Current); // dylib ordinal<br>
+      State.ImportName = reinterpret_cast<const char*>(State.Current);<br>
+    } else {<br>
+      State.Address = readULEB128(State.Current);<br>
+                       if (State.Flags &  MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)<br>
+                               State.Other = readULEB128(State.Current);<br>
+    }<br>
+  }<br>
+  State.ChildCount = *Children;<br>
+  State.Current = Children + 1;<br>
+  State.NextChildIndex = 0;<br>
+  State.ParentStringLength = CumulativeString.size();<br>
+  Stack.push_back(State);<br>
+}<br>
+<br>
+void ExportEntry::pushDownUntilBottom() {<br>
+  while (Stack.back().NextChildIndex < Stack.back().ChildCount) {<br>
+    NodeState &Top = Stack.back();<br>
+    CumulativeString.resize(Top.ParentStringLength);<br>
+    for (;*Top.Current != 0; Top.Current++) {<br>
+      char c = *Top.Current;<br>
+      CumulativeString.push_back(c);<br>
+    }<br>
+    Top.Current += 1;<br>
+    uint64_t childNodeIndex = readULEB128(Top.Current);<br>
+    Top.NextChildIndex += 1;<br>
+    pushNode(childNodeIndex);<br>
+  }<br>
+  if (!Stack.back().IsExportNode) {<br>
+    Malformed = true;<br>
+    moveToEnd();<br>
+  }<br>
+}<br>
+<br>
+// We have a trie data structure and need a way to walk it that is compatible<br>
+// with the C++ iterator model. The solution is a non-recursive depth first<br>
+// traversal where the iterator contains a stack of parent nodes along with a<br>
+// string that is the accumulation of all edge strings along the parent chain<br>
+// to this point.<br>
+//<br>
+// There is one â€œexport† node for each exported symbol.  But because some<br>
+// symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export<br>
+// node may have child nodes too.<br>
+//<br>
+// The algorithm for moveNext() is to keep moving down the leftmost unvisited<br>
+// child until hitting a node with no children (which is an export node or<br>
+// else the trie is malformed). On the way down, each node is pushed on the<br>
+// stack ivar.  If there is no more ways down, it pops up one and tries to go<br>
+// down a sibling path until a childless node is reached.<br>
+void ExportEntry::moveNext() {<br>
+  if (Stack.empty() || !Stack.back().IsExportNode) {<br>
+    Malformed = true;<br>
+    moveToEnd();<br>
+    return;<br>
+  }<br>
+<br>
+  Stack.pop_back();<br>
+  while (!Stack.empty()) {<br>
+    NodeState &Top = Stack.back();<br>
+    if (Top.NextChildIndex < Top.ChildCount) {<br>
+      pushDownUntilBottom();<br>
+      // Now at the next export node.<br>
+      return;<br>
+    } else {<br>
+      if (Top.IsExportNode) {<br>
+        // This node has no children but is itself an export node.<br>
+        CumulativeString.resize(Top.ParentStringLength);<br>
+        return;<br>
+      }<br>
+      Stack.pop_back();<br>
+    }<br>
+  }<br>
+  Done = true;<br>
+}<br>
+<br>
+iterator_range<export_iterator><br>
+MachOObjectFile::exports(ArrayRef<uint8_t> Trie) {<br>
+  ExportEntry Start(Trie);<br>
+  Start.moveToFirst();<br>
+<br>
+  ExportEntry Finish(Trie);<br>
+  Finish.moveToEnd();<br>
+<br>
+  return iterator_range<export_iterator>(export_iterator(Start),<br>
+                                         export_iterator(Finish));<br>
+}<br>
+<br>
+iterator_range<export_iterator> MachOObjectFile::exports() const {<br>
+  return exports(getDyldInfoExportsTrie());<br>
+}<br>
+<br>
+<br>
 StringRef<br>
 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const {<br>
   ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec);<br>
@@ -1748,6 +1931,62 @@ MachOObjectFile::getDataInCodeLoadComman<br>
   return Cmd;<br>
 }<br>
<br>
+ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const {<br>
+  if (!DyldInfoLoadCmd)<br>
+    return ArrayRef<uint8_t>();<br>
+<br>
+  MachO::dyld_info_command DyldInfo<br>
+                   = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);<br>
+  const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(<br>
+                                             getPtr(this, DyldInfo.rebase_off));<br>
+  return ArrayRef<uint8_t>(Ptr, DyldInfo.rebase_size);<br>
+}<br>
+<br>
+ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const {<br>
+  if (!DyldInfoLoadCmd)<br>
+    return ArrayRef<uint8_t>();<br>
+<br>
+  MachO::dyld_info_command DyldInfo<br>
+                   = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);<br>
+  const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(<br>
+                                               getPtr(this, DyldInfo.bind_off));<br>
+  return ArrayRef<uint8_t>(Ptr, DyldInfo.bind_size);<br>
+}<br>
+<br>
+ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const {<br>
+  if (!DyldInfoLoadCmd)<br>
+    return ArrayRef<uint8_t>();<br>
+<br>
+  MachO::dyld_info_command DyldInfo<br>
+                   = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);<br>
+  const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(<br>
+                                          getPtr(this, DyldInfo.weak_bind_off));<br>
+  return ArrayRef<uint8_t>(Ptr, DyldInfo.weak_bind_size);<br>
+}<br>
+<br>
+ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const {<br>
+  if (!DyldInfoLoadCmd)<br>
+    return ArrayRef<uint8_t>();<br>
+<br>
+  MachO::dyld_info_command DyldInfo<br>
+                   = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);<br>
+  const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(<br>
+                                          getPtr(this, DyldInfo.lazy_bind_off));<br>
+  return ArrayRef<uint8_t>(Ptr, DyldInfo.lazy_bind_size);<br>
+}<br>
+<br>
+ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const {<br>
+  if (!DyldInfoLoadCmd)<br>
+    return ArrayRef<uint8_t>();<br>
+<br>
+  MachO::dyld_info_command DyldInfo<br>
+                   = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd);<br>
+  const uint8_t *Ptr = reinterpret_cast<const uint8_t*>(<br>
+                                             getPtr(this, DyldInfo.export_off));<br>
+  return ArrayRef<uint8_t>(Ptr, DyldInfo.export_size);<br>
+}<br>
+<br>
+<br>
 StringRef MachOObjectFile::getStringTableData() const {<br>
   MachO::symtab_command S = getSymtabLoadCommand();<br>
   return getData().substr(S.stroff, S.strsize);<br>
<br>
Added: llvm/trunk/test/tools/llvm-objdump/Inputs/exports-trie.macho-x86_64<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-objdump/Inputs/exports-trie.macho-x86_64?rev=216808&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-objdump/Inputs/exports-trie.macho-x86_64?rev=216808&view=auto</a><br>

==============================================================================<br>
Binary file - no diff available.<br>
<br>
Propchange: llvm/trunk/test/tools/llvm-objdump/Inputs/exports-trie.macho-x86_64<br>
------------------------------------------------------------------------------<br>
    svn:executable = *<br>
<br>
Propchange: llvm/trunk/test/tools/llvm-objdump/Inputs/exports-trie.macho-x86_64<br>
------------------------------------------------------------------------------<br>
    svn:mime-type = application/octet-stream<br>
<br>
Added: llvm/trunk/test/tools/llvm-objdump/macho-exports-trie.test<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-objdump/macho-exports-trie.test?rev=216808&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-objdump/macho-exports-trie.test?rev=216808&view=auto</a><br>

==============================================================================<br>
--- llvm/trunk/test/tools/llvm-objdump/macho-exports-trie.test (added)<br>
+++ llvm/trunk/test/tools/llvm-objdump/macho-exports-trie.test Fri Aug 29 19:20:14 2014<br>
@@ -0,0 +1,11 @@<br>
+# RUN: llvm-objdump -macho -exports-trie -arch x86_64 \<br>
+# RUN:   %p/Inputs/exports-trie.macho-x86_64 2>/dev/null | FileCheck %s<br>
+<br>
+<br>
+# CHECK:[re-export] _malloc (from libSystem)<br>
+# CHECK:[re-export] _myfree (_free from libSystem)<br>
+# CHECK:0x00000F70  _myWeakweak_def]<br>
+# CHECK:0x00001018  _myTLVper-thread]<br>
+# CHECK:0x12345678  _myAbsabsolute]<br>
+# CHECK:0x00000F60  _foo<br>
+<br>
<br>
Modified: llvm/trunk/tools/llvm-objdump/MachODump.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-objdump/MachODump.cpp?rev=216808&r1=216807&r2=216808&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-objdump/MachODump.cpp?rev=216808&r1=216807&r2=216808&view=diff</a><br>

==============================================================================<br>
--- llvm/trunk/tools/llvm-objdump/MachODump.cpp (original)<br>
+++ llvm/trunk/tools/llvm-objdump/MachODump.cpp Fri Aug 29 19:20:14 2014<br>
@@ -1783,3 +1783,63 @@ void llvm::printMachOFileHeader(const ob<br>
   getAndPrintMachHeader(file, ncmds, filetype, cputype, true);<br>
   PrintLoadCommands(file, ncmds, filetype, cputype, true);<br>
 }<br>
+<br>
+//===----------------------------------------------------------------------===//<br>
+// export trie dumping<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+void llvm::printMachOExportsTrie(const object::MachOObjectFile *Obj) {<br>
+  for (const llvm::object::ExportEntry &entry : Obj->exports()) {<br>
+    uint64_t Flags = entry.flags();<br>
+    bool ReExport = (Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT);<br>
+    bool WeakDef = (Flags & MachO::EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION);<br>
+    bool ThreadLocal = ((Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK) ==<br>
+                        MachO::EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL);<br>
+    bool Abs = ((Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK) ==<br>
+                MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE);<br>
+    bool Resolver = (Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER);<br>
+    if (ReExport)<br>
+      outs() << "[re-export] ";<br>
+    else<br>
+      outs()<br>
+          << format("0x%08llX  ", entry.address()); // FIXME:add in base address<br>
+    outs() << <a href="http://entry.name/" target="_blank">entry.name</a>();<br>
+    if (WeakDef || ThreadLocal || Resolver || Abs) {<br>
+      bool needComma = false;<br>
+      printf(" [");<br>
+      if (WeakDef) {<br>
+        outs() << "weak_def";<br>
+        needComma = true;<br>
+      }<br>
+      if (ThreadLocal) {<br>
+        if (needComma)<br>
+          outs() << ", ";<br>
+        outs() << "per-thread";<br>
+        needComma = true;<br>
+      }<br>
+      if (Abs) {<br>
+        if (needComma)<br>
+          outs() << ", ";<br>
+        outs() << "absolute";<br>
+        needComma = true;<br>
+      }<br>
+      if (Resolver) {<br>
+        if (needComma)<br>
+          outs() << ", ";<br>
+        outs() << format("resolver=0x%08llX", entry.other());<br>
+        needComma = true;<br>
+      }<br>
+      outs() << "]";<br>
+    }<br>
+    if (ReExport) {<br>
+      StringRef DylibName = "unknown";<br>
+      int ordinal = entry.other() - 1;<br>
+      Obj->getLibraryShortNameByIndex(ordinal, DylibName);<br>
+      if (entry.otherName().empty())<br>
+        outs() << " (from " << DylibName << ")";<br>
+      else<br>
+        outs() << " (" << entry.otherName() << " from " << DylibName << ")";<br>
+    }<br>
+    outs() << "\n";<br>
+  }<br>
+}<br>
<br>
Modified: llvm/trunk/tools/llvm-objdump/llvm-objdump.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-objdump/llvm-objdump.cpp?rev=216808&r1=216807&r2=216808&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-objdump/llvm-objdump.cpp?rev=216808&r1=216807&r2=216808&view=diff</a><br>

==============================================================================<br>
--- llvm/trunk/tools/llvm-objdump/llvm-objdump.cpp (original)<br>
+++ llvm/trunk/tools/llvm-objdump/llvm-objdump.cpp Fri Aug 29 19:20:14 2014<br>
@@ -85,6 +85,9 @@ static cl::opt<bool><br>
 SymbolTable("t", cl::desc("Display the symbol table"));<br>
<br>
 static cl::opt<bool><br>
+ExportsTrie("exports-trie", cl::desc("Display mach-o exported symbols"));<br>
+<br>
+static cl::opt<bool><br>
 MachOOpt("macho", cl::desc("Use MachO specific object file parser"));<br>
 static cl::alias<br>
 MachOm("m", cl::desc("Alias for --macho"), cl::aliasopt(MachOOpt));<br>
@@ -829,6 +832,17 @@ static void PrintUnwindInfo(const Object<br>
   }<br>
 }<br>
<br>
+static void printExportsTrie(const ObjectFile *o) {<br>
+  outs() << "Exports trie:\n";<br>
+  if (const MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o))<br>
+    printMachOExportsTrie(MachO);<br>
+  else {<br>
+    errs() << "This operation is only currently supported "<br>
+              "for Mach-O executable files.\n";<br>
+    return;<br>
+  }<br>
+}<br>
+<br>
 static void printPrivateFileHeader(const ObjectFile *o) {<br>
   if (o->isELF()) {<br>
     printELFFileHeader(o);<br>
@@ -858,6 +872,8 @@ static void DumpObject(const ObjectFile<br>
     PrintUnwindInfo(o);<br>
   if (PrivateHeaders)<br>
     printPrivateFileHeader(o);<br>
+  if (ExportsTrie)<br>
+    printExportsTrie(o);<br>
 }<br>
<br>
 /// @brief Dump each object file in \a a;<br>
@@ -939,7 +955,8 @@ int main(int argc, char **argv) {<br>
       && !SectionContents<br>
       && !SymbolTable<br>
       && !UnwindInfo<br>
-      && !PrivateHeaders) {<br>
+      && !PrivateHeaders<br>
+      && !ExportsTrie) {<br>
     cl::PrintHelpMessage();<br>
     return 2;<br>
   }<br>
<br>
Modified: llvm/trunk/tools/llvm-objdump/llvm-objdump.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-objdump/llvm-objdump.h?rev=216808&r1=216807&r2=216808&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-objdump/llvm-objdump.h?rev=216808&r1=216807&r2=216808&view=diff</a><br>

==============================================================================<br>
--- llvm/trunk/tools/llvm-objdump/llvm-objdump.h (original)<br>
+++ llvm/trunk/tools/llvm-objdump/llvm-objdump.h Fri Aug 29 19:20:14 2014<br>
@@ -35,7 +35,7 @@ void DumpBytes(StringRef bytes);<br>
 void DisassembleInputMachO(StringRef Filename);<br>
 void printCOFFUnwindInfo(const object::COFFObjectFile* o);<br>
 void printMachOUnwindInfo(const object::MachOObjectFile* o);<br>
-<br>
+void printMachOExportsTrie(const object::MachOObjectFile* o);<br>
 void printELFFileHeader(const object::ObjectFile *o);<br>
 void printCOFFFileHeader(const object::ObjectFile *o);<br>
 void printMachOFileHeader(const object::ObjectFile *o);<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br></div>
</blockquote></div><br></body></html>