14b169a6bSchristos /* GNU/Linux/MIPS specific low level interface, for the remote server for GDB. 2*2be465b0Schristos Copyright (C) 2022-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 "tdesc.h" 204b169a6bSchristos #include "linux-low.h" 214b169a6bSchristos #include <sys/ptrace.h> 224b169a6bSchristos #include "gdb_proc_service.h" 234b169a6bSchristos #include <asm/ptrace.h> 244b169a6bSchristos #include <elf.h> 254b169a6bSchristos #include "arch/csky.h" 264b169a6bSchristos 274b169a6bSchristos /* Linux target op definitions for the CSKY architecture. */ 284b169a6bSchristos 294b169a6bSchristos class csky_target : public linux_process_target 304b169a6bSchristos { 314b169a6bSchristos public: 324b169a6bSchristos 334b169a6bSchristos const regs_info *get_regs_info () override; 344b169a6bSchristos 354b169a6bSchristos const gdb_byte *sw_breakpoint_from_kind (int kind, int *size) override; 364b169a6bSchristos 374b169a6bSchristos bool supports_z_point_type (char z_type) override; 384b169a6bSchristos 394b169a6bSchristos bool supports_hardware_single_step () override; 404b169a6bSchristos 414b169a6bSchristos protected: 424b169a6bSchristos 434b169a6bSchristos void low_arch_setup () override; 444b169a6bSchristos 454b169a6bSchristos bool low_cannot_fetch_register (int regno) override; 464b169a6bSchristos 474b169a6bSchristos bool low_cannot_store_register (int regno) override; 484b169a6bSchristos 494b169a6bSchristos CORE_ADDR low_get_pc (regcache *regcache) override; 504b169a6bSchristos 514b169a6bSchristos void low_set_pc (regcache *regcache, CORE_ADDR newpc) override; 524b169a6bSchristos 534b169a6bSchristos bool low_breakpoint_at (CORE_ADDR pc) override; 544b169a6bSchristos }; 554b169a6bSchristos 564b169a6bSchristos /* The singleton target ops object. */ 574b169a6bSchristos 584b169a6bSchristos static csky_target the_csky_target; 594b169a6bSchristos 604b169a6bSchristos /* Return the ptrace "address" of register REGNO. */ 614b169a6bSchristos static int csky_regmap[] = { 624b169a6bSchristos 0*4, 1*4, 2*4, 3*4, 4*4, 5*4, 6*4, 7*4, 634b169a6bSchristos 8*4, 9*4, 10*4, 11*4, 12*4, 13*4, 14*4, 15*4, 644b169a6bSchristos 16*4, 17*4, 18*4, 19*4, 20*4, 21*4, 22*4, 23*4, 654b169a6bSchristos 24*4, 25*4, 26*4, 27*4, 28*4, 29*4, 30*4, 31*4, 664b169a6bSchristos -1, -1, -1, -1, 34*4, 35*4, -1, -1, 674b169a6bSchristos 40*4, 42*4, 44*4, 46*4, 48*4, 50*4, 52*4, 54*4, /* fr0 ~ fr15, 64bit */ 684b169a6bSchristos 56*4, 58*4, 60*4, 62*4, 64*4, 66*4, 68*4, 70*4, 694b169a6bSchristos 72*4, 76*4, 80*4, 84*4, 88*4, 92*4, 96*4,100*4, /* vr0 ~ vr15, 128bit */ 704b169a6bSchristos 104*4,108*4,112*4,116*4,120*4,124*4,128*4,132*4, 714b169a6bSchristos 33*4, /* pc */ 724b169a6bSchristos -1, -1, -1, -1, -1, -1, -1, -1, 734b169a6bSchristos -1, -1, -1, -1, -1, -1, -1, -1, 744b169a6bSchristos 32*4, -1, -1, -1, -1, -1, -1, -1, /* psr */ 754b169a6bSchristos -1, -1, -1, -1, -1, -1, -1, -1, 764b169a6bSchristos -1, -1, -1, -1, -1, -1, -1, -1, 774b169a6bSchristos -1, -1, -1, -1, -1, -1, -1, -1, 784b169a6bSchristos 73*4, 72*4, 74*4, -1, -1, -1, 14*4, /* fcr, fid, fesr, usp */ 794b169a6bSchristos }; 804b169a6bSchristos 814b169a6bSchristos /* CSKY software breakpoint instruction code. */ 824b169a6bSchristos 834b169a6bSchristos /* When the kernel code version is behind v4.x, 844b169a6bSchristos illegal insn 0x1464 will be a software bkpt trigger. 854b169a6bSchristos When an illegal insn exception happens, the case 864b169a6bSchristos that insn at EPC is 0x1464 will be recognized as SIGTRAP. */ 874b169a6bSchristos static unsigned short csky_breakpoint_illegal_2_v2 = 0x1464; 884b169a6bSchristos static unsigned int csky_breakpoint_illegal_4_v2 = 0x14641464; 894b169a6bSchristos 904b169a6bSchristos bool 914b169a6bSchristos csky_target::low_cannot_fetch_register (int regno) 924b169a6bSchristos { 934b169a6bSchristos if (csky_regmap[regno] == -1) 944b169a6bSchristos return true; 954b169a6bSchristos 964b169a6bSchristos return false; 974b169a6bSchristos } 984b169a6bSchristos 994b169a6bSchristos bool 1004b169a6bSchristos csky_target::low_cannot_store_register (int regno) 1014b169a6bSchristos { 1024b169a6bSchristos if (csky_regmap[regno] == -1) 1034b169a6bSchristos return true; 1044b169a6bSchristos 1054b169a6bSchristos return false; 1064b169a6bSchristos } 1074b169a6bSchristos 1084b169a6bSchristos /* Get the value of pc register. */ 1094b169a6bSchristos 1104b169a6bSchristos CORE_ADDR 1114b169a6bSchristos csky_target::low_get_pc (struct regcache *regcache) 1124b169a6bSchristos { 1134b169a6bSchristos unsigned long pc; 1144b169a6bSchristos collect_register_by_name (regcache, "pc", &pc); 1154b169a6bSchristos return pc; 1164b169a6bSchristos } 1174b169a6bSchristos 1184b169a6bSchristos /* Set pc register. */ 1194b169a6bSchristos 1204b169a6bSchristos void 1214b169a6bSchristos csky_target::low_set_pc (struct regcache *regcache, CORE_ADDR pc) 1224b169a6bSchristos { 1234b169a6bSchristos unsigned long new_pc = pc; 1244b169a6bSchristos supply_register_by_name (regcache, "pc", &new_pc); 1254b169a6bSchristos } 1264b169a6bSchristos 1274b169a6bSchristos 1284b169a6bSchristos void 1294b169a6bSchristos csky_target::low_arch_setup () 1304b169a6bSchristos { 1314b169a6bSchristos static const char *expedite_regs[] = { "r14", "pc", NULL }; 1324b169a6bSchristos target_desc_up tdesc = csky_create_target_description (); 1334b169a6bSchristos 134*2be465b0Schristos if (tdesc->expedite_regs.empty ()) 135*2be465b0Schristos { 1364b169a6bSchristos init_target_desc (tdesc.get (), expedite_regs); 137*2be465b0Schristos gdb_assert (!tdesc->expedite_regs.empty ()); 138*2be465b0Schristos } 1394b169a6bSchristos 1404b169a6bSchristos current_process ()->tdesc = tdesc.release (); 1414b169a6bSchristos 1424b169a6bSchristos return; 1434b169a6bSchristos } 1444b169a6bSchristos 1454b169a6bSchristos /* Fetch the thread-local storage pointer for libthread_db. */ 1464b169a6bSchristos 1474b169a6bSchristos ps_err_e 1484b169a6bSchristos ps_get_thread_area (struct ps_prochandle *ph, 1494b169a6bSchristos lwpid_t lwpid, int idx, void **base) 1504b169a6bSchristos { 1514b169a6bSchristos struct pt_regs regset; 1524b169a6bSchristos if (ptrace (PTRACE_GETREGSET, lwpid, 1534b169a6bSchristos (PTRACE_TYPE_ARG3) (long) NT_PRSTATUS, ®set) != 0) 1544b169a6bSchristos return PS_ERR; 1554b169a6bSchristos 1564b169a6bSchristos *base = (void *) regset.tls; 1574b169a6bSchristos 1584b169a6bSchristos /* IDX is the bias from the thread pointer to the beginning of the 1594b169a6bSchristos thread descriptor. It has to be subtracted due to implementation 1604b169a6bSchristos quirks in libthread_db. */ 1614b169a6bSchristos *base = (void *) ((char *)*base - idx); 1624b169a6bSchristos 1634b169a6bSchristos return PS_OK; 1644b169a6bSchristos } 1654b169a6bSchristos 1664b169a6bSchristos /* Gdbserver uses PTRACE_GET/SET_RGESET. */ 1674b169a6bSchristos 1684b169a6bSchristos static void 1694b169a6bSchristos csky_fill_pt_gregset (struct regcache *regcache, void *buf) 1704b169a6bSchristos { 1714b169a6bSchristos int i, base; 1724b169a6bSchristos struct pt_regs *regset = (struct pt_regs *)buf; 1734b169a6bSchristos 1744b169a6bSchristos collect_register_by_name (regcache, "r15", ®set->lr); 1754b169a6bSchristos collect_register_by_name (regcache, "pc", ®set->pc); 1764b169a6bSchristos collect_register_by_name (regcache, "psr", ®set->sr); 1774b169a6bSchristos collect_register_by_name (regcache, "r14", ®set->usp); 1784b169a6bSchristos 1794b169a6bSchristos collect_register_by_name (regcache, "r0", ®set->a0); 1804b169a6bSchristos collect_register_by_name (regcache, "r1", ®set->a1); 1814b169a6bSchristos collect_register_by_name (regcache, "r2", ®set->a2); 1824b169a6bSchristos collect_register_by_name (regcache, "r3", ®set->a3); 1834b169a6bSchristos 1844b169a6bSchristos base = find_regno (regcache->tdesc, "r4"); 1854b169a6bSchristos 1864b169a6bSchristos for (i = 0; i < 10; i++) 1874b169a6bSchristos collect_register (regcache, base + i, ®set->regs[i]); 1884b169a6bSchristos 1894b169a6bSchristos base = find_regno (regcache->tdesc, "r16"); 1904b169a6bSchristos for (i = 0; i < 16; i++) 1914b169a6bSchristos collect_register (regcache, base + i, ®set->exregs[i]); 1924b169a6bSchristos 1934b169a6bSchristos collect_register_by_name (regcache, "hi", ®set->rhi); 1944b169a6bSchristos collect_register_by_name (regcache, "lo", ®set->rlo); 1954b169a6bSchristos } 1964b169a6bSchristos 1974b169a6bSchristos static void 1984b169a6bSchristos csky_store_pt_gregset (struct regcache *regcache, const void *buf) 1994b169a6bSchristos { 2004b169a6bSchristos int i, base; 2014b169a6bSchristos const struct pt_regs *regset = (const struct pt_regs *) buf; 2024b169a6bSchristos 2034b169a6bSchristos supply_register_by_name (regcache, "r15", ®set->lr); 2044b169a6bSchristos supply_register_by_name (regcache, "pc", ®set->pc); 2054b169a6bSchristos supply_register_by_name (regcache, "psr", ®set->sr); 2064b169a6bSchristos supply_register_by_name (regcache, "r14", ®set->usp); 2074b169a6bSchristos 2084b169a6bSchristos supply_register_by_name (regcache, "r0", ®set->a0); 2094b169a6bSchristos supply_register_by_name (regcache, "r1", ®set->a1); 2104b169a6bSchristos supply_register_by_name (regcache, "r2", ®set->a2); 2114b169a6bSchristos supply_register_by_name (regcache, "r3", ®set->a3); 2124b169a6bSchristos 2134b169a6bSchristos base = find_regno (regcache->tdesc, "r4"); 2144b169a6bSchristos 2154b169a6bSchristos for (i = 0; i < 10; i++) 2164b169a6bSchristos supply_register (regcache, base + i, ®set->regs[i]); 2174b169a6bSchristos 2184b169a6bSchristos base = find_regno (regcache->tdesc, "r16"); 2194b169a6bSchristos for (i = 0; i < 16; i++) 2204b169a6bSchristos supply_register (regcache, base + i, ®set->exregs[i]); 2214b169a6bSchristos 2224b169a6bSchristos supply_register_by_name (regcache, "hi", ®set->rhi); 2234b169a6bSchristos supply_register_by_name (regcache, "lo", ®set->rlo); 2244b169a6bSchristos } 2254b169a6bSchristos 2264b169a6bSchristos static void 2274b169a6bSchristos csky_fill_pt_vrregset (struct regcache *regcache, void *buf) 2284b169a6bSchristos { 2294b169a6bSchristos int i, base; 2304b169a6bSchristos struct user_fp *regset = (struct user_fp *)buf; 2314b169a6bSchristos 2324b169a6bSchristos base = find_regno (regcache->tdesc, "vr0"); 2334b169a6bSchristos 2344b169a6bSchristos for (i = 0; i < 16; i++) 2354b169a6bSchristos collect_register (regcache, base + i, ®set->vr[i * 4]); 2364b169a6bSchristos collect_register_by_name (regcache, "fcr", ®set->fcr); 2374b169a6bSchristos collect_register_by_name (regcache, "fesr", ®set->fesr); 2384b169a6bSchristos collect_register_by_name (regcache, "fid", ®set->fid); 2394b169a6bSchristos } 2404b169a6bSchristos 2414b169a6bSchristos 2424b169a6bSchristos static void 2434b169a6bSchristos csky_store_pt_vrregset (struct regcache *regcache, const void *buf) 2444b169a6bSchristos { 2454b169a6bSchristos int i, base; 2464b169a6bSchristos const struct user_fp *regset = (const struct user_fp *)buf; 2474b169a6bSchristos 2484b169a6bSchristos base = find_regno (regcache->tdesc, "vr0"); 2494b169a6bSchristos 2504b169a6bSchristos for (i = 0; i < 16; i++) 2514b169a6bSchristos supply_register (regcache, base + i, ®set->vr[i * 4]); 2524b169a6bSchristos 2534b169a6bSchristos base = find_regno (regcache->tdesc, "fr0"); 2544b169a6bSchristos 2554b169a6bSchristos for (i = 0; i < 16; i++) 2564b169a6bSchristos supply_register (regcache, base + i, ®set->vr[i * 4]); 2574b169a6bSchristos supply_register_by_name (regcache, "fcr", ®set->fcr); 2584b169a6bSchristos supply_register_by_name (regcache, "fesr", ®set->fesr); 2594b169a6bSchristos supply_register_by_name (regcache, "fid", ®set->fid); 2604b169a6bSchristos } 2614b169a6bSchristos 2624b169a6bSchristos struct regset_info csky_regsets[] = { 2634b169a6bSchristos { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_PRSTATUS, sizeof(struct pt_regs), 2644b169a6bSchristos GENERAL_REGS, csky_fill_pt_gregset, csky_store_pt_gregset}, 2654b169a6bSchristos 2664b169a6bSchristos { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_FPREGSET, sizeof(struct user_fp), 2674b169a6bSchristos FP_REGS, csky_fill_pt_vrregset, csky_store_pt_vrregset}, 2684b169a6bSchristos NULL_REGSET 2694b169a6bSchristos }; 2704b169a6bSchristos 2714b169a6bSchristos 2724b169a6bSchristos static struct regsets_info csky_regsets_info = 2734b169a6bSchristos { 2744b169a6bSchristos csky_regsets, /* Regsets */ 2754b169a6bSchristos 0, /* Num_regsets */ 2764b169a6bSchristos NULL, /* Disabled_regsets */ 2774b169a6bSchristos }; 2784b169a6bSchristos 2794b169a6bSchristos 2804b169a6bSchristos static struct regs_info csky_regs_info = 2814b169a6bSchristos { 2824b169a6bSchristos NULL, /* FIXME: what's this */ 283*2be465b0Schristos NULL, /* PEEKUSER/POKEUSR isn't supported by kernel > 4.x */ 2844b169a6bSchristos &csky_regsets_info 2854b169a6bSchristos }; 2864b169a6bSchristos 2874b169a6bSchristos 2884b169a6bSchristos const regs_info * 2894b169a6bSchristos csky_target::get_regs_info () 2904b169a6bSchristos { 2914b169a6bSchristos return &csky_regs_info; 2924b169a6bSchristos } 2934b169a6bSchristos 2944b169a6bSchristos /* Implementation of linux_target_ops method "sw_breakpoint_from_kind". */ 2954b169a6bSchristos 2964b169a6bSchristos const gdb_byte * 2974b169a6bSchristos csky_target::sw_breakpoint_from_kind (int kind, int *size) 2984b169a6bSchristos { 2994b169a6bSchristos if (kind == 4) 3004b169a6bSchristos { 3014b169a6bSchristos *size = 4; 3024b169a6bSchristos return (const gdb_byte *) &csky_breakpoint_illegal_4_v2; 3034b169a6bSchristos } 3044b169a6bSchristos else 3054b169a6bSchristos { 3064b169a6bSchristos *size = 2; 3074b169a6bSchristos return (const gdb_byte *) &csky_breakpoint_illegal_2_v2; 3084b169a6bSchristos } 3094b169a6bSchristos } 3104b169a6bSchristos 3114b169a6bSchristos bool 3124b169a6bSchristos csky_target::supports_z_point_type (char z_type) 3134b169a6bSchristos { 3144b169a6bSchristos /* FIXME: hardware breakpoint support ?? */ 3154b169a6bSchristos if (z_type == Z_PACKET_SW_BP) 3164b169a6bSchristos return true; 3174b169a6bSchristos 3184b169a6bSchristos return false; 3194b169a6bSchristos } 3204b169a6bSchristos 3214b169a6bSchristos bool 3224b169a6bSchristos csky_target::low_breakpoint_at (CORE_ADDR where) 3234b169a6bSchristos { 3244b169a6bSchristos unsigned int insn; 3254b169a6bSchristos 3264b169a6bSchristos /* Here just read 2 bytes, as csky_breakpoint_illegal_4_v2 3274b169a6bSchristos is double of csky_breakpoint_illegal_2_v2, csky_breakpoint_bkpt_4 3284b169a6bSchristos is double of csky_breakpoint_bkpt_2. Others are 2 bytes bkpt. */ 3294b169a6bSchristos read_memory (where, (unsigned char *) &insn, 2); 3304b169a6bSchristos 3314b169a6bSchristos if (insn == csky_breakpoint_illegal_2_v2) 3324b169a6bSchristos return true; 3334b169a6bSchristos 3344b169a6bSchristos return false; 3354b169a6bSchristos } 3364b169a6bSchristos 3374b169a6bSchristos /* Support for hardware single step. */ 3384b169a6bSchristos 3394b169a6bSchristos bool 3404b169a6bSchristos csky_target::supports_hardware_single_step () 3414b169a6bSchristos { 3424b169a6bSchristos return true; 3434b169a6bSchristos } 3444b169a6bSchristos 3454b169a6bSchristos /* The linux target ops object. */ 3464b169a6bSchristos 3474b169a6bSchristos linux_process_target *the_linux_target = &the_csky_target; 3484b169a6bSchristos 3494b169a6bSchristos void 3504b169a6bSchristos initialize_low_arch (void) 3514b169a6bSchristos { 3524b169a6bSchristos initialize_regsets_info (&csky_regsets_info); 3534b169a6bSchristos } 354