Index: llvm/include/llvm/Object/COFF.h
===================================================================
--- llvm/include/llvm/Object/COFF.h
+++ llvm/include/llvm/Object/COFF.h
@@ -1204,6 +1204,9 @@
   ResourceSectionRef() = default;
   explicit ResourceSectionRef(StringRef Ref) : BBS(Ref, support::little) {}
 
+  Error load(const COFFObjectFile *O);
+  Error load(const COFFObjectFile *O, const SectionRef &S);
+
   Expected<ArrayRef<UTF16>>
   getEntryNameString(const coff_resource_dir_entry &Entry);
   Expected<const coff_resource_dir_table &>
@@ -1214,9 +1217,16 @@
   Expected<const coff_resource_dir_entry &>
   getTableEntry(const coff_resource_dir_table &Table, uint32_t Index);
 
+  Expected<StringRef> getContents(const coff_resource_data_entry &Entry);
+
 private:
   BinaryByteStream BBS;
 
+  SectionRef Section;
+  const COFFObjectFile *Obj;
+
+  std::vector<const coff_relocation *> Relocs;
+
   Expected<const coff_resource_dir_table &> getTableAtOffset(uint32_t Offset);
   Expected<const coff_resource_dir_entry &>
   getTableEntryAtOffset(uint32_t Offset);
Index: llvm/lib/Object/COFFObjectFile.cpp
===================================================================
--- llvm/lib/Object/COFFObjectFile.cpp
+++ llvm/lib/Object/COFFObjectFile.cpp
@@ -1744,3 +1744,120 @@
   return getTableEntryAtOffset(TableOffset + sizeof(Table) +
                                Index * sizeof(coff_resource_dir_entry));
 }
