这条 Intel Xeon mov 指令如何破坏我的应用程序内存?
How is this Intel Xeon mov instruction corrupting my application's memory?
我有一个使用 gcc v7.3.0 构建并在 Intel(R) Xeon(R) CPU E3-1220 v6
芯片上执行的应用程序,该应用程序确定性地破坏堆栈内存并由于执行 mov
指令而获得 SEGV。我 运行 valgrind
并且没有报告内存损坏。
我在堆栈上有一个 struct SolutionPattern
,它的 const float * const &
类型的成员变量在我开始调用成员函数 inline void RoleToEquation(float threshold)
时被破坏了。在 GDB
中,当插入成员函数时,第四条指令 mov %rdi,-0x18(%rbp)
导致损坏,如调试器所示:
Dump of assembler code for function SolutionPattern::RoleToEquation(float):
0x00007fff9556b684 <+0>: push %rbp
0x00007fff9556b685 <+1>: mov %rsp,%rbp
0x00007fff9556b688 <+4>: sub [=10=]x20,%rsp
=> 0x00007fff9556b68c <+8>: mov %rdi,-0x18(%rbp)
0x00007fff9556b690 <+12>: movss %xmm0,-0x1c(%rbp)
0x00007fff9556b695 <+17>: mov -0x18(%rbp),%rax
0x00007fff9556b699 <+21>: pxor %xmm0,%xmm0
0x00007fff9556b69d <+25>: movss %xmm0,0x88(%rax)
0x00007fff9556b6a5 <+33>: mov -0x18(%rbp),%rax
[...]
End of assembler dump.
(gdb) si
Hardware watchpoint 99: *5
Old value = (const float * const) 0x7fffafb6087a <fflush+106>
New value = (const float * const) 0x7fffffff9ac0
0x00007fff9556b690 in SolutionPattern::RoleToEquation (this=0x7fffffff9ac0, threshold=4.59163468e-41) at calculate_edge.h:250
(gdb) disas
Dump of assembler code for function SolutionPattern::RoleToEquation(float):
0x00007fff9556b684 <+0>: push %rbp
0x00007fff9556b685 <+1>: mov %rsp,%rbp
0x00007fff9556b688 <+4>: sub [=10=]x20,%rsp
0x00007fff9556b68c <+8>: mov %rdi,-0x18(%rbp)
=> 0x00007fff9556b690 <+12>: movss %xmm0,-0x1c(%rbp)
0x00007fff9556b695 <+17>: mov -0x18(%rbp),%rax
0x00007fff9556b699 <+21>: pxor %xmm0,%xmm0
0x00007fff9556b69d <+25>: movss %xmm0,0x88(%rax)
0x00007fff9556b6a5 <+33>: mov -0x18(%rbp),%rax
[...]
End of assembler dump.
成员函数源码是这样开头的:
inline void RoleToEquation(float threshold) {
A = B = 0.f;
C = threshold;
D = E = 0.f;
F = threshold;
[...]
}
A
、B
、C
、D
、E
、F
是float
的成员变量在被损坏的内存之后出现几个成员变量的结构。
反汇编没完全看懂,不过貌似功能设置还在运行,A
和B
设置为0.f
还没有开始。我在调试器中注意到参数 threshold
在第五条指令 movss
执行之前未初始化。在堆栈上设置参数变量 threshold
的代码如何导致位于调用帧的堆栈内存中的结构被破坏?
这里可能发生了什么,我该如何着手找出这种损坏的根源。拆卸看起来合适吗?这看起来像编译器错误吗?请注意,只有调试版本会崩溃,优化版本不会崩溃。这个成员函数的前四个指令正在执行什么?是否为正在调用的新函数设置了不正确的框架?
mov %rdi,-0x18(%rbp)
只是溢出了第一个函数 arg。 (this
指针,因为这是一个成员函数。)
这不是 "corrupting" 任何东西,您只是在禁用优化的情况下进行编译,因此 所有内容 都会在 C++ 语句之间溢出到内存,包括所有函数参数(隐式和显式)在功能入口上。
-0x18(%rbp)
在本函数自身栈帧的0x20
字节内,用sub [=14=]x20,%rsp
保留(在mov %rsp, %rbp
后设置帧指针指向下面的qword return 地址)。
How does the code to set up the argument variable threshold on the stack cause the struct to be corrupted that is located in the calling frame's stack memory?
没有。 movss %xmm0,-0x1c(%rbp)
也存储在这个函数自己的栈帧中。这是溢出的 this
指针正下方的 4 字节存储。 (这些是负偏移量,0x1c - 0x18
= 4 = 商店的宽度。)
如果您通过设置 HW 观察点 找到它,那可能是在本地地址上。 包含该局部函数的函数已 return 编辑,现在堆栈内存正在被重用 作为不同函数的不同调用的堆栈帧。
我有一个使用 gcc v7.3.0 构建并在 Intel(R) Xeon(R) CPU E3-1220 v6
芯片上执行的应用程序,该应用程序确定性地破坏堆栈内存并由于执行 mov
指令而获得 SEGV。我 运行 valgrind
并且没有报告内存损坏。
我在堆栈上有一个 struct SolutionPattern
,它的 const float * const &
类型的成员变量在我开始调用成员函数 inline void RoleToEquation(float threshold)
时被破坏了。在 GDB
中,当插入成员函数时,第四条指令 mov %rdi,-0x18(%rbp)
导致损坏,如调试器所示:
Dump of assembler code for function SolutionPattern::RoleToEquation(float):
0x00007fff9556b684 <+0>: push %rbp
0x00007fff9556b685 <+1>: mov %rsp,%rbp
0x00007fff9556b688 <+4>: sub [=10=]x20,%rsp
=> 0x00007fff9556b68c <+8>: mov %rdi,-0x18(%rbp)
0x00007fff9556b690 <+12>: movss %xmm0,-0x1c(%rbp)
0x00007fff9556b695 <+17>: mov -0x18(%rbp),%rax
0x00007fff9556b699 <+21>: pxor %xmm0,%xmm0
0x00007fff9556b69d <+25>: movss %xmm0,0x88(%rax)
0x00007fff9556b6a5 <+33>: mov -0x18(%rbp),%rax
[...]
End of assembler dump.
(gdb) si
Hardware watchpoint 99: *5
Old value = (const float * const) 0x7fffafb6087a <fflush+106>
New value = (const float * const) 0x7fffffff9ac0
0x00007fff9556b690 in SolutionPattern::RoleToEquation (this=0x7fffffff9ac0, threshold=4.59163468e-41) at calculate_edge.h:250
(gdb) disas
Dump of assembler code for function SolutionPattern::RoleToEquation(float):
0x00007fff9556b684 <+0>: push %rbp
0x00007fff9556b685 <+1>: mov %rsp,%rbp
0x00007fff9556b688 <+4>: sub [=10=]x20,%rsp
0x00007fff9556b68c <+8>: mov %rdi,-0x18(%rbp)
=> 0x00007fff9556b690 <+12>: movss %xmm0,-0x1c(%rbp)
0x00007fff9556b695 <+17>: mov -0x18(%rbp),%rax
0x00007fff9556b699 <+21>: pxor %xmm0,%xmm0
0x00007fff9556b69d <+25>: movss %xmm0,0x88(%rax)
0x00007fff9556b6a5 <+33>: mov -0x18(%rbp),%rax
[...]
End of assembler dump.
成员函数源码是这样开头的:
inline void RoleToEquation(float threshold) {
A = B = 0.f;
C = threshold;
D = E = 0.f;
F = threshold;
[...]
}
A
、B
、C
、D
、E
、F
是float
的成员变量在被损坏的内存之后出现几个成员变量的结构。
反汇编没完全看懂,不过貌似功能设置还在运行,A
和B
设置为0.f
还没有开始。我在调试器中注意到参数 threshold
在第五条指令 movss
执行之前未初始化。在堆栈上设置参数变量 threshold
的代码如何导致位于调用帧的堆栈内存中的结构被破坏?
这里可能发生了什么,我该如何着手找出这种损坏的根源。拆卸看起来合适吗?这看起来像编译器错误吗?请注意,只有调试版本会崩溃,优化版本不会崩溃。这个成员函数的前四个指令正在执行什么?是否为正在调用的新函数设置了不正确的框架?
mov %rdi,-0x18(%rbp)
只是溢出了第一个函数 arg。 (this
指针,因为这是一个成员函数。)
这不是 "corrupting" 任何东西,您只是在禁用优化的情况下进行编译,因此 所有内容 都会在 C++ 语句之间溢出到内存,包括所有函数参数(隐式和显式)在功能入口上。
-0x18(%rbp)
在本函数自身栈帧的0x20
字节内,用sub [=14=]x20,%rsp
保留(在mov %rsp, %rbp
后设置帧指针指向下面的qword return 地址)。
How does the code to set up the argument variable threshold on the stack cause the struct to be corrupted that is located in the calling frame's stack memory?
没有。 movss %xmm0,-0x1c(%rbp)
也存储在这个函数自己的栈帧中。这是溢出的 this
指针正下方的 4 字节存储。 (这些是负偏移量,0x1c - 0x18
= 4 = 商店的宽度。)
如果您通过设置 HW 观察点 找到它,那可能是在本地地址上。 包含该局部函数的函数已 return 编辑,现在堆栈内存正在被重用 作为不同函数的不同调用的堆栈帧。