Index: lldb/lit/SymbolFile/NativePDB/Inputs/simple-breakpoints.lldbinit
===================================================================
--- /dev/null
+++ lldb/lit/SymbolFile/NativePDB/Inputs/simple-breakpoints.lldbinit
@@ -0,0 +1,2 @@
+break set -n main
+quit
Index: lldb/lit/SymbolFile/NativePDB/simple-breakpoints.cpp
===================================================================
--- /dev/null
+++ lldb/lit/SymbolFile/NativePDB/simple-breakpoints.cpp
@@ -0,0 +1,16 @@
+// clang-format off
+
+// Test that we can set simple breakpoints using PDB on any platform.
+// RUN: clang-cl /Z7 /GS- /GR- /c %s /Fo%t.obj
+// RUN: lld-link /DEBUG /nodefaultlib /entry:main /OUT:%t.exe /PDB:%t.pdb %t.obj
+// RUN: env LLDB_USE_NATIVE_PDB_READER=1 lldb -f %t.exe -s \
+// RUN:     %p/Inputs/simple-breakpoints.lldbinit | FileCheck %s
+
+// CHECK: (lldb) target create "{{.*}}simple-breakpoints.cpp.tmp.exe"
+// CHECK: Current executable set to '{{.*}}simple-breakpoints.cpp.tmp.exe' (x86_64).
+// CHECK: (lldb) break set -n main
+// CHECK: Breakpoint 1: where = simple-breakpoints.cpp.tmp.exe`main + 23 at simple-breakpoints.cpp:15, address = 0x0000000140001017
+
+int main(int argc, char **argv) {
+  return 0;
+}
Index: lldb/lit/lit.cfg
===================================================================
--- lldb/lit/lit.cfg
+++ lldb/lit/lit.cfg
@@ -64,6 +64,8 @@
                                config.test_source_root)
 
 lldbmi = lit.util.which('lldb-mi', lldb_tools_dir)
+if lldbmi:
+    config.available_features.add('lldb-mi')
 
 if not os.path.exists(config.cc):
     config.cc = lit.util.which(config.cc, config.environment['PATH'])
@@ -90,7 +92,8 @@
 config.substitutions.append(('%cc', config.cc))
 config.substitutions.append(('%cxx', config.cxx))
 
-config.substitutions.append(('%lldbmi', lldbmi + " --synchronous"))
+if lldbmi:
+  config.substitutions.append(('%lldbmi', lldbmi + " --synchronous"))
 config.substitutions.append(('%lldb', lldb))
 
 if debugserver is not None:
Index: lldb/source/Plugins/SymbolFile/CMakeLists.txt
===================================================================
--- lldb/source/Plugins/SymbolFile/CMakeLists.txt
+++ lldb/source/Plugins/SymbolFile/CMakeLists.txt
@@ -1,3 +1,4 @@
 add_subdirectory(DWARF)
 add_subdirectory(Symtab)
+add_subdirectory(NativePDB)
 add_subdirectory(PDB)
