xref: /netbsd-src/external/gpl3/gdb/dist/gdbserver/linux-or1k-low.cc (revision 64f917f5a88990e32dd65fcd4348042fa7f852b9)
14b169a6bSchristos /* GNU/Linux/OR1K specific low level interface for the GDB server.
2*64f917f5Schristos    Copyright (C) 2021-2024 Free Software Foundation, Inc.
34b169a6bSchristos 
44b169a6bSchristos    This file is part of GDB.
54b169a6bSchristos 
64b169a6bSchristos    This program is free software; you can redistribute it and/or modify
74b169a6bSchristos    it under the terms of the GNU General Public License as published by
84b169a6bSchristos    the Free Software Foundation; either version 3 of the License, or
94b169a6bSchristos    (at your option) any later version.
104b169a6bSchristos 
114b169a6bSchristos    This program is distributed in the hope that it will be useful,
124b169a6bSchristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
134b169a6bSchristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
144b169a6bSchristos    GNU General Public License for more details.
154b169a6bSchristos 
164b169a6bSchristos    You should have received a copy of the GNU General Public License
174b169a6bSchristos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
184b169a6bSchristos 
194b169a6bSchristos #include "linux-low.h"
204b169a6bSchristos #include "elf/common.h"
214b169a6bSchristos #include "nat/gdb_ptrace.h"
224b169a6bSchristos #include <endian.h>
234b169a6bSchristos #include "gdb_proc_service.h"
244b169a6bSchristos #include <asm/ptrace.h>
254b169a6bSchristos 
264b169a6bSchristos #ifndef PTRACE_GET_THREAD_AREA
274b169a6bSchristos #define PTRACE_GET_THREAD_AREA 25
284b169a6bSchristos #endif
294b169a6bSchristos 
304b169a6bSchristos /* Linux target op definitions for the OpenRISC architecture.  */
314b169a6bSchristos 
324b169a6bSchristos class or1k_target : public linux_process_target
334b169a6bSchristos {
344b169a6bSchristos public:
354b169a6bSchristos 
364b169a6bSchristos   const regs_info *get_regs_info () override;
374b169a6bSchristos 
384b169a6bSchristos   const gdb_byte *sw_breakpoint_from_kind (int kind, int *size) override;
394b169a6bSchristos 
404b169a6bSchristos protected:
414b169a6bSchristos 
424b169a6bSchristos   void low_arch_setup () override;
434b169a6bSchristos 
444b169a6bSchristos   bool low_cannot_fetch_register (int regno) override;
454b169a6bSchristos 
464b169a6bSchristos   bool low_cannot_store_register (int regno) override;
474b169a6bSchristos 
484b169a6bSchristos   bool low_supports_breakpoints () override;
494b169a6bSchristos 
504b169a6bSchristos   CORE_ADDR low_get_pc (regcache *regcache) override;
514b169a6bSchristos 
524b169a6bSchristos   void low_set_pc (regcache *regcache, CORE_ADDR newpc) override;
534b169a6bSchristos 
544b169a6bSchristos   bool low_breakpoint_at (CORE_ADDR pc) override;
554b169a6bSchristos };
564b169a6bSchristos 
574b169a6bSchristos /* The singleton target ops object.  */
584b169a6bSchristos 
594b169a6bSchristos static or1k_target the_or1k_target;
604b169a6bSchristos 
614b169a6bSchristos bool
624b169a6bSchristos or1k_target::low_supports_breakpoints ()
634b169a6bSchristos {
644b169a6bSchristos   return true;
654b169a6bSchristos }
664b169a6bSchristos 
674b169a6bSchristos CORE_ADDR
684b169a6bSchristos or1k_target::low_get_pc (regcache *regcache)
694b169a6bSchristos {
704b169a6bSchristos   return linux_get_pc_32bit (regcache);
714b169a6bSchristos }
724b169a6bSchristos 
734b169a6bSchristos void
744b169a6bSchristos or1k_target::low_set_pc (regcache *regcache, CORE_ADDR pc)
754b169a6bSchristos {
764b169a6bSchristos   linux_set_pc_32bit (regcache, pc);
774b169a6bSchristos }
784b169a6bSchristos 
794b169a6bSchristos /* The following definition must agree with the number of registers
804b169a6bSchristos    defined in "struct user_regs" in GLIBC
814b169a6bSchristos    (sysdeps/unix/sysv/linux/or1k/sys/ucontext.h), and also with
824b169a6bSchristos    OR1K_NUM_REGS in GDB proper.  */
834b169a6bSchristos 
844b169a6bSchristos #define or1k_num_regs 35
854b169a6bSchristos 
864b169a6bSchristos /* Defined in auto-generated file or1k-linux.c.  */
874b169a6bSchristos 
884b169a6bSchristos void init_registers_or1k_linux (void);
894b169a6bSchristos extern const struct target_desc *tdesc_or1k_linux;
904b169a6bSchristos 
914b169a6bSchristos /* This union is used to convert between int and byte buffer
924b169a6bSchristos    representations of register contents.  */
934b169a6bSchristos 
944b169a6bSchristos union or1k_register
954b169a6bSchristos {
964b169a6bSchristos   unsigned char buf[4];
974b169a6bSchristos   int reg32;
984b169a6bSchristos };
994b169a6bSchristos 
1004b169a6bSchristos /* Return the ptrace ``address'' of register REGNO. */
1014b169a6bSchristos 
1024b169a6bSchristos static int or1k_regmap[] = {
1034b169a6bSchristos   -1,  1,  2,  3,  4,  5,  6,  7,
1044b169a6bSchristos   8,  9,  10, 11, 12, 13, 14, 15,
1054b169a6bSchristos   16, 17, 18, 19, 20, 21, 22, 23,
1064b169a6bSchristos   24, 25, 26, 27, 28, 29, 30, 31,
1074b169a6bSchristos   -1, /* PC */
1084b169a6bSchristos   -1, /* ORIGINAL R11 */
1094b169a6bSchristos   -1  /* SYSCALL NO */
1104b169a6bSchristos };
1114b169a6bSchristos 
1124b169a6bSchristos /* Implement the low_arch_setup linux target ops method.  */
1134b169a6bSchristos 
1144b169a6bSchristos void
1154b169a6bSchristos or1k_target::low_arch_setup ()
1164b169a6bSchristos {
1174b169a6bSchristos   current_process ()->tdesc = tdesc_or1k_linux;
1184b169a6bSchristos }
1194b169a6bSchristos 
1204b169a6bSchristos /* Implement the low_cannot_fetch_register linux target ops method.  */
1214b169a6bSchristos 
1224b169a6bSchristos bool
1234b169a6bSchristos or1k_target::low_cannot_fetch_register (int regno)
1244b169a6bSchristos {
1254b169a6bSchristos   return (or1k_regmap[regno] == -1);
1264b169a6bSchristos }
1274b169a6bSchristos 
1284b169a6bSchristos /* Implement the low_cannot_store_register linux target ops method.  */
1294b169a6bSchristos 
1304b169a6bSchristos bool
1314b169a6bSchristos or1k_target::low_cannot_store_register (int regno)
1324b169a6bSchristos {
1334b169a6bSchristos   return (or1k_regmap[regno] == -1);
1344b169a6bSchristos }
1354b169a6bSchristos 
1364b169a6bSchristos /* Breakpoint support.  */
1374b169a6bSchristos 
1384b169a6bSchristos static const unsigned int or1k_breakpoint = 0x21000001;
1394b169a6bSchristos #define or1k_breakpoint_len 4
1404b169a6bSchristos 
1414b169a6bSchristos /* Implementation of target ops method "sw_breakpoint_from_kind".  */
1424b169a6bSchristos 
1434b169a6bSchristos const gdb_byte *
1444b169a6bSchristos or1k_target::sw_breakpoint_from_kind (int kind, int *size)
1454b169a6bSchristos {
1464b169a6bSchristos   *size = or1k_breakpoint_len;
1474b169a6bSchristos   return (const gdb_byte *) &or1k_breakpoint;
1484b169a6bSchristos }
1494b169a6bSchristos 
1504b169a6bSchristos /* Implement the low_breakpoint_at linux target ops method.  */
1514b169a6bSchristos 
1524b169a6bSchristos bool
1534b169a6bSchristos or1k_target::low_breakpoint_at (CORE_ADDR where)
1544b169a6bSchristos {
1554b169a6bSchristos   unsigned int insn;
1564b169a6bSchristos 
1574b169a6bSchristos   read_memory (where, (unsigned char *) &insn, or1k_breakpoint_len);
1584b169a6bSchristos   if (insn == or1k_breakpoint)
1594b169a6bSchristos     return true;
1604b169a6bSchristos   return false;
1614b169a6bSchristos }
1624b169a6bSchristos 
1634b169a6bSchristos /* Fetch the thread-local storage pointer for libthread_db.  */
1644b169a6bSchristos 
1654b169a6bSchristos ps_err_e
1664b169a6bSchristos ps_get_thread_area (struct ps_prochandle *ph,
1674b169a6bSchristos 		    lwpid_t lwpid, int idx, void **base)
1684b169a6bSchristos {
1694b169a6bSchristos   if (ptrace (PTRACE_GET_THREAD_AREA, lwpid, NULL, base) != 0)
1704b169a6bSchristos     return PS_ERR;
1714b169a6bSchristos 
1724b169a6bSchristos   /* IDX is the bias from the thread pointer to the beginning of the
1734b169a6bSchristos      thread descriptor.  It has to be subtracted due to implementation
1744b169a6bSchristos      quirks in libthread_db.  */
1754b169a6bSchristos   *base = (void *) ((char *) *base - idx);
1764b169a6bSchristos 
1774b169a6bSchristos   return PS_OK;
1784b169a6bSchristos }
1794b169a6bSchristos 
1804b169a6bSchristos /* Helper functions to collect/supply a single register REGNO.  */
1814b169a6bSchristos 
1824b169a6bSchristos static void
1834b169a6bSchristos or1k_collect_register (struct regcache *regcache, int regno,
1844b169a6bSchristos 			union or1k_register *reg)
1854b169a6bSchristos {
1864b169a6bSchristos   union or1k_register tmp_reg;
1874b169a6bSchristos 
1884b169a6bSchristos   collect_register (regcache, regno, &tmp_reg.reg32);
1894b169a6bSchristos   reg->reg32 = tmp_reg.reg32;
1904b169a6bSchristos }
1914b169a6bSchristos 
1924b169a6bSchristos static void
1934b169a6bSchristos or1k_supply_register (struct regcache *regcache, int regno,
1944b169a6bSchristos 		       const union or1k_register *reg)
1954b169a6bSchristos {
1964b169a6bSchristos   supply_register (regcache, regno, reg->buf);
1974b169a6bSchristos }
1984b169a6bSchristos 
1994b169a6bSchristos /* We have only a single register set on OpenRISC.  */
2004b169a6bSchristos 
2014b169a6bSchristos static void
2024b169a6bSchristos or1k_fill_gregset (struct regcache *regcache, void *buf)
2034b169a6bSchristos {
2044b169a6bSchristos   union or1k_register *regset = (union or1k_register *) buf;
2054b169a6bSchristos   int i;
2064b169a6bSchristos 
2074b169a6bSchristos   for (i = 1; i < or1k_num_regs; i++)
2084b169a6bSchristos     or1k_collect_register (regcache, i, regset + i);
2094b169a6bSchristos }
2104b169a6bSchristos 
2114b169a6bSchristos static void
2124b169a6bSchristos or1k_store_gregset (struct regcache *regcache, const void *buf)
2134b169a6bSchristos {
2144b169a6bSchristos   const union or1k_register *regset = (union or1k_register *) buf;
2154b169a6bSchristos   int i;
2164b169a6bSchristos 
2174b169a6bSchristos   for (i = 0; i < or1k_num_regs; i++)
2184b169a6bSchristos     or1k_supply_register (regcache, i, regset + i);
2194b169a6bSchristos }
2204b169a6bSchristos 
2214b169a6bSchristos static struct regset_info or1k_regsets[] =
2224b169a6bSchristos {
2234b169a6bSchristos   { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_PRSTATUS,
2244b169a6bSchristos     or1k_num_regs * 4, GENERAL_REGS,
2254b169a6bSchristos     or1k_fill_gregset, or1k_store_gregset },
2264b169a6bSchristos   NULL_REGSET
2274b169a6bSchristos };
2284b169a6bSchristos 
2294b169a6bSchristos static struct regsets_info or1k_regsets_info =
2304b169a6bSchristos   {
2314b169a6bSchristos     or1k_regsets, /* regsets */
2324b169a6bSchristos     0, /* num_regsets */
2334b169a6bSchristos     NULL, /* disabled_regsets */
2344b169a6bSchristos   };
2354b169a6bSchristos 
2364b169a6bSchristos static struct usrregs_info or1k_usrregs_info =
2374b169a6bSchristos   {
2384b169a6bSchristos     or1k_num_regs,
2394b169a6bSchristos     or1k_regmap,
2404b169a6bSchristos   };
2414b169a6bSchristos 
2424b169a6bSchristos static struct regs_info or1k_regs =
2434b169a6bSchristos   {
2444b169a6bSchristos     NULL, /* regset_bitmap */
2454b169a6bSchristos     &or1k_usrregs_info,
2464b169a6bSchristos     &or1k_regsets_info
2474b169a6bSchristos   };
2484b169a6bSchristos 
2494b169a6bSchristos const regs_info *
2504b169a6bSchristos or1k_target::get_regs_info ()
2514b169a6bSchristos {
2524b169a6bSchristos   return &or1k_regs;
2534b169a6bSchristos }
2544b169a6bSchristos 
2554b169a6bSchristos /* The linux target ops object.  */
2564b169a6bSchristos 
2574b169a6bSchristos linux_process_target *the_linux_target = &the_or1k_target;
2584b169a6bSchristos 
2594b169a6bSchristos void
2604b169a6bSchristos initialize_low_arch (void)
2614b169a6bSchristos {
2624b169a6bSchristos   init_registers_or1k_linux ();
2634b169a6bSchristos 
2644b169a6bSchristos   initialize_regsets_info (&or1k_regsets_info);
2654b169a6bSchristos }
266