1 /* Target-dependent code for GNU/Linux on LoongArch processors. 2 3 Copyright (C) 2022-2024 Free Software Foundation, Inc. 4 Contributed by Loongson Ltd. 5 6 This file is part of GDB. 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 3 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 20 21 #include "extract-store-integer.h" 22 #include "glibc-tdep.h" 23 #include "inferior.h" 24 #include "linux-tdep.h" 25 #include "loongarch-tdep.h" 26 #include "solib-svr4.h" 27 #include "target-descriptions.h" 28 #include "trad-frame.h" 29 #include "tramp-frame.h" 30 #include "xml-syscall.h" 31 32 /* The syscall's XML filename for LoongArch. */ 33 #define XML_SYSCALL_FILENAME_LOONGARCH "syscalls/loongarch-linux.xml" 34 35 /* Unpack an elf_gregset_t into GDB's register cache. */ 36 37 static void 38 loongarch_supply_gregset (const struct regset *regset, 39 struct regcache *regcache, int regnum, 40 const void *gprs, size_t len) 41 { 42 int regsize = register_size (regcache->arch (), 0); 43 const gdb_byte *buf = nullptr; 44 45 if (regnum == -1) 46 { 47 regcache->raw_supply_zeroed (0); 48 49 for (int i = 1; i < 32; i++) 50 { 51 buf = (const gdb_byte*) gprs + regsize * i; 52 regcache->raw_supply (i, (const void *) buf); 53 } 54 55 buf = (const gdb_byte*) gprs + regsize * LOONGARCH_ORIG_A0_REGNUM; 56 regcache->raw_supply (LOONGARCH_ORIG_A0_REGNUM, (const void *) buf); 57 58 buf = (const gdb_byte*) gprs + regsize * LOONGARCH_PC_REGNUM; 59 regcache->raw_supply (LOONGARCH_PC_REGNUM, (const void *) buf); 60 61 buf = (const gdb_byte*) gprs + regsize * LOONGARCH_BADV_REGNUM; 62 regcache->raw_supply (LOONGARCH_BADV_REGNUM, (const void *) buf); 63 } 64 else if (regnum == 0) 65 regcache->raw_supply_zeroed (0); 66 else if ((regnum > 0 && regnum < 32) 67 || regnum == LOONGARCH_ORIG_A0_REGNUM 68 || regnum == LOONGARCH_PC_REGNUM 69 || regnum == LOONGARCH_BADV_REGNUM) 70 { 71 buf = (const gdb_byte*) gprs + regsize * regnum; 72 regcache->raw_supply (regnum, (const void *) buf); 73 } 74 } 75 76 /* Pack the GDB's register cache value into an elf_gregset_t. */ 77 78 static void 79 loongarch_fill_gregset (const struct regset *regset, 80 const struct regcache *regcache, int regnum, 81 void *gprs, size_t len) 82 { 83 int regsize = register_size (regcache->arch (), 0); 84 gdb_byte *buf = nullptr; 85 86 if (regnum == -1) 87 { 88 for (int i = 0; i < 32; i++) 89 { 90 buf = (gdb_byte *) gprs + regsize * i; 91 regcache->raw_collect (i, (void *) buf); 92 } 93 94 buf = (gdb_byte *) gprs + regsize * LOONGARCH_ORIG_A0_REGNUM; 95 regcache->raw_collect (LOONGARCH_ORIG_A0_REGNUM, (void *) buf); 96 97 buf = (gdb_byte *) gprs + regsize * LOONGARCH_PC_REGNUM; 98 regcache->raw_collect (LOONGARCH_PC_REGNUM, (void *) buf); 99 100 buf = (gdb_byte *) gprs + regsize * LOONGARCH_BADV_REGNUM; 101 regcache->raw_collect (LOONGARCH_BADV_REGNUM, (void *) buf); 102 } 103 else if ((regnum >= 0 && regnum < 32) 104 || regnum == LOONGARCH_ORIG_A0_REGNUM 105 || regnum == LOONGARCH_PC_REGNUM 106 || regnum == LOONGARCH_BADV_REGNUM) 107 { 108 buf = (gdb_byte *) gprs + regsize * regnum; 109 regcache->raw_collect (regnum, (void *) buf); 110 } 111 } 112 113 /* Define the general register regset. */ 114 115 const struct regset loongarch_gregset = 116 { 117 nullptr, 118 loongarch_supply_gregset, 119 loongarch_fill_gregset, 120 }; 121 122 /* Unpack an elf_fpregset_t into GDB's register cache. */ 123 static void 124 loongarch_supply_fpregset (const struct regset *r, 125 struct regcache *regcache, int regnum, 126 const void *fprs, size_t len) 127 { 128 const gdb_byte *buf = nullptr; 129 int fprsize = register_size (regcache->arch (), LOONGARCH_FIRST_FP_REGNUM); 130 int fccsize = register_size (regcache->arch (), LOONGARCH_FIRST_FCC_REGNUM); 131 132 if (regnum == -1) 133 { 134 for (int i = 0; i < LOONGARCH_LINUX_NUM_FPREGSET; i++) 135 { 136 buf = (const gdb_byte *)fprs + fprsize * i; 137 regcache->raw_supply (LOONGARCH_FIRST_FP_REGNUM + i, (const void *)buf); 138 } 139 for (int i = 0; i < LOONGARCH_LINUX_NUM_FCC; i++) 140 { 141 buf = (const gdb_byte *)fprs + fprsize * LOONGARCH_LINUX_NUM_FPREGSET + 142 fccsize * i; 143 regcache->raw_supply (LOONGARCH_FIRST_FCC_REGNUM + i, (const void *)buf); 144 } 145 buf = (const gdb_byte *)fprs + fprsize * LOONGARCH_LINUX_NUM_FPREGSET + 146 fccsize * LOONGARCH_LINUX_NUM_FCC; 147 regcache->raw_supply (LOONGARCH_FCSR_REGNUM, (const void *)buf); 148 } 149 else if (regnum >= LOONGARCH_FIRST_FP_REGNUM && regnum < LOONGARCH_FIRST_FCC_REGNUM) 150 { 151 buf = (const gdb_byte *)fprs + fprsize * (regnum - LOONGARCH_FIRST_FP_REGNUM); 152 regcache->raw_supply (regnum, (const void *)buf); 153 } 154 else if (regnum >= LOONGARCH_FIRST_FCC_REGNUM && regnum < LOONGARCH_FCSR_REGNUM) 155 { 156 buf = (const gdb_byte *)fprs + fprsize * LOONGARCH_LINUX_NUM_FPREGSET + 157 fccsize * (regnum - LOONGARCH_FIRST_FCC_REGNUM); 158 regcache->raw_supply (regnum, (const void *)buf); 159 } 160 else if (regnum == LOONGARCH_FCSR_REGNUM) 161 { 162 buf = (const gdb_byte *)fprs + fprsize * LOONGARCH_LINUX_NUM_FPREGSET + 163 fccsize * LOONGARCH_LINUX_NUM_FCC; 164 regcache->raw_supply (regnum, (const void *)buf); 165 } 166 } 167 168 /* Pack the GDB's register cache value into an elf_fpregset_t. */ 169 static void 170 loongarch_fill_fpregset (const struct regset *r, 171 const struct regcache *regcache, int regnum, 172 void *fprs, size_t len) 173 { 174 gdb_byte *buf = nullptr; 175 int fprsize = register_size (regcache->arch (), LOONGARCH_FIRST_FP_REGNUM); 176 int fccsize = register_size (regcache->arch (), LOONGARCH_FIRST_FCC_REGNUM); 177 178 if (regnum == -1) 179 { 180 for (int i = 0; i < LOONGARCH_LINUX_NUM_FPREGSET; i++) 181 { 182 buf = (gdb_byte *)fprs + fprsize * i; 183 regcache->raw_collect (LOONGARCH_FIRST_FP_REGNUM + i, (void *)buf); 184 } 185 for (int i = 0; i < LOONGARCH_LINUX_NUM_FCC; i++) 186 { 187 buf = (gdb_byte *)fprs + fprsize * LOONGARCH_LINUX_NUM_FPREGSET + 188 fccsize * i; 189 regcache->raw_collect (LOONGARCH_FIRST_FCC_REGNUM + i, (void *)buf); 190 } 191 buf = (gdb_byte *)fprs + fprsize * LOONGARCH_LINUX_NUM_FPREGSET + 192 fccsize * LOONGARCH_LINUX_NUM_FCC; 193 regcache->raw_collect (LOONGARCH_FCSR_REGNUM, (void *)buf); 194 } 195 else if (regnum >= LOONGARCH_FIRST_FP_REGNUM && regnum < LOONGARCH_FIRST_FCC_REGNUM) 196 { 197 buf = (gdb_byte *)fprs + fprsize * (regnum - LOONGARCH_FIRST_FP_REGNUM); 198 regcache->raw_collect (regnum, (void *)buf); 199 } 200 else if (regnum >= LOONGARCH_FIRST_FCC_REGNUM && regnum < LOONGARCH_FCSR_REGNUM) 201 { 202 buf = (gdb_byte *)fprs + fprsize * LOONGARCH_LINUX_NUM_FPREGSET + 203 fccsize * (regnum - LOONGARCH_FIRST_FCC_REGNUM); 204 regcache->raw_collect (regnum, (void *)buf); 205 } 206 else if (regnum == LOONGARCH_FCSR_REGNUM) 207 { 208 buf = (gdb_byte *)fprs + fprsize * LOONGARCH_LINUX_NUM_FPREGSET + 209 fccsize * LOONGARCH_LINUX_NUM_FCC; 210 regcache->raw_collect (regnum, (void *)buf); 211 } 212 } 213 214 /* Define the FP register regset. */ 215 const struct regset loongarch_fpregset = 216 { 217 nullptr, 218 loongarch_supply_fpregset, 219 loongarch_fill_fpregset, 220 }; 221 222 /* Unpack elf_lsxregset_t into GDB's register cache. */ 223 224 static void 225 loongarch_supply_lsxregset (const struct regset *regset, 226 struct regcache *regcache, int regnum, 227 const void *lsxrs, size_t len) 228 { 229 int lsxrsize = register_size (regcache->arch (), LOONGARCH_FIRST_LSX_REGNUM); 230 const gdb_byte *buf = nullptr; 231 232 if (regnum == -1) 233 { 234 for (int i = 0; i < LOONGARCH_LINUX_NUM_LSXREGSET; i++) 235 { 236 buf = (const gdb_byte*) lsxrs + lsxrsize * i; 237 regcache->raw_supply (LOONGARCH_FIRST_LSX_REGNUM + i, (const void *) buf); 238 } 239 240 } 241 else if (regnum >= LOONGARCH_FIRST_LSX_REGNUM && regnum < LOONGARCH_FIRST_LASX_REGNUM) 242 { 243 buf = (const gdb_byte*) lsxrs + lsxrsize * (regnum - LOONGARCH_FIRST_LSX_REGNUM); 244 regcache->raw_supply (regnum, (const void *) buf); 245 } 246 } 247 248 /* Pack the GDB's register cache value into an elf_lsxregset_t. */ 249 250 static void 251 loongarch_fill_lsxregset (const struct regset *regset, 252 const struct regcache *regcache, int regnum, 253 void *lsxrs, size_t len) 254 { 255 int lsxrsize = register_size (regcache->arch (), LOONGARCH_FIRST_LSX_REGNUM); 256 gdb_byte *buf = nullptr; 257 258 if (regnum == -1) 259 { 260 for (int i = 0; i < LOONGARCH_LINUX_NUM_LSXREGSET; i++) 261 { 262 buf = (gdb_byte *) lsxrs + lsxrsize * i; 263 regcache->raw_collect (LOONGARCH_FIRST_LSX_REGNUM + i, (void *) buf); 264 } 265 } 266 else if (regnum >= LOONGARCH_FIRST_LSX_REGNUM && regnum < LOONGARCH_FIRST_LASX_REGNUM) 267 { 268 buf = (gdb_byte *) lsxrs + lsxrsize * (regnum - LOONGARCH_FIRST_LSX_REGNUM); 269 regcache->raw_collect (regnum, (void *) buf); 270 } 271 } 272 273 /* Define the Loongson SIMD Extension register regset. */ 274 275 const struct regset loongarch_lsxregset = 276 { 277 nullptr, 278 loongarch_supply_lsxregset, 279 loongarch_fill_lsxregset, 280 }; 281 282 /* Unpack elf_lasxregset_t into GDB's register cache. */ 283 284 static void 285 loongarch_supply_lasxregset (const struct regset *regset, 286 struct regcache *regcache, int regnum, 287 const void *lasxrs, size_t len) 288 { 289 int lasxrsize = register_size (regcache->arch (), LOONGARCH_FIRST_LASX_REGNUM); 290 const gdb_byte *buf = nullptr; 291 292 if (regnum == -1) 293 { 294 for (int i = 0; i < LOONGARCH_LINUX_NUM_LASXREGSET; i++) 295 { 296 buf = (const gdb_byte*) lasxrs + lasxrsize * i; 297 regcache->raw_supply (LOONGARCH_FIRST_LASX_REGNUM + i, (const void *) buf); 298 } 299 300 } 301 else if (regnum >= LOONGARCH_FIRST_LASX_REGNUM 302 && regnum < LOONGARCH_FIRST_LASX_REGNUM + LOONGARCH_LINUX_NUM_LASXREGSET) 303 { 304 buf = (const gdb_byte*) lasxrs + lasxrsize * (regnum - LOONGARCH_FIRST_LASX_REGNUM); 305 regcache->raw_supply (regnum, (const void *) buf); 306 } 307 } 308 309 /* Pack the GDB's register cache value into an elf_lasxregset_t. */ 310 311 static void 312 loongarch_fill_lasxregset (const struct regset *regset, 313 const struct regcache *regcache, int regnum, 314 void *lasxrs, size_t len) 315 { 316 int lasxrsize = register_size (regcache->arch (), LOONGARCH_FIRST_LASX_REGNUM); 317 gdb_byte *buf = nullptr; 318 319 if (regnum == -1) 320 { 321 for (int i = 0; i < LOONGARCH_LINUX_NUM_LASXREGSET; i++) 322 { 323 buf = (gdb_byte *) lasxrs + lasxrsize * i; 324 regcache->raw_collect (LOONGARCH_FIRST_LASX_REGNUM + i, (void *) buf); 325 } 326 } 327 else if (regnum >= LOONGARCH_FIRST_LASX_REGNUM 328 && regnum < LOONGARCH_FIRST_LASX_REGNUM + LOONGARCH_LINUX_NUM_LASXREGSET) 329 330 { 331 buf = (gdb_byte *) lasxrs + lasxrsize * (regnum - LOONGARCH_FIRST_LASX_REGNUM); 332 regcache->raw_collect (regnum, (void *) buf); 333 } 334 } 335 336 /* Define the Loongson Advanced SIMD Extension register regset. */ 337 338 const struct regset loongarch_lasxregset = 339 { 340 nullptr, 341 loongarch_supply_lasxregset, 342 loongarch_fill_lasxregset, 343 }; 344 345 /* Unpack an lbt regset into GDB's register cache. */ 346 347 static void 348 loongarch_supply_lbtregset (const struct regset *regset, 349 struct regcache *regcache, int regnum, 350 const void *regs, size_t len) 351 { 352 int scrsize = register_size (regcache->arch (), LOONGARCH_FIRST_SCR_REGNUM); 353 int eflagssize = register_size (regcache->arch (), LOONGARCH_EFLAGS_REGNUM); 354 const gdb_byte *buf = nullptr; 355 356 if (regnum == -1) 357 { 358 for (int i = 0; i < LOONGARCH_LINUX_NUM_SCR; i++) 359 { 360 buf = (const gdb_byte *) regs + scrsize * i; 361 regcache->raw_supply (LOONGARCH_FIRST_SCR_REGNUM + i, 362 (const void *) buf); 363 } 364 365 buf = (const gdb_byte*) regs + scrsize * LOONGARCH_LINUX_NUM_SCR; 366 regcache->raw_supply (LOONGARCH_EFLAGS_REGNUM, (const void *) buf); 367 368 buf = (const gdb_byte*) regs 369 + scrsize * LOONGARCH_LINUX_NUM_SCR 370 + eflagssize; 371 regcache->raw_supply (LOONGARCH_FTOP_REGNUM, (const void *) buf); 372 } 373 else if (regnum >= LOONGARCH_FIRST_SCR_REGNUM 374 && regnum <= LOONGARCH_LAST_SCR_REGNUM) 375 { 376 buf = (const gdb_byte*) regs 377 + scrsize * (regnum - LOONGARCH_FIRST_SCR_REGNUM); 378 regcache->raw_supply (regnum, (const void *) buf); 379 } 380 else if (regnum == LOONGARCH_EFLAGS_REGNUM) 381 { 382 buf = (const gdb_byte*) regs + scrsize * LOONGARCH_LINUX_NUM_SCR; 383 regcache->raw_supply (regnum, (const void *) buf); 384 } 385 else if (regnum == LOONGARCH_FTOP_REGNUM) 386 { 387 buf = (const gdb_byte*) regs 388 + scrsize * LOONGARCH_LINUX_NUM_SCR 389 + eflagssize; 390 regcache->raw_supply (regnum, (const void *) buf); 391 } 392 } 393 394 /* Pack the GDB's register cache value into an lbt regset. */ 395 396 static void 397 loongarch_fill_lbtregset (const struct regset *regset, 398 const struct regcache *regcache, int regnum, 399 void *regs, size_t len) 400 { 401 int scrsize = register_size (regcache->arch (), LOONGARCH_FIRST_SCR_REGNUM); 402 int eflagssize = register_size (regcache->arch (), LOONGARCH_EFLAGS_REGNUM); 403 gdb_byte *buf = nullptr; 404 405 if (regnum == -1) 406 { 407 for (int i = 0; i < LOONGARCH_LINUX_NUM_SCR; i++) 408 { 409 buf = (gdb_byte *) regs + scrsize * i; 410 regcache->raw_collect (LOONGARCH_FIRST_SCR_REGNUM + i, (void *) buf); 411 } 412 413 buf = (gdb_byte *) regs + scrsize * LOONGARCH_LINUX_NUM_SCR; 414 regcache->raw_collect (LOONGARCH_EFLAGS_REGNUM, (void *) buf); 415 416 buf = (gdb_byte *) regs + scrsize * LOONGARCH_LINUX_NUM_SCR + eflagssize; 417 regcache->raw_collect (LOONGARCH_FTOP_REGNUM, (void *) buf); 418 } 419 else if (regnum >= LOONGARCH_FIRST_SCR_REGNUM 420 && regnum <= LOONGARCH_LAST_SCR_REGNUM) 421 { 422 buf = (gdb_byte *) regs + scrsize * (regnum - LOONGARCH_FIRST_SCR_REGNUM); 423 regcache->raw_collect (regnum, (void *) buf); 424 } 425 else if (regnum == LOONGARCH_EFLAGS_REGNUM) 426 { 427 buf = (gdb_byte *) regs + scrsize * LOONGARCH_LINUX_NUM_SCR; 428 regcache->raw_collect (regnum, (void *) buf); 429 } 430 else if (regnum == LOONGARCH_FTOP_REGNUM) 431 { 432 buf = (gdb_byte *) regs + scrsize * LOONGARCH_LINUX_NUM_SCR + eflagssize; 433 regcache->raw_collect (regnum, (void *) buf); 434 } 435 } 436 437 /* Define the lbt register regset. */ 438 439 const struct regset loongarch_lbtregset = 440 { 441 nullptr, 442 loongarch_supply_lbtregset, 443 loongarch_fill_lbtregset, 444 }; 445 446 /* Implement the "init" method of struct tramp_frame. */ 447 448 #define LOONGARCH_RT_SIGFRAME_UCONTEXT_OFFSET 128 449 #define LOONGARCH_UCONTEXT_SIGCONTEXT_OFFSET 176 450 451 static void 452 loongarch_linux_rt_sigframe_init (const struct tramp_frame *self, 453 const frame_info_ptr &this_frame, 454 struct trad_frame_cache *this_cache, 455 CORE_ADDR func) 456 { 457 CORE_ADDR frame_sp = get_frame_sp (this_frame); 458 CORE_ADDR sigcontext_base = (frame_sp + LOONGARCH_RT_SIGFRAME_UCONTEXT_OFFSET 459 + LOONGARCH_UCONTEXT_SIGCONTEXT_OFFSET); 460 461 trad_frame_set_reg_addr (this_cache, LOONGARCH_PC_REGNUM, sigcontext_base); 462 for (int i = 0; i < 32; i++) 463 trad_frame_set_reg_addr (this_cache, i, sigcontext_base + 8 + i * 8); 464 465 trad_frame_set_id (this_cache, frame_id_build (frame_sp, func)); 466 } 467 468 /* li.w a7, __NR_rt_sigreturn */ 469 #define LOONGARCH_INST_LIW_A7_RT_SIGRETURN 0x03822c0b 470 /* syscall 0 */ 471 #define LOONGARCH_INST_SYSCALL 0x002b0000 472 473 static const struct tramp_frame loongarch_linux_rt_sigframe = 474 { 475 SIGTRAMP_FRAME, 476 4, 477 { 478 { LOONGARCH_INST_LIW_A7_RT_SIGRETURN, ULONGEST_MAX }, 479 { LOONGARCH_INST_SYSCALL, ULONGEST_MAX }, 480 { TRAMP_SENTINEL_INSN, ULONGEST_MAX } 481 }, 482 loongarch_linux_rt_sigframe_init, 483 nullptr 484 }; 485 486 /* Implement the "iterate_over_regset_sections" gdbarch method. */ 487 488 static void 489 loongarch_iterate_over_regset_sections (struct gdbarch *gdbarch, 490 iterate_over_regset_sections_cb *cb, 491 void *cb_data, 492 const struct regcache *regcache) 493 { 494 int gprsize = register_size (gdbarch, 0); 495 int gpsize = gprsize * LOONGARCH_LINUX_NUM_GREGSET; 496 int fprsize = register_size (gdbarch, LOONGARCH_FIRST_FP_REGNUM); 497 int fccsize = register_size (gdbarch, LOONGARCH_FIRST_FCC_REGNUM); 498 int fcsrsize = register_size (gdbarch, LOONGARCH_FCSR_REGNUM); 499 int fpsize = fprsize * LOONGARCH_LINUX_NUM_FPREGSET + 500 fccsize * LOONGARCH_LINUX_NUM_FCC + fcsrsize; 501 int lsxrsize = register_size (gdbarch, LOONGARCH_FIRST_LSX_REGNUM); 502 int lsxsize = lsxrsize * LOONGARCH_LINUX_NUM_LSXREGSET; 503 int lasxrsize = register_size (gdbarch, LOONGARCH_FIRST_LASX_REGNUM); 504 int lasxsize = lasxrsize * LOONGARCH_LINUX_NUM_LASXREGSET; 505 int scrsize = register_size (gdbarch, LOONGARCH_FIRST_SCR_REGNUM); 506 int eflagssize = register_size (gdbarch, LOONGARCH_EFLAGS_REGNUM); 507 int ftopsize = register_size (gdbarch, LOONGARCH_FTOP_REGNUM); 508 int lbtsize = scrsize * LOONGARCH_LINUX_NUM_SCR + eflagssize + ftopsize; 509 510 cb (".reg", gpsize, gpsize, 511 &loongarch_gregset, nullptr, cb_data); 512 cb (".reg2", fpsize, fpsize, 513 &loongarch_fpregset, nullptr, cb_data); 514 cb (".reg-loongarch-lsx", lsxsize, lsxsize, 515 &loongarch_lsxregset, nullptr, cb_data); 516 cb (".reg-loongarch-lasx", lasxsize, lasxsize, 517 &loongarch_lasxregset, nullptr, cb_data); 518 cb (".reg-loongarch-lbt", lbtsize, lbtsize, 519 &loongarch_lbtregset, nullptr, cb_data); 520 } 521 522 /* The following value is derived from __NR_rt_sigreturn in 523 <include/uapi/asm-generic/unistd.h> from the Linux source tree. */ 524 525 #define LOONGARCH_NR_rt_sigreturn 139 526 527 /* When FRAME is at a syscall instruction, return the PC of the next 528 instruction to be executed. */ 529 530 static CORE_ADDR 531 loongarch_linux_syscall_next_pc (const frame_info_ptr &frame) 532 { 533 const CORE_ADDR pc = get_frame_pc (frame); 534 ULONGEST a7 = get_frame_register_unsigned (frame, LOONGARCH_A7_REGNUM); 535 536 /* If we are about to make a sigreturn syscall, use the unwinder to 537 decode the signal frame. */ 538 if (a7 == LOONGARCH_NR_rt_sigreturn) 539 return frame_unwind_caller_pc (frame); 540 541 return pc + 4; 542 } 543 544 /* Implement the "get_syscall_number" gdbarch method. */ 545 546 static LONGEST 547 loongarch_linux_get_syscall_number (struct gdbarch *gdbarch, thread_info *thread) 548 { 549 struct regcache *regcache = get_thread_regcache (thread); 550 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); 551 int regsize = register_size (gdbarch, LOONGARCH_A7_REGNUM); 552 /* The content of a register. */ 553 gdb_byte buf[8]; 554 /* The result. */ 555 LONGEST ret; 556 557 gdb_assert (regsize <= sizeof (buf)); 558 559 /* Getting the system call number from the register. 560 When dealing with the LoongArch architecture, this information 561 is stored at the a7 register. */ 562 regcache->cooked_read (LOONGARCH_A7_REGNUM, buf); 563 564 ret = extract_signed_integer (buf, regsize, byte_order); 565 566 return ret; 567 } 568 569 /* Initialize LoongArch Linux ABI info. */ 570 571 static void 572 loongarch_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) 573 { 574 loongarch_gdbarch_tdep *tdep = gdbarch_tdep<loongarch_gdbarch_tdep> (gdbarch); 575 576 linux_init_abi (info, gdbarch, 0); 577 578 set_solib_svr4_fetch_link_map_offsets (gdbarch, 579 info.bfd_arch_info->bits_per_address == 32 580 ? linux_ilp32_fetch_link_map_offsets 581 : linux_lp64_fetch_link_map_offsets); 582 583 /* GNU/Linux uses SVR4-style shared libraries. */ 584 set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target); 585 586 /* GNU/Linux uses the dynamic linker included in the GNU C Library. */ 587 set_gdbarch_skip_solib_resolver (gdbarch, glibc_skip_solib_resolver); 588 589 /* Enable TLS support. */ 590 set_gdbarch_fetch_tls_load_module_address (gdbarch, svr4_fetch_objfile_link_map); 591 592 /* Prepend tramp frame unwinder for signal. */ 593 tramp_frame_prepend_unwinder (gdbarch, &loongarch_linux_rt_sigframe); 594 595 /* Core file support. */ 596 set_gdbarch_iterate_over_regset_sections (gdbarch, loongarch_iterate_over_regset_sections); 597 598 tdep->syscall_next_pc = loongarch_linux_syscall_next_pc; 599 600 /* Set the correct XML syscall filename. */ 601 set_xml_syscall_file_name (gdbarch, XML_SYSCALL_FILENAME_LOONGARCH); 602 603 /* Get the syscall number from the arch's register. */ 604 set_gdbarch_get_syscall_number (gdbarch, loongarch_linux_get_syscall_number); 605 } 606 607 /* Initialize LoongArch Linux target support. */ 608 609 void _initialize_loongarch_linux_tdep (); 610 void 611 _initialize_loongarch_linux_tdep () 612 { 613 gdbarch_register_osabi (bfd_arch_loongarch, bfd_mach_loongarch32, 614 GDB_OSABI_LINUX, loongarch_linux_init_abi); 615 gdbarch_register_osabi (bfd_arch_loongarch, bfd_mach_loongarch64, 616 GDB_OSABI_LINUX, loongarch_linux_init_abi); 617 } 618