Index: lld/trunk/test/COFF/pdb.test
===================================================================
--- lld/trunk/test/COFF/pdb.test
+++ lld/trunk/test/COFF/pdb.test
@@ -6,7 +6,7 @@
 # RUN: llvm-pdbutil pdb2yaml -stream-metadata -stream-directory -pdb-stream \
 # RUN:   -dbi-stream -ipi-stream -tpi-stream %t.pdb | FileCheck %s
 
-# RUN: llvm-pdbutil dump -modules -section-map -section-contribs \
+# RUN: llvm-pdbutil dump -modules -section-map -section-contribs -section-headers \
 # RUN:   -publics -public-extras -types -ids -type-extras -id-extras %t.pdb \
 # RUN:   | FileCheck -check-prefix RAW %s
 
@@ -188,6 +188,64 @@
 RAW-NEXT:  Address Map
 RAW-NEXT:    off = 20
 RAW-NEXT:    off = 0
+RAW:                            Section Headers
+RAW-NEXT: ============================================================
+RAW:        SECTION HEADER #1
+RAW-NEXT:     .pdata name
+RAW-NEXT:          C virtual size
+RAW-NEXT:       1000 virtual address
+RAW-NEXT:        200 size of raw data
+RAW-NEXT:        400 file pointer to raw data
+RAW-NEXT:          0 file pointer to relocation table
+RAW-NEXT:          0 file pointer to line numbers
+RAW-NEXT:          0 number of relocations
+RAW-NEXT:          0 number of line numbers
+RAW-NEXT:   40000040 flags
+RAW-NEXT:            IMAGE_SCN_CNT_INITIALIZED_DATA
+RAW-NEXT:            IMAGE_SCN_MEM_READ
+RAW:        SECTION HEADER #2
+RAW-NEXT:      .text name
+RAW-NEXT:         16 virtual size
+RAW-NEXT:       2000 virtual address
+RAW-NEXT:        200 size of raw data
+RAW-NEXT:        600 file pointer to raw data
+RAW-NEXT:          0 file pointer to relocation table
+RAW-NEXT:          0 file pointer to line numbers
+RAW-NEXT:          0 number of relocations
+RAW-NEXT:          0 number of line numbers
+RAW-NEXT:   60000020 flags
+RAW-NEXT:            IMAGE_SCN_CNT_CODE
+RAW-NEXT:            IMAGE_SCN_MEM_EXECUTE
+RAW-NEXT:            IMAGE_SCN_MEM_READ
+RAW:        SECTION HEADER #3
+RAW-NEXT:     .xdata name
+RAW-NEXT:          8 virtual size
+RAW-NEXT:       3000 virtual address
+RAW-NEXT:        200 size of raw data
+RAW-NEXT:        800 file pointer to raw data
+RAW-NEXT:          0 file pointer to relocation table
+RAW-NEXT:          0 file pointer to line numbers
+RAW-NEXT:          0 number of relocations
+RAW-NEXT:          0 number of line numbers
+RAW-NEXT:   40000040 flags
+RAW-NEXT:            IMAGE_SCN_CNT_INITIALIZED_DATA
+RAW-NEXT:            IMAGE_SCN_MEM_READ
+RAW:        SECTION HEADER #4
+RAW-NEXT:     .rdata name
+RAW-NEXT:         77 virtual size
+RAW-NEXT:       4000 virtual address
+RAW-NEXT:        200 size of raw data
+RAW-NEXT:        A00 file pointer to raw data
+RAW-NEXT:          0 file pointer to relocation table
+RAW-NEXT:          0 file pointer to line numbers
+RAW-NEXT:          0 number of relocations
+RAW-NEXT:          0 number of line numbers
+RAW-NEXT:   40000040 flags
+RAW-NEXT:            IMAGE_SCN_CNT_INITIALIZED_DATA
+RAW-NEXT:            IMAGE_SCN_MEM_READ
+RAW:                        Original Section Headers
+RAW-NEXT: ============================================================
+RAW-NEXT:   PDB does not contain the requested image section header type
 RAW:                        Section Contributions
 RAW-NEXT: ============================================================
 RAW-NEXT:   SC  | mod = 0, 0001:0000, size = 12, data crc = 0, reloc crc = 0
@@ -202,18 +260,18 @@
 RAW-NEXT:         IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_ALIGN_4BYTES | IMAGE_SCN_MEM_READ
 RAW:                             Section Map
 RAW-NEXT: ============================================================
