GDB在Popf后设置陷阱标志(可能有错误?)
看一看:GDB在Popf后设置陷阱标志(可能有错误?),gdb,Gdb,看一看: (gdb) x/x $esp 0xb720a621: 0x00000000 (gdb) info register eflags eflags 0x200286 [ PF SF IF ID ] (gdb) x/5i $pc => 0x15a965d <tables+11901>: popf 0x15a965e <tables+11902>: mo
(gdb) x/x $esp
0xb720a621: 0x00000000
(gdb) info register eflags
eflags 0x200286 [ PF SF IF ID ]
(gdb) x/5i $pc
=> 0x15a965d <tables+11901>: popf
0x15a965e <tables+11902>: mov $0xd7fb0aa3,%ecx
0x15a9663 <tables+11907>: ret $0x849d
0x15a9666 <tables+11910>: xor (%ebx),%esi
0x15a9668 <tables+11912>: aam $0x78
(gdb) stepi
0x015a965e in tables () from /usr/local/apache2/modules/libphp5.so
(gdb) info register eflags
eflags 0x202 [ IF ]
(gdb) stepi
0x015a9663 in tables () from /usr/local/apache2/modules/libphp5.so
(gdb) info register eflags
eflags 0x302 [ TF IF ]
(gdb)x/x$esp
0xb720a621:0x00000000
(gdb)信息寄存器eflags
eflags 0x200286[PF SF IF ID]
(gdb)x/5i$pc
=>0x15a965d:popf
0x15a965e:mov$0xd7fb0aa3,%ecx
0x15a9663:ret$0x849d
0x15a9666:xor(%ebx),%esi
0x15a9668:aam$0x78
(gdb)stepi
0x015a965e位于/usr/local/apache2/modules/libphp5.so的表()中
(gdb)信息寄存器eflags
eflags 0x202[如果]
(gdb)stepi
0x015a9663位于/usr/local/apache2/modules/libphp5.so的表()中
(gdb)信息寄存器eflags
eflags 0x302[TF IF]
不确定为什么在下一条指令之后设置TF。我认为这是一个内核错误。当单步执行时,内核必须设置
TF
,但用户模式也可能正在修改TF
。为了处理这个问题,内核试图维护设置TF的用户:
/*在内核堆栈上设置TF*/
regs->flags |=X86\u EFLAGS\u TF;
/*
*..但如果TF被指令改变,我们将跟踪,
*不要把它标记为是“我们”设定的,这样我们
*以后不会用手清理的。
*
*请注意,如果我们没有实际执行popf,因为
*如果信号马上到达,我们就输了
*事实上是“我们”决定了这一切。
*/
如果(正在设置陷阱标志(子项、注册表)){
清除线程标志(子级,TIF强制);
返回0;
}
请注意,它甚至承认一些角落的情况可能会使它迷失方向。
更糟糕的是,is\u setting\u trap\u flag
只检查指令是否会修改TF
,而不检查指令是否实际设置了它:
开关(操作码[i]){
/*popf和iret*/
案例0x9d:案例0xcf:
返回1;
因此,即使已清除,它也会将TF
标记为用户设置。在get_flags
中,如果内核设置了TF
,它将尝试屏蔽TF
,如下所示:
/*
*如果调试器设置了TF,则将其从读数中隐藏。
*/
if(测试线程标志(任务,TIF强制)
retval&=~X86个字符集;
由于TIF_FORCED\u TF
被错误清除,此条件将不为真,因此实际上由内核为单步执行设置的TF
将返回到调试器
我认为可以通过修改is\u setting\u trap\u flag
来解决这个问题,这样它就可以检查堆栈中标志的新值,并且只有在TF
实际被设置时才返回1
。我认为这是一个内核错误。内核在单步执行时必须设置TF
,但用户模式也可能正在修改TF代码>。为了处理这个问题,内核会尝试维护谁设置了TF
:
/*在内核堆栈上设置TF*/
regs->flags |=X86\u EFLAGS\u TF;
/*
*..但如果TF被指令改变,我们将跟踪,
*不要把它标记为是“我们”设定的,这样我们
*以后不会用手清理的。
*
*请注意,如果我们没有实际执行popf,因为
*如果信号马上到达,我们就输了
*事实上是“我们”决定了这一切。
*/
如果(正在设置陷阱标志(子项、注册表)){
清除线程标志(子级,TIF强制);
返回0;
}
请注意,它甚至承认一些角落的情况可能会使它迷失方向。
更糟糕的是,is\u setting\u trap\u flag
只检查指令是否会修改TF
,而不检查指令是否实际设置了它:
开关(操作码[i]){
/*popf和iret*/
案例0x9d:案例0xcf:
返回1;
因此,即使已清除,它也会将TF
标记为用户设置。在get_flags
中,如果内核设置了TF
,它将尝试屏蔽TF
,如下所示:
/*
*如果调试器设置了TF,则将其从读数中隐藏。
*/
if(测试线程标志(任务,TIF强制)
retval&=~X86个字符集;
由于TIF_FORCED\u TF
被错误清除,此条件将不为真,因此实际上由内核为单步执行设置的TF
将返回到调试器
我认为这可以通过修改is\u setting\u trap\u flag
来解决,这样它就可以检查堆栈中标志的新值,并且只有在TF
实际被设置时才返回1