/* Target-dependent code for the HP PA architecture, for GDB.
- Copyright 1986, 1987, 1989-1996, 1999-2000, 2001 Free Software
- Foundation, Inc.
+
+ Copyright 1986, 1987, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
+ 1996, 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
Contributed by the Center for Software Science at the
University of Utah (pa-gdb-bugs@cs.utah.edu).
#include "inferior.h"
#include "value.h"
#include "regcache.h"
+#include "completer.h"
+#include "language.h"
+#include "osabi.h"
/* For argument passing to the inferior */
#include "symtab.h"
static void pa_print_fp_reg (int);
static void pa_strcat_fp_reg (int, struct ui_file *, enum precision_type);
static void record_text_segment_lowaddr (bfd *, asection *, void *);
+/* FIXME: brobecker 2002-11-07: We will likely be able to make the
+ following functions static, once we hppa is partially multiarched. */
+int hppa_reg_struct_has_addr (int gcc_p, struct type *type);
+int hppa_inner_than (CORE_ADDR lhs, CORE_ADDR rhs);
+CORE_ADDR hppa_stack_align (CORE_ADDR sp);
+int hppa_pc_requires_run_before_use (CORE_ADDR pc);
+int hppa_instruction_nullified (void);
+int hppa_register_byte (int reg_nr);
+struct type * hppa_register_virtual_type (int reg_nr);
+void hppa_store_struct_return (CORE_ADDR addr, CORE_ADDR sp);
+int hppa_cannot_store_register (int regnum);
+CORE_ADDR hppa_frame_args_address (struct frame_info *fi);
+CORE_ADDR hppa_frame_locals_address (struct frame_info *fi);
+CORE_ADDR hppa_smash_text_address (CORE_ADDR addr);
+int hppa_coerce_float_to_double (struct type *formal, struct type *actual);
typedef struct
{
/* In breakpoint.c */
extern int exception_catchpoints_are_fragile;
-/* This is defined in valops.c. */
-extern value_ptr find_function_in_inferior (char *);
-
/* Should call_function allocate stack space for a struct return? */
+
int
hppa_use_struct_convention (int gcc_p, struct type *type)
{
static void
record_text_segment_lowaddr (bfd *abfd, asection *section, void *ignored)
{
- if ((section->flags & (SEC_ALLOC | SEC_LOAD | SEC_READONLY)
+ if (((section->flags & (SEC_ALLOC | SEC_LOAD | SEC_READONLY))
== (SEC_ALLOC | SEC_LOAD | SEC_READONLY))
&& section->vma < low_text_segment_address)
low_text_segment_address = section->vma;
its frame isn't a pure interrupt frame. Deal with this. */
msym_us = lookup_minimal_symbol_by_pc (pc);
- return u->HP_UX_interrupt_marker && !IN_SIGTRAMP (pc, SYMBOL_NAME (msym_us));
+ return (u->HP_UX_interrupt_marker
+ && !PC_IN_SIGTRAMP (pc, SYMBOL_NAME (msym_us)));
}
/* Called when no unwind descriptor was found for PC. Returns 1 if it
/* If Save_SP is set, and we're not in an interrupt or signal caller,
then we have a frame pointer. Use it. */
- if (u->Save_SP && !pc_in_interrupt_handler (pc)
- && !IN_SIGTRAMP (pc, SYMBOL_NAME (msym_us)))
+ if (u->Save_SP
+ && !pc_in_interrupt_handler (pc)
+ && msym_us
+ && !PC_IN_SIGTRAMP (pc, SYMBOL_NAME (msym_us)))
return -1;
return u->Total_frame_size << 3;
return (u->Total_frame_size == 0 && u->stub_unwind.stub_type == 0);
}
+/* Immediately after a function call, return the saved pc.
+ Can't go through the frames for this because on some machines
+ the new frame is not set up until the new function executes
+ some instructions. */
+
CORE_ADDR
saved_pc_after_call (struct frame_info *frame)
{
#ifdef FRAME_SAVED_PC_IN_SIGTRAMP
/* Deal with signal handler caller frames too. */
- if (frame->signal_handler_caller)
+ if ((get_frame_type (frame) == SIGTRAMP_FRAME))
{
CORE_ADDR rp;
FRAME_SAVED_PC_IN_SIGTRAMP (frame, &rp);
register area to get the return pointer (the values
in the registers may not correspond to anything useful). */
if (frame->next
- && (frame->next->signal_handler_caller
+ && ((get_frame_type (frame->next) == SIGTRAMP_FRAME)
|| pc_in_interrupt_handler (frame->next->pc)))
{
struct frame_saved_regs saved_regs;
- get_frame_saved_regs (frame->next, &saved_regs);
+ deprecated_get_frame_saved_regs (frame->next, &saved_regs);
if (read_memory_integer (saved_regs.regs[FLAGS_REGNUM],
TARGET_PTR_BIT / 8) & 0x2)
{
information out of the saved register info. */
if (rp_offset == 0
&& frame->next
- && (frame->next->signal_handler_caller
+ && ((get_frame_type (frame->next) == SIGTRAMP_FRAME)
|| pc_in_interrupt_handler (frame->next->pc)))
{
struct frame_saved_regs saved_regs;
- get_frame_saved_regs (frame->next, &saved_regs);
+ deprecated_get_frame_saved_regs (frame->next, &saved_regs);
if (read_memory_integer (saved_regs.regs[FLAGS_REGNUM],
TARGET_PTR_BIT / 8) & 0x2)
{
frame->frame = read_register (SP_REGNUM) - framesize;
}
\f
-/* Given a GDB frame, determine the address of the calling function's frame.
- This will be used to create a new GDB frame struct, and then
- INIT_EXTRA_FRAME_INFO and INIT_FRAME_PC will be called for the new frame.
+/* Given a GDB frame, determine the address of the calling function's
+ frame. This will be used to create a new GDB frame struct, and
+ then INIT_EXTRA_FRAME_INFO and DEPRECATED_INIT_FRAME_PC will be
+ called for the new frame.
This may involve searching through prologues for several functions
at boundaries where GCC calls HP C code, or where code which has
frame_base = read_memory_integer (frame->frame + SP_REGNUM * 4,
TARGET_PTR_BIT / 8);
#ifdef FRAME_BASE_BEFORE_SIGTRAMP
- else if (frame->signal_handler_caller)
+ else if ((get_frame_type (frame) == SIGTRAMP_FRAME))
{
FRAME_BASE_BEFORE_SIGTRAMP (frame, &frame_base);
}
}
if (u->Save_SP
- || tmp_frame->signal_handler_caller
+ || (get_frame_type (tmp_frame) == SIGTRAMP_FRAME)
|| pc_in_interrupt_handler (tmp_frame->pc))
break;
/* The unwind entry claims that r3 is saved here. However,
in optimized code, GCC often doesn't actually save r3.
We'll discover this if we look at the prologue. */
- get_frame_saved_regs (tmp_frame, &saved_regs);
+ deprecated_get_frame_saved_regs (tmp_frame, &saved_regs);
saved_regs_frame = tmp_frame;
/* If we have an address for r3, that's good. */
/* We may have walked down the chain into a function with a frame
pointer. */
if (u->Save_SP
- && !tmp_frame->signal_handler_caller
+ && !(get_frame_type (tmp_frame) == SIGTRAMP_FRAME)
&& !pc_in_interrupt_handler (tmp_frame->pc))
{
return read_memory_integer (tmp_frame->frame, TARGET_PTR_BIT / 8);
system call has a variable sized stack frame. */
if (tmp_frame != saved_regs_frame)
- get_frame_saved_regs (tmp_frame, &saved_regs);
+ deprecated_get_frame_saved_regs (tmp_frame, &saved_regs);
/* Abominable hack. */
if (current_target.to_has_execution == 0
tmp_frame = tmp_frame->next;
if (tmp_frame != saved_regs_frame)
- get_frame_saved_regs (tmp_frame, &saved_regs);
+ deprecated_get_frame_saved_regs (tmp_frame, &saved_regs);
/* Abominable hack. See above. */
if (current_target.to_has_execution == 0
and doesn't "call" an interrupt routine or signal handler caller,
then its not valid. */
if (u->Save_SP || u->Total_frame_size || u->stub_unwind.stub_type != 0
- || (thisframe->next && thisframe->next->signal_handler_caller)
+ || (thisframe->next && (get_frame_type (thisframe->next) == SIGTRAMP_FRAME))
|| (next_u && next_u->HP_UX_interrupt_marker))
return 1;
We also need a number of horrid hacks to deal with lossage in the
PC queue registers (apparently they're not valid when the in syscall
bit is set). */
- pc = target_read_pc (inferior_pid);
+ pc = target_read_pc (inferior_ptid);
int_buffer = read_register (FLAGS_REGNUM);
if (int_buffer & 0x2)
{
for (regnum = FP0_REGNUM; regnum < NUM_REGS; regnum++)
{
- read_register_bytes (REGISTER_BYTE (regnum), (char *) &freg_buffer, 8);
+ deprecated_read_register_bytes (REGISTER_BYTE (regnum),
+ (char *) &freg_buffer, 8);
sp = push_bytes (sp, (char *) &freg_buffer, 8);
}
sp = push_word (sp, read_register (IPSW_REGNUM));
struct frame_saved_regs fsr;
double freg_buffer;
- fp = FRAME_FP (frame);
- get_frame_saved_regs (frame, &fsr);
+ fp = get_frame_base (frame);
+ deprecated_get_frame_saved_regs (frame, &fsr);
#ifndef NO_PC_SPACE_QUEUE_RESTORE
if (fsr.regs[IPSW_REGNUM]) /* Restoring a call dummy frame */
if (fsr.regs[regnum])
{
read_memory (fsr.regs[regnum], (char *) &freg_buffer, 8);
- write_register_bytes (REGISTER_BYTE (regnum), (char *) &freg_buffer, 8);
+ deprecated_write_register_bytes (REGISTER_BYTE (regnum),
+ (char *) &freg_buffer, 8);
}
if (fsr.regs[IPSW_REGNUM])
for "return_command" will print the frame we returned to. */
sal = find_pc_line (target_pc, 0);
sal.pc = target_pc;
- breakpoint = set_momentary_breakpoint (sal, NULL, bp_finish);
+ breakpoint = set_momentary_breakpoint (sal, null_frame_id, bp_finish);
breakpoint->silent = 1;
/* So we can clean things up. */
any other choice? Is there *any* way to do this stuff with
ptrace() or some equivalent?). */
resume (1, 0);
- target_wait (inferior_pid, &w);
+ target_wait (inferior_ptid, &w);
if (w.kind == TARGET_WAITKIND_SIGNALLED)
{
to the callee, so we do that too. */
CORE_ADDR
-hppa_push_arguments (int nargs, value_ptr *args, CORE_ADDR sp,
+hppa_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
int struct_return, CORE_ADDR struct_addr)
{
/* array of arguments' offsets */
arguments into registers as needed by the ABI. */
CORE_ADDR
-hppa_push_arguments (int nargs, value_ptr *args, CORE_ADDR sp,
+hppa_push_arguments (int nargs, struct value **args, CORE_ADDR sp,
int struct_return, CORE_ADDR struct_addr)
{
/* array of arguments' offsets */
target. */
bytes_reserved = (lengths[i] + REGISTER_SIZE - 1) & -REGISTER_SIZE;
- offset[i] = cum_bytes_reserved + lengths[i];
+ offset[i] = (cum_bytes_reserved
+ + (lengths[i] > 4 ? bytes_reserved : lengths[i]));
/* If the argument is a double word argument, then it needs to be
double word aligned. */
This function does the same stuff as value_being_returned in values.c, but
gets the value from the stack rather than from the buffer where all the
registers were saved when the function called completed. */
-value_ptr
+struct value *
hppa_value_returned_from_stack (register struct type *valtype, CORE_ADDR addr)
{
- register value_ptr val;
+ register struct value *val;
val = allocate_value (valtype);
CHECK_TYPEDEF (valtype);
struct symbol *get_sym, *symbol2;
struct minimal_symbol *buff_minsym, *msymbol;
struct type *ftype;
- value_ptr *args;
- value_ptr funcval, val;
+ struct value **args;
+ struct value *funcval;
+ struct value *val;
int x, namelen, err_value, tmp = -1;
CORE_ADDR endo_buff_addr, value_return_addr, errno_return_addr;
CORE_ADDR stub_addr;
- args = (value_ptr *) alloca (sizeof (value_ptr) * 8); /* 6 for the arguments and one null one??? */
+ args = alloca (sizeof (struct value *) * 8); /* 6 for the arguments and one null one??? */
funcval = find_function_in_inferior ("__d_shl_get");
get_sym = lookup_symbol ("__d_shl_get", NULL, VAR_NAMESPACE, NULL, NULL);
buff_minsym = lookup_minimal_symbol ("__buffer", NULL, NULL);
CORE_ADDR
hppa_fix_call_dummy (char *dummy, CORE_ADDR pc, CORE_ADDR fun, int nargs,
- value_ptr *args, struct type *type, int gcc_p)
+ struct value **args, struct type *type, int gcc_p)
{
CORE_ADDR dyncall_addr;
struct minimal_symbol *msymbol;
such that it points to the PC value written immediately above
(ie the call dummy). */
resume (1, 0);
- target_wait (inferior_pid, &w);
+ target_wait (inferior_ptid, &w);
resume (1, 0);
- target_wait (inferior_pid, &w);
+ target_wait (inferior_ptid, &w);
/* Restore the two instructions at the old PC locations. */
*((int *) buf) = inst1;
stub rather than the export stub or real function for lazy binding
to work correctly
- /* If we are using the gcc PLT call routine, then we need to
+ If we are using the gcc PLT call routine, then we need to
get the import stub for the target function. */
if (using_gcc_plt_call && som_solib_get_got_by_pc (fun))
{
if (flags & 2)
return pc;
#ifndef GDB_TARGET_IS_PA_ELF
- else if (som_solib_get_got_by_pc (target_read_pc (inferior_pid)))
+ else if (som_solib_get_got_by_pc (target_read_pc (inferior_ptid)))
return pc;
#endif
else
bits. */
CORE_ADDR
-target_read_pc (int pid)
+target_read_pc (ptid_t ptid)
{
- int flags = read_register_pid (FLAGS_REGNUM, pid);
+ int flags = read_register_pid (FLAGS_REGNUM, ptid);
/* The following test does not belong here. It is OS-specific, and belongs
in native code. */
/* Test SS_INSYSCALL */
if (flags & 2)
- return read_register_pid (31, pid) & ~0x3;
+ return read_register_pid (31, ptid) & ~0x3;
- return read_register_pid (PC_REGNUM, pid) & ~0x3;
+ return read_register_pid (PC_REGNUM, ptid) & ~0x3;
}
/* Write out the PC. If currently in a syscall, then also write the new
PC value into %r31. */
void
-target_write_pc (CORE_ADDR v, int pid)
+target_write_pc (CORE_ADDR v, ptid_t ptid)
{
- int flags = read_register_pid (FLAGS_REGNUM, pid);
+ int flags = read_register_pid (FLAGS_REGNUM, ptid);
/* The following test does not belong here. It is OS-specific, and belongs
in native code. */
privilege bits set correctly. */
/* Test SS_INSYSCALL */
if (flags & 2)
- write_register_pid (31, v | 0x3, pid);
+ write_register_pid (31, v | 0x3, ptid);
- write_register_pid (PC_REGNUM, v, pid);
- write_register_pid (NPC_REGNUM, v + 4, pid);
+ write_register_pid (PC_REGNUM, v, ptid);
+ write_register_pid (NPC_REGNUM, v + 4, ptid);
}
/* return the alignment of a type in bytes. Structures have the maximum
/* Make a copy of gdb's save area (may cause actual
reads from the target). */
for (i = 0; i < NUM_REGS; i++)
- read_relative_register_raw_bytes (i, raw_regs + REGISTER_BYTE (i));
+ frame_register_read (deprecated_selected_frame, i, raw_regs + REGISTER_BYTE (i));
if (regnum == -1)
pa_print_registers (raw_regs, regnum, fpregs);
if (!is_pa_2)
{
- printf_unfiltered ("%s %x\n", REGISTER_NAME (regnum), reg_val[1]);
+ printf_unfiltered ("%s %lx\n", REGISTER_NAME (regnum), reg_val[1]);
}
else
{
/* Fancy % formats to prevent leading zeros. */
if (reg_val[0] == 0)
- printf_unfiltered ("%s %x\n", REGISTER_NAME (regnum), reg_val[1]);
+ printf_unfiltered ("%s %lx\n", REGISTER_NAME (regnum), reg_val[1]);
else
- printf_unfiltered ("%s %x%8.8x\n", REGISTER_NAME (regnum),
+ printf_unfiltered ("%s %lx%8.8lx\n", REGISTER_NAME (regnum),
reg_val[0], reg_val[1]);
}
}
/* Make a copy of gdb's save area (may cause actual
reads from the target). */
for (i = 0; i < NUM_REGS; i++)
- read_relative_register_raw_bytes (i, raw_regs + REGISTER_BYTE (i));
+ frame_register_read (deprecated_selected_frame, i, raw_regs + REGISTER_BYTE (i));
if (regnum == -1)
pa_strcat_registers (raw_regs, regnum, fpregs, stream);
if (!is_pa_2)
{
- fprintf_unfiltered (stream, "%s %x", REGISTER_NAME (regnum), reg_val[1]);
+ fprintf_unfiltered (stream, "%s %lx", REGISTER_NAME (regnum), reg_val[1]);
}
else
{
/* Fancy % formats to prevent leading zeros. */
if (reg_val[0] == 0)
- fprintf_unfiltered (stream, "%s %x", REGISTER_NAME (regnum),
+ fprintf_unfiltered (stream, "%s %lx", REGISTER_NAME (regnum),
reg_val[1]);
else
- fprintf_unfiltered (stream, "%s %x%8.8x", REGISTER_NAME (regnum),
+ fprintf_unfiltered (stream, "%s %lx%8.8lx", REGISTER_NAME (regnum),
reg_val[0], reg_val[1]);
}
}
for (i = start; i < 2; i++)
{
errno = 0;
- raw_val[i] = call_ptrace (PT_RUREGS, inferior_pid,
+ raw_val[i] = call_ptrace (PT_RUREGS, PIDGET (inferior_ptid),
(PTRACE_ARG3_TYPE) regaddr, 0);
if (errno != 0)
{
/* Being big-endian, on this machine the low bits
(the ones we want to look at) are in the second longword. */
long_val = extract_signed_integer (&raw_val[1], 4);
- printf_filtered ("%10.10s: %8x ",
+ printf_filtered ("%10.10s: %8lx ",
REGISTER_NAME (regnum), long_val);
}
else
{
/* raw_val = extract_signed_integer(&raw_val, 8); */
if (raw_val[0] == 0)
- printf_filtered ("%10.10s: %8x ",
+ printf_filtered ("%10.10s: %8lx ",
REGISTER_NAME (regnum), raw_val[1]);
else
- printf_filtered ("%10.10s: %8x%8.8x ",
+ printf_filtered ("%10.10s: %8lx%8.8lx ",
REGISTER_NAME (regnum),
raw_val[0], raw_val[1]);
}
/* Being big-endian, on this machine the low bits
(the ones we want to look at) are in the second longword. */
long_val = extract_signed_integer (&raw_val[1], 4);
- fprintf_filtered (stream, "%8.8s: %8x ", REGISTER_NAME (i + (j * 18)), long_val);
+ fprintf_filtered (stream, "%8.8s: %8lx ",
+ REGISTER_NAME (i + (j * 18)), long_val);
}
else
{
/* raw_val = extract_signed_integer(&raw_val, 8); */
if (raw_val[0] == 0)
- fprintf_filtered (stream, "%8.8s: %8x ", REGISTER_NAME (i + (j * 18)),
- raw_val[1]);
+ fprintf_filtered (stream, "%8.8s: %8lx ",
+ REGISTER_NAME (i + (j * 18)), raw_val[1]);
else
- fprintf_filtered (stream, "%8.8s: %8x%8.8x ", REGISTER_NAME (i + (j * 18)),
- raw_val[0], raw_val[1]);
+ fprintf_filtered (stream, "%8.8s: %8lx%8.8lx ",
+ REGISTER_NAME (i + (j * 18)), raw_val[0],
+ raw_val[1]);
}
}
fprintf_unfiltered (stream, "\n");
char virtual_buffer[MAX_REGISTER_VIRTUAL_SIZE];
/* Get 32bits of data. */
- read_relative_register_raw_bytes (i, raw_buffer);
+ frame_register_read (deprecated_selected_frame, i, raw_buffer);
/* Put it in the buffer. No conversions are ever necessary. */
memcpy (virtual_buffer, raw_buffer, REGISTER_RAW_SIZE (i));
if ((i % 2) == 0)
{
/* Get the data in raw format for the 2nd half. */
- read_relative_register_raw_bytes (i + 1, raw_buffer);
+ frame_register_read (deprecated_selected_frame, i + 1, raw_buffer);
/* Copy it into the appropriate part of the virtual buffer. */
memcpy (virtual_buffer + REGISTER_RAW_SIZE (i), raw_buffer,
print_spaces_filtered (8 - strlen (REGISTER_NAME (i)), stream);
/* Get 32bits of data. */
- read_relative_register_raw_bytes (i, raw_buffer);
+ frame_register_read (deprecated_selected_frame, i, raw_buffer);
/* Put it in the buffer. No conversions are ever necessary. */
memcpy (virtual_buffer, raw_buffer, REGISTER_RAW_SIZE (i));
char raw_buf[MAX_REGISTER_RAW_SIZE];
/* Get the data in raw format for the 2nd half. */
- read_relative_register_raw_bytes (i + 1, raw_buf);
+ frame_register_read (deprecated_selected_frame, i + 1, raw_buf);
/* Copy it into the appropriate part of the virtual buffer. */
memcpy (virtual_buffer + REGISTER_RAW_SIZE (i), raw_buf, REGISTER_RAW_SIZE (i));
stubsym = lookup_minimal_symbol_by_pc (loc);
if (stubsym == NULL)
{
- warning ("Unable to find symbol for 0x%x", loc);
+ warning ("Unable to find symbol for 0x%lx", loc);
return orig_pc == pc ? 0 : pc & ~0x3;
}
#ifdef FRAME_FIND_SAVED_REGS_IN_SIGTRAMP
/* Handle signal handler callers. */
- if (frame_info->signal_handler_caller)
+ if ((get_frame_type (frame_info) == SIGTRAMP_FRAME))
{
FRAME_FIND_SAVED_REGS_IN_SIGTRAMP (frame_info, frame_saved_regs);
return;
}
}
- /* Quit if we hit any kind of branch the previous iteration.
+ /* Quit if we hit any kind of branch the previous iteration. */
if (final_iteration)
break;
}
anaddr = SYMBOL_VALUE_ADDRESS (msymbol);
- store_unsigned_integer (buf, 4, inferior_pid); /* FIXME 32x64? */
+ store_unsigned_integer (buf, 4, PIDGET (inferior_ptid)); /* FIXME 32x64? */
if (target_write_memory (anaddr, buf, 4)) /* FIXME 32x64? */
{
warning ("Unable to write __d_pid");
if (!eh_notify_callback_addr)
{
/* We can get here either if there is no plabel in the export list
- for the main image, or if something strange happened (??) */
+ for the main image, or if something strange happened (?) */
warning ("Couldn't find a plabel (indirect function label) for the exception callback.");
warning ("GDB will not be able to intercept exception events.");
return 0;
if (enable)
{
/* Ensure that __d_pid is set up correctly -- end.c code checks this. :-( */
- if (inferior_pid > 0)
+ if (PIDGET (inferior_ptid) > 0)
{
if (setup_d_pid_in_inferior ())
return (struct symtab_and_line *) -1;
{
break_callback_sal = (struct symtab_and_line *) xmalloc (sizeof (struct symtab_and_line));
}
- INIT_SAL (break_callback_sal);
+ init_sal (break_callback_sal);
break_callback_sal->symtab = NULL;
break_callback_sal->pc = eh_break_addr;
break_callback_sal->line = 0;
if (level != 0)
return (struct exception_event_record *) NULL;
- select_frame (fi, -1);
+ select_frame (fi);
/* Read in the arguments */
/* __d_eh_notify_callback() is called with 3 arguments:
if (level != 0)
return (struct exception_event_record *) NULL;
- select_frame (fi, -1);
+ select_frame (fi);
throw_addr = fi->pc;
/* Go back to original (top) frame */
- select_frame (curr_frame, -1);
+ select_frame (curr_frame);
current_ex_event.kind = (enum exception_event_kind) event_kind;
current_ex_event.throw_sal = find_pc_line (throw_addr, 1);
return;
}
- printf_unfiltered ("unwind_table_entry (0x%x):\n", u);
+ printf_unfiltered ("unwind_table_entry (0x%s):\n",
+ paddr_nz (host_pointer_to_address (u)));
printf_unfiltered ("\tregion_start = ");
print_address (u->region_start, gdb_stdout);
printf_unfiltered ("\n\tregion_end = ");
print_address (u->region_end, gdb_stdout);
-#ifdef __STDC__
#define pif(FLD) if (u->FLD) printf_unfiltered (" "#FLD);
-#else
-#define pif(FLD) if (u->FLD) printf_unfiltered (" FLD");
-#endif
printf_unfiltered ("\n\tflags =");
pif (Cannot_unwind);
putchar_unfiltered ('\n');
-#ifdef __STDC__
#define pin(FLD) printf_unfiltered ("\t"#FLD" = 0x%x\n", u->FLD);
-#else
-#define pin(FLD) printf_unfiltered ("\tFLD = 0x%x\n", u->FLD);
-#endif
pin (Region_description);
pin (Entry_FR);
For these reasons, we have to violate information hiding and
call "breakpoint_here_p". If core gdb thinks there is a bpt
here, that's what counts, as core gdb is the one which is
- putting the BPT instruction in and taking it out. */
+ putting the BPT instruction in and taking it out.
+
+ Note that this implementation is potentially redundant now that
+ default_prepare_to_proceed() has been added.
+
+ FIXME This may not support switching threads after Ctrl-C
+ correctly. The default implementation does support this. */
int
hppa_prepare_to_proceed (void)
{
pid_t old_thread;
pid_t current_thread;
- old_thread = hppa_switched_threads (inferior_pid);
+ old_thread = hppa_switched_threads (PIDGET (inferior_ptid));
if (old_thread != 0)
{
/* Switched over from "old_thread". Try to do
/* Yuk, shouldn't use global to specify current
thread. But that's how gdb does it. */
- current_thread = inferior_pid;
- inferior_pid = old_thread;
+ current_thread = PIDGET (inferior_ptid);
+ inferior_ptid = pid_to_ptid (old_thread);
new_pc = read_pc ();
if (new_pc != old_pc /* If at same pc, no need */
registers_changed ();
#if 0
printf ("---> PREPARE_TO_PROCEED (was %d, now %d)!\n",
- current_thread, inferior_pid);
+ current_thread, PIDGET (inferior_ptid));
#endif
return 1;
}
/* Otherwise switch back to the user-chosen thread. */
- inferior_pid = current_thread;
+ inferior_ptid = pid_to_ptid (current_thread);
new_pc = read_pc (); /* Re-prime register cache */
}
/* We can leave the tail's space the same, since there's no jump. */
}
+/* Copy the function value from VALBUF into the proper location
+ for a function return.
+
+ Called only in the context of the "return" command. */
+
+void
+hppa_store_return_value (struct type *type, char *valbuf)
+{
+ /* For software floating point, the return value goes into the
+ integer registers. But we do not have any flag to key this on,
+ so we always store the value into the integer registers.
+
+ If its a float value, then we also store it into the floating
+ point registers. */
+ deprecated_write_register_bytes (REGISTER_BYTE (28)
+ + (TYPE_LENGTH (type) > 4
+ ? (8 - TYPE_LENGTH (type))
+ : (4 - TYPE_LENGTH (type))),
+ valbuf, TYPE_LENGTH (type));
+ if (! SOFT_FLOAT && TYPE_CODE (type) == TYPE_CODE_FLT)
+ deprecated_write_register_bytes (REGISTER_BYTE (FP4_REGNUM),
+ valbuf, TYPE_LENGTH (type));
+}
+
+/* Copy the function's return value into VALBUF.
+
+ This function is called only in the context of "target function calls",
+ ie. when the debugger forces a function to be called in the child, and
+ when the debugger forces a fucntion to return prematurely via the
+ "return" command. */
+
+void
+hppa_extract_return_value (struct type *type, char *regbuf, char *valbuf)
+{
+ if (! SOFT_FLOAT && TYPE_CODE (type) == TYPE_CODE_FLT)
+ memcpy (valbuf,
+ (char *)regbuf + REGISTER_BYTE (FP4_REGNUM),
+ TYPE_LENGTH (type));
+ else
+ memcpy (valbuf,
+ ((char *)regbuf
+ + REGISTER_BYTE (28)
+ + (TYPE_LENGTH (type) > 4
+ ? (8 - TYPE_LENGTH (type))
+ : (4 - TYPE_LENGTH (type)))),
+ TYPE_LENGTH (type));
+}
+
+int
+hppa_reg_struct_has_addr (int gcc_p, struct type *type)
+{
+ /* On the PA, any pass-by-value structure > 8 bytes is actually passed
+ via a pointer regardless of its type or the compiler used. */
+ return (TYPE_LENGTH (type) > 8);
+}
+
+int
+hppa_inner_than (CORE_ADDR lhs, CORE_ADDR rhs)
+{
+ /* Stack grows upward */
+ return (lhs > rhs);
+}
+
+CORE_ADDR
+hppa_stack_align (CORE_ADDR sp)
+{
+ /* elz: adjust the quantity to the next highest value which is
+ 64-bit aligned. This is used in valops.c, when the sp is adjusted.
+ On hppa the sp must always be kept 64-bit aligned */
+ return ((sp % 8) ? (sp + 7) & -8 : sp);
+}
+
+int
+hppa_pc_requires_run_before_use (CORE_ADDR pc)
+{
+ /* Sometimes we may pluck out a minimal symbol that has a negative address.
+
+ An example of this occurs when an a.out is linked against a foo.sl.
+ The foo.sl defines a global bar(), and the a.out declares a signature
+ for bar(). However, the a.out doesn't directly call bar(), but passes
+ its address in another call.
+
+ If you have this scenario and attempt to "break bar" before running,
+ gdb will find a minimal symbol for bar() in the a.out. But that
+ symbol's address will be negative. What this appears to denote is
+ an index backwards from the base of the procedure linkage table (PLT)
+ into the data linkage table (DLT), the end of which is contiguous
+ with the start of the PLT. This is clearly not a valid address for
+ us to set a breakpoint on.
+
+ Note that one must be careful in how one checks for a negative address.
+ 0xc0000000 is a legitimate address of something in a shared text
+ segment, for example. Since I don't know what the possible range
+ is of these "really, truly negative" addresses that come from the
+ minimal symbols, I'm resorting to the gross hack of checking the
+ top byte of the address for all 1's. Sigh. */
+
+ return (!target_has_stack && (pc & 0xFF000000));
+}
+
+int
+hppa_instruction_nullified (void)
+{
+ /* brobecker 2002/11/07: Couldn't we use a ULONGEST here? It would
+ avoid the type cast. I'm leaving it as is for now as I'm doing
+ semi-mechanical multiarching-related changes. */
+ const int ipsw = (int) read_register (IPSW_REGNUM);
+ const int flags = (int) read_register (FLAGS_REGNUM);
+
+ return ((ipsw & 0x00200000) && !(flags & 0x2));
+}
+
+/* Index within the register vector of the first byte of the space i
+ used for register REG_NR. */
+
+int
+hppa_register_byte (int reg_nr)
+{
+ return reg_nr * 4;
+}
+
+/* Return the GDB type object for the "standard" data type of data
+ in register N. */
+
+struct type *
+hppa_register_virtual_type (int reg_nr)
+{
+ if (reg_nr < FP4_REGNUM)
+ return builtin_type_int;
+ else
+ return builtin_type_float;
+}
+
+/* Store the address of the place in which to copy the structure the
+ subroutine will return. This is called from call_function. */
+
+void
+hppa_store_struct_return (CORE_ADDR addr, CORE_ADDR sp)
+{
+ write_register (28, addr);
+}
+
+/* Return True if REGNUM is not a register available to the user
+ through ptrace(). */
+
+int
+hppa_cannot_store_register (int regnum)
+{
+ return (regnum == 0
+ || regnum == PCSQ_HEAD_REGNUM
+ || (regnum >= PCSQ_TAIL_REGNUM && regnum < IPSW_REGNUM)
+ || (regnum > IPSW_REGNUM && regnum < FP4_REGNUM));
+
+}
+
+CORE_ADDR
+hppa_frame_args_address (struct frame_info *fi)
+{
+ return fi->frame;
+}
+
+CORE_ADDR
+hppa_frame_locals_address (struct frame_info *fi)
+{
+ return fi->frame;
+}
+
+CORE_ADDR
+hppa_smash_text_address (CORE_ADDR addr)
+{
+ /* The low two bits of the PC on the PA contain the privilege level.
+ Some genius implementing a (non-GCC) compiler apparently decided
+ this means that "addresses" in a text section therefore include a
+ privilege level, and thus symbol tables should contain these bits.
+ This seems like a bonehead thing to do--anyway, it seems to work
+ for our purposes to just ignore those bits. */
+
+ return (addr &= ~0x3);
+}
+
+int
+hppa_coerce_float_to_double (struct type *formal, struct type *actual)
+{
+ /* FIXME: For the pa, it appears that the debug info marks the
+ parameters as floats regardless of whether the function is
+ prototyped, but the actual values are passed as doubles for the
+ non-prototyped case and floats for the prototyped case. Thus we
+ choose to make the non-prototyped case work for C and break the
+ prototyped case, since the non-prototyped case is probably much
+ more common. */
+ return (current_language -> la_language == language_c);
+}
+
+static struct gdbarch *
+hppa_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
+{
+ struct gdbarch *gdbarch;
+ enum gdb_osabi osabi = GDB_OSABI_UNKNOWN;
+
+ /* Try to determine the ABI of the object we are loading. */
+
+ if (info.abfd != NULL)
+ {
+ osabi = gdbarch_lookup_osabi (info.abfd);
+ if (osabi == GDB_OSABI_UNKNOWN)
+ {
+ /* If it's a SOM file, assume it's HP/UX SOM. */
+ if (bfd_get_flavour (info.abfd) == bfd_target_som_flavour)
+ osabi = GDB_OSABI_HPUX_SOM;
+ }
+ }
+
+ /* find a candidate among the list of pre-declared architectures. */
+ arches = gdbarch_list_lookup_by_info (arches, &info);
+ if (arches != NULL)
+ return (arches->gdbarch);
+
+ /* If none found, then allocate and initialize one. */
+ gdbarch = gdbarch_alloc (&info, NULL);
+
+ /* Hook in ABI-specific overrides, if they have been registered. */
+ gdbarch_init_osabi (info, gdbarch, osabi);
+
+ return gdbarch;
+}
+
+static void
+hppa_dump_tdep (struct gdbarch *current_gdbarch, struct ui_file *file)
+{
+ /* Nothing to print for the moment. */
+}
+
void
_initialize_hppa_tdep (void)
{
+ struct cmd_list_element *c;
+ void break_at_finish_command (char *arg, int from_tty);
+ void tbreak_at_finish_command (char *arg, int from_tty);
+ void break_at_finish_at_depth_command (char *arg, int from_tty);
+
+ gdbarch_register (bfd_arch_hppa, hppa_gdbarch_init, hppa_dump_tdep);
tm_print_insn = print_insn_hppa;
add_cmd ("unwind", class_maintenance, unwind_command,
"Print unwind table entry at given address.",
&maintenanceprintlist);
+
+ deprecate_cmd (add_com ("xbreak", class_breakpoint,
+ break_at_finish_command,
+ concat ("Set breakpoint at procedure exit. \n\
+Argument may be function name, or \"*\" and an address.\n\
+If function is specified, break at end of code for that function.\n\
+If an address is specified, break at the end of the function that contains \n\
+that exact address.\n",
+ "With no arg, uses current execution address of selected stack frame.\n\
+This is useful for breaking on return to a stack frame.\n\
+\n\
+Multiple breakpoints at one place are permitted, and useful if conditional.\n\
+\n\
+Do \"help breakpoints\" for info on other commands dealing with breakpoints.", NULL)), NULL);
+ deprecate_cmd (add_com_alias ("xb", "xbreak", class_breakpoint, 1), NULL);
+ deprecate_cmd (add_com_alias ("xbr", "xbreak", class_breakpoint, 1), NULL);
+ deprecate_cmd (add_com_alias ("xbre", "xbreak", class_breakpoint, 1), NULL);
+ deprecate_cmd (add_com_alias ("xbrea", "xbreak", class_breakpoint, 1), NULL);
+
+ deprecate_cmd (c = add_com ("txbreak", class_breakpoint,
+ tbreak_at_finish_command,
+"Set temporary breakpoint at procedure exit. Either there should\n\
+be no argument or the argument must be a depth.\n"), NULL);
+ set_cmd_completer (c, location_completer);
+
+ if (xdb_commands)
+ deprecate_cmd (add_com ("bx", class_breakpoint,
+ break_at_finish_at_depth_command,
+"Set breakpoint at procedure exit. Either there should\n\
+be no argument or the argument must be a depth.\n"), NULL);
}
+