用glibc现代x86_64的Linux将检测到CPU具有支持AVX扩展,并会从通用实现许多字符串函数切换到AVX优化版(带ifunc调度员的帮助:1,2).
这个功能可以很好地提高性能,但它可以防止像valgrind(较旧的libVEXs,在valgrind-3.8之前)和gdb的" target record"(反向执行)之类的工具正常工作(Ubuntu"Z"17.04 beta,gdb 7.12 .50.20170207-0ubuntu2, gcc 6.3.0-8ubuntu1 20170221,Ubuntu GLIBC 2.24-7ubuntu2):
$ cat a.c
#include <string.h>
#define N 1000
int main(){
char src[N], dst[N];
memcpy(dst, src, N);
return 0;
}
$ gcc a.c -o a -fno-builtin
$ gdb -q ./a
Reading symbols from ./a...(no debugging symbols found)...done.
(gdb) start
Temporary breakpoint 1 at 0x724
Starting program: /home/user/src/a
Temporary breakpoint 1, 0x0000555555554724 in main ()
(gdb) …Run Code Online (Sandbox Code Playgroud) 这是我的代码结构的简化示例:
void increment(int j);
int main()
{
int i = 0;
while(1) {
i = increment(i);
}
return 0;
}
int increment(int j)
{
return j + 1;
}
Run Code Online (Sandbox Code Playgroud)
这是相应的GDB脚本:
b increment
command 1
finish
print i
continue
end
Run Code Online (Sandbox Code Playgroud)
问题是该finish命令阻止了之后的命令(即print i和continue)被调用.
有没有办法告诉GDB i在任何increment电话后立即打印?
我有一些代码的汇编代码,将在程序中的某个点执行.我不知道内存中代码的地址.
当前指令与输入指令匹配时,是否可以使gdb中断?
例如,每当gdb到达此指令时,我希望gdb中断:
leaq 0x000008eb(%rip),%rax
Run Code Online (Sandbox Code Playgroud) 我开始尝试使用gdb 7进行反向调试,按照教程:
http://www.sourceware.org/gdb/wiki/ProcessRecord/Tutorial
Run Code Online (Sandbox Code Playgroud)
我想,太好了!
然后我开始调试一个真正的程序,最后给出一个错误.所以我用gdb运行它,并在我认为错误出现的地方之前放置一个断点.然后我键入"record"以开始记录操作以便将来进行反向调试.但经过一些步骤,我得到了
Process record doesn't support instruction 0xf0d at address 0x2aaaab4c4b4e.
Process record: failed to record execution log.
Program received signal SIGTRAP, Trace/breakpoint trap.
0x00002aaaab4c4b4e in memcpy () from /lib64/libc.so.6
(gdb) n
Single stepping until exit from function memcpy,
which has no line number information.
Process record doesn't support instruction 0xf0d at address 0x2aaaab4c4b4e.
Process record: failed to record execution log.
Program received signal SIGABRT, Aborted.
0x00002aaaab4c4b4e in memcpy () from /lib64/libc.so.6
Run Code Online (Sandbox Code Playgroud)
在我详细介绍之前,我想知道这个功能是否还有错误,或者我是否应该从头开始录制.
发生此"记录"错误的地方,只创建一个对象作为其他对象的副本.
假设我在 A() 和 A() 调用 B()。我刚刚进入 A() 并且我希望程序运行到我进入 B() 为止。它不必是特定的函数 B()。我只希望我的程序在进入新函数时暂停。有没有办法做到这一点?
我真正在做的是尝试在设置或清除单个位时设置观察点。我通过在包含该位的字上设置一个观察点,然后使其成为条件*word & mask(用于设置或(~*word) & mask清除)来做到这一点。
问题是同一个字中的一些其他位可能会被修改,并且条件可能已经匹配。如果我有旧值和新值,我可以设置(($old ^ $new) & mask).
我查看了 pythongdb.Breakpoint类,但它似乎也没有收到此信息。
我想我可以发疯并设置一个命令列表,该列表在值*word更改时记录当前值,并将其用作$old. 但有一半时间我使用它,我实际上是通过 rr 使用它,所以我可能会倒退。
我正在尝试通过 gdb 脚本记录函数的输入和输出。下面是一个示例脚本。
set logging on
b func2
commands
silent
bt 1
continue
end
b func1
commands
silent
bt 1
set logging off
continue
end
Run Code Online (Sandbox Code Playgroud)
它工作正常并在指定的函数处断点,打印回溯并继续。有没有办法在被调用函数返回调用函数之前自动设置断点,这样我就可以在这个“新”断点之后通过 gdb 打印输出变量。这将大大简化我的调试,并有助于理解代码中不同调用的函数行为。
任何帮助都受到高度赞赏。非常感谢!