Index: include/lldb/Core/FileSpecList.h
===================================================================
--- include/lldb/Core/FileSpecList.h
+++ include/lldb/Core/FileSpecList.h
@@ -48,6 +48,9 @@
   //------------------------------------------------------------------
   FileSpecList(const FileSpecList &rhs);
 
+  /// Initialize this object from a vector of FileSpecs
+  FileSpecList(std::vector<FileSpec> &&rhs) : m_files(std::move(rhs)) {}
+
   //------------------------------------------------------------------
   /// Destructor.
   //------------------------------------------------------------------
@@ -64,7 +67,11 @@
   /// @return
   ///     A const reference to this object.
   //------------------------------------------------------------------
-  const FileSpecList &operator=(const FileSpecList &rhs);
+  FileSpecList &operator=(const FileSpecList &rhs) = default;
+
+  /// Move-assignment operator.
+  FileSpecList &operator=(FileSpecList &&rhs) = default;
+
 
   //------------------------------------------------------------------
   /// Append a FileSpec object to the list.
Index: lit/SymbolFile/Breakpad/Inputs/line-table.syms
===================================================================
--- /dev/null
+++ lit/SymbolFile/Breakpad/Inputs/line-table.syms
@@ -0,0 +1,9 @@
+MODULE Linux x86_64 761550E08086333960A9074A9CE2895C0 a.out
+INFO CODE_ID E05015768680393360A9074A9CE2895C
+FILE 0 /tmp/a.c
+FILE 2 /tmp/c.c
+FUNC b0 10 0 func
+b0 1 1 0
+b1 1 2 0
+b2 1 2 2
+b4 1 3 2
Index: lit/SymbolFile/Breakpad/line-table.test
===================================================================
--- /dev/null
+++ lit/SymbolFile/Breakpad/line-table.test
@@ -0,0 +1,23 @@
+# RUN: yaml2obj %S/Inputs/basic-elf.yaml > %T/line-table.out
+# RUN: %lldb %T/line-table.out -o "target symbols add -s line-table.out %S/Inputs/line-table.syms" \
+# RUN:   -s %s | FileCheck %s
+
+image dump line-table line-table.out
+# CHECK-LABEL: Line table for {{.*}}line-table.out
+# CHECK-NEXT: 0x00000000004000b0: /tmp/a.c:1
+# CHECK-NEXT: 0x00000000004000b1: /tmp/a.c:2
+# CHECK-NEXT: 0x00000000004000b2: /tmp/c.c:2
+# CHECK-NEXT: 0x00000000004000b3: 
+# CHECK-EMPTY: 
+# CHECK-NEXT: 0x00000000004000b4: /tmp/c.c:3
+# CHECK-NEXT: 0x00000000004000b5: 
+
+image lookup -a 0x4000b2 -v
+# CHECK-LABEL: image lookup -a 0x4000b2 -v
+# CHECK: Summary: line-table.out`func + 2
+
+breakpoint set -f c.c -l 2
+# CHECK-LABEL: breakpoint set -f c.c -l 2
+# CHECK: Breakpoint 1: where = line-table.out`func + 2, address = 0x00000000004000b2
+
+exit
Index: source/Core/FileSpecList.cpp
===================================================================
--- source/Core/FileSpecList.cpp
+++ source/Core/FileSpecList.cpp
@@ -25,15 +25,6 @@
 
 FileSpecList::~FileSpecList() = default;
 
-//------------------------------------------------------------------
-// Assignment operator
-//------------------------------------------------------------------
-const FileSpecList &FileSpecList::operator=(const FileSpecList &rhs) {
-  if (this != &rhs)
-    m_files = rhs.m_files;
-  return *this;
-}
-
 //------------------------------------------------------------------
 // Append the "file_spec" to the end of the file spec list.
 //------------------------------------------------------------------
Index: source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h
===================================================================
--- source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h
+++ source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h
@@ -43,7 +43,7 @@
 
   uint32_t CalculateAbilities() override;
 
-  void InitializeObject() override {}
+  void InitializeObject() override;
 
   //------------------------------------------------------------------
   // Compile Unit function calls
