mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-04 05:48:20 +08:00
2007-07-03 Paul Gilliam <pgilliam@us.ibm.com>
Thiago Bauermann <bauerman@br.ibm.com> Joseph S. Myers <joseph@codesourcery.com> Daniel Jacobowitz <dan@codesourcery.com> gdb/ * remote.c (remote_check_symbols): Use gdbarch_convert_from_func_ptr_addr. * infcall.c (find_function_addr): Handle function descriptors without debugging information. * ppc-linux-tdep.c (ppc_linux_convert_from_func_ptr_addr): Renamed from ppc64_linux_convert_from_func_ptr_addr. Handle -msecure-plt. (ppc_linux_init_abi): Always set convert_from_func_ptr_addr. * solib-svr4.c (solib_break_names): Remove "._dl_debug_state". (bfd_lookup_symbol): Do not take a SECT_FLAGS argument. Always allow SEC_CODE and SEC_DATA. (enable_break): Update calls. Pass current_target to solib_add. Use gdbarch_convert_from_func_ptr_addr. gdb/gdbserver/ * remote-utils.c (look_up_one_symbol): Handle 'm' packets.
This commit is contained in:
@ -1,3 +1,21 @@
|
|||||||
|
2007-07-03 Paul Gilliam <pgilliam@us.ibm.com>
|
||||||
|
Thiago Bauermann <bauerman@br.ibm.com>
|
||||||
|
Joseph S. Myers <joseph@codesourcery.com>
|
||||||
|
Daniel Jacobowitz <dan@codesourcery.com>
|
||||||
|
|
||||||
|
* remote.c (remote_check_symbols): Use
|
||||||
|
gdbarch_convert_from_func_ptr_addr.
|
||||||
|
* infcall.c (find_function_addr): Handle function descriptors
|
||||||
|
without debugging information.
|
||||||
|
* ppc-linux-tdep.c (ppc_linux_convert_from_func_ptr_addr): Renamed
|
||||||
|
from ppc64_linux_convert_from_func_ptr_addr. Handle -msecure-plt.
|
||||||
|
(ppc_linux_init_abi): Always set convert_from_func_ptr_addr.
|
||||||
|
* solib-svr4.c (solib_break_names): Remove "._dl_debug_state".
|
||||||
|
(bfd_lookup_symbol): Do not take a SECT_FLAGS argument. Always
|
||||||
|
allow SEC_CODE and SEC_DATA.
|
||||||
|
(enable_break): Update calls. Pass current_target to solib_add.
|
||||||
|
Use gdbarch_convert_from_func_ptr_addr.
|
||||||
|
|
||||||
2007-07-03 Ilko Iliev <iliev@ronetix.at>
|
2007-07-03 Ilko Iliev <iliev@ronetix.at>
|
||||||
Daniel Jacobowitz <dan@codesourcery.com>
|
Daniel Jacobowitz <dan@codesourcery.com>
|
||||||
|
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
2007-07-03 Daniel Jacobowitz <dan@codesourcery.com>
|
||||||
|
|
||||||
|
* remote-utils.c (look_up_one_symbol): Handle 'm' packets.
|
||||||
|
|
||||||
2007-07-02 Daniel Jacobowitz <dan@codesourcery.com>
|
2007-07-02 Daniel Jacobowitz <dan@codesourcery.com>
|
||||||
|
|
||||||
* inferiors.c (change_inferior_id): Add comment.
|
* inferiors.c (change_inferior_id): Add comment.
|
||||||
|
@ -1109,15 +1109,34 @@ look_up_one_symbol (const char *name, CORE_ADDR *addrp)
|
|||||||
if (len < 0)
|
if (len < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
/* We ought to handle pretty much any packet at this point while we
|
||||||
|
wait for the qSymbol "response". That requires re-entering the
|
||||||
|
main loop. For now, this is an adequate approximation; allow
|
||||||
|
GDB to read from memory while it figures out the address of the
|
||||||
|
symbol. */
|
||||||
|
while (own_buf[0] == 'm')
|
||||||
|
{
|
||||||
|
CORE_ADDR mem_addr;
|
||||||
|
unsigned char *mem_buf;
|
||||||
|
unsigned int mem_len;
|
||||||
|
|
||||||
|
decode_m_packet (&own_buf[1], &mem_addr, &mem_len);
|
||||||
|
mem_buf = malloc (mem_len);
|
||||||
|
if (read_inferior_memory (mem_addr, mem_buf, mem_len) == 0)
|
||||||
|
convert_int_to_ascii (mem_buf, own_buf, mem_len);
|
||||||
|
else
|
||||||
|
write_enn (own_buf);
|
||||||
|
free (mem_buf);
|
||||||
|
if (putpkt (own_buf) < 0)
|
||||||
|
return -1;
|
||||||
|
len = getpkt (own_buf);
|
||||||
|
if (len < 0)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (strncmp (own_buf, "qSymbol:", strlen ("qSymbol:")) != 0)
|
if (strncmp (own_buf, "qSymbol:", strlen ("qSymbol:")) != 0)
|
||||||
{
|
{
|
||||||
/* Malformed response. */
|
warning ("Malformed response to qSymbol, ignoring: %s\n", own_buf);
|
||||||
if (remote_debug)
|
|
||||||
{
|
|
||||||
fprintf (stderr, "Malformed response to qSymbol, ignoring.\n");
|
|
||||||
fflush (stderr);
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -222,8 +222,24 @@ find_function_addr (struct value *function, struct type **retval_type)
|
|||||||
if (TYPE_LENGTH (ftype) == 1)
|
if (TYPE_LENGTH (ftype) == 1)
|
||||||
funaddr = value_as_address (value_addr (function));
|
funaddr = value_as_address (value_addr (function));
|
||||||
else
|
else
|
||||||
/* Handle integer used as address of a function. */
|
{
|
||||||
funaddr = (CORE_ADDR) value_as_long (function);
|
/* Handle function descriptors lacking debug info. */
|
||||||
|
int found_descriptor = 0;
|
||||||
|
if (VALUE_LVAL (function) == lval_memory)
|
||||||
|
{
|
||||||
|
CORE_ADDR nfunaddr;
|
||||||
|
funaddr = value_as_address (value_addr (function));
|
||||||
|
nfunaddr = funaddr;
|
||||||
|
funaddr = gdbarch_convert_from_func_ptr_addr (current_gdbarch,
|
||||||
|
funaddr,
|
||||||
|
¤t_target);
|
||||||
|
if (funaddr != nfunaddr)
|
||||||
|
found_descriptor = 1;
|
||||||
|
}
|
||||||
|
if (!found_descriptor)
|
||||||
|
/* Handle integer used as address of a function. */
|
||||||
|
funaddr = (CORE_ADDR) value_as_long (function);
|
||||||
|
}
|
||||||
|
|
||||||
value_type = builtin_type_int;
|
value_type = builtin_type_int;
|
||||||
}
|
}
|
||||||
|
@ -591,39 +591,73 @@ ppc64_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Support for CONVERT_FROM_FUNC_PTR_ADDR (ARCH, ADDR, TARG) on PPC64
|
/* Support for convert_from_func_ptr_addr (ARCH, ADDR, TARG) on PPC
|
||||||
GNU/Linux.
|
GNU/Linux.
|
||||||
|
|
||||||
Usually a function pointer's representation is simply the address
|
Usually a function pointer's representation is simply the address
|
||||||
of the function. On GNU/Linux on the 64-bit PowerPC however, a
|
of the function. On GNU/Linux on the PowerPC however, a function
|
||||||
function pointer is represented by a pointer to a TOC entry. This
|
pointer may be a pointer to a function descriptor.
|
||||||
TOC entry contains three words, the first word is the address of
|
|
||||||
the function, the second word is the TOC pointer (r2), and the
|
For PPC64, a function descriptor is a TOC entry, in a data section,
|
||||||
third word is the static chain value. Throughout GDB it is
|
which contains three words: the first word is the address of the
|
||||||
currently assumed that a function pointer contains the address of
|
function, the second word is the TOC pointer (r2), and the third word
|
||||||
the function, which is not easy to fix. In addition, the
|
is the static chain value.
|
||||||
|
|
||||||
|
For PPC32, there are two kinds of function pointers: non-secure and
|
||||||
|
secure. Non-secure function pointers point directly to the
|
||||||
|
function in a code section and thus need no translation. Secure
|
||||||
|
ones (from GCC's -msecure-plt option) are in a data section and
|
||||||
|
contain one word: the address of the function.
|
||||||
|
|
||||||
|
Throughout GDB it is currently assumed that a function pointer contains
|
||||||
|
the address of the function, which is not easy to fix. In addition, the
|
||||||
conversion of a function address to a function pointer would
|
conversion of a function address to a function pointer would
|
||||||
require allocation of a TOC entry in the inferior's memory space,
|
require allocation of a TOC entry in the inferior's memory space,
|
||||||
with all its drawbacks. To be able to call C++ virtual methods in
|
with all its drawbacks. To be able to call C++ virtual methods in
|
||||||
the inferior (which are called via function pointers),
|
the inferior (which are called via function pointers),
|
||||||
find_function_addr uses this function to get the function address
|
find_function_addr uses this function to get the function address
|
||||||
from a function pointer. */
|
from a function pointer.
|
||||||
|
|
||||||
/* If ADDR points at what is clearly a function descriptor, transform
|
If ADDR points at what is clearly a function descriptor, transform
|
||||||
it into the address of the corresponding function. Be
|
it into the address of the corresponding function, if needed. Be
|
||||||
conservative, otherwize GDB will do the transformation on any
|
conservative, otherwise GDB will do the transformation on any
|
||||||
random addresses such as occures when there is no symbol table. */
|
random addresses such as occur when there is no symbol table. */
|
||||||
|
|
||||||
static CORE_ADDR
|
static CORE_ADDR
|
||||||
ppc64_linux_convert_from_func_ptr_addr (struct gdbarch *gdbarch,
|
ppc_linux_convert_from_func_ptr_addr (struct gdbarch *gdbarch,
|
||||||
CORE_ADDR addr,
|
CORE_ADDR addr,
|
||||||
struct target_ops *targ)
|
struct target_ops *targ)
|
||||||
{
|
{
|
||||||
|
struct gdbarch_tdep *tdep;
|
||||||
struct section_table *s = target_section_by_addr (targ, addr);
|
struct section_table *s = target_section_by_addr (targ, addr);
|
||||||
|
char *sect_name = NULL;
|
||||||
|
|
||||||
|
if (!s)
|
||||||
|
return addr;
|
||||||
|
|
||||||
|
tdep = gdbarch_tdep (gdbarch);
|
||||||
|
|
||||||
|
switch (tdep->wordsize)
|
||||||
|
{
|
||||||
|
case 4:
|
||||||
|
sect_name = ".plt";
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
sect_name = ".opd";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
internal_error (__FILE__, __LINE__,
|
||||||
|
_("failed internal consistency check"));
|
||||||
|
}
|
||||||
|
|
||||||
/* Check if ADDR points to a function descriptor. */
|
/* Check if ADDR points to a function descriptor. */
|
||||||
if (s && strcmp (s->the_bfd_section->name, ".opd") == 0)
|
|
||||||
return get_target_memory_unsigned (targ, addr, 8);
|
/* NOTE: this depends on the coincidence that the address of a functions
|
||||||
|
entry point is contained in the first word of its function descriptor
|
||||||
|
for both PPC-64 and for PPC-32 with secure PLTs. */
|
||||||
|
if ((strcmp (s->the_bfd_section->name, sect_name) == 0)
|
||||||
|
&& s->the_bfd_section->flags & SEC_DATA)
|
||||||
|
return get_target_memory_unsigned (targ, addr, tdep->wordsize);
|
||||||
|
|
||||||
return addr;
|
return addr;
|
||||||
}
|
}
|
||||||
@ -907,6 +941,11 @@ ppc_linux_init_abi (struct gdbarch_info info,
|
|||||||
/* NOTE: cagney/2005-01-25: True for both 32- and 64-bit. */
|
/* NOTE: cagney/2005-01-25: True for both 32- and 64-bit. */
|
||||||
set_gdbarch_long_double_bit (gdbarch, 8 * TARGET_CHAR_BIT);
|
set_gdbarch_long_double_bit (gdbarch, 8 * TARGET_CHAR_BIT);
|
||||||
|
|
||||||
|
/* Handle PPC GNU/Linux 64-bit function pointers (which are really
|
||||||
|
function descriptors) and 32-bit secure PLT entries. */
|
||||||
|
set_gdbarch_convert_from_func_ptr_addr
|
||||||
|
(gdbarch, ppc_linux_convert_from_func_ptr_addr);
|
||||||
|
|
||||||
if (tdep->wordsize == 4)
|
if (tdep->wordsize == 4)
|
||||||
{
|
{
|
||||||
/* Until November 2001, gcc did not comply with the 32 bit SysV
|
/* Until November 2001, gcc did not comply with the 32 bit SysV
|
||||||
@ -934,13 +973,8 @@ ppc_linux_init_abi (struct gdbarch_info info,
|
|||||||
|
|
||||||
if (tdep->wordsize == 8)
|
if (tdep->wordsize == 8)
|
||||||
{
|
{
|
||||||
/* Handle PPC64 GNU/Linux function pointers (which are really
|
|
||||||
function descriptors). */
|
|
||||||
set_gdbarch_convert_from_func_ptr_addr
|
|
||||||
(gdbarch, ppc64_linux_convert_from_func_ptr_addr);
|
|
||||||
set_gdbarch_skip_trampoline_code (gdbarch, ppc64_skip_trampoline_code);
|
|
||||||
|
|
||||||
/* Shared library handling. */
|
/* Shared library handling. */
|
||||||
|
set_gdbarch_skip_trampoline_code (gdbarch, ppc64_skip_trampoline_code);
|
||||||
set_solib_svr4_fetch_link_map_offsets
|
set_solib_svr4_fetch_link_map_offsets
|
||||||
(gdbarch, svr4_lp64_fetch_link_map_offsets);
|
(gdbarch, svr4_lp64_fetch_link_map_offsets);
|
||||||
|
|
||||||
|
16
gdb/remote.c
16
gdb/remote.c
@ -2259,9 +2259,19 @@ remote_check_symbols (struct objfile *objfile)
|
|||||||
if (sym == NULL)
|
if (sym == NULL)
|
||||||
xsnprintf (msg, get_remote_packet_size (), "qSymbol::%s", &reply[8]);
|
xsnprintf (msg, get_remote_packet_size (), "qSymbol::%s", &reply[8]);
|
||||||
else
|
else
|
||||||
xsnprintf (msg, get_remote_packet_size (), "qSymbol:%s:%s",
|
{
|
||||||
paddr_nz (SYMBOL_VALUE_ADDRESS (sym)),
|
CORE_ADDR sym_addr = SYMBOL_VALUE_ADDRESS (sym);
|
||||||
&reply[8]);
|
|
||||||
|
/* If this is a function address, return the start of code
|
||||||
|
instead of any data function descriptor. */
|
||||||
|
sym_addr = gdbarch_convert_from_func_ptr_addr (current_gdbarch,
|
||||||
|
sym_addr,
|
||||||
|
¤t_target);
|
||||||
|
|
||||||
|
xsnprintf (msg, get_remote_packet_size (), "qSymbol:%s:%s",
|
||||||
|
paddr_nz (sym_addr), &reply[8]);
|
||||||
|
}
|
||||||
|
|
||||||
putpkt (msg);
|
putpkt (msg);
|
||||||
getpkt (&rs->buf, &rs->buf_size, 0);
|
getpkt (&rs->buf, &rs->buf_size, 0);
|
||||||
reply = rs->buf;
|
reply = rs->buf;
|
||||||
|
@ -84,16 +84,6 @@ static char *solib_break_names[] =
|
|||||||
"rtld_db_dlactivity",
|
"rtld_db_dlactivity",
|
||||||
"_rtld_debug_state",
|
"_rtld_debug_state",
|
||||||
|
|
||||||
/* On the 64-bit PowerPC, the linker symbol with the same name as
|
|
||||||
the C function points to a function descriptor, not to the entry
|
|
||||||
point. The linker symbol whose name is the C function name
|
|
||||||
prefixed with a '.' points to the function's entry point. So
|
|
||||||
when we look through this table, we ignore symbols that point
|
|
||||||
into the data section (thus skipping the descriptor's symbol),
|
|
||||||
and eventually try this one, giving us the real entry point
|
|
||||||
address. */
|
|
||||||
"._dl_debug_state",
|
|
||||||
|
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -263,7 +253,7 @@ static char *debug_loader_name;
|
|||||||
|
|
||||||
static int match_main (char *);
|
static int match_main (char *);
|
||||||
|
|
||||||
static CORE_ADDR bfd_lookup_symbol (bfd *, char *, flagword);
|
static CORE_ADDR bfd_lookup_symbol (bfd *, char *);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
@ -273,24 +263,25 @@ static CORE_ADDR bfd_lookup_symbol (bfd *, char *, flagword);
|
|||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
|
|
||||||
CORE_ADDR bfd_lookup_symbol (bfd *abfd, char *symname, flagword sect_flags)
|
CORE_ADDR bfd_lookup_symbol (bfd *abfd, char *symname)
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
|
|
||||||
An expensive way to lookup the value of a single symbol for
|
An expensive way to lookup the value of a single symbol for
|
||||||
bfd's that are only temporary anyway. This is used by the
|
bfd's that are only temporary anyway. This is used by the
|
||||||
shared library support to find the address of the debugger
|
shared library support to find the address of the debugger
|
||||||
interface structures in the shared library.
|
notification routine in the shared library.
|
||||||
|
|
||||||
If SECT_FLAGS is non-zero, only match symbols in sections whose
|
The returned symbol may be in a code or data section; functions
|
||||||
flags include all those in SECT_FLAGS.
|
will normally be in a code section, but may be in a data section
|
||||||
|
if this architecture uses function descriptors.
|
||||||
|
|
||||||
Note that 0 is specifically allowed as an error return (no
|
Note that 0 is specifically allowed as an error return (no
|
||||||
such symbol).
|
such symbol).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static CORE_ADDR
|
static CORE_ADDR
|
||||||
bfd_lookup_symbol (bfd *abfd, char *symname, flagword sect_flags)
|
bfd_lookup_symbol (bfd *abfd, char *symname)
|
||||||
{
|
{
|
||||||
long storage_needed;
|
long storage_needed;
|
||||||
asymbol *sym;
|
asymbol *sym;
|
||||||
@ -312,9 +303,9 @@ bfd_lookup_symbol (bfd *abfd, char *symname, flagword sect_flags)
|
|||||||
{
|
{
|
||||||
sym = *symbol_table++;
|
sym = *symbol_table++;
|
||||||
if (strcmp (sym->name, symname) == 0
|
if (strcmp (sym->name, symname) == 0
|
||||||
&& (sym->section->flags & sect_flags) == sect_flags)
|
&& (sym->section->flags & (SEC_CODE | SEC_DATA)) != 0)
|
||||||
{
|
{
|
||||||
/* Bfd symbols are section relative. */
|
/* BFD symbols are section relative. */
|
||||||
symaddr = sym->value + sym->section->vma;
|
symaddr = sym->value + sym->section->vma;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -341,9 +332,9 @@ bfd_lookup_symbol (bfd *abfd, char *symname, flagword sect_flags)
|
|||||||
sym = *symbol_table++;
|
sym = *symbol_table++;
|
||||||
|
|
||||||
if (strcmp (sym->name, symname) == 0
|
if (strcmp (sym->name, symname) == 0
|
||||||
&& (sym->section->flags & sect_flags) == sect_flags)
|
&& (sym->section->flags & (SEC_CODE | SEC_DATA)) != 0)
|
||||||
{
|
{
|
||||||
/* Bfd symbols are section relative. */
|
/* BFD symbols are section relative. */
|
||||||
symaddr = sym->value + sym->section->vma;
|
symaddr = sym->value + sym->section->vma;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1033,7 +1024,7 @@ enable_break (void)
|
|||||||
|
|
||||||
/* On a running target, we can get the dynamic linker's base
|
/* On a running target, we can get the dynamic linker's base
|
||||||
address from the shared library table. */
|
address from the shared library table. */
|
||||||
solib_add (NULL, 0, NULL, auto_solib_add);
|
solib_add (NULL, 0, ¤t_target, auto_solib_add);
|
||||||
so = master_so_list ();
|
so = master_so_list ();
|
||||||
while (so)
|
while (so)
|
||||||
{
|
{
|
||||||
@ -1056,7 +1047,7 @@ enable_break (void)
|
|||||||
debug_loader_name = xstrdup (buf);
|
debug_loader_name = xstrdup (buf);
|
||||||
debug_loader_offset_p = 1;
|
debug_loader_offset_p = 1;
|
||||||
debug_loader_offset = load_addr;
|
debug_loader_offset = load_addr;
|
||||||
solib_add (NULL, 0, NULL, auto_solib_add);
|
solib_add (NULL, 0, ¤t_target, auto_solib_add);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Record the relocated start and end address of the dynamic linker
|
/* Record the relocated start and end address of the dynamic linker
|
||||||
@ -1081,20 +1072,19 @@ enable_break (void)
|
|||||||
/* Now try to set a breakpoint in the dynamic linker. */
|
/* Now try to set a breakpoint in the dynamic linker. */
|
||||||
for (bkpt_namep = solib_break_names; *bkpt_namep != NULL; bkpt_namep++)
|
for (bkpt_namep = solib_break_names; *bkpt_namep != NULL; bkpt_namep++)
|
||||||
{
|
{
|
||||||
/* On ABI's that use function descriptors, there are usually
|
sym_addr = bfd_lookup_symbol (tmp_bfd, *bkpt_namep);
|
||||||
two linker symbols associated with each C function: one
|
|
||||||
pointing at the actual entry point of the machine code,
|
|
||||||
and one pointing at the function's descriptor. The
|
|
||||||
latter symbol has the same name as the C function.
|
|
||||||
|
|
||||||
What we're looking for here is the machine code entry
|
|
||||||
point, so we are only interested in symbols in code
|
|
||||||
sections. */
|
|
||||||
sym_addr = bfd_lookup_symbol (tmp_bfd, *bkpt_namep, SEC_CODE);
|
|
||||||
if (sym_addr != 0)
|
if (sym_addr != 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sym_addr != 0)
|
||||||
|
/* Convert 'sym_addr' from a function pointer to an address.
|
||||||
|
Because we pass tmp_bfd_target instead of the current
|
||||||
|
target, this will always produce an unrelocated value. */
|
||||||
|
sym_addr = gdbarch_convert_from_func_ptr_addr (current_gdbarch,
|
||||||
|
sym_addr,
|
||||||
|
tmp_bfd_target);
|
||||||
|
|
||||||
/* We're done with both the temporary bfd and target. Remember,
|
/* We're done with both the temporary bfd and target. Remember,
|
||||||
closing the target closes the underlying bfd. */
|
closing the target closes the underlying bfd. */
|
||||||
target_close (tmp_bfd_target, 0);
|
target_close (tmp_bfd_target, 0);
|
||||||
|
Reference in New Issue
Block a user