This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

bfd_find_nearest_line on powerpc64


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]