Hi Mark,
jankratochvil/xauxfile-filep-scnfindvma-ppc64bidir
obsoletes:
[patch 3/3] ppc64 .opd: Bidirectional provider
https://lists.fedorahosted.org/pipermail/elfutils-devel/2012-December/002...
here is the new variant of bi-directional ppc64 .opd resolver.
Thanks,
Jan
commit e477998865cd170c1ed24d9d0f0f91f45a9e7785
Author: Jan Kratochvil <jan.kratochvil(a)redhat.com>
Date: Wed Nov 6 20:38:05 2013 +0100
Provide virtual symbols for ppc64 function descriptors
backends/
2013-11-06 Jan Kratochvil <jan.kratochvil(a)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(a)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(a)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(a)redhat.com>
diff --git a/backends/Makefile.am b/backends/Makefile.am
index 557ed87..332ca65 100644
--- a/backends/Makefile.am
+++ b/backends/Makefile.am
@@ -92,7 +92,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..9b1bc87
--- /dev/null
+++ b/backends/ppc64_get_symbol.c
@@ -0,0 +1,178 @@
+/* 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;
+};
+
+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 = elf_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 2926726..ebb850a 100644
--- a/libdwfl/dwfl_module_addrsym.c
+++ b/libdwfl/dwfl_module_addrsym.c
@@ -161,16 +161,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 fe30472..f82be55 100644
--- a/libdwfl/libdwflP.h
+++ b/libdwfl/libdwflP.h
@@ -74,7 +74,8 @@
DWFL_ERROR (BADELF, N_("not a valid ELF file")) \
DWFL_ERROR (WEIRD_TYPE, N_("cannot handle DWARF type description")) \
DWFL_ERROR (WRONG_ID_ELF, N_("ELF file does not match build ID")) \
- DWFL_ERROR (BAD_PRELINK, N_("corrupt .gnu.prelink_undo section data"))
+ DWFL_ERROR (BAD_PRELINK, N_("corrupt .gnu.prelink_undo section data"))
\
+ 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;
@@ -155,8 +156,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 4d62fad..db22c32 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
+ eblstother.c eblgetsymbol.c
libebl_a_SOURCES = $(gen_SOURCES)
diff --git a/libebl/ebl-hooks.h b/libebl/ebl-hooks.h
index d3cf3e6..d3c5f71 100644
--- a/libebl/ebl-hooks.h
+++ b/libebl/ebl-hooks.h
@@ -155,5 +155,23 @@ int EBLHOOK(disasm) (const uint8_t **startp, const uint8_t *end,
Function returns 0 on success and -1 on error. */
int EBLHOOK(abi_cfi) (Ebl *ebl, Dwarf_CIE *abi_info);
+/* 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 990167a..821d9ad 100644
--- a/libebl/libebl.h
+++ b/libebl/libebl.h
@@ -383,6 +383,25 @@ extern int ebl_auxv_info (Ebl *ebl, GElf_Xword a_type,
const char **name, const char **format)
__nonnull_attribute__ (1, 3, 4);
+/* 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
}
diff --git a/libebl/libeblP.h b/libebl/libeblP.h
index 5ec26a4..c8196bd 100644
--- a/libebl/libeblP.h
+++ b/libebl/libeblP.h
@@ -62,6 +62,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 d07cb0b..4eaeb43 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