1699b0f92Schristos /* Motorola m68k native support for GNU/Linux. 2699b0f92Schristos 3*6881a400Schristos Copyright (C) 1996-2023 Free Software Foundation, Inc. 4699b0f92Schristos 5699b0f92Schristos This file is part of GDB. 6699b0f92Schristos 7699b0f92Schristos This program is free software; you can redistribute it and/or modify 8699b0f92Schristos it under the terms of the GNU General Public License as published by 9699b0f92Schristos the Free Software Foundation; either version 3 of the License, or 10699b0f92Schristos (at your option) any later version. 11699b0f92Schristos 12699b0f92Schristos This program is distributed in the hope that it will be useful, 13699b0f92Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of 14699b0f92Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15699b0f92Schristos GNU General Public License for more details. 16699b0f92Schristos 17699b0f92Schristos You should have received a copy of the GNU General Public License 18699b0f92Schristos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 19699b0f92Schristos 20699b0f92Schristos #include "defs.h" 21699b0f92Schristos #include "frame.h" 22699b0f92Schristos #include "inferior.h" 23699b0f92Schristos #include "language.h" 24699b0f92Schristos #include "gdbcore.h" 25699b0f92Schristos #include "regcache.h" 26699b0f92Schristos #include "target.h" 27699b0f92Schristos #include "linux-nat.h" 287d62b00eSchristos #include "gdbarch.h" 29699b0f92Schristos 30699b0f92Schristos #include "m68k-tdep.h" 31699b0f92Schristos 32699b0f92Schristos #include <sys/dir.h> 33699b0f92Schristos #include <signal.h> 34699b0f92Schristos #include "nat/gdb_ptrace.h" 35699b0f92Schristos #include <sys/user.h> 36699b0f92Schristos #include <sys/ioctl.h> 37699b0f92Schristos #include <fcntl.h> 38699b0f92Schristos #include <sys/procfs.h> 39699b0f92Schristos 40699b0f92Schristos #ifdef HAVE_SYS_REG_H 41699b0f92Schristos #include <sys/reg.h> 42699b0f92Schristos #endif 43699b0f92Schristos 44699b0f92Schristos #include <sys/file.h> 45699b0f92Schristos #include <sys/stat.h> 46699b0f92Schristos 47699b0f92Schristos #include "floatformat.h" 48699b0f92Schristos 49699b0f92Schristos /* Prototypes for supply_gregset etc. */ 50699b0f92Schristos #include "gregset.h" 51699b0f92Schristos 52699b0f92Schristos /* Defines ps_err_e, struct ps_prochandle. */ 53699b0f92Schristos #include "gdb_proc_service.h" 54699b0f92Schristos 55699b0f92Schristos #include "inf-ptrace.h" 56699b0f92Schristos 57699b0f92Schristos #ifndef PTRACE_GET_THREAD_AREA 58699b0f92Schristos #define PTRACE_GET_THREAD_AREA 25 59699b0f92Schristos #endif 60699b0f92Schristos 617f2ac410Schristos 627f2ac410Schristos class m68k_linux_nat_target final : public linux_nat_target 637f2ac410Schristos { 647f2ac410Schristos public: 657f2ac410Schristos /* Add our register access methods. */ 667f2ac410Schristos void fetch_registers (struct regcache *, int) override; 677f2ac410Schristos void store_registers (struct regcache *, int) override; 687f2ac410Schristos }; 697f2ac410Schristos 707f2ac410Schristos static m68k_linux_nat_target the_m68k_linux_nat_target; 717f2ac410Schristos 72699b0f92Schristos /* This table must line up with gdbarch_register_name in "m68k-tdep.c". */ 73699b0f92Schristos static const int regmap[] = 74699b0f92Schristos { 75699b0f92Schristos PT_D0, PT_D1, PT_D2, PT_D3, PT_D4, PT_D5, PT_D6, PT_D7, 76699b0f92Schristos PT_A0, PT_A1, PT_A2, PT_A3, PT_A4, PT_A5, PT_A6, PT_USP, 77699b0f92Schristos PT_SR, PT_PC, 78699b0f92Schristos /* PT_FP0, ..., PT_FP7 */ 79699b0f92Schristos 21, 24, 27, 30, 33, 36, 39, 42, 80699b0f92Schristos /* PT_FPCR, PT_FPSR, PT_FPIAR */ 81699b0f92Schristos 45, 46, 47 82699b0f92Schristos }; 83699b0f92Schristos 84699b0f92Schristos /* Which ptrace request retrieves which registers? 85699b0f92Schristos These apply to the corresponding SET requests as well. */ 86699b0f92Schristos #define NUM_GREGS (18) 87699b0f92Schristos #define MAX_NUM_REGS (NUM_GREGS + 11) 88699b0f92Schristos 89699b0f92Schristos static int 90699b0f92Schristos getregs_supplies (int regno) 91699b0f92Schristos { 92699b0f92Schristos return 0 <= regno && regno < NUM_GREGS; 93699b0f92Schristos } 94699b0f92Schristos 95699b0f92Schristos static int 96699b0f92Schristos getfpregs_supplies (int regno) 97699b0f92Schristos { 98699b0f92Schristos return M68K_FP0_REGNUM <= regno && regno <= M68K_FPI_REGNUM; 99699b0f92Schristos } 100699b0f92Schristos 101699b0f92Schristos /* Does the current host support the GETREGS request? */ 102699b0f92Schristos static int have_ptrace_getregs = 103699b0f92Schristos #ifdef HAVE_PTRACE_GETREGS 104699b0f92Schristos 1 105699b0f92Schristos #else 106699b0f92Schristos 0 107699b0f92Schristos #endif 108699b0f92Schristos ; 109699b0f92Schristos 110699b0f92Schristos 111699b0f92Schristos 112699b0f92Schristos /* Fetching registers directly from the U area, one at a time. */ 113699b0f92Schristos 114699b0f92Schristos /* Fetch one register. */ 115699b0f92Schristos 116699b0f92Schristos static void 117699b0f92Schristos fetch_register (struct regcache *regcache, int regno) 118699b0f92Schristos { 1197f2ac410Schristos struct gdbarch *gdbarch = regcache->arch (); 120699b0f92Schristos long regaddr, val; 121699b0f92Schristos int i; 122699b0f92Schristos gdb_byte buf[M68K_MAX_REGISTER_SIZE]; 1237f2ac410Schristos pid_t tid = get_ptrace_pid (regcache->ptid ()); 124699b0f92Schristos 125699b0f92Schristos regaddr = 4 * regmap[regno]; 126699b0f92Schristos for (i = 0; i < register_size (gdbarch, regno); i += sizeof (long)) 127699b0f92Schristos { 128699b0f92Schristos errno = 0; 129699b0f92Schristos val = ptrace (PTRACE_PEEKUSER, tid, regaddr, 0); 130699b0f92Schristos memcpy (&buf[i], &val, sizeof (long)); 131699b0f92Schristos regaddr += sizeof (long); 132699b0f92Schristos if (errno != 0) 133699b0f92Schristos error (_("Couldn't read register %s (#%d): %s."), 134699b0f92Schristos gdbarch_register_name (gdbarch, regno), 135699b0f92Schristos regno, safe_strerror (errno)); 136699b0f92Schristos } 1377f2ac410Schristos regcache->raw_supply (regno, buf); 138699b0f92Schristos } 139699b0f92Schristos 140699b0f92Schristos /* Fetch register values from the inferior. 141699b0f92Schristos If REGNO is negative, do this for all registers. 142699b0f92Schristos Otherwise, REGNO specifies which register (so we can save time). */ 143699b0f92Schristos 144699b0f92Schristos static void 145699b0f92Schristos old_fetch_inferior_registers (struct regcache *regcache, int regno) 146699b0f92Schristos { 147699b0f92Schristos if (regno >= 0) 148699b0f92Schristos { 149699b0f92Schristos fetch_register (regcache, regno); 150699b0f92Schristos } 151699b0f92Schristos else 152699b0f92Schristos { 153699b0f92Schristos for (regno = 0; 1547f2ac410Schristos regno < gdbarch_num_regs (regcache->arch ()); 155699b0f92Schristos regno++) 156699b0f92Schristos { 157699b0f92Schristos fetch_register (regcache, regno); 158699b0f92Schristos } 159699b0f92Schristos } 160699b0f92Schristos } 161699b0f92Schristos 162699b0f92Schristos /* Store one register. */ 163699b0f92Schristos 164699b0f92Schristos static void 165699b0f92Schristos store_register (const struct regcache *regcache, int regno) 166699b0f92Schristos { 1677f2ac410Schristos struct gdbarch *gdbarch = regcache->arch (); 168699b0f92Schristos long regaddr, val; 169699b0f92Schristos int i; 170699b0f92Schristos gdb_byte buf[M68K_MAX_REGISTER_SIZE]; 1717f2ac410Schristos pid_t tid = get_ptrace_pid (regcache->ptid ()); 172699b0f92Schristos 173699b0f92Schristos regaddr = 4 * regmap[regno]; 174699b0f92Schristos 175699b0f92Schristos /* Put the contents of regno into a local buffer. */ 1767f2ac410Schristos regcache->raw_collect (regno, buf); 177699b0f92Schristos 178699b0f92Schristos /* Store the local buffer into the inferior a chunk at the time. */ 179699b0f92Schristos for (i = 0; i < register_size (gdbarch, regno); i += sizeof (long)) 180699b0f92Schristos { 181699b0f92Schristos errno = 0; 182699b0f92Schristos memcpy (&val, &buf[i], sizeof (long)); 183699b0f92Schristos ptrace (PTRACE_POKEUSER, tid, regaddr, val); 184699b0f92Schristos regaddr += sizeof (long); 185699b0f92Schristos if (errno != 0) 186699b0f92Schristos error (_("Couldn't write register %s (#%d): %s."), 187699b0f92Schristos gdbarch_register_name (gdbarch, regno), 188699b0f92Schristos regno, safe_strerror (errno)); 189699b0f92Schristos } 190699b0f92Schristos } 191699b0f92Schristos 192699b0f92Schristos /* Store our register values back into the inferior. 193699b0f92Schristos If REGNO is negative, do this for all registers. 194699b0f92Schristos Otherwise, REGNO specifies which register (so we can save time). */ 195699b0f92Schristos 196699b0f92Schristos static void 197699b0f92Schristos old_store_inferior_registers (const struct regcache *regcache, int regno) 198699b0f92Schristos { 199699b0f92Schristos if (regno >= 0) 200699b0f92Schristos { 201699b0f92Schristos store_register (regcache, regno); 202699b0f92Schristos } 203699b0f92Schristos else 204699b0f92Schristos { 205699b0f92Schristos for (regno = 0; 2067f2ac410Schristos regno < gdbarch_num_regs (regcache->arch ()); 207699b0f92Schristos regno++) 208699b0f92Schristos { 209699b0f92Schristos store_register (regcache, regno); 210699b0f92Schristos } 211699b0f92Schristos } 212699b0f92Schristos } 213699b0f92Schristos 214699b0f92Schristos /* Given a pointer to a general register set in /proc format 215699b0f92Schristos (elf_gregset_t *), unpack the register contents and supply 216699b0f92Schristos them as gdb's idea of the current register values. */ 217699b0f92Schristos 218699b0f92Schristos void 219699b0f92Schristos supply_gregset (struct regcache *regcache, const elf_gregset_t *gregsetp) 220699b0f92Schristos { 2217f2ac410Schristos struct gdbarch *gdbarch = regcache->arch (); 222699b0f92Schristos const elf_greg_t *regp = (const elf_greg_t *) gregsetp; 223699b0f92Schristos int regi; 224699b0f92Schristos 225699b0f92Schristos for (regi = M68K_D0_REGNUM; 226699b0f92Schristos regi <= gdbarch_sp_regnum (gdbarch); 227699b0f92Schristos regi++) 2287f2ac410Schristos regcache->raw_supply (regi, ®p[regmap[regi]]); 2297f2ac410Schristos regcache->raw_supply (gdbarch_ps_regnum (gdbarch), ®p[PT_SR]); 2307f2ac410Schristos regcache->raw_supply (gdbarch_pc_regnum (gdbarch), ®p[PT_PC]); 231699b0f92Schristos } 232699b0f92Schristos 233699b0f92Schristos /* Fill register REGNO (if it is a general-purpose register) in 234699b0f92Schristos *GREGSETPS with the value in GDB's register array. If REGNO is -1, 235699b0f92Schristos do this for all registers. */ 236699b0f92Schristos void 237699b0f92Schristos fill_gregset (const struct regcache *regcache, 238699b0f92Schristos elf_gregset_t *gregsetp, int regno) 239699b0f92Schristos { 240699b0f92Schristos elf_greg_t *regp = (elf_greg_t *) gregsetp; 241699b0f92Schristos int i; 242699b0f92Schristos 243699b0f92Schristos for (i = 0; i < NUM_GREGS; i++) 244699b0f92Schristos if (regno == -1 || regno == i) 2457f2ac410Schristos regcache->raw_collect (i, regp + regmap[i]); 246699b0f92Schristos } 247699b0f92Schristos 248699b0f92Schristos #ifdef HAVE_PTRACE_GETREGS 249699b0f92Schristos 250699b0f92Schristos /* Fetch all general-purpose registers from process/thread TID and 251699b0f92Schristos store their values in GDB's register array. */ 252699b0f92Schristos 253699b0f92Schristos static void 254699b0f92Schristos fetch_regs (struct regcache *regcache, int tid) 255699b0f92Schristos { 256699b0f92Schristos elf_gregset_t regs; 257699b0f92Schristos 258699b0f92Schristos if (ptrace (PTRACE_GETREGS, tid, 0, (int) ®s) < 0) 259699b0f92Schristos { 260699b0f92Schristos if (errno == EIO) 261699b0f92Schristos { 262699b0f92Schristos /* The kernel we're running on doesn't support the GETREGS 263699b0f92Schristos request. Reset `have_ptrace_getregs'. */ 264699b0f92Schristos have_ptrace_getregs = 0; 265699b0f92Schristos return; 266699b0f92Schristos } 267699b0f92Schristos 268699b0f92Schristos perror_with_name (_("Couldn't get registers")); 269699b0f92Schristos } 270699b0f92Schristos 271699b0f92Schristos supply_gregset (regcache, (const elf_gregset_t *) ®s); 272699b0f92Schristos } 273699b0f92Schristos 274699b0f92Schristos /* Store all valid general-purpose registers in GDB's register array 275699b0f92Schristos into the process/thread specified by TID. */ 276699b0f92Schristos 277699b0f92Schristos static void 278699b0f92Schristos store_regs (const struct regcache *regcache, int tid, int regno) 279699b0f92Schristos { 280699b0f92Schristos elf_gregset_t regs; 281699b0f92Schristos 282699b0f92Schristos if (ptrace (PTRACE_GETREGS, tid, 0, (int) ®s) < 0) 283699b0f92Schristos perror_with_name (_("Couldn't get registers")); 284699b0f92Schristos 285699b0f92Schristos fill_gregset (regcache, ®s, regno); 286699b0f92Schristos 287699b0f92Schristos if (ptrace (PTRACE_SETREGS, tid, 0, (int) ®s) < 0) 288699b0f92Schristos perror_with_name (_("Couldn't write registers")); 289699b0f92Schristos } 290699b0f92Schristos 291699b0f92Schristos #else 292699b0f92Schristos 293699b0f92Schristos static void fetch_regs (struct regcache *regcache, int tid) 294699b0f92Schristos { 295699b0f92Schristos } 296699b0f92Schristos 297699b0f92Schristos static void store_regs (const struct regcache *regcache, int tid, int regno) 298699b0f92Schristos { 299699b0f92Schristos } 300699b0f92Schristos 301699b0f92Schristos #endif 302699b0f92Schristos 303699b0f92Schristos 304699b0f92Schristos /* Transfering floating-point registers between GDB, inferiors and cores. */ 305699b0f92Schristos 306699b0f92Schristos /* What is the address of fpN within the floating-point register set F? */ 307699b0f92Schristos #define FPREG_ADDR(f, n) (&(f)->fpregs[(n) * 3]) 308699b0f92Schristos 309699b0f92Schristos /* Fill GDB's register array with the floating-point register values in 310699b0f92Schristos *FPREGSETP. */ 311699b0f92Schristos 312699b0f92Schristos void 313699b0f92Schristos supply_fpregset (struct regcache *regcache, const elf_fpregset_t *fpregsetp) 314699b0f92Schristos { 3157f2ac410Schristos struct gdbarch *gdbarch = regcache->arch (); 316699b0f92Schristos int regi; 317699b0f92Schristos 318699b0f92Schristos for (regi = gdbarch_fp0_regnum (gdbarch); 319699b0f92Schristos regi < gdbarch_fp0_regnum (gdbarch) + 8; regi++) 3207f2ac410Schristos regcache->raw_supply 3217f2ac410Schristos (regi, FPREG_ADDR (fpregsetp, regi - gdbarch_fp0_regnum (gdbarch))); 3227f2ac410Schristos regcache->raw_supply (M68K_FPC_REGNUM, &fpregsetp->fpcntl[0]); 3237f2ac410Schristos regcache->raw_supply (M68K_FPS_REGNUM, &fpregsetp->fpcntl[1]); 3247f2ac410Schristos regcache->raw_supply (M68K_FPI_REGNUM, &fpregsetp->fpcntl[2]); 325699b0f92Schristos } 326699b0f92Schristos 327699b0f92Schristos /* Fill register REGNO (if it is a floating-point register) in 328699b0f92Schristos *FPREGSETP with the value in GDB's register array. If REGNO is -1, 329699b0f92Schristos do this for all registers. */ 330699b0f92Schristos 331699b0f92Schristos void 332699b0f92Schristos fill_fpregset (const struct regcache *regcache, 333699b0f92Schristos elf_fpregset_t *fpregsetp, int regno) 334699b0f92Schristos { 3357f2ac410Schristos struct gdbarch *gdbarch = regcache->arch (); 336699b0f92Schristos int i; 337699b0f92Schristos 338699b0f92Schristos /* Fill in the floating-point registers. */ 339699b0f92Schristos for (i = gdbarch_fp0_regnum (gdbarch); 340699b0f92Schristos i < gdbarch_fp0_regnum (gdbarch) + 8; i++) 341699b0f92Schristos if (regno == -1 || regno == i) 3427f2ac410Schristos regcache->raw_collect 3437f2ac410Schristos (i, FPREG_ADDR (fpregsetp, i - gdbarch_fp0_regnum (gdbarch))); 344699b0f92Schristos 345699b0f92Schristos /* Fill in the floating-point control registers. */ 346699b0f92Schristos for (i = M68K_FPC_REGNUM; i <= M68K_FPI_REGNUM; i++) 347699b0f92Schristos if (regno == -1 || regno == i) 3487f2ac410Schristos regcache->raw_collect (i, &fpregsetp->fpcntl[i - M68K_FPC_REGNUM]); 349699b0f92Schristos } 350699b0f92Schristos 351699b0f92Schristos #ifdef HAVE_PTRACE_GETREGS 352699b0f92Schristos 353699b0f92Schristos /* Fetch all floating-point registers from process/thread TID and store 354699b0f92Schristos thier values in GDB's register array. */ 355699b0f92Schristos 356699b0f92Schristos static void 357699b0f92Schristos fetch_fpregs (struct regcache *regcache, int tid) 358699b0f92Schristos { 359699b0f92Schristos elf_fpregset_t fpregs; 360699b0f92Schristos 361699b0f92Schristos if (ptrace (PTRACE_GETFPREGS, tid, 0, (int) &fpregs) < 0) 362699b0f92Schristos perror_with_name (_("Couldn't get floating point status")); 363699b0f92Schristos 364699b0f92Schristos supply_fpregset (regcache, (const elf_fpregset_t *) &fpregs); 365699b0f92Schristos } 366699b0f92Schristos 367699b0f92Schristos /* Store all valid floating-point registers in GDB's register array 368699b0f92Schristos into the process/thread specified by TID. */ 369699b0f92Schristos 370699b0f92Schristos static void 371699b0f92Schristos store_fpregs (const struct regcache *regcache, int tid, int regno) 372699b0f92Schristos { 373699b0f92Schristos elf_fpregset_t fpregs; 374699b0f92Schristos 375699b0f92Schristos if (ptrace (PTRACE_GETFPREGS, tid, 0, (int) &fpregs) < 0) 376699b0f92Schristos perror_with_name (_("Couldn't get floating point status")); 377699b0f92Schristos 378699b0f92Schristos fill_fpregset (regcache, &fpregs, regno); 379699b0f92Schristos 380699b0f92Schristos if (ptrace (PTRACE_SETFPREGS, tid, 0, (int) &fpregs) < 0) 381699b0f92Schristos perror_with_name (_("Couldn't write floating point status")); 382699b0f92Schristos } 383699b0f92Schristos 384699b0f92Schristos #else 385699b0f92Schristos 386699b0f92Schristos static void fetch_fpregs (struct regcache *regcache, int tid) 387699b0f92Schristos { 388699b0f92Schristos } 389699b0f92Schristos 390699b0f92Schristos static void store_fpregs (const struct regcache *regcache, int tid, int regno) 391699b0f92Schristos { 392699b0f92Schristos } 393699b0f92Schristos 394699b0f92Schristos #endif 395699b0f92Schristos 396699b0f92Schristos /* Transferring arbitrary registers between GDB and inferior. */ 397699b0f92Schristos 398699b0f92Schristos /* Fetch register REGNO from the child process. If REGNO is -1, do 399699b0f92Schristos this for all registers (including the floating point and SSE 400699b0f92Schristos registers). */ 401699b0f92Schristos 4027f2ac410Schristos void 4037f2ac410Schristos m68k_linux_nat_target::fetch_registers (struct regcache *regcache, int regno) 404699b0f92Schristos { 405699b0f92Schristos pid_t tid; 406699b0f92Schristos 407699b0f92Schristos /* Use the old method of peeking around in `struct user' if the 408699b0f92Schristos GETREGS request isn't available. */ 409699b0f92Schristos if (! have_ptrace_getregs) 410699b0f92Schristos { 411699b0f92Schristos old_fetch_inferior_registers (regcache, regno); 412699b0f92Schristos return; 413699b0f92Schristos } 414699b0f92Schristos 4157f2ac410Schristos tid = get_ptrace_pid (regcache->ptid ()); 416699b0f92Schristos 417699b0f92Schristos /* Use the PTRACE_GETFPXREGS request whenever possible, since it 418699b0f92Schristos transfers more registers in one system call, and we'll cache the 419699b0f92Schristos results. But remember that fetch_fpxregs can fail, and return 420699b0f92Schristos zero. */ 421699b0f92Schristos if (regno == -1) 422699b0f92Schristos { 423699b0f92Schristos fetch_regs (regcache, tid); 424699b0f92Schristos 425699b0f92Schristos /* The call above might reset `have_ptrace_getregs'. */ 426699b0f92Schristos if (! have_ptrace_getregs) 427699b0f92Schristos { 428699b0f92Schristos old_fetch_inferior_registers (regcache, -1); 429699b0f92Schristos return; 430699b0f92Schristos } 431699b0f92Schristos 432699b0f92Schristos fetch_fpregs (regcache, tid); 433699b0f92Schristos return; 434699b0f92Schristos } 435699b0f92Schristos 436699b0f92Schristos if (getregs_supplies (regno)) 437699b0f92Schristos { 438699b0f92Schristos fetch_regs (regcache, tid); 439699b0f92Schristos return; 440699b0f92Schristos } 441699b0f92Schristos 442699b0f92Schristos if (getfpregs_supplies (regno)) 443699b0f92Schristos { 444699b0f92Schristos fetch_fpregs (regcache, tid); 445699b0f92Schristos return; 446699b0f92Schristos } 447699b0f92Schristos 448*6881a400Schristos internal_error (_("Got request for bad register number %d."), regno); 449699b0f92Schristos } 450699b0f92Schristos 451699b0f92Schristos /* Store register REGNO back into the child process. If REGNO is -1, 452699b0f92Schristos do this for all registers (including the floating point and SSE 453699b0f92Schristos registers). */ 4547f2ac410Schristos void 4557f2ac410Schristos m68k_linux_nat_target::store_registers (struct regcache *regcache, int regno) 456699b0f92Schristos { 457699b0f92Schristos pid_t tid; 458699b0f92Schristos 459699b0f92Schristos /* Use the old method of poking around in `struct user' if the 460699b0f92Schristos SETREGS request isn't available. */ 461699b0f92Schristos if (! have_ptrace_getregs) 462699b0f92Schristos { 463699b0f92Schristos old_store_inferior_registers (regcache, regno); 464699b0f92Schristos return; 465699b0f92Schristos } 466699b0f92Schristos 4677f2ac410Schristos tid = get_ptrace_pid (regcache->ptid ()); 468699b0f92Schristos 469699b0f92Schristos /* Use the PTRACE_SETFPREGS requests whenever possible, since it 470699b0f92Schristos transfers more registers in one system call. But remember that 471699b0f92Schristos store_fpregs can fail, and return zero. */ 472699b0f92Schristos if (regno == -1) 473699b0f92Schristos { 474699b0f92Schristos store_regs (regcache, tid, regno); 475699b0f92Schristos store_fpregs (regcache, tid, regno); 476699b0f92Schristos return; 477699b0f92Schristos } 478699b0f92Schristos 479699b0f92Schristos if (getregs_supplies (regno)) 480699b0f92Schristos { 481699b0f92Schristos store_regs (regcache, tid, regno); 482699b0f92Schristos return; 483699b0f92Schristos } 484699b0f92Schristos 485699b0f92Schristos if (getfpregs_supplies (regno)) 486699b0f92Schristos { 487699b0f92Schristos store_fpregs (regcache, tid, regno); 488699b0f92Schristos return; 489699b0f92Schristos } 490699b0f92Schristos 491*6881a400Schristos internal_error (_("Got request to store bad register number %d."), regno); 492699b0f92Schristos } 493699b0f92Schristos 494699b0f92Schristos 495699b0f92Schristos /* Fetch the thread-local storage pointer for libthread_db. */ 496699b0f92Schristos 497699b0f92Schristos ps_err_e 498699b0f92Schristos ps_get_thread_area (struct ps_prochandle *ph, 499699b0f92Schristos lwpid_t lwpid, int idx, void **base) 500699b0f92Schristos { 501699b0f92Schristos if (ptrace (PTRACE_GET_THREAD_AREA, lwpid, NULL, base) < 0) 502699b0f92Schristos return PS_ERR; 503699b0f92Schristos 504699b0f92Schristos /* IDX is the bias from the thread pointer to the beginning of the 505699b0f92Schristos thread descriptor. It has to be subtracted due to implementation 506699b0f92Schristos quirks in libthread_db. */ 507699b0f92Schristos *base = (char *) *base - idx; 508699b0f92Schristos 509699b0f92Schristos return PS_OK; 510699b0f92Schristos } 511699b0f92Schristos 5127d62b00eSchristos void _initialize_m68k_linux_nat (); 513699b0f92Schristos void 5147d62b00eSchristos _initialize_m68k_linux_nat () 515699b0f92Schristos { 516699b0f92Schristos /* Register the target. */ 5177f2ac410Schristos linux_target = &the_m68k_linux_nat_target; 5187f2ac410Schristos add_inf_child_target (&the_m68k_linux_nat_target); 519699b0f92Schristos } 520