如何设置 dr7 寄存器的值以便在 x86-64 上创建硬件断点?

2023-12-05

我正在开发一个允许使用的“绑定”库ptrace()在 OCaml 语言中,但我的问题仅涉及ptrace().

所以,现在,我正在尝试编写一小段代码,以便使用以下命令在 Linux x86-64 上创建一个简单的硬件断点ptrace():

#define DR_OFFSET(x) (((struct user *)0)->u_debugreg + x)

typedef struct {
    int           dr0_local:    1;
    int           dr0_global:   1;
    int           dr1_local:    1;
    int           dr1_global:   1;
    int           dr2_local:    1;
    int           dr2_global:   1;
    int           dr3_local:    1;
    int           dr3_global:   1;
    int           reserverd:    8;
    break_flag_t  dr0_break:    2;
    data_length_t dr0_len:      2;
    break_flag_t  dr1_break:    2;
    data_length_t dr1_len:      2;
    break_flag_t  dr2_break:    2;
    data_length_t dr2_len:      2;
    break_flag_t  dr3_break:    2;
    data_length_t dr3_len:      2;
} dr7_t;

CAMLprim value ptrace_breakpoint(value ml_pid, value ml_addr)
{
    CAMLparam2(ml_pid, ml_addr);
    dr7_t dr7 = {0};

    dr7.dr0_local = 1;
    dr7.dr0_break = 0; /* break on execution */
    dr7.dr0_len   = 0x03; /* len 4 */

    ptrace(PTRACE_POKEUSER, Int_val(ml_pid), DR_OFFSET(0), (void*)Int64_val(ml_addr));
    ptrace(PTRACE_POKEUSER, Int_val(ml_pid), DR_OFFSET(7), (void*)dr7));
    ptrace(PTRACE_POKEUSER, Int_val(ml_pid), DR_OFFSET(6), (void*)0);
    CAMLreturn0;
}

当我执行这段代码时,我得到了一个Invalid argument。的价值dr7 is 0xc0001。为了找到有效值,我检查了GDB如何使用ptrace通过使用strace:

ptrace(PTRACE_POKEUSER, 6459, offsetof(struct user, u_debugreg), 0x400519) = 0
ptrace(PTRACE_POKEUSER, 6459, offsetof(struct user, u_debugreg) + 56, 0x101) = 0
ptrace(PTRACE_POKEUSER, 6459, offsetof(struct user, u_debugreg) + 48, 0) = 0

因此,GDB将dr7寄存器设置为值0x101。我尝试了这个值并且它有效。因此,我想知道GDB使用的值的含义是什么?是个dr7_t我之前使用的位字段有效吗?

谢谢。

Edit:

感谢 Neitsa,解决方案如下:

typedef struct {
    unsigned int  dr0_local:      1;  
    unsigned int  dr0_global:     1;  
    unsigned int  dr1_local:      1;  
    unsigned int  dr1_global:     1;  
    unsigned int  dr2_local:      1;  
    unsigned int  dr2_global:     1;  
    unsigned int  dr3_local:      1;  
    unsigned int  dr3_global:     1;  
    unsigned int  le:             1;  
    unsigned int  ge:             1;  
    unsigned int  reserved_10:    1;  
    unsigned int  rtm:            1;  
    unsigned int  reserved_12:    1;  
    unsigned int  gd:             1;  
    unsigned int  reserved_14_15: 2;
    break_flag_t  dr0_break:      2;  
    data_length_t dr0_len:        2;  
    break_flag_t  dr1_break:      2;  
    data_length_t dr1_len:        2;  
    break_flag_t  dr2_break:      2;  
    data_length_t dr2_len:        2;  
    break_flag_t  dr3_break:      2;  
    data_length_t dr3_len:        2;  
} dr7_t;

CAMLprim value ptrace_breakpoint(value ml_pid, value ml_addr)
{
    CAMLparam2(ml_pid, ml_addr);
    dr7_t dr7 = {0};

    dr7.dr0_local = 1;
    dr7.le = 1;
    dr7.ge = 1;
    dr7.reserved_10 = 1;

    my_ptrace(PTRACE_POKEUSER, Int_val(ml_pid), DR_OFFSET(0), (void*)Int64_val(ml_addr));
    my_ptrace(PTRACE_POKEUSER, Int_val(ml_pid), DR_OFFSET(7), (void*)dr7));
    my_ptrace(PTRACE_POKEUSER, Int_val(ml_pid), DR_OFFSET(6), (void*)0);
    CAMLreturn0;
}

你的结构看起来不错(我会用unsigned int尽管)。

DR7 bits

几点说明(引自Intel Manual chap 17.2: Debug Registers):

  • Reserved bits (must be set accordingly to the documentation):
    • 位 10 保留但设置为 1。
    • 位 12、14 和 15 被保留,必须设置为 0 (memset整个结构预先为0)。

