X-Git-Url: https://repo.jachan.dev/binutils.git/blobdiff_plain/dd99f8e4b2fba127ae6b01a832094d5d0ec6cb03..54eacbe683ddaa9c5ba6a3ab576d21344bf16802:/gdb/sparc-tdep.c diff --git a/gdb/sparc-tdep.c b/gdb/sparc-tdep.c index 5bfd263b5b..060d29a498 100644 --- a/gdb/sparc-tdep.c +++ b/gdb/sparc-tdep.c @@ -1,5 +1,6 @@ /* Target-dependent code for the SPARC for GDB, the GNU debugger. - Copyright 1986, 1987, 1989, 1991, 1992, 1993 Free Software Foundation, Inc. + Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994 + Free Software Foundation, Inc. This file is part of GDB. @@ -22,7 +23,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "inferior.h" #include "obstack.h" #include "target.h" -#include "ieee-float.h" +#include "value.h" #include "symfile.h" /* for objfiles.h */ #include "objfiles.h" /* for find_pc_section */ @@ -89,7 +90,7 @@ single_step (ignore) npc4 = next_pc + 4; /* branch not taken */ target_insert_breakpoint (next_pc, break_mem[0]); - /* printf ("set break at %x\n",next_pc); */ + /* printf_unfiltered ("set break at %x\n",next_pc); */ pc = read_register (PC_REGNUM); pc_instruction = read_memory_integer (pc, sizeof(pc_instruction)); @@ -131,58 +132,75 @@ single_step (ignore) } } -#define FRAME_SAVED_L0 0 /* Byte offset from SP */ -#define FRAME_SAVED_I0 (8 * REGISTER_RAW_SIZE (0)) /* Byte offset from SP */ - CORE_ADDR sparc_frame_chain (thisframe) FRAME thisframe; { - REGISTER_TYPE retval; + char buf[MAX_REGISTER_RAW_SIZE]; int err; CORE_ADDR addr; addr = thisframe->frame + FRAME_SAVED_I0 + REGISTER_RAW_SIZE (FP_REGNUM) * (FP_REGNUM - I0_REGNUM); - err = target_read_memory (addr, (char *) &retval, sizeof (REGISTER_TYPE)); + err = target_read_memory (addr, buf, REGISTER_RAW_SIZE (FP_REGNUM)); if (err) return 0; - SWAP_TARGET_AND_HOST (&retval, sizeof (retval)); - return retval; + return extract_address (buf, REGISTER_RAW_SIZE (FP_REGNUM)); } CORE_ADDR sparc_extract_struct_value_address (regbuf) char regbuf[REGISTER_BYTES]; { - /* FIXME, handle byte swapping */ return read_memory_integer (((int *)(regbuf))[SP_REGNUM]+(16*4), - sizeof (CORE_ADDR)); + TARGET_PTR_BIT / TARGET_CHAR_BIT); } /* Find the pc saved in frame FRAME. */ CORE_ADDR -frame_saved_pc (frame) +sparc_frame_saved_pc (frame) FRAME frame; { - REGISTER_TYPE retval; - CORE_ADDR addr,prev_pc; + char buf[MAX_REGISTER_RAW_SIZE]; + CORE_ADDR addr; - if (get_current_frame () == frame) /* FIXME, debug check. Remove >=gdb-4.6 */ + if (frame->signal_handler_caller) { - if (read_register (SP_REGNUM) != frame->bottom) abort(); - } + /* This is the signal trampoline frame. + Get the saved PC from the sigcontext structure. */ + +#ifndef SIGCONTEXT_PC_OFFSET +#define SIGCONTEXT_PC_OFFSET 12 +#endif + CORE_ADDR sigcontext_addr; + char scbuf[TARGET_PTR_BIT / HOST_CHAR_BIT]; + int saved_pc_offset = SIGCONTEXT_PC_OFFSET; + char *name = NULL; + + /* Solaris2 ucbsigvechandler passes a pointer to a sigcontext + as the third parameter. The offset to the saved pc is 12. */ + find_pc_partial_function (frame->pc, &name, + (CORE_ADDR *)NULL,(CORE_ADDR *)NULL); + if (name && STREQ (name, "ucbsigvechandler")) + saved_pc_offset = 12; + + /* The sigcontext address is contained in register O2. */ + get_saved_register (buf, (int *)NULL, (CORE_ADDR *)NULL, + frame, O0_REGNUM + 2, (enum lval_type *)NULL); + sigcontext_addr = extract_address (buf, REGISTER_RAW_SIZE (O0_REGNUM)); + + /* Don't cause a memory_error when accessing sigcontext in case the + stack layout has changed or the stack is corrupt. */ + target_read_memory (sigcontext_addr + saved_pc_offset, + scbuf, sizeof (scbuf)); + return extract_address (scbuf, sizeof (scbuf)); + } addr = (frame->bottom + FRAME_SAVED_I0 + REGISTER_RAW_SIZE (I7_REGNUM) * (I7_REGNUM - I0_REGNUM)); - read_memory (addr, (char *) &retval, sizeof (REGISTER_TYPE)); - SWAP_TARGET_AND_HOST (&retval, sizeof (retval)); - - /* CORE_ADDR isn't always the same size as REGISTER_TYPE, so convert. */ - - prev_pc = (CORE_ADDR) retval; - return PC_ADJUST (prev_pc); + read_memory (addr, buf, REGISTER_RAW_SIZE (I7_REGNUM)); + return PC_ADJUST (extract_address (buf, REGISTER_RAW_SIZE (I7_REGNUM))); } /* @@ -380,7 +398,7 @@ sparc_frame_find_saved_regs (fi, saved_regs_addr) struct frame_saved_regs *saved_regs_addr; { register int regnum; - FRAME_ADDR frame = read_register (FP_REGNUM); + FRAME_ADDR frame = FRAME_FP(fi); FRAME fid = FRAME_INFO_ID (fi); if (!fid) @@ -388,10 +406,6 @@ sparc_frame_find_saved_regs (fi, saved_regs_addr) memset (saved_regs_addr, 0, sizeof (*saved_regs_addr)); - /* Old test. - if (fi->pc >= frame - CALL_DUMMY_LENGTH - 0x140 - && fi->pc <= frame) */ - if (fi->pc >= (fi->bottom ? fi->bottom : read_register (SP_REGNUM)) && fi->pc <= FRAME_FP(fi)) @@ -438,57 +452,41 @@ sparc_frame_find_saved_regs (fi, saved_regs_addr) We save the non-windowed registers and the ins. The locals and outs are new; they don't need to be saved. The i's and l's of - the last frame were already saved on the stack - - The return pointer register %i7 does not have the pc saved into it - (return from this frame will be accomplished by a POP_FRAME). In - fact, we must leave it unclobbered, since we must preserve it in - the calling routine except across call instructions. I'm not sure - the preceding sentence is true; isn't it based on confusing the %i7 - saved in the dummy frame versus the one saved in the frame of the - calling routine? */ + the last frame were already saved on the stack. */ /* Definitely see tm-sparc.h for more doc of the frame format here. */ void sparc_push_dummy_frame () { - CORE_ADDR sp; - char register_temp[REGISTER_BYTES]; + CORE_ADDR sp, old_sp; + char register_temp[0x140]; - sp = read_register (SP_REGNUM); + old_sp = sp = read_register (SP_REGNUM); - read_register_bytes (REGISTER_BYTE (FP0_REGNUM), register_temp, - REGISTER_RAW_SIZE (FP0_REGNUM) * 32); - write_memory (sp - 0x80, register_temp, REGISTER_RAW_SIZE (FP0_REGNUM) * 32); + /* Y, PS, WIM, TBR, PC, NPC, FPS, CPS regs */ + read_register_bytes (REGISTER_BYTE (Y_REGNUM), ®ister_temp[0], + REGISTER_RAW_SIZE (Y_REGNUM) * 8); + + read_register_bytes (REGISTER_BYTE (O0_REGNUM), ®ister_temp[8 * 4], + REGISTER_RAW_SIZE (O0_REGNUM) * 8); - read_register_bytes (REGISTER_BYTE (G0_REGNUM), register_temp, + read_register_bytes (REGISTER_BYTE (G0_REGNUM), ®ister_temp[16 * 4], REGISTER_RAW_SIZE (G0_REGNUM) * 8); - write_memory (sp - 0xa0, register_temp, REGISTER_RAW_SIZE (G0_REGNUM) * 8); - read_register_bytes (REGISTER_BYTE (O0_REGNUM), register_temp, - REGISTER_RAW_SIZE (O0_REGNUM) * 8); - write_memory (sp - 0xc0, register_temp, REGISTER_RAW_SIZE (O0_REGNUM) * 8); + read_register_bytes (REGISTER_BYTE (FP0_REGNUM), ®ister_temp[24 * 4], + REGISTER_RAW_SIZE (FP0_REGNUM) * 32); - /* Y, PS, WIM, TBR, PC, NPC, FPS, CPS regs */ - read_register_bytes (REGISTER_BYTE (Y_REGNUM), register_temp, - REGISTER_RAW_SIZE (Y_REGNUM) * 8); - write_memory (sp - 0xe0, register_temp, REGISTER_RAW_SIZE (Y_REGNUM) * 8); - - { - CORE_ADDR old_sp = sp; - - /* Now move the stack pointer (equivalent to the add part of a save - instruction). */ - sp -= 0x140; - write_register (SP_REGNUM, sp); - - /* Now make sure that the frame pointer we save in the new frame points - to the old frame (equivalent to the register window shift part of - a save instruction). Need to do this after the write to the sp, or - else this might get written into the wrong set of saved ins&locals. */ - write_register (FP_REGNUM, old_sp); - } + sp -= 0x140; + + write_register (SP_REGNUM, sp); + + write_memory (sp + 0x60, ®ister_temp[0], (8 + 8 + 8 + 32) * 4); + + write_register (FP_REGNUM, old_sp); + + /* Set return address register for the call dummy to the current PC. */ + write_register (I7_REGNUM, read_pc() - 8); } /* Discard from the stack the innermost frame, restoring all saved registers. @@ -521,6 +519,16 @@ sparc_pop_frame () read_memory (fsr.regs[FP0_REGNUM], raw_buffer, 32 * 4); write_register_bytes (REGISTER_BYTE (FP0_REGNUM), raw_buffer, 32 * 4); } + if (fsr.regs[FPS_REGNUM]) + { + read_memory (fsr.regs[FPS_REGNUM], raw_buffer, 4); + write_register_bytes (REGISTER_BYTE (FPS_REGNUM), raw_buffer, 4); + } + if (fsr.regs[CPS_REGNUM]) + { + read_memory (fsr.regs[CPS_REGNUM], raw_buffer, 4); + write_register_bytes (REGISTER_BYTE (CPS_REGNUM), raw_buffer, 4); + } if (fsr.regs[G1_REGNUM]) { read_memory (fsr.regs[G1_REGNUM], raw_buffer, 7 * 4); @@ -582,26 +590,17 @@ CORE_ADDR sparc_pc_adjust(pc) CORE_ADDR pc; { - long insn; + unsigned long insn; + char buf[4]; int err; - err = target_read_memory (pc + 8, (char *)&insn, sizeof(long)); - SWAP_TARGET_AND_HOST (&insn, sizeof(long)); + err = target_read_memory (pc + 8, buf, sizeof(long)); + insn = extract_unsigned_integer (buf, 4); if ((err == 0) && (insn & 0xfffffe00) == 0) return pc+12; else return pc+8; } - - -/* Structure of SPARC extended floating point numbers. - This information is not currently used by GDB, since no current SPARC - implementations support extended float. */ - -const struct ext_format ext_format_sparc = { -/* tot sbyte smask expbyte manbyte */ - 16, 0, 0x80, 0,1, 4,8, /* sparc */ -}; #ifdef USE_PROC_FS /* Target dependent support for /proc */ @@ -769,14 +768,16 @@ get_longjmp_target(pc) CORE_ADDR *pc; { CORE_ADDR jb_addr; +#define LONGJMP_TARGET_SIZE 4 + char buf[LONGJMP_TARGET_SIZE]; jb_addr = read_register(O0_REGNUM); - if (target_read_memory(jb_addr + JB_PC * JB_ELEMENT_SIZE, (char *) pc, - sizeof(CORE_ADDR))) + if (target_read_memory(jb_addr + JB_PC * JB_ELEMENT_SIZE, buf, + LONGJMP_TARGET_SIZE)) return 0; - SWAP_TARGET_AND_HOST(pc, sizeof(CORE_ADDR)); + *pc = extract_address (buf, LONGJMP_TARGET_SIZE); return 1; } @@ -797,8 +798,8 @@ in_solib_trampoline(pc, name) s = find_pc_section(pc); retval = (s != NULL - && s->sec_ptr->name != NULL - && STREQ (s->sec_ptr->name, ".plt")); + && s->the_bfd_section->name != NULL + && STREQ (s->the_bfd_section->name, ".plt")); return(retval); }