Home | History | Annotate | Line # | Download | only in gdb
      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