Fix potential crashes when Target::make_symbol() returns NULL.
[deliverable/binutils-gdb.git] / gold / dwarf_reader.cc
index df14bd5ad3e53107a5bf725ec7ab11a8312eb58b..769d3d8825d47a2e73af3f420d7e797f6e515465 100644 (file)
@@ -1,6 +1,6 @@
 // dwarf_reader.cc -- parse dwarf2/3 debug information
 
-// Copyright (C) 2007-2014 Free Software Foundation, Inc.
+// Copyright (C) 2007-2016 Free Software Foundation, Inc.
 // Written by Ian Lance Taylor <iant@google.com>.
 
 // This file is part of gold.
@@ -580,6 +580,12 @@ Dwarf_pubnames_table::read_header(off_t offset)
     }
   this->end_of_table_ = pinfo + unit_length;
 
+  // If unit_length is too big, maybe we should reject the whole table,
+  // but in cases we know about, it seems OK to assume that the table
+  // is valid through the actual end of the section.
+  if (this->end_of_table_ > this->buffer_end_)
+    this->end_of_table_ = this->buffer_end_;
+
   // Check the version.
   unsigned int version = this->dwinfo_->read_from_pointer<16>(pinfo);
   pinfo += 2;
@@ -2199,13 +2205,33 @@ Sized_dwarf_line_info<size, big_endian>::do_addr2line(
     return "";
 
   std::string result = this->format_file_lineno(*it);
+  gold_debug(DEBUG_LOCATION, "do_addr2line: canonical result: %s",
+            result.c_str());
   if (other_lines != NULL)
-    for (++it; it != offsets->end() && it->offset == offset; ++it)
-      {
-        if (it->line_num == -1)
-          continue;  // The end of a previous function.
-        other_lines->push_back(this->format_file_lineno(*it));
-      }
+    {
+      unsigned int last_file_num = it->file_num;
+      int last_line_num = it->line_num;
+      // Return up to 4 more locations from the beginning of the function
+      // for fuzzy matching.
+      for (++it; it != offsets->end(); ++it)
+       {
+         if (it->offset == offset && it->line_num == -1)
+           continue;  // The end of a previous function.
+         if (it->line_num == -1)
+           break;  // The end of the current function.
+         if (it->file_num != last_file_num || it->line_num != last_line_num)
+           {
+             other_lines->push_back(this->format_file_lineno(*it));
+             gold_debug(DEBUG_LOCATION, "do_addr2line: other: %s",
+                        other_lines->back().c_str());
+             last_file_num = it->file_num;
+             last_line_num = it->line_num;
+           }
+         if (it->offset > offset && other_lines->size() >= 4)
+           break;
+       }
+    }
+
   return result;
 }
 
This page took 0.026461 seconds and 4 git commands to generate.