/* Target-dependent code for GDB, the GNU debugger.
- Copyright (C) 1986, 1987, 1989, 1991, 1992, 1993, 1994, 1995, 1996,
- 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+ Copyright (C) 1986, 1987, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
+ 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
Free Software Foundation, Inc.
This file is part of GDB.
CORE_ADDR (*rs6000_find_toc_address_hook) (CORE_ADDR) = NULL;
-/* Hook to set the current architecture when starting a child process.
- rs6000-nat.c sets this. */
-
-void (*rs6000_set_host_arch_hook) (int) = NULL;
-
/* Static function prototypes */
static CORE_ADDR branch_dest (int opcode, int instr, CORE_ADDR pc,
something like 0x3c90. The current frame is a signal handler
caller frame, upon completion of the sigreturn system call
execution will return to the saved PC in the frame. */
- if (dest < TEXT_SEGMENT_BASE)
+ if (dest < gdbarch_tdep (current_gdbarch)->text_segment_base)
{
struct frame_info *fi;
/* If we are about to execute a system call, dest is something
like 0x22fc or 0x3b00. Upon completion the system call
will return to the address in the link register. */
- if (dest < TEXT_SEGMENT_BASE)
+ if (dest < gdbarch_tdep (current_gdbarch)->text_segment_base)
dest = read_register (gdbarch_tdep (current_gdbarch)->ppc_lr_regnum) & ~3;
}
else
default:
return -1;
}
- return (dest < TEXT_SEGMENT_BASE) ? safety : dest;
+ return (dest < gdbarch_tdep (current_gdbarch)->text_segment_base) ? safety : dest;
}
return 0;
}
+/* Assuming that INSN is a "bl" instruction located at PC, return
+ nonzero if the destination of the branch is a "blrl" instruction.
+
+ This sequence is sometimes found in certain function prologues.
+ It allows the function to load the LR register with a value that
+ they can use to access PIC data using PC-relative offsets. */
+
+static int
+bl_to_blrl_insn_p (CORE_ADDR pc, int insn)
+{
+ const int opcode = 18;
+ const CORE_ADDR dest = branch_dest (opcode, insn, pc, -1);
+ int dest_insn;
+
+ if (dest == -1)
+ return 0; /* Should never happen, but just return zero to be safe. */
+
+ dest_insn = read_memory_integer (dest, 4);
+ if ((dest_insn & 0xfc00ffff) == 0x4c000021) /* blrl */
+ return 1;
+
+ return 0;
+}
+
static CORE_ADDR
skip_prologue (CORE_ADDR pc, CORE_ADDR lim_pc, struct rs6000_framedata *fdata)
{
to save fprs??? */
fdata->frameless = 0;
+
+ /* If the return address has already been saved, we can skip
+ calls to blrl (for PIC). */
+ if (lr_reg != -1 && bl_to_blrl_insn_p (pc, op))
+ continue;
+
/* Don't skip over the subroutine call if it is not within
the first three instructions of the prologue and either
we have no line table information or the line info tells
offset = fdata->offset;
continue;
}
+ else if ((op & 0xffff0000) == 0x38210000)
+ { /* addi r1,r1,SIMM */
+ fdata->frameless = 0;
+ fdata->offset += SIGNED_SHORT (op);
+ offset = fdata->offset;
+ continue;
+ }
/* Load up minimal toc pointer */
else if (((op >> 22) == 0x20f || /* l r31,... or l r30,... */
(op >> 22) == 0x3af) /* ld r31,... or ld r30,... */
}
}
-/* Hook called when a new child process is started. */
-
-void
-rs6000_create_inferior (int pid)
-{
- if (rs6000_set_host_arch_hook)
- rs6000_set_host_arch_hook (pid);
-}
\f
/* Support for CONVERT_FROM_FUNC_PTR_ADDR (ARCH, ADDR, TARG).
static int
gdb_print_insn_powerpc (bfd_vma memaddr, disassemble_info *info)
{
+ if (!info->disassembler_options)
+ info->disassembler_options = "any";
+
if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
return print_insn_big_powerpc (memaddr, info);
else
(*this_cache) = cache;
cache->saved_regs = trad_frame_alloc_saved_regs (next_frame);
- func = frame_func_unwind (next_frame);
+ func = frame_func_unwind (next_frame, NORMAL_FRAME);
pc = frame_pc_unwind (next_frame);
skip_prologue (func, pc, &fdata);
{
struct rs6000_frame_cache *info = rs6000_frame_cache (next_frame,
this_cache);
- (*this_id) = frame_id_build (info->base, frame_func_unwind (next_frame));
+ (*this_id) = frame_id_build (info->base,
+ frame_func_unwind (next_frame, NORMAL_FRAME));
}
static void
set_gdbarch_pc_regnum (gdbarch, 64);
set_gdbarch_sp_regnum (gdbarch, 1);
set_gdbarch_deprecated_fp_regnum (gdbarch, 1);
+ set_gdbarch_fp0_regnum (gdbarch, 32);
set_gdbarch_register_sim_regno (gdbarch, rs6000_register_sim_regno);
if (sysv_abi && wordsize == 8)
set_gdbarch_return_value (gdbarch, ppc64_sysv_abi_return_value);
/* Helpers for function argument information. */
set_gdbarch_fetch_pointer_argument (gdbarch, rs6000_fetch_pointer_argument);
+ /* Trampoline. */
+ set_gdbarch_in_solib_return_trampoline
+ (gdbarch, rs6000_in_solib_return_trampoline);
+ set_gdbarch_skip_trampoline_code (gdbarch, rs6000_skip_trampoline_code);
+
/* Hook in ABI-specific overrides, if they have been registered. */
gdbarch_init_osabi (info, gdbarch);