#include "ppc-macosx-regs.h"
#include "ppc-macosx-tdep.h"
#include "ppc-macosx-frameinfo.h"
#include "ppc-macosx-frameops.h"
#include "defs.h"
#include "frame.h"
#include "inferior.h"
#include "symtab.h"
#include "target.h"
#include "gdbcore.h"
#include "symfile.h"
#include "objfiles.h"
#include "gdbcmd.h"
#include "arch-utils.h"
#include "floatformat.h"
#include "gdbtypes.h"
#include "regcache.h"
#include "libbfd.h"
#include "elf-bfd.h"
#include "dis-asm.h"
#include "ppc-tdep.h"
#undef XMALLOC
#define XMALLOC(TYPE) ((TYPE*) xmalloc (sizeof (TYPE)))
static int ppc_debugflag = 0;
static unsigned int ppc_max_frame_size = UINT_MAX;
void ppc_debug (const char *fmt, ...)
{
va_list ap;
if (ppc_debugflag) {
va_start (ap, fmt);
vfprintf (stderr, fmt, ap);
va_end (ap);
}
}
#define DEFAULT_LR_SAVE 8
void
ppc_init_extra_frame_info (int fromleaf, struct frame_info *frame)
{
CHECK_FATAL (frame != NULL);
frame->extra_info = (struct frame_extra_info *)
frame_obstack_alloc (sizeof (struct frame_extra_info));
frame->extra_info->initial_sp = 0;
frame->extra_info->bounds = NULL;
frame->extra_info->props = 0;
frame->signal_handler_caller = 0;
}
void
ppc_print_extra_frame_info (struct frame_info *frame)
{
if (frame->signal_handler_caller) {
printf_filtered (" This function was called from a signal handler.\n");
} else {
printf_filtered (" This function was not called from a signal handler.\n");
}
ppc_frame_cache_initial_stack_address (frame);
if (frame->extra_info->initial_sp) {
printf_filtered (" The initial stack pointer for this frame was 0x%lx.\n",
(unsigned long) frame->extra_info->initial_sp);
} else {
printf_filtered (" Unable to determine initial stack pointer for this frame.\n");
}
ppc_frame_cache_boundaries (frame, NULL);
if (frame->extra_info->bounds != NULL) {
ppc_print_boundaries (frame->extra_info->bounds);
} else {
printf_filtered (" Unable to determine function boundary information.\n");
}
ppc_frame_cache_properties (frame, NULL);
if (frame->extra_info->props != NULL) {
ppc_print_properties (frame->extra_info->props);
} else {
printf_filtered (" Unable to determine function property information.\n");
}
}
struct ppc_init_frame_pc_args
{
int fromleaf;
struct frame_info *frame;
};
int
ppc_init_frame_pc_first_unsafe (struct ppc_init_frame_pc_args *args)
{
struct frame_info *frame = args->frame;
struct frame_info *next;
CHECK_FATAL (frame != NULL);
next = get_next_frame (frame);
CHECK_FATAL (next != NULL);
frame->pc = ppc_frame_saved_pc (next);
return 1;
}
void
ppc_init_frame_pc_first (int fromleaf, struct frame_info *frame)
{
struct ppc_init_frame_pc_args args;
args.fromleaf = fromleaf;
args.frame = frame;
if (! catch_errors ((catch_errors_ftype *) ppc_init_frame_pc_first_unsafe,
&args, "", RETURN_MASK_ERROR))
{
ppc_debug ("ppc_init_frame_pc_first: got an error calling %s.\n",
"ppc_frame_saved_pc.\n");
}
}
void
ppc_init_frame_pc (int fromleaf, struct frame_info *frame)
{
CHECK_FATAL (frame != NULL);
}
CORE_ADDR
ppc_get_unsaved_pc (struct frame_info *frame, ppc_function_properties *props)
{
struct frame_info *cur_frame;
CORE_ADDR retval;
if ((props->lr_reg == -1)
|| ((props->lr_invalid == 0)
|| (frame->pc <= props->lr_invalid)
|| (frame->pc > props->lr_valid_again)))
{
ppc_debug ("ppc_get_unsaved_pc: link register was not saved.\n");
cur_frame = get_current_frame ();
set_current_frame (frame);
retval = read_register (LR_REGNUM);
set_current_frame (cur_frame);
}
else
{
ppc_debug ("ppc_get_unsaved_pc: link register stashed in register %d.\n",
props->lr_reg);
cur_frame = get_current_frame ();
set_current_frame (frame);
retval = read_register (props->lr_reg);
set_current_frame (cur_frame);
}
return retval;
}
CORE_ADDR
ppc_frame_find_pc (frame)
struct frame_info *frame;
{
CORE_ADDR prev;
CHECK_FATAL (frame != NULL);
if (PC_IN_CALL_DUMMY (frame->pc, frame->frame, frame->frame))
return deprecated_read_register_dummy (frame->pc, frame->frame, PC_REGNUM);
if (frame->next)
if (PC_IN_CALL_DUMMY (frame->next->pc, frame->next->frame, frame->next->frame))
return deprecated_read_register_dummy
(frame->next->pc, frame->next->frame, LR_REGNUM);
if (frame->signal_handler_caller) {
CORE_ADDR psp = read_memory_unsigned_integer (frame->frame, 4);
CORE_ADDR retval;
ppc_debug ("ppc_frame_saved_pc: determing previous pc from signal context\n");
retval = read_memory_unsigned_integer (psp + 0x98, 4);
ppc_debug ("Signal frame at: 0x%lx, saved pc at: 0x%lx.\n", psp, retval);
return retval;
}
prev = ppc_frame_chain (frame);
if ((prev == 0) || (! ppc_frame_chain_valid (prev, frame))) {
ppc_debug ("ppc_frame_find_pc: previous stack frame not valid: returning 0\n");
return 0;
}
ppc_debug ("ppc_frame_find_pc: value of prev is 0x%lx\n", (unsigned long) prev);
if (ppc_frame_cache_properties (frame, NULL) != 0)
{
ppc_debug ("ppc_frame_find_pc: unable to find properties of function containing 0x%lx\n",
(unsigned long) frame->pc);
ppc_debug ("ppc_frame_find_pc: assuming link register saved in normal location\n");
if (ppc_frameless_function_invocation (frame))
{
return read_register (LR_REGNUM);
}
else
{
ppc_function_properties lprops;
CORE_ADDR body_start;
body_start = ppc_parse_instructions (frame->pc, INVALID_ADDRESS,
&lprops);
if ((frame->next == NULL && lprops.lr_saved == 0) ||
(lprops.lr_saved >= frame->pc))
{
return ppc_get_unsaved_pc (frame, &lprops);
}
else
{
return read_memory_unsigned_integer (prev + DEFAULT_LR_SAVE, 4);
}
}
}
else
{
ppc_function_properties *props;
props = frame->extra_info->props;
CHECK_FATAL (props != NULL);
if (props->lr_saved)
{
if (props->lr_saved < frame->pc)
{
return read_memory_unsigned_integer (prev
+ props->lr_offset, 4);
}
else
{
ppc_debug ("ppc_frame_find_pc: function did not save link register\n");
return ppc_get_unsaved_pc (frame, props);
}
}
else if (frame->next && frame->next->signal_handler_caller)
{
ppc_debug ("ppc_frame_find_pc: %s\n",
"using link area from signal handler.");
return read_memory_unsigned_integer (frame->frame - 0x320
+ DEFAULT_LR_SAVE, 4);
}
else if (frame->next && ppc_is_dummy_frame (frame->next))
{
ppc_debug ("ppc_frame_find_pc: using link area from call dummy\n");
return read_memory_unsigned_integer (frame->frame - 0x1c, 4);
}
else if (!props->lr_saved)
{
return ppc_get_unsaved_pc (frame, props);
}
else
{
ppc_debug ("ppc_frame_find_pc: function is not a leaf\n");
ppc_debug ("ppc_frame_find_pc: assuming link register saved in normal location\n");
return read_memory_unsigned_integer (prev + DEFAULT_LR_SAVE, 4);
}
}
return 0;
}
CORE_ADDR
ppc_frame_saved_pc (struct frame_info *frame)
{
return (ppc_frame_find_pc (frame));
}
CORE_ADDR
ppc_frame_saved_pc_after_call (struct frame_info *frame)
{
CHECK_FATAL (frame != NULL);
return read_register (LR_REGNUM);
}
CORE_ADDR
ppc_frame_chain (struct frame_info *frame)
{
CORE_ADDR psp = read_memory_unsigned_integer (frame->frame, 4);
if (PC_IN_CALL_DUMMY (frame->pc, frame->frame, frame->frame))
return psp;
if (frame->signal_handler_caller) {
return read_memory_unsigned_integer (psp + 0x98 + 0xc, 4);
}
if (frame->next != NULL
&& frame->next->signal_handler_caller
&& ppc_frameless_function_invocation (frame)) {
return frame->frame;
}
return psp;
}
int
ppc_frame_chain_valid (CORE_ADDR chain, struct frame_info *frame)
{
unsigned long retval;
if (chain == 0) { return 0; }
if (!safe_read_memory_unsigned_integer (chain, 4, &retval))
{
ppc_debug ("ppc_frame_chain_valid: Got an error reading at 0x%lx",
chain);
return 0;
}
else
if (retval == 0) { return 0; }
#if 0
if (inside_entry_func (frame->pc)) { return 0; }
if (inside_main_func (frame->pc)) { return 0; }
#endif
if (! (chain >= frame->frame)) {
warning ("ppc_frame_chain_valid: stack pointer from 0x%lx to 0x%lx "
"grows upward; assuming invalid\n",
(unsigned long) frame->frame, (unsigned long) chain);
return 0;
}
if ((chain - frame->frame) > ppc_max_frame_size) {
warning ("ppc_frame_chain_valid: stack frame from 0x%lx to 0x%lx "
"larger than ppc-maximum-frame-size bytes; assuming invalid",
(unsigned long) frame->frame, (unsigned long) chain);
return 0;
}
return 1;
}
int
ppc_is_dummy_frame (struct frame_info *frame)
{
CORE_ADDR chain = read_memory_unsigned_integer (frame->frame, 4);
if (frame->signal_handler_caller) {
chain = read_memory_unsigned_integer (chain + 0x98 + 0xc, 4);
}
if (chain == 0) { return 0; }
return (PC_IN_CALL_DUMMY (frame->pc, frame->frame, chain));
}
CORE_ADDR
ppc_frame_cache_initial_stack_address (struct frame_info *frame)
{
CHECK_FATAL (frame != NULL);
CHECK_FATAL (frame->extra_info != NULL);
if (frame->extra_info->initial_sp == 0) {
frame->extra_info->initial_sp = ppc_frame_initial_stack_address (frame);
}
return frame->extra_info->initial_sp;
}
CORE_ADDR
ppc_frame_initial_stack_address (struct frame_info *frame)
{
CORE_ADDR tmpaddr;
struct frame_info *callee;
if (ppc_frame_cache_properties (frame, NULL) != 0) {
ppc_debug ("ppc_frame_initial_stack_address: unable to find properties of "
"function containing 0x%lx\n", frame->pc);
return 0;
}
ppc_frame_cache_saved_regs (frame);
if (frame->extra_info->props->frameptr_reg < 0) {
frame->extra_info->initial_sp = frame->frame;
return frame->extra_info->initial_sp;
}
if (! get_next_frame (frame))
{
frame->extra_info->initial_sp
= read_register (frame->extra_info->props->frameptr_reg);
return frame->extra_info->initial_sp;
}
for (callee = get_next_frame (frame); callee != NULL;
callee = get_next_frame (callee))
{
ppc_frame_cache_saved_regs (callee);
tmpaddr = callee->saved_regs[frame->extra_info->props->frameptr_reg];
if (tmpaddr) {
frame->extra_info->initial_sp
= read_memory_unsigned_integer (tmpaddr, 4);
return frame->extra_info->initial_sp;
}
}
frame->extra_info->initial_sp
= read_register (frame->extra_info->props->frameptr_reg);
return frame->extra_info->initial_sp;
}
int ppc_use_struct_convention (int gccp, struct type *valtype)
{
return 1;
}
CORE_ADDR
ppc_extract_struct_value_address (char regbuf[REGISTER_BYTES])
{
return extract_unsigned_integer (®buf[REGISTER_BYTE (GP0_REGNUM + 3)], 4);
}
void
ppc_extract_return_value (struct type *valtype, char *regbuf, char *valbuf)
{
int offset = 0;
if (TYPE_CODE (valtype) == TYPE_CODE_FLT)
{
double dd;
float ff;
if (TYPE_LENGTH (valtype) > 4)
memcpy (valbuf,
®buf[REGISTER_BYTE (FP0_REGNUM + 1)],
TYPE_LENGTH (valtype));
else
{
memcpy (&dd, ®buf[REGISTER_BYTE (FP0_REGNUM + 1)], 8);
ff = (float) dd;
memcpy (valbuf, &ff, sizeof (float));
}
}
else if (TYPE_CODE (valtype) == TYPE_CODE_ARRAY
&& TYPE_LENGTH (valtype) == 16
&& TYPE_VECTOR (valtype))
{
memcpy (valbuf, regbuf + REGISTER_BYTE (VP0_REGNUM + 2),
TYPE_LENGTH (valtype));
}
else
{
if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG
&& TYPE_LENGTH (valtype) < REGISTER_RAW_SIZE (3))
offset = REGISTER_RAW_SIZE (3) - TYPE_LENGTH (valtype);
memcpy (valbuf,
regbuf + REGISTER_BYTE (3) + offset,
TYPE_LENGTH (valtype));
}
}
CORE_ADDR
ppc_skip_prologue (CORE_ADDR pc)
{
ppc_function_boundaries_request request;
ppc_function_boundaries bounds;
int ret;
ppc_clear_function_boundaries_request (&request);
ppc_clear_function_boundaries (&bounds);
request.prologue_start = pc;
ret = ppc_find_function_boundaries (&request, &bounds);
if (ret != 0) { return 0; }
return bounds.body_start;
}
int
ppc_frameless_function_invocation (struct frame_info *frame)
{
if (frame->next != NULL
&& !frame->next->signal_handler_caller
&& !ppc_is_dummy_frame (frame->next))
{
return 0;
}
if (ppc_frame_cache_properties (frame, NULL) != 0) {
ppc_debug ("frameless_function_invocation: unable to find properties of "
"function containing 0x%lx; assuming not frameless\n",
frame->pc);
return 0;
}
return frame->extra_info->props->frameless;
}
const char *gdb_register_names[] =
{
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
"r8", "r9", "r10","r11","r12","r13","r14","r15",
"r16","r17","r18","r19","r20","r21","r22","r23",
"r24","r25","r26","r27","r28","r29","r30","r31",
"f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
"f8", "f9", "f10","f11","f12","f13","f14","f15",
"f16","f17","f18","f19","f20","f21","f22","f23",
"f24","f25","f26","f27","f28","f29","f30","f31",
"v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7",
"v8", "v9", "v10","v11","v12","v13","v14","v15",
"v16","v17","v18","v19","v20","v21","v22","v23",
"v24","v25","v26","v27","v28","v29","v30","v31",
"pc", "ps", "cr", "lr", "ctr", "xer", "mq",
"fpscr",
"vscr", "vrsave"
};
const char *
ppc_register_name (int reg_nr)
{
if (reg_nr < 0)
return NULL;
if (reg_nr >= (sizeof (gdb_register_names) / sizeof (*gdb_register_names)))
return NULL;
return gdb_register_names[reg_nr];
}
void ppc_store_struct_return (CORE_ADDR addr, CORE_ADDR sp)
{
write_register (SRA_REGNUM, addr);
}
void ppc_store_return_value (struct type *type, char *valbuf)
{
unsigned int regbase = -1;
unsigned int offset = 0;
if (TYPE_CODE (type) == TYPE_CODE_FLT)
regbase = FP0_REGNUM + 1;
else if ((TYPE_CODE (type) == TYPE_CODE_ARRAY) && TYPE_VECTOR (type))
regbase = VP0_REGNUM + 2;
else
regbase = GP0_REGNUM + 3;
if ((REGISTER_RAW_SIZE (regbase) > TYPE_LENGTH (type))
&& (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG))
{
offset = REGISTER_RAW_SIZE (regbase) - TYPE_LENGTH (type);
}
if ((TYPE_CODE (type) == TYPE_CODE_FLT) && (TYPE_LENGTH (type) < 8))
{
char buf[8];
double d = extract_floating (valbuf, TYPE_LENGTH (type));
store_floating (buf, 8, d);
write_register_bytes (REGISTER_BYTE (regbase), buf, 8);
}
else
write_register_bytes (REGISTER_BYTE (regbase) + offset, valbuf, TYPE_LENGTH (type));
}
CORE_ADDR ppc_push_return_address (CORE_ADDR pc, CORE_ADDR sp)
{
unsigned char buf[4];
store_address (buf, 4, CALL_DUMMY_ADDRESS ());
write_register (LR_REGNUM, CALL_DUMMY_ADDRESS ());
write_memory (sp + 8, buf, 4);
return sp;
}
int ppc_register_convertible (int regno)
{
return ((regno >= FIRST_FP_REGNUM) && (regno <= LAST_FP_REGNUM));
}
void ppc_register_convert_to_virtual
(int regno, struct type *type, char *from, char *to)
{
if (TYPE_LENGTH (type) != REGISTER_RAW_SIZE (regno))
{
double val = extract_floating (from, REGISTER_RAW_SIZE (regno));
store_floating (to, TYPE_LENGTH (type), val);
}
else
memcpy (to, from, REGISTER_RAW_SIZE (regno));
}
void ppc_register_convert_to_raw
(struct type *type, int regno, char *from, char *to)
{
if (TYPE_LENGTH (type) != REGISTER_RAW_SIZE (regno))
{
double val = extract_floating (from, TYPE_LENGTH (type));
store_floating (to, REGISTER_RAW_SIZE (regno), val);
}
else
memcpy (to, from, REGISTER_RAW_SIZE (regno));
}
#define BIG_BREAKPOINT { 0x7f, 0xe0, 0x00, 0x08 }
#define LITTLE_BREAKPOINT { 0x08, 0x00, 0xe0, 0x7f }
static const unsigned char *
ppc_breakpoint_from_pc (CORE_ADDR *addr, int *size)
{
static unsigned char big_breakpoint[] = BIG_BREAKPOINT;
static unsigned char little_breakpoint[] = LITTLE_BREAKPOINT;
*size = 4;
if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
return big_breakpoint;
else
return little_breakpoint;
}
static int
ppc_register_byte (int N)
{
return (((N) >= FIRST_SP_REGNUM) ? ((((N) - FIRST_SP_REGNUM) * 4) + SIZE_GP_REGS + SIZE_FP_REGS + SIZE_VP_REGS) \
: (((N) >= FIRST_VP_REGNUM) ? ((((N) - FIRST_VP_REGNUM) * 16) + SIZE_GP_REGS + SIZE_FP_REGS) \
: (((N) >= FIRST_FP_REGNUM) ? ((((N) - FIRST_FP_REGNUM) * 8) + SIZE_GP_REGS) \
: ((N) * 4))));
}
static int
ppc_register_raw_size (int N)
{
return (((N) >= FIRST_SP_REGNUM) ? 4
: (((N) >= FIRST_VP_REGNUM) ? 16
: (((N) >= FIRST_FP_REGNUM) ? 8
: 4)));
}
static int
ppc_register_virtual_size (int N)
{
return (((N) >= FIRST_SP_REGNUM) ? 4
: (((N) >= FIRST_VP_REGNUM) ? 16
: (((N) >= FIRST_FP_REGNUM) ? 8
: 4)));
}
static struct type *
ppc_register_virtual_type (int N)
{
return (((N) >= FIRST_SP_REGNUM) ? builtin_type_unsigned_int
: (((N) >= FIRST_VP_REGNUM) ? builtin_type_vec128
: (((N) >= FIRST_FP_REGNUM) ? builtin_type_double
: builtin_type_unsigned_int)));
}
CORE_ADDR
rs6000_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
int struct_return, CORE_ADDR struct_addr);
#define INSTRUCTION_SIZE 4
static struct gdbarch *
ppc_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
{
struct gdbarch *gdbarch;
struct gdbarch_tdep *tdep;
arches = gdbarch_list_lookup_by_info (arches, &info);
if (arches != NULL)
return arches->gdbarch;
tdep = XMALLOC (struct gdbarch_tdep);
gdbarch = gdbarch_alloc (&info, tdep);
tdep->wordsize = 4;
tdep->ppc_lr_regnum = LR_REGNUM;
set_gdbarch_sp_regnum (gdbarch, SP_REGNUM);
set_gdbarch_fp_regnum (gdbarch, FP_REGNUM);
set_gdbarch_pc_regnum (gdbarch, PC_REGNUM);
set_gdbarch_ps_regnum (gdbarch, -1);
set_gdbarch_fp0_regnum (gdbarch, FP0_REGNUM);
set_gdbarch_npc_regnum (gdbarch, -1);
set_gdbarch_read_pc (gdbarch, generic_target_read_pc);
set_gdbarch_write_pc (gdbarch, generic_target_write_pc);
set_gdbarch_read_fp (gdbarch, generic_target_read_fp);
set_gdbarch_read_sp (gdbarch, generic_target_read_sp);
set_gdbarch_write_sp (gdbarch, generic_target_write_sp);
set_gdbarch_num_regs (gdbarch, NUM_REGS);
set_gdbarch_sp_regnum (gdbarch, SP_REGNUM);
set_gdbarch_fp_regnum (gdbarch, FP_REGNUM);
set_gdbarch_pc_regnum (gdbarch, PC_REGNUM);
set_gdbarch_register_name (gdbarch, ppc_register_name);
set_gdbarch_register_size (gdbarch, 4);
set_gdbarch_register_bytes (gdbarch, REGISTER_BYTES);
set_gdbarch_register_byte (gdbarch, ppc_register_byte);
set_gdbarch_register_raw_size (gdbarch, ppc_register_raw_size);
set_gdbarch_max_register_raw_size (gdbarch, 16);
set_gdbarch_register_virtual_size (gdbarch, ppc_register_virtual_size);
set_gdbarch_max_register_virtual_size (gdbarch, 16);
set_gdbarch_register_virtual_type (gdbarch, ppc_register_virtual_type);
set_gdbarch_ptr_bit (gdbarch, 4 * TARGET_CHAR_BIT);
set_gdbarch_short_bit (gdbarch, 2 * TARGET_CHAR_BIT);
set_gdbarch_int_bit (gdbarch, 4 * TARGET_CHAR_BIT);
set_gdbarch_long_bit (gdbarch, 4 * TARGET_CHAR_BIT);
set_gdbarch_long_long_bit (gdbarch, 8 * TARGET_CHAR_BIT);
set_gdbarch_float_bit (gdbarch, 4 * TARGET_CHAR_BIT);
set_gdbarch_double_bit (gdbarch, 8 * TARGET_CHAR_BIT);
set_gdbarch_long_double_bit (gdbarch, 8 * TARGET_CHAR_BIT);
set_gdbarch_addr_bit (gdbarch, 4 * TARGET_CHAR_BIT);
switch (info.byte_order)
{
case BFD_ENDIAN_BIG:
set_gdbarch_float_format (gdbarch, &floatformat_ieee_single_big);
set_gdbarch_double_format (gdbarch, &floatformat_ieee_double_big);
set_gdbarch_long_double_format (gdbarch, &floatformat_ieee_double_big);
break;
case BFD_ENDIAN_LITTLE:
set_gdbarch_float_format (gdbarch, &floatformat_ieee_single_little);
set_gdbarch_double_format (gdbarch, &floatformat_ieee_double_little);
set_gdbarch_long_double_format (gdbarch, &floatformat_ieee_double_little);
break;
default:
internal_error (__FILE__, __LINE__, "ppc_gdbarch_init: bad byte order for float format");
}
set_gdbarch_use_generic_dummy_frames (gdbarch, 1);
set_gdbarch_call_dummy_length (gdbarch, 0);
set_gdbarch_call_dummy_location (gdbarch, AT_ENTRY_POINT);
set_gdbarch_call_dummy_address (gdbarch, entry_point_address);
set_gdbarch_call_dummy_breakpoint_offset_p (gdbarch, 1);
set_gdbarch_call_dummy_breakpoint_offset (gdbarch, 0);
set_gdbarch_call_dummy_start_offset (gdbarch, 0);
set_gdbarch_sizeof_call_dummy_words (gdbarch, 0);
set_gdbarch_call_dummy_words (gdbarch, NULL);
set_gdbarch_pc_in_call_dummy (gdbarch, generic_pc_in_call_dummy);
set_gdbarch_call_dummy_p (gdbarch, 1);
set_gdbarch_call_dummy_stack_adjust_p (gdbarch, 0);
set_gdbarch_get_saved_register (gdbarch, generic_unwind_get_saved_register);
set_gdbarch_push_dummy_frame (gdbarch, generic_push_dummy_frame);
set_gdbarch_save_dummy_frame_tos (gdbarch, generic_save_dummy_frame_tos);
set_gdbarch_call_dummy_stack_adjust_p (gdbarch, 0);
set_gdbarch_fix_call_dummy (gdbarch, generic_fix_call_dummy);
set_gdbarch_push_return_address (gdbarch, ppc_push_return_address);
set_gdbarch_believe_pcc_promotion (gdbarch, 1);
set_gdbarch_coerce_float_to_double (gdbarch, standard_coerce_float_to_double);
set_gdbarch_register_convertible (gdbarch, ppc_register_convertible);
set_gdbarch_register_convert_to_virtual (gdbarch, ppc_register_convert_to_virtual);
set_gdbarch_register_convert_to_raw (gdbarch, ppc_register_convert_to_raw);
set_gdbarch_stab_reg_to_regnum (gdbarch, ppc_macosx_stab_reg_to_regnum);
set_gdbarch_deprecated_extract_return_value (gdbarch, ppc_extract_return_value);
set_gdbarch_push_arguments (gdbarch, rs6000_push_arguments);
set_gdbarch_store_struct_return (gdbarch, ppc_store_struct_return);
set_gdbarch_deprecated_store_return_value (gdbarch, ppc_store_return_value);
set_gdbarch_deprecated_extract_struct_value_address (gdbarch, ppc_extract_struct_value_address);
set_gdbarch_pop_frame (gdbarch, rs6000_pop_frame);
set_gdbarch_use_struct_convention (gdbarch, ppc_use_struct_convention);
set_gdbarch_skip_prologue (gdbarch, ppc_skip_prologue);
set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
set_gdbarch_decr_pc_after_break (gdbarch, 0);
set_gdbarch_function_start_offset (gdbarch, 0);
set_gdbarch_breakpoint_from_pc (gdbarch, ppc_breakpoint_from_pc);
set_gdbarch_frame_args_skip (gdbarch, 0);
set_gdbarch_frame_chain_valid (gdbarch, ppc_frame_chain_valid);
set_gdbarch_frameless_function_invocation (gdbarch, ppc_frameless_function_invocation);
set_gdbarch_frame_chain (gdbarch, ppc_frame_chain);
set_gdbarch_frame_saved_pc (gdbarch, ppc_frame_saved_pc);
set_gdbarch_frame_init_saved_regs (gdbarch, ppc_frame_cache_saved_regs);
set_gdbarch_init_extra_frame_info (gdbarch, ppc_init_extra_frame_info);
set_gdbarch_frame_args_address (gdbarch, ppc_frame_cache_initial_stack_address);
set_gdbarch_frame_locals_address (gdbarch, ppc_frame_cache_initial_stack_address);
set_gdbarch_saved_pc_after_call (gdbarch, ppc_frame_saved_pc_after_call);
set_gdbarch_init_frame_pc_first (gdbarch, ppc_init_frame_pc_first);
set_gdbarch_skip_trampoline_code (gdbarch, ppc_macosx_skip_trampoline_code);
set_gdbarch_dynamic_trampoline_nextpc (gdbarch, ppc_macosx_dynamic_trampoline_nextpc);
set_gdbarch_frame_num_args (gdbarch, frame_num_args_unknown);
set_gdbarch_in_solib_call_trampoline (gdbarch, ppc_macosx_in_solib_call_trampoline);
set_gdbarch_in_solib_return_trampoline (gdbarch, ppc_macosx_in_solib_return_trampoline);
set_gdbarch_init_frame_pc_first (gdbarch, ppc_init_frame_pc_first);
set_gdbarch_init_frame_pc (gdbarch, ppc_init_frame_pc);
return gdbarch;
}
int
ppc_fast_show_stack (int show_frames, int get_names, int limit, int *count,
void (print_fun) (struct ui_out *uiout, int frame_num,
CORE_ADDR pc, CORE_ADDR fp))
{
CORE_ADDR fp;
static CORE_ADDR sigtramp_start = 0;
static CORE_ADDR sigtramp_end = 0;
struct frame_info *fi;
int i = 0, valid = 0;
unsigned long next_fp, pc;
int should_print;
if (sigtramp_start == 0)
{
char *name;
struct minimal_symbol *msymbol;
msymbol = lookup_minimal_symbol ("_sigtramp", NULL, NULL);
if (msymbol == NULL)
warning ("Couldn't find minimal symbol for \"_sigtramp\" - backtraces may be unreliable");
else
{
pc = SYMBOL_VALUE_ADDRESS (msymbol);
if (find_pc_partial_function (pc, &name,
&sigtramp_start, &sigtramp_end) == 0)
{
error ("Couldn't find _sigtramp symbol - backtraces will be unreliable");
}
}
}
if (show_frames && print_fun)
should_print = 1;
else
should_print = 0;
if (show_frames)
ui_out_list_begin (uiout, "frames");
i = 0;
fi = get_current_frame();
if (fi == NULL)
{
goto ppc_count_finish;
}
if (should_print)
print_fun (uiout, i, fi->pc, fi->frame);
i = 1;
valid = 1;
if (limit == 1)
goto ppc_count_finish;
fi = get_prev_frame(fi);
if (fi == NULL)
{
goto ppc_count_finish;
}
pc = fi->pc;
fp = fi->frame;
if (should_print)
print_fun (uiout, i, pc, fp);
i = 2;
if (safe_read_memory_unsigned_integer (fp, 4, &next_fp))
{
while (1) {
if (limit != 0 && i == limit)
{
should_print = 0;
}
if ((sigtramp_start<= pc) && (pc <= sigtramp_end))
{
fp = next_fp + 0x98 + 0xc;
if (!safe_read_memory_unsigned_integer (fp,
4, &next_fp))
goto ppc_count_finish;
if (!safe_read_memory_unsigned_integer (fp - 0xc, 4, &pc))
goto ppc_count_finish;
fp = next_fp;
if (!safe_read_memory_unsigned_integer (fp, 4, &next_fp))
goto ppc_count_finish;
}
else
{
fp = next_fp;
if (!safe_read_memory_unsigned_integer (fp, 4, &next_fp))
goto ppc_count_finish;
if (next_fp == 0)
{
valid = 1;
goto ppc_count_finish;
}
if (i > 10000)
goto ppc_count_finish;
if (!safe_read_memory_unsigned_integer (fp + DEFAULT_LR_SAVE, 4, &pc))
goto ppc_count_finish;
}
if (should_print)
{
print_fun (uiout, i, pc, fp);
}
i++;
}
}
ppc_count_finish:
if (show_frames)
ui_out_list_end (uiout);
*count = i;
return valid;
}
CORE_ADDR ppc_macosx_skip_trampoline_code (CORE_ADDR pc)
{
return dyld_symbol_stub_function_address (pc, NULL);
}
CORE_ADDR ppc_macosx_dynamic_trampoline_nextpc (CORE_ADDR pc)
{
return dyld_symbol_stub_function_address (pc, NULL);
}
int ppc_macosx_in_solib_return_trampoline (CORE_ADDR pc, char *name)
{
return 0;
}
int ppc_macosx_in_solib_call_trampoline (CORE_ADDR pc, char *name)
{
if (ppc_macosx_skip_trampoline_code (pc) != 0) { return 1; }
return 0;
}
void
_initialize_ppc_tdep ()
{
struct cmd_list_element *cmd = NULL;
register_gdbarch_init (bfd_arch_powerpc, ppc_gdbarch_init);
tm_print_insn = print_insn_big_powerpc;
cmd = add_set_cmd ("ppc", class_obscure, var_boolean,
(char *) &ppc_debugflag,
"Set if printing PPC stack analysis debugging statements.",
&setdebuglist),
add_show_from_set (cmd, &showdebuglist);
cmd = add_set_cmd
("ppc-maximum-frame-size", class_obscure, var_uinteger,
(char *) &ppc_max_frame_size,
"Set the maximum size to expect for a valid PPC frame.",
&setlist);
add_show_from_set (cmd, &showlist);
}