#include "linux-tdep.h"
#include "linux-record.h"
#include "record-full.h"
+#include "infrun.h"
#include "stap-probe.h"
#include "ax.h"
return 0;
}
-/* Follow PLT stub to actual routine. */
+/* Follow PLT stub to actual routine.
+
+ When the execution direction is EXEC_REVERSE, scan backward to
+ check whether we are in the middle of a PLT stub. Currently,
+ we only look-behind at most 4 instructions (the max length of PLT
+ stub sequence. */
static CORE_ADDR
ppc_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
CORE_ADDR target = 0;
+ int scan_limit, i;
- if (ppc_insns_match_pattern (frame, pc, powerpc32_plt_stub, insnbuf))
- {
- /* Insn pattern is
- lis r11, xxxx
- lwz r11, xxxx(r11)
- Branch target is in r11. */
-
- target = (ppc_insn_d_field (insnbuf[0]) << 16)
- | ppc_insn_d_field (insnbuf[1]);
- target = read_memory_unsigned_integer (target, 4, byte_order);
- }
+ scan_limit = 1;
+ /* When reverse-debugging, scan backward to check whether we are
+ in the middle of trampoline code. */
+ if (execution_direction == EXEC_REVERSE)
+ scan_limit = 4; /* At more 4 instructions. */
- if (ppc_insns_match_pattern (frame, pc, powerpc32_plt_stub_so, insnbuf))
+ for (i = 0; i < scan_limit; i++)
{
- /* Insn pattern is
- lwz r11, xxxx(r30)
- Branch target is in r11. */
+ if (ppc_insns_match_pattern (frame, pc, powerpc32_plt_stub, insnbuf))
+ {
+ /* Insn pattern is
+ lis r11, xxxx
+ lwz r11, xxxx(r11)
+ Branch target is in r11. */
+
+ target = (ppc_insn_d_field (insnbuf[0]) << 16)
+ | ppc_insn_d_field (insnbuf[1]);
+ target = read_memory_unsigned_integer (target, 4, byte_order);
+ }
+ else if (ppc_insns_match_pattern (frame, pc, powerpc32_plt_stub_so,
+ insnbuf))
+ {
+ /* Insn pattern is
+ lwz r11, xxxx(r30)
+ Branch target is in r11. */
+
+ target = get_frame_register_unsigned (frame,
+ tdep->ppc_gp0_regnum + 30)
+ + ppc_insn_d_field (insnbuf[0]);
+ target = read_memory_unsigned_integer (target, 4, byte_order);
+ }
+ else
+ {
+ /* Scan backward one more instructions if doesn't match. */
+ pc -= 4;
+ continue;
+ }
- target = get_frame_register_unsigned (frame, tdep->ppc_gp0_regnum + 30)
- + ppc_insn_d_field (insnbuf[0]);
- target = read_memory_unsigned_integer (target, 4, byte_order);
+ return target;
}
- return target;
+ return 0;
}
/* Wrappers to handle Linux-only registers. */
struct regcache *regcache,
int regnum, const void *gregs, size_t len)
{
- const struct ppc_reg_offsets *offsets = regset->regmap;
+ const struct ppc_reg_offsets *offsets
+ = (const struct ppc_reg_offsets *) regset->regmap;
ppc_supply_gregset (regset, regcache, regnum, gregs, len);
{
/* "orig_r3" is stored 2 slots after "pc". */
if (regnum == -1 || regnum == PPC_ORIG_R3_REGNUM)
- ppc_supply_reg (regcache, PPC_ORIG_R3_REGNUM, gregs,
+ ppc_supply_reg (regcache, PPC_ORIG_R3_REGNUM, (const gdb_byte *) gregs,
offsets->pc_offset + 2 * offsets->gpr_size,
offsets->gpr_size);
/* "trap" is stored 8 slots after "pc". */
if (regnum == -1 || regnum == PPC_TRAP_REGNUM)
- ppc_supply_reg (regcache, PPC_TRAP_REGNUM, gregs,
+ ppc_supply_reg (regcache, PPC_TRAP_REGNUM, (const gdb_byte *) gregs,
offsets->pc_offset + 8 * offsets->gpr_size,
offsets->gpr_size);
}
const struct regcache *regcache,
int regnum, void *gregs, size_t len)
{
- const struct ppc_reg_offsets *offsets = regset->regmap;
+ const struct ppc_reg_offsets *offsets
+ = (const struct ppc_reg_offsets *) regset->regmap;
/* Clear areas in the linux gregset not written elsewhere. */
if (regnum == -1)
{
/* "orig_r3" is stored 2 slots after "pc". */
if (regnum == -1 || regnum == PPC_ORIG_R3_REGNUM)
- ppc_collect_reg (regcache, PPC_ORIG_R3_REGNUM, gregs,
+ ppc_collect_reg (regcache, PPC_ORIG_R3_REGNUM, (gdb_byte *) gregs,
offsets->pc_offset + 2 * offsets->gpr_size,
offsets->gpr_size);
/* "trap" is stored 8 slots after "pc". */
if (regnum == -1 || regnum == PPC_TRAP_REGNUM)
- ppc_collect_reg (regcache, PPC_TRAP_REGNUM, gregs,
+ ppc_collect_reg (regcache, PPC_TRAP_REGNUM, (gdb_byte *) gregs,
offsets->pc_offset + 8 * offsets->gpr_size,
offsets->gpr_size);
}
ppc64_linux_sighandler_cache_init
};
-
-/* 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)
static struct linux_record_tdep ppc_linux_record_tdep;
static struct linux_record_tdep ppc64_linux_record_tdep;
+/* ppc_canonicalize_syscall maps from the native PowerPC Linux set of
+ syscall ids into a canonical set of syscall ids used by process
+ record. (See arch/powerpc/include/uapi/asm/unistd.h in kernel tree.)
+ Return -1 if this system call is not supported by process record.
+ Otherwise, return the syscall number for preocess reocrd of given
+ SYSCALL. */
+
static enum gdb_syscall
ppc_canonicalize_syscall (int syscall)
{
- /* See arch/powerpc/include/uapi/asm/unistd.h */
+ int result = -1;
if (syscall <= 165)
- return syscall;
+ result = syscall;
else if (syscall >= 167 && syscall <= 190) /* Skip query_module 166 */
- return syscall + 1;
+ result = syscall + 1;
else if (syscall >= 192 && syscall <= 197) /* mmap2 */
- return syscall;
+ result = syscall;
else if (syscall == 208) /* tkill */
- return gdb_sys_tkill;
+ result = gdb_sys_tkill;
else if (syscall >= 207 && syscall <= 220) /* gettid */
- return syscall + 224 - 207;
+ result = syscall + 224 - 207;
else if (syscall >= 234 && syscall <= 239) /* exit_group */
- return syscall + 252 - 234;
- else if (syscall >= 240 && syscall <=248) /* timer_create */
- return syscall += 259 - 240;
- else if (syscall >= 250 && syscall <=251) /* tgkill */
- return syscall + 270 - 250;
+ result = syscall + 252 - 234;
+ else if (syscall >= 240 && syscall <= 248) /* timer_create */
+ result = syscall += 259 - 240;
+ else if (syscall >= 250 && syscall <= 251) /* tgkill */
+ result = syscall + 270 - 250;
else if (syscall == 336)
- return gdb_sys_recv;
+ result = gdb_sys_recv;
else if (syscall == 337)
- return gdb_sys_recvfrom;
+ result = gdb_sys_recvfrom;
else if (syscall == 342)
- return gdb_sys_recvmsg;
- return -1;
+ result = gdb_sys_recvmsg;
+
+ return (enum gdb_syscall) result;
}
+/* Record registers which might be clobbered during system call.
+ Return 0 if successful. */
+
static int
ppc_linux_syscall_record (struct regcache *regcache)
{
return 0;
}
+/* Record registers which might be clobbered during signal handling.
+ Return 0 if successful. */
+
static int
ppc_linux_record_signal (struct gdbarch *gdbarch, struct regcache *regcache,
enum gdb_signal signal)
static int
ppc_linux_spu_section (bfd *abfd, asection *asect, void *user_data)
{
- return strncmp (bfd_section_name (abfd, asect), "SPU/", 4) == 0;
+ return startswith (bfd_section_name (abfd, asect), "SPU/");
}
static const struct target_desc *
}
len = s - p->arg;
- regname = alloca (len + 2);
+ regname = (char *) alloca (len + 2);
regname[0] = 'r';
strncpy (regname + 1, p->arg, len);
{
spe_context_objfile = objfile;
spe_context_lm_addr = svr4_fetch_objfile_link_map (objfile);
- spe_context_offset = BMSYMBOL_VALUE_ADDRESS (sym);
+ spe_context_offset = MSYMBOL_VALUE_RAW_ADDRESS (sym.minsym);
spe_context_cache_ptid = minus_one_ptid;
spe_context_cache_address = 0;
return;
if (!ptid_equal (spe_context_cache_ptid, inferior_ptid))
{
struct target_ops *target = ¤t_target;
- volatile struct gdb_exception ex;
- TRY_CATCH (ex, RETURN_MASK_ERROR)
+ TRY
{
/* We do not call target_translate_tls_address here, because
svr4_fetch_objfile_link_map may invalidate the frame chain,
spe_context_cache_ptid = inferior_ptid;
}
- if (ex.reason < 0)
- return 0;
+ CATCH (ex, RETURN_MASK_ERROR)
+ {
+ return 0;
+ }
+ END_CATCH
}
/* Read variable value. */
static struct gdbarch *
ppu2spu_prev_arch (struct frame_info *this_frame, void **this_cache)
{
- struct ppu2spu_cache *cache = *this_cache;
+ struct ppu2spu_cache *cache = (struct ppu2spu_cache *) *this_cache;
return get_regcache_arch (cache->regcache);
}
ppu2spu_this_id (struct frame_info *this_frame,
void **this_cache, struct frame_id *this_id)
{
- struct ppu2spu_cache *cache = *this_cache;
+ struct ppu2spu_cache *cache = (struct ppu2spu_cache *) *this_cache;
*this_id = cache->frame_id;
}
ppu2spu_prev_register (struct frame_info *this_frame,
void **this_cache, int regnum)
{
- struct ppu2spu_cache *cache = *this_cache;
+ struct ppu2spu_cache *cache = (struct ppu2spu_cache *) *this_cache;
struct gdbarch *gdbarch = get_regcache_arch (cache->regcache);
gdb_byte *buf;
- buf = alloca (register_size (gdbarch, regnum));
+ buf = (gdb_byte *) alloca (register_size (gdbarch, regnum));
if (regnum < gdbarch_num_regs (gdbarch))
regcache_raw_read (cache->regcache, regnum, buf);
gdb_byte gprs[128*16];
};
-static int
+static enum register_status
ppu2spu_unwind_register (void *src, int regnum, gdb_byte *buf)
{
- struct ppu2spu_data *data = src;
+ struct ppu2spu_data *data = (struct ppu2spu_data *) src;
enum bfd_endian byte_order = gdbarch_byte_order (data->gdbarch);
if (regnum >= 0 && regnum < SPU_NUM_GPRS)
info.bfd_arch_info = bfd_lookup_arch (bfd_arch_spu, bfd_mach_spu);
info.byte_order = BFD_ENDIAN_BIG;
info.osabi = GDB_OSABI_LINUX;
- info.tdep_info = (void *) &data.id;
+ info.tdep_info = &data.id;
data.gdbarch = gdbarch_find_by_info (info);
if (!data.gdbarch)
return 0;
static void
ppu2spu_dealloc_cache (struct frame_info *self, void *this_cache)
{
- struct ppu2spu_cache *cache = this_cache;
+ struct ppu2spu_cache *cache = (struct ppu2spu_cache *) this_cache;
regcache_xfree (cache->regcache);
}
ppu2spu_prev_arch,
};
-/* Initialize linux_record_tdep if not initialized yet. */
+/* Initialize linux_record_tdep if not initialized yet.
+ WORDSIZE is 4 or 8 for 32- or 64-bit PowerPC Linux respectively.
+ Sizes of data structures are initialized accordingly. */
static void
ppc_init_linux_record_tdep (struct linux_record_tdep *record_tdep,
record_tdep->size_flock = 32;
record_tdep->size_oldold_utsname = 45;
record_tdep->size_ustat = 32;
- record_tdep->size_old_sigaction = 152;
- record_tdep->size_old_sigset_t = 128;
+ record_tdep->size_old_sigaction = 32;
+ record_tdep->size_old_sigset_t = 8;
record_tdep->size_rlimit = 16;
record_tdep->size_rusage = 144;
record_tdep->size_timeval = 16;
record_tdep->size_old_gid_t = 4;
record_tdep->size_old_uid_t = 4;
record_tdep->size_fd_set = 128;
- record_tdep->size_dirent = 280;
- record_tdep->size_dirent64 = 280;
+ record_tdep->size_old_dirent = 280;
record_tdep->size_statfs = 120;
record_tdep->size_statfs64 = 120;
record_tdep->size_sockaddr = 16;
record_tdep->size_pollfd = 8;
record_tdep->size_NFS_FHSIZE = 32;
record_tdep->size_knfsd_fh = 132;
- record_tdep->size_TASK_COMM_LEN = 32;
- record_tdep->size_sigaction = 152;
- record_tdep->size_sigset_t = 128;
+ record_tdep->size_TASK_COMM_LEN = 16;
+ record_tdep->size_sigaction = 32;
+ record_tdep->size_sigset_t = 8;
record_tdep->size_siginfo_t = 128;
record_tdep->size_cap_user_data_t = 8;
record_tdep->size_stack_t = 24;
record_tdep->size_epoll_event = 16;
record_tdep->size_itimerspec = 32;
record_tdep->size_mq_attr = 64;
- record_tdep->size_siginfo = 128;
record_tdep->size_termios = 44;
record_tdep->size_pid_t = 4;
record_tdep->size_winsize = 8;
record_tdep->size_serial_icounter_struct = 80;
record_tdep->size_size_t = 8;
record_tdep->size_iovec = 16;
+ record_tdep->size_time_t = 8;
}
else if (wordsize == 4)
{
record_tdep->size_flock = 16;
record_tdep->size_oldold_utsname = 45;
record_tdep->size_ustat = 20;
- record_tdep->size_old_sigaction = 152;
- record_tdep->size_old_sigset_t = 128;
+ record_tdep->size_old_sigaction = 16;
+ record_tdep->size_old_sigset_t = 4;
record_tdep->size_rlimit = 8;
record_tdep->size_rusage = 72;
record_tdep->size_timeval = 8;
record_tdep->size_old_gid_t = 4;
record_tdep->size_old_uid_t = 4;
record_tdep->size_fd_set = 128;
- record_tdep->size_dirent = 268;
- record_tdep->size_dirent64 = 280;
+ record_tdep->size_old_dirent = 268;
record_tdep->size_statfs = 64;
record_tdep->size_statfs64 = 88;
record_tdep->size_sockaddr = 16;
record_tdep->size_pollfd = 8;
record_tdep->size_NFS_FHSIZE = 32;
record_tdep->size_knfsd_fh = 132;
- record_tdep->size_TASK_COMM_LEN = 32;
- record_tdep->size_sigaction = 140;
- record_tdep->size_sigset_t = 128;
+ record_tdep->size_TASK_COMM_LEN = 16;
+ record_tdep->size_sigaction = 20;
+ record_tdep->size_sigset_t = 8;
record_tdep->size_siginfo_t = 128;
record_tdep->size_cap_user_data_t = 4;
record_tdep->size_stack_t = 12;
record_tdep->size_epoll_event = 16;
record_tdep->size_itimerspec = 16;
record_tdep->size_mq_attr = 32;
- record_tdep->size_siginfo = 128;
record_tdep->size_termios = 44;
record_tdep->size_pid_t = 4;
record_tdep->size_winsize = 8;
record_tdep->size_serial_icounter_struct = 80;
record_tdep->size_size_t = 4;
record_tdep->size_iovec = 8;
+ record_tdep->size_time_t = 4;
}
else
internal_error (__FILE__, __LINE__, _("unexpected wordsize"));
struct gdbarch *gdbarch)
{
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
- struct tdesc_arch_data *tdesc_data = (void *) info.tdep_info;
+ struct tdesc_arch_data *tdesc_data
+ = (struct tdesc_arch_data *) info.tdep_info;
static const char *const stap_integer_prefixes[] = { "i", NULL };
static const char *const stap_register_indirection_prefixes[] = { "(",
NULL };
/* Cell/B.E. cross-architecture unwinder support. */
frame_unwind_prepend_unwinder (gdbarch, &ppu2spu_unwind);
-
- /* 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);
}
- set_gdbarch_get_siginfo_type (gdbarch, linux_get_siginfo_type);
+ set_gdbarch_displaced_step_location (gdbarch,
+ linux_displaced_step_location);
/* Support reverse debugging. */
set_gdbarch_process_record (gdbarch, ppc_process_record);
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);
-
/* Attach to observers to track __spe_current_active_context. */
observer_attach_inferior_created (ppc_linux_spe_context_inferior_created);
observer_attach_solib_loaded (ppc_linux_spe_context_solib_loaded);