public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* bfd_find_nearest_line on powerpc64
@ 2012-01-23  5:54 Alan Modra
  2012-02-07  7:05 ` Alan Modra
  0 siblings, 1 reply; 2+ messages in thread
From: Alan Modra @ 2012-01-23  5:54 UTC (permalink / raw)
  To: binutils

This fixes a problem we see on powerpc64 with bfd_find_nearest_line,
used by tools like addr2line and in linker error messages.  Absent
debug info, bfd_find_nearest_line fals back to inspecting the ELF
symbol table (elf.c:elf_find_function).  That doesn't work so well on
final linked executables, since global symbols can't be reliably
associated with input files using FILE symbols.  Even worse on
PowerPC64, a function symbol is defined on an OPD entry rather than at
the start of the function's code.  So given an address, addr2line
fails to find the function name let alone the source file.  Instead
you match some linker created stub symbol in .text, which is nonsense.

	* elf-bfd.h: Formatting.
	(struct elf_backend_data): Add "maybe_function_sym".
	(_bfd_elf_maybe_function_sym): Declare.
	* elfxx-target.h (elf_backend_maybe_function_sym): Define.
	(elfNN_bed): Init new field.
	* elf.c (elf_find_function): Use maybe_function_sym.
	(_bfd_elf_maybe_function_sym): New function.
	* elf64-ppc.c (elf_backend_maybe_function_sym): Define.
	(ppc64_elf_maybe_function_sym): New function.

Index: bfd/elf-bfd.h
===================================================================
RCS file: /cvs/src/src/bfd/elf-bfd.h,v
retrieving revision 1.331
diff -u -p -r1.331 elf-bfd.h
--- bfd/elf-bfd.h	13 Dec 2011 14:02:18 -0000	1.331
+++ bfd/elf-bfd.h	23 Jan 2012 01:38:19 -0000
@@ -1221,6 +1221,11 @@ struct elf_backend_data
   /* Return TRUE if type is a function symbol type.  */
   bfd_boolean (*is_function_type) (unsigned int type);
 
+  /* Return TRUE if symbol may be a function.  Set *CODE_SEC and *CODE_VAL
+     to the function's entry point.  */
+  bfd_boolean (*maybe_function_sym) (const elf_symbol_type *sym,
+				     asection **code_sec, bfd_vma *code_off);
+
   /* Used to handle bad SHF_LINK_ORDER input.  */
   bfd_error_handler_type link_order_error_handler;
 
@@ -1413,14 +1418,14 @@ struct bfd_elf_section_data
   void *sec_info;
 };
 
-#define elf_section_data(sec)  ((struct bfd_elf_section_data*)(sec)->used_by_bfd)
+#define elf_section_data(sec) ((struct bfd_elf_section_data*)(sec)->used_by_bfd)
 #define elf_linked_to_section(sec) (elf_section_data(sec)->linked_to)
-#define elf_section_type(sec)  (elf_section_data(sec)->this_hdr.sh_type)
-#define elf_section_flags(sec) (elf_section_data(sec)->this_hdr.sh_flags)
-#define elf_group_name(sec)    (elf_section_data(sec)->group.name)
-#define elf_group_id(sec)      (elf_section_data(sec)->group.id)
-#define elf_next_in_group(sec) (elf_section_data(sec)->next_in_group)
-#define elf_fde_list(sec)      (elf_section_data(sec)->fde_list)
+#define elf_section_type(sec)	(elf_section_data(sec)->this_hdr.sh_type)
+#define elf_section_flags(sec)	(elf_section_data(sec)->this_hdr.sh_flags)
+#define elf_group_name(sec)	(elf_section_data(sec)->group.name)
+#define elf_group_id(sec)	(elf_section_data(sec)->group.id)
+#define elf_next_in_group(sec)	(elf_section_data(sec)->next_in_group)
+#define elf_fde_list(sec)	(elf_section_data(sec)->fde_list)
 #define elf_sec_group(sec)	(elf_section_data(sec)->sec_group)
 
 #define xvec_get_elf_backend_data(xvec) \
@@ -2197,6 +2202,9 @@ extern bfd_boolean _bfd_elf_map_sections
 
 extern bfd_boolean _bfd_elf_is_function_type (unsigned int);
 
+extern bfd_boolean _bfd_elf_maybe_function_sym (const elf_symbol_type *,
+						asection **, bfd_vma *);
+
 extern int bfd_elf_get_default_section_type (flagword);
 
 extern void bfd_elf_lookup_section_flags
Index: bfd/elfxx-target.h
===================================================================
RCS file: /cvs/src/src/bfd/elfxx-target.h,v
retrieving revision 1.128
diff -u -p -r1.128 elfxx-target.h
--- bfd/elfxx-target.h	28 Jul 2011 17:39:20 -0000	1.128
+++ bfd/elfxx-target.h	23 Jan 2012 01:38:45 -0000
@@ -655,6 +655,10 @@
 #define elf_backend_is_function_type _bfd_elf_is_function_type
 #endif
 
+#ifndef elf_backend_maybe_function_sym
+#define elf_backend_maybe_function_sym _bfd_elf_maybe_function_sym
+#endif
+
 #ifndef elf_match_priority
 #define elf_match_priority \
   (ELF_ARCH == bfd_arch_unknown ? 2 : ELF_OSABI == ELFOSABI_NONE ? 1 : 0)
@@ -750,6 +754,7 @@ static struct elf_backend_data elfNN_bed
   elf_backend_merge_symbol,
   elf_backend_hash_symbol,
   elf_backend_is_function_type,
+  elf_backend_maybe_function_sym,
   elf_backend_link_order_error_handler,
   elf_backend_relplt_name,
   ELF_MACHINE_ALT1,
Index: bfd/elf.c
===================================================================
RCS file: /cvs/src/src/bfd/elf.c,v
retrieving revision 1.546
diff -u -p -r1.546 elf.c
--- bfd/elf.c	13 Dec 2011 14:02:18 -0000	1.546
+++ bfd/elf.c	23 Jan 2012 01:38:24 -0000
@@ -7406,6 +7406,8 @@ elf_find_function (bfd *abfd,
     {
       elf_symbol_type *q;
       unsigned int type;
+      asection *code_sec;
+      bfd_vma code_off;
 
       q = (elf_symbol_type *) *p;
 
@@ -7418,15 +7420,13 @@ elf_find_function (bfd *abfd,
 	    state = file_after_symbol_seen;
 	  continue;
 	default:
-	  if (!bed->is_function_type (type))
-	    break;
-	case STT_NOTYPE:
-	  if (bfd_get_section (&q->symbol) == section
-	      && q->symbol.value >= low_func
-	      && q->symbol.value <= offset)
+	  if (bed->maybe_function_sym (q, &code_sec, &code_off)
+	      && code_sec == section
+	      && code_off >= low_func
+	      && code_off <= offset)
 	    {
 	      func = (asymbol *) q;
-	      low_func = q->symbol.value;
+	      low_func = code_off;
 	      filename = NULL;
 	      if (file != NULL
 		  && (ELF_ST_BIND (q->internal_elf_sym.st_info) == STB_LOCAL
@@ -9686,3 +9686,22 @@ _bfd_elf_is_function_type (unsigned int 
   return (type == STT_FUNC
 	  || type == STT_GNU_IFUNC);
 }
+
+/* Return TRUE iff the ELF symbol SYM might be a function.  Set *CODE_SEC
+   and *CODE_OFF to the function's entry point.  */
+
+bfd_boolean
+_bfd_elf_maybe_function_sym (const elf_symbol_type *sym,
+			     asection **code_sec, bfd_vma *code_off)
+{
+  unsigned int type = ELF_ST_TYPE (sym->internal_elf_sym.st_info);
+  if (type == STT_NOTYPE
+      || type == STT_FUNC
+      || type == STT_GNU_IFUNC)
+    {
+      *code_sec = sym->symbol.section;
+      *code_off = sym->symbol.value;
+      return TRUE;
+    }
+  return FALSE;
+}
Index: bfd/elf64-ppc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-ppc.c,v
retrieving revision 1.374
diff -u -p -r1.374 elf64-ppc.c
--- bfd/elf64-ppc.c	16 Jan 2012 22:30:19 -0000	1.374
+++ bfd/elf64-ppc.c	23 Jan 2012 05:11:38 -0000
@@ -105,6 +105,7 @@ static bfd_vma opd_entry_value
 #define elf_backend_gc_sweep_hook	      ppc64_elf_gc_sweep_hook
 #define elf_backend_adjust_dynamic_symbol     ppc64_elf_adjust_dynamic_symbol
 #define elf_backend_hide_symbol		      ppc64_elf_hide_symbol
+#define elf_backend_maybe_function_sym	      ppc64_elf_maybe_function_sym
 #define elf_backend_always_size_sections      ppc64_elf_func_desc_adjust
 #define elf_backend_size_dynamic_sections     ppc64_elf_size_dynamic_sections
 #define elf_backend_init_index_section	      _bfd_elf_init_2_index_sections
@@ -5528,7 +5529,8 @@ opd_entry_value (asection *opd_sec,
   Elf_Internal_Rela *lo, *hi, *look;
   bfd_vma val;
 
-  /* No relocs implies we are linking a --just-symbols object.  */
+  /* No relocs implies we are linking a --just-symbols object, or looking
+     at a final linked executable with addr2line or somesuch.  */
   if (opd_sec->reloc_count == 0)
     {
       char buf[8];
@@ -5631,6 +5633,23 @@ opd_entry_value (asection *opd_sec,
   return val;
 }
 
+/* Return TRUE iff the ELF symbol SYM might be a function.  Set *CODE_SEC
+   and *CODE_OFF to the function's entry point.  */
+
+static bfd_boolean
+ppc64_elf_maybe_function_sym (const elf_symbol_type *sym,
+			      asection **code_sec, bfd_vma *code_off)
+{
+  if (_bfd_elf_maybe_function_sym (sym, code_sec, code_off))
+    {
+      if (strcmp (sym->symbol.section->name, ".opd") == 0)
+	opd_entry_value (sym->symbol.section, sym->symbol.value,
+			 code_sec, code_off);
+      return TRUE;
+    }
+  return FALSE;
+}
+
 /* Return true if symbol is defined in a regular object file.  */
 
 static bfd_boolean

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: bfd_find_nearest_line on powerpc64
  2012-01-23  5:54 bfd_find_nearest_line on powerpc64 Alan Modra
@ 2012-02-07  7:05 ` Alan Modra
  0 siblings, 0 replies; 2+ messages in thread