Index: lldb/source/Plugins/SymbolFile/NativePDB/CMakeLists.txt
===================================================================
--- /dev/null
+++ lldb/source/Plugins/SymbolFile/NativePDB/CMakeLists.txt
@@ -0,0 +1,16 @@
+add_lldb_library(lldbPluginSymbolFileNativePDB PLUGIN
+  CompileUnitIndex.cpp
+  PdbIndex.cpp
+  PdbUtil.cpp
+  SymbolFileNativePDB.cpp
+
+  LINK_LIBS
+    clangAST
+    clangLex
+    lldbCore
+    lldbSymbol
+	lldbUtility
+  LINK_COMPONENTS
+    DebugInfoPDB
+    Support
+  )
Index: lldb/source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.h
===================================================================
--- /dev/null
+++ lldb/source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.h
@@ -0,0 +1,93 @@
+//===-- CompileUnitIndex.h --------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_PLUGINS_SYMBOLFILENATIVEPDB_COMPILEUNITINDEX_H
+#define LLDB_PLUGINS_SYMBOLFILENATIVEPDB_COMPILEUNITINDEX_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/IntervalMap.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/DebugInfo/CodeView/StringsAndChecksums.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/CodeView/TypeIndex.h"
+#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h"
+#include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h"
+#include "llvm/DebugInfo/PDB/PDBTypes.h"
+
+#include "PdbSymUid.h"
+
+#include <map>
+#include <memory>
+
+namespace lldb_private {
+
+namespace npdb {
+class PdbIndex;
+
+struct CompilandIndexItem {
+  CompilandIndexItem(PdbSymUid uid,
+                     llvm::pdb::ModuleDebugStreamRef debug_stream,
+                     llvm::pdb::DbiModuleDescriptor descriptor);
+
+  // uid of this compile unit.
+  PdbSymUid m_uid;
+
+  // debug stream.
+  llvm::pdb::ModuleDebugStreamRef m_debug_stream;
+
+  // dbi module descriptor.
+  llvm::pdb::DbiModuleDescriptor m_module_descriptor;
+
+  llvm::codeview::StringsAndChecksumsRef m_strings;
+
+  // List of files which contribute to this compiland.
+  std::vector<llvm::StringRef> m_file_list;
+
+  // Maps virtual address to global symbol id, which can then be used to
+  // locate the exact compile unit and offset of the symbol.  Note that this
+  // is intentionally an ordered map so that we can find all symbols up to a
+  // given starting address.
+  std::map<lldb::addr_t, PdbSymUid> m_symbols_by_va;
+
+  // S_COMPILE3 sym describing compilation settings for the module.
+  llvm::Optional<llvm::codeview::Compile3Sym> m_compile_opts;
+
+  // S_OBJNAME sym describing object name.
+  llvm::Optional<llvm::codeview::ObjNameSym> m_obj_name;
+
+  // LF_BUILDINFO sym describing source file name, working directory,
+  // command line, etc.  This usually contains exactly 5 items which
+  // are references to other strings.
+  llvm::SmallVector<llvm::codeview::TypeIndex, 5> m_build_info;
+};
+
+class CompileUnitIndex {
+  PdbIndex &m_index;
+  llvm::DenseMap<lldb::user_id_t, std::unique_ptr<CompilandIndexItem>>
+      m_comp_units;
+
+public:
+  explicit CompileUnitIndex(PdbIndex &index) : m_index(index) {}
+
+  CompilandIndexItem &GetOrCreateCompiland(uint16_t modi);
+  CompilandIndexItem &GetOrCreateCompiland(PdbSymUid compiland_uid);
+
+  const CompilandIndexItem *GetCompiland(uint16_t modi) const;
+  const CompilandIndexItem *GetCompiland(PdbSymUid compiland_uid) const;
+
+  CompilandIndexItem *GetCompiland(uint16_t modi);
+  CompilandIndexItem *GetCompiland(PdbSymUid compiland_uid);
+
+  llvm::SmallString<64> GetMainSourceFile(const CompilandIndexItem &item) const;
+};
+} // namespace npdb
+} // namespace lldb_private
+
+#endif
Index: lldb/source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.cpp
===================================================================
--- /dev/null
+++ lldb/source/Plugins/SymbolFile/NativePDB/CompileUnitIndex.cpp
@@ -0,0 +1,224 @@
+//===-- CompileUnitIndex.cpp ------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CompileUnitIndex.h"
+
+#include "PdbIndex.h"
+#include "PdbUtil.h"
+
+#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
+#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
+#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
+#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
+#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h"
+#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
+#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
+#include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h"
+#include "llvm/DebugInfo/PDB/Native/NamedStreamMap.h"
+#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
+#include "llvm/Support/Path.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::npdb;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+static bool IsMainFile(llvm::StringRef main, llvm::StringRef other) {
+  if (main == other)
+    return true;
+
+  // If the files refer to the local file system, we can just ask the file
+  // system if they're equivalent.  But if the source isn't present on disk
+  // then we still want to try.
+  if (llvm::sys::fs::equivalent(main, other))
+    return true;
+
+  // FIXME: If we ever want to support PDB debug info for non-Windows systems
+  // the following check will be wrong, but we need a way to store the host
+  // information in the PDB.
+  llvm::SmallString<64> normalized(other);
+  llvm::sys::path::native(normalized, llvm::sys::path::Style::windows);
+  return main.equals_lower(normalized);
+}
+
+static void ParseCompile3(const CVSymbol &sym, CompilandIndexItem &cci) {
+  cci.m_compile_opts.emplace();
+  llvm::cantFail(
+      SymbolDeserializer::deserializeAs<Compile3Sym>(sym, *cci.m_compile_opts));
+}
+
+static void ParseObjname(const CVSymbol &sym, CompilandIndexItem &cci) {
+  cci.m_obj_name.emplace();
+  llvm::cantFail(
+      SymbolDeserializer::deserializeAs<ObjNameSym>(sym, *cci.m_obj_name));
+}
+
+static void ParseBuildInfo(PdbIndex &index, const CVSymbol &sym,
+                           CompilandIndexItem &cci) {
+  BuildInfoSym bis(SymbolRecordKind::BuildInfoSym);
+  llvm::cantFail(SymbolDeserializer::deserializeAs<BuildInfoSym>(sym, bis));
+
+  // S_BUILDINFO just points to an LF_BUILDINFO in the IPI stream.  Let's do
+  // a little extra work to pull out the LF_BUILDINFO.
+  LazyRandomTypeCollection &types = index.ipi().typeCollection();
+  llvm::Optional<CVType> cvt = types.tryGetType(bis.BuildId);
+
+  if (!cvt || cvt->kind() != LF_BUILDINFO)
+    return;
+
+  BuildInfoRecord bir;
+  llvm::cantFail(TypeDeserializer::deserializeAs<BuildInfoRecord>(*cvt, bir));
+  cci.m_build_info.assign(bir.ArgIndices.begin(), bir.ArgIndices.end());
+}
+
+static void ParseExtendedInfo(PdbIndex &index, CompilandIndexItem &item) {
+  const CVSymbolArray &syms = item.m_debug_stream.getSymbolArray();
+
+  if (item.m_obj_name && item.m_compile_opts)
+    return;
+
+  // We're looking for 3 things.  S_COMPILE3, S_OBJNAME, and S_BUILDINFO.
+  int found = 0;
+  for (const CVSymbol &sym : syms) {
+    switch (sym.kind()) {
+    case S_COMPILE3:
+      ParseCompile3(sym, item);
+      break;
+    case S_OBJNAME:
+      ParseObjname(sym, item);
+      break;
+    case S_BUILDINFO:
+      ParseBuildInfo(index, sym, item);
+      break;
+    default:
+      continue;
+    }
+    if (++found >= 3)
+      break;
+  }
+}
+
+CompilandIndexItem::CompilandIndexItem(
+    PdbSymUid uid, llvm::pdb::ModuleDebugStreamRef debug_stream,
+    llvm::pdb::DbiModuleDescriptor descriptor)
+    : m_uid(uid), m_debug_stream(std::move(debug_stream)),
+      m_module_descriptor(std::move(descriptor)) {}
+
+CompilandIndexItem &CompileUnitIndex::GetOrCreateCompiland(uint16_t modi) {
+  PdbSymUid uid = PdbSymUid::makeCompilandId(modi);
+  return GetOrCreateCompiland(uid);
+}
+
+CompilandIndexItem &
+CompileUnitIndex::GetOrCreateCompiland(PdbSymUid compiland_uid) {
+  auto result = m_comp_units.try_emplace(compiland_uid.toOpaqueId(), nullptr);
+  if (!result.second)
+    return *result.first->second;
+
+  // Find the module list and load its debug information stream and cache it
+  // since we need to use it for almost all interesting operations.
+  const DbiModuleList &modules = m_index.dbi().modules();
+  uint16_t modi = compiland_uid.asCompiland().modi;
+  llvm::pdb::DbiModuleDescriptor descriptor = modules.getModuleDescriptor(modi);
+  uint16_t stream = descriptor.getModuleStreamIndex();
+  std::unique_ptr<llvm::msf::MappedBlockStream> stream_data =
+      m_index.pdb().createIndexedStream(stream);
+  llvm::pdb::ModuleDebugStreamRef debug_stream(descriptor,
+                                               std::move(stream_data));
+  cantFail(debug_stream.reload());
+
+  std::unique_ptr<CompilandIndexItem> &cci = result.first->second;
+
+  cci = llvm::make_unique<CompilandIndexItem>(
+      compiland_uid, std::move(debug_stream), std::move(descriptor));
+  ParseExtendedInfo(m_index, *cci);
+
+  cci->m_strings.initialize(debug_stream.getSubsectionsArray());
+  PDBStringTable &strings = cantFail(m_index.pdb().getStringTable());
+  cci->m_strings.setStrings(strings.getStringTable());
+
+  // We want the main source file to always comes first.  Note that we can't
+  // just push_back the main file onto the front because `GetMainSourceFile`
+  // computes it in such a way that it doesn't own the resulting memory.  So we
+  // have to iterate the module file list comparing each one to the main file
+  // name until we find it, and we can cache that one since the memory is backed
+  // by a contiguous chunk inside the mapped PDB.
+  llvm::SmallString<64> main_file = GetMainSourceFile(*cci);
+  llvm::sys::path::native(main_file, llvm::sys::path::Style::windows);
+
+  uint32_t file_count = modules.getSourceFileCount(modi);
+  cci->m_file_list.reserve(file_count);
+  bool found_main_file = false;
+  for (llvm::StringRef file : modules.source_files(modi)) {
+    if (!found_main_file && IsMainFile(main_file, file)) {
+      cci->m_file_list.insert(cci->m_file_list.begin(), file);
+      found_main_file = true;
+      continue;
+    }
+    cci->m_file_list.push_back(file);
+  }
+
+  return *cci;
+}
+
+const CompilandIndexItem *CompileUnitIndex::GetCompiland(uint16_t modi) const {
+  return GetCompiland(PdbSymUid::makeCompilandId(modi));
+}
+
+const CompilandIndexItem *
+CompileUnitIndex::GetCompiland(PdbSymUid compiland_uid) const {
+  auto iter = m_comp_units.find(compiland_uid.toOpaqueId());
+  if (iter == m_comp_units.end())
+    return nullptr;
+  return iter->second.get();
+}
+
+CompilandIndexItem *CompileUnitIndex::GetCompiland(uint16_t modi) {
+  return GetCompiland(PdbSymUid::makeCompilandId(modi));
+}
+
+CompilandIndexItem *CompileUnitIndex::GetCompiland(PdbSymUid compiland_uid) {
+  auto iter = m_comp_units.find(compiland_uid.toOpaqueId());
+  if (iter == m_comp_units.end())
+    return nullptr;
+  return iter->second.get();
+}
+
+llvm::SmallString<64>
+CompileUnitIndex::GetMainSourceFile(const CompilandIndexItem &item) const {
+  // LF_BUILDINFO contains a list of arg indices which point to LF_STRING_ID
+  // records in the IPI stream.  The order of the arg indices is as follows:
+  // [0] - working directory where compiler was invoked.
+  // [1] - absolute path to compiler binary
+  // [2] - source file name
+  // [3] - path to compiler generated PDB (the /Zi PDB, although this entry gets
+  //       added even when using /Z7)
+  // [4] - full command line invocation.
+  //
+  // We need to form the path [0]\[2] to generate the full path to the main
+  // file.source
+  if (item.m_build_info.size() < 3)
+    return {""};
+
+  LazyRandomTypeCollection &types = m_index.ipi().typeCollection();
+
+  StringIdRecord working_dir;
+  StringIdRecord file_name;
+  CVType dir_cvt = types.getType(item.m_build_info[0]);
+  CVType file_cvt = types.getType(item.m_build_info[2]);
+  llvm::cantFail(
+      TypeDeserializer::deserializeAs<StringIdRecord>(dir_cvt, working_dir));
+  llvm::cantFail(
+      TypeDeserializer::deserializeAs<StringIdRecord>(file_cvt, file_name));
+
+  llvm::SmallString<64> absolute_path = working_dir.String;
+  llvm::sys::path::append(absolute_path, file_name.String);
+  return absolute_path;
+}
Index: lldb/source/Plugins/SymbolFile/NativePDB/PdbIndex.h
===================================================================
--- /dev/null
+++ lldb/source/Plugins/SymbolFile/NativePDB/PdbIndex.h
@@ -0,0 +1,156 @@
+//===-- PdbIndex.h ----------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_PLUGINS_SYMBOLFILENATIVEPDB_PDBINDEX_H
+#define LLDB_PLUGINS_SYMBOLFILENATIVEPDB_PDBINDEX_H
+
+#include "lldb/lldb-types.h"
+#include "llvm/ADT/IntervalMap.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
+#include "llvm/DebugInfo/PDB/PDBTypes.h"
+
+#include "CompileUnitIndex.h"
+#include "PdbSymUid.h"
+
+#include <map>
+#include <memory>
+
+namespace llvm {
+namespace pdb {
+class DbiStream;
+class TpiStream;
+class TpiStream;
+class InfoStream;
+class PublicsStream;
+class GlobalsStream;
+class SymbolStream;
+} // namespace pdb
+} // namespace llvm
+
+namespace lldb_private {
+namespace npdb {
+
+/// PdbIndex - Lazy access to the important parts of a PDB file.
+///
+/// This is a layer on top of LLVM's native PDB support libraries which cache
+/// certain data when it is accessed the first time.  The entire PDB file is
+/// mapped into memory, and the underlying support libraries vend out memory
+/// that is always backed by the file, so it is safe to hold StringRefs and
+/// ArrayRefs into the backing memory as long as the PdbIndex instance is
+/// alive.
+class PdbIndex {
+
+  /// The underlying PDB file.
+  std::unique_ptr<llvm::pdb::PDBFile> m_file;
+
+  /// The DBI stream.  This contains general high level information about the
+  /// features present in the PDB file, compile units (such as the information
+  /// necessary to locate full symbol information for each compile unit),
+  /// section contributions, and other data which is not specifically symbol or
+  /// type records.
+  llvm::pdb::DbiStream *m_dbi;
+
+  /// TPI (types) and IPI (indices) streams.  These are both in the exact same
+  /// format with different data.  Most type records are stored in the TPI
+  /// stream but certain specific types of records are stored in the IPI stream.
+  /// The IPI stream records can refer to the records in the TPI stream, but not
+  /// the other way around.
+  llvm::pdb::TpiStream *m_tpi;
+  llvm::pdb::TpiStream *m_ipi;
+
+  /// This is called the "PDB Stream" in the Microsoft reference implementation.
+  /// It contains information about the structure of the file, as well as fields
+  /// used to match EXE and PDB.
+  llvm::pdb::InfoStream *m_info;
+
+  /// Publics stream.  Is actually a serialized hash table where the keys are
+  /// addresses of symbols in the executable, and values are a record containing
+  /// mangled names and an index which can be used to locate more detailed info
+  /// about the symbol in the Symbol Records stream.  The publics stream only
+  /// contains info about externally visible symbols.
+  llvm::pdb::PublicsStream *m_publics;
+
+  /// Globals stream.  Contrary to its name, this does not contain information
+  /// about all "global variables" or "global functions".  Rather, it is the
+  /// "global symbol table", i.e. it contains information about *every* symbol
+  /// in the executable.  It is a hash table keyed on name, whose values are
+  /// indices into the symbol records stream to find the full record.
+  llvm::pdb::GlobalsStream *m_globals;
+
+  /// Symbol records stream.  The publics and globals stream refer to records
+  /// in this stream.  For some records, like constants and typedefs, the
+  /// complete record lives in this stream.  For other symbol types, such as
+  /// functions, data, and other things that have been materialied into a
+  /// specific compile unit, the records here simply provide a reference
+  /// necessary to locate the full information.
+  llvm::pdb::SymbolStream *m_symrecords;
+
+  CompileUnitIndex m_cus;
+
+  /// An allocator for the interval maps
+  llvm::IntervalMap<lldb::addr_t, uint32_t>::Allocator m_allocator;
+
+  /// Maps virtual address to module index
+  llvm::IntervalMap<lldb::addr_t, uint16_t> m_va_to_modi;
+
+  /// The address at which the program has been loaded into memory.
+  lldb::addr_t m_load_address = 0;
+
+  PdbIndex();
+
+  void BuildAddrToSymbolMap(CompilandIndexItem &cci);
+
+public:
+  static std::unique_ptr<PdbIndex> create(std::unique_ptr<llvm::pdb::PDBFile>);
+
+  void SetLoadAddress(lldb::addr_t addr) { m_load_address = addr; }
+  void ParseSectionContribs();
+
+  llvm::pdb::PDBFile &pdb() { return *m_file; }
+  const llvm::pdb::PDBFile &pdb() const { return *m_file; }
+
+  llvm::pdb::DbiStream &dbi() { return *m_dbi; }
+  const llvm::pdb::DbiStream &dbi() const { return *m_dbi; }
+
+  llvm::pdb::TpiStream &tpi() { return *m_tpi; }
+  const llvm::pdb::TpiStream &tpi() const { return *m_tpi; }
+
+  llvm::pdb::TpiStream &ipi() { return *m_ipi; }
+  const llvm::pdb::TpiStream &ipi() const { return *m_ipi; }
+
+  llvm::pdb::InfoStream &info() { return *m_info; }
+  const llvm::pdb::InfoStream &info() const { return *m_info; }
+
+  llvm::pdb::PublicsStream &publics() { return *m_publics; }
+  const llvm::pdb::PublicsStream &publics() const { return *m_publics; }
+
+  llvm::pdb::GlobalsStream &globals() { return *m_globals; }
+  const llvm::pdb::GlobalsStream &globals() const { return *m_globals; }
+
+  llvm::pdb::SymbolStream &symrecords() { return *m_symrecords; }
+  const llvm::pdb::SymbolStream &symrecords() const { return *m_symrecords; }
+
+  CompileUnitIndex &compilands() { return m_cus; }
+  const CompileUnitIndex &compilands() const { return m_cus; }
+
+  lldb::addr_t MakeVirtualAddress(uint16_t segment, uint32_t offset) const;
+
+  std::vector<SymbolAndUid> FindSymbolsByVa(lldb::addr_t va);
+
+  llvm::codeview::CVSymbol ReadSymbolRecord(PdbCuSymId cu_sym) const;
+
+  llvm::Optional<uint16_t> GetModuleIndexForAddr(uint16_t segment,
+                                                 uint32_t offset) const;
+  llvm::Optional<uint16_t> GetModuleIndexForVa(lldb::addr_t va) const;
+};
+} // namespace npdb
+} // namespace lldb_private
+
+#endif
Index: lldb/source/Plugins/SymbolFile/NativePDB/PdbIndex.cpp
===================================================================
--- /dev/null
+++ lldb/source/Plugins/SymbolFile/NativePDB/PdbIndex.cpp
@@ -0,0 +1,220 @@
+//===-- PdbIndex.cpp --------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PdbIndex.h"
+#include "PdbUtil.h"
+
+#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
+#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
+#include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"
+#include "llvm/DebugInfo/PDB/Native/ISectionContribVisitor.h"
+#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
+#include "llvm/DebugInfo/PDB/Native/PublicsStream.h"
+#include "llvm/DebugInfo/PDB/Native/SymbolStream.h"
+#include "llvm/Object/COFF.h"
+#include "llvm/Support/Error.h"
+
+#include "lldb/lldb-defines.h"
+
+using namespace lldb_private;
+using namespace lldb_private::npdb;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+PdbIndex::PdbIndex() : m_cus(*this), m_va_to_modi(m_allocator) {}
+
+std::unique_ptr<PdbIndex>
+PdbIndex::create(std::unique_ptr<llvm::pdb::PDBFile> file) {
+  assert(file);
+  auto ExpectedDBI = file->getPDBDbiStream();
+  if (!ExpectedDBI) {
+    llvm::consumeError(ExpectedDBI.takeError());
+    return nullptr;
+  }
+
+  auto ExpectedTPI = file->getPDBTpiStream();
+  if (!ExpectedTPI) {
+    llvm::consumeError(ExpectedTPI.takeError());
+    return nullptr;
+  }
+
+  auto ExpectedIPI = file->getPDBIpiStream();
+  if (!ExpectedIPI) {
+    llvm::consumeError(ExpectedIPI.takeError());
+    return nullptr;
+  }
+
+  auto ExpectedPublics = file->getPDBPublicsStream();
+  if (!ExpectedPublics) {
+    llvm::consumeError(ExpectedPublics.takeError());
+    return nullptr;
+  }
+
+  auto ExpectedGlobals = file->getPDBGlobalsStream();
+  if (!ExpectedGlobals) {
+    llvm::consumeError(ExpectedGlobals.takeError());
+    return nullptr;
+  }
+
+  auto ExpectedSymRecords = file->getPDBSymbolStream();
+  if (!ExpectedSymRecords) {
+    llvm::consumeError(ExpectedSymRecords.takeError());
+    return nullptr;
+  }
+
+  auto ExpectedInfo = file->getPDBInfoStream();
+  if (!ExpectedInfo) {
+    llvm::consumeError(ExpectedInfo.takeError());
+    return nullptr;
+  }
+
+  std::unique_ptr<PdbIndex> result(new PdbIndex());
+  result->m_file = std::move(file);
+  result->m_dbi = &ExpectedDBI.get();
+  result->m_tpi = &ExpectedTPI.get();
+  result->m_ipi = &ExpectedIPI.get();
+  result->m_info = &ExpectedInfo.get();
+  result->m_publics = &ExpectedPublics.get();
+  result->m_globals = &ExpectedGlobals.get();
+  result->m_symrecords = &ExpectedSymRecords.get();
+
+  return std::move(result);
+}
+
+lldb::addr_t PdbIndex::MakeVirtualAddress(uint16_t segment,
+                                          uint32_t offset) const {
+  // Segment indices are 1-based.
+  assert(segment > 0);
+
+  uint32_t max_section = dbi().getSectionHeaders().size();
+  assert(segment <= max_section + 1);
+
+  // If this is an absolute symbol, it's indicated by the magic section index
+  // |max_section+1|.  In this case, the offset is meaningless, so just return.
+  if (segment == max_section + 1)
+    return LLDB_INVALID_ADDRESS;
+
+  const llvm::object::coff_section &cs = dbi().getSectionHeaders()[segment - 1];
+  return m_load_address + static_cast<lldb::addr_t>(cs.VirtualAddress) +
+         static_cast<lldb::addr_t>(offset);
+}
+
+llvm::Optional<uint16_t>
+PdbIndex::GetModuleIndexForAddr(uint16_t segment, uint32_t offset) const {
+  return GetModuleIndexForVa(MakeVirtualAddress(segment, offset));
+}
+
+llvm::Optional<uint16_t> PdbIndex::GetModuleIndexForVa(lldb::addr_t va) const {
+  auto iter = m_va_to_modi.find(va);
+  if (iter == m_va_to_modi.end())
+    return llvm::None;
+
+  return iter.value();
+}
+
+void PdbIndex::ParseSectionContribs() {
+  struct Visitor : public ISectionContribVisitor {
+    Visitor(PdbIndex &ctx, llvm::IntervalMap<uint64_t, uint16_t> &imap)
+        : m_ctx(ctx), m_imap(imap) {}
+
+    void visit(const SectionContrib &C) override {
+      uint64_t va = m_ctx.MakeVirtualAddress(C.ISect, C.Off);
+      uint64_t end = va + C.Size;
+      // IntervalMap's start and end represent a closed range, not a half-open
+      // range, so we have to subtract 1.
+      m_imap.insert(va, end - 1, C.Imod);
+    }
+    void visit(const SectionContrib2 &C) override { visit(C.Base); }
+
+    PdbIndex &m_ctx;
+    llvm::IntervalMap<uint64_t, uint16_t> &m_imap;
+  };
+  Visitor v(*this, m_va_to_modi);
+  dbi().visitSectionContributions(v);
+}
+
+void PdbIndex::BuildAddrToSymbolMap(CompilandIndexItem &cci) {
+  uint16_t modi = cci.m_uid.asCompiland().modi;
+  const CVSymbolArray &syms = cci.m_debug_stream.getSymbolArray();
+  for (auto iter = syms.begin(); iter != syms.end(); ++iter) {
+    if (!SymbolHasAddress(*iter))
+      continue;
+
+    uint16_t segment;
+    uint32_t offset;
+    std::tie(segment, offset) = GetSegmentAndOffset(*iter);
+    lldb::addr_t va = MakeVirtualAddress(segment, offset);
+    assert(cci.m_symbols_by_va.count(va) == 0);
+
+    // We need to add 4 here to adjust for the codeview debug magic
+    // at the beginning of the debug info stream.
+    uint32_t sym_offset = iter.offset() + 4;
+    PdbSymUid cu_sym_uid =
+        PdbSymUid::makeCuSymId(CVSymToPDBSym(iter->kind()), modi, sym_offset);
+    cci.m_symbols_by_va.insert(std::make_pair(va, cu_sym_uid));
+  }
+}
+
+std::vector<SymbolAndUid> PdbIndex::FindSymbolsByVa(lldb::addr_t va) {
+  std::vector<SymbolAndUid> result;
+
+  llvm::Optional<uint16_t> modi = GetModuleIndexForVa(va);
+  if (!modi)
+    return result;
+
+  CompilandIndexItem &cci = compilands().GetOrCreateCompiland(*modi);
+  if (cci.m_symbols_by_va.empty())
+    BuildAddrToSymbolMap(cci);
+
+  // The map is sorted by starting address of the symbol.  So for example
+  // we could (in theory) have this situation
+  //
+  // [------------------]
+  //    [----------]
+  //      [-----------]
+  //          [-------------]
+  //            [----]
+  //               [-----]
+  //             ^ Address we're searching for
+  // In order to find this, we use the upper_bound of the key value which would
+  // be the first symbol whose starting address is higher than the element we're
+  // searching for.
+
+  auto ub = cci.m_symbols_by_va.upper_bound(va);
+
+  for (auto iter = cci.m_symbols_by_va.begin(); iter != ub; ++iter) {
+    const PdbCuSymId &cu_sym_id = iter->second.asCuSym();
+    CVSymbol sym = ReadSymbolRecord(cu_sym_id);
+
+    uint16_t segment = 0;
+    uint32_t offset = 0;
+    uint32_t length = 0;
+    if (SymbolIsCode(sym))
+      std::tie(segment, offset, length) = GetSegmentOffsetAndLength(sym);
+    else
+      std::tie(segment, offset) = GetSegmentAndOffset(sym);
+
+    lldb::addr_t start = MakeVirtualAddress(segment, offset);
+    lldb::addr_t end = start + length;
+    if (va >= start && va < end)
+      result.push_back({std::move(sym), iter->second});
+  }
+
+  return result;
+}
+
+CVSymbol PdbIndex::ReadSymbolRecord(PdbCuSymId cu_sym) const {
+  // We need to subtract 4 here to adjust for the codeview debug magic
+  // at the beginning of the debug info stream.
+  PdbSymUid cuid = PdbSymUid::makeCompilandId(cu_sym.modi);
+  const CompilandIndexItem *cci = compilands().GetCompiland(cuid);
+  auto iter = cci->m_debug_stream.getSymbolArray().at(cu_sym.offset - 4);
+  assert(iter != cci->m_debug_stream.getSymbolArray().end());
+  return *iter;
+}
Index: lldb/source/Plugins/SymbolFile/NativePDB/PdbSymUid.h
===================================================================
--- /dev/null
+++ lldb/source/Plugins/SymbolFile/NativePDB/PdbSymUid.h
@@ -0,0 +1,200 @@
+//===-- PdbSymUid.h ---------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// A unique identification scheme for Pdb records.
+// The scheme is to partition a 64-bit integer into an 8-bit tag field, which
+// will contain some value from the PDB_SymType enumeration.  The format of the
+// other 48-bits depend on the tag, but must be sufficient to locate the
+// corresponding entry in the underlying PDB file quickly.  For example, for
+// a compile unit, we use 2 bytes to represent the index, which allows fast
+// access to the compile unit's information.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_PLUGINS_SYMBOLFILENATIVEPDB_PDBSYMUID_H
+#define LLDB_PLUGINS_SYMBOLFILENATIVEPDB_PDBSYMUID_H
+
+#include "lldb/lldb-types.h"
+#include "llvm/DebugInfo/PDB/PDBTypes.h"
+#include "llvm/Support/Compiler.h"
+
+namespace lldb_private {
+namespace npdb {
+
+// **important** - All concrete id types must have the 1-byte tag field at
+// the beginning so that the types are all layout-compatible with each
+// other, which is necessary in order to be able to safely access the tag
+// member through any union member.
+
+struct PdbCompilandId {
+  uint64_t tag : 8;   // PDB_SymType::Compiland
+  uint64_t modi : 16; // 0-based index of module in PDB
+  uint64_t unused : 32;
+};
+struct PdbCuSymId {
+  uint64_t tag : 8; // PDB_SymType::Data, Function, Block, etc.
+  uint64_t
+      offset : 32;    // Offset of symbol's record in module stream.  This is
+                      // offset by 4 from the CVSymbolArray's notion of offset
+                      // due to the debug magic at the beginning of the stream.
+  uint64_t modi : 16; // 0-based index of module in PDB
+};
+struct PdbTypeSymId {
+  uint64_t tag : 8;    // PDB_SymType::FunctionSig, Enum, PointerType, etc.
+  uint64_t is_ipi : 8; // 1 if this value is from the IPI stream, 0 for TPI.
+  uint64_t unused : 16;
+  uint64_t index : 32; // codeview::TypeIndex
+};
+
+static_assert(sizeof(PdbCompilandId) == 8, "invalid uid size");
+static_assert(sizeof(PdbCuSymId) == 8, "invalid uid size");
+static_assert(std::is_standard_layout<PdbCompilandId>::value,
+              "type is not standard layout!");
+static_assert(std::is_standard_layout<PdbCuSymId>::value,
+              "type is not standard layout!");
+
+class PdbSymUid {
+  union {
+    PdbCompilandId comp_id;
+    PdbCuSymId cu_sym;
+    PdbTypeSymId type_sym;
+  } m_uid;
+
+  PdbSymUid() { ::memset(&m_uid, 0, sizeof(m_uid)); }
+
+public:
+  static bool isTypeSym(llvm::pdb::PDB_SymType tag) {
+    switch (tag) {
+    case llvm::pdb::PDB_SymType::ArrayType:
+    case llvm::pdb::PDB_SymType::BaseClass:
+    case llvm::pdb::PDB_SymType::BaseInterface:
+    case llvm::pdb::PDB_SymType::BuiltinType:
+    case llvm::pdb::PDB_SymType::CustomType:
+    case llvm::pdb::PDB_SymType::Enum:
+    case llvm::pdb::PDB_SymType::FunctionArg:
+    case llvm::pdb::PDB_SymType::FunctionSig:
+    case llvm::pdb::PDB_SymType::Typedef:
+    case llvm::pdb::PDB_SymType::VectorType:
+    case llvm::pdb::PDB_SymType::VTableShape:
+    case llvm::pdb::PDB_SymType::PointerType:
+    case llvm::pdb::PDB_SymType::UDT:
+      return true;
+    default:
+      return false;
+    }
+  }
+
+  static bool isCuSym(llvm::pdb::PDB_SymType tag) {
+    switch (tag) {
+    case llvm::pdb::PDB_SymType::Block:
+    case llvm::pdb::PDB_SymType::Callee:
+    case llvm::pdb::PDB_SymType::Caller:
+    case llvm::pdb::PDB_SymType::CallSite:
+    case llvm::pdb::PDB_SymType::CoffGroup:
+    case llvm::pdb::PDB_SymType::CompilandDetails:
+    case llvm::pdb::PDB_SymType::CompilandEnv:
+    case llvm::pdb::PDB_SymType::Custom:
+    case llvm::pdb::PDB_SymType::Data:
+    case llvm::pdb::PDB_SymType::Function:
+    case llvm::pdb::PDB_SymType::Inlinee:
+    case llvm::pdb::PDB_SymType::InlineSite:
+    case llvm::pdb::PDB_SymType::Label:
+    case llvm::pdb::PDB_SymType::Thunk:
+      return true;
+    default:
+      return false;
+    }
+  }
+
+  static PdbSymUid makeCuSymId(llvm::codeview::ProcRefSym sym) {
+    return makeCuSymId(llvm::pdb::PDB_SymType::Function, sym.Module - 1,
+                       sym.SymOffset);
+  }
+
+  static PdbSymUid makeCuSymId(llvm::pdb::PDB_SymType type, uint16_t modi,
+                               uint32_t offset) {
+    assert(isCuSym(type));
+
+    PdbSymUid uid;
+    uid.m_uid.cu_sym.modi = modi;
+    uid.m_uid.cu_sym.offset = offset;
+    uid.m_uid.cu_sym.tag = static_cast<uint8_t>(type);
+    return uid;
+  }
+
+  static PdbSymUid makeCompilandId(llvm::codeview::ProcRefSym sym) {
+    // S_PROCREF symbols are 1-based
+    assert(sym.Module > 0);
+    return makeCompilandId(sym.Module - 1);
+  }
+
+  static PdbSymUid makeCompilandId(uint16_t modi) {
+    PdbSymUid uid;
+    uid.m_uid.comp_id.modi = modi;
+    uid.m_uid.cu_sym.tag =
+        static_cast<uint8_t>(llvm::pdb::PDB_SymType::Compiland);
+    return uid;
+  }
+
+  static PdbSymUid makeTypeSymId(llvm::pdb::PDB_SymType type,
+                                 llvm::codeview::TypeIndex index, bool is_ipi) {
+    assert(isTypeSym(type));
+
+    PdbSymUid uid;
+    uid.m_uid.type_sym.tag = static_cast<uint8_t>(type);
+    uid.m_uid.type_sym.index = index.getIndex();
+    uid.m_uid.type_sym.is_ipi = static_cast<uint8_t>(is_ipi);
+    return uid;
+  }
+
+  static PdbSymUid fromOpaqueId(uint64_t value) {
+    PdbSymUid result;
+    ::memcpy(&result.m_uid, &value, sizeof(value));
+    return result;
+  }
+
+  uint64_t toOpaqueId() const {
+    uint64_t result;
+    ::memcpy(&result, &m_uid, sizeof(m_uid));
+    return result;
+  }
+
+  bool isPubSym() const {
+    return tag() == llvm::pdb::PDB_SymType::PublicSymbol;
+  }
+  bool isCompiland() const {
+    return tag() == llvm::pdb::PDB_SymType::Compiland;
+  }
+
+  llvm::pdb::PDB_SymType tag() const {
+    return static_cast<llvm::pdb::PDB_SymType>(m_uid.comp_id.tag);
+  }
+
+  const PdbCompilandId &asCompiland() const {
+    assert(tag() == llvm::pdb::PDB_SymType::Compiland);
+    return m_uid.comp_id;
+  }
+
+  const PdbCuSymId &asCuSym() const {
+    assert(isCuSym(tag()));
+    return m_uid.cu_sym;
+  }
+
+  const PdbTypeSymId &asTypeSym() const {
+    assert(isTypeSym(tag()));
+    return m_uid.type_sym;
+  }
+};
+
+struct SymbolAndUid {
+  llvm::codeview::CVSymbol sym;
+  PdbSymUid uid;
+};
+} // namespace npdb
+} // namespace lldb_private
+
+#endif
Index: lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.h
===================================================================
--- /dev/null
+++ lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.h
@@ -0,0 +1,34 @@
+//===-- PdbUtil.h -----------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_PLUGINS_SYMBOLFILENATIVEPDB_PDBUTIL_H
+#define LLDB_PLUGINS_SYMBOLFILENATIVEPDB_PDBUTIL_H
+
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/PDB/PDBTypes.h"
+
+#include <tuple>
+#include <utility>
+
+namespace lldb_private {
+namespace npdb {
+llvm::pdb::PDB_SymType CVSymToPDBSym(llvm::codeview::SymbolKind kind);
+
+bool SymbolHasAddress(const llvm::codeview::CVSymbol &sym);
+bool SymbolIsCode(const llvm::codeview::CVSymbol &sym);
+
+std::pair<uint16_t, uint32_t>
+GetSegmentAndOffset(const llvm::codeview::CVSymbol &sym);
+std::tuple<uint16_t, uint32_t, uint32_t>
+GetSegmentOffsetAndLength(const llvm::codeview::CVSymbol &sym);
+
+} // namespace npdb
+} // namespace lldb_private
+
+#endif
Index: lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp
===================================================================
--- /dev/null
+++ lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp
@@ -0,0 +1,266 @@
+//===-- PdbUtil.cpp ---------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PdbUtil.h"
+
+#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
+
+using namespace lldb_private;
+using namespace lldb_private::npdb;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+llvm::pdb::PDB_SymType
+lldb_private::npdb::CVSymToPDBSym(llvm::codeview::SymbolKind kind) {
+  switch (kind) {
+  case S_COMPILE3:
+  case S_OBJNAME:
+    return PDB_SymType::CompilandDetails;
+  case S_ENVBLOCK:
+    return PDB_SymType::CompilandEnv;
+  case S_THUNK32:
+  case S_TRAMPOLINE:
+    return PDB_SymType::Thunk;
+  case S_COFFGROUP:
+    return PDB_SymType::CoffGroup;
+  case S_EXPORT:
+    return PDB_SymType::Export;
+  case S_LPROC32:
+  case S_GPROC32:
+  case S_LPROC32_DPC:
+    return PDB_SymType::Function;
+  case S_PUB32:
+    return PDB_SymType::PublicSymbol;
+  case S_INLINESITE:
+    return PDB_SymType::InlineSite;
+  case S_LOCAL:
+  case S_BPREL32:
+  case S_REGREL32:
+  case S_MANCONSTANT:
+  case S_CONSTANT:
+  case S_LDATA32:
+  case S_GDATA32:
+  case S_LMANDATA:
+  case S_GMANDATA:
+  case S_LTHREAD32:
+  case S_GTHREAD32:
+    return PDB_SymType::Data;
+  case S_BLOCK32:
+    return PDB_SymType::Block;
+  case S_LABEL32:
+    return PDB_SymType::Label;
+  case S_CALLSITEINFO:
+    return PDB_SymType::CallSite;
+  case S_HEAPALLOCSITE:
+    return PDB_SymType::HeapAllocationSite;
+  case S_CALLEES:
+    return PDB_SymType::Callee;
+  case S_CALLERS:
+    return PDB_SymType::Caller;
+  default:
+    assert(false && "Invalid symbol record kind!");
+  }
+  return PDB_SymType::None;
+}
+
+bool lldb_private::npdb::SymbolHasAddress(const llvm::codeview::CVSymbol &sym) {
+  switch (sym.kind()) {
+  case S_GPROC32:
+  case S_LPROC32:
+  case S_GPROC32_ID:
+  case S_LPROC32_ID:
+  case S_LPROC32_DPC:
+  case S_LPROC32_DPC_ID:
+  case S_THUNK32:
+  case S_TRAMPOLINE:
+  case S_COFFGROUP:
+  case S_BLOCK32:
+  case S_LABEL32:
+  case S_CALLSITEINFO:
+  case S_HEAPALLOCSITE:
+  case S_LDATA32:
+  case S_GDATA32:
+  case S_LMANDATA:
+  case S_GMANDATA:
+  case S_LTHREAD32:
+  case S_GTHREAD32:
+    return true;
+  default:
+    return false;
+  }
+}
+
+bool lldb_private::npdb::SymbolIsCode(const llvm::codeview::CVSymbol &sym) {
+  switch (sym.kind()) {
+  case S_GPROC32:
+  case S_LPROC32:
+  case S_GPROC32_ID:
+  case S_LPROC32_ID:
+  case S_LPROC32_DPC:
+  case S_LPROC32_DPC_ID:
+  case S_THUNK32:
+  case S_TRAMPOLINE:
+  case S_COFFGROUP:
+  case S_BLOCK32:
+    return true;
+  default:
+    return false;
+  }
+}
+
+template <typename RecordT> RecordT createRecord(const CVSymbol &sym) {
+  RecordT record(static_cast<SymbolRecordKind>(sym.kind()));
+  cantFail(SymbolDeserializer::deserializeAs<RecordT>(sym, record));
+  return record;
+}
+
+template <typename RecordT>
+static std::pair<uint16_t, uint32_t> GetSegmentAndOffset(const CVSymbol &sym) {
+  RecordT record = createRecord<RecordT>(sym);
+  return {record.Segment, record.CodeOffset};
+}
+
+template <>
+std::pair<uint16_t, uint32_t>
+GetSegmentAndOffset<TrampolineSym>(const CVSymbol &sym) {
+  TrampolineSym record = createRecord<TrampolineSym>(sym);
+  return {record.ThunkSection, record.ThunkOffset};
+}
+
+template <>
+std::pair<uint16_t, uint32_t>
+GetSegmentAndOffset<Thunk32Sym>(const CVSymbol &sym) {
+  Thunk32Sym record = createRecord<Thunk32Sym>(sym);
+  return {record.Segment, record.Offset};
+}
+
+template <>
+std::pair<uint16_t, uint32_t>
+GetSegmentAndOffset<CoffGroupSym>(const CVSymbol &sym) {
+  CoffGroupSym record = createRecord<CoffGroupSym>(sym);
+  return {record.Segment, record.Offset};
+}
+
+template <>
+std::pair<uint16_t, uint32_t>
+GetSegmentAndOffset<DataSym>(const CVSymbol &sym) {
+  DataSym record = createRecord<DataSym>(sym);
+  return {record.Segment, record.DataOffset};
+}
+
+template <>
+std::pair<uint16_t, uint32_t>
+GetSegmentAndOffset<ThreadLocalDataSym>(const CVSymbol &sym) {
+  ThreadLocalDataSym record = createRecord<ThreadLocalDataSym>(sym);
+  return {record.Segment, record.DataOffset};
+}
+
+std::pair<uint16_t, uint32_t>
+lldb_private::npdb::GetSegmentAndOffset(const llvm::codeview::CVSymbol &sym) {
+  switch (sym.kind()) {
+  case S_GPROC32:
+  case S_LPROC32:
+  case S_GPROC32_ID:
+  case S_LPROC32_ID:
+  case S_LPROC32_DPC:
+  case S_LPROC32_DPC_ID:
+    return ::GetSegmentAndOffset<ProcSym>(sym);
+  case S_THUNK32:
+    return ::GetSegmentAndOffset<Thunk32Sym>(sym);
+    break;
+  case S_TRAMPOLINE:
+    return ::GetSegmentAndOffset<TrampolineSym>(sym);
+    break;
+  case S_COFFGROUP:
+    return ::GetSegmentAndOffset<CoffGroupSym>(sym);
+    break;
+  case S_BLOCK32:
+    return ::GetSegmentAndOffset<BlockSym>(sym);
+    break;
+  case S_LABEL32:
+    return ::GetSegmentAndOffset<LabelSym>(sym);
+    break;
+  case S_CALLSITEINFO:
+    return ::GetSegmentAndOffset<CallSiteInfoSym>(sym);
+    break;
+  case S_HEAPALLOCSITE:
+    return ::GetSegmentAndOffset<HeapAllocationSiteSym>(sym);
+    break;
+  case S_LDATA32:
+  case S_GDATA32:
+  case S_LMANDATA:
+  case S_GMANDATA:
+    return ::GetSegmentAndOffset<DataSym>(sym);
+    break;
+  case S_LTHREAD32:
+  case S_GTHREAD32:
+    return ::GetSegmentAndOffset<ThreadLocalDataSym>(sym);
+    break;
+  default:
+    assert(false && "Record does not have a segment/offset!");
+  }
+  return {0, 0};
+}
+
+template <typename RecordT>
+static std::tuple<uint16_t, uint32_t, uint32_t>
+GetSegmentOffsetAndLength(const CVSymbol &sym) {
+  RecordT record = createRecord<RecordT>(sym);
+  return {record.Segment, record.CodeOffset, record.CodeSize};
+}
+
+template <>
+std::tuple<uint16_t, uint32_t, uint32_t>
+GetSegmentOffsetAndLength<TrampolineSym>(const CVSymbol &sym) {
+  TrampolineSym record = createRecord<TrampolineSym>(sym);
+  return {record.ThunkSection, record.ThunkOffset, record.Size};
+}
+
+template <>
+std::tuple<uint16_t, uint32_t, uint32_t>
+GetSegmentOffsetAndLength<Thunk32Sym>(const CVSymbol &sym) {
+  Thunk32Sym record = createRecord<Thunk32Sym>(sym);
+  return {record.Segment, record.Offset, record.Length};
+}
+
+template <>
+std::tuple<uint16_t, uint32_t, uint32_t>
+GetSegmentOffsetAndLength<CoffGroupSym>(const CVSymbol &sym) {
+  CoffGroupSym record = createRecord<CoffGroupSym>(sym);
+  return {record.Segment, record.Offset, record.Size};
+}
+
+std::tuple<uint16_t, uint32_t, uint32_t>
+lldb_private::npdb::GetSegmentOffsetAndLength(
+    const llvm::codeview::CVSymbol &sym) {
+  switch (sym.kind()) {
+  case S_GPROC32:
+  case S_LPROC32:
+  case S_GPROC32_ID:
+  case S_LPROC32_ID:
+  case S_LPROC32_DPC:
+  case S_LPROC32_DPC_ID:
+    return ::GetSegmentOffsetAndLength<ProcSym>(sym);
+  case S_THUNK32:
+    return ::GetSegmentOffsetAndLength<Thunk32Sym>(sym);
+    break;
+  case S_TRAMPOLINE:
+    return ::GetSegmentOffsetAndLength<TrampolineSym>(sym);
+    break;
+  case S_COFFGROUP:
+    return ::GetSegmentOffsetAndLength<CoffGroupSym>(sym);
+    break;
+  case S_BLOCK32:
+    return ::GetSegmentOffsetAndLength<BlockSym>(sym);
+    break;
+  default:
+    assert(false && "Record does not have a segment/offset/length triple!");
+  }
+  return {0, 0, 0};
+}
Index: lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
===================================================================
--- /dev/null
+++ lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
@@ -0,0 +1,181 @@
+//===-- SymbolFileNativePDB.h -----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef lldb_Plugins_SymbolFile_PDB_SymbolFileNativePDB_h_
+#define lldb_Plugins_SymbolFile_PDB_SymbolFileNativePDB_h_
+
+#include "lldb/Core/UniqueCStringMap.h"
+#include "lldb/Symbol/SymbolFile.h"
+#include "lldb/Symbol/VariableList.h"
+#include "lldb/Utility/UserID.h"
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/DebugInfo/CodeView/CVRecord.h"
+#include "llvm/DebugInfo/CodeView/StringsAndChecksums.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h"
+#include "llvm/DebugInfo/PDB/PDBTypes.h"
+
+#include "CompileUnitIndex.h"
+#include "PdbIndex.h"
+
+#include <unordered_map>
+
+namespace llvm {
+namespace pdb {
+class PDBFile;
+class PDBSymbol;
+class PDBSymbolCompiland;
+class PDBSymbolData;
+class PDBSymbolFunc;
+
+class DbiStream;
+class TpiStream;
+class TpiStream;
+class InfoStream;
+class PublicsStream;
+class GlobalsStream;
+class SymbolStream;
+class ModuleDebugStreamRef;
+} // namespace pdb
+} // namespace llvm
+
+namespace lldb_private {
+namespace npdb {
+
+class SymbolFileNativePDB : public lldb_private::SymbolFile {
+public:
+  //------------------------------------------------------------------
+  // Static Functions
+  //------------------------------------------------------------------
+  static void Initialize();
+
+  static void Terminate();
+
+  static void DebuggerInitialize(lldb_private::Debugger &debugger);
+
+  static lldb_private::ConstString GetPluginNameStatic();
+
+  static const char *GetPluginDescriptionStatic();
+
+  static lldb_private::SymbolFile *
+  CreateInstance(lldb_private::ObjectFile *obj_file);
+
+  //------------------------------------------------------------------
+  // Constructors and Destructors
+  //------------------------------------------------------------------
+  SymbolFileNativePDB(lldb_private::ObjectFile *ofile);
+
+  ~SymbolFileNativePDB() override;
+
+  uint32_t CalculateAbilities() override;
+
+  void InitializeObject() override;
+
+  //------------------------------------------------------------------
+  // Compile Unit function calls
+  //------------------------------------------------------------------
+
+  uint32_t GetNumCompileUnits() override;
+
+  lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) override;
+
+  lldb::LanguageType
+  ParseCompileUnitLanguage(const lldb_private::SymbolContext &sc) override;
+
+  size_t
+  ParseCompileUnitFunctions(const lldb_private::SymbolContext &sc) override;
+
+  bool
+  ParseCompileUnitLineTable(const lldb_private::SymbolContext &sc) override;
+
+  bool
+  ParseCompileUnitDebugMacros(const lldb_private::SymbolContext &sc) override;
+
+  bool ParseCompileUnitSupportFiles(
+      const lldb_private::SymbolContext &sc,
+      lldb_private::FileSpecList &support_files) override;
+
+  bool ParseImportedModules(
+      const lldb_private::SymbolContext &sc,
+      std::vector<lldb_private::ConstString> &imported_modules) override;
+
+  size_t ParseFunctionBlocks(const lldb_private::SymbolContext &sc) override;
+
+  size_t ParseTypes(const lldb_private::SymbolContext &sc) override {
+    return 0;
+  }
+  size_t
+  ParseVariablesForContext(const lldb_private::SymbolContext &sc) override {
+    return 0;
+  }
+  lldb_private::Type *ResolveTypeUID(lldb::user_id_t type_uid) override {
+    return nullptr;
+  }
+  bool CompleteType(lldb_private::CompilerType &compiler_type) override {
+    return false;
+  }
+  uint32_t ResolveSymbolContext(const lldb_private::Address &so_addr,
+                                uint32_t resolve_scope,
+                                lldb_private::SymbolContext &sc) override;
+
+  virtual size_t GetTypes(lldb_private::SymbolContextScope *sc_scope,
+                          uint32_t type_mask,
+                          lldb_private::TypeList &type_list) override {
+    return 0;
+  }
+
+  uint32_t
+  FindFunctions(const lldb_private::ConstString &name,
+                const lldb_private::CompilerDeclContext *parent_decl_ctx,
+                uint32_t name_type_mask, bool include_inlines, bool append,
+                lldb_private::SymbolContextList &sc_list) override;
+
+  uint32_t FindFunctions(const lldb_private::RegularExpression &regex,
+                         bool include_inlines, bool append,
+                         lldb_private::SymbolContextList &sc_list) override;
+
+  lldb_private::TypeSystem *
+  GetTypeSystemForLanguage(lldb::LanguageType language) override;
+
+  lldb_private::CompilerDeclContext FindNamespace(
+      const lldb_private::SymbolContext &sc,
+      const lldb_private::ConstString &name,
+      const lldb_private::CompilerDeclContext *parent_decl_ctx) override;
+
+  lldb_private::ConstString GetPluginName() override;
+
+  uint32_t GetPluginVersion() override;
+
+  llvm::pdb::PDBFile &GetPDBFile() { return m_index->pdb(); }
+  const llvm::pdb::PDBFile &GetPDBFile() const { return m_index->pdb(); }
+
+private:
+  lldb::FunctionSP GetOrCreateFunction(PdbSymUid func_uid,
+                                       const SymbolContext &sc);
+  lldb::CompUnitSP GetOrCreateCompileUnit(const CompilandIndexItem &cci);
+
+  lldb::FunctionSP CreateFunction(PdbSymUid func_uid, const SymbolContext &sc);
+  lldb::CompUnitSP CreateCompileUnit(const CompilandIndexItem &cci);
+
+  llvm::BumpPtrAllocator m_allocator;
+
+  lldb::addr_t m_obj_load_address = 0;
+
+  std::unique_ptr<PdbIndex> m_index;
+
+  llvm::DenseMap<lldb::user_id_t, lldb::FunctionSP> m_functions;
+  llvm::DenseMap<lldb::user_id_t, lldb::CompUnitSP> m_compilands;
+};
+
+} // namespace npdb
+} // namespace lldb_private
+
+#endif // lldb_Plugins_SymbolFile_PDB_SymbolFilePDB_h_
Index: lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
===================================================================
--- /dev/null
+++ lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
@@ -0,0 +1,616 @@
+//===-- SymbolFileNativePDB.cpp ---------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SymbolFileNativePDB.h"
+
+#include "clang/Lex/Lexer.h"
+
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/CompileUnit.h"
+#include "lldb/Symbol/LineTable.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Symbol/SymbolVendor.h"
+#include "lldb/Symbol/TypeList.h"
+#include "lldb/Symbol/TypeMap.h"
+#include "lldb/Symbol/Variable.h"
+#include "lldb/Utility/RegularExpression.h"
+
+#include "llvm/ADT/IntervalMap.h"
+#include "llvm/DebugInfo/CodeView/CVRecord.h"
+#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
+#include "llvm/DebugInfo/CodeView/RecordName.h"
+#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
+#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
+#include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"
+#include "llvm/DebugInfo/PDB/Native/ISectionContribVisitor.h"
+#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
+#include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h"
+#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
+#include "llvm/DebugInfo/PDB/Native/PublicsStream.h"
+#include "llvm/DebugInfo/PDB/Native/SymbolStream.h"
+#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
+#include "llvm/DebugInfo/PDB/PDBTypes.h"
+#include "llvm/Object/COFF.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/BinaryByteStream.h"
+#include "llvm/Support/BinaryStreamReader.h"
+#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/MemoryBuffer.h"
+
+#include "PdbSymUid.h"
+#include "PdbUtil.h"
+#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h" // For IsCPPMangledName
+
+#include <regex>
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::npdb;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+static lldb::LanguageType TranslateLanguage(PDB_Lang lang) {
+  switch (lang) {
+  case PDB_Lang::Cpp:
+    return lldb::LanguageType::eLanguageTypeC_plus_plus;
+  case PDB_Lang::C:
+    return lldb::LanguageType::eLanguageTypeC;
+  default:
+    return lldb::LanguageType::eLanguageTypeUnknown;
+  }
+}
+
+static std::unique_ptr<PDBFile> loadPDBFile(std::string PdbPath,
+                                            llvm::BumpPtrAllocator &Allocator) {
+  llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> ErrorOrBuffer =
+      llvm::MemoryBuffer::getFile(PdbPath, /*FileSize=*/-1,
+                                  /*RequiresNullTerminator=*/false);
+  if (!ErrorOrBuffer)
+    return nullptr;
+  std::unique_ptr<llvm::MemoryBuffer> Buffer = std::move(*ErrorOrBuffer);
+
+  llvm::StringRef Path = Buffer->getBufferIdentifier();
+  auto Stream = llvm::make_unique<llvm::MemoryBufferByteStream>(
+      std::move(Buffer), llvm::support::little);
+
+  auto File = llvm::make_unique<PDBFile>(Path, std::move(Stream), Allocator);
+  if (auto EC = File->parseFileHeaders())
+    return nullptr;
+  if (auto EC = File->parseStreamData())
+    return nullptr;
+
+  return std::move(File);
+}
+
+static std::unique_ptr<PDBFile>
+loadMatchingPDBFile(std::string exe_path, llvm::BumpPtrAllocator &allocator) {
+  // Try to find a matching PDB for an EXE.
+  using namespace llvm::object;
+  auto expected_binary = createBinary(exe_path);
+
+  // If the file isn't a PE/COFF executable, fail.
+  if (!expected_binary) {
+    llvm::consumeError(expected_binary.takeError());
+    return nullptr;
+  }
+  OwningBinary<Binary> binary = std::move(*expected_binary);
+
+  auto *obj = llvm::dyn_cast<llvm::object::COFFObjectFile>(binary.getBinary());
+  if (!obj)
+    return nullptr;
+  const llvm::codeview::DebugInfo *pdb_info = nullptr;
+
+  // If it doesn't have a debug directory, fail.
+  llvm::StringRef pdb_file;
+  auto ec = obj->getDebugPDBInfo(pdb_info, pdb_file);
+  if (ec)
+    return nullptr;
+
+  // if the file doesn't exist, is not a pdb, or doesn't have a matching guid,
+  // fail.
+  llvm::file_magic magic;
+  ec = llvm::identify_magic(pdb_file, magic);
+  if (ec || magic != llvm::file_magic::pdb)
+    return nullptr;
+  std::unique_ptr<PDBFile> pdb = loadPDBFile(pdb_file, allocator);
+  auto expected_info = pdb->getPDBInfoStream();
+  if (!expected_info) {
+    llvm::consumeError(expected_info.takeError());
+    return nullptr;
+  }
+  llvm::codeview::GUID guid;
+  memcpy(&guid, pdb_info->PDB70.Signature, 16);
+
+  if (expected_info->getGuid() != guid)
+    return nullptr;
+  return std::move(pdb);
+}
+
+static bool IsFunctionPrologue(const CompilandIndexItem &cci,
+                               lldb::addr_t addr) {
+  // FIXME: Implement this.
+  return false;
+}
+
+static bool IsFunctionEpilogue(const CompilandIndexItem &cci,
+                               lldb::addr_t addr) {
+  // FIXME: Implement this.
+  return false;
+}
+
+void SymbolFileNativePDB::Initialize() {
+  PluginManager::RegisterPlugin(GetPluginNameStatic(),
+                                GetPluginDescriptionStatic(), CreateInstance,
+                                DebuggerInitialize);
+}
+
+void SymbolFileNativePDB::Terminate() {
+  PluginManager::UnregisterPlugin(CreateInstance);
+}
+
+void SymbolFileNativePDB::DebuggerInitialize(lldb_private::Debugger &debugger) {
+}
+
+lldb_private::ConstString SymbolFileNativePDB::GetPluginNameStatic() {
+  static ConstString g_name("native-pdb");
+  return g_name;
+}
+
+const char *SymbolFileNativePDB::GetPluginDescriptionStatic() {
+  return "Microsoft PDB debug symbol cross-platform file reader.";
+}
+
+lldb_private::SymbolFile *
+SymbolFileNativePDB::CreateInstance(lldb_private::ObjectFile *obj_file) {
+  return new SymbolFileNativePDB(obj_file);
+}
+
+SymbolFileNativePDB::SymbolFileNativePDB(lldb_private::ObjectFile *object_file)
+    : SymbolFile(object_file) {}
+
+SymbolFileNativePDB::~SymbolFileNativePDB() {}
+
+uint32_t SymbolFileNativePDB::CalculateAbilities() {
+  uint32_t abilities = 0;
+  if (!m_obj_file)
+    return 0;
+
+  if (!m_index) {
+    // Lazily load and match the PDB file, but only do this once.
+    std::unique_ptr<PDBFile> file_up =
+        loadMatchingPDBFile(m_obj_file->GetFileSpec().GetPath(), m_allocator);
+
+    if (!file_up) {
+      auto module_sp = m_obj_file->GetModule();
+      if (!module_sp)
+        return 0;
+      // See if any symbol file is specified through `--symfile` option.
+      FileSpec symfile = module_sp->GetSymbolFileFileSpec();
+      if (!symfile)
+        return 0;
+      file_up = loadPDBFile(symfile.GetPath(), m_allocator);
+    }
+
+    if (!file_up)
+      return 0;
+
+    m_index = PdbIndex::create(std::move(file_up));
+  }
+  if (!m_index)
+    return 0;
+
+  // We don't especially have to be precise here.  We only distinguish between
+  // stripped and not stripped.
+  abilities = kAllAbilities;
+
+  if (m_index->dbi().isStripped())
+    abilities &= ~(Blocks | LocalVariables);
+  return abilities;
+}
+
+void SymbolFileNativePDB::InitializeObject() {
+  m_obj_load_address = m_obj_file->GetFileOffset();
+  m_index->SetLoadAddress(m_obj_load_address);
+  m_index->ParseSectionContribs();
+}
+
+uint32_t SymbolFileNativePDB::GetNumCompileUnits() {
+  const DbiModuleList &modules = m_index->dbi().modules();
+  uint32_t count = modules.getModuleCount();
+  if (count == 0)
+    return count;
+
+  // The linker can inject an additional "dummy" compilation unit into the
+  // PDB. Ignore this special compile unit for our purposes, if it is there.
+  // It is always the last one.
+  DbiModuleDescriptor last = modules.getModuleDescriptor(count - 1);
+  if (last.getModuleName() == "* Linker *")
+    --count;
+  return count;
+}
+
+lldb::FunctionSP SymbolFileNativePDB::CreateFunction(PdbSymUid func_uid,
+                                                     const SymbolContext &sc) {
+  assert(func_uid.tag() == PDB_SymType::Function);
+
+  uint16_t segment = 0;
+  uint32_t offset = 0;
+  uint32_t length = 0;
+  PdbSymUid cuid = PdbSymUid::makeCompilandId(func_uid.asCuSym().modi);
+
+  const CompilandIndexItem *cci = m_index->compilands().GetCompiland(cuid);
+  assert(cci);
+  CVSymbol sym_record =
+      cci->m_debug_stream.readSymbolAtOffset(func_uid.asCuSym().offset);
+
+  assert(sym_record.kind() == S_LPROC32 || sym_record.kind() == S_GPROC32);
+  std::tie(segment, offset, length) = GetSegmentOffsetAndLength(sym_record);
+
+  auto file_vm_addr = m_index->MakeVirtualAddress(segment, offset);
+  if (file_vm_addr == LLDB_INVALID_ADDRESS || file_vm_addr == 0)
+    return nullptr;
+
+  AddressRange func_range(file_vm_addr, length, sc.module_sp->GetSectionList());
+  if (!func_range.GetBaseAddress().IsValid())
+    return nullptr;
+
+  lldb_private::Type *func_type = nullptr;
+
+  // FIXME: Resolve types and mangled names.
+  PdbSymUid sig_uid =
+      PdbSymUid::makeTypeSymId(PDB_SymType::FunctionSig, TypeIndex{0}, false);
+  Mangled mangled(getSymbolName(sym_record));
+
+  FunctionSP func_sp = std::make_shared<Function>(
+      sc.comp_unit, func_uid.toOpaqueId(), sig_uid.toOpaqueId(), mangled,
+      func_type, func_range);
+
+  sc.comp_unit->AddFunction(func_sp);
+  return func_sp;
+}
+
+CompUnitSP
+SymbolFileNativePDB::CreateCompileUnit(const CompilandIndexItem &cci) {
+  lldb::LanguageType lang =
+      cci.m_compile_opts ? TranslateLanguage(cci.m_compile_opts->getLanguage())
+                         : lldb::eLanguageTypeUnknown;
+
+  LazyBool optimized = eLazyBoolNo;
+  if (cci.m_compile_opts && cci.m_compile_opts->hasOptimizations())
+    optimized = eLazyBoolYes;
+
+  llvm::StringRef source_file_name =
+      m_index->compilands().GetMainSourceFile(cci);
+  lldb_private::FileSpec fs(source_file_name, false);
+
+  CompUnitSP cu_sp =
+      std::make_shared<CompileUnit>(m_obj_file->GetModule(), nullptr, fs,
+                                    cci.m_uid.toOpaqueId(), lang, optimized);
+
+  const PdbCompilandId &cuid = cci.m_uid.asCompiland();
+  m_obj_file->GetModule()->GetSymbolVendor()->SetCompileUnitAtIndex(cuid.modi,
+                                                                    cu_sp);
+  return cu_sp;
+}
+
+FunctionSP SymbolFileNativePDB::GetOrCreateFunction(PdbSymUid func_uid,
+                                                    const SymbolContext &sc) {
+  assert(func_uid.tag() == PDB_SymType::Function);
+  auto emplace_result = m_functions.try_emplace(func_uid.toOpaqueId(), nullptr);
+  if (emplace_result.second)
+    emplace_result.first->second = CreateFunction(func_uid, sc);
+
+  assert(emplace_result.first->second);
+  return emplace_result.first->second;
+}
+
+CompUnitSP
+SymbolFileNativePDB::GetOrCreateCompileUnit(const CompilandIndexItem &cci) {
+  auto emplace_result =
+      m_compilands.try_emplace(cci.m_uid.toOpaqueId(), nullptr);
+  if (emplace_result.second)
+    emplace_result.first->second = CreateCompileUnit(cci);
+
+  assert(emplace_result.first->second);
+  return emplace_result.first->second;
+}
+
+lldb::CompUnitSP SymbolFileNativePDB::ParseCompileUnitAtIndex(uint32_t index) {
+  if (index >= GetNumCompileUnits())
+    return CompUnitSP();
+  assert(index < UINT16_MAX);
+  if (index >= UINT16_MAX)
+    return nullptr;
+
+  CompilandIndexItem &item = m_index->compilands().GetOrCreateCompiland(index);
+
+  return GetOrCreateCompileUnit(item);
+}
+
+lldb::LanguageType SymbolFileNativePDB::ParseCompileUnitLanguage(
+    const lldb_private::SymbolContext &sc) {
+  // What fields should I expect to be filled out on the SymbolContext?  Is it
+  // safe to assume that `sc.comp_unit` is valid?
+  if (!sc.comp_unit)
+    return lldb::eLanguageTypeUnknown;
+  PdbSymUid uid = PdbSymUid::fromOpaqueId(sc.comp_unit->GetID());
+  assert(uid.tag() == PDB_SymType::Compiland);
+
+  CompilandIndexItem *item = m_index->compilands().GetCompiland(uid);
+  assert(item);
+  if (!item->m_compile_opts)
+    return lldb::eLanguageTypeUnknown;
+
+  return TranslateLanguage(item->m_compile_opts->getLanguage());
+}
+
+size_t SymbolFileNativePDB::ParseCompileUnitFunctions(
+    const lldb_private::SymbolContext &sc) {
+  lldbassert(sc.comp_unit);
+  return false;
+}
+
+uint32_t
+SymbolFileNativePDB::ResolveSymbolContext(const lldb_private::Address &so_addr,
+                                          uint32_t resolve_scope,
+                                          lldb_private::SymbolContext &sc) {
+  uint32_t resolved_flags = 0;
+  lldb::addr_t file_addr = so_addr.GetFileAddress();
+  llvm::Optional<uint16_t> modi = m_index->GetModuleIndexForVa(file_addr);
+  if (!modi)
+    return 0;
+
+  if (resolve_scope & eSymbolContextCompUnit) {
+    PdbSymUid cuid = PdbSymUid::makeCompilandId(*modi);
+    CompilandIndexItem *cci = m_index->compilands().GetCompiland(cuid);
+    if (cci) {
+      sc.comp_unit = GetOrCreateCompileUnit(*cci).get();
+      resolved_flags |= eSymbolContextCompUnit;
+    }
+  }
+
+  if (resolve_scope & eSymbolContextFunction) {
+    addr_t file_vm_addr = so_addr.GetFileAddress();
+    std::vector<SymbolAndUid> matches = m_index->FindSymbolsByVa(file_vm_addr);
+    for (const auto &match : matches) {
+      if (match.uid.tag() != PDB_SymType::Function)
+        continue;
+      sc.function = GetOrCreateFunction(match.uid, sc).get();
+    }
+    resolved_flags |= eSymbolContextCompUnit;
+  }
+
+  if (resolve_scope & eSymbolContextLineEntry) {
+    if (auto *line_table = sc.comp_unit->GetLineTable()) {
+      Address addr(so_addr);
+      if (line_table->FindLineEntryByAddress(addr, sc.line_entry))
+        resolved_flags |= eSymbolContextLineEntry;
+    }
+  }
+
+  return 0;
+}
+
+static void AppendLineEntryToSequence(LineTable &table, LineSequence &sequence,
+                                      const CompilandIndexItem &cci,
+                                      lldb::addr_t base_addr,
+                                      uint32_t file_number,
+                                      const LineFragmentHeader &block,
+                                      const LineNumberEntry &cur) {
+  LineInfo cur_info(cur.Flags);
+
+  if (cur_info.isAlwaysStepInto() || cur_info.isNeverStepInto())
+    return;
+
+  uint64_t addr = base_addr + cur.Offset;
+
+  bool is_statement = cur_info.isStatement();
+  bool is_prologue = IsFunctionPrologue(cci, addr);
+  bool is_epilogue = IsFunctionEpilogue(cci, addr);
+
+  uint32_t lno = cur_info.getStartLine();
+
+  table.AppendLineEntryToSequence(&sequence, addr, lno, 0, file_number,
+                                  is_statement, false, is_prologue, is_epilogue,
+                                  false);
+}
+
+static void TerminateLineSequence(LineTable &table,
+                                  const LineFragmentHeader &block,
+                                  lldb::addr_t base_addr, uint32_t file_number,
+                                  uint32_t last_line,
+                                  std::unique_ptr<LineSequence> seq) {
+  // The end is always a terminal entry, so insert it regardless.
+  table.AppendLineEntryToSequence(seq.get(), base_addr + block.CodeSize,
+                                  last_line, 0, file_number, false, false,
+                                  false, false, true);
+  table.InsertSequence(seq.release());
+}
+
+bool SymbolFileNativePDB::ParseCompileUnitLineTable(
+    const lldb_private::SymbolContext &sc) {
+  // Unfortunately LLDB is set up to parse the entire compile unit line table
+  // all at once, even if all it really needs is line info for a specific
+  // function.  In the future it would be nice if it could set the sc.m_function
+  // member, and we could only get the line info for the function in question.
+  lldbassert(sc.comp_unit);
+  PdbSymUid cu_id = PdbSymUid::fromOpaqueId(sc.comp_unit->GetID());
+  assert(cu_id.isCompiland());
+  CompilandIndexItem *cci = m_index->compilands().GetCompiland(cu_id);
+  assert(cci);
+  auto line_table = llvm::make_unique<LineTable>(sc.comp_unit);
+
+  llvm::StringMap<uint32_t> file_index_lookup;
+
+  // This is basically a copy of the .debug$S subsections from the original COFF
+  // object file.  We are looking for all DEBUG_S_LINES subsections.
+  for (const DebugSubsectionRecord &dssr :
+       cci->m_debug_stream.getSubsectionsArray()) {
+    if (dssr.kind() != DebugSubsectionKind::Lines)
+      continue;
+
+    DebugLinesSubsectionRef lines;
+    llvm::BinaryStreamReader reader(dssr.getRecordData());
+    if (auto EC = lines.initialize(reader)) {
+      llvm::consumeError(std::move(EC));
+      return false;
+    }
+
+    const LineFragmentHeader *lfh = lines.header();
+    uint64_t virtual_addr =
+        m_index->MakeVirtualAddress(lfh->RelocSegment, lfh->RelocOffset);
+
+    const auto &checksums = cci->m_strings.checksums().getArray();
+    const auto &strings = cci->m_strings.strings();
+    for (const LineColumnEntry &group : lines) {
+      // Indices in this structure are actually offsets of records in the
+      // DEBUG_S_FILECHECKSUMS subsection.  Those entries then have an index
+      // into the global PDB string table.
+      auto iter = checksums.at(group.NameIndex);
+      if (iter == checksums.end())
+        continue;
+
+      llvm::Expected<llvm::StringRef> efn =
+          strings.getString(iter->FileNameOffset);
+      if (!efn) {
+        llvm::consumeError(efn.takeError());
+        continue;
+      }
+
+      // LLDB wants the index of the file in the list of support files.
+      llvm::StringRef file_name = *efn;
+      auto fn_iter = llvm::find(cci->m_file_list, *efn);
+      assert(fn_iter != cci->m_file_list.end());
+      uint32_t file_index = std::distance(cci->m_file_list.begin(), fn_iter);
+
+      std::unique_ptr<LineSequence> sequence(
+          line_table->CreateLineSequenceContainer());
+      assert(!group.LineNumbers.empty());
+
+      for (const LineNumberEntry &entry : group.LineNumbers) {
+        AppendLineEntryToSequence(*line_table, *sequence, *cci, virtual_addr,
+                                  file_index, *lfh, entry);
+      }
+      LineInfo last_line(group.LineNumbers.back().Flags);
+      TerminateLineSequence(*line_table, *lfh, virtual_addr, file_index,
+                            last_line.getEndLine(), std::move(sequence));
+    }
+  }
+
+  if (line_table->GetSize() == 0)
+    return false;
+
+  sc.comp_unit->SetLineTable(line_table.release());
+  return true;
+}
+
+bool SymbolFileNativePDB::ParseCompileUnitDebugMacros(
+    const lldb_private::SymbolContext &sc) {
+  // PDB doesn't contain information about macros
+  return false;
+}
+
+bool SymbolFileNativePDB::ParseCompileUnitSupportFiles(
+    const lldb_private::SymbolContext &sc,
+    lldb_private::FileSpecList &support_files) {
+  lldbassert(sc.comp_unit);
+
+  PdbSymUid comp_uid = PdbSymUid::fromOpaqueId(sc.comp_unit->GetID());
+  assert(comp_uid.tag() == PDB_SymType::Compiland);
+
+  const CompilandIndexItem *cci = m_index->compilands().GetCompiland(comp_uid);
+  assert(cci);
+
+  for (llvm::StringRef f : cci->m_file_list) {
+    FileSpec spec(f, false, FileSpec::Style::windows);
+    support_files.Append(spec);
+  }
+
+  return true;
+}
+
+bool SymbolFileNativePDB::ParseImportedModules(
+    const lldb_private::SymbolContext &sc,
+    std::vector<lldb_private::ConstString> &imported_modules) {
+  // PDB does not yet support module debug info
+  return false;
+}
+
+size_t SymbolFileNativePDB::ParseFunctionBlocks(
+    const lldb_private::SymbolContext &sc) {
+  lldbassert(sc.comp_unit && sc.function);
+  return 0;
+}
+
+uint32_t SymbolFileNativePDB::FindFunctions(
+    const lldb_private::ConstString &name,
+    const lldb_private::CompilerDeclContext *parent_decl_ctx,
+    uint32_t name_type_mask, bool include_inlines, bool append,
+    lldb_private::SymbolContextList &sc_list) {
+  // For now we only support lookup by method name.
+  if (!(name_type_mask & eFunctionNameTypeMethod))
+    return 0;
+
+  using SymbolAndOffset = std::pair<uint32_t, llvm::codeview::CVSymbol>;
+
+  std::vector<SymbolAndOffset> matches = m_index->globals().findRecordsByName(
+      name.GetStringRef(), m_index->symrecords());
+  for (const SymbolAndOffset &match : matches) {
+    if (match.second.kind() != S_PROCREF && match.second.kind() != S_LPROCREF)
+      continue;
+    ProcRefSym proc(match.second.kind());
+    cantFail(SymbolDeserializer::deserializeAs<ProcRefSym>(match.second, proc));
+
+    PdbSymUid cuid = PdbSymUid::makeCompilandId(proc);
+    CompilandIndexItem &cci = m_index->compilands().GetOrCreateCompiland(cuid);
+    lldb_private::SymbolContext sc;
+
+    sc.comp_unit = GetOrCreateCompileUnit(cci).get();
+    sc.module_sp = sc.comp_unit->GetModule();
+    PdbSymUid func_uid = PdbSymUid::makeCuSymId(proc);
+    sc.function = GetOrCreateFunction(func_uid, sc).get();
+
+    sc_list.Append(sc);
+  }
+
+  return sc_list.GetSize();
+}
+
+uint32_t
+SymbolFileNativePDB::FindFunctions(const lldb_private::RegularExpression &regex,
+                                   bool include_inlines, bool append,
+                                   lldb_private::SymbolContextList &sc_list) {
+  return 0;
+}
+
+lldb_private::CompilerDeclContext SymbolFileNativePDB::FindNamespace(
+    const lldb_private::SymbolContext &sc,
+    const lldb_private::ConstString &name,
+    const lldb_private::CompilerDeclContext *parent_decl_ctx) {
+  return {};
+}
+
+lldb_private::TypeSystem *
+SymbolFileNativePDB::GetTypeSystemForLanguage(lldb::LanguageType language) {
+  auto type_system =
+      m_obj_file->GetModule()->GetTypeSystemForLanguage(language);
+  if (type_system)
+    type_system->SetSymbolFile(this);
+  return type_system;
+}
+
+lldb_private::ConstString SymbolFileNativePDB::GetPluginName() {
+  static ConstString g_name("pdb");
+  return g_name;
+}
+
+uint32_t SymbolFileNativePDB::GetPluginVersion() { return 1; }
Index: lldb/source/Plugins/SymbolFile/PDB/CMakeLists.txt
===================================================================
--- lldb/source/Plugins/SymbolFile/PDB/CMakeLists.txt
+++ lldb/source/Plugins/SymbolFile/PDB/CMakeLists.txt
@@ -9,6 +9,7 @@
     lldbCore
     lldbSymbol
 	lldbUtility
