More updated translations
[binutils-gdb.git] / gdbserver / linux-loongarch-low.cc
blob795b6f5b1c0efe44ad1ee8a224972179895809c5
1 /* GNU/Linux/LoongArch specific low level interface, for the remote server
2 for GDB.
3 Copyright (C) 2022-2024 Free Software Foundation, Inc.
5 This file is part of GDB.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
20 #include "linux-low.h"
21 #include "nat/loongarch-hw-point.h"
22 #include "nat/loongarch-linux.h"
23 #include "nat/loongarch-linux-hw-point.h"
24 #include "tdesc.h"
25 #include "elf/common.h"
26 #include "arch/loongarch.h"
28 /* Linux target ops definitions for the LoongArch architecture. */
30 class loongarch_target : public linux_process_target
32 public:
34 const regs_info *get_regs_info () override;
36 int breakpoint_kind_from_pc (CORE_ADDR *pcptr) override;
38 const gdb_byte *sw_breakpoint_from_kind (int kind, int *size) override;
40 bool supports_z_point_type (char z_type) override;
42 protected:
44 void low_arch_setup () override;
46 bool low_cannot_fetch_register (int regno) override;
48 bool low_cannot_store_register (int regno) override;
50 bool low_fetch_register (regcache *regcache, int regno) override;
52 bool low_supports_breakpoints () override;
54 CORE_ADDR low_get_pc (regcache *regcache) override;
56 void low_set_pc (regcache *regcache, CORE_ADDR newpc) override;
58 bool low_breakpoint_at (CORE_ADDR pc) override;
60 int low_insert_point (raw_bkpt_type type, CORE_ADDR addr,
61 int size, raw_breakpoint *bp) override;
63 int low_remove_point (raw_bkpt_type type, CORE_ADDR addr,
64 int size, raw_breakpoint *bp) override;
66 bool low_stopped_by_watchpoint () override;
68 CORE_ADDR low_stopped_data_address () override;
70 arch_process_info *low_new_process () override;
72 void low_delete_process (arch_process_info *info) override;
74 void low_new_thread (lwp_info *) override;
76 void low_delete_thread (arch_lwp_info *) override;
78 void low_new_fork (process_info *parent, process_info *child) override;
80 void low_prepare_to_resume (lwp_info *lwp) override;
83 /* The singleton target ops object. */
85 static loongarch_target the_loongarch_target;
87 bool
88 loongarch_target::low_cannot_fetch_register (int regno)
90 gdb_assert_not_reached ("linux target op low_cannot_fetch_register "
91 "is not implemented by the target");
94 bool
95 loongarch_target::low_cannot_store_register (int regno)
97 gdb_assert_not_reached ("linux target op low_cannot_store_register "
98 "is not implemented by the target");
101 void
102 loongarch_target::low_prepare_to_resume (lwp_info *lwp)
104 loongarch_linux_prepare_to_resume (lwp);
107 /* Per-process arch-specific data we want to keep. */
109 struct arch_process_info
111 struct loongarch_debug_reg_state debug_reg_state;
114 /* Implementation of linux target ops method "low_arch_setup". */
116 void
117 loongarch_target::low_arch_setup ()
119 static const char *expedite_regs[] = { "r3", "pc", NULL };
120 loongarch_gdbarch_features features;
121 target_desc_up tdesc;
123 features.xlen = sizeof (elf_greg_t);
124 tdesc = loongarch_create_target_description (features);
126 if (tdesc->expedite_regs.empty ())
128 init_target_desc (tdesc.get (), expedite_regs, GDB_OSABI_LINUX);
129 gdb_assert (!tdesc->expedite_regs.empty ());
131 current_process ()->tdesc = tdesc.release ();
132 loongarch_linux_get_debug_reg_capacity (current_thread->id.lwp ());
135 /* Collect GPRs from REGCACHE into BUF. */
137 static void
138 loongarch_fill_gregset (struct regcache *regcache, void *buf)
140 elf_gregset_t *regset = (elf_gregset_t *) buf;
141 int i;
143 for (i = 1; i < 32; i++)
144 collect_register (regcache, i, *regset + i);
145 collect_register (regcache, LOONGARCH_ORIG_A0_REGNUM, *regset + LOONGARCH_ORIG_A0_REGNUM);
146 collect_register (regcache, LOONGARCH_PC_REGNUM, *regset + LOONGARCH_PC_REGNUM);
147 collect_register (regcache, LOONGARCH_BADV_REGNUM, *regset + LOONGARCH_BADV_REGNUM);
150 /* Supply GPRs from BUF into REGCACHE. */
152 static void
153 loongarch_store_gregset (struct regcache *regcache, const void *buf)
155 const elf_gregset_t *regset = (const elf_gregset_t *) buf;
156 int i;
158 supply_register_zeroed (regcache, 0);
159 for (i = 1; i < 32; i++)
160 supply_register (regcache, i, *regset + i);
161 supply_register (regcache, LOONGARCH_ORIG_A0_REGNUM, *regset + LOONGARCH_ORIG_A0_REGNUM);
162 supply_register (regcache, LOONGARCH_PC_REGNUM, *regset + LOONGARCH_PC_REGNUM);
163 supply_register (regcache, LOONGARCH_BADV_REGNUM, *regset + LOONGARCH_BADV_REGNUM);
166 /* Collect FPRs from REGCACHE into BUF. */
168 static void
169 loongarch_fill_fpregset (struct regcache *regcache, void *buf)
171 gdb_byte *regbuf = nullptr;
172 int fprsize = register_size (regcache->tdesc, LOONGARCH_FIRST_FP_REGNUM);
173 int fccsize = register_size (regcache->tdesc, LOONGARCH_FIRST_FCC_REGNUM);
175 for (int i = 0; i < LOONGARCH_LINUX_NUM_FPREGSET; i++)
177 regbuf = (gdb_byte *)buf + fprsize * i;
178 collect_register (regcache, LOONGARCH_FIRST_FP_REGNUM + i, regbuf);
181 for (int i = 0; i < LOONGARCH_LINUX_NUM_FCC; i++)
183 regbuf = (gdb_byte *)buf + fprsize * LOONGARCH_LINUX_NUM_FPREGSET +
184 fccsize * i;
185 collect_register (regcache, LOONGARCH_FIRST_FCC_REGNUM + i, regbuf);
188 regbuf = (gdb_byte *)buf + fprsize * LOONGARCH_LINUX_NUM_FPREGSET +
189 fccsize * LOONGARCH_LINUX_NUM_FCC;
190 collect_register (regcache, LOONGARCH_FCSR_REGNUM, regbuf);
193 /* Supply FPRs from BUF into REGCACHE. */
195 static void
196 loongarch_store_fpregset (struct regcache *regcache, const void *buf)
198 const gdb_byte *regbuf = nullptr;
199 int fprsize = register_size (regcache->tdesc, LOONGARCH_FIRST_FP_REGNUM);
200 int fccsize = register_size (regcache->tdesc, LOONGARCH_FIRST_FCC_REGNUM);
202 for (int i = 0; i < LOONGARCH_LINUX_NUM_FPREGSET; i++)
204 regbuf = (const gdb_byte *)buf + fprsize * i;
205 supply_register (regcache, LOONGARCH_FIRST_FP_REGNUM + i, regbuf);
208 for (int i = 0; i < LOONGARCH_LINUX_NUM_FCC; i++)
210 regbuf = (const gdb_byte *)buf + fprsize * LOONGARCH_LINUX_NUM_FPREGSET +
211 fccsize * i;
212 supply_register (regcache, LOONGARCH_FIRST_FCC_REGNUM + i, regbuf);
215 regbuf = (const gdb_byte *)buf + fprsize * LOONGARCH_LINUX_NUM_FPREGSET +
216 fccsize * LOONGARCH_LINUX_NUM_FCC;
217 supply_register (regcache, LOONGARCH_FCSR_REGNUM, regbuf);
220 /* Collect lsx regs from REGCACHE into BUF. */
222 static void
223 loongarch_fill_lsxregset (struct regcache *regcache, void *buf)
225 elf_lsxregset_t *regset = (elf_lsxregset_t *) buf;
226 int i;
228 for (i = 0; i < LOONGARCH_LINUX_NUM_LSXREGSET; i++)
229 collect_register (regcache, LOONGARCH_FIRST_LSX_REGNUM + i, *regset + i);
232 /* Supply lsx regs from BUF into REGCACHE. */
234 static void
235 loongarch_store_lsxregset (struct regcache *regcache, const void *buf)
237 const elf_lsxregset_t *regset = (const elf_lsxregset_t *) buf;
238 int i;
240 for (i = 0; i < LOONGARCH_LINUX_NUM_LSXREGSET; i++)
241 supply_register (regcache, LOONGARCH_FIRST_LSX_REGNUM + i, *regset + i);
244 /* Collect lasx regs from REGCACHE into BUF. */
246 static void
247 loongarch_fill_lasxregset (struct regcache *regcache, void *buf)
249 elf_lasxregset_t *regset = (elf_lasxregset_t *) buf;
250 int i;
252 for (i = 0; i < LOONGARCH_LINUX_NUM_LASXREGSET; i++)
253 collect_register (regcache, LOONGARCH_FIRST_LASX_REGNUM + i, *regset + i);
256 /* Supply lasx regs from BUF into REGCACHE. */
258 static void
259 loongarch_store_lasxregset (struct regcache *regcache, const void *buf)
261 const elf_lasxregset_t *regset = (const elf_lasxregset_t *) buf;
262 int i;
264 for (i = 0; i < LOONGARCH_LINUX_NUM_LASXREGSET; i++)
265 supply_register (regcache, LOONGARCH_FIRST_LASX_REGNUM + i, *regset + i);
268 /* Collect lbt regs from REGCACHE into BUF. */
270 static void
271 loongarch_fill_lbtregset (struct regcache *regcache, void *buf)
273 gdb_byte *regbuf = (gdb_byte*)buf;
274 int scrsize = register_size (regcache->tdesc, LOONGARCH_FIRST_SCR_REGNUM);
275 int eflagssize = register_size (regcache->tdesc, LOONGARCH_EFLAGS_REGNUM);
276 int i;
278 for (i = 0; i < LOONGARCH_LINUX_NUM_SCR; i++)
279 collect_register (regcache, LOONGARCH_FIRST_SCR_REGNUM + i, regbuf + scrsize * i);
281 collect_register (regcache, LOONGARCH_EFLAGS_REGNUM,
282 regbuf + LOONGARCH_LINUX_NUM_SCR * scrsize);
283 collect_register (regcache, LOONGARCH_FTOP_REGNUM,
284 regbuf + LOONGARCH_LINUX_NUM_SCR * scrsize + eflagssize);
288 /* Supply lbt regs from BUF into REGCACHE. */
290 static void
291 loongarch_store_lbtregset (struct regcache *regcache, const void *buf)
294 gdb_byte *regbuf = (gdb_byte*)buf;
295 int scrsize = register_size (regcache->tdesc, LOONGARCH_FIRST_SCR_REGNUM);
296 int eflagssize = register_size (regcache->tdesc, LOONGARCH_EFLAGS_REGNUM);
297 int i;
299 for (i = 0; i < LOONGARCH_LINUX_NUM_SCR; i++)
300 supply_register (regcache, LOONGARCH_FIRST_SCR_REGNUM + i, regbuf + scrsize * i);
302 supply_register (regcache, LOONGARCH_EFLAGS_REGNUM,
303 regbuf + LOONGARCH_LINUX_NUM_SCR * scrsize);
304 supply_register (regcache, LOONGARCH_FTOP_REGNUM,
305 regbuf + LOONGARCH_LINUX_NUM_SCR * scrsize + eflagssize);
309 /* LoongArch/Linux regsets. */
310 static struct regset_info loongarch_regsets[] = {
311 { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_PRSTATUS, sizeof (elf_gregset_t),
312 GENERAL_REGS, loongarch_fill_gregset, loongarch_store_gregset },
313 { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_FPREGSET, sizeof (elf_fpregset_t),
314 FP_REGS, loongarch_fill_fpregset, loongarch_store_fpregset },
315 { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_LARCH_LSX, sizeof (elf_lsxregset_t),
316 OPTIONAL_REGS, loongarch_fill_lsxregset, loongarch_store_lsxregset },
317 { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_LARCH_LASX, sizeof (elf_lasxregset_t),
318 OPTIONAL_REGS, loongarch_fill_lasxregset, loongarch_store_lasxregset },
319 { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_LARCH_LBT, LOONGARCH_LBT_REGS_SIZE,
320 OPTIONAL_REGS, loongarch_fill_lbtregset, loongarch_store_lbtregset },
321 NULL_REGSET
324 /* LoongArch/Linux regset information. */
325 static struct regsets_info loongarch_regsets_info =
327 loongarch_regsets, /* regsets */
328 0, /* num_regsets */
329 NULL, /* disabled_regsets */
332 /* Definition of linux_target_ops data member "regs_info". */
333 static struct regs_info loongarch_regs =
335 NULL, /* regset_bitmap */
336 NULL, /* usrregs */
337 &loongarch_regsets_info,
340 /* Implementation of linux target ops method "get_regs_info". */
342 const regs_info *
343 loongarch_target::get_regs_info ()
345 return &loongarch_regs;
348 /* Implementation of linux target ops method "low_fetch_register". */
350 bool
351 loongarch_target::low_fetch_register (regcache *regcache, int regno)
353 if (regno != 0)
354 return false;
355 supply_register_zeroed (regcache, 0);
356 return true;
359 bool
360 loongarch_target::low_supports_breakpoints ()
362 return true;
365 /* Implementation of linux target ops method "low_get_pc". */
367 CORE_ADDR
368 loongarch_target::low_get_pc (regcache *regcache)
370 if (register_size (regcache->tdesc, 0) == 8)
371 return linux_get_pc_64bit (regcache);
372 else
373 return linux_get_pc_32bit (regcache);
376 /* Implementation of linux target ops method "low_set_pc". */
378 void
379 loongarch_target::low_set_pc (regcache *regcache, CORE_ADDR newpc)
381 if (register_size (regcache->tdesc, 0) == 8)
382 linux_set_pc_64bit (regcache, newpc);
383 else
384 linux_set_pc_32bit (regcache, newpc);
387 #define loongarch_breakpoint_len 4
389 /* LoongArch BRK software debug mode instruction.
390 This instruction needs to match gdb/loongarch-tdep.c
391 (loongarch_default_breakpoint). */
392 static const gdb_byte loongarch_breakpoint[] = {0x05, 0x00, 0x2a, 0x00};
394 /* Implementation of target ops method "breakpoint_kind_from_pc". */
397 loongarch_target::breakpoint_kind_from_pc (CORE_ADDR *pcptr)
399 return loongarch_breakpoint_len;
402 /* Implementation of target ops method "sw_breakpoint_from_kind". */
404 const gdb_byte *
405 loongarch_target::sw_breakpoint_from_kind (int kind, int *size)
407 *size = loongarch_breakpoint_len;
408 return (const gdb_byte *) &loongarch_breakpoint;
411 /* Implementation of linux target ops method "low_breakpoint_at". */
413 bool
414 loongarch_target::low_breakpoint_at (CORE_ADDR pc)
416 gdb_byte insn[loongarch_breakpoint_len];
418 read_memory (pc, (unsigned char *) &insn, loongarch_breakpoint_len);
419 if (memcmp (insn, loongarch_breakpoint, loongarch_breakpoint_len) == 0)
420 return true;
422 return false;
425 static void
426 loongarch_init_debug_reg_state (struct loongarch_debug_reg_state *state)
428 int i;
430 for (i = 0; i < LOONGARCH_HBP_MAX_NUM; ++i)
432 state->dr_addr_bp[i] = 0;
433 state->dr_ctrl_bp[i] = 0;
434 state->dr_ref_count_bp[i] = 0;
437 for (i = 0; i < LOONGARCH_HWP_MAX_NUM; ++i)
439 state->dr_addr_wp[i] = 0;
440 state->dr_ctrl_wp[i] = 0;
441 state->dr_ref_count_wp[i] = 0;
445 /* See nat/loongarch-linux-hw-point.h. */
447 struct loongarch_debug_reg_state *
448 loongarch_get_debug_reg_state (pid_t pid)
450 struct process_info *proc = find_process_pid (pid);
452 return &proc->priv->arch_private->debug_reg_state;
455 /* Implementation of target ops method "supports_z_point_type". */
457 bool
458 loongarch_target::supports_z_point_type (char z_type)
460 switch (z_type)
462 case Z_PACKET_SW_BP:
463 case Z_PACKET_HW_BP:
464 case Z_PACKET_WRITE_WP:
465 case Z_PACKET_READ_WP:
466 case Z_PACKET_ACCESS_WP:
467 return true;
468 default:
469 return false;
473 /* Implementation of linux target ops method "low_insert_point".
475 It actually only records the info of the to-be-inserted bp/wp;
476 the actual insertion will happen when threads are resumed. */
479 loongarch_target::low_insert_point (raw_bkpt_type type, CORE_ADDR addr,
480 int len, raw_breakpoint *bp)
482 int ret;
483 enum target_hw_bp_type targ_type;
484 struct loongarch_debug_reg_state *state
485 = loongarch_get_debug_reg_state (current_thread->id.pid ());
487 if (show_debug_regs)
488 fprintf (stderr, "insert_point on entry (addr=0x%08lx, len=%d)\n",
489 (unsigned long) addr, len);
491 /* Determine the type from the raw breakpoint type. */
492 targ_type = raw_bkpt_type_to_target_hw_bp_type (type);
494 if (targ_type != hw_execute)
496 if (loongarch_region_ok_for_watchpoint (addr, len))
497 ret = loongarch_handle_watchpoint (targ_type, addr, len,
498 1 /* is_insert */,
499 current_lwp_ptid (), state);
500 else
501 ret = -1;
503 else
505 ret = loongarch_handle_breakpoint (targ_type, addr, len,
506 1 /* is_insert */, current_lwp_ptid (),
507 state);
510 if (show_debug_regs)
511 loongarch_show_debug_reg_state (state, "insert_point", addr, len,
512 targ_type);
514 return ret;
517 /* Implementation of linux target ops method "low_remove_point".
519 It actually only records the info of the to-be-removed bp/wp,
520 the actual removal will be done when threads are resumed. */
523 loongarch_target::low_remove_point (raw_bkpt_type type, CORE_ADDR addr,
524 int len, raw_breakpoint *bp)
526 int ret;
527 enum target_hw_bp_type targ_type;
528 struct loongarch_debug_reg_state *state
529 = loongarch_get_debug_reg_state (current_thread->id.pid ());
531 if (show_debug_regs)
532 fprintf (stderr, "remove_point on entry (addr=0x%08lx, len=%d)\n",
533 (unsigned long) addr, len);
535 /* Determine the type from the raw breakpoint type. */
536 targ_type = raw_bkpt_type_to_target_hw_bp_type (type);
538 /* Set up state pointers. */
539 if (targ_type != hw_execute)
540 ret =
541 loongarch_handle_watchpoint (targ_type, addr, len, 0 /* is_insert */,
542 current_lwp_ptid (), state);
543 else
545 ret = loongarch_handle_breakpoint (targ_type, addr, len,
546 0 /* is_insert */, current_lwp_ptid (),
547 state);
550 if (show_debug_regs)
551 loongarch_show_debug_reg_state (state, "remove_point", addr, len,
552 targ_type);
554 return ret;
558 /* Implementation of linux target ops method "low_stopped_data_address". */
560 CORE_ADDR
561 loongarch_target::low_stopped_data_address ()
563 siginfo_t siginfo;
564 struct loongarch_debug_reg_state *state;
565 int pid = current_thread->id.lwp ();
567 /* Get the siginfo. */
568 if (ptrace (PTRACE_GETSIGINFO, pid, NULL, &siginfo) != 0)
569 return (CORE_ADDR) 0;
571 /* Need to be a hardware breakpoint/watchpoint trap. */
572 if (siginfo.si_signo != SIGTRAP
573 || (siginfo.si_code & 0xffff) != 0x0004 /* TRAP_HWBKPT */)
574 return (CORE_ADDR) 0;
576 /* Check if the address matches any watched address. */
577 state = loongarch_get_debug_reg_state (current_thread->id.pid ());
578 CORE_ADDR result;
579 if (loongarch_stopped_data_address (state, (CORE_ADDR) siginfo.si_addr, &result))
580 return result;
582 return (CORE_ADDR) 0;
585 /* Implementation of linux target ops method "low_stopped_by_watchpoint". */
587 bool
588 loongarch_target::low_stopped_by_watchpoint ()
590 return (low_stopped_data_address () != 0);
593 /* Implementation of linux target ops method "low_new_process". */
595 arch_process_info *
596 loongarch_target::low_new_process ()
598 struct arch_process_info *info = XCNEW (struct arch_process_info);
600 loongarch_init_debug_reg_state (&info->debug_reg_state);
602 return info;
605 /* Implementation of linux target ops method "low_delete_process". */
607 void
608 loongarch_target::low_delete_process (arch_process_info *info)
610 xfree (info);
613 void
614 loongarch_target::low_new_thread (lwp_info *lwp)
616 loongarch_linux_new_thread (lwp);
619 void
620 loongarch_target::low_delete_thread (arch_lwp_info *arch_lwp)
622 loongarch_linux_delete_thread (arch_lwp);
625 /* Implementation of linux target ops method "low_new_fork". */
627 void
628 loongarch_target::low_new_fork (process_info *parent,
629 process_info *child)
631 /* These are allocated by linux_add_process. */
632 gdb_assert (parent->priv != NULL
633 && parent->priv->arch_private != NULL);
634 gdb_assert (child->priv != NULL
635 && child->priv->arch_private != NULL);
637 /* GDB core assumes the child inherits the watchpoints/hw
638 breakpoints of the parent, and will remove them all from the
639 forked off process. Copy the debug registers mirrors into the
640 new process so that all breakpoints and watchpoints can be
641 removed together. The debug registers mirror will become zeroed
642 in the end before detaching the forked off process, thus making
643 this compatible with older Linux kernels too. */
645 *child->priv->arch_private = *parent->priv->arch_private;
648 /* The linux target ops object. */
650 linux_process_target *the_linux_target = &the_loongarch_target;
652 /* Initialize the LoongArch/Linux target. */
654 void
655 initialize_low_arch ()
657 initialize_regsets_info (&loongarch_regsets_info);