+
+Error ResourceSectionRef::load(const COFFObjectFile *O) {
+  for (const SectionRef &S : O->sections()) {
+    Expected<StringRef> Name = S.getName();
+    if (!Name)
+      return Name.takeError();
+
+    if (*Name == ".rsrc" || *Name == ".rsrc$01")
+      return load(O, S);
+  }
+  return createStringError(object_error::parse_failed,
+                           "no resource section found");
+}
+
+Error ResourceSectionRef::load(const COFFObjectFile *O, const SectionRef &S) {
+  Obj = O;
+  Section = S;
+  Expected<StringRef> Contents = Section.getContents();
+  if (!Contents)
+    return Contents.takeError();
+  BBS = BinaryByteStream(*Contents, support::little);
+  const coff_section *COFFSect = Obj->getCOFFSection(Section);
+  ArrayRef<coff_relocation> OrigRelocs = Obj->getRelocations(COFFSect);
+  Relocs.reserve(OrigRelocs.size());
+  for (const coff_relocation &R : OrigRelocs)
+    Relocs.push_back(&R);
+  std::sort(Relocs.begin(), Relocs.end(),
+            [](const coff_relocation *A, const coff_relocation *B) {
+              return A->VirtualAddress < B->VirtualAddress;
+            });
+  return Error::success();
+}
+
+Expected<StringRef>
+ResourceSectionRef::getContents(const coff_resource_data_entry &Entry) {
+  if (!Obj)
+    return createStringError(object_error::parse_failed, "no object provided");
+
+  // Find a potential relocation at the DataRVA field (first member of
+  // the coff_resource_data_entry struct).
+  const uint8_t *EntryPtr = reinterpret_cast<const uint8_t *>(&Entry);
+  ptrdiff_t EntryOffset = EntryPtr - BBS.data().data();
+  coff_relocation RelocTarget{ulittle32_t(EntryOffset), ulittle32_t(0),
+                              ulittle16_t(0)};
+  auto RelocsForOffset =
+      std::equal_range(Relocs.begin(), Relocs.end(), &RelocTarget,
+                       [](const coff_relocation *A, const coff_relocation *B) {
+                         return A->VirtualAddress < B->VirtualAddress;
+                       });
+
+  if (RelocsForOffset.first != RelocsForOffset.second) {
+    // We found a relocation with the right offset. Check that it does have
+    // the expected type.
+    const coff_relocation &R = **RelocsForOffset.first;
+    uint16_t RVAReloc;
+    switch (Obj->getMachine()) {
+    case COFF::IMAGE_FILE_MACHINE_I386:
+      RVAReloc = COFF::IMAGE_REL_I386_DIR32NB;
+      break;
+    case COFF::IMAGE_FILE_MACHINE_AMD64:
+      RVAReloc = COFF::IMAGE_REL_AMD64_ADDR32NB;
+      break;
+    case COFF::IMAGE_FILE_MACHINE_ARMNT:
+      RVAReloc = COFF::IMAGE_REL_ARM_ADDR32NB;
+      break;
+    case COFF::IMAGE_FILE_MACHINE_ARM64:
+      RVAReloc = COFF::IMAGE_REL_ARM64_ADDR32NB;
+      break;
+    default:
+      return createStringError(object_error::parse_failed,
+                               "unsupported architecture");
+    }
+    if (R.Type != RVAReloc)
+      return createStringError(object_error::parse_failed,
+                               "unexpected relocation type");
+    // Get the relocation's symbol
+    Expected<COFFSymbolRef> Sym = Obj->getSymbol(R.SymbolTableIndex);
+    if (!Sym)
+      return Sym.takeError();
+    const coff_section *Section = nullptr;
+    // And the symbol's section
+    if (std::error_code EC = Obj->getSection(Sym->getSectionNumber(), Section))
+      return errorCodeToError(EC);
+    // Add the initial value of DataRVA to the symbol's offset to find the
+    // data it points at.
+    uint64_t Offset = Entry.DataRVA + Sym->getValue();
+    ArrayRef<uint8_t> Contents;
+    if (Error E = Obj->getSectionContents(Section, Contents))
+      return std::move(E);
+    if (Offset + Entry.DataSize > Contents.size())
+      return createStringError(object_error::parse_failed,
+                               "data outside of section");
+    // Return a reference to the data inside the section.
+    return StringRef(reinterpret_cast<const char *>(Contents.data()) + Offset,
+                     Entry.DataSize);
+  } else {
+    // Relocatable objects need a relocation for the DataRVA field.
+    if (Obj->isRelocatableObject())
+      return createStringError(object_error::parse_failed,
+                               "no relocation found for DataRVA");
+
+    // Locate the section that contains the address that DataRVA points at.
+    uint64_t VA = Entry.DataRVA + Obj->getImageBase();
+    for (const SectionRef &S : Obj->sections()) {
+      if (VA >= S.getAddress() &&
+          VA + Entry.DataSize <= S.getAddress() + S.getSize()) {
+        uint64_t Offset = VA - S.getAddress();
+        Expected<StringRef> Contents = S.getContents();
+        if (!Contents)
+          return Contents.takeError();
+        return Contents->slice(Offset, Offset + Entry.DataSize);
+      }
+    }
+    return createStringError(object_error::parse_failed,
+                             "address not found in image");
+  }
+}
Index: llvm/test/tools/llvm-cvtres/combined.test
===================================================================
--- llvm/test/tools/llvm-cvtres/combined.test
+++ llvm/test/tools/llvm-cvtres/combined.test
@@ -34,6 +34,8 @@
 CHECK-NEXT:          DataSize: 57
 CHECK-NEXT:          Codepage: 0
 CHECK-NEXT:          Reserved: 0
+CHECK-NEXT:          Data (
+CHECK:               )
 CHECK-NEXT:        ]
 CHECK-NEXT:      ]
 CHECK-NEXT:    ]
@@ -57,6 +59,8 @@
 CHECK-NEXT:          DataSize: 808
 CHECK-NEXT:          Codepage: 0
 CHECK-NEXT:          Reserved: 0
+CHECK-NEXT:          Data (
+CHECK:               )
 CHECK-NEXT:        ]
 CHECK-NEXT:      ]
 CHECK-NEXT:    ]
