PATCH: binutils/2096: addr2line fails on linux-kernel

H. J. Lu hjl@lucon.org
Sat Dec 31 20:25:00 GMT 2005


There are 2 bugs in dwarf2.c. BFD section's lvm is not very useful
for ELF since ELF section doesn't have it and it is made up by bfd:

[hjl@gnu-3 addr2line]$ readelf -S vmlinux
There are 41 section headers, starting at offset 0x20f06bc:

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .text             PROGBITS        c0100000 001000 226f60 00  AX  0   0 16
...
[hjl@gnu-3 addr2line]$ objdump -h  vmlinux

vmlinux:     file format elf32-i386

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .text         00226f60  c0100000  00100000  00001000  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE

dwarf2.c should use vma for ELF.

The section bug is when comp_unit_contains_address return TRUE,
it doesn't necessary mean a compilation unit really contains the
given address. It may happen when "asm" is used to define functions
like arch/i386/kernel/semaphore.c in the Linux 2.6.14 kernel. My
patch checks the line info table to make sure that a compilation
unit really contains the given address.


H.J.
-------------- next part --------------
2005-12-31  H.J. Lu  <hongjiu.lu@intel.com>

	PR binutils/2096
	* dwarf2.c (_bfd_dwarf2_find_nearest_line): Use section's vma,
	instead of lvm for ELF.

--- bfd/dwarf2.c.addr	2005-12-27 12:35:54.000000000 -0800
+++ bfd/dwarf2.c	2005-12-31 12:05:36.000000000 -0800
@@ -2209,10 +2209,21 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd
 
   stash = *pinfo;
   addr = offset;
-  if (section->output_section)
-    addr += section->output_section->lma + section->output_offset;
+  if (abfd->xvec->flavour == bfd_target_elf_flavour)
+    {
+      if (section->output_section)
+	addr += section->output_section->vma + section->output_offset;
+      else
+	addr += section->vma;
+    }
   else
-    addr += section->lma;
+    {
+      if (section->output_section)
+	addr += section->output_section->lma + section->output_offset;
+      else
+	addr += section->lma;
+    }
+
   *filename_ptr = NULL;
   *functionname_ptr = NULL;
   *linenumber_ptr = 0;
@@ -2418,10 +2429,20 @@ _bfd_dwarf2_find_line (bfd *abfd,
   section = bfd_get_section (symbol);
 
   addr = symbol->value;
-  if (section->output_section)
-    addr += section->output_section->lma + section->output_offset;
+  if (abfd->xvec->flavour == bfd_target_elf_flavour)
+    {
+      if (section->output_section)
+	addr += section->output_section->vma + section->output_offset;
+      else
+	addr += section->vma;
+    }
   else
-    addr += section->lma;
+    {
+      if (section->output_section)
+	addr += section->output_section->lma + section->output_offset;
+      else
+	addr += section->lma;
+    }
 
   *filename_ptr = NULL;
   stash = *pinfo;
-------------- next part --------------
2005-12-31  H.J. Lu  <hongjiu.lu@intel.com>

	PR binutils/2096
	* dwarf2.c (comp_unit_contains_address): Update comment.
	(_bfd_dwarf2_find_nearest_line): Return TRUE only if both
	comp_unit_contains_address and comp_unit_find_nearest_line
	return TRUE.

--- bfd/dwarf2.c.unit	2005-12-31 09:12:48.000000000 -0800
+++ bfd/dwarf2.c	2005-12-31 11:49:06.000000000 -0800
@@ -2006,7 +2006,9 @@ parse_comp_unit (bfd *abfd,
   return unit;
 }
 
-/* Return TRUE if UNIT contains the address given by ADDR.  */
+/* Return TRUE if UNIT may contain the address given by ADDR.  We need
+   to consult the line info table to see if a compilation unit really
+   contains the given address.  */
 
 static bfd_boolean
 comp_unit_contains_address (struct comp_unit *unit, bfd_vma addr)
@@ -2293,16 +2295,16 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd
 
   /* Check the previously read comp. units first.  */
   for (each = stash->all_comp_units; each; each = each->next_unit)
-    if (comp_unit_contains_address (each, addr))
-      return comp_unit_find_nearest_line (each, addr, filename_ptr,
-					  functionname_ptr, linenumber_ptr,
-					  stash);
+    if (comp_unit_contains_address (each, addr)
+	&& comp_unit_find_nearest_line (each, addr, filename_ptr,
+					functionname_ptr,
+					linenumber_ptr, stash))
+      return TRUE;
 
   /* Read each remaining comp. units checking each as they are read.  */
   while (stash->info_ptr < stash->info_ptr_end)
     {
       bfd_vma length;
-      bfd_boolean found;
       unsigned int offset_size = addr_size;
       bfd_byte *info_ptr_unit = stash->info_ptr;
 
@@ -2358,25 +2360,14 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd
 		 unit->high == 0), we need to consult the line info
 		 table to see if a compilation unit contains the given
 		 address.  */
-	      if (each->arange.high > 0)
-		{
-		  if (comp_unit_contains_address (each, addr))
-		    return comp_unit_find_nearest_line (each, addr,
-							filename_ptr,
-							functionname_ptr,
-							linenumber_ptr,
-							stash);
-		}
-	      else
-		{
-		  found = comp_unit_find_nearest_line (each, addr,
-						       filename_ptr,
-						       functionname_ptr,
-						       linenumber_ptr,
-						       stash);
-		  if (found)
-		    return TRUE;
-		}
+	      if ((each->arange.high == 0
+		   || comp_unit_contains_address (each, addr))
+		  && comp_unit_find_nearest_line (each, addr,
+						  filename_ptr,
+						  functionname_ptr,
+						  linenumber_ptr,
+						  stash))
+		return TRUE;
 	    }
 	}
     }


More information about the Binutils mailing list