diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h
--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h
@@ -140,6 +140,10 @@
   /// Return the offset into the section where the offset list begins.
   uint64_t getOffsetBase() const { return getHashBase() + getNumHashes() * 4; }
 
+  uint64_t getEntriesBase() const {
+    return getOffsetBase() + getNumHashes() * 4;
+  }
+
   /// Return the offset into the section where the I-th offset is.
   uint64_t getIthOffsetBase(uint32_t I) const {
     return getOffsetBase() + I * 4;
@@ -244,6 +248,92 @@
     }
   };
 
+  template <bool HasName = false> struct MaybeWithName {};
+  template <> struct MaybeWithName<true> {
+    StringRef Name;
+  };
+
+  /// A general iterator for all entries in the table. We offer two variants of
+  /// this iterator: one that also keeps track of the name of each entry, and
+  /// one that doesn't. The nameless version is substantially faster.
+  template <bool StoreName = true> class Iterator : MaybeWithName<StoreName> {
+    constexpr static auto EndMarker = std::numeric_limits<uint64_t>::max();
+
+    Entry Current;
+    uint64_t Offset;
+    uint32_t NumEntriesToCome;
+
+    void setToEnd() { Offset = EndMarker; }
+    bool isEnd() const { return Offset == EndMarker; }
+
+    /// Reads the next Entry in the table, populating `Current`.
+    /// If not possible (e.g. end of the section), becomes the end iterator.
+    void prepareNextEntryOrEnd() {
+      if (NumEntriesToCome == 0)
+        prepareNextStringOrEnd();
+      if (isEnd())
+        return;
+      uint64_t OffsetCopy = Offset;
+      Current.extract(&OffsetCopy);
+      NumEntriesToCome--;
+      Offset += Current.Table.getHashDataEntryLength();
+    }
+
+    /// Reads the next string pointer and the entry count for that string,
+    /// populating `NumEntriesToCome` and `Name` (if enabled).
+    /// If not possible (e.g. end of the section), becomes the end iterator.
+    /// Assumes `Offset` points to a string reference.
+    void prepareNextStringOrEnd() {
+      std::optional<uint32_t> StrOffset =
+          Current.Table.readStringOffsetAt(Offset);
+      if (!StrOffset)
+        return setToEnd();
+
+      // A zero denotes the end of the collision list. Read the next string
+      // again.
+      if (*StrOffset == 0)
+        return prepareNextStringOrEnd();
+
+      if constexpr (StoreName) {
+        std::optional<StringRef> MaybeStr =
+            Current.Table.readStringFromStrSection(*StrOffset);
+        if (!MaybeStr)
+          return setToEnd();
+        this->Name = *MaybeStr;
+      }
+
+      std::optional<uint32_t> MaybeNumEntries =
+          Current.Table.readU32FromAccel(Offset);
+      if (!MaybeNumEntries || *MaybeNumEntries == 0)
+        return setToEnd();
+      NumEntriesToCome = *MaybeNumEntries;
+    }
+
+  public:
+    Iterator(const AppleAcceleratorTable &Table, bool SetEnd = false)
+        : Current(Table), Offset(Table.getEntriesBase()), NumEntriesToCome(0) {
+      if (SetEnd)
+        setToEnd();
+      else
+        prepareNextEntryOrEnd();
+    }
+
+    Iterator &operator++() {
+      prepareNextEntryOrEnd();
+      return *this;
+    }
+    bool operator==(const Iterator &It) { return Offset == It.Offset; }
+    bool operator!=(const Iterator &It) { return Offset != It.Offset; }
+
+    decltype(auto) operator*() const {
+      assert(!isEnd() && "dereferencing end iterator");
+      if constexpr (StoreName)
+        return std::make_pair(Current, this->Name);
+      else
+        return (Current);
+    }
+  };
+
   AppleAcceleratorTable(const DWARFDataExtractor &AccelSection,
                         DataExtractor StringSection)
       : DWARFAcceleratorTable(AccelSection, StringSection) {}
