mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-23 18:14:13 +08:00
2002-04-20 Daniel Jacobowitz <drow@mvista.com>
* gdbserver/mem-break.c: New file. * gdbserver/mem-break.h: New file. * gdbserver/Makefile.in: Add mem-break.o rule; update server.h dependencies. * gdbserver/inferiors.c (struct inferior_info): Add target_data member. (clear_inferiors): Free target_data member if set. (inferior_target_data, set_inferior_target_data): New functions. * gdbserver/linux-i386-low.c (i386_breakpoint, i386_breakpoint_len) (i386_stop_pc, i386_set_pc): New. Add to the_low_target. * gdbserver/linux-low.c (linux_bp_reinsert): New variable. (struct inferior_linux_data): New. (linux_create_inferior): Use set_inferior_target_data. (linux_attach): Likewise. Call add_inferior. (linux_wait_for_one_inferior): New function. (linux_wait): Call it. (linux_write_memory): Add const. (initialize_low): Call set_breakpoint_data. * gdbserver/linux-low.h (struct linux_target_ops): Add breakpoint handling members. * gdbserver/server.c (attach_inferior): Remove extra add_inferior call. * gdbserver/server.h: Include mem-break.h. Update inferior.c prototypes. * gdbserver/target.c (read_inferior_memory) (write_inferior_memory): New functions. * gdbserver/target.h (read_inferior_memory) (write_inferior_memory): Change macros to prototypes. (struct target_ops): Update comments. Add const to write_memory definition.
This commit is contained in:
parent
e101598283
commit
611cb4a542
@ -1,3 +1,36 @@
|
||||
2002-04-20 Daniel Jacobowitz <drow@mvista.com>
|
||||
|
||||
* gdbserver/mem-break.c: New file.
|
||||
* gdbserver/mem-break.h: New file.
|
||||
* gdbserver/Makefile.in: Add mem-break.o rule; update server.h
|
||||
dependencies.
|
||||
* gdbserver/inferiors.c (struct inferior_info): Add target_data
|
||||
member.
|
||||
(clear_inferiors): Free target_data member if set.
|
||||
(inferior_target_data, set_inferior_target_data): New functions.
|
||||
* gdbserver/linux-i386-low.c (i386_breakpoint, i386_breakpoint_len)
|
||||
(i386_stop_pc, i386_set_pc): New. Add to the_low_target.
|
||||
* gdbserver/linux-low.c (linux_bp_reinsert): New variable.
|
||||
(struct inferior_linux_data): New.
|
||||
(linux_create_inferior): Use set_inferior_target_data.
|
||||
(linux_attach): Likewise. Call add_inferior.
|
||||
(linux_wait_for_one_inferior): New function.
|
||||
(linux_wait): Call it.
|
||||
(linux_write_memory): Add const.
|
||||
(initialize_low): Call set_breakpoint_data.
|
||||
* gdbserver/linux-low.h (struct linux_target_ops): Add breakpoint
|
||||
handling members.
|
||||
* gdbserver/server.c (attach_inferior): Remove extra add_inferior
|
||||
call.
|
||||
* gdbserver/server.h: Include mem-break.h. Update inferior.c
|
||||
prototypes.
|
||||
* gdbserver/target.c (read_inferior_memory)
|
||||
(write_inferior_memory): New functions.
|
||||
* gdbserver/target.h (read_inferior_memory)
|
||||
(write_inferior_memory): Change macros to prototypes.
|
||||
(struct target_ops): Update comments. Add const to write_memory
|
||||
definition.
|
||||
|
||||
2002-04-19 Andrew Cagney <ac131313@redhat.com>
|
||||
|
||||
* sparc-tdep.c (sparc_get_saved_register): Use get_prev_frame
|
||||
|
@ -124,6 +124,7 @@ TAGFILES = $(SOURCES) ${HFILES} ${ALLPARAM} ${POSSLIBS}
|
||||
|
||||
OBS = inferiors.o regcache.o remote-utils.o server.o signals.o target.o \
|
||||
utils.o \
|
||||
mem-break.o \
|
||||
$(DEPFILES)
|
||||
|
||||
# Prevent Sun make from putting in the machine type. Setting
|
||||
@ -233,9 +234,11 @@ unexport CHILLFLAGS CHILL_LIB CHILL_FOR_TARGET :
|
||||
regdat_sh = $(srcdir)/../regformats/regdat.sh
|
||||
regdef_h = $(srcdir)/../regformats/regdef.h
|
||||
regcache_h = $(srcdir)/regcache.h
|
||||
server_h = $(srcdir)/server.h $(regcache_h) config.h $(srcdir)/target.h
|
||||
server_h = $(srcdir)/server.h $(regcache_h) config.h $(srcdir)/target.h \
|
||||
$(srcdir)/mem-break.h
|
||||
|
||||
inferiors.o: inferiors.c $(server_h)
|
||||
mem-break.o: mem-break.c $(server_h)
|
||||
regcache.o: regcache.c $(server_h) $(regdef_h)
|
||||
remote-utils.o: remote-utils.c terminal.h $(server_h)
|
||||
server.o: server.c $(server_h)
|
||||
|
@ -28,6 +28,7 @@
|
||||
struct inferior_info
|
||||
{
|
||||
int pid;
|
||||
void *target_data;
|
||||
struct inferior_info *next;
|
||||
};
|
||||
|
||||
@ -63,9 +64,25 @@ clear_inferiors (void)
|
||||
while (inf)
|
||||
{
|
||||
next_inf = inf->next;
|
||||
|
||||
if (inf->target_data)
|
||||
free (inf->target_data);
|
||||
|
||||
free (inf);
|
||||
inf = next_inf;
|
||||
}
|
||||
|
||||
inferiors = NULL;
|
||||
}
|
||||
|
||||
void *
|
||||
inferior_target_data (struct inferior_info *inferior)
|
||||
{
|
||||
return inferior->target_data;
|
||||
}
|
||||
|
||||
void
|
||||
set_inferior_target_data (struct inferior_info *inferior, void *data)
|
||||
{
|
||||
inferior->target_data = data;
|
||||
}
|
||||
|
@ -121,9 +121,37 @@ struct regset_info target_regsets[] = {
|
||||
|
||||
#endif /* HAVE_LINUX_REGSETS */
|
||||
|
||||
static const char i386_breakpoint[] = { 0xCC };
|
||||
#define i386_breakpoint_len 1
|
||||
|
||||
static CORE_ADDR
|
||||
i386_stop_pc ()
|
||||
{
|
||||
unsigned long pc;
|
||||
|
||||
/* Overkill */
|
||||
fetch_inferior_registers (0);
|
||||
|
||||
collect_register_by_name ("eip", &pc);
|
||||
return pc - 1;
|
||||
}
|
||||
|
||||
static void
|
||||
i386_set_pc (CORE_ADDR newpc)
|
||||
{
|
||||
supply_register_by_name ("eip", &newpc);
|
||||
|
||||
/* Overkill */
|
||||
store_inferior_registers (0);
|
||||
}
|
||||
|
||||
struct linux_target_ops the_low_target = {
|
||||
i386_num_regs,
|
||||
i386_regmap,
|
||||
i386_cannot_fetch_register,
|
||||
i386_cannot_store_register,
|
||||
i386_stop_pc,
|
||||
i386_set_pc,
|
||||
i386_breakpoint,
|
||||
i386_breakpoint_len,
|
||||
};
|
||||
|
@ -35,6 +35,10 @@
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static CORE_ADDR linux_bp_reinsert;
|
||||
|
||||
static void linux_resume (int step, int signal);
|
||||
|
||||
#define PTRACE_ARG3_TYPE long
|
||||
#define PTRACE_XFER_TYPE long
|
||||
|
||||
@ -46,12 +50,18 @@ extern int errno;
|
||||
|
||||
static int inferior_pid;
|
||||
|
||||
struct inferior_linux_data
|
||||
{
|
||||
int pid;
|
||||
};
|
||||
|
||||
/* Start an inferior process and returns its pid.
|
||||
ALLARGS is a vector of program-name and args. */
|
||||
|
||||
static int
|
||||
linux_create_inferior (char *program, char **allargs)
|
||||
{
|
||||
struct inferior_linux_data *tdata;
|
||||
int pid;
|
||||
|
||||
pid = fork ();
|
||||
@ -71,6 +81,10 @@ linux_create_inferior (char *program, char **allargs)
|
||||
}
|
||||
|
||||
add_inferior (pid);
|
||||
tdata = (struct inferior_linux_data *) malloc (sizeof (*tdata));
|
||||
tdata->pid = pid;
|
||||
set_inferior_target_data (current_inferior, tdata);
|
||||
|
||||
/* FIXME remove */
|
||||
inferior_pid = pid;
|
||||
return 0;
|
||||
@ -81,6 +95,8 @@ linux_create_inferior (char *program, char **allargs)
|
||||
static int
|
||||
linux_attach (int pid)
|
||||
{
|
||||
struct inferior_linux_data *tdata;
|
||||
|
||||
if (ptrace (PTRACE_ATTACH, pid, 0, 0) != 0)
|
||||
{
|
||||
fprintf (stderr, "Cannot attach to process %d: %s (%d)\n", pid,
|
||||
@ -90,6 +106,10 @@ linux_attach (int pid)
|
||||
_exit (0177);
|
||||
}
|
||||
|
||||
add_inferior (pid);
|
||||
tdata = (struct inferior_linux_data *) malloc (sizeof (*tdata));
|
||||
tdata->pid = pid;
|
||||
set_inferior_target_data (current_inferior, tdata);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -112,19 +132,75 @@ linux_thread_alive (int pid)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
linux_wait_for_one_inferior (struct inferior_info *child)
|
||||
{
|
||||
struct inferior_linux_data *child_data = inferior_target_data (child);
|
||||
int pid, wstat;
|
||||
|
||||
while (1)
|
||||
{
|
||||
pid = waitpid (child_data->pid, &wstat, 0);
|
||||
|
||||
if (pid != child_data->pid)
|
||||
perror_with_name ("wait");
|
||||
|
||||
/* If this target supports breakpoints, see if we hit one. */
|
||||
if (the_low_target.stop_pc != NULL
|
||||
&& WIFSTOPPED (wstat)
|
||||
&& WSTOPSIG (wstat) == SIGTRAP)
|
||||
{
|
||||
CORE_ADDR stop_pc;
|
||||
|
||||
if (linux_bp_reinsert != 0)
|
||||
{
|
||||
reinsert_breakpoint (linux_bp_reinsert);
|
||||
linux_bp_reinsert = 0;
|
||||
linux_resume (0, 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
fetch_inferior_registers (0);
|
||||
stop_pc = (*the_low_target.stop_pc) ();
|
||||
|
||||
if (check_breakpoints (stop_pc) != 0)
|
||||
{
|
||||
if (the_low_target.set_pc != NULL)
|
||||
(*the_low_target.set_pc) (stop_pc);
|
||||
|
||||
if (the_low_target.breakpoint_reinsert_addr == NULL)
|
||||
{
|
||||
linux_bp_reinsert = stop_pc;
|
||||
uninsert_breakpoint (stop_pc);
|
||||
linux_resume (1, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
reinsert_breakpoint_by_bp
|
||||
(stop_pc, (*the_low_target.breakpoint_reinsert_addr) ());
|
||||
linux_resume (0, 0);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return wstat;
|
||||
}
|
||||
/* NOTREACHED */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Wait for process, returns status */
|
||||
|
||||
static unsigned char
|
||||
linux_wait (char *status)
|
||||
{
|
||||
int pid;
|
||||
int w;
|
||||
|
||||
enable_async_io ();
|
||||
pid = waitpid (inferior_pid, &w, 0);
|
||||
w = linux_wait_for_one_inferior (current_inferior);
|
||||
disable_async_io ();
|
||||
if (pid != inferior_pid)
|
||||
perror_with_name ("wait");
|
||||
|
||||
if (WIFEXITED (w))
|
||||
{
|
||||
@ -440,7 +516,7 @@ linux_read_memory (CORE_ADDR memaddr, char *myaddr, int len)
|
||||
returns the value of errno. */
|
||||
|
||||
static int
|
||||
linux_write_memory (CORE_ADDR memaddr, char *myaddr, int len)
|
||||
linux_write_memory (CORE_ADDR memaddr, const char *myaddr, int len)
|
||||
{
|
||||
register int i;
|
||||
/* Round starting address down to longword boundary. */
|
||||
@ -508,5 +584,7 @@ void
|
||||
initialize_low (void)
|
||||
{
|
||||
set_target_ops (&linux_target_ops);
|
||||
set_breakpoint_data (the_low_target.breakpoint,
|
||||
the_low_target.breakpoint_len);
|
||||
init_registers ();
|
||||
}
|
||||
|
@ -39,6 +39,11 @@ struct linux_target_ops
|
||||
store the register, and 2 if failure to store the register
|
||||
is acceptable. */
|
||||
int (*cannot_store_register) (int);
|
||||
CORE_ADDR (*stop_pc) (void);
|
||||
void (*set_pc) (CORE_ADDR newpc);
|
||||
const char *breakpoint;
|
||||
int breakpoint_len;
|
||||
CORE_ADDR (*breakpoint_reinsert_addr) (void);
|
||||
};
|
||||
|
||||
extern struct linux_target_ops the_low_target;
|
||||
|
280
gdb/gdbserver/mem-break.c
Normal file
280
gdb/gdbserver/mem-break.c
Normal file
@ -0,0 +1,280 @@
|
||||
/* Memory breakpoint operations for the remote server for GDB.
|
||||
Copyright 2002
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
Contributed by MontaVista Software.
|
||||
|
||||
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"
|
||||
|
||||
const char *breakpoint_data;
|
||||
int breakpoint_len;
|
||||
|
||||
#define MAX_BREAKPOINT_LEN 8
|
||||
|
||||
struct breakpoint
|
||||
{
|
||||
struct breakpoint *next;
|
||||
CORE_ADDR pc;
|
||||
unsigned char old_data[MAX_BREAKPOINT_LEN];
|
||||
|
||||
/* Non-zero iff we are stepping over this breakpoint. */
|
||||
int reinserting;
|
||||
|
||||
/* Non-NULL iff this breakpoint was inserted to step over
|
||||
another one. Points to the other breakpoint (which is also
|
||||
in the *next chain somewhere). */
|
||||
struct breakpoint *breakpoint_to_reinsert;
|
||||
|
||||
/* Function to call when we hit this breakpoint. */
|
||||
void (*handler) (CORE_ADDR);
|
||||
};
|
||||
|
||||
struct breakpoint *breakpoints;
|
||||
|
||||
void
|
||||
set_breakpoint_at (CORE_ADDR where, void (*handler) (CORE_ADDR))
|
||||
{
|
||||
struct breakpoint *bp;
|
||||
|
||||
if (breakpoint_data == NULL)
|
||||
error ("Target does not support breakpoints.");
|
||||
|
||||
bp = malloc (sizeof (struct breakpoint));
|
||||
memset (bp, 0, sizeof (struct breakpoint));
|
||||
|
||||
(*the_target->read_memory) (where, bp->old_data,
|
||||
breakpoint_len);
|
||||
(*the_target->write_memory) (where, breakpoint_data,
|
||||
breakpoint_len);
|
||||
|
||||
bp->pc = where;
|
||||
bp->handler = handler;
|
||||
|
||||
bp->next = breakpoints;
|
||||
breakpoints = bp;
|
||||
}
|
||||
|
||||
static void
|
||||
delete_breakpoint (struct breakpoint *bp)
|
||||
{
|
||||
struct breakpoint *cur;
|
||||
|
||||
if (breakpoints == bp)
|
||||
{
|
||||
breakpoints = bp->next;
|
||||
(*the_target->write_memory) (bp->pc, bp->old_data,
|
||||
breakpoint_len);
|
||||
free (bp);
|
||||
return;
|
||||
}
|
||||
cur = breakpoints;
|
||||
while (cur->next)
|
||||
{
|
||||
if (cur->next == bp)
|
||||
{
|
||||
cur->next = bp->next;
|
||||
(*the_target->write_memory) (bp->pc, bp->old_data,
|
||||
breakpoint_len);
|
||||
free (bp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
warning ("Could not find breakpoint in list.");
|
||||
}
|
||||
|
||||
static struct breakpoint *
|
||||
find_breakpoint_at (CORE_ADDR where)
|
||||
{
|
||||
struct breakpoint *bp = breakpoints;
|
||||
|
||||
while (bp != NULL)
|
||||
{
|
||||
if (bp->pc == where)
|
||||
return bp;
|
||||
bp = bp->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
reinsert_breakpoint_handler (CORE_ADDR stop_pc)
|
||||
{
|
||||
struct breakpoint *stop_bp, *orig_bp;
|
||||
|
||||
stop_bp = find_breakpoint_at (stop_pc);
|
||||
if (stop_bp == NULL)
|
||||
error ("lost the stopping breakpoint.");
|
||||
|
||||
orig_bp = stop_bp->breakpoint_to_reinsert;
|
||||
if (orig_bp == NULL)
|
||||
error ("no breakpoint to reinsert");
|
||||
|
||||
(*the_target->write_memory) (orig_bp->pc, breakpoint_data,
|
||||
breakpoint_len);
|
||||
orig_bp->reinserting = 0;
|
||||
delete_breakpoint (stop_bp);
|
||||
}
|
||||
|
||||
void
|
||||
reinsert_breakpoint_by_bp (CORE_ADDR stop_pc, CORE_ADDR stop_at)
|
||||
{
|
||||
struct breakpoint *bp, *orig_bp;
|
||||
|
||||
set_breakpoint_at (stop_at, reinsert_breakpoint_handler);
|
||||
|
||||
orig_bp = find_breakpoint_at (stop_at);
|
||||
if (orig_bp == NULL)
|
||||
error ("Could not find original breakpoint in list.");
|
||||
|
||||
bp = find_breakpoint_at (stop_at);
|
||||
if (bp == NULL)
|
||||
error ("Could not find breakpoint in list (reinserting by breakpoint).");
|
||||
bp->breakpoint_to_reinsert = orig_bp;
|
||||
|
||||
(*the_target->write_memory) (orig_bp->pc, orig_bp->old_data,
|
||||
breakpoint_len);
|
||||
orig_bp->reinserting = 1;
|
||||
}
|
||||
|
||||
void
|
||||
uninsert_breakpoint (CORE_ADDR stopped_at)
|
||||
{
|
||||
struct breakpoint *bp;
|
||||
|
||||
bp = find_breakpoint_at (stopped_at);
|
||||
if (bp == NULL)
|
||||
error ("Could not find breakpoint in list (uninserting).");
|
||||
|
||||
(*the_target->write_memory) (bp->pc, bp->old_data,
|
||||
breakpoint_len);
|
||||
bp->reinserting = 1;
|
||||
}
|
||||
|
||||
void
|
||||
reinsert_breakpoint (CORE_ADDR stopped_at)
|
||||
{
|
||||
struct breakpoint *bp;
|
||||
|
||||
bp = find_breakpoint_at (stopped_at);
|
||||
if (bp == NULL)
|
||||
error ("Could not find breakpoint in list (uninserting).");
|
||||
if (! bp->reinserting)
|
||||
error ("Breakpoint already inserted at reinsert time.");
|
||||
|
||||
(*the_target->write_memory) (bp->pc, breakpoint_data,
|
||||
breakpoint_len);
|
||||
bp->reinserting = 0;
|
||||
}
|
||||
|
||||
int
|
||||
check_breakpoints (CORE_ADDR stop_pc)
|
||||
{
|
||||
struct breakpoint *bp;
|
||||
|
||||
bp = find_breakpoint_at (stop_pc);
|
||||
if (bp == NULL)
|
||||
return 0;
|
||||
if (bp->reinserting)
|
||||
{
|
||||
warning ("Hit a removed breakpoint?");
|
||||
return 0;
|
||||
}
|
||||
|
||||
(*bp->handler) (bp->pc);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
set_breakpoint_data (const char *bp_data, int bp_len)
|
||||
{
|
||||
breakpoint_data = bp_data;
|
||||
breakpoint_len = bp_len;
|
||||
}
|
||||
|
||||
void
|
||||
check_mem_read (CORE_ADDR mem_addr, char *buf, int mem_len)
|
||||
{
|
||||
struct breakpoint *bp = breakpoints;
|
||||
CORE_ADDR mem_end = mem_addr + mem_len;
|
||||
|
||||
for (; bp != NULL; bp = bp->next)
|
||||
{
|
||||
CORE_ADDR bp_end = bp->pc + breakpoint_len;
|
||||
CORE_ADDR start, end;
|
||||
int copy_offset, copy_len, buf_offset;
|
||||
|
||||
if (mem_addr >= bp_end)
|
||||
continue;
|
||||
if (bp->pc >= mem_end)
|
||||
continue;
|
||||
|
||||
start = bp->pc;
|
||||
if (mem_addr > start)
|
||||
start = mem_addr;
|
||||
|
||||
end = bp_end;
|
||||
if (end > mem_end)
|
||||
end = mem_end;
|
||||
|
||||
copy_len = end - start;
|
||||
copy_offset = start - bp->pc;
|
||||
buf_offset = start - mem_addr;
|
||||
|
||||
memcpy (buf + buf_offset, bp->old_data + copy_offset, copy_len);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
check_mem_write (CORE_ADDR mem_addr, char *buf, int mem_len)
|
||||
{
|
||||
struct breakpoint *bp = breakpoints;
|
||||
CORE_ADDR mem_end = mem_addr + mem_len;
|
||||
|
||||
for (; bp != NULL; bp = bp->next)
|
||||
{
|
||||
CORE_ADDR bp_end = bp->pc + breakpoint_len;
|
||||
CORE_ADDR start, end;
|
||||
int copy_offset, copy_len, buf_offset;
|
||||
|
||||
if (mem_addr >= bp_end)
|
||||
continue;
|
||||
if (bp->pc >= mem_end)
|
||||
continue;
|
||||
|
||||
start = bp->pc;
|
||||
if (mem_addr > start)
|
||||
start = mem_addr;
|
||||
|
||||
end = bp_end;
|
||||
if (end > mem_end)
|
||||
end = mem_end;
|
||||
|
||||
copy_len = end - start;
|
||||
copy_offset = start - bp->pc;
|
||||
buf_offset = start - mem_addr;
|
||||
|
||||
memcpy (bp->old_data + copy_offset, buf + buf_offset, copy_len);
|
||||
if (bp->reinserting == 0)
|
||||
memcpy (buf + buf_offset, breakpoint_data + copy_offset, copy_len);
|
||||
}
|
||||
}
|
||||
|
||||
|
71
gdb/gdbserver/mem-break.h
Normal file
71
gdb/gdbserver/mem-break.h
Normal file
@ -0,0 +1,71 @@
|
||||
/* Memory breakpoint interfaces for the remote server for GDB.
|
||||
Copyright 2002
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
Contributed by MontaVista Software.
|
||||
|
||||
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. */
|
||||
|
||||
#ifndef MEM_BREAK_H
|
||||
#define MEM_BREAK_H
|
||||
|
||||
/* Breakpoints are opaque. */
|
||||
|
||||
/* Create a new breakpoint at WHERE, and call HANDLER when
|
||||
it is hit. */
|
||||
|
||||
void set_breakpoint_at (CORE_ADDR where,
|
||||
void (*handler) (CORE_ADDR));
|
||||
|
||||
/* Create a reinsertion breakpoint at STOP_AT for the breakpoint
|
||||
currently at STOP_PC (and temporarily remove the breakpoint at
|
||||
STOP_PC). */
|
||||
|
||||
void reinsert_breakpoint_by_bp (CORE_ADDR stop_pc, CORE_ADDR stop_at);
|
||||
|
||||
/* Change the status of the breakpoint at WHERE to inserted. */
|
||||
|
||||
void reinsert_breakpoint (CORE_ADDR where);
|
||||
|
||||
/* Change the status of the breakpoint at WHERE to uninserted. */
|
||||
|
||||
void uninsert_breakpoint (CORE_ADDR where);
|
||||
|
||||
/* See if any breakpoint claims ownership of STOP_PC. Call the handler for
|
||||
the breakpoint, if found. */
|
||||
|
||||
int check_breakpoints (CORE_ADDR stop_pc);
|
||||
|
||||
/* See if any breakpoints shadow the target memory area from MEM_ADDR
|
||||
to MEM_ADDR + MEM_LEN. Update the data already read from the target
|
||||
(in BUF) if necessary. */
|
||||
|
||||
void check_mem_read (CORE_ADDR mem_addr, char *buf, int mem_len);
|
||||
|
||||
/* See if any breakpoints shadow the target memory area from MEM_ADDR
|
||||
to MEM_ADDR + MEM_LEN. Update the data to be written to the target
|
||||
(in BUF) if necessary, as well as the original data for any breakpoints. */
|
||||
|
||||
void check_mem_write (CORE_ADDR mem_addr, char *buf, int mem_len);
|
||||
|
||||
/* Set the byte pattern to insert for memory breakpoints. This function
|
||||
must be called before any breakpoints are set. */
|
||||
|
||||
void set_breakpoint_data (const char *bp_data, int bp_len);
|
||||
|
||||
#endif /* MEM_BREAK_H */
|
@ -48,8 +48,6 @@ attach_inferior (int pid, char *statusptr, unsigned char *sigptr)
|
||||
if (myattach (pid) != 0)
|
||||
return -1;
|
||||
|
||||
add_inferior (pid);
|
||||
|
||||
*sigptr = mywait (statusptr);
|
||||
|
||||
return 0;
|
||||
|
@ -58,6 +58,7 @@ typedef long long CORE_ADDR;
|
||||
#include "gdb/signals.h"
|
||||
|
||||
#include "target.h"
|
||||
#include "mem-break.h"
|
||||
|
||||
/* Target-specific functions */
|
||||
|
||||
@ -74,6 +75,9 @@ extern struct inferior_info *current_inferior;
|
||||
extern int signal_pid;
|
||||
void add_inferior (int pid);
|
||||
void clear_inferiors (void);
|
||||
void *inferior_target_data (struct inferior_info *);
|
||||
void set_inferior_target_data (struct inferior_info *, void *);
|
||||
|
||||
|
||||
/* Public variables in server.c */
|
||||
|
||||
|
@ -25,6 +25,20 @@
|
||||
|
||||
struct target_ops *the_target;
|
||||
|
||||
void
|
||||
read_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len)
|
||||
{
|
||||
(*the_target->read_memory) (memaddr, myaddr, len);
|
||||
check_mem_read (memaddr, myaddr, len);
|
||||
}
|
||||
|
||||
int
|
||||
write_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len)
|
||||
{
|
||||
check_mem_write (memaddr, myaddr, len);
|
||||
return (*the_target->write_memory) (memaddr, myaddr, len);
|
||||
}
|
||||
|
||||
void
|
||||
set_target_ops (struct target_ops *target)
|
||||
{
|
||||
|
@ -81,24 +81,27 @@ struct target_ops
|
||||
|
||||
void (*store_registers) (int regno);
|
||||
|
||||
/* Read memory from the inferior process.
|
||||
/* Read memory from the inferior process. This should generally be
|
||||
called through read_inferior_memory, which handles breakpoint shadowing.
|
||||
|
||||
Read LEN bytes at MEMADDR into a buffer at MYADDR. */
|
||||
|
||||
void (*read_memory) (CORE_ADDR memaddr, char *myaddr, int len);
|
||||
|
||||
/* Write memory to the inferior process.
|
||||
/* Write memory to the inferior process. This should generally be
|
||||
called through write_inferior_memory, which handles breakpoint shadowing.
|
||||
|
||||
Write LEN bytes from the buffer at MYADDR to MEMADDR.
|
||||
|
||||
Returns 0 on success and errno on failure. */
|
||||
|
||||
int (*write_memory) (CORE_ADDR memaddr, char *myaddr, int len);
|
||||
int (*write_memory) (CORE_ADDR memaddr, const char *myaddr, int len);
|
||||
|
||||
/* Query GDB for the values of any symbols we're interested in.
|
||||
This function is called whenever we receive a "qSymbols::"
|
||||
query, which corresponds to every time more symbols (might)
|
||||
become available. */
|
||||
become available. NULL if we aren't interested in any
|
||||
symbols. */
|
||||
|
||||
void (*look_up_symbols) (void);
|
||||
};
|
||||
@ -131,10 +134,8 @@ void set_target_ops (struct target_ops *);
|
||||
#define store_inferior_registers(regno) \
|
||||
(*the_target->store_registers) (regno)
|
||||
|
||||
#define read_inferior_memory(memaddr,myaddr,len) \
|
||||
(*the_target->read_memory) (memaddr, myaddr, len)
|
||||
void read_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len);
|
||||
|
||||
#define write_inferior_memory(memaddr,myaddr,len) \
|
||||
(*the_target->write_memory) (memaddr, myaddr, len)
|
||||
int write_inferior_memory (CORE_ADDR memaddr, char *myaddr, int len);
|
||||
|
||||
#endif /* TARGET_H */
|
||||
|
Loading…
Reference in New Issue
Block a user