Home | History | Annotate | Line # | Download | only in gdbserver
      1      1.1  christos /* GNU/Linux/LoongArch specific low level interface, for the remote server
      2      1.1  christos    for GDB.
      3  1.1.1.2  christos    Copyright (C) 2022-2024 Free Software Foundation, Inc.
      4      1.1  christos 
      5      1.1  christos    This file is part of GDB.
      6      1.1  christos 
      7      1.1  christos    This program is free software; you can redistribute it and/or modify
      8      1.1  christos    it under the terms of the GNU General Public License as published by
      9      1.1  christos    the Free Software Foundation; either version 3 of the License, or
     10      1.1  christos    (at your option) any later version.
     11      1.1  christos 
     12      1.1  christos    This program is distributed in the hope that it will be useful,
     13      1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     14      1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15      1.1  christos    GNU General Public License for more details.
     16      1.1  christos 
     17      1.1  christos    You should have received a copy of the GNU General Public License
     18      1.1  christos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     19      1.1  christos 
     20      1.1  christos #include "linux-low.h"
     21      1.1  christos #include "tdesc.h"
     22      1.1  christos #include "elf/common.h"
     23      1.1  christos #include "arch/loongarch.h"
     24      1.1  christos 
     25      1.1  christos /* Linux target ops definitions for the LoongArch architecture.  */
     26      1.1  christos 
     27      1.1  christos class loongarch_target : public linux_process_target
     28      1.1  christos {
     29      1.1  christos public:
     30      1.1  christos 
     31      1.1  christos   const regs_info *get_regs_info () override;
     32      1.1  christos 
     33      1.1  christos   int breakpoint_kind_from_pc (CORE_ADDR *pcptr) override;
     34      1.1  christos 
     35      1.1  christos   const gdb_byte *sw_breakpoint_from_kind (int kind, int *size) override;
     36      1.1  christos 
     37      1.1  christos protected:
     38      1.1  christos 
     39      1.1  christos   void low_arch_setup () override;
     40      1.1  christos 
     41      1.1  christos   bool low_cannot_fetch_register (int regno) override;
     42      1.1  christos 
     43      1.1  christos   bool low_cannot_store_register (int regno) override;
     44      1.1  christos 
     45      1.1  christos   bool low_fetch_register (regcache *regcache, int regno) override;
     46      1.1  christos 
     47      1.1  christos   bool low_supports_breakpoints () override;
     48      1.1  christos 
     49      1.1  christos   CORE_ADDR low_get_pc (regcache *regcache) override;
     50      1.1  christos 
     51      1.1  christos   void low_set_pc (regcache *regcache, CORE_ADDR newpc) override;
     52      1.1  christos 
     53      1.1  christos   bool low_breakpoint_at (CORE_ADDR pc) override;
     54      1.1  christos };
     55      1.1  christos 
     56      1.1  christos /* The singleton target ops object.  */
     57      1.1  christos 
     58      1.1  christos static loongarch_target the_loongarch_target;
     59      1.1  christos 
     60      1.1  christos bool
     61      1.1  christos loongarch_target::low_cannot_fetch_register (int regno)
     62      1.1  christos {
     63      1.1  christos   gdb_assert_not_reached ("linux target op low_cannot_fetch_register "
     64      1.1  christos 			  "is not implemented by the target");
     65      1.1  christos }
     66      1.1  christos 
     67      1.1  christos bool
     68      1.1  christos loongarch_target::low_cannot_store_register (int regno)
     69      1.1  christos {
     70      1.1  christos   gdb_assert_not_reached ("linux target op low_cannot_store_register "
     71      1.1  christos 			  "is not implemented by the target");
     72      1.1  christos }
     73      1.1  christos 
     74      1.1  christos /* Implementation of linux target ops method "low_arch_setup".  */
     75      1.1  christos 
     76      1.1  christos void
     77      1.1  christos loongarch_target::low_arch_setup ()
     78      1.1  christos {
     79      1.1  christos   static const char *expedite_regs[] = { "r3", "pc", NULL };
     80      1.1  christos   loongarch_gdbarch_features features;
     81      1.1  christos   target_desc_up tdesc;
     82      1.1  christos 
     83      1.1  christos   features.xlen = sizeof (elf_greg_t);
     84      1.1  christos   tdesc = loongarch_create_target_description (features);
     85      1.1  christos 
     86  1.1.1.2  christos   if (tdesc->expedite_regs.empty ())
     87  1.1.1.2  christos     {
     88  1.1.1.2  christos       init_target_desc (tdesc.get (), expedite_regs);
     89  1.1.1.2  christos       gdb_assert (!tdesc->expedite_regs.empty ());
     90  1.1.1.2  christos     }
     91      1.1  christos   current_process ()->tdesc = tdesc.release ();
     92      1.1  christos }
     93      1.1  christos 
     94      1.1  christos /* Collect GPRs from REGCACHE into BUF.  */
     95      1.1  christos 
     96      1.1  christos static void
     97      1.1  christos loongarch_fill_gregset (struct regcache *regcache, void *buf)
     98      1.1  christos {
     99      1.1  christos   elf_gregset_t *regset = (elf_gregset_t *) buf;
    100      1.1  christos   int i;
    101      1.1  christos 
    102      1.1  christos   for (i = 1; i < 32; i++)
    103      1.1  christos     collect_register (regcache, i, *regset + i);
    104      1.1  christos   collect_register (regcache, LOONGARCH_ORIG_A0_REGNUM, *regset + LOONGARCH_ORIG_A0_REGNUM);
    105      1.1  christos   collect_register (regcache, LOONGARCH_PC_REGNUM, *regset + LOONGARCH_PC_REGNUM);
    106      1.1  christos   collect_register (regcache, LOONGARCH_BADV_REGNUM, *regset + LOONGARCH_BADV_REGNUM);
    107      1.1  christos }
    108      1.1  christos 
    109      1.1  christos /* Supply GPRs from BUF into REGCACHE.  */
    110      1.1  christos 
    111      1.1  christos static void
    112      1.1  christos loongarch_store_gregset (struct regcache *regcache, const void *buf)
    113      1.1  christos {
    114      1.1  christos   const elf_gregset_t *regset = (const elf_gregset_t *) buf;
    115      1.1  christos   int i;
    116      1.1  christos 
    117      1.1  christos   supply_register_zeroed (regcache, 0);
    118      1.1  christos   for (i = 1; i < 32; i++)
    119      1.1  christos     supply_register (regcache, i, *regset + i);
    120      1.1  christos   supply_register (regcache, LOONGARCH_ORIG_A0_REGNUM, *regset + LOONGARCH_ORIG_A0_REGNUM);
    121      1.1  christos   supply_register (regcache, LOONGARCH_PC_REGNUM, *regset + LOONGARCH_PC_REGNUM);
    122      1.1  christos   supply_register (regcache, LOONGARCH_BADV_REGNUM, *regset + LOONGARCH_BADV_REGNUM);
    123      1.1  christos }
    124      1.1  christos 
    125      1.1  christos /* Collect FPRs from REGCACHE into BUF.  */
    126      1.1  christos 
    127      1.1  christos static void
    128      1.1  christos loongarch_fill_fpregset (struct regcache *regcache, void *buf)
    129      1.1  christos {
    130      1.1  christos   gdb_byte *regbuf = nullptr;
    131      1.1  christos   int fprsize = register_size (regcache->tdesc, LOONGARCH_FIRST_FP_REGNUM);
    132      1.1  christos   int fccsize = register_size (regcache->tdesc, LOONGARCH_FIRST_FCC_REGNUM);
    133      1.1  christos 
    134      1.1  christos   for (int i = 0; i < LOONGARCH_LINUX_NUM_FPREGSET; i++)
    135      1.1  christos     {
    136      1.1  christos       regbuf = (gdb_byte *)buf + fprsize * i;
    137      1.1  christos       collect_register (regcache, LOONGARCH_FIRST_FP_REGNUM + i, regbuf);
    138      1.1  christos     }
    139      1.1  christos 
    140      1.1  christos   for (int i = 0; i < LOONGARCH_LINUX_NUM_FCC; i++)
    141      1.1  christos     {
    142      1.1  christos       regbuf = (gdb_byte *)buf + fprsize * LOONGARCH_LINUX_NUM_FPREGSET +
    143      1.1  christos 	fccsize * i;
    144      1.1  christos       collect_register (regcache, LOONGARCH_FIRST_FCC_REGNUM + i, regbuf);
    145      1.1  christos     }
    146      1.1  christos 
    147      1.1  christos   regbuf = (gdb_byte *)buf + fprsize * LOONGARCH_LINUX_NUM_FPREGSET +
    148      1.1  christos     fccsize * LOONGARCH_LINUX_NUM_FCC;
    149      1.1  christos   collect_register (regcache, LOONGARCH_FCSR_REGNUM, regbuf);
    150      1.1  christos }
    151      1.1  christos 
    152      1.1  christos /* Supply FPRs from BUF into REGCACHE.  */
    153      1.1  christos 
    154      1.1  christos static void
    155      1.1  christos loongarch_store_fpregset (struct regcache *regcache, const void *buf)
    156      1.1  christos {
    157      1.1  christos   const gdb_byte *regbuf = nullptr;
    158      1.1  christos   int fprsize = register_size (regcache->tdesc, LOONGARCH_FIRST_FP_REGNUM);
    159      1.1  christos   int fccsize = register_size (regcache->tdesc, LOONGARCH_FIRST_FCC_REGNUM);
    160      1.1  christos 
    161      1.1  christos   for (int i = 0; i < LOONGARCH_LINUX_NUM_FPREGSET; i++)
    162      1.1  christos     {
    163      1.1  christos       regbuf = (const gdb_byte *)buf + fprsize * i;
    164      1.1  christos       supply_register (regcache, LOONGARCH_FIRST_FP_REGNUM + i, regbuf);
    165      1.1  christos     }
    166      1.1  christos 
    167      1.1  christos   for (int i = 0; i < LOONGARCH_LINUX_NUM_FCC; i++)
    168      1.1  christos     {
    169      1.1  christos       regbuf = (const gdb_byte *)buf + fprsize * LOONGARCH_LINUX_NUM_FPREGSET +
    170      1.1  christos 	fccsize * i;
    171      1.1  christos       supply_register (regcache, LOONGARCH_FIRST_FCC_REGNUM + i, regbuf);
    172      1.1  christos     }
    173      1.1  christos 
    174      1.1  christos   regbuf = (const gdb_byte *)buf + fprsize * LOONGARCH_LINUX_NUM_FPREGSET +
    175      1.1  christos     fccsize * LOONGARCH_LINUX_NUM_FCC;
    176      1.1  christos   supply_register (regcache, LOONGARCH_FCSR_REGNUM, regbuf);
    177      1.1  christos }
    178      1.1  christos 
    179  1.1.1.2  christos /* Collect lsx regs from REGCACHE into BUF.  */
    180  1.1.1.2  christos 
    181  1.1.1.2  christos static void
    182  1.1.1.2  christos loongarch_fill_lsxregset (struct regcache *regcache, void *buf)
    183  1.1.1.2  christos {
    184  1.1.1.2  christos   elf_lsxregset_t *regset = (elf_lsxregset_t *) buf;
    185  1.1.1.2  christos   int i;
    186  1.1.1.2  christos 
    187  1.1.1.2  christos   for (i = 0; i < LOONGARCH_LINUX_NUM_LSXREGSET; i++)
    188  1.1.1.2  christos     collect_register (regcache, LOONGARCH_FIRST_LSX_REGNUM + i, *regset + i);
    189  1.1.1.2  christos }
    190  1.1.1.2  christos 
    191  1.1.1.2  christos /* Supply lsx regs from BUF into REGCACHE.  */
    192  1.1.1.2  christos 
    193  1.1.1.2  christos static void
    194  1.1.1.2  christos loongarch_store_lsxregset (struct regcache *regcache, const void *buf)
    195  1.1.1.2  christos {
    196  1.1.1.2  christos   const elf_lsxregset_t *regset = (const elf_lsxregset_t *) buf;
    197  1.1.1.2  christos   int i;
    198  1.1.1.2  christos 
    199  1.1.1.2  christos   for (i = 0; i < LOONGARCH_LINUX_NUM_LSXREGSET; i++)
    200  1.1.1.2  christos     supply_register (regcache, LOONGARCH_FIRST_LSX_REGNUM + i, *regset + i);
    201  1.1.1.2  christos }
    202  1.1.1.2  christos 
    203  1.1.1.2  christos /* Collect lasx regs from REGCACHE into BUF.  */
    204  1.1.1.2  christos 
    205  1.1.1.2  christos static void
    206  1.1.1.2  christos loongarch_fill_lasxregset (struct regcache *regcache, void *buf)
    207  1.1.1.2  christos {
    208  1.1.1.2  christos   elf_lasxregset_t *regset = (elf_lasxregset_t *) buf;
    209  1.1.1.2  christos   int i;
    210  1.1.1.2  christos 
    211  1.1.1.2  christos   for (i = 0; i < LOONGARCH_LINUX_NUM_LASXREGSET; i++)
    212  1.1.1.2  christos     collect_register (regcache, LOONGARCH_FIRST_LASX_REGNUM + i, *regset + i);
    213  1.1.1.2  christos }
    214  1.1.1.2  christos 
    215  1.1.1.2  christos /* Supply lasx regs from BUF into REGCACHE.  */
    216  1.1.1.2  christos 
    217  1.1.1.2  christos static void
    218  1.1.1.2  christos loongarch_store_lasxregset (struct regcache *regcache, const void *buf)
    219  1.1.1.2  christos {
    220  1.1.1.2  christos   const elf_lasxregset_t *regset = (const elf_lasxregset_t *) buf;
    221  1.1.1.2  christos   int i;
    222  1.1.1.2  christos 
    223  1.1.1.2  christos   for (i = 0; i < LOONGARCH_LINUX_NUM_LASXREGSET; i++)
    224  1.1.1.2  christos     supply_register (regcache, LOONGARCH_FIRST_LASX_REGNUM + i, *regset + i);
    225  1.1.1.2  christos }
    226  1.1.1.2  christos 
    227  1.1.1.2  christos /* Collect lbt regs from REGCACHE into BUF.  */
    228  1.1.1.2  christos 
    229  1.1.1.2  christos static void
    230  1.1.1.2  christos loongarch_fill_lbtregset (struct regcache *regcache, void *buf)
    231  1.1.1.2  christos {
    232  1.1.1.2  christos   gdb_byte *regbuf = (gdb_byte*)buf;
    233  1.1.1.2  christos   int scrsize = register_size (regcache->tdesc, LOONGARCH_FIRST_SCR_REGNUM);
    234  1.1.1.2  christos   int eflagssize = register_size (regcache->tdesc, LOONGARCH_EFLAGS_REGNUM);
    235  1.1.1.2  christos   int i;
    236  1.1.1.2  christos 
    237  1.1.1.2  christos   for (i = 0; i < LOONGARCH_LINUX_NUM_SCR; i++)
    238  1.1.1.2  christos     collect_register (regcache, LOONGARCH_FIRST_SCR_REGNUM + i, regbuf + scrsize * i);
    239  1.1.1.2  christos 
    240  1.1.1.2  christos   collect_register (regcache, LOONGARCH_EFLAGS_REGNUM,
    241  1.1.1.2  christos 		    regbuf + LOONGARCH_LINUX_NUM_SCR * scrsize);
    242  1.1.1.2  christos   collect_register (regcache, LOONGARCH_FTOP_REGNUM,
    243  1.1.1.2  christos 		    regbuf + LOONGARCH_LINUX_NUM_SCR * scrsize + eflagssize);
    244  1.1.1.2  christos 
    245  1.1.1.2  christos }
    246  1.1.1.2  christos 
    247  1.1.1.2  christos /* Supply lbt regs from BUF into REGCACHE.  */
    248  1.1.1.2  christos 
    249  1.1.1.2  christos static void
    250  1.1.1.2  christos loongarch_store_lbtregset (struct regcache *regcache, const void *buf)
    251  1.1.1.2  christos {
    252  1.1.1.2  christos 
    253  1.1.1.2  christos   gdb_byte *regbuf = (gdb_byte*)buf;
    254  1.1.1.2  christos   int scrsize = register_size (regcache->tdesc, LOONGARCH_FIRST_SCR_REGNUM);
    255  1.1.1.2  christos   int eflagssize = register_size (regcache->tdesc, LOONGARCH_EFLAGS_REGNUM);
    256  1.1.1.2  christos   int i;
    257  1.1.1.2  christos 
    258  1.1.1.2  christos   for (i = 0; i < LOONGARCH_LINUX_NUM_SCR; i++)
    259  1.1.1.2  christos     supply_register (regcache, LOONGARCH_FIRST_SCR_REGNUM + i, regbuf + scrsize * i);
    260  1.1.1.2  christos 
    261  1.1.1.2  christos   supply_register (regcache, LOONGARCH_EFLAGS_REGNUM,
    262  1.1.1.2  christos 		    regbuf + LOONGARCH_LINUX_NUM_SCR * scrsize);
    263  1.1.1.2  christos   supply_register (regcache, LOONGARCH_FTOP_REGNUM,
    264  1.1.1.2  christos 		    regbuf + LOONGARCH_LINUX_NUM_SCR * scrsize + eflagssize);
    265  1.1.1.2  christos 
    266  1.1.1.2  christos }
    267  1.1.1.2  christos 
    268      1.1  christos /* LoongArch/Linux regsets.  */
    269      1.1  christos static struct regset_info loongarch_regsets[] = {
    270      1.1  christos   { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_PRSTATUS, sizeof (elf_gregset_t),
    271      1.1  christos     GENERAL_REGS, loongarch_fill_gregset, loongarch_store_gregset },
    272      1.1  christos   { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_FPREGSET, sizeof (elf_fpregset_t),
    273      1.1  christos     FP_REGS, loongarch_fill_fpregset, loongarch_store_fpregset },
    274  1.1.1.2  christos   { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_LARCH_LSX, sizeof (elf_lsxregset_t),
    275  1.1.1.2  christos     OPTIONAL_REGS, loongarch_fill_lsxregset, loongarch_store_lsxregset },
    276  1.1.1.2  christos   { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_LARCH_LASX, sizeof (elf_lasxregset_t),
    277  1.1.1.2  christos     OPTIONAL_REGS, loongarch_fill_lasxregset, loongarch_store_lasxregset },
    278  1.1.1.2  christos   { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_LARCH_LBT, LOONGARCH_LBT_REGS_SIZE,
    279  1.1.1.2  christos     OPTIONAL_REGS, loongarch_fill_lbtregset, loongarch_store_lbtregset },
    280      1.1  christos   NULL_REGSET
    281      1.1  christos };
    282      1.1  christos 
    283      1.1  christos /* LoongArch/Linux regset information.  */
    284      1.1  christos static struct regsets_info loongarch_regsets_info =
    285      1.1  christos   {
    286      1.1  christos     loongarch_regsets, /* regsets */
    287      1.1  christos     0, /* num_regsets */
    288      1.1  christos     NULL, /* disabled_regsets */
    289      1.1  christos   };
    290      1.1  christos 
    291      1.1  christos /* Definition of linux_target_ops data member "regs_info".  */
    292      1.1  christos static struct regs_info loongarch_regs =
    293      1.1  christos   {
    294      1.1  christos     NULL, /* regset_bitmap */
    295      1.1  christos     NULL, /* usrregs */
    296      1.1  christos     &loongarch_regsets_info,
    297      1.1  christos   };
    298      1.1  christos 
    299      1.1  christos /* Implementation of linux target ops method "get_regs_info".  */
    300      1.1  christos 
    301      1.1  christos const regs_info *
    302      1.1  christos loongarch_target::get_regs_info ()
    303      1.1  christos {
    304      1.1  christos   return &loongarch_regs;
    305      1.1  christos }
    306      1.1  christos 
    307      1.1  christos /* Implementation of linux target ops method "low_fetch_register".  */
    308      1.1  christos 
    309      1.1  christos bool
    310      1.1  christos loongarch_target::low_fetch_register (regcache *regcache, int regno)
    311      1.1  christos {
    312      1.1  christos   if (regno != 0)
    313      1.1  christos     return false;
    314      1.1  christos   supply_register_zeroed (regcache, 0);
    315      1.1  christos   return true;
    316      1.1  christos }
    317      1.1  christos 
    318      1.1  christos bool
    319      1.1  christos loongarch_target::low_supports_breakpoints ()
    320      1.1  christos {
    321      1.1  christos   return true;
    322      1.1  christos }
    323      1.1  christos 
    324      1.1  christos /* Implementation of linux target ops method "low_get_pc".  */
    325      1.1  christos 
    326      1.1  christos CORE_ADDR
    327      1.1  christos loongarch_target::low_get_pc (regcache *regcache)
    328      1.1  christos {
    329      1.1  christos   if (register_size (regcache->tdesc, 0) == 8)
    330      1.1  christos     return linux_get_pc_64bit (regcache);
    331      1.1  christos   else
    332      1.1  christos     return linux_get_pc_32bit (regcache);
    333      1.1  christos }
    334      1.1  christos 
    335      1.1  christos /* Implementation of linux target ops method "low_set_pc".  */
    336      1.1  christos 
    337      1.1  christos void
    338      1.1  christos loongarch_target::low_set_pc (regcache *regcache, CORE_ADDR newpc)
    339      1.1  christos {
    340      1.1  christos   if (register_size (regcache->tdesc, 0) == 8)
    341      1.1  christos     linux_set_pc_64bit (regcache, newpc);
    342      1.1  christos   else
    343      1.1  christos     linux_set_pc_32bit (regcache, newpc);
    344      1.1  christos }
    345      1.1  christos 
    346      1.1  christos #define loongarch_breakpoint_len 4
    347      1.1  christos 
    348      1.1  christos /* LoongArch BRK software debug mode instruction.
    349      1.1  christos    This instruction needs to match gdb/loongarch-tdep.c
    350      1.1  christos    (loongarch_default_breakpoint).  */
    351      1.1  christos static const gdb_byte loongarch_breakpoint[] = {0x05, 0x00, 0x2a, 0x00};
    352      1.1  christos 
    353      1.1  christos /* Implementation of target ops method "breakpoint_kind_from_pc".  */
    354      1.1  christos 
    355      1.1  christos int
    356      1.1  christos loongarch_target::breakpoint_kind_from_pc (CORE_ADDR *pcptr)
    357      1.1  christos {
    358      1.1  christos   return loongarch_breakpoint_len;
    359      1.1  christos }
    360      1.1  christos 
    361      1.1  christos /* Implementation of target ops method "sw_breakpoint_from_kind".  */
    362      1.1  christos 
    363      1.1  christos const gdb_byte *
    364      1.1  christos loongarch_target::sw_breakpoint_from_kind (int kind, int *size)
    365      1.1  christos {
    366      1.1  christos   *size = loongarch_breakpoint_len;
    367      1.1  christos   return (const gdb_byte *) &loongarch_breakpoint;
    368      1.1  christos }
    369      1.1  christos 
    370      1.1  christos /* Implementation of linux target ops method "low_breakpoint_at".  */
    371      1.1  christos 
    372      1.1  christos bool
    373      1.1  christos loongarch_target::low_breakpoint_at (CORE_ADDR pc)
    374      1.1  christos {
    375      1.1  christos   gdb_byte insn[loongarch_breakpoint_len];
    376      1.1  christos 
    377      1.1  christos   read_memory (pc, (unsigned char *) &insn, loongarch_breakpoint_len);
    378      1.1  christos   if (memcmp (insn, loongarch_breakpoint, loongarch_breakpoint_len) == 0)
    379      1.1  christos     return true;
    380      1.1  christos 
    381      1.1  christos   return false;
    382      1.1  christos }
    383      1.1  christos 
    384      1.1  christos /* The linux target ops object.  */
    385      1.1  christos 
    386      1.1  christos linux_process_target *the_linux_target = &the_loongarch_target;
    387      1.1  christos 
    388      1.1  christos /* Initialize the LoongArch/Linux target.  */
    389      1.1  christos 
    390      1.1  christos void
    391      1.1  christos initialize_low_arch ()
    392      1.1  christos {
    393      1.1  christos   initialize_regsets_info (&loongarch_regsets_info);
    394      1.1  christos }
    395