其他领域:

  • You should还实现位 8 和位 9 并将它们设置为 1

LE 和 GE(本地和全局精确断点启用)标志(位 8、9) — P6 系列处理器稍后不支持此功能 IA-32 处理器和 Intel 64 处理器。 [...],我们建议 如果需要精确的断点,则 LE 和 GE 标志设置为 1

  • 指令的指令断点must长度设置为 1 个字节(这意味着相应的LENn字段必须设置为 0):

指令断点地址的长度规范必须为 1 字节 (LENn 字段设置为 00)。其他操作数大小的代码断点未定义

因此,要在执行时设置断点:

  • 将保留位设置为正确的值
  • 将 DR7.LE 和 DR7.GE 设置为 1
  • 将 DR7.L0(L1、L2、L3)设置为1[本地断点]
  • 确保 DR7.RW/0 (RW/1, RW/2, RW/3) 是0[执行指令时中断]
  • 确保 DR7.LEN0(LEN1、LEN2、LEN3)是0[1字节长度]
  • Set DR0 (1, 2, 3) to the instruction linear address
    • 断点的线性地址[DR0到DR3]must落在指令的第一个字节上。

处理器识别指令断点地址只有当 它指向指令的第一个字节。如果指令有 前缀,断点地址必须指向第一个前缀。


edit

  • 0x101 :
    • bin(0x101) = '0b100000001'
    • DR7.L0 & DR7.LE 设置为 1

