问题描述
我正在对进程内存在运行时进行一些实验,发现在gdb进程中调用 calloc
时,该调用似乎可以正常工作并返回原始传递的指针,但内存似乎没有初始化为 0
:
I'm doing some experimentation with editing a process memory while it's running, and I noticed when I call calloc
in a gdb'd process, the call seems to work and return the original passed pointer, but the memory does not appear to be initialized to 0
:
(gdb) call calloc(1, 32)
$88 = (void *) 0x8d9d50
(gdb) x/8xw 0x8d9d50
0x8d9d50: 0xf74a87d8 0x00007fff 0xf74a87d8 0x00007fff
0x8d9d60: 0xfbfbfbfb 0xfbfbfbfb 0x00000000 0x9b510000
但是,如果我在结果指针上调用 memset
,则初始化工作就很好了:
If I call memset
on the resulting pointer, however, the initialization works just fine:
(gdb) call memset(0x8d9d50, 0, 32)
$89 = 9280848
(gdb) x/8xw 0x8d9d50
0x8d9d50: 0x00000000 0x00000000 0x00000000 0x00000000
0x8d9d60: 0x00000000 0x00000000 0x00000000 0x00000000
推荐答案
有趣的问题.答案是:在Linux(我假设您运行过程序)上:
Interesting question. The answer is: on Linux (where I assume you ran your program) this:
(gdb) call calloc(1, 32)
不会从 libc.so.6
中调用 calloc
.
相反,它从 ld-linux.so.2
调用 calloc
.而且 calloc
很小.它期望仅从 ld-linux.so.2
本身被调用,并且假定它可以访问的任何页面都是干净的"和不需要 >内存集.(也就是说,我无法使用glibc-2.19复制不干净的 calloc
).
Rather it calls calloc
from ld-linux.so.2
. And that calloc
is very minimal. It expects to be called only from ld-linux.so.2
itself, and it assumes that whatever pages it has access to are "clean" and do not require a memset
. (That said, I could not reproduce the unclean calloc
using glibc-2.19).
您可以这样确认:
#include <stdlib.h>
int main()
{
void *p = calloc(1, 10);
return p == 0;
}
gcc -g foo.c -m32 && gdb -q ./a.out
Reading symbols from ./a.out...done.
(gdb) start
Temporary breakpoint 1 at 0x8048426: file foo.c, line 4.
Starting program: /tmp/a.out
Temporary breakpoint 1, main () at foo.c:4
warning: Source file is more recent than executable.
4 void *p = calloc(1, 10);
(gdb) b __libc_calloc
Breakpoint 2 at 0xf7e845a0
(gdb) n
Breakpoint 2, 0xf7e845a0 in calloc () from /lib32/libc.so.6
(gdb) fin
Run till exit from #0 0xf7e845a0 in calloc () from /lib32/libc.so.6
0x0804843a in main () at foo.c:4
4 void *p = calloc(1, 10);
请注意程序对 calloc
的调用是如何到达断点2的.
Note how the call from the program to calloc
hit breakpoint #2.
(gdb) n
5 return p == 0;
(gdb) call calloc(1,32)
$1 = 134524952
请注意,上述来自GDB的调用不是达到断点2.
Note that above call from GDB did not hit breakpoint #2.
让我们再试一次:
(gdb) info func calloc
All functions matching regular expression "calloc":
Non-debugging symbols:
0x08048310 calloc@plt
0xf7fdc820 calloc@plt
0xf7ff16a0 calloc
0xf7e25450 calloc@plt
0xf7e845a0 __libc_calloc
0xf7e845a0 calloc
(gdb) info sym 0xf7ff16a0
calloc in section .text of /lib/ld-linux.so.2 ## this is the wrong one!
(gdb) break *0xf7ff16a0
Breakpoint 3, 0xf7ff16a0 in calloc () from /lib/ld-linux.so.2
(gdb) disable
(gdb) start
Temporary breakpoint 7 at 0x8048426: file foo.c, line 4.
Starting program: /tmp/a.out
Temporary breakpoint 7, main () at foo.c:4
4 void *p = calloc(1, 10);
(gdb) ena 3
(gdb) n
5 return p == 0;
请注意,断点3并没有在上面触发(因为调用了真实的" __ libc_calloc
).
Note that breakpoint #3 did not fire above (because the "real" __libc_calloc
was called).
(gdb) call calloc(1,32)
Breakpoint 3, 0xf7ff16a0 in calloc () from /lib/ld-linux.so.2
The program being debugged stopped while in a function called from GDB.
Evaluation of the expression containing the function
(calloc) will be abandoned.
When the function is done executing, GDB will silently stop.
(gdb) bt
#0 0xf7ff16a0 in calloc () from /lib/ld-linux.so.2
#1 <function called from gdb>
#2 main () at foo.c:5
QED.
更新:
我认为您在 info func
中看到的内容取决于是否安装了调试符号.对于具有调试符号的(64位)glibc ,这是我看到的内容:
I think what you see in info func
depends on whether you have debug symbols installed. For a (64-bit) glibc with debug symbols, here is what I see:
(gdb) info func calloc
All functions matching regular expression "calloc":
File dl-minimal.c:
void *calloc(size_t, size_t); <<< this is the wrong one!
File malloc.c:
void *__libc_calloc(size_t, size_t); <<< this is the one you want!
Non-debugging symbols:
0x0000000000400440 calloc@plt
0x00007ffff7ddaab0 calloc@plt
0x00007ffff7a344e0 calloc@plt
这是找出GDB认为应该调用的 calloc
的另一种方法:
Here is another way to figure out what calloc
GDB thinks it should be calling:
(gdb) start
Temporary breakpoint 1 at 0x8048426: file foo.c, line 4.
Starting program: /tmp/a.out
Temporary breakpoint 1, main () at foo.c:4
warning: Source file is more recent than executable.
4 void *p = calloc(1, 10);
(gdb) p &calloc
$1 = (<text variable, no debug info> *) 0xf7ff16a0 <calloc>
(gdb) info sym 0xf7ff16a0
calloc in section .text of /lib/ld-linux.so.2
或者,为完整起见,请使用带有调试符号的64位glibc:
Or, for completness, using 64-bit glibc with debug symbols:
(gdb) start
Temporary breakpoint 1 at 0x400555: file foo.c, line 4.
Starting program: /tmp/a.out
Temporary breakpoint 1, main () at foo.c:4
4 void *p = calloc(1, 10);
(gdb) p &calloc
$1 = (void *(*)(size_t, size_t)) 0x7ffff7df1bc0 <calloc>
(gdb) info sym 0x7ffff7df1bc0
calloc in section .text of /lib64/ld-linux-x86-64.so.2
这篇关于为什么在gdb中调用calloc似乎不会使内存归零?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!