This is the mail archive of the elfutils-devel@sourceware.org mailing list for the elfutils 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]

[patchv3 4/4] Provide virtual symbols for ppc64 function descriptors


Hi Mark,

jankratochvil/ppc64bidir

obsoletes:
	[patch 3/3] ppc64 .opd: Bidirectional provider
	https://lists.fedorahosted.org/pipermail/elfutils-devel/2012-December/002840.html

here is the new variant of bi-directional ppc64 .opd resolver.


Thanks,
Jan

commit cbfa801a935c078bab41b85fc024d4028a84cfe8
Author: Jan Kratochvil <jan.kratochvil@redhat.com>
Date:   Wed Nov 6 20:38:05 2013 +0100

    Provide virtual symbols for ppc64 function descriptors
    
    backends/
    2013-11-13  Jan Kratochvil  <jan.kratochvil@redhat.com>
    
    	Provide virtual symbols for ppc64 function descriptors.
    	* Makefile.am (ppc64_SRCS): Add ppc64_get_symbol.c.
    	* ppc64_get_symbol.c: New file.
    	* ppc64_init.c (ppc64_init): Install init_symbols, get_symbol and
    	destr.
    	* dwfl_module_addrsym.c (dwfl_module_addrsym): Adjust FIRST_GLOBAL also
    	for EBL_FIRST_GLOBAL.
    	* dwfl_module_getdwarf.c (getsym_helper): New function.
    	(find_symtab): Call also ebl_init_symbols.
    	(dwfl_module_getsymtab): Count also EBL_SYMENTS.
    	* dwfl_module_getsym.c (__libdwfl_module_getsym): Count also
    	EBL_FIRST_GLOBAL, EBL_SYMENTS.  Call also ebl_get_symbol.
    	* libdwflP.h (DWFL_ERRORS): Add INVALID_INDEX.
    	(struct Dwfl_Module): Add fields ebl_syments and ebl_first_global.
    
    libebl/
    2013-11-06  Jan Kratochvil  <jan.kratochvil@redhat.com>
    
    	Provide virtual symbols for ppc64 function descriptors.
    	* Makefile.am (gen_SOURCES): Add eblgetsymbol.c.
    	* ebl-hooks.h (init_symbols, get_symbol): New.
    	* eblgetsymbol.c: New file.
    	* libebl.h (ebl_getsym_t): New definition.
    	(ebl_init_symbols, ebl_get_symbol): New declarations.
    	* libeblP.h (struct ebl): New field backend.
    
    tests/
    2013-11-06  Jan Kratochvil  <jan.kratochvil@redhat.com>
    
    	Provide virtual symbols for ppc64 function descriptors.
    	* Makefile.am (EXTRA_DIST): Add testfile66.bz2.
    	* run-addrname-test.sh (testfile66): New test.
    	* testfile66.bz2: New file.
    
    Signed-off-by: Jan Kratochvil <jan.kratochvil@redhat.com>

diff --git a/backends/Makefile.am b/backends/Makefile.am
index 5b5e067..0e00329 100644
--- a/backends/Makefile.am
+++ b/backends/Makefile.am
@@ -94,7 +94,7 @@ am_libebl_ppc_pic_a_OBJECTS = $(ppc_SRCS:.c=.os)
 
 ppc64_SRCS = ppc64_init.c ppc64_symbol.c ppc64_retval.c \
 	     ppc64_corenote.c ppc_regs.c ppc_auxv.c ppc_attrs.c ppc_syscall.c \
-	     ppc_cfi.c
+	     ppc_cfi.c ppc64_get_symbol.c
 libebl_ppc64_pic_a_SOURCES = $(ppc64_SRCS)
 am_libebl_ppc64_pic_a_OBJECTS = $(ppc64_SRCS:.c=.os)
 
