backtrace.h (backtrace_syminfo): Update comment and parameter name to take any address, not just a PC value.

* backtrace.h (backtrace_syminfo): Update comment and parameter
	name to take any address, not just a PC value.
	* elf.c (STT_OBJECT): Define.
	(elf_nosyms): Rename parameter pc to addr.
	(elf_symbol_search): Rename local variable pc to addr.
	(elf_initialize_syminfo): Add STT_OBJECT symbols to elf_symbols.
	(elf_syminfo): Rename parameter pc to addr.
	* btest.c (global): New global variable.
	(test5): New test.
	(main): Call test5.

From-SVN: r204904
This commit is contained in:
Ian Lance Taylor 2013-11-16 18:20:33 +00:00 committed by Ian Lance Taylor
parent b032ec0d50
commit cfa658e4f8
4 changed files with 93 additions and 24 deletions

View File

@ -1,3 +1,16 @@
2013-11-15 Ian Lance Taylor <iant@google.com>
* backtrace.h (backtrace_syminfo): Update comment and parameter
name to take any address, not just a PC value.
* elf.c (STT_OBJECT): Define.
(elf_nosyms): Rename parameter pc to addr.
(elf_symbol_search): Rename local variable pc to addr.
(elf_initialize_syminfo): Add STT_OBJECT symbols to elf_symbols.
(elf_syminfo): Rename parameter pc to addr.
* btest.c (global): New global variable.
(test5): New test.
(main): Call test5.
2013-10-17 Ian Lance Taylor <iant@google.com>
* elf.c (elf_add): Don't get the wrong offsets if a debug section

View File

@ -177,17 +177,17 @@ typedef void (*backtrace_syminfo_callback) (void *data, uintptr_t pc,
const char *symname,
uintptr_t symval);
/* Given PC, a program counter in the current program, call the
callback information with the symbol name and value describing the
function in which PC may be found. This will call either CALLBACK
or ERROR_CALLBACK exactly once. This returns 1 on success, 0 on
failure. This function requires the symbol table but does not
require the debug info. Note that if the symbol table is present
but PC could not be found in the table, CALLBACK will be called
with a NULL SYMNAME argument. Returns 1 on success, 0 on
error. */
/* Given ADDR, an address or program counter in the current program,
call the callback information with the symbol name and value
describing the function or variable in which ADDR may be found.
This will call either CALLBACK or ERROR_CALLBACK exactly once.
This returns 1 on success, 0 on failure. This function requires
the symbol table but does not require the debug info. Note that if
the symbol table is present but ADDR could not be found in the
table, CALLBACK will be called with a NULL SYMNAME argument.
Returns 1 on success, 0 on error. */
extern int backtrace_syminfo (struct backtrace_state *state, uintptr_t pc,
extern int backtrace_syminfo (struct backtrace_state *state, uintptr_t addr,
backtrace_syminfo_callback callback,
backtrace_error_callback error_callback,
void *data);

View File

@ -598,6 +598,53 @@ f33 (int f1line, int f2line)
return failures;
}
int global = 1;
static int
test5 (void)
{
struct symdata symdata;
int i;
symdata.name = NULL;
symdata.val = 0;
symdata.failed = 0;
i = backtrace_syminfo (state, (uintptr_t) &global, callback_three,
error_callback_three, &symdata);
if (i == 0)
{
fprintf (stderr,
"test5: unexpected return value from backtrace_syminfo %d\n",
i);
symdata.failed = 1;
}
if (!symdata.failed)
{
if (symdata.name == NULL)
{
fprintf (stderr, "test5: NULL syminfo name\n");
symdata.failed = 1;
}
else if (strcmp (symdata.name, "global") != 0)
{
fprintf (stderr,
"test5: unexpected syminfo name got %s expected %s\n",
symdata.name, "global");
symdata.failed = 1;
}
}
printf ("%s: backtrace_syminfo variable\n",
symdata.failed ? "FAIL" : "PASS");
if (symdata.failed)
++failures;
return failures;
}
static void
error_callback_create (void *data ATTRIBUTE_UNUSED, const char *msg,
int errnum)
@ -622,6 +669,7 @@ main (int argc ATTRIBUTE_UNUSED, char **argv)
test2 ();
test3 ();
test4 ();
test5 ();
#endif
exit (failures ? EXIT_FAILURE : EXIT_SUCCESS);