@@ -75,6 +79,8 @@
 CHECK-NEXT:          DataSize: 808
 CHECK-NEXT:          Codepage: 0
 CHECK-NEXT:          Reserved: 0
+CHECK-NEXT:          Data (
+CHECK:               )
 CHECK-NEXT:        ]
 CHECK-NEXT:      ]
 CHECK-NEXT:    ]
@@ -98,6 +104,8 @@
 CHECK-NEXT:          DataSize: 48
 CHECK-NEXT:          Codepage: 0
 CHECK-NEXT:          Reserved: 0
+CHECK-NEXT:          Data (
+CHECK:               )
 CHECK-NEXT:        ]
 CHECK-NEXT:      ]
 CHECK-NEXT:    ]
@@ -116,6 +124,8 @@
 CHECK-NEXT:          DataSize: 46
 CHECK-NEXT:          Codepage: 0
 CHECK-NEXT:          Reserved: 0
+CHECK-NEXT:          Data (
+CHECK:               )
 CHECK-NEXT:        ]
 CHECK-NEXT:      ]
 CHECK-NEXT:    ]
@@ -139,6 +149,8 @@
 CHECK-NEXT:          DataSize: 108
 CHECK-NEXT:          Codepage: 0
 CHECK-NEXT:          Reserved: 0
+CHECK-NEXT:          Data (
+CHECK:               )
 CHECK-NEXT:        ]
 CHECK-NEXT:      ]
 CHECK-NEXT:    ]
@@ -162,6 +174,8 @@
 CHECK-NEXT:          DataSize: 24
 CHECK-NEXT:          Codepage: 0
 CHECK-NEXT:          Reserved: 0
+CHECK-NEXT:          Data (
+CHECK:               )
 CHECK-NEXT:        ]
 CHECK-NEXT:      ]
 CHECK-NEXT:      Language: (ID 2052) [
@@ -175,6 +189,8 @@
 CHECK-NEXT:          DataSize: 24
 CHECK-NEXT:          Codepage: 0
 CHECK-NEXT:          Reserved: 0
+CHECK-NEXT:          Data (
+CHECK:               )
 CHECK-NEXT:        ]
 CHECK-NEXT:      ]
 CHECK-NEXT:    ]
@@ -193,6 +209,8 @@
 CHECK-NEXT:          DataSize: 24
 CHECK-NEXT:          Codepage: 0
 CHECK-NEXT:          Reserved: 0
+CHECK-NEXT:          Data (
+CHECK:               )
 CHECK-NEXT:        ]
 CHECK-NEXT:      ]
 CHECK-NEXT:    ]
@@ -216,6 +234,8 @@
 CHECK-NEXT:          DataSize: 54
 CHECK-NEXT:          Codepage: 0
 CHECK-NEXT:          Reserved: 0
+CHECK-NEXT:          Data (
+CHECK:               )
 CHECK-NEXT:        ]
 CHECK-NEXT:      ]
 CHECK-NEXT:      Language: (ID 2052) [
@@ -229,6 +249,8 @@
 CHECK-NEXT:          DataSize: 67
 CHECK-NEXT:          Codepage: 0
 CHECK-NEXT:          Reserved: 0
+CHECK-NEXT:          Data (
+CHECK:               )
 CHECK-NEXT:        ]
 CHECK-NEXT:      ]
 CHECK-NEXT:      Language: (ID 4103) [
@@ -242,6 +264,8 @@
 CHECK-NEXT:          DataSize: 66
 CHECK-NEXT:          Codepage: 0
 CHECK-NEXT:          Reserved: 0
+CHECK-NEXT:          Data (
+CHECK:               )
 CHECK-NEXT:        ]
 CHECK-NEXT:      ]
 CHECK-NEXT:    ]
Index: llvm/test/tools/llvm-cvtres/object.test
===================================================================
--- llvm/test/tools/llvm-cvtres/object.test
+++ llvm/test/tools/llvm-cvtres/object.test
@@ -33,6 +33,8 @@
 CHECK-NEXT:          DataSize: 57
 CHECK-NEXT:          Codepage: 0
 CHECK-NEXT:          Reserved: 0
