home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fresh Fish 7
/
FreshFishVol7.bin
/
bbs
/
gnu
/
gdb-4.12-src.lha
/
GNU
/
src
/
amiga
/
gdb-4.12
/
gdb
/
remote-mm.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-02-03
|
50KB
|
1,627 lines
/* Remote debugging interface for Am290*0 running MiniMON monitor, for GDB.
Copyright 1990, 1991, 1992 Free Software Foundation, Inc.
Originally written by Daniel Mann at AMD.
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 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. */
/* This is like remote.c but ecpects MiniMON to be running on the Am29000
target hardware.
- David Wood (wood@lab.ultra.nyu.edu) at New York University adapted this
file to gdb 3.95. I was unable to get this working on sun3os4
with termio, only with sgtty. Because we are only attempting to
use this module to debug our kernel, which is already loaded when
gdb is started up, I did not code up the file downloading facilities.
As a result this module has only the stubs to download files.
You should get tagged at compile time if you need to make any
changes/additions. */
#include "defs.h"
#include "inferior.h"
#include "wait.h"
#include "value.h"
#include <ctype.h>
#include <fcntl.h>
#include <signal.h>
#include <errno.h>
#include <string.h>
#include "terminal.h"
#include "minimon.h"
#include "target.h"
/* Offset of member MEMBER in a struct of type TYPE. */
#define offsetof(TYPE, MEMBER) ((int) &((TYPE *)0)->MEMBER)
#define DRAIN_INPUT() (msg_recv_serial((union msg_t*)0))
extern int stop_soon_quietly; /* for wait_for_inferior */
static void mm_resume();
static void mm_fetch_registers ();
static int fetch_register ();
static void mm_store_registers ();
static int store_register ();
static int regnum_to_srnum();
static void mm_close ();
static char* msg_str();
static char* error_msg_str();
static int expect_msg();
static void init_target_mm();
static int mm_memory_space();
#define FREEZE_MODE (read_register(CPS_REGNUM) && 0x400)
#define USE_SHADOW_PC ((processor_type == a29k_freeze_mode) && FREEZE_MODE)
/* FIXME: Replace with `set remotedebug'. */
#define LLOG_FILE "minimon.log"
#if defined (LOG_FILE)
FILE *log_file;
#endif
/*
* Size of message buffers. I couldn't get memory reads to work when
* the byte_count was larger than 512 (it may be a baud rate problem).
*/
#define BUFER_SIZE 512
/*
* Size of data area in message buffer on the TARGET (remote system).
*/
#define MAXDATA_T (target_config.max_msg_size - \
offsetof(struct write_r_msg_t,data[0]))
/*
* Size of data area in message buffer on the HOST (gdb).
*/
#define MAXDATA_H (BUFER_SIZE - offsetof(struct write_r_msg_t,data[0]))
/*
* Defined as the minimum size of data areas of the two message buffers
*/
#define MAXDATA (MAXDATA_H < MAXDATA_T ? MAXDATA_H : MAXDATA_T)
static char out_buf[BUFER_SIZE];
static char in_buf[BUFER_SIZE];
int msg_recv_serial();
int msg_send_serial();
#define MAX_RETRIES 5000
extern struct target_ops mm_ops; /* Forward declaration */
struct config_msg_t target_config; /* HIF needs this */
union msg_t *out_msg_buf = (union msg_t*)out_buf;
union msg_t *in_msg_buf = (union msg_t*)in_buf;
static int timeout = 5;
/* Descriptor for I/O to remote machine. Initialize it to -1 so that
mm_open knows that we don't have a file open when the program
starts. */
int mm_desc = -1;
/* stream which is fdopen'd from mm_desc. Only valid when
mm_desc != -1. */
FILE *mm_stream;
/* Called when SIGALRM signal sent due to alarm() timeout. */
#ifndef HAVE_TERMIO
#ifndef __STDC__
# ifndef volatile
# define volatile /**/
# endif
#endif
volatile int n_alarms;
static void
mm_timer ()
{
#if 0
if (kiodebug)
printf ("mm_timer called\n");
#endif
n_alarms++;
}
#endif /* HAVE_TERMIO */
/* malloc'd name of the program on the remote system. */
static char *prog_name = NULL;
/* Number of SIGTRAPs we need to simulate. That is, the next
NEED_ARTIFICIAL_TRAP calls to mm_wait should just return
SIGTRAP without actually waiting for anything. */
/**************************************************** REMOTE_CREATE_INFERIOR */
/* This is called not only when we first attach, but also when the
user types "run" after having attached. */
static void
mm_create_inferior (execfile, args, env)
char *execfile;
char *args;
char **env;
{
#define MAX_TOKENS 25
#define BUFFER_SIZE 256
int token_count;
int result;
char *token[MAX_TOKENS];
char cmd_line[BUFFER_SIZE];
if (args && *args)
error ("Can't pass arguments to remote mm process (yet).");
if (execfile == 0 /* || exec_bfd == 0 */ )
error ("No exec file specified");
if (!mm_stream) {
printf("Minimon not open yet.\n");
return;
}
/* On ultra3 (NYU) we assume the kernel is already running so there is
no file to download.
FIXME: Fixed required here -> load your program, possibly with mm_load().
*/
printf_filtered ("\n\
Assuming you are at NYU debuging a kernel, i.e., no need to download.\n\n");
/* We will get a task spawn event immediately. */
init_wait_for_inferior ();
clear_proceed_status ();
stop_soon_quietly = 1;
proceed (-1, TARGET_SIGNAL_DEFAULT, 0);
normal_stop ();
}
/**************************************************** REMOTE_MOURN_INFERIOR */
static void
mm_mourn()
{
pop_target (); /* Pop back to no-child state */
generic_mourn_inferior ();
}
/********************************************************************** damn_b
*/
/* Translate baud rates from integers to damn B_codes. Unix should
have outgrown this crap years ago, but even POSIX wouldn't buck it. */
#ifndef B19200
#define B19200 EXTA
#endif
#ifndef B38400
#define B38400 EXTB
#endif
static struct {int rate, damn_b;} baudtab[] = {
{0, B0},
{50, B50},
{75, B75},
{110, B110},
{134, B134},
{150, B150},
{200, B200},
{300, B300},
{600, B600},
{1200, B1200},
{1800, B1800},
{2400, B2400},
{4800, B4800},
{9600, B9600},
{19200, B19200},
{38400, B38400},
{-1, -1},
};
static int damn_b (rate)
int rate;
{
int i;
for (i = 0; baudtab[i].rate != -1; i++)
if (rate == baudtab[i].rate) return baudtab[i].damn_b;
return B38400; /* Random */
}
/***************************************************************** REMOTE_OPEN
** Open a connection to remote minimon.
NAME is the filename used for communication, then a space,
then the baud rate.
'target adapt /dev/ttya 9600 [prognam]' for example.
*/
static char *dev_name;
int baudrate = 9600;
static void
mm_open (name, from_tty)
char *name;
int from_tty;
{
TERMINAL sg;
unsigned int prl;
char *p;
/* Find the first whitespace character, it separates dev_name from
prog_name. */
for (p = name;
p && *p && !isspace (*p); p++)
;
if (p == 0 || *p == '\0')
erroid:
error ("Usage : <command> <serial-device> <baud-rate> [progname]");
dev_name = (char*)malloc (p - name + 1);
strncpy (dev_name, name, p - name);
dev_name[p - name] = '\0';
/* Skip over the whitespace after dev_name */
for (; isspace (*p); p++)
/*EMPTY*/;
if (1 != sscanf (p, "%d ", &baudrate))
goto erroid;
/* Skip the number and then the spaces */
for (; isdigit (*p); p++)
/*EMPTY*/;
for (; isspace (*p); p++)
/*EMPTY*/;
if (prog_name != NULL)
free (prog_name);
prog_name = savestring (p, strlen (p));
if (mm_desc >= 0)
close (mm_desc);
mm_desc = open (dev_name, O_RDWR);
if (mm_desc < 0)
perror_with_name (dev_name);
ioctl (mm_desc, TIOCGETP, &sg);
#ifdef HAVE_TERMIO
sg.c_cc[VMIN] = 0; /* read with timeout. */
sg.c_cc[VTIME] = timeout * 10;
sg.c_lflag &= ~(ICANON | ECHO);
sg.c_cflag = (sg.c_cflag & ~CBAUD) | damn_b (baudrate);
#else
sg.sg_ispeed = dam