return (pc == handler || pc == handler + 4);
}
-static inline int
+static int
insn_is_sigreturn (unsigned long pcinsn)
{
switch(pcinsn)
/* This might not work right if we have multiple symbols with the
same name; the only way to really get it right is to perform
the same sort of lookup as the dynamic linker. */
- msymbol = lookup_minimal_symbol_text (symname, NULL, NULL);
+ msymbol = lookup_minimal_symbol_text (symname, NULL);
if (!msymbol)
return 0;
{
CORE_ADDR regs_addr;
int i;
- if (get_frame_saved_regs (fi))
+ if (deprecated_get_frame_saved_regs (fi))
return;
frame_saved_regs_zalloc (fi);
regs_addr =
read_memory_integer (get_frame_base (fi)
+ PPC_LINUX_REGS_PTR_OFFSET, 4);
- get_frame_saved_regs (fi)[PC_REGNUM] = regs_addr + 4 * PPC_LINUX_PT_NIP;
- get_frame_saved_regs (fi)[gdbarch_tdep (current_gdbarch)->ppc_ps_regnum] =
+ deprecated_get_frame_saved_regs (fi)[PC_REGNUM] = regs_addr + 4 * PPC_LINUX_PT_NIP;
+ deprecated_get_frame_saved_regs (fi)[gdbarch_tdep (current_gdbarch)->ppc_ps_regnum] =
regs_addr + 4 * PPC_LINUX_PT_MSR;
- get_frame_saved_regs (fi)[gdbarch_tdep (current_gdbarch)->ppc_cr_regnum] =
+ deprecated_get_frame_saved_regs (fi)[gdbarch_tdep (current_gdbarch)->ppc_cr_regnum] =
regs_addr + 4 * PPC_LINUX_PT_CCR;
- get_frame_saved_regs (fi)[gdbarch_tdep (current_gdbarch)->ppc_lr_regnum] =
+ deprecated_get_frame_saved_regs (fi)[gdbarch_tdep (current_gdbarch)->ppc_lr_regnum] =
regs_addr + 4 * PPC_LINUX_PT_LNK;
- get_frame_saved_regs (fi)[gdbarch_tdep (current_gdbarch)->ppc_ctr_regnum] =
+ deprecated_get_frame_saved_regs (fi)[gdbarch_tdep (current_gdbarch)->ppc_ctr_regnum] =
regs_addr + 4 * PPC_LINUX_PT_CTR;
- get_frame_saved_regs (fi)[gdbarch_tdep (current_gdbarch)->ppc_xer_regnum] =
+ deprecated_get_frame_saved_regs (fi)[gdbarch_tdep (current_gdbarch)->ppc_xer_regnum] =
regs_addr + 4 * PPC_LINUX_PT_XER;
- get_frame_saved_regs (fi)[gdbarch_tdep (current_gdbarch)->ppc_mq_regnum] =
+ deprecated_get_frame_saved_regs (fi)[gdbarch_tdep (current_gdbarch)->ppc_mq_regnum] =
regs_addr + 4 * PPC_LINUX_PT_MQ;
for (i = 0; i < 32; i++)
- get_frame_saved_regs (fi)[gdbarch_tdep (current_gdbarch)->ppc_gp0_regnum + i] =
+ deprecated_get_frame_saved_regs (fi)[gdbarch_tdep (current_gdbarch)->ppc_gp0_regnum + i] =
regs_addr + 4 * PPC_LINUX_PT_R0 + 4 * i;
for (i = 0; i < 32; i++)
- get_frame_saved_regs (fi)[FP0_REGNUM + i] = regs_addr + 4 * PPC_LINUX_PT_FPR0 + 8 * i;
+ deprecated_get_frame_saved_regs (fi)[FP0_REGNUM + i] = regs_addr + 4 * PPC_LINUX_PT_FPR0 + 8 * i;
}
else
rs6000_frame_init_saved_regs (fi);
return val;
}
+/* For historic reasons, PPC 32 GNU/Linux follows PowerOpen rather
+ than the 32 bit SYSV R4 ABI structure return convention - all
+ structures, no matter their size, are put in memory. Vectors,
+ which were added later, do get returned in a register though. */
+
+static enum return_value_convention
+ppc_linux_return_value (struct gdbarch *gdbarch, struct type *valtype,
+ struct regcache *regcache, void *readbuf,
+ const void *writebuf)
+{
+ if ((TYPE_CODE (valtype) == TYPE_CODE_STRUCT
+ || TYPE_CODE (valtype) == TYPE_CODE_UNION)
+ && !((TYPE_LENGTH (valtype) == 16 || TYPE_LENGTH (valtype) == 8)
+ && TYPE_VECTOR (valtype)))
+ return RETURN_VALUE_STRUCT_CONVENTION;
+ else
+ return ppc_sysv_abi_return_value (gdbarch, valtype, regcache, readbuf,
+ writebuf);
+}
+
/* Fetch (and possibly build) an appropriate link_map_offsets
structure for GNU/Linux PPC targets using the struct offsets
defined in link.h (but without actual reference to that file).
}
-/* Support for CONVERT_FROM_FUNC_PTR_ADDR(ADDR) on PPC64 GNU/Linux.
+/* Support for CONVERT_FROM_FUNC_PTR_ADDR (ARCH, ADDR, TARG) on PPC64
+ GNU/Linux.
Usually a function pointer's representation is simply the address
of the function. On GNU/Linux on the 64-bit PowerPC however, a
find_function_addr uses this function to get the function address
from a function pointer. */
-/* Return real function address if ADDR (a function pointer) is in the data
- space and is therefore a special function pointer. */
+/* If ADDR points at what is clearly a function descriptor, transform
+ it into the address of the corresponding function. Be
+ conservative, otherwize GDB will do the transformation on any
+ random addresses such as occures when there is no symbol table. */
static CORE_ADDR
-ppc64_linux_convert_from_func_ptr_addr (CORE_ADDR addr)
+ppc64_linux_convert_from_func_ptr_addr (struct gdbarch *gdbarch,
+ CORE_ADDR addr,
+ struct target_ops *targ)
{
- struct obj_section *s;
+ struct section_table *s = target_section_by_addr (targ, addr);
- s = find_pc_section (addr);
- if (s && s->the_bfd_section->flags & SEC_CODE)
- return addr;
+ /* 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);
- /* ADDR is in the data space, so it's a pointer to a descriptor, not
- the entry point. */
- return ppc64_desc_entry_point (addr);
-}
-
-
-/* On 64-bit PowerPC GNU/Linux, the ELF header's e_entry field is the
- address of a function descriptor for the entry point function, not
- the actual entry point itself. So to find the actual address at
- which execution should begin, we need to fetch the function's entry
- point from that descriptor. */
-static CORE_ADDR
-ppc64_call_dummy_address (void)
-{
- return ppc64_desc_entry_point (entry_point_address ());
+ return addr;
}
{
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
- /* Until November 2001, gcc was not complying to the SYSV ABI for
- returning structures less than or equal to 8 bytes in size. It was
- returning everything in memory. When this was corrected, it wasn't
- fixed for native platforms. */
- set_gdbarch_use_struct_convention (gdbarch,
- ppc_sysv_abi_broken_use_struct_convention);
-
if (tdep->wordsize == 4)
{
+ /* Until November 2001, gcc did not comply with the 32 bit SysV
+ R4 ABI requirement that structures less than or equal to 8
+ bytes should be returned in registers. Instead GCC was using
+ the the AIX/PowerOpen ABI - everything returned in memory
+ (well ignoring vectors that is). When this was corrected, it
+ wasn't fixed for GNU/Linux native platform. Use the
+ PowerOpen struct convention. */
+ set_gdbarch_return_value (gdbarch, ppc_linux_return_value);
+
/* Note: kevinb/2002-04-12: See note in rs6000_gdbarch_init regarding
*_push_arguments(). The same remarks hold for the methods below. */
set_gdbarch_frameless_function_invocation (gdbarch,
set_gdbarch_convert_from_func_ptr_addr
(gdbarch, ppc64_linux_convert_from_func_ptr_addr);
- set_gdbarch_call_dummy_address (gdbarch, ppc64_call_dummy_address);
-
set_gdbarch_in_solib_call_trampoline
(gdbarch, ppc64_in_solib_call_trampoline);
set_gdbarch_skip_trampoline_code (gdbarch, ppc64_skip_trampoline_code);
+
+ /* PPC64 malloc's entry-point is called ".malloc". */
+ set_gdbarch_name_of_malloc (gdbarch, ".malloc");
}
}
void
_initialize_ppc_linux_tdep (void)
{
- gdbarch_register_osabi (bfd_arch_powerpc, 0, GDB_OSABI_LINUX,
- ppc_linux_init_abi);
+ /* Register for all sub-familes of the POWER/PowerPC: 32-bit and
+ 64-bit PowerPC, and the older rs6k. */
+ gdbarch_register_osabi (bfd_arch_powerpc, bfd_mach_ppc, GDB_OSABI_LINUX,
+ ppc_linux_init_abi);
+ gdbarch_register_osabi (bfd_arch_powerpc, bfd_mach_ppc64, GDB_OSABI_LINUX,
+ ppc_linux_init_abi);
+ gdbarch_register_osabi (bfd_arch_rs6000, bfd_mach_rs6k, GDB_OSABI_LINUX,
+ ppc_linux_init_abi);
add_core_fns (&ppc_linux_regset_core_fns);
}