Home | History | Annotate | Line # | Download | only in gdbserver
      1  1.1  christos /* GNU/Linux/Microblaze specific low level interface, for the remote server for
      2  1.1  christos    GDB.
      3  1.1  christos    Copyright (C) 1995-2025 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 "server.h"
     21  1.1  christos #include "linux-low.h"
     22  1.1  christos 
     23  1.1  christos #include "elf/common.h"
     24  1.1  christos #include "nat/gdb_ptrace.h"
     25  1.1  christos #include <endian.h>
     26  1.1  christos 
     27  1.1  christos #include <asm/ptrace.h>
     28  1.1  christos #include <sys/procfs.h>
     29  1.1  christos #include <sys/ptrace.h>
     30  1.1  christos 
     31  1.1  christos #include "gdb_proc_service.h"
     32  1.1  christos 
     33  1.1  christos 
     34  1.1  christos static int microblaze_regmap[] =
     35  1.1  christos  {PT_GPR(0),     PT_GPR(1),     PT_GPR(2),     PT_GPR(3),
     36  1.1  christos   PT_GPR(4),     PT_GPR(5),     PT_GPR(6),     PT_GPR(7),
     37  1.1  christos   PT_GPR(8),     PT_GPR(9),     PT_GPR(10),    PT_GPR(11),
     38  1.1  christos   PT_GPR(12),    PT_GPR(13),    PT_GPR(14),    PT_GPR(15),
     39  1.1  christos   PT_GPR(16),    PT_GPR(17),    PT_GPR(18),    PT_GPR(19),
     40  1.1  christos   PT_GPR(20),    PT_GPR(21),    PT_GPR(22),    PT_GPR(23),
     41  1.1  christos   PT_GPR(24),    PT_GPR(25),    PT_GPR(26),    PT_GPR(27),
     42  1.1  christos   PT_GPR(28),    PT_GPR(29),    PT_GPR(30),    PT_GPR(31),
     43  1.1  christos   PT_PC,         PT_MSR,        PT_EAR,        PT_ESR,
     44  1.1  christos   PT_FSR
     45  1.1  christos   };
     46  1.1  christos 
     47  1.1  christos 
     48  1.1  christos 
     49  1.1  christos class microblaze_target : public linux_process_target
     50  1.1  christos {
     51  1.1  christos public:
     52  1.1  christos 
     53  1.1  christos   const regs_info *get_regs_info () override;
     54  1.1  christos 
     55  1.1  christos   const gdb_byte *sw_breakpoint_from_kind (int kind, int *size) override;
     56  1.1  christos 
     57  1.1  christos protected:
     58  1.1  christos 
     59  1.1  christos   void low_arch_setup () override;
     60  1.1  christos 
     61  1.1  christos   bool low_cannot_fetch_register (int regno) override;
     62  1.1  christos 
     63  1.1  christos   bool low_cannot_store_register (int regno) override;
     64  1.1  christos 
     65  1.1  christos   bool low_supports_breakpoints () override;
     66  1.1  christos 
     67  1.1  christos   CORE_ADDR low_get_pc (regcache *regcache) override;
     68  1.1  christos 
     69  1.1  christos   void low_set_pc (regcache *regcache, CORE_ADDR newpc) override;
     70  1.1  christos 
     71  1.1  christos   bool low_breakpoint_at (CORE_ADDR pc) override;
     72  1.1  christos };
     73  1.1  christos 
     74  1.1  christos /* The singleton target ops object.  */
     75  1.1  christos 
     76  1.1  christos static microblaze_target the_microblaze_target;
     77  1.1  christos 
     78  1.1  christos constexpr auto microblaze_num_regs
     79  1.1  christos   = sizeof (microblaze_regmap) / sizeof (microblaze_regmap[0]);
     80  1.1  christos 
     81  1.1  christos /* Defined in auto-generated file microblaze-linux-generated.c.  */
     82  1.1  christos void init_registers_microblaze_linux ();
     83  1.1  christos extern const target_desc *tdesc_microblaze_linux;
     84  1.1  christos 
     85  1.1  christos bool
     86  1.1  christos microblaze_target::low_supports_breakpoints ()
     87  1.1  christos {
     88  1.1  christos   return true;
     89  1.1  christos }
     90  1.1  christos 
     91  1.1  christos bool
     92  1.1  christos microblaze_target::low_cannot_store_register (int regno)
     93  1.1  christos {
     94  1.1  christos   if (microblaze_regmap[regno] == -1 || regno == 0)
     95  1.1  christos     return 1;
     96  1.1  christos 
     97  1.1  christos   return 0;
     98  1.1  christos }
     99  1.1  christos 
    100  1.1  christos bool
    101  1.1  christos microblaze_target::low_cannot_fetch_register (int regno)
    102  1.1  christos {
    103  1.1  christos   return 0;
    104  1.1  christos }
    105  1.1  christos 
    106  1.1  christos CORE_ADDR
    107  1.1  christos microblaze_target::low_get_pc (regcache *regcache)
    108  1.1  christos {
    109  1.1  christos   unsigned long pc;
    110  1.1  christos 
    111  1.1  christos   collect_register_by_name (regcache, "rpc", &pc);
    112  1.1  christos   return pc;
    113  1.1  christos }
    114  1.1  christos 
    115  1.1  christos void
    116  1.1  christos microblaze_target::low_set_pc (regcache *regcache, CORE_ADDR pc)
    117  1.1  christos {
    118  1.1  christos   unsigned long newpc = pc;
    119  1.1  christos 
    120  1.1  christos   supply_register_by_name (regcache, "rpc", &newpc);
    121  1.1  christos }
    122  1.1  christos 
    123  1.1  christos /* dbtrap insn */
    124  1.1  christos /* brki r16, 0x18; */
    125  1.1  christos static const uint32_t microblaze_breakpoint = 0xba0c0018;
    126  1.1  christos #define microblaze_breakpoint_len 4
    127  1.1  christos 
    128  1.1  christos const gdb_byte *
    129  1.1  christos microblaze_target::sw_breakpoint_from_kind (int kind, int *size)
    130  1.1  christos {
    131  1.1  christos   *size = microblaze_breakpoint_len;
    132  1.1  christos   return reinterpret_cast<const gdb_byte *> (&microblaze_breakpoint);
    133  1.1  christos }
    134  1.1  christos 
    135  1.1  christos bool
    136  1.1  christos microblaze_target::low_breakpoint_at (CORE_ADDR where)
    137  1.1  christos {
    138  1.1  christos   uint32_t insn;
    139  1.1  christos 
    140  1.1  christos   read_memory (where, (unsigned char *) &insn, 4);
    141  1.1  christos   /* If necessary, recognize more trap instructions here.  GDB only uses the
    142  1.1  christos      one.  */
    143  1.1  christos   return insn == microblaze_breakpoint;
    144  1.1  christos }
    145  1.1  christos 
    146  1.1  christos #ifdef HAVE_PTRACE_GETREGS
    147  1.1  christos 
    148  1.1  christos static void
    149  1.1  christos microblaze_collect_ptrace_register (struct regcache *regcache, int regno,
    150  1.1  christos 				    char *buf)
    151  1.1  christos {
    152  1.1  christos   memset (buf, 0, sizeof (long));
    153  1.1  christos 
    154  1.1  christos   if (__BYTE_ORDER == __LITTLE_ENDIAN)
    155  1.1  christos     {
    156  1.1  christos       collect_register (regcache, regno, buf);
    157  1.1  christos     }
    158  1.1  christos   else if (__BYTE_ORDER == __BIG_ENDIAN)
    159  1.1  christos     {
    160  1.1  christos 	int size = register_size (regcache->tdesc, regno);
    161  1.1  christos 
    162  1.1  christos 	if (size < sizeof (long))
    163  1.1  christos 		collect_register (regcache, regno, buf + sizeof (long) - size);
    164  1.1  christos 	else
    165  1.1  christos 		collect_register (regcache, regno, buf);
    166  1.1  christos     }
    167  1.1  christos }
    168  1.1  christos 
    169  1.1  christos /* Collect GPRs from REGCACHE into BUF.  */
    170  1.1  christos 
    171  1.1  christos static void microblaze_fill_gregset (struct regcache *regcache, void *buf)
    172  1.1  christos {
    173  1.1  christos   int i;
    174  1.1  christos 
    175  1.1  christos   for (i = 0; i < microblaze_num_regs; i++)
    176  1.1  christos     microblaze_collect_ptrace_register (regcache, i,
    177  1.1  christos 					(char *) buf + microblaze_regmap[i]);
    178  1.1  christos }
    179  1.1  christos 
    180  1.1  christos /* Supply GPRs from BUF into REGCACHE.  */
    181  1.1  christos 
    182  1.1  christos static void
    183  1.1  christos microblaze_store_gregset (struct regcache *regcache, const void *buf)
    184  1.1  christos {
    185  1.1  christos   int i;
    186  1.1  christos 
    187  1.1  christos   for (i = 0; i < microblaze_num_regs; i++)
    188  1.1  christos     supply_register (regcache, i, (char *) buf + microblaze_regmap[i]);
    189  1.1  christos }
    190  1.1  christos 
    191  1.1  christos static struct regset_info microblaze_regsets[] = {
    192  1.1  christos   { PTRACE_GETREGS, PTRACE_SETREGS, NT_PRSTATUS,
    193  1.1  christos     sizeof (elf_gregset_t), GENERAL_REGS,
    194  1.1  christos     microblaze_fill_gregset, microblaze_store_gregset
    195  1.1  christos   },
    196  1.1  christos   NULL_REGSET
    197  1.1  christos };
    198  1.1  christos #endif /* HAVE_PTRACE_GETREGS */
    199  1.1  christos 
    200  1.1  christos static struct usrregs_info microblaze_usrregs_info =
    201  1.1  christos   {
    202  1.1  christos     microblaze_num_regs,
    203  1.1  christos     microblaze_regmap,
    204  1.1  christos   };
    205  1.1  christos 
    206  1.1  christos #ifdef HAVE_PTRACE_GETREGS
    207  1.1  christos static struct regsets_info microblaze_regsets_info =
    208  1.1  christos   {
    209  1.1  christos     microblaze_regsets, /* regsets */
    210  1.1  christos     0, /* num_regsets */
    211  1.1  christos     nullptr /* disabled_regsets */
    212  1.1  christos   };
    213  1.1  christos #endif /* HAVE_PTRACE_GETREGS */
    214  1.1  christos 
    215  1.1  christos static struct regs_info microblaze_regs_info =
    216  1.1  christos   {
    217  1.1  christos     nullptr, /* regset_bitmap */
    218  1.1  christos     &microblaze_usrregs_info,
    219  1.1  christos #ifdef HAVE_PTRACE_GETREGS
    220  1.1  christos     &microblaze_regsets_info
    221  1.1  christos #endif /* HAVE_PTRACE_GETREGS */
    222  1.1  christos   };
    223  1.1  christos 
    224  1.1  christos const regs_info *
    225  1.1  christos microblaze_target::get_regs_info ()
    226  1.1  christos {
    227  1.1  christos   return &microblaze_regs_info;
    228  1.1  christos }
    229  1.1  christos 
    230  1.1  christos void
    231  1.1  christos microblaze_target::low_arch_setup ()
    232  1.1  christos {
    233  1.1  christos   current_process ()->tdesc = tdesc_microblaze_linux;
    234  1.1  christos }
    235  1.1  christos 
    236  1.1  christos linux_process_target *the_linux_target = &the_microblaze_target;
    237  1.1  christos 
    238  1.1  christos void
    239  1.1  christos initialize_low_arch ()
    240  1.1  christos {
    241  1.1  christos   init_registers_microblaze_linux ();
    242  1.1  christos #ifdef HAVE_PTRACE_GETREGS
    243  1.1  christos   initialize_regsets_info (&microblaze_regsets_info);
    244  1.1  christos #endif /* HAVE_PTRACE_GETREGS */
    245  1.1  christos }
    246