2006-05-08 Nathan Sidwell * 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 * linux-mips-low.c: Include 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;