diff --git a/backends/ppc64_get_symbol.c b/backends/ppc64_get_symbol.c
new file mode 100644
index 0000000..970dfbd
--- /dev/null
+++ b/backends/ppc64_get_symbol.c
@@ -0,0 +1,194 @@
+/* Provide virtual symbols for ppc64 function descriptors.
+   Copyright (C) 2013 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <endian.h>
+#include <string.h>
+#include <stdlib.h>
+
+#define BACKEND ppc64_
+#include "libebl_CPU.h"
+
+/* Pointer to the first entry is stored into ebl->backend.
+   It has Dwfl_Module->ebl_syments entries and its memory is followed by
+   strings for the NAME entries.  */
+
+struct sym_entry
+{
+  GElf_Sym sym;
+  GElf_Word shndx;
+  void *file;
+  const char *name;
+};
+
+static Elf_Scn *
+scnfindvma (Elf *elf, GElf_Addr vma)
+{
+  Elf_Scn *scn = NULL;
+  while ((scn = elf_nextscn (elf, scn)) != NULL)
+    {
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+      if (likely (shdr != NULL)
+	  && vma >= shdr->sh_addr
+	  && vma < shdr->sh_addr + shdr->sh_size)
+	break;
+    }
+  return scn;
+}
+
+void
+ppc64_init_symbols (Ebl *ebl, size_t syments, int first_global,
+		    GElf_Addr main_bias, ebl_getsym_t *getsym, void *arg,
+		    size_t *ebl_symentsp, int *ebl_first_globalp)
+{
+  assert (ebl != NULL);
+  assert (ebl->backend == NULL);
+  Elf *elf = ebl->elf;
+  assert (*ebl_symentsp == 0);
+  assert (*ebl_first_globalp == 0);
+  GElf_Ehdr ehdr_mem, *ehdr = gelf_getehdr (elf, &ehdr_mem);
+  if (ehdr == NULL)
+    return;
+  GElf_Word opd_shndx = 0;
+  GElf_Shdr opd_shdr_mem, *opd_shdr;
+  Elf_Data *opd_data;
+  Elf_Scn *scn = NULL;
+  while ((scn = elf_nextscn (elf, scn)) != NULL)
+    {
+      opd_shdr = gelf_getshdr (scn, &opd_shdr_mem);
+      if (opd_shdr == NULL)
+	continue;
+      if (strcmp (elf_strptr (elf, ehdr->e_shstrndx, opd_shdr->sh_name), ".opd")
+	  != 0)
+	continue;
+      opd_data = elf_getdata (scn, NULL);
+      /* SHT_NOBITS will produce NULL D_BUF.  */
+      if (opd_data == NULL || opd_data->d_buf == NULL)
+	return;
+      assert (opd_data->d_size == opd_shdr->sh_size);
+      opd_shndx = elf_ndxscn (scn);
+      break;
+    }
+  if (opd_shndx == 0)
+    return;
+  size_t names_size = 0;
+  size_t ebl_syments = 0;
+  int ebl_first_global = 0;
+  for (size_t symi = 0; symi < syments; symi++)
+    {
+      GElf_Sym sym;
+      GElf_Word shndx;
+      const char *symname = getsym (arg, symi, &sym, &shndx, NULL);
+      if (symname == NULL || shndx != opd_shndx)
+	continue;
+      Elf64_Addr val;
+      if (sym.st_value < opd_shdr->sh_addr + main_bias
+          || sym.st_value > (opd_shdr->sh_addr + main_bias
+			     + opd_shdr->sh_size - sizeof (val)))
+	continue;
+      ebl_syments++;
+      if ((ssize_t) symi < first_global)
+	ebl_first_global++;
+      names_size += 1 + strlen (symname) + 1;
+    }
+  if (ebl_syments == 0)
+    return;
+  struct sym_entry *sym_table;
+  sym_table = malloc (ebl_syments * sizeof (*sym_table) + names_size);
+  if (sym_table == NULL)
+    return;
+  struct sym_entry *dest = sym_table;
+  char *names = (void *) &sym_table[ebl_syments];
+  char *names_dest = names;
+  for (size_t symi = 0; symi < syments; symi++)
+    {
+      GElf_Sym sym;
+      GElf_Word shndx;
+      void *file;
+      const char *symname = getsym (arg, symi, &sym, &shndx, &file);
+      if (symname == NULL || shndx != opd_shndx)
+	continue;
+      uint64_t val64;
+      if (sym.st_value < opd_shdr->sh_addr + main_bias
+          || sym.st_value > (opd_shdr->sh_addr + main_bias
+			     + opd_shdr->sh_size - sizeof (val64)))
+	continue;
+      val64 = *(const uint64_t *) (opd_data->d_buf + sym.st_value
+				   - (opd_shdr->sh_addr + main_bias));
+      val64 = (elf_getident (elf, NULL)[EI_DATA] == ELFDATA2MSB
+               ? be64toh (val64) : le64toh (val64));
+      assert ((char *) dest < names);
+      dest->sym = sym;
+      dest->sym.st_value = val64;
+      Elf_Scn *sym_scn = scnfindvma (elf, val64);
+      dest->shndx = sym_scn == NULL ? SHN_ABS : elf_ndxscn (sym_scn);
+      dest->sym.st_shndx = SHN_XINDEX;
+      dest->file = file;
+      dest->name = names_dest;
+      *names_dest++ = '.';
+      names_dest = stpcpy (names_dest, symname) + 1;
+      dest++;
+    }
+  assert ((char *) dest == names);
+  assert (names_dest == names + names_size);
+  *ebl_symentsp = ebl_syments;
+  *ebl_first_globalp = ebl_first_global;
+  ebl->backend = sym_table;
+}
+
+const char *
+ppc64_get_symbol (Ebl *ebl, size_t ndx, GElf_Sym *symp, GElf_Word *shndxp,
+		  void **filep)
+{
+  assert (ebl != NULL);
+  if (ebl->backend == NULL)
+    return NULL;
+  struct sym_entry *sym_table = ebl->backend;
+  const struct sym_entry *found = &sym_table[ndx];
+  *symp = found->sym;
+  if (shndxp)
+    *shndxp = found->shndx;
+  if (filep)
+    *filep = found->file;
+  return found->name;
+}
+
+void
+ppc64_destr (Ebl *ebl)
+{
+  if (ebl->backend == NULL)
+    return;
+  struct sym_entry *sym_table = ebl->backend;
+  free (sym_table);
+  ebl->backend = NULL;
+}
diff --git a/backends/ppc64_init.c b/backends/ppc64_init.c
index 1435875..3ed882b 100644
--- a/backends/ppc64_init.c
+++ b/backends/ppc64_init.c
@@ -65,6 +65,9 @@ ppc64_init (elf, machine, eh, ehlen)
   HOOK (eh, core_note);
   HOOK (eh, auxv_info);
   HOOK (eh, abi_cfi);
