mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-27 03:51:15 +08:00
6ced1278fc
LoongArch defines hardware watchpoint functions for fetch operations. After the software configures the watchpoints for fetch, the processor hardware will monitor the access addresses of the fetch operations and trigger a watchpoint exception when the watchpoint setting conditions are met. Hardware watchpoints for fetch operations is used to implement hardware breakpoint function on LoongArch. Refer to the following document for hardware breakpoint. https://loongson.github.io/LoongArch-Documentation/LoongArch-Vol1-EN.html#control-and-status-registers-related-to-watchpoints A simple test is as follows: lihui@bogon:~$ cat test.c #include <stdio.h> int a = 0; int main() { printf("start test\n"); a = 1; printf("a = %d\n", a); printf("end test\n"); return 0; } lihui@bogon:~$ gcc -g test.c -o test without this patch: lihui@bogon:~$ gdb test ... (gdb) start ... Temporary breakpoint 1, main () at test.c:5 5 printf("start test\n"); (gdb) hbreak 8 No hardware breakpoint support in the target. with this patch: lihui@bogon:~$ gdb test ... (gdb) start ... Temporary breakpoint 1, main () at test.c:5 5 printf("start test\n"); (gdb) hbreak 8 Hardware assisted breakpoint 2 at 0x1200006ec: file test.c, line 8. (gdb) c Continuing. start test a = 1 Breakpoint 2, main () at test.c:8 8 printf("end test\n"); (gdb) c Continuing. end test [Inferior 1 (process 25378) exited normally] Signed-off-by: Hui Li <lihui@loongson.cn> Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
104 lines
3.6 KiB
C
104 lines
3.6 KiB
C
/* Native-dependent code for GNU/Linux on LoongArch processors.
|
|
|
|
Copyright (C) 2024 Free Software Foundation, Inc.
|
|
Contributed by Loongson Ltd.
|
|
|
|
This file is part of GDB.
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
|
|
|
#ifndef NAT_LOONGARCH_HW_POINT_H
|
|
#define NAT_LOONGARCH_HW_POINT_H
|
|
|
|
/* Macro definitions, data structures, and code for the hardware
|
|
breakpoint and hardware watchpoint support follow. We use the
|
|
following abbreviations throughout the code:
|
|
|
|
hw - hardware
|
|
bp - breakpoint
|
|
wp - watchpoint */
|
|
|
|
/* Maximum number of hardware breakpoint and watchpoint registers.
|
|
Neither of these values may exceed the width of dr_changed_t
|
|
measured in bits. */
|
|
|
|
#define LOONGARCH_HBP_MAX_NUM 8
|
|
#define LOONGARCH_HWP_MAX_NUM 8
|
|
|
|
|
|
/* The maximum length of a memory region that can be watched by one
|
|
hardware watchpoint register. */
|
|
|
|
#define LOONGARCH_HWP_MAX_LEN_PER_REG 8
|
|
#define CTRL_PLV3_ENABLE 0x10
|
|
|
|
#define DR_CONTROL_ENABLED(ctrl) ((ctrl & CTRL_PLV3_ENABLE) == CTRL_PLV3_ENABLE)
|
|
|
|
/* Structure for managing the hardware breakpoint/watchpoint resources.
|
|
DR_ADDR_* stores the address, DR_CTRL_* stores the control register
|
|
content, and DR_REF_COUNT_* counts the numbers of references to the
|
|
corresponding bp/wp, by which way the limited hardware resources
|
|
are not wasted on duplicated bp/wp settings (though so far gdb has
|
|
done a good job by not sending duplicated bp/wp requests). */
|
|
|
|
struct loongarch_debug_reg_state
|
|
{
|
|
/* hardware breakpoint */
|
|
CORE_ADDR dr_addr_bp[LOONGARCH_HBP_MAX_NUM];
|
|
unsigned int dr_ctrl_bp[LOONGARCH_HBP_MAX_NUM];
|
|
unsigned int dr_ref_count_bp[LOONGARCH_HBP_MAX_NUM];
|
|
|
|
/* hardware watchpoint */
|
|
CORE_ADDR dr_addr_wp[LOONGARCH_HWP_MAX_NUM];
|
|
unsigned int dr_ctrl_wp[LOONGARCH_HWP_MAX_NUM];
|
|
unsigned int dr_ref_count_wp[LOONGARCH_HWP_MAX_NUM];
|
|
};
|
|
|
|
extern int loongarch_num_bp_regs;
|
|
extern int loongarch_num_wp_regs;
|
|
|
|
/* Invoked when IDXth breakpoint/watchpoint register pair needs to be
|
|
updated. */
|
|
|
|
void loongarch_notify_debug_reg_change (ptid_t ptid, int is_watchpoint,
|
|
unsigned int idx);
|
|
|
|
|
|
int loongarch_handle_breakpoint (enum target_hw_bp_type type, CORE_ADDR addr,
|
|
int len, int is_insert, ptid_t ptid,
|
|
struct loongarch_debug_reg_state *state);
|
|
|
|
int loongarch_handle_watchpoint (enum target_hw_bp_type type, CORE_ADDR addr,
|
|
int len, int is_insert, ptid_t ptid,
|
|
struct loongarch_debug_reg_state *state);
|
|
|
|
/* Return TRUE if there are any hardware breakpoints. If WATCHPOINT is TRUE,
|
|
check hardware watchpoints instead. */
|
|
|
|
bool loongarch_any_set_debug_regs_state (loongarch_debug_reg_state *state,
|
|
bool watchpoint);
|
|
|
|
/* Print the values of the cached breakpoint/watchpoint registers. */
|
|
|
|
void loongarch_show_debug_reg_state (struct loongarch_debug_reg_state *state,
|
|
const char *func, CORE_ADDR addr,
|
|
int len, enum target_hw_bp_type type);
|
|
|
|
/* Return true if we can watch a memory region that starts address
|
|
ADDR and whose length is LEN in bytes. */
|
|
|
|
int loongarch_region_ok_for_watchpoint (CORE_ADDR addr, int len);
|
|
|
|
#endif /* NAT_LOONGARCH_HW_POINT_H */
|