-RAW-NEXT:   Section 0000 | ovl = 0, group = 0, frame = 0, name = 1
+RAW-NEXT:   Section 0000 | ovl = 0, group = 0, frame = 1, name = 65535
 RAW-NEXT:                  class = 65535, offset = 0, size =
 RAW-NEXT:                  flags = read | 32 bit addr | selector
-RAW-NEXT:   Section 0001 | ovl = 1, group = 0, frame = 0, name = 2
+RAW-NEXT:   Section 0001 | ovl = 0, group = 0, frame = 2, name = 65535
 RAW-NEXT:                  class = 65535, offset = 0, size =
 RAW-NEXT:                  flags = read | execute | 32 bit addr | selector
-RAW-NEXT:   Section 0002 | ovl = 2, group = 0, frame = 0, name = 3
+RAW-NEXT:   Section 0002 | ovl = 0, group = 0, frame = 3, name = 65535
 RAW-NEXT:                  class = 65535, offset = 0, size =
 RAW-NEXT:                  flags = read | 32 bit addr | selector
-RAW-NEXT:   Section 0003 | ovl = 3, group = 0, frame = 0, name = 4
+RAW-NEXT:   Section 0003 | ovl = 0, group = 0, frame = 4, name = 65535
 RAW-NEXT:                  class = 65535, offset = 0, size =
 RAW-NEXT:                  flags = read | 32 bit addr | selector
-RAW-NEXT:   Section 0004 | ovl = 4, group = 0, frame = 0, name = 5
+RAW-NEXT:   Section 0004 | ovl = 0, group = 0, frame = 5, name = 65535
 RAW-NEXT:                  class = 65535, offset = 0, size =
 RAW-NEXT:                  flags = 32 bit addr | absolute addr
Index: llvm/trunk/test/DebugInfo/PDB/pdbdump-headers.test
===================================================================
--- llvm/trunk/test/DebugInfo/PDB/pdbdump-headers.test
+++ llvm/trunk/test/DebugInfo/PDB/pdbdump-headers.test
@@ -534,19 +534,19 @@
 ALL-NEXT:         IMAGE_SCN_MEM_WRITE
 ALL:                              Section Map
 ALL-NEXT: ============================================================
-ALL-NEXT:   Section 0000 | ovl = 0, group = 0, frame = 0, name = 1
+ALL-NEXT:   Section 0000 | ovl = 0, group = 0, frame = 1, name = 65535
 ALL-NEXT:                  class = 65535, offset = 0, size = 4122
 ALL-NEXT:                  flags = read | execute | 32 bit addr | selector
-ALL-NEXT:   Section 0001 | ovl = 1, group = 0, frame = 0, name = 2
+ALL-NEXT:   Section 0001 | ovl = 0, group = 0, frame = 2, name = 65535
 ALL-NEXT:                  class = 65535, offset = 0, size = 690
 ALL-NEXT:                  flags = read | 32 bit addr | selector
-ALL-NEXT:   Section 0002 | ovl = 2, group = 0, frame = 0, name = 3
+ALL-NEXT:   Section 0002 | ovl = 0, group = 0, frame = 3, name = 65535
 ALL-NEXT:                  class = 65535, offset = 0, size = 4
 ALL-NEXT:                  flags = read | write | 32 bit addr | selector
-ALL-NEXT:   Section 0003 | ovl = 3, group = 0, frame = 0, name = 4
+ALL-NEXT:   Section 0003 | ovl = 0, group = 0, frame = 4, name = 65535
 ALL-NEXT:                  class = 65535, offset = 0, size = 8
 ALL-NEXT:                  flags = read | 32 bit addr | selector
-ALL-NEXT:   Section 0004 | ovl = 4, group = 0, frame = 0, name = 0
+ALL-NEXT:   Section 0004 | ovl = 0, group = 0, frame = 0, name = 65535
 ALL-NEXT:                  class = 65535, offset = 0, size = 4294967295
 ALL-NEXT:                  flags = 32 bit addr | absolute addr
 
