在Linux上转储正在运行的进程堆栈的C程序

6
我正在尝试在Linux Fedora 20上转储运行进程的堆栈(我想自己完成,而不使用gdb/ ...),但似乎即使/proc/x/mem的read()返回正数,我的缓冲区(buf)的默认值也从未被替换。 我已禁用selinux。
[me@localhost ~]$ cat /proc/2419/maps
00400000-00401000 r-xp 00000000 fd:02 164622                             /home/me/memo
00600000-00601000 r--p 00000000 fd:02 164622                             /home/me/memo
00601000-00602000 rw-p 00001000 fd:02 164622                             /home/me/memo
7fd7cbea2000-7fd7cc056000 r-xp 00000000 fd:02 8636                       /usr/lib64/libc-2.18.so
7fd7cc056000-7fd7cc256000 ---p 001b4000 fd:02 8636                       /usr/lib64/libc-2.18.so
7fd7cc256000-7fd7cc25a000 r--p 001b4000 fd:02 8636                       /usr/lib64/libc-2.18.so
7fd7cc25a000-7fd7cc25c000 rw-p 001b8000 fd:02 8636                       /usr/lib64/libc-2.18.so
7fd7cc25c000-7fd7cc261000 rw-p 00000000 00:00 0 
7fd7cc261000-7fd7cc281000 r-xp 00000000 fd:02 723                        /usr/lib64/ld-2.18.so
7fd7cc469000-7fd7cc46c000 rw-p 00000000 00:00 0 
7fd7cc47d000-7fd7cc480000 rw-p 00000000 00:00 0 
7fd7cc480000-7fd7cc481000 r--p 0001f000 fd:02 723                        /usr/lib64/ld-2.18.so
7fd7cc481000-7fd7cc482000 rw-p 00020000 fd:02 723                        /usr/lib64/ld-2.18.so
7fd7cc482000-7fd7cc483000 rw-p 00000000 00:00 0 
7fffc8479000-7fffc849a000 rw-p 00000000 00:00 0                          [stack]
7fffc854e000-7fffc8550000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]


[me@localhost ~]$ cat analyse.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ptrace.h>
#include <fcntl.h>

#define STACK_BEGIN 0x7fffc8479000
#define STACK_END 0x7fffc849a000
#define STACK_SIZE STACK_END - STACK_BEGIN

void main(int argc, char** argv)
{
    int pid = atoi(argv[1]);
    char mem_file_name[30];

    int mem_fd; 
    char buf[STACK_SIZE];

    sprintf(mem_file_name, "/proc/%d/mem", pid);
    mem_fd = open(mem_file_name, O_RDONLY);
    printf("PID=%d\n\
            NAME=%s\n\
            FD=%d\n\
            Initial value of buf : %x\n", pid, mem_file_name, mem_fd, buf);

    int ptrace_log = ptrace(PTRACE_ATTACH, pid, NULL, NULL);

    waitpid(pid, NULL, 0);
    int lseek_log = lseek(mem_fd, STACK_BEGIN, SEEK_SET);
    int rd = read(mem_fd, buf, STACK_SIZE);

    printf("in Memory at : %zd, %x (readed %d chari - ptrace ret = %d - lseek ret = %d)\n", STACK_BEGIN, buf, rd, ptrace_log, lseek_log);

    ptrace(PTRACE_DETACH, pid, NULL, NULL);
    close(mem_fd);
}

[me@localhost ~]$sudo ./analyse 2419
PID=2419
NAME=/proc/2419/mem
FD=3
Initial value of buf : da5030f0
in Memory at : 140736553521152, da5030f0 (readed 135168 chari - ptrace ret = 0 - lseek ret = -934834176)

你正在打印buf的地址,而不是它的内容。 - Barmar
1
打印 *bufbuf[0],你应该会看到一个区别。 - Barmar
我仍然遇到麻烦(因为buf中有0),所以我使用了write(STDOUT_FILENO,bug,STACK_SIZE); 现在它可以工作了,谢谢 :) - IggY
@Barmar,您能否回答这个问题,以便它被接受并标记为已回答? - corazza
1个回答

0

read() 不会改变 buf 的地址(它怎么可能呢?),它只会改变内容。如果你想看到这个变化,你需要打印出内容。打印 *buf 将会显示缓冲区的第一个字符。

void main(int argc, char** argv)
{
    int pid = atoi(argv[1]);
    char mem_file_name[30];

    int mem_fd; 
    char buf[STACK_SIZE];

    sprintf(mem_file_name, "/proc/%d/mem", pid);
    mem_fd = open(mem_file_name, O_RDONLY);
    printf("PID=%d\n\
            NAME=%s\n\
            FD=%d\n\
            Initial value of buf : %c\n", pid, mem_file_name, mem_fd, *buf);

    int ptrace_log = ptrace(PTRACE_ATTACH, pid, NULL, NULL);

    waitpid(pid, NULL, 0);
    int lseek_log = lseek(mem_fd, STACK_BEGIN, SEEK_SET);
    int rd = read(mem_fd, buf, STACK_SIZE);

    printf("in Memory at : %zd, %c (readed %d chari - ptrace ret = %d - lseek ret = %d)\n", STACK_BEGIN, *buf, rd, ptrace_log, lseek_log);

    ptrace(PTRACE_DETACH, pid, NULL, NULL);
    close(mem_fd);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接