[llvm] 47e4663 - [llvm-objdump] Add -dyld_info to llvm-otool

Daniel Bertalan via llvm-commits llvm-commits at lists.llvm.org
Sun Aug 28 00:35:41 PDT 2022


Author: Daniel Bertalan
Date: 2022-08-28T09:22:41+02:00
New Revision: 47e4663c4eacaedab63e407651f5b045446bb36d

URL: https://github.com/llvm/llvm-project/commit/47e4663c4eacaedab63e407651f5b045446bb36d
DIFF: https://github.com/llvm/llvm-project/commit/47e4663c4eacaedab63e407651f5b045446bb36d.diff

LOG: [llvm-objdump] Add -dyld_info to llvm-otool

This option outputs the location, encoded value and target of chained
fixups, using the same format as `otool -dyld_info`.

This initial implementation only supports the DYLD_CHAINED_PTR_64 and
DYLD_CHAINED_PTR_64_OFFSET pointer encodings, which are used in x86_64
and arm64 userspace binaries.

When Apple's effort to upstream their chained fixups code continues,
we'll replace this code with the then-upstreamed code. But we need
something in the meantime for testing ld64.lld's chained fixups code.

Differential Revision: https://reviews.llvm.org/D132036

Added: 
    

Modified: 
    llvm/include/llvm/BinaryFormat/MachO.h
    llvm/include/llvm/Object/MachO.h
    llvm/lib/Object/MachOObjectFile.cpp
    llvm/test/tools/llvm-objdump/MachO/dyld-info.test
    llvm/tools/llvm-objdump/MachODump.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/BinaryFormat/MachO.h b/llvm/include/llvm/BinaryFormat/MachO.h
index a9fc7954d52ce..81b315a59ea9e 100644
--- a/llvm/include/llvm/BinaryFormat/MachO.h
+++ b/llvm/include/llvm/BinaryFormat/MachO.h
@@ -1103,6 +1103,27 @@ struct dyld_chained_import_addend64 {
   uint64_t addend;
 };
 