Index: llvm/trunk/test/DebugInfo/PDB/section-headers.test
===================================================================
--- llvm/trunk/test/DebugInfo/PDB/section-headers.test
+++ llvm/trunk/test/DebugInfo/PDB/section-headers.test
@@ -0,0 +1,66 @@
+RUN: llvm-pdbutil dump -section-headers %p/Inputs/empty.pdb | FileCheck %s
+
+CHECK:                       Section Headers
+CHECK-NEXT: ============================================================
+CHECK-LABEL:  SECTION HEADER #1
+CHECK-NEXT:      .text name
+CHECK-NEXT:       101A virtual size
+CHECK-NEXT:       1000 virtual address
+CHECK-NEXT:       1200 size of raw data
+CHECK-NEXT:        400 file pointer to raw data
+CHECK-NEXT:          0 file pointer to relocation table
+CHECK-NEXT:          0 file pointer to line numbers
+CHECK-NEXT:          0 number of relocations
+CHECK-NEXT:          0 number of line numbers
+CHECK-NEXT:   60000020 flags
+CHECK-NEXT:            IMAGE_SCN_CNT_CODE
+CHECK-NEXT:            IMAGE_SCN_MEM_EXECUTE
+CHECK-NEXT:            IMAGE_SCN_MEM_READ
+
+CHECK-LABEL:  SECTION HEADER #2
+CHECK-NEXT:     .rdata name
+CHECK-NEXT:        2B2 virtual size
+CHECK-NEXT:       3000 virtual address
+CHECK-NEXT:        400 size of raw data
+CHECK-NEXT:       1600 file pointer to raw data
+CHECK-NEXT:          0 file pointer to relocation table
+CHECK-NEXT:          0 file pointer to line numbers
+CHECK-NEXT:          0 number of relocations
+CHECK-NEXT:          0 number of line numbers
+CHECK-NEXT:   40000040 flags
+CHECK-NEXT:            IMAGE_SCN_CNT_INITIALIZED_DATA
+CHECK-NEXT:            IMAGE_SCN_MEM_READ
+
+CHECK-LABEL:  SECTION HEADER #3
+CHECK-NEXT:      .data name
+CHECK-NEXT:          4 virtual size
+CHECK-NEXT:       4000 virtual address
+CHECK-NEXT:          0 size of raw data
+CHECK-NEXT:          0 file pointer to raw data
+CHECK-NEXT:          0 file pointer to relocation table
+CHECK-NEXT:          0 file pointer to line numbers
+CHECK-NEXT:          0 number of relocations
+CHECK-NEXT:          0 number of line numbers
+CHECK-NEXT:   C0000040 flags
+CHECK-NEXT:            IMAGE_SCN_CNT_INITIALIZED_DATA
+CHECK-NEXT:            IMAGE_SCN_MEM_READ
+CHECK-NEXT:            IMAGE_SCN_MEM_WRITE
+
+CHECK-LABEL:  SECTION HEADER #4
+CHECK-NEXT:     .reloc name
+CHECK-NEXT:          8 virtual size
+CHECK-NEXT:       5000 virtual address
+CHECK-NEXT:        200 size of raw data
+CHECK-NEXT:       1A00 file pointer to raw data
+CHECK-NEXT:          0 file pointer to relocation table
+CHECK-NEXT:          0 file pointer to line numbers
+CHECK-NEXT:          0 number of relocations
+CHECK-NEXT:          0 number of line numbers
+CHECK-NEXT:   42000040 flags
+CHECK-NEXT:            IMAGE_SCN_CNT_INITIALIZED_DATA
+CHECK-NEXT:            IMAGE_SCN_MEM_DISCARDABLE
+CHECK-NEXT:            IMAGE_SCN_MEM_READ
+
+CHECK:                        Original Section Headers
+CHECK-NEXT: ============================================================
+CHECK-NEXT:   PDB does not contain the requested image section header type
Index: llvm/trunk/tools/llvm-pdbutil/DumpOutputStyle.h
===================================================================
--- llvm/trunk/tools/llvm-pdbutil/DumpOutputStyle.h
+++ llvm/trunk/tools/llvm-pdbutil/DumpOutputStyle.h
@@ -15,6 +15,7 @@
 
 #include "llvm/ADT/Optional.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
 
 #include <string>
 
@@ -51,9 +52,12 @@
   Error dumpGlobals();
   Error dumpPublics();
   Error dumpSymbolsFromGSI(const GSIHashTable &Table, bool HashExtras);
+  Error dumpSectionHeaders();
   Error dumpSectionContribs();
   Error dumpSectionMap();
 
+  void dumpSectionHeaders(StringRef Label, DbgHeaderType Type);
+
   PDBFile &File;
   LinePrinter P;
   std::unique_ptr<codeview::LazyRandomTypeCollection> TpiTypes;
