gdbserver for m68k-uclinux

Nathan Sidwell
2006-05-08T14:16:51Z

[-- Attachment #1: Type: text/plain, Size: 660 bytes --]

This patch implements the necessary qOffsets logic tso that a uclinux hosted
gdbserver can tell a remote gdb what the text & data offsets are. It also uses
vfork on such systems.

This implementation clearly separates the gdb protocol pieces of qOffsets from
the system specific pieces of determining the offsets. The original diff I
found on the uclinux site did not have such a separation, I used that
implementation for inspiration.

Tested on a m5208evb hosted uclinux system.

ok?

nathan
--
Nathan Sidwell :: http://www.codesourcery.com :: CodeSourcery
nathan@codesourcery.com :: http://www.planetfall.pwp.blueyonder.co.uk

[-- Attachment #2: all.diff --]
[-- Type: text/plain, Size: 6140 bytes --]

2006-05-08 Nathan Sidwell <nathan@codesourcery.com>

* configure.srv (m68k*-*-uclinux*): New target.
* 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.
* server.c (handle_query): Add qOffsets logic.
* target.h (struct target_ops): Add read_offsets.

2006-03-15 Daniel Jacobowitz <dan@codesourcery.com>

* linux-mips-low.c: Include <sys/ptrace.h> and "gdb_proc_service.h".
Index: gdbserver/configure.srv
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/configure.srv,v
retrieving revision 1.13
diff -c -3 -p -r1.13 configure.srv
*** gdbserver/configure.srv 2 Nov 2005 19:54:44 -0000 1.13
--- gdbserver/configure.srv 8 May 2006 14:07:50 -0000
*************** case "${target}" in
*** 54,59 ****
--- 54,66 ----
srv_linux_regsets=yes
srv_linux_thread_db=yes
;;
+ m68*-*-uclinux*) srv_regobj=reg-m68k.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
Index: gdbserver/linux-low.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/linux-low.c,v
retrieving revision 1.43
diff -c -3 -p -r1.43 linux-low.c
*** gdbserver/linux-low.c 15 Feb 2006 14:36:32 -0000 1.43
--- gdbserver/linux-low.c 8 May 2006 14:07:51 -0000
*************** linux_create_inferior (char *program, ch
*** 140,146 ****
--- 140,150 ----
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");

*************** linux_resume_one_process (struct inferio
*** 896,902 ****
if (debug_threads && the_low_target.get_pc != NULL)
{
fprintf (stderr, " ");
! (long) (*the_low_target.get_pc) ();
}

/* If we have pending signals, consume one unless we are trying to reinsert
--- 900,906 ----
if (debug_threads && the_low_target.get_pc != NULL)
{
fprintf (stderr, " ");
! (*the_low_target.get_pc) ();
}

/* If we have pending signals, consume one unless we are trying to reinsert
*************** linux_stopped_data_address (void)
*** 1550,1555 ****
--- 1554,1604 ----
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. */
+ *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,
*************** static struct target_ops linux_target_op
*** 1569,1574 ****
--- 1618,1626 ----
linux_remove_watchpoint,
linux_stopped_by_watchpoint,
linux_stopped_data_address,
+ #if defined(__UCLIBC__) && !defined(__UCLIBC_HAS_MMU__)
+ linux_read_offsets,
+ #endif
};

static void
Index: gdbserver/server.c
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/server.c,v
retrieving revision 1.32
diff -c -3 -p -r1.32 server.c
*** gdbserver/server.c 8 Feb 2006 20:26:44 -0000 1.32
--- gdbserver/server.c 8 May 2006 14:07:52 -0000
*************** handle_query (char *own_buf)
*** 129,134 ****
--- 129,148 ----
}
}

+ 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)
{
Index: gdbserver/target.h
===================================================================
RCS file: /cvs/src/src/gdb/gdbserver/target.h,v
retrieving revision 1.15
diff -c -3 -p -r1.15 target.h
*** gdbserver/target.h 23 Dec 2005 18:11:55 -0000 1.15
--- gdbserver/target.h 8 May 2006 14:07:52 -0000
*************** struct target_ops
*** 156,161 ****
--- 156,166 ----

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;