Merge branch 'dataquality' of github.com:haberman/bloaty into dataquality
diff --git a/src/bloaty.cc b/src/bloaty.cc
index 58fb7af..9cc0c59 100644
--- a/src/bloaty.cc
+++ b/src/bloaty.cc
@@ -878,8 +878,12 @@
   for (auto& pair : outputs_) {
     const std::string label = pair.second->Munge(name);
     if (translator_) {
-      pair.first->file_map.AddRangeWithTranslation(
+      bool ok = pair.first->file_map.AddRangeWithTranslation(
           fileoff, filesize, label, translator_->file_map, &pair.first->vm_map);
+      if (!ok) {
+        THROWF("File range ($0, $1) for label $2 extends beyond base map",
+               fileoff, filesize, name);
+      }
     } else {
       pair.first->file_map.AddRange(fileoff, filesize, label);
     }
@@ -902,9 +906,13 @@
     std::string label;
     uint64_t offset;
     if (pair.first->vm_map.TryGetLabel(label_from_vmaddr, &label, &offset)) {
-      pair.first->file_map.AddRangeWithTranslation(
+      bool ok = pair.first->file_map.AddRangeWithTranslation(
           file_offset, file_range.size(), label, translator_->file_map,
           &pair.first->vm_map);
+      if (!ok) {
+        THROWF("File range ($0, $1) for label $2 extends beyond base map",
+               offset, file_range.size(), label);
+      }
     } else if (verbose_level > 2) {
       printf("No label found for vmaddr %" PRIx64 "\n", label_from_vmaddr);
     }
@@ -924,8 +932,12 @@
     std::string label;
     uint64_t offset;
     if (pair.first->vm_map.TryGetLabel(label_from_vmaddr, &label, &offset)) {
-      pair.first->vm_map.AddRangeWithTranslation(
+      bool ok = pair.first->vm_map.AddRangeWithTranslation(
           addr, size, label, translator_->vm_map, &pair.first->file_map);
+      if (!ok) {
+        THROWF("VM range ($0, $1) for label $2 extends beyond base map", addr,
+               size, label);
+      }
     } else if (verbose_level > 2) {
       printf("No label found for vmaddr %" PRIx64 "\n", label_from_vmaddr);
     }
@@ -942,8 +954,12 @@
   assert(translator_);
   for (auto& pair : outputs_) {
     const std::string label = pair.second->Munge(name);
-    pair.first->vm_map.AddRangeWithTranslation(
+    bool ok = pair.first->vm_map.AddRangeWithTranslation(
         vmaddr, vmsize, label, translator_->vm_map, &pair.first->file_map);
+    if (!ok) {
+      THROWF("VM range ($0, $1) for label $2 extends beyond base map", vmaddr,
+             vmsize, name);
+    }
   }
 }
 
diff --git a/src/elf.cc b/src/elf.cc
index 55989c7..94ce2ad 100644
--- a/src/elf.cc
+++ b/src/elf.cc
@@ -1201,7 +1201,11 @@
              });
 
   // The last-line fallback to make sure we cover the entire VM space.
-  DoReadELFSegments(sink, kReportByEscapedSegmentName);
+  if (IsObjectFile(sink->input_file().data())) {
+    DoReadELFSections(sink, kReportByEscapedSectionName);
+  } else {
+    DoReadELFSegments(sink, kReportByEscapedSegmentName);
+  }
 
   // The last-line fallback to make sure we cover the entire file.
   sink->AddFileRange("elf_catchall", "[Unmapped]", sink->input_file().data());
diff --git a/src/range_map.cc b/src/range_map.cc
index 6e20cf2..abee140 100644
--- a/src/range_map.cc
+++ b/src/range_map.cc
@@ -29,9 +29,6 @@
 bool RangeMap::TranslateAndTrimRangeWithEntry(T iter, uint64_t addr,
                                               uint64_t size, uint64_t* out_addr,
                                               uint64_t* out_size) const {
-  if (!iter->second.HasTranslation()) {
-    return false;
-  }
 
   addr = std::max(addr, iter->first);
 
@@ -40,11 +37,16 @@
   } else {
     uint64_t end = std::min(addr + size, iter->first + iter->second.size);
     if (addr >= end) {
+      *out_size = 0;
       return false;
     }
     *out_size = end - addr;
   }
 
+  if (!iter->second.HasTranslation()) {
+    return false;
+  }
+
   *out_addr = TranslateWithEntry(iter, addr);
   return true;
 }
@@ -226,7 +228,7 @@
 // span several section mappings.  If we really wanted to get particular here,
 // we could pass a parameter indicating whether such spanning is expected, and
 // warn if not.
-void RangeMap::AddRangeWithTranslation(uint64_t addr, uint64_t size,
+bool RangeMap::AddRangeWithTranslation(uint64_t addr, uint64_t size,
                                        const std::string& val,
                                        const RangeMap& translator,
                                        RangeMap* other) {
@@ -240,6 +242,7 @@
     end = addr + size;
     assert(end >= addr);
   }
+  uint64_t total_size = 0;
 
   // TODO: optionally warn about when we span ranges of the translator.  In some
   // cases this would be a bug (ie. symbols VM->file).  In other cases it's
@@ -255,8 +258,11 @@
       }
       other->AddRange(this_addr, this_size, val);
     }
+    total_size += this_size;
     ++it;
   }
+
+  return total_size == size;
 }
 
 }  // namespace bloaty
diff --git a/src/range_map.h b/src/range_map.h
index f2dfc0f..c227382 100644
--- a/src/range_map.h
+++ b/src/range_map.h
@@ -63,7 +63,11 @@
   // to |other| (in domain D2), using |translator| (in domain D1) to translate
   // D1->D2.  The translation is performed using information from previous
   // AddDualRange() calls on |translator|.
-  void AddRangeWithTranslation(uint64_t addr, uint64_t size,
+  //
+  // Returns true if the entire range [addr, size] was present in the
+  // |translator| map.  (This does not necessarily mean that every part of the
+  // range was actually translated).
+  bool AddRangeWithTranslation(uint64_t addr, uint64_t size,
                                const std::string& val,
                                const RangeMap& translator, RangeMap* other);
 
@@ -270,9 +274,24 @@
       // Starting a new continuous range: all iterators must start at the same
       // place.
       current = iters[0]->first;
-      for (auto iter : iters) {
-        assert(iter->first == current);
-        keys.push_back(iter->second.label);
+      for (int i = 0; i < range_maps.size(); i++)  {
+        if (range_maps[i]->IterIsEnd(iters[i])) {
+          printf(
+              "Error, no more ranges for index %d but we need one "
+              "to match (%s)\n",
+              i, range_maps[0]->EntryDebugString(iters[0]).c_str());
+          assert(false);
+          throw std::runtime_error("No more ranges.");
+        } else if (iters[i]->first != current) {
+          printf(
+              "Error, range (%s) doesn't cover the beginning of base range "
+              "(%s)\n",
+              range_maps[i]->EntryDebugString(iters[i]).c_str(),
+              range_maps[0]->EntryDebugString(iters[0]).c_str());
+          assert(false);
+          throw std::runtime_error("No more ranges.");
+        }
+        keys.push_back(iters[i]->second.label);
       }
     }