diff options
Diffstat (limited to 'gdb/ppc-linux-tdep.c')
-rw-r--r-- | gdb/ppc-linux-tdep.c | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c index a15d283..1aaac0b 100644 --- a/gdb/ppc-linux-tdep.c +++ b/gdb/ppc-linux-tdep.c @@ -33,11 +33,15 @@ #include "osabi.h" #include "regset.h" #include "solib-svr4.h" +#include "solib-spu.h" #include "ppc-tdep.h" #include "ppc-linux-tdep.h" #include "trad-frame.h" #include "frame-unwind.h" #include "tramp-frame.h" +#include "observer.h" +#include "auxv.h" +#include "elf/common.h" #include "features/rs6000/powerpc-32l.c" #include "features/rs6000/powerpc-altivec32l.c" @@ -1003,6 +1007,46 @@ static struct tramp_frame ppc64_linux_sighandler_tramp_frame = { }; +/* Address to use for displaced stepping. When debugging a stand-alone + SPU executable, entry_point_address () will point to an SPU local-store + address and is thus not usable as displaced stepping location. We use + the auxiliary vector to determine the PowerPC-side entry point address + instead. */ + +static CORE_ADDR ppc_linux_entry_point_addr = 0; + +static void +ppc_linux_inferior_created (struct target_ops *target, int from_tty) +{ + ppc_linux_entry_point_addr = 0; +} + +static CORE_ADDR +ppc_linux_displaced_step_location (struct gdbarch *gdbarch) +{ + if (ppc_linux_entry_point_addr == 0) + { + CORE_ADDR addr; + + /* Determine entry point from target auxiliary vector. */ + if (target_auxv_search (¤t_target, AT_ENTRY, &addr) <= 0) + error (_("Cannot find AT_ENTRY auxiliary vector entry.")); + + /* Make certain that the address points at real code, and not a + function descriptor. */ + addr = gdbarch_convert_from_func_ptr_addr (gdbarch, addr, + ¤t_target); + + /* Inferior calls also use the entry point as a breakpoint location. + We don't want displaced stepping to interfere with those + breakpoints, so leave space. */ + ppc_linux_entry_point_addr = addr + 2 * PPC_INSN_SIZE; + } + + return ppc_linux_entry_point_addr; +} + + /* Return 1 if PPC_ORIG_R3_REGNUM and PPC_TRAP_REGNUM are usable. */ int ppc_linux_trap_reg_p (struct gdbarch *gdbarch) @@ -1189,6 +1233,19 @@ ppc_linux_init_abi (struct gdbarch_info info, PPC_TRAP_REGNUM, "trap"); } } + + /* Enable Cell/B.E. if supported by the target. */ + if (tdesc_compatible_p (info.target_desc, + bfd_lookup_arch (bfd_arch_spu, bfd_mach_spu))) + { + /* Cell/B.E. multi-architecture support. */ + set_spu_solib_ops (gdbarch); + + /* The default displaced_step_at_entry_point doesn't work for + SPU stand-alone executables. */ + set_gdbarch_displaced_step_location (gdbarch, + ppc_linux_displaced_step_location); + } } /* Provide a prototype to silence -Wmissing-prototypes. */ @@ -1206,6 +1263,9 @@ _initialize_ppc_linux_tdep (void) gdbarch_register_osabi (bfd_arch_rs6000, bfd_mach_rs6k, GDB_OSABI_LINUX, ppc_linux_init_abi); + /* Attach to inferior_created observer. */ + observer_attach_inferior_created (ppc_linux_inferior_created); + /* Initialize the Linux target descriptions. */ initialize_tdesc_powerpc_32l (); initialize_tdesc_powerpc_altivec32l (); |