diff options
-rw-r--r-- | gdb/.Sanitize | 1 | ||||
-rw-r--r-- | gdb/ChangeLog | 22 | ||||
-rwxr-xr-x | gdb/configure | 3 | ||||
-rw-r--r-- | gdb/configure.in | 3 | ||||
-rw-r--r-- | gdb/monitor.c | 47 | ||||
-rw-r--r-- | gdb/monitor.h | 12 | ||||
-rw-r--r-- | gdb/parse.c | 4 | ||||
-rw-r--r-- | gdb/sparc-tdep.c | 143 | ||||
-rw-r--r-- | gdb/sparclet-rom.c | 279 | ||||
-rw-r--r-- | gdb/symfile.c | 82 |
10 files changed, 507 insertions, 89 deletions
diff --git a/gdb/.Sanitize b/gdb/.Sanitize index 6de1d5d..5f5925f 100644 --- a/gdb/.Sanitize +++ b/gdb/.Sanitize @@ -349,6 +349,7 @@ sparc-stub.c sparc-tdep.c sparcl-stub.c sparcl-tdep.c +sparclet-rom.c srec.h stabsread.c stabsread.h diff --git a/gdb/ChangeLog b/gdb/ChangeLog index eb60268..e16d983 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,25 @@ + + + +Fri Jun 28 06:34:19 1996 Dawn Perchik <dawn@cygnus.com> + + * configure,configure.in: Add target sparclet. + * monitor.h,monitor.c: + Added monitor flags MO_NO_ECHO_ON_SETMEM (don't expect echo on + setmem command), MO_RUN_FIRST_TIME (if command to start process + running on target is different from one to continue execution), + MO_HEX_PREFIX (if addresses from monitor have a "0x" prefix). + * monitor.c,parse.c,sparc-tdep.c: + Don't require strings in the registers array. This is to allow + NULLs to be place holders in the tm-*.h file so that only minor + changes are needed when a new processor is introduced (eg, one + without floating point). + * sparc-tdep.c: Conditionally remove dependancies on floating point. + * sparclet-rom.c,config/sparc/sparclet.mt,config/sparc/tm-sparclet.h: + New files for target sparclet. + * symfile.c: Add option for 2nd parameter on load command : a load + offset added to the vma of each section. + Fri Jun 28 05:39:19 1996 Dawn Perchik <dawn@cygnus.com> * main.c (main): Add option "l" for setting remote_timeout. diff --git a/gdb/configure b/gdb/configure index 8d7fb10..910e3d7 100755 --- a/gdb/configure +++ b/gdb/configure @@ -3535,8 +3535,7 @@ sparc-*-sunos4*) gdb_target=sun4os4 ;; sparc-*-sunos5*) gdb_target=sun4sol2 ;; sparc-*-vxworks*) gdb_target=vxsparc ;; sparc-*-*) gdb_target=sun4os4 ;; -# Use sparc-em for sparclet for now. -sparclet-*-*) gdb_target=sparc-em ;; +sparclet-*-*) gdb_target=sparclet ;; sparclite*-*-*) gdb_target=sparclite ;; # It's not clear what the right solution for "v8plus" systems is yet. # For now, stick with sparc-sun-solaris2 since that's what config.guess diff --git a/gdb/configure.in b/gdb/configure.in index 2390b46..44439ab 100644 --- a/gdb/configure.in +++ b/gdb/configure.in @@ -644,8 +644,7 @@ sparc-*-sunos4*) gdb_target=sun4os4 ;; sparc-*-sunos5*) gdb_target=sun4sol2 ;; sparc-*-vxworks*) gdb_target=vxsparc ;; sparc-*-*) gdb_target=sun4os4 ;; -# Use sparc-em for sparclet for now. -sparclet-*-*) gdb_target=sparc-em ;; +sparclet-*-*) gdb_target=sparclet;; sparclite*-*-*) gdb_target=sparclite ;; # It's not clear what the right solution for "v8plus" systems is yet. # For now, stick with sparc-sun-solaris2 since that's what config.guess diff --git a/gdb/monitor.c b/gdb/monitor.c index 69edc9a..503930f 100644 --- a/gdb/monitor.c +++ b/gdb/monitor.c @@ -123,6 +123,8 @@ static int dump_reg_flag; /* Non-zero means do a dump_registers cmd when monitor_wait wakes up. */ static DCACHE *remote_dcache; +static int first_time=0; /* is this the first time we're executing after + gaving created the child proccess? */ /* monitor_debug is like fputs_unfiltered, except it prints special characters in printable fashion. */ @@ -139,7 +141,7 @@ monitor_debug (prefix, string, suffix) static int new_line=1; static char *prev_prefix = ""; static char *prev_suffix = ""; - + /* if the prefix is changing, print the previous suffix, a new line, and the new prefix */ if (strcmp(prev_prefix, prefix) != 0 && !new_line) @@ -693,6 +695,15 @@ monitor_resume (pid, step, sig) int pid, step; enum target_signal sig; { + /* Some monitors require a different command when starting a program */ + if (current_monitor->flags & MO_RUN_FIRST_TIME && first_time == 1) + { + first_time = 0; + monitor_printf ("run\r"); + if (current_monitor->flags & MO_NEED_REGDUMP_AFTER_CONT) + dump_reg_flag = 1; + return; + } dcache_flush (remote_dcache); if (step) monitor_printf (current_monitor->step); @@ -885,6 +896,20 @@ monitor_fetch_register (regno) if (current_monitor->getreg.resp_delim) monitor_expect (current_monitor->getreg.resp_delim, NULL, 0); + /* Skip leading spaces and "0x" if MO_HEX_PREFIX flag is set */ + if (current_monitor->flags & MO_HEX_PREFIX) + { + int c; + c = readchar (timeout); + while (c == ' ') + c = readchar (timeout); + if ((c == '0') && ((c = readchar (timeout)) == 'x')) + ; + else + error ("Bad value returned from monitor while fetching register %x.", + regno); + } + /* Read upto the maximum number of hex digits for this register, skipping spaces, but stop reading if something else is seen. Some monitors like to drop leading zeros. */ @@ -1078,7 +1103,10 @@ monitor_write_memory (memaddr, myaddr, len) val = extract_unsigned_integer (myaddr, len); - monitor_printf (cmd, memaddr, val); + if (current_monitor->flags & MO_NO_ECHO_ON_SETMEM) + monitor_printf_noecho (cmd, memaddr, val); + else + monitor_printf (cmd, memaddr, val); monitor_expect_prompt (NULL, 0); @@ -1135,6 +1163,19 @@ monitor_read_memory_single (memaddr, myaddr, len) /* Now, read the appropriate number of hex digits for this loc, skipping spaces. */ + /* Skip leading spaces and "0x" if MO_HEX_PREFIX flag is set */ + if (current_monitor->flags & MO_HEX_PREFIX) + { + int c; + c = readchar (timeout); + while (c == ' ') + c = readchar (timeout); + if ((c == '0') && ((c = readchar (timeout)) == 'x')) + ; + else + error ("monitor_read_memory_single (0x%x): bad response from monitor: %.*s%c.", + memaddr, i, membuf, c); + } for (i = 0; i < len * 2; i++) { int c; @@ -1331,6 +1372,7 @@ monitor_create_inferior (exec_file, args, env) if (args && (*args != '\000')) error ("Args are not supported by the monitor."); + first_time = 1; clear_proceed_status (); proceed (bfd_get_start_address (exec_bfd), TARGET_SIGNAL_0, 0); } @@ -1432,6 +1474,7 @@ monitor_load (file, from_tty) if (current_monitor->loadresp) monitor_expect (current_monitor->loadresp, NULL, 0); +/* FIXME Should add arg here for load_offset (already done for generic_load) */ load_srec (monitor_desc, file, 32, SREC_ALL, hashmark, current_monitor->flags & MO_SREC_ACK ? monitor_wait_srec_ack : NULL); diff --git a/gdb/monitor.h b/gdb/monitor.h index dc2f124..f658921 100644 --- a/gdb/monitor.h +++ b/gdb/monitor.h @@ -152,6 +152,18 @@ struct monitor_ops #define MO_SREC_ACK 0x100 +/* Allow 0x prefix on addresses retured from monitor */ + +#define MO_HEX_PREFIX 0x200 + +/* Some monitors require a different command when starting a program */ + +#define MO_RUN_FIRST_TIME 0x400 + +/* Don't expect echos when getting memory */ + +#define MO_NO_ECHO_ON_SETMEM 0x800 + #define SREC_SIZE 160 extern void monitor_open PARAMS ((char *args, struct monitor_ops *ops, diff --git a/gdb/parse.c b/gdb/parse.c index 7d458c1..e4ff571 100644 --- a/gdb/parse.c +++ b/gdb/parse.c @@ -459,13 +459,13 @@ write_dollar_variable (str) /* Handle tokens that refer to machine registers: $ followed by a register name. */ for (i = 0; i < NUM_REGS; i++) - if (str.length - 1 == strlen (reg_names[i]) + if (reg_names[i] && str.length - 1 == strlen (reg_names[i]) && STREQN (str.ptr + 1, reg_names[i], str.length - 1)) { goto handle_register; } for (i = 0; i < num_std_regs; i++) - if (str.length - 1 == strlen (std_regs[i].name) + if (std_regs[i].name && str.length - 1 == strlen (std_regs[i].name) && STREQN (str.ptr + 1, std_regs[i].name, str.length - 1)) { i = std_regs[i].regnum; diff --git a/gdb/sparc-tdep.c b/gdb/sparc-tdep.c index 5a1eaa3..98ec9e2 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 + Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc. This file is part of GDB. @@ -34,9 +34,14 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "gdbcore.h" #ifdef GDB_TARGET_IS_SPARC64 -#define NUM_SPARC_FPREGS 64 +#define FP_REGISTER_BYTES (64 * 4) #else -#define NUM_SPARC_FPREGS 32 +#define FP_REGISTER_BYTES (32 * 4) +#endif + +/* If not defined, assume 32 bit sparc. */ +#ifndef FP_MAX_REGNUM +#define FP_MAX_REGNUM (FP0_REGNUM + 32) #endif #define SPARC_INTREG_SIZE (REGISTER_RAW_SIZE (G0_REGNUM)) @@ -607,6 +612,22 @@ get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lval) *optimized = 0; addr = 0; + + /* FIXME This code extracted from infcmd.c; should put elsewhere! */ + if (frame == NULL) + { + /* error ("No selected frame."); */ + if (!target_has_registers) + error ("The program has no registers now."); + if (selected_frame == NULL) + error ("No selected frame."); + /* Try to use selected frame */ + frame = get_prev_frame (selected_frame); + if (frame == 0) + error ("Cmd not meaningful in the outermost frame."); + } + + frame1 = frame->next; while (frame1 != NULL) { @@ -614,20 +635,36 @@ get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lval) read_register (SP_REGNUM)) && frame1->pc <= FRAME_FP (frame1)) { - /* Dummy frame. All but the window regs are in there somewhere. */ - /* FIXME: The offsets are wrong for sparc64 (eg: 0xa0). */ + /* Dummy frame. All but the window regs are in there somewhere. + The window registers are saved on the stack, just like in a + normal frame. */ if (regnum >= G1_REGNUM && regnum < G1_REGNUM + 7) addr = frame1->frame + (regnum - G0_REGNUM) * SPARC_INTREG_SIZE - - (NUM_SPARC_FPREGS * 4 + 8 * SPARC_INTREG_SIZE); + - (FP_REGISTER_BYTES + 8 * SPARC_INTREG_SIZE); else if (regnum >= I0_REGNUM && regnum < I0_REGNUM + 8) - addr = frame1->frame + (regnum - I0_REGNUM) * SPARC_INTREG_SIZE - - (NUM_SPARC_FPREGS * 4 + 16 * SPARC_INTREG_SIZE); - else if (regnum >= FP0_REGNUM && regnum < FP0_REGNUM + NUM_SPARC_FPREGS) + addr = (frame1->prev->bottom + + (regnum - I0_REGNUM) * SPARC_INTREG_SIZE + + FRAME_SAVED_I0); + else if (regnum >= L0_REGNUM && regnum < L0_REGNUM + 8) + addr = (frame1->prev->bottom + + (regnum - L0_REGNUM) * SPARC_INTREG_SIZE + + FRAME_SAVED_L0); + else if (regnum >= O0_REGNUM && regnum < O0_REGNUM + 8) + addr = frame1->frame + (regnum - O0_REGNUM) * SPARC_INTREG_SIZE + - (FP_REGISTER_BYTES + 16 * SPARC_INTREG_SIZE); +#ifdef FP0_REGNUM + else if (regnum >= FP0_REGNUM && regnum < FP0_REGNUM + 32) addr = frame1->frame + (regnum - FP0_REGNUM) * 4 - - (NUM_SPARC_FPREGS * 4); + - (FP_REGISTER_BYTES); +#ifdef GDB_TARGET_IS_SPARC64 + else if (regnum >= FP0_REGNUM + 32 && regnum < FP_MAX_REGNUM) + addr = frame1->frame + 32 * 4 + (regnum - FP0_REGNUM - 32) * 8 + - (FP_REGISTER_BYTES); +#endif +#endif /* FP0_REGNUM */ else if (regnum >= Y_REGNUM && regnum < NUM_REGS) addr = frame1->frame + (regnum - Y_REGNUM) * SPARC_INTREG_SIZE - - (NUM_SPARC_FPREGS * 4 + 24 * SPARC_INTREG_SIZE); + - (FP_REGISTER_BYTES + 24 * SPARC_INTREG_SIZE); } else if (frame1->flat) { @@ -715,8 +752,13 @@ get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lval) #endif /* See tm-sparc.h for how this is calculated. */ +#ifdef FP0_REGNUM #define DUMMY_STACK_REG_BUF_SIZE \ (((8+8+8) * SPARC_INTREG_SIZE) + (32 * REGISTER_RAW_SIZE (FP0_REGNUM))) +#else +#define DUMMY_STACK_REG_BUF_SIZE \ +(((8+8+8) * SPARC_INTREG_SIZE) ) +#endif /* FP0_REGNUM */ #define DUMMY_STACK_SIZE (DUMMY_STACK_REG_BUF_SIZE + DUMMY_REG_SAVE_OFFSET) void @@ -743,11 +785,11 @@ sparc_push_dummy_frame () ®ister_temp[16 * SPARC_INTREG_SIZE], SPARC_INTREG_SIZE * 8); - /* ??? The 32 here should be NUM_SPARC_FPREGS, but until we decide what - REGISTER_RAW_SIZE should be for fp regs, it's left as is. */ +#ifdef FP0_REGNUM read_register_bytes (REGISTER_BYTE (FP0_REGNUM), ®ister_temp[24 * SPARC_INTREG_SIZE], - REGISTER_RAW_SIZE (FP0_REGNUM) * 32); + FP_REGISTER_BYTES); +#endif /* FP0_REGNUM */ sp -= DUMMY_STACK_SIZE; @@ -820,19 +862,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 - - (NUM_SPARC_FPREGS * 4 + 8 * SPARC_INTREG_SIZE); + - (FP_REGISTER_BYTES + 8 * 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 - - (NUM_SPARC_FPREGS * 4 + 16 * SPARC_INTREG_SIZE); + - (FP_REGISTER_BYTES + 16 * 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 - - (NUM_SPARC_FPREGS * 4); + - (FP_REGISTER_BYTES); +#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); +#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; - - (NUM_SPARC_FPREGS * 4 + 24 * SPARC_INTREG_SIZE); + - (FP_REGISTER_BYTES + 24 * SPARC_INTREG_SIZE); frame_addr = fi->bottom ? fi->bottom : read_register (SP_REGNUM); } @@ -908,11 +958,12 @@ sparc_pop_frame () int regnum; sparc_frame_find_saved_regs (frame, &fsr); +#ifdef FP0_REGNUM if (fsr.regs[FP0_REGNUM]) { - read_memory (fsr.regs[FP0_REGNUM], raw_buffer, NUM_SPARC_FPREGS * 4); + read_memory (fsr.regs[FP0_REGNUM], raw_buffer, FP_REGISTER_BYTES); write_register_bytes (REGISTER_BYTE (FP0_REGNUM), - raw_buffer, NUM_SPARC_FPREGS * 4); + raw_buffer, FP_REGISTER_BYTES); } #ifndef GDB_TARGET_IS_SPARC64 if (fsr.regs[FPS_REGNUM]) @@ -926,6 +977,7 @@ sparc_pop_frame () write_register_bytes (REGISTER_BYTE (CPS_REGNUM), raw_buffer, 4); } #endif +#endif /* FP0_REGNUM */ if (fsr.regs[G1_REGNUM]) { read_memory (fsr.regs[G1_REGNUM], raw_buffer, 7 * SPARC_INTREG_SIZE); @@ -1205,7 +1257,7 @@ prfpregset_t *fpregsetp; register int regi; char *from; - for (regi = FP0_REGNUM ; regi < FP0_REGNUM+32 ; regi++) + for (regi = FP0_REGNUM ; regi < FP_MAX_REGNUM ; regi++) { from = (char *) &fpregsetp->pr_fr.pr_regs[regi-FP0_REGNUM]; supply_register (regi, from); @@ -1228,9 +1280,7 @@ int regno; char *to; char *from; - /* ??? The 32 should probably be NUM_SPARC_FPREGS, but again we're - waiting on what REGISTER_RAW_SIZE should be for fp regs. */ - for (regi = FP0_REGNUM ; regi < FP0_REGNUM + 32 ; regi++) + for (regi = FP0_REGNUM ; regi < FP_MAX_REGNUM ; regi++) { if ((regno == -1) || (regno == regi)) { @@ -1360,17 +1410,50 @@ sparc_print_register_hook (regno) { unsigned LONGEST val; - if (((unsigned) (regno) - FP0_REGNUM < FP_MAX_REGNUM - FP0_REGNUM) - && ((regno) & 1) == 0) + /* Handle double/quad versions of lower 32 fp regs. */ + if (regno >= FP0_REGNUM && regno < FP0_REGNUM + 32 + && (regno & 1) == 0) + { + char value[16]; + + if (!read_relative_register_raw_bytes (regno, value) + && !read_relative_register_raw_bytes (regno + 1, value + 4)) + { + printf_unfiltered ("\t"); + print_floating (value, builtin_type_double, gdb_stdout); + } +#if 0 /* FIXME: gdb doesn't handle long doubles */ + if ((regno & 3) == 0) + { + if (!read_relative_register_raw_bytes (regno + 2, value + 8) + && !read_relative_register_raw_bytes (regno + 3, value + 12)) + { + printf_unfiltered ("\t"); + print_floating (value, builtin_type_long_double, gdb_stdout); + } + } +#endif + return; + } + +#if 0 /* FIXME: gdb doesn't handle long doubles */ + /* Print upper fp regs as long double if appropriate. */ + if (regno >= FP0_REGNUM + 32 && regno < FP_MAX_REGNUM + /* We test for even numbered regs and not a multiple of 4 because + the upper fp regs are recorded as doubles. */ + && (regno & 1) == 0) { - char doublereg[8]; /* two float regs */ - if (!read_relative_register_raw_bytes ((regno), doublereg)) + char value[16]; + + if (!read_relative_register_raw_bytes (regno, value) + && !read_relative_register_raw_bytes (regno + 1, value + 8)) { - printf_unfiltered("\t"); - print_floating (doublereg, builtin_type_double, gdb_stdout); + printf_unfiltered ("\t"); + print_floating (value, builtin_type_long_double, gdb_stdout); } return; } +#endif /* FIXME: Some of these are priviledged registers. Not sure how they should be handled. */ diff --git a/gdb/sparclet-rom.c b/gdb/sparclet-rom.c new file mode 100644 index 0000000..98bc27b --- /dev/null +++ b/gdb/sparclet-rom.c @@ -0,0 +1,279 @@ +/* Remote target glue for the SPARC Sparclet ROM monitor. + Copyright 1995, 1996 Free Software Foundation, Inc. + +This file is part of GDB. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + + +#include "defs.h" +#include "gdbcore.h" +#include "target.h" +#include "monitor.h" +#include "serial.h" +#include "srec.h" +#include "symtab.h" +#include "symfile.h" /* for generic_load */ + +#if !defined (HAVE_TERMIOS) && !defined (HAVE_TERMIO) && !defined (HAVE_SGTTY) +#define HAVE_SGTTY +#endif + +#ifdef HAVE_SGTTY +#include <sys/ioctl.h> +#endif + +#include <sys/types.h> /* Needed by file.h on Sys V */ +#include <sys/file.h> +#include <signal.h> +#include <sys/stat.h> + +#define USE_GENERIC_LOAD +#define USE_SW_BREAKS + +static struct target_ops sparclet_ops; + +static void sparclet_open PARAMS ((char *args, int from_tty)); + +#ifdef USE_GENERIC_LOAD + +static void +sparclet_load_gen (filename, from_tty) + char *filename; + int from_tty; +{ + extern int inferior_pid; + + generic_load (filename, from_tty); + /* Finally, make the PC point at the start address */ + if (exec_bfd) + write_pc (bfd_get_start_address (exec_bfd)); + + inferior_pid = 0; /* No process now */ +} + +#else + +static void +sparclet_xmodem_load (desc, file, hashmark) + serial_t desc; + char *file; + int hashmark; +{ + bfd *abfd; + asection *s; + char *buffer; + int i; + + buffer = alloca (XMODEM_PACKETSIZE); + abfd = bfd_openr (file, 0); + if (!abfd) + { + printf_filtered ("Unable to open file %s\n", file); + return; + } + if (bfd_check_format (abfd, bfd_object) == 0) + { + printf_filtered ("File is not an object file\n"); + return; + } + for (s = abfd->sections; s; s = s->next) + if (s->flags & SEC_LOAD) + { + bfd_size_type section_size; + printf_filtered ("%s\t: 0x%4x .. 0x%4x ", s->name, s->vma, + s->vma + s->_raw_size); + gdb_flush (gdb_stdout); + monitor_printf (current_monitor->load, s->vma); + if (current_monitor->loadresp) + monitor_expect (current_monitor->loadresp, NULL, 0); + xmodem_init_xfer (desc); + section_size = bfd_section_size (abfd, s); + for (i = 0; i < section_size; i += XMODEM_DATASIZE) + { + int numbytes; + numbytes = min (XMODEM_DATASIZE, section_size - i); + bfd_get_section_contents (abfd, s, buffer + XMODEM_DATAOFFSET, i, + numbytes); + xmodem_send_packet (desc, buffer, numbytes, hashmark); + if (hashmark) + { + putchar_unfiltered ('#'); + gdb_flush (gdb_stdout); + } + } /* Per-packet (or S-record) loop */ + xmodem_finish_xfer (desc); + monitor_expect_prompt (NULL, 0); + putchar_unfiltered ('\n'); + } /* Loadable sections */ + if (hashmark) + putchar_unfiltered ('\n'); +} + +static void +sparclet_load (desc, file, hashmark) + serial_t desc; + char *file; + int hashmark; +{ +??? +} +#endif /* USE_GENERIC_LOAD */ + +/* This array of registers need to match the indexes used by GDB. + This exists because the various ROM monitors use different strings + than does GDB, and don't necessarily support all the registers + either. So, typing "info reg sp" becomes a "r30". */ + +/*PSR 0x00000080 impl ver icc AW LE EE EC EF PIL S PS ET CWP WIM + 0x0 0x0 0x0 0 0 0 0 0 0x0 1 0 0 0x00 0x2 + 0000010 + INS LOCALS OUTS GLOBALS + 0 0x00000000 0x00000000 0x00000000 0x00000000 + 1 0x00000000 0x00000000 0x00000000 0x00000000 + 2 0x00000000 0x00000000 0x00000000 0x00000000 + 3 0x00000000 0x00000000 0x00000000 0x00000000 + 4 0x00000000 0x00000000 0x00000000 0x00000000 + 5 0x00000000 0x00001000 0x00000000 0x00000000 + 6 0x00000000 0x00000000 0x123f0000 0x00000000 + 7 0x00000000 0x00000000 0x00000000 0x00000000 +pc: 0x12010000 0x00000000 unimp +npc: 0x12010004 0x00001000 unimp 0x1000 +tbr: 0x00000000 +y: 0x00000000 +*/ +/* these correspond to the offsets from tm-* files from config directories */ + +/* is wim part of psr?? */ +/* monitor wants lower case */ +static char *sparclet_regnames[NUM_REGS] = REGISTER_NAMES; + +/* Define the monitor command strings. Since these are passed directly + through to a printf style function, we may include formatting + strings. We also need a CR or LF on the end. */ + +/* need to pause the monitor for timing reasons, so slow it down */ + +static char *sparclet_inits[] = {"\n\r\r\n", NULL}; + +static struct monitor_ops sparclet_cmds = +{ + MO_CLR_BREAK_USES_ADDR + | MO_HEX_PREFIX + | MO_HANDLE_NL + | MO_NO_ECHO_ON_OPEN + | MO_NO_ECHO_ON_SETMEM + | MO_RUN_FIRST_TIME + | MO_GETMEM_READ_SINGLE, /* flags */ + sparclet_inits, /* Init strings */ + "cont\r", /* continue command */ + "step\r", /* single step */ + "\r", /* break interrupts the program */ + "+bp %x\r", /* set a breakpoint */ + /* can't use "br" because only 2 hw bps are supported */ + "-bp %x\r", /* clear a breakpoint */ + "-bp\r", /* clear all breakpoints */ + NULL, /* fill (start end val) */ + /* can't use "fi" because it takes words, not bytes */ + { + /* ex [addr] [-n count] [-b|-s|-l] default: ex cur -n 1 -b */ + "ex %x -b\r%x\rq\r", /* setmem.cmdb (addr, value) */ + "ex %x -s\r%x\rq\r", /* setmem.cmdw (addr, value) */ + "ex %x -l\r%x\rq\r", + NULL, /* setmem.cmdll (addr, value) */ + NULL, /*": ", /* setmem.resp_delim */ + NULL, /*"? ", /* setmem.term */ + NULL, /*"q\r", /* setmem.term_cmd */ + }, + { + /* since the parsing of multiple bytes is difficult due to + interspersed addresses, we'll only read 1 value at a time, + even tho these can handle a count */ + /* we can use -n to set count to read, but may have to parse? */ + "ex %x -n 1 -b\r", /* getmem.cmdb (addr, #bytes) */ + "ex %x -n 1 -s\r", /* getmem.cmdw (addr, #swords) */ + "ex %x -n 1 -l\r", /* getmem.cmdl (addr, #words) */ + NULL, /* getmem.cmdll (addr, #dwords) */ + ": ", /* getmem.resp_delim */ + NULL, /* getmem.term */ + NULL, /* getmem.term_cmd */ + }, + { + "reg %s 0x%x\r", /* setreg.cmd (name, value) */ + NULL, /* setreg.resp_delim */ + NULL, /* setreg.term */ + NULL /* setreg.term_cmd */ + }, + { + "reg %s\r", /* getreg.cmd (name) */ + ": ", /* getreg.resp_delim */ + NULL, /* getreg.term */ + NULL, /* getreg.term_cmd */ + }, + "reg\r", /* dump_registers */ + "\\(\\w+\\)=\\([0-9a-fA-F]+\\)", /* register_pattern */ + NULL, /* supply_register */ +#ifdef USE_GENERIC_LOAD + NULL, /* load_routine (defaults to SRECs) */ + NULL, /* download command */ + NULL, /* load response */ +#else + sparclet_load, /* load_routine (defaults to SRECs) */ + /* load [c|a] [s|f|r] [addr count] */ + "load a s %x\r", /* download command */ + "load: ", /* load response */ +#endif + "monitor>", /* monitor command prompt */ + /* yikes! gdb core dumps without this delimitor!! */ + "\r", /* end-of-command delimitor */ + NULL, /* optional command terminator */ + &sparclet_ops, /* target operations */ + SERIAL_1_STOPBITS, /* number of stop bits */ + sparclet_regnames, /* registers names */ + MONITOR_OPS_MAGIC /* magic */ +}; + +static void +sparclet_open (args, from_tty) + char *args; + int from_tty; +{ + monitor_open (args, &sparclet_cmds, from_tty); +} + +void +_initialize_sparclet () +{ + init_monitor_ops (&sparclet_ops); + + sparclet_ops.to_shortname = "sparclet"; /* for the target command */ + sparclet_ops.to_longname = "SPARC Sparclet monitor"; +#ifdef USE_GENERIC_LOAD + sparclet_ops.to_load = sparclet_load_gen; /* FIXME - should go back and try "do" */ +#endif +#ifdef USE_SW_BREAKS + /* use SW breaks; target only supports 2 HW breakpoints */ + sparclet_ops.to_insert_breakpoint = memory_insert_breakpoint; + sparclet_ops.to_remove_breakpoint = memory_remove_breakpoint; +#endif + + sparclet_ops.to_doc = + "Use a board running the Sparclet debug monitor.\n\ +Specify the serial device it is connected to (e.g. /dev/ttya)."; + + sparclet_ops.to_open = sparclet_open; + add_target (&sparclet_ops); +} + diff --git a/gdb/symfile.c b/gdb/symfile.c index e95d1db..f9a99ae 100644 --- a/gdb/symfile.c +++ b/gdb/symfile.c @@ -657,6 +657,8 @@ symbol_file_add (name, from_tty, addr, mainline, mapped, readnow) new_symfile_objfile (objfile, mainline, from_tty); + target_new_objfile (objfile); + return (objfile); } @@ -920,6 +922,16 @@ generic_load (filename, from_tty) bfd *loadfile_bfd; time_t start_time, end_time; /* Start and end times of download */ unsigned long data_count = 0; /* Number of bytes transferred to memory */ + int n; + unsigned long load_offset = 0; /* offset to add to vma for each section */ + char buf[128]; + + /* enable user to specify address for downloading as 2nd arg to load */ + n = sscanf(filename, "%s 0x%x", buf, &load_offset); + if (n > 1 ) + filename = buf; + else + load_offset = 0; loadfile_bfd = bfd_openr (filename, gnutarget); if (loadfile_bfd == NULL) @@ -959,6 +971,7 @@ generic_load (filename, from_tty) old_chain = make_cleanup (free, buffer); vma = bfd_get_section_vma (loadfile_bfd, s); + vma += load_offset; /* Is this really necessary? I guess it gives the user something to look at during a long download. */ @@ -979,6 +992,8 @@ generic_load (filename, from_tty) end_time = time (NULL); + printf_filtered ("Start address 0x%lx\n", loadfile_bfd->start_address); + /* We were doing this in remote-mips.c, I suspect it is right for other targets too. */ write_pc (loadfile_bfd->start_address); @@ -1424,6 +1439,7 @@ clear_symtab_users () current_source_symtab = 0; current_source_line = 0; clear_pc_function_cache (); + target_new_objfile (NULL); } /* clear_symtab_users_once: @@ -1654,76 +1670,42 @@ start_psymtab_common (objfile, section_offsets, return (psymtab); } -/* Debugging versions of functions that are usually inline macros - (see symfile.h). */ - -#if !INLINE_ADD_PSYMBOL - /* Add a symbol with a long value to a psymtab. Since one arg is a struct, we pass in a ptr and deref it (sigh). */ void -add_psymbol_to_list (name, namelength, namespace, class, list, val, language, - objfile) +add_psymbol_to_list (name, namelength, namespace, class, list, val, coreaddr, + language, objfile) char *name; int namelength; namespace_enum namespace; enum address_class class; struct psymbol_allocation_list *list; - long val; + long val; /* Value as a long */ + CORE_ADDR coreaddr; /* Value as a CORE_ADDR */ enum language language; struct objfile *objfile; { register struct partial_symbol *psym; char *buf = alloca (namelength + 1); - struct partial_symbol psymbol; + /* psymbol is static so that there will be no uninitialized gaps in the + structure which might contain random data, causing cache misses in + bcache. */ + static struct partial_symbol psymbol; /* Create local copy of the partial symbol */ memcpy (buf, name, namelength); buf[namelength] = '\0'; SYMBOL_NAME (&psymbol) = bcache (buf, namelength + 1, &objfile->psymbol_cache); - SYMBOL_VALUE (&psymbol) = val; - SYMBOL_SECTION (&psymbol) = 0; - SYMBOL_LANGUAGE (&psymbol) = language; - PSYMBOL_NAMESPACE (&psymbol) = namespace; - PSYMBOL_CLASS (&psymbol) = class; - SYMBOL_INIT_LANGUAGE_SPECIFIC (&psymbol, language); - - /* Stash the partial symbol away in the cache */ - psym = bcache (&psymbol, sizeof (struct partial_symbol), &objfile->psymbol_cache); - - /* Save pointer to partial symbol in psymtab, growing symtab if needed. */ - if (list->next >= list->list + list->size) + /* val and coreaddr are mutually exclusive, one of them *will* be zero */ + if (val != 0) { - extend_psymbol_list (list, objfile); + SYMBOL_VALUE (&psymbol) = val; + } + else + { + SYMBOL_VALUE_ADDRESS (&psymbol) = coreaddr; } - *list->next++ = psym; - OBJSTAT (objfile, n_psyms++); -} - -/* Add a symbol with a CORE_ADDR value to a psymtab. */ - -void -add_psymbol_addr_to_list (name, namelength, namespace, class, list, val, - language, objfile) - char *name; - int namelength; - namespace_enum namespace; - enum address_class class; - struct psymbol_allocation_list *list; - CORE_ADDR val; - enum language language; - struct objfile *objfile; -{ - register struct partial_symbol *psym; - char *buf = alloca (namelength + 1); - struct partial_symbol psymbol; - - /* Create local copy of the partial symbol */ - memcpy (buf, name, namelength); - buf[namelength] = '\0'; - SYMBOL_NAME (&psymbol) = bcache (buf, namelength + 1, &objfile->psymbol_cache); - SYMBOL_VALUE_ADDRESS (&psymbol) = val; SYMBOL_SECTION (&psymbol) = 0; SYMBOL_LANGUAGE (&psymbol) = language; PSYMBOL_NAMESPACE (&psymbol) = namespace; @@ -1742,8 +1724,6 @@ add_psymbol_addr_to_list (name, namelength, namespace, class, list, val, OBJSTAT (objfile, n_psyms++); } -#endif /* !INLINE_ADD_PSYMBOL */ - /* Initialize storage for partial symbols. */ void |