1 /* Target-dependent code for GNU/Linux on LoongArch processors.
3 Copyright (C) 2022-2024 Free Software Foundation, Inc.
4 Contributed by Loongson Ltd.
6 This file is part of GDB.
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.
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.
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/>. */
21 #include "extract-store-integer.h"
22 #include "glibc-tdep.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"
32 /* The syscall's XML filename for LoongArch. */
33 #define XML_SYSCALL_FILENAME_LOONGARCH "syscalls/loongarch-linux.xml"
35 /* Unpack an elf_gregset_t into GDB's register cache. */
38 loongarch_supply_gregset (const struct regset
*regset
,
39 struct regcache
*regcache
, int regnum
,
40 const void *gprs
, size_t len
)
42 int regsize
= register_size (regcache
->arch (), 0);
43 const gdb_byte
*buf
= nullptr;
47 regcache
->raw_supply_zeroed (0);
49 for (int i
= 1; i
< 32; i
++)
51 buf
= (const gdb_byte
*) gprs
+ regsize
* i
;
52 regcache
->raw_supply (i
, (const void *) buf
);
55 buf
= (const gdb_byte
*) gprs
+ regsize
* LOONGARCH_ORIG_A0_REGNUM
;
56 regcache
->raw_supply (LOONGARCH_ORIG_A0_REGNUM
, (const void *) buf
);
58 buf
= (const gdb_byte
*) gprs
+ regsize
* LOONGARCH_PC_REGNUM
;
59 regcache
->raw_supply (LOONGARCH_PC_REGNUM
, (const void *) buf
);
61 buf
= (const gdb_byte
*) gprs
+ regsize
* LOONGARCH_BADV_REGNUM
;
62 regcache
->raw_supply (LOONGARCH_BADV_REGNUM
, (const void *) buf
);
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
)
71 buf
= (const gdb_byte
*) gprs
+ regsize
* regnum
;
72 regcache
->raw_supply (regnum
, (const void *) buf
);
76 /* Pack the GDB's register cache value into an elf_gregset_t. */
79 loongarch_fill_gregset (const struct regset
*regset
,
80 const struct regcache
*regcache
, int regnum
,
81 void *gprs
, size_t len
)
83 int regsize
= register_size (regcache
->arch (), 0);
84 gdb_byte
*buf
= nullptr;
88 for (int i
= 0; i
< 32; i
++)
90 buf
= (gdb_byte
*) gprs
+ regsize
* i
;
91 regcache
->raw_collect (i
, (void *) buf
);
94 buf
= (gdb_byte
*) gprs
+ regsize
* LOONGARCH_ORIG_A0_REGNUM
;
95 regcache
->raw_collect (LOONGARCH_ORIG_A0_REGNUM
, (void *) buf
);
97 buf
= (gdb_byte
*) gprs
+ regsize
* LOONGARCH_PC_REGNUM
;
98 regcache
->raw_collect (LOONGARCH_PC_REGNUM
, (void *) buf
);
100 buf
= (gdb_byte
*) gprs
+ regsize
* LOONGARCH_BADV_REGNUM
;
101 regcache
->raw_collect (LOONGARCH_BADV_REGNUM
, (void *) buf
);
103 else if ((regnum
>= 0 && regnum
< 32)
104 || regnum
== LOONGARCH_ORIG_A0_REGNUM
105 || regnum
== LOONGARCH_PC_REGNUM
106 || regnum
== LOONGARCH_BADV_REGNUM
)
108 buf
= (gdb_byte
*) gprs
+ regsize
* regnum
;
109 regcache
->raw_collect (regnum
, (void *) buf
);
113 /* Define the general register regset. */
115 const struct regset loongarch_gregset
=
118 loongarch_supply_gregset
,
119 loongarch_fill_gregset
,
122 /* Unpack an elf_fpregset_t into GDB's register cache. */
124 loongarch_supply_fpregset (const struct regset
*r
,
125 struct regcache
*regcache
, int regnum
,
126 const void *fprs
, size_t len
)
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
);
134 for (int i
= 0; i
< LOONGARCH_LINUX_NUM_FPREGSET
; i
++)
136 buf
= (const gdb_byte
*)fprs
+ fprsize
* i
;
137 regcache
->raw_supply (LOONGARCH_FIRST_FP_REGNUM
+ i
, (const void *)buf
);
139 for (int i
= 0; i
< LOONGARCH_LINUX_NUM_FCC
; i
++)
141 buf
= (const gdb_byte
*)fprs
+ fprsize
* LOONGARCH_LINUX_NUM_FPREGSET
+
143 regcache
->raw_supply (LOONGARCH_FIRST_FCC_REGNUM
+ i
, (const void *)buf
);
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
);
149 else if (regnum
>= LOONGARCH_FIRST_FP_REGNUM
&& regnum
< LOONGARCH_FIRST_FCC_REGNUM
)
151 buf
= (const gdb_byte
*)fprs
+ fprsize
* (regnum
- LOONGARCH_FIRST_FP_REGNUM
);
152 regcache
->raw_supply (regnum
, (const void *)buf
);
154 else if (regnum
>= LOONGARCH_FIRST_FCC_REGNUM
&& regnum
< LOONGARCH_FCSR_REGNUM
)
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
);
160 else if (regnum
== LOONGARCH_FCSR_REGNUM
)
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
);
168 /* Pack the GDB's register cache value into an elf_fpregset_t. */
170 loongarch_fill_fpregset (const struct regset
*r
,
171 const struct regcache
*regcache
, int regnum
,
172 void *fprs
, size_t len
)
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
);
180 for (int i
= 0; i
< LOONGARCH_LINUX_NUM_FPREGSET
; i
++)
182 buf
= (gdb_byte
*)fprs
+ fprsize
* i
;
183 regcache
->raw_collect (LOONGARCH_FIRST_FP_REGNUM
+ i
, (void *)buf
);
185 for (int i
= 0; i
< LOONGARCH_LINUX_NUM_FCC
; i
++)
187 buf
= (gdb_byte
*)fprs
+ fprsize
* LOONGARCH_LINUX_NUM_FPREGSET
+
189 regcache
->raw_collect (LOONGARCH_FIRST_FCC_REGNUM
+ i
, (void *)buf
);
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
);
195 else if (regnum
>= LOONGARCH_FIRST_FP_REGNUM
&& regnum
< LOONGARCH_FIRST_FCC_REGNUM
)
197 buf
= (gdb_byte
*)fprs
+ fprsize
* (regnum
- LOONGARCH_FIRST_FP_REGNUM
);
198 regcache
->raw_collect (regnum
, (void *)buf
);
200 else if (regnum
>= LOONGARCH_FIRST_FCC_REGNUM
&& regnum
< LOONGARCH_FCSR_REGNUM
)
202 buf
= (gdb_byte
*)fprs
+ fprsize
* LOONGARCH_LINUX_NUM_FPREGSET
+
203 fccsize
* (regnum
- LOONGARCH_FIRST_FCC_REGNUM
);
204 regcache
->raw_collect (regnum
, (void *)buf
);
206 else if (regnum
== LOONGARCH_FCSR_REGNUM
)
208 buf
= (gdb_byte
*)fprs
+ fprsize
* LOONGARCH_LINUX_NUM_FPREGSET
+
209 fccsize
* LOONGARCH_LINUX_NUM_FCC
;
210 regcache
->raw_collect (regnum
, (void *)buf
);
214 /* Define the FP register regset. */
215 const struct regset loongarch_fpregset
=
218 loongarch_supply_fpregset
,
219 loongarch_fill_fpregset
,
222 /* Unpack elf_lsxregset_t into GDB's register cache. */
225 loongarch_supply_lsxregset (const struct regset
*regset
,
226 struct regcache
*regcache
, int regnum
,
227 const void *lsxrs
, size_t len
)
229 int lsxrsize
= register_size (regcache
->arch (), LOONGARCH_FIRST_LSX_REGNUM
);
230 const gdb_byte
*buf
= nullptr;
234 for (int i
= 0; i
< LOONGARCH_LINUX_NUM_LSXREGSET
; i
++)
236 buf
= (const gdb_byte
*) lsxrs
+ lsxrsize
* i
;
237 regcache
->raw_supply (LOONGARCH_FIRST_LSX_REGNUM
+ i
, (const void *) buf
);
241 else if (regnum
>= LOONGARCH_FIRST_LSX_REGNUM
&& regnum
< LOONGARCH_FIRST_LASX_REGNUM
)
243 buf
= (const gdb_byte
*) lsxrs
+ lsxrsize
* (regnum
- LOONGARCH_FIRST_LSX_REGNUM
);
244 regcache
->raw_supply (regnum
, (const void *) buf
);
248 /* Pack the GDB's register cache value into an elf_lsxregset_t. */
251 loongarch_fill_lsxregset (const struct regset
*regset
,
252 const struct regcache
*regcache
, int regnum
,
253 void *lsxrs
, size_t len
)
255 int lsxrsize
= register_size (regcache
->arch (), LOONGARCH_FIRST_LSX_REGNUM
);
256 gdb_byte
*buf
= nullptr;
260 for (int i
= 0; i
< LOONGARCH_LINUX_NUM_LSXREGSET
; i
++)
262 buf
= (gdb_byte
*) lsxrs
+ lsxrsize
* i
;
263 regcache
->raw_collect (LOONGARCH_FIRST_LSX_REGNUM
+ i
, (void *) buf
);
266 else if (regnum
>= LOONGARCH_FIRST_LSX_REGNUM
&& regnum
< LOONGARCH_FIRST_LASX_REGNUM
)
268 buf
= (gdb_byte
*) lsxrs
+ lsxrsize
* (regnum
- LOONGARCH_FIRST_LSX_REGNUM
);
269 regcache
->raw_collect (regnum
, (void *) buf
);
273 /* Define the Loongson SIMD Extension register regset. */
275 const struct regset loongarch_lsxregset
=
278 loongarch_supply_lsxregset
,
279 loongarch_fill_lsxregset
,
282 /* Unpack elf_lasxregset_t into GDB's register cache. */
285 loongarch_supply_lasxregset (const struct regset
*regset
,
286 struct regcache
*regcache
, int regnum
,
287 const void *lasxrs
, size_t len
)
289 int lasxrsize
= register_size (regcache
->arch (), LOONGARCH_FIRST_LASX_REGNUM
);
290 const gdb_byte
*buf
= nullptr;
294 for (int i
= 0; i
< LOONGARCH_LINUX_NUM_LASXREGSET
; i
++)
296 buf
= (const gdb_byte
*) lasxrs
+ lasxrsize
* i
;
297 regcache
->raw_supply (LOONGARCH_FIRST_LASX_REGNUM
+ i
, (const void *) buf
);
301 else if (regnum
>= LOONGARCH_FIRST_LASX_REGNUM
302 && regnum
< LOONGARCH_FIRST_LASX_REGNUM
+ LOONGARCH_LINUX_NUM_LASXREGSET
)
304 buf
= (const gdb_byte
*) lasxrs
+ lasxrsize
* (regnum
- LOONGARCH_FIRST_LASX_REGNUM
);
305 regcache
->raw_supply (regnum
, (const void *) buf
);
309 /* Pack the GDB's register cache value into an elf_lasxregset_t. */
312 loongarch_fill_lasxregset (const struct regset
*regset
,
313 const struct regcache
*regcache
, int regnum
,
314 void *lasxrs
, size_t len
)
316 int lasxrsize
= register_size (regcache
->arch (), LOONGARCH_FIRST_LASX_REGNUM
);
317 gdb_byte
*buf
= nullptr;
321 for (int i
= 0; i
< LOONGARCH_LINUX_NUM_LASXREGSET
; i
++)
323 buf
= (gdb_byte
*) lasxrs
+ lasxrsize
* i
;
324 regcache
->raw_collect (LOONGARCH_FIRST_LASX_REGNUM
+ i
, (void *) buf
);
327 else if (regnum
>= LOONGARCH_FIRST_LASX_REGNUM
328 && regnum
< LOONGARCH_FIRST_LASX_REGNUM
+ LOONGARCH_LINUX_NUM_LASXREGSET
)
331 buf
= (gdb_byte
*) lasxrs
+ lasxrsize
* (regnum
- LOONGARCH_FIRST_LASX_REGNUM
);
332 regcache
->raw_collect (regnum
, (void *) buf
);
336 /* Define the Loongson Advanced SIMD Extension register regset. */
338 const struct regset loongarch_lasxregset
=
341 loongarch_supply_lasxregset
,
342 loongarch_fill_lasxregset
,
345 /* Unpack an lbt regset into GDB's register cache. */
348 loongarch_supply_lbtregset (const struct regset
*regset
,
349 struct regcache
*regcache
, int regnum
,
350 const void *regs
, size_t len
)
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;
358 for (int i
= 0; i
< LOONGARCH_LINUX_NUM_SCR
; i
++)
360 buf
= (const gdb_byte
*) regs
+ scrsize
* i
;
361 regcache
->raw_supply (LOONGARCH_FIRST_SCR_REGNUM
+ i
,
365 buf
= (const gdb_byte
*) regs
+ scrsize
* LOONGARCH_LINUX_NUM_SCR
;
366 regcache
->raw_supply (LOONGARCH_EFLAGS_REGNUM
, (const void *) buf
);
368 buf
= (const gdb_byte
*) regs
369 + scrsize
* LOONGARCH_LINUX_NUM_SCR
371 regcache
->raw_supply (LOONGARCH_FTOP_REGNUM
, (const void *) buf
);
373 else if (regnum
>= LOONGARCH_FIRST_SCR_REGNUM
374 && regnum
<= LOONGARCH_LAST_SCR_REGNUM
)
376 buf
= (const gdb_byte
*) regs
377 + scrsize
* (regnum
- LOONGARCH_FIRST_SCR_REGNUM
);
378 regcache
->raw_supply (regnum
, (const void *) buf
);
380 else if (regnum
== LOONGARCH_EFLAGS_REGNUM
)
382 buf
= (const gdb_byte
*) regs
+ scrsize
* LOONGARCH_LINUX_NUM_SCR
;
383 regcache
->raw_supply (regnum
, (const void *) buf
);
385 else if (regnum
== LOONGARCH_FTOP_REGNUM
)
387 buf
= (const gdb_byte
*) regs
388 + scrsize
* LOONGARCH_LINUX_NUM_SCR
390 regcache
->raw_supply (regnum
, (const void *) buf
);
394 /* Pack the GDB's register cache value into an lbt regset. */
397 loongarch_fill_lbtregset (const struct regset
*regset
,
398 const struct regcache
*regcache
, int regnum
,
399 void *regs
, size_t len
)
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;
407 for (int i
= 0; i
< LOONGARCH_LINUX_NUM_SCR
; i
++)
409 buf
= (gdb_byte
*) regs
+ scrsize
* i
;
410 regcache
->raw_collect (LOONGARCH_FIRST_SCR_REGNUM
+ i
, (void *) buf
);
413 buf
= (gdb_byte
*) regs
+ scrsize
* LOONGARCH_LINUX_NUM_SCR
;
414 regcache
->raw_collect (LOONGARCH_EFLAGS_REGNUM
, (void *) buf
);
416 buf
= (gdb_byte
*) regs
+ scrsize
* LOONGARCH_LINUX_NUM_SCR
+ eflagssize
;
417 regcache
->raw_collect (LOONGARCH_FTOP_REGNUM
, (void *) buf
);
419 else if (regnum
>= LOONGARCH_FIRST_SCR_REGNUM
420 && regnum
<= LOONGARCH_LAST_SCR_REGNUM
)
422 buf
= (gdb_byte
*) regs
+ scrsize
* (regnum
- LOONGARCH_FIRST_SCR_REGNUM
);
423 regcache
->raw_collect (regnum
, (void *) buf
);
425 else if (regnum
== LOONGARCH_EFLAGS_REGNUM
)
427 buf
= (gdb_byte
*) regs
+ scrsize
* LOONGARCH_LINUX_NUM_SCR
;
428 regcache
->raw_collect (regnum
, (void *) buf
);
430 else if (regnum
== LOONGARCH_FTOP_REGNUM
)
432 buf
= (gdb_byte
*) regs
+ scrsize
* LOONGARCH_LINUX_NUM_SCR
+ eflagssize
;
433 regcache
->raw_collect (regnum
, (void *) buf
);
437 /* Define the lbt register regset. */
439 const struct regset loongarch_lbtregset
=
442 loongarch_supply_lbtregset
,
443 loongarch_fill_lbtregset
,
446 /* Implement the "init" method of struct tramp_frame. */
448 #define LOONGARCH_RT_SIGFRAME_UCONTEXT_OFFSET 128
449 #define LOONGARCH_UCONTEXT_SIGCONTEXT_OFFSET 176
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
,
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
);
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);
465 trad_frame_set_id (this_cache
, frame_id_build (frame_sp
, func
));
468 /* li.w a7, __NR_rt_sigreturn */
469 #define LOONGARCH_INST_LIW_A7_RT_SIGRETURN 0x03822c0b
471 #define LOONGARCH_INST_SYSCALL 0x002b0000
473 static const struct tramp_frame loongarch_linux_rt_sigframe
=
478 { LOONGARCH_INST_LIW_A7_RT_SIGRETURN
, ULONGEST_MAX
},
479 { LOONGARCH_INST_SYSCALL
, ULONGEST_MAX
},
480 { TRAMP_SENTINEL_INSN
, ULONGEST_MAX
}
482 loongarch_linux_rt_sigframe_init
,
486 /* Implement the "iterate_over_regset_sections" gdbarch method. */
489 loongarch_iterate_over_regset_sections (struct gdbarch
*gdbarch
,
490 iterate_over_regset_sections_cb
*cb
,
492 const struct regcache
*regcache
)
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
;
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
);
522 /* The following value is derived from __NR_rt_sigreturn in
523 <include/uapi/asm-generic/unistd.h> from the Linux source tree. */
525 #define LOONGARCH_NR_rt_sigreturn 139
527 /* When FRAME is at a syscall instruction, return the PC of the next
528 instruction to be executed. */
531 loongarch_linux_syscall_next_pc (const frame_info_ptr
&frame
)
533 const CORE_ADDR pc
= get_frame_pc (frame
);
534 ULONGEST a7
= get_frame_register_unsigned (frame
, LOONGARCH_A7_REGNUM
);
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
);
544 /* Implement the "get_syscall_number" gdbarch method. */
547 loongarch_linux_get_syscall_number (struct gdbarch
*gdbarch
, thread_info
*thread
)
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. */
557 gdb_assert (regsize
<= sizeof (buf
));
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
);
564 ret
= extract_signed_integer (buf
, regsize
, byte_order
);
569 /* Initialize LoongArch Linux ABI info. */
572 loongarch_linux_init_abi (struct gdbarch_info info
, struct gdbarch
*gdbarch
)
574 loongarch_gdbarch_tdep
*tdep
= gdbarch_tdep
<loongarch_gdbarch_tdep
> (gdbarch
);
576 linux_init_abi (info
, gdbarch
, 0);
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
);
583 /* GNU/Linux uses SVR4-style shared libraries. */
584 set_gdbarch_skip_trampoline_code (gdbarch
, find_solib_trampoline_target
);
586 /* GNU/Linux uses the dynamic linker included in the GNU C Library. */
587 set_gdbarch_skip_solib_resolver (gdbarch
, glibc_skip_solib_resolver
);
589 /* Enable TLS support. */
590 set_gdbarch_fetch_tls_load_module_address (gdbarch
, svr4_fetch_objfile_link_map
);
592 /* Prepend tramp frame unwinder for signal. */
593 tramp_frame_prepend_unwinder (gdbarch
, &loongarch_linux_rt_sigframe
);
595 /* Core file support. */
596 set_gdbarch_iterate_over_regset_sections (gdbarch
, loongarch_iterate_over_regset_sections
);
598 tdep
->syscall_next_pc
= loongarch_linux_syscall_next_pc
;
600 /* Set the correct XML syscall filename. */
601 set_xml_syscall_file_name (gdbarch
, XML_SYSCALL_FILENAME_LOONGARCH
);
603 /* Get the syscall number from the arch's register. */
604 set_gdbarch_get_syscall_number (gdbarch
, loongarch_linux_get_syscall_number
);
607 /* Initialize LoongArch Linux target support. */
609 void _initialize_loongarch_linux_tdep ();
611 _initialize_loongarch_linux_tdep ()
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
);