@@ -67,9 +67,7 @@
   }
 
   bool ParseCompileUnitSupportFiles(const SymbolContext &sc,
-                                    FileSpecList &support_files) override {
-    return false;
-  }
+                                    FileSpecList &support_files) override;
 
   bool
   ParseImportedModules(const SymbolContext &sc,
@@ -98,10 +96,16 @@
   }
 
   bool CompleteType(CompilerType &compiler_type) override { return false; }
+
   uint32_t ResolveSymbolContext(const Address &so_addr,
                                 lldb::SymbolContextItem resolve_scope,
                                 SymbolContext &sc) override;
 
+  uint32_t ResolveSymbolContext(const FileSpec &file_spec, uint32_t line,
+                                bool check_inlines,
+                                lldb::SymbolContextItem resolve_scope,
+                                SymbolContextList &sc_list) override;
+
   size_t GetTypes(SymbolContextScope *sc_scope, lldb::TypeClass type_mask,
                   TypeList &type_list) override {
     return 0;
@@ -141,6 +145,7 @@
   uint32_t GetPluginVersion() override { return 1; }
 
 private:
+  lldb::CompUnitSP m_comp_unit_sp;
 };
 
 } // namespace breakpad
Index: source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp
===================================================================
--- source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp
+++ source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp
@@ -13,7 +13,10 @@
 #include "lldb/Core/PluginManager.h"
 #include "lldb/Core/Section.h"
 #include "lldb/Host/FileSystem.h"
+#include "lldb/Symbol/CompileUnit.h"
+#include "lldb/Symbol/LineTable.h"
 #include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/SymbolVendor.h"
 #include "lldb/Symbol/TypeMap.h"
 #include "lldb/Utility/Log.h"
 #include "llvm/ADT/StringExtras.h"
@@ -103,17 +106,23 @@
   if (m_obj_file->GetPluginName() != ObjectFileBreakpad::GetPluginNameStatic())
     return 0;
 
-  return CompileUnits | Functions;
+  return CompileUnits | Functions | LineTables;
 }
 