+CHECK-NEXT:          Data (
+CHECK:               )
 CHECK-NEXT:        ]
 CHECK-NEXT:      ]
 CHECK-NEXT:    ]
@@ -56,6 +58,8 @@
 CHECK-NEXT:          DataSize: 808
 CHECK-NEXT:          Codepage: 0
 CHECK-NEXT:          Reserved: 0
+CHECK-NEXT:          Data (
+CHECK:               )
 CHECK-NEXT:        ]
 CHECK-NEXT:      ]
 CHECK-NEXT:    ]
@@ -74,6 +78,8 @@
 CHECK-NEXT:          DataSize: 808
 CHECK-NEXT:          Codepage: 0
 CHECK-NEXT:          Reserved: 0
+CHECK-NEXT:          Data (
+CHECK:               )
 CHECK-NEXT:        ]
 CHECK-NEXT:      ]
 CHECK-NEXT:    ]
@@ -97,6 +103,8 @@
 CHECK-NEXT:          DataSize: 48
 CHECK-NEXT:          Codepage: 0
 CHECK-NEXT:          Reserved: 0
+CHECK-NEXT:          Data (
+CHECK:               )
 CHECK-NEXT:        ]
 CHECK-NEXT:      ]
 CHECK-NEXT:    ]
@@ -115,6 +123,8 @@
 CHECK-NEXT:          DataSize: 46
 CHECK-NEXT:          Codepage: 0
 CHECK-NEXT:          Reserved: 0
+CHECK-NEXT:          Data (
+CHECK:               )
 CHECK-NEXT:        ]
 CHECK-NEXT:      ]
 CHECK-NEXT:    ]
@@ -138,6 +148,8 @@
 CHECK-NEXT:          DataSize: 108
 CHECK-NEXT:          Codepage: 0
 CHECK-NEXT:          Reserved: 0
+CHECK-NEXT:          Data (
+CHECK:               )
 CHECK-NEXT:        ]
 CHECK-NEXT:      ]
 CHECK-NEXT:    ]
@@ -161,6 +173,8 @@
 CHECK-NEXT:          DataSize: 24
 CHECK-NEXT:          Codepage: 0
 CHECK-NEXT:          Reserved: 0
+CHECK-NEXT:          Data (
+CHECK:               )
 CHECK-NEXT:        ]
 CHECK-NEXT:      ]
 CHECK-NEXT:    ]
@@ -179,6 +193,8 @@
 CHECK-NEXT:          DataSize: 24
 CHECK-NEXT:          Codepage: 0
 CHECK-NEXT:          Reserved: 0
+CHECK-NEXT:          Data (
+CHECK:               )
 CHECK-NEXT:        ]
 CHECK-NEXT:      ]
 CHECK-NEXT:    ]
Index: llvm/test/tools/llvm-readobj/coff-resources.test
===================================================================
--- llvm/test/tools/llvm-readobj/coff-resources.test
+++ llvm/test/tools/llvm-readobj/coff-resources.test
@@ -33,6 +33,11 @@
 ZERO-NEXT:          DataSize: 42
 ZERO-NEXT:          Codepage: 0
 ZERO-NEXT:          Reserved: 0
+ZERO-NEXT:          Data (
+ZERO-NEXT:            0000: 00000500 48006500 6C006C00 6F000000  |....H.e.l.l.o...|
+ZERO-NEXT:            0010: 00000000 00000000 00000000 00000000  |................|
+ZERO-NEXT:            0020: 00000000 00000000 0000               |..........|
+ZERO-NEXT:          )
 ZERO-NEXT:        ]
 ZERO-NEXT:      ]
 ZERO-NEXT:    ]
@@ -62,6 +67,8 @@
 TEST_RES-NEXT:          DataSize: 808
 TEST_RES-NEXT:          Codepage: 0
 TEST_RES-NEXT:          Reserved: 0