从技术上讲,0x701 应该是正确的:

  • 0x701 :
    • bin(0x701) = '0b11100000001'
    • DR7.L0 & DR7.LE & DR7.GE & DR7.bit10 设置为 1
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何设置 dr7 寄存器的值以便在 x86-64 上创建硬件断点? 的相关文章

  • 获取按下的按钮的返回值

    我有一个在特定事件中弹出的表单 它从数组中提取按钮并将标签值设置为特定值 因此 如果您要按下或单击此按钮 该函数应返回标签值 我怎样才能做到这一点 我如何知道点击了哪个按钮 此时代码返回 DialogResult 但我想从函数返回 Tag
  • pthread_cond_timedwait() 和 pthread_cond_broadcast() 解释

    因此 我在堆栈溢出和其他资源上进行了大量搜索 但我无法理解有关上述函数的一些内容 具体来说 1 当pthread cond timedwait 因为定时器值用完而返回时 它如何自动重新获取互斥锁 互斥锁可能被锁定在其他地方 例如 在生产者
  • 未解决的包含:“cocos2d.h” - Cocos2dx

    当我在 Eclipse 中导入 cocos2dx android 项目时 我的头文件上收到此警告 Unresolved inclusion cocos2d h 为什么是这样 它实际上困扰着我 该项目可以正确编译并运行 但我希望这种情况消失
  • 如何忽略“有符号和无符号整数表达式之间的比较”?

    谁能告诉我必须使用哪个标志才能使 gcc 忽略 有符号和无符号整数表达式之间的比较 警告消息 gcc Wno sign compare 但你确实应该修复它警告你的比较
  • 使闭包捕获的变量变得易失性

    闭包捕获的变量如何与不同线程交互 在下面的示例代码中 我想将totalEvents 声明为易失性的 但C 不允许这样做 是的 我知道这是错误的代码 这只是一个例子 private void WaitFor10Events volatile
  • 在 Visual Studio 2008 上设置预调试事件

    我想在 Visual Studio 中开始调试程序之前运行一个任务 我每次调试程序时都需要运行此任务 因此构建后事件还不够好 我查看了设置的 调试 选项卡 但没有这样的选项 有什么办法可以做到这一点吗 你唯一可以尝试的 IMO 就是尝试Co
  • 获取没有非标准端口的原始 url (C#)

    第一个问题 环境 MVC C AppHarbor Problem 我正在调用 openid 提供商 并根据域生成绝对回调 url 在我的本地机器上 如果我点击的话 效果很好http localhost 12345 login Request
  • 将目录压缩为单个文件的方法有哪些

    不知道怎么问 所以我会解释一下情况 我需要存储一些压缩文件 最初的想法是创建一个文件夹并存储所需数量的压缩文件 并创建一个文件来保存有关每个压缩文件的数据 但是 我不被允许创建许多文件 只能有一个 我决定创建一个压缩文件 其中包含有关进一步
  • 如果使用 SingleOrDefault() 并在数字列表中搜索不在列表中的数字,如何返回 null?

    使用查询正数列表时SingleOrDefault 当在列表中找不到数字时 如何返回 null 或像 1 这样的自定义值 而不是类型的默认值 在本例中为 0 你可以使用 var first theIntegers Cast
  • Qt moc 在头文件中实现?

    是否可以告诉 Qt MOC 我想声明该类并在单个文件中实现它 而不是将它们拆分为 h 和 cpp 文件 如果要在 cpp 文件中声明并实现 QObject 子类 则必须手动包含 moc 文件 例如 文件main cpp struct Sub
  • 指针减法混乱

    当我们从另一个指针中减去一个指针时 差值不等于它们相距多少字节 而是等于它们相距多少个整数 如果指向整数 为什么这样 这个想法是你指向内存块 06 07 08 09 10 11 mem 18 24 17 53 7 14 data 如果你有i
  • 使用 System.Text.Json 即时格式化 JSON 流

    我有一个未缩进的 Json 字符串 例如 hash 123 id 456 我想缩进字符串并将其序列化为 JSON 文件 天真地 我可以使用缩进字符串Newtonsoft如下 using Newtonsoft Json Linq JToken
  • clang 实例化后静态成员初始化

    这样的代码可以用 GCC 编译 但 clang 3 5 失败 include
  • 从库中捕获主线程 SynchronizationContext 或 Dispatcher

    我有一个 C 库 希望能够将工作发送 发布到 主 ui 线程 如果存在 该库可供以下人员使用 一个winforms应用程序 本机应用程序 带 UI 控制台应用程序 没有 UI 在库中 我想在初始化期间捕获一些东西 Synchronizati
  • C++ 复制初始化和直接初始化,奇怪的情况

    在继续阅读本文之前 请阅读在 C 中 复制初始化和直接初始化之间有区别吗 https stackoverflow com questions 1051379 is there a difference in c between copy i
  • 如何在 Linux shell 中将十六进制转换为 ASCII 字符?

    假设我有一个字符串5a 这是 ASCII 字母的十六进制表示Z 我需要找到一个 Linux shell 命令 它将接受一个十六进制字符串并输出该十六进制字符串代表的 ASCII 字符 所以如果我这样做 echo 5a command im
  • const、span 和迭代器的问题

    我尝试编写一个按索引迭代容器的迭代器 AIt and a const It两者都允许更改容器的内容 AConst it and a const Const it两者都禁止更改容器的内容 之后 我尝试写一个span
  • C 中的异或运算符

    在进行按位操作时 我在确定何时使用 XOR 运算符时遇到一些困难 按位与和或非常简单 当您想要屏蔽位时 请使用按位 AND 常见用例是 IP 寻址和子网掩码 当您想要打开位时 请使用包含或 然而 XOR 总是让我明白 我觉得如果在面试中被问
  • 限制C#中的并行线程数

    我正在编写一个 C 程序来生成并通过 FTP 上传 50 万个文件 我想并行处理4个文件 因为机器有4个核心 文件生成需要更长的时间 是否可以将以下 Powershell 示例转换为 C 或者是否有更好的框架 例如 C 中的 Actor 框
  • 防止索引超出范围错误

    我想编写对某些条件的检查 而不必使用 try catch 并且我想避免出现 Index Out of Range 错误的可能性 if array Element 0 Object Length gt 0 array Element 1 Ob

随机推荐

  • 独立 VS 2010 C++ 程序

    我已经很久没有使用 VS 2010 和 C 了 当我重新开始使用它时 我遇到了去年困扰我的同样的问题 我编译的 exe 运行得不好没有正确的 C 运行时的旧机器 我什至不知道给他们什么链接 我告诉他们安装this他们收到错误消息 该程序无法
  • 如何在 AEM 6.1 中创建系统用户 (rep:SystemUser)?

    在 AEM 6 1 上 我尝试创建一个系统用户 rep SystemUser 谁能帮我 我需要这个系统用户映射到 OSGI 中的一个服务 我想用它来将一些数据写入 aem 内容 我可以在 CRX 中的以下位置看到 系统用户 home use
  • 在 C'# 中以编程方式获取所有 TFS 分支

    我正在尝试以编程方式获取 TFS for Visual Studio 2013 中所有分支的列表 经过一些研究 我发现此博客详细介绍了如何获取分支 显示 TFS 2010 中的所有分支层次结构 我修改了代码 将所有内容存储在列表中 priv
  • MPICH:如何发布_名称以便客户端应用程序可以查找_名称?

    在 Windows 1 4 1p1 中使用 MPICH 学习 MPI 时 我发现了一些示例代码here 最初 当我运行服务器时 我必须复制生成的port name并用它启动客户端 这样 客户端就可以连接到服务器了 我修改它以包括MPI Pu
  • 魔法记录导入(下一步)

    我在标题中添加了下一步 因为这与我之前的问题不同 标题几乎完全相同 我有一个Person entity Person name mappedKeyName FullName email mappedKeyName EmailAddress
  • 每天在两列范围之间的数据框中添加行

    我需要知道按房型划分的预订数量 我有这个 DataFrame 其中包含每个预订的开始和结束及其房间类型 date from date to room type 0 2017 08 07 2017 08 12 SUI 1 2017 08 09
  • 为什么 Xcode 4.3.2 存档时会挂起?

    当我尝试归档构建时 xcode 因彩色旋转死亡之轮而挂起 它曾经工作正常 但我无法再浏览存档 除非我手动删除存档文件 不过 我可以毫无问题地构建一个设备 我手动删除了存档中的所有内容 通过删除实际的存档文件 并且存档 组织器窗格显示正常 因
  • 提供的注册令牌未注册

    我正在尝试通过 Google 云功能发送 iOS 推送通知 但它返回错误The provided registration token is not registered 但我已经通过调试我的应用程序进行了检查 并且 FCM 注册令牌是正确
  • MySQL:选择前n个最大值?

    我对需要返回特定列上具有最大值的前 N 行的查询感到非常困惑 例如 如果行N 1 N N 1具有相同的值 我必须返回吗just top N or top N 1 rows 如果你这样做 select from t order by valu
  • 渲染透明外壳

    假设我正在渲染神奇女侠驾驶她的隐形喷气机 射流由多个网格组成 大部分是透明的 在透明网格重叠的地方 它变得更加不透明 我不想有这种重叠 这样透明部分仍然有阴影 但材质会丢弃其他片段后面的透明片段 就好像神奇女侠坐在透明的外壳内一样 也许一个
  • 下载并使用现代 CMake 构建 Lua

    让我们尝试通过 cmake 构建 lua 动机 cmake 通过 CLion 等 IDE 获得更多关注和支持or甚至视觉 Studio 2017 及更新版本 如果您想提供独立于平台的开源并促进整个构建过程 那么这非常有用 现在的问题是创建一
  • 如何在 Angular 中定义枚举类型以不违反 tslint typedef 规则

    为了能够在模板中使用枚举 我们在 ts 文件中编写以下代码 在工作流程Progress ts中 export enum WorkflowProgress cancelled 0 inProgress done 在组件 ts中 export
  • python中numpy多维数组的非相邻切片

    我有一个多维数组 a a np random uniform 1 10 2 4 2 3 10 10 对于维度 4 6 我有 3 个列表 其中包含用于切片数组 a 的该维度的索引 dim4 0 2 dim5 3 5 9 dim6 1 2 7
  • 打印所有对 n 个整数求和的方法,使它们的总和达到给定的和。

    我正在尝试提出一种算法 该算法将打印出对 N 个整数求和的所有可能方法 以便它们总计达到给定值 例子 打印所有对 4 个整数求和的方法 使它们的总和为 5 结果应该是这样的 5 0 0 0 4 1 0 0 3 2 0 0 3 1 1 0 2
  • ANDROID - ExpandableListView

    我试图弄清楚如何构建一个包含 许多 的视图 PARENT1 可勾选 可扩展 子级 1 单选按钮 子级 2 单选按钮 PARENT2 可勾选 可扩展 儿童 1 可勾选 儿童2 可勾选 要点是父级必须是可检查的 并且子级必须更改图标 有人可以指
  • @JsonCreator 和 mixin 通过模块不适用于第 3 方类

    我正在尝试反序列化 java net HttpCookie 它没有默认的无参数构造函数 并且得到 org codehaus jackson map JsonMappingException 找不到类型 简单类型 类 java net Htt
  • 在 Firebase 和代码中编写规则

    Firebase 建议除了代码 swift java 等 中的规则之外 我们还可以在其控制台的在线 Firebase 规则部分中编写安全规则 数据库 存储 为什么是这样 我感觉这样会重复吗 这在客户端 服务器架构中很常见 服务器must验证
  • NSApplication 和 -applicationDidFinishLaunching:

    我有一个应用程序 其中我有一个main m返回NSApplicationMain argc const char argv 我想运行代码 applicationDidFinishLaunching 但我只是不知道该怎么做 任何人都可以帮忙或
  • C++ 有没有关闭计算机的函数?

    C 有没有关闭计算机的函数 因为我怀疑是否有一个 至少在标准库中 所以我可以从 C 调用的 Windows 函数是什么 基本上 用 C 关闭 Windows XP 计算机的代码是什么 在 Windows 上 您可以使用此处描述的 ExitW
  • 如何设置 dr7 寄存器的值以便在 x86-64 上创建硬件断点?

    我正在开发一个允许使用的 绑定 库ptrace 在 OCaml 语言中 但我的问题仅涉及ptrace 所以 现在 我正在尝试编写一小段代码 以便使用以下命令在 Linux x86 64 上创建一个简单的硬件断点ptrace define D