1130812Smarcel/* Native-dependent code for LynxOS. 2130812Smarcel 3130812Smarcel Copyright 1993, 1994, 1995, 1996, 1999, 2000, 2001, 2003 Free 4130812Smarcel Software Foundation, Inc. 5130812Smarcel 6130812Smarcel This file is part of GDB. 7130812Smarcel 8130812Smarcel This program is free software; you can redistribute it and/or modify 9130812Smarcel it under the terms of the GNU General Public License as published by 10130812Smarcel the Free Software Foundation; either version 2 of the License, or 11130812Smarcel (at your option) any later version. 12130812Smarcel 13130812Smarcel This program is distributed in the hope that it will be useful, 14130812Smarcel but WITHOUT ANY WARRANTY; without even the implied warranty of 15130812Smarcel MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16130812Smarcel GNU General Public License for more details. 17130812Smarcel 18130812Smarcel You should have received a copy of the GNU General Public License 19130812Smarcel along with this program; if not, write to the Free Software 20130812Smarcel Foundation, Inc., 59 Temple Place - Suite 330, 21130812Smarcel Boston, MA 02111-1307, USA. */ 22130812Smarcel 23130812Smarcel#include "defs.h" 24130812Smarcel#include "frame.h" 25130812Smarcel#include "inferior.h" 26130812Smarcel#include "target.h" 27130812Smarcel#include "gdbcore.h" 28130812Smarcel#include "regcache.h" 29130812Smarcel 30130812Smarcel#include <sys/ptrace.h> 31130812Smarcel#Include "gdb_wait.h" 32130812Smarcel#include <sys/fpp.h> 33130812Smarcel 34130812Smarcelstatic unsigned long registers_addr (int pid); 35130812Smarcelstatic void fetch_core_registers (char *, unsigned, int, CORE_ADDR); 36130812Smarcel 37130812Smarcel#define X(ENTRY)(offsetof(struct econtext, ENTRY)) 38130812Smarcel 39130812Smarcel#ifdef I386 40130812Smarcel/* Mappings from tm-i386v.h */ 41130812Smarcel 42130812Smarcelstatic int regmap[] = 43130812Smarcel{ 44130812Smarcel X (eax), 45130812Smarcel X (ecx), 46130812Smarcel X (edx), 47130812Smarcel X (ebx), 48130812Smarcel X (esp), /* sp */ 49130812Smarcel X (ebp), /* fp */ 50130812Smarcel X (esi), 51130812Smarcel X (edi), 52130812Smarcel X (eip), /* pc */ 53130812Smarcel X (flags), /* ps */ 54130812Smarcel X (cs), 55130812Smarcel X (ss), 56130812Smarcel X (ds), 57130812Smarcel X (es), 58130812Smarcel X (ecode), /* Lynx doesn't give us either fs or gs, so */ 59130812Smarcel X (fault), /* we just substitute these two in the hopes 60130812Smarcel that they are useful. */ 61130812Smarcel}; 62130812Smarcel#endif /* I386 */ 63130812Smarcel 64130812Smarcel#ifdef M68K 65130812Smarcel/* Mappings from tm-m68k.h */ 66130812Smarcel 67130812Smarcelstatic int regmap[] = 68130812Smarcel{ 69130812Smarcel X (regs[0]), /* d0 */ 70130812Smarcel X (regs[1]), /* d1 */ 71130812Smarcel X (regs[2]), /* d2 */ 72130812Smarcel X (regs[3]), /* d3 */ 73130812Smarcel X (regs[4]), /* d4 */ 74130812Smarcel X (regs[5]), /* d5 */ 75130812Smarcel X (regs[6]), /* d6 */ 76130812Smarcel X (regs[7]), /* d7 */ 77130812Smarcel X (regs[8]), /* a0 */ 78130812Smarcel X (regs[9]), /* a1 */ 79130812Smarcel X (regs[10]), /* a2 */ 80130812Smarcel X (regs[11]), /* a3 */ 81130812Smarcel X (regs[12]), /* a4 */ 82130812Smarcel X (regs[13]), /* a5 */ 83130812Smarcel X (regs[14]), /* fp */ 84130812Smarcel offsetof (st_t, usp) - offsetof (st_t, ec), /* sp */ 85130812Smarcel X (status), /* ps */ 86130812Smarcel X (pc), 87130812Smarcel 88130812Smarcel X (fregs[0 * 3]), /* fp0 */ 89130812Smarcel X (fregs[1 * 3]), /* fp1 */ 90130812Smarcel X (fregs[2 * 3]), /* fp2 */ 91130812Smarcel X (fregs[3 * 3]), /* fp3 */ 92130812Smarcel X (fregs[4 * 3]), /* fp4 */ 93130812Smarcel X (fregs[5 * 3]), /* fp5 */ 94130812Smarcel X (fregs[6 * 3]), /* fp6 */ 95130812Smarcel X (fregs[7 * 3]), /* fp7 */ 96130812Smarcel 97130812Smarcel X (fcregs[0]), /* fpcontrol */ 98130812Smarcel X (fcregs[1]), /* fpstatus */ 99130812Smarcel X (fcregs[2]), /* fpiaddr */ 100130812Smarcel X (ssw), /* fpcode */ 101130812Smarcel X (fault), /* fpflags */ 102130812Smarcel}; 103130812Smarcel#endif /* M68K */ 104130812Smarcel 105130812Smarcel#ifdef SPARC 106130812Smarcel/* Mappings from tm-sparc.h */ 107130812Smarcel 108130812Smarcel#define FX(ENTRY)(offsetof(struct fcontext, ENTRY)) 109130812Smarcel 110130812Smarcelstatic int regmap[] = 111130812Smarcel{ 112130812Smarcel -1, /* g0 */ 113130812Smarcel X (g1), 114130812Smarcel X (g2), 115130812Smarcel X (g3), 116130812Smarcel X (g4), 117130812Smarcel -1, /* g5->g7 aren't saved by Lynx */ 118130812Smarcel -1, 119130812Smarcel -1, 120130812Smarcel 121130812Smarcel X (o[0]), 122130812Smarcel X (o[1]), 123130812Smarcel X (o[2]), 124130812Smarcel X (o[3]), 125130812Smarcel X (o[4]), 126130812Smarcel X (o[5]), 127130812Smarcel X (o[6]), /* sp */ 128130812Smarcel X (o[7]), /* ra */ 129130812Smarcel 130130812Smarcel -1, -1, -1, -1, -1, -1, -1, -1, /* l0 -> l7 */ 131130812Smarcel 132130812Smarcel -1, -1, -1, -1, -1, -1, -1, -1, /* i0 -> i7 */ 133130812Smarcel 134130812Smarcel FX (f.fregs[0]), /* f0 */ 135130812Smarcel FX (f.fregs[1]), 136130812Smarcel FX (f.fregs[2]), 137130812Smarcel FX (f.fregs[3]), 138130812Smarcel FX (f.fregs[4]), 139130812Smarcel FX (f.fregs[5]), 140130812Smarcel FX (f.fregs[6]), 141130812Smarcel FX (f.fregs[7]), 142130812Smarcel FX (f.fregs[8]), 143130812Smarcel FX (f.fregs[9]), 144130812Smarcel FX (f.fregs[10]), 145130812Smarcel FX (f.fregs[11]), 146130812Smarcel FX (f.fregs[12]), 147130812Smarcel FX (f.fregs[13]), 148130812Smarcel FX (f.fregs[14]), 149130812Smarcel FX (f.fregs[15]), 150130812Smarcel FX (f.fregs[16]), 151130812Smarcel FX (f.fregs[17]), 152130812Smarcel FX (f.fregs[18]), 153130812Smarcel FX (f.fregs[19]), 154130812Smarcel FX (f.fregs[20]), 155130812Smarcel FX (f.fregs[21]), 156130812Smarcel FX (f.fregs[22]), 157130812Smarcel FX (f.fregs[23]), 158130812Smarcel FX (f.fregs[24]), 159130812Smarcel FX (f.fregs[25]), 160130812Smarcel FX (f.fregs[26]), 161130812Smarcel FX (f.fregs[27]), 162130812Smarcel FX (f.fregs[28]), 163130812Smarcel FX (f.fregs[29]), 164130812Smarcel FX (f.fregs[30]), 165130812Smarcel FX (f.fregs[31]), 166130812Smarcel 167130812Smarcel X (y), 168130812Smarcel X (psr), 169130812Smarcel X (wim), 170130812Smarcel X (tbr), 171130812Smarcel X (pc), 172130812Smarcel X (npc), 173130812Smarcel FX (fsr), /* fpsr */ 174130812Smarcel -1, /* cpsr */ 175130812Smarcel}; 176130812Smarcel#endif /* SPARC */ 177130812Smarcel 178130812Smarcel#ifdef rs6000 179130812Smarcel 180130812Smarcelstatic int regmap[] = 181130812Smarcel{ 182130812Smarcel X (iregs[0]), /* r0 */ 183130812Smarcel X (iregs[1]), 184130812Smarcel X (iregs[2]), 185130812Smarcel X (iregs[3]), 186130812Smarcel X (iregs[4]), 187130812Smarcel X (iregs[5]), 188130812Smarcel X (iregs[6]), 189130812Smarcel X (iregs[7]), 190130812Smarcel X (iregs[8]), 191130812Smarcel X (iregs[9]), 192130812Smarcel X (iregs[10]), 193130812Smarcel X (iregs[11]), 194130812Smarcel X (iregs[12]), 195130812Smarcel X (iregs[13]), 196130812Smarcel X (iregs[14]), 197130812Smarcel X (iregs[15]), 198130812Smarcel X (iregs[16]), 199130812Smarcel X (iregs[17]), 200130812Smarcel X (iregs[18]), 201130812Smarcel X (iregs[19]), 202130812Smarcel X (iregs[20]), 203130812Smarcel X (iregs[21]), 204130812Smarcel X (iregs[22]), 205130812Smarcel X (iregs[23]), 206130812Smarcel X (iregs[24]), 207130812Smarcel X (iregs[25]), 208130812Smarcel X (iregs[26]), 209130812Smarcel X (iregs[27]), 210130812Smarcel X (iregs[28]), 211130812Smarcel X (iregs[29]), 212130812Smarcel X (iregs[30]), 213130812Smarcel X (iregs[31]), 214130812Smarcel 215130812Smarcel X (fregs[0]), /* f0 */ 216130812Smarcel X (fregs[1]), 217130812Smarcel X (fregs[2]), 218130812Smarcel X (fregs[3]), 219130812Smarcel X (fregs[4]), 220130812Smarcel X (fregs[5]), 221130812Smarcel X (fregs[6]), 222130812Smarcel X (fregs[7]), 223130812Smarcel X (fregs[8]), 224130812Smarcel X (fregs[9]), 225130812Smarcel X (fregs[10]), 226130812Smarcel X (fregs[11]), 227130812Smarcel X (fregs[12]), 228130812Smarcel X (fregs[13]), 229130812Smarcel X (fregs[14]), 230130812Smarcel X (fregs[15]), 231130812Smarcel X (fregs[16]), 232130812Smarcel X (fregs[17]), 233130812Smarcel X (fregs[18]), 234130812Smarcel X (fregs[19]), 235130812Smarcel X (fregs[20]), 236130812Smarcel X (fregs[21]), 237130812Smarcel X (fregs[22]), 238130812Smarcel X (fregs[23]), 239130812Smarcel X (fregs[24]), 240130812Smarcel X (fregs[25]), 241130812Smarcel X (fregs[26]), 242130812Smarcel X (fregs[27]), 243130812Smarcel X (fregs[28]), 244130812Smarcel X (fregs[29]), 245130812Smarcel X (fregs[30]), 246130812Smarcel X (fregs[31]), 247130812Smarcel 248130812Smarcel X (srr0), /* IAR (PC) */ 249130812Smarcel X (srr1), /* MSR (PS) */ 250130812Smarcel X (cr), /* CR */ 251130812Smarcel X (lr), /* LR */ 252130812Smarcel X (ctr), /* CTR */ 253130812Smarcel X (xer), /* XER */ 254130812Smarcel X (mq) /* MQ */ 255130812Smarcel}; 256130812Smarcel 257130812Smarcel#endif /* rs6000 */ 258130812Smarcel 259130812Smarcel#if defined (I386) || defined (M68K) || defined (rs6000) 260130812Smarcel 261130812Smarcel/* Return the offset relative to the start of the per-thread data to the 262130812Smarcel saved context block. */ 263130812Smarcel 264130812Smarcelstatic unsigned long 265130812Smarcelregisters_addr (int pid) 266130812Smarcel{ 267130812Smarcel CORE_ADDR stblock; 268130812Smarcel int ecpoff = offsetof (st_t, ecp); 269130812Smarcel CORE_ADDR ecp; 270130812Smarcel 271130812Smarcel errno = 0; 272130812Smarcel stblock = (CORE_ADDR) ptrace (PTRACE_THREADUSER, pid, (PTRACE_ARG3_TYPE) 0, 273130812Smarcel 0); 274130812Smarcel if (errno) 275130812Smarcel perror_with_name ("ptrace(PTRACE_THREADUSER)"); 276130812Smarcel 277130812Smarcel ecp = (CORE_ADDR) ptrace (PTRACE_PEEKTHREAD, pid, (PTRACE_ARG3_TYPE) ecpoff, 278130812Smarcel 0); 279130812Smarcel if (errno) 280130812Smarcel perror_with_name ("ptrace(PTRACE_PEEKTHREAD)"); 281130812Smarcel 282130812Smarcel return ecp - stblock; 283130812Smarcel} 284130812Smarcel 285130812Smarcel/* Fetch one or more registers from the inferior. REGNO == -1 to get 286130812Smarcel them all. We actually fetch more than requested, when convenient, 287130812Smarcel marking them as valid so we won't fetch them again. */ 288130812Smarcel 289130812Smarcelvoid 290130812Smarcelfetch_inferior_registers (int regno) 291130812Smarcel{ 292130812Smarcel int reglo, reghi; 293130812Smarcel int i; 294130812Smarcel unsigned long ecp; 295130812Smarcel 296130812Smarcel if (regno == -1) 297130812Smarcel { 298130812Smarcel reglo = 0; 299130812Smarcel reghi = NUM_REGS - 1; 300130812Smarcel } 301130812Smarcel else 302130812Smarcel reglo = reghi = regno; 303130812Smarcel 304130812Smarcel ecp = registers_addr (PIDGET (inferior_ptid)); 305130812Smarcel 306130812Smarcel { 307130812Smarcel char buf[MAX_REGISTER_SIZE]; 308130812Smarcel for (regno = reglo; regno <= reghi; regno++) 309130812Smarcel { 310130812Smarcel int ptrace_fun = PTRACE_PEEKTHREAD; 311130812Smarcel 312130812Smarcel#ifdef M68K 313130812Smarcel ptrace_fun = regno == SP_REGNUM ? PTRACE_PEEKUSP : PTRACE_PEEKTHREAD; 314130812Smarcel#endif 315130812Smarcel 316130812Smarcel for (i = 0; i < DEPRECATED_REGISTER_RAW_SIZE (regno); i += sizeof (int)) 317130812Smarcel { 318130812Smarcel unsigned int reg; 319130812Smarcel 320130812Smarcel errno = 0; 321130812Smarcel reg = ptrace (ptrace_fun, PIDGET (inferior_ptid), 322130812Smarcel (PTRACE_ARG3_TYPE) (ecp + regmap[regno] + i), 0); 323130812Smarcel if (errno) 324130812Smarcel perror_with_name ("ptrace(PTRACE_PEEKUSP)"); 325130812Smarcel 326130812Smarcel *(int *) &buf[i] = reg; 327130812Smarcel } 328130812Smarcel supply_register (regno, buf); 329130812Smarcel } 330130812Smarcel } 331130812Smarcel} 332130812Smarcel 333130812Smarcel/* Store our register values back into the inferior. 334130812Smarcel If REGNO is -1, do this for all registers. 335130812Smarcel Otherwise, REGNO specifies which register (so we can save time). */ 336130812Smarcel 337130812Smarcelvoid 338130812Smarcelstore_inferior_registers (int regno) 339130812Smarcel{ 340130812Smarcel int reglo, reghi; 341130812Smarcel int i; 342130812Smarcel unsigned long ecp; 343130812Smarcel 344130812Smarcel if (regno == -1) 345130812Smarcel { 346130812Smarcel reglo = 0; 347130812Smarcel reghi = NUM_REGS - 1; 348130812Smarcel } 349130812Smarcel else 350130812Smarcel reglo = reghi = regno; 351130812Smarcel 352130812Smarcel ecp = registers_addr (PIDGET (inferior_ptid)); 353130812Smarcel 354130812Smarcel for (regno = reglo; regno <= reghi; regno++) 355130812Smarcel { 356130812Smarcel int ptrace_fun = PTRACE_POKEUSER; 357130812Smarcel 358130812Smarcel if (CANNOT_STORE_REGISTER (regno)) 359130812Smarcel continue; 360130812Smarcel 361130812Smarcel#ifdef M68K 362130812Smarcel ptrace_fun = regno == SP_REGNUM ? PTRACE_POKEUSP : PTRACE_POKEUSER; 363130812Smarcel#endif 364130812Smarcel 365130812Smarcel for (i = 0; i < DEPRECATED_REGISTER_RAW_SIZE (regno); i += sizeof (int)) 366130812Smarcel { 367130812Smarcel unsigned int reg; 368130812Smarcel 369130812Smarcel reg = *(unsigned int *) &deprecated_registers[DEPRECATED_REGISTER_BYTE (regno) + i]; 370130812Smarcel 371130812Smarcel errno = 0; 372130812Smarcel ptrace (ptrace_fun, PIDGET (inferior_ptid), 373130812Smarcel (PTRACE_ARG3_TYPE) (ecp + regmap[regno] + i), reg); 374130812Smarcel if (errno) 375130812Smarcel perror_with_name ("ptrace(PTRACE_POKEUSP)"); 376130812Smarcel } 377130812Smarcel } 378130812Smarcel} 379130812Smarcel#endif /* defined (I386) || defined (M68K) || defined (rs6000) */ 380130812Smarcel 381130812Smarcel/* Wait for child to do something. Return pid of child, or -1 in case 382130812Smarcel of error; store status through argument pointer OURSTATUS. */ 383130812Smarcel 384130812Smarcelptid_t 385130812Smarcelchild_wait (ptid_t ptid, struct target_waitstatus *ourstatus) 386130812Smarcel{ 387130812Smarcel int save_errno; 388130812Smarcel int thread; 389130812Smarcel union wait status; 390130812Smarcel int pid; 391130812Smarcel 392130812Smarcel while (1) 393130812Smarcel { 394130812Smarcel int sig; 395130812Smarcel 396130812Smarcel set_sigint_trap (); /* Causes SIGINT to be passed on to the 397130812Smarcel attached process. */ 398130812Smarcel pid = wait (&status); 399130812Smarcel 400130812Smarcel save_errno = errno; 401130812Smarcel 402130812Smarcel clear_sigint_trap (); 403130812Smarcel 404130812Smarcel if (pid == -1) 405130812Smarcel { 406130812Smarcel if (save_errno == EINTR) 407130812Smarcel continue; 408130812Smarcel fprintf_unfiltered (gdb_stderr, "Child process unexpectedly missing: %s.\n", 409130812Smarcel safe_strerror (save_errno)); 410130812Smarcel /* Claim it exited with unknown signal. */ 411130812Smarcel ourstatus->kind = TARGET_WAITKIND_SIGNALLED; 412130812Smarcel ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN; 413130812Smarcel return -1; 414130812Smarcel } 415130812Smarcel 416130812Smarcel if (pid != PIDGET (inferior_ptid)) /* Some other process?!? */ 417130812Smarcel continue; 418130812Smarcel 419130812Smarcel thread = status.w_tid; /* Get thread id from status */ 420130812Smarcel 421130812Smarcel /* Initial thread value can only be acquired via wait, so we have to 422130812Smarcel resort to this hack. */ 423130812Smarcel 424130812Smarcel if (TIDGET (inferior_ptid) == 0 && thread != 0) 425130812Smarcel { 426130812Smarcel inferior_ptid = MERGEPID (PIDGET (inferior_ptid), thread); 427130812Smarcel add_thread (inferior_ptid); 428130812Smarcel } 429130812Smarcel 430130812Smarcel ptid = BUILDPID (pid, thread); 431130812Smarcel 432130812Smarcel /* We've become a single threaded process again. */ 433130812Smarcel if (thread == 0) 434130812Smarcel inferior_ptid = ptid; 435130812Smarcel 436130812Smarcel /* Check for thread creation. */ 437130812Smarcel if (WIFSTOPPED (status) 438130812Smarcel && WSTOPSIG (status) == SIGTRAP 439130812Smarcel && !in_thread_list (ptid)) 440130812Smarcel { 441130812Smarcel int realsig; 442130812Smarcel 443130812Smarcel realsig = ptrace (PTRACE_GETTRACESIG, PIDGET (ptid), 444130812Smarcel (PTRACE_ARG3_TYPE) 0, 0); 445130812Smarcel 446130812Smarcel if (realsig == SIGNEWTHREAD) 447130812Smarcel { 448130812Smarcel /* It's a new thread notification. We don't want to much with 449130812Smarcel realsig -- the code in wait_for_inferior expects SIGTRAP. */ 450130812Smarcel ourstatus->kind = TARGET_WAITKIND_SPURIOUS; 451130812Smarcel ourstatus->value.sig = TARGET_SIGNAL_0; 452130812Smarcel return ptid; 453130812Smarcel } 454130812Smarcel else 455130812Smarcel error ("Signal for unknown thread was not SIGNEWTHREAD"); 456130812Smarcel } 457130812Smarcel 458130812Smarcel /* Check for thread termination. */ 459130812Smarcel else if (WIFSTOPPED (status) 460130812Smarcel && WSTOPSIG (status) == SIGTRAP 461130812Smarcel && in_thread_list (ptid)) 462130812Smarcel { 463130812Smarcel int realsig; 464130812Smarcel 465130812Smarcel realsig = ptrace (PTRACE_GETTRACESIG, PIDGET (ptid), 466130812Smarcel (PTRACE_ARG3_TYPE) 0, 0); 467130812Smarcel 468130812Smarcel if (realsig == SIGTHREADEXIT) 469130812Smarcel { 470130812Smarcel ptrace (PTRACE_CONT, PIDGET (ptid), (PTRACE_ARG3_TYPE) 0, 0); 471130812Smarcel continue; 472130812Smarcel } 473130812Smarcel } 474130812Smarcel 475130812Smarcel#ifdef SPARC 476130812Smarcel /* SPARC Lynx uses an byte reversed wait status; we must use the 477130812Smarcel host macros to access it. These lines just a copy of 478130812Smarcel store_waitstatus. We can't use CHILD_SPECIAL_WAITSTATUS 479130812Smarcel because target.c can't include the Lynx <sys/wait.h>. */ 480130812Smarcel if (WIFEXITED (status)) 481130812Smarcel { 482130812Smarcel ourstatus->kind = TARGET_WAITKIND_EXITED; 483130812Smarcel ourstatus->value.integer = WEXITSTATUS (status); 484130812Smarcel } 485130812Smarcel else if (!WIFSTOPPED (status)) 486130812Smarcel { 487130812Smarcel ourstatus->kind = TARGET_WAITKIND_SIGNALLED; 488130812Smarcel ourstatus->value.sig = 489130812Smarcel target_signal_from_host (WTERMSIG (status)); 490130812Smarcel } 491130812Smarcel else 492130812Smarcel { 493130812Smarcel ourstatus->kind = TARGET_WAITKIND_STOPPED; 494130812Smarcel ourstatus->value.sig = 495130812Smarcel target_signal_from_host (WSTOPSIG (status)); 496130812Smarcel } 497130812Smarcel#else 498130812Smarcel store_waitstatus (ourstatus, status.w_status); 499130812Smarcel#endif 500130812Smarcel 501130812Smarcel return ptid; 502130812Smarcel } 503130812Smarcel} 504130812Smarcel 505130812Smarcel/* Return nonzero if the given thread is still alive. */ 506130812Smarcelint 507130812Smarcelchild_thread_alive (ptid_t ptid) 508130812Smarcel{ 509130812Smarcel int pid = PIDGET (ptid); 510130812Smarcel 511130812Smarcel /* Arggh. Apparently pthread_kill only works for threads within 512130812Smarcel the process that calls pthread_kill. 513130812Smarcel 514130812Smarcel We want to avoid the lynx signal extensions as they simply don't 515130812Smarcel map well to the generic gdb interface we want to keep. 516130812Smarcel 517130812Smarcel All we want to do is determine if a particular thread is alive; 518130812Smarcel it appears as if we can just make a harmless thread specific 519130812Smarcel ptrace call to do that. */ 520130812Smarcel return (ptrace (PTRACE_THREADUSER, pid, 0, 0) != -1); 521130812Smarcel} 522130812Smarcel 523130812Smarcel/* Resume execution of the inferior process. 524130812Smarcel If STEP is nonzero, single-step it. 525130812Smarcel If SIGNAL is nonzero, give it that signal. */ 526130812Smarcel 527130812Smarcelvoid 528130812Smarcelchild_resume (ptid_t ptid, int step, enum target_signal signal) 529130812Smarcel{ 530130812Smarcel int func; 531130812Smarcel int pid = PIDGET (ptid); 532130812Smarcel 533130812Smarcel errno = 0; 534130812Smarcel 535130812Smarcel /* If pid == -1, then we want to step/continue all threads, else 536130812Smarcel we only want to step/continue a single thread. */ 537130812Smarcel if (pid == -1) 538130812Smarcel { 539130812Smarcel pid = PIDGET (inferior_ptid); 540130812Smarcel func = step ? PTRACE_SINGLESTEP : PTRACE_CONT; 541130812Smarcel } 542130812Smarcel else 543130812Smarcel func = step ? PTRACE_SINGLESTEP_ONE : PTRACE_CONT_ONE; 544130812Smarcel 545130812Smarcel 546130812Smarcel /* An address of (PTRACE_ARG3_TYPE)1 tells ptrace to continue from where 547130812Smarcel it was. (If GDB wanted it to start some other way, we have already 548130812Smarcel written a new PC value to the child.) 549130812Smarcel 550130812Smarcel If this system does not support PT_STEP, a higher level function will 551130812Smarcel have called single_step() to transmute the step request into a 552130812Smarcel continue request (by setting breakpoints on all possible successor 553130812Smarcel instructions), so we don't have to worry about that here. */ 554130812Smarcel 555130812Smarcel ptrace (func, pid, (PTRACE_ARG3_TYPE) 1, target_signal_to_host (signal)); 556130812Smarcel 557130812Smarcel if (errno) 558130812Smarcel perror_with_name ("ptrace"); 559130812Smarcel} 560130812Smarcel 561130812Smarcel/* Convert a Lynx process ID to a string. Returns the string in a static 562130812Smarcel buffer. */ 563130812Smarcel 564130812Smarcelchar * 565130812Smarcelchild_pid_to_str (ptid_t ptid) 566130812Smarcel{ 567130812Smarcel static char buf[40]; 568130812Smarcel 569130812Smarcel sprintf (buf, "process %d thread %d", PIDGET (ptid), TIDGET (ptid)); 570130812Smarcel 571130812Smarcel return buf; 572130812Smarcel} 573130812Smarcel 574130812Smarcel/* Extract the register values out of the core file and store 575130812Smarcel them where `read_register' will find them. 576130812Smarcel 577130812Smarcel CORE_REG_SECT points to the register values themselves, read into memory. 578130812Smarcel CORE_REG_SIZE is the size of that area. 579130812Smarcel WHICH says which set of registers we are handling (0 = int, 2 = float 580130812Smarcel on machines where they are discontiguous). 581130812Smarcel REG_ADDR is the offset from u.u_ar0 to the register values relative to 582130812Smarcel core_reg_sect. This is used with old-fashioned core files to 583130812Smarcel locate the registers in a large upage-plus-stack ".reg" section. 584130812Smarcel Original upage address X is at location core_reg_sect+x+reg_addr. 585130812Smarcel */ 586130812Smarcel 587130812Smarcelstatic void 588130812Smarcelfetch_core_registers (char *core_reg_sect, unsigned core_reg_size, int which, 589130812Smarcel CORE_ADDR reg_addr) 590130812Smarcel{ 591130812Smarcel struct st_entry s; 592130812Smarcel unsigned int regno; 593130812Smarcel 594130812Smarcel for (regno = 0; regno < NUM_REGS; regno++) 595130812Smarcel if (regmap[regno] != -1) 596130812Smarcel supply_register (regno, core_reg_sect + offsetof (st_t, ec) 597130812Smarcel + regmap[regno]); 598130812Smarcel 599130812Smarcel#ifdef SPARC 600130812Smarcel/* Fetching this register causes all of the I & L regs to be read from the 601130812Smarcel stack and validated. */ 602130812Smarcel 603130812Smarcel fetch_inferior_registers (I0_REGNUM); 604130812Smarcel#endif 605130812Smarcel} 606130812Smarcel 607130812Smarcel 608130812Smarcel/* Register that we are able to handle lynx core file formats. 609130812Smarcel FIXME: is this really bfd_target_unknown_flavour? */ 610130812Smarcel 611130812Smarcelstatic struct core_fns lynx_core_fns = 612130812Smarcel{ 613130812Smarcel bfd_target_unknown_flavour, /* core_flavour */ 614130812Smarcel default_check_format, /* check_format */ 615130812Smarcel default_core_sniffer, /* core_sniffer */ 616130812Smarcel fetch_core_registers, /* core_read_registers */ 617130812Smarcel NULL /* next */ 618130812Smarcel}; 619130812Smarcel 620130812Smarcelvoid 621130812Smarcel_initialize_core_lynx (void) 622130812Smarcel{ 623130812Smarcel add_core_fns (&lynx_core_fns); 624130812Smarcel} 625