1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269
|
/* Low level interface to simulators, for the remote server for GDB.
Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
Free Software Foundation, Inc.
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., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "server.h"
#include "bfd.h"
#include "callback.h" /* GDB simulator callback interface */
#include "remote-sim.h" /* GDB simulator interface */
extern int remote_debug;
extern host_callback default_callback; /* in sim/common/callback.c */
static char my_registers[REGISTER_BYTES] __attribute__ ((aligned));
char * registers = my_registers;
int target_byte_order; /* used by simulator */
/* We record the result of sim_open so we can pass it
back to the other sim_foo routines. */
static SIM_DESC gdbsim_desc = 0;
/* This version of "load" should be usable for any simulator that
does not support loading itself. */
static void
mygeneric_load (bfd *loadfile_bfd)
{
asection *s;
for (s = loadfile_bfd->sections; s; s = s->next)
{
if (s->flags & SEC_LOAD)
{
bfd_size_type size;
size = bfd_get_section_size_before_reloc (s);
if (size > 0)
{
char *buffer;
bfd_vma lma; /* use load address, not virtual address */
buffer = xmalloc (size);
lma = s->lma;
/* Is this really necessary? I guess it gives the user something
to look at during a long download. */
printf ("Loading section %s, size 0x%lx lma 0x%lx\n",
bfd_get_section_name (loadfile_bfd, s),
(unsigned long) size,
(unsigned long) lma); /* chops high 32 bits. FIXME!! */
bfd_get_section_contents (loadfile_bfd, s, buffer, 0, size);
write_inferior_memory (lma, buffer, size);
free (buffer);
}
}
}
printf ("Start address 0x%lx\n",
(unsigned long) loadfile_bfd->start_address);
/* We were doing this in remote-mips.c, I suspect it is right
for other targets too. */
/* write_pc (loadfile_bfd->start_address); *//* FIXME!! */
}
int
create_inferior (char *program, char **argv)
{
bfd *abfd;
int pid = 0;
char **new_argv;
int nargs;
abfd = bfd_openr (program, 0);
if (!abfd)
{
fprintf (stderr, "gdbserver: can't open %s: %s\n",
program, bfd_errmsg (bfd_get_error ()));
exit (1);
}
if (!bfd_check_format (abfd, bfd_object))
{
fprintf (stderr, "gdbserver: unknown load format for %s: %s\n",
program, bfd_errmsg (bfd_get_error ()));
exit (1);
}
/* Add "-E big" or "-E little" to the argument list depending on the
endianness of the program to be loaded. */
for (nargs = 0; argv[nargs] != NULL; nargs++) /* count the args */
;
new_argv = alloca (sizeof (char *) * (nargs + 3)); /* allocate new args */
for (nargs = 0; argv[nargs] != NULL; nargs++) /* copy old to new */
new_argv[nargs] = argv[nargs];
new_argv[nargs] = "-E";
new_argv[nargs + 1] = bfd_big_endian (abfd) ? "big" : "little";
new_argv[nargs + 2] = NULL;
argv = new_argv;
/* Create an instance of the simulator. */
default_callback.init (&default_callback);
gdbsim_desc = sim_open (SIM_OPEN_STANDALONE, &default_callback, abfd, argv);
if (gdbsim_desc == 0)
exit (1);
/* Load the program into the simulator. */
if (abfd)
if (sim_load (gdbsim_desc, program, NULL, 0) == SIM_RC_FAIL)
mygeneric_load (abfd);
/* Create an inferior process in the simulator. This initializes SP. */
sim_create_inferior (gdbsim_desc, abfd, argv, /* env */ NULL);
sim_resume (gdbsim_desc, 1, 0); /* execute one instr */
return pid;
}
/* Attaching is not supported. */
int
myattach (int pid)
{
return -1;
}
/* Kill the inferior process. Make us have no inferior. */
void
kill_inferior (void)
{
sim_close (gdbsim_desc, 0);
default_callback.shutdown (&default_callback);
}
/* Fetch one register. */
static void
fetch_register (int regno)
{
sim_fetch_register (gdbsim_desc, regno, ®isters[REGISTER_BYTE (regno)],
REGISTER_RAW_SIZE (regno));
}
/* Fetch all registers, or just one, from the child process. */
void
fetch_inferior_registers (int regno)
{
if (regno == -1 || regno == 0)
for (regno = 0; regno < NUM_REGS /*-NUM_FREGS*/ ; regno++)
fetch_register (regno);
else
fetch_register (regno);
}
/* Store our register values back into the inferior.
If REGNO is -1, do this for all registers.
Otherwise, REGNO specifies which register (so we can save time). */
void
store_inferior_registers (int regno)
{
if (regno == -1)
{
for (regno = 0; regno < NUM_REGS; regno++)
store_inferior_registers (regno);
}
else
sim_store_register (gdbsim_desc, regno, ®isters[REGISTER_BYTE (regno)],
REGISTER_RAW_SIZE (regno));
}
/* Return nonzero if the given thread is still alive. */
int
mythread_alive (int pid)
{
return 1;
}
/* Wait for process, returns status */
unsigned char
mywait (char *status)
{
int sigrc;
enum sim_stop reason;
sim_stop_reason (gdbsim_desc, &reason, &sigrc);
switch (reason)
{
case sim_exited:
if (remote_debug)
printf ("\nChild exited with retcode = %x \n", sigrc);
*status = 'W';
return sigrc;
#if 0
case sim_stopped:
if (remote_debug)
printf ("\nChild terminated with signal = %x \n", sigrc);
*status = 'X';
return sigrc;
#endif
default: /* should this be sim_signalled or sim_stopped? FIXME!! */
if (remote_debug)
printf ("\nChild received signal = %x \n", sigrc);
fetch_inferior_registers (0);
*status = 'T';
return (unsigned char) sigrc;
}
}
/* Resume execution of the inferior process.
If STEP is nonzero, single-step it.
If SIGNAL is nonzero, give it that signal. */
void
myresume (int step, int signo)
{
/* Should be using target_signal_to_host() or signal numbers in target.h
to convert GDB signal number to target signal number. */
sim_resume (gdbsim_desc, step, signo);
}
/* Copy LEN bytes from inferior's memory starting at MEMADDR
to debugger memory starting at MYADDR. */
void
read_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len)
{
sim_read (gdbsim_desc, memaddr, myaddr, len);
}
/* Copy LEN bytes of data from debugger memory at MYADDR
to inferior's memory at MEMADDR.
On failure (cannot write the inferior)
returns the value of errno. */
int
write_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len)
{
sim_write (gdbsim_desc, memaddr, myaddr, len); /* should check for error. FIXME!! */
return 0;
}
void
initialize_low (void)
{
}
|