From e50f526e68f36447f1e99fcfa79125b60a6b1a97 Mon Sep 17 00:00:00 2001 From: Mark Alexander Date: Wed, 15 Apr 1998 00:25:58 +0000 Subject: [PATCH] * sparc-tdep.c (sparc_extract_struct_value_address): Make it work correctly on little-endian hosts. (sparc_push_arguments): New function. (gdb_print_insn_sparc): New function. (_initialize_sparc_tdep): Make gdb_print_insn_sparc the default disassembler, so that SPARClite-specific instructions will be recognized. * sparcl-tdep.c (readchar): Print debugging information. (debug_serial_write): New function, a replacement for SERIAL_WRITE that prints debugging information. * config/sparc/tm-sparc.h (PUSH_ARGUMENTS): Define. (sparc_push_arguments): Declare. --- gdb/ChangeLog | 16 +++- gdb/config/sparc/tm-sparc.h | 14 +++- gdb/sparc-tdep.c | 162 ++++++++++++++++++++++++++++++------ gdb/sparcl-tdep.c | 33 +++++++- 4 files changed, 194 insertions(+), 31 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index adb74e2431..fd25765bd0 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,18 @@ +Tue Apr 14 16:52:59 1998 Mark Alexander + + * sparc-tdep.c (sparc_extract_struct_value_address): Make it + work correctly on little-endian hosts. + (sparc_push_arguments): New function. + (gdb_print_insn_sparc): New function. + (_initialize_sparc_tdep): Make gdb_print_insn_sparc the default + disassembler, so that SPARClite-specific instructions will + be recognized. + * sparcl-tdep.c (readchar): Print debugging information. + (debug_serial_write): New function, a replacement for SERIAL_WRITE + that prints debugging information. + * config/sparc/tm-sparc.h (PUSH_ARGUMENTS): Define. + (sparc_push_arguments): Declare. + Tue Apr 14 15:43:49 1998 John Metzler * gdbcfgxref (xref_menu): Call new regex and wild card searches @@ -95,7 +110,6 @@ Wed Apr 8 16:47:33 1998 Jason Molenda (crash@bugshack.cygnus.com) * breakpoint.c (breakpoint_re_set_one): Remove Ulrich Drepper's patch of March 23 1998. ->>>>>>> 1.4385 Sat Apr 4 10:05:00 1998 Dawn Perchik * mdebugread.c (parse_partial_symbols): If this is an .mdebug diff --git a/gdb/config/sparc/tm-sparc.h b/gdb/config/sparc/tm-sparc.h index 2bbda589d8..96b25504cb 100644 --- a/gdb/config/sparc/tm-sparc.h +++ b/gdb/config/sparc/tm-sparc.h @@ -245,7 +245,7 @@ extern CORE_ADDR sparc_pc_adjust PARAMS ((CORE_ADDR)); #define CANNOT_STORE_REGISTER(regno) ((regno) == G0_REGNUM) /* Store the address of the place in which to copy the structure the - subroutine will return. This is called from call_function. */ + subroutine will return. This is called from call_function_by_hand. */ #define STORE_STRUCT_RETURN(ADDR, SP) \ { char val[4]; \ @@ -648,3 +648,15 @@ extern int deferred_stores; /* Select the sparc disassembler */ #define TM_PRINT_INSN_MACH bfd_mach_sparc + +/* Arguments smaller than an int must promoted to ints when synthesizing + function calls. */ + +#ifdef __STDC__ +struct value; +#endif + +#define PUSH_ARGUMENTS(nargs, args, sp, struct_return, struct_addr) \ + sp = sparc_push_arguments((nargs), (args), (sp), (struct_return), (struct_addr)) +extern CORE_ADDR +sparc_push_arguments PARAMS ((int, struct value **, CORE_ADDR, int, CORE_ADDR)); diff --git a/gdb/sparc-tdep.c b/gdb/sparc-tdep.c index bd85d28e21..2b970a6f89 100644 --- a/gdb/sparc-tdep.c +++ b/gdb/sparc-tdep.c @@ -1,5 +1,5 @@ /* Target-dependent code for the SPARC for GDB, the GNU debugger. - Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994, 1995, 1996 + Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997 Free Software Foundation, Inc. This file is part of GDB. @@ -27,6 +27,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "target.h" #include "value.h" #include "bfd.h" +#include "gdb_string.h" #ifdef USE_PROC_FS #include @@ -75,14 +76,12 @@ int deferred_stores = 0; /* Cumulates stores we want to do eventually. */ /* Sign extension macros. */ #define X_SIMM13(i) ((X_IMM13 (i) ^ 0x1000) - 0x1000) #define X_DISP22(i) ((X_IMM22 (i) ^ 0x200000) - 0x200000) -#ifdef GDB_TARGET_IS_SPARC64 #define X_CC(i) (((i) >> 20) & 3) #define X_P(i) (((i) >> 19) & 1) #define X_DISP19(i) ((((i) & 0x7ffff) ^ 0x40000) - 0x40000) #define X_RCOND(i) (((i) >> 25) & 7) #define X_DISP16(i) ((((((i) >> 6) && 0xc000) | ((i) & 0x3fff)) ^ 0x8000) - 0x8000) #define X_FCN(i) (((i) >> 25) & 31) -#endif typedef enum { @@ -109,6 +108,8 @@ static binsn_quantum break_mem[3]; int one_stepped; +static branch_type isbranch PARAMS ((long, CORE_ADDR, CORE_ADDR *)); + /* single_step() is called just before we want to resume the inferior, if we want to single-step it but there is no hardware or kernel single-step support (as on all SPARCs). We find all the possible targets of the @@ -119,9 +120,9 @@ int one_stepped; void single_step (ignore) - int ignore; /* pid, but we don't need it */ + enum target_signal ignore; /* pid, but we don't need it */ { - branch_type br, isbranch(); + branch_type br; CORE_ADDR pc; long pc_instruction; @@ -206,14 +207,24 @@ sparc_init_extra_frame_info (fromleaf, fi) if (fi->next) { char buf[MAX_REGISTER_RAW_SIZE]; - int err; /* Compute ->frame as if not flat. If it is flat, we'll change it later. */ - /* FIXME: If error reading memory, should just stop backtracing, rather - than error(). */ - get_saved_register (buf, 0, 0, fi, FP_REGNUM, 0); - fi->frame = extract_address (buf, REGISTER_RAW_SIZE (FP_REGNUM)); + if (fi->next->next != NULL + && (fi->next->next->signal_handler_caller + || frame_in_dummy (fi->next->next)) + && frameless_look_for_prologue (fi->next)) + { + /* A frameless function interrupted by a signal did not change + the frame pointer, fix up frame pointer accordingly. */ + fi->frame = FRAME_FP (fi->next); + fi->bottom = fi->next->bottom; + } + else + { + get_saved_register (buf, 0, 0, fi, FP_REGNUM, 0); + fi->frame = extract_address (buf, REGISTER_RAW_SIZE (FP_REGNUM)); + } } /* Decide whether this is a function with a ``flat register window'' @@ -289,7 +300,9 @@ sparc_extract_struct_value_address (regbuf) return extract_address (regbuf + REGISTER_BYTE (O0_REGNUM), REGISTER_RAW_SIZE (O0_REGNUM)); #else - return read_memory_integer (((int *)(regbuf)) [SP_REGNUM] + (16 * SPARC_INTREG_SIZE), + CORE_ADDR sp = extract_address (®buf [REGISTER_BYTE (SP_REGNUM)], + REGISTER_RAW_SIZE (SP_REGNUM)); + return read_memory_integer (sp + (16 * SPARC_INTREG_SIZE), TARGET_PTR_BIT / TARGET_CHAR_BIT); #endif } @@ -335,6 +348,17 @@ sparc_frame_saved_pc (frame) scbuf, sizeof (scbuf)); return extract_address (scbuf, sizeof (scbuf)); } + else if (frame->next != NULL + && (frame->next->signal_handler_caller + || frame_in_dummy (frame->next)) + && frameless_look_for_prologue (frame)) + { + /* A frameless function interrupted by a signal did not save + the PC, it is still in %o7. */ + get_saved_register (buf, (int *)NULL, (CORE_ADDR *)NULL, + frame, O7_REGNUM, (enum lval_type *)NULL); + return PC_ADJUST (extract_address (buf, SPARC_INTREG_SIZE)); + } if (frame->flat) addr = frame->pc_addr; else @@ -517,24 +541,23 @@ skip_prologue (start_pc, frameless_p) This isn't static as it's used by remote-sa.sparc.c. */ -branch_type +static branch_type isbranch (instruction, addr, target) long instruction; CORE_ADDR addr, *target; { branch_type val = not_branch; - long int offset; /* Must be signed for sign-extend. */ + long int offset = 0; /* Must be signed for sign-extend. */ *target = 0; if (X_OP (instruction) == 0 && (X_OP2 (instruction) == 2 || X_OP2 (instruction) == 6 -#ifdef GDB_TARGET_IS_SPARC64 || X_OP2 (instruction) == 1 || X_OP2 (instruction) == 3 || X_OP2 (instruction) == 5 -#else +#ifndef GDB_TARGET_IS_SPARC64 || X_OP2 (instruction) == 7 #endif )) @@ -552,7 +575,6 @@ isbranch (instruction, addr, target) #endif offset = 4 * X_DISP22 (instruction); break; -#ifdef GDB_TARGET_IS_SPARC64 case 1: case 5: offset = 4 * X_DISP19 (instruction); @@ -560,7 +582,6 @@ isbranch (instruction, addr, target) case 3: offset = 4 * X_DISP16 (instruction); break; -#endif } *target = addr + offset; } @@ -630,6 +651,22 @@ get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lval) frame1 = frame->next; + + /* Get saved PC from the frame info if not in innermost frame. */ + if (regnum == PC_REGNUM && frame1 != NULL) + { + if (lval != NULL) + *lval = not_lval; + if (raw_buffer != NULL) + { + /* Put it back in target format. */ + store_address (raw_buffer, REGISTER_RAW_SIZE (regnum), frame->pc); + } + if (addrp != NULL) + *addrp = 0; + return; + } + while (frame1 != NULL) { if (frame1->pc >= (frame1->bottom ? frame1->bottom : @@ -863,27 +900,27 @@ sparc_frame_find_saved_regs (fi, saved_regs_addr) for (regnum = G1_REGNUM; regnum < G1_REGNUM+7; regnum++) saved_regs_addr->regs[regnum] = frame_addr + (regnum - G0_REGNUM) * SPARC_INTREG_SIZE - - (FP_REGISTER_BYTES + 8 * SPARC_INTREG_SIZE); + - DUMMY_STACK_REG_BUF_SIZE + 16 * SPARC_INTREG_SIZE; for (regnum = I0_REGNUM; regnum < I0_REGNUM+8; regnum++) saved_regs_addr->regs[regnum] = frame_addr + (regnum - I0_REGNUM) * SPARC_INTREG_SIZE - - (FP_REGISTER_BYTES + 16 * SPARC_INTREG_SIZE); + - DUMMY_STACK_REG_BUF_SIZE + 8 * SPARC_INTREG_SIZE; #ifdef FP0_REGNUM for (regnum = FP0_REGNUM; regnum < FP0_REGNUM + 32; regnum++) saved_regs_addr->regs[regnum] = frame_addr + (regnum - FP0_REGNUM) * 4 - - (FP_REGISTER_BYTES); + - DUMMY_STACK_REG_BUF_SIZE + 24 * SPARC_INTREG_SIZE; #ifdef GDB_TARGET_IS_SPARC64 for (regnum = FP0_REGNUM + 32; regnum < FP_MAX_REGNUM; regnum++) saved_regs_addr->regs[regnum] = frame_addr + 32 * 4 + (regnum - FP0_REGNUM - 32) * 8 - - (FP_REGISTER_BYTES); + - DUMMY_STACK_REG_BUF_SIZE + 24 * SPARC_INTREG_SIZE; #endif #endif /* FP0_REGNUM */ for (regnum = Y_REGNUM; regnum < NUM_REGS; regnum++) saved_regs_addr->regs[regnum] = - frame_addr + (regnum - Y_REGNUM) * SPARC_INTREG_SIZE - 0xe0; - - (FP_REGISTER_BYTES + 24 * SPARC_INTREG_SIZE); + frame_addr + (regnum - Y_REGNUM) * SPARC_INTREG_SIZE + - DUMMY_STACK_REG_BUF_SIZE; frame_addr = fi->bottom ? fi->bottom : read_register (SP_REGNUM); } @@ -1094,7 +1131,7 @@ sparc_pc_adjust(pc) char buf[4]; int err; - err = target_read_memory (pc + 8, buf, sizeof(long)); + err = target_read_memory (pc + 8, buf, 4); insn = extract_unsigned_integer (buf, 4); if ((err == 0) && (insn & 0xffc00000) == 0) return pc+12; @@ -1409,7 +1446,7 @@ void sparc_print_register_hook (regno) int regno; { - unsigned LONGEST val; + ULONGEST val; /* Handle double/quad versions of lower 32 fp regs. */ if (regno >= FP0_REGNUM && regno < FP0_REGNUM + 32 @@ -1546,9 +1583,82 @@ sparc_print_register_hook (regno) #endif +int +gdb_print_insn_sparc (memaddr, info) + bfd_vma memaddr; + disassemble_info *info; +{ + /* It's necessary to override mach again because print_insn messes it up. */ + info->mach = TM_PRINT_INSN_MACH; + return print_insn_sparc (memaddr, info); +} + +/* The SPARC passes the arguments on the stack; arguments smaller + than an int are promoted to an int. */ + +CORE_ADDR +sparc_push_arguments (nargs, args, sp, struct_return, struct_addr) + int nargs; + value_ptr *args; + CORE_ADDR sp; + int struct_return; + CORE_ADDR struct_addr; +{ + int i; + int accumulate_size = 0; + struct sparc_arg + { + char *contents; + int len; + int offset; + }; + struct sparc_arg *sparc_args = + (struct sparc_arg*)alloca (nargs * sizeof (struct sparc_arg)); + struct sparc_arg *m_arg; + + /* Promote arguments if necessary, and calculate their stack offsets + and sizes. */ + for (i = 0, m_arg = sparc_args; i < nargs; i++, m_arg++) + { + value_ptr arg = args[i]; + struct type *arg_type = check_typedef (VALUE_TYPE (arg)); + /* Cast argument to long if necessary as the compiler does it too. */ + switch (TYPE_CODE (arg_type)) + { + case TYPE_CODE_INT: + case TYPE_CODE_BOOL: + case TYPE_CODE_CHAR: + case TYPE_CODE_RANGE: + case TYPE_CODE_ENUM: + if (TYPE_LENGTH (arg_type) < TYPE_LENGTH (builtin_type_long)) + { + arg_type = builtin_type_long; + arg = value_cast (arg_type, arg); + } + break; + default: + break; + } + m_arg->len = TYPE_LENGTH (arg_type); + m_arg->offset = accumulate_size; + accumulate_size = (accumulate_size + m_arg->len + 3) & ~3; + m_arg->contents = VALUE_CONTENTS(arg); + } + + /* Make room for the arguments on the stack. */ + accumulate_size += CALL_DUMMY_STACK_ADJUST; + sp = ((sp - accumulate_size) & ~7) + CALL_DUMMY_STACK_ADJUST; + + /* `Push' arguments on the stack. */ + for (i = nargs; m_arg--, --i >= 0; ) + write_memory(sp + m_arg->offset, m_arg->contents, m_arg->len); + + return sp; +} + void _initialize_sparc_tdep () { - tm_print_insn = print_insn_sparc; + tm_print_insn = gdb_print_insn_sparc; tm_print_insn_info.mach = TM_PRINT_INSN_MACH; /* Selects sparc/sparclite */ } diff --git a/gdb/sparcl-tdep.c b/gdb/sparcl-tdep.c index 10d3618acf..c59065280c 100644 --- a/gdb/sparcl-tdep.c +++ b/gdb/sparcl-tdep.c @@ -302,6 +302,7 @@ readchar (desc, timeout) int timeout; { int ch; + char s[10]; ch = SERIAL_READCHAR (desc, timeout); @@ -314,16 +315,42 @@ readchar (desc, timeout) case SERIAL_TIMEOUT: error ("SPARClite remote timeout"); default: + if (remote_debug > 0) + { + sprintf (s, "[%02x]", ch & 0xff); + puts_debug ("read -->", s, "<--"); + } return ch; } } +static void +debug_serial_write (desc, buf, len) + serial_t desc; + char *buf; + int len; +{ + char s[10]; + + SERIAL_WRITE (desc, buf, len); + if (remote_debug > 0) + { + while (len-- > 0) + { + sprintf (s, "[%02x]", *buf & 0xff); + puts_debug ("Sent -->", s, "<--"); + buf++; + } + } +} + + static int send_resp (desc, c) serial_t desc; char c; { - SERIAL_WRITE (desc, &c, 1); + debug_serial_write (desc, &c, 1); return readchar (desc, 2); } @@ -659,7 +686,7 @@ sparclite_serial_start (entry) buffer[0] = 0x03; store_unsigned_integer (buffer + 1, 4, entry); - SERIAL_WRITE (remote_desc, buffer, 1 + 4); + debug_serial_write (remote_desc, buffer, 1 + 4); i = readchar (remote_desc, 2); if (i != 0x55) error ("Can't start SparcLite. Error code %d\n", i); @@ -691,7 +718,7 @@ sparclite_serial_write (from_bfd, from_sec, from_addr, to_addr, len) if (i != 0x5a) error ("Bad response from load command (0x%x)", i); - SERIAL_WRITE (remote_desc, buffer, 4 + 4 + len); + debug_serial_write (remote_desc, buffer, 4 + 4 + len); i = readchar (remote_desc, 2); if (i != checksum) -- 2.34.1