X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fhppa-tdep.c;h=db497efdeefa448215ef37e58ecffd6f0d615a7c;hb=54c7009d04fc3da51b50cfbefe5f5894db2cad32;hp=c27d9641431c1284e2f583bf6406290be7ac249c;hpb=5ba2abebe76a125d8e4e3181db399e489bd63eeb;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/hppa-tdep.c b/gdb/hppa-tdep.c index c27d964143..db497efdee 100644 --- a/gdb/hppa-tdep.c +++ b/gdb/hppa-tdep.c @@ -1,6 +1,7 @@ /* Target-dependent code for the HP PA architecture, for GDB. - Copyright 1986, 1987, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, - 1998, 1999, 2000, 2001 Free Software Foundation, Inc. + + Copyright 1986, 1987, 1989, 1990, 1991, 1992, 1993, 1994, 1995, + 1996, 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. Contributed by the Center for Software Science at the University of Utah (pa-gdb-bugs@cs.utah.edu). @@ -29,6 +30,8 @@ #include "value.h" #include "regcache.h" #include "completer.h" +#include "language.h" +#include "osabi.h" /* For argument passing to the inferior */ #include "symtab.h" @@ -60,6 +63,9 @@ #include "symfile.h" #include "objfiles.h" +/* Some local constants. */ +static const int hppa_num_regs = 128; + /* To support detection of the pseudo-initial frame that threads have. */ #define THREAD_INITIAL_FRAME_SYMBOL "__pthread_exit" @@ -129,6 +135,46 @@ static void pa_register_look_aside (char *, int, long *); 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); +CORE_ADDR hppa_skip_prologue (CORE_ADDR pc); +CORE_ADDR hppa_skip_trampoline_code (CORE_ADDR pc); +int hppa_in_solib_call_trampoline (CORE_ADDR pc, char *name); +int hppa_in_solib_return_trampoline (CORE_ADDR pc, char *name); +CORE_ADDR hppa_saved_pc_after_call (struct frame_info *frame); +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_raw_size (int reg_nr); +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); +void hppa_extract_return_value (struct type *type, char *regbuf, char *valbuf); +int hppa_use_struct_convention (int gcc_p, struct type *type); +void hppa_store_return_value (struct type *type, char *valbuf); +CORE_ADDR hppa_extract_struct_value_address (char *regbuf); +int hppa_cannot_store_register (int regnum); +void hppa_init_extra_frame_info (int fromleaf, struct frame_info *frame); +CORE_ADDR hppa_frame_chain (struct frame_info *frame); +int hppa_frame_chain_valid (CORE_ADDR chain, struct frame_info *thisframe); +int hppa_frameless_function_invocation (struct frame_info *frame); +CORE_ADDR hppa_frame_saved_pc (struct frame_info *frame); +CORE_ADDR hppa_frame_args_address (struct frame_info *fi); +CORE_ADDR hppa_frame_locals_address (struct frame_info *fi); +int hppa_frame_num_args (struct frame_info *frame); +void hppa_push_dummy_frame (struct inferior_status *inf_status); +void hppa_pop_frame (void); +CORE_ADDR hppa_fix_call_dummy (char *dummy, CORE_ADDR pc, CORE_ADDR fun, + int nargs, struct value **args, + struct type *type, int gcc_p); +CORE_ADDR hppa_push_arguments (int nargs, struct value **args, CORE_ADDR sp, + int struct_return, CORE_ADDR struct_addr); +CORE_ADDR hppa_smash_text_address (CORE_ADDR addr); +CORE_ADDR hppa_target_read_pc (ptid_t ptid); +void hppa_target_write_pc (CORE_ADDR v, ptid_t ptid); +CORE_ADDR hppa_target_read_fp (void); typedef struct { @@ -138,7 +184,7 @@ typedef struct } args_for_find_stub; -static int cover_find_stub_with_shl_get (PTR); +static int cover_find_stub_with_shl_get (void *); static int is_pa_2 = 0; /* False */ @@ -148,10 +194,8 @@ extern int hp_som_som_object_present; /* In breakpoint.c */ extern int exception_catchpoints_are_fragile; -/* This is defined in valops.c. */ -extern struct value *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) { @@ -299,7 +343,7 @@ static CORE_ADDR low_text_segment_address; 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; @@ -329,7 +373,7 @@ internalize_unwinds (struct objfile *objfile, struct unwind_table_entry *table, if (TARGET_PTR_BIT == 64 && text_offset == 0) { bfd_map_over_sections (objfile->obfd, - record_text_segment_lowaddr, (PTR) NULL); + record_text_segment_lowaddr, NULL); /* ?!? Mask off some low bits. Should this instead subtract out the lowest section's filepos or something like that? @@ -530,7 +574,7 @@ read_unwind_info (struct objfile *objfile) obj_private->so_info = NULL; obj_private->dp = 0; - objfile->obj_private = (PTR) obj_private; + objfile->obj_private = obj_private; } obj_private = (obj_private_data_t *) objfile->obj_private; obj_private->unwind_info = ui; @@ -632,7 +676,8 @@ pc_in_interrupt_handler (CORE_ADDR pc) 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 @@ -747,8 +792,10 @@ find_proc_framesize (CORE_ADDR pc) /* 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; @@ -797,7 +844,7 @@ rp_saved (CORE_ADDR pc) } int -frameless_function_invocation (struct frame_info *frame) +hppa_frameless_function_invocation (struct frame_info *frame) { struct unwind_table_entry *u; @@ -809,8 +856,13 @@ frameless_function_invocation (struct frame_info *frame) 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) +hppa_saved_pc_after_call (struct frame_info *frame) { int ret_regnum; CORE_ADDR pc; @@ -868,7 +920,7 @@ hppa_frame_saved_pc (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); @@ -876,7 +928,7 @@ hppa_frame_saved_pc (struct frame_info *frame) } #endif - if (frameless_function_invocation (frame)) + if (hppa_frameless_function_invocation (frame)) { int ret_regnum; @@ -887,12 +939,12 @@ hppa_frame_saved_pc (struct frame_info *frame) 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) { @@ -927,12 +979,12 @@ hppa_frame_saved_pc (struct frame_info *frame) 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) { @@ -1008,7 +1060,7 @@ hppa_frame_saved_pc (struct frame_info *frame) in a system call. */ void -init_extra_frame_info (int fromleaf, struct frame_info *frame) +hppa_init_extra_frame_info (int fromleaf, struct frame_info *frame) { int flags; int framesize; @@ -1056,16 +1108,17 @@ init_extra_frame_info (int fromleaf, struct frame_info *frame) frame->frame = read_register (SP_REGNUM) - framesize; } -/* 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 a frame pointer calls code without a frame pointer. */ CORE_ADDR -frame_chain (struct frame_info *frame) +hppa_frame_chain (struct frame_info *frame) { int my_framesize, caller_framesize; struct unwind_table_entry *u; @@ -1121,7 +1174,7 @@ frame_chain (struct frame_info *frame) 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); } @@ -1192,7 +1245,7 @@ frame_chain (struct frame_info *frame) } if (u->Save_SP - || tmp_frame->signal_handler_caller + || (get_frame_type (tmp_frame) == SIGTRAMP_FRAME) || pc_in_interrupt_handler (tmp_frame->pc)) break; @@ -1203,7 +1256,7 @@ frame_chain (struct frame_info *frame) /* 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. */ @@ -1217,7 +1270,7 @@ frame_chain (struct frame_info *frame) /* 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); @@ -1252,7 +1305,7 @@ frame_chain (struct frame_info *frame) 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 @@ -1287,7 +1340,7 @@ frame_chain (struct frame_info *frame) 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 @@ -1328,9 +1381,6 @@ hppa_frame_chain_valid (CORE_ADDR chain, struct frame_info *thisframe) struct unwind_table_entry *u, *next_u = NULL; struct frame_info *next; - if (!chain) - return 0; - u = find_unwind_entry (thisframe->pc); if (u == NULL) @@ -1365,7 +1415,7 @@ hppa_frame_chain_valid (CORE_ADDR chain, struct frame_info *thisframe) 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; @@ -1382,7 +1432,7 @@ hppa_frame_chain_valid (CORE_ADDR chain, struct frame_info *thisframe) to be aligned to a 64-byte boundary. */ void -push_dummy_frame (struct inferior_status *inf_status) +hppa_push_dummy_frame (struct inferior_status *inf_status) { CORE_ADDR sp, pc, pcspace; register int regnum; @@ -1398,7 +1448,7 @@ push_dummy_frame (struct inferior_status *inf_status) 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_ptid); + pc = hppa_target_read_pc (inferior_ptid); int_buffer = read_register (FLAGS_REGNUM); if (int_buffer & 0x2) { @@ -1446,7 +1496,8 @@ push_dummy_frame (struct inferior_status *inf_status) 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)); @@ -1508,8 +1559,8 @@ hppa_pop_frame (void) 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 */ @@ -1525,7 +1576,8 @@ hppa_pop_frame (void) 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]) @@ -1577,7 +1629,7 @@ hppa_pop_frame (void) 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. */ @@ -1980,7 +2032,7 @@ find_stub_with_shl_get (struct minimal_symbol *function, CORE_ADDR handle) /* Cover routine for find_stub_with_shl_get to pass to catch_errors */ static int -cover_find_stub_with_shl_get (PTR args_untyped) +cover_find_stub_with_shl_get (void *args_untyped) { args_for_find_stub *args = args_untyped; args->return_val = find_stub_with_shl_get (args->msym, args->solib_handle); @@ -2373,7 +2425,7 @@ hppa_fix_call_dummy (char *dummy, CORE_ADDR pc, CORE_ADDR fun, int nargs, if (flags & 2) return pc; #ifndef GDB_TARGET_IS_PA_ELF - else if (som_solib_get_got_by_pc (target_read_pc (inferior_ptid))) + else if (som_solib_get_got_by_pc (hppa_target_read_pc (inferior_ptid))) return pc; #endif else @@ -2381,14 +2433,12 @@ hppa_fix_call_dummy (char *dummy, CORE_ADDR pc, CORE_ADDR fun, int nargs, #endif } - - - /* If the pid is in a syscall, then the FP register is not readable. We'll return zero in that case, rather than attempting to read it and cause a warning. */ + CORE_ADDR -target_read_fp (int pid) +hppa_read_fp (int pid) { int flags = read_register (FLAGS_REGNUM); @@ -2402,12 +2452,17 @@ target_read_fp (int pid) return read_register (FP_REGNUM); } +CORE_ADDR +hppa_target_read_fp (void) +{ + return hppa_read_fp (PIDGET (inferior_ptid)); +} /* Get the PC from %r31 if currently in a syscall. Also mask out privilege bits. */ CORE_ADDR -target_read_pc (ptid_t ptid) +hppa_target_read_pc (ptid_t ptid) { int flags = read_register_pid (FLAGS_REGNUM, ptid); @@ -2424,7 +2479,7 @@ target_read_pc (ptid_t ptid) PC value into %r31. */ void -target_write_pc (CORE_ADDR v, ptid_t ptid) +hppa_target_write_pc (CORE_ADDR v, ptid_t ptid) { int flags = read_register_pid (FLAGS_REGNUM, ptid); @@ -2486,7 +2541,7 @@ pa_do_registers_info (int regnum, int fpregs) /* 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); @@ -2530,7 +2585,7 @@ pa_do_strcat_registers_info (int regnum, int fpregs, struct ui_file *stream, /* 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); @@ -2581,7 +2636,7 @@ pa_register_look_aside (char *raw_regs, int regnum, long *raw_val) int start; - char buf[MAX_REGISTER_RAW_SIZE]; + char *buf = alloca (max_register_size (current_gdbarch)); long long reg_val; if (!know_which) @@ -2778,11 +2833,11 @@ pa_strcat_registers (char *raw_regs, int regnum, int fpregs, static void pa_print_fp_reg (int i) { - char raw_buffer[MAX_REGISTER_RAW_SIZE]; - char virtual_buffer[MAX_REGISTER_VIRTUAL_SIZE]; + char *raw_buffer = alloca (max_register_size (current_gdbarch)); + char *virtual_buffer = alloca (max_register_size (current_gdbarch)); /* 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)); @@ -2800,7 +2855,7 @@ pa_print_fp_reg (int 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, @@ -2821,14 +2876,14 @@ pa_print_fp_reg (int i) static void pa_strcat_fp_reg (int i, struct ui_file *stream, enum precision_type precision) { - char raw_buffer[MAX_REGISTER_RAW_SIZE]; - char virtual_buffer[MAX_REGISTER_VIRTUAL_SIZE]; + char *raw_buffer = alloca (max_register_size (current_gdbarch)); + char *virtual_buffer = alloca (max_register_size (current_gdbarch)); fputs_filtered (REGISTER_NAME (i), stream); 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)); @@ -2836,10 +2891,10 @@ pa_strcat_fp_reg (int i, struct ui_file *stream, enum precision_type precision) if (precision == double_precision && (i % 2) == 0) { - char raw_buf[MAX_REGISTER_RAW_SIZE]; + char *raw_buf = alloca (max_register_size (current_gdbarch)); /* 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)); @@ -2862,7 +2917,7 @@ pa_strcat_fp_reg (int i, struct ui_file *stream, enum precision_type precision) just shared library trampolines (import, export). */ int -in_solib_call_trampoline (CORE_ADDR pc, char *name) +hppa_in_solib_call_trampoline (CORE_ADDR pc, char *name) { struct minimal_symbol *minsym; struct unwind_table_entry *u; @@ -3022,7 +3077,7 @@ in_solib_call_trampoline (CORE_ADDR pc, char *name) just shared library trampolines (import, export). */ int -in_solib_return_trampoline (CORE_ADDR pc, char *name) +hppa_in_solib_return_trampoline (CORE_ADDR pc, char *name) { struct unwind_table_entry *u; @@ -3095,7 +3150,7 @@ in_solib_return_trampoline (CORE_ADDR pc, char *name) used in dynamic executables. */ CORE_ADDR -skip_trampoline_code (CORE_ADDR pc, char *name) +hppa_skip_trampoline_code (CORE_ADDR pc) { long orig_pc = pc; long prev_inst, curr_inst, loc; @@ -3863,7 +3918,7 @@ hppa_frame_find_saved_regs (struct frame_info *frame_info, #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; @@ -4245,7 +4300,7 @@ initialize_hp_cxx_exception_support (void) args.return_val = 0; recurse++; - catch_errors (cover_find_stub_with_shl_get, (PTR) &args, message, + catch_errors (cover_find_stub_with_shl_get, &args, message, RETURN_MASK_ALL); eh_notify_callback_addr = args.return_val; recurse--; @@ -4422,7 +4477,7 @@ child_enable_exception_callback (enum exception_event_kind kind, int enable) { 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; @@ -4461,7 +4516,7 @@ child_get_current_exception_event (void) 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: @@ -4487,11 +4542,11 @@ child_get_current_exception_event (void) 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); @@ -4500,6 +4555,16 @@ child_get_current_exception_event (void) return ¤t_ex_event; } +/* Instead of this nasty cast, add a method pvoid() that prints out a + host VOID data type (remember %p isn't portable). */ + +static CORE_ADDR +hppa_pointer_to_address_hack (void *ptr) +{ + gdb_assert (sizeof (ptr) == TYPE_LENGTH (builtin_type_void_data_ptr)); + return POINTER_TO_ADDRESS (builtin_type_void_data_ptr, &ptr); +} + static void unwind_command (char *exp, int from_tty) { @@ -4522,7 +4587,7 @@ unwind_command (char *exp, int from_tty) } printf_unfiltered ("unwind_table_entry (0x%s):\n", - paddr_nz (host_pointer_to_address (u))); + paddr_nz (hppa_pointer_to_address_hack (u))); printf_unfiltered ("\tregion_start = "); print_address (u->region_start, gdb_stdout); @@ -4673,6 +4738,305 @@ hppa_skip_permanent_breakpoint (void) /* 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)); +} + +int +hppa_register_raw_size (int reg_nr) +{ + /* All registers have the same size. */ + return REGISTER_SIZE; +} + +/* 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); +} + +CORE_ADDR +hppa_extract_struct_value_address (char *regbuf) +{ + /* Extract from an array REGBUF containing the (raw) register state + the address in which a function should return its structure value, + as a CORE_ADDR (or an expression that can be used as one). */ + /* FIXME: brobecker 2002-12-26. + The current implementation is historical, but we should eventually + implement it in a more robust manner as it relies on the fact that + the address size is equal to the size of an int* _on the host_... + One possible implementation that crossed my mind is to use + extract_address. */ + return (*(int *)(regbuf + REGISTER_BYTE (28))); +} + +/* 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; +} + +int +hppa_frame_num_args (struct frame_info *frame) +{ + /* We can't tell how many args there are now that the C compiler delays + popping them. */ + return -1; +} + +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); +} + +static struct gdbarch * +hppa_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) +{ + struct gdbarch *gdbarch; + + /* Try to determine the ABI of the object we are loading. */ + if (info.abfd != NULL && info.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) + info.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); + + set_gdbarch_reg_struct_has_addr (gdbarch, hppa_reg_struct_has_addr); + set_gdbarch_function_start_offset (gdbarch, 0); + set_gdbarch_skip_prologue (gdbarch, hppa_skip_prologue); + set_gdbarch_skip_trampoline_code (gdbarch, hppa_skip_trampoline_code); + set_gdbarch_in_solib_call_trampoline (gdbarch, hppa_in_solib_call_trampoline); + set_gdbarch_in_solib_return_trampoline (gdbarch, + hppa_in_solib_return_trampoline); + set_gdbarch_saved_pc_after_call (gdbarch, hppa_saved_pc_after_call); + set_gdbarch_inner_than (gdbarch, hppa_inner_than); + set_gdbarch_stack_align (gdbarch, hppa_stack_align); + set_gdbarch_extra_stack_alignment_needed (gdbarch, 0); + set_gdbarch_decr_pc_after_break (gdbarch, 0); + set_gdbarch_register_size (gdbarch, 4); + set_gdbarch_num_regs (gdbarch, hppa_num_regs); + set_gdbarch_fp_regnum (gdbarch, 3); + set_gdbarch_sp_regnum (gdbarch, 30); + set_gdbarch_fp0_regnum (gdbarch, 64); + set_gdbarch_pc_regnum (gdbarch, PCOQ_HEAD_REGNUM); + set_gdbarch_npc_regnum (gdbarch, PCOQ_TAIL_REGNUM); + set_gdbarch_register_raw_size (gdbarch, hppa_register_raw_size); + set_gdbarch_register_bytes (gdbarch, hppa_num_regs * 4); + set_gdbarch_register_byte (gdbarch, hppa_register_byte); + set_gdbarch_register_virtual_size (gdbarch, hppa_register_raw_size); + set_gdbarch_max_register_raw_size (gdbarch, 4); + set_gdbarch_max_register_virtual_size (gdbarch, 8); + set_gdbarch_register_virtual_type (gdbarch, hppa_register_virtual_type); + set_gdbarch_store_struct_return (gdbarch, hppa_store_struct_return); + set_gdbarch_deprecated_extract_return_value (gdbarch, + hppa_extract_return_value); + set_gdbarch_use_struct_convention (gdbarch, hppa_use_struct_convention); + set_gdbarch_deprecated_store_return_value (gdbarch, hppa_store_return_value); + set_gdbarch_deprecated_extract_struct_value_address + (gdbarch, hppa_extract_struct_value_address); + set_gdbarch_cannot_store_register (gdbarch, hppa_cannot_store_register); + set_gdbarch_init_extra_frame_info (gdbarch, hppa_init_extra_frame_info); + set_gdbarch_frame_chain (gdbarch, hppa_frame_chain); + set_gdbarch_frame_chain_valid (gdbarch, hppa_frame_chain_valid); + set_gdbarch_frameless_function_invocation + (gdbarch, hppa_frameless_function_invocation); + set_gdbarch_frame_saved_pc (gdbarch, hppa_frame_saved_pc); + set_gdbarch_frame_args_address (gdbarch, hppa_frame_args_address); + set_gdbarch_frame_locals_address (gdbarch, hppa_frame_locals_address); + set_gdbarch_frame_num_args (gdbarch, hppa_frame_num_args); + set_gdbarch_frame_args_skip (gdbarch, 0); + /* set_gdbarch_push_dummy_frame (gdbarch, hppa_push_dummy_frame); */ + set_gdbarch_pop_frame (gdbarch, hppa_pop_frame); + set_gdbarch_call_dummy_length (gdbarch, INSTRUCTION_SIZE * 28); + set_gdbarch_call_dummy_start_offset (gdbarch, 0); + /* set_gdbarch_fix_call_dummy (gdbarch, hppa_fix_call_dummy); */ + set_gdbarch_push_arguments (gdbarch, hppa_push_arguments); + set_gdbarch_smash_text_address (gdbarch, hppa_smash_text_address); + set_gdbarch_believe_pcc_promotion (gdbarch, 1); + set_gdbarch_read_pc (gdbarch, hppa_target_read_pc); + set_gdbarch_write_pc (gdbarch, hppa_target_write_pc); + set_gdbarch_read_fp (gdbarch, hppa_target_read_fp); + + 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) { @@ -4681,6 +5045,7 @@ _initialize_hppa_tdep (void) 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, @@ -4718,52 +5083,3 @@ be no argument or the argument must be a depth.\n"), NULL); be no argument or the argument must be a depth.\n"), NULL); } -/* 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. */ - 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) - 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)); -}