+  HOOK (eh, init_symbols);
+  HOOK (eh, get_symbol);
+  HOOK (eh, destr);
 
   return MODVERSION;
 }
diff --git a/libdwfl/dwfl_module_addrsym.c b/libdwfl/dwfl_module_addrsym.c
index d9eb0a2..6a39346 100644
--- a/libdwfl/dwfl_module_addrsym.c
+++ b/libdwfl/dwfl_module_addrsym.c
@@ -173,16 +173,17 @@ dwfl_module_addrsym (Dwfl_Module *mod, GElf_Addr addr,
 	}
     }
 
-  /* First go through global symbols.  mod->first_global and
-     mod->aux_first_global are setup by dwfl_module_getsymtab to the
-     index of the first global symbol in those symbol tables.  Both
-     are non-zero when the table exist, except when there is only a
-     dynsym table loaded through phdrs, then first_global is zero and
-     there will be no auxiliary table.  All symbols with local binding
-     come first in the symbol table, then all globals.  The zeroth,
-     null entry, in the auxiliary table is skipped if there is a main
-     table.  */
-  int first_global = mod->first_global + mod->aux_first_global;
+  /* First go through global symbols.  mod->first_global,
+     mod->aux_first_global and mod->ebl_first_global are setup by
+     dwfl_module_getsymtab to the index of the first global symbol in
+     those symbol tables.  Both are non-zero when the table exist,
+     except when there is only a dynsym table loaded through phdrs, then
+     first_global is zero and there will be no auxiliary table.  All
+     symbols with local binding come first in the symbol table, then all
+     globals.  The zeroth, null entry, in the auxiliary table is skipped
+     if there is a main table.  */
+  int first_global = (mod->first_global + mod->aux_first_global
+		      + mod->ebl_first_global);
   if (mod->syments > 0 && mod->aux_syments > 0)
     first_global--;
   search_table (first_global == 0 ? 1 : first_global, syments);
