Added compileunits coverage for rela sections.
diff --git a/src/elf.cc b/src/elf.cc
index 885a537..ce47911 100644
--- a/src/elf.cc
+++ b/src/elf.cc
@@ -176,10 +176,12 @@
                     string_view* file_range) const;
 
     // Requires: header().sh_type == SHT_REL
-    void ReadRelocation(Elf64_Word index, Elf64_Rel* rel) const;
+    void ReadRelocation(Elf64_Word index, Elf64_Rel* rel,
+                        string_view* file_range) const;
 
     // Requires: header().sh_type == SHT_RELA
-    void ReadRelocationWithAddend(Elf64_Word index, Elf64_Rela* rel) const;
+    void ReadRelocationWithAddend(Elf64_Word index, Elf64_Rela* rel,
+                                  string_view* file_range) const;
 
     const ElfFile& elf() const { return *elf_; }
 
@@ -451,22 +453,31 @@
   size_t offset = header_.sh_entsize * index;
   reader.Read<Elf32_Sym>(offset, SymMunger(), sym);
   if (file_range) {
-    size_t size = elf_->is_64bit() ? sizeof(Elf64_Sym) : sizeof(Elf32_Sym);
-    *file_range = contents().substr(offset, size);
+    *file_range = contents().substr(offset, header_.sh_entsize);
   }
 }
 
-void ElfFile::Section::ReadRelocation(Elf64_Word index, Elf64_Rel* rel) const {
+void ElfFile::Section::ReadRelocation(Elf64_Word index, Elf64_Rel* rel,
+                                      string_view* file_range) const {
   assert(header().sh_type == SHT_REL);
   ElfFile::StructReader reader(*elf_, contents());
-  reader.Read<Elf32_Rel>(header_.sh_entsize * index, RelMunger(), rel);
+  size_t offset = header_.sh_entsize * index;
+  reader.Read<Elf32_Rel>(offset, RelMunger(), rel);
+  if (file_range) {
+    *file_range = contents().substr(offset, header_.sh_entsize);
+  }
 }
 
 void ElfFile::Section::ReadRelocationWithAddend(Elf64_Word index,
-                                                Elf64_Rela* rela) const {
+                                                Elf64_Rela* rela,
+                                                string_view* file_range) const {
   assert(header().sh_type == SHT_RELA);
   ElfFile::StructReader reader(*elf_, contents());
-  reader.Read<Elf32_Rela>(header_.sh_entsize * index, RelaMunger(), rela);
+  size_t offset = header_.sh_entsize * index;
+  reader.Read<Elf32_Rela>(offset, RelaMunger(), rela);
+  if (file_range) {
+    *file_range = contents().substr(offset, header_.sh_entsize);
+  }
 }
 
 bool ElfFile::Initialize() {
@@ -865,13 +876,63 @@
       });
 }
 
+static void ReadELFSymbolTableEntries(const ElfFile& elf,
+                                      const ElfFile::Section& section,
+                                      uint64_t index_base, bool is_object,
+                                      RangeSink* sink) {
+  Elf64_Word symbol_count = section.GetEntryCount();
+
+  // Find the corresponding section where the strings for the symbol
+  // table can be found.
+  ElfFile::Section strtab_section;
+  elf.ReadSection(section.header().sh_link, &strtab_section);
+  if (strtab_section.header().sh_type != SHT_STRTAB) {
+    THROW("symtab section pointed to non-strtab section");
+  }
+
+  for (Elf64_Word i = 1; i < symbol_count; i++) {
+    Elf64_Sym sym;
+    string_view sym_range;
+    section.ReadSymbol(i, &sym, &sym_range);
+
+    if (ELF64_ST_TYPE(sym.st_info) == STT_SECTION ||
+        sym.st_shndx == STN_UNDEF ||
+        sym.st_name == SHN_UNDEF) {
+      continue;
+    }
+
+    string_view name = strtab_section.ReadString(sym.st_name);
+    uint64_t full_addr =
+        ToVMAddr(sym.st_value, index_base + sym.st_shndx, is_object);
+    // Capture the trailing NULL.
+    name = string_view(name.data(), name.size() + 1);
+    sink->AddFileRangeFor(full_addr, name);
+    sink->AddFileRangeFor(full_addr, sym_range);
+  }
+}
+
+static void ReadELFRelaEntries(const ElfFile::Section& section,
+                               uint64_t index_base, bool is_object,
+                               RangeSink* sink) {
+  Elf64_Word rela_count = section.GetEntryCount();
+  for (Elf64_Word i = 1; i < rela_count; i++) {
+    Elf64_Rela rela;
+    string_view rela_range;
+    section.ReadRelocationWithAddend(i, &rela, &rela_range);
+    // TODO(haberman): fix this for object files.
+    uint64_t full_addr = ToVMAddr(rela.r_offset, index_base, is_object);
+    full_addr = rela.r_offset;
+    sink->AddFileRangeFor(full_addr, rela_range);
+  }
+}
+
 // Adds file ranges for the symbol tables and string tables *themselves* (ie.
 // the space that the symtab/strtab take up in the file).  This will cover
 //   .symtab
 //   .strtab
 //   .dynsym
 //   .dynstr
