Automatic date update in version.in
[binutils-gdb.git] / gdb / loongarch-linux-tdep.c
blob715780603034c310f52071760741fc3245ad94ef
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"
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"
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. */
37 static void
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;
45 if (regnum == -1)
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);
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)
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. */
78 static void
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;
86 if (regnum == -1)
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 =
117 nullptr,
118 loongarch_supply_gregset,
119 loongarch_fill_gregset,
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)
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);
132 if (regnum == -1)
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 +
142 fccsize * i;
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. */
169 static void
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);
178 if (regnum == -1)
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 +
188 fccsize * i;
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 =
217 nullptr,
218 loongarch_supply_fpregset,
219 loongarch_fill_fpregset,
222 /* Unpack elf_lsxregset_t into GDB's register cache. */
224 static void
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;
232 if (regnum == -1)
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. */
250 static void
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;
258 if (regnum == -1)
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 =
277 nullptr,
278 loongarch_supply_lsxregset,
279 loongarch_fill_lsxregset,
282 /* Unpack elf_lasxregset_t into GDB's register cache. */
284 static void
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;
292 if (regnum == -1)
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. */
311 static void
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;
319 if (regnum == -1)
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 =
340 nullptr,
341 loongarch_supply_lasxregset,
342 loongarch_fill_lasxregset,
345 /* Unpack an lbt regset into GDB's register cache. */
347 static void
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;
356 if (regnum == -1)
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,
362 (const void *) buf);
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
370 + eflagssize;
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
389 + eflagssize;
390 regcache->raw_supply (regnum, (const void *) buf);
394 /* Pack the GDB's register cache value into an lbt regset. */
396 static void
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;
405 if (regnum == -1)
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 =
441 nullptr,
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
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)
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
470 /* syscall 0 */
471 #define LOONGARCH_INST_SYSCALL 0x002b0000
473 static const struct tramp_frame loongarch_linux_rt_sigframe =
475 SIGTRAMP_FRAME,
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,
483 nullptr
486 /* Implement the "iterate_over_regset_sections" gdbarch method. */
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)
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. */
530 static CORE_ADDR
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);
541 return pc + 4;
544 /* Implement the "get_syscall_number" gdbarch method. */
546 static LONGEST
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. */
553 gdb_byte buf[8];
554 /* The result. */
555 LONGEST ret;
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);
566 return ret;
569 /* Initialize LoongArch Linux ABI info. */
571 static void
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 ();
610 void
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);