diff --git a/libdwfl/dwfl_module_getdwarf.c b/libdwfl/dwfl_module_getdwarf.c
index 7a65ec3..8f7f72d 100644
--- a/libdwfl/dwfl_module_getdwarf.c
+++ b/libdwfl/dwfl_module_getdwarf.c
@@ -945,6 +945,15 @@ find_aux_sym (Dwfl_Module *mod __attribute__ ((unused)),
 #endif
 }
 
+static const char *
+getsym_helper (void *arg, int ndx, GElf_Sym *sym, GElf_Word *shndxp,
+	       void **voidfilep)
+{
+  Dwfl_Module *mod = arg;
+  struct dwfl_file **filep = (struct dwfl_file **) voidfilep;
+  return __libdwfl_module_getsym (mod, ndx, sym, shndxp, filep);
+}
+
 /* Try to find a symbol table in either MOD->main.elf or MOD->debug.elf.  */
 static void
 find_symtab (Dwfl_Module *mod)
@@ -1064,7 +1073,7 @@ find_symtab (Dwfl_Module *mod)
 	  mod->aux_syments = 0;
 	  elf_end (mod->aux_sym.elf);
 	  mod->aux_sym.elf = NULL;
-	  return;
+	  goto aux_done;
 	}
 
       mod->aux_symstrdata = elf_getdata (elf_getscn (mod->aux_sym.elf,
@@ -1085,7 +1094,15 @@ find_symtab (Dwfl_Module *mod)
       mod->aux_symdata = elf_getdata (aux_symscn, NULL);
       if (mod->aux_symdata == NULL)
 	goto aux_cleanup;
+  aux_done:;
     }
+
+  Dwfl_Error error = __libdwfl_module_getebl (mod);
+  if (error == DWFL_E_NOERROR)
+    ebl_init_symbols (mod->ebl, mod->syments + mod->aux_syments,
+		      mod->first_global + mod->aux_first_global,
+		      mod->main_bias, getsym_helper, mod,
+		      &mod->ebl_syments, &mod->ebl_first_global);
 }
 
 
@@ -1242,7 +1259,7 @@ dwfl_module_getsymtab (Dwfl_Module *mod)
   find_symtab (mod);
   if (mod->symerr == DWFL_E_NOERROR)
     /* We will skip the auxiliary zero entry if there is another one.  */
