1 /* Xtensa GNU/Linux native support. 2 3 Copyright (C) 2007-2019 Free Software Foundation, Inc. 4 5 This file is part of GDB. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 19 20 #include "defs.h" 21 #include "frame.h" 22 #include "inferior.h" 23 #include "gdbcore.h" 24 #include "regcache.h" 25 #include "target.h" 26 #include "linux-nat.h" 27 #include <sys/types.h> 28 #include <signal.h> 29 #include <sys/user.h> 30 #include <sys/ioctl.h> 31 #include "common/gdb_wait.h" 32 #include <fcntl.h> 33 #include <sys/procfs.h> 34 #include "nat/gdb_ptrace.h" 35 #include <asm/ptrace.h> 36 37 #include "gregset.h" 38 #include "xtensa-tdep.h" 39 40 /* Defines ps_err_e, struct ps_prochandle. */ 41 #include "gdb_proc_service.h" 42 43 /* Extended register set depends on hardware configs. 44 Keeping these definitions separately allows to introduce 45 hardware-specific overlays. */ 46 #include "xtensa-xtregs.c" 47 48 class xtensa_linux_nat_target final : public linux_nat_target 49 { 50 public: 51 /* Add our register access methods. */ 52 void fetch_registers (struct regcache *, int) override; 53 void store_registers (struct regcache *, int) override; 54 }; 55 56 static xtensa_linux_nat_target the_xtensa_linux_nat_target; 57 58 void 59 fill_gregset (const struct regcache *regcache, 60 gdb_gregset_t *gregsetp, int regnum) 61 { 62 int i; 63 xtensa_elf_gregset_t *regs = (xtensa_elf_gregset_t *) gregsetp; 64 struct gdbarch *gdbarch = regcache->arch (); 65 66 if (regnum == gdbarch_pc_regnum (gdbarch) || regnum == -1) 67 regcache->raw_collect (gdbarch_pc_regnum (gdbarch), ®s->pc); 68 if (regnum == gdbarch_ps_regnum (gdbarch) || regnum == -1) 69 regcache->raw_collect (gdbarch_ps_regnum (gdbarch), ®s->ps); 70 71 if (regnum == gdbarch_tdep (gdbarch)->wb_regnum || regnum == -1) 72 regcache->raw_collect (gdbarch_tdep (gdbarch)->wb_regnum, 73 ®s->windowbase); 74 if (regnum == gdbarch_tdep (gdbarch)->ws_regnum || regnum == -1) 75 regcache->raw_collect (gdbarch_tdep (gdbarch)->ws_regnum, 76 ®s->windowstart); 77 if (regnum == gdbarch_tdep (gdbarch)->lbeg_regnum || regnum == -1) 78 regcache->raw_collect (gdbarch_tdep (gdbarch)->lbeg_regnum, 79 ®s->lbeg); 80 if (regnum == gdbarch_tdep (gdbarch)->lend_regnum || regnum == -1) 81 regcache->raw_collect (gdbarch_tdep (gdbarch)->lend_regnum, 82 ®s->lend); 83 if (regnum == gdbarch_tdep (gdbarch)->lcount_regnum || regnum == -1) 84 regcache->raw_collect (gdbarch_tdep (gdbarch)->lcount_regnum, 85 ®s->lcount); 86 if (regnum == gdbarch_tdep (gdbarch)->sar_regnum || regnum == -1) 87 regcache->raw_collect (gdbarch_tdep (gdbarch)->sar_regnum, 88 ®s->sar); 89 if (regnum == gdbarch_tdep (gdbarch)->threadptr_regnum || regnum == -1) 90 regcache->raw_collect (gdbarch_tdep (gdbarch)->threadptr_regnum, 91 ®s->threadptr); 92 if (regnum >=gdbarch_tdep (gdbarch)->ar_base 93 && regnum < gdbarch_tdep (gdbarch)->ar_base 94 + gdbarch_tdep (gdbarch)->num_aregs) 95 regcache->raw_collect (regnum, 96 ®s->ar[regnum - gdbarch_tdep (gdbarch)->ar_base]); 97 else if (regnum == -1) 98 { 99 for (i = 0; i < gdbarch_tdep (gdbarch)->num_aregs; ++i) 100 regcache->raw_collect (gdbarch_tdep (gdbarch)->ar_base + i, 101 ®s->ar[i]); 102 } 103 if (regnum >= gdbarch_tdep (gdbarch)->a0_base 104 && regnum < gdbarch_tdep (gdbarch)->a0_base + C0_NREGS) 105 regcache->raw_collect (regnum, 106 ®s->ar[(4 * regs->windowbase + regnum 107 - gdbarch_tdep (gdbarch)->a0_base) 108 % gdbarch_tdep (gdbarch)->num_aregs]); 109 else if (regnum == -1) 110 { 111 for (i = 0; i < C0_NREGS; ++i) 112 regcache->raw_collect (gdbarch_tdep (gdbarch)->a0_base + i, 113 (®s->ar[(4 * regs->windowbase + i) 114 % gdbarch_tdep (gdbarch)->num_aregs])); 115 } 116 } 117 118 static void 119 supply_gregset_reg (struct regcache *regcache, 120 const gdb_gregset_t *gregsetp, int regnum) 121 { 122 int i; 123 xtensa_elf_gregset_t *regs = (xtensa_elf_gregset_t *) gregsetp; 124 125 struct gdbarch *gdbarch = regcache->arch (); 126 127 if (regnum == gdbarch_pc_regnum (gdbarch) || regnum == -1) 128 regcache->raw_supply (gdbarch_pc_regnum (gdbarch), ®s->pc); 129 if (regnum == gdbarch_ps_regnum (gdbarch) || regnum == -1) 130 regcache->raw_supply (gdbarch_ps_regnum (gdbarch), ®s->ps); 131 132 if (regnum == gdbarch_tdep (gdbarch)->wb_regnum || regnum == -1) 133 regcache->raw_supply (gdbarch_tdep (gdbarch)->wb_regnum, 134 ®s->windowbase); 135 if (regnum == gdbarch_tdep (gdbarch)->ws_regnum || regnum == -1) 136 regcache->raw_supply (gdbarch_tdep (gdbarch)->ws_regnum, 137 ®s->windowstart); 138 if (regnum == gdbarch_tdep (gdbarch)->lbeg_regnum || regnum == -1) 139 regcache->raw_supply (gdbarch_tdep (gdbarch)->lbeg_regnum, 140 ®s->lbeg); 141 if (regnum == gdbarch_tdep (gdbarch)->lend_regnum || regnum == -1) 142 regcache->raw_supply (gdbarch_tdep (gdbarch)->lend_regnum, 143 ®s->lend); 144 if (regnum == gdbarch_tdep (gdbarch)->lcount_regnum || regnum == -1) 145 regcache->raw_supply (gdbarch_tdep (gdbarch)->lcount_regnum, 146 ®s->lcount); 147 if (regnum == gdbarch_tdep (gdbarch)->sar_regnum || regnum == -1) 148 regcache->raw_supply (gdbarch_tdep (gdbarch)->sar_regnum, 149 ®s->sar); 150 if (regnum == gdbarch_tdep (gdbarch)->threadptr_regnum || regnum == -1) 151 regcache->raw_supply (gdbarch_tdep (gdbarch)->threadptr_regnum, 152 ®s->threadptr); 153 if (regnum >=gdbarch_tdep (gdbarch)->ar_base 154 && regnum < gdbarch_tdep (gdbarch)->ar_base 155 + gdbarch_tdep (gdbarch)->num_aregs) 156 regcache->raw_supply (regnum, 157 ®s->ar[regnum - gdbarch_tdep (gdbarch)->ar_base]); 158 else if (regnum == -1) 159 { 160 for (i = 0; i < gdbarch_tdep (gdbarch)->num_aregs; ++i) 161 regcache->raw_supply (gdbarch_tdep (gdbarch)->ar_base + i, 162 ®s->ar[i]); 163 } 164 if (regnum >= gdbarch_tdep (gdbarch)->a0_base 165 && regnum < gdbarch_tdep (gdbarch)->a0_base + C0_NREGS) 166 regcache->raw_supply (regnum, 167 ®s->ar[(4 * regs->windowbase + regnum 168 - gdbarch_tdep (gdbarch)->a0_base) 169 % gdbarch_tdep (gdbarch)->num_aregs]); 170 else if (regnum == -1) 171 { 172 for (i = 0; i < C0_NREGS; ++i) 173 regcache->raw_supply (gdbarch_tdep (gdbarch)->a0_base + i, 174 ®s->ar[(4 * regs->windowbase + i) 175 % gdbarch_tdep (gdbarch)->num_aregs]); 176 } 177 } 178 179 void 180 supply_gregset (struct regcache *regcache, const gdb_gregset_t *gregsetp) 181 { 182 supply_gregset_reg (regcache, gregsetp, -1); 183 } 184 185 void 186 fill_fpregset (const struct regcache *regcache, 187 gdb_fpregset_t *fpregsetp, int regnum) 188 { 189 return; 190 } 191 192 void 193 supply_fpregset (struct regcache *regcache, 194 const gdb_fpregset_t *fpregsetp) 195 { 196 return; 197 } 198 199 /* Fetch greg-register(s) from process/thread TID 200 and store value(s) in GDB's register array. */ 201 202 static void 203 fetch_gregs (struct regcache *regcache, int regnum) 204 { 205 int tid = regcache->ptid ().lwp (); 206 gdb_gregset_t regs; 207 int areg; 208 209 if (ptrace (PTRACE_GETREGS, tid, 0, (long) ®s) < 0) 210 { 211 perror_with_name (_("Couldn't get registers")); 212 return; 213 } 214 215 supply_gregset_reg (regcache, ®s, regnum); 216 } 217 218 /* Store greg-register(s) in GDB's register 219 array into the process/thread specified by TID. */ 220 221 static void 222 store_gregs (struct regcache *regcache, int regnum) 223 { 224 int tid = regcache->ptid ().lwp (); 225 gdb_gregset_t regs; 226 int areg; 227 228 if (ptrace (PTRACE_GETREGS, tid, 0, (long) ®s) < 0) 229 { 230 perror_with_name (_("Couldn't get registers")); 231 return; 232 } 233 234 fill_gregset (regcache, ®s, regnum); 235 236 if (ptrace (PTRACE_SETREGS, tid, 0, (long) ®s) < 0) 237 { 238 perror_with_name (_("Couldn't write registers")); 239 return; 240 } 241 } 242 243 static int xtreg_lo; 244 static int xtreg_high; 245 246 /* Fetch/Store Xtensa TIE registers. Xtensa GNU/Linux PTRACE 247 interface provides special requests for this. */ 248 249 static void 250 fetch_xtregs (struct regcache *regcache, int regnum) 251 { 252 int tid = regcache->ptid ().lwp (); 253 const xtensa_regtable_t *ptr; 254 char xtregs [XTENSA_ELF_XTREG_SIZE]; 255 256 if (ptrace (PTRACE_GETXTREGS, tid, 0, (long)&xtregs) < 0) 257 perror_with_name (_("Couldn't get extended registers")); 258 259 for (ptr = xtensa_regmap_table; ptr->name; ptr++) 260 if (regnum == ptr->gdb_regnum || regnum == -1) 261 regcache->raw_supply (ptr->gdb_regnum, xtregs + ptr->ptrace_offset); 262 } 263 264 static void 265 store_xtregs (struct regcache *regcache, int regnum) 266 { 267 int tid = regcache->ptid ().lwp (); 268 const xtensa_regtable_t *ptr; 269 char xtregs [XTENSA_ELF_XTREG_SIZE]; 270 271 if (ptrace (PTRACE_GETXTREGS, tid, 0, (long)&xtregs) < 0) 272 perror_with_name (_("Couldn't get extended registers")); 273 274 for (ptr = xtensa_regmap_table; ptr->name; ptr++) 275 if (regnum == ptr->gdb_regnum || regnum == -1) 276 regcache->raw_collect (ptr->gdb_regnum, xtregs + ptr->ptrace_offset); 277 278 if (ptrace (PTRACE_SETXTREGS, tid, 0, (long)&xtregs) < 0) 279 perror_with_name (_("Couldn't write extended registers")); 280 } 281 282 void 283 xtensa_linux_nat_target::fetch_registers (struct regcache *regcache, 284 int regnum) 285 { 286 if (regnum == -1) 287 { 288 fetch_gregs (regcache, regnum); 289 fetch_xtregs (regcache, regnum); 290 } 291 else if ((regnum < xtreg_lo) || (regnum > xtreg_high)) 292 fetch_gregs (regcache, regnum); 293 else 294 fetch_xtregs (regcache, regnum); 295 } 296 297 void 298 xtensa_linux_nat_target::store_registers (struct regcache *regcache, 299 int regnum) 300 { 301 if (regnum == -1) 302 { 303 store_gregs (regcache, regnum); 304 store_xtregs (regcache, regnum); 305 } 306 else if ((regnum < xtreg_lo) || (regnum > xtreg_high)) 307 store_gregs (regcache, regnum); 308 else 309 store_xtregs (regcache, regnum); 310 } 311 312 /* Called by libthread_db. */ 313 314 ps_err_e 315 ps_get_thread_area (struct ps_prochandle *ph, 316 lwpid_t lwpid, int idx, void **base) 317 { 318 xtensa_elf_gregset_t regs; 319 320 if (ptrace (PTRACE_GETREGS, lwpid, NULL, ®s) != 0) 321 return PS_ERR; 322 323 /* IDX is the bias from the thread pointer to the beginning of the 324 thread descriptor. It has to be subtracted due to implementation 325 quirks in libthread_db. */ 326 *base = (void *) ((char *) regs.threadptr - idx); 327 328 return PS_OK; 329 } 330 331 void 332 _initialize_xtensa_linux_nat (void) 333 { 334 const xtensa_regtable_t *ptr; 335 336 /* Calculate the number range for extended registers. */ 337 xtreg_lo = 1000000000; 338 xtreg_high = -1; 339 for (ptr = xtensa_regmap_table; ptr->name; ptr++) 340 { 341 if (ptr->gdb_regnum < xtreg_lo) 342 xtreg_lo = ptr->gdb_regnum; 343 if (ptr->gdb_regnum > xtreg_high) 344 xtreg_high = ptr->gdb_regnum; 345 } 346 347 linux_target = &the_xtensa_linux_nat_target; 348 add_inf_child_target (&the_xtensa_linux_nat_target); 349 } 350