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