1 /* GNU/Linux/LoongArch specific low level interface, for the remote server
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"
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
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
;
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
;
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");
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");
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". */
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. */
138 loongarch_fill_gregset (struct regcache
*regcache
, void *buf
)
140 elf_gregset_t
*regset
= (elf_gregset_t
*) buf
;
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. */
153 loongarch_store_gregset (struct regcache
*regcache
, const void *buf
)
155 const elf_gregset_t
*regset
= (const elf_gregset_t
*) buf
;
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. */
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
+
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. */
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
+
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. */
223 loongarch_fill_lsxregset (struct regcache
*regcache
, void *buf
)
225 elf_lsxregset_t
*regset
= (elf_lsxregset_t
*) buf
;
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. */
235 loongarch_store_lsxregset (struct regcache
*regcache
, const void *buf
)
237 const elf_lsxregset_t
*regset
= (const elf_lsxregset_t
*) buf
;
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. */
247 loongarch_fill_lasxregset (struct regcache
*regcache
, void *buf
)
249 elf_lasxregset_t
*regset
= (elf_lasxregset_t
*) buf
;
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. */
259 loongarch_store_lasxregset (struct regcache
*regcache
, const void *buf
)
261 const elf_lasxregset_t
*regset
= (const elf_lasxregset_t
*) buf
;
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. */
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
);
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. */
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
);
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
},
324 /* LoongArch/Linux regset information. */
325 static struct regsets_info loongarch_regsets_info
=
327 loongarch_regsets
, /* 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 */
337 &loongarch_regsets_info
,
340 /* Implementation of linux target ops method "get_regs_info". */
343 loongarch_target::get_regs_info ()
345 return &loongarch_regs
;
348 /* Implementation of linux target ops method "low_fetch_register". */
351 loongarch_target::low_fetch_register (regcache
*regcache
, int regno
)
355 supply_register_zeroed (regcache
, 0);
360 loongarch_target::low_supports_breakpoints ()
365 /* Implementation of linux target ops method "low_get_pc". */
368 loongarch_target::low_get_pc (regcache
*regcache
)
370 if (register_size (regcache
->tdesc
, 0) == 8)
371 return linux_get_pc_64bit (regcache
);
373 return linux_get_pc_32bit (regcache
);
376 /* Implementation of linux target ops method "low_set_pc". */
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
);
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". */
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". */
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)
426 loongarch_init_debug_reg_state (struct loongarch_debug_reg_state
*state
)
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". */
458 loongarch_target::supports_z_point_type (char z_type
)
464 case Z_PACKET_WRITE_WP
:
465 case Z_PACKET_READ_WP
:
466 case Z_PACKET_ACCESS_WP
:
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
)
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 ());
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
,
499 current_lwp_ptid (), state
);
505 ret
= loongarch_handle_breakpoint (targ_type
, addr
, len
,
506 1 /* is_insert */, current_lwp_ptid (),
511 loongarch_show_debug_reg_state (state
, "insert_point", addr
, len
,
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
)
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 ());
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
)
541 loongarch_handle_watchpoint (targ_type
, addr
, len
, 0 /* is_insert */,
542 current_lwp_ptid (), state
);
545 ret
= loongarch_handle_breakpoint (targ_type
, addr
, len
,
546 0 /* is_insert */, current_lwp_ptid (),
551 loongarch_show_debug_reg_state (state
, "remove_point", addr
, len
,
558 /* Implementation of linux target ops method "low_stopped_data_address". */
561 loongarch_target::low_stopped_data_address ()
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 ());
579 if (loongarch_stopped_data_address (state
, (CORE_ADDR
) siginfo
.si_addr
, &result
))
582 return (CORE_ADDR
) 0;
585 /* Implementation of linux target ops method "low_stopped_by_watchpoint". */
588 loongarch_target::low_stopped_by_watchpoint ()
590 return (low_stopped_data_address () != 0);
593 /* Implementation of linux target ops method "low_new_process". */
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
);
605 /* Implementation of linux target ops method "low_delete_process". */
608 loongarch_target::low_delete_process (arch_process_info
*info
)
614 loongarch_target::low_new_thread (lwp_info
*lwp
)
616 loongarch_linux_new_thread (lwp
);
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". */
628 loongarch_target::low_new_fork (process_info
*parent
,
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. */
655 initialize_low_arch ()
657 initialize_regsets_info (&loongarch_regsets_info
);