Index: llvm/trunk/tools/llvm-pdbutil/DumpOutputStyle.cpp
===================================================================
--- llvm/trunk/tools/llvm-pdbutil/DumpOutputStyle.cpp
+++ llvm/trunk/tools/llvm-pdbutil/DumpOutputStyle.cpp
@@ -145,6 +145,11 @@
       return EC;
   }
 
+  if (opts::dump::DumpSectionHeaders) {
+    if (auto EC = dumpSectionHeaders())
+      return EC;
+  }
+
   if (opts::dump::DumpSectionContribs) {
     if (auto EC = dumpSectionContribs())
       return EC;
@@ -974,7 +979,9 @@
 }
 
 static std::string formatSectionCharacteristics(uint32_t IndentLevel,
-                                                uint32_t C) {
+                                                uint32_t C,
+                                                uint32_t FlagsPerLine,
+                                                StringRef Separator) {
   using SC = COFF::SectionCharacteristics;
   std::vector<std::string> Opts;
   if (C == COFF::SC_Invalid)
@@ -1036,7 +1043,7 @@
   PUSH_FLAG(SC, IMAGE_SCN_MEM_EXECUTE, C, "IMAGE_SCN_MEM_EXECUTE");
   PUSH_FLAG(SC, IMAGE_SCN_MEM_READ, C, "IMAGE_SCN_MEM_READ");
   PUSH_FLAG(SC, IMAGE_SCN_MEM_WRITE, C, "IMAGE_SCN_MEM_WRITE");
-  return typesetItemList(Opts, IndentLevel, 3, " | ");
+  return typesetItemList(Opts, IndentLevel, FlagsPerLine, Separator);
 }
 
 static std::string formatSegMapDescriptorFlag(uint32_t IndentLevel,
@@ -1055,6 +1062,79 @@
   return typesetItemList(Opts, IndentLevel, 4, " | ");
 }
 
+Error DumpOutputStyle::dumpSectionHeaders() {
+  dumpSectionHeaders("Section Headers", DbgHeaderType::SectionHdr);
+  dumpSectionHeaders("Original Section Headers", DbgHeaderType::SectionHdrOrig);
+  return Error::success();
+}
+
+void DumpOutputStyle::dumpSectionHeaders(StringRef Label, DbgHeaderType Type) {
+  printHeader(P, Label);
+  ExitOnError Err("Error dumping publics stream: ");
+
+  AutoIndent Indent(P);
+  if (!File.hasPDBDbiStream()) {
+    P.formatLine(
+        "Section headers require a DBI Stream, which could not be loaded");
+    return;
+  }
+
+  auto &Dbi = Err(File.getPDBDbiStream());
+  uint32_t SI = Dbi.getDebugStreamIndex(Type);
+
+  if (SI == kInvalidStreamIndex) {
+    P.formatLine(
+        "PDB does not contain the requested image section header type");
+    return;
+  }
+
+  auto Stream = MappedBlockStream::createIndexedStream(
+      File.getMsfLayout(), File.getMsfBuffer(), SI, File.getAllocator());
+  if (!Stream) {
+    P.formatLine("Could not load the required stream data");
+    return;
+  }
+  ArrayRef<object::coff_section> Headers;
+  if (Stream->getLength() % sizeof(object::coff_section) != 0) {
+    P.formatLine(
+        "Section header array size is not a multiple of section header size");
+    return;
+  }
+  uint32_t NumHeaders = Stream->getLength() / sizeof(object::coff_section);
+  BinaryStreamReader Reader(*Stream);
+  cantFail(Reader.readArray(Headers, NumHeaders));
+  if (Headers.empty()) {
+    P.formatLine("No section headers");
+    return;
+  }
+
+  uint32_t I = 1;
+  for (const auto &Header : Headers) {
+    P.NewLine();
+    P.formatLine("SECTION HEADER #{0}", I);
+    P.formatLine("{0,8} name", Header.Name);
+    P.formatLine("{0,8:X-} virtual size", uint32_t(Header.VirtualSize));
+    P.formatLine("{0,8:X-} virtual address", uint32_t(Header.VirtualAddress));
+    P.formatLine("{0,8:X-} size of raw data", uint32_t(Header.SizeOfRawData));
+    P.formatLine("{0,8:X-} file pointer to raw data",
+                 uint32_t(Header.PointerToRawData));
+    P.formatLine("{0,8:X-} file pointer to relocation table",
+                 uint32_t(Header.PointerToRelocations));
+    P.formatLine("{0,8:X-} file pointer to line numbers",
+                 uint32_t(Header.PointerToLinenumbers));
+    P.formatLine("{0,8:X-} number of relocations",
+                 uint32_t(Header.NumberOfRelocations));
+    P.formatLine("{0,8:X-} number of line numbers",
+                 uint32_t(Header.NumberOfLinenumbers));
+    P.formatLine("{0,8:X-} flags", uint32_t(Header.Characteristics));
+    AutoIndent IndentMore(P, 9);
+    P.formatLine("{0}", formatSectionCharacteristics(
+                            P.getIndentLevel(), Header.Characteristics, 1, ""));
+    ++I;
+  }
+  return;
+}
+
 Error DumpOutputStyle::dumpSectionContribs() {
   printHeader(P, "Section Contributions");
   ExitOnError Err("Error dumping publics stream: ");
@@ -1078,7 +1158,7 @@
           fmtle(SC.DataCrc), fmtle(SC.RelocCrc));
       P.formatLine("      {0}",
                    formatSectionCharacteristics(P.getIndentLevel() + 6,
-                                                SC.Characteristics));
+                                                SC.Characteristics, 3, " | "));
     }
     void visit(const SectionContrib2 &SC) override {
       P.formatLine("SC2 | mod = {2}, {0}, size = {1}, data crc = {3}, reloc "
@@ -1087,9 +1167,9 @@
                    fmtle(SC.Base.Size), fmtle(SC.Base.Imod),
                    fmtle(SC.Base.DataCrc), fmtle(SC.Base.RelocCrc),
                    fmtle(SC.ISectCoff));
-      P.formatLine("      {0}",
-                   formatSectionCharacteristics(P.getIndentLevel() + 6,
-                                                SC.Base.Characteristics));
+      P.formatLine("      {0}", formatSectionCharacteristics(
+                                    P.getIndentLevel() + 6,
+                                    SC.Base.Characteristics, 3, " | "));
     }
 
   private:
