diff options
45 files changed, 2275 insertions, 2479 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index cc2d5e37dbc..1fb60e9222f 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,222 @@ +1999-10-18 Elena Zannoni <ezannoni@kwikemart.cygnus.com> + + * breakpoint.h: Change return type of field print_it of struct + bpstats to enumeration print_stop_action. + Define new enumeration print_stop_action. + + * breakpoint.c (print_it_normal): Change return type to + enumeration type print_stop_action. Handle bp_shlib_event here + instead of in normal_stop(). + (bpstat_print): Change return type to enumeration type + print_stop_action. + (print_it_done): Ditto. + (print_it_noop): Ditto. + + * infrun.c (is_internal_shlib_eventpoint): Delete this function. + (stopped_for_internal_shlib_event): Delete. + (normal_stop): Move logic to handle bp_shlib_event from here to + print_it_normal(). Use switch to handle return value from + bpstat_print(). + +Mon Oct 18 17:32:51 1999 Andrew Cagney <cagney@b1.cygnus.com> + + * symfile.c (generic_load): Rewrite. Make the size of each + chunk/block write a run-time option. Check for quit_flag. + Use target_write_memory_partial for downloads. + +1999-10-18 Jim Blandy <jimb@zenia.red-bean.com> + + Change Linux x86 register support to use the new tm-i386.h layout. + * config/i386/tm-linux.h (HAVE_I387_REGS): #define this, so we get + the full set of FP register definitions from tm-i386.h. + (REGISTER_RAW_SIZE, REGISTER_NAMES, REGISTER_BYTES, REGISTER_BYTE, + MAX_REGISTER_VIRTUAL_SIZE, MAX_REGISTER_RAW_SIZE, NUM_REGS, + NUM_FREGS): Remove #undefs and subsequent redefinitions: we're + using the values from tm-i386.h now. + (FPSTART_REGNUM, FPCONTROL_REGNUM, FPSTATUS_REGNUM, FPTAG_REGNUM, + FPDATA_REGNUM, FPEND_REGNUM, FPENV_BYTES, FPREG_RAW_SIZE, + FPREG_BYTES): Deleted. + (TARGET_LONG_DOUBLE_BIT): Deleted. + (REGISTER_CONVERTIBLE, REGISTER_CONVERT_TO_VIRTUAL, + REGISTER_CONVERT_TO_RAW): Redefine these only if LD_I387 is #defined. + * i386-linux-nat.c (convert_to_gregset, convert_to_fpregset, + FPREGSET_T_FPREG_OFFSET): New functions and macros. + (supply_gregset, fill_gregset, supply_fpregset, + fill_fpregset, fetch_fpregs, store_fpregs, fetch_regs, + store_regs, fetch_inferior_registers, store_inferior_registers): + Adjusted to use new macros from tm-i386.h. + + * config/i386/tm-i386.h: Provide a decent x86 FPU description here, + so that the various i386 targets can share more FPU handling code. + (NUM_GREGS): New macro. + (NUM_SSE_REGS): New macro, dependent on HAVE_SSE_REGS + (NUM_FREGS): Depend on HAVE_I387_REGS. + (NUM_REGS, REGISTER_BYTES): Define in terms of NUM_GREGS, + NUM_FREGS, and NUM_SSE_REGS. + (MAX_NUM_REGS): New macro. + (REGISTER_NAMES): Expand name list with FPU control registers and + SSE registers. + (FP7_REGNUM, FCTRL_REGNUM, FSTAT_REGNUM, FTAG_REGNUM, FCS_REGNUM, + FCOFF_REGNUM, FDS_REGNUM, FDOFF_REGNUM, FOP_REGNUM, + FIRST_FPU_CTRL_REGNUM, LAST_FPU_CTRL_REGNUM): New macros, more + fully describing the FPU register set. + (XMM0_REGNUM, XMM7_REGNUM, MXCSR_REGNUM): New macros, describing + the SSE register set. + (IS_FP_REGNUM, IS_SSE_REGNUM, FPU_REG_RAW_SIZE, SIZEOF_GREGS, + SIZEOF_FPU_REGS, SIZEOF_FPU_CTRL_REGS, SIZEOF_SSE_REGS): New + convenience macros. + (REGISTER_BYTE, REGISTER_RAW_SIZE, REGISTER_VIRTUAL_SIZE): Turn + these into tables, since the register sizes are pretty irregular. + (i386_register_byte, i386_register_raw_size, + i386_register_virtual_size): New extern declarations. + (TARGET_LONG_DOUBLE_BIT): Define. + (MAX_REGISTER_RAW_SIZE): Bump to 16, for the SSE registers. + (REGISTER_VIRTUAL_TYPE, REGISTER_CONVERTIBLE, + REGISTER_CONVERT_TO_VIRTUAL, REGISTER_CONVERT_TO_RAW): New macros + for handling floating-point registers. + (i387_to_double, double_to_i387): New extern declarations. + * i386-tdep.c (i386_register_byte, i386_register_raw_size, + i386_register_virtual_size): New arrays. + (_initialize_i386_tdep): Initialize i386_register_byte and + i386_register_virtual_size. + + * i386-tdep.c (_initialize_i386_tdep): Move new_cmd to a block + created specially for its use. + +Mon Oct 18 23:36:58 1999 Andrew Cagney <cagney@b1.cygnus.com> + + * symfile.c (generic_load): Cleanup the validate code - remove + #ifdef, use paddr to print address. + (validate_download): Static, replace VALIDATE_DOWNLOAD + + * symfile.c (generic_load): Use strtoul to scan the optional load + offset. Allocate a filename of the correct size. + +Mon Oct 18 17:32:51 1999 Andrew Cagney <cagney@b1.cygnus.com> + + * symfile.c (generic_load): Don't filter output. Use + print_transfer_performance for summary. Use paddr for addresses. + (print_transfer_performance): New function. Includes write count. + (report_transfer_performance): Call + print_transfer_performance. Deprecate. + + * defs.h (print_transfer_performance): Add declaration. + (generic_load): Move declaration to here. + * symfile.h (generic_load): From here. + +Mon Oct 18 16:29:52 1999 Andrew Cagney <cagney@amy.cygnus.com> + + * remote.c (remote_write_bytes): Re-write. Transfer a single + packet and then return the that packets byte size. + +Sun Oct 17 15:09:00 1999 Andrew Cagney <cagney@b1.cygnus.com> + + * remote.c (remote_console_output): Flush gdb_stdtarg after + processing an ``O'' packet. + * remote.h (remote_console_output): Strip PARAMS. + +Sun Oct 17 15:12:33 1999 Andrew Cagney <cagney@b1.cygnus.com> + + * target.c (target_xfer_memory_partial): New function. Simple + implementation of partial memory reads. + (target_read_memory_partial): New function. Replaces old + target_read_memory_partial. + (target_write_memory_partial): New function. + * target.h: Update. + + * valprint.c (partial_memory_read): New function, based on old + memory_read_partial. Implement partial memory reads the way that + val_print_string likes. + (val_print_string): Use partial_memory_read. + +Sun Oct 17 13:58:56 1999 Andrew Cagney <cagney@b1.cygnus.com> + + * defs.h (ui_load_progress_hook): Add declaration. + * dsrec.c (ui_load_progress_hook): Delete extern declaration. + + * symfile.c (ui_load_progress_hook): Make first argument const. + (generic_load): Don't cast the result of bfd_get_section_name. + Replace ``sect'' with ``sect_name'', use consistently. + +1999-10-15 Jim Blandy <jimb@zenia.red-bean.com> + + Add beginnings of support for SIMD register types. + * gdbtypes.c (init_simd_type): New function for building + types for registers consisting of arrays of objects. + (builtin_type_v4sf): New built-in type. + (build_gdbtypes): Initialize it. + (_initialize_gdbtypes): Arrange for gdbarch swapping. + * gdbtypes.h (builtin_type_v4sf): Add external decl. + +Fri Oct 15 18:20:33 1999 Andrew Cagney <cagney@b1.cygnus.com> + + * remote-hms.c: Commented out H8 code. + +Fri Oct 15 17:46:39 1999 Andrew Cagney <cagney@b1.cygnus.com> + + * dcache.c (dcache_p): Rename variable remote_dcache. Make + static. + (_initialize_dcache): Fix description of ``set remotecache''. + Cache is OFF by default. + +1999-10-13 Jim Blandy <jimb@zenia.red-bean.com> + + * valops.c (value_push): Don't forget to initialize container_len. + +Wed Oct 13 17:58:20 1999 Andrew Cagney <cagney@b1.cygnus.com> + + * utils.c (tui_file_flush): Don't call flush_hook. Don't try to + flush ``astring''. + * gdb-events.sh: Update + * top.c (flush_hook): Delete. + +1999-10-13 Kevin Buettner <kevinb@cygnus.com> + + * mem-break.c (memory_insert_breakpoint, + memory_remove_breakpoint): Added missing return statements. + +Wed Oct 13 20:53:42 1999 Andrew Cagney <cagney@b1.cygnus.com> + + * utils.c (mem_fileopen, mem_file_delete, mem_file_new, + mem_file_rewind, mem_file_put, mem_file_fputs): New functions. + * defs.h (mem_fileopen): Declare. + +1999-10-13 Kevin Buettner <kevinb@cygnus.com> + + * mem-break.c (default_memory_insert_breakpoint): Renamed from + memory_insert_breakpoint. + (default_memory_remove_breakpoint): Renamed from + memory_remove_breakpoint. + (memory_insert_breakpoint, memory_remove_breakpoint, + MEMORY_INSERT_BREAKPOINT, MEMORY_REMOVE_BREAKPOINT): New + wrappers. + * target.h (default_memory_remove_breakpoint, + default_memory_insert_breakpoint): Added declarations. + * gdbarch.sh (MEMORY_INSERT_BREAKPOINT, MEMORY_REMOVE_BREAKPOINT): + New methods. + * gdbarch.h, gdbarch.c (MEMORY_INSERT_BREAKPOINT, + MEMORY_REMOVE_BREAKPOINT, gdbarch_memory_insert_breakpoint, + gdbarch_memory_remove_breakpoint, set_gdbarch_memory_insert_breakpoint, + set_gdbarch_memory_remove_breakpoint) : Generated from gdbarch.sh. + +Wed Oct 13 19:15:51 1999 Andrew Cagney <cagney@b1.cygnus.com> + + * defs.h: Remove PARAMS from all declarations. Re-indent. Clean + up the gdb_file declarations. + +Tue Oct 12 12:19:07 1999 David Taylor <taylor@texas.cygnus.com> + + * i386-linux-nat.c (supply_fpregset, fill_fpregset): copy + from/to start of fpregsetp not start of st_space as the first + stuff we copy is the FP control registers not the actual FP values. + +1999-10-12 Fernando Nasser <fnasser@totem.to.cygnus.com> + + * eval.c (evaluate_subexp_standard): Fix gdb invocation of + inferior C functions when debugging C++ code. + * valops.c (find_overload_match): Ditto. + * symtab.c (make_symbol_overload_list): Ditto. + 1999-10-11 Jim Blandy <jimb@zwingli.cygnus.com> * config/pa/tm-hppa.h (SYMBOLS_CAN_START_WITH_DOLLAR): It's not diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 950e2a1b39a..0dfabdac563 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -229,7 +229,7 @@ CDEPS = $(XM_CDEPS) $(TM_CDEPS) $(NAT_CDEPS) $(SIM) $(BFD) $(READLINE) \ ADD_FILES = $(REGEX) $(XM_ADD_FILES) $(TM_ADD_FILES) $(NAT_ADD_FILES) ADD_DEPS = $(REGEX1) $(XM_ADD_FILES) $(TM_ADD_FILES) $(NAT_ADD_FILES) -VERSION = 19991011 +VERSION = 19991018 DIST=gdb LINT=/usr/5bin/lint diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index b9fdcb0a076..ec78b31c780 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -157,7 +157,7 @@ insertion_state_t; static int remove_breakpoint PARAMS ((struct breakpoint *, insertion_state_t)); -static int print_it_normal PARAMS ((bpstat)); +static enum print_stop_action print_it_normal PARAMS ((bpstat)); typedef struct { @@ -170,9 +170,9 @@ static int watchpoint_check PARAMS ((PTR)); static int cover_target_enable_exception_callback PARAMS ((PTR)); -static int print_it_done PARAMS ((bpstat)); +static enum print_stop_action print_it_done PARAMS ((bpstat)); -static int print_it_noop PARAMS ((bpstat)); +static enum print_stop_action print_it_noop PARAMS ((bpstat)); static void maintenance_info_breakpoints PARAMS ((char *, int)); @@ -1752,13 +1752,15 @@ top: Return values from this routine (used by bpstat_print() to decide what to do): - 1: Means we printed something, and we do *not* desire that + PRINT_NOTHING: Means we already printed all we needed to print, don't + print anything else. + PRINT_SRC_ONLY: Means we printed something, and we do *not* desire that something to be followed by a location. - 0: Means we printed something, and we *do* desire that + PRINT_SCR_AND_LOC: Means we printed something, and we *do* desire that something to be followed by a location. - -1: Means we printed nothing. */ + PRINT_UNKNOWN: Means we printed nothing or we need to do some more analysis. */ -static int +static enum print_stop_action print_it_normal (bs) bpstat bs; { @@ -1766,6 +1768,7 @@ print_it_normal (bs) which has since been deleted. */ if (bs->breakpoint_at == NULL || (bs->breakpoint_at->type != bp_breakpoint + && bs->breakpoint_at->type != bp_shlib_event && bs->breakpoint_at->type != bp_catch_load && bs->breakpoint_at->type != bp_catch_unload && bs->breakpoint_at->type != bp_catch_fork @@ -1778,7 +1781,7 @@ print_it_normal (bs) && bs->breakpoint_at->type != bp_read_watchpoint && bs->breakpoint_at->type != bp_access_watchpoint && bs->breakpoint_at->type != bp_hardware_watchpoint)) - return -1; + return PRINT_UNKNOWN; if (ep_is_shlib_catchpoint (bs->breakpoint_at)) { @@ -1789,7 +1792,15 @@ print_it_normal (bs) else if (bs->breakpoint_at->type == bp_catch_unload) printf_filtered ("unloaded"); printf_filtered (" %s), ", bs->breakpoint_at->triggered_dll_pathname); - return 0; + return PRINT_SRC_AND_LOC; + } + else if (bs->breakpoint_at->type == bp_shlib_event) + { + /* Did we stop because the user set the stop_on_solib_events + variable? (If so, we report this as a generic, "Stopped due + to shlib event" message.) */ + printf_filtered ("Stopped due to shared library event\n"); + return PRINT_NOTHING; } else if (bs->breakpoint_at->type == bp_catch_fork || bs->breakpoint_at->type == bp_catch_vfork) @@ -1802,7 +1813,7 @@ print_it_normal (bs) printf_filtered ("vforked"); printf_filtered (" process %d), ", bs->breakpoint_at->forked_inferior_pid); - return 0; + return PRINT_SRC_AND_LOC; } else if (bs->breakpoint_at->type == bp_catch_exec) { @@ -1810,7 +1821,7 @@ print_it_normal (bs) printf_filtered ("\nCatchpoint %d (exec'd %s), ", bs->breakpoint_at->number, bs->breakpoint_at->exec_pathname); - return 0; + return PRINT_SRC_AND_LOC; } else if (bs->breakpoint_at->type == bp_catch_catch) { @@ -1837,11 +1848,11 @@ print_it_normal (bs) printf_filtered ("unknown"); printf_filtered ("\n"); - return 1; /* don't bother to print location frame info */ + return PRINT_SRC_ONLY; /* don't bother to print location frame info */ } else { - return -1; /* really throw, some other bpstat will handle it */ + return PRINT_UNKNOWN; /* really throw, some other bpstat will handle it */ } } else if (bs->breakpoint_at->type == bp_catch_throw) @@ -1869,11 +1880,11 @@ print_it_normal (bs) printf_filtered ("unknown"); printf_filtered ("\n"); - return 1; /* don't bother to print location frame info */ + return PRINT_SRC_ONLY; /* don't bother to print location frame info */ } else { - return -1; /* really catch, some other bpstat willhandle it */ + return PRINT_UNKNOWN; /* really catch, some other bpstat willhandle it */ } } @@ -1884,7 +1895,7 @@ print_it_normal (bs) number, not all of them. */ annotate_breakpoint (bs->breakpoint_at->number); printf_filtered ("\nBreakpoint %d, ", bs->breakpoint_at->number); - return 0; + return PRINT_SRC_AND_LOC; } else if ((bs->old_val != NULL) && (bs->breakpoint_at->type == bp_watchpoint || @@ -1902,7 +1913,7 @@ print_it_normal (bs) value_free (bs->old_val); bs->old_val = NULL; /* More than one watchpoint may have been triggered. */ - return -1; + return PRINT_UNKNOWN; } else if (bs->breakpoint_at->type == bp_access_watchpoint || bs->breakpoint_at->type == bp_read_watchpoint) @@ -1912,11 +1923,11 @@ print_it_normal (bs) value_print (bs->breakpoint_at->val, gdb_stdout, 0, Val_pretty_default); printf_filtered ("\n"); - return -1; + return PRINT_UNKNOWN; } /* We can't deal with it. Maybe another member of the bpstat chain can. */ - return -1; + return PRINT_UNKNOWN; } /* Print a message indicating what happened. @@ -1928,27 +1939,29 @@ print_it_normal (bs) the "Breakpoint n," part of the output. The return value of this routine is one of: - -1: Means we printed nothing - 0: Means we printed something, and expect subsequent + PRINT_UNKNOWN: Means we printed nothing + PRINT_SRC_AND_LOC: Means we printed something, and expect subsequent code to print the location. An example is "Breakpoint 1, " which should be followed by the location. - 1 : Means we printed something, but there is no need + PRINT_SRC_ONLY: Means we printed something, but there is no need to also print the location part of the message. An example is the catch/throw messages, which - don't require a location appended to the end. */ + don't require a location appended to the end. + PRINT_NOTHING: We have done some printing and we don't need any + further info to be printed.*/ -int +enum print_stop_action bpstat_print (bs) bpstat bs; { int val; if (bs == NULL) - return -1; + return PRINT_UNKNOWN; val = (*bs->print_it) (bs); - if (val >= 0) + if (val == PRINT_SRC_ONLY || val == PRINT_SRC_AND_LOC || val == PRINT_NOTHING) return val; /* Maybe another breakpoint in the chain caused us to stop. @@ -1959,7 +1972,7 @@ bpstat_print (bs) return bpstat_print (bs->next); /* We reached the end of the chain without printing anything. */ - return -1; + return PRINT_UNKNOWN; } /* Evaluate the expression EXP and return 1 if value is zero. @@ -2096,11 +2109,11 @@ which its expression is valid.\n", bs->breakpoint_at->number); two possibilities. See comments in bpstat_print() and in header of print_it_normal() for more detail. */ -static int +static enum print_stop_action print_it_done (bs) bpstat bs; { - return 0; + return PRINT_SRC_AND_LOC; } /* This is used when nothing should be printed for this bpstat entry. */ @@ -2112,11 +2125,11 @@ print_it_done (bs) two possibilities. See comments in bpstat_print() and in header of print_it_normal() for more detail. */ -static int +static enum print_stop_action print_it_noop (bs) bpstat bs; { - return -1; + return PRINT_UNKNOWN; } /* Get a bpstat associated with having just stopped at address *PC diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h index fb29c84301d..89655fe4528 100644 --- a/gdb/breakpoint.h +++ b/gdb/breakpoint.h @@ -455,7 +455,7 @@ struct bpstats /* Function called by bpstat_print to print stuff associated with this element of the bpstat chain. Returns 0 or 1 just like bpstat_print, or -1 if it can't deal with it. */ - int (*print_it) PARAMS ((bpstat bs)); + enum print_stop_action (*print_it) PARAMS ((bpstat bs)); }; enum inf_context @@ -473,6 +473,16 @@ enum breakpoint_here ordinary_breakpoint_here, permanent_breakpoint_here }; + +/* The possible return values for print_bpstat, print_it_normal, + print_it_done, print_it_noop. */ +enum print_stop_action + { + PRINT_UNKNOWN = -1, + PRINT_SRC_AND_LOC, + PRINT_SRC_ONLY, + PRINT_NOTHING + }; /* Prototypes for breakpoint-related functions. */ diff --git a/gdb/config/i386/tm-i386.h b/gdb/config/i386/tm-i386.h index 44e58d1510d..051b3c70176 100644 --- a/gdb/config/i386/tm-i386.h +++ b/gdb/config/i386/tm-i386.h @@ -76,10 +76,40 @@ extern int i386_skip_prologue PARAMS ((int)); #define REGISTER_SIZE 4 -/* Number of machine registers */ - -#define NUM_FREGS 0 /*8*/ /* Number of FP regs */ -#define NUM_REGS (16 + NUM_FREGS) /* Basic i*86 regs + FP regs */ +/* This register file is parameterized by two macros: + HAVE_I387_REGS --- register file should include i387 registers + HAVE_SSE_REGS --- register file should include SSE registers + If HAVE_SSE_REGS is #defined, then HAVE_I387_REGS must also be #defined. + + However, GDB code should not test those macros with #ifdef, since + that makes code which is annoying to multi-arch. Instead, GDB code + should check the values of NUM_GREGS, NUM_FREGS, and NUM_SSE_REGS, + which will eventually get mapped onto architecture vector entries. + + It's okay to use the macros in tm-*.h files, though, since those + files will get completely replaced when we multi-arch anyway. */ + +/* Number of general registers, present on every 32-bit x86 variant. */ +#define NUM_GREGS (16) + +/* Number of floating-point unit registers. */ +#ifdef HAVE_I387_REGS +#define NUM_FREGS (16) +#else +#define NUM_FREGS (0) +#endif + +/* Number of SSE registers. */ +#ifdef HAVE_SSE_REGS +#define NUM_SSE_REGS (9) +#else +#define NUM_SSE_REGS (0) +#endif + +#define NUM_REGS (NUM_GREGS + NUM_FREGS + NUM_SSE_REGS) + +/* Largest number of registers we could have in any configuration. */ +#define MAX_NUM_REGS (16 + 16 + 9) /* Initializer for an array of names of registers. There should be at least NUM_REGS strings in this initializer. Any excess ones are simply ignored. @@ -87,13 +117,18 @@ extern int i386_skip_prologue PARAMS ((int)); scheme (which is the same as the 386 scheme) and also regmap in the various *-nat.c files. */ -#define REGISTER_NAMES { "eax", "ecx", "edx", "ebx", \ - "esp", "ebp", "esi", "edi", \ - "eip", "eflags", "cs", "ss", \ - "ds", "es", "fs", "gs", \ - "st0", "st1", "st2", "st3", \ - "st4", "st5", "st6", "st7", \ - } +#define REGISTER_NAMES { "eax", "ecx", "edx", "ebx", \ + "esp", "ebp", "esi", "edi", \ + "eip", "eflags", "cs", "ss", \ + "ds", "es", "fs", "gs", \ + "st0", "st1", "st2", "st3", \ + "st4", "st5", "st6", "st7", \ + "fctrl", "fstat", "ftag", "fcs", \ + "fcoff", "fds", "fdoff", "fop", \ + "xmm0", "xmm1", "xmm2", "xmm3", \ + "xmm4", "xmm5", "xmm6", "xmm7", \ + "mxcsr" \ + } /* Register numbers of various important registers. Note that some of these values are "real" register numbers, @@ -102,53 +137,127 @@ extern int i386_skip_prologue PARAMS ((int)); to be actual register numbers as far as the user is concerned but do serve to get the desired values when passed to read_register. */ -#define FP_REGNUM 5 /* (ebp) Contains address of executing stack frame */ +#define FP_REGNUM 5 /* (ebp) Contains address of executing stack + frame */ #define SP_REGNUM 4 /* (usp) Contains address of top of stack */ #define PC_REGNUM 8 /* (eip) Contains program counter */ #define PS_REGNUM 9 /* (ps) Contains processor status */ -#define FP0_REGNUM 16 /* (st0) 387 register */ -#define FPC_REGNUM 25 /* 80387 control register */ +/* These registers are present only if HAVE_I387_REGS is #defined. + We promise that FP0 .. FP7 will always be consecutive register numbers. */ +#define FP0_REGNUM 16 /* first FPU floating-point register */ +#define FP7_REGNUM 23 /* last FPU floating-point register */ + +/* All of these control registers are sixteen bits long (at most) in + the FPU, but are zero-extended to thirty-two bits in GDB's register + file. This makes it easier to compute the size of the control + register file, and somewhat easier to convert to and from the FSAVE + instruction's 32-bit format. */ +#define FIRST_FPU_CTRL_REGNUM 24 +#define FCTRL_REGNUM 24 /* FPU control word */ +#define FPC_REGNUM 24 /* old name for FCTRL_REGNUM */ +#define FSTAT_REGNUM 25 /* FPU status word */ +#define FTAG_REGNUM 26 /* FPU register tag word */ +#define FCS_REGNUM 27 /* FPU instruction's code segment selector + 16 bits, called "FPU Instruction Pointer + Selector" in the x86 manuals */ +#define FCOFF_REGNUM 28 /* FPU instruction's offset within segment + ("Fpu Code OFFset") */ +#define FDS_REGNUM 29 /* FPU operand's data segment */ +#define FDOFF_REGNUM 30 /* FPU operand's offset within segment */ +#define FOP_REGNUM 31 /* FPU opcode, bottom eleven bits */ +#define LAST_FPU_CTRL_REGNUM 31 + +/* These registers are present only if HAVE_SSE_REGS is #defined. + We promise that XMM0 .. XMM7 will always have consecutive reg numbers. */ +#define XMM0_REGNUM 32 /* first SSE data register */ +#define XMM7_REGNUM 39 /* last SSE data register */ +#define MXCSR_REGNUM 40 /* Streaming SIMD Extension control/status */ + +#define IS_FP_REGNUM(n) (FP0_REGNUM <= (n) && (n) <= FP7_REGNUM) +#define IS_SSE_REGNUM(n) (XMM0_REGNUM <= (n) && (n) <= XMM7_REGNUM) + +#define FPU_REG_RAW_SIZE (10) + +/* Sizes of individual register sets. These cover the entire register + file, so summing up the sizes of those portions actually present + yields REGISTER_BYTES. */ +#define SIZEOF_GREGS (NUM_GREGS * 4) +#define SIZEOF_FPU_REGS (8 * FPU_REG_RAW_SIZE) +#define SIZEOF_FPU_CTRL_REGS \ + ((LAST_FPU_CTRL_REGNUM - FIRST_FPU_CTRL_REGNUM + 1) * 4) +#define SIZEOF_SSE_REGS (8 * 16 + 4) + /* Total amount of space needed to store our copies of the machine's register state, the array `registers'. */ - -#define REGISTER_BYTES ((NUM_REGS - NUM_FREGS)*4 + NUM_FREGS*10) +#ifdef HAVE_SSE_REGS +#define REGISTER_BYTES \ + (SIZEOF_GREGS + SIZEOF_FPU_REGS + SIZEOF_FPU_CTRL_REGS + SIZEOF_SSE_REGS) +#else +#ifdef HAVE_I387_REGS +#define REGISTER_BYTES (SIZEOF_GREGS + SIZEOF_FPU_REGS + SIZEOF_FPU_CTRL_REGS) +#else +#define REGISTER_BYTES (SIZEOF_GREGS) +#endif +#endif /* Index within `registers' of the first byte of the space for register N. */ - -#define REGISTER_BYTE(N) \ - (((N) < FP0_REGNUM) ? ((N) * 4) : ((((N) - FP0_REGNUM) * 10) + 64)) +#define REGISTER_BYTE(n) (i386_register_byte[(n)]) +extern int i386_register_byte[]; /* Number of bytes of storage in the actual machine representation for - register N. All registers are 4 bytes, except 387 st(0) - st(7), - which are 80 bits each. */ - -#define REGISTER_RAW_SIZE(N) (((N) < FP0_REGNUM) ? 4 : 10) + register N. */ +#define REGISTER_RAW_SIZE(n) (i386_register_raw_size[(n)]) +extern int i386_register_raw_size[]; /* Largest value REGISTER_RAW_SIZE can have. */ - -#define MAX_REGISTER_RAW_SIZE 10 +#define MAX_REGISTER_RAW_SIZE 16 /* Number of bytes of storage in the program's representation for register N. */ - -#define REGISTER_VIRTUAL_SIZE(N) (((N) < FP0_REGNUM) ? 4 : 8) +#define REGISTER_VIRTUAL_SIZE(n) (i386_register_virtual_size[(n)]) +extern int i386_register_virtual_size[]; /* Largest value REGISTER_VIRTUAL_SIZE can have. */ - -#define MAX_REGISTER_VIRTUAL_SIZE 8 +#define MAX_REGISTER_VIRTUAL_SIZE 16 /* Return the GDB type object for the "standard" data type of data in register N. Perhaps si and di should go here, but potentially they could be used for things other than address. */ -#define REGISTER_VIRTUAL_TYPE(N) \ - (((N) == PC_REGNUM || (N) == FP_REGNUM || (N) == SP_REGNUM) \ - ? lookup_pointer_type (builtin_type_void) \ - : (((N) < FP0_REGNUM) \ - ? builtin_type_int \ - : builtin_type_double)) +#define REGISTER_VIRTUAL_TYPE(N) \ + (((N) == PC_REGNUM || (N) == FP_REGNUM || (N) == SP_REGNUM) \ + ? lookup_pointer_type (builtin_type_void) \ + : IS_FP_REGNUM(N) ? builtin_type_double \ + : IS_SSE_REGNUM(N) ? builtin_type_v4sf \ + : builtin_type_int) + +/* REGISTER_CONVERTIBLE(N) is true iff register N's virtual format is + different from its raw format. Note that this definition assumes + that the host supports IEEE 32-bit floats, since it doesn't say + that SSE registers need conversion. Even if we can't find a + counterexample, this is still sloppy. */ +#define REGISTER_CONVERTIBLE(n) (IS_FP_REGNUM (n)) + +/* Convert data from raw format for register REGNUM in buffer FROM + to virtual format with type TYPE in buffer TO. */ +extern void i387_to_double (char *, char *); + +#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,TYPE,FROM,TO) \ +{ \ + double val; \ + i387_to_double ((FROM), (char *)&val); \ + store_floating ((TO), TYPE_LENGTH (TYPE), val); \ +} + +extern void double_to_i387 (char *, char *); + +#define REGISTER_CONVERT_TO_RAW(TYPE,REGNUM,FROM,TO) \ +{ \ + double val = extract_floating ((FROM), TYPE_LENGTH (TYPE)); \ + double_to_i387((char *)&val, (TO)); \ +} /* Store the address of the place in which to copy the structure the subroutine will return. This is called from call_function. */ diff --git a/gdb/config/i386/tm-linux.h b/gdb/config/i386/tm-linux.h index 9f5ac78436f..5faa6ff6264 100644 --- a/gdb/config/i386/tm-linux.h +++ b/gdb/config/i386/tm-linux.h @@ -22,6 +22,7 @@ #define TM_LINUX_H #define I386_GNULINUX_TARGET +#define HAVE_I387_REGS #include "i386/tm-i386.h" @@ -38,100 +39,18 @@ #include "tm-sysv4.h" -/* copy of tm-cygwin32.h */ -#undef REGISTER_RAW_SIZE -#undef REGISTER_VIRTUAL_SIZE -#undef REGISTER_VIRTUAL_TYPE -#undef REGISTER_NAMES -#undef REGISTER_BYTES -#undef REGISTER_BYTE -#undef MAX_REGISTER_VIRTUAL_SIZE -#undef NUM_REGS -#undef NUM_FREGS - -/* Number of machine registers */ - -#define NUM_REGS 31 -#define NUM_FREGS 15 - -/* Initializer for an array of names of registers. - There should be NUM_REGS strings in this initializer. */ - -/* the order of the first 8 registers must match the compiler's - * numbering scheme (which is the same as the 386 scheme) - * also, this table must match regmap in i386-pinsn.c. - */ - -#define REGISTER_NAMES { "eax", "ecx", "edx", "ebx", \ - "esp", "ebp", "esi", "edi", \ - "eip", "eflags","cs", "ss", \ - "ds", "es", "fs", "gs", \ - "cwd", "swd", "twd", "fip", \ - "fcs", "fopo", "fos", \ - "st", "st1", "st2", "st3", \ - "st4", "st5", "st6", "st7",} - #define LOW_RETURN_REGNUM 0 /* holds low four bytes of result */ #define HIGH_RETURN_REGNUM 2 /* holds high four bytes of result */ -#define FPSTART_REGNUM 16 /* start of FPU registers */ -#define FPCONTROL_REGNUM 16 /* FPU control register */ -#define FPSTATUS_REGNUM 17 /* FPU status register */ -#define FPTAG_REGNUM 18 /* FPU tag register */ -#define FPDATA_REGNUM 23 /* actual floating-point values */ -#define FPEND_REGNUM (FPSTART_REGNUM + 14) /* last FPU register */ - -#define FPENV_BYTES (7 * 4) - -#define FPREG_RAW_SIZE (10) - -/* Total amount of space needed to store our copies of the machine's - FPU state. */ - -#define FPREG_BYTES (FPENV_BYTES + 8 * FPREG_RAW_SIZE) - -/* Total amount of space needed to store our copies of the machine's - register state, the array `registers'. */ - -#define REGISTER_BYTES (FPSTART_REGNUM * 4 + FPREG_BYTES) - -/* Index within `registers' of the first byte of the space for - register N. */ - -#define REGISTER_BYTE(N) (((N) < FPDATA_REGNUM) ? \ - (N) * 4 : \ - (((N) - FPDATA_REGNUM) * FPREG_RAW_SIZE) \ - + (FPDATA_REGNUM * 4)) - -/* Number of bytes of storage in the actual machine representation - for register N. */ - -#define REGISTER_RAW_SIZE(N) (((N) < FPDATA_REGNUM) ? 4 : FPREG_RAW_SIZE) - -/* Number of bytes of storage in the program's representation - for register N. */ - -#define REGISTER_VIRTUAL_SIZE(N) (((N) < FPDATA_REGNUM) ? 4 : FPREG_RAW_SIZE) - -/* Largest value REGISTER_RAW_SIZE can have. */ - -#undef MAX_REGISTER_RAW_SIZE -#define MAX_REGISTER_RAW_SIZE FPREG_RAW_SIZE - -/* Largest value REGISTER_VIRTUAL_SIZE can have. */ - -#define MAX_REGISTER_VIRTUAL_SIZE FPREG_RAW_SIZE +/* This should probably move to tm-i386.h. */ +#define TARGET_LONG_DOUBLE_BIT 80 #if defined(HAVE_LONG_DOUBLE) && defined(HOST_I386) /* The host and target are i386 machines and the compiler supports long doubles. Long doubles on the host therefore have the same layout as a 387 FPU stack register. */ #define LD_I387 -#endif -#define TARGET_LONG_DOUBLE_BIT 80 - -#ifdef LD_I387 extern int i387_extract_floating (PTR addr, int len, long double *dretptr); extern int i387_store_floating (PTR addr, int len, long double val); @@ -153,67 +72,29 @@ extern int i387_store_floating (PTR addr, int len, long double val); && (((high & 0x7fffffff) | low) != 0); \ } \ while (0) -#endif - -#ifndef LD_I387 -/* Nonzero if register N requires conversion - from raw format to virtual format. */ -#define REGISTER_CONVERTIBLE(N) \ - ((N < FPDATA_REGNUM) ? 0 : 1) -#endif - -#ifdef LD_I387 -#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,TYPE,FROM,TO) \ -{ \ - long double val = *((long double *)FROM); \ - store_floating ((TO), TYPE_LENGTH (TYPE), val); \ -} -#else -/* Convert data from raw format for register REGNUM in buffer FROM - to virtual format with type TYPE in buffer TO. */ -extern void -i387_to_double PARAMS ((char *, char *)); - -#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,TYPE,FROM,TO) \ -{ \ - double val; \ - i387_to_double ((FROM), (char *)&val); \ - store_floating ((TO), TYPE_LENGTH (TYPE), val); \ -} -#endif -#ifdef LD_I387 -#define REGISTER_CONVERT_TO_RAW(TYPE,REGNUM,FROM,TO) \ -{ \ - long double val = extract_floating ((FROM), TYPE_LENGTH (TYPE)); \ - *((long double *)TO) = val; \ +#undef REGISTER_CONVERT_TO_VIRTUAL +#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,TYPE,FROM,TO) \ +{ \ + long double val = *((long double *)FROM); \ + store_floating ((TO), TYPE_LENGTH (TYPE), val); \ } -#else -extern void -double_to_i387 PARAMS ((char *, char *)); -#define REGISTER_CONVERT_TO_RAW(TYPE,REGNUM,FROM,TO) \ -{ \ - double val = extract_floating ((FROM), TYPE_LENGTH (TYPE)); \ - double_to_i387((char *)&val, (TO)); \ +#undef REGISTER_CONVERT_TO_RAW +#define REGISTER_CONVERT_TO_RAW(TYPE,REGNUM,FROM,TO) \ +{ \ + long double val = extract_floating ((FROM), TYPE_LENGTH (TYPE)); \ + *((long double *)TO) = val; \ } -#endif /* Return the GDB type object for the "standard" data type of data in register N. */ +#undef REGISTER_VIRTUAL_TYPE +#define REGISTER_VIRTUAL_TYPE(N) \ + (IS_FP_REGNUM (N) ? builtin_type_long_double : builtin_type_int) -#ifdef LD_I387 -#define REGISTER_VIRTUAL_TYPE(N) \ - ((N < FPDATA_REGNUM) ? builtin_type_int : \ - builtin_type_long_double) -#else -#define REGISTER_VIRTUAL_TYPE(N) \ - ((N < FPDATA_REGNUM) ? builtin_type_int : \ - builtin_type_double) #endif -/* end of copy */ - /* The following works around a problem with /usr/include/sys/procfs.h */ #define sys_quotactl 1 @@ -304,4 +185,3 @@ extern CORE_ADDR i386_linux_skip_solib_resolver (CORE_ADDR pc); #define SOFUN_ADDRESS_MAYBE_MISSING #endif /* #ifndef TM_LINUX_H */ - diff --git a/gdb/dcache.c b/gdb/dcache.c index a184498c84c..5f09ca88686 100644 --- a/gdb/dcache.c +++ b/gdb/dcache.c @@ -1,7 +1,7 @@ /* Caching code. Typically used by remote back ends for caching remote memory. - Copyright 1992, 1993, 1995, 1998 Free Software Foundation, Inc. + Copyright 1992-1993, 1995, 1998-1999 Free Software Foundation, Inc. This file is part of GDB. @@ -168,7 +168,7 @@ static void dcache_info PARAMS ((char *exp, int tty)); void _initialize_dcache PARAMS ((void)); -int remote_dcache = 0; +static int dcache_enabled_p = 0; DCACHE *last_cache; /* Used by info dcache */ @@ -288,7 +288,7 @@ dcache_alloc (dcache) { register struct dcache_block *db; - if (remote_dcache == 0) + if (dcache_enabled_p == 0) abort (); /* Take something from the free list */ @@ -479,7 +479,7 @@ dcache_xfer_memory (dcache, memaddr, myaddr, len, should_write) { int i; - if (remote_dcache) + if (dcache_enabled_p) { int (*xfunc) PARAMS ((DCACHE * dcache, CORE_ADDR addr, char *ptr)); xfunc = should_write ? dcache_poke_byte : dcache_peek_byte; @@ -512,7 +512,7 @@ dcache_info (exp, tty) { struct dcache_block *p; - if (!remote_dcache) + if (!dcache_enabled_p) { printf_filtered ("Dcache not enabled\n"); return; @@ -543,14 +543,14 @@ _initialize_dcache () { add_show_from_set (add_set_cmd ("remotecache", class_support, var_boolean, - (char *) &remote_dcache, + (char *) &dcache_enabled_p, "\ Set cache use for remote targets.\n\ When on, use data caching for remote targets. For many remote targets\n\ this option can offer better throughput for reading target memory.\n\ Unfortunately, gdb does not currently know anything about volatile\n\ registers and thus data caching will produce incorrect results with\n\ -volatile registers are in use. By default, this option is on.", +volatile registers are in use. By default, this option is off.", &setlist), &showlist); diff --git a/gdb/defs.h b/gdb/defs.h index ca5b6e188f4..fb0eb7a5ccb 100644 --- a/gdb/defs.h +++ b/gdb/defs.h @@ -29,9 +29,9 @@ #include <limits.h> #ifdef HAVE_STDDEF_H -# include <stddef.h> +#include <stddef.h> #else -# include <sys/types.h> /* for size_t */ +#include <sys/types.h> /* for size_t */ #endif #ifdef HAVE_UNISTD_H @@ -52,12 +52,12 @@ #include "ansidecl.h" -#include <stdarg.h> /* for va_list */ +#include <stdarg.h> /* for va_list */ #include "libiberty.h" /* libiberty.h can't declare this one, but evidently we can. */ -extern char *strsignal PARAMS ((int)); +extern char *strsignal (int); #include "progress.h" @@ -87,27 +87,27 @@ typedef bfd_vma CORE_ADDR; #else /* No BFD64 */ -# ifdef CC_HAS_LONG_LONG -# define LONGEST long long -# define ULONGEST unsigned long long -# else +#ifdef CC_HAS_LONG_LONG +#define LONGEST long long +#define ULONGEST unsigned long long +#else +#ifdef BFD_HOST_64_BIT /* BFD_HOST_64_BIT is defined for some hosts that don't have long long (e.g. i386-windows) so try it. */ -# ifdef BFD_HOST_64_BIT -# define LONGEST BFD_HOST_64_BIT -# define ULONGEST BFD_HOST_U_64_BIT -# else -# define LONGEST long -# define ULONGEST unsigned long -# endif -# endif +#define LONGEST BFD_HOST_64_BIT +#define ULONGEST BFD_HOST_U_64_BIT +#else +#define LONGEST long +#define ULONGEST unsigned long +#endif +#endif #endif /* No BFD64 */ #endif /* ! LONGEST */ -extern int core_addr_lessthan PARAMS ((CORE_ADDR lhs, CORE_ADDR rhs)); -extern int core_addr_greaterthan PARAMS ((CORE_ADDR lhs, CORE_ADDR rhs)); +extern int core_addr_lessthan (CORE_ADDR lhs, CORE_ADDR rhs); +extern int core_addr_greaterthan (CORE_ADDR lhs, CORE_ADDR rhs); #ifndef min @@ -129,7 +129,7 @@ extern int core_addr_greaterthan PARAMS ((CORE_ADDR lhs, CORE_ADDR rhs)); #define CPLUS_MARKER '$' /* May be overridden to '.' for SysV */ /* Check if a character is one of the commonly used C++ marker characters. */ -extern int is_cplus_marker PARAMS ((int)); +extern int is_cplus_marker (int); /* use tui interface if non-zero */ extern int tui_version; @@ -151,7 +151,7 @@ extern int quit_flag; extern int immediate_quit; extern int sevenbit_strings; -extern void quit PARAMS ((void)); +extern void quit (void); #ifdef QUIT /* do twice to force compiler warning */ @@ -170,27 +170,27 @@ extern void quit PARAMS ((void)); be forward declared to satisfy opaque references before their actual definition, needs to be here. */ -enum language -{ - language_unknown, /* Language not known */ - language_auto, /* Placeholder for automatic setting */ - language_c, /* C */ - language_cplus, /* C++ */ - language_java, /* Java */ - language_chill, /* Chill */ - language_fortran, /* Fortran */ - language_m2, /* Modula-2 */ - language_asm, /* Assembly language */ - language_scm /* Scheme / Guile */ -}; +enum language + { + language_unknown, /* Language not known */ + language_auto, /* Placeholder for automatic setting */ + language_c, /* C */ + language_cplus, /* C++ */ + language_java, /* Java */ + language_chill, /* Chill */ + language_fortran, /* Fortran */ + language_m2, /* Modula-2 */ + language_asm, /* Assembly language */ + language_scm /* Scheme / Guile */ + }; enum precision_type -{ - single_precision, - double_precision, - unspecified_precision -}; - + { + single_precision, + double_precision, + unspecified_precision + }; + /* the cleanup list records things that have to be undone if an error happens (descriptors to be closed, memory to be freed, etc.) Each link in the chain records a function to call and an @@ -202,11 +202,11 @@ enum precision_type from the chain back to a given point, not doing them. */ struct cleanup -{ - struct cleanup *next; - void (*function) PARAMS ((PTR)); - PTR arg; -}; + { + struct cleanup *next; + void (*function) (PTR); + PTR arg; + }; /* The ability to declare that a function never returns is useful, but @@ -217,12 +217,12 @@ struct cleanup "volatile" to indicate that it does not return. */ #ifndef NORETURN -# if defined(__GNUC__) \ +#if defined(__GNUC__) \ && (__GNUC__ == 1 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)) -# define NORETURN volatile -# else -# define NORETURN /* nothing */ -# endif +#define NORETURN volatile +#else +#define NORETURN /* nothing */ +#endif #endif /* GCC 2.5 and later versions define a function attribute "noreturn", @@ -231,19 +231,19 @@ struct cleanup works everywhere we use it. */ #ifndef ATTR_NORETURN -# if defined(__GNUC__) && __GNUC__ >= 2 && __GNUC_MINOR__ >= 7 -# define ATTR_NORETURN __attribute__ ((noreturn)) -# else -# define ATTR_NORETURN /* nothing */ -# endif +#if defined(__GNUC__) && __GNUC__ >= 2 && __GNUC_MINOR__ >= 7 +#define ATTR_NORETURN __attribute__ ((noreturn)) +#else +#define ATTR_NORETURN /* nothing */ +#endif #endif #ifndef ATTR_FORMAT -# if defined(__GNUC__) && __GNUC__ >= 2 && __GNUC_MINOR__ >= 4 -# define ATTR_FORMAT(type, x, y) __attribute__ ((format(type, x, y))) -# else -# define ATTR_FORMAT(type, x, y) /* nothing */ -# endif +#if defined(__GNUC__) && __GNUC__ >= 2 && __GNUC_MINOR__ >= 4 +#define ATTR_FORMAT(type, x, y) __attribute__ ((format(type, x, y))) +#else +#define ATTR_FORMAT(type, x, y) /* nothing */ +#endif #endif /* Needed for various prototypes */ @@ -253,113 +253,110 @@ struct breakpoint; /* From blockframe.c */ -extern int inside_entry_func PARAMS ((CORE_ADDR)); +extern int inside_entry_func (CORE_ADDR); -extern int inside_entry_file PARAMS ((CORE_ADDR addr)); +extern int inside_entry_file (CORE_ADDR addr); -extern int inside_main_func PARAMS ((CORE_ADDR pc)); +extern int inside_main_func (CORE_ADDR pc); /* From ch-lang.c, for the moment. (FIXME) */ -extern char *chill_demangle PARAMS ((const char *)); +extern char *chill_demangle (const char *); /* From utils.c */ -extern void initialize_utils PARAMS ((void)); +extern void initialize_utils (void); -extern void notice_quit PARAMS ((void)); +extern void notice_quit (void); -extern int strcmp_iw PARAMS ((const char *, const char *)); +extern int strcmp_iw (const char *, const char *); -extern int subset_compare PARAMS ((char *, char *)); +extern int subset_compare (char *, char *); -extern char *safe_strerror PARAMS ((int)); +extern char *safe_strerror (int); -extern char *safe_strsignal PARAMS ((int)); +extern char *safe_strsignal (int); -extern void init_malloc PARAMS ((void *)); +extern void init_malloc (void *); -extern void request_quit PARAMS ((int)); +extern void request_quit (int); -extern void do_cleanups PARAMS ((struct cleanup *)); -extern void do_final_cleanups PARAMS ((struct cleanup *)); -extern void do_my_cleanups PARAMS ((struct cleanup **, struct cleanup *)); -extern void do_run_cleanups PARAMS ((struct cleanup *)); -extern void do_exec_cleanups PARAMS ((struct cleanup *)); -extern void do_exec_error_cleanups PARAMS ((struct cleanup *)); +extern void do_cleanups (struct cleanup *); +extern void do_final_cleanups (struct cleanup *); +extern void do_my_cleanups (struct cleanup **, struct cleanup *); +extern void do_run_cleanups (struct cleanup *); +extern void do_exec_cleanups (struct cleanup *); +extern void do_exec_error_cleanups (struct cleanup *); -extern void discard_cleanups PARAMS ((struct cleanup *)); -extern void discard_final_cleanups PARAMS ((struct cleanup *)); -extern void discard_exec_error_cleanups PARAMS ((struct cleanup *)); -extern void discard_my_cleanups PARAMS ((struct cleanup **, struct cleanup *)); +extern void discard_cleanups (struct cleanup *); +extern void discard_final_cleanups (struct cleanup *); +extern void discard_exec_error_cleanups (struct cleanup *); +extern void discard_my_cleanups (struct cleanup **, struct cleanup *); -typedef void (*make_cleanup_func) PARAMS ((void *)); +typedef void (*make_cleanup_func) (void *); -extern struct cleanup *make_cleanup PARAMS ((make_cleanup_func, void *)); +extern struct cleanup *make_cleanup (make_cleanup_func, void *); -extern struct cleanup *make_cleanup_freeargv PARAMS ((char **)); +extern struct cleanup *make_cleanup_freeargv (char **); -extern struct cleanup *make_final_cleanup PARAMS ((make_cleanup_func, void *)); +extern struct cleanup *make_final_cleanup (make_cleanup_func, void *); -extern struct cleanup *make_my_cleanup PARAMS ((struct cleanup **, - make_cleanup_func, void *)); +extern struct cleanup *make_my_cleanup (struct cleanup **, + make_cleanup_func, void *); -extern struct cleanup *make_run_cleanup PARAMS ((make_cleanup_func, void *)); +extern struct cleanup *make_run_cleanup (make_cleanup_func, void *); -extern struct cleanup *make_exec_cleanup PARAMS ((make_cleanup_func, void *)); -extern struct cleanup *make_exec_error_cleanup PARAMS ((make_cleanup_func, void *)); +extern struct cleanup *make_exec_cleanup (make_cleanup_func, void *); +extern struct cleanup *make_exec_error_cleanup (make_cleanup_func, void *); -extern struct cleanup *save_cleanups PARAMS ((void)); -extern struct cleanup *save_final_cleanups PARAMS ((void)); -extern struct cleanup *save_my_cleanups PARAMS ((struct cleanup **)); +extern struct cleanup *save_cleanups (void); +extern struct cleanup *save_final_cleanups (void); +extern struct cleanup *save_my_cleanups (struct cleanup **); -extern void restore_cleanups PARAMS ((struct cleanup *)); -extern void restore_final_cleanups PARAMS ((struct cleanup *)); -extern void restore_my_cleanups PARAMS ((struct cleanup **, struct cleanup *)); +extern void restore_cleanups (struct cleanup *); +extern void restore_final_cleanups (struct cleanup *); +extern void restore_my_cleanups (struct cleanup **, struct cleanup *); -extern void free_current_contents PARAMS ((char **)); +extern void free_current_contents (char **); -extern void null_cleanup PARAMS ((PTR)); +extern void null_cleanup (PTR); -extern int myread PARAMS ((int, char *, int)); +extern int myread (int, char *, int); -extern int query PARAMS((char *, ...)) - ATTR_FORMAT(printf, 1, 2); +extern int query (char *, ...) ATTR_FORMAT (printf, 1, 2); #if !defined (USE_MMALLOC) -extern PTR mmalloc PARAMS ((PTR, size_t)); -extern PTR mrealloc PARAMS ((PTR, PTR, size_t)); -extern void mfree PARAMS ((PTR, PTR)); +extern PTR mmalloc (PTR, size_t); +extern PTR mrealloc (PTR, PTR, size_t); +extern void mfree (PTR, PTR); #endif -extern void init_page_info PARAMS ((void)); +extern void init_page_info (void); /* From demangle.c */ -extern void set_demangling_style PARAMS ((char *)); +extern void set_demangling_style (char *); /* From tm.h */ struct type; -typedef int (use_struct_convention_fn) PARAMS ((int gcc_p, struct type *value_type)); +typedef int (use_struct_convention_fn) (int gcc_p, struct type * value_type); extern use_struct_convention_fn generic_use_struct_convention; -typedef unsigned char *(breakpoint_from_pc_fn) PARAMS ((CORE_ADDR *pcptr, int *lenptr)); - - +typedef unsigned char *(breakpoint_from_pc_fn) (CORE_ADDR * pcptr, int *lenptr); /* Annotation stuff. */ -extern int annotation_level; /* in stack.c */ +extern int annotation_level; /* in stack.c */ -extern void begin_line PARAMS ((void)); +extern void begin_line (void); -extern void wrap_here PARAMS ((char *)); +extern void wrap_here (char *); -extern void reinitialize_more_filter PARAMS ((void)); +extern void reinitialize_more_filter (void); struct gdb_file; -typedef struct gdb_file GDB_FILE; /* deprecated */ +typedef struct gdb_file GDB_FILE; /* deprecated */ /* Normal results */ extern GDB_FILE *gdb_stdout; @@ -385,124 +382,115 @@ extern GDB_FILE *gdb_stdtarg; #include "tuiWin.h" #endif -/* Create a new gdb_file with the specified methods. */ +/* Create a generic gdb_file object with null methods. */ -typedef void (gdb_file_flush_ftype) PARAMS ((struct gdb_file *stream)); -extern void set_gdb_file_flush PARAMS ((struct gdb_file *stream, gdb_file_flush_ftype *flush)); +extern struct gdb_file *gdb_file_new (void); -typedef void (gdb_file_fputs_ftype) PARAMS ((const char *, struct gdb_file *stream)); -extern void set_gdb_file_fputs PARAMS ((struct gdb_file *stream, gdb_file_fputs_ftype *fputs)); +/* Override methods used by specific implementations of a GDB_FILE + object. */ -typedef int (gdb_file_isatty_ftype) PARAMS ((struct gdb_file *stream)); -extern void set_gdb_file_isatty PARAMS ((struct gdb_file *stream, gdb_file_isatty_ftype *isatty)); +typedef void (gdb_file_flush_ftype) (struct gdb_file * stream); +extern void set_gdb_file_flush (struct gdb_file *stream, gdb_file_flush_ftype * flush); -typedef void (gdb_file_rewind_ftype) PARAMS ((struct gdb_file *stream)); -extern void set_gdb_file_rewind PARAMS ((struct gdb_file *stream, gdb_file_rewind_ftype *rewind)); +typedef void (gdb_file_fputs_ftype) (const char *, struct gdb_file * stream); +extern void set_gdb_file_fputs (struct gdb_file *stream, gdb_file_fputs_ftype * fputs); -typedef void (gdb_file_put_ftype) PARAMS ((struct gdb_file *stream, struct gdb_file *dest)); -extern void set_gdb_file_put PARAMS ((struct gdb_file *stream, gdb_file_put_ftype *put)); +typedef int (gdb_file_isatty_ftype) (struct gdb_file * stream); +extern void set_gdb_file_isatty (struct gdb_file *stream, gdb_file_isatty_ftype * isatty); -typedef void (gdb_file_delete_ftype) PARAMS ((struct gdb_file *stream)); -extern void set_gdb_file_data PARAMS ((struct gdb_file *stream, void *data, gdb_file_delete_ftype *delete)); +typedef void (gdb_file_rewind_ftype) (struct gdb_file * stream); +extern void set_gdb_file_rewind (struct gdb_file *stream, gdb_file_rewind_ftype * rewind); -extern struct gdb_file *gdb_file_new PARAMS ((void)); +typedef void (gdb_file_put_ftype) (struct gdb_file * stream, struct gdb_file * dest); +extern void set_gdb_file_put (struct gdb_file *stream, gdb_file_put_ftype * put); -extern void gdb_file_delete PARAMS ((struct gdb_file *stream)); +typedef void (gdb_file_delete_ftype) (struct gdb_file * stream); +extern void set_gdb_file_data (struct gdb_file *stream, void *data, gdb_file_delete_ftype * delete); -extern void gdb_file_rewind PARAMS ((struct gdb_file *stream)); - -/* NOTE: copies left to right */ -extern void gdb_file_put PARAMS ((struct gdb_file *src, struct gdb_file *dest)); +extern void *gdb_file_data (struct gdb_file *file); -extern void *gdb_file_data PARAMS ((struct gdb_file *file)); /* Open the specified FILE as a gdb_file. */ -extern struct gdb_file *stdio_fileopen PARAMS ((FILE *)); -/* #if defined (TUI) */ -extern struct gdb_file *tui_fileopen PARAMS ((FILE *)); -extern struct gdb_file *tui_sfileopen PARAMS ((int)); -/* #endif */ +extern struct gdb_file *stdio_fileopen (FILE *file); -/* deprecated - use gdb_file_delete */ -extern void gdb_fclose PARAMS ((GDB_FILE **)); +/* Open NAME returning a GDB_FILE. */ +extern GDB_FILE *gdb_fopen (char *name, char *mode); -extern void gdb_flush PARAMS ((GDB_FILE *)); +/* Create/open a memory based file. Can be used as a scratch + buffer for collecting output. */ +extern struct gdb_file *mem_fileopen (void); -extern GDB_FILE *gdb_fopen PARAMS ((char * name, char * mode)); +extern void gdb_flush (GDB_FILE *); -extern void fputs_filtered PARAMS ((const char *, GDB_FILE *)); +extern void gdb_file_delete (struct gdb_file *stream); -extern void fputs_unfiltered PARAMS ((const char *, GDB_FILE *)); +extern void gdb_file_rewind (struct gdb_file *stream); -extern int fputc_filtered PARAMS ((int c, GDB_FILE *)); +extern int gdb_file_isatty (GDB_FILE *); -extern int fputc_unfiltered PARAMS ((int c, GDB_FILE *)); +/* NOTE: copies left to right */ +extern void gdb_file_put (struct gdb_file *src, struct gdb_file *dest); -extern int putchar_unfiltered PARAMS ((int c)); +/* More generic printf like operations */ -extern void puts_filtered PARAMS ((const char *)); +extern void fputs_filtered (const char *, GDB_FILE *); -extern void puts_unfiltered PARAMS ((const char *)); +extern void fputs_unfiltered (const char *, GDB_FILE *); -extern void puts_debug PARAMS ((char *prefix, char *string, char *suffix)); +extern int fputc_filtered (int c, GDB_FILE *); -extern void vprintf_filtered PARAMS ((const char *, va_list)) - ATTR_FORMAT(printf, 1, 0); +extern int fputc_unfiltered (int c, GDB_FILE *); -extern void vfprintf_filtered PARAMS ((GDB_FILE *, const char *, va_list)) - ATTR_FORMAT(printf, 2, 0); +extern int putchar_unfiltered (int c); -extern void fprintf_filtered PARAMS ((GDB_FILE *, const char *, ...)) - ATTR_FORMAT(printf, 2, 3); +extern void puts_filtered (const char *); -extern void fprintfi_filtered PARAMS ((int, GDB_FILE *, const char *, ...)) - ATTR_FORMAT(printf, 3, 4); +extern void puts_unfiltered (const char *); -extern void printf_filtered PARAMS ((const char *, ...)) - ATTR_FORMAT(printf, 1, 2); +extern void puts_debug (char *prefix, char *string, char *suffix); -extern void printfi_filtered PARAMS ((int, const char *, ...)) - ATTR_FORMAT(printf, 2, 3); +extern void vprintf_filtered (const char *, va_list) ATTR_FORMAT (printf, 1, 0); -extern void vprintf_unfiltered PARAMS ((const char *, va_list)) - ATTR_FORMAT(printf, 1, 0); +extern void vfprintf_filtered (GDB_FILE *, const char *, va_list) ATTR_FORMAT (printf, 2, 0); -extern void vfprintf_unfiltered PARAMS ((GDB_FILE *, const char *, va_list)) - ATTR_FORMAT(printf, 2, 0); +extern void fprintf_filtered (GDB_FILE *, const char *, ...) ATTR_FORMAT (printf, 2, 3); -extern void fprintf_unfiltered PARAMS ((GDB_FILE *, const char *, ...)) - ATTR_FORMAT(printf, 2, 3); +extern void fprintfi_filtered (int, GDB_FILE *, const char *, ...) ATTR_FORMAT (printf, 3, 4); -extern void printf_unfiltered PARAMS ((const char *, ...)) - ATTR_FORMAT(printf, 1, 2); +extern void printf_filtered (const char *, ...) ATTR_FORMAT (printf, 1, 2); -extern int gdb_file_isatty PARAMS ((GDB_FILE *)); +extern void printfi_filtered (int, const char *, ...) ATTR_FORMAT (printf, 2, 3); -/* #if defined (TUI) */ -extern GDB_FILE *gdb_file_init_astring PARAMS ((int)); -/* #endif */ +extern void vprintf_unfiltered (const char *, va_list) ATTR_FORMAT (printf, 1, 0); -extern void gdb_file_deallocate PARAMS ((GDB_FILE **)); +extern void vfprintf_unfiltered (GDB_FILE *, const char *, va_list) ATTR_FORMAT (printf, 2, 0); -/* #if defined (TUI) */ -extern char *gdb_file_get_strbuf PARAMS ((GDB_FILE *)); -/* #endif */ +extern void fprintf_unfiltered (GDB_FILE *, const char *, ...) ATTR_FORMAT (printf, 2, 3); + +extern void printf_unfiltered (const char *, ...) ATTR_FORMAT (printf, 1, 2); /* #if defined (TUI) */ -extern void gdb_file_adjust_strbuf PARAMS ((int, GDB_FILE *)); +/* DEPRECATED: Only the TUI should use these methods. */ +extern GDB_FILE *gdb_file_init_astring (int); +extern struct gdb_file *tui_fileopen (FILE *); +extern struct gdb_file *tui_sfileopen (int); +extern void gdb_fclose (GDB_FILE **); +extern void gdb_file_deallocate (GDB_FILE **); +extern char *gdb_file_get_strbuf (GDB_FILE *); +extern void gdb_file_adjust_strbuf (int, GDB_FILE *); /* #endif */ -extern void print_spaces PARAMS ((int, GDB_FILE *)); +extern void print_spaces (int, GDB_FILE *); -extern void print_spaces_filtered PARAMS ((int, GDB_FILE *)); +extern void print_spaces_filtered (int, GDB_FILE *); -extern char *n_spaces PARAMS ((int)); +extern char *n_spaces (int); -extern void fputstr_filtered PARAMS ((const char *str, int quotr, GDB_FILE *stream)); +extern void fputstr_filtered (const char *str, int quotr, GDB_FILE * stream); -extern void fputstr_unfiltered PARAMS ((const char *str, int quotr, GDB_FILE *stream)); +extern void fputstr_unfiltered (const char *str, int quotr, GDB_FILE * stream); -extern void fputstrn_unfiltered PARAMS ((const char *str, int n, int quotr, GDB_FILE *stream)); +extern void fputstrn_unfiltered (const char *str, int n, int quotr, GDB_FILE * stream); /* Display the host ADDR on STREAM formatted as ``0x%x''. */ extern void gdb_print_host_address (void *addr, struct gdb_file *stream); @@ -511,72 +499,81 @@ extern void gdb_print_host_address (void *addr, struct gdb_file *stream); paddr_nz() is like %lx. paddr_u() is like %lu. paddr_width() is for ``%*''. */ extern int strlen_paddr (void); -extern char* paddr (CORE_ADDR addr); -extern char* paddr_nz (CORE_ADDR addr); -extern char* paddr_u (CORE_ADDR addr); -extern char* paddr_d (LONGEST addr); +extern char *paddr (CORE_ADDR addr); +extern char *paddr_nz (CORE_ADDR addr); +extern char *paddr_u (CORE_ADDR addr); +extern char *paddr_d (LONGEST addr); typedef bfd_vma t_reg; -extern char* preg (t_reg reg); -extern char* preg_nz (t_reg reg); +extern char *preg (t_reg reg); +extern char *preg_nz (t_reg reg); -extern void fprintf_symbol_filtered PARAMS ((GDB_FILE *, char *, - enum language, int)); +extern void fprintf_symbol_filtered (GDB_FILE *, char *, + enum language, int); -extern NORETURN void perror_with_name PARAMS ((char *)) ATTR_NORETURN; +extern NORETURN void perror_with_name (char *) ATTR_NORETURN; -extern void print_sys_errmsg PARAMS ((char *, int)); +extern void print_sys_errmsg (char *, int); /* From regex.c or libc. BSD 4.4 declares this with the argument type as "const char *" in unistd.h, so we can't declare the argument as "char *". */ -extern char *re_comp PARAMS ((const char *)); +extern char *re_comp (const char *); /* From symfile.c */ -extern void symbol_file_command PARAMS ((char *, int)); +extern void symbol_file_command (char *, int); + +/* Remote targets may wish to use this as their load function. */ +extern void generic_load (char *name, int from_tty); + +/* Summarise a download */ +extern void print_transfer_performance (struct gdb_file *stream, + unsigned long data_count, + unsigned long write_count, + unsigned long time_count); /* From top.c */ typedef void initialize_file_ftype (void); -extern char *skip_quoted PARAMS ((char *)); +extern char *skip_quoted (char *); -extern char *gdb_readline PARAMS ((char *)); +extern char *gdb_readline (char *); -extern char *command_line_input PARAMS ((char *, int, char *)); +extern char *command_line_input (char *, int, char *); -extern void print_prompt PARAMS ((void)); +extern void print_prompt (void); -extern int input_from_terminal_p PARAMS ((void)); +extern int input_from_terminal_p (void); extern int info_verbose; /* From printcmd.c */ -extern void set_next_address PARAMS ((CORE_ADDR)); +extern void set_next_address (CORE_ADDR); -extern void print_address_symbolic PARAMS ((CORE_ADDR, GDB_FILE *, int, - char *)); +extern void print_address_symbolic (CORE_ADDR, GDB_FILE *, int, + char *); -extern void print_address_numeric PARAMS ((CORE_ADDR, int, GDB_FILE *)); +extern void print_address_numeric (CORE_ADDR, int, GDB_FILE *); -extern void print_address PARAMS ((CORE_ADDR, GDB_FILE *)); +extern void print_address (CORE_ADDR, GDB_FILE *); /* From source.c */ -extern int openp PARAMS ((char *, int, char *, int, int, char **)); +extern int openp (char *, int, char *, int, int, char **); -extern int source_full_path_of PARAMS ((char *, char **)); +extern int source_full_path_of (char *, char **); -extern void mod_path PARAMS ((char *, char **)); +extern void mod_path (char *, char **); -extern void directory_command PARAMS ((char *, int)); +extern void directory_command (char *, int); -extern void init_source_path PARAMS ((void)); +extern void init_source_path (void); -extern char *symtab_to_filename PARAMS ((struct symtab *)); +extern char *symtab_to_filename (struct symtab *); /* From exec.c */ @@ -586,7 +583,7 @@ extern void exec_set_section_offsets (bfd_signed_vma text_off, /* From findvar.c */ -extern int read_relative_register_raw_bytes PARAMS ((int, char *)); +extern int read_relative_register_raw_bytes (int, char *); /* Possible lvalue types. Like enum language, this should be in value.h, but needs to be here for the same reason. */ @@ -611,50 +608,50 @@ enum lval_type struct frame_info; -void default_get_saved_register PARAMS ((char *raw_buffer, int *optimized, - CORE_ADDR *addrp, - struct frame_info *frame, int regnum, - enum lval_type *lval)); +void default_get_saved_register (char *raw_buffer, int *optimized, + CORE_ADDR * addrp, + struct frame_info *frame, int regnum, + enum lval_type *lval); /* From readline (but not in any readline .h files). */ -extern char *tilde_expand PARAMS ((char *)); +extern char *tilde_expand (char *); /* Control types for commands */ enum misc_command_type -{ - ok_command, - end_command, - else_command, - nop_command -}; + { + ok_command, + end_command, + else_command, + nop_command + }; enum command_control_type -{ - simple_control, - break_control, - continue_control, - while_control, - if_control, - invalid_control -}; + { + simple_control, + break_control, + continue_control, + while_control, + if_control, + invalid_control + }; /* Structure for saved commands lines (for breakpoints, defined commands, etc). */ struct command_line -{ - struct command_line *next; - char *line; - enum command_control_type control_type; - int body_count; - struct command_line **body_list; -}; + { + struct command_line *next; + char *line; + enum command_control_type control_type; + int body_count; + struct command_line **body_list; + }; -extern struct command_line *read_command_lines PARAMS ((char *, int)); +extern struct command_line *read_command_lines (char *, int); -extern void free_command_lines PARAMS ((struct command_line **)); +extern void free_command_lines (struct command_line **); /* To continue the execution commands when running gdb asynchronously. A continuation structure contains a pointer to a function to be called @@ -663,27 +660,27 @@ extern void free_command_lines PARAMS ((struct command_line **)); when opening an extended-remote connection. */ struct continuation_arg -{ - struct continuation_arg *next; - PTR data; -}; + { + struct continuation_arg *next; + PTR data; + }; struct continuation -{ - void (*continuation_hook) PARAMS ((struct continuation_arg *)); - struct continuation_arg *arg_list; - struct continuation *next; -} -continuation; + { + void (*continuation_hook) (struct continuation_arg *); + struct continuation_arg *arg_list; + struct continuation *next; + }; +struct continuation continuation; /* In infrun.c. */ extern struct continuation *cmd_continuation; /* From utils.c */ -extern void add_continuation PARAMS ((void (*) PARAMS ((struct continuation_arg *)), - struct continuation_arg *)); -extern void do_all_continuations PARAMS ((void)); -extern void discard_all_continuations PARAMS ((void)); +extern void add_continuation (void (*)(struct continuation_arg *), + struct continuation_arg *); +extern void do_all_continuations (void); +extern void discard_all_continuations (void); /* String containing the current directory (what getwd would return). */ @@ -700,14 +697,14 @@ extern unsigned output_radix; value.h. */ enum val_prettyprint -{ - Val_no_prettyprint = 0, - Val_prettyprint, - /* Use the default setting which the user has specified. */ - Val_pretty_default -}; - + { + Val_no_prettyprint = 0, + Val_prettyprint, + /* Use the default setting which the user has specified. */ + Val_pretty_default + }; + /* Host machine definition. This will be a symlink to one of the xm-*.h files, built by the `configure' script. */ @@ -747,11 +744,11 @@ enum val_prettyprint #ifndef volatile #ifndef __STDC__ -# ifdef __GNUC__ -# define volatile __volatile__ -# else -# define volatile /*nothing*/ -# endif /* GNUC */ +#ifdef __GNUC__ +#define volatile __volatile__ +#else +#define volatile /* nothing */ +#endif /* GNUC */ #endif /* STDC */ #endif /* volatile */ @@ -759,11 +756,11 @@ enum val_prettyprint FIXME: Assumes 2's complement arithmetic */ #if !defined (UINT_MAX) -#define UINT_MAX ((unsigned int)(~0)) /* 0xFFFFFFFF for 32-bits */ +#define UINT_MAX ((unsigned int)(~0)) /* 0xFFFFFFFF for 32-bits */ #endif #if !defined (INT_MAX) -#define INT_MAX ((int)(UINT_MAX >> 1)) /* 0x7FFFFFFF for 32-bits */ +#define INT_MAX ((int)(UINT_MAX >> 1)) /* 0x7FFFFFFF for 32-bits */ #endif #if !defined (INT_MIN) @@ -782,30 +779,30 @@ enum val_prettyprint arguments to a function, number in a value history, register number, etc.) where the value must not be larger than can fit in an int. */ -extern int longest_to_int PARAMS ((LONGEST)); +extern int longest_to_int (LONGEST); /* Assorted functions we can declare, now that const and volatile are defined. */ -extern char *savestring PARAMS ((const char *, int)); - -extern char *msavestring PARAMS ((void *, const char *, int)); +extern char *savestring (const char *, int); -extern char *strsave PARAMS ((const char *)); +extern char *msavestring (void *, const char *, int); -extern char *mstrsave PARAMS ((void *, const char *)); +extern char *strsave (const char *); -#ifdef _MSC_VER /* FIXME; was long, but this causes compile errors in msvc if already defined */ -extern PTR xmmalloc PARAMS ((PTR, size_t)); +extern char *mstrsave (void *, const char *); -extern PTR xmrealloc PARAMS ((PTR, PTR, size_t)); +/* FIXME; was long, but this causes compile errors in msvc if already + defined */ +#ifdef _MSC_VER +extern PTR xmmalloc (PTR, size_t); +extern PTR xmrealloc (PTR, PTR, size_t); #else -extern PTR xmmalloc PARAMS ((PTR, long)); - -extern PTR xmrealloc PARAMS ((PTR, PTR, long)); +extern PTR xmmalloc (PTR, long); +extern PTR xmrealloc (PTR, PTR, long); #endif -extern int parse_escape PARAMS ((char **)); +extern int parse_escape (char **); /* Message to be printed before the error message, when an error occurs. */ @@ -819,26 +816,27 @@ extern char *quit_pre_print; extern char *warning_pre_print; -extern NORETURN void error PARAMS((const char *, ...)) ATTR_NORETURN; +extern NORETURN void error (const char *, ...) ATTR_NORETURN; -extern void error_begin PARAMS ((void)); +extern void error_begin (void); extern NORETURN void internal_error (char *, ...) ATTR_NORETURN; -extern NORETURN void error_stream PARAMS ((GDB_FILE *)) ATTR_NORETURN; +extern NORETURN void error_stream (GDB_FILE *) ATTR_NORETURN; -extern char *error_last_message PARAMS ((void)); +extern char *error_last_message (void); -extern NORETURN void nomem PARAMS ((long)) ATTR_NORETURN; +extern NORETURN void nomem (long) ATTR_NORETURN; /* Reasons for calling return_to_top_level. */ -enum return_reason { - /* User interrupt. */ - RETURN_QUIT, - /* Any other error. */ - RETURN_ERROR -}; +enum return_reason + { + /* User interrupt. */ + RETURN_QUIT, + /* Any other error. */ + RETURN_ERROR + }; #define ALL_CLEANUPS ((struct cleanup *)0) @@ -847,23 +845,21 @@ enum return_reason { #define RETURN_MASK_ALL (RETURN_MASK_QUIT | RETURN_MASK_ERROR) typedef int return_mask; -extern NORETURN void -return_to_top_level PARAMS ((enum return_reason)) ATTR_NORETURN; +extern NORETURN void return_to_top_level (enum return_reason) ATTR_NORETURN; -typedef int (catch_errors_ftype) PARAMS ((PTR)); -extern int catch_errors PARAMS ((catch_errors_ftype *, PTR, char *, return_mask)); +typedef int (catch_errors_ftype) (PTR); +extern int catch_errors (catch_errors_ftype *, PTR, char *, return_mask); -extern void warning_begin PARAMS ((void)); +extern void warning_begin (void); -extern void warning PARAMS ((const char *, ...)) - ATTR_FORMAT(printf, 1, 2); +extern void warning (const char *, ...) ATTR_FORMAT (printf, 1, 2); /* Global functions from other, non-gdb GNU thingies. Libiberty thingies are no longer declared here. We include libiberty.h above, instead. */ #ifndef GETENV_PROVIDED -extern char *getenv PARAMS ((const char *)); +extern char *getenv (const char *); #endif /* From other system libraries */ @@ -894,11 +890,11 @@ extern char *getenv PARAMS ((const char *)); somewhere. */ #ifndef FCLOSE_PROVIDED -extern int fclose PARAMS ((FILE *)); +extern int fclose (FILE *); #endif #ifndef atof -extern double atof PARAMS ((const char *)); /* X3.159-1989 4.10.1.1 */ +extern double atof (const char *); /* X3.159-1989 4.10.1.1 */ #endif #ifndef MALLOC_INCOMPATIBLE @@ -919,27 +915,27 @@ extern void free (); /* Various possibilities for alloca. */ #ifndef alloca -# ifdef __GNUC__ -# define alloca __builtin_alloca -# else /* Not GNU C */ -# ifdef HAVE_ALLOCA_H -# include <alloca.h> -# else -# ifdef _AIX - #pragma alloca -# else +#ifdef __GNUC__ +#define alloca __builtin_alloca +#else /* Not GNU C */ +#ifdef HAVE_ALLOCA_H +#include <alloca.h> +#else +#ifdef _AIX +#pragma alloca +#else /* We need to be careful not to declare this in a way which conflicts with bison. Bison never declares it as char *, but under various circumstances (like __hpux) we need to use void *. */ -# if defined (__STDC__) || defined (__hpux) - extern void *alloca (); -# else /* Don't use void *. */ - extern char *alloca (); -# endif /* Don't use void *. */ -# endif /* Not _AIX */ -# endif /* Not HAVE_ALLOCA_H */ -# endif /* Not GNU C */ +#if defined (__STDC__) || defined (__hpux) +extern void *alloca (); +#else /* Don't use void *. */ +extern char *alloca (); +#endif /* Don't use void *. */ +#endif /* Not _AIX */ +#endif /* Not HAVE_ALLOCA_H */ +#endif /* Not GNU C */ #endif /* alloca not defined */ /* HOST_BYTE_ORDER must be defined to one of these. */ @@ -1028,19 +1024,19 @@ extern void free (); /* In findvar.c. */ -extern LONGEST extract_signed_integer PARAMS ((void *, int)); +extern LONGEST extract_signed_integer (void *, int); -extern ULONGEST extract_unsigned_integer PARAMS ((void *, int)); +extern ULONGEST extract_unsigned_integer (void *, int); -extern int extract_long_unsigned_integer PARAMS ((void *, int, LONGEST *)); +extern int extract_long_unsigned_integer (void *, int, LONGEST *); -extern CORE_ADDR extract_address PARAMS ((void *, int)); +extern CORE_ADDR extract_address (void *, int); -extern void store_signed_integer PARAMS ((PTR, int, LONGEST)); +extern void store_signed_integer (PTR, int, LONGEST); -extern void store_unsigned_integer PARAMS ((PTR, int, ULONGEST)); +extern void store_unsigned_integer (PTR, int, ULONGEST); -extern void store_address PARAMS ((PTR, int, LONGEST)); +extern void store_address (PTR, int, LONGEST); /* Setup definitions for host and target floating point formats. We need to consider the format for `float', `double', and `long double' for both target @@ -1055,19 +1051,19 @@ extern void store_address PARAMS ((PTR, int, LONGEST)); extern const struct floatformat floatformat_unknown; #if HOST_BYTE_ORDER == BIG_ENDIAN -# ifndef HOST_FLOAT_FORMAT -# define HOST_FLOAT_FORMAT &floatformat_ieee_single_big -# endif -# ifndef HOST_DOUBLE_FORMAT -# define HOST_DOUBLE_FORMAT &floatformat_ieee_double_big -# endif -#else /* LITTLE_ENDIAN */ -# ifndef HOST_FLOAT_FORMAT -# define HOST_FLOAT_FORMAT &floatformat_ieee_single_little -# endif -# ifndef HOST_DOUBLE_FORMAT -# define HOST_DOUBLE_FORMAT &floatformat_ieee_double_little -# endif +#ifndef HOST_FLOAT_FORMAT +#define HOST_FLOAT_FORMAT &floatformat_ieee_single_big +#endif +#ifndef HOST_DOUBLE_FORMAT +#define HOST_DOUBLE_FORMAT &floatformat_ieee_double_big +#endif +#else /* LITTLE_ENDIAN */ +#ifndef HOST_FLOAT_FORMAT +#define HOST_FLOAT_FORMAT &floatformat_ieee_single_little +#endif +#ifndef HOST_DOUBLE_FORMAT +#define HOST_DOUBLE_FORMAT &floatformat_ieee_double_little +#endif #endif #ifndef HOST_LONG_DOUBLE_FORMAT @@ -1086,7 +1082,7 @@ extern const struct floatformat floatformat_unknown; #endif #ifndef TARGET_LONG_DOUBLE_FORMAT -# define TARGET_LONG_DOUBLE_FORMAT &floatformat_unknown +#define TARGET_LONG_DOUBLE_FORMAT &floatformat_unknown #endif /* Use `long double' if the host compiler supports it. (Note that this is not @@ -1104,13 +1100,13 @@ typedef long double DOUBLEST; typedef double DOUBLEST; #endif -extern void floatformat_to_doublest PARAMS ((const struct floatformat *, - char *, DOUBLEST *)); -extern void floatformat_from_doublest PARAMS ((const struct floatformat *, - DOUBLEST *, char *)); -extern DOUBLEST extract_floating PARAMS ((void *, int)); +extern void floatformat_to_doublest (const struct floatformat *, + char *, DOUBLEST *); +extern void floatformat_from_doublest (const struct floatformat *, + DOUBLEST *, char *); +extern DOUBLEST extract_floating (void *, int); -extern void store_floating PARAMS ((void *, int, DOUBLEST)); +extern void store_floating (void *, int, DOUBLEST); /* On some machines there are bits in addresses which are not really part of the address, but are used by the kernel, the hardware, etc. @@ -1127,9 +1123,9 @@ extern void store_floating PARAMS ((void *, int, DOUBLEST)); /* From valops.c */ -extern CORE_ADDR push_bytes PARAMS ((CORE_ADDR, char *, int)); +extern CORE_ADDR push_bytes (CORE_ADDR, char *, int); -extern CORE_ADDR push_word PARAMS ((CORE_ADDR, ULONGEST)); +extern CORE_ADDR push_word (CORE_ADDR, ULONGEST); extern int watchdog; @@ -1140,42 +1136,46 @@ struct cmd_list_element; /* Should the asynchronous variant of the interpreter (using the event-loop) be enabled? */ extern int event_loop_p; - -extern void (*init_ui_hook) PARAMS ((char *argv0)); -extern void (*command_loop_hook) PARAMS ((void)); -extern void (*fputs_unfiltered_hook) PARAMS ((const char *linebuffer, - GDB_FILE *stream)); -extern void (*print_frame_info_listing_hook) PARAMS ((struct symtab *s, - int line, int stopline, - int noerror)); -extern struct frame_info *parse_frame_specification PARAMS ((char *frame_exp)); -extern int (*query_hook) PARAMS ((const char *, va_list)); -extern void (*warning_hook) PARAMS ((const char *, va_list)); -extern void (*flush_hook) PARAMS ((GDB_FILE *stream)); -extern void (*create_breakpoint_hook) PARAMS ((struct breakpoint *b)); -extern void (*delete_breakpoint_hook) PARAMS ((struct breakpoint *bpt)); -extern void (*modify_breakpoint_hook) PARAMS ((struct breakpoint *bpt)); -extern void (*interactive_hook) PARAMS ((void)); -extern void (*registers_changed_hook) PARAMS ((void)); -extern void (*readline_begin_hook) PARAMS ((char *, ...)); -extern char * (*readline_hook) PARAMS ((char *)); -extern void (*readline_end_hook) PARAMS ((void)); -extern void (*register_changed_hook) PARAMS ((int regno)); -extern void (*memory_changed_hook) PARAMS ((CORE_ADDR addr, int len)); -extern void (*context_hook) PARAMS ((int)); -extern int (*target_wait_hook) PARAMS ((int pid, - struct target_waitstatus *status)); - -extern void (*attach_hook) PARAMS ((void)); -extern void (*detach_hook) PARAMS ((void)); -extern void (*call_command_hook) PARAMS ((struct cmd_list_element *c, - char *cmd, int from_tty)); - -extern void (*set_hook) PARAMS ((struct cmd_list_element *c)); - -extern NORETURN void (*error_hook) PARAMS ((void)) ATTR_NORETURN; - -extern void (*error_begin_hook) PARAMS ((void)); + +extern void (*init_ui_hook) (char *argv0); +extern void (*command_loop_hook) (void); +/* NOTE: cagney/1999-10-14: fputs_unfiltered_hook is deprecated. + Instead code wanting to control GDB's output should be overriding + the gdb_std* files. */ +extern void (*fputs_unfiltered_hook) (const char *linebuffer, + GDB_FILE * stream); +extern void (*print_frame_info_listing_hook) (struct symtab * s, + int line, int stopline, + int noerror); +extern struct frame_info *parse_frame_specification (char *frame_exp); +extern int (*query_hook) (const char *, va_list); +extern void (*warning_hook) (const char *, va_list); +extern void (*flush_hook) (GDB_FILE * stream); +extern void (*create_breakpoint_hook) (struct breakpoint * b); +extern void (*delete_breakpoint_hook) (struct breakpoint * bpt); +extern void (*modify_breakpoint_hook) (struct breakpoint * bpt); +extern void (*interactive_hook) (void); +extern void (*registers_changed_hook) (void); +extern void (*readline_begin_hook) (char *,...); +extern char *(*readline_hook) (char *); +extern void (*readline_end_hook) (void); +extern void (*register_changed_hook) (int regno); +extern void (*memory_changed_hook) (CORE_ADDR addr, int len); +extern void (*context_hook) (int); +extern int (*target_wait_hook) (int pid, struct target_waitstatus * status); + +extern void (*attach_hook) (void); +extern void (*detach_hook) (void); +extern void (*call_command_hook) (struct cmd_list_element * c, + char *cmd, int from_tty); + +extern void (*set_hook) (struct cmd_list_element * c); + +extern NORETURN void (*error_hook) (void) ATTR_NORETURN; + +extern void (*error_begin_hook) (void); + +extern int (*ui_load_progress_hook) (const char *section, unsigned long num); /* Inhibit window interface if non-zero. */ diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index 077da82b5da..cfb80b494df 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,13 @@ +1999-10-15 Kevin Buettner <kevinb@cygnus.com> + + * gdbint.texinfo (MEMORY_INSERT_BREAKPOINT, + MEMORY_REMOVE_BREAKPOINT): Document. + +Thu Oct 14 21:17:17 1999 Andrew Cagney <cagney@b1.cygnus.com> + + * gdb.texinfo (remote): Document how GDB ignores the qOffsets BSS + offset re-using the DATA offset instead. + 1999-10-11 Jim Kingdon <kingdon@redhat.com> * gdbint.texinfo (Target Architecture Definition): Add PARM_BOUNDARY. diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 9a257e6cd97..316d58c3142 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -9226,7 +9226,11 @@ digits). See @code{remote.c:parse_threadlist_response()}. @item query sect offs @tab @code{q}@code{Offsets} -@tab Get section offsets. +@tab +Get section offsets that the target used when re-locating the downloaded +image. @emph{Note: while a @code{Bss} offset is included in the +response, @value{GDBN} ignores this and instead applies the @code{Data} +offset to the @code{Bss} section.} @item @tab reply @code{Text=}@var{xxx}@code{;Data=}@var{yyy}@code{;Bss=}@var{zzz} diff --git a/gdb/doc/gdbint.texinfo b/gdb/doc/gdbint.texinfo index 0115375e3fa..25666c39c2a 100644 --- a/gdb/doc/gdbint.texinfo +++ b/gdb/doc/gdbint.texinfo @@ -1239,6 +1239,23 @@ instruction of the architecture. Replaces all the other @var{BREAKPOINT} macros. +@item MEMORY_INSERT_BREAKPOINT (addr, contents_cache) +@item MEMORY_REMOVE_BREAKPOINT (addr, contents_cache) + +Insert or remove memory based breakpoints. Reasonable defaults +(@code{default_memory_insert_breakpoint} and +@code{default_memory_remove_breakpoint} respectively) have been +provided so that it is not necessary to define these for most +architectures. Architectures which may want to define +@var{MEMORY_INSERT_BREAKPOINT} and @var{MEMORY_REMOVE_BREAKPOINT} will +likely have instructions that are oddly sized or are not stored in a +conventional manner. + +It may also be desirable (from an efficiency standpoint) to define +custom breakpoint insertion and removal routines if +@var{BREAKPOINT_FROM_PC} needs to read the target's memory for some +reason. + @item CALL_DUMMY_P A C expresson that is non-zero when the target suports inferior function calls. diff --git a/gdb/dsrec.c b/gdb/dsrec.c index 76e32ab2ba6..b51d857daef 100644 --- a/gdb/dsrec.c +++ b/gdb/dsrec.c @@ -23,7 +23,6 @@ #include "srec.h" #include <time.h> -int (*ui_load_progress_hook) PARAMS ((char *, unsigned long)); extern void report_transfer_performance PARAMS ((unsigned long, time_t, time_t)); extern int remote_debug; diff --git a/gdb/eval.c b/gdb/eval.c index 30bb04f63d9..44e173ac642 100644 --- a/gdb/eval.c +++ b/gdb/eval.c @@ -892,9 +892,12 @@ evaluate_subexp_standard (expect_type, exp, pos, noside) argvec[1] = arg2; argvec[0] = arg1; } - else + else if (op == OP_VAR_VALUE) { /* Non-member function being called */ + /* fn: This can only be done for C++ functions. A C-style function + in a C++ program, for instance, does not have the fields that + are expected here */ if (overload_resolution && (exp->language_defn->la_language == language_cplus)) { @@ -908,11 +911,11 @@ evaluate_subexp_standard (expect_type, exp, pos, noside) (void) find_overload_match (arg_types, nargs, NULL /* no need for name */ , 0 /* not method */ , 0 /* strict match */ , - NULL, exp->elts[5].symbol /* the function */ , + NULL, exp->elts[save_pos1+2].symbol /* the function */ , NULL, &symp, NULL); /* Now fix the expression being evaluated */ - exp->elts[5].symbol = symp; + exp->elts[save_pos1+2].symbol = symp; argvec[0] = evaluate_subexp_with_coercion (exp, &save_pos1, noside); } else @@ -921,6 +924,11 @@ evaluate_subexp_standard (expect_type, exp, pos, noside) /* nothing to be done; argvec already correctly set up */ } } + else + { + /* It is probably a C-style function */ + /* nothing to be done; argvec already correctly set up */ + } do_call_it: diff --git a/gdb/gdb-events.sh b/gdb/gdb-events.sh index ab70bb19d06..5854e8439d3 100755 --- a/gdb/gdb-events.sh +++ b/gdb/gdb-events.sh @@ -77,7 +77,6 @@ f:void:breakpoint_modify:int b:b #*:void:print_frame_info_listing_hook:struct symtab *s, int line, int stopline, int noerror:s, line, stopline, noerror #*:int:query_hook:const char *query, va_list args:query, args #*:void:warning_hook:const char *string, va_list args:string, args -#*:void:flush_hook:GDB_FILE *stream:stream #*:void:target_output_hook:char *b:b #*:void:interactive_hook:void #*:void:registers_changed_hook:void diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c index 17870d0e1c6..54fd44469ba 100644 --- a/gdb/gdbarch.c +++ b/gdb/gdbarch.c @@ -192,6 +192,8 @@ struct gdbarch gdbarch_skip_prologue_ftype *skip_prologue; gdbarch_inner_than_ftype *inner_than; gdbarch_breakpoint_from_pc_ftype *breakpoint_from_pc; + gdbarch_memory_insert_breakpoint_ftype *memory_insert_breakpoint; + gdbarch_memory_remove_breakpoint_ftype *memory_remove_breakpoint; CORE_ADDR decr_pc_after_break; CORE_ADDR function_start_offset; gdbarch_remote_translate_xfer_address_ftype *remote_translate_xfer_address; @@ -300,6 +302,8 @@ struct gdbarch default_gdbarch = { 0, 0, 0, + 0, + 0, /* default_gdbarch() */ }; struct gdbarch *current_gdbarch = &default_gdbarch; @@ -336,6 +340,8 @@ gdbarch_alloc (const struct gdbarch_info *info, gdbarch->call_dummy_length = -1; gdbarch->call_dummy_p = -1; gdbarch->call_dummy_stack_adjust_p = -1; + gdbarch->memory_insert_breakpoint = default_memory_insert_breakpoint; + gdbarch->memory_remove_breakpoint = default_memory_remove_breakpoint; gdbarch->decr_pc_after_break = -1; gdbarch->function_start_offset = -1; gdbarch->frame_args_skip = -1; @@ -549,6 +555,12 @@ verify_gdbarch (struct gdbarch *gdbarch) && (gdbarch->breakpoint_from_pc == 0)) internal_error ("gdbarch: verify_gdbarch: breakpoint_from_pc invalid"); if ((GDB_MULTI_ARCH >= 2) + && (0)) + internal_error ("gdbarch: verify_gdbarch: memory_insert_breakpoint invalid"); + if ((GDB_MULTI_ARCH >= 2) + && (0)) + internal_error ("gdbarch: verify_gdbarch: memory_remove_breakpoint invalid"); + if ((GDB_MULTI_ARCH >= 2) && (gdbarch->decr_pc_after_break == -1)) internal_error ("gdbarch: verify_gdbarch: decr_pc_after_break invalid"); if ((GDB_MULTI_ARCH >= 2) @@ -845,6 +857,14 @@ gdbarch_dump (void) (long) current_gdbarch->breakpoint_from_pc /*BREAKPOINT_FROM_PC ()*/); fprintf_unfiltered (gdb_stdlog, + "gdbarch_update: MEMORY_INSERT_BREAKPOINT = 0x%08lx\n", + (long) current_gdbarch->memory_insert_breakpoint + /*MEMORY_INSERT_BREAKPOINT ()*/); + fprintf_unfiltered (gdb_stdlog, + "gdbarch_update: MEMORY_REMOVE_BREAKPOINT = 0x%08lx\n", + (long) current_gdbarch->memory_remove_breakpoint + /*MEMORY_REMOVE_BREAKPOINT ()*/); + fprintf_unfiltered (gdb_stdlog, "gdbarch_update: DECR_PC_AFTER_BREAK = %ld\n", (long) DECR_PC_AFTER_BREAK); fprintf_unfiltered (gdb_stdlog, @@ -2117,6 +2137,42 @@ set_gdbarch_breakpoint_from_pc (struct gdbarch *gdbarch, gdbarch->breakpoint_from_pc = breakpoint_from_pc; } +int +gdbarch_memory_insert_breakpoint (struct gdbarch *gdbarch, CORE_ADDR addr, char *contents_cache) +{ + if (gdbarch->memory_insert_breakpoint == 0) + internal_error ("gdbarch: gdbarch_memory_insert_breakpoint invalid"); + if (gdbarch_debug >= 2) + /* FIXME: gdb_std??? */ + fprintf_unfiltered (gdb_stdlog, "gdbarch_memory_insert_breakpoint called\n"); + return gdbarch->memory_insert_breakpoint (addr, contents_cache); +} + +void +set_gdbarch_memory_insert_breakpoint (struct gdbarch *gdbarch, + gdbarch_memory_insert_breakpoint_ftype memory_insert_breakpoint) +{ + gdbarch->memory_insert_breakpoint = memory_insert_breakpoint; +} + +int +gdbarch_memory_remove_breakpoint (struct gdbarch *gdbarch, CORE_ADDR addr, char *contents_cache) +{ + if (gdbarch->memory_remove_breakpoint == 0) + internal_error ("gdbarch: gdbarch_memory_remove_breakpoint invalid"); + if (gdbarch_debug >= 2) + /* FIXME: gdb_std??? */ + fprintf_unfiltered (gdb_stdlog, "gdbarch_memory_remove_breakpoint called\n"); + return gdbarch->memory_remove_breakpoint (addr, contents_cache); +} + +void +set_gdbarch_memory_remove_breakpoint (struct gdbarch *gdbarch, + gdbarch_memory_remove_breakpoint_ftype memory_remove_breakpoint) +{ + gdbarch->memory_remove_breakpoint = memory_remove_breakpoint; +} + CORE_ADDR gdbarch_decr_pc_after_break (struct gdbarch *gdbarch) { diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h index 72cef37f78e..95776adf6fc 100644 --- a/gdb/gdbarch.h +++ b/gdb/gdbarch.h @@ -673,6 +673,24 @@ extern void set_gdbarch_breakpoint_from_pc (struct gdbarch *gdbarch, gdbarch_bre #endif #endif +typedef int (gdbarch_memory_insert_breakpoint_ftype) (CORE_ADDR addr, char *contents_cache); +extern int gdbarch_memory_insert_breakpoint (struct gdbarch *gdbarch, CORE_ADDR addr, char *contents_cache); +extern void set_gdbarch_memory_insert_breakpoint (struct gdbarch *gdbarch, gdbarch_memory_insert_breakpoint_ftype *memory_insert_breakpoint); +#if GDB_MULTI_ARCH +#if (GDB_MULTI_ARCH > 1) || !defined (MEMORY_INSERT_BREAKPOINT) +#define MEMORY_INSERT_BREAKPOINT(addr, contents_cache) (gdbarch_memory_insert_breakpoint (current_gdbarch, addr, contents_cache)) +#endif +#endif + +typedef int (gdbarch_memory_remove_breakpoint_ftype) (CORE_ADDR addr, char *contents_cache); +extern int gdbarch_memory_remove_breakpoint (struct gdbarch *gdbarch, CORE_ADDR addr, char *contents_cache); +extern void set_gdbarch_memory_remove_breakpoint (struct gdbarch *gdbarch, gdbarch_memory_remove_breakpoint_ftype *memory_remove_breakpoint); +#if GDB_MULTI_ARCH +#if (GDB_MULTI_ARCH > 1) || !defined (MEMORY_REMOVE_BREAKPOINT) +#define MEMORY_REMOVE_BREAKPOINT(addr, contents_cache) (gdbarch_memory_remove_breakpoint (current_gdbarch, addr, contents_cache)) +#endif +#endif + extern CORE_ADDR gdbarch_decr_pc_after_break (struct gdbarch *gdbarch); extern void set_gdbarch_decr_pc_after_break (struct gdbarch *gdbarch, CORE_ADDR decr_pc_after_break); #if GDB_MULTI_ARCH diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh index cf9650f8ee4..7da02047af4 100755 --- a/gdb/gdbarch.sh +++ b/gdb/gdbarch.sh @@ -208,6 +208,8 @@ f:2:INIT_EXTRA_FRAME_INFO:void:init_extra_frame_info:int fromleaf, struct frame_ f:2:SKIP_PROLOGUE:CORE_ADDR:skip_prologue:CORE_ADDR ip:ip::0:0 f:2:INNER_THAN:int:inner_than:CORE_ADDR lhs, CORE_ADDR rhs:lhs, rhs::0:0 f:2:BREAKPOINT_FROM_PC:unsigned char *:breakpoint_from_pc:CORE_ADDR *pcptr, int *lenptr:pcptr, lenptr::0:0 +f:2:MEMORY_INSERT_BREAKPOINT:int:memory_insert_breakpoint:CORE_ADDR addr, char *contents_cache:addr, contents_cache::0:default_memory_insert_breakpoint:0 +f:2:MEMORY_REMOVE_BREAKPOINT:int:memory_remove_breakpoint:CORE_ADDR addr, char *contents_cache:addr, contents_cache::0:default_memory_remove_breakpoint:0 v:2:DECR_PC_AFTER_BREAK:CORE_ADDR:decr_pc_after_break::::0:-1 v:2:FUNCTION_START_OFFSET:CORE_ADDR:function_start_offset::::0:-1 # diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c index ae44fbd5c4b..ffed1e6e2e8 100644 --- a/gdb/gdbtypes.c +++ b/gdb/gdbtypes.c @@ -65,6 +65,7 @@ struct type *builtin_type_uint32; struct type *builtin_type_int64; struct type *builtin_type_uint64; struct type *builtin_type_bool; +struct type *builtin_type_v4sf; int opaque_type_resolution = 1; @@ -633,6 +634,43 @@ create_set_type (result_type, domain_type) return (result_type); } + +/* Construct and return a type of the form: + struct NAME { ELT_TYPE ELT_NAME[N]; } + We use these types for SIMD registers. For example, the type of + the SSE registers on the late x86-family processors is: + struct __builtin_v4sf { float f[4]; } + built by the function call: + init_simd_type ("__builtin_v4sf", builtin_type_float, "f", 4) + The type returned is a permanent type, allocated using malloc; it + doesn't live in any objfile's obstack. */ +struct type * +init_simd_type (char *name, + struct type *elt_type, + char *elt_name, + int n) +{ + struct type *t; + struct field *f; + + /* Build the field structure. */ + f = xmalloc (sizeof (*f)); + memset (f, 0, sizeof (*f)); + f->loc.bitpos = 0; + f->type = create_array_type (0, elt_type, + create_range_type (0, builtin_type_int, 0, n)); + f->name = elt_name; + + /* Build a struct type with that field. */ + t = init_type (TYPE_CODE_STRUCT, n * TYPE_LENGTH (elt_type), 0, 0, 0); + t->nfields = 1; + t->fields = f; + t->tag_name = name; + + return t; +} + + /* Smash TYPE to be a type of members of DOMAIN with type TO_TYPE. A MEMBER is a wierd thing -- it amounts to a typed offset into a struct, e.g. "an int at offset 8". A MEMBER TYPE doesn't @@ -2925,6 +2963,10 @@ build_gdbtypes () &showlist); opaque_type_resolution = 1; + + /* Build SIMD types. */ + builtin_type_v4sf + = init_simd_type ("__builtin_v4sf", builtin_type_float, "f", 4); } @@ -2963,5 +3005,6 @@ _initialize_gdbtypes () register_gdbarch_swap (&builtin_type_uint32, sizeof (struct type *), NULL); register_gdbarch_swap (&builtin_type_int64, sizeof (struct type *), NULL); register_gdbarch_swap (&builtin_type_uint64, sizeof (struct type *), NULL); + register_gdbarch_swap (&builtin_type_v4sf, sizeof (struct type *), NULL); register_gdbarch_swap (NULL, 0, build_gdbtypes); } diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h index dcd65ee6f45..f723c79fee0 100644 --- a/gdb/gdbtypes.h +++ b/gdb/gdbtypes.h @@ -855,6 +855,7 @@ extern struct type *builtin_type_int32; extern struct type *builtin_type_uint32; extern struct type *builtin_type_int64; extern struct type *builtin_type_uint64; +extern struct type *builtin_type_v4sf; /* We use this for the '/c' print format, because builtin_type_char is just a one-byte integral type, which languages less laid back than diff --git a/gdb/i386-linux-nat.c b/gdb/i386-linux-nat.c index 8c63a9414d9..12fbe3e280c 100644 --- a/gdb/i386-linux-nat.c +++ b/gdb/i386-linux-nat.c @@ -45,16 +45,9 @@ static int regmap[] = }; -/* FIXME: These routine absolutely depends upon (NUM_REGS - NUM_FREGS) - being less than or equal to the number of registers that can be stored - in a gregset_t. Note that with the current scheme there will typically - be more registers actually stored in a gregset_t that what we know - about. This is bogus and should be fixed. */ - -/* Given a pointer to a general register set in /proc format (gregset_t *), - unpack the register contents and supply them as gdb's idea of the current - register values. */ - +/* Given a pointer to a general register set in struct user format + (gregset_t *), unpack the register contents and supply them as + gdb's idea of the current register values. */ void supply_gregset (gregsetp) gregset_t *gregsetp; @@ -62,197 +55,234 @@ supply_gregset (gregsetp) register int regi; register greg_t *regp = (greg_t *) gregsetp; - for (regi = 0 ; regi < (NUM_REGS - NUM_FREGS) ; regi++) + for (regi = 0; regi < NUM_GREGS; regi++) { supply_register (regi, (char *) (regp + regmap[regi])); } } +/* Fill in a gregset_t object with selected data from a gdb-format + register file. + - GREGSETP points to the gregset_t object to be filled. + - GDB_REGS points to the GDB-style register file providing the data. + - VALID is an array indicating which registers in GDB_REGS are + valid; the parts of *GREGSETP that would hold registers marked + invalid in GDB_REGS are left unchanged. If VALID is zero, all + registers are assumed to be valid. */ void -fill_gregset (gregsetp, regno) - gregset_t *gregsetp; - int regno; +convert_to_gregset (gregset_t *gregsetp, + char *gdb_regs, + signed char *valid) { int regi; register greg_t *regp = (greg_t *) gregsetp; - for (regi = 0 ; regi < (NUM_REGS - NUM_FREGS) ; regi++) + for (regi = 0; regi < NUM_GREGS; regi++) + if (! valid || valid[regi]) + *(regp + regmap[regi]) = * (int *) ®isters[REGISTER_BYTE (regi)]; +} + +void +fill_gregset (gregset_t *gregsetp, + int regno) +{ + if (regno == -1) + convert_to_gregset (gregsetp, registers, 0); + else { - if ((regno == -1) || (regno == regi)) - { - *(regp + regmap[regi]) = *(int *) ®isters[REGISTER_BYTE (regi)]; - } + signed char valid[NUM_GREGS]; + memset (valid, 0, sizeof (valid)); + valid[regno] = 1; + convert_to_gregset (gregsetp, valid, valid); } } -/* Given a pointer to a floating point register set in (fpregset_t *) - format, unpack the register contents and supply them as gdb's - idea of the current floating point register values. */ +/* Where does st(N) start in the fpregset_t structure F? */ +#define FPREGSET_T_FPREG_OFFSET(f, n) \ + ((char *) &(f)->st_space + (n) * 10) +/* Fill GDB's register file with the floating-point register values in + *FPREGSETP. */ void -supply_fpregset (fpregsetp) - fpregset_t *fpregsetp; +supply_fpregset (fpregset_t *fpregsetp) { - register int regi; - char *from; - from = (char *) &(fpregsetp->st_space[0]); - for (regi = FPSTART_REGNUM ; regi <= FPEND_REGNUM ; regi++) - { - supply_register(regi, from); - from += REGISTER_RAW_SIZE(regi); - } + int i; + + /* Supply the floating-point registers. */ + for (i = 0; i < 8; i++) + supply_register (FP0_REGNUM + i, FPREGSET_T_FPREG_OFFSET (fpregsetp, i)); + + supply_register (FCTRL_REGNUM, (char *) &fpregsetp->cwd); + supply_register (FSTAT_REGNUM, (char *) &fpregsetp->swd); + supply_register (FTAG_REGNUM, (char *) &fpregsetp->twd); + supply_register (FCOFF_REGNUM, (char *) &fpregsetp->fip); + supply_register (FDS_REGNUM, (char *) &fpregsetp->fos); + supply_register (FDOFF_REGNUM, (char *) &fpregsetp->foo); + + /* Extract the code segment and opcode from the "fcs" member. */ + { + long l; + + l = fpregsetp->fcs & 0xffff; + supply_register (FCS_REGNUM, (char *) &l); + + l = (fpregsetp->fcs >> 16) & ((1 << 11) - 1); + supply_register (FOP_REGNUM, (char *) &l); + } } -/* Given a pointer to a floating point register set in (fpregset_t *) - format, update all of the registers from gdb's idea - of the current floating point register set. */ +/* Fill in an fpregset_t structure with selected data from a + gdb-format register file. + - FPREGSETP points to the structure to be filled. + - GDB_REGS points to the GDB-style register file providing the data. + - VALID is an array indicating which registers in GDB_REGS are + valid; the parts of *FPREGSETP that would hold registers marked + invalid in GDB_REGS are left unchanged. If VALID is zero, all + registers are assumed to be valid. */ void -fill_fpregset (fpregsetp, regno) - fpregset_t *fpregsetp; - int regno; +convert_to_fpregset (fpregset_t *fpregsetp, + char *gdb_regs, + signed char *valid) { - int regi; - char *to; - char *from; + int i; + + /* Fill in the floating-point registers. */ + for (i = 0; i < 8; i++) + if (!valid || valid[i]) + memcpy (FPREGSET_T_FPREG_OFFSET (fpregsetp, i), + ®isters[REGISTER_BYTE (FP0_REGNUM + i)], + REGISTER_RAW_SIZE(FP0_REGNUM + i)); + +#define fill(MEMBER, REGNO) \ + if (! valid || valid[(REGNO)]) \ + memcpy (&fpregsetp->MEMBER, ®isters[REGISTER_BYTE (REGNO)], \ + sizeof (fpregsetp->MEMBER)) + + fill (cwd, FCTRL_REGNUM); + fill (swd, FSTAT_REGNUM); + fill (twd, FTAG_REGNUM); + fill (fip, FCOFF_REGNUM); + fill (foo, FDOFF_REGNUM); + fill (fos, FDS_REGNUM); + +#undef fill + + if (! valid || valid[FCS_REGNUM]) + fpregsetp->fcs + = ((fpregsetp->fcs & ~0xffff) + | (* (int *) ®isters[REGISTER_BYTE (FCS_REGNUM)] & 0xffff)); + + if (! valid || valid[FOP_REGNUM]) + fpregsetp->fcs + = ((fpregsetp->fcs & 0xffff) + | ((*(int *) ®isters[REGISTER_BYTE (FOP_REGNUM)] & ((1 << 11) - 1)) + << 16)); +} - to = (char *) &(fpregsetp->st_space[0]); - for (regi = FPSTART_REGNUM ; regi <= FPEND_REGNUM ; regi++) - { - from = (char *) ®isters[REGISTER_BYTE (regi)]; - memcpy (to, from, REGISTER_RAW_SIZE (regi)); - to += REGISTER_RAW_SIZE(regi); - } + +/* Given a pointer to a floating point register set in (fpregset_t *) + format, update all of the registers from gdb's idea of the current + floating point register set. */ + +void +fill_fpregset (fpregset_t *fpregsetp, + int regno) +{ + convert_to_fpregset (fpregsetp, registers, 0); } -/* - Get the whole floating point state of the process and - store the floating point stack into registers[]. - */ + +/* Get the whole floating point state of the process and store the + floating point stack into registers[]. */ static void -fetch_fpregs(void) +fetch_fpregs () { int ret, regno; - char buf[FPREG_BYTES]; + fpregset_t buf; - ret = ptrace (PTRACE_GETFPREGS, inferior_pid, 0, (int)buf); - if ( ret < 0 ) + ret = ptrace (PTRACE_GETFPREGS, inferior_pid, 0, (int) &buf); + if (ret < 0) { warning ("Couldn't get floating point status"); return; } - for ( regno = 0; regno < NUM_FREGS; regno++ ) - { - if ( regno < 7 ) - supply_register (NUM_REGS-NUM_FREGS+regno, buf + regno*4); - else - supply_register (NUM_REGS-NUM_FREGS+regno, - buf + FPENV_BYTES + (regno-7)*FPREG_RAW_SIZE); - } - + /* ptrace fills an fpregset_t, so we can use the same function we do + for core files. */ + supply_fpregset (&buf); } -/* - Get the whole floating point state of the process and - replace the contents from registers[]. - */ +/* Set the inferior's floating-point registers to the values in + registers[] --- but only those registers marked valid. */ static void -store_fpregs(void) +store_fpregs () { - int ret, regno; - char buf[FPREG_BYTES]; + int ret; + fpregset_t buf; - ret = ptrace (PTRACE_GETFPREGS, inferior_pid, 0, (int)buf); - if ( ret < 0 ) + ret = ptrace (PTRACE_GETFPREGS, inferior_pid, 0, (int) &buf); + if (ret < 0) { warning ("Couldn't get floating point status"); return; } - for ( regno = 0; regno < NUM_FREGS; regno++ ) - { - if ( register_valid[regno] ) - { - if ( regno < 7 ) - { - read_register_gen (NUM_REGS-NUM_FREGS+regno, - buf + regno*4); - } - else - { - read_register_gen (NUM_REGS-NUM_FREGS+regno, - buf + FPENV_BYTES + (regno-7)*FPREG_RAW_SIZE); - } - } - } + convert_to_fpregset (&buf, registers, register_valid); - ret = ptrace (PTRACE_SETFPREGS, inferior_pid, 0, (int)buf); - if ( ret < 0 ) + ret = ptrace (PTRACE_SETFPREGS, inferior_pid, 0, (int) &buf); + if (ret < 0) { warning ("Couldn't write floating point status"); return; } - } -/* - Get state of all non-fp registers of the process and - store into registers[]. - */ +/* Read the general registers from the process, and store them + in registers[]. */ static void -fetch_regs(void) +fetch_regs () { int ret, regno; - char buf[17*sizeof(unsigned int)]; + gregset_t buf; - ret = ptrace (PTRACE_GETREGS, inferior_pid, 0, (int)buf); - if ( ret < 0 ) + ret = ptrace (PTRACE_GETREGS, inferior_pid, 0, (int) &buf); + if (ret < 0) { warning ("Couldn't get registers"); return; } - for ( regno = 0; regno < NUM_REGS-NUM_FREGS; regno++ ) - supply_register (regno, buf + register_addr (regno, U_REGS_OFFSET)); - + supply_gregset (&buf); } -/* - Get the whole non-floating-point register state of the process and - replace them in the process from registers[]. - */ +/* Set the inferior's general registers to the values in registers[] + --- but only those registers marked as valid. */ static void -store_regs(void) +store_regs () { int ret, regno; - char buf[17*sizeof(unsigned int)]; + gregset_t buf; - ret = ptrace (PTRACE_GETREGS, inferior_pid, 0, (int)buf); - if ( ret < 0 ) + ret = ptrace (PTRACE_GETREGS, inferior_pid, 0, (int) &buf); + if (ret < 0) { warning ("Couldn't get registers"); return; } - for ( regno = 0; regno < NUM_REGS-NUM_FREGS; regno++ ) - { - if ( register_valid[regno] ) - read_register_gen (regno, buf + register_addr (regno, U_REGS_OFFSET)); - } + convert_to_gregset (&buf, registers, register_valid); ret = ptrace (PTRACE_SETREGS, inferior_pid, 0, (int)buf); - - if ( ret < 0 ) + if (ret < 0) { - warning ("Couldn't write floating point status"); + warning ("Couldn't write registers"); return; } - } @@ -262,14 +292,13 @@ store_regs(void) upon the value of regno. */ void -fetch_inferior_registers (regno) - int regno; +fetch_inferior_registers (int regno) { - if ( (regno < NUM_REGS - NUM_FREGS) || (regno == -1) ) - fetch_regs(); + if (regno < NUM_GREGS || regno == -1) + fetch_regs (); - if ( (regno >= NUM_REGS - NUM_FREGS) || (regno == -1) ) - fetch_fpregs(); + if (regno >= NUM_GREGS || regno == -1) + fetch_fpregs (); } @@ -283,11 +312,11 @@ void store_inferior_registers (regno) int regno; { - if ( (regno < NUM_REGS - NUM_FREGS) || (regno == -1) ) - store_regs(); + if (regno < NUM_GREGS || regno == -1) + store_regs (); - if ( (regno >= NUM_REGS - NUM_FREGS) || (regno == -1) ) - store_fpregs(); + if (regno >= NUM_GREGS || regno == -1) + store_fpregs (); } diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c index e8c1bc943d5..1fbf76ab966 100644 --- a/gdb/i386-tdep.c +++ b/gdb/i386-tdep.c @@ -46,6 +46,32 @@ static int gdb_print_insn_i386 (bfd_vma, disassemble_info *); void _initialize_i386_tdep PARAMS ((void)); +/* i386_register_byte[i] is the offset into the register file of the + start of register number i. We initialize this from + i386_register_raw_size. */ +int i386_register_byte[MAX_NUM_REGS]; + +/* i386_register_raw_size[i] is the number of bytes of storage in the + actual machine representation for register i. */ +int i386_register_raw_size[MAX_NUM_REGS] = { + 4, 4, 4, 4, + 4, 4, 4, 4, + 4, 4, 4, 4, + 4, 4, 4, 4, + 10, 10, 10, 10, + 10, 10, 10, 10, + 4, 4, 4, 4, + 4, 4, 4, 4, + 16, 16, 16, 16, + 16, 16, 16, 16, + 4 +}; + +/* i386_register_virtual_size[i] is the size in bytes of the virtual + type of register i. */ +int i386_register_virtual_size[MAX_NUM_REGS]; + + /* This is the variable the is set with "set disassembly-flavor", and its legitimate values. */ static char att_flavor[] = "att"; @@ -974,25 +1000,46 @@ set_disassembly_flavor () void _initialize_i386_tdep () { - struct cmd_list_element *new_cmd; + /* Initialize the table saying where each register starts in the + register file. */ + { + int i, offset; + + offset = 0; + for (i = 0; i < MAX_NUM_REGS; i++) + { + i386_register_byte[i] = offset; + offset += i386_register_raw_size[i]; + } + } + + /* Initialize the table of virtual register sizes. */ + { + int i; + + for (i = 0; i < MAX_NUM_REGS; i++) + i386_register_virtual_size[i] = TYPE_LENGTH (REGISTER_VIRTUAL_TYPE (i)); + } tm_print_insn = gdb_print_insn_i386; tm_print_insn_info.mach = bfd_lookup_arch (bfd_arch_i386, 0)->mach; /* Add the variable that controls the disassembly flavor */ + { + struct cmd_list_element *new_cmd; - new_cmd = add_set_enum_cmd ("disassembly-flavor", no_class, - valid_flavors, - (char *) &disassembly_flavor, - "Set the disassembly flavor, the valid values are \"att\" and \"intel\", \ + new_cmd = add_set_enum_cmd ("disassembly-flavor", no_class, + valid_flavors, + (char *) &disassembly_flavor, + "Set the disassembly flavor, the valid values are \"att\" and \"intel\", \ and the default value is \"att\".", - &setlist); - new_cmd->function.sfunc = set_disassembly_flavor_sfunc; - add_show_from_set (new_cmd, &showlist); + &setlist); + new_cmd->function.sfunc = set_disassembly_flavor_sfunc; + add_show_from_set (new_cmd, &showlist); + } /* Finally, initialize the disassembly flavor to the default given in the disassembly_flavor variable */ set_disassembly_flavor (); - } diff --git a/gdb/infrun.c b/gdb/infrun.c index cc8c1bfc960..527bb2ddbb6 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -73,10 +73,6 @@ static void follow_vfork (int parent_pid, int child_pid); static void set_schedlock_func (char *args, int from_tty, struct cmd_list_element * c); -static int is_internal_shlib_eventpoint (struct breakpoint * ep); - -static int stopped_for_internal_shlib_event (bpstat bs); - struct execution_control_state; static int currently_stepping (struct execution_control_state *ecs); @@ -2427,7 +2423,6 @@ handle_inferior_event (struct execution_control_state *ecs) dynamically loaded objects (among other things). */ if (stop_on_solib_events) { - stop_print_frame = 0; stop_stepping (ecs); return; } @@ -3197,40 +3192,6 @@ prepare_to_wait (struct execution_control_state *ecs) soon. */ ecs->wait_some_more = 1; } - -/* This function returns TRUE if ep is an internal breakpoint - set to catch generic shared library (aka dynamically-linked - library) events. (This is *NOT* the same as a catchpoint for a - shlib event. The latter is something a user can set; this is - something gdb sets for its own use, and isn't ever shown to a - user.) */ -static int -is_internal_shlib_eventpoint (struct breakpoint *ep) -{ - return - (ep->type == bp_shlib_event) - ; -} - -/* This function returns TRUE if bs indicates that the inferior - stopped due to a shared library (aka dynamically-linked library) - event. */ - -static int -stopped_for_internal_shlib_event (bpstat bs) -{ - /* Note that multiple eventpoints may've caused the stop. Any - that are associated with shlib events will be accepted. */ - for (; bs != NULL; bs = bs->next) - { - if ((bs->breakpoint_at != NULL) - && is_internal_shlib_eventpoint (bs->breakpoint_at)) - return 1; - } - - /* If we get here, then no candidate was found. */ - return 0; -} /* Here to return control to GDB when the inferior stops for real. @@ -3305,14 +3266,6 @@ The same program may be running in another process.\n"); target_terminal_ours (); - /* Did we stop because the user set the stop_on_solib_events - variable? (If so, we report this as a generic, "Stopped due - to shlib event" message.) */ - if (stopped_for_internal_shlib_event (stop_bpstat)) - { - printf_filtered ("Stopped due to shared library event\n"); - } - /* Look up the hook_stop and run it if it exists. */ if (stop_command && stop_command->hook) @@ -3346,32 +3299,39 @@ The same program may be running in another process.\n"); { int bpstat_ret; int source_flag; + int do_frame_printing = 1; bpstat_ret = bpstat_print (stop_bpstat); - /* bpstat_print() returned one of: - -1: Didn't print anything - 0: Printed preliminary "Breakpoint n, " message, desires - location tacked on - 1: Printed something, don't tack on location */ - - if (bpstat_ret == -1) - if (stop_step - && step_frame_address == FRAME_FP (get_current_frame ()) - && step_start_function == find_pc_function (stop_pc)) - source_flag = -1; /* finished step, just print source line */ - else - source_flag = 1; /* print location and source line */ - else if (bpstat_ret == 0) /* hit bpt, desire location */ - source_flag = 1; /* print location and source line */ - else /* bpstat_ret == 1, hit bpt, do not desire location */ - source_flag = -1; /* just print source line */ + switch (bpstat_ret) + { + case PRINT_UNKNOWN: + if (stop_step + && step_frame_address == FRAME_FP (get_current_frame ()) + && step_start_function == find_pc_function (stop_pc)) + source_flag = -1; /* finished step, just print source line */ + else + source_flag = 1; /* print location and source line */ + break; + case PRINT_SRC_AND_LOC: + source_flag = 1; /* print location and source line */ + break; + case PRINT_SRC_ONLY: + source_flag = -1; + break; + case PRINT_NOTHING: + do_frame_printing = 0; + break; + default: + internal_error ("Unknown value."); + } /* The behavior of this routine with respect to the source flag is: -1: Print only source line 0: Print only location 1: Print location and source line */ - show_and_print_stack_frame (selected_frame, -1, source_flag); + if (do_frame_printing) + show_and_print_stack_frame (selected_frame, -1, source_flag); /* Display the auto-display expressions. */ do_displays (); diff --git a/gdb/mem-break.c b/gdb/mem-break.c index da400e041c3..99db9d29233 100644 --- a/gdb/mem-break.c +++ b/gdb/mem-break.c @@ -84,7 +84,7 @@ memory_breakpoint_from_pc (pcptr, lenptr) is accomplished via BREAKPOINT_MAX). */ int -memory_insert_breakpoint (addr, contents_cache) +default_memory_insert_breakpoint (addr, contents_cache) CORE_ADDR addr; char *contents_cache; { @@ -109,7 +109,7 @@ memory_insert_breakpoint (addr, contents_cache) int -memory_remove_breakpoint (addr, contents_cache) +default_memory_remove_breakpoint (addr, contents_cache) CORE_ADDR addr; char *contents_cache; { @@ -123,3 +123,28 @@ memory_remove_breakpoint (addr, contents_cache) return target_write_memory (addr, contents_cache, bplen); } + + +#if !defined(MEMORY_INSERT_BREAKPOINT) +#define MEMORY_INSERT_BREAKPOINT(addr, contents_cache) \ + default_memory_insert_breakpoint(addr, contents_cache) +#endif +int +memory_insert_breakpoint (addr, contents_cache) + CORE_ADDR addr; + char *contents_cache; +{ + return MEMORY_INSERT_BREAKPOINT(addr, contents_cache); +} + +#if !defined(MEMORY_REMOVE_BREAKPOINT) +#define MEMORY_REMOVE_BREAKPOINT(addr, contents_cache) \ + default_memory_remove_breakpoint(addr, contents_cache) +#endif +int +memory_remove_breakpoint (addr, contents_cache) + CORE_ADDR addr; + char *contents_cache; +{ + return MEMORY_REMOVE_BREAKPOINT(addr, contents_cache); +} diff --git a/gdb/remote-hms.c b/gdb/remote-hms.c index 328fc01965c..5e66464f032 100644 --- a/gdb/remote-hms.c +++ b/gdb/remote-hms.c @@ -1,5 +1,5 @@ /* Remote debugging interface for Hitachi HMS Monitor Version 1.0 - Copyright 1995 Free Software Foundation, Inc. + Copyright 1995,1999 Free Software Foundation, Inc. Contributed by Cygnus Support. Written by Steve Chamberlain (sac@cygnus.com). @@ -159,1342 +159,3 @@ Specify the serial device it is connected to (e.g. /dev/ttya)."; write_dos_tick_delay = 1; add_target (&hms_ops); } - -#if 0 -/* This is kept here because we used to support the H8/500 in this module, - and I haven't done the H8/500 yet */ -#include "defs.h" -#include "inferior.h" -#include "wait.h" -#include "value.h" -#include "gdb_string.h" -#include <ctype.h> -#include <fcntl.h> -#include <signal.h> -#include <setjmp.h> -#include <errno.h> -#include "terminal.h" -#include "target.h" -#include "gdbcore.h" -#include "serial.h" -#include "remote-utils.h" -/* External data declarations */ -extern int stop_soon_quietly; /* for wait_for_inferior */ - -/* Forward data declarations */ -extern struct target_ops hms_ops; /* Forward declaration */ - -/* Forward function declarations */ -static void hms_fetch_registers (); -static int hms_store_registers (); -static void hms_close (); -static int hms_clear_breakpoints (); - -extern struct target_ops hms_ops; -static void hms_drain (); -static void add_commands (); -static void remove_commands (); - -static int quiet = 1; /* FIXME - can be removed after Dec '94 */ - - - -/*********************************************************************** - * I/O stuff stolen from remote-eb.c - ***********************************************************************/ - -static int timeout = 2; - -static const char *dev_name; - -/* Descriptor for I/O to remote machine. Initialize it to -1 so that - hms_open knows that we don't have a file open when the program - starts. */ - -static int before = 0xdead; -static int is_open = 0; -static int after = 0xdead; -int -check_open () -{ - if (before != 0xdead - || after != 0xdead) - printf ("OUTCH! \n"); - if (!is_open) - { - error ("remote device not open"); - } -} - -#define ON 1 -#define OFF 0 - -/* Read a character from the remote system, doing all the fancy - timeout stuff. */ -static int -readchar () -{ - int buf; - - buf = SERIAL_READCHAR (desc, timeout); - - if (buf == SERIAL_TIMEOUT) - { - hms_write (".\r\n", 3); - error ("Timeout reading from remote system."); - } - if (buf == SERIAL_ERROR) - { - error ("Serial port error!"); - } - - if (!quiet || remote_debug) - printf_unfiltered ("%c", buf); - - return buf & 0x7f; -} - -static void -flush () -{ - while (1) - { - int b = SERIAL_READCHAR (desc, 0); - if (b == SERIAL_TIMEOUT) - return; - } -} - -static int -readchar_nofail () -{ - int buf; - - buf = SERIAL_READCHAR (desc, timeout); - if (buf == SERIAL_TIMEOUT) - buf = 0; - if (!quiet || remote_debug) - printf_unfiltered ("%c", buf); - - return buf & 0x7f; - -} - -/* Keep discarding input from the remote system, until STRING is found. - Let the user break out immediately. */ -static void -expect (string) - char *string; -{ - char *p = string; - char c; - immediate_quit = 1; - while (1) - { - c = readchar (); - if (c == *p) - { - p++; - if (*p == '\0') - { - immediate_quit = 0; - return; - } - } - else - { - p = string; - if (c == *p) - p++; - } - } -} - -/* Keep discarding input until we see the hms prompt. - - The convention for dealing with the prompt is that you - o give your command - o *then* wait for the prompt. - - Thus the last thing that a procedure does with the serial line - will be an expect_prompt(). Exception: hms_resume does not - wait for the prompt, because the terminal is being handed over - to the inferior. However, the next thing which happens after that - is a hms_wait which does wait for the prompt. - Note that this includes abnormal exit, e.g. error(). This is - necessary to prevent getting into states from which we can't - recover. */ -static void -expect_prompt () -{ - expect ("HMS>"); -} - -/* Get a hex digit from the remote system & return its value. - If ignore_space is nonzero, ignore spaces (not newline, tab, etc). */ -static int -get_hex_digit (ignore_space) - int ignore_space; -{ - int ch; - - while (1) - { - ch = readchar (); - if (ch >= '0' && ch <= '9') - return ch - '0'; - else if (ch >= 'A' && ch <= 'F') - return ch - 'A' + 10; - else if (ch >= 'a' && ch <= 'f') - return ch - 'a' + 10; - else if (ch == ' ' && ignore_space) - ; - else - { - expect_prompt (); - error ("Invalid hex digit from remote system."); - } - } -} - -/* Get a byte from hms_desc and put it in *BYT. Accept any number - leading spaces. */ -static void -get_hex_byte (byt) - char *byt; -{ - int val; - - val = get_hex_digit (1) << 4; - val |= get_hex_digit (0); - *byt = val; -} - -/* Read a 32-bit hex word from the hms, preceded by a space */ -static long -get_hex_word () -{ - long val; - int j; - - val = 0; - for (j = 0; j < 8; j++) - val = (val << 4) + get_hex_digit (j == 0); - return val; -} - -/* Called when SIGALRM signal sent due to alarm() timeout. */ - -/* Number of SIGTRAPs we need to simulate. That is, the next - NEED_ARTIFICIAL_TRAP calls to hms_wait should just return - SIGTRAP without actually waiting for anything. */ - -static int need_artificial_trap = 0; - -void -hms_kill (arg, from_tty) - char *arg; - int from_tty; -{ - -} - -/* This is called not only when we first attach, but also when the - user types "run" after having attached. */ -void -hms_create_inferior (execfile, args, env) - char *execfile; - char *args; - char **env; -{ - int entry_pt; - char buffer[100]; - - if (args && *args) - error ("Can't pass arguments to remote hms process."); - - if (execfile == 0 || exec_bfd == 0) - error ("No executable file specified"); - - entry_pt = (int) bfd_get_start_address (exec_bfd); - check_open (); - - hms_kill (NULL, NULL); - hms_clear_breakpoints (); - init_wait_for_inferior (); - hms_write_cr (""); - expect_prompt (); - - insert_breakpoints (); /* Needed to get correct instruction in cache */ - proceed (entry_pt, TARGET_SIGNAL_DEFAULT, 0); -} - -/* Open a connection to a remote debugger. - NAME is the filename used for communication, then a space, - then the baud rate. - */ - -static char * -find_end_of_word (s) - char *s; -{ - while (*s && !isspace (*s)) - s++; - return s; -} - -static char * -get_word (p) - char **p; -{ - char *s = *p; - char *word; - char *copy; - size_t len; - - while (isspace (*s)) - s++; - - word = s; - - len = 0; - - while (*s && !isspace (*s)) - { - s++; - len++; - - } - copy = xmalloc (len + 1); - memcpy (copy, word, len); - copy[len] = 0; - *p = s; - return copy; -} - -static int baudrate = 9600; - -static int -is_baudrate_right () -{ - int ok; - - /* Put this port into NORMAL mode, send the 'normal' character */ - - hms_write ("\001", 1); /* Control A */ - hms_write ("\r\n", 2); /* Cr */ - - while (1) - { - ok = SERIAL_READCHAR (desc, timeout); - if (ok < 0) - break; - } - - hms_write ("r", 1); - - if (readchar_nofail () == 'r') - return 1; - - /* Not the right baudrate, or the board's not on */ - return 0; -} -static void -set_rate () -{ - if (!SERIAL_SETBAUDRATE (desc, baudrate)) - error ("Can't set baudrate"); -} - - - -/* Close out all files and local state before this target loses control. */ - -static void -hms_close (quitting) - int quitting; -{ - /* Clear any break points */ - remove_commands (); - hms_clear_breakpoints (); - sleep (1); /* Let any output make it all the way back */ - if (is_open) - { - SERIAL_WRITE (desc, "R\r\n", 3); - SERIAL_CLOSE (desc); - } - is_open = 0; -} - -/* Terminate the open connection to the remote debugger. Use this - when you want to detach and do something else with your gdb. */ void -hms_detach (args, from_tty) - char *args; - int from_tty; -{ - if (is_open) - { - hms_clear_breakpoints (); - } - - pop_target (); /* calls hms_close to do the real work - */ - if (from_tty) - printf_filtered ("Ending remote %s debugging\n", - target_shortname); -} - -/* Tell the remote machine to resume. */ - -void -hms_resume (pid, step, sig) - int pid, step; - enum target_signal - sig; -{ - if (step) - { - hms_write_cr ("s"); - expect ("Step>"); - - /* Force the next hms_wait to return a trap. Not doing anything - about I/O from the target means that the user has to type "continue" - to see any. FIXME, this should be fixed. */ - need_artificial_trap = 1; - } - else - { - hms_write_cr ("g"); - expect ("g"); - } -} - -/* Wait until the remote machine stops, then return, storing status in - STATUS just as `wait' would. */ - -int -hms_wait (pid, status) - int pid; - struct target_waitstatus *status; -{ - /* Strings to look for. '?' means match any single character. Note - that with the algorithm we use, the initial character of the string - cannot recur in the string, or we will not find some cases of the - string in the input. */ - - static char bpt[] = "At breakpoint:"; - - /* It would be tempting to look for "\n[__exit + 0x8]\n" but that - requires loading symbols with "yc i" and even if we did do that we - don't know that the file has symbols. */ - static char exitmsg[] = "HMS>"; - char *bp = bpt; - char *ep = exitmsg; - - /* Large enough for either sizeof (bpt) or sizeof (exitmsg) chars. - */ - char swallowed[50]; - - /* Current position in swallowed. */ - char *swallowed_p = swallowed; - - int ch; - int ch_handled; - int old_timeout = timeout; - int - old_immediate_quit = immediate_quit; - int swallowed_cr = 0; - - status->kind = TARGET_WAITKIND_EXITED; - status->value.integer = 0; - - if (need_artificial_trap != 0) - { - status->kind = - TARGET_WAITKIND_STOPPED; - status->value.sig = TARGET_SIGNAL_TRAP; - need_artificial_trap--; - return 0; - } - - timeout = 5; /* Don't time out for a while - user program is running. - */ - immediate_quit = 1; /* Helps ability to QUIT */ - while (1) - { - QUIT; /* Let user quit and leave process running */ - ch_handled = 0; - ch = readchar (); - if (ch == *bp) - { - bp++; - if (*bp == '\0') - break; - ch_handled = 1; - - *swallowed_p++ = ch; - } - else - { - bp = bpt; - } - if - (ch == *ep || *ep == '?') - { - ep++; - if (*ep == '\0') - break; - - if (!ch_handled) - *swallowed_p++ = ch; - ch_handled = - 1; - } - else - { - ep = exitmsg; - } - - if (!ch_handled) - { - char *p; - - /* Print out any characters which have been swallowed. */ - for (p = swallowed; p < swallowed_p; ++p) - putchar_unfiltered (*p); - swallowed_p = swallowed; - - if ((ch != '\r' && ch != '\n') || swallowed_cr > 10) - { - putchar_unfiltered (ch); - swallowed_cr = 10; - } - swallowed_cr++; - - } - } - if (*bp == '\0') - { - status->kind = TARGET_WAITKIND_STOPPED; - status->value.sig = TARGET_SIGNAL_TRAP; - expect_prompt (); - } - else - { - status->kind = TARGET_WAITKIND_EXITED; - status->value.integer = - TARGET_SIGNAL_STOP; - } - - timeout = old_timeout; - immediate_quit = old_immediate_quit; - return - 0; -} - -/* Return the name of register number REGNO in the form input and - output by hms. - - Returns a pointer to a static buffer containing the answer. */ -static char * -get_reg_name (regno) - int regno; -{ - static char *rn[] = - REGISTER_NAMES; - - return rn[regno]; -} - -/* Read the remote registers. */ - -static int -gethex (length, start, ok) - unsigned int length; - char *start; - int *ok; -{ - int result = 0; - - while (length--) - { - result <<= 4; - if (*start >= 'a' && *start <= 'f') - { - result += *start - 'a' + 10; - } - else if (*start >= 'A' && - *start <= 'F') - { - result += *start - 'A' + 10; - } - else if - (*start >= '0' && *start <= '9') - { - result += *start - '0'; - } - else - *ok = 0; - start++; - - } - return result; -} -static int -timed_read (buf, n, timeout) - char - *buf; - -{ - int i; - char c; - - i = 0; - while (i < n) - { - c = readchar (); - - if (c == 0) - return i; - buf[i] = c; - i++; - - } - return i; -} - -hms_write (a, l) - char *a; -{ - int i; - - SERIAL_WRITE (desc, a, l); - - if (!quiet || remote_debug) - { - printf_unfiltered ("<"); - for (i = 0; i < l; i++) - { - printf_unfiltered ("%c", a[i]); - } - printf_unfiltered (">"); - } -} - -hms_write_cr (s) - char *s; -{ - hms_write (s, strlen (s)); - hms_write ("\r\n", 2); -} - -#ifdef GDB_TARGET_IS_H8500 - -/* H8/500 monitor reg dump looks like: - - HMS>r - PC:8000 SR:070C .7NZ.. CP:00 DP:00 EP:00 TP:00 BR:00 - R0-R7: FF5A 0001 F4FE F500 0000 F528 F528 F4EE - HMS> - - - */ - -supply_val (n, size, ptr, segptr) - int n; - int size; - char *ptr; - char *segptr; -{ - int ok; - char raw[4]; - switch (size) - { - case 2: - raw[0] = gethex (2, ptr, &ok); - raw[1] = gethex (2, ptr + 2, &ok); - supply_register (n, raw); - break; - case 1: - raw[0] = gethex (2, ptr, &ok); - supply_register (n, raw); - break; - case 4: - { - int v = gethex (4, ptr, &ok); - v |= gethex (2, segptr, &ok) << 16; - raw[0] = 0; - raw[1] = (v >> 16) & 0xff; - raw[2] = (v >> 8) & 0xff; - raw[3] = (v >> 0) & 0xff; - supply_register (n, raw); - } - } - -} -static void -hms_fetch_register (dummy) - int dummy; -{ -#define REGREPLY_SIZE 108 - char linebuf[REGREPLY_SIZE + 1]; - int i; - int s; - int gottok; - - LONGEST reg[NUM_REGS]; - check_open (); - - do - { - - hms_write_cr ("r"); - expect ("r"); - s = timed_read (linebuf + 1, REGREPLY_SIZE, 1); - - linebuf[REGREPLY_SIZE] = 0; - gottok = 0; - if (linebuf[3] == 'P' && - linebuf[4] == 'C' && - linebuf[5] == ':' && - linebuf[105] == 'H' && - linebuf[106] == 'M' && - linebuf[107] == 'S') - { - - /* - 012 - r** - -------1---------2---------3---------4---------5----- - 345678901234567890123456789012345678901234567890123456 - PC:8000 SR:070C .7NZ.. CP:00 DP:00 EP:00 TP:00 BR:00** - ---6---------7---------8---------9--------10---- - 789012345678901234567890123456789012345678901234 - R0-R7: FF5A 0001 F4FE F500 0000 F528 F528 F4EE** - - 56789 - HMS> - */ - gottok = 1; - - - supply_val (PC_REGNUM, 4, linebuf + 6, linebuf + 29); - - supply_val (CCR_REGNUM, 2, linebuf + 14); - supply_val (SEG_C_REGNUM, 1, linebuf + 29); - supply_val (SEG_D_REGNUM, 1, linebuf + 35); - supply_val (SEG_E_REGNUM, 1, linebuf + 41); - supply_val (SEG_T_REGNUM, 1, linebuf + 47); - for (i = 0; i < 8; i++) - { - static int sr[8] = - {35, 35, 35, 35, - 41, 41, 47, 47}; - - char raw[4]; - char *src = linebuf + 64 + 5 * i; - char *segsrc = linebuf + sr[i]; - supply_val (R0_REGNUM + i, 2, src); - supply_val (PR0_REGNUM + i, 4, src, segsrc); - } - } - if (!gottok) - { - hms_write_cr (""); - expect ("HMS>"); - } - } - while (!gottok); -} -#endif - -#ifdef GDB_TARGET_IS_H8300 -static void -hms_fetch_register (dummy) - int dummy; -{ -#define REGREPLY_SIZE 79 - char linebuf[REGREPLY_SIZE + 1]; - int i; - int s; - int gottok; - - ULONGEST reg[NUM_REGS]; - - check_open (); - - do - { - hms_write_cr ("r"); - - s = timed_read (linebuf, 1, 1); - - while (linebuf[0] != 'r') - s = timed_read (linebuf, 1, 1); - - s = timed_read (linebuf + 1, REGREPLY_SIZE - 1, 1); - - linebuf[REGREPLY_SIZE] = 0; - gottok = 0; - if (linebuf[0] == 'r' && - linebuf[3] == 'P' && - linebuf[4] == 'C' && - linebuf[5] == '=' && - linebuf[75] == 'H' && - linebuf[76] == 'M' && - linebuf[77] == 'S') - { - /* - PC=XXXX CCR=XX:XXXXXXXX R0-R7= XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX - 5436789012345678901234567890123456789012345678901234567890123456789012 - 0 1 2 3 4 5 6 - */ - gottok = 1; - - reg[PC_REGNUM] = gethex (4, linebuf + 6, &gottok); - reg[CCR_REGNUM] = gethex (2, linebuf + 15, &gottok); - for (i = 0; i < 8; i++) - { - reg[i] = gethex (4, linebuf + 34 + 5 * i, &gottok); - } - } - } - while (!gottok); - for (i = 0; i < NUM_REGS; i++) - { - char swapped[2]; - - swapped[1] = reg[i]; - swapped[0] = (reg[i]) >> 8; - - supply_register (i, swapped); - } -} -#endif -/* Store register REGNO, or all if REGNO == -1. - Return errno value. */ -static void -hms_store_register (regno) - int regno; -{ - if (regno == -1) - { - for (regno = 0; regno < NUM_REGS; regno++) - { - hms_store_register (regno); - } - } - else - { - char *name = get_reg_name (regno); - char buffer[100]; - /* Some regs dont really exist */ - if (!(name[0] == 'p' && name[1] == 'r') - && !(name[0] == 'c' && name[1] == 'y') - && !(name[0] == 't' && name[1] == 'i') - && !(name[0] == 'i' && name[1] == 'n')) - { - sprintf (buffer, "r %s=%x", name, read_register (regno)); - hms_write_cr (buffer); - expect_prompt (); - } - } -} - - -/* Get ready to modify the registers array. On machines which store - individual registers, this doesn't need to do anything. On machines - which store all the registers in one fell swoop, this makes sure - that registers contains all the registers from the program being - debugged. */ - -void -hms_prepare_to_store () -{ - /* Do nothing, since we can store individual regs */ -} - -static CORE_ADDR -translate_addr (addr) - CORE_ADDR addr; -{ - - return (addr); - -} - - -int -hms_xfer_inferior_memory (memaddr, myaddr, len, write, target) - CORE_ADDR memaddr; - char *myaddr; - int len; - int write; - struct target_ops *target; /* ignored */ -{ - - return len; -} - -int -hms_write_inferior_memory (memaddr, myaddr, len) - CORE_ADDR memaddr; - unsigned char *myaddr; - int len; -{ - bfd_vma addr; - int done; - int todo; - char buffer[100]; - done = 0; - hms_write_cr ("."); - expect_prompt (); - while (done < len) - { - char *ptr = buffer; - int thisgo; - int idx; - - thisgo = len - done; - if (thisgo > 20) - thisgo = 20; - - sprintf (ptr, "M.B %4x =", memaddr + done); - ptr += 10; - for (idx = 0; idx < thisgo; idx++) - { - sprintf (ptr, "%2x ", myaddr[idx + done]); - ptr += 3; - } - hms_write_cr (buffer); - expect_prompt (); - done += thisgo; - } -} - -void -hms_files_info () -{ - char *file = "nothing"; - - if (exec_bfd) - file = bfd_get_filename (exec_bfd); - - if (exec_bfd) -#ifdef __GO32__ - printf_filtered ("\tAttached to DOS asynctsr and running program %s\n", file); -#else - printf_filtered ("\tAttached to %s at %d baud and running program %s\n", dev_name, baudrate, file); -#endif - printf_filtered ("\ton an H8/300 processor.\n"); -} - -/* Copy LEN bytes of data from debugger memory at MYADDR - to inferior's memory at MEMADDR. Returns errno value. - * sb/sh instructions don't work on unaligned addresses, when TU=1. - */ - -/* Read LEN bytes from inferior memory at MEMADDR. Put the result - at debugger address MYADDR. Returns errno value. */ -int -hms_read_inferior_memory (memaddr, myaddr, len) - CORE_ADDR memaddr; - char *myaddr; - int len; -{ - /* Align to nearest low 16 bits */ - int i; - - CORE_ADDR start = memaddr; - CORE_ADDR end = memaddr + len - 1; - - int ok = 1; - - /* - AAAA: XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX '................' - 012345678901234567890123456789012345678901234567890123456789012345 - 0 1 2 3 4 5 6 - */ - char buffer[66]; - - if (memaddr & 0xf) - abort (); - if (len != 16) - abort (); - - sprintf (buffer, "m %4x %4x", start & 0xffff, end & 0xffff); - - flush (); - hms_write_cr (buffer); - /* drop the echo and newline */ - for (i = 0; i < 13; i++) - readchar (); - - /* Grab the lines as they come out and fill the area */ - /* Skip over cr */ - while (1) - { - int p; - int i; - int addr; - size_t idx; - - char byte[16]; - - buffer[0] = readchar (); - while (buffer[0] == '\r' - || buffer[0] == '\n') - buffer[0] = readchar (); - - if (buffer[0] == 'M') - break; - - for (i = 1; i < 50; i++) - { - buffer[i] = readchar (); - } - /* sometimes we loose characters in the ascii representation of the - data. I don't know where. So just scan for the end of line */ - i = readchar (); - while (i != '\n' && i != '\r') - i = readchar (); - - /* Now parse the line */ - - addr = gethex (4, buffer, &ok); - idx = 6; - for (p = 0; p < 16; p += 2) - { - byte[p] = gethex (2, buffer + idx, &ok); - byte[p + 1] = gethex (2, buffer + idx + 2, &ok); - idx += 5; - } - - for (p = 0; p < 16; p++) - { - if (addr + p >= memaddr && - addr + p < memaddr + len) - { - myaddr[(addr + p) - memaddr] = byte[p]; - - } - - } - } -#ifdef GDB_TARGET_IS_H8500 - expect ("ore>"); -#endif -#ifdef GDB_TARGET_IS_H8300 - expect ("emory>"); -#endif - hms_write_cr ("."); - - expect_prompt (); - return len; -} - - - -#define MAX_BREAKS 16 -static int num_brkpts = 0; -static int -hms_insert_breakpoint (addr, save) - CORE_ADDR addr; - char *save; /* Throw away, let hms save instructions */ -{ - check_open (); - - if (num_brkpts < MAX_BREAKS) - { - char buffer[100]; - - num_brkpts++; - sprintf (buffer, "b %x", addr & 0xffff); - hms_write_cr (buffer); - expect_prompt (); - return (0); - } - else - { - fprintf_filtered (gdb_stderr, - "Too many break points, break point not installed\n"); - return (1); - } - -} -static int -hms_remove_breakpoint (addr, save) - CORE_ADDR addr; - char *save; /* Throw away, let hms save instructions */ -{ - if (num_brkpts > 0) - { - char buffer[100]; - - num_brkpts--; - sprintf (buffer, "b - %x", addr & 0xffff); - hms_write_cr (buffer); - expect_prompt (); - - } - return (0); -} - -/* Clear the hmss notion of what the break points are */ -static int -hms_clear_breakpoints () -{ - - if (is_open) - { - hms_write_cr ("b -"); - expect_prompt (); - } - num_brkpts = 0; -} -static void -hms_mourn () -{ - hms_clear_breakpoints (); - unpush_target (&hms_ops); - generic_mourn_inferior (); -} - -/* Put a command string, in args, out to the hms. The hms is assumed to - be in raw mode, all writing/reading done through desc. - Ouput from the hms is placed on the users terminal until the - prompt from the hms is seen. - FIXME: Can't handle commands that take input. */ - -void -hms_com (args, fromtty) - char *args; - int fromtty; -{ - check_open (); - - if (!args) - return; - - /* Clear all input so only command relative output is displayed */ - - hms_write_cr (args); -/* hms_write ("\030", 1); */ - expect_prompt (); -} - -static void -hms_open (name, from_tty) - char *name; - int from_tty; -{ - unsigned int prl; - char *p; - - if (name == 0) - { - name = ""; - } - if (is_open) - hms_close (0); - dev_name = strdup (name); - - if (!(desc = SERIAL_OPEN (dev_name))) - perror_with_name ((char *) dev_name); - - SERIAL_RAW (desc); - is_open = 1; - push_target (&hms_ops); - dcache_ptr = dcache_init (hms_read_inferior_memory, - hms_write_inferior_memory); - remote_dcache = 1; - /* Hello? Are you there? */ - SERIAL_WRITE (desc, "\r\n", 2); - expect_prompt (); - - /* Clear any break points */ - hms_clear_breakpoints (); - - printf_filtered ("Connected to remote board running HMS monitor.\n"); - add_commands (); -/* hms_drain (); */ -} - -/* Define the target subroutine names */ - -struct target_ops hms_ops; - -static void -init_hms_ops (void) -{ - hms_ops.to_shortname = "hms"; - hms_ops.to_longname = "Remote HMS monitor"; - hms_ops.to_doc = "Use the H8 evaluation board running the HMS monitor connected\n\ -by a serial line."; - hms_ops.to_open = hms_open; - hms_ops.to_close = hms_close; - hms_ops.to_attach = 0; - hms_ops.to_post_attach = NULL; - hms_ops.to_require_attach = NULL; - hms_ops.to_detach = hms_detach; - hms_ops.to_require_detach = NULL; - hms_ops.to_resume = hms_resume; - hms_ops.to_wait = hms_wait; - hms_ops.to_post_wait = NULL; - hms_ops.to_fetch_registers = hms_fetch_register; - hms_ops.to_store_registers = hms_store_register; - hms_ops.to_prepare_to_store = hms_prepare_to_store; - hms_ops.to_xfer_memory = hms_xfer_inferior_memory; - hms_ops.to_files_info = hms_files_info; - hms_ops.to_insert_breakpoint = hms_insert_breakpoint; - hms_ops.to_remove_breakpoint = hms_remove_breakpoint; - hms_ops.to_terminal_init = 0; - hms_ops.to_terminal_inferior = 0; - hms_ops.to_terminal_ours_for_output = 0; - hms_ops.to_terminal_ours = 0; - hms_ops.to_terminal_info = 0; - hms_ops.to_kill = hms_kill; - hms_ops.to_load = generic_load; - hms_ops.to_lookup_symbol = 0; - hms_ops.to_create_inferior = hms_create_inferior; - hms_ops.to_post_startup_inferior = NULL; - hms_ops.to_acknowledge_created_inferior = NULL; - hms_ops.to_clone_and_follow_inferior = NULL; - hms_ops.to_post_follow_inferior_by_clone = NULL; - hms_ops.to_insert_fork_catchpoint = NULL; - hms_ops.to_remove_fork_catchpoint = NULL; - hms_ops.to_insert_vfork_catchpoint = NULL; - hms_ops.to_remove_vfork_catchpoint = NULL; - hms_ops.to_has_forked = NULL; - hms_ops.to_has_vforked = NULL; - hms_ops.to_can_follow_vfork_prior_to_exec = NULL; - hms_ops.to_post_follow_vfork = NULL; - hms_ops.to_insert_exec_catchpoint = NULL; - hms_ops.to_remove_exec_catchpoint = NULL; - hms_ops.to_has_execd = NULL; - hms_ops.to_reported_exec_events_per_exec_call = NULL; - hms_ops.to_has_exited = NULL; - hms_ops.to_mourn_inferior = hms_mourn; - hms_ops.to_can_run = 0; - hms_ops.to_notice_signals = 0; - hms_ops.to_thread_alive = 0; - hms_ops.to_stop = 0; - hms_ops.to_pid_to_exec_file = NULL; - hms_ops.to_core_file_to_sym_file = NULL; - hms_ops.to_stratum = process_stratum; - hms_ops.DONT_USE = 0; - hms_ops.to_has_all_memory = 1; - hms_ops.to_has_memory = 1; - hms_ops.to_has_stack = 1; - hms_ops.to_has_registers = 1; - hms_ops.to_has_execution = 1; - hms_ops.to_sections = 0; - hms_ops.to_sections_end = 0; - hms_ops.to_magic = OPS_MAGIC; -}; - -hms_quiet () /* FIXME - this routine can be removed after Dec '94 */ -{ - quiet = !quiet; - if (quiet) - printf_filtered ("Snoop disabled\n"); - else - printf_filtered ("Snoop enabled\n"); - - printf_filtered ("`snoop' is obsolete, please use `set remotedebug'.\n"); -} - -hms_device (s) - char *s; -{ - if (s) - { - dev_name = get_word (&s); - } -} - -static -hms_speed (s) - char *s; -{ - check_open (); - - if (s) - { - char buffer[100]; - int newrate = atoi (s); - int which = 0; - - if (SERIAL_SETBAUDRATE (desc, newrate)) - error ("Can't use %d baud\n", newrate); - - printf_filtered ("Checking target is in sync\n"); - - printf_filtered ("Sending commands to set target to %d\n", - baudrate); - - sprintf (buffer, "tm %d. N 8 1", baudrate); - hms_write_cr (buffer); - } -} - -/***********************************************************************/ - -static void -hms_drain (args, fromtty) - char *args; - int fromtty; -{ - int c; - while (1) - { - c = SERIAL_READCHAR (desc, 1); - if (c == SERIAL_TIMEOUT) - break; - if (c == SERIAL_ERROR) - break; - if (c > ' ' && c < 127) - printf ("%c", c & 0xff); - else - printf ("<%x>", c & 0xff); - } -} - -static void -add_commands () -{ - - add_com ("hms_drain", class_obscure, hms_drain, - "Drain pending hms text buffers."); -} - -static void -remove_commands () -{ - extern struct cmd_list_element *cmdlist; - delete_cmd ("hms-drain", &cmdlist); -} - - -void -_initialize_remote_hms () -{ - init_hms_ops (); - add_target (&hms_ops); - - add_com ("hms <command>", class_obscure, hms_com, - "Send a command to the HMS monitor."); - - /* FIXME - hms_quiet and `snoop' can be removed after Dec '94 */ - add_com ("snoop", class_obscure, hms_quiet, - "Show what commands are going to the monitor (OBSOLETE - see 'set remotedebug')"); - - add_com ("device", class_obscure, hms_device, - "Set the terminal line for HMS communications"); - - add_com ("speed", class_obscure, hms_speed, - "Set the terminal line speed for HMS communications"); - - dev_name = NULL; -} -#endif diff --git a/gdb/remote.c b/gdb/remote.c index aae39bef8a2..24d382e86eb 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -64,8 +64,7 @@ void async_remote_interrupt_twice PARAMS ((gdb_client_data)); static void build_remote_gdbarch_data PARAMS ((void)); -static int remote_write_bytes PARAMS ((CORE_ADDR memaddr, - char *myaddr, int len)); +static int remote_write_bytes (CORE_ADDR memaddr, char *myaddr, int len); static int remote_read_bytes PARAMS ((CORE_ADDR memaddr, char *myaddr, int len)); @@ -2269,8 +2268,7 @@ remote_async_terminal_ours (void) int kill_kludge; void -remote_console_output (msg) - char *msg; +remote_console_output (char *msg) { char *p; @@ -2282,6 +2280,7 @@ remote_console_output (msg) tb[1] = 0; fputs_unfiltered (tb, gdb_stdtarg); } + gdb_flush (gdb_stdtarg); } /* Wait until the remote machine stops, then return, @@ -3078,139 +3077,134 @@ check_binary_download (addr) MYADDR is the address of the buffer in our space. LEN is the number of bytes. - Returns number of bytes transferred, or 0 for error. */ + Returns number of bytes transferred, or 0 (setting errno) for + error. Only transfer a single packet. */ static int -remote_write_bytes (memaddr, myaddr, len) - CORE_ADDR memaddr; - char *myaddr; - int len; +remote_write_bytes (CORE_ADDR memaddr, char *myaddr, int len) { - unsigned char *buf = alloca (PBUFSIZ); + unsigned char *buf; int max_buf_size; /* Max size of packet output buffer */ - int origlen; + unsigned char *p; + unsigned char *plen; + int plenlen; + int todo; + int nr_bytes; /* Verify that the target can support a binary download */ check_binary_download (memaddr); - /* Chop the transfer down if necessary */ - + /* Determine the max packet size. */ max_buf_size = min (remote_write_size, PBUFSIZ); if (remote_register_buf_size != 0) max_buf_size = min (max_buf_size, remote_register_buf_size); + buf = alloca (max_buf_size + 1); /* Subtract header overhead from max payload size - $M<memaddr>,<len>:#nn */ max_buf_size -= 2 + hexnumlen (memaddr + len - 1) + 1 + hexnumlen (len) + 4; - origlen = len; - while (len > 0) - { - unsigned char *p, *plen; - int plenlen; - int todo; - int i; + /* construct "M"<memaddr>","<len>":" */ + /* sprintf (buf, "M%lx,%x:", (unsigned long) memaddr, todo); */ + p = buf; - /* construct "M"<memaddr>","<len>":" */ - /* sprintf (buf, "M%lx,%x:", (unsigned long) memaddr, todo); */ - memaddr = remote_address_masked (memaddr); - p = buf; - switch (remote_protocol_binary_download.support) + /* Append [XM]. Compute a best guess of the number of bytes + actually transfered. */ + switch (remote_protocol_binary_download.support) + { + case PACKET_ENABLE: + *p++ = 'X'; + /* Best guess at number of bytes that will fit. */ + todo = min (len, max_buf_size); + break; + case PACKET_DISABLE: + *p++ = 'M'; + /* num bytes that will fit */ + todo = min (len, max_buf_size / 2); + break; + case PACKET_SUPPORT_UNKNOWN: + internal_error ("remote_write_bytes: bad switch"); + } + + /* Append <memaddr> */ + memaddr = remote_address_masked (memaddr); + p += hexnumstr (p, (ULONGEST) memaddr); + *p++ = ','; + + /* Append <len>. Retain the location/size of <len>. It may + need to be adjusted once the packet body has been created. */ + plen = p; + plenlen = hexnumstr (p, (ULONGEST) todo); + p += plenlen; + *p++ = ':'; + *p = '\0'; + + /* Append the packet body. */ + switch (remote_protocol_binary_download.support) + { + case PACKET_ENABLE: + /* Binary mode. Send target system values byte by byte, in + increasing byte addresses. Only escape certain critical + characters. */ + for (nr_bytes = 0; + (nr_bytes < todo) && (p - buf) < (max_buf_size - 2); + nr_bytes++) { - case PACKET_ENABLE: - *p++ = 'X'; - todo = min (len, max_buf_size); - break; - case PACKET_DISABLE: - *p++ = 'M'; - todo = min (len, max_buf_size / 2); /* num bytes that will fit */ - break; - case PACKET_SUPPORT_UNKNOWN: - internal_error ("remote_write_bytes: bad switch"); + switch (myaddr[nr_bytes] & 0xff) + { + case '$': + case '#': + case 0x7d: + /* These must be escaped */ + *p++ = 0x7d; + *p++ = (myaddr[nr_bytes] & 0xff) ^ 0x20; + break; + default: + *p++ = myaddr[nr_bytes] & 0xff; + break; + } } - - p += hexnumstr (p, (ULONGEST) memaddr); - *p++ = ','; - - plen = p; /* remember where len field goes */ - plenlen = hexnumstr (p, (ULONGEST) todo); - p += plenlen; - *p++ = ':'; - *p = '\0'; - - /* We send target system values byte by byte, in increasing byte - addresses, each byte encoded as two hex characters (or one - binary character). */ - switch (remote_protocol_binary_download.support) + if (nr_bytes < todo) { - case PACKET_ENABLE: - { - int escaped = 0; - for (i = 0; - (i < todo) && (i + escaped) < (max_buf_size - 2); - i++) - { - switch (myaddr[i] & 0xff) - { - case '$': - case '#': - case 0x7d: - /* These must be escaped */ - escaped++; - *p++ = 0x7d; - *p++ = (myaddr[i] & 0xff) ^ 0x20; - break; - default: - *p++ = myaddr[i] & 0xff; - break; - } - } - - if (i < todo) - { - /* Escape chars have filled up the buffer prematurely, - and we have actually sent fewer bytes than planned. - Fix-up the length field of the packet. Use the same - number of characters as before. */ - - plen += hexnumnstr (plen, (ULONGEST) i, plenlen); - *plen = ':'; /* overwrite \0 from hexnumnstr() */ - } - break; - } - case PACKET_DISABLE: - { - for (i = 0; i < todo; i++) - { - *p++ = tohex ((myaddr[i] >> 4) & 0xf); - *p++ = tohex (myaddr[i] & 0xf); - } - *p = '\0'; - break; - } - case PACKET_SUPPORT_UNKNOWN: - internal_error ("remote_write_bytes: bad switch"); + /* Escape chars have filled up the buffer prematurely, + and we have actually sent fewer bytes than planned. + Fix-up the length field of the packet. Use the same + number of characters as before. */ + + plen += hexnumnstr (plen, (ULONGEST) nr_bytes, plenlen); + *plen = ':'; /* overwrite \0 from hexnumnstr() */ } - - putpkt_binary (buf, (int) (p - buf)); - getpkt (buf, 0); - - if (buf[0] == 'E') + break; + case PACKET_DISABLE: + /* Normal mode: Send target system values byte by byte, in + increasing byte addresses. Each byte is encoded as a two hex + value. */ + for (nr_bytes = 0; nr_bytes < todo; nr_bytes++) { - /* There is no correspondance between what the remote protocol uses - for errors and errno codes. We would like a cleaner way of - representing errors (big enough to include errno codes, bfd_error - codes, and others). But for now just return EIO. */ - errno = EIO; - return 0; + *p++ = tohex ((myaddr[nr_bytes] >> 4) & 0xf); + *p++ = tohex (myaddr[nr_bytes] & 0xf); } - - /* Increment by i, not by todo, in case escape chars - caused us to send fewer bytes than we'd planned. */ - myaddr += i; - memaddr += i; - len -= i; + *p = '\0'; + break; + case PACKET_SUPPORT_UNKNOWN: + internal_error ("remote_write_bytes: bad switch"); } - return origlen; + + putpkt_binary (buf, (int) (p - buf)); + getpkt (buf, 0); + + if (buf[0] == 'E') + { + /* There is no correspondance between what the remote protocol + uses for errors and errno codes. We would like a cleaner way + of representing errors (big enough to include errno codes, + bfd_error codes, and others). But for now just return EIO. */ + errno = EIO; + return 0; + } + + /* Return NR_BYTES, not TODO, in case escape chars caused us to send fewer + bytes than we'd planned. */ + return nr_bytes; } /* Read memory data directly from the remote machine. @@ -3221,6 +3215,13 @@ remote_write_bytes (memaddr, myaddr, len) Returns number of bytes transferred, or 0 for error. */ +/* NOTE: cagney/1999-10-18: This function (and its siblings in other + remote targets) shouldn't attempt to read the entire buffer. + Instead it should read a single packet worth of data and then + return the byte size of that packet to the caller. The caller (its + caller and its callers caller ;-) already contains code for + handling partial reads. */ + static int remote_read_bytes (memaddr, myaddr, len) CORE_ADDR memaddr; diff --git a/gdb/remote.h b/gdb/remote.h index 93fd04a589b..f6fb450e2eb 100644 --- a/gdb/remote.h +++ b/gdb/remote.h @@ -40,7 +40,7 @@ extern int putpkt (char *buf); /* Send HEX encoded string to the target console. (gdb_stdtarg) */ -extern void remote_console_output PARAMS ((char *)); +extern void remote_console_output (char *); /* FIXME: cagney/1999-09-20: The remote cisco stuff in remote.c needs diff --git a/gdb/symfile.c b/gdb/symfile.c index 8390b6de261..c7271686523 100644 --- a/gdb/symfile.c +++ b/gdb/symfile.c @@ -63,7 +63,7 @@ extern int hp_cxx_exception_support_initialized; } while (0) #endif -int (*ui_load_progress_hook) PARAMS ((char *, unsigned long)); +int (*ui_load_progress_hook) (const char *section, unsigned long num); void (*pre_add_symbol_hook) PARAMS ((char *)); void (*post_add_symbol_hook) PARAMS ((void)); @@ -1207,42 +1207,52 @@ load_command (arg, from_tty) to worry about finding it, and (b) On VMS, fork() is very slow and so we don't want to run a subprocess. On the other hand, I'm not sure how performance compares. */ -#define GENERIC_LOAD_CHUNK 256 -#define VALIDATE_DOWNLOAD 0 + +static int download_write_size = 512; +static int validate_download = 0; + void -generic_load (filename, from_tty) - char *filename; - int from_tty; +generic_load (char *args, int from_tty) { - struct cleanup *old_cleanups; asection *s; 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[GENERIC_LOAD_CHUNK + 8]; -#if VALIDATE_DOWNLOAD - char verify_buffer[GENERIC_LOAD_CHUNK + 8]; -#endif - - /* enable user to specify address for downloading as 2nd arg to load */ - n = sscanf (filename, "%s 0x%lx", buf, &load_offset); - if (n > 1) - filename = buf; + unsigned long write_count = 0; /* Number of writes needed. */ + unsigned long load_offset; /* offset to add to vma for each section */ + char *filename; + struct cleanup *old_cleanups; + char *offptr; + + /* Parse the input argument - the user can specify a load offset as + a second argument. */ + filename = xmalloc (strlen (args) + 1); + old_cleanups = make_cleanup (free, filename); + strcpy (filename, args); + offptr = strchr (filename, ' '); + if (offptr != NULL) + { + char *endptr; + load_offset = strtoul (offptr, &endptr, 0); + if (offptr == endptr) + error ("Invalid download offset:%s\n", offptr); + *offptr = '\0'; + } else load_offset = 0; + /* Open the file for loading. */ loadfile_bfd = bfd_openr (filename, gnutarget); if (loadfile_bfd == NULL) { perror_with_name (filename); return; } + /* FIXME: should be checking for errors from bfd_close (for one thing, on error it does not free all the storage associated with the bfd). */ - old_cleanups = make_cleanup ((make_cleanup_func) bfd_close, loadfile_bfd); + make_cleanup ((make_cleanup_func) bfd_close, loadfile_bfd); if (!bfd_check_format (loadfile_bfd, bfd_object)) { @@ -1256,72 +1266,78 @@ generic_load (filename, from_tty) { if (s->flags & SEC_LOAD) { - bfd_size_type size; - - size = bfd_get_section_size_before_reloc (s); + CORE_ADDR size = bfd_get_section_size_before_reloc (s); if (size > 0) { char *buffer; struct cleanup *old_chain; - bfd_vma lma; - unsigned long l = size; + CORE_ADDR lma = s->lma + load_offset; + CORE_ADDR block_size; int err; - char *sect; - unsigned long sent; - unsigned long len; + const char *sect_name = bfd_get_section_name (loadfile_bfd, s); + CORE_ADDR sent; - l = l > GENERIC_LOAD_CHUNK ? GENERIC_LOAD_CHUNK : l; + if (download_write_size > 0 && size > download_write_size) + block_size = download_write_size; + else + block_size = size; buffer = xmalloc (size); old_chain = make_cleanup (free, buffer); - lma = s->lma; - lma += load_offset; - /* Is this really necessary? I guess it gives the user something to look at during a long download. */ - printf_filtered ("Loading section %s, size 0x%lx lma ", - bfd_get_section_name (loadfile_bfd, s), - (unsigned long) size); - print_address_numeric (lma, 1, gdb_stdout); - printf_filtered ("\n"); + fprintf_unfiltered (gdb_stdout, + "Loading section %s, size 0x%s lma 0x%s\n", + sect_name, paddr_nz (size), paddr_nz (lma)); bfd_get_section_contents (loadfile_bfd, s, buffer, 0, size); - sect = (char *) bfd_get_section_name (loadfile_bfd, s); sent = 0; do { - len = (size - sent) < l ? (size - sent) : l; - sent += len; - err = target_write_memory (lma, buffer, len); - if (ui_load_progress_hook) - if (ui_load_progress_hook (sect, sent)) - error ("Canceled the download"); -#if VALIDATE_DOWNLOAD - /* Broken memories and broken monitors manifest themselves - here when bring new computers to life. - This doubles already slow downloads. - */ + CORE_ADDR len; + CORE_ADDR this_transfer = size - sent; + if (this_transfer >= block_size) + this_transfer = block_size; + len = target_write_memory_partial (lma, buffer, + this_transfer, &err); if (err) break; - { - target_read_memory (lma, verify_buffer, len); - if (0 != bcmp (buffer, verify_buffer, len)) - error ("Download verify failed at %08x", - (unsigned long) lma); - } - -#endif + if (validate_download) + { + /* Broken memories and broken monitors manifest + themselves here when bring new computers to + life. This doubles already slow downloads. */ + /* NOTE: cagney/1999-10-18: A more efficient + implementation might add a verify_memory() + method to the target vector and then use + that. remote.c could implement that method + using the ``qCRC'' packet. */ + char *check = xmalloc (len); + struct cleanup *verify_cleanups = make_cleanup (free, check); + if (target_read_memory (lma, check, len) != 0) + error ("Download verify read failed at 0x%s", + paddr (lma)); + if (memcmp (buffer, check, len) != 0) + error ("Download verify compare failed at 0x%s", + paddr (lma)); + do_cleanups (verify_cleanups); + } data_count += len; lma += len; buffer += len; - } /* od */ - while (err == 0 && sent < size); + write_count += 1; + sent += len; + if (quit_flag + || (ui_load_progress_hook != NULL + && ui_load_progress_hook (sect_name, sent))) + error ("Canceled the download"); + } + while (sent < size); if (err != 0) - error ("Memory access error while loading section %s.", - bfd_get_section_name (loadfile_bfd, s)); + error ("Memory access error while loading section %s.", sect_name); do_cleanups (old_chain); } @@ -1330,9 +1346,11 @@ generic_load (filename, from_tty) end_time = time (NULL); { - unsigned long entry; + CORE_ADDR entry; entry = bfd_get_start_address (loadfile_bfd); - printf_filtered ("Start address 0x%lx , load size %ld\n", entry, data_count); + fprintf_unfiltered (gdb_stdout, + "Start address 0x%s , load size %ld\n", + paddr_nz (entry), data_count); /* We were doing this in remote-mips.c, I suspect it is right for other targets too. */ write_pc (entry); @@ -1344,25 +1362,40 @@ generic_load (filename, from_tty) loaded in. remote-nindy.c had no call to symbol_file_add, but remote-vx.c does. */ - report_transfer_performance (data_count, start_time, end_time); + print_transfer_performance (gdb_stdout, data_count, write_count, + end_time - start_time); do_cleanups (old_cleanups); } /* Report how fast the transfer went. */ +/* DEPRECATED: cagney/1999-10-18: report_transfer_performance is being + replaced by print_transfer_performance (with a very different + function signature). */ + void report_transfer_performance (data_count, start_time, end_time) unsigned long data_count; time_t start_time, end_time; { - printf_filtered ("Transfer rate: "); - if (end_time != start_time) - printf_filtered ("%ld bits/sec", - (data_count * 8) / (end_time - start_time)); + print_transfer_performance (gdb_stdout, data_count, end_time - start_time, 0); +} + +void +print_transfer_performance (struct gdb_file *stream, + unsigned long data_count, + unsigned long write_count, + unsigned long time_count) +{ + fprintf_unfiltered (stream, "Transfer rate: "); + if (time_count > 0) + fprintf_unfiltered (stream, "%ld bits/sec", (data_count * 8) / time_count); else - printf_filtered ("%ld bits in <1 sec", (data_count * 8)); - printf_filtered (".\n"); + fprintf_unfiltered (stream, "%ld bits in <1 sec", (data_count * 8)); + if (write_count > 0) + fprintf_unfiltered (stream, ", %ld bytes/write", data_count / write_count); + fprintf_unfiltered (stream, ".\n"); } /* This function allows the addition of incrementally linked object files. @@ -3291,4 +3324,16 @@ Usage: set extension-language .foo bar", add_info ("extensions", info_ext_lang_command, "All filename extensions associated with a source language."); + + add_show_from_set + (add_set_cmd ("download-write-size", class_obscure, + var_integer, (char *) &download_write_size, + "Set the write size used when downloading a program.\n" + "Only used when downloading a program onto a remote\n" + "target. Specify zero, or a negative value, to disable\n" + "blocked writes. The actual size of each transfer is also\n" + "limited by the size of the target packet and the memory\n" + "cache.\n", + &setlist), + &showlist); } diff --git a/gdb/symfile.h b/gdb/symfile.h index bcf00eb816e..aeeb28f1e06 100644 --- a/gdb/symfile.h +++ b/gdb/symfile.h @@ -221,9 +221,6 @@ extern void find_lowest_section PARAMS ((bfd *, asection *, PTR)); extern bfd *symfile_bfd_open PARAMS ((char *)); -/* Remote targets may wish to use this as their load function. */ -extern void generic_load PARAMS ((char *name, int from_tty)); - /* Utility functions for overlay sections: */ extern int overlay_debugging; extern int overlay_cache_invalid; diff --git a/gdb/symtab.c b/gdb/symtab.c index 36a40519416..92af60a599e 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -4413,7 +4413,10 @@ overload_list_add_symbol (sym, oload_name) /* skip symbols that cannot match */ if (strcmp (sym_name, oload_name) != 0) - return; + { + free (sym_name); + return; + } /* If there is no type information, we can't do anything, so skip */ if (SYMBOL_TYPE (sym) == NULL) @@ -4475,18 +4478,8 @@ make_symbol_overload_list (fsym) sym_return_val = (struct symbol **) xmalloc ((sym_return_val_size + 1) * sizeof (struct symbol *)); sym_return_val[0] = NULL; - /* Comment and #if 0 from Rajiv Mirani <mirani@cup.hp.com>. - However, leaving #if 0's around is uncool. We need to figure out - what this is really trying to do, decide whether we want that, - and either fix it or delete it. --- Jim Blandy, Mar 1999 */ - - /* ??? RM: What in hell is this? overload_list_add_symbol expects a symbol, - * not a partial_symbol or a minimal_symbol. And it looks at the type field - * of the symbol, and we don't know the type of minimal and partial symbols - */ -#if 0 /* Look through the partial symtabs for all symbols which begin - by matching OLOAD_NAME. Add each one that you find to the list. */ + by matching OLOAD_NAME. Make sure we read that symbol table in. */ ALL_PSYMTABS (objfile, ps) { @@ -4504,7 +4497,8 @@ make_symbol_overload_list (fsym) { /* If interrupted, then quit. */ QUIT; - overload_list_add_symbol (*psym, oload_name); + /* This will cause the symbol table to be read if it has not yet been */ + s = PSYMTAB_TO_SYMTAB (ps); } for (psym = objfile->static_psymbols.list + ps->statics_offset; @@ -4513,22 +4507,11 @@ make_symbol_overload_list (fsym) psym++) { QUIT; - overload_list_add_symbol (*psym, oload_name); + /* This will cause the symbol table to be read if it has not yet been */ + s = PSYMTAB_TO_SYMTAB (ps); } } - /* At this point scan through the misc symbol vectors and add each - symbol you find to the list. Eventually we want to ignore - anything that isn't a text symbol (everything else will be - handled by the psymtab code above). */ - - ALL_MSYMBOLS (objfile, msymbol) - { - QUIT; - overload_list_add_symbol (msymbol, oload_name); - } -#endif - /* Search upwards from currently selected frame (so that we can complete on local vars. */ diff --git a/gdb/target.c b/gdb/target.c index 6d0b796047c..aa8f28d163b 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -87,10 +87,11 @@ static void nosupport_runtime PARAMS ((void)); static void normal_target_post_startup_inferior PARAMS ((int pid)); -/* Transfer LEN bytes between target address MEMADDR and GDB address MYADDR. - Returns 0 for success, errno code for failure (which includes partial - transfers--if you want a more useful response to partial transfers, try - target_read_memory_partial). */ +/* Transfer LEN bytes between target address MEMADDR and GDB address + MYADDR. Returns 0 for success, errno code for failure (which + includes partial transfers -- if you want a more useful response to + partial transfers, try either target_read_memory_partial or + target_write_memory_partial). */ static int target_xfer_memory PARAMS ((CORE_ADDR memaddr, char *myaddr, int len, @@ -787,48 +788,6 @@ target_read_memory_section (memaddr, myaddr, len, bfd_section) return target_xfer_memory (memaddr, myaddr, len, 0, bfd_section); } -/* Read LEN bytes of target memory at address MEMADDR, placing the results - in GDB's memory at MYADDR. Returns a count of the bytes actually read, - and optionally an errno value in the location pointed to by ERRNOPTR - if ERRNOPTR is non-null. */ - -int -target_read_memory_partial (memaddr, myaddr, len, errnoptr) - CORE_ADDR memaddr; - char *myaddr; - int len; - int *errnoptr; -{ - int nread; /* Number of bytes actually read. */ - int errcode; /* Error from last read. */ - - /* First try a complete read. */ - errcode = target_xfer_memory (memaddr, myaddr, len, 0, NULL); - if (errcode == 0) - { - /* Got it all. */ - nread = len; - } - else - { - /* Loop, reading one byte at a time until we get as much as we can. */ - for (errcode = 0, nread = 0; len > 0 && errcode == 0; nread++, len--) - { - errcode = target_xfer_memory (memaddr++, myaddr++, 1, 0, NULL); - } - /* If an error, the last read was unsuccessful, so adjust count. */ - if (errcode != 0) - { - nread--; - } - } - if (errnoptr != NULL) - { - *errnoptr = errcode; - } - return (nread); -} - int target_write_memory (memaddr, myaddr, len) CORE_ADDR memaddr; @@ -923,6 +882,75 @@ target_xfer_memory (memaddr, myaddr, len, write, bfd_section) } +/* Perform a partial memory transfer. */ + +static int +target_xfer_memory_partial (CORE_ADDR memaddr, char *buf, int len, + int write_p, int *err) +{ + int res; + int err_res; + int len_res; + struct target_ops *t; + struct target_stack_item *item; + + /* Zero length requests are ok and require no work. */ + if (len == 0) + { + *err = 0; + return 0; + } + + /* The quick case is that the top target does it all. */ + res = current_target.to_xfer_memory (memaddr, buf, len, write_p, ¤t_target); + if (res > 0) + { + *err = 0; + return res; + } + + /* xfer memory doesn't always reliably set errno. */ + errno = 0; + + /* Try all levels of the target stack to see one can handle it. */ + for (item = target_stack; item; item = item->next) + { + t = item->target_ops; + if (!t->to_has_memory) + continue; + res = t->to_xfer_memory (memaddr, buf, len, write_p, t); + if (res > 0) + { + /* Handled all or part of xfer */ + *err = 0; + return res; + } + if (t->to_has_all_memory) + break; + } + + /* Total failure. Return error. */ + if (errno != 0) + { + *err = errno; + return -1; + } + *err = EIO; + return -1; +} + +int +target_read_memory_partial (CORE_ADDR memaddr, char *buf, int len, int *err) +{ + return target_xfer_memory_partial (memaddr, buf, len, 0, err); +} + +int +target_write_memory_partial (CORE_ADDR memaddr, char *buf, int len, int *err) +{ + return target_xfer_memory_partial (memaddr, buf, len, 1, err); +} + /* ARGSUSED */ static void target_info (args, from_tty) diff --git a/gdb/target.h b/gdb/target.h index 276657f0fbd..7fc9e8642ba 100644 --- a/gdb/target.h +++ b/gdb/target.h @@ -591,9 +591,6 @@ target_read_memory_section PARAMS ((CORE_ADDR memaddr, char *myaddr, int len, asection * bfd_section)); extern int -target_read_memory_partial PARAMS ((CORE_ADDR, char *, int, int *)); - -extern int target_write_memory PARAMS ((CORE_ADDR, char *, int)); extern int @@ -602,6 +599,16 @@ xfer_memory PARAMS ((CORE_ADDR, char *, int, int, struct target_ops *)); extern int child_xfer_memory PARAMS ((CORE_ADDR, char *, int, int, struct target_ops *)); +/* Make a single attempt at transfering LEN bytes. On a successful + transfer, the number of bytes actually transfered is returned and + ERR is set to 0. When a transfer fails, -1 is returned (the number + of bytes actually transfered is not defined) and ERR is set to a + non-zero error indication. */ + +extern int target_read_memory_partial (CORE_ADDR addr, char *buf, int len, int *err); + +extern int target_write_memory_partial (CORE_ADDR addr, char *buf, int len, int *err); + extern char * child_pid_to_exec_file PARAMS ((int)); @@ -1258,6 +1265,10 @@ extern int memory_remove_breakpoint PARAMS ((CORE_ADDR, char *)); extern int memory_insert_breakpoint PARAMS ((CORE_ADDR, char *)); +extern int default_memory_remove_breakpoint PARAMS ((CORE_ADDR, char *)); + +extern int default_memory_insert_breakpoint PARAMS ((CORE_ADDR, char *)); + extern breakpoint_from_pc_fn memory_breakpoint_from_pc; #ifndef BREAKPOINT_FROM_PC #define BREAKPOINT_FROM_PC(pcptr, lenptr) memory_breakpoint_from_pc (pcptr, lenptr) diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 6fa430c5b2a..06e699f25f2 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,16 @@ +1999-10-18 Jim Blandy <jimb@zwingli.cygnus.com> + + * gdb.threads/linux-dp.c, gdb.threads/linux-dp.exp: New test suite + for LinuxThreads support, merged from the Code Fusion branch. + +Mon Oct 11 13:57:21 1999 Andrew Cagney <cagney@amy.cygnus.com> + + * lib/gdb.exp (gdb_run_cmd): Break complicated gdb_expect + containing exp_continue into a while within an expect. Don't + attempt a start more than three times. Check return value from + gdb_load. + + Wed Oct 6 12:05:58 1999 Andrew Cagney <cagney@b1.cygnus.com> * gdb.base/watchpoint.exp: Match fail ``finish from marker1'' with diff --git a/gdb/testsuite/gdb.threads/linux-dp.c b/gdb/testsuite/gdb.threads/linux-dp.c new file mode 100644 index 00000000000..b66649b6411 --- /dev/null +++ b/gdb/testsuite/gdb.threads/linux-dp.c @@ -0,0 +1,205 @@ +/* linux-dp.c --- dining philosophers, on LinuxThreads + Jim Blandy <jimb@cygnus.com> --- March 1999 */ + +/* It's okay to edit this file and shift line numbers around. The + tests use gdb_get_line_number to find source locations, so they + don't depend on having certain line numbers in certain places. */ + +#include <stdarg.h> +#include <stdlib.h> +#include <stdio.h> +#include <pthread.h> +#include <sys/time.h> +#include <sys/types.h> + +/* The number of philosophers at the table. */ +int num_philosophers; + +/* Mutex ordering - + If you want to lock a mutex M, all the mutexes you have locked + already must appear before M on this list. + + fork_mutex[0] + fork_mutex[1] + ... + fork_mutex[num_philosophers - 1] + stdout_mutex + random_mutex +*/ + +/* You must hold this mutex while writing to stdout. */ +pthread_mutex_t stdout_mutex; + +/* You must hold this mutex while calling any of the random number + generation routines. */ +pthread_mutex_t random_mutex; + +/* array of mutexes, one for each fork; fork_mutex[i] is to the left + of philosopher i. A philosopher is holding fork i iff his/her + thread has locked fork_mutex[i]. */ +pthread_mutex_t *fork_mutex; + +/* array of threads, one representing each philosopher. */ +pthread_t *philosophers; + +void * +xmalloc (size_t n) +{ + void *p = malloc (n); + + if (! p) + { + fprintf (stderr, "out of memory\n"); + exit (2); + } + + return p; +} + +void +shared_printf (char *format, ...) +{ + va_list ap; + + va_start (ap, format); + pthread_mutex_lock (&stdout_mutex); + vprintf (format, ap); + pthread_mutex_unlock (&stdout_mutex); + va_end (ap); +} + +int +shared_random () +{ + static unsigned int seed; + int result; + + pthread_mutex_lock (&random_mutex); + result = rand_r (&seed); + pthread_mutex_unlock (&random_mutex); + return result; +} + +void +my_usleep (long usecs) +{ + struct timeval timeout; + + timeout.tv_sec = usecs / 1000000; + timeout.tv_usec = usecs % 1000000; + + select (0, 0, 0, 0, &timeout); +} + +void +random_delay () +{ + my_usleep ((shared_random () % 2000) * 100); +} + +void +print_philosopher (int n, char left, char right) +{ + int i; + + shared_printf ("%*s%c %d %c\n", (n * 4) + 2, "", left, n, right); +} + +void * +philosopher (void *data) +{ + int n = * (int *) data; + + print_philosopher (n, '_', '_'); + +#if 1 + if (n == num_philosophers - 1) + for (;;) + { + /* The last philosopher is different. He goes for his right + fork first, so there is no cycle in the mutex graph. */ + + /* Grab the right fork. */ + pthread_mutex_lock (&fork_mutex[(n + 1) % num_philosophers]); + print_philosopher (n, '_', '!'); + random_delay (); + + /* Then grab the left fork. */ + pthread_mutex_lock (&fork_mutex[n]); + print_philosopher (n, '!', '!'); + random_delay (); + + print_philosopher (n, '_', '_'); + pthread_mutex_unlock (&fork_mutex[n]); + pthread_mutex_unlock (&fork_mutex[(n + 1) % num_philosophers]); + random_delay (); + } + else +#endif + for (;;) + { + /* Grab the left fork. */ + pthread_mutex_lock (&fork_mutex[n]); + print_philosopher (n, '!', '_'); + random_delay (); + + /* Then grab the right fork. */ + pthread_mutex_lock (&fork_mutex[(n + 1) % num_philosophers]); + print_philosopher (n, '!', '!'); + random_delay (); + + print_philosopher (n, '_', '_'); + pthread_mutex_unlock (&fork_mutex[n]); + pthread_mutex_unlock (&fork_mutex[(n + 1) % num_philosophers]); + random_delay (); + } +} + +int +main (int argc, char **argv) +{ + num_philosophers = 5; + + /* Set up the mutexes. */ + { + pthread_mutexattr_t ma; + int i; + + pthread_mutexattr_init (&ma); + pthread_mutex_init (&stdout_mutex, &ma); + pthread_mutex_init (&random_mutex, &ma); + fork_mutex = xmalloc (num_philosophers * sizeof (fork_mutex[0])); + for (i = 0; i < num_philosophers; i++) + pthread_mutex_init (&fork_mutex[i], &ma); + pthread_mutexattr_destroy (&ma); + } + + /* Set off the threads. */ + { + int i; + int *numbers = xmalloc (num_philosophers * sizeof (*numbers)); + pthread_attr_t ta; + + philosophers = xmalloc (num_philosophers * sizeof (*philosophers)); + + pthread_attr_init (&ta); + + for (i = 0; i < num_philosophers; i++) + { + numbers[i] = i; + /* linuxthreads.exp: create philosopher */ + pthread_create (&philosophers[i], &ta, philosopher, &numbers[i]); + } + + pthread_attr_destroy (&ta); + } + + /* linuxthreads.exp: info threads 2 */ + sleep (1000000); + + /* Drink yourself into oblivion. */ + for (;;) + sleep (1000000); + + return 0; +} diff --git a/gdb/testsuite/gdb.threads/linux-dp.exp b/gdb/testsuite/gdb.threads/linux-dp.exp new file mode 100644 index 00000000000..87dc868f9d4 --- /dev/null +++ b/gdb/testsuite/gdb.threads/linux-dp.exp @@ -0,0 +1,186 @@ +# Copyright (C) 1999 Free Software Foundation, Inc. + +# 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. + +# Please email any bugs, comments, and/or additions to this file to: +# bug-gdb@gnu.org + +#### Dining Philosophers, on LinuxThreads - Jim Blandy <jimb@cygnus.com> +#### +#### At the moment, GDB's support for LinuxThreads is pretty +#### idiosyncratic --- GDB's output doesn't look much like the output +#### it produces for other thread implementations, messages appear at +#### different times, etc. So these tests are specific to LinuxThreads. +#### +#### However, if all goes well, Linux will soon have a libthread_db +#### interface, and GDB will manage it the same way it does other +#### libthread_db-based systems. Then, we can adjust this file to +#### work with any such system. + +### Other things we ought to test: +### stepping a thread while others are running +### killing and restarting +### quitting gracefully + +if $tracelevel then { + strace $tracelevel +} + +set prms_id 0 +set bug_id 0 + +# This only works with Linux configurations. +if ![istarget *-*-linux-gnu] then { + return +} + +set testfile "linux-dp" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} +if {[gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug libs=-lpthread}] != ""} { + gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." +} + +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} +send_gdb "set print sevenbit-strings\n" ; gdb_expect -re "$gdb_prompt $" +runto_main + +# There should be no threads initially. +gdb_test "info threads" "" "info threads 1" + +# Try stepping over the thread creation function. +gdb_breakpoint [gdb_get_line_number "linuxthreads.exp: create philosopher"] +for {set i 0} {$i < 5} {incr i} { + gdb_continue_to_breakpoint "about to create philosopher: $i" + gdb_test "next" "\\\[New Thread .*\\\].*" "create philosopher: $i" +} + +# Run until there are some threads. +gdb_breakpoint [gdb_get_line_number "linuxthreads.exp: info threads 2"] +gdb_continue_to_breakpoint "main thread's sleep" +gdb_test "info threads" "7 Thread .*6 Thread .*5 Thread .*4 Thread .*3 Thread .*2 Thread .* \\(initial thread\\) main \\(argc=1, argv=.*\\) at .*linux-dp.c:.*1 Thread .* \\(manager thread\\).*" "info threads 2" + +# Try setting a thread-specific breakpoint. +gdb_breakpoint "print_philosopher thread 5" +gdb_continue_to_breakpoint "thread 5's print" +gdb_test "where" "print_philosopher.*philosopher.*pthread_start_thread.*" \ + "first thread-specific breakpoint hit" + +# Make sure it's catching the right thread. Try hitting the +# breakpoint ten times, and make sure we don't get anyone else. +set only_five 1 +for {set i 0} {$only_five > 0 && $i < 10} {incr i} { + gdb_continue_to_breakpoint "thread 5's print, pass: $i" + send_gdb "info threads\n" + gdb_expect { + -re "\\* 5 Thread .* print_philosopher .*\r\n$gdb_prompt $" { + # Okay this time. + } + -re ".*$gdb_prompt $" { + set only_five 0 + } + timeout { + set only_five -1 + } + } +} + +set name "thread-specific breakpoint is thread-specific" +if {$only_five == 1} { pass $name } +if {$only_five == 0} { fail $name } +if {$only_five == -1} { fail "$name (timeout)" } + + +### Select a particular thread. +proc select_thread {thread} { + global gdb_prompt + + send_gdb "thread $thread\n" + gdb_expect { + -re "\\\[Switching to thread .*\\\].*\r\n$gdb_prompt $" { + pass "selected thread: $thread" + } + -re "$gdb_prompt $" { + fail "selected thread: $thread" + } + timeout { + fail "selected thread: $thread (timeout)" + } + } +} + +### Select THREAD, check for a plausible backtrace, and make sure +### we're actually selecting a different philosopher each time. +### Return true if the thread had a stack which was not only +### acceptable, but interesting. SEEN should be an array in which +### SEEN(N) exists iff we have found philosopher number N before. +proc check_philosopher_stack {thread seen_name} { + global gdb_prompt + upvar $seen_name seen + + set name "philosopher is distinct: $thread" + set interesting 0 + + select_thread $thread + send_gdb "where\n" + gdb_expect { + -re ".* in philosopher \\(data=(0x\[0-9a-f\]+).*\r\n$gdb_prompt $" { + set data $expect_out(1,string) + if {[info exists seen($data)]} { + fail $name + } else { + pass $name + set seen($data) yep + } + set interesting 1 + } + -re "pthread_start_thread.*\r\n$gdb_prompt $" { + ## Maybe the thread hasn't started yet. + pass $name + } + -re " in \\?\\?.*\r\n$gdb_prompt $" { + ## Sometimes we can't get a backtrace. I'm going to call + ## this a pass, since we do verify that at least one + ## thread was interesting, so we can get more consistent + ## test suite totals. But in my heart, I think it should + ## be an xfail. + pass $name + } + -re "$gdb_prompt $" { + fail $name + } + timeout { + fail "$name (timeout)" + } + } + + return $interesting +} + +set any_interesting 0 +array set seen {} +for {set i 3} {$i <= 7} {incr i} { + if [check_philosopher_stack $i seen] { + set any_interesting 1 + } +} + +if {$any_interesting} { + pass "found an interesting thread" +} else { + fail "found an interesting thread" +} diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp index ab640a380ad..f3e3ed33b5f 100644 --- a/gdb/testsuite/lib/gdb.exp +++ b/gdb/testsuite/lib/gdb.exp @@ -180,8 +180,11 @@ proc gdb_run_cmd {args} { if [target_info exists use_gdb_stub] { if [target_info exists gdb,do_reload_on_run] { - # According to Stu, this will always work. - gdb_load ""; + # Specifying no file, defaults to the executable + # currently being debugged. + if { [gdb_load ""] < 0 } { + return; + } send_gdb "continue\n"; gdb_expect 60 { -re "Continu\[^\r\n\]*\[\r\n\]" {} @@ -196,31 +199,44 @@ proc gdb_run_cmd {args} { set start "start"; } send_gdb "jump *$start\n" - gdb_expect 30 { - -re "Continuing at \[^\r\n\]*\[\r\n\]" { - if ![target_info exists gdb_stub] { - return; - } - } - -re "No symbol \"start\" in current.*$gdb_prompt $" { - send_gdb "jump *_start\n"; - exp_continue; - } - -re "No symbol \"_start\" in current.*$gdb_prompt $" { - perror "Can't find start symbol to run in gdb_run"; + set start_attempt 1; + while { $start_attempt } { + # Cap (re)start attempts at three to ensure that this loop + # always eventually fails. Don't worry about trying to be + # clever and not send a command when it has failed. + if [expr $start_attempt > 3] { + perror "Jump to start() failed (retry count exceeded)"; return; } - -re "Line.* Jump anyway.*y or n. $" { - send_gdb "y\n" - exp_continue; - } - -re "No symbol.*context.*$gdb_prompt $" {} - -re "The program is not being run.*$gdb_prompt $" { - gdb_load ""; - send_gdb "jump *$start\n"; - exp_continue; + set start_attempt [expr $start_attempt + 1]; + gdb_expect 30 { + -re "Continuing at \[^\r\n\]*\[\r\n\]" { + set start_attempt 0; + } + -re "No symbol \"_start\" in current.*$gdb_prompt $" { + perror "Can't find start symbol to run in gdb_run"; + return; + } + -re "No symbol \"start\" in current.*$gdb_prompt $" { + send_gdb "jump *_start\n"; + } + -re "No symbol.*context.*$gdb_prompt $" { + set start_attempt 0; + } + -re "Line.* Jump anyway.*y or n. $" { + send_gdb "y\n" + } + -re "The program is not being run.*$gdb_prompt $" { + if { [gdb_load ""] < 0 } { + return; + } + send_gdb "jump *$start\n"; + } + timeout { + perror "Jump to start() failed (timeout)"; + return + } } - timeout { perror "Jump to start() failed (timeout)"; return } } if [target_info exists gdb_stub] { gdb_expect 60 { diff --git a/gdb/top.c b/gdb/top.c index 47f74a10868..5baf38a51b3 100644 --- a/gdb/top.c +++ b/gdb/top.c @@ -391,10 +391,6 @@ int (*query_hook) PARAMS ((const char *, va_list)); void (*warning_hook) PARAMS ((const char *, va_list)); -/* Called from gdb_flush to flush output. */ - -void (*flush_hook) PARAMS ((GDB_FILE * stream)); - /* These three functions support getting lines of text from the user. They are used in sequence. First readline_begin_hook is called with a text string that might be (for example) a message for the user to type in a diff --git a/gdb/tui/tui.c b/gdb/tui/tui.c index 53b8452df69..1e5593c10f8 100644 --- a/gdb/tui/tui.c +++ b/gdb/tui/tui.c @@ -85,7 +85,6 @@ tuiInit (argv0) * the bottom of the screen (tuiTermUnsetup()). */ fputs_unfiltered_hook = NULL; - flush_hook = NULL; rl_initialize (); /* need readline initialization to * create termcap sequences */ diff --git a/gdb/utils.c b/gdb/utils.c index f486199febf..61d9e46796e 100644 --- a/gdb/utils.c +++ b/gdb/utils.c @@ -47,6 +47,9 @@ #include <readline/readline.h> +#undef XMALLOC +#define XMALLOC(TYPE) ((TYPE*) xmalloc (sizeof (TYPE))) + /* readline defines this. */ #undef savestring @@ -1727,6 +1730,108 @@ stdio_fileopen (file) } +/* A pure memory based ``struct gdb_file'' that can be used an output + collector. It's input is available through gdb_file_put(). */ + +struct mem_file + { + int *magic; + char *buffer; + int sizeof_buffer; + int strlen_buffer; + }; + +extern gdb_file_fputs_ftype mem_file_fputs; +static gdb_file_rewind_ftype mem_file_rewind; +static gdb_file_put_ftype mem_file_put; +static gdb_file_delete_ftype mem_file_delete; +static struct gdb_file *mem_file_new PARAMS ((void)); +static int mem_file_magic; + +static struct gdb_file * +mem_file_new (void) +{ + struct mem_file *stream = XMALLOC (struct mem_file); + struct gdb_file *file = gdb_file_new (); + set_gdb_file_data (file, stream, mem_file_delete); + set_gdb_file_fputs (file, mem_file_fputs); + set_gdb_file_rewind (file, mem_file_rewind); + set_gdb_file_put (file, mem_file_put); + stream->magic = &mem_file_magic; + stream->buffer = NULL; + stream->sizeof_buffer = 0; + return file; +} + +static void +mem_file_delete (struct gdb_file *file) +{ + struct mem_file *stream = gdb_file_data (file); + if (stream->magic != &mem_file_magic) + internal_error ("mem_file_delete: bad magic number"); + if (stream->buffer != NULL) + free (stream->buffer); + free (stream); +} + +struct gdb_file * +mem_fileopen (void) +{ + return mem_file_new (); +} + +static void +mem_file_rewind (struct gdb_file *file) +{ + struct mem_file *stream = gdb_file_data (file); + if (stream->magic != &mem_file_magic) + internal_error ("mem_file_rewind: bad magic number"); + if (stream->buffer != NULL) + { + stream->buffer[0] = '\0'; + stream->strlen_buffer = 0; + } +} + +static void +mem_file_put (struct gdb_file *file, struct gdb_file *dest) +{ + struct mem_file *stream = gdb_file_data (file); + if (stream->magic != &mem_file_magic) + internal_error ("mem_file_put: bad magic number"); + if (stream->buffer != NULL) + fputs_unfiltered (stream->buffer, dest); +} + +void +mem_file_fputs (const char *linebuffer, struct gdb_file *file) +{ + struct mem_file *stream = gdb_file_data (file); + if (stream->magic != &mem_file_magic) + internal_error ("mem_file_fputs: bad magic number"); + if (stream->buffer == NULL) + { + stream->strlen_buffer = strlen (linebuffer); + stream->sizeof_buffer = stream->strlen_buffer + 1; + stream->buffer = xmalloc (stream->sizeof_buffer); + strcpy (stream->buffer, linebuffer); + } + else + { + int len = strlen (linebuffer); + int new_strlen = stream->strlen_buffer + len; + int new_sizeof = new_strlen + 1; + if (new_sizeof >= stream->sizeof_buffer) + { + stream->sizeof_buffer = new_sizeof; + stream->buffer = xrealloc (stream->buffer, stream->sizeof_buffer); + } + strcpy (stream->buffer + stream->strlen_buffer, linebuffer); + stream->strlen_buffer = new_strlen; + } +} + + /* A ``struct gdb_file'' that is compatible with all the legacy code. */ @@ -1875,12 +1980,10 @@ tui_file_fputs (linebuffer, file) #if defined(TUI) extern int tui_owns_terminal; #endif - /* If anything (GUI, TUI) wants to capture GDB output, this is - * the place... the way to do it is to set up - * fputs_unfiltered_hook. - * Our TUI ("gdb -tui") used to hook output, but in the - * new (XDB style) scheme, we do not do that anymore... - RT - */ + /* NOTE: cagney/1999-10-13: The use of fputs_unfiltered_hook is + seriously discouraged. Those wanting to hook output should + instead implement their own gdb_file object and install that. See + also tui_file_flush(). */ if (fputs_unfiltered_hook && (file == gdb_stdout || file == gdb_stderr)) @@ -2028,16 +2131,23 @@ tui_file_flush (file) { struct tui_stream *stream = gdb_file_data (file); if (stream->ts_magic != &tui_file_magic) - error ("Internal error: bad magic number"); - if (flush_hook - && (file == gdb_stdout - || file == gdb_stderr)) + internal_error ("tui_file_flush: bad magic number"); + + /* NOTE: cagney/1999-10-12: If we've been linked with code that uses + fputs_unfiltered_hook then we assume that it doesn't need to know + about flushes. Code that does need to know about flushes can + implement a proper gdb_file object. */ + if (fputs_unfiltered_hook) + return; + + switch (stream->ts_streamtype) { - flush_hook (file); - return; + case astring: + break; + case afile: + fflush (stream->ts_filestream); + break; } - - fflush (stream->ts_filestream); } void diff --git a/gdb/valops.c b/gdb/valops.c index d51b67db64d..515531f17ab 100644 --- a/gdb/valops.c +++ b/gdb/valops.c @@ -1074,7 +1074,7 @@ value_push (sp, arg) value_ptr arg; { register int len = TYPE_LENGTH (VALUE_ENCLOSING_TYPE (arg)); - register int container_len; + register int container_len = len; register int offset; /* How big is the container we're going to put this value in? */ @@ -2677,6 +2677,14 @@ find_overload_match (arg_types, nargs, name, method, lax, obj, fsym, valp, symp, int i = -1; func_name = cplus_demangle (SYMBOL_NAME (fsym), DMGL_NO_OPTS); + /* If the name is NULL this must be a C-style function. + Just return the same symbol. */ + if (!func_name) + { + *symp = fsym; + return 0; + } + oload_syms = make_symbol_overload_list (fsym); while (oload_syms[++i]) num_fns++; diff --git a/gdb/valprint.c b/gdb/valprint.c index 60a34be6102..83ce1168f5f 100644 --- a/gdb/valprint.c +++ b/gdb/valprint.c @@ -37,6 +37,9 @@ /* Prototypes for local functions */ +static int partial_memory_read (CORE_ADDR memaddr, char *myaddr, + int len, int *errnoptr); + static void print_hex_chars PARAMS ((GDB_FILE *, unsigned char *, unsigned int)); @@ -1149,6 +1152,47 @@ val_print_array_elements (type, valaddr, address, stream, format, deref_ref, } } +/* Read LEN bytes of target memory at address MEMADDR, placing the + results in GDB's memory at MYADDR. Returns a count of the bytes + actually read, and optionally an errno value in the location + pointed to by ERRNOPTR if ERRNOPTR is non-null. */ + +/* FIXME: cagney/1999-10-14: Only used by val_print_string. Can this + function be eliminated. */ + +static int +partial_memory_read (CORE_ADDR memaddr, char *myaddr, int len, int *errnoptr) +{ + int nread; /* Number of bytes actually read. */ + int errcode; /* Error from last read. */ + + /* First try a complete read. */ + errcode = target_read_memory (memaddr, myaddr, len); + if (errcode == 0) + { + /* Got it all. */ + nread = len; + } + else + { + /* Loop, reading one byte at a time until we get as much as we can. */ + for (errcode = 0, nread = 0; len > 0 && errcode == 0; nread++, len--) + { + errcode = target_read_memory (memaddr++, myaddr++, 1); + } + /* If an error, the last read was unsuccessful, so adjust count. */ + if (errcode != 0) + { + nread--; + } + } + if (errnoptr != NULL) + { + *errnoptr = errcode; + } + return (nread); +} + /* Print a string from the inferior, starting at ADDR and printing up to LEN characters, of WIDTH bytes a piece, to STREAM. If LEN is -1, printing stops at the first null byte, otherwise printing proceeds (including null @@ -1208,7 +1252,7 @@ val_print_string (addr, len, width, stream) bufptr = buffer; old_chain = make_cleanup (free, buffer); - nfetch = target_read_memory_partial (addr, bufptr, len * width, &errcode) + nfetch = partial_memory_read (addr, bufptr, len * width, &errcode) / width; addr += nfetch * width; bufptr += nfetch * width; @@ -1234,7 +1278,7 @@ val_print_string (addr, len, width, stream) bufsize += nfetch; /* Read as much as we can. */ - nfetch = target_read_memory_partial (addr, bufptr, nfetch * width, &errcode) + nfetch = partial_memory_read (addr, bufptr, nfetch * width, &errcode) / width; /* Scan this chunk for the null byte that terminates the string diff --git a/sim/common/ChangeLog b/sim/common/ChangeLog index 9cdbd7bf225..a1df5fef8cd 100644 --- a/sim/common/ChangeLog +++ b/sim/common/ChangeLog @@ -1,3 +1,19 @@ +1999-10-18 Dave Brolley <brolley@cygnus.com> + + * cgen-par.h (CGEN_MEM_DI_WRITE): New enumerator. + (CGEN_MEM_DF_WRITE): New enumerator. + (mem_di_write): New union member. + (mem_df_write): New union member. + * cgen-par.c (sim_queue_mem_di_write): New function. + (sim_queue_mem_df_write): New function. + (cgen_write_queue_element_execute): Handle CGEN_MEM_DI_WRITE and + CGEN_MEM_DF_WRITE. + * cgen-accfp.c (divsf): Check for division errors. + +1999-10-14 Doug Evans <devans@casey.cygnus.com> + + * cgen-engine.h (EXTRACT_INT,EXTRACT_UINT): Delete. + 1999-10-07 Dave Brolley <brolley@cygnus.com> * cgen-par.h (CGEN_FN_HI_WRITE): New enumerator. diff --git a/sim/common/cgen-accfp.c b/sim/common/cgen-accfp.c index 9ce204f97a2..0ef61fd4185 100644 --- a/sim/common/cgen-accfp.c +++ b/sim/common/cgen-accfp.c @@ -74,10 +74,13 @@ divsf (CGEN_FPU* fpu, SF x, SF y) sim_fpu op2; sim_fpu ans; unsigned32 res; + sim_fpu_status status; sim_fpu_32to (&op1, x); sim_fpu_32to (&op2, y); - sim_fpu_div (&ans, &op1, &op2); + status = sim_fpu_div (&ans, &op1, &op2); + if (status != 0) + (*fpu->ops->error) (fpu, status); sim_fpu_to32 (&res, &ans); return res; diff --git a/sim/common/cgen-engine.h b/sim/common/cgen-engine.h index d8bda1a7085..a0daf80f627 100644 --- a/sim/common/cgen-engine.h +++ b/sim/common/cgen-engine.h @@ -18,7 +18,9 @@ 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. */ -/* This file must be included after eng.h and before ${cpu}.h. */ +/* This file must be included after eng.h and before ${cpu}.h. + ??? A lot of this could be moved to genmloop.sh to be put in eng.h + and thus remove some conditional compilation. Worth it? */ /* Semantic functions come in six versions on two axes: fast/full-featured, and using one of the simple/scache/compilation engines. @@ -61,22 +63,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #define EXTRACT_LSB0_UINT(val, total, start, length) \ (((UINT) (val) << ((sizeof (UINT) * 8) - (start) - 1)) \ >> ((sizeof (UINT) * 8) - (length))) - -#if CGEN_INSN_LSB0_P - -#define EXTRACT_INT(val, total, start, length) \ - EXTRACT_LSB0_INT ((val), (total), (start), (length)) -#define EXTRACT_UINT(val, total, start, length) \ - EXTRACT_LSB0_UINT ((val), (total), (start), (length)) - -#else - -#define EXTRACT_INT(val, total, start, length) \ - EXTRACT_MSB0_INT ((val), (total), (start), (length)) -#define EXTRACT_UINT(val, total, start, length) \ - EXTRACT_MSB0_UINT ((val), (total), (start), (length)) - -#endif /* Semantic routines. */ diff --git a/sim/common/cgen-par.c b/sim/common/cgen-par.c index 1919aea3baf..d6450db0aba 100644 --- a/sim/common/cgen-par.c +++ b/sim/common/cgen-par.c @@ -155,6 +155,24 @@ void sim_queue_mem_si_write (SIM_CPU *cpu, SI address, SI value) element->kinds.mem_si_write.value = value; } +void sim_queue_mem_di_write (SIM_CPU *cpu, SI address, DI value) +{ + CGEN_WRITE_QUEUE *q = CPU_WRITE_QUEUE (cpu); + CGEN_WRITE_QUEUE_ELEMENT *element = CGEN_WRITE_QUEUE_NEXT (q); + element->kind = CGEN_MEM_DI_WRITE; + element->kinds.mem_di_write.address = address; + element->kinds.mem_di_write.value = value; +} + +void sim_queue_mem_df_write (SIM_CPU *cpu, SI address, DF value) +{ + CGEN_WRITE_QUEUE *q = CPU_WRITE_QUEUE (cpu); + CGEN_WRITE_QUEUE_ELEMENT *element = CGEN_WRITE_QUEUE_NEXT (q); + element->kind = CGEN_MEM_DF_WRITE; + element->kinds.mem_df_write.address = address; + element->kinds.mem_df_write.value = value; +} + /* Execute a write stored on the write queue. */ void cgen_write_queue_element_execute (SIM_CPU *cpu, CGEN_WRITE_QUEUE_ELEMENT *item) @@ -212,6 +230,16 @@ cgen_write_queue_element_execute (SIM_CPU *cpu, CGEN_WRITE_QUEUE_ELEMENT *item) SETMEMSI (cpu, pc, item->kinds.mem_si_write.address, item->kinds.mem_si_write.value); break; + case CGEN_MEM_DI_WRITE: + pc = CPU_PC_GET (cpu); + SETMEMDI (cpu, pc, item->kinds.mem_di_write.address, + item->kinds.mem_di_write.value); + break; + case CGEN_MEM_DF_WRITE: + pc = CPU_PC_GET (cpu); + SETMEMDF (cpu, pc, item->kinds.mem_df_write.address, + item->kinds.mem_df_write.value); + break; default: break; /* FIXME: for now....print message later. */ } diff --git a/sim/common/cgen-par.h b/sim/common/cgen-par.h index f0edfa6d0b4..c786d1c4896 100644 --- a/sim/common/cgen-par.h +++ b/sim/common/cgen-par.h @@ -26,7 +26,8 @@ enum cgen_write_queue_kind { CGEN_BI_WRITE, CGEN_QI_WRITE, CGEN_SI_WRITE, CGEN_SF_WRITE, CGEN_PC_WRITE, CGEN_FN_HI_WRITE, CGEN_FN_SI_WRITE, CGEN_FN_DI_WRITE, CGEN_FN_DF_WRITE, - CGEN_MEM_QI_WRITE, CGEN_MEM_HI_WRITE, CGEN_MEM_SI_WRITE, + CGEN_MEM_QI_WRITE, CGEN_MEM_HI_WRITE, CGEN_MEM_SI_WRITE, CGEN_MEM_DI_WRITE, + CGEN_MEM_DF_WRITE, CGEN_NUM_WRITE_KINDS }; @@ -85,6 +86,14 @@ typedef struct { SI address; SI value; } mem_si_write; + struct { + SI address; + DI value; + } mem_di_write; + struct { + SI address; + DI value; + } mem_df_write; } kinds; } CGEN_WRITE_QUEUE_ELEMENT; @@ -131,5 +140,7 @@ extern void sim_queue_fn_df_write (SIM_CPU *, void (*)(SIM_CPU *, UINT, DI), UIN extern void sim_queue_mem_qi_write (SIM_CPU *, SI, QI); extern void sim_queue_mem_hi_write (SIM_CPU *, SI, HI); extern void sim_queue_mem_si_write (SIM_CPU *, SI, SI); +extern void sim_queue_mem_di_write (SIM_CPU *, SI, DI); +extern void sim_queue_mem_df_write (SIM_CPU *, SI, DF); #endif /* CGEN_PAR_H */ |