From: Alan Modra @ 2012-02-07  7:05 UTC (permalink / raw)
  To: binutils

On Mon, Jan 23, 2012 at 04:24:19PM +1030, Alan Modra wrote:
> This fixes a problem we see on powerpc64 with bfd_find_nearest_line,
> used by tools like addr2line and in linker error messages.

So that didn't quite do the trick for oprofile (opreport really),
where synthetic symbols are included in the set of syms passed to
bfd_find_nearest_line.  The trouble is that a synthetic symbol is just
an asymbol;  They don't have the internal_elf_sym part of
elf_symbol_type.  Fortunately there wasn't any real need for
elf_find_function to look at that part of elf_symbol_type.

	* elf.c (elf_find_function): Don't use internal_elf_sym.
	(_bfd_elf_maybe_function_sym): Likewise.  Replace elf_symbol_type
	parameter with asymbol.
	* elf64-ppc.c (ppc64_elf_maybe_function_sym): Likewise.
	* elf-bfd.h (_bfd_elf_maybe_function_sym): Update prototype.
	(struct elf_backend_data <maybe_function_sym>): Likewise.

Index: bfd/elf-bfd.h
===================================================================
RCS file: /cvs/src/src/bfd/elf-bfd.h,v
retrieving revision 1.332
diff -u -p -r1.332 elf-bfd.h
--- bfd/elf-bfd.h	23 Jan 2012 06:16:37 -0000	1.332
+++ bfd/elf-bfd.h	7 Feb 2012 01:38:18 -0000
@@ -1223,7 +1223,7 @@ struct elf_backend_data
 
   /* Return TRUE if symbol may be a function.  Set *CODE_SEC and *CODE_VAL
      to the function's entry point.  */