@@ -275,6 +365,19 @@
 
   /// Look up all entries in the accelerator table matching \c Key.
   iterator_range<SameNameIterator> equal_range(StringRef Key) const;
+
+  /// Lookup all entries in the accelerator table and the name of each entry.
+  auto all_entries_and_names() const {
+    using ItWithName = Iterator</*StoreName*/ true>;
+    return make_range(ItWithName(*this), ItWithName(*this, /*SetEnd*/ true));
+  }
+
+  /// Lookup all entries in the accelerator table, without the name of each
+  /// entry.
+  auto all_entries() const {
+    using It = Iterator</*StoreName*/ false>;
+    return make_range(It(*this), It(*this, /*SetEnd*/ true));
+  }
 };
 
 /// .debug_names section consists of one or more units. Each unit starts with a
diff --git a/llvm/test/DebugInfo/Generic/apple-names-hash-collisions.ll b/llvm/test/DebugInfo/Generic/apple-names-hash-collisions.ll
--- a/llvm/test/DebugInfo/Generic/apple-names-hash-collisions.ll
+++ b/llvm/test/DebugInfo/Generic/apple-names-hash-collisions.ll
@@ -1,6 +1,7 @@
 ; RUN: %llc_dwarf -accel-tables=Apple -filetype=obj -o %t < %s
 ; RUN: llvm-dwarfdump -apple-names %t | FileCheck %s --check-prefix=NUM_HASHES
 ; RUN: llvm-dwarfdump  --find=bb --find=cA %t | FileCheck %s --check-prefix=FOUND_VARS
+; RUN: llvm-dwarfdump  --find-all-apple %t | FileCheck %s --check-prefix=ALL_ENTRIES
 
 
 ; The strings 'bb' and 'cA' hash to the same value under the Apple accelerator
@@ -8,13 +9,23 @@
 ; We first test that there is exactly one bucket and one hash.
 ; Then we check that both values are found.
 
-; NUM_HASHES:      Bucket count: 1
-; NUM_HASHES-NEXT: Hashes count: 1
+; NUM_HASHES:      Bucket count: 2
+; NUM_HASHES-NEXT: Hashes count: 2
 ; FOUND_VARS: DW_AT_name        ("bb")
 ; FOUND_VARS: DW_AT_name        ("cA")
 
+; ALL_ENTRIES: Apple accelerator entries with name = "cA":
+; ALL_ENTRIES: DW_AT_name        ("cA")
+; ALL_ENTRIES: Apple accelerator entries with name = "some_other_hash":
+; ALL_ENTRIES: DW_AT_name        ("some_other_hash")
+; ALL_ENTRIES: Apple accelerator entries with name = "int":
+; ALL_ENTRIES: DW_AT_name        ("int")
+; ALL_ENTRIES: Apple accelerator entries with name = "bb":
+; ALL_ENTRIES: DW_AT_name        ("bb")
+
 @bb = global i32 200, align 4, !dbg !0
 @cA = global i32 10, align 4, !dbg !5
+@some_other_hash = global i32 10, !dbg !17
 
 !llvm.module.flags = !{!9, !10, !11, !12, !13}
 !llvm.dbg.cu = !{!2}
@@ -24,7 +35,7 @@
 !1 = distinct !DIGlobalVariable(name: "bb", scope: !2, file: !3, line: 1, type: !7, isDefinition: true)
 !2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !3, producer: "", emissionKind: FullDebug, globals: !4)
 !3 = !DIFile(filename: "test.cpp", directory: "blah")
-!4 = !{!0, !5}
+!4 = !{!0, !5, !17}
 !5 = !DIGlobalVariableExpression(var: !6, expr: !DIExpression())
 !6 = distinct !DIGlobalVariable(name: "cA", scope: !2, file: !3, line: 2, type: !7, isLocal: false, isDefinition: true)
 !7 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
