Dựa trên câu trả lời tuyệt vời user512106, tôi mã hóa lên một chút "thư viện" rằng ai đó có thể tìm thấy hữu ích:
Đó là trên github tại https://github.com/whh8b/hwbp_lib. Tôi ước gì tôi có thể nhận xét trực tiếp câu trả lời của anh ấy, nhưng tôi chưa có đủ đại diện.
Dựa trên phản hồi từ cộng đồng, tôi sẽ sao chép/dán mã liên quan ở đây:
#include <stdio.h>
#include <stddef.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/ptrace.h>
#include <sys/user.h>
#include <sys/prctl.h>
#include <stdint.h>
#include <errno.h>
#include <stdbool.h>
extern int errno;
enum {
BREAK_EXEC = 0x0,
BREAK_WRITE = 0x1,
BREAK_READWRITE = 0x3,
};
enum {
BREAK_ONE = 0x0,
BREAK_TWO = 0x1,
BREAK_FOUR = 0x3,
BREAK_EIGHT = 0x2,
};
#define ENABLE_BREAKPOINT(x) (0x1<<(x*2))
#define ENABLE_BREAK_EXEC(x) (BREAK_EXEC<<(16+(x*4)))
#define ENABLE_BREAK_WRITE(x) (BREAK_WRITE<<(16+(x*4)))
#define ENABLE_BREAK_READWRITE(x) (BREAK_READWRITE<<(16+(x*4)))
/*
* This function fork()s a child that will use
* ptrace to set a hardware breakpoint for
* memory r/w at _addr_. When the breakpoint is
* hit, then _handler_ is invoked in a signal-
* handling context.
*/
bool install_breakpoint(void *addr, int bpno, void (*handler)(int)) {
pid_t child = 0;
uint32_t enable_breakpoint = ENABLE_BREAKPOINT(bpno);
uint32_t enable_breakwrite = ENABLE_BREAK_WRITE(bpno);
pid_t parent = getpid();
int child_status = 0;
if (!(child = fork()))
{
int parent_status = 0;
if (ptrace(PTRACE_ATTACH, parent, NULL, NULL))
_exit(1);
while (!WIFSTOPPED(parent_status))
waitpid(parent, &parent_status, 0);
/*
* set the breakpoint address.
*/
if (ptrace(PTRACE_POKEUSER,
parent,
offsetof(struct user, u_debugreg[bpno]),
addr))
_exit(1);
/*
* set parameters for when the breakpoint should be triggered.
*/
if (ptrace(PTRACE_POKEUSER,
parent,
offsetof(struct user, u_debugreg[7]),
enable_breakwrite | enable_breakpoint))
_exit(1);
if (ptrace(PTRACE_DETACH, parent, NULL, NULL))
_exit(1);
_exit(0);
}
waitpid(child, &child_status, 0);
signal(SIGTRAP, handler);
if (WIFEXITED(child_status) && !WEXITSTATUS(child_status))
return true;
return false;
}
/*
* This function will disable a breakpoint by
* invoking install_breakpoint is a 0x0 _addr_
* and no handler function. See comments above
* for implementation details.
*/
bool disable_breakpoint(int bpno)
{
return install_breakpoint(0x0, bpno, NULL);
}
/*
* Example of how to use this /library/.
*/
int handled = 0;
void handle(int s) {
handled = 1;
return;
}
int main(int argc, char **argv) {
int a = 0;
if (!install_breakpoint(&a, 0, handle))
printf("failed to set the breakpoint!\n");
a = 1;
printf("handled: %d\n", handled);
if (!disable_breakpoint(0))
printf("failed to disable the breakpoint!\n");
return 1;
}
Tôi hy vọng rằng điều này sẽ giúp người!
Will
Từ liên kết của bạn: ** breakpoint phần cứng đôi khi có sẵn như là một tính năng gỡ lỗi BUILTIN với một số chip.Thông thường các tác phẩm này có đăng ký chuyên dụng vào đó địa chỉ điểm ngắt có thể được lưu trữ. ** – Neil
@Neil yes, tôi có nghĩa là nó đã được triển khai như thế nào; Tôi đã cập nhật câu trả lời – Kevin
GDB có thể không hỗ trợ nó, nhưng chắc chắn là x86. Infact tập tin gdb bạn liên kết để cho thấy làm thế nào để làm điều đó! Xem hàm ** i386_insert_aligned_watchpoint **. Nó có vẻ hiệu quả thiết lập thanh ghi DR7, nhưng tôi đoán đó là một hướng dẫn đặc quyền vì vậy tôi không thể sử dụng nó từ chế độ không phải hạt nhân. – Neil