@@ -1117,7 +1197,7 @@
   uint32_t I = 0;
   for (auto &M : Dbi.getSectionMap()) {
     P.formatLine(
-        "Section {0:4} | ovl = {0}, group = {1}, frame = {2}, name = {3}", I,
+        "Section {0:4} | ovl = {1}, group = {2}, frame = {3}, name = {4}", I,
         fmtle(M.Ovl), fmtle(M.Group), fmtle(M.Frame), fmtle(M.SecName));
     P.formatLine("               class = {0}, offset = {1}, size = {2}",
                  fmtle(M.ClassName), fmtle(M.Offset), fmtle(M.SecByteLength));
Index: llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.h
===================================================================
--- llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.h
+++ llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.h
@@ -139,6 +139,7 @@
 extern llvm::cl::opt<bool> DumpTypeExtras;
 extern llvm::cl::list<uint32_t> DumpTypeIndex;
 extern llvm::cl::opt<bool> DumpTypeDependents;
+extern llvm::cl::opt<bool> DumpSectionHeaders;
 
 extern llvm::cl::opt<bool> DumpIds;
 extern llvm::cl::opt<bool> DumpIdData;
Index: llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.cpp
===================================================================
--- llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.cpp
+++ llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.cpp
@@ -518,6 +518,9 @@
                                   cl::sub(DumpSubcommand));
 cl::opt<bool> DumpSectionMap("section-map", cl::desc("dump section map"),
                              cl::cat(MiscOptions), cl::sub(DumpSubcommand));
+cl::opt<bool> DumpSectionHeaders("section-headers",
+                                 cl::desc("Dump image section headers"),
+                                 cl::cat(MiscOptions), cl::sub(DumpSubcommand));
 
 cl::opt<bool> RawAll("all", cl::desc("Implies most other options."),
                      cl::cat(MiscOptions), cl::sub(DumpSubcommand));
@@ -1092,6 +1095,7 @@
       opts::dump::DumpStreams = true;
       opts::dump::DumpStreamBlocks = true;
       opts::dump::DumpStringTable = true;
+      opts::dump::DumpSectionHeaders = true;
       opts::dump::DumpSummary = true;
       opts::dump::DumpSymbols = true;
       opts::dump::DumpIds = true;