FreeBSD specific modifications.
Obtained from /usr/ports/devel/gdb. 2.2. candidate ? Should I put $FreeBSD$ into these files ?
This commit is contained in:
parent
649c409d03
commit
8a9a74a887
@ -67,15 +67,15 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
static void
|
||||
fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr)
|
||||
char *core_reg_sect;
|
||||
unsigned core_reg_size;
|
||||
int which;
|
||||
unsigned reg_addr;
|
||||
char *core_reg_sect;
|
||||
unsigned core_reg_size;
|
||||
int which;
|
||||
CORE_ADDR reg_addr;
|
||||
{
|
||||
register int regno;
|
||||
register unsigned int addr;
|
||||
register CORE_ADDR addr;
|
||||
int bad_reg = -1;
|
||||
register reg_ptr = -reg_addr; /* Original u.u_ar0 is -reg_addr. */
|
||||
register CORE_ADDR reg_ptr = -reg_addr; /* Original u.u_ar0 is -reg_addr. */
|
||||
int numregs = ARCH_NUM_REGS;
|
||||
|
||||
/* If u.u_ar0 was an absolute address in the core file, relativize it now,
|
||||
@ -84,7 +84,7 @@ fetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr)
|
||||
CORE_REGISTER_ADDR to offset to the other registers. If this is a modern
|
||||
core file without a upage, reg_ptr will be zero and this is all a big
|
||||
NOP. */
|
||||
if (reg_ptr > (int) core_reg_size)
|
||||
if (reg_ptr > core_reg_size)
|
||||
reg_ptr -= KERNEL_U_ADDR;
|
||||
|
||||
for (regno = 0; regno < numregs; regno++)
|
||||
@ -114,7 +114,7 @@ register_addr (regno, blockend)
|
||||
int regno;
|
||||
int blockend;
|
||||
{
|
||||
int addr;
|
||||
CORE_ADDR addr;
|
||||
|
||||
if (regno < 0 || regno >= ARCH_NUM_REGS)
|
||||
error ("Invalid register number %d.", regno);
|
||||
|
@ -72,13 +72,32 @@ fetch_core_registers (core_reg_sect, core_reg_size, which, ignore)
|
||||
|
||||
#include <machine/reg.h>
|
||||
|
||||
/* Some systems don't provide all the registers on a trap. Use SS as a
|
||||
default if so. */
|
||||
|
||||
#ifndef tDS
|
||||
#define tDS tSS
|
||||
#endif
|
||||
#ifndef tES
|
||||
#define tES tSS
|
||||
#endif
|
||||
#ifndef tFS
|
||||
#define tFS tSS
|
||||
#endif
|
||||
#ifndef tGS
|
||||
#define tGS tSS
|
||||
#endif
|
||||
|
||||
/* These tables map between the registers on a trap frame, and the register
|
||||
order used by the rest of GDB. */
|
||||
/* this table must line up with REGISTER_NAMES in tm-i386.h */
|
||||
/* symbols like 'tEAX' come from <machine/reg.h> */
|
||||
static int tregmap[] =
|
||||
{
|
||||
tEAX, tECX, tEDX, tEBX,
|
||||
tESP, tEBP, tESI, tEDI,
|
||||
tEIP, tEFLAGS, tCS, tSS
|
||||
tEIP, tEFLAGS, tCS, tSS,
|
||||
tDS, tES, tFS, tGS
|
||||
};
|
||||
|
||||
#ifdef sEAX
|
||||
@ -97,7 +116,8 @@ static int sregmap[] =
|
||||
{
|
||||
tEAX, tECX, tEDX, tEBX,
|
||||
tESP, tEBP, tESI, tEDI,
|
||||
tEIP, tEFLAGS, tCS, tSS
|
||||
tEIP, tEFLAGS, tCS, tSS,
|
||||
tDS, tES, tFS, tGS
|
||||
};
|
||||
#endif /* No sEAX */
|
||||
|
||||
@ -125,6 +145,7 @@ i386_register_u_addr (blockend, regnum)
|
||||
#endif /* !FETCH_INFERIOR_REGISTERS */
|
||||
|
||||
#ifdef FLOAT_INFO
|
||||
#include "expression.h"
|
||||
#include "language.h" /* for local_hex_string */
|
||||
#include "floatformat.h"
|
||||
|
||||
@ -195,7 +216,7 @@ print_387_status (status, ep)
|
||||
}
|
||||
|
||||
print_387_control_word ((unsigned int)ep->control);
|
||||
printf_unfiltered ("last exception: ");
|
||||
printf_unfiltered ("last instruction: ");
|
||||
printf_unfiltered ("opcode %s; ", local_hex_string(ep->opcode));
|
||||
printf_unfiltered ("pc %s:", local_hex_string(ep->code_seg));
|
||||
printf_unfiltered ("%s; ", local_hex_string(ep->eip));
|
||||
@ -227,6 +248,7 @@ print_387_status (status, ep)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
i386_float_info ()
|
||||
{
|
||||
struct user u; /* just for address computations */
|
||||
@ -271,9 +293,15 @@ i386_float_info ()
|
||||
skip = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
fpstatep = (struct fpstate *)(buf + skip);
|
||||
print_387_status (fpstatep->sv_ex_sw, (struct env387 *)fpstatep);
|
||||
#else
|
||||
print_387_status (0, (struct env387 *)buf);
|
||||
#endif
|
||||
}
|
||||
#endif /* FLOAT_INFO */
|
||||
|
||||
int
|
||||
kernel_u_size ()
|
||||
@ -281,4 +309,16 @@ kernel_u_size ()
|
||||
return (sizeof (struct user));
|
||||
}
|
||||
|
||||
#endif
|
||||
#ifdef SETUP_ARBITRARY_FRAME
|
||||
#include "frame.h"
|
||||
struct frame_info *
|
||||
setup_arbitrary_frame (argc, argv)
|
||||
int argc;
|
||||
CORE_ADDR *argv;
|
||||
{
|
||||
if (argc != 2)
|
||||
error ("i386 frame specifications require two arguments: sp and pc");
|
||||
|
||||
return create_new_frame (argv[0], argv[1]);
|
||||
}
|
||||
#endif /* SETUP_ARBITRARY_FRAME */
|
||||
|
@ -312,6 +312,183 @@ serial_t remote_desc = NULL;
|
||||
doesn't support 'P', the only consequence is some unnecessary traffic. */
|
||||
static int stub_supports_P = 1;
|
||||
|
||||
|
||||
/*
|
||||
* Support for quasi-interactive control of device through GDB port.
|
||||
* While we're waiting for an event to occur, chat with the running device.
|
||||
*/
|
||||
#define REMOTE_CHAT
|
||||
#ifdef REMOTE_CHAT
|
||||
|
||||
extern int quit_flag;
|
||||
|
||||
static char tty_input[256];
|
||||
static int escape_count;
|
||||
static int echo_check;
|
||||
static int remote_chat = 0;
|
||||
|
||||
enum read_stat {
|
||||
READ_MORE,
|
||||
FATAL_ERROR,
|
||||
ENTER_DEBUG
|
||||
};
|
||||
|
||||
static enum read_stat
|
||||
readtarget()
|
||||
{
|
||||
int j;
|
||||
int data;
|
||||
|
||||
/* Loop until the socket doesn't have any more data */
|
||||
while ((data = readchar(0)) >= 0) {
|
||||
|
||||
/* Check for the escape sequence */
|
||||
if (data == '|') {
|
||||
/* If this is the fourth escape, get out */
|
||||
if (++escape_count == 4)
|
||||
return (ENTER_DEBUG);
|
||||
continue; /* Not the fourth, continue */
|
||||
|
||||
} else {
|
||||
/*
|
||||
* Not an escape any more, Ensure any pending ones are flushed
|
||||
*/
|
||||
for (j = 1; j <= escape_count; j++)
|
||||
putchar('|');
|
||||
escape_count = 0;
|
||||
}
|
||||
|
||||
if (data == '\r') /* If this is a return character */
|
||||
continue; /* just supress it */
|
||||
|
||||
if (echo_check != -1) { /* If we are checking for an echo */
|
||||
/* If this might be an echo */
|
||||
if (tty_input[echo_check] == data) {
|
||||
echo_check++; /* Note one more character match */
|
||||
continue; /* Go and loop */
|
||||
} else {
|
||||
|
||||
if ((data == '\n') && (tty_input[echo_check] == '\r')) {
|
||||
/* If this is the end of the line */
|
||||
echo_check = -1; /* No more echo supression */
|
||||
continue; /* Go and loop */
|
||||
}
|
||||
|
||||
/* Not an echo, print out the data */
|
||||
for (j = 0; j < echo_check; j++)
|
||||
putchar(tty_input[j]);
|
||||
|
||||
echo_check = -1;/* No more echo checking */
|
||||
}
|
||||
}
|
||||
putchar(data); /* Output the character */
|
||||
}
|
||||
return (READ_MORE); /* Indicate to read some more */
|
||||
}
|
||||
|
||||
static enum read_stat
|
||||
readtty()
|
||||
{
|
||||
enum read_stat status;
|
||||
int tty_bc;
|
||||
|
||||
/* First, read a buffer full from the terminal */
|
||||
if ((tty_bc = read(fileno(stdin), tty_input, sizeof(tty_input) - 1)) < 0) {
|
||||
perror_with_name("readtty: read failed");
|
||||
return (FATAL_ERROR);
|
||||
}
|
||||
|
||||
/* Turn trailing newlines into returns */
|
||||
if (tty_input[tty_bc - 1] == '\n')
|
||||
tty_input[tty_bc - 1] = '\r';
|
||||
|
||||
if ((tty_input[0] == '~') && (tty_bc == 3))
|
||||
switch (tty_input[1]) {
|
||||
case 'b': /* ~b\n = send break & gdb */
|
||||
SERIAL_SEND_BREAK (remote_desc);
|
||||
/* fall through */
|
||||
|
||||
case 'c': /* ~c\n = return to gdb */
|
||||
return (ENTER_DEBUG);
|
||||
}
|
||||
|
||||
/* Make this a zero terminated string and write it out */
|
||||
tty_input[tty_bc] = '\0';
|
||||
|
||||
if (SERIAL_WRITE(remote_desc, tty_input, tty_bc)) {
|
||||
perror_with_name("readtty: write failed");
|
||||
return (FATAL_ERROR);
|
||||
}
|
||||
|
||||
return (READ_MORE);
|
||||
}
|
||||
|
||||
static int
|
||||
remote_talk()
|
||||
{
|
||||
fd_set input;
|
||||
int tablesize;
|
||||
enum read_stat status;
|
||||
int panic_flag = 0;
|
||||
char buf[4];
|
||||
|
||||
escape_count = 0;
|
||||
echo_check = -1;
|
||||
|
||||
tablesize = getdtablesize();
|
||||
|
||||
for (;;) {
|
||||
|
||||
/*
|
||||
* Check for anything from our socket - doesn't block. Note that this
|
||||
* must be done *before* the select as there may be buffered I/O
|
||||
* waiting to be processed.
|
||||
*/
|
||||
if ((status = readtarget()) != READ_MORE)
|
||||
return (status);
|
||||
|
||||
fflush(stdout); /* Flush output before blocking */
|
||||
|
||||
/* Now block on more socket input or TTY input */
|
||||
FD_ZERO(&input);
|
||||
FD_SET(fileno(stdin), &input);
|
||||
FD_SET(remote_desc->fd, &input);
|
||||
|
||||
status = select(tablesize, &input, 0, 0, 0);
|
||||
if ((status < 0) && (errno != EINTR)) {
|
||||
perror_with_name("remote_talk: select");
|
||||
return (FATAL_ERROR);
|
||||
}
|
||||
|
||||
/* Handle Control-C typed */
|
||||
if (quit_flag) {
|
||||
if ((++panic_flag) == 3) {
|
||||
printf("\nAre you repeating Control-C to terminate "
|
||||
"the session? (y/n) [n] ");
|
||||
fgets(buf, 3, stdin);
|
||||
if (buf[0] == 'y') {
|
||||
pop_target(); /* Clean up */
|
||||
error("Debugging terminated by user interrupt");
|
||||
}
|
||||
panic_flag = 0;
|
||||
}
|
||||
quit_flag = 0;
|
||||
SERIAL_WRITE(remote_desc, "\003", 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Handle terminal input */
|
||||
if (FD_ISSET(fileno(stdin), &input)) {
|
||||
panic_flag = 0;
|
||||
status = readtty();
|
||||
if (status != READ_MORE)
|
||||
return (status);
|
||||
echo_check = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* REMOTE_CHAT */
|
||||
|
||||
/* These are the threads which we last sent to the remote system. -1 for all
|
||||
or -2 for not sent yet. */
|
||||
@ -405,6 +582,11 @@ get_offsets ()
|
||||
CORE_ADDR text_addr, data_addr, bss_addr;
|
||||
struct section_offsets *offs;
|
||||
|
||||
#ifdef REMOTE_CHAT
|
||||
if (remote_chat)
|
||||
(void) remote_talk();
|
||||
#endif /* REMOTE_CHAT */
|
||||
|
||||
putpkt ("qOffsets");
|
||||
|
||||
getpkt (buf, 0);
|
||||
@ -729,6 +911,11 @@ remote_wait (pid, status)
|
||||
{
|
||||
unsigned char *p;
|
||||
|
||||
#ifdef REMOTE_CHAT
|
||||
if (remote_chat)
|
||||
(void) remote_talk();
|
||||
#endif /* REMOTE_CHAT */
|
||||
|
||||
ofunc = (void (*)()) signal (SIGINT, remote_interrupt);
|
||||
getpkt ((char *) buf, 1);
|
||||
signal (SIGINT, ofunc);
|
||||
@ -1401,6 +1588,16 @@ putpkt (buf)
|
||||
getpkt (junkbuf, 0);
|
||||
continue; /* Now, go look for + */
|
||||
}
|
||||
|
||||
#ifdef REMOTE_CHAT
|
||||
case '|':
|
||||
{
|
||||
if (!started_error_output)
|
||||
continue;
|
||||
/* else fall through */
|
||||
}
|
||||
#endif /* REMOTE_CHAT */
|
||||
|
||||
default:
|
||||
if (remote_debug)
|
||||
{
|
||||
@ -1836,4 +2033,12 @@ _initialize_remote ()
|
||||
var_integer, (char *)&remote_break,
|
||||
"Set whether to send break if interrupted.\n", &setlist),
|
||||
&showlist);
|
||||
|
||||
#ifdef REMOTE_CHAT
|
||||
add_show_from_set (add_set_cmd ("remotechat", no_class,
|
||||
var_zinteger, (char *)&remote_chat,
|
||||
"Set remote port interacts with target.\n", &setlist),
|
||||
&showlist);
|
||||
#endif /* REMOTE_CHAT */
|
||||
}
|
||||
|
||||
|
@ -905,7 +905,7 @@ find_core_target ()
|
||||
for (t = target_structs; t < target_structs + target_struct_size;
|
||||
++t)
|
||||
{
|
||||
if ((*t)->to_stratum == core_stratum)
|
||||
if ((*t)->to_stratum == (kernel_debugging ? kcore_stratum : core_stratum))
|
||||
{
|
||||
runable = *t;
|
||||
++count;
|
||||
|
@ -46,6 +46,7 @@ enum strata {
|
||||
dummy_stratum, /* The lowest of the low */
|
||||
file_stratum, /* Executable files, etc */
|
||||
core_stratum, /* Core dump files */
|
||||
kcore_stratum, /* Kernel core files */
|
||||
download_stratum, /* Downloading of remote targets */
|
||||
process_stratum /* Executing processes */
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user