-uint32_t SymbolFileBreakpad::GetNumCompileUnits() {
-  // TODO
-  return 0;
+void SymbolFileBreakpad::InitializeObject() {
+  m_comp_unit_sp = std::make_shared<CompileUnit>(
+      m_obj_file->GetModule(), /*user_data*/ nullptr,
+      m_obj_file->GetModule()->GetObjectFile()->GetFileSpec(),
+      /*uid*/ 0, eLanguageTypeUnknown, /*is_optimized*/ eLazyBoolNo);
 }
 
+uint32_t SymbolFileBreakpad::GetNumCompileUnits() { return 1; }
+
 CompUnitSP SymbolFileBreakpad::ParseCompileUnitAtIndex(uint32_t index) {
-  // TODO
-  return nullptr;
+  assert(index == 0);
+  m_obj_file->GetModule()->GetSymbolVendor()->SetCompileUnitAtIndex(
+      0, m_comp_unit_sp);
+  return m_comp_unit_sp;
 }
 
 size_t SymbolFileBreakpad::ParseCompileUnitFunctions(const SymbolContext &sc) {
@@ -122,16 +131,131 @@
 }
 
 bool SymbolFileBreakpad::ParseCompileUnitLineTable(const SymbolContext &sc) {
-  // TODO
-  return 0;
+  Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYMBOLS);
+  addr_t base = m_obj_file->GetModule()
+                    ->GetObjectFile()
+                    ->GetBaseAddress()
+                    .GetFileAddress();
+  if (base == LLDB_INVALID_ADDRESS) {
+    LLDB_LOG(log, "Unable to fetch the base address of object file. Skipping "
+                  "symtab population.");
+    return false;
+  }
+  auto line_table_up = llvm::make_unique<LineTable>(sc.comp_unit);
+  std::unique_ptr<LineSequence> line_seq_up(
+      line_table_up->CreateLineSequenceContainer());
+  llvm::Optional<addr_t> next_addr;
+  auto finish_sequence = [&]() {
+    line_table_up->AppendLineEntryToSequence(
+        line_seq_up.get(), *next_addr, /*line*/ 0, /*column*/ 0,
+        /*file_idx*/ 0, /*is_start_of_statement*/ false,
+        /*is_start_of_basic_block*/ false, /*is_prologue_end*/ false,
+        /*is_epilogue_begin*/ false, /*is_terminal_entry*/ true);
+    line_table_up->InsertSequence(line_seq_up.get());
+    line_seq_up->Clear();
+  };
+  for (llvm::StringRef line: lines(*m_obj_file, Token::Func)) {
+    llvm::StringRef token_str;
+    std::tie(token_str, line) = getToken(line);
+    if (toToken(token_str) == Token::Func)
+      continue;
+
+    // address size line filenum
+    addr_t address;
+    if (!to_integer(token_str, address, 16))
+      continue;
+    address += base;
+    std::tie(token_str, line) = getToken(line);
+    addr_t size;
+    if (!to_integer(token_str, size, 16))
+      continue;
+    std::tie(token_str, line) = getToken(line);
+    uint32_t linenum;
+    if (!to_integer(token_str, linenum, 10))
+      continue;
+    std::tie(token_str, line) = getToken(line);
+    uint32_t filenum;
+    if (!to_integer(token_str, filenum, 10))
+      continue;
+    ++filenum; // LLDB file IDs are 1-based
+
+    if (next_addr && *next_addr != address) {
+      // Discontiguous entries. Finish off the previous sequence and reset.
+      finish_sequence();
+    }
+    line_table_up->AppendLineEntryToSequence(
+        line_seq_up.get(), address, /*line*/ linenum, /*column*/ 0,
+        /*file_idx*/ filenum, /*is_start_of_statement*/ true,
+        /*is_start_of_basic_block*/ false, /*is_prologue_end*/ false,
+        /*is_epilogue_begin*/ false, /*is_terminal_entry*/ false);
+    next_addr = address + size;
+  }
+  if (next_addr)
+    finish_sequence();
+  sc.comp_unit->SetLineTable(line_table_up.release());
+  return true;
+}
+
+bool SymbolFileBreakpad::ParseCompileUnitSupportFiles(
+    const SymbolContext &sc, FileSpecList &support_files) {
+  assert(sc.comp_unit == m_comp_unit_sp.get());
+  std::vector<FileSpec> files;
+  for (llvm::StringRef line: lines(*m_obj_file, Token::File)) {
+    // FILE number name
+
+    // skip FILE
+    line = getToken(line).second;
+
+    llvm::StringRef token;
+    std::tie(token, line) = getToken(line);
+    uint32_t number;
+    if (!to_integer(token, number, 10))
+      continue;
+    ++number; // LLDB file IDs are 1-based
+
+    llvm::StringRef name = line.trim();
+    if (number >= files.size())
+      files.resize(number+1);
+    files[number] = FileSpec(name);
+  }
+  support_files = FileSpecList(std::move(files));
+  return true;
 }
 
 uint32_t
 SymbolFileBreakpad::ResolveSymbolContext(const Address &so_addr,
                                          SymbolContextItem resolve_scope,
                                          SymbolContext &sc) {
-  // TODO
-  return 0;
+  if (!(resolve_scope & (eSymbolContextCompUnit | eSymbolContextLineEntry)))
+    return 0;
+  sc.comp_unit = m_comp_unit_sp.get();
+  SymbolContextItem result = eSymbolContextCompUnit;
+  if (resolve_scope & eSymbolContextLineEntry) {
+    if (sc.comp_unit->GetLineTable()->FindLineEntryByAddress(so_addr,
+                                                             sc.line_entry)) {
+      result |= eSymbolContextLineEntry;
+    }
+  }
+  
+  return result;
+}
+
+uint32_t SymbolFileBreakpad::ResolveSymbolContext(const FileSpec &file_spec, uint32_t line,
+                              bool check_inlines,
+                              lldb::SymbolContextItem resolve_scope,
+                              SymbolContextList &sc_list) {
+  const uint32_t old_size = sc_list.GetSize();
+  if (resolve_scope & eSymbolContextCompUnit) {
+    FileSpecList support_files = m_comp_unit_sp->GetSupportFiles();
+    const bool full_match(file_spec.GetDirectory());
+    if (FileSpec::Equal(file_spec, *m_comp_unit_sp, full_match) ||
+        (check_inlines && support_files.FindFileIndex(1, file_spec, true))) {
+      SymbolContext sc(m_obj_file->GetModule());
+      sc.comp_unit = m_comp_unit_sp.get();
+      sc_list.Append(sc);
+    }
+  }
+  return sc_list.GetSize() - old_size;
 }
 
 uint32_t SymbolFileBreakpad::FindFunctions(