From 78161e4820b9668db2fcf81c3446997b9140ac4a Mon Sep 17 00:00:00 2001 From: Andrew Cagney Date: Sun, 7 Mar 2004 18:06:14 +0000 Subject: [PATCH] 2004-03-07 Andrew Cagney * infcall.c (legacy_push_dummy_code): Delete #ifdef GDB_TARGET_IS_HPPA code. * config/pa/tm-hppa.h (DEPRECATED_FIX_CALL_DUMMY) (hppa_fix_call_dummy, DEPRECATED_CALL_DUMMY_HAS_COMPLETED) (DEPRECATED_DUMMY_WRITE_SP, CALL_DUMMY): Delete. * config/pa/tm-hppa64.h (CALL_DUMMY): Delete. * hppa-tdep.c (hppa_frame_chain, hppa_frame_chain_valid) (hppa_push_dummy_frame, hppa_pop_frame, hppa_push_arguments) (hppa_fix_call_dummy, hppa64_stack_align, hppa_frame_saved_pc) (hppa_init_extra_frame_info, hppa_saved_pc_after_call) (hppa64_call_dummy_breakpoint_offset, hppa_frame_init_saved_regs) (hppa_frameless_function_invocation, hppa64_store_return_value) (hppa_store_struct_return, hppa64_extract_return_value) (hppa64_use_struct_convention, hppa_frame_find_saved_regs) (hppa32_call_dummy_length, hppa64_call_dummy_length) (find_dummy_frame_regs, FUNC_LDIL_OFFSET, FUNC_LDO_OFFSET) (find_proc_framesize, deposit_21, restore_pc_queue) (find_return_regnum, pc_in_interrupt_handler, deposit_14) (rp_saved, pc_in_linker_stub): --- gdb/ChangeLog | 22 +- gdb/config/pa/tm-hppa.h | 97 -- gdb/config/pa/tm-hppa64.h | 46 - gdb/hppa-tdep.c | 2092 +------------------------------------ gdb/infcall.c | 5 - 5 files changed, 32 insertions(+), 2230 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 12bf8bd40c7..5545a1e1936 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,25 @@ 2004-03-07 Andrew Cagney + * infcall.c (legacy_push_dummy_code): Delete #ifdef + GDB_TARGET_IS_HPPA code. + * config/pa/tm-hppa.h (DEPRECATED_FIX_CALL_DUMMY) + (hppa_fix_call_dummy, DEPRECATED_CALL_DUMMY_HAS_COMPLETED) + (DEPRECATED_DUMMY_WRITE_SP, CALL_DUMMY): Delete. + * config/pa/tm-hppa64.h (CALL_DUMMY): Delete. + * hppa-tdep.c (hppa_frame_chain, hppa_frame_chain_valid) + (hppa_push_dummy_frame, hppa_pop_frame, hppa_push_arguments) + (hppa_fix_call_dummy, hppa64_stack_align, hppa_frame_saved_pc) + (hppa_init_extra_frame_info, hppa_saved_pc_after_call) + (hppa64_call_dummy_breakpoint_offset, hppa_frame_init_saved_regs) + (hppa_frameless_function_invocation, hppa64_store_return_value) + (hppa_store_struct_return, hppa64_extract_return_value) + (hppa64_use_struct_convention, hppa_frame_find_saved_regs) + (hppa32_call_dummy_length, hppa64_call_dummy_length) + (find_dummy_frame_regs, FUNC_LDIL_OFFSET, FUNC_LDO_OFFSET) + (find_proc_framesize, deposit_21, restore_pc_queue) + (find_return_regnum, pc_in_interrupt_handler, deposit_14) + (rp_saved, pc_in_linker_stub): + Unconditionally enable 64-bit frame and ABI code. * hppa-tdep.c (hppa_gdbarch_init): Do not set deprecated call_dummy_breakpoint_offset, call_dummy_length, stack_align, @@ -9,7 +29,7 @@ init_frame_pc, frame_init_saved_regs, init_extra_frame_info, frame_chain, frame_chain_valid, frameless_function_invocation, frame_saved_pc, and pop_frame. - + * hppa-tdep.c: Replace PC_REGNUM with PCOQ_HEAD_REGNUM. (hppa64_return_value, hppa64_push_dummy_call): Rewrite. (hppa_gdbarch_init): Do not set PC_REGNUM. diff --git a/gdb/config/pa/tm-hppa.h b/gdb/config/pa/tm-hppa.h index 9924ffa9678..c824bf5b6cf 100644 --- a/gdb/config/pa/tm-hppa.h +++ b/gdb/config/pa/tm-hppa.h @@ -26,9 +26,6 @@ #include "regcache.h" -/* Wonder if this is correct? Should be using push_dummy_call(). */ -#define DEPRECATED_DUMMY_WRITE_SP(SP) deprecated_write_sp (SP) - #define GDB_MULTI_ARCH 1 /* Hack, get around problem with including "arch-utils.h". */ @@ -107,102 +104,8 @@ extern int hppa_instruction_nullified (void); #define INSTRUCTION_SIZE 4 -/* This sequence of words is the instructions - - ; Call stack frame has already been built by gdb. Since we could be calling - ; a varargs function, and we do not have the benefit of a stub to put things in - ; the right place, we load the first 4 word of arguments into both the general - ; and fp registers. - call_dummy - ldw -36(sp), arg0 - ldw -40(sp), arg1 - ldw -44(sp), arg2 - ldw -48(sp), arg3 - ldo -36(sp), r1 - fldws 0(0, r1), fr4 - fldds -4(0, r1), fr5 - fldws -8(0, r1), fr6 - fldds -12(0, r1), fr7 - ldil 0, r22 ; FUNC_LDIL_OFFSET must point here - ldo 0(r22), r22 ; FUNC_LDO_OFFSET must point here - ldsid (0,r22), r4 - ldil 0, r1 ; SR4EXPORT_LDIL_OFFSET must point here - ldo 0(r1), r1 ; SR4EXPORT_LDO_OFFSET must point here - ldsid (0,r1), r20 - combt,=,n r4, r20, text_space ; If target is in data space, do a - ble 0(sr5, r22) ; "normal" procedure call - copy r31, r2 - break 4, 8 - mtsp r21, sr0 - ble,n 0(sr0, r22) - text_space ; Otherwise, go through _sr4export, - ble (sr4, r1) ; which will return back here. - stw r31,-24(r30) - break 4, 8 - mtsp r21, sr0 - ble,n 0(sr0, r22) - nop ; To avoid kernel bugs - nop ; and keep the dummy 8 byte aligned - - The dummy decides if the target is in text space or data space. If - it's in data space, there's no problem because the target can - return back to the dummy. However, if the target is in text space, - the dummy calls the secret, undocumented routine _sr4export, which - calls a function in text space and can return to any space. Instead - of including fake instructions to represent saved registers, we - know that the frame is associated with the call dummy and treat it - specially. - - The trailing NOPs are needed to avoid a bug in HPUX, BSD and OSF1 - kernels. If the memory at the location pointed to by the PC is - 0xffffffff then a ptrace step call will fail (even if the instruction - is nullified). - - The code to pop a dummy frame single steps three instructions - starting with the last mtsp. This includes the nullified "instruction" - following the ble (which is uninitialized junk). If the - "instruction" following the last BLE is 0xffffffff, then the ptrace - will fail and the dummy frame is not correctly popped. - - By placing a NOP in the delay slot of the BLE instruction we can be - sure that we never try to execute a 0xffffffff instruction and - avoid the kernel bug. The second NOP is needed to keep the call - dummy 8 byte aligned. */ - -#define CALL_DUMMY {0x4BDA3FB9, 0x4BD93FB1, 0x4BD83FA9, 0x4BD73FA1,\ - 0x37C13FB9, 0x24201004, 0x2C391005, 0x24311006,\ - 0x2C291007, 0x22C00000, 0x36D60000, 0x02C010A4,\ - 0x20200000, 0x34210000, 0x002010b4, 0x82842022,\ - 0xe6c06000, 0x081f0242, 0x00010004, 0x00151820,\ - 0xe6c00002, 0xe4202000, 0x6bdf3fd1, 0x00010004,\ - 0x00151820, 0xe6c00002, 0x08000240, 0x08000240} - #define REG_PARM_STACK_SPACE 16 -/* If we've reached a trap instruction within the call dummy, then - we'll consider that to mean that we've reached the call dummy's - end after its successful completion. */ -#define DEPRECATED_CALL_DUMMY_HAS_COMPLETED(pc, sp, frame_address) \ - (DEPRECATED_PC_IN_CALL_DUMMY((pc), (sp), (frame_address)) && \ - (read_memory_integer((pc), 4) == BREAKPOINT32)) - -/* Insert the specified number of args and function address into a - call sequence of the above form stored at DUMMYNAME. - - On the hppa we need to call the stack dummy through $$dyncall. - Therefore our version of DEPRECATED_FIX_CALL_DUMMY takes an extra - argument, real_pc, which is the location where gdb should start up - the inferior to do the function call. */ - -/* FIXME: brobecker 2002-12-26. This macro is going to cause us some - problems before we can go to multiarch partial as it has been - diverted on HPUX to return the value of the PC! */ -/* NOTE: cagney/2003-05-03: This has been replaced by push_dummy_code. - Hopefully that has all the parameters HP/UX needs. */ -#define DEPRECATED_FIX_CALL_DUMMY hppa_fix_call_dummy -extern CORE_ADDR hppa_fix_call_dummy (char *, CORE_ADDR, CORE_ADDR, int, - struct value **, struct type *, int); - #define GDB_TARGET_IS_HPPA /* diff --git a/gdb/config/pa/tm-hppa64.h b/gdb/config/pa/tm-hppa64.h index 62bcebc7423..79fd15cea1c 100644 --- a/gdb/config/pa/tm-hppa64.h +++ b/gdb/config/pa/tm-hppa64.h @@ -57,52 +57,6 @@ extern int hpread_adjust_stack_address (CORE_ADDR); /* jimb: omitted dynamic linking stuff here */ -/* This sequence of words is the instructions - -; Call stack frame has already been built by gdb. Since we could be calling -; a varargs function, and we do not have the benefit of a stub to put things in -; the right place, we load the first 8 word of arguments into both the general -; and fp registers. -call_dummy - nop - copy %r4,%r29 - copy %r5,%r22 - copy %r6,%r27 - fldd -64(0,%r29),%fr4 - fldd -56(0,%r29),%fr5 - fldd -48(0,%r29),%fr6 - fldd -40(0,%r29),%fr7 - fldd -32(0,%r29),%fr8 - fldd -24(0,%r29),%fr9 - fldd -16(0,%r29),%fr10 - fldd -8(0,%r29),%fr11 - copy %r22,%r1 - ldd -64(%r29), %r26 - ldd -56(%r29), %r25 - ldd -48(%r29), %r24 - ldd -40(%r29), %r23 - ldd -32(%r29), %r22 - ldd -24(%r29), %r21 - ldd -16(%r29), %r20 - bve,l (%r1),%r2 - ldd -8(%r29), %r19 - break 4, 8 - mtsp %r21, %sr0 - ble 0(%sr0, %r22) - nop -*/ - -/* Call dummys are sized and written out in word sized hunks. So we have - to pack the instructions into words. Ugh. */ -#undef CALL_DUMMY -#define CALL_DUMMY {0x08000240349d0000LL, 0x34b6000034db0000LL, \ - 0x53a43f8353a53f93LL, 0x53a63fa353a73fb3LL,\ - 0x53a83fc353a93fd3LL, 0x2fa1100a2fb1100bLL,\ - 0x36c1000053ba3f81LL, 0x53b93f9153b83fa1LL,\ - 0x53b73fb153b63fc1LL, 0x53b53fd10fa110d4LL,\ - 0xe820f0000fb110d3LL, 0x0001000400151820LL,\ - 0xe6c0000008000240LL} - /* The PA64 ABI reserves 64 bytes of stack space for outgoing register parameters. */ #undef REG_PARM_STACK_SPACE diff --git a/gdb/hppa-tdep.c b/gdb/hppa-tdep.c index 05c6f453ef9..c906962b196 100644 --- a/gdb/hppa-tdep.c +++ b/gdb/hppa-tdep.c @@ -76,26 +76,12 @@ static const int hppa32_num_regs = 128; static const int hppa64_num_regs = 96; -static const int hppa64_call_dummy_breakpoint_offset = 22 * 4; - -/* DEPRECATED_CALL_DUMMY_LENGTH is computed based on the size of a - word on the target machine, not the size of an instruction. Since - a word on this target holds two instructions we have to divide the - instruction size by two to get the word size of the dummy. */ -static const int hppa32_call_dummy_length = INSTRUCTION_SIZE * 28; -static const int hppa64_call_dummy_length = INSTRUCTION_SIZE * 26 / 2; - /* Get at various relevent fields of an instruction word. */ #define MASK_5 0x1f #define MASK_11 0x7ff #define MASK_14 0x3fff #define MASK_21 0x1fffff -/* Define offsets into the call dummy for the target function address. - See comments related to CALL_DUMMY for more info. */ -#define FUNC_LDIL_OFFSET (INSTRUCTION_SIZE * 9) -#define FUNC_LDO_OFFSET (INSTRUCTION_SIZE * 10) - /* Define offsets into the call dummy for the _sr4export address. See comments related to CALL_DUMMY for more info. */ #define SR4EXPORT_LDIL_OFFSET (INSTRUCTION_SIZE * 12) @@ -118,24 +104,12 @@ static unsigned extract_5R_store (unsigned int); static unsigned extract_5r_store (unsigned int); -static void hppa_frame_init_saved_regs (struct frame_info *frame); - -static void find_dummy_frame_regs (struct frame_info *, CORE_ADDR *); - -static int find_proc_framesize (CORE_ADDR); - -static int find_return_regnum (CORE_ADDR); - struct unwind_table_entry *find_unwind_entry (CORE_ADDR); static int extract_17 (unsigned int); -static unsigned deposit_21 (unsigned int, unsigned int); - static int extract_21 (unsigned); -static unsigned deposit_14 (int, unsigned int); - static int extract_14 (unsigned); static void unwind_command (char *, int); @@ -144,8 +118,6 @@ static int low_sign_extend (unsigned int, unsigned int); static int sign_extend (unsigned int, unsigned int); -static int restore_pc_queue (CORE_ADDR *); - static int hppa_alignof (struct type *); static int prologue_inst_adjust_sp (unsigned long); @@ -156,10 +128,6 @@ static int inst_saves_gr (unsigned long); static int inst_saves_fr (unsigned long); -static int pc_in_interrupt_handler (CORE_ADDR); - -static int pc_in_linker_stub (CORE_ADDR); - static int compare_unwind_entries (const void *, const void *); static void read_unwind_info (struct objfile *); @@ -181,35 +149,14 @@ 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 hppa64_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 * hppa32_register_virtual_type (int reg_nr); struct type * hppa64_register_virtual_type (int reg_nr); -void hppa_store_struct_return (CORE_ADDR addr, CORE_ADDR sp); -void hppa64_extract_return_value (struct type *type, char *regbuf, - char *valbuf); -int hppa64_use_struct_convention (int gcc_p, struct type *type); -void hppa64_store_return_value (struct type *type, char *valbuf); 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); -int hppa_frame_num_args (struct frame_info *frame); -void hppa_push_dummy_frame (void); -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); @@ -233,15 +180,6 @@ extern int hp_som_som_object_present; /* In breakpoint.c */ extern int exception_catchpoints_are_fragile; -/* Should call_function allocate stack space for a struct return? */ - -int -hppa64_use_struct_convention (int gcc_p, struct type *type) -{ - /* RM: struct upto 128 bits are returned in registers */ - return TYPE_LENGTH (type) > 16; -} - /* Handle 32/64-bit struct return conventions. */ static enum return_value_convention @@ -409,16 +347,6 @@ extract_14 (unsigned word) return low_sign_extend (word & MASK_14, 14); } -/* deposit a 14 bit constant in a word */ - -static unsigned -deposit_14 (int opnd, unsigned word) -{ - unsigned sign = (opnd < 0 ? 1 : 0); - - return word | ((unsigned) opnd << 1 & MASK_14) | sign; -} - /* extract a 21 bit constant */ static int @@ -440,27 +368,6 @@ extract_21 (unsigned word) return sign_extend (val, 21) << 11; } -/* deposit a 21 bit constant in a word. Although 21 bit constants are - usually the top 21 bits of a 32 bit constant, we assume that only - the low 21 bits of opnd are relevant */ - -static unsigned -deposit_21 (unsigned opnd, unsigned word) -{ - unsigned val = 0; - - val |= get_field (opnd, 11 + 14, 11 + 18); - val <<= 2; - val |= get_field (opnd, 11 + 12, 11 + 13); - val <<= 2; - val |= get_field (opnd, 11 + 19, 11 + 20); - val <<= 11; - val |= get_field (opnd, 11 + 1, 11 + 11); - val <<= 1; - val |= get_field (opnd, 11 + 0, 11 + 0); - return word | val; -} - /* extract a 17 bit constant from branch instructions, returning the 19 bit signed value. */ @@ -889,1276 +796,20 @@ hppa64_register_name (int i) as presented by hpread.c. This is necessary because of the stack direction on the PA and the - bizarre way in which someone (?) decided they wanted to handle - frame pointerless code in GDB. */ -int -hpread_adjust_stack_address (CORE_ADDR func_addr) -{ - struct unwind_table_entry *u; - - u = find_unwind_entry (func_addr); - if (!u) - return 0; - else - return u->Total_frame_size << 3; -} - -/* Called to determine if PC is in an interrupt handler of some - kind. */ - -static int -pc_in_interrupt_handler (CORE_ADDR pc) -{ - struct unwind_table_entry *u; - struct minimal_symbol *msym_us; - - u = find_unwind_entry (pc); - if (!u) - return 0; - - /* Oh joys. HPUX sets the interrupt bit for _sigreturn even though - 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 - && !PC_IN_SIGTRAMP (pc, DEPRECATED_SYMBOL_NAME (msym_us))); -} - -/* Called when no unwind descriptor was found for PC. Returns 1 if it - appears that PC is in a linker stub. - - ?!? Need to handle stubs which appear in PA64 code. */ - -static int -pc_in_linker_stub (CORE_ADDR pc) -{ - int found_magic_instruction = 0; - int i; - char buf[4]; - - /* If unable to read memory, assume pc is not in a linker stub. */ - if (target_read_memory (pc, buf, 4) != 0) - return 0; - - /* We are looking for something like - - ; $$dyncall jams RP into this special spot in the frame (RP') - ; before calling the "call stub" - ldw -18(sp),rp - - ldsid (rp),r1 ; Get space associated with RP into r1 - mtsp r1,sp ; Move it into space register 0 - be,n 0(sr0),rp) ; back to your regularly scheduled program */ - - /* Maximum known linker stub size is 4 instructions. Search forward - from the given PC, then backward. */ - for (i = 0; i < 4; i++) - { - /* If we hit something with an unwind, stop searching this direction. */ - - if (find_unwind_entry (pc + i * 4) != 0) - break; - - /* Check for ldsid (rp),r1 which is the magic instruction for a - return from a cross-space function call. */ - if (read_memory_integer (pc + i * 4, 4) == 0x004010a1) - { - found_magic_instruction = 1; - break; - } - /* Add code to handle long call/branch and argument relocation stubs - here. */ - } - - if (found_magic_instruction != 0) - return 1; - - /* Now look backward. */ - for (i = 0; i < 4; i++) - { - /* If we hit something with an unwind, stop searching this direction. */ - - if (find_unwind_entry (pc - i * 4) != 0) - break; - - /* Check for ldsid (rp),r1 which is the magic instruction for a - return from a cross-space function call. */ - if (read_memory_integer (pc - i * 4, 4) == 0x004010a1) - { - found_magic_instruction = 1; - break; - } - /* Add code to handle long call/branch and argument relocation stubs - here. */ - } - return found_magic_instruction; -} - -static int -find_return_regnum (CORE_ADDR pc) -{ - struct unwind_table_entry *u; - - u = find_unwind_entry (pc); - - if (!u) - return RP_REGNUM; - - if (u->Millicode) - return 31; - - return RP_REGNUM; -} - -/* Return size of frame, or -1 if we should use a frame pointer. */ -static int -find_proc_framesize (CORE_ADDR pc) -{ - struct unwind_table_entry *u; - struct minimal_symbol *msym_us; - - /* This may indicate a bug in our callers... */ - if (pc == (CORE_ADDR) 0) - return -1; - - u = find_unwind_entry (pc); - - if (!u) - { - if (pc_in_linker_stub (pc)) - /* Linker stubs have a zero size frame. */ - return 0; - else - return -1; - } - - msym_us = lookup_minimal_symbol_by_pc (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) - && msym_us - && !PC_IN_SIGTRAMP (pc, DEPRECATED_SYMBOL_NAME (msym_us))) - return -1; - - return u->Total_frame_size << 3; -} - -/* Return offset from sp at which rp is saved, or 0 if not saved. */ -static int rp_saved (CORE_ADDR); - -static int -rp_saved (CORE_ADDR pc) -{ - struct unwind_table_entry *u; - - /* A function at, and thus a return PC from, address 0? Not in HP-UX! */ - if (pc == (CORE_ADDR) 0) - return 0; - - u = find_unwind_entry (pc); - - if (!u) - { - if (pc_in_linker_stub (pc)) - /* This is the so-called RP'. */ - return -24; - else - return 0; - } - - if (u->Save_RP) - return (TARGET_PTR_BIT == 64 ? -16 : -20); - else if (u->stub_unwind.stub_type != 0) - { - switch (u->stub_unwind.stub_type) - { - case EXPORT: - case IMPORT: - return -24; - case PARAMETER_RELOCATION: - return -8; - default: - return 0; - } - } - else - return 0; -} - -int -hppa_frameless_function_invocation (struct frame_info *frame) -{ - struct unwind_table_entry *u; - - u = find_unwind_entry (get_frame_pc (frame)); - - if (u == 0) - return 0; - - 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 -hppa_saved_pc_after_call (struct frame_info *frame) -{ - int ret_regnum; - CORE_ADDR pc; - struct unwind_table_entry *u; - - ret_regnum = find_return_regnum (get_frame_pc (frame)); - pc = read_register (ret_regnum) & ~0x3; - - /* If PC is in a linker stub, then we need to dig the address - the stub will return to out of the stack. */ - u = find_unwind_entry (pc); - if (u && u->stub_unwind.stub_type != 0) - return DEPRECATED_FRAME_SAVED_PC (frame); - else - return pc; -} - -CORE_ADDR -hppa_frame_saved_pc (struct frame_info *frame) -{ - CORE_ADDR pc = get_frame_pc (frame); - struct unwind_table_entry *u; - CORE_ADDR old_pc = 0; - int spun_around_loop = 0; - int rp_offset = 0; - - /* BSD, HPUX & OSF1 all lay out the hardware state in the same manner - at the base of the frame in an interrupt handler. Registers within - are saved in the exact same order as GDB numbers registers. How - convienent. */ - if (pc_in_interrupt_handler (pc)) - return read_memory_integer (get_frame_base (frame) + PCOQ_HEAD_REGNUM * 4, - TARGET_PTR_BIT / 8) & ~0x3; - - if ((get_frame_pc (frame) >= get_frame_base (frame) - && (get_frame_pc (frame) - <= (get_frame_base (frame) - /* A call dummy is sized in words, but it is actually a - series of instructions. Account for that scaling - factor. */ - + ((DEPRECATED_REGISTER_SIZE / INSTRUCTION_SIZE) - * DEPRECATED_CALL_DUMMY_LENGTH) - /* Similarly we have to account for 64bit wide register - saves. */ - + (32 * DEPRECATED_REGISTER_SIZE) - /* We always consider FP regs 8 bytes long. */ - + (NUM_REGS - FP0_REGNUM) * 8 - /* Similarly we have to account for 64bit wide register - saves. */ - + (6 * DEPRECATED_REGISTER_SIZE))))) - { - return read_memory_integer ((get_frame_base (frame) - + (TARGET_PTR_BIT == 64 ? -16 : -20)), - TARGET_PTR_BIT / 8) & ~0x3; - } - -#ifdef FRAME_SAVED_PC_IN_SIGTRAMP - /* Deal with signal handler caller frames too. */ - if ((get_frame_type (frame) == SIGTRAMP_FRAME)) - { - CORE_ADDR rp; - FRAME_SAVED_PC_IN_SIGTRAMP (frame, &rp); - return rp & ~0x3; - } -#endif - - if (hppa_frameless_function_invocation (frame)) - { - int ret_regnum; - - ret_regnum = find_return_regnum (pc); - - /* If the next frame is an interrupt frame or a signal - handler caller, then we need to look in the saved - register area to get the return pointer (the values - in the registers may not correspond to anything useful). */ - if (get_next_frame (frame) - && ((get_frame_type (get_next_frame (frame)) == SIGTRAMP_FRAME) - || pc_in_interrupt_handler (get_frame_pc (get_next_frame (frame))))) - { - CORE_ADDR *saved_regs; - hppa_frame_init_saved_regs (get_next_frame (frame)); - saved_regs = deprecated_get_frame_saved_regs (get_next_frame (frame)); - if (read_memory_integer (saved_regs[FLAGS_REGNUM], - TARGET_PTR_BIT / 8) & 0x2) - { - pc = read_memory_integer (saved_regs[31], - TARGET_PTR_BIT / 8) & ~0x3; - - /* Syscalls are really two frames. The syscall stub itself - with a return pointer in %rp and the kernel call with - a return pointer in %r31. We return the %rp variant - if %r31 is the same as frame->pc. */ - if (pc == get_frame_pc (frame)) - pc = read_memory_integer (saved_regs[RP_REGNUM], - TARGET_PTR_BIT / 8) & ~0x3; - } - else - pc = read_memory_integer (saved_regs[RP_REGNUM], - TARGET_PTR_BIT / 8) & ~0x3; - } - else - pc = read_register (ret_regnum) & ~0x3; - } - else - { - spun_around_loop = 0; - old_pc = pc; - - restart: - rp_offset = rp_saved (pc); - - /* Similar to code in frameless function case. If the next - frame is a signal or interrupt handler, then dig the right - information out of the saved register info. */ - if (rp_offset == 0 - && get_next_frame (frame) - && ((get_frame_type (get_next_frame (frame)) == SIGTRAMP_FRAME) - || pc_in_interrupt_handler (get_frame_pc (get_next_frame (frame))))) - { - CORE_ADDR *saved_regs; - hppa_frame_init_saved_regs (get_next_frame (frame)); - saved_regs = deprecated_get_frame_saved_regs (get_next_frame (frame)); - if (read_memory_integer (saved_regs[FLAGS_REGNUM], - TARGET_PTR_BIT / 8) & 0x2) - { - pc = read_memory_integer (saved_regs[31], - TARGET_PTR_BIT / 8) & ~0x3; - - /* Syscalls are really two frames. The syscall stub itself - with a return pointer in %rp and the kernel call with - a return pointer in %r31. We return the %rp variant - if %r31 is the same as frame->pc. */ - if (pc == get_frame_pc (frame)) - pc = read_memory_integer (saved_regs[RP_REGNUM], - TARGET_PTR_BIT / 8) & ~0x3; - } - else - pc = read_memory_integer (saved_regs[RP_REGNUM], - TARGET_PTR_BIT / 8) & ~0x3; - } - else if (rp_offset == 0) - { - old_pc = pc; - pc = read_register (RP_REGNUM) & ~0x3; - } - else - { - old_pc = pc; - pc = read_memory_integer (get_frame_base (frame) + rp_offset, - TARGET_PTR_BIT / 8) & ~0x3; - } - } - - /* If PC is inside a linker stub, then dig out the address the stub - will return to. - - Don't do this for long branch stubs. Why? For some unknown reason - _start is marked as a long branch stub in hpux10. */ - u = find_unwind_entry (pc); - if (u && u->stub_unwind.stub_type != 0 - && u->stub_unwind.stub_type != LONG_BRANCH) - { - unsigned int insn; - - /* If this is a dynamic executable, and we're in a signal handler, - then the call chain will eventually point us into the stub for - _sigreturn. Unlike most cases, we'll be pointed to the branch - to the real sigreturn rather than the code after the real branch!. - - Else, try to dig the address the stub will return to in the normal - fashion. */ - insn = read_memory_integer (pc, 4); - if ((insn & 0xfc00e000) == 0xe8000000) - return (pc + extract_17 (insn) + 8) & ~0x3; - else - { - if (old_pc == pc) - spun_around_loop++; - - if (spun_around_loop > 1) - { - /* We're just about to go around the loop again with - no more hope of success. Die. */ - error ("Unable to find return pc for this frame"); - } - else - goto restart; - } - } - - return pc; -} - -/* We need to correct the PC and the FP for the outermost frame when we are - in a system call. */ - -void -hppa_init_extra_frame_info (int fromleaf, struct frame_info *frame) -{ - int flags; - int framesize; - - if (get_next_frame (frame) && !fromleaf) - return; - - /* If the next frame represents a frameless function invocation then - we have to do some adjustments that are normally done by - DEPRECATED_FRAME_CHAIN. (DEPRECATED_FRAME_CHAIN is not called in - this case.) */ - if (fromleaf) - { - /* Find the framesize of *this* frame without peeking at the PC - in the current frame structure (it isn't set yet). */ - framesize = find_proc_framesize (DEPRECATED_FRAME_SAVED_PC (get_next_frame (frame))); - - /* Now adjust our base frame accordingly. If we have a frame pointer - use it, else subtract the size of this frame from the current - frame. (we always want frame->frame to point at the lowest address - in the frame). */ - if (framesize == -1) - deprecated_update_frame_base_hack (frame, deprecated_read_fp ()); - else - deprecated_update_frame_base_hack (frame, get_frame_base (frame) - framesize); - return; - } - - flags = read_register (FLAGS_REGNUM); - if (flags & 2) /* In system call? */ - deprecated_update_frame_pc_hack (frame, read_register (31) & ~0x3); - - /* The outermost frame is always derived from PC-framesize - - One might think frameless innermost frames should have - a frame->frame that is the same as the parent's frame->frame. - That is wrong; frame->frame in that case should be the *high* - address of the parent's frame. It's complicated as hell to - explain, but the parent *always* creates some stack space for - the child. So the child actually does have a frame of some - sorts, and its base is the high address in its parent's frame. */ - framesize = find_proc_framesize (get_frame_pc (frame)); - if (framesize == -1) - deprecated_update_frame_base_hack (frame, deprecated_read_fp ()); - else - deprecated_update_frame_base_hack (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 DEPRECATED_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 -hppa_frame_chain (struct frame_info *frame) -{ - int my_framesize, caller_framesize; - struct unwind_table_entry *u; - CORE_ADDR frame_base; - struct frame_info *tmp_frame; - - /* A frame in the current frame list, or zero. */ - struct frame_info *saved_regs_frame = 0; - /* Where the registers were saved in saved_regs_frame. If - saved_regs_frame is zero, this is garbage. */ - CORE_ADDR *saved_regs = NULL; - - CORE_ADDR caller_pc; - - struct minimal_symbol *min_frame_symbol; - struct symbol *frame_symbol; - char *frame_symbol_name; - - /* If this is a threaded application, and we see the - routine "__pthread_exit", treat it as the stack root - for this thread. */ - min_frame_symbol = lookup_minimal_symbol_by_pc (get_frame_pc (frame)); - frame_symbol = find_pc_function (get_frame_pc (frame)); - - if ((min_frame_symbol != 0) /* && (frame_symbol == 0) */ ) - { - /* The test above for "no user function name" would defend - against the slim likelihood that a user might define a - routine named "__pthread_exit" and then try to debug it. - - If it weren't commented out, and you tried to debug the - pthread library itself, you'd get errors. - - So for today, we don't make that check. */ - frame_symbol_name = DEPRECATED_SYMBOL_NAME (min_frame_symbol); - if (frame_symbol_name != 0) - { - if (0 == strncmp (frame_symbol_name, - THREAD_INITIAL_FRAME_SYMBOL, - THREAD_INITIAL_FRAME_SYM_LEN)) - { - /* Pretend we've reached the bottom of the stack. */ - return (CORE_ADDR) 0; - } - } - } /* End of hacky code for threads. */ - - /* Handle HPUX, BSD, and OSF1 style interrupt frames first. These - are easy; at *sp we have a full save state strucutre which we can - pull the old stack pointer from. Also see frame_saved_pc for - code to dig a saved PC out of the save state structure. */ - if (pc_in_interrupt_handler (get_frame_pc (frame))) - frame_base = read_memory_integer (get_frame_base (frame) + SP_REGNUM * 4, - TARGET_PTR_BIT / 8); -#ifdef FRAME_BASE_BEFORE_SIGTRAMP - else if ((get_frame_type (frame) == SIGTRAMP_FRAME)) - { - FRAME_BASE_BEFORE_SIGTRAMP (frame, &frame_base); - } -#endif - else - frame_base = get_frame_base (frame); - - /* Get frame sizes for the current frame and the frame of the - caller. */ - my_framesize = find_proc_framesize (get_frame_pc (frame)); - caller_pc = DEPRECATED_FRAME_SAVED_PC (frame); - - /* If we can't determine the caller's PC, then it's not likely we can - really determine anything meaningful about its frame. We'll consider - this to be stack bottom. */ - if (caller_pc == (CORE_ADDR) 0) - return (CORE_ADDR) 0; - - caller_framesize = find_proc_framesize (DEPRECATED_FRAME_SAVED_PC (frame)); - - /* If caller does not have a frame pointer, then its frame - can be found at current_frame - caller_framesize. */ - if (caller_framesize != -1) - { - return frame_base - caller_framesize; - } - /* Both caller and callee have frame pointers and are GCC compiled - (SAVE_SP bit in unwind descriptor is on for both functions. - The previous frame pointer is found at the top of the current frame. */ - if (caller_framesize == -1 && my_framesize == -1) - { - return read_memory_integer (frame_base, TARGET_PTR_BIT / 8); - } - /* Caller has a frame pointer, but callee does not. This is a little - more difficult as GCC and HP C lay out locals and callee register save - areas very differently. - - The previous frame pointer could be in a register, or in one of - several areas on the stack. - - Walk from the current frame to the innermost frame examining - unwind descriptors to determine if %r3 ever gets saved into the - stack. If so return whatever value got saved into the stack. - If it was never saved in the stack, then the value in %r3 is still - valid, so use it. - - We use information from unwind descriptors to determine if %r3 - is saved into the stack (Entry_GR field has this information). */ - - for (tmp_frame = frame; tmp_frame; tmp_frame = get_next_frame (tmp_frame)) - { - u = find_unwind_entry (get_frame_pc (tmp_frame)); - - if (!u) - { - /* We could find this information by examining prologues. I don't - think anyone has actually written any tools (not even "strip") - which leave them out of an executable, so maybe this is a moot - point. */ - /* ??rehrauer: Actually, it's quite possible to stepi your way into - code that doesn't have unwind entries. For example, stepping into - the dynamic linker will give you a PC that has none. Thus, I've - disabled this warning. */ -#if 0 - warning ("Unable to find unwind for PC 0x%x -- Help!", get_frame_pc (tmp_frame)); -#endif - return (CORE_ADDR) 0; - } - - if (u->Save_SP - || (get_frame_type (tmp_frame) == SIGTRAMP_FRAME) - || pc_in_interrupt_handler (get_frame_pc (tmp_frame))) - break; - - /* Entry_GR specifies the number of callee-saved general registers - saved in the stack. It starts at %r3, so %r3 would be 1. */ - if (u->Entry_GR >= 1) - { - /* 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. */ - hppa_frame_init_saved_regs (tmp_frame); - saved_regs = deprecated_get_frame_saved_regs (tmp_frame); - saved_regs_frame = tmp_frame; - - /* If we have an address for r3, that's good. */ - if (saved_regs[DEPRECATED_FP_REGNUM]) - break; - } - } - - if (tmp_frame) - { - /* We may have walked down the chain into a function with a frame - pointer. */ - if (u->Save_SP - && !(get_frame_type (tmp_frame) == SIGTRAMP_FRAME) - && !pc_in_interrupt_handler (get_frame_pc (tmp_frame))) - { - return read_memory_integer (get_frame_base (tmp_frame), TARGET_PTR_BIT / 8); - } - /* %r3 was saved somewhere in the stack. Dig it out. */ - else - { - /* Sick. - - For optimization purposes many kernels don't have the - callee saved registers into the save_state structure upon - entry into the kernel for a syscall; the optimization - is usually turned off if the process is being traced so - that the debugger can get full register state for the - process. - - This scheme works well except for two cases: - - * Attaching to a process when the process is in the - kernel performing a system call (debugger can't get - full register state for the inferior process since - the process wasn't being traced when it entered the - system call). - - * Register state is not complete if the system call - causes the process to core dump. - - - The following heinous code is an attempt to deal with - the lack of register state in a core dump. It will - fail miserably if the function which performs the - system call has a variable sized stack frame. */ - - if (tmp_frame != saved_regs_frame) - { - hppa_frame_init_saved_regs (tmp_frame); - saved_regs = deprecated_get_frame_saved_regs (tmp_frame); - } - - /* Abominable hack. */ - if (current_target.to_has_execution == 0 - && ((saved_regs[FLAGS_REGNUM] - && (read_memory_integer (saved_regs[FLAGS_REGNUM], - TARGET_PTR_BIT / 8) - & 0x2)) - || (saved_regs[FLAGS_REGNUM] == 0 - && read_register (FLAGS_REGNUM) & 0x2))) - { - u = find_unwind_entry (DEPRECATED_FRAME_SAVED_PC (frame)); - if (!u) - { - return read_memory_integer (saved_regs[DEPRECATED_FP_REGNUM], - TARGET_PTR_BIT / 8); - } - else - { - return frame_base - (u->Total_frame_size << 3); - } - } - - return read_memory_integer (saved_regs[DEPRECATED_FP_REGNUM], - TARGET_PTR_BIT / 8); - } - } - else - { - /* Get the innermost frame. */ - tmp_frame = frame; - while (get_next_frame (tmp_frame) != NULL) - tmp_frame = get_next_frame (tmp_frame); - - if (tmp_frame != saved_regs_frame) - { - hppa_frame_init_saved_regs (tmp_frame); - saved_regs = deprecated_get_frame_saved_regs (tmp_frame); - } - - /* Abominable hack. See above. */ - if (current_target.to_has_execution == 0 - && ((saved_regs[FLAGS_REGNUM] - && (read_memory_integer (saved_regs[FLAGS_REGNUM], - TARGET_PTR_BIT / 8) - & 0x2)) - || (saved_regs[FLAGS_REGNUM] == 0 - && read_register (FLAGS_REGNUM) & 0x2))) - { - u = find_unwind_entry (DEPRECATED_FRAME_SAVED_PC (frame)); - if (!u) - { - return read_memory_integer (saved_regs[DEPRECATED_FP_REGNUM], - TARGET_PTR_BIT / 8); - } - else - { - return frame_base - (u->Total_frame_size << 3); - } - } - - /* The value in %r3 was never saved into the stack (thus %r3 still - holds the value of the previous frame pointer). */ - return deprecated_read_fp (); - } -} - - -/* To see if a frame chain is valid, see if the caller looks like it - was compiled with gcc. */ - -int -hppa_frame_chain_valid (CORE_ADDR chain, struct frame_info *thisframe) -{ - struct minimal_symbol *msym_us; - struct minimal_symbol *msym_start; - struct unwind_table_entry *u, *next_u = NULL; - struct frame_info *next; - - u = find_unwind_entry (get_frame_pc (thisframe)); - - if (u == NULL) - return 1; - - /* We can't just check that the same of msym_us is "_start", because - someone idiotically decided that they were going to make a Ltext_end - symbol with the same address. This Ltext_end symbol is totally - indistinguishable (as nearly as I can tell) from the symbol for a function - which is (legitimately, since it is in the user's namespace) - named Ltext_end, so we can't just ignore it. */ - msym_us = lookup_minimal_symbol_by_pc (DEPRECATED_FRAME_SAVED_PC (thisframe)); - msym_start = lookup_minimal_symbol ("_start", NULL, NULL); - if (msym_us - && msym_start - && SYMBOL_VALUE_ADDRESS (msym_us) == SYMBOL_VALUE_ADDRESS (msym_start)) - return 0; - - /* Grrrr. Some new idiot decided that they don't want _start for the - PRO configurations; $START$ calls main directly.... Deal with it. */ - msym_start = lookup_minimal_symbol ("$START$", NULL, NULL); - if (msym_us - && msym_start - && SYMBOL_VALUE_ADDRESS (msym_us) == SYMBOL_VALUE_ADDRESS (msym_start)) - return 0; - - next = get_next_frame (thisframe); - if (next) - next_u = find_unwind_entry (get_frame_pc (next)); - - /* If this frame does not save SP, has no stack, isn't a stub, - 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 - || (get_next_frame (thisframe) && (get_frame_type (get_next_frame (thisframe)) == SIGTRAMP_FRAME)) - || (next_u && next_u->HP_UX_interrupt_marker)) - return 1; - - if (pc_in_linker_stub (get_frame_pc (thisframe))) - return 1; - - return 0; -} - -/* These functions deal with saving and restoring register state - around a function call in the inferior. They keep the stack - double-word aligned; eventually, on an hp700, the stack will have - to be aligned to a 64-byte boundary. */ - -void -hppa_push_dummy_frame (void) -{ - CORE_ADDR sp, pc, pcspace; - int regnum; - CORE_ADDR int_buffer; - double freg_buffer; - - pc = hppa_target_read_pc (inferior_ptid); - int_buffer = read_register (FLAGS_REGNUM); - if (int_buffer & 0x2) - { - const unsigned int sid = (pc >> 30) & 0x3; - if (sid == 0) - pcspace = read_register (SR4_REGNUM); - else - pcspace = read_register (SR4_REGNUM + 4 + sid); - } - else - pcspace = read_register (PCSQ_HEAD_REGNUM); - - /* Space for "arguments"; the RP goes in here. */ - sp = read_register (SP_REGNUM) + 48; - int_buffer = read_register (RP_REGNUM) | 0x3; - - /* The 32bit and 64bit ABIs save the return pointer into different - stack slots. */ - if (DEPRECATED_REGISTER_SIZE == 8) - write_memory (sp - 16, (char *) &int_buffer, DEPRECATED_REGISTER_SIZE); - else - write_memory (sp - 20, (char *) &int_buffer, DEPRECATED_REGISTER_SIZE); - - int_buffer = deprecated_read_fp (); - write_memory (sp, (char *) &int_buffer, DEPRECATED_REGISTER_SIZE); - - write_register (DEPRECATED_FP_REGNUM, sp); - - sp += 2 * DEPRECATED_REGISTER_SIZE; - - for (regnum = 1; regnum < 32; regnum++) - if (regnum != RP_REGNUM && regnum != DEPRECATED_FP_REGNUM) - sp = push_word (sp, read_register (regnum)); - - /* This is not necessary for the 64bit ABI. In fact it is dangerous. */ - if (DEPRECATED_REGISTER_SIZE != 8) - sp += 4; - - for (regnum = FP0_REGNUM; regnum < NUM_REGS; regnum++) - { - deprecated_read_register_bytes (DEPRECATED_REGISTER_BYTE (regnum), - (char *) &freg_buffer, 8); - sp = push_bytes (sp, (char *) &freg_buffer, 8); - } - sp = push_word (sp, read_register (IPSW_REGNUM)); - sp = push_word (sp, read_register (SAR_REGNUM)); - sp = push_word (sp, pc); - sp = push_word (sp, pcspace); - sp = push_word (sp, pc + 4); - sp = push_word (sp, pcspace); - write_register (SP_REGNUM, sp); -} - -static void -find_dummy_frame_regs (struct frame_info *frame, - CORE_ADDR frame_saved_regs[]) -{ - CORE_ADDR fp = get_frame_base (frame); - int i; - - /* The 32bit and 64bit ABIs save RP into different locations. */ - if (DEPRECATED_REGISTER_SIZE == 8) - frame_saved_regs[RP_REGNUM] = (fp - 16) & ~0x3; - else - frame_saved_regs[RP_REGNUM] = (fp - 20) & ~0x3; - - frame_saved_regs[DEPRECATED_FP_REGNUM] = fp; - - frame_saved_regs[1] = fp + (2 * DEPRECATED_REGISTER_SIZE); - - for (fp += 3 * DEPRECATED_REGISTER_SIZE, i = 3; i < 32; i++) - { - if (i != DEPRECATED_FP_REGNUM) - { - frame_saved_regs[i] = fp; - fp += DEPRECATED_REGISTER_SIZE; - } - } - - /* This is not necessary or desirable for the 64bit ABI. */ - if (DEPRECATED_REGISTER_SIZE != 8) - fp += 4; - - for (i = FP0_REGNUM; i < NUM_REGS; i++, fp += 8) - frame_saved_regs[i] = fp; - - frame_saved_regs[IPSW_REGNUM] = fp; - frame_saved_regs[SAR_REGNUM] = fp + DEPRECATED_REGISTER_SIZE; - frame_saved_regs[PCOQ_HEAD_REGNUM] = fp + 2 * DEPRECATED_REGISTER_SIZE; - frame_saved_regs[PCSQ_HEAD_REGNUM] = fp + 3 * DEPRECATED_REGISTER_SIZE; - frame_saved_regs[PCOQ_TAIL_REGNUM] = fp + 4 * DEPRECATED_REGISTER_SIZE; - frame_saved_regs[PCSQ_TAIL_REGNUM] = fp + 5 * DEPRECATED_REGISTER_SIZE; -} - -void -hppa_pop_frame (void) -{ - struct frame_info *frame = get_current_frame (); - CORE_ADDR fp, npc, target_pc; - int regnum; - CORE_ADDR *fsr; - double freg_buffer; - - fp = get_frame_base (frame); - hppa_frame_init_saved_regs (frame); - fsr = deprecated_get_frame_saved_regs (frame); - -#ifndef NO_PC_SPACE_QUEUE_RESTORE - if (fsr[IPSW_REGNUM]) /* Restoring a call dummy frame */ - restore_pc_queue (fsr); -#endif - - for (regnum = 31; regnum > 0; regnum--) - if (fsr[regnum]) - write_register (regnum, read_memory_integer (fsr[regnum], - DEPRECATED_REGISTER_SIZE)); - - for (regnum = NUM_REGS - 1; regnum >= FP0_REGNUM; regnum--) - if (fsr[regnum]) - { - read_memory (fsr[regnum], (char *) &freg_buffer, 8); - deprecated_write_register_bytes (DEPRECATED_REGISTER_BYTE (regnum), - (char *) &freg_buffer, 8); - } - - if (fsr[IPSW_REGNUM]) - write_register (IPSW_REGNUM, - read_memory_integer (fsr[IPSW_REGNUM], - DEPRECATED_REGISTER_SIZE)); - - if (fsr[SAR_REGNUM]) - write_register (SAR_REGNUM, - read_memory_integer (fsr[SAR_REGNUM], - DEPRECATED_REGISTER_SIZE)); - - /* If the PC was explicitly saved, then just restore it. */ - if (fsr[PCOQ_TAIL_REGNUM]) - { - npc = read_memory_integer (fsr[PCOQ_TAIL_REGNUM], - DEPRECATED_REGISTER_SIZE); - write_register (PCOQ_TAIL_REGNUM, npc); - } - /* Else use the value in %rp to set the new PC. */ - else - { - npc = read_register (RP_REGNUM); - write_pc (npc); - } - - write_register (DEPRECATED_FP_REGNUM, read_memory_integer (fp, DEPRECATED_REGISTER_SIZE)); - - if (fsr[IPSW_REGNUM]) /* call dummy */ - write_register (SP_REGNUM, fp - 48); - else - write_register (SP_REGNUM, fp); - - /* The PC we just restored may be inside a return trampoline. If so - we want to restart the inferior and run it through the trampoline. - - Do this by setting a momentary breakpoint at the location the - trampoline returns to. - - Don't skip through the trampoline if we're popping a dummy frame. */ - target_pc = SKIP_TRAMPOLINE_CODE (npc & ~0x3) & ~0x3; - if (target_pc && !fsr[IPSW_REGNUM]) - { - struct symtab_and_line sal; - struct breakpoint *breakpoint; - struct cleanup *old_chain; - - /* Set up our breakpoint. Set it to be silent as the MI code - 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_frame_id, bp_finish); - breakpoint->silent = 1; - - /* So we can clean things up. */ - old_chain = make_cleanup_delete_breakpoint (breakpoint); - - /* Start up the inferior. */ - clear_proceed_status (); - proceed_to_finish = 1; - proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 0); - - /* Perform our cleanups. */ - do_cleanups (old_chain); - } - flush_cached_frames (); -} - -/* After returning to a dummy on the stack, restore the instruction - queue space registers. */ - -static int -restore_pc_queue (CORE_ADDR *fsr) -{ - CORE_ADDR pc = read_pc (); - CORE_ADDR new_pc = read_memory_integer (fsr[PCOQ_HEAD_REGNUM], - TARGET_PTR_BIT / 8); - struct target_waitstatus w; - int insn_count; - - /* Advance past break instruction in the call dummy. */ - write_register (PCOQ_HEAD_REGNUM, pc + 4); - write_register (PCOQ_TAIL_REGNUM, pc + 8); - - /* HPUX doesn't let us set the space registers or the space - registers of the PC queue through ptrace. Boo, hiss. - Conveniently, the call dummy has this sequence of instructions - after the break: - mtsp r21, sr0 - ble,n 0(sr0, r22) - - So, load up the registers and single step until we are in the - right place. */ - - write_register (21, read_memory_integer (fsr[PCSQ_HEAD_REGNUM], - DEPRECATED_REGISTER_SIZE)); - write_register (22, new_pc); - - for (insn_count = 0; insn_count < 3; insn_count++) - { - /* FIXME: What if the inferior gets a signal right now? Want to - merge this into wait_for_inferior (as a special kind of - watchpoint? By setting a breakpoint at the end? Is there - any other choice? Is there *any* way to do this stuff with - ptrace() or some equivalent?). */ - resume (1, 0); - target_wait (inferior_ptid, &w); - - if (w.kind == TARGET_WAITKIND_SIGNALLED) - { - stop_signal = w.value.sig; - terminal_ours_for_output (); - printf_unfiltered ("\nProgram terminated with signal %s, %s.\n", - target_signal_to_name (stop_signal), - target_signal_to_string (stop_signal)); - gdb_flush (gdb_stdout); - return 0; - } - } - target_terminal_ours (); - target_fetch_registers (-1); - return 1; -} - - -#ifdef PA20W_CALLING_CONVENTIONS - -/* This function pushes a stack frame with arguments as part of the - inferior function calling mechanism. - - This is the version for the PA64, in which later arguments appear - at higher addresses. (The stack always grows towards higher - addresses.) - - We simply allocate the appropriate amount of stack space and put - arguments into their proper slots. The call dummy code will copy - arguments into registers as needed by the ABI. - - This ABI also requires that the caller provide an argument pointer - to the callee, so we do that too. */ - -CORE_ADDR -hppa_push_arguments (int nargs, struct value **args, CORE_ADDR sp, - int struct_return, CORE_ADDR struct_addr) -{ - /* array of arguments' offsets */ - int *offset = (int *) alloca (nargs * sizeof (int)); - - /* array of arguments' lengths: real lengths in bytes, not aligned to - word size */ - int *lengths = (int *) alloca (nargs * sizeof (int)); - - /* The value of SP as it was passed into this function after - aligning. */ - CORE_ADDR orig_sp = DEPRECATED_STACK_ALIGN (sp); - - /* The number of stack bytes occupied by the current argument. */ - int bytes_reserved; - - /* The total number of bytes reserved for the arguments. */ - int cum_bytes_reserved = 0; - - /* Similarly, but aligned. */ - int cum_bytes_aligned = 0; - int i; - - /* Iterate over each argument provided by the user. */ - for (i = 0; i < nargs; i++) - { - struct type *arg_type = VALUE_TYPE (args[i]); - - /* Integral scalar values smaller than a register are padded on - the left. We do this by promoting them to full-width, - although the ABI says to pad them with garbage. */ - if (is_integral_type (arg_type) - && TYPE_LENGTH (arg_type) < DEPRECATED_REGISTER_SIZE) - { - args[i] = value_cast ((TYPE_UNSIGNED (arg_type) - ? builtin_type_unsigned_long - : builtin_type_long), - args[i]); - arg_type = VALUE_TYPE (args[i]); - } - - lengths[i] = TYPE_LENGTH (arg_type); - - /* Align the size of the argument to the word size for this - target. */ - bytes_reserved = (lengths[i] + DEPRECATED_REGISTER_SIZE - 1) & -DEPRECATED_REGISTER_SIZE; - - offset[i] = cum_bytes_reserved; - - /* Aggregates larger than eight bytes (the only types larger - than eight bytes we have) are aligned on a 16-byte boundary, - possibly padded on the right with garbage. This may leave an - empty word on the stack, and thus an unused register, as per - the ABI. */ - if (bytes_reserved > 8) - { - /* Round up the offset to a multiple of two slots. */ - int new_offset = ((offset[i] + 2*DEPRECATED_REGISTER_SIZE-1) - & -(2*DEPRECATED_REGISTER_SIZE)); - - /* Note the space we've wasted, if any. */ - bytes_reserved += new_offset - offset[i]; - offset[i] = new_offset; - } - - cum_bytes_reserved += bytes_reserved; - } - - /* CUM_BYTES_RESERVED already accounts for all the arguments - passed by the user. However, the ABIs mandate minimum stack space - allocations for outgoing arguments. - - The ABIs also mandate minimum stack alignments which we must - preserve. */ - cum_bytes_aligned = DEPRECATED_STACK_ALIGN (cum_bytes_reserved); - sp += max (cum_bytes_aligned, REG_PARM_STACK_SPACE); - - /* Now write each of the args at the proper offset down the stack. */ - for (i = 0; i < nargs; i++) - write_memory (orig_sp + offset[i], VALUE_CONTENTS (args[i]), lengths[i]); - - /* If a structure has to be returned, set up register 28 to hold its - address */ - if (struct_return) - write_register (28, struct_addr); - - /* For the PA64 we must pass a pointer to the outgoing argument list. - The ABI mandates that the pointer should point to the first byte of - storage beyond the register flushback area. - - However, the call dummy expects the outgoing argument pointer to - be passed in register %r4. */ - write_register (4, orig_sp + REG_PARM_STACK_SPACE); - - /* ?!? This needs further work. We need to set up the global data - pointer for this procedure. This assumes the same global pointer - for every procedure. The call dummy expects the dp value to - be passed in register %r6. */ - write_register (6, read_register (27)); - - /* The stack will have 64 bytes of additional space for a frame marker. */ - return sp + 64; -} - -#else - -/* This function pushes a stack frame with arguments as part of the - inferior function calling mechanism. - - This is the version of the function for the 32-bit PA machines, in - which later arguments appear at lower addresses. (The stack always - grows towards higher addresses.) - - We simply allocate the appropriate amount of stack space and put - arguments into their proper slots. The call dummy code will copy - arguments into registers as needed by the ABI. */ - -CORE_ADDR -hppa_push_arguments (int nargs, struct value **args, CORE_ADDR sp, - int struct_return, CORE_ADDR struct_addr) -{ - /* array of arguments' offsets */ - int *offset = (int *) alloca (nargs * sizeof (int)); - - /* array of arguments' lengths: real lengths in bytes, not aligned to - word size */ - int *lengths = (int *) alloca (nargs * sizeof (int)); - - /* The number of stack bytes occupied by the current argument. */ - int bytes_reserved; - - /* The total number of bytes reserved for the arguments. */ - int cum_bytes_reserved = 0; - - /* Similarly, but aligned. */ - int cum_bytes_aligned = 0; - int i; - - /* Iterate over each argument provided by the user. */ - for (i = 0; i < nargs; i++) - { - lengths[i] = TYPE_LENGTH (VALUE_TYPE (args[i])); - - /* Align the size of the argument to the word size for this - target. */ - bytes_reserved = (lengths[i] + DEPRECATED_REGISTER_SIZE - 1) & -DEPRECATED_REGISTER_SIZE; - - 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. */ - if ((bytes_reserved == 2 * DEPRECATED_REGISTER_SIZE) - && (offset[i] % 2 * DEPRECATED_REGISTER_SIZE)) - { - int new_offset = 0; - /* BYTES_RESERVED is already aligned to the word, so we put - the argument at one word more down the stack. - - This will leave one empty word on the stack, and one unused - register as mandated by the ABI. */ - new_offset = ((offset[i] + 2 * DEPRECATED_REGISTER_SIZE - 1) - & -(2 * DEPRECATED_REGISTER_SIZE)); - - if ((new_offset - offset[i]) >= 2 * DEPRECATED_REGISTER_SIZE) - { - bytes_reserved += DEPRECATED_REGISTER_SIZE; - offset[i] += DEPRECATED_REGISTER_SIZE; - } - } - - cum_bytes_reserved += bytes_reserved; - - } - - /* CUM_BYTES_RESERVED already accounts for all the arguments passed - by the user. However, the ABI mandates minimum stack space - allocations for outgoing arguments. - - The ABI also mandates minimum stack alignments which we must - preserve. */ - cum_bytes_aligned = DEPRECATED_STACK_ALIGN (cum_bytes_reserved); - sp += max (cum_bytes_aligned, REG_PARM_STACK_SPACE); - - /* Now write each of the args at the proper offset down the stack. - ?!? We need to promote values to a full register instead of skipping - words in the stack. */ - for (i = 0; i < nargs; i++) - write_memory (sp - offset[i], VALUE_CONTENTS (args[i]), lengths[i]); - - /* If a structure has to be returned, set up register 28 to hold its - address */ - if (struct_return) - write_register (28, struct_addr); + bizarre way in which someone (?) decided they wanted to handle + frame pointerless code in GDB. */ +int +hpread_adjust_stack_address (CORE_ADDR func_addr) +{ + struct unwind_table_entry *u; - /* The stack will have 32 bytes of additional space for a frame marker. */ - return sp + 32; + u = find_unwind_entry (func_addr); + if (!u) + return 0; + else + return u->Total_frame_size << 3; } -#endif - /* This function pushes a stack frame with arguments as part of the inferior function calling mechanism. @@ -2509,400 +1160,6 @@ cover_find_stub_with_shl_get (void *args_untyped) return 0; } -/* Insert the specified number of args and function address - into a call sequence of the above form stored at DUMMYNAME. - - On the hppa we need to call the stack dummy through $$dyncall. - Therefore our version of DEPRECATED_FIX_CALL_DUMMY takes an extra - argument, real_pc, which is the location where gdb should start up - the inferior to do the function call. - - This has to work across several versions of hpux, bsd, osf1. It has to - work regardless of what compiler was used to build the inferior program. - It should work regardless of whether or not end.o is available. It has - to work even if gdb can not call into the dynamic loader in the inferior - to query it for symbol names and addresses. - - Yes, all those cases should work. Luckily code exists to handle most - of them. The complexity is in selecting exactly what scheme should - be used to perform the inferior call. - - At the current time this routine is known not to handle cases where - the program was linked with HP's compiler without including end.o. - - Please contact Jeff Law (law@cygnus.com) before changing this code. */ - -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 dyncall_addr; - struct minimal_symbol *msymbol; - struct minimal_symbol *trampoline; - int flags = read_register (FLAGS_REGNUM); - struct unwind_table_entry *u = NULL; - CORE_ADDR new_stub = 0; - CORE_ADDR solib_handle = 0; - - /* Nonzero if we will use GCC's PLT call routine. This routine must be - passed an import stub, not a PLABEL. It is also necessary to set %r19 - (the PIC register) before performing the call. - - If zero, then we are using __d_plt_call (HP's PLT call routine) or we - are calling the target directly. When using __d_plt_call we want to - use a PLABEL instead of an import stub. */ - int using_gcc_plt_call = 1; - -#ifdef GDB_TARGET_IS_HPPA_20W - /* We currently use completely different code for the PA2.0W inferior - function call sequences. This needs to be cleaned up. */ - { - CORE_ADDR pcsqh, pcsqt, pcoqh, pcoqt, sr5; - struct target_waitstatus w; - int inst1, inst2; - char buf[4]; - int status; - struct objfile *objfile; - - /* We can not modify the PC space queues directly, so we start - up the inferior and execute a couple instructions to set the - space queues so that they point to the call dummy in the stack. */ - pcsqh = read_register (PCSQ_HEAD_REGNUM); - sr5 = read_register (SR5_REGNUM); - if (1) - { - pcoqh = read_register (PCOQ_HEAD_REGNUM); - pcoqt = read_register (PCOQ_TAIL_REGNUM); - if (target_read_memory (pcoqh, buf, 4) != 0) - error ("Couldn't modify space queue\n"); - inst1 = extract_unsigned_integer (buf, 4); - - if (target_read_memory (pcoqt, buf, 4) != 0) - error ("Couldn't modify space queue\n"); - inst2 = extract_unsigned_integer (buf, 4); - - /* BVE (r1) */ - *((int *) buf) = 0xe820d000; - if (target_write_memory (pcoqh, buf, 4) != 0) - error ("Couldn't modify space queue\n"); - - /* NOP */ - *((int *) buf) = 0x08000240; - if (target_write_memory (pcoqt, buf, 4) != 0) - { - *((int *) buf) = inst1; - target_write_memory (pcoqh, buf, 4); - error ("Couldn't modify space queue\n"); - } - - write_register (1, pc); - - /* Single step twice, the BVE instruction will set the space queue - such that it points to the PC value written immediately above - (ie the call dummy). */ - resume (1, 0); - target_wait (inferior_ptid, &w); - resume (1, 0); - target_wait (inferior_ptid, &w); - - /* Restore the two instructions at the old PC locations. */ - *((int *) buf) = inst1; - target_write_memory (pcoqh, buf, 4); - *((int *) buf) = inst2; - target_write_memory (pcoqt, buf, 4); - } - - /* The call dummy wants the ultimate destination address initially - in register %r5. */ - write_register (5, fun); - - /* We need to see if this objfile has a different DP value than our - own (it could be a shared library for example). */ - ALL_OBJFILES (objfile) - { - struct obj_section *s; - obj_private_data_t *obj_private; - - /* See if FUN is in any section within this shared library. */ - for (s = objfile->sections; s < objfile->sections_end; s++) - if (s->addr <= fun && fun < s->endaddr) - break; - - if (s >= objfile->sections_end) - continue; - - obj_private = (obj_private_data_t *) objfile->obj_private; - - /* The DP value may be different for each objfile. But within an - objfile each function uses the same dp value. Thus we do not need - to grope around the opd section looking for dp values. - - ?!? This is not strictly correct since we may be in a shared library - and want to call back into the main program. To make that case - work correctly we need to set obj_private->dp for the main program's - objfile, then remove this conditional. */ - if (obj_private->dp) - write_register (27, obj_private->dp); - break; - } - return pc; - } -#endif - -#ifndef GDB_TARGET_IS_HPPA_20W - /* Prefer __gcc_plt_call over the HP supplied routine because - __gcc_plt_call works for any number of arguments. */ - trampoline = NULL; - if (lookup_minimal_symbol ("__gcc_plt_call", NULL, NULL) == NULL) - using_gcc_plt_call = 0; - - msymbol = lookup_minimal_symbol ("$$dyncall", NULL, NULL); - if (msymbol == NULL) - error ("Can't find an address for $$dyncall trampoline"); - - dyncall_addr = SYMBOL_VALUE_ADDRESS (msymbol); - - /* FUN could be a procedure label, in which case we have to get - its real address and the value of its GOT/DP if we plan to - call the routine via gcc_plt_call. */ - if ((fun & 0x2) && using_gcc_plt_call) - { - /* Get the GOT/DP value for the target function. It's - at *(fun+4). Note the call dummy is *NOT* allowed to - trash %r19 before calling the target function. */ - write_register (19, read_memory_integer ((fun & ~0x3) + 4, - DEPRECATED_REGISTER_SIZE)); - - /* Now get the real address for the function we are calling, it's - at *fun. */ - fun = (CORE_ADDR) read_memory_integer (fun & ~0x3, - TARGET_PTR_BIT / 8); - } - else - { - -#ifndef GDB_TARGET_IS_PA_ELF - /* FUN could be an export stub, the real address of a function, or - a PLABEL. When using gcc's PLT call routine we must call an import - 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 - get the import stub for the target function. */ - if (using_gcc_plt_call && som_solib_get_got_by_pc (fun)) - { - struct objfile *objfile; - struct minimal_symbol *funsymbol, *stub_symbol; - CORE_ADDR newfun = 0; - - funsymbol = lookup_minimal_symbol_by_pc (fun); - if (!funsymbol) - error ("Unable to find minimal symbol for target function.\n"); - - /* Search all the object files for an import symbol with the - right name. */ - ALL_OBJFILES (objfile) - { - stub_symbol - = lookup_minimal_symbol_solib_trampoline - (DEPRECATED_SYMBOL_NAME (funsymbol), objfile); - - if (!stub_symbol) - stub_symbol = lookup_minimal_symbol (DEPRECATED_SYMBOL_NAME (funsymbol), - NULL, objfile); - - /* Found a symbol with the right name. */ - if (stub_symbol) - { - struct unwind_table_entry *u; - /* It must be a shared library trampoline. */ - if (MSYMBOL_TYPE (stub_symbol) != mst_solib_trampoline) - continue; - - /* It must also be an import stub. */ - u = find_unwind_entry (SYMBOL_VALUE (stub_symbol)); - if (u == NULL - || (u->stub_unwind.stub_type != IMPORT -#ifdef GDB_NATIVE_HPUX_11 - /* Sigh. The hpux 10.20 dynamic linker will blow - chunks if we perform a call to an unbound function - via the IMPORT_SHLIB stub. The hpux 11.00 dynamic - linker will blow chunks if we do not call the - unbound function via the IMPORT_SHLIB stub. - - We currently have no way to select bevahior on just - the target. However, we only support HPUX/SOM in - native mode. So we conditinalize on a native - #ifdef. Ugly. Ugly. Ugly */ - && u->stub_unwind.stub_type != IMPORT_SHLIB -#endif - )) - continue; - - /* OK. Looks like the correct import stub. */ - newfun = SYMBOL_VALUE (stub_symbol); - fun = newfun; - - /* If we found an IMPORT stub, then we want to stop - searching now. If we found an IMPORT_SHLIB, we want - to continue the search in the hopes that we will find - an IMPORT stub. */ - if (u->stub_unwind.stub_type == IMPORT) - break; - } - } - - /* Ouch. We did not find an import stub. Make an attempt to - do the right thing instead of just croaking. Most of the - time this will actually work. */ - if (newfun == 0) - write_register (19, som_solib_get_got_by_pc (fun)); - - u = find_unwind_entry (fun); - if (u - && (u->stub_unwind.stub_type == IMPORT - || u->stub_unwind.stub_type == IMPORT_SHLIB)) - trampoline = lookup_minimal_symbol ("__gcc_plt_call", NULL, NULL); - - /* If we found the import stub in the shared library, then we have - to set %r19 before we call the stub. */ - if (u && u->stub_unwind.stub_type == IMPORT_SHLIB) - write_register (19, som_solib_get_got_by_pc (fun)); - } -#endif - } - - /* If we are calling into another load module then have sr4export call the - magic __d_plt_call routine which is linked in from end.o. - - You can't use _sr4export to make the call as the value in sp-24 will get - fried and you end up returning to the wrong location. You can't call the - target as the code to bind the PLT entry to a function can't return to a - stack address. - - Also, query the dynamic linker in the inferior to provide a suitable - PLABEL for the target function. */ - if (!using_gcc_plt_call) - { - CORE_ADDR new_fun; - - /* Get a handle for the shared library containing FUN. Given the - handle we can query the shared library for a PLABEL. */ - solib_handle = som_solib_get_solib_by_pc (fun); - - if (solib_handle) - { - struct minimal_symbol *fmsymbol = lookup_minimal_symbol_by_pc (fun); - - trampoline = lookup_minimal_symbol ("__d_plt_call", NULL, NULL); - - if (trampoline == NULL) - { - error ("Can't find an address for __d_plt_call or __gcc_plt_call trampoline\nSuggest linking executable with -g or compiling with gcc."); - } - - /* This is where sr4export will jump to. */ - new_fun = SYMBOL_VALUE_ADDRESS (trampoline); - - /* If the function is in a shared library, then call __d_shl_get to - get a PLABEL for the target function. */ - new_stub = find_stub_with_shl_get (fmsymbol, solib_handle); - - if (new_stub == 0) - error ("Can't find an import stub for %s", DEPRECATED_SYMBOL_NAME (fmsymbol)); - - /* We have to store the address of the stub in __shlib_funcptr. */ - msymbol = lookup_minimal_symbol ("__shlib_funcptr", NULL, - (struct objfile *) NULL); - - if (msymbol == NULL) - error ("Can't find an address for __shlib_funcptr"); - target_write_memory (SYMBOL_VALUE_ADDRESS (msymbol), - (char *) &new_stub, 4); - - /* We want sr4export to call __d_plt_call, so we claim it is - the final target. Clear trampoline. */ - fun = new_fun; - trampoline = NULL; - } - } - - /* Store upper 21 bits of function address into ldil. fun will either be - the final target (most cases) or __d_plt_call when calling into a shared - library and __gcc_plt_call is not available. */ - store_unsigned_integer - (&dummy[FUNC_LDIL_OFFSET], - INSTRUCTION_SIZE, - deposit_21 (fun >> 11, - extract_unsigned_integer (&dummy[FUNC_LDIL_OFFSET], - INSTRUCTION_SIZE))); - - /* Store lower 11 bits of function address into ldo */ - store_unsigned_integer - (&dummy[FUNC_LDO_OFFSET], - INSTRUCTION_SIZE, - deposit_14 (fun & MASK_11, - extract_unsigned_integer (&dummy[FUNC_LDO_OFFSET], - INSTRUCTION_SIZE))); -#ifdef SR4EXPORT_LDIL_OFFSET - - { - CORE_ADDR trampoline_addr; - - /* We may still need sr4export's address too. */ - - if (trampoline == NULL) - { - msymbol = lookup_minimal_symbol ("_sr4export", NULL, NULL); - if (msymbol == NULL) - error ("Can't find an address for _sr4export trampoline"); - - trampoline_addr = SYMBOL_VALUE_ADDRESS (msymbol); - } - else - trampoline_addr = SYMBOL_VALUE_ADDRESS (trampoline); - - - /* Store upper 21 bits of trampoline's address into ldil */ - store_unsigned_integer - (&dummy[SR4EXPORT_LDIL_OFFSET], - INSTRUCTION_SIZE, - deposit_21 (trampoline_addr >> 11, - extract_unsigned_integer (&dummy[SR4EXPORT_LDIL_OFFSET], - INSTRUCTION_SIZE))); - - /* Store lower 11 bits of trampoline's address into ldo */ - store_unsigned_integer - (&dummy[SR4EXPORT_LDO_OFFSET], - INSTRUCTION_SIZE, - deposit_14 (trampoline_addr & MASK_11, - extract_unsigned_integer (&dummy[SR4EXPORT_LDO_OFFSET], - INSTRUCTION_SIZE))); - } -#endif - - write_register (22, pc); - - /* If we are in a syscall, then we should call the stack dummy - directly. $$dyncall is not needed as the kernel sets up the - space id registers properly based on the value in %r31. In - fact calling $$dyncall will not work because the value in %r22 - will be clobbered on the syscall exit path. - - Similarly if the current PC is in a shared library. Note however, - this scheme won't work if the shared library isn't mapped into - the same space as the stack. */ - if (flags & 2) - return pc; -#ifndef GDB_TARGET_IS_PA_ELF - else if (som_solib_get_got_by_pc (hppa_target_read_pc (inferior_ptid))) - return pc; -#endif - else - return dyncall_addr; -#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. */ @@ -4331,262 +2588,6 @@ hppa_skip_prologue (CORE_ADDR pc) return (skip_prologue_hard_way (pc)); } -/* Put here the code to store, into the SAVED_REGS, the addresses of - the saved registers of frame described by FRAME_INFO. This - includes special registers such as pc and fp saved in special ways - in the stack frame. sp is even more special: the address we return - for it IS the sp for the next frame. */ - -void -hppa_frame_find_saved_regs (struct frame_info *frame_info, - CORE_ADDR frame_saved_regs[]) -{ - CORE_ADDR pc; - struct unwind_table_entry *u; - unsigned long inst, stack_remaining, save_gr, save_fr, save_rp, save_sp; - int status, i, reg; - char buf[4]; - int fp_loc = -1; - int final_iteration; - - /* Zero out everything. */ - memset (frame_saved_regs, '\0', SIZEOF_FRAME_SAVED_REGS); - - /* Call dummy frames always look the same, so there's no need to - examine the dummy code to determine locations of saved registers; - instead, let find_dummy_frame_regs fill in the correct offsets - for the saved registers. */ - if ((get_frame_pc (frame_info) >= get_frame_base (frame_info) - && (get_frame_pc (frame_info) - <= (get_frame_base (frame_info) - /* A call dummy is sized in words, but it is actually a - series of instructions. Account for that scaling - factor. */ - + ((DEPRECATED_REGISTER_SIZE / INSTRUCTION_SIZE) - * DEPRECATED_CALL_DUMMY_LENGTH) - /* Similarly we have to account for 64bit wide register - saves. */ - + (32 * DEPRECATED_REGISTER_SIZE) - /* We always consider FP regs 8 bytes long. */ - + (NUM_REGS - FP0_REGNUM) * 8 - /* Similarly we have to account for 64bit wide register - saves. */ - + (6 * DEPRECATED_REGISTER_SIZE))))) - find_dummy_frame_regs (frame_info, frame_saved_regs); - - /* Interrupt handlers are special too. They lay out the register - state in the exact same order as the register numbers in GDB. */ - if (pc_in_interrupt_handler (get_frame_pc (frame_info))) - { - for (i = 0; i < NUM_REGS; i++) - { - /* SP is a little special. */ - if (i == SP_REGNUM) - frame_saved_regs[SP_REGNUM] - = read_memory_integer (get_frame_base (frame_info) + SP_REGNUM * 4, - TARGET_PTR_BIT / 8); - else - frame_saved_regs[i] = get_frame_base (frame_info) + i * 4; - } - return; - } - -#ifdef FRAME_FIND_SAVED_REGS_IN_SIGTRAMP - /* Handle signal handler callers. */ - if ((get_frame_type (frame_info) == SIGTRAMP_FRAME)) - { - FRAME_FIND_SAVED_REGS_IN_SIGTRAMP (frame_info, frame_saved_regs); - return; - } -#endif - - /* Get the starting address of the function referred to by the PC - saved in frame. */ - pc = get_frame_func (frame_info); - - /* Yow! */ - u = find_unwind_entry (pc); - if (!u) - return; - - /* This is how much of a frame adjustment we need to account for. */ - stack_remaining = u->Total_frame_size << 3; - - /* Magic register saves we want to know about. */ - save_rp = u->Save_RP; - save_sp = u->Save_SP; - - /* Turn the Entry_GR field into a bitmask. */ - save_gr = 0; - for (i = 3; i < u->Entry_GR + 3; i++) - { - /* Frame pointer gets saved into a special location. */ - if (u->Save_SP && i == DEPRECATED_FP_REGNUM) - continue; - - save_gr |= (1 << i); - } - - /* Turn the Entry_FR field into a bitmask too. */ - save_fr = 0; - for (i = 12; i < u->Entry_FR + 12; i++) - save_fr |= (1 << i); - - /* The frame always represents the value of %sp at entry to the - current function (and is thus equivalent to the "saved" stack - pointer. */ - frame_saved_regs[SP_REGNUM] = get_frame_base (frame_info); - - /* Loop until we find everything of interest or hit a branch. - - For unoptimized GCC code and for any HP CC code this will never ever - examine any user instructions. - - For optimized GCC code we're faced with problems. GCC will schedule - its prologue and make prologue instructions available for delay slot - filling. The end result is user code gets mixed in with the prologue - and a prologue instruction may be in the delay slot of the first branch - or call. - - Some unexpected things are expected with debugging optimized code, so - we allow this routine to walk past user instructions in optimized - GCC code. */ - final_iteration = 0; - while ((save_gr || save_fr || save_rp || save_sp || stack_remaining > 0) - && pc <= get_frame_pc (frame_info)) - { - status = target_read_memory (pc, buf, 4); - inst = extract_unsigned_integer (buf, 4); - - /* Yow! */ - if (status != 0) - return; - - /* Note the interesting effects of this instruction. */ - stack_remaining -= prologue_inst_adjust_sp (inst); - - /* There are limited ways to store the return pointer into the - stack. */ - if (inst == 0x6bc23fd9) /* stw rp,-0x14(sr0,sp) */ - { - save_rp = 0; - frame_saved_regs[RP_REGNUM] = get_frame_base (frame_info) - 20; - } - else if (inst == 0x0fc212c1) /* std rp,-0x10(sr0,sp) */ - { - save_rp = 0; - frame_saved_regs[RP_REGNUM] = get_frame_base (frame_info) - 16; - } - - /* Note if we saved SP into the stack. This also happens to indicate - the location of the saved frame pointer. */ - if ( (inst & 0xffffc000) == 0x6fc10000 /* stw,ma r1,N(sr0,sp) */ - || (inst & 0xffffc00c) == 0x73c10008) /* std,ma r1,N(sr0,sp) */ - { - frame_saved_regs[DEPRECATED_FP_REGNUM] = get_frame_base (frame_info); - save_sp = 0; - } - - /* Account for general and floating-point register saves. */ - reg = inst_saves_gr (inst); - if (reg >= 3 && reg <= 18 - && (!u->Save_SP || reg != DEPRECATED_FP_REGNUM)) - { - save_gr &= ~(1 << reg); - - /* stwm with a positive displacement is a *post modify*. */ - if ((inst >> 26) == 0x1b - && extract_14 (inst) >= 0) - frame_saved_regs[reg] = get_frame_base (frame_info); - /* A std has explicit post_modify forms. */ - else if ((inst & 0xfc00000c) == 0x70000008) - frame_saved_regs[reg] = get_frame_base (frame_info); - else - { - CORE_ADDR offset; - - if ((inst >> 26) == 0x1c) - offset = (inst & 0x1 ? -1 << 13 : 0) | (((inst >> 4) & 0x3ff) << 3); - else if ((inst >> 26) == 0x03) - offset = low_sign_extend (inst & 0x1f, 5); - else - offset = extract_14 (inst); - - /* Handle code with and without frame pointers. */ - if (u->Save_SP) - frame_saved_regs[reg] - = get_frame_base (frame_info) + offset; - else - frame_saved_regs[reg] - = (get_frame_base (frame_info) + (u->Total_frame_size << 3) - + offset); - } - } - - - /* GCC handles callee saved FP regs a little differently. - - It emits an instruction to put the value of the start of - the FP store area into %r1. It then uses fstds,ma with - a basereg of %r1 for the stores. - - HP CC emits them at the current stack pointer modifying - the stack pointer as it stores each register. */ - - /* ldo X(%r3),%r1 or ldo X(%r30),%r1. */ - if ((inst & 0xffffc000) == 0x34610000 - || (inst & 0xffffc000) == 0x37c10000) - fp_loc = extract_14 (inst); - - reg = inst_saves_fr (inst); - if (reg >= 12 && reg <= 21) - { - /* Note +4 braindamage below is necessary because the FP status - registers are internally 8 registers rather than the expected - 4 registers. */ - save_fr &= ~(1 << reg); - if (fp_loc == -1) - { - /* 1st HP CC FP register store. After this instruction - we've set enough state that the GCC and HPCC code are - both handled in the same manner. */ - frame_saved_regs[reg + FP4_REGNUM + 4] = get_frame_base (frame_info); - fp_loc = 8; - } - else - { - frame_saved_regs[reg + FP0_REGNUM + 4] - = get_frame_base (frame_info) + fp_loc; - fp_loc += 8; - } - } - - /* Quit if we hit any kind of branch the previous iteration. */ - if (final_iteration) - break; - - /* We want to look precisely one instruction beyond the branch - if we have not found everything yet. */ - if (is_branch (inst)) - final_iteration = 1; - - /* Bump the PC. */ - pc += 4; - } -} - -/* XXX - deprecated. This is a compatibility function for targets - that do not yet implement DEPRECATED_FRAME_INIT_SAVED_REGS. */ -/* Find the addresses in which registers are saved in FRAME. */ - -static void -hppa_frame_init_saved_regs (struct frame_info *frame) -{ - if (deprecated_get_frame_saved_regs (frame) == NULL) - frame_saved_regs_zalloc (frame); - hppa_frame_find_saved_regs (frame, deprecated_get_frame_saved_regs (frame)); -} - struct hppa_frame_cache { CORE_ADDR base; @@ -5458,62 +3459,6 @@ hppa_skip_permanent_breakpoint (void) /* We can leave the tail's space the same, since there's no jump. */ } -/* Same as hppa32_store_return_value(), but for the PA64 ABI. */ - -void -hppa64_store_return_value (struct type *type, char *valbuf) -{ - if (TYPE_CODE (type) == TYPE_CODE_FLT) - deprecated_write_register_bytes - (DEPRECATED_REGISTER_BYTE (FP4_REGNUM) - + DEPRECATED_REGISTER_SIZE - TYPE_LENGTH (type), - valbuf, TYPE_LENGTH (type)); - else if (is_integral_type(type)) - deprecated_write_register_bytes - (DEPRECATED_REGISTER_BYTE (28) - + DEPRECATED_REGISTER_SIZE - TYPE_LENGTH (type), - valbuf, TYPE_LENGTH (type)); - else if (TYPE_LENGTH (type) <= 8) - deprecated_write_register_bytes - (DEPRECATED_REGISTER_BYTE (28),valbuf, TYPE_LENGTH (type)); - else if (TYPE_LENGTH (type) <= 16) - { - deprecated_write_register_bytes (DEPRECATED_REGISTER_BYTE (28),valbuf, 8); - deprecated_write_register_bytes - (DEPRECATED_REGISTER_BYTE (29), valbuf + 8, TYPE_LENGTH (type) - 8); - } -} - -/* Same as hppa32_extract_return_value but for the PA64 ABI case. */ - -void -hppa64_extract_return_value (struct type *type, char *regbuf, char *valbuf) -{ - /* RM: Floats are returned in FR4R, doubles in FR4. - Integral values are in r28, padded on the left. - Aggregates less that 65 bits are in r28, right padded. - Aggregates upto 128 bits are in r28 and r29, right padded. */ - if (TYPE_CODE (type) == TYPE_CODE_FLT) - memcpy (valbuf, - regbuf + DEPRECATED_REGISTER_BYTE (FP4_REGNUM) - + DEPRECATED_REGISTER_SIZE - TYPE_LENGTH (type), - TYPE_LENGTH (type)); - else if (is_integral_type(type)) - memcpy (valbuf, - regbuf + DEPRECATED_REGISTER_BYTE (28) - + DEPRECATED_REGISTER_SIZE - TYPE_LENGTH (type), - TYPE_LENGTH (type)); - else if (TYPE_LENGTH (type) <= 8) - memcpy (valbuf, regbuf + DEPRECATED_REGISTER_BYTE (28), - TYPE_LENGTH (type)); - else if (TYPE_LENGTH (type) <= 16) - { - memcpy (valbuf, regbuf + DEPRECATED_REGISTER_BYTE (28), 8); - memcpy (valbuf + 8, regbuf + DEPRECATED_REGISTER_BYTE (29), - TYPE_LENGTH (type) - 8); - } -} - int hppa_reg_struct_has_addr (int gcc_p, struct type *type) { @@ -5529,13 +3474,6 @@ hppa_inner_than (CORE_ADDR lhs, CORE_ADDR rhs) return (lhs > rhs); } -CORE_ADDR -hppa64_stack_align (CORE_ADDR sp) -{ - /* The PA64 ABI mandates a 16 byte stack alignment. */ - return ((sp % 16) ? (sp + 15) & -16 : sp); -} - int hppa_pc_requires_run_before_use (CORE_ADDR pc) { @@ -5618,14 +3556,6 @@ hppa64_register_virtual_type (int reg_nr) return builtin_type_double; } -/* 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(). */ diff --git a/gdb/infcall.c b/gdb/infcall.c index 11ce018087c..b10f8071daf 100644 --- a/gdb/infcall.c +++ b/gdb/infcall.c @@ -277,10 +277,6 @@ legacy_push_dummy_code (struct gdbarch *gdbarch, (PUSH_DUMMY_BREAKPOINT?) should just do everything. */ if (!gdbarch_push_dummy_call_p (current_gdbarch)) { -#ifdef GDB_TARGET_IS_HPPA - (*real_pc) = DEPRECATED_FIX_CALL_DUMMY (dummy1, start_sp, funaddr, nargs, - args, value_type, using_gcc); -#else if (DEPRECATED_FIX_CALL_DUMMY_P ()) { /* gdb_assert (CALL_DUMMY_LOCATION == ON_STACK) true? */ @@ -288,7 +284,6 @@ legacy_push_dummy_code (struct gdbarch *gdbarch, value_type, using_gcc); } (*real_pc) = start_sp; -#endif } /* Yes, the offset is applied to the real_pc and not the dummy addr. Ulgh! Blame the HP/UX target. */ -- 2.30.2