summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@codesourcery.com>2006-03-31 15:35:33 +0000
committerNathan Sidwell <nathan@codesourcery.com>2006-03-31 15:35:33 +0000
commit2c99eb21bce8f26926561e927b4285dbf406c919 (patch)
treecb7d77e5032307d165bca6faee693fdf2aa1f281
parentf18141ab3d3277ce865bff08f0066d980557e4e1 (diff)
downloadgdb-2c99eb21bce8f26926561e927b4285dbf406c919.tar.gz
* gdb/gdbserver/Makefile.in (reg-cf.o, reg-cf.c): New targets.
* gdb/gdbserver/configure.srv (m68k*-*-uclinux*): New target. * gdb/gdbserver/linux-low.c (linux_create_inferior): Use vfork on mmuless systems. (linux_resume_one_process): Remove extraneous cast. (linux_read_offsets): New. (linux_target_op): Add linux_read_offsets on mmuless systems. * gdb/gdbserver/server.c (handle_query): Add qOffsets logic. * gdb/gdbserver/target.h (struct target_ops): Add read_offsets.
-rw-r--r--ChangeLog.csl12
-rw-r--r--gdb/gdbserver/Makefile.in3
-rw-r--r--gdb/gdbserver/configure.srv8
-rw-r--r--gdb/gdbserver/linux-low.c56
-rw-r--r--gdb/gdbserver/server.c14
-rw-r--r--gdb/gdbserver/target.h5
-rw-r--r--gdb/regformats/reg-cf.dat33
7 files changed, 130 insertions, 1 deletions
diff --git a/ChangeLog.csl b/ChangeLog.csl
index 7abedbfbb15..0e1e069e99b 100644
--- a/ChangeLog.csl
+++ b/ChangeLog.csl
@@ -1,3 +1,15 @@
+2006-03-31 Nathan Sidwell <nathan@codesourcery.com>
+
+ * gdb/gdbserver/Makefile.in (reg-cf.o, reg-cf.c): New targets.
+ * gdb/gdbserver/configure.srv (m68k*-*-uclinux*): New target.
+ * gdb/gdbserver/linux-low.c (linux_create_inferior): Use vfork on
+ mmuless systems.
+ (linux_resume_one_process): Remove extraneous cast.
+ (linux_read_offsets): New.
+ (linux_target_op): Add linux_read_offsets on mmuless systems.
+ * gdb/gdbserver/server.c (handle_query): Add qOffsets logic.
+ * gdb/gdbserver/target.h (struct target_ops): Add read_offsets.
+
2006-03-30 Mark Mitchell <mark@codesourcery.com>
* libiberty/configure.ac: Add cygpath for mingw hosts.
diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in
index 0da5f6cde68..d13e465bc2c 100644
--- a/gdb/gdbserver/Makefile.in
+++ b/gdb/gdbserver/Makefile.in
@@ -309,6 +309,9 @@ reg-m32r.c : $(srcdir)/../regformats/reg-m32r.dat $(regdat_sh)
reg-m68k.o : reg-m68k.c $(regdef_h)
reg-m68k.c : $(srcdir)/../regformats/reg-m68k.dat $(regdat_sh)
sh $(regdat_sh) $(srcdir)/../regformats/reg-m68k.dat reg-m68k.c
+reg-cf.o : reg-cf.c $(regdef_h)
+reg-cf.c : $(srcdir)/../regformats/reg-cf.dat $(regdat_sh)
+ sh $(regdat_sh) $(srcdir)/../regformats/reg-cf.dat reg-cf.c
reg-mips.o : reg-mips.c $(regdef_h)
reg-mips.c : $(srcdir)/../regformats/reg-mips.dat $(regdat_sh)
sh $(regdat_sh) $(srcdir)/../regformats/reg-mips.dat reg-mips.c
diff --git a/gdb/gdbserver/configure.srv b/gdb/gdbserver/configure.srv
index e2d52c09e75..5249c6a6783 100644
--- a/gdb/gdbserver/configure.srv
+++ b/gdb/gdbserver/configure.srv
@@ -54,6 +54,14 @@ case "${target}" in
srv_linux_regsets=yes
srv_linux_thread_db=yes
;;
+ m68*-*-uclinux*) # FIXME, we really need a way of distinguishing
+ srv_regobj=reg-cf.o
+ srv_tgtobj="linux-low.o linux-m68k-low.o"
+ srv_linux_usrregs=yes
+ srv_linux_regsets=yes
+ srv_linux_thread_db=yes
+ LDFLAGS=-elf2flt
+ ;;
mips*-*-linux*) srv_regobj=reg-mips.o
srv_tgtobj="linux-low.o linux-mips-low.o"
srv_linux_usrregs=yes
diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index 8518484fa76..c570e73bd02 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -140,7 +140,11 @@ linux_create_inferior (char *program, char **allargs)
void *new_process;
int pid;
+#if defined(__UCLIBC__) && !defined(__UCLIBC_HAS_MMU__)
+ pid = vfork ();
+#else
pid = fork ();
+#endif
if (pid < 0)
perror_with_name ("fork");
@@ -896,7 +900,7 @@ linux_resume_one_process (struct inferior_list_entry *entry,
if (debug_threads && the_low_target.get_pc != NULL)
{
fprintf (stderr, " ");
- (long) (*the_low_target.get_pc) ();
+ (*the_low_target.get_pc) ();
}
/* If we have pending signals, consume one unless we are trying to reinsert
@@ -1550,6 +1554,53 @@ linux_stopped_data_address (void)
return 0;
}
+#if defined(__UCLIBC__) && !defined(__UCLIBC_HAS_MMU__)
+#if defined(__mcoldfire__)
+/* These should really be defined in the kernel's ptrace.h header. */
+#define PT_TEXT_ADDR 49*4
+#define PT_DATA_ADDR 50*4
+#define PT_TEXT_END_ADDR 51*4
+#endif
+
+/* Under uClinux, programs are loaded at non-zero offsets, which we need
+ to tell gdb about. */
+
+static int
+linux_read_offsets (CORE_ADDR *text_p, CORE_ADDR *data_p)
+{
+#if defined(PT_TEXT_ADDR) && defined(PT_DATA_ADDR) && defined(PT_TEXT_END_ADDR)
+ unsigned long text, text_end, data;
+ int pid = get_thread_process (current_inferior)->head.id;
+
+ errno = 0;
+
+ text = ptrace (PTRACE_PEEKUSER, pid, (long)PT_TEXT_ADDR, 0);
+ text_end = ptrace (PTRACE_PEEKUSER, pid, (long)PT_TEXT_END_ADDR, 0);
+ data = ptrace (PTRACE_PEEKUSER, pid, (long)PT_DATA_ADDR, 0);
+
+ if (errno == 0)
+ {
+ /* Both text and data offsets produced at compile-time (and so
+ used by gdb) are relative to the beginning of the program,
+ with the data segment immediately following the text segment.
+ However, the actual runtime layout in memory may put the data
+ somewhere else, so when we send gdb a data base-address, we
+ use the real data base address and subtract the compile-time
+ data base-address from it (which is just the length of the
+ text segment). BSS immediately follows data in both
+ cases. */
+ printf ("%lx, %lx, %lx\n", text, text_end, data);
+
+ *text_p = text;
+ *data_p = data - (text_end - text);
+
+ return 1;
+ }
+#endif
+ return 0;
+}
+#endif
+
static struct target_ops linux_target_ops = {
linux_create_inferior,
linux_attach,
@@ -1569,6 +1620,9 @@ static struct target_ops linux_target_ops = {
linux_remove_watchpoint,
linux_stopped_by_watchpoint,
linux_stopped_data_address,
+#if defined(__UCLIBC__) && !defined(__UCLIBC_HAS_MMU__)
+ linux_read_offsets,
+#endif
};
static void
diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
index 0722e5996ef..51b87642a83 100644
--- a/gdb/gdbserver/server.c
+++ b/gdb/gdbserver/server.c
@@ -129,6 +129,20 @@ handle_query (char *own_buf)
}
}
+ if (the_target->read_offsets != NULL
+ && strcmp ("qOffsets", own_buf) == 0)
+ {
+ CORE_ADDR text, data;
+
+ if (the_target->read_offsets (&text, &data))
+ sprintf (own_buf, "Text=%lX;Data=%lX;Bss=%lX",
+ (long)text, (long)data, (long)data);
+ else
+ write_enn (own_buf);
+
+ return;
+ }
+
if (the_target->read_auxv != NULL
&& strncmp ("qPart:auxv:read::", own_buf, 17) == 0)
{
diff --git a/gdb/gdbserver/target.h b/gdb/gdbserver/target.h
index 7f65d3dbe4a..6c9a4d7baa5 100644
--- a/gdb/gdbserver/target.h
+++ b/gdb/gdbserver/target.h
@@ -156,6 +156,11 @@ struct target_ops
CORE_ADDR (*stopped_data_address) (void);
+ /* Reports the text, data offsets of the executable. This is
+ needed for uclinux where the executable is relocated during load
+ time. */
+
+ int (*read_offsets) (CORE_ADDR *text, CORE_ADDR *data);
};
extern struct target_ops *the_target;
diff --git a/gdb/regformats/reg-cf.dat b/gdb/regformats/reg-cf.dat
new file mode 100644
index 00000000000..068aa755564
--- /dev/null
+++ b/gdb/regformats/reg-cf.dat
@@ -0,0 +1,33 @@
+name:m68k
+expedite:sp,fp,pc
+32:d0
+32:d1
+32:d2
+32:d3
+32:d4
+32:d5
+32:d6
+32:d7
+32:a0
+32:a1
+32:a2
+32:a3
+32:a4
+32:a5
+32:fp
+32:sp
+32:ps
+32:pc
+
+64:fp0
+64:fp1
+64:fp2
+64:fp3
+64:fp4
+64:fp5
+64:fp6
+64:fp7
+
+32:fpcontrol
+32:fpstatus
+32:fpiaddr