merge from gcc
[deliverable/binutils-gdb.git] / bfd / dwarf2.c
index 37d68f9b9e67dca9cf9801339f28615a47911b7a..d0b50ff9a1796759bb4acfc4be17604a919fcf57 100644 (file)
@@ -1,6 +1,6 @@
 /* DWARF 2 support.
    Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
-   2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+   2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
 
    Adapted from gdb/dwarf2read.c by Gavin Koch of Cygnus Solutions
    (gavin@cygnus.com).
@@ -967,7 +967,18 @@ add_line_info (struct line_info_table *table,
 
      Note: we may receive duplicate entries from 'decode_line_info'.  */
 
-  if (!table->last_line
+  if (table->last_line
+      && table->last_line->address == address
+      && table->last_line->end_sequence == end_sequence)
+    {
+      /* We only keep the last entry with the same address and end
+        sequence.  See PR ld/4986.  */
+      if (table->lcl_head == table->last_line)
+       table->lcl_head = info;
+      info->prev_line = table->last_line->prev_line;
+      table->last_line = info;
+    }
+  else if (!table->last_line
       || new_line_sorts_after (info, table->last_line))
     {
       /* Normal case: add 'info' to the beginning of the list */
@@ -3057,6 +3068,10 @@ find_line (bfd *abfd,
        {
          each = parse_comp_unit (stash, length, info_ptr_unit,
                                  offset_size);
+         if (!each)
+           /* The dwarf information is damaged, don't trust it any
+              more.  */
+           break;
          stash->info_ptr += length;
 
          if ((bfd_vma) (stash->info_ptr - stash->sec_info_ptr)
@@ -3066,40 +3081,37 @@ find_line (bfd *abfd,
              stash->sec_info_ptr = stash->info_ptr;
            }
 
-         if (each)
-           {
-             if (stash->all_comp_units)
-               stash->all_comp_units->prev_unit = each;
-             else
-               stash->last_comp_unit = each;
-
-             each->next_unit = stash->all_comp_units;
-             stash->all_comp_units = each;
-
-             /* DW_AT_low_pc and DW_AT_high_pc are optional for
-                compilation units.  If we don't have them (i.e.,
-                unit->high == 0), we need to consult the line info
-                table to see if a compilation unit contains the given
-                address.  */
-             if (do_line)
-               found = (((symbol->flags & BSF_FUNCTION) == 0
-                         || each->arange.high == 0
-                         || comp_unit_contains_address (each, addr))
-                        && comp_unit_find_line (each, symbol, addr,
-                                                filename_ptr,
-                                                linenumber_ptr,
-                                                stash));
-             else
-               found = ((each->arange.high == 0
-                         || comp_unit_contains_address (each, addr))
-                        && comp_unit_find_nearest_line (each, addr,
-                                                        filename_ptr,
-                                                        functionname_ptr,
-                                                        linenumber_ptr,
-                                                        stash));
-             if (found)
-               goto done;
-           }
+         if (stash->all_comp_units)
+           stash->all_comp_units->prev_unit = each;
+         else
+           stash->last_comp_unit = each;
+         
+         each->next_unit = stash->all_comp_units;
+         stash->all_comp_units = each;
+         
+         /* DW_AT_low_pc and DW_AT_high_pc are optional for
+            compilation units.  If we don't have them (i.e.,
+            unit->high == 0), we need to consult the line info table
+            to see if a compilation unit contains the given
+            address.  */
+         if (do_line)
+           found = (((symbol->flags & BSF_FUNCTION) == 0
+                     || each->arange.high == 0
+                     || comp_unit_contains_address (each, addr))
+                    && comp_unit_find_line (each, symbol, addr,
+                                            filename_ptr,
+                                            linenumber_ptr,
+                                            stash));
+         else
+           found = ((each->arange.high == 0
+                     || comp_unit_contains_address (each, addr))
+                    && comp_unit_find_nearest_line (each, addr,
+                                                    filename_ptr,
+                                                    functionname_ptr,
+                                                    linenumber_ptr,
+                                                    stash));
+         if (found)
+           goto done;
        }
     }
 
This page took 0.024355 seconds and 4 git commands to generate.