+// The `bind` field (most significant bit) of the encoded fixup determines
+// whether it is dyld_chained_ptr_64_bind or dyld_chained_ptr_64_rebase.
+
+// DYLD_CHAINED_PTR_64/DYLD_CHAINED_PTR_64_OFFSET
+struct dyld_chained_ptr_64_bind {
+  uint64_t ordinal : 24;
+  uint64_t addend : 8;
+  uint64_t reserved : 19;
+  uint64_t next : 12;
+  uint64_t bind : 1; // set to 1
+};
+
+// DYLD_CHAINED_PTR_64/DYLD_CHAINED_PTR_64_OFFSET
+struct dyld_chained_ptr_64_rebase {
+  uint64_t target : 36;
+  uint64_t high8 : 8;
+  uint64_t reserved : 7;
+  uint64_t next : 12;
+  uint64_t bind : 1; // set to 0
+};
+
 // Byte order swapping functions for MachO structs
 
 inline void swapStruct(fat_header &mh) {

diff  --git a/llvm/include/llvm/Object/MachO.h b/llvm/include/llvm/Object/MachO.h
index ee928c1175a99..caeee6a13b341 100644
--- a/llvm/include/llvm/Object/MachO.h
+++ b/llvm/include/llvm/Object/MachO.h
@@ -296,6 +296,19 @@ struct ChainedFixupTarget {
   bool WeakImport;
 };
 
+struct ChainedFixupsSegment {
+  ChainedFixupsSegment(uint8_t SegIdx, uint32_t Offset,
+                       const MachO::dyld_chained_starts_in_segment &Header,
+                       std::vector<uint16_t> &&PageStarts)
+      : SegIdx(SegIdx), Offset(Offset), Header(Header),
+        PageStarts(PageStarts){};
+
+  uint32_t SegIdx;
+  uint32_t Offset; // dyld_chained_starts_in_image::seg_info_offset[SegIdx]
+  MachO::dyld_chained_starts_in_segment Header;
+  std::vector<uint16_t> PageStarts; // page_start[] entries, host endianness
+};
+
 /// MachOAbstractFixupEntry is an abstract class representing a fixup in a
 /// MH_DYLDLINK file. Fixups generally represent rebases and binds. Binds also
 /// subdivide into additional subtypes (weak, lazy, reexport).
@@ -364,19 +377,29 @@ class MachOAbstractFixupEntry {
 
 class MachOChainedFixupEntry : public MachOAbstractFixupEntry {
 public:
-  enum class FixupKind { All, Bind, WeakBind, Rebase };
+  enum class FixupKind { Bind, Rebase };
 
   MachOChainedFixupEntry(Error *Err, const MachOObjectFile *O, bool Parse);
 
   bool operator==(const MachOChainedFixupEntry &) const;
 
+  bool isBind() const { return Kind == FixupKind::Bind; }
+  bool isRebase() const { return Kind == FixupKind::Rebase; }
+
   void moveNext();
   void moveToFirst();
   void moveToEnd();
 
 private:
+  void findNextPageWithFixups();
+
   std::vector<ChainedFixupTarget> FixupTargets;
-  uint32_t FixupIndex = 0;
+  std::vector<ChainedFixupsSegment> Segments;
+  ArrayRef<uint8_t> SegmentData;
+  FixupKind Kind;
+  uint32_t InfoSegIndex = 0; // Index into Segments
+  uint32_t PageIndex = 0;    // Index into Segments[InfoSegIdx].PageStarts
+  uint32_t PageOffset = 0;   // Page offset of the current fixup
 };
 using fixup_iterator = content_iterator<MachOChainedFixupEntry>;
 
@@ -436,6 +459,7 @@ class MachOObjectFile : public ObjectFile {
 
   /// Return the raw contents of an entire segment.
   ArrayRef<uint8_t> getSegmentContents(StringRef SegmentName) const;
+  ArrayRef<uint8_t> getSegmentContents(size_t SegmentIndex) const;
 
   /// When dsymutil generates the companion file, it strips all unnecessary
   /// sections (e.g. everything in the _TEXT segment) by omitting their body
@@ -697,18 +721,6 @@ class MachOObjectFile : public ObjectFile {
   // upstreams their implementation. Please do not rely on this.
   Expected<Optional<MachO::linkedit_data_command>>
   getChainedFixupsLoadCommand() const;
-  struct ChainedFixupsSegment {
-    ChainedFixupsSegment(uint8_t SegIdx, uint32_t Offset,
-                         const MachO::dyld_chained_starts_in_segment &Header,
-                         std::vector<uint16_t> &&PageStarts)
-        : SegIdx(SegIdx), Offset(Offset), Header(Header),
-          PageStarts(PageStarts){};
-
-    uint32_t SegIdx;
-    uint32_t Offset; // dyld_chained_starts_in_image::seg_info_offset[SegIdx]
-    MachO::dyld_chained_starts_in_segment Header;
-    std::vector<uint16_t> PageStarts; // page_start[] entries, host endianness
-  };
   // Returns the number of sections listed in dyld_chained_starts_in_image, and
   // a ChainedFixupsSegment for each segment that has fixups.
   Expected<std::pair<size_t, std::vector<ChainedFixupsSegment>>>

diff  --git a/llvm/lib/Object/MachOObjectFile.cpp b/llvm/lib/Object/MachOObjectFile.cpp
index 0c202b2f189a3..0b06ec3b4d4fe 100644
--- a/llvm/lib/Object/MachOObjectFile.cpp
+++ b/llvm/lib/Object/MachOObjectFile.cpp
@@ -2073,6 +2073,19 @@ ArrayRef<uint8_t> getSegmentContents(const MachOObjectFile &Obj,
         Segment.fileoff, Segment.fileoff + Segment.filesize));
   return {};
 }
+
+template <typename LoadCommandType>
+ArrayRef<uint8_t> getSegmentContents(const MachOObjectFile &Obj,
+                                     MachOObjectFile::LoadCommandInfo LoadCmd) {
+  auto SegmentOrErr = getStructOrErr<LoadCommandType>(Obj, LoadCmd.Ptr);
+  if (!SegmentOrErr) {
+    consumeError(SegmentOrErr.takeError());
+    return {};
+  }
+  auto &Segment = SegmentOrErr.get();
+  return arrayRefFromStringRef(
+      Obj.getData().slice(Segment.fileoff, Segment.fileoff + Segment.filesize));
+}
 } // namespace
 
 ArrayRef<uint8_t>
@@ -2097,6 +2110,28 @@ MachOObjectFile::getSegmentContents(StringRef SegmentName) const {
   return {};
 }
 
+ArrayRef<uint8_t>
+MachOObjectFile::getSegmentContents(size_t SegmentIndex) const {
+  size_t Idx = 0;
+  for (auto LoadCmd : load_commands()) {
+    switch (LoadCmd.C.cmd) {
+    case MachO::LC_SEGMENT:
+      if (Idx == SegmentIndex)
+        return ::getSegmentContents<MachO::segment_command>(*this, LoadCmd);
+      ++Idx;
+      break;
+    case MachO::LC_SEGMENT_64:
+      if (Idx == SegmentIndex)
+        return ::getSegmentContents<MachO::segment_command_64>(*this, LoadCmd);
+      ++Idx;
+      break;
+    default:
+      continue;
+    }
+  }
+  return {};
+}
+
 unsigned MachOObjectFile::getSectionID(SectionRef Sec) const {
   return Sec.getRawDataRefImpl().d.a;
 }
@@ -3257,6 +3292,8 @@ void MachOAbstractFixupEntry::moveToFirst() {
 
 void MachOAbstractFixupEntry::moveToEnd() { Done = true; }
 
+void MachOAbstractFixupEntry::moveNext() {}
+
 MachOChainedFixupEntry::MachOChainedFixupEntry(Error *E,
                                                const MachOObjectFile *O,
                                                bool Parse)
@@ -3264,17 +3301,54 @@ MachOChainedFixupEntry::MachOChainedFixupEntry(Error *E,
   ErrorAsOutParameter e(E);
   if (!Parse)
     return;
-  if (auto FixupTargetsOrErr = O->getDyldChainedFixupTargets())
+
+  if (auto FixupTargetsOrErr = O->getDyldChainedFixupTargets()) {
     FixupTargets = *FixupTargetsOrErr;
-  else {
+  } else {
     *E = FixupTargetsOrErr.takeError();
     return;
   }
+
+  if (auto SegmentsOrErr = O->getChainedFixupsSegments()) {
+    Segments = std::move(SegmentsOrErr->second);
+  } else {
+    *E = SegmentsOrErr.takeError();
+    return;
+  }
+}
+
+void MachOChainedFixupEntry::findNextPageWithFixups() {
+  auto FindInSegment = [this]() {
+    const ChainedFixupsSegment &SegInfo = Segments[InfoSegIndex];
+    while (PageIndex < SegInfo.PageStarts.size() &&
+           SegInfo.PageStarts[PageIndex] == MachO::DYLD_CHAINED_PTR_START_NONE)
+      ++PageIndex;
+    return PageIndex < SegInfo.PageStarts.size();
+  };
+
+  while (InfoSegIndex < Segments.size()) {
+    if (FindInSegment()) {
+      PageOffset = Segments[InfoSegIndex].PageStarts[PageIndex];
+      SegmentData = O->getSegmentContents(Segments[InfoSegIndex].SegIdx);
+      return;
+    }
+
+    InfoSegIndex++;
+    PageIndex = 0;
+  }
 }
 
 void MachOChainedFixupEntry::moveToFirst() {
   MachOAbstractFixupEntry::moveToFirst();
-  FixupIndex = 0;
+  if (Segments.empty()) {
+    Done = true;
+    return;
+  }
+
+  InfoSegIndex = 0;
+  PageIndex = 0;
+
+  findNextPageWithFixups();
   moveNext();
 }
 
@@ -3282,15 +3356,104 @@ void MachOChainedFixupEntry::moveToEnd() {
   MachOAbstractFixupEntry::moveToEnd();
 }
 
-void MachOChainedFixupEntry::moveNext() { Done = true; }
+void MachOChainedFixupEntry::moveNext() {
+  ErrorAsOutParameter ErrAsOutParam(E);
+
+  if (InfoSegIndex == Segments.size()) {
+    Done = true;
+    return;
+  }
+
+  const ChainedFixupsSegment &SegInfo = Segments[InfoSegIndex];
+  SegmentIndex = SegInfo.SegIdx;
+  SegmentOffset = SegInfo.Header.page_size * PageIndex + PageOffset;
+
+  // FIXME: Handle other pointer formats.
+  uint16_t PointerFormat = SegInfo.Header.pointer_format;
+  if (PointerFormat != MachO::DYLD_CHAINED_PTR_64 &&
+      PointerFormat != MachO::DYLD_CHAINED_PTR_64_OFFSET) {
+    *E = createError("segment " + Twine(SegmentIndex) +
+                     " has unsupported chained fixup pointer_format " +
+                     Twine(PointerFormat));
+    moveToEnd();
+    return;
+  }
+
+  Ordinal = 0;
+  Flags = 0;
+  Addend = 0;
+  PointerValue = 0;
+  SymbolName = {};
+
+  if (SegmentOffset + sizeof(RawValue) > SegmentData.size()) {
+    *E = malformedError("fixup in segment " + Twine(SegmentIndex) +
+                        " at offset " + Twine(SegmentOffset) +
+                        " extends past segment's end");
+    moveToEnd();
+    return;
+  }
+
+  static_assert(sizeof(RawValue) == sizeof(MachO::dyld_chained_import_addend));
+  memcpy(&RawValue, SegmentData.data() + SegmentOffset, sizeof(RawValue));
+  if (O->isLittleEndian() != sys::IsLittleEndianHost)
+    sys::swapByteOrder(RawValue);
+
+  // The bit extraction below assumes little-endian fixup entries.
+  assert(O->isLittleEndian() && "big-endian object should have been rejected "
+                                "by getDyldChainedFixupTargets()");
+  auto Field = [this](uint8_t Right, uint8_t Count) {
+    return (RawValue >> Right) & ((1ULL << Count) - 1);
+  };
+
+  // The `bind` field (most significant bit) of the encoded fixup determines
+  // whether it is dyld_chained_ptr_64_bind or dyld_chained_ptr_64_rebase.
+  bool IsBind = Field(63, 1);
+  Kind = IsBind ? FixupKind::Bind : FixupKind::Rebase;
+  uint32_t Next = Field(51, 12);
+  if (IsBind) {
+    uint32_t ImportOrdinal = Field(0, 24);
+    uint8_t InlineAddend = Field(24, 8);
+
+    if (ImportOrdinal >= FixupTargets.size()) {
+      *E = malformedError("fixup in segment " + Twine(SegmentIndex) +
+                          " at offset " + Twine(SegmentOffset) +
+                          "  has out-of range import ordinal " +
+                          Twine(ImportOrdinal));
+      moveToEnd();
+      return;
+    }
+
+    ChainedFixupTarget &Target = FixupTargets[ImportOrdinal];
+    Ordinal = Target.libOrdinal();
+    Addend = InlineAddend ? InlineAddend : Target.addend();
+    Flags = Target.weakImport() ? MachO::BIND_SYMBOL_FLAGS_WEAK_IMPORT : 0;
+    SymbolName = Target.symbolName();
+  } else {
+    uint64_t Target = Field(0, 36);
+    uint64_t High8 = Field(36, 8);
+
+    PointerValue = Target | (High8 << 56);
+    if (PointerFormat == MachO::DYLD_CHAINED_PTR_64_OFFSET)
+      PointerValue += textAddress();
+  }
+
+  // The stride is 4 bytes for DYLD_CHAINED_PTR_64(_OFFSET).
+  if (Next != 0) {
+    PageOffset += 4 * Next;
+  } else {
+    ++PageIndex;
+    findNextPageWithFixups();
+  }
+}
 
 bool MachOChainedFixupEntry::operator==(
     const MachOChainedFixupEntry &Other) const {
-  if (Done == Other.Done)
-    return true;
-  if ((FixupIndex == Other.FixupIndex))
+  if (Done && Other.Done)
     return true;
-  return false;
+  if (Done != Other.Done)
+    return false;
+  return InfoSegIndex == Other.InfoSegIndex && PageIndex == Other.PageIndex &&
+         PageOffset == Other.PageOffset;
 }
 
 MachORebaseEntry::MachORebaseEntry(Error *E, const MachOObjectFile *O,
@@ -4302,6 +4465,9 @@ iterator_range<bind_iterator> MachOObjectFile::weakBindTable(Error &Err) {
 }
 
 iterator_range<fixup_iterator> MachOObjectFile::fixupTable(Error &Err) {
+  if (BindRebaseSectionTable == nullptr)
+    BindRebaseSectionTable = std::make_unique<BindRebaseSegInfo>(this);
+
   MachOChainedFixupEntry Start(&Err, this, true);
   Start.moveToFirst();
 
@@ -4836,13 +5002,13 @@ MachOObjectFile::getChainedFixupsHeader() const {
   return CFHeader;
 }
 
-Expected<std::pair<size_t, std::vector<MachOObjectFile::ChainedFixupsSegment>>>
+Expected<std::pair<size_t, std::vector<ChainedFixupsSegment>>>
 MachOObjectFile::getChainedFixupsSegments() const {
   auto CFOrErr = getChainedFixupsLoadCommand();
   if (!CFOrErr)
     return CFOrErr.takeError();
 
-  std::vector<MachOObjectFile::ChainedFixupsSegment> Segments;
+  std::vector<ChainedFixupsSegment> Segments;
   if (!CFOrErr->has_value())
     return std::make_pair(0, Segments);
 

diff  --git a/llvm/test/tools/llvm-objdump/MachO/dyld-info.test b/llvm/test/tools/llvm-objdump/MachO/dyld-info.test
index 85e94688ae87f..20a08b9f2c465 100644
--- a/llvm/test/tools/llvm-objdump/MachO/dyld-info.test
+++ b/llvm/test/tools/llvm-objdump/MachO/dyld-info.test
@@ -1,9 +1,22 @@
-RUN: llvm-objdump --macho --dyld-info %p/Inputs/bind.macho-x86_64 \
-RUN:   | FileCheck %s --match-full-lines --strict-whitespace \
-RUN:     --implicit-check-not={{.}}
-RUN: llvm-otool -dyld_info %p/Inputs/bind.macho-x86_64 \
-RUN:   | FileCheck %s --match-full-lines --strict-whitespace \
-RUN:     --implicit-check-not={{.}}
+RUN: llvm-objdump --macho --dyld-info %p/Inputs/chained-fixups.macho-x86_64 | \
+RUN:     FileCheck -DNAME=%p/Inputs/chained-fixups.macho-x86_64 %s
+RUN: llvm-otool -dyld_info %p/Inputs/chained-fixups.macho-x86_64 | \
+RUN:     FileCheck -DNAME=%p/Inputs/chained-fixups.macho-x86_64 %s
 
-CHECK:{{.*}}bind.macho-x86_64:
-CHECK:dyld information:
+
+## See chained-fixups.test for how the test input was generated.
+CHECK:      [[NAME]]:
+CHECK-NEXT: dyld information:
+CHECK-NEXT: segment      section address       pointer      type   addend dylib          symbol/vm address
+CHECK-NEXT: __DATA_CONST __const 0x3E0   0x8010000000000001 bind   0x0    libdylib       _weakImport (weak import)
+CHECK-NEXT: __DATA_CONST __const 0x3E8   0x8000000000000000 bind   0x0    flat-namespace _dynamicLookup
+CHECK-NEXT: __DATA       __data  0x3F0   0x00200000000003F0 rebase                       0x3F0
+CHECK-NEXT: __DATA       __data  0x400   0x8000000000000004 bind   0x0     weak          _weak
+CHECK-NEXT: __DATA       __data  0x1410  0x8000000000000003 bind   0x0     weak          _weakLocal
+CHECK-NEXT: __DATA       __data  0x3410  0x8010000000000002 bind   0x0     libdylib      _dylib
+CHECK-NEXT: __DATA       __data  0x3418  0x800000002A000002 bind   0x2A    libdylib      _dylib
+
+## TODO: Print opcode-based fixups/binds as well
+## For now, test that execution doesn't fail if the input uses those.
+RUN: llvm-objdump --macho --dyld-info %p/Inputs/bind.macho-x86_64
+RUN: llvm-objdump --macho --dyld-info %p/Inputs/bind.macho-x86_64

diff  --git a/llvm/tools/llvm-objdump/MachODump.cpp b/llvm/tools/llvm-objdump/MachODump.cpp
index 31bb52a795c44..c0820380fff8f 100644
--- a/llvm/tools/llvm-objdump/MachODump.cpp
+++ b/llvm/tools/llvm-objdump/MachODump.cpp
@@ -1188,15 +1188,6 @@ static void PrintLinkOptHints(MachOObjectFile *O) {
   }
 }
 
-static void printMachOChainedFixups(object::MachOObjectFile *Obj) {
-  Error Err = Error::success();
-  for (const object::MachOChainedFixupEntry &Entry : Obj->fixupTable(Err)) {
-    (void)Entry;
-  }
-  if (Err)
-    reportError(std::move(Err), Obj->getFileName());
-}
-
 static SmallVector<std::string> GetSegmentNames(object::MachOObjectFile *O) {
   SmallVector<std::string> Ret;
   for (const MachOObjectFile::LoadCommandInfo &Command : O->load_commands()) {
@@ -1255,9 +1246,8 @@ static constexpr std::array<StringRef, 13> PointerFormats{
     "DYLD_CHAINED_PTR_ARM64E_USERLAND24",
 };
 
-static void
-PrintChainedFixupsSegment(const MachOObjectFile::ChainedFixupsSegment &Segment,
-                          StringRef SegName) {
+static void PrintChainedFixupsSegment(const ChainedFixupsSegment &Segment,
+                                      StringRef SegName) {
   outs() << "chained starts in segment " << Segment.SegIdx << " (" << SegName
          << ")\n";
   outs() << "  size = " << Segment.Header.size << '\n';
@@ -1333,7 +1323,7 @@ static void PrintChainedFixups(MachOObjectFile *O) {
            << SegNames[I] << ")\n";
   }
 
-  for (const MachOObjectFile::ChainedFixupsSegment &S : Segments)
+  for (const ChainedFixupsSegment &S : Segments)
     PrintChainedFixupsSegment(S, SegNames[S.SegIdx]);
 
   auto FixupTargets =
@@ -1345,8 +1335,62 @@ static void PrintChainedFixups(MachOObjectFile *O) {
 }
 
 static void PrintDyldInfo(MachOObjectFile *O) {
-  outs() << "dyld information:" << '\n';
-  printMachOChainedFixups(O);
+  Error Err = Error::success();
+
+  size_t SegmentWidth = strlen("segment");
+  size_t SectionWidth = strlen("section");
+  size_t AddressWidth = strlen("address");
+  size_t AddendWidth = strlen("addend");
+  size_t DylibWidth = strlen("dylib");
+  const size_t PointerWidth = 2 + O->getBytesInAddress() * 2;
+
+  auto HexLength = [](uint64_t Num) {
+    return Num ? (size_t)divideCeil(Log2_64(Num), 4) : 1;
+  };
+  for (const object::MachOChainedFixupEntry &Entry : O->fixupTable(Err)) {
+    SegmentWidth = std::max(SegmentWidth, Entry.segmentName().size());
+    SectionWidth = std::max(SectionWidth, Entry.sectionName().size());
+    AddressWidth = std::max(AddressWidth, HexLength(Entry.address()) + 2);
+    if (Entry.isBind()) {
+      AddendWidth = std::max(AddendWidth, HexLength(Entry.addend()) + 2);
+      DylibWidth = std::max(DylibWidth, Entry.symbolName().size());
+    }
+  }
+  // Errors will be handled when printing the table.
+  if (Err)
+    consumeError(std::move(Err));
+
+  outs() << "dyld information:\n";
+  outs() << left_justify("segment", SegmentWidth) << ' '
+         << left_justify("section", SectionWidth) << ' '
+         << left_justify("address", AddressWidth) << ' '
+         << left_justify("pointer", PointerWidth) << " type   "
+         << left_justify("addend", AddendWidth) << ' '
+         << left_justify("dylib", DylibWidth) << " symbol/vm address\n";
+  for (const object::MachOChainedFixupEntry &Entry : O->fixupTable(Err)) {
+    outs() << left_justify(Entry.segmentName(), SegmentWidth) << ' '
+           << left_justify(Entry.sectionName(), SectionWidth) << ' ' << "0x"
+           << left_justify(utohexstr(Entry.address()), AddressWidth - 2) << ' '
+           << format_hex(Entry.rawValue(), PointerWidth, true) << ' ';
+    if (Entry.isBind()) {
+      outs() << "bind   "
+             << "0x" << left_justify(utohexstr(Entry.addend()), AddendWidth - 2)
+             << ' ' << left_justify(ordinalName(O, Entry.ordinal()), DylibWidth)
+             << ' ' << Entry.symbolName();
+      if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_WEAK_IMPORT)
+        outs() << " (weak import)";
+      outs() << '\n';
+    } else {
+      assert(Entry.isRebase());
+      outs() << "rebase";
+      outs().indent(AddendWidth + DylibWidth + 2);
+      outs() << format("0x%" PRIX64, Entry.pointerValue()) << '\n';
+    }
+  }
+  if (Err)
+    reportError(std::move(Err), O->getFileName());
+
+  // TODO: Print opcode-based fixups if the object uses those.
 }
 
 static void PrintDylibs(MachOObjectFile *O, bool JustId) {


        


More information about the llvm-commits mailing list