From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 18299 invoked by alias); 7 Feb 2003 23:15:05 -0000 Mailing-List: contact rda-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Post: List-Help: , Sender: rda-owner@sources.redhat.com Received: (qmail 18270 invoked from network); 7 Feb 2003 23:15:04 -0000 Date: Fri, 07 Feb 2003 23:15:00 -0000 From: Kevin Buettner Message-Id: <1030207231457.ZM16139@localhost.localdomain> X-Mailer: Z-Mail (4.0.1 13Jan97 Caldera) To: rda@sources.redhat.com Subject: [PATCH] Fix single step for n32, n64 mips/linux targets MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-SW-Source: 2003-q1/txt/msg00018.txt.bz2 I've just committed the patch below. I recently discovered that rda's single step support for mips/linux targets using the n32 and n64 ABIs was quite broken. This was due to the following: - For threaded programs, rda was attempting to invoke the PTRACE_SINGLESTEP operation even though there's no support for this in the kernel. - For non-threaded programs, the existing mips singlestep code was getting called, but it was not working correctly due to the fact that the ptrace transfer size for mips64 targets is 64-bits whereas the instruction size is only 32-bits. I noticed in the course of debugging these issues that gdb wasn't fetching s0 or s1 for multithreaded programs, but that it was correctly fetching them for singlethreaded programs. It turns out that I had made some mistakes in constructing the table which describes the layout of the registers in the gregset. (I also noticed that the values corresponding to fpregset offsets and sizes was wrong.) I've included these adjustments in the patch below too. 2003-02-07 Kevin Buettner * gdbserv-thread-db.h (singlestep_lwp): Add ``struct gdbserv *'' argument. Adjust all callers. (mips_singlestep) [MIPS_LINUX_TARGET, MIPS64_LINUX_TARGET]: New function. * linux-target.c (reginfo) [MIPS64_LINUX_TARGET]: Adjust some of the fpregset/gregset related constants in this table. (mips_get_reg): Add ``struct gdbserv *'' argument. Adjust all callers. (mips_addr_as_reg, mips_peek_instruction, mips_poke_instruction): New functions. (mips_singlestep_program): Move bulk of implementation to and call... (mips_singlestep): ...new function. This new function no longer makes any direct PTRACE_PEEKTEXT or PTRACE_POKETEXT operations. Shadow breakpoint information is also stored in a slightly different format. * ptrace-target.c (server.h, ptrace-target.h): Adjust location of #include statements so that gdbserv.h is included first. (handle_waitstatus): Call ptrace_set_mem() instead of invoking ptrace() directly. Also adjust code to use somewhat different shadow breakpoint structs. (ptrace_set_mem, ptrace_get_mem): Remove ``static'' qualifier from function declarators. (singlestep_lwp): Add ``struct gdbserv *'' argument. * ptrace-target.h (ptrace_get_mem, ptrace_set_mem): Declare. * server.c (gdbserv.h): Include. * server.h (struct ss_save): Add field ``in_use''. Change type of field ``ss_addr'' to struct ``gdbserv_reg''. * thread-db.c (wait_all_threads): Revise diagnostic message to print signal number for SIGDEBUG signal. (singlestep_thread): Add ``struct gdbserv *'' argument. Adjust all callers. Index: gdbserv-thread-db.h =================================================================== RCS file: /cvs/src/src/rda/unix/gdbserv-thread-db.h,v retrieving revision 1.1 diff -u -p -r1.1 gdbserv-thread-db.h --- gdbserv-thread-db.h 28 Aug 2002 01:22:28 -0000 1.1 +++ gdbserv-thread-db.h 7 Feb 2003 23:01:50 -0000 @@ -87,7 +87,12 @@ extern int reg_from_xregset (struct gdbs extern int continue_lwp (lwpid_t lid, int signal); /* Step a stopped LWP. */ -extern int singlestep_lwp (lwpid_t lid, int signal); +extern int singlestep_lwp (struct gdbserv *serv, lwpid_t lid, int signal); + +/* Software singlestep for mips. */ +#if defined (MIPS_LINUX_TARGET) || defined (MIPS64_LINUX_TARGET) +extern int mips_singlestep (struct gdbserv *serv, pid_t pid, int sig); +#endif /* Attach an LWP. */ extern int attach_lwp (lwpid_t lid); Index: linux-target.c =================================================================== RCS file: /cvs/src/src/rda/unix/linux-target.c,v retrieving revision 1.4 diff -u -p -r1.4 linux-target.c --- linux-target.c 23 Jan 2003 06:40:07 -0000 1.4 +++ linux-target.c 7 Feb 2003 23:01:50 -0000 @@ -582,8 +582,8 @@ static struct peekuser_pokeuser_reginfo { 30, 8, GREGS, 30 * 8, 8, 8 }, /* s8/fp */ { 31, 8, GREGS, 31 * 8, 8, 8 }, /* ra */ { 0, 8, NOREGS, 0, 8, 8 }, /* sr */ - { 68, 8, GREGS, 33 * 4, 8, 8 }, /* lo */ - { 67, 8, GREGS, 32 * 4, 8, 8 }, /* hi */ + { 68, 8, GREGS, 33 * 8, 8, 8 }, /* lo */ + { 67, 8, GREGS, 32 * 8, 8, 8 }, /* hi */ /* glibc's ucontext.h doesn't specify the order of the following three registerss. But there is space allocated for them. (Well, @@ -595,13 +595,13 @@ static struct peekuser_pokeuser_reginfo #if 0 /* CAUSE and BADVADDR are readable via ptrace, but they're not writable. */ - { 66, 8, GREGS, 35 * 4, 8, 8 }, /* bad */ - { 65, 8, GREGS, 36 * 4, 8, 8 }, /* cause */ + { 66, 8, GREGS, 35 * 8, 8, 8 }, /* bad */ + { 65, 8, GREGS, 36 * 8, 8, 8 }, /* cause */ #else { 0, 8, NOREGS, 0, 8, 8 }, /* bad */ { 0, 8, NOREGS, 0, 8, 8 }, /* cause */ #endif - { 64, 8, GREGS, 34 * 4, 8, 8 }, /* pc */ + { 64, 8, GREGS, 34 * 8, 8, 8 }, /* pc */ /* Linux/MIPS floating point is a bit of a mess. On the one hand, the elf_fpregset_t contains space for 32 doubles plus the control @@ -610,39 +610,39 @@ static struct peekuser_pokeuser_reginfo 16 double precision floats via ptrace(). It also means that only slightly more than half of elf_fpregset_t is unused. */ - { 32 + 0, 8, FPREGS, 0 * 4, 8, 8 }, /* $f0 */ - { 32 + 1, 8, FPREGS, 1 * 4, 8, 8 }, /* $f1 */ - { 32 + 2, 8, FPREGS, 2 * 4, 8, 8 }, /* $f2 */ - { 32 + 3, 8, FPREGS, 3 * 4, 8, 8 }, /* $f3 */ - { 32 + 4, 8, FPREGS, 4 * 4, 8, 8 }, /* $f4 */ - { 32 + 5, 8, FPREGS, 5 * 4, 8, 8 }, /* $f5 */ - { 32 + 6, 8, FPREGS, 6 * 4, 8, 8 }, /* $f6 */ - { 32 + 7, 8, FPREGS, 7 * 4, 8, 8 }, /* $f7 */ - { 32 + 8, 8, FPREGS, 8 * 4, 8, 8 }, /* $f8 */ - { 32 + 9, 8, FPREGS, 9 * 4, 8, 8 }, /* $f9 */ - { 32 + 10, 8, FPREGS, 10 * 4, 8, 8 }, /* $f10 */ - { 32 + 11, 8, FPREGS, 11 * 4, 8, 8 }, /* $f11 */ - { 32 + 12, 8, FPREGS, 12 * 4, 8, 8 }, /* $f12 */ - { 32 + 13, 8, FPREGS, 13 * 4, 8, 8 }, /* $f13 */ - { 32 + 14, 8, FPREGS, 14 * 4, 8, 8 }, /* $f14 */ - { 32 + 15, 8, FPREGS, 15 * 4, 8, 8 }, /* $f15 */ - { 32 + 16, 8, FPREGS, 16 * 4, 8, 8 }, /* $f16 */ - { 32 + 17, 8, FPREGS, 17 * 4, 8, 8 }, /* $f17 */ - { 32 + 18, 8, FPREGS, 18 * 4, 8, 8 }, /* $f18 */ - { 32 + 19, 8, FPREGS, 19 * 4, 8, 8 }, /* $f19 */ - { 32 + 20, 8, FPREGS, 20 * 4, 8, 8 }, /* $f20 */ - { 32 + 21, 8, FPREGS, 21 * 4, 8, 8 }, /* $f21 */ - { 32 + 22, 8, FPREGS, 22 * 4, 8, 8 }, /* $f22 */ - { 32 + 23, 8, FPREGS, 23 * 4, 8, 8 }, /* $f23 */ - { 32 + 24, 8, FPREGS, 24 * 4, 8, 8 }, /* $f24 */ - { 32 + 25, 8, FPREGS, 25 * 4, 8, 8 }, /* $f25 */ - { 32 + 26, 8, FPREGS, 26 * 4, 8, 8 }, /* $f26 */ - { 32 + 27, 8, FPREGS, 27 * 4, 8, 8 }, /* $f27 */ - { 32 + 28, 8, FPREGS, 28 * 4, 8, 8 }, /* $f28 */ - { 32 + 29, 8, FPREGS, 29 * 4, 8, 8 }, /* $f29 */ - { 32 + 30, 8, FPREGS, 30 * 4, 8, 8 }, /* $f30 */ - { 32 + 31, 8, FPREGS, 31 * 4, 8, 8 }, /* $f31 */ - { 69, 8, FPREGS, 64 * 4, 8, 8 } /* fsr */ + { 32 + 0, 8, FPREGS, 0 * 8, 8, 8 }, /* $f0 */ + { 32 + 1, 8, FPREGS, 1 * 8, 8, 8 }, /* $f1 */ + { 32 + 2, 8, FPREGS, 2 * 8, 8, 8 }, /* $f2 */ + { 32 + 3, 8, FPREGS, 3 * 8, 8, 8 }, /* $f3 */ + { 32 + 4, 8, FPREGS, 4 * 8, 8, 8 }, /* $f4 */ + { 32 + 5, 8, FPREGS, 5 * 8, 8, 8 }, /* $f5 */ + { 32 + 6, 8, FPREGS, 6 * 8, 8, 8 }, /* $f6 */ + { 32 + 7, 8, FPREGS, 7 * 8, 8, 8 }, /* $f7 */ + { 32 + 8, 8, FPREGS, 8 * 8, 8, 8 }, /* $f8 */ + { 32 + 9, 8, FPREGS, 9 * 8, 8, 8 }, /* $f9 */ + { 32 + 10, 8, FPREGS, 10 * 8, 8, 8 }, /* $f10 */ + { 32 + 11, 8, FPREGS, 11 * 8, 8, 8 }, /* $f11 */ + { 32 + 12, 8, FPREGS, 12 * 8, 8, 8 }, /* $f12 */ + { 32 + 13, 8, FPREGS, 13 * 8, 8, 8 }, /* $f13 */ + { 32 + 14, 8, FPREGS, 14 * 8, 8, 8 }, /* $f14 */ + { 32 + 15, 8, FPREGS, 15 * 8, 8, 8 }, /* $f15 */ + { 32 + 16, 8, FPREGS, 16 * 8, 8, 8 }, /* $f16 */ + { 32 + 17, 8, FPREGS, 17 * 8, 8, 8 }, /* $f17 */ + { 32 + 18, 8, FPREGS, 18 * 8, 8, 8 }, /* $f18 */ + { 32 + 19, 8, FPREGS, 19 * 8, 8, 8 }, /* $f19 */ + { 32 + 20, 8, FPREGS, 20 * 8, 8, 8 }, /* $f20 */ + { 32 + 21, 8, FPREGS, 21 * 8, 8, 8 }, /* $f21 */ + { 32 + 22, 8, FPREGS, 22 * 8, 8, 8 }, /* $f22 */ + { 32 + 23, 8, FPREGS, 23 * 8, 8, 8 }, /* $f23 */ + { 32 + 24, 8, FPREGS, 24 * 8, 8, 8 }, /* $f24 */ + { 32 + 25, 8, FPREGS, 25 * 8, 8, 8 }, /* $f25 */ + { 32 + 26, 8, FPREGS, 26 * 8, 8, 8 }, /* $f26 */ + { 32 + 27, 8, FPREGS, 27 * 8, 8, 8 }, /* $f27 */ + { 32 + 28, 8, FPREGS, 28 * 8, 8, 8 }, /* $f28 */ + { 32 + 29, 8, FPREGS, 29 * 8, 8, 8 }, /* $f29 */ + { 32 + 30, 8, FPREGS, 30 * 8, 8, 8 }, /* $f30 */ + { 32 + 31, 8, FPREGS, 31 * 8, 8, 8 }, /* $f31 */ + { 69, 4, FPREGS, 32 * 8, 4, 8 } /* fsr */ }; static void mips_singlestep_program (struct gdbserv *serv); @@ -2504,11 +2504,9 @@ decr_pc_after_break (struct gdbserv *ser */ static ptrace_xfer_type -mips_get_reg(struct gdbserv *serv, int regno) +mips_get_reg(struct gdbserv *serv, int pid, int regno) { ptrace_xfer_type value; - struct child_process *process = gdbserv_target_data (serv); - pid_t pid = process->pid; if (read_reg_bytes (serv, pid, regno, &value) < 0) return 0; @@ -2516,41 +2514,84 @@ mips_get_reg(struct gdbserv *serv, int r return value; } +static struct gdbserv_reg +mips_addr_as_reg (struct gdbserv *serv, ptrace_arg3_type addr) +{ + struct gdbserv_reg addr_as_reg; + + gdbserv_host_bytes_to_reg (serv, &addr, sizeof (addr), + &addr_as_reg, sizeof (ptrace_arg3_type), + sign_extend); + return addr_as_reg; +} + +/* peek / poke mips instructions. Using an ``unsigned int'' to represent + a mips instruction is correct (with regard to size) for the o32, n32, + and n64 ABIs. */ +static unsigned int +mips_peek_instruction (struct gdbserv *serv, ptrace_arg3_type addr) +{ + struct gdbserv_reg addr_as_reg; + unsigned int insn; + + addr_as_reg = mips_addr_as_reg (serv, addr); + ptrace_get_mem (serv, &addr_as_reg, &insn, sizeof (insn)); + return insn; +} + +static void +mips_poke_instruction (struct gdbserv *serv, ptrace_arg3_type addr, + unsigned int insn) +{ + struct gdbserv_reg addr_as_reg; + + addr_as_reg = mips_addr_as_reg (serv, addr); + ptrace_set_mem (serv, &addr_as_reg, &insn, sizeof (insn)); +} + /* * mips singlestep * * necessary since no support in ptrace. */ - static void mips_singlestep_program (struct gdbserv *serv) { struct child_process *process = gdbserv_target_data (serv); + + mips_singlestep (serv, process->pid, process->signal_to_send); + process->stop_signal = 0; + process->stop_status = 0; + process->signal_to_send = 0; +} + +int +mips_singlestep (struct gdbserv *serv, pid_t pid, int sig) +{ + struct child_process *process = gdbserv_target_data (serv); ptrace_arg3_type targ; ptrace_xfer_type mips_pc; union mips_instruction insn; int is_branch, is_cond, i; - ptrace_xfer_type bp_inst = 0x0000000d; + unsigned int bp_inst = 0x0000000d; /* FIXME: handle signals! */ if (process->debug_backend) - fprintf (stderr, "mips_singlestep_program %ld\n", process->signal_to_send); - process->stop_signal = 0; - process->stop_status = 0; + fprintf (stderr, "mips_singlestep %d %ld\n", pid, sig); errno = 0; - /* Following is equiv to ptrace (PTRACE_SINGLESTEP, process->pid, 1L, process->signal_to_send); */ + /* Following is equiv to ptrace (PTRACE_SINGLESTEP, pid, 1L, sig); */ /* get the current PC */ - mips_pc = mips_get_reg(serv, PC_REGNUM); + mips_pc = mips_get_reg(serv, pid, PC_REGNUM); targ = mips_pc; /* get the word there (opcode) */ - insn.word = ptrace (PTRACE_PEEKTEXT, process->pid, mips_pc, 0L); + insn.word = mips_peek_instruction (serv, mips_pc); is_branch = is_cond = 0; @@ -2565,7 +2606,7 @@ mips_singlestep_program (struct gdbserv switch (insn.r_format.func) { case jalr_op: case jr_op: - targ = mips_get_reg(serv, insn.r_format.rs); + targ = mips_get_reg(serv, pid, insn.r_format.rs); is_branch = 1; break; } @@ -2613,25 +2654,33 @@ mips_singlestep_program (struct gdbserv break; } - if (is_branch) { - i = 0; - if (is_cond && targ != (mips_pc + 8)) { - process->ss_info[i].ss_addr = mips_pc + 8; - process->ss_info[i++].ss_val = ptrace (PTRACE_PEEKTEXT, process->pid, mips_pc+8, 0L); - ptrace (PTRACE_POKETEXT, process->pid, mips_pc+8, bp_inst); - } - process->ss_info[i].ss_addr = targ; - process->ss_info[i].ss_val = ptrace (PTRACE_PEEKTEXT, process->pid, targ, 0L); - ptrace (PTRACE_POKETEXT, process->pid, targ, bp_inst); - } else { - process->ss_info[0].ss_addr = mips_pc + 4; - process->ss_info[0].ss_val = ptrace (PTRACE_PEEKTEXT, process->pid, mips_pc+4, 0L); - process->ss_info[1].ss_addr = 0; - ptrace (PTRACE_POKETEXT, process->pid, mips_pc+4, bp_inst); - } + process->ss_info[1].in_use = 0; /* Mark unused. */ + if (is_branch) + { + i = 0; + if (is_cond && targ != (mips_pc + 8)) + { + process->ss_info[i].in_use = 1; + process->ss_info[i].ss_addr = mips_addr_as_reg (serv, mips_pc + 8); + process->ss_info[i++].ss_val + = mips_peek_instruction (serv, mips_pc + 8); + mips_poke_instruction (serv, mips_pc + 8, bp_inst); + } + process->ss_info[i].in_use = 1; + process->ss_info[i].ss_addr = mips_addr_as_reg (serv, targ); + process->ss_info[i].ss_val = mips_peek_instruction (serv, targ); + mips_poke_instruction (serv, targ, bp_inst); + } + else + { + process->ss_info[0].in_use = 1; + process->ss_info[0].ss_addr = mips_addr_as_reg (serv, mips_pc + 4); + process->ss_info[0].ss_val = mips_peek_instruction (serv, mips_pc + 4); + mips_poke_instruction (serv, mips_pc + 4, bp_inst); + } - process->signal_to_send = 0; - ptrace (PTRACE_CONT, process->pid, 1L, process->signal_to_send); + ptrace (PTRACE_CONT, pid, 1L, sig); + return 0; } #endif /* _MIPSEL */ Index: ptrace-target.c =================================================================== RCS file: /cvs/src/src/rda/unix/ptrace-target.c,v retrieving revision 1.3 diff -u -p -r1.3 ptrace-target.c --- ptrace-target.c 18 Dec 2002 20:25:11 -0000 1.3 +++ ptrace-target.c 7 Feb 2003 23:01:50 -0000 @@ -28,9 +28,6 @@ #include #include -#include "server.h" -#include "ptrace-target.h" - #include #include #include @@ -43,6 +40,8 @@ #include "gdb_proc_service.h" #include "gdbserv-thread-db.h" +#include "server.h" +#include "ptrace-target.h" /* This is unix ptrace gdbserv target that uses the RDA library to implement a remote gdbserver on a unix ptrace host. It controls the process to be debugged on the linux host, allowing GDB to pull the strings @@ -149,13 +148,16 @@ handle_waitstatus (struct child_process */ if (process->is_ss) { - ptrace (PTRACE_POKETEXT, process->pid, process->ss_info[0].ss_addr, process->ss_info[0].ss_val); - process->ss_info[0].ss_addr = 0; - - if (process->ss_info[1].ss_addr) { - ptrace (PTRACE_POKETEXT, process->pid, process->ss_info[1].ss_addr, process->ss_info[1].ss_val); - process->ss_info[1].ss_addr = 0; - } + int i; + for (i = 0; i < 2; i++) + if (process->ss_info[i].in_use) + { + ptrace_set_mem (process->serv, + &process->ss_info[i].ss_addr, + &process->ss_info[i].ss_val, + sizeof (process->ss_info[i].ss_val)); + process->ss_info[i].in_use = 0; + } process->is_ss = 0; } #endif /* _MIPSEL */ @@ -1083,7 +1085,7 @@ ptrace_xfer_mem (struct gdbserv *serv, return len; } -static long +long ptrace_set_mem (struct gdbserv *serv, struct gdbserv_reg *addr, void *data, @@ -1092,7 +1094,7 @@ ptrace_set_mem (struct gdbserv *serv, return ptrace_xfer_mem (serv, addr, data, len, 0); } -static long +long ptrace_get_mem (struct gdbserv *serv, struct gdbserv_reg *addr, void *data, @@ -1269,9 +1271,18 @@ continue_lwp (lwpid_t lwpid, int signal) Send PTRACE_SINGLESTEP to an lwp. Returns -1 for failure, zero for success. */ -extern int -singlestep_lwp (lwpid_t lwpid, int signal) +int +singlestep_lwp (struct gdbserv *serv, lwpid_t lwpid, int signal) { + +#if defined (MIPS_LINUX_TARGET) || defined (MIPS64_LINUX_TARGET) + { + if (thread_db_noisy) + fprintf (stderr, "\n", lwpid, signal); + mips_singlestep (serv, lwpid, signal); + return 0; + } +#else if (thread_db_noisy) fprintf (stderr, "\n", lwpid, signal); @@ -1280,6 +1291,7 @@ singlestep_lwp (lwpid_t lwpid, int signa fprintf (stderr, "<<< ERROR: PTRACE_SINGLESTEP %d failed >>>\n", lwpid); return -1; } +#endif return 0; } Index: ptrace-target.h =================================================================== RCS file: /cvs/src/src/rda/unix/ptrace-target.h,v retrieving revision 1.2 diff -u -p -r1.2 ptrace-target.h --- ptrace-target.h 18 Dec 2002 20:25:11 -0000 1.2 +++ ptrace-target.h 7 Feb 2003 23:01:50 -0000 @@ -78,3 +78,5 @@ int ptrace_set_fpregs (struct gdbserv *s int ptrace_get_fpxregs (struct gdbserv *serv, int alt_pid, void *buff); int ptrace_set_fpxregs (struct gdbserv *serv, int alt_pid, const void *buff); int ptrace_check_child_state (struct child_process *process); +long ptrace_set_mem (struct gdbserv *serv, struct gdbserv_reg *addr, void *data, long len); +long ptrace_get_mem (struct gdbserv *serv, struct gdbserv_reg *addr, void *data, long len); Index: server.c =================================================================== RCS file: /cvs/src/src/rda/unix/server.c,v retrieving revision 1.1 diff -u -p -r1.1 server.c --- server.c 28 Aug 2002 01:22:28 -0000 1.1 +++ server.c 7 Feb 2003 23:01:51 -0000 @@ -32,6 +32,7 @@ #include "gdbsocket.h" #include "gdbloop.h" +#include "gdbserv.h" #include "server.h" /* Signal a request to terminate main loop. */ Index: server.h =================================================================== RCS file: /cvs/src/src/rda/unix/server.h,v retrieving revision 1.1 diff -u -p -r1.1 server.h --- server.h 28 Aug 2002 01:22:28 -0000 1.1 +++ server.h 7 Feb 2003 23:01:51 -0000 @@ -33,7 +33,8 @@ */ struct ss_save { - unsigned int ss_addr; + int in_use; + struct gdbserv_reg ss_addr; unsigned int ss_val; }; #endif Index: thread-db.c =================================================================== RCS file: /cvs/src/src/rda/unix/thread-db.c,v retrieving revision 1.1 diff -u -p -r1.1 thread-db.c --- thread-db.c 28 Aug 2002 01:22:28 -0000 1.1 +++ thread-db.c 7 Feb 2003 23:01:51 -0000 @@ -1520,7 +1520,8 @@ wait_all_threads (struct child_process * { /* This signal does not need to be forwarded. */ if (thread_db_noisy) - fprintf (stderr, "\n", + fprintf (stderr, "\n", + debug_signal, thread->ti.ti_lid); } else @@ -1617,9 +1618,11 @@ thread_db_continue_program (struct gdbse Send SINGLESTEP to a struct gdbserv_thread. */ static void -singlestep_thread (struct gdbserv_thread *thread, int signal) +singlestep_thread (struct gdbserv *serv, + struct gdbserv_thread *thread, + int signal) { - singlestep_lwp (thread->ti.ti_lid, signal); + singlestep_lwp (serv, thread->ti.ti_lid, signal); thread->stopped = thread->attached = thread->waited = 0; thread->stepping = 1; } @@ -1638,9 +1641,9 @@ thread_db_singlestep_program (struct gdb /* First singlestep the event thread. */ if (process->event_thread) - singlestep_thread (process->event_thread, process->signal_to_send); + singlestep_thread (serv, process->event_thread, process->signal_to_send); else - singlestep_lwp (process->pid, process->signal_to_send); + singlestep_lwp (serv, process->pid, process->signal_to_send); process->stop_status = process->stop_signal = process->signal_to_send = 0; @@ -1712,7 +1715,7 @@ thread_db_singlestep_thread (struct gdbs thread_db_singlestep_program (serv); else { - singlestep_thread (thread, process->signal_to_send); + singlestep_thread (serv, thread, process->signal_to_send); process->stop_status = process->stop_signal = process->signal_to_send = 0; process->running = 1;