-    return (mod->syments + mod->aux_syments
+    return (mod->syments + mod->aux_syments + mod->ebl_syments
 	    - (mod->syments > 0 && mod->aux_syments > 0 ? 1 : 0));
 
   __libdwfl_seterrno (mod->symerr);
diff --git a/libdwfl/dwfl_module_getsym.c b/libdwfl/dwfl_module_getsym.c
index 0f5dd37..f05880b 100644
--- a/libdwfl/dwfl_module_getsym.c
+++ b/libdwfl/dwfl_module_getsym.c
@@ -55,8 +55,7 @@ __libdwfl_module_getsym (Dwfl_Module *mod, int ndx,
   Elf_Data *symdata;
   Elf_Data *symxndxdata;
   Elf_Data *symstrdata;
-  if (mod->aux_symdata == NULL
-      || ndx < mod->first_global)
+  if (ndx < mod->first_global)
     {
       /* main symbol table (locals).  */
       tndx = ndx;
@@ -74,24 +73,63 @@ __libdwfl_module_getsym (Dwfl_Module *mod, int ndx,
       symxndxdata = mod->aux_symxndxdata;
       symstrdata = mod->aux_symstrdata;
     }
-  else if ((size_t) ndx < mod->syments + mod->aux_first_global - skip_aux_zero)
+  else if (ndx < (mod->first_global + mod->aux_first_global
+		  + mod->ebl_first_global - skip_aux_zero))
+    {
+      /* ebl symbol lookup (locals).  */
+      symdata = NULL;
+      tndx = ndx - (mod->first_global + mod->aux_first_global - skip_aux_zero);
+    }
+  else if ((size_t) ndx < (mod->syments + mod->aux_first_global
+			   + mod->ebl_first_global - skip_aux_zero))
     {
       /* main symbol table (globals).  */
-      tndx = ndx - mod->aux_first_global + skip_aux_zero;
+      tndx = ndx - (mod->aux_first_global + mod->ebl_first_global
+		    - skip_aux_zero);
       file = mod->symfile;
       symdata = mod->symdata;
       symxndxdata = mod->symxndxdata;
       symstrdata = mod->symstrdata;
     }
-  else
+  else if ((size_t) ndx < (mod->syments + mod->aux_syments
+			   + mod->ebl_first_global - skip_aux_zero))
     {
       /* aux symbol table (globals).  */
-      tndx = ndx - mod->syments + skip_aux_zero;
+      tndx = ndx - (mod->syments + mod->ebl_first_global - skip_aux_zero);
       file = &mod->aux_sym;
       symdata = mod->aux_symdata;
       symxndxdata = mod->aux_symxndxdata;
       symstrdata = mod->aux_symstrdata;
     }
+  else if ((size_t) ndx < (mod->syments + mod->aux_syments
+			   + mod->ebl_syments - skip_aux_zero))
+    {
+      /* ebl symbol lookup (globals).  */
+      symdata = NULL;
+      tndx = ndx - (mod->syments + mod->aux_syments - skip_aux_zero);
+    }
+  else
+    {
+      /* out of range NDX.  */
+      __libdwfl_seterrno (DWFL_E_INVALID_INDEX);
+      return NULL;
+    }
+
+  if (symdata == NULL)
+    {
+      void *voidfile;
+      const char *name = ebl_get_symbol (mod->ebl, tndx, sym, &shndx,
+					 &voidfile);
+      if (likely (name != NULL))
+	{
+	  if (filep)
+	    *filep = voidfile;
+	  return name;
+	}
+      __libdwfl_seterrno (DWFL_E_LIBEBL);
+      return NULL;
+    }
+
   sym = gelf_getsymshndx (symdata, symxndxdata, tndx, sym, &shndx);
 
   if (unlikely (sym == NULL))
diff --git a/libdwfl/libdwflP.h b/libdwfl/libdwflP.h
index 0c862b3..ee89344 100644
--- a/libdwfl/libdwflP.h
+++ b/libdwfl/libdwflP.h
@@ -89,7 +89,8 @@ typedef struct Dwfl_Process Dwfl_Process;
   DWFL_ERROR (ATTACH_STATE_CONFLICT, N_("Dwfl already has attached state"))   \
   DWFL_ERROR (NO_ATTACH_STATE, N_("Dwfl has no attached state"))	      \
   DWFL_ERROR (NO_UNWIND, N_("Unwinding not supported for this architecture")) \
-  DWFL_ERROR (INVALID_ARGUMENT, N_("Invalid argument"))
+  DWFL_ERROR (INVALID_ARGUMENT, N_("Invalid argument"))			      \
+  DWFL_ERROR (INVALID_INDEX, N_("invalid section index"))
 
 #define DWFL_ERROR(name, text) DWFL_E_##name,
 typedef enum { DWFL_ERRORS DWFL_E_NUM } Dwfl_Error;
@@ -172,8 +173,10 @@ struct Dwfl_Module
   Elf_Data *aux_symdata;	/* Data in the auxiliary ELF symbol table.  */
   size_t syments;		/* sh_size / sh_entsize of that section.  */
   size_t aux_syments;		/* sh_size / sh_entsize of aux_sym section.  */
+  size_t ebl_syments;		/* Number of symbols from ebl_getsym.  */
   int first_global;		/* Index of first global symbol of table.  */
   int aux_first_global;		/* Index of first global of aux_sym table.  */
+  int ebl_first_global;		/* Index of first global from ebl_getsym.  */
   Elf_Data *symstrdata;		/* Data for its string table.  */
   Elf_Data *aux_symstrdata;	/* Data for aux_sym string table.  */
   Elf_Data *symxndxdata;	/* Data in the extended section index table. */
diff --git a/libebl/Makefile.am b/libebl/Makefile.am
index 4487c5f..1fb3da3 100644
--- a/libebl/Makefile.am
+++ b/libebl/Makefile.am
@@ -54,7 +54,7 @@ gen_SOURCES = eblopenbackend.c eblclosebackend.c eblstrtab.c \
 	      eblreginfo.c eblnonerelocp.c eblrelativerelocp.c \
 	      eblsysvhashentrysize.c eblauxvinfo.c eblcheckobjattr.c \
 	      ebl_check_special_section.c ebl_syscall_abi.c eblabicfi.c \
-	      eblstother.c eblinitreg.c
+	      eblstother.c eblinitreg.c eblgetsymbol.c
 
 libebl_a_SOURCES = $(gen_SOURCES)
 
diff --git a/libebl/ebl-hooks.h b/libebl/ebl-hooks.h
index cb52fee..45ff66a 100644
--- a/libebl/ebl-hooks.h
+++ b/libebl/ebl-hooks.h
@@ -162,5 +162,23 @@ bool EBLHOOK(set_initial_registers_tid) (pid_t tid,
 					 ebl_tid_registers_t *setfunc,
 					 void *arg);
 
+/* Initialize virtual backend symbol table for EBL->elf currently containing
+   SYMENTS symbols, FIRST_GLOBAL of them are local, EBL->elf is using
+   MAIN_BIAS.  GETSYM is a callback to fetch the existing EBL->elf symbols,
+   ARG is an opaque parameter for GETSYM.  Fill in *EBL_SYMENTSP with the total
+   number of virtual symbols found, *EBL_FIRST_GLOBALP of them are local.
+   Both return values have to be initialized to zero by caller.  */
+void EBLHOOK(init_symbols) (Ebl *ebl, size_t syments, int first_global,
+			    GElf_Addr main_bias,
+			    ebl_getsym_t *getsym, void *arg,
+			    size_t *ebl_symentsp, int *ebl_first_globalp);
+
+/* Return NDXth virtual backend symbol from MOD, store it to *SYM, its section
+   to *SHNDX and its file pointer to *FILEP.  Return its name.  NDX must be
+   less than *EBL_SYMENTSP returned by init_symbols above.  SHNDXP or FILEP may
+   be NULL.  Returned name is valid as long as EBL is valid.  */
+const char *EBLHOOK(get_symbol) (Ebl *ebl, size_t ndx, GElf_Sym *symp,
+				 GElf_Word *shndxp, void **filep);
+
 /* Destructor for ELF backend handle.  */
 void EBLHOOK(destr) (struct ebl *);
diff --git a/libebl/eblgetsymbol.c b/libebl/eblgetsymbol.c
new file mode 100644
index 0000000..50d714e
--- /dev/null
+++ b/libebl/eblgetsymbol.c
@@ -0,0 +1,58 @@
+/* Provide virtual symbols from backend.
+   Copyright (C) 2013 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libeblP.h>
+#include <assert.h>
+
+void
+ebl_init_symbols (Ebl *ebl, size_t syments, int first_global,
+		  GElf_Addr main_bias, ebl_getsym_t *getsym, void *arg,
+		  size_t *ebl_symentsp, int *ebl_first_globalp)
+{
+  if (ebl == NULL)
+    return;
+  if (ebl->init_symbols == NULL)
+    return;
+  ebl->init_symbols (ebl, syments, first_global, main_bias, getsym, arg,
+		     ebl_symentsp, ebl_first_globalp);
+}
+
+const char *
+ebl_get_symbol (Ebl *ebl, size_t ndx, GElf_Sym *symp, GElf_Word *shndxp,
+		void **filep)
+{
+  if (ebl == NULL)
+    return NULL;
+  if (ebl->get_symbol == NULL)
+    return NULL;
+  return ebl->get_symbol (ebl, ndx, symp, shndxp, filep);
+}
diff --git a/libebl/libebl.h b/libebl/libebl.h
index 622f9e8..a5b39a9 100644
--- a/libebl/libebl.h
+++ b/libebl/libebl.h
@@ -404,6 +404,26 @@ extern bool ebl_set_initial_registers_tid (Ebl *ebl,
 extern size_t ebl_frame_nregs (Ebl *ebl)
   __nonnull_attribute__ (1);
 
+/* Callback type for ebl_init_symbols,
+   it is forwarded to __libdwfl_module_getsym.  */
+typedef const char *(ebl_getsym_t) (void *arg, int ndx, GElf_Sym *symp,
+				    GElf_Word *shndxp, void **filep)
+  __nonnull_attribute__ (3);
+
+extern void ebl_init_symbols (Ebl *ebl, size_t syments, int first_global,
+			      Dwarf_Addr symbias, ebl_getsym_t *getsym,
+			      void *arg, size_t *ebl_symentsp,
+			      int *ebl_first_globalp)
+  __nonnull_attribute__ (1, 5, 7, 8);
+
+/* Return NDXth backend symbol from MOD, store it to *SYM and *SHNDX and return
+   its new name.  If NDX is -1 then only initialize MOD's EBLSYMENTS (and
+   associated fields) and return NULL (SYM and SHNDXP are ignored in such
+   case).  Returned name is valid as long as EBL is valid.  */
+extern const char *ebl_get_symbol (Ebl *ebl, size_t ndx, GElf_Sym *symp,
+				   GElf_Word *shndxp, void **filep)
+  __nonnull_attribute__ (1, 3);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/libebl/libeblP.h b/libebl/libeblP.h
index 4f4137d..3282050 100644
--- a/libebl/libeblP.h
+++ b/libebl/libeblP.h
@@ -66,6 +66,9 @@ struct ebl
 
   /* Internal data.  */
   void *dlhandle;
+
+  /* Data specific to the backend.  */
+  void *backend;
 };
 
 
diff --git a/tests/Makefile.am b/tests/Makefile.am
index bc97523..550d207 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -214,7 +214,8 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh \
 	     testfile_implicit_pointer.c testfile_implicit_pointer.bz2 \
 	     testfile_parameter_ref.c testfile_parameter_ref.bz2 \
 	     testfile_entry_value.c testfile_entry_value.bz2 \
-	     testfile_implicit_value.c testfile_implicit_value.bz2
+	     testfile_implicit_value.c testfile_implicit_value.bz2 \
+	     testfile66.bz2
 
 if USE_VALGRIND
 valgrind_cmd='valgrind -q --trace-children=yes --error-exitcode=1 --run-libc-freeres=no'
diff --git a/tests/run-addrname-test.sh b/tests/run-addrname-test.sh
index 8624074..2edc7ca 100755
--- a/tests/run-addrname-test.sh
+++ b/tests/run-addrname-test.sh
@@ -298,6 +298,18 @@ __vdso_time
 ??:0
 EOF
 
+testfiles testfile66
+testrun_compare ${abs_top_builddir}/src/addr2line -S -e testfile66 func 0x10340 .func 0x250 <<\EOF
+func
+??:0
+func
+??:0
+.func
+??:0
+.func
+??:0
+EOF
+
 testfiles testfile69.core testfile69.so
 testrun_compare ${abs_top_builddir}/src/addr2line --core=./testfile69.core -S 0x7f0bc6a33535 0x7f0bc6a33546 <<\EOF
 libstatic+0x9
diff --git a/tests/testfile66.bz2 b/tests/testfile66.bz2
new file mode 100644
index 0000000..db07f25
Binary files /dev/null and b/tests/testfile66.bz2 differ

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