简体   繁体   English

为什么在gdb中调用calloc似乎没有将内存清零?

[英]Why does calling calloc in gdb not appear to zero out the memory?

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'd进程中调用calloc时,调用似乎工作并返回原始传递的指针,但内存似乎没有被初始化到0

(gdb) call calloc(1, 32)
$88 = (void *) 0x8d9d50
(gdb) x/8xw 0x8d9d50
0x8d9d50:       0xf74a87d8      0x00007fff      0xf74a87d8      0x00007fff
0x8d9d60:       0xfbfbfbfb      0xfbfbfbfb      0x00000000      0x9b510000

If I call memset on the resulting pointer, however, the initialization works just fine: 但是,如果我在结果指针上调用memset ,则初始化工作正常:

(gdb) call memset(0x8d9d50, 0, 32)
$89 = 9280848
(gdb) x/8xw 0x8d9d50
0x8d9d50:       0x00000000      0x00000000      0x00000000      0x00000000
0x8d9d60:       0x00000000      0x00000000      0x00000000      0x00000000

Interesting question. 有趣的问题。 The answer is: on Linux (where I assume you ran your program) this: 答案是:在Linux上(我假设你运行你的程序)这个:

(gdb) call calloc(1, 32)

doesn't call calloc from libc.so.6 . 不会从libc.so.6调用calloc

Rather it calls calloc from ld-linux.so.2 . 而是从ld-linux.so.2调用calloc And that calloc is very minimal. 那个 calloc非常小。 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 . 它期望仅从ld-linux.so.2本身调用,并且它假定它可以访问的任何页面都是“干净的”并且不需要 memset (That said, I could not reproduce the unclean calloc using glibc-2.19). (也就是说,我无法使用glibc-2.19重现不洁的calloc )。

You can confirm this like so: 您可以这样确认:

#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);

Note how the call from the program to calloc hit breakpoint #2. 注意从程序到calloc的调用如何命中断点#2。

(gdb) n
5         return p == 0;
(gdb) call calloc(1,32)
$1 = 134524952

Note that above call from GDB did not hit breakpoint #2. 请注意,上面的GDB调用达到断点#2。

Let's try again with: 让我们再试一次:

(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;

Note that breakpoint #3 did not fire above (because the "real" __libc_calloc was called). 请注意,断点#3 火以上(因为“真正的” __libc_calloc叫)。

(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. QED。

Update: 更新:

I don't see the ld-linux version in the output of "info func calloc" 我在“info func calloc”的输出中没有看到ld-linux版本

I think what you see in info func depends on whether you have debug symbols installed. 我认为你在info func看到的内容取决于你是否安装了调试符号。 For a (64-bit) glibc with debug symbols, here is what I see: 对于带有调试符号的(64位)glibc,这是我看到的:

(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

Here is another way to figure out what calloc GDB thinks it should be calling: 这里是另一种方式来找出calloc GDB认为它应该叫:

(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

Or, for completness, using 64-bit glibc with debug symbols: 或者,为了完整性,使用带有调试符号的64位glibc:

(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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM