mirror of
https://github.com/darlinghq/darling-gdb.git
synced 2024-11-24 04:29:49 +00:00
import gdb-1999-10-18 snapshot
This commit is contained in:
parent
446a06c9b8
commit
917317f4c6
219
gdb/ChangeLog
219
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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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. */
|
||||
|
@ -76,10 +76,40 @@ extern int i386_skip_prologue PARAMS ((int));
|
||||
|
||||
#define REGISTER_SIZE 4
|
||||
|
||||
/* Number of machine registers */
|
||||
/* 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.
|
||||
|
||||
#define NUM_FREGS 0 /*8*/ /* Number of FP regs */
|
||||
#define NUM_REGS (16 + NUM_FREGS) /* Basic i*86 regs + FP regs */
|
||||
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. */
|
||||
|
@ -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); \
|
||||
#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
|
||||
/* 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); \
|
||||
#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
|
||||
|
||||
#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; \
|
||||
}
|
||||
#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)); \
|
||||
}
|
||||
#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 */
|
||||
|
||||
|
14
gdb/dcache.c
14
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);
|
||||
|
||||
|
774
gdb/defs.h
774
gdb/defs.h
File diff suppressed because it is too large
Load Diff
@ -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.
|
||||
|
@ -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}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
14
gdb/eval.c
14
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:
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
@ -548,6 +554,12 @@ verify_gdbarch (struct gdbarch *gdbarch)
|
||||
if ((GDB_MULTI_ARCH >= 2)
|
||||
&& (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");
|
||||
@ -844,6 +856,14 @@ gdbarch_dump (void)
|
||||
"gdbarch_update: BREAKPOINT_FROM_PC = 0x%08lx\n",
|
||||
(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);
|
||||
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
#
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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++)
|
||||
{
|
||||
if ((regno == -1) || (regno == regi))
|
||||
{
|
||||
*(regp + regmap[regi]) = *(int *) ®isters[REGISTER_BYTE (regi)];
|
||||
}
|
||||
}
|
||||
for (regi = 0; regi < NUM_GREGS; regi++)
|
||||
if (! valid || valid[regi])
|
||||
*(regp + regmap[regi]) = * (int *) ®isters[REGISTER_BYTE (regi)];
|
||||
}
|
||||
|
||||
|
||||
/* 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. */
|
||||
|
||||
void
|
||||
supply_fpregset (fpregsetp)
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/* 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 (fpregsetp, regno)
|
||||
fpregset_t *fpregsetp;
|
||||
int regno;
|
||||
fill_gregset (gregset_t *gregsetp,
|
||||
int regno)
|
||||
{
|
||||
int regi;
|
||||
char *to;
|
||||
char *from;
|
||||
|
||||
to = (char *) &(fpregsetp->st_space[0]);
|
||||
for (regi = FPSTART_REGNUM ; regi <= FPEND_REGNUM ; regi++)
|
||||
if (regno == -1)
|
||||
convert_to_gregset (gregsetp, registers, 0);
|
||||
else
|
||||
{
|
||||
from = (char *) ®isters[REGISTER_BYTE (regi)];
|
||||
memcpy (to, from, REGISTER_RAW_SIZE (regi));
|
||||
to += REGISTER_RAW_SIZE(regi);
|
||||
signed char valid[NUM_GREGS];
|
||||
memset (valid, 0, sizeof (valid));
|
||||
valid[regno] = 1;
|
||||
convert_to_gregset (gregsetp, valid, valid);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Get the whole floating point state of the process and
|
||||
store the floating point stack into registers[].
|
||||
*/
|
||||
|
||||
/* 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 (fpregset_t *fpregsetp)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* 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
|
||||
convert_to_fpregset (fpregset_t *fpregsetp,
|
||||
char *gdb_regs,
|
||||
signed char *valid)
|
||||
{
|
||||
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));
|
||||
}
|
||||
|
||||
|
||||
/* 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[]. */
|
||||
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 ();
|
||||
}
|
||||
|
||||
|
||||
|
@ -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 ();
|
||||
|
||||
}
|
||||
|
90
gdb/infrun.c
90
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 ();
|
||||
|
@ -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);
|
||||
}
|
||||
|
1341
gdb/remote-hms.c
1341
gdb/remote-hms.c
File diff suppressed because it is too large
Load Diff
241
gdb/remote.c
241
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)
|
||||
/* construct "M"<memaddr>","<len>":" */
|
||||
/* sprintf (buf, "M%lx,%x:", (unsigned long) memaddr, todo); */
|
||||
p = buf;
|
||||
|
||||
/* Append [XM]. Compute a best guess of the number of bytes
|
||||
actually transfered. */
|
||||
switch (remote_protocol_binary_download.support)
|
||||
{
|
||||
unsigned char *p, *plen;
|
||||
int plenlen;
|
||||
int todo;
|
||||
int i;
|
||||
|
||||
/* 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)
|
||||
{
|
||||
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");
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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");
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
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");
|
||||
}
|
||||
return origlen;
|
||||
|
||||
/* 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++)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
if (nr_bytes < 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) nr_bytes, plenlen);
|
||||
*plen = ':'; /* overwrite \0 from hexnumnstr() */
|
||||
}
|
||||
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++)
|
||||
{
|
||||
*p++ = tohex ((myaddr[nr_bytes] >> 4) & 0xf);
|
||||
*p++ = tohex (myaddr[nr_bytes] & 0xf);
|
||||
}
|
||||
*p = '\0';
|
||||
break;
|
||||
case PACKET_SUPPORT_UNKNOWN:
|
||||
internal_error ("remote_write_bytes: bad switch");
|
||||
}
|
||||
|
||||
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;
|
||||
|
@ -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
|
||||
|
181
gdb/symfile.c
181
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
|
||||
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;
|
||||
|
||||
/* 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;
|
||||
/* 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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
35
gdb/symtab.c
35
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. */
|
||||
|
||||
|
120
gdb/target.c
120
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)
|
||||
|
17
gdb/target.h
17
gdb/target.h
@ -590,9 +590,6 @@ extern int
|
||||
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));
|
||||
|
||||
@ -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)
|
||||
|
@ -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
|
||||
|
205
gdb/testsuite/gdb.threads/linux-dp.c
Normal file
205
gdb/testsuite/gdb.threads/linux-dp.c
Normal file
@ -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;
|
||||
}
|
186
gdb/testsuite/gdb.threads/linux-dp.exp
Normal file
186
gdb/testsuite/gdb.threads/linux-dp.exp
Normal file
@ -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"
|
||||
}
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
*/
|
||||
|
140
gdb/utils.c
140
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))
|
||||
{
|
||||
flush_hook (file);
|
||||
return;
|
||||
}
|
||||
internal_error ("tui_file_flush: bad magic number");
|
||||
|
||||
fflush (stream->ts_filestream);
|
||||
/* 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)
|
||||
{
|
||||
case astring:
|
||||
break;
|
||||
case afile:
|
||||
fflush (stream->ts_filestream);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
10
gdb/valops.c
10
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++;
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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. */
|
||||
|
||||
|
@ -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. */
|
||||
}
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user