+  lldbPluginSymbolFileNativePDB
   LINK_COMPONENTS
     DebugInfoPDB
     Support
Index: lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
+++ lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
@@ -46,6 +46,7 @@
 #include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
 
 #include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h" // For IsCPPMangledName
+#include "Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h"
 #include "Plugins/SymbolFile/PDB/PDBASTParser.h"
 #include "Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.h"
 
@@ -74,14 +75,31 @@
 }
 } // namespace
 
+static bool ShouldUseNativeReader() {
+#if !defined(_WIN32)
+  return true;
+#endif
+  llvm::StringRef use_native = ::getenv("LLDB_USE_NATIVE_PDB_READER");
+  return use_native.equals_lower("on") || use_native.equals_lower("yes") ||
+         use_native.equals_lower("1") || use_native.equals_lower("true");
+}
+
 void SymbolFilePDB::Initialize() {
-  PluginManager::RegisterPlugin(GetPluginNameStatic(),
-                                GetPluginDescriptionStatic(), CreateInstance,
-                                DebuggerInitialize);
+  if (ShouldUseNativeReader()) {
+    npdb::SymbolFileNativePDB::Initialize();
+  } else {
+    PluginManager::RegisterPlugin(GetPluginNameStatic(),
+                                  GetPluginDescriptionStatic(), CreateInstance,
+                                  DebuggerInitialize);
+  }
 }
 
 void SymbolFilePDB::Terminate() {
-  PluginManager::UnregisterPlugin(CreateInstance);
+  if (ShouldUseNativeReader()) {
+    npdb::SymbolFileNativePDB::Terminate();
+  } else {
+    PluginManager::UnregisterPlugin(CreateInstance);
+  }
 }
 
 void SymbolFilePDB::DebuggerInitialize(lldb_private::Debugger &debugger) {}
@@ -286,7 +304,7 @@
 
   FunctionSP func_sp =
       std::make_shared<Function>(sc.comp_unit, pdb_func.getSymIndexId(),
-                                 func_type_uid, mangled, func_type, func_range);
+                                 func_type_uid, mangled, nullptr, func_range);
 
   sc.comp_unit->AddFunction(func_sp);
   return func_sp.get();