@@ -34,3 +45,5 @@
 !12 = !{i32 8, !"PIC Level", i32 2}
 !13 = !{i32 7, !"uwtable", i32 1}
 !15 = !{!"blah"}
+!16 = distinct !DIGlobalVariable(name: "some_other_hash", scope: !2, file: !3, line: 2, type: !7, isLocal: false, isDefinition: true)
+!17 = !DIGlobalVariableExpression(var: !16, expr: !DIExpression())
diff --git a/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp b/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
--- a/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
+++ b/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
@@ -12,6 +12,7 @@
 
 #include "llvm-dwarfdump.h"
 #include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/StringSet.h"
 #include "llvm/DebugInfo/DIContext.h"
 #include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
@@ -25,6 +26,7 @@
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/Format.h"
+#include "llvm/Support/FormatVariadic.h"
 #include "llvm/Support/InitLLVM.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/Path.h"
@@ -171,6 +173,10 @@
          value_desc("name"), cat(DwarfDumpCategory));
 static alias FindAlias("f", desc("Alias for --find."), aliasopt(Find),
                        cl::NotHidden);
+static opt<bool> FindAllApple(
+    "find-all-apple",
+    desc("Print every debug information entry in the accelerator tables."),
+    cat(DwarfDumpCategory));
 static opt<bool> IgnoreCase("ignore-case",
                             desc("Ignore case distinctions when using --name."),
                             value_desc("i"), cat(DwarfDumpCategory));
@@ -453,6 +459,35 @@
     Die.dump(OS, 0, DumpOpts);
 }
 
+/// Print all DIEs in apple accelerator tables
+static void findAllApple(
+    DWARFContext &DICtx, raw_ostream &OS,
+    std::function<StringRef(uint64_t RegNum, bool IsEH)> GetNameForDWARFReg) {
+  StringMap<llvm::SmallSet<DWARFDie, 2>> NameToDies;
+
+  auto PushDIEs = [&](const AppleAcceleratorTable &Accel) {
+    for (const auto &[Entry, Name] : Accel.all_entries_and_names()) {
+      if (std::optional<uint64_t> Off = Entry.getDIESectionOffset()) {
+        if (DWARFDie Die = DICtx.getDIEForOffset(*Off))
+          NameToDies[Name].insert(Die);
+      }
+    }
+  };
+
+  PushDIEs(DICtx.getAppleNames());
+  PushDIEs(DICtx.getAppleNamespaces());
+  PushDIEs(DICtx.getAppleTypes());
+
+  DIDumpOptions DumpOpts = getDumpOpts(DICtx);
+  DumpOpts.GetNameForDWARFReg = GetNameForDWARFReg;
+  for (const auto &[Name, Dies] : NameToDies) {
+    OS << llvm::formatv("\nApple accelerator entries with name = \"{0}\":\n",
+                        Name);
+    for (DWARFDie Die : Dies)
+      Die.dump(OS, 0, DumpOpts);
+  }
+}
+
 /// Handle the --lookup option and dump the DIEs and line info for the given
 /// address.
 /// TODO: specified Address for --lookup option could relate for several
@@ -625,6 +660,12 @@
     return true;
   }
 
+  // Handle the --find-all-apple option and lower it to --debug-info=<offset>.
+  if (FindAllApple) {
+    findAllApple(DICtx, OS, GetRegName);
+    return true;
+  }
+
   // Dump the complete DWARF structure.
   auto DumpOpts = getDumpOpts(DICtx);
   DumpOpts.GetNameForDWARFReg = GetRegName;
@@ -782,7 +823,7 @@
 
   // Unless dumping a specific DIE, default to --show-children.
   if (!ShowChildren && !Verify && !OffsetRequested && Name.empty() &&
-      Find.empty())
+      Find.empty() && !FindAllApple)
     ShowChildren = true;
 
   // Defaults to a.out if no filenames specified.