Hmm.. The ChangeLog went in, but not the code....
* monitor.c: Turn on caching. (monitor_printf): If a ^C was sent, don't expect to see its echo. (monitor_open): Enable caching. (monitor_resume, monitor_load): Flush cache. (monitor_xfer_memory): Call cache routine. (monitor_dump_regs): New. (monitor_fetch_registers): If monitor_dump_regs available then use it. (monitor_load): Don't ref exec_bfd if it's NULL. (monitor_load_srec): Use new monitor_make_srec calling convention. (monitor_make_srec): Rewrite to cope with two, three and four byte addresses. * remote-hms.c (hms_cmds): Initialze end-of-command delim. * dcache.h, dcache.h: Rewritten. * remote.c: Reenable caching. (getpkt): Reduce MAX_TRIES to 3. (remote_xfer_memory): Use dcache_xfer_memory. * defs.h (error_hook): New. * top.c (error_hook): New definition. * utils.c (error): Use error_hook if initialized. * sparcl-tdep.c (HAVE_SOCKETS): Don't define if GO32 or WIN32. Use HAVE_SOCKETS in place of #ifndef GO32.
This commit is contained in:
parent
65b175c5e6
commit
45993f6118
9 changed files with 757 additions and 471 deletions
574
gdb/dcache.c
574
gdb/dcache.c
|
@ -1,65 +1,191 @@
|
|||
/* Caching code. Typically used by remote back ends for
|
||||
caching remote memory.
|
||||
|
||||
Copyright 1992, 1993 Free Software Foundation, Inc.
|
||||
Copyright 1992, 1993, 1995 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
This file is part of GDB.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
This program is 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.
|
||||
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., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
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., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
#include "defs.h"
|
||||
#include "dcache.h"
|
||||
#include "gdbcmd.h"
|
||||
#include <string.h>
|
||||
|
||||
int remote_dcache = 0;
|
||||
|
||||
/* In case the system header files define a prototype for insque and
|
||||
remque that uses a pointer to a struct qelem, silence the warnings */
|
||||
#define Insque(a,b) insque((PTR)(a), (PTR)(b))
|
||||
#define Remque(a) remque((PTR)(a))
|
||||
/*
|
||||
The data cache could lead to incorrect results because it doesn't know
|
||||
about volatile variables, thus making it impossible to debug
|
||||
functions which use memory mapped I/O devices.
|
||||
|
||||
/* The data cache records all the data read from the remote machine
|
||||
since the last time it stopped.
|
||||
set remotecache 0
|
||||
|
||||
Each cache block holds LINE_SIZE bytes of data
|
||||
In those cases.
|
||||
|
||||
In general the dcache speeds up performance, some speed improvement
|
||||
comes from the actual caching mechanism, but the major gain is in
|
||||
the reduction of the remote protocol overhead; instead of reading
|
||||
or writing a large area of memory in 4 byte requests, the cache
|
||||
bundles up the requests into 32 byte (actually LINE_SIZE) chunks.
|
||||
Reducing the overhead to an eighth of what it was. This is very
|
||||
obvious when displaying a large amount of data,
|
||||
|
||||
eg, x/200x 0
|
||||
|
||||
caching | no yes
|
||||
----------------------------
|
||||
first time | 4 sec 2 sec improvement due to chunking
|
||||
second time | 4 sec 0 sec improvement due to caching
|
||||
|
||||
The cache structure is unusual, we keep a number of cache blocks
|
||||
(DCACHE_SIZE) and each one caches a LINE_SIZEed area of memory.
|
||||
Within each line we remember the address of the line (always a
|
||||
multiple of the LINE_SIZE) and a vector of bytes over the range.
|
||||
There's another vector which contains the state of the bytes.
|
||||
|
||||
ENTRY_BAD means that the byte is just plain wrong, and has no
|
||||
correspondence with anything else (as it would when the cache is
|
||||
turned on, but nothing has been done to it.
|
||||
|
||||
ENTRY_DIRTY means that the byte has some data in it which should be
|
||||
written out to the remote target one day, but contains correct
|
||||
data. ENTRY_OK means that the data is the same in the cache as it
|
||||
is in remote memory.
|
||||
|
||||
|
||||
The ENTRY_DIRTY state is necessary because GDB likes to write large
|
||||
lumps of memory in small bits. If the caching mechanism didn't
|
||||
maintain the DIRTY information, then something like a two byte
|
||||
write would mean that the entire cache line would have to be read,
|
||||
the two bytes modified and then written out again. The alternative
|
||||
would be to not read in the cache line in the first place, and just
|
||||
write the two bytes directly into target memory. The trouble with
|
||||
that is that it really nails performance, because of the remote
|
||||
protocol overhead. This way, all those little writes are bundled
|
||||
up into an entire cache line write in one go, without having to
|
||||
read the cache line in the first place.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/* This value regulates the number of cache blocks stored.
|
||||
Smaller values reduce the time spent searching for a cache
|
||||
line, and reduce memory requirements, but increase the risk
|
||||
of a line not being in memory */
|
||||
|
||||
#define DCACHE_SIZE 64
|
||||
|
||||
/* This value regulates the size of a cache line. Smaller values
|
||||
reduce the time taken to read a single byte, but reduce overall
|
||||
throughput. */
|
||||
|
||||
#define LINE_SIZE_POWER (5)
|
||||
#define LINE_SIZE (1 << LINE_SIZE_POWER)
|
||||
|
||||
/* Each cache block holds LINE_SIZE bytes of data
|
||||
starting at a multiple-of-LINE_SIZE address. */
|
||||
|
||||
#define LINE_SIZE_MASK ((LINE_SIZE - 1)) /* eg 7*2+1= 111*/
|
||||
#define XFORM(x) (((x) & LINE_SIZE_MASK) >> 2)
|
||||
#define LINE_SIZE_MASK ((LINE_SIZE - 1))
|
||||
#define XFORM(x) ((x) & LINE_SIZE_MASK)
|
||||
#define MASK(x) ((x) & ~LINE_SIZE_MASK)
|
||||
|
||||
|
||||
#define ENTRY_BAD 0 /* data at this byte is wrong */
|
||||
#define ENTRY_DIRTY 1 /* data at this byte needs to be written back */
|
||||
#define ENTRY_OK 2 /* data at this byte is same as in memory */
|
||||
|
||||
|
||||
struct dcache_block
|
||||
{
|
||||
struct dcache_block *p; /* next in list */
|
||||
unsigned int addr; /* Address for which data is recorded. */
|
||||
unsigned char data[LINE_SIZE]; /* bytes at given address */
|
||||
unsigned char state[LINE_SIZE]; /* what state the data is in */
|
||||
|
||||
/* whether anything in state is dirty - used to speed up the
|
||||
dirty scan. */
|
||||
int anydirty;
|
||||
|
||||
int refs;
|
||||
};
|
||||
|
||||
|
||||
struct dcache_struct
|
||||
{
|
||||
/* Function to actually read the target memory. */
|
||||
memxferfunc read_memory;
|
||||
|
||||
/* Function to actually write the target memory */
|
||||
memxferfunc write_memory;
|
||||
|
||||
/* free list */
|
||||
struct dcache_block *free_head;
|
||||
struct dcache_block *free_tail;
|
||||
|
||||
/* in use list */
|
||||
struct dcache_block *valid_head;
|
||||
struct dcache_block *valid_tail;
|
||||
|
||||
/* The cache itself. */
|
||||
struct dcache_block *the_cache;
|
||||
|
||||
/* potentially, if the cache was enabled, and then turned off, and
|
||||
then turned on again, the stuff in it could be stale, so this is
|
||||
used to mark it */
|
||||
int cache_has_stuff;
|
||||
} ;
|
||||
|
||||
int remote_dcache = 1;
|
||||
|
||||
DCACHE *last_cache; /* Used by info dcache */
|
||||
|
||||
|
||||
|
||||
/* Free all the data cache blocks, thus discarding all cached data. */
|
||||
|
||||
void
|
||||
dcache_flush (dcache)
|
||||
DCACHE *dcache;
|
||||
{
|
||||
register struct dcache_block *db;
|
||||
int i;
|
||||
dcache->valid_head = 0;
|
||||
dcache->valid_tail = 0;
|
||||
|
||||
if (remote_dcache > 0)
|
||||
while ((db = dcache->dcache_valid.next) != &dcache->dcache_valid)
|
||||
{
|
||||
Remque (db);
|
||||
Insque (db, &dcache->dcache_free);
|
||||
}
|
||||
dcache->free_head = 0;
|
||||
dcache->free_tail = 0;
|
||||
|
||||
for (i = 0; i < DCACHE_SIZE; i++)
|
||||
{
|
||||
struct dcache_block *db = dcache->the_cache + i;
|
||||
|
||||
if (!dcache->free_head)
|
||||
dcache->free_head = db;
|
||||
else
|
||||
dcache->free_tail->p = db;
|
||||
dcache->free_tail = db;
|
||||
db->p = 0;
|
||||
}
|
||||
|
||||
dcache->cache_has_stuff = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* If addr is present in the dcache, return the address of the block
|
||||
* containing it.
|
||||
*/
|
||||
/* If addr is present in the dcache, return the address of the block
|
||||
containing it. */
|
||||
static
|
||||
struct dcache_block *
|
||||
dcache_hit (dcache, addr)
|
||||
|
@ -68,35 +194,66 @@ dcache_hit (dcache, addr)
|
|||
{
|
||||
register struct dcache_block *db;
|
||||
|
||||
if (addr & 3
|
||||
|| remote_dcache == 0)
|
||||
abort ();
|
||||
|
||||
/* Search all cache blocks for one that is at this address. */
|
||||
db = dcache->dcache_valid.next;
|
||||
while (db != &dcache->dcache_valid)
|
||||
db = dcache->valid_head;
|
||||
|
||||
while (db)
|
||||
{
|
||||
if ((addr & ~LINE_SIZE_MASK) == db->addr)
|
||||
return db;
|
||||
db = db->next;
|
||||
if (MASK(addr) == db->addr)
|
||||
{
|
||||
db->refs++;
|
||||
return db;
|
||||
}
|
||||
db = db->p;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Return the int data at address ADDR in dcache block DC. */
|
||||
static
|
||||
int
|
||||
dcache_value (db, addr)
|
||||
struct dcache_block *db;
|
||||
unsigned int addr;
|
||||
/* Make sure that anything in this line which needs to
|
||||
be written is. */
|
||||
|
||||
static int
|
||||
dcache_write_line (dcache, db)
|
||||
DCACHE *dcache;
|
||||
register struct dcache_block *db;
|
||||
{
|
||||
if (addr & 3
|
||||
|| remote_dcache == 0)
|
||||
abort ();
|
||||
return (db->data[XFORM (addr)]);
|
||||
int s;
|
||||
int e;
|
||||
s = 0;
|
||||
if (db->anydirty)
|
||||
{
|
||||
for (s = 0; s < LINE_SIZE; s++)
|
||||
{
|
||||
if (db->state[s] == ENTRY_DIRTY)
|
||||
{
|
||||
int len = 0;
|
||||
for (e = s ; e < LINE_SIZE; e++, len++)
|
||||
if (db->state[e] != ENTRY_DIRTY)
|
||||
{
|
||||
/* all bytes from s..s+len-1 need to
|
||||
be written out */
|
||||
int done = 0;
|
||||
while (done < len) {
|
||||
int t = dcache->write_memory (db->addr + s + done,
|
||||
db->data + s + done,
|
||||
len - done);
|
||||
if (t == 0)
|
||||
return 0;
|
||||
done += t;
|
||||
}
|
||||
memset (db->state + s, ENTRY_OK, len);
|
||||
s = e;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
db->anydirty = 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* Get a free cache block, put or keep it on the valid list,
|
||||
and return its address. The caller should store into the block
|
||||
the address and data that it describes, then remque it from the
|
||||
|
@ -112,22 +269,120 @@ dcache_alloc (dcache)
|
|||
register struct dcache_block *db;
|
||||
|
||||
if (remote_dcache == 0)
|
||||
abort();
|
||||
abort ();
|
||||
|
||||
if ((db = dcache->dcache_free.next) == &dcache->dcache_free)
|
||||
/* Take something from the free list */
|
||||
if (db = dcache->free_head)
|
||||
{
|
||||
/* If we can't get one from the free list, take last valid and put
|
||||
it on the free list. */
|
||||
db = dcache->dcache_valid.last;
|
||||
Remque (db);
|
||||
Insque (db, &dcache->dcache_free);
|
||||
dcache->free_head = db->p;
|
||||
}
|
||||
|
||||
Remque (db);
|
||||
Insque (db, &dcache->dcache_valid);
|
||||
return (db);
|
||||
if (!db)
|
||||
{
|
||||
/* Nothing left on free list, so grab on from the valid list */
|
||||
db = dcache->valid_head;
|
||||
dcache->valid_head = db->p;
|
||||
|
||||
dcache_write_line (dcache, db);
|
||||
}
|
||||
|
||||
/* append this line to end of valid list */
|
||||
if (!dcache->valid_head)
|
||||
dcache->valid_head = db;
|
||||
else
|
||||
dcache->valid_tail->p = db;
|
||||
dcache->valid_tail = db;
|
||||
db->p = 0;
|
||||
|
||||
return db;
|
||||
}
|
||||
|
||||
/* Using the data cache DCACHE return the contents of the byte at
|
||||
address ADDR in the remote machine.
|
||||
|
||||
Returns 0 on error. */
|
||||
|
||||
int
|
||||
dcache_peek_byte (dcache, addr, ptr)
|
||||
DCACHE *dcache;
|
||||
CORE_ADDR addr;
|
||||
unsigned char *ptr;
|
||||
{
|
||||
register struct dcache_block *db = dcache_hit (dcache, addr);
|
||||
int ok=1;
|
||||
int done = 0;
|
||||
if (db == 0
|
||||
|| db->state[XFORM (addr)] == ENTRY_BAD)
|
||||
{
|
||||
if (db)
|
||||
{
|
||||
dcache_write_line (dcache, db);
|
||||
}
|
||||
else
|
||||
db = dcache_alloc (dcache);
|
||||
immediate_quit++;
|
||||
db->addr = MASK (addr);
|
||||
while (done < LINE_SIZE)
|
||||
{
|
||||
int try =
|
||||
(*dcache->read_memory)
|
||||
(db->addr + done,
|
||||
(unsigned char *) db->data + done,
|
||||
LINE_SIZE - done);
|
||||
if (try == 0)
|
||||
return 0;
|
||||
done += try;
|
||||
}
|
||||
immediate_quit--;
|
||||
|
||||
memset (db->state, ENTRY_OK, sizeof (db->data));
|
||||
db->anydirty = 0;
|
||||
}
|
||||
*ptr = db->data[XFORM (addr)];
|
||||
return ok;
|
||||
}
|
||||
|
||||
/* Using the data cache DCACHE return the contents of the word at
|
||||
address ADDR in the remote machine.
|
||||
|
||||
Returns 0 on error. */
|
||||
|
||||
int
|
||||
dcache_peek (dcache, addr, data)
|
||||
DCACHE *dcache;
|
||||
CORE_ADDR addr;
|
||||
int *data;
|
||||
{
|
||||
unsigned char *dp = (unsigned char *) data;
|
||||
int i;
|
||||
for (i = 0; i < sizeof (int); i++)
|
||||
{
|
||||
if (!dcache_peek_byte (dcache, addr, dp + i))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* Writeback any dirty lines to the remote. */
|
||||
static int
|
||||
dcache_writeback (dcache)
|
||||
DCACHE *dcache;
|
||||
{
|
||||
struct dcache_block *db;
|
||||
|
||||
db = dcache->valid_head;
|
||||
|
||||
while (db)
|
||||
{
|
||||
if (!dcache_write_line (dcache, db))
|
||||
return 0;
|
||||
db = db->p;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* Using the data cache DCACHE return the contents of the word at
|
||||
address ADDR in the remote machine. */
|
||||
int
|
||||
|
@ -135,93 +390,160 @@ dcache_fetch (dcache, addr)
|
|||
DCACHE *dcache;
|
||||
CORE_ADDR addr;
|
||||
{
|
||||
register struct dcache_block *db;
|
||||
|
||||
if (remote_dcache == 0)
|
||||
{
|
||||
int i;
|
||||
|
||||
(*dcache->read_memory) (addr, (unsigned char *) &i, 4);
|
||||
return(i);
|
||||
}
|
||||
|
||||
db = dcache_hit (dcache, addr);
|
||||
if (db == 0)
|
||||
{
|
||||
db = dcache_alloc (dcache);
|
||||
immediate_quit++;
|
||||
(*dcache->read_memory) (addr & ~LINE_SIZE_MASK, (unsigned char *) db->data, LINE_SIZE);
|
||||
immediate_quit--;
|
||||
db->addr = addr & ~LINE_SIZE_MASK;
|
||||
Remque (db); /* Off the free list */
|
||||
Insque (db, &dcache->dcache_valid); /* On the valid list */
|
||||
}
|
||||
return (dcache_value (db, addr));
|
||||
int res;
|
||||
dcache_peek (dcache, addr, &res);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Write the word at ADDR both in the data cache and in the remote machine. */
|
||||
void
|
||||
|
||||
/* Write the byte at PTR into ADDR in the data cache.
|
||||
Return zero on write error.
|
||||
*/
|
||||
|
||||
int
|
||||
dcache_poke_byte (dcache, addr, ptr)
|
||||
DCACHE *dcache;
|
||||
CORE_ADDR addr;
|
||||
char *ptr;
|
||||
{
|
||||
register struct dcache_block *db = dcache_hit (dcache, addr);
|
||||
|
||||
if (!db)
|
||||
{
|
||||
db = dcache_alloc (dcache);
|
||||
db->addr = MASK (addr);
|
||||
memset (db->state, ENTRY_BAD, sizeof (db->data));
|
||||
}
|
||||
|
||||
db->data[XFORM (addr)] = *ptr;
|
||||
db->state[XFORM (addr)] = ENTRY_DIRTY;
|
||||
db->anydirty = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Write the word at ADDR both in the data cache and in the remote machine.
|
||||
Return zero on write error.
|
||||
*/
|
||||
|
||||
int
|
||||
dcache_poke (dcache, addr, data)
|
||||
DCACHE *dcache;
|
||||
CORE_ADDR addr;
|
||||
int data;
|
||||
{
|
||||
register struct dcache_block *db;
|
||||
|
||||
if (remote_dcache == 0)
|
||||
unsigned char *dp = (unsigned char *) (&data);
|
||||
int i;
|
||||
for (i = 0; i < sizeof (int); i++)
|
||||
{
|
||||
(*dcache->write_memory) (addr, (unsigned char *) &data, 4);
|
||||
return;
|
||||
if (!dcache_poke_byte (dcache, addr, dp + i))
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* First make sure the word is IN the cache. DB is its cache block. */
|
||||
db = dcache_hit (dcache, addr);
|
||||
if (db == 0)
|
||||
{
|
||||
db = dcache_alloc (dcache);
|
||||
immediate_quit++;
|
||||
(*dcache->write_memory) (addr & ~LINE_SIZE_MASK, (unsigned char *) db->data, LINE_SIZE);
|
||||
immediate_quit--;
|
||||
db->addr = addr & ~LINE_SIZE_MASK;
|
||||
Remque (db); /* Off the free list */
|
||||
Insque (db, &dcache->dcache_valid); /* On the valid list */
|
||||
}
|
||||
|
||||
/* Modify the word in the cache. */
|
||||
db->data[XFORM (addr)] = data;
|
||||
|
||||
/* Send the changed word. */
|
||||
immediate_quit++;
|
||||
(*dcache->write_memory) (addr, (unsigned char *) &data, 4);
|
||||
immediate_quit--;
|
||||
dcache_writeback (dcache);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* Initialize the data cache. */
|
||||
DCACHE *
|
||||
dcache_init (reading, writing)
|
||||
memxferfunc reading;
|
||||
memxferfunc writing;
|
||||
{
|
||||
register i;
|
||||
register struct dcache_block *db;
|
||||
int csize = sizeof (struct dcache_block) * DCACHE_SIZE;
|
||||
DCACHE *dcache;
|
||||
|
||||
dcache = (DCACHE *) xmalloc (sizeof (*dcache));
|
||||
dcache->read_memory = reading;
|
||||
dcache->write_memory = writing;
|
||||
dcache->the_cache = (struct dcache_block *)
|
||||
xmalloc (sizeof (*dcache->the_cache) * DCACHE_SIZE);
|
||||
|
||||
dcache->dcache_free.next = dcache->dcache_free.last = &dcache->dcache_free;
|
||||
dcache->dcache_valid.next = dcache->dcache_valid.last = &dcache->dcache_valid;
|
||||
for (db = dcache->the_cache, i = 0; i < DCACHE_SIZE; i++, db++)
|
||||
Insque (db, &dcache->dcache_free);
|
||||
dcache->the_cache = (struct dcache_block *) xmalloc (csize);
|
||||
memset (dcache->the_cache, 0, csize);
|
||||
|
||||
return(dcache);
|
||||
dcache_flush (dcache);
|
||||
|
||||
last_cache = dcache;
|
||||
return dcache;
|
||||
}
|
||||
|
||||
/* Read or write LEN bytes from inferior memory at MEMADDR, transferring
|
||||
to or from debugger address MYADDR. Write to inferior if SHOULD_WRITE is
|
||||
nonzero.
|
||||
|
||||
Returns length of data written or read; 0 for error.
|
||||
|
||||
This routine is indended to be called by remote_xfer_ functions. */
|
||||
|
||||
int
|
||||
dcache_xfer_memory (dcache, memaddr, myaddr, len, should_write)
|
||||
DCACHE *dcache;
|
||||
CORE_ADDR memaddr;
|
||||
char *myaddr;
|
||||
int len;
|
||||
int should_write;
|
||||
{
|
||||
int i;
|
||||
|
||||
if (remote_dcache)
|
||||
{
|
||||
int (*xfunc) ()
|
||||
= should_write ? dcache_poke_byte : dcache_peek_byte;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
if (!xfunc (dcache, memaddr + i, myaddr + i))
|
||||
return 0;
|
||||
}
|
||||
dcache->cache_has_stuff = 1;
|
||||
dcache_writeback (dcache);
|
||||
}
|
||||
else
|
||||
{
|
||||
int (*xfunc) ()
|
||||
= should_write ? dcache->write_memory : dcache->read_memory;
|
||||
|
||||
if (dcache->cache_has_stuff)
|
||||
dcache_flush (dcache);
|
||||
|
||||
len = xfunc (memaddr, myaddr, len);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
static void
|
||||
dcache_info (exp, tty)
|
||||
char *exp;
|
||||
int tty;
|
||||
{
|
||||
struct dcache_block *p;
|
||||
|
||||
if (!remote_dcache)
|
||||
{
|
||||
printf_filtered ("Dcache not enabled\n");
|
||||
return;
|
||||
}
|
||||
printf_filtered ("Dcache enabled, line width %d, depth %d\n",
|
||||
LINE_SIZE, DCACHE_SIZE);
|
||||
|
||||
printf_filtered ("Cache state:\n");
|
||||
|
||||
for (p = last_cache->valid_head; p; p = p->p)
|
||||
{
|
||||
int j;
|
||||
printf_filtered ("Line at %08xd, referenced %d times\n",
|
||||
p->addr, p->refs);
|
||||
|
||||
for (j = 0; j < LINE_SIZE; j++)
|
||||
printf_filtered ("%02x", p->data[j]);
|
||||
printf_filtered ("\n");
|
||||
|
||||
for (j = 0; j < LINE_SIZE; j++)
|
||||
printf_filtered ("% 2x", p->state[j]);
|
||||
printf_filtered ("\n");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_initialitize_dcache ()
|
||||
_initialize_dcache ()
|
||||
{
|
||||
add_show_from_set
|
||||
(add_set_cmd ("remotecache", class_support, var_boolean,
|
||||
|
@ -232,7 +554,11 @@ 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 off.",
|
||||
volatile registers are in use. By default, this option is on.",
|
||||
&setlist),
|
||||
&showlist);
|
||||
|
||||
add_info ("dcache", dcache_info,
|
||||
"Print information on the dcache performance.");
|
||||
|
||||
}
|
||||
|
|
49
gdb/dcache.h
49
gdb/dcache.h
|
@ -22,50 +22,11 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
|||
#ifndef DCACHE_H
|
||||
#define DCACHE_H
|
||||
|
||||
/* The data cache leads to incorrect results because it doesn't know about
|
||||
volatile variables, thus making it impossible to debug functions which
|
||||
use hardware registers. Therefore it is #if 0'd out. Effect on
|
||||
performance is some, for backtraces of functions with a few
|
||||
arguments each. For functions with many arguments, the stack
|
||||
frames don't fit in the cache blocks, which makes the cache less
|
||||
helpful. Disabling the cache is a big performance win for fetching
|
||||
large structures, because the cache code fetched data in 16-byte
|
||||
chunks. */
|
||||
|
||||
#define LINE_SIZE_POWER (4)
|
||||
/* eg 1<<3 == 8 */
|
||||
#define LINE_SIZE (1 << LINE_SIZE_POWER)
|
||||
/* Number of cache blocks */
|
||||
#define DCACHE_SIZE (64)
|
||||
|
||||
struct dcache_block
|
||||
{
|
||||
struct dcache_block *next, *last;
|
||||
unsigned int addr; /* Address for which data is recorded. */
|
||||
int data[LINE_SIZE / sizeof (int)];
|
||||
};
|
||||
|
||||
typedef int (*memxferfunc) PARAMS((CORE_ADDR memaddr,
|
||||
unsigned char *myaddr,
|
||||
int len));
|
||||
|
||||
typedef struct {
|
||||
/* Function to actually read the target memory. */
|
||||
memxferfunc read_memory;
|
||||
|
||||
/* Function to actually write the target memory */
|
||||
memxferfunc write_memory;
|
||||
|
||||
/* free list */
|
||||
struct dcache_block dcache_free;
|
||||
|
||||
/* in use list */
|
||||
struct dcache_block dcache_valid;
|
||||
|
||||
/* The cache itself. */
|
||||
struct dcache_block *the_cache;
|
||||
|
||||
} DCACHE;
|
||||
typedef struct dcache_struct DCACHE;
|
||||
|
||||
/* Using the data cache DCACHE return the contents of the word at
|
||||
address ADDR in the remote machine. */
|
||||
|
@ -78,6 +39,12 @@ void dcache_flush PARAMS((DCACHE *dcache));
|
|||
DCACHE *dcache_init PARAMS((memxferfunc reading, memxferfunc writing));
|
||||
|
||||
/* Write the word at ADDR both in the data cache and in the remote machine. */
|
||||
void dcache_poke PARAMS((DCACHE *dcache, CORE_ADDR addr, int data));
|
||||
int dcache_poke PARAMS((DCACHE *dcache, CORE_ADDR addr, int data));
|
||||
|
||||
/* Simple to call from <remote>_xfer_memory */
|
||||
|
||||
int dcache_xfer_memory PARAMS((DCACHE *cache, CORE_ADDR mem, char *my, int len, int should_write));
|
||||
|
||||
/* Write the bytes at ADDR into the data cache and the remote machine. */
|
||||
int dcache_poke_block PARAMS((DCACHE *cache, CORE_ADDR mem, char* my, int len));
|
||||
#endif /* DCACHE_H */
|
||||
|
|
48
gdb/defs.h
48
gdb/defs.h
|
@ -28,6 +28,12 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
|||
|
||||
#include "ansidecl.h"
|
||||
|
||||
#ifdef ANSI_PROTOTYPES
|
||||
#include <stdarg.h>
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#endif
|
||||
|
||||
#include "libiberty.h"
|
||||
|
||||
/* libiberty.h can't declare this one, but evidently we can. */
|
||||
|
@ -256,10 +262,10 @@ extern void puts_filtered PARAMS ((char *));
|
|||
|
||||
extern void puts_unfiltered PARAMS ((char *));
|
||||
|
||||
extern void vprintf_filtered PARAMS ((char *, ...))
|
||||
extern void vprintf_filtered PARAMS ((char *, va_list))
|
||||
ATTR_FORMAT(printf, 1, 0);
|
||||
|
||||
extern void vfprintf_filtered PARAMS ((FILE *, char *, ...))
|
||||
extern void vfprintf_filtered PARAMS ((FILE *, char *, va_list))
|
||||
ATTR_FORMAT(printf, 2, 0);
|
||||
|
||||
extern void fprintf_filtered PARAMS ((FILE *, char *, ...))
|
||||
|
@ -274,10 +280,10 @@ extern void printf_filtered PARAMS ((char *, ...))
|
|||
extern void printfi_filtered PARAMS ((int, char *, ...))
|
||||
ATTR_FORMAT(printf, 2, 3);
|
||||
|
||||
extern void vprintf_unfiltered PARAMS ((char *, ...))
|
||||
extern void vprintf_unfiltered PARAMS ((char *, va_list))
|
||||
ATTR_FORMAT(printf, 1, 0);
|
||||
|
||||
extern void vfprintf_unfiltered PARAMS ((FILE *, char *, ...))
|
||||
extern void vfprintf_unfiltered PARAMS ((FILE *, char *, va_list))
|
||||
ATTR_FORMAT(printf, 2, 0);
|
||||
|
||||
extern void fprintf_unfiltered PARAMS ((FILE *, char *, ...))
|
||||
|
@ -631,6 +637,7 @@ extern void free ();
|
|||
|
||||
#endif /* MALLOC_INCOMPATIBLE */
|
||||
|
||||
#ifndef WIN32
|
||||
extern char *strchr ();
|
||||
|
||||
extern char *strrchr ();
|
||||
|
@ -640,6 +647,7 @@ extern char *strstr ();
|
|||
extern char *strtok ();
|
||||
|
||||
extern char *strerror ();
|
||||
#endif
|
||||
|
||||
/* Various possibilities for alloca. */
|
||||
#ifndef alloca
|
||||
|
@ -815,6 +823,10 @@ extern CORE_ADDR push_word PARAMS ((CORE_ADDR, unsigned LONGEST));
|
|||
#define MAINTENANCE_CMDS 1
|
||||
#endif
|
||||
|
||||
#ifdef MAINTENANCE_CMDS
|
||||
extern int watchdog;
|
||||
#endif
|
||||
|
||||
#include "dis-asm.h" /* Get defs for disassemble_info */
|
||||
|
||||
extern int dis_asm_read_memory PARAMS ((bfd_vma memaddr, bfd_byte *myaddr,
|
||||
|
@ -856,8 +868,36 @@ extern int (*target_wait_hook) PARAMS ((int pid,
|
|||
extern void (*call_command_hook) PARAMS ((struct cmd_list_element *c,
|
||||
char *cmd, int from_tty));
|
||||
|
||||
extern NORETURN void (*error_hook) PARAMS (());
|
||||
|
||||
|
||||
|
||||
/* Inhibit window interface if non-zero. */
|
||||
|
||||
extern int use_windows;
|
||||
|
||||
/* Symbolic definitions of filename-related things. */
|
||||
/* FIXME, this doesn't work very well if host and executable
|
||||
filesystems conventions are different. */
|
||||
|
||||
#ifndef DIRNAME_SEPARATOR
|
||||
#define DIRNAME_SEPARATOR ':'
|
||||
#endif
|
||||
|
||||
#ifndef SLASH_P
|
||||
#define SLASH_P(X) ((X)=='/')
|
||||
#endif
|
||||
|
||||
#ifndef SLASH_CHAR
|
||||
#define SLASH_CHAR '/'
|
||||
#endif
|
||||
|
||||
#ifndef SLASH_STRING
|
||||
#define SLASH_STRING "/"
|
||||
#endif
|
||||
|
||||
#ifndef ROOTED_P
|
||||
#define ROOTED_P(X) (SLASH_P((X)[0]))
|
||||
#endif
|
||||
|
||||
#endif /* #ifndef DEFS_H */
|
||||
|
|
154
gdb/monitor.c
154
gdb/monitor.c
|
@ -46,6 +46,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
|||
#include "gdbcmd.h"
|
||||
#include "inferior.h"
|
||||
#include "regex.h"
|
||||
#include "dcache.h"
|
||||
|
||||
static int readchar PARAMS ((int timeout));
|
||||
|
||||
|
@ -80,6 +81,9 @@ static void monitor_load PARAMS ((char *file, int from_tty));
|
|||
static void monitor_mourn_inferior PARAMS ((void));
|
||||
static void monitor_stop PARAMS ((void));
|
||||
|
||||
static int monitor_read_memory PARAMS ((CORE_ADDR addr, char *myaddr,int len));
|
||||
static int monitor_write_memory PARAMS ((CORE_ADDR addr, char *myaddr,int len));
|
||||
|
||||
static int from_hex PARAMS ((int a));
|
||||
static unsigned long get_hex_word PARAMS ((void));
|
||||
|
||||
|
@ -113,6 +117,8 @@ static char fastmap[256];
|
|||
static int dump_reg_flag; /* Non-zero means do a dump_registers cmd when
|
||||
monitor_wait wakes up. */
|
||||
|
||||
static DCACHE *remote_dcache;
|
||||
|
||||
/* monitor_printf_noecho -- Send data to monitor, but don't expect an echo.
|
||||
Works just like printf. */
|
||||
|
||||
|
@ -194,12 +200,15 @@ monitor_printf (va_alist)
|
|||
|
||||
if (c != sndbuf[i])
|
||||
{
|
||||
/* Don't fail if we sent a ^C, they're never echoed */
|
||||
if (sndbuf[i] == '\003')
|
||||
continue;
|
||||
#if 0
|
||||
if (sndbuf[i] == '\r'
|
||||
&& c == '\n')
|
||||
goto trycr;
|
||||
#endif
|
||||
error ("monitor_printf: Bad echo. Sent: \"%s\", Got: \"%.*s%c\".",
|
||||
warning ("monitor_printf: Bad echo. Sent: \"%s\", Got: \"%.*s%c\".",
|
||||
sndbuf, i, sndbuf, c);
|
||||
}
|
||||
}
|
||||
|
@ -459,6 +468,8 @@ monitor_open (args, mon_ops, from_tty)
|
|||
|
||||
monitor_printf (current_monitor->line_term);
|
||||
|
||||
remote_dcache = dcache_init (monitor_read_memory, monitor_write_memory);
|
||||
|
||||
start_remote ();
|
||||
}
|
||||
|
||||
|
@ -520,6 +531,7 @@ monitor_resume (pid, step, sig)
|
|||
int pid, step;
|
||||
enum target_signal sig;
|
||||
{
|
||||
dcache_flush (remote_dcache);
|
||||
if (step)
|
||||
monitor_printf (STEP_CMD);
|
||||
else
|
||||
|
@ -724,7 +736,7 @@ monitor_fetch_register (regno)
|
|||
continue;
|
||||
|
||||
error ("monitor_fetch_register (%d): bad response from monitor: %.*s%c.",
|
||||
regno, i, regbuf, c);
|
||||
regno, i, regbuf, c);
|
||||
}
|
||||
|
||||
regbuf[i] = c;
|
||||
|
@ -754,18 +766,38 @@ monitor_fetch_register (regno)
|
|||
|
||||
/* Read the remote registers into the block regs. */
|
||||
|
||||
static void monitor_dump_regs ()
|
||||
{
|
||||
if (current_monitor->dump_registers)
|
||||
{
|
||||
char buf[200];
|
||||
int resp_len;
|
||||
monitor_printf (current_monitor->dump_registers);
|
||||
resp_len = monitor_expect_prompt (buf, sizeof (buf));
|
||||
parse_register_dump (buf, resp_len);
|
||||
}
|
||||
else
|
||||
abort(); /* Need some way to read registers */
|
||||
}
|
||||
|
||||
static void
|
||||
monitor_fetch_registers (regno)
|
||||
int regno;
|
||||
{
|
||||
if (regno >= 0)
|
||||
if (current_monitor->getreg.cmd)
|
||||
{
|
||||
monitor_fetch_register (regno);
|
||||
return;
|
||||
}
|
||||
if (regno >= 0)
|
||||
{
|
||||
monitor_fetch_register (regno);
|
||||
return;
|
||||
}
|
||||
|
||||
for (regno = 0; regno < NUM_REGS; regno++)
|
||||
monitor_fetch_register (regno);
|
||||
for (regno = 0; regno < NUM_REGS; regno++)
|
||||
monitor_fetch_register (regno);
|
||||
}
|
||||
else {
|
||||
monitor_dump_regs ();
|
||||
}
|
||||
}
|
||||
|
||||
/* Store register REGNO, or all if REGNO == 0. Return errno value. */
|
||||
|
@ -1102,10 +1134,7 @@ monitor_xfer_memory (memaddr, myaddr, len, write, target)
|
|||
int write;
|
||||
struct target_ops *target; /* ignored */
|
||||
{
|
||||
if (write)
|
||||
return monitor_write_memory (memaddr, myaddr, len);
|
||||
else
|
||||
return monitor_read_memory (memaddr, myaddr, len);
|
||||
return dcache_xfer_memory (remote_dcache, memaddr, myaddr, len, write);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1205,6 +1234,8 @@ monitor_load (file, from_tty)
|
|||
char *file;
|
||||
int from_tty;
|
||||
{
|
||||
dcache_flush (remote_dcache);
|
||||
|
||||
if (current_monitor->load_routine)
|
||||
current_monitor->load_routine (monitor_desc, file, hashmark);
|
||||
else
|
||||
|
@ -1212,7 +1243,8 @@ monitor_load (file, from_tty)
|
|||
|
||||
/* Finally, make the PC point at the start address */
|
||||
|
||||
write_pc (bfd_get_start_address (exec_bfd));
|
||||
if (exec_bfd)
|
||||
write_pc (bfd_get_start_address (exec_bfd));
|
||||
|
||||
inferior_pid = 0; /* No process now */
|
||||
|
||||
|
@ -1288,46 +1320,47 @@ monitor_load_srec (args)
|
|||
return;
|
||||
}
|
||||
|
||||
monitor_printf (LOAD_CMD); /* tell the monitor to load */
|
||||
monitor_printf (LOAD_CMD); /* tell the monitor to load */
|
||||
if (current_monitor->loadresp)
|
||||
monitor_expect (current_monitor->loadresp, NULL, 0);
|
||||
|
||||
for (s = abfd->sections; s; s = s->next)
|
||||
if (s->flags & SEC_LOAD)
|
||||
{
|
||||
printf_filtered ("%s\t: 0x%4x .. 0x%4x ", s->name, s->vma,
|
||||
s->vma + s->_raw_size);
|
||||
gdb_flush (gdb_stdout);
|
||||
{
|
||||
if (s->flags & SEC_LOAD)
|
||||
{
|
||||
int numbytes;
|
||||
|
||||
for (i = 0; i < s->_raw_size; i += srec_frame)
|
||||
{
|
||||
int numbytes;
|
||||
printf_filtered ("%s\t: 0x%4x .. 0x%4x ", s->name, s->vma,
|
||||
s->vma + s->_raw_size);
|
||||
gdb_flush (gdb_stdout);
|
||||
|
||||
numbytes = min (srec_frame, s->_raw_size - i);
|
||||
for (i = 0; i < s->_raw_size; i += numbytes)
|
||||
{
|
||||
numbytes = min (srec_frame, s->_raw_size - i);
|
||||
|
||||
bfd_get_section_contents (abfd, s, buffer, i, numbytes);
|
||||
bfd_get_section_contents (abfd, s, buffer, i, numbytes);
|
||||
|
||||
reclen = monitor_make_srec (srec, 3, s->vma + i, buffer, numbytes);
|
||||
reclen = monitor_make_srec (srec, 'd', s->vma + i, buffer, numbytes);
|
||||
|
||||
monitor_printf_noecho ("%.*s\r", reclen, srec);
|
||||
monitor_printf_noecho ("%.*s\r", reclen, srec);
|
||||
|
||||
if (hashmark)
|
||||
{
|
||||
putchar_unfiltered ('#');
|
||||
gdb_flush (gdb_stdout);
|
||||
}
|
||||
} /* Per-packet (or S-record) loop */
|
||||
if (hashmark)
|
||||
{
|
||||
putchar_unfiltered ('#');
|
||||
gdb_flush (gdb_stdout);
|
||||
}
|
||||
} /* Per-packet (or S-record) loop */
|
||||
|
||||
putchar_unfiltered ('\n');
|
||||
} /* Loadable sections */
|
||||
|
||||
putchar_unfiltered ('\n');
|
||||
} /* Loadable sections */
|
||||
}
|
||||
if (hashmark)
|
||||
putchar_unfiltered ('\n');
|
||||
|
||||
/* Write a type 7 terminator record. no data for a type 7, and there
|
||||
is no data, so len is 0. */
|
||||
|
||||
reclen = monitor_make_srec (srec, 7, abfd->start_address, NULL, 0);
|
||||
reclen = monitor_make_srec (srec, 't', abfd->start_address, NULL, 0);
|
||||
|
||||
monitor_printf_noecho ("%.*s\r", reclen, srec);
|
||||
|
||||
|
@ -1393,23 +1426,58 @@ monitor_make_srec (buffer, type, memaddr, myaddr, len)
|
|||
unsigned char checksum;
|
||||
int i;
|
||||
char *buf;
|
||||
static char hextab[] = "0123456789ABCDEF";
|
||||
|
||||
static char hextab[16] = "0123456789ABCDEF";
|
||||
static char data_code_table[] = { 0,0,1,2,3};
|
||||
static char term_code_table[] = { 0,0,9,8,7};
|
||||
int addr_size; /* Number of bytes in the record */
|
||||
int type_code;
|
||||
buf = buffer;
|
||||
|
||||
checksum = 0;
|
||||
|
||||
/* Create the header for the srec. 4 is the number of bytes in the address,
|
||||
addr_size = 2;
|
||||
if (memaddr >= 0xffffff)
|
||||
addr_size = 4;
|
||||
else if (memaddr >= 0xffffff)
|
||||
addr_size = 3;
|
||||
else
|
||||
addr_size = 2;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case 't':
|
||||
type_code = term_code_table[addr_size];
|
||||
break;
|
||||
case 'd':
|
||||
type_code = data_code_table[addr_size];
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
/* Create the header for the srec. addr_size is the number of bytes in the address,
|
||||
and 1 is the number of bytes in the count. */
|
||||
|
||||
sprintf (buf, "S%d%02X%08X", type, len + 4 + 1, memaddr);
|
||||
buf += 12;
|
||||
|
||||
switch (addr_size)
|
||||
{
|
||||
case 4:
|
||||
sprintf (buf, "S%d%02X%08X", type_code, len + addr_size + 1, memaddr);
|
||||
buf += 12;
|
||||
break;
|
||||
case 3:
|
||||
sprintf (buf, "S%d%02X%06X", type_code, len + addr_size + 1, memaddr);
|
||||
buf += 10;
|
||||
break;
|
||||
case 2:
|
||||
sprintf (buf, "S%d%02X%04X", type_code, len + addr_size + 1, memaddr);
|
||||
buf += 8;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Note that the checksum is calculated on the raw data, not the hexified
|
||||
data. It includes the length, address and the data portions of the
|
||||
packet. */
|
||||
|
||||
checksum += (len + 4 + 1 /* Packet length */
|
||||
checksum += (len + addr_size + 1 /* Packet length */
|
||||
+ (memaddr & 0xff) /* Address... */
|
||||
+ ((memaddr >> 8) & 0xff)
|
||||
+ ((memaddr >> 16) & 0xff)
|
||||
|
|
|
@ -131,7 +131,7 @@ static struct monitor_ops hms_cmds =
|
|||
"tl\r", /* download command */
|
||||
NULL, /* load response */
|
||||
">", /* monitor command prompt */
|
||||
NULL, /* end-of-command delimitor */
|
||||
"\r", /* end-of-command delimitor */
|
||||
NULL, /* optional command terminator */
|
||||
&hms_ops, /* target operations */
|
||||
SERIAL_1_STOPBITS, /* number of stop bits */
|
||||
|
@ -202,9 +202,6 @@ static void remove_commands ();
|
|||
|
||||
static int quiet = 1; /* FIXME - can be removed after Dec '94 */
|
||||
|
||||
DCACHE *dcache_ptr;
|
||||
int remote_dcache;
|
||||
serial_t desc;
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
|
@ -532,7 +529,6 @@ hms_close (quitting)
|
|||
SERIAL_CLOSE (desc);
|
||||
}
|
||||
is_open = 0;
|
||||
remote_dcache = 0;
|
||||
}
|
||||
|
||||
/* Terminate the open connection to the remote debugger. Use this
|
||||
|
@ -561,8 +557,6 @@ hms_resume (pid, step, sig)
|
|||
enum target_signal
|
||||
sig;
|
||||
{
|
||||
dcache_flush (dcache_ptr);
|
||||
|
||||
if (step)
|
||||
{
|
||||
hms_write_cr ("s");
|
||||
|
@ -1034,26 +1028,6 @@ translate_addr (addr)
|
|||
|
||||
}
|
||||
|
||||
/* Read a word from remote address ADDR and return it.
|
||||
* This goes through the data cache.
|
||||
*/
|
||||
int
|
||||
hms_fetch_word (addr)
|
||||
CORE_ADDR addr;
|
||||
{
|
||||
return dcache_fetch (dcache_ptr, addr);
|
||||
}
|
||||
|
||||
/* Write a word WORD into remote address ADDR.
|
||||
This goes through the data cache. */
|
||||
|
||||
void
|
||||
hms_store_word (addr, word)
|
||||
CORE_ADDR addr;
|
||||
int word;
|
||||
{
|
||||
dcache_poke (dcache_ptr, addr, word);
|
||||
}
|
||||
|
||||
int
|
||||
hms_xfer_inferior_memory (memaddr, myaddr, len, write, target)
|
||||
|
@ -1063,73 +1037,6 @@ hms_xfer_inferior_memory (memaddr, myaddr, len, write, target)
|
|||
int write;
|
||||
struct target_ops *target; /* ignored */
|
||||
{
|
||||
register int i;
|
||||
|
||||
/* Round starting address down to longword boundary. */
|
||||
register CORE_ADDR addr;
|
||||
|
||||
/* Round ending address up; get number of longwords that makes. */
|
||||
register int count;
|
||||
|
||||
/* Allocate buffer of that many longwords. */
|
||||
register int *buffer;
|
||||
|
||||
memaddr &= 0xffff;
|
||||
addr = memaddr & -sizeof (int);
|
||||
count = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
|
||||
|
||||
buffer = (int *) alloca (count * sizeof (int));
|
||||
|
||||
if (write)
|
||||
{
|
||||
/* Fill start and end extra bytes of buffer with existing memory data. */
|
||||
|
||||
if (addr != memaddr || len < (int) sizeof (int))
|
||||
{
|
||||
/* Need part of initial word -- fetch it. */
|
||||
buffer[0] = hms_fetch_word (addr);
|
||||
}
|
||||
|
||||
if (count > 1) /* FIXME, avoid if even boundary */
|
||||
{
|
||||
buffer[count - 1]
|
||||
= hms_fetch_word (addr + (count - 1) * sizeof (int));
|
||||
}
|
||||
|
||||
/* Copy data to be written over corresponding part of buffer */
|
||||
|
||||
memcpy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr, len);
|
||||
|
||||
/* Write the entire buffer. */
|
||||
|
||||
for (i = 0; i < count; i++, addr += sizeof (int))
|
||||
{
|
||||
errno = 0;
|
||||
hms_store_word (addr, buffer[i]);
|
||||
if (errno)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Read all the longwords */
|
||||
for (i = 0; i < count; i++, addr += sizeof (int))
|
||||
{
|
||||
errno = 0;
|
||||
buffer[i] = hms_fetch_word (addr);
|
||||
if (errno)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
QUIT;
|
||||
}
|
||||
|
||||
/* Copy appropriate bytes out of the buffer. */
|
||||
memcpy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), len);
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
|
202
gdb/remote.c
202
gdb/remote.c
|
@ -1,5 +1,5 @@
|
|||
/* Remote target communications for serial-line targets in custom GDB protocol
|
||||
Copyright 1988, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
|
||||
Copyright 1988, 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GDB.
|
||||
|
||||
|
@ -177,6 +177,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
|||
#include "gdbcmd.h"
|
||||
#include "objfiles.h"
|
||||
#include "gdb-stabs.h"
|
||||
#include "thread.h"
|
||||
|
||||
#include "dcache.h"
|
||||
|
||||
|
@ -189,71 +190,56 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
|||
|
||||
/* Prototypes for local functions */
|
||||
|
||||
static int
|
||||
remote_write_bytes PARAMS ((CORE_ADDR memaddr, unsigned char *myaddr, int len));
|
||||
static int remote_write_bytes PARAMS ((CORE_ADDR memaddr,
|
||||
unsigned char *myaddr, int len));
|
||||
|
||||
static int
|
||||
remote_read_bytes PARAMS ((CORE_ADDR memaddr, unsigned char *myaddr, int len));
|
||||
static int remote_read_bytes PARAMS ((CORE_ADDR memaddr,
|
||||
unsigned char *myaddr, int len));
|
||||
|
||||
static void
|
||||
remote_files_info PARAMS ((struct target_ops *ignore));
|
||||
static void remote_files_info PARAMS ((struct target_ops *ignore));
|
||||
|
||||
static int
|
||||
remote_xfer_memory PARAMS ((CORE_ADDR memaddr, char *myaddr, int len,
|
||||
int should_write, struct target_ops *target));
|
||||
static int remote_xfer_memory PARAMS ((CORE_ADDR memaddr, char *myaddr,
|
||||
int len, int should_write,
|
||||
struct target_ops *target));
|
||||
|
||||
static void
|
||||
remote_prepare_to_store PARAMS ((void));
|
||||
static void remote_prepare_to_store PARAMS ((void));
|
||||
|
||||
static void
|
||||
remote_fetch_registers PARAMS ((int regno));
|
||||
static void remote_fetch_registers PARAMS ((int regno));
|
||||
|
||||
static void
|
||||
remote_resume PARAMS ((int pid, int step, enum target_signal siggnal));
|
||||
static void remote_resume PARAMS ((int pid, int step,
|
||||
enum target_signal siggnal));
|
||||
|
||||
static int
|
||||
remote_start_remote PARAMS ((char *dummy));
|
||||
static int remote_start_remote PARAMS ((char *dummy));
|
||||
|
||||
static void
|
||||
remote_open PARAMS ((char *name, int from_tty));
|
||||
static void remote_open PARAMS ((char *name, int from_tty));
|
||||
|
||||
static void
|
||||
remote_close PARAMS ((int quitting));
|
||||
static void remote_close PARAMS ((int quitting));
|
||||
|
||||
static void
|
||||
remote_store_registers PARAMS ((int regno));
|
||||
static void remote_store_registers PARAMS ((int regno));
|
||||
|
||||
static void
|
||||
getpkt PARAMS ((char *buf, int forever));
|
||||
static void getpkt PARAMS ((char *buf, int forever));
|
||||
|
||||
static int
|
||||
putpkt PARAMS ((char *buf));
|
||||
static int putpkt PARAMS ((char *buf));
|
||||
|
||||
static void
|
||||
remote_send PARAMS ((char *buf));
|
||||
static void remote_send PARAMS ((char *buf));
|
||||
|
||||
static int
|
||||
readchar PARAMS ((int timeout));
|
||||
static int readchar PARAMS ((int timeout));
|
||||
|
||||
static int remote_wait PARAMS ((int pid, struct target_waitstatus *status));
|
||||
|
||||
static int
|
||||
tohex PARAMS ((int nib));
|
||||
static void remote_kill PARAMS ((void));
|
||||
|
||||
static int
|
||||
fromhex PARAMS ((int a));
|
||||
static int tohex PARAMS ((int nib));
|
||||
|
||||
static void
|
||||
remote_detach PARAMS ((char *args, int from_tty));
|
||||
static int fromhex PARAMS ((int a));
|
||||
|
||||
static void
|
||||
remote_interrupt PARAMS ((int signo));
|
||||
static void remote_detach PARAMS ((char *args, int from_tty));
|
||||
|
||||
static void
|
||||
remote_interrupt_twice PARAMS ((int signo));
|
||||
static void remote_interrupt PARAMS ((int signo));
|
||||
|
||||
static void
|
||||
interrupt_query PARAMS ((void));
|
||||
static void remote_interrupt_twice PARAMS ((int signo));
|
||||
|
||||
static void interrupt_query PARAMS ((void));
|
||||
|
||||
extern struct target_ops remote_ops; /* Forward decl */
|
||||
|
||||
|
@ -261,11 +247,8 @@ extern struct target_ops remote_ops; /* Forward decl */
|
|||
Unless this is going though some terminal server or multiplexer or
|
||||
other form of hairy serial connection, I would think 2 seconds would
|
||||
be plenty. */
|
||||
static int remote_timeout = 2;
|
||||
|
||||
#if 0
|
||||
int icache;
|
||||
#endif
|
||||
static int remote_timeout = 2;
|
||||
|
||||
/* Descriptor for I/O to remote machine. Initialize it to NULL so that
|
||||
remote_open knows that we don't have a file open when the program
|
||||
|
@ -381,12 +364,6 @@ get_offsets ()
|
|||
+ symfile_objfile->num_sections
|
||||
* sizeof (offs->offsets));
|
||||
|
||||
/* FIXME: This code assumes gdb-stabs.h is being used; it's broken
|
||||
for xcoff, dwarf, sdb-coff, etc. But there is no simple
|
||||
canonical representation for this stuff. (Just what does "text"
|
||||
as seen by the stub mean, anyway? I think it means all sections
|
||||
with SEC_CODE set, but we currently have no way to deal with that). */
|
||||
|
||||
ANOFFSET (offs, SECT_OFF_TEXT) = text_addr;
|
||||
|
||||
/* This is a temporary kludge to force data and bss to use the same offsets
|
||||
|
@ -408,7 +385,6 @@ remote_start_remote (dummy)
|
|||
immediate_quit = 1; /* Allow user to interrupt it */
|
||||
|
||||
/* Ack any packet which the remote side has already sent. */
|
||||
|
||||
SERIAL_WRITE (remote_desc, "+", 1);
|
||||
|
||||
/* Let the stub know that we want it to return the thread. */
|
||||
|
@ -420,7 +396,6 @@ remote_start_remote (dummy)
|
|||
immediate_quit = 0;
|
||||
|
||||
start_remote (); /* Initialize gdb process mechanisms */
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -435,8 +410,7 @@ remote_open (name, from_tty)
|
|||
int from_tty;
|
||||
{
|
||||
if (name == 0)
|
||||
error (
|
||||
"To open a remote debug connection, you need to specify what serial\n\
|
||||
error ("To open a remote debug connection, you need to specify what serial\n\
|
||||
device is attached to the remote system (e.g. /dev/ttya).");
|
||||
|
||||
target_preopen (from_tty);
|
||||
|
@ -458,6 +432,7 @@ device is attached to the remote system (e.g. /dev/ttya).");
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
SERIAL_RAW (remote_desc);
|
||||
|
||||
/* If there is something sitting in the buffer we might take it as a
|
||||
|
@ -488,12 +463,11 @@ device is attached to the remote system (e.g. /dev/ttya).");
|
|||
several processes. */
|
||||
|
||||
inferior_pid = 42000;
|
||||
|
||||
/* Start the remote connection; if error (0), discard this target.
|
||||
In particular, if the user quits, be sure to discard it
|
||||
(we'd be in an inconsistent state otherwise). */
|
||||
if (!catch_errors (remote_start_remote, (char *)0,
|
||||
"Couldn't establish connection to remote target\n", RETURN_MASK_ALL))
|
||||
"Couldn't establish connection to remote target\n", RETURN_MASK_ALL))
|
||||
pop_target();
|
||||
}
|
||||
|
||||
|
@ -676,8 +650,10 @@ remote_wait (pid, status)
|
|||
while (*p)
|
||||
{
|
||||
unsigned char *p1;
|
||||
char *p_temp;
|
||||
|
||||
regno = strtol (p, &p1, 16); /* Read the register number */
|
||||
regno = strtol (p, &p_temp, 16); /* Read the register number */
|
||||
p1 = (unsigned char *)p_temp;
|
||||
|
||||
if (p1 == p)
|
||||
{
|
||||
|
@ -688,8 +664,8 @@ Packet: '%s'\n",
|
|||
p, buf);
|
||||
if (strncmp (p, "thread", p1 - p) == 0)
|
||||
{
|
||||
char *p2;
|
||||
thread_num = strtol (++p1, &p, 16);
|
||||
thread_num = strtol (++p1, &p_temp, 16);
|
||||
p = (unsigned char *)p_temp;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -918,16 +894,18 @@ remote_store_registers (regno)
|
|||
remote_send (buf);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
/* Use of the data cache is disabled because it loses for looking at
|
||||
/*
|
||||
Use of the data cache *used* to be disabled because it loses for looking at
|
||||
and changing hardware I/O ports and the like. Accepting `volatile'
|
||||
would perhaps be one way to fix it, but a better way which would
|
||||
win for more cases would be to use the executable file for the text
|
||||
segment, like the `icache' code below but done cleanly (in some
|
||||
target-independent place, perhaps in target_xfer_memory, perhaps
|
||||
based on assigning each target a speed or perhaps by some simpler
|
||||
mechanism). */
|
||||
would perhaps be one way to fix it. Another idea would be to use the
|
||||
executable file for the text segment (for all SEC_CODE sections?
|
||||
For all SEC_READONLY sections?). This has problems if you want to
|
||||
actually see what the memory contains (e.g. self-modifying code,
|
||||
clobbered memory, user downloaded the wrong thing).
|
||||
|
||||
Because it speeds so much up, it's now enabled, if you're playing
|
||||
with registers you turn it of (set remotecache 0)
|
||||
*/
|
||||
|
||||
/* Read a word from remote address ADDR and return it.
|
||||
This goes through the data cache. */
|
||||
|
@ -936,19 +914,6 @@ static int
|
|||
remote_fetch_word (addr)
|
||||
CORE_ADDR addr;
|
||||
{
|
||||
#if 0
|
||||
if (icache)
|
||||
{
|
||||
extern CORE_ADDR text_start, text_end;
|
||||
|
||||
if (addr >= text_start && addr < text_end)
|
||||
{
|
||||
int buffer;
|
||||
target_read_memory (addr, &buffer, sizeof (int));
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return dcache_fetch (remote_dcache, addr);
|
||||
}
|
||||
|
||||
|
@ -962,7 +927,7 @@ remote_store_word (addr, word)
|
|||
{
|
||||
dcache_poke (remote_dcache, addr, word);
|
||||
}
|
||||
#endif /* 0 */
|
||||
|
||||
|
||||
/* Write memory data directly to the remote machine.
|
||||
This does not inform the data cache; the data cache uses this.
|
||||
|
@ -1078,38 +1043,10 @@ remote_xfer_memory(memaddr, myaddr, len, should_write, target)
|
|||
int should_write;
|
||||
struct target_ops *target; /* ignored */
|
||||
{
|
||||
int xfersize;
|
||||
int bytes_xferred;
|
||||
int total_xferred = 0;
|
||||
|
||||
set_thread (inferior_pid, 1);
|
||||
|
||||
while (len > 0)
|
||||
{
|
||||
if (len > MAXBUFBYTES)
|
||||
xfersize = MAXBUFBYTES;
|
||||
else
|
||||
xfersize = len;
|
||||
|
||||
if (should_write)
|
||||
bytes_xferred = remote_write_bytes (memaddr,
|
||||
(unsigned char *)myaddr, xfersize);
|
||||
else
|
||||
bytes_xferred = remote_read_bytes (memaddr,
|
||||
(unsigned char *)myaddr, xfersize);
|
||||
|
||||
/* If we get an error, we are done xferring. */
|
||||
if (bytes_xferred == 0)
|
||||
break;
|
||||
|
||||
memaddr += bytes_xferred;
|
||||
myaddr += bytes_xferred;
|
||||
len -= bytes_xferred;
|
||||
total_xferred += bytes_xferred;
|
||||
}
|
||||
return total_xferred;
|
||||
return dcache_xfer_memory (remote_dcache, memaddr, myaddr, len, should_write);
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
/* Enable after 4.12. */
|
||||
|
||||
|
@ -1225,7 +1162,6 @@ static void
|
|||
remote_send (buf)
|
||||
char *buf;
|
||||
{
|
||||
|
||||
putpkt (buf);
|
||||
getpkt (buf, 0);
|
||||
|
||||
|
@ -1245,6 +1181,7 @@ putpkt (buf)
|
|||
char buf2[PBUFSIZ];
|
||||
int cnt = strlen (buf);
|
||||
int ch;
|
||||
int tcount = 0;
|
||||
char *p;
|
||||
|
||||
/* Copy the packet into buffer BUF2, encapsulating it
|
||||
|
@ -1285,7 +1222,7 @@ putpkt (buf)
|
|||
{
|
||||
ch = readchar (remote_timeout);
|
||||
|
||||
if (remote_debug)
|
||||
if (remote_debug)
|
||||
{
|
||||
switch (ch)
|
||||
{
|
||||
|
@ -1294,7 +1231,7 @@ putpkt (buf)
|
|||
case '$':
|
||||
if (started_error_output)
|
||||
{
|
||||
putc_unfiltered ('\n');
|
||||
putchar_unfiltered ('\n');
|
||||
started_error_output = 0;
|
||||
}
|
||||
}
|
||||
|
@ -1307,6 +1244,9 @@ putpkt (buf)
|
|||
printf_unfiltered("Ack\n");
|
||||
return 1;
|
||||
case SERIAL_TIMEOUT:
|
||||
tcount ++;
|
||||
if (tcount > 3)
|
||||
return 0;
|
||||
break; /* Retransmit buffer */
|
||||
case '$':
|
||||
{
|
||||
|
@ -1325,7 +1265,7 @@ putpkt (buf)
|
|||
started_error_output = 1;
|
||||
printf_unfiltered ("putpkt: Junk: ");
|
||||
}
|
||||
putc_unfiltered (ch & 0177);
|
||||
putchar_unfiltered (ch & 0177);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
@ -1451,12 +1391,21 @@ getpkt (buf, forever)
|
|||
int timeout;
|
||||
int val;
|
||||
|
||||
strcpy (buf,"timeout");
|
||||
|
||||
if (forever)
|
||||
timeout = -1;
|
||||
{
|
||||
#ifdef MAINTENANCE_CMDS
|
||||
timeout = watchdog > 0 ? watchdog : -1;
|
||||
#else
|
||||
timeout = -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
else
|
||||
timeout = remote_timeout;
|
||||
|
||||
#define MAX_TRIES 10
|
||||
#define MAX_TRIES 3
|
||||
|
||||
for (tries = 1; tries <= MAX_TRIES; tries++)
|
||||
{
|
||||
|
@ -1474,6 +1423,13 @@ getpkt (buf, forever)
|
|||
|
||||
if (c == SERIAL_TIMEOUT)
|
||||
{
|
||||
#ifdef MAINTENANCE_CMDS
|
||||
if (forever) /* Watchdog went off. Kill the target. */
|
||||
{
|
||||
target_mourn_inferior ();
|
||||
error ("Watchdog has expired. Target detached.\n");
|
||||
}
|
||||
#endif
|
||||
if (remote_debug)
|
||||
puts_filtered ("Timed out.\n");
|
||||
goto retry;
|
||||
|
@ -1494,7 +1450,7 @@ getpkt (buf, forever)
|
|||
}
|
||||
|
||||
/* Try the whole thing again. */
|
||||
retry:
|
||||
retry:
|
||||
SERIAL_WRITE (remote_desc, "-", 1);
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,15 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
|||
#include "serial.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#ifndef __GO32__
|
||||
|
||||
#if defined(__GO32__) || defined(WIN32)
|
||||
#undef HAVE_SOCKETS
|
||||
#else
|
||||
#define HAVE_SOCKETS
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef HAVE_SOCKETS
|
||||
#include <unistd.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
|
@ -37,14 +45,14 @@ extern struct target_ops remote_ops;
|
|||
static char *remote_target_name = NULL;
|
||||
static serial_t remote_desc = NULL;
|
||||
static int serial_flag;
|
||||
#ifndef __GO32__
|
||||
#ifdef HAVE_SOCKETS
|
||||
static int udp_fd = -1;
|
||||
#endif
|
||||
|
||||
static serial_t open_tty PARAMS ((char *name));
|
||||
static int send_resp PARAMS ((serial_t desc, char c));
|
||||
static void close_tty PARAMS ((int ignore));
|
||||
#ifndef __GO32__
|
||||
#ifdef HAVE_SOCKETS
|
||||
static int recv_udp_buf PARAMS ((int fd, unsigned char *buf, int len, int timeout));
|
||||
static int send_udp_buf PARAMS ((int fd, unsigned char *buf, int len));
|
||||
#endif
|
||||
|
@ -60,7 +68,7 @@ static void sparclite_serial_start PARAMS ((bfd_vma entry));
|
|||
static void sparclite_serial_write PARAMS ((bfd *from_bfd, asection *from_sec,
|
||||
file_ptr from_addr,
|
||||
bfd_vma to_addr, int len));
|
||||
#ifndef __GO32__
|
||||
#ifdef HAVE_SOCKETS
|
||||
static unsigned short calc_checksum PARAMS ((unsigned char *buffer,
|
||||
int count));
|
||||
static void sparclite_udp_start PARAMS ((bfd_vma entry));
|
||||
|
@ -324,7 +332,7 @@ close_tty (ignore)
|
|||
remote_desc = NULL;
|
||||
}
|
||||
|
||||
#ifndef __GO32__
|
||||
#ifdef HAVE_SOCKETS
|
||||
static int
|
||||
recv_udp_buf (fd, buf, len, timeout)
|
||||
int fd, len;
|
||||
|
@ -449,7 +457,7 @@ or: target sparclite udp host");
|
|||
}
|
||||
else
|
||||
{
|
||||
#ifndef __GO32__
|
||||
#ifdef HAVE_SOCKETS
|
||||
struct hostent *he;
|
||||
struct sockaddr_in sockaddr;
|
||||
unsigned char buffer[100];
|
||||
|
@ -503,7 +511,7 @@ sparclite_close (quitting)
|
|||
{
|
||||
if (serial_flag)
|
||||
close_tty (0);
|
||||
#ifndef __GO32__
|
||||
#ifdef HAVE_SOCKETS
|
||||
else
|
||||
if (udp_fd != -1)
|
||||
close (udp_fd);
|
||||
|
@ -684,7 +692,7 @@ sparclite_serial_write (from_bfd, from_sec, from_addr, to_addr, len)
|
|||
error ("Bad checksum from load command (0x%x)", i);
|
||||
}
|
||||
|
||||
#ifndef __GO32__
|
||||
#ifdef HAVE_SOCKETS
|
||||
|
||||
static unsigned short
|
||||
calc_checksum (buffer, count)
|
||||
|
@ -806,7 +814,7 @@ sparclite_download (filename, from_tty)
|
|||
int from_tty;
|
||||
{
|
||||
if (!serial_flag)
|
||||
#ifndef __GO32__
|
||||
#ifdef HAVE_SOCKETS
|
||||
download (remote_target_name, filename, from_tty, sparclite_udp_write,
|
||||
sparclite_udp_start);
|
||||
#else
|
||||
|
|
|
@ -417,6 +417,13 @@ int (*target_wait_hook) PARAMS ((int pid, struct target_waitstatus *status));
|
|||
|
||||
void (*call_command_hook) PARAMS ((struct cmd_list_element *c, char *cmd,
|
||||
int from_tty));
|
||||
|
||||
|
||||
/* Takes control from error (). Typically used to prevent longjmps out of the
|
||||
middle of the GUI. Usually used in conjunction with a catch routine. */
|
||||
|
||||
NORETURN void (*error_hook) PARAMS (());
|
||||
|
||||
|
||||
/* Where to go for return_to_top_level (RETURN_ERROR). */
|
||||
jmp_buf error_return;
|
||||
|
|
73
gdb/utils.c
73
gdb/utils.c
|
@ -23,7 +23,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
|||
#include <sys/param.h>
|
||||
#include <pwd.h>
|
||||
#endif
|
||||
#ifdef __STDC__
|
||||
#ifdef ANSI_PROTOTYPES
|
||||
#include <stdarg.h>
|
||||
#else
|
||||
#include <varargs.h>
|
||||
|
@ -254,7 +254,7 @@ warning_begin ()
|
|||
|
||||
/* VARARGS */
|
||||
void
|
||||
#ifdef __STDC__
|
||||
#ifdef ANSI_PROTOTYPES
|
||||
warning (char *string, ...)
|
||||
#else
|
||||
warning (va_alist)
|
||||
|
@ -262,7 +262,7 @@ warning (va_alist)
|
|||
#endif
|
||||
{
|
||||
va_list args;
|
||||
#ifdef __STDC__
|
||||
#ifdef ANSI_PROTOTYPES
|
||||
va_start (args, string);
|
||||
#else
|
||||
char *string;
|
||||
|
@ -300,31 +300,39 @@ error_begin ()
|
|||
The first argument STRING is the error message, used as a fprintf string,
|
||||
and the remaining args are passed as arguments to it. */
|
||||
|
||||
/* VARARGS */
|
||||
#ifdef ANSI_PROTOTYPES
|
||||
NORETURN void
|
||||
#ifdef __STDC__
|
||||
error (char *string, ...)
|
||||
#else
|
||||
error (va_alist)
|
||||
va_dcl
|
||||
#endif
|
||||
{
|
||||
#ifdef ANSI_PROTOTYPES
|
||||
va_list args;
|
||||
#ifdef __STDC__
|
||||
va_start (args, string);
|
||||
#else
|
||||
char *string;
|
||||
|
||||
va_start (args);
|
||||
string = va_arg (args, char *);
|
||||
#endif
|
||||
error_begin ();
|
||||
vfprintf_filtered (gdb_stderr, string, args);
|
||||
fprintf_filtered (gdb_stderr, "\n");
|
||||
va_end (args);
|
||||
return_to_top_level (RETURN_ERROR);
|
||||
if (error_hook)
|
||||
error_hook();
|
||||
else
|
||||
{
|
||||
char *string1;
|
||||
error_begin ();
|
||||
#ifdef ANSI_PROTOTYPES
|
||||
vfprintf_filtered (gdb_stderr, string, args);
|
||||
#else
|
||||
string1 = va_arg (args, char *);
|
||||
vfprintf_filtered (gdb_stderr, string1, args);
|
||||
#endif
|
||||
fprintf_filtered (gdb_stderr, "\n");
|
||||
va_end (args);
|
||||
return_to_top_level (RETURN_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Print an error message and exit reporting failure.
|
||||
This is for a error that we cannot continue from.
|
||||
The arguments are printed a la printf.
|
||||
|
@ -334,7 +342,7 @@ error (va_alist)
|
|||
|
||||
/* VARARGS */
|
||||
NORETURN void
|
||||
#ifdef __STDC__
|
||||
#ifdef ANSI_PROTOTYPES
|
||||
fatal (char *string, ...)
|
||||
#else
|
||||
fatal (va_alist)
|
||||
|
@ -342,11 +350,10 @@ fatal (va_alist)
|
|||
#endif
|
||||
{
|
||||
va_list args;
|
||||
#ifdef __STDC__
|
||||
#ifdef ANSI_PROTOTYPES
|
||||
va_start (args, string);
|
||||
#else
|
||||
char *string;
|
||||
|
||||
va_start (args);
|
||||
string = va_arg (args, char *);
|
||||
#endif
|
||||
|
@ -362,7 +369,7 @@ fatal (va_alist)
|
|||
|
||||
/* VARARGS */
|
||||
static void
|
||||
#ifdef __STDC__
|
||||
#ifdef ANSI_PROTOTYPES
|
||||
fatal_dump_core (char *string, ...)
|
||||
#else
|
||||
fatal_dump_core (va_alist)
|
||||
|
@ -370,7 +377,7 @@ fatal_dump_core (va_alist)
|
|||
#endif
|
||||
{
|
||||
va_list args;
|
||||
#ifdef __STDC__
|
||||
#ifdef ANSI_PROTOTYPES
|
||||
va_start (args, string);
|
||||
#else
|
||||
char *string;
|
||||
|
@ -875,7 +882,7 @@ gdb_print_address (addr, stream)
|
|||
|
||||
/* VARARGS */
|
||||
int
|
||||
#ifdef __STDC__
|
||||
#ifdef ANSI_PROTOTYPES
|
||||
query (char *ctlstr, ...)
|
||||
#else
|
||||
query (va_alist)
|
||||
|
@ -887,7 +894,7 @@ query (va_alist)
|
|||
register int ans2;
|
||||
int retval;
|
||||
|
||||
#ifdef __STDC__
|
||||
#ifdef ANSI_PROTOTYPES
|
||||
va_start (args, ctlstr);
|
||||
#else
|
||||
char *ctlstr;
|
||||
|
@ -1539,7 +1546,7 @@ vprintf_unfiltered (format, args)
|
|||
|
||||
/* VARARGS */
|
||||
void
|
||||
#ifdef __STDC__
|
||||
#ifdef ANSI_PROTOTYPES
|
||||
fprintf_filtered (FILE *stream, char *format, ...)
|
||||
#else
|
||||
fprintf_filtered (va_alist)
|
||||
|
@ -1547,7 +1554,7 @@ fprintf_filtered (va_alist)
|
|||
#endif
|
||||
{
|
||||
va_list args;
|
||||
#ifdef __STDC__
|
||||
#ifdef ANSI_PROTOTYPES
|
||||
va_start (args, format);
|
||||
#else
|
||||
FILE *stream;
|
||||
|
@ -1563,7 +1570,7 @@ fprintf_filtered (va_alist)
|
|||
|
||||
/* VARARGS */
|
||||
void
|
||||
#ifdef __STDC__
|
||||
#ifdef ANSI_PROTOTYPES
|
||||
fprintf_unfiltered (FILE *stream, char *format, ...)
|
||||
#else
|
||||
fprintf_unfiltered (va_alist)
|
||||
|
@ -1571,7 +1578,7 @@ fprintf_unfiltered (va_alist)
|
|||
#endif
|
||||
{
|
||||
va_list args;
|
||||
#ifdef __STDC__
|
||||
#ifdef ANSI_PROTOTYPES
|
||||
va_start (args, format);
|
||||
#else
|
||||
FILE *stream;
|
||||
|
@ -1590,7 +1597,7 @@ fprintf_unfiltered (va_alist)
|
|||
|
||||
/* VARARGS */
|
||||
void
|
||||
#ifdef __STDC__
|
||||
#ifdef ANSI_PROTOTYPES
|
||||
fprintfi_filtered (int spaces, FILE *stream, char *format, ...)
|
||||
#else
|
||||
fprintfi_filtered (va_alist)
|
||||
|
@ -1598,7 +1605,7 @@ fprintfi_filtered (va_alist)
|
|||
#endif
|
||||
{
|
||||
va_list args;
|
||||
#ifdef __STDC__
|
||||
#ifdef ANSI_PROTOTYPES
|
||||
va_start (args, format);
|
||||
#else
|
||||
int spaces;
|
||||
|
@ -1619,7 +1626,7 @@ fprintfi_filtered (va_alist)
|
|||
|
||||
/* VARARGS */
|
||||
void
|
||||
#ifdef __STDC__
|
||||
#ifdef ANSI_PROTOTYPES
|
||||
printf_filtered (char *format, ...)
|
||||
#else
|
||||
printf_filtered (va_alist)
|
||||
|
@ -1627,7 +1634,7 @@ printf_filtered (va_alist)
|
|||
#endif
|
||||
{
|
||||
va_list args;
|
||||
#ifdef __STDC__
|
||||
#ifdef ANSI_PROTOTYPES
|
||||
va_start (args, format);
|
||||
#else
|
||||
char *format;
|
||||
|
@ -1642,7 +1649,7 @@ printf_filtered (va_alist)
|
|||
|
||||
/* VARARGS */
|
||||
void
|
||||
#ifdef __STDC__
|
||||
#ifdef ANSI_PROTOTYPES
|
||||
printf_unfiltered (char *format, ...)
|
||||
#else
|
||||
printf_unfiltered (va_alist)
|
||||
|
@ -1650,7 +1657,7 @@ printf_unfiltered (va_alist)
|
|||
#endif
|
||||
{
|
||||
va_list args;
|
||||
#ifdef __STDC__
|
||||
#ifdef ANSI_PROTOTYPES
|
||||
va_start (args, format);
|
||||
#else
|
||||
char *format;
|
||||
|
@ -1667,7 +1674,7 @@ printf_unfiltered (va_alist)
|
|||
|
||||
/* VARARGS */
|
||||
void
|
||||
#ifdef __STDC__
|
||||
#ifdef ANSI_PROTOTYPES
|
||||
printfi_filtered (int spaces, char *format, ...)
|
||||
#else
|
||||
printfi_filtered (va_alist)
|
||||
|
@ -1675,7 +1682,7 @@ printfi_filtered (va_alist)
|
|||
#endif
|
||||
{
|
||||
va_list args;
|
||||
#ifdef __STDC__
|
||||
#ifdef ANSI_PROTOTYPES
|
||||
va_start (args, format);
|
||||
#else
|
||||
int spaces;
|
||||
|
|
Loading…
Reference in a new issue