-  bfd_boolean (*maybe_function_sym) (const elf_symbol_type *sym,
+  bfd_boolean (*maybe_function_sym) (const asymbol *sym,
 				     asection **code_sec, bfd_vma *code_off);
 
   /* Used to handle bad SHF_LINK_ORDER input.  */
@@ -2202,7 +2202,7 @@ extern bfd_boolean _bfd_elf_map_sections
 
 extern bfd_boolean _bfd_elf_is_function_type (unsigned int);
 
-extern bfd_boolean _bfd_elf_maybe_function_sym (const elf_symbol_type *,
+extern bfd_boolean _bfd_elf_maybe_function_sym (const asymbol *,
 						asection **, bfd_vma *);
 
 extern int bfd_elf_get_default_section_type (flagword);
Index: bfd/elf.c
===================================================================
RCS file: /cvs/src/src/bfd/elf.c,v
retrieving revision 1.548
diff -u -p -r1.548 elf.c
--- bfd/elf.c	23 Jan 2012 06:16:37 -0000	1.548
+++ bfd/elf.c	7 Feb 2012 01:38:22 -0000
@@ -7404,36 +7404,30 @@ elf_find_function (bfd *abfd,
 
   for (p = symbols; *p != NULL; p++)
     {
-      elf_symbol_type *q;
-      unsigned int type;
+      asymbol *sym = *p;
       asection *code_sec;
       bfd_vma code_off;
 
-      q = (elf_symbol_type *) *p;
-
-      type = ELF_ST_TYPE (q->internal_elf_sym.st_info);
-      switch (type)
+      if ((sym->flags & BSF_FILE) != 0)
 	{
-	case STT_FILE:
-	  file = &q->symbol;
+	  file = sym;
 	  if (state == symbol_seen)
 	    state = file_after_symbol_seen;
 	  continue;
-	default:
-	  if (bed->maybe_function_sym (q, &code_sec, &code_off)
-	      && code_sec == section
-	      && code_off >= low_func
-	      && code_off <= offset)
-	    {
-	      func = (asymbol *) q;
-	      low_func = code_off;
-	      filename = NULL;
-	      if (file != NULL
-		  && (ELF_ST_BIND (q->internal_elf_sym.st_info) == STB_LOCAL
-		      || state != file_after_symbol_seen))
-		filename = bfd_asymbol_name (file);
-	    }
-	  break;
+	}
+
+      if (bed->maybe_function_sym (sym, &code_sec, &code_off)
+	  && code_sec == section
+	  && code_off >= low_func
+	  && code_off <= offset)
+	{
+	  func = sym;
+	  low_func = code_off;
+	  filename = NULL;
+	  if (file != NULL
+	      && ((sym->flags & BSF_LOCAL) != 0
+		  || state != file_after_symbol_seen))
+	    filename = bfd_asymbol_name (file);
 	}
       if (state == nothing_seen)
 	state = symbol_seen;
@@ -9695,17 +9689,14 @@ _bfd_elf_is_function_type (unsigned int 
    and *CODE_OFF to the function's entry point.  */
 
 bfd_boolean
-_bfd_elf_maybe_function_sym (const elf_symbol_type *sym,
+_bfd_elf_maybe_function_sym (const asymbol *sym,
 			     asection **code_sec, bfd_vma *code_off)
 {
-  unsigned int type = ELF_ST_TYPE (sym->internal_elf_sym.st_info);
-  if (type == STT_NOTYPE
-      || type == STT_FUNC
-      || type == STT_GNU_IFUNC)
-    {
-      *code_sec = sym->symbol.section;
-      *code_off = sym->symbol.value;
-      return TRUE;
-    }
-  return FALSE;
+  if ((sym->flags & (BSF_SECTION_SYM | BSF_FILE | BSF_OBJECT
+		     | BSF_THREAD_LOCAL | BSF_RELC | BSF_SRELC)) != 0)
+    return FALSE;
+
+  *code_sec = sym->section;
+  *code_off = sym->value;
+  return TRUE;
 }
Index: bfd/elf64-ppc.c
===================================================================
RCS file: /cvs/src/src/bfd/elf64-ppc.c,v
retrieving revision 1.375
diff -u -p -r1.375 elf64-ppc.c
--- bfd/elf64-ppc.c	23 Jan 2012 06:16:38 -0000	1.375
+++ bfd/elf64-ppc.c	7 Feb 2012 01:38:34 -0000
@@ -5637,14 +5637,13 @@ opd_entry_value (asection *opd_sec,
    and *CODE_OFF to the function's entry point.  */
 
 static bfd_boolean
-ppc64_elf_maybe_function_sym (const elf_symbol_type *sym,
+ppc64_elf_maybe_function_sym (const asymbol *sym,
 			      asection **code_sec, bfd_vma *code_off)
 {
   if (_bfd_elf_maybe_function_sym (sym, code_sec, code_off))
     {
-      if (strcmp (sym->symbol.section->name, ".opd") == 0)
-	opd_entry_value (sym->symbol.section, sym->symbol.value,
-			 code_sec, code_off);
+      if (strcmp (sym->section->name, ".opd") == 0)
+	opd_entry_value (sym->section, sym->value, code_sec, code_off);
       return TRUE;
     }
   return FALSE;

-- 
Alan Modra
Australia Development Lab, IBM

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2012-02-07  7:05 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-01-23  5:54 bfd_find_nearest_line on powerpc64 Alan Modra
2012-02-07  7:05 ` Alan Modra

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).