diff mbox

Fix libbacktrace on prelinked shared libraries

Message ID 20131118164602.GI892@tucnak.redhat.com
State New
Headers show

Commit Message

Jakub Jelinek Nov. 18, 2013, 4:46 p.m. UTC
On Mon, Nov 18, 2013 at 08:29:05AM -0800, Ian Lance Taylor wrote:
> On Mon, Nov 18, 2013 at 5:11 AM, Jakub Jelinek <jakub@redhat.com> wrote:
> >
> > info->dlpi_addr == 0 is true for executables (but those have also
> > info->dlpi_name set to ""), but not just for those, it is true also
> > for successfully prelinked shared libraries or any other libraries that
> > have been linked at non-zero offset and the dynamic linker managed to mmap
> > them where they were prelinked resp. linked to.
> >
> > BTW, I'm surprised you aren't adding base_address (well, in fact it is
> > actually not base address, but load bias, difference between load address
> > and link base address) to elf_initialize_syminfo created symbol addresses,
> > because all of them should be biased by the load address.
> > And, elf_initialize_syminfo should ignore st_shndx == SHN_UNDEF symbols,
> > those shouldn't be biased but not even entered into the table.
> 
> You're right, these are bugs.

So what about this fix then?

Tested on a short testcase that links against a shared library without
debug info and looks up the symbol using backtrace_syminfo.
make check in libbacktrace also passes.

2013-11-18  Jakub Jelinek  <jakub@redhat.com>

	* elf.c (SHN_UNDEF): Define.
	(elf_initialize_syminfo): Add base_address argument.  Ignore symbols
	with st_shndx == SHN_UNDEF.  Add base_address to address fields.
	(elf_add): Adjust caller.



	Jakub

Comments

Ian Lance Taylor Nov. 18, 2013, 5:10 p.m. UTC | #1
On Mon, Nov 18, 2013 at 8:46 AM, Jakub Jelinek <jakub@redhat.com> wrote:
>
> 2013-11-18  Jakub Jelinek  <jakub@redhat.com>
>
>         * elf.c (SHN_UNDEF): Define.
>         (elf_initialize_syminfo): Add base_address argument.  Ignore symbols
>         with st_shndx == SHN_UNDEF.  Add base_address to address fields.
>         (elf_add): Adjust caller.

This is OK.

Thanks.

Ian
diff mbox

Patch

--- libbacktrace/elf.c.jj	2013-11-18 12:48:07.000000000 +0100
+++ libbacktrace/elf.c	2013-11-18 17:41:38.903835173 +0100
@@ -98,6 +98,7 @@  dl_iterate_phdr (int (*callback) (struct
 #undef EV_CURRENT
 #undef SHN_LORESERVE
 #undef SHN_XINDEX
+#undef SHN_UNDEF
 #undef SHT_SYMTAB
 #undef SHT_STRTAB
 #undef SHT_DYNSYM
@@ -183,6 +184,7 @@  typedef struct {
   b_elf_wxword	sh_entsize;		/* Entry size if section holds table */
 } b_elf_shdr;  /* Elf_Shdr.  */
 
+#define SHN_UNDEF	0x0000		/* Undefined section */
 #define SHN_LORESERVE	0xFF00		/* Begin range of reserved indices */
 #define SHN_XINDEX	0xFFFF		/* Section index is held elsewhere */
 
@@ -342,6 +344,7 @@  elf_symbol_search (const void *vkey, con
 
 static int
 elf_initialize_syminfo (struct backtrace_state *state,
+			uintptr_t base_address,
 			const unsigned char *symtab_data, size_t symtab_size,
 			const unsigned char *strtab, size_t strtab_size,
 			backtrace_error_callback error_callback,
@@ -365,7 +368,8 @@  elf_initialize_syminfo (struct backtrace
       int info;
 
       info = sym->st_info & 0xf;
-      if (info == STT_FUNC || info == STT_OBJECT)
+      if ((info == STT_FUNC || info == STT_OBJECT)
+	  && sym->st_shndx != SHN_UNDEF)
 	++elf_symbol_count;
     }
 
@@ -385,6 +389,8 @@  elf_initialize_syminfo (struct backtrace
       info = sym->st_info & 0xf;
       if (info != STT_FUNC && info != STT_OBJECT)
 	continue;
+      if (sym->st_shndx == SHN_UNDEF)
+	continue;
       if (sym->st_name >= strtab_size)
 	{
 	  error_callback (data, "symbol string index out of range", 0);
@@ -393,7 +399,7 @@  elf_initialize_syminfo (struct backtrace
 	  return 0;
 	}
       elf_symbols[j].name = (const char *) strtab + sym->st_name;
-      elf_symbols[j].address = sym->st_value;
+      elf_symbols[j].address = sym->st_value + base_address;
       elf_symbols[j].size = sym->st_size;
       ++j;
     }
@@ -733,7 +739,7 @@  elf_add (struct backtrace_state *state,
       if (sdata == NULL)
 	goto fail;
 
-      if (!elf_initialize_syminfo (state,
+      if (!elf_initialize_syminfo (state, base_address,
 				   symtab_view.data, symtab_shdr->sh_size,
 				   strtab_view.data, strtab_shdr->sh_size,
 				   error_callback, data, sdata))