import gdb-1999-10-18 snapshot

This commit is contained in:
Jason Molenda 1999-10-19 02:47:02 +00:00
parent 446a06c9b8
commit 917317f4c6
45 changed files with 2287 additions and 2491 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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. */

View File

@ -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. */

View File

@ -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 */

View File

@ -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);

File diff suppressed because it is too large Load Diff

View File

@ -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.

View File

@ -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}

View File

@ -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.

View File

@ -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;

View File

@ -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:

View File

@ -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

View File

@ -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)
{

View File

@ -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

View File

@ -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
#

View File

@ -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);
}

View File

@ -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

View File

@ -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 *) &registers[REGISTER_BYTE (regi)];
}
}
for (regi = 0; regi < NUM_GREGS; regi++)
if (! valid || valid[regi])
*(regp + regmap[regi]) = * (int *) &registers[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 *) &registers[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),
&registers[REGISTER_BYTE (FP0_REGNUM + i)],
REGISTER_RAW_SIZE(FP0_REGNUM + i));
#define fill(MEMBER, REGNO) \
if (! valid || valid[(REGNO)]) \
memcpy (&fpregsetp->MEMBER, &registers[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 *) &registers[REGISTER_BYTE (FCS_REGNUM)] & 0xffff));
if (! valid || valid[FOP_REGNUM])
fpregsetp->fcs
= ((fpregsetp->fcs & 0xffff)
| ((*(int *) &registers[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 ();
}

View File

@ -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 ();
}

View File

@ -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 ();

View File

@ -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);
}

File diff suppressed because it is too large Load Diff

View File

@ -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;

View File

@ -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

View File

@ -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);
}

View File

@ -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;

View File

@ -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. */

View File

@ -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, &current_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)

View File

@ -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)

View File

@ -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

View 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;
}

View 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"
}

View File

@ -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 {

View File

@ -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

View File

@ -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
*/

View File

@ -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

View File

@ -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++;

View File

@ -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

View File

@ -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.

View File

@ -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;

View File

@ -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. */

View File

@ -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. */
}

View File

@ -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 */