-static void ReadELFSymbolTables(const InputFile& file, RangeSink* sink) {
+static void ReadELFTables(const InputFile& file, RangeSink* sink) {
   bool is_object = IsObjectFile(file.data());
 
   ForEachElf(
@@ -881,39 +942,15 @@
           ElfFile::Section section;
           elf.ReadSection(i, &section);
 
-          if (section.header().sh_type != SHT_SYMTAB &&
-              section.header().sh_type != SHT_DYNSYM) {
-            continue;
-          }
-
-          Elf64_Word symbol_count = section.GetEntryCount();
-
-          // Find the corresponding section where the strings for the symbol
-          // table can be found.
-          ElfFile::Section strtab_section;
-          elf.ReadSection(section.header().sh_link, &strtab_section);
-          if (strtab_section.header().sh_type != SHT_STRTAB) {
-            THROW("symtab section pointed to non-strtab section");
-          }
-
-          for (Elf64_Word i = 1; i < symbol_count; i++) {
-            Elf64_Sym sym;
-            string_view sym_range;
-            section.ReadSymbol(i, &sym, &sym_range);
-
-            if (ELF64_ST_TYPE(sym.st_info) == STT_SECTION ||
-                sym.st_shndx == STN_UNDEF ||
-                sym.st_name == SHN_UNDEF) {
-              continue;
-            }
-
-            string_view name = strtab_section.ReadString(sym.st_name);
-            uint64_t full_addr =
-                ToVMAddr(sym.st_value, index_base + sym.st_shndx, is_object);
-            // Capture the trailing NULL.
-            name = string_view(name.data(), name.size() + 1);
-            sink->AddFileRangeFor(full_addr, name);
-            sink->AddFileRangeFor(full_addr, sym_range);
+          switch (section.header().sh_type) {
+            case SHT_SYMTAB:
+            case SHT_DYNSYM:
+              ReadELFSymbolTableEntries(elf, section, index_base, is_object,
+                                        sink);
+              break;
+            case SHT_RELA:
+              ReadELFRelaEntries(section, index_base, is_object, sink);
+              break;
           }
         }
       });
@@ -1167,8 +1204,6 @@
         case DataSource::kShortSymbols:
         case DataSource::kFullSymbols:
           ReadELFSymbols(debug_file().file_data(), sink, nullptr);
-          ReadELFSymbolTables(sink->input_file(), sink);
-          DoReadELFSections(sink, kReportByEscapedSectionName);
           break;
         case DataSource::kArchiveMembers:
           DoReadELFSections(sink, kReportByArchiveMember);
@@ -1186,8 +1221,6 @@
           dwarf::File dwarf;
           ReadDWARFSections(debug_file().file_data(), &dwarf);
           ReadDWARFCompileUnits(dwarf, symtab, symbol_map, sink);
-          ReadELFSymbolTables(sink->input_file(), sink);
-          DoReadELFSections(sink, kReportByEscapedSectionName);
           break;
         }
         case DataSource::kInlines: {
@@ -1201,6 +1234,18 @@
         default:
           THROW("unknown data source");
       }
+
+      switch (sink->data_source()) {
+        case DataSource::kSegments:
+        case DataSource::kSections:
+        case DataSource::kArchiveMembers:
+          break;
+        default:
+          ReadELFTables(sink->input_file(), sink);
+          DoReadELFSections(sink, kReportByEscapedSectionName);
+          break;
+      }
+
       // Add these *after* processing all other data sources.
       AddCatchAll(sink);
     }