+ return section_rel_end(DRI);
+}
+
+dice_iterator MachOObjectFile::begin_dices() const {
+ DataRefImpl DRI;
+ if (!DataInCodeLoadCmd)
+ return dice_iterator(DiceRef(DRI, this));
+
+ MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
+ DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff));
+ return dice_iterator(DiceRef(DRI, this));
+}
+
+dice_iterator MachOObjectFile::end_dices() const {
+ DataRefImpl DRI;
+ if (!DataInCodeLoadCmd)
+ return dice_iterator(DiceRef(DRI, this));
+
+ MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
+ unsigned Offset = DicLC.dataoff + DicLC.datasize;
+ DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset));
+ return dice_iterator(DiceRef(DRI, this));
+}
+
+ExportEntry::ExportEntry(ArrayRef<uint8_t> T)
+ : Trie(T), Malformed(false), Done(false) { }
+
+void ExportEntry::moveToFirst() {
+ pushNode(0);
+ pushDownUntilBottom();
+}
+
+void ExportEntry::moveToEnd() {
+ Stack.clear();
+ Done = true;
+}
+
+bool ExportEntry::operator==(const ExportEntry &Other) const {
+ // Common case, one at end, other iterating from begin.
+ if (Done || Other.Done)
+ return (Done == Other.Done);
+ // Not equal if different stack sizes.
+ if (Stack.size() != Other.Stack.size())
+ return false;
+ // Not equal if different cumulative strings.
+ if (!CumulativeString.str().equals(Other.CumulativeString.str()))
+ return false;
+ // Equal if all nodes in both stacks match.
+ for (unsigned i=0; i < Stack.size(); ++i) {
+ if (Stack[i].Start != Other.Stack[i].Start)
+ return false;
+ }
+ return true;
+}
+
+uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) {
+ unsigned Count;
+ uint64_t Result = decodeULEB128(Ptr, &Count);
+ Ptr += Count;
+ if (Ptr > Trie.end()) {
+ Ptr = Trie.end();
+ Malformed = true;
+ }
+ return Result;
+}
+
+StringRef ExportEntry::name() const {
+ return CumulativeString.str();
+}
+
+uint64_t ExportEntry::flags() const {
+ return Stack.back().Flags;
+}
+
+uint64_t ExportEntry::address() const {
+ return Stack.back().Address;
+}
+
+uint64_t ExportEntry::other() const {
+ return Stack.back().Other;
+}
+
+StringRef ExportEntry::otherName() const {
+ const char* ImportName = Stack.back().ImportName;
+ if (ImportName)
+ return StringRef(ImportName);
+ return StringRef();
+}
+
+uint32_t ExportEntry::nodeOffset() const {
+ return Stack.back().Start - Trie.begin();
+}
+
+ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
+ : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0),
+ ImportName(nullptr), ChildCount(0), NextChildIndex(0),
+ ParentStringLength(0), IsExportNode(false) {
+}
+
+void ExportEntry::pushNode(uint64_t offset) {
+ const uint8_t *Ptr = Trie.begin() + offset;
+ NodeState State(Ptr);
+ uint64_t ExportInfoSize = readULEB128(State.Current);
+ State.IsExportNode = (ExportInfoSize != 0);
+ const uint8_t* Children = State.Current + ExportInfoSize;
+ if (State.IsExportNode) {
+ State.Flags = readULEB128(State.Current);
+ if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
+ State.Address = 0;
+ State.Other = readULEB128(State.Current); // dylib ordinal
+ State.ImportName = reinterpret_cast<const char*>(State.Current);
+ } else {
+ State.Address = readULEB128(State.Current);
+ if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
+ State.Other = readULEB128(State.Current);
+ }
+ }
+ State.ChildCount = *Children;
+ State.Current = Children + 1;
+ State.NextChildIndex = 0;
+ State.ParentStringLength = CumulativeString.size();
+ Stack.push_back(State);
+}
+
+void ExportEntry::pushDownUntilBottom() {
+ while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
+ NodeState &Top = Stack.back();
+ CumulativeString.resize(Top.ParentStringLength);
+ for (;*Top.Current != 0; Top.Current++) {
+ char C = *Top.Current;
+ CumulativeString.push_back(C);
+ }
+ Top.Current += 1;
+ uint64_t childNodeIndex = readULEB128(Top.Current);
+ Top.NextChildIndex += 1;
+ pushNode(childNodeIndex);
+ }
+ if (!Stack.back().IsExportNode) {
+ Malformed = true;
+ moveToEnd();
+ }
+}
+
+// We have a trie data structure and need a way to walk it that is compatible
+// with the C++ iterator model. The solution is a non-recursive depth first
+// traversal where the iterator contains a stack of parent nodes along with a
+// string that is the accumulation of all edge strings along the parent chain
+// to this point.
+//
+// There is one “export” node for each exported symbol. But because some
+// symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
+// node may have child nodes too.
+//
+// The algorithm for moveNext() is to keep moving down the leftmost unvisited
+// child until hitting a node with no children (which is an export node or
+// else the trie is malformed). On the way down, each node is pushed on the
+// stack ivar. If there is no more ways down, it pops up one and tries to go
+// down a sibling path until a childless node is reached.
+void ExportEntry::moveNext() {
+ if (Stack.empty() || !Stack.back().IsExportNode) {
+ Malformed = true;
+ moveToEnd();
+ return;
+ }
+
+ Stack.pop_back();
+ while (!Stack.empty()) {
+ NodeState &Top = Stack.back();
+ if (Top.NextChildIndex < Top.ChildCount) {
+ pushDownUntilBottom();
+ // Now at the next export node.
+ return;
+ } else {
+ if (Top.IsExportNode) {
+ // This node has no children but is itself an export node.
+ CumulativeString.resize(Top.ParentStringLength);
+ return;
+ }
+ Stack.pop_back();
+ }
+ }
+ Done = true;