+TEST_RES-NEXT:          Data (
+TEST_RES:               )
 TEST_RES-NEXT:        ]
 TEST_RES-NEXT:      ]
 TEST_RES-NEXT:    ]
@@ -80,6 +87,8 @@
 TEST_RES-NEXT:          DataSize: 808
 TEST_RES-NEXT:          Codepage: 0
 TEST_RES-NEXT:          Reserved: 0
+TEST_RES-NEXT:          Data (
+TEST_RES:               )
 TEST_RES-NEXT:        ]
 TEST_RES-NEXT:      ]
 TEST_RES-NEXT:    ]
@@ -103,6 +112,8 @@
 TEST_RES-NEXT:          DataSize: 48
 TEST_RES-NEXT:          Codepage: 0
 TEST_RES-NEXT:          Reserved: 0
+TEST_RES-NEXT:          Data (
+TEST_RES:               )
 TEST_RES-NEXT:        ]
 TEST_RES-NEXT:      ]
 TEST_RES-NEXT:    ]
@@ -121,6 +132,8 @@
 TEST_RES-NEXT:          DataSize: 46
 TEST_RES-NEXT:          Codepage: 0
 TEST_RES-NEXT:          Reserved: 0
+TEST_RES-NEXT:          Data (
+TEST_RES:               )
 TEST_RES-NEXT:        ]
 TEST_RES-NEXT:      ]
 TEST_RES-NEXT:    ]
@@ -144,6 +157,8 @@
 TEST_RES-NEXT:          DataSize: 108
 TEST_RES-NEXT:          Codepage: 0
 TEST_RES-NEXT:          Reserved: 0
+TEST_RES-NEXT:          Data (
+TEST_RES:               )
 TEST_RES-NEXT:        ]
 TEST_RES-NEXT:      ]
 TEST_RES-NEXT:    ]
@@ -167,6 +182,8 @@
 TEST_RES-NEXT:          DataSize: 24
 TEST_RES-NEXT:          Codepage: 0
 TEST_RES-NEXT:          Reserved: 0
+TEST_RES-NEXT:          Data (
+TEST_RES:               )
 TEST_RES-NEXT:        ]
 TEST_RES-NEXT:      ]
 TEST_RES-NEXT:    ]
@@ -185,6 +202,8 @@
 TEST_RES-NEXT:          DataSize: 24
 TEST_RES-NEXT:          Codepage: 0
 TEST_RES-NEXT:          Reserved: 0
+TEST_RES-NEXT:          Data (
+TEST_RES:               )
 TEST_RES-NEXT:        ]
 TEST_RES-NEXT:      ]
 TEST_RES-NEXT:    ]
Index: llvm/tools/llvm-readobj/COFFDumper.cpp
===================================================================
--- llvm/tools/llvm-readobj/COFFDumper.cpp
+++ llvm/tools/llvm-readobj/COFFDumper.cpp
@@ -1766,7 +1766,10 @@
     StringRef Ref = unwrapOrError(Obj->getFileName(), S.getContents());
 
     if ((Name == ".rsrc") || (Name == ".rsrc$01")) {
-      ResourceSectionRef RSF(Ref);
+      ResourceSectionRef RSF;
+      Error E = RSF.load(Obj, S);
+      if (E)
+        reportError(std::move(E), Obj->getFileName());
       auto &BaseTable = unwrapOrError(Obj->getFileName(), RSF.getBaseTable());
       W.printNumber("Total Number of Resources",
                     countTotalTableEntries(RSF, BaseTable, "Type"));
@@ -1871,6 +1874,9 @@
       W.printNumber("DataSize", DataEntry.DataSize);
       W.printNumber("Codepage", DataEntry.Codepage);
       W.printNumber("Reserved", DataEntry.Reserved);
+      StringRef Contents =
+          unwrapOrError(Obj->getFileName(), RSF.getContents(DataEntry));
+      W.printBinaryBlock("Data", Contents);
     }
   }
 }