|
|
2c2fa1 |
commit d4094b6a8883ae481c7644c5a210254efe92e9ad
|
|
|
2c2fa1 |
Author: Ulrich Weigand <ulrich.weigand@de.ibm.com>
|
|
|
2c2fa1 |
Date: Tue Feb 4 18:40:16 2014 +0100
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
PowerPC64 ELFv2 ABI: no function descriptors
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
This implements the most significant difference with the ELFv2 ABI:
|
|
|
2c2fa1 |
we no longer use function descriptors. The patch consists mostly
|
|
|
2c2fa1 |
of switching off code to deal with descriptors :-)
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
In addition, when calling an inferior function, we no longer need
|
|
|
2c2fa1 |
to provide its TOC in r2. Instead, ELFv2 code expects to be called
|
|
|
2c2fa1 |
with r12 pointing to the code address itself.
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
gdb/ChangeLog:
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
* ppc-linux-tdep.c (ppc_linux_init_abi): Only call
|
|
|
2c2fa1 |
set_gdbarch_convert_from_func_ptr_addr and
|
|
|
2c2fa1 |
set_gdbarch_elf_make_msymbol_special for ELFv1.
|
|
|
2c2fa1 |
* ppc-sysv-tdep.c (ppc64_sysv_abi_push_param): Only handle
|
|
|
2c2fa1 |
function descriptors on ELFv1.
|
|
|
2c2fa1 |
(ppc64_sysv_abi_push_dummy_call): Likewise. On ELFv2,
|
|
|
2c2fa1 |
set up r12 at function entry.
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
Index: gdb-7.6.1/gdb/ppc-linux-tdep.c
|
|
|
2c2fa1 |
===================================================================
|
|
|
2c2fa1 |
--- gdb-7.6.1.orig/gdb/ppc-linux-tdep.c
|
|
|
2c2fa1 |
+++ gdb-7.6.1/gdb/ppc-linux-tdep.c
|
|
|
2c2fa1 |
@@ -1331,13 +1331,16 @@ ppc_linux_init_abi (struct gdbarch_info
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
if (tdep->wordsize == 8)
|
|
|
2c2fa1 |
{
|
|
|
2c2fa1 |
- /* Handle PPC GNU/Linux 64-bit function pointers (which are really
|
|
|
2c2fa1 |
- function descriptors). */
|
|
|
2c2fa1 |
- set_gdbarch_convert_from_func_ptr_addr
|
|
|
2c2fa1 |
- (gdbarch, ppc64_convert_from_func_ptr_addr);
|
|
|
2c2fa1 |
+ if (tdep->elf_abi == POWERPC_ELF_V1)
|
|
|
2c2fa1 |
+ {
|
|
|
2c2fa1 |
+ /* Handle PPC GNU/Linux 64-bit function pointers (which are really
|
|
|
2c2fa1 |
+ function descriptors). */
|
|
|
2c2fa1 |
+ set_gdbarch_convert_from_func_ptr_addr
|
|
|
2c2fa1 |
+ (gdbarch, ppc64_convert_from_func_ptr_addr);
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
- set_gdbarch_elf_make_msymbol_special (gdbarch,
|
|
|
2c2fa1 |
- ppc64_elf_make_msymbol_special);
|
|
|
2c2fa1 |
+ set_gdbarch_elf_make_msymbol_special
|
|
|
2c2fa1 |
+ (gdbarch, ppc64_elf_make_msymbol_special);
|
|
|
2c2fa1 |
+ }
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
/* Shared library handling. */
|
|
|
2c2fa1 |
set_gdbarch_skip_trampoline_code (gdbarch, ppc64_skip_trampoline_code);
|
|
|
2c2fa1 |
Index: gdb-7.6.1/gdb/ppc-sysv-tdep.c
|
|
|
2c2fa1 |
===================================================================
|
|
|
2c2fa1 |
--- gdb-7.6.1.orig/gdb/ppc-sysv-tdep.c
|
|
|
2c2fa1 |
+++ gdb-7.6.1/gdb/ppc-sysv-tdep.c
|
|
|
2c2fa1 |
@@ -1351,8 +1351,9 @@ ppc64_sysv_abi_push_param (struct gdbarc
|
|
|
2c2fa1 |
word = unpack_long (type, val);
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
/* Convert any function code addresses into descriptors. */
|
|
|
2c2fa1 |
- if (TYPE_CODE (type) == TYPE_CODE_PTR
|
|
|
2c2fa1 |
- || TYPE_CODE (type) == TYPE_CODE_REF)
|
|
|
2c2fa1 |
+ if (tdep->elf_abi == POWERPC_ELF_V1
|
|
|
2c2fa1 |
+ && (TYPE_CODE (type) == TYPE_CODE_PTR
|
|
|
2c2fa1 |
+ || TYPE_CODE (type) == TYPE_CODE_REF))
|
|
|
2c2fa1 |
{
|
|
|
2c2fa1 |
struct type *target_type
|
|
|
2c2fa1 |
= check_typedef (TYPE_TARGET_TYPE (type));
|
|
|
2c2fa1 |
@@ -1552,24 +1553,32 @@ ppc64_sysv_abi_push_dummy_call (struct g
|
|
|
2c2fa1 |
breakpoint. */
|
|
|
2c2fa1 |
regcache_cooked_write_signed (regcache, tdep->ppc_lr_regnum, bp_addr);
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
- /* Use the func_addr to find the descriptor, and use that to find
|
|
|
2c2fa1 |
- the TOC. If we're calling via a function pointer, the pointer
|
|
|
2c2fa1 |
- itself identifies the descriptor. */
|
|
|
2c2fa1 |
- {
|
|
|
2c2fa1 |
- struct type *ftype = check_typedef (value_type (function));
|
|
|
2c2fa1 |
- CORE_ADDR desc_addr = value_as_address (function);
|
|
|
2c2fa1 |
-
|
|
|
2c2fa1 |
- if (TYPE_CODE (ftype) == TYPE_CODE_PTR
|
|
|
2c2fa1 |
- || convert_code_addr_to_desc_addr (func_addr, &desc_addr))
|
|
|
2c2fa1 |
- {
|
|
|
2c2fa1 |
- /* The TOC is the second double word in the descriptor. */
|
|
|
2c2fa1 |
- CORE_ADDR toc =
|
|
|
2c2fa1 |
- read_memory_unsigned_integer (desc_addr + tdep->wordsize,
|
|
|
2c2fa1 |
- tdep->wordsize, byte_order);
|
|
|
2c2fa1 |
- regcache_cooked_write_unsigned (regcache,
|
|
|
2c2fa1 |
- tdep->ppc_gp0_regnum + 2, toc);
|
|
|
2c2fa1 |
- }
|
|
|
2c2fa1 |
- }
|
|
|
2c2fa1 |
+ /* In the ELFv1 ABI, use the func_addr to find the descriptor, and use
|
|
|
2c2fa1 |
+ that to find the TOC. If we're calling via a function pointer,
|
|
|
2c2fa1 |
+ the pointer itself identifies the descriptor. */
|
|
|
2c2fa1 |
+ if (tdep->elf_abi == POWERPC_ELF_V1)
|
|
|
2c2fa1 |
+ {
|
|
|
2c2fa1 |
+ struct type *ftype = check_typedef (value_type (function));
|
|
|
2c2fa1 |
+ CORE_ADDR desc_addr = value_as_address (function);
|
|
|
2c2fa1 |
+
|
|
|
2c2fa1 |
+ if (TYPE_CODE (ftype) == TYPE_CODE_PTR
|
|
|
2c2fa1 |
+ || convert_code_addr_to_desc_addr (func_addr, &desc_addr))
|
|
|
2c2fa1 |
+ {
|
|
|
2c2fa1 |
+ /* The TOC is the second double word in the descriptor. */
|
|
|
2c2fa1 |
+ CORE_ADDR toc =
|
|
|
2c2fa1 |
+ read_memory_unsigned_integer (desc_addr + tdep->wordsize,
|
|
|
2c2fa1 |
+ tdep->wordsize, byte_order);
|
|
|
2c2fa1 |
+
|
|
|
2c2fa1 |
+ regcache_cooked_write_unsigned (regcache,
|
|
|
2c2fa1 |
+ tdep->ppc_gp0_regnum + 2, toc);
|
|
|
2c2fa1 |
+ }
|
|
|
2c2fa1 |
+ }
|
|
|
2c2fa1 |
+
|
|
|
2c2fa1 |
+ /* In the ELFv2 ABI, we need to pass the target address in r12 since
|
|
|
2c2fa1 |
+ we may be calling a global entry point. */
|
|
|
2c2fa1 |
+ if (tdep->elf_abi == POWERPC_ELF_V2)
|
|
|
2c2fa1 |
+ regcache_cooked_write_unsigned (regcache,
|
|
|
2c2fa1 |
+ tdep->ppc_gp0_regnum + 12, func_addr);
|
|
|
2c2fa1 |
|
|
|
2c2fa1 |
return sp;
|
|
|
2c2fa1 |
}
|