View File

@ -101,6 +101,7 @@ dl_iterate_phdr (int (*callback) (struct dl_phdr_info *,
#undef SHT_SYMTAB
#undef SHT_STRTAB
#undef SHT_DYNSYM
#undef STT_OBJECT
#undef STT_FUNC
/* Basic types. */
@ -215,6 +216,7 @@ typedef struct
#endif /* BACKTRACE_ELF_SIZE != 32 */
#define STT_OBJECT 1
#define STT_FUNC 2
/* An index of ELF sections we care about. */
@ -293,7 +295,7 @@ elf_nodebug (struct backtrace_state *state ATTRIBUTE_UNUSED,
static void
elf_nosyms (struct backtrace_state *state ATTRIBUTE_UNUSED,
uintptr_t pc ATTRIBUTE_UNUSED,
uintptr_t addr ATTRIBUTE_UNUSED,
backtrace_syminfo_callback callback ATTRIBUTE_UNUSED,
backtrace_error_callback error_callback, void *data)
{
@ -316,7 +318,7 @@ elf_symbol_compare (const void *v1, const void *v2)
return 0;
}
/* Compare a PC against an elf_symbol for bsearch. We allocate one
/* Compare an ADDR against an elf_symbol for bsearch. We allocate one
extra entry in the array so that this can look safely at the next
entry. */
@ -325,12 +327,12 @@ elf_symbol_search (const void *vkey, const void *ventry)
{
const uintptr_t *key = (const uintptr_t *) vkey;
const struct elf_symbol *entry = (const struct elf_symbol *) ventry;
uintptr_t pc;
uintptr_t addr;
pc = *key;
if (pc < entry->address)
addr = *key;
if (addr < entry->address)
return -1;
else if (pc >= entry->address + entry->size)
else if (addr >= entry->address + entry->size)
return 1;
else
return 0;
@ -360,7 +362,10 @@ elf_initialize_syminfo (struct backtrace_state *state,
elf_symbol_count = 0;
for (i = 0; i < sym_count; ++i, ++sym)
{
if ((sym->st_info & 0xf) == STT_FUNC)
int info;
info = sym->st_info & 0xf;
if (info == STT_FUNC || info == STT_OBJECT)
++elf_symbol_count;
}
@ -375,7 +380,10 @@ elf_initialize_syminfo (struct backtrace_state *state,
j = 0;
for (i = 0; i < sym_count; ++i, ++sym)
{
if ((sym->st_info & 0xf) != STT_FUNC)
int info;
info = sym->st_info & 0xf;
if (info != STT_FUNC && info != STT_OBJECT)
continue;
if (sym->st_name >= strtab_size)
{
@ -445,10 +453,10 @@ elf_add_syminfo_data (struct backtrace_state *state,
}
}
/* Return the symbol name and value for a PC. */
/* Return the symbol name and value for an ADDR. */
static void
elf_syminfo (struct backtrace_state *state, uintptr_t pc,
elf_syminfo (struct backtrace_state *state, uintptr_t addr,
backtrace_syminfo_callback callback,
backtrace_error_callback error_callback ATTRIBUTE_UNUSED,
void *data)
@ -463,7 +471,7 @@ elf_syminfo (struct backtrace_state *state, uintptr_t pc,
edata = edata->next)
{
sym = ((struct elf_symbol *)
bsearch (&pc, edata->symbols, edata->count,
bsearch (&addr, edata->symbols, edata->count,
sizeof (struct elf_symbol), elf_symbol_search));
if (sym != NULL)
break;
@ -485,7 +493,7 @@ elf_syminfo (struct backtrace_state *state, uintptr_t pc,
break;
sym = ((struct elf_symbol *)
bsearch (&pc, edata->symbols, edata->count,
bsearch (&addr, edata->symbols, edata->count,
sizeof (struct elf_symbol), elf_symbol_search));
if (sym != NULL)
break;
@ -495,9 +503,9 @@ elf_syminfo (struct backtrace_state *state, uintptr_t pc,
}
if (sym == NULL)
callback (data, pc, NULL, 0);
callback (data, addr, NULL, 0);
else
callback (data, pc, sym->name, sym->address);
callback (data, addr, sym->name, sym->address);
}
/* Add the backtrace data for one ELF file. */