2

我正在尝试读取进程的 proc/pid/mem 堆栈(我使用 ptrace 来跟踪它)

1)我阅读 /proc/pid/maps 并将堆栈的开头和结尾保存在

unsigned int start_stack, end_stack;

2)我使用 lseek 和 read 读取堆栈地址处的内存

当我尝试阅读时遇到问题:

  int mem_file = open (mem_file_name, O_RDONLY);
  if(mem_file==-1)perror("open file mem_file failed");

  printf("start_stack = %x, end_stack = %x \n", 
     start_stack, end_stack);

  /*I think the problem is here, but i'm not sure*/
  if(lseek(mem_file, start_stack, 
       SEEK_SET)==-1)perror("lseek failed");

  int buf_size = (int)(end_stack-start_stack);
  buf = calloc(buf_size, sizeof(char));

  if(read(mem_file, buf, size_buf) == -1 )perror("read failed");
  printf("buf=");
  for(i=0; i<size_buf; i+=2)
      printf("%02x",buf[i]);

输出是:

start stack = bffde000, end stack = bffff000 
buf = 00000000000000000000000000000000000000000000

也许我错了 lseek 的偏移量?在此示例中,偏移量为 (unsigned int)bffde00,即堆栈的开头。

有什么建议么 ?谢谢

4

2 回答 2

4

int或者unsigned int不足以描述 64 位 Linux 架构上的内存地址(因为它们都是 LP64,而不是 ILP64)。

改为使用unsigned long。它足够大,可以容纳所有 Linux 架构上的任何内存地址。

在 Linux 中的大多数体系结构上,堆栈都会向下增长。这意味着预期堆栈的最低地址为零。堆栈中的“最旧”值位于最高地址。

unistd.h允许低级 I/O 返回短读取。这意味着您不能只调用read(),检查结果是否不是 -1,并假设它读取了您所要求的所有内容。它返回它确实读取的字符数,这很可能比您要求的要少。所有常见的低级 I/O 函数也可能返回 -1,errno == EINTR以防传递信号(例如,停止或继续程序时)。

例如,以只读方式打开文件或伪文件:

do {
    fd = open(filename, O_RDONLY);
} while (fd == -1 && errno == EINTR);
if (fd == -1)
    /* Cannot open, see strerror(errno) */

要关闭文件描述符,

do {
    result = close(fd);
} while (result == -1 && errno == EINTR);
if (result == -1)
    /* Delayed write error, or other I/O error,
       see strerror(errno) */

要从特定偏移量读取一些数据,#define _POSIX_C_SOURCE 200809L并使用pread()

/* Read length chars into buffer starting at offset
 * from descriptor fd. Returns 0 if success,
 * errno error code otherwise; ENOSPC if a premature
 * end of input occurs. */
int read_from(const int fd, const off_t offset,
              void *const buffer, size_t const length)
{
    char   *const ptr = buffer;
    size_t  have = 0;
    ssize_t n;

    while (have < length) {

        n = pread(fd, ptr + have, length - have, offset + (off_t)have);
        if (n > (ssize_t)0)
            have += n;

        else
        if (n == (ssize_t)0)
            return errno = ENOSPC; /* Premature end of input */

        else
        if (n != (ssize_t)-1)
            return errno = EIO; /* Kernel bug catcher */

        else
        if (errno != EINTR)
            return errno;
    }

    return 0;
}

虽然您不必使用,但即使多个线程同时从同一个文件中读取,上述函数也可以工作;这就是为什么 POSIX.1-2001 增加了对和的支持。pread()read_from()pread()pwrite()

(如果你想确保off_t是 64 位,#define _FILE_OFFSET_BITS 64. 在所有 64 位 Linux 系统上它已经是,所以对于这个特定的程序,它不是必需的。)

于 2013-07-22T22:22:28.443 回答
0

您正在读取内存,并且 printf 将在它找到的第一个空字节 (0) 处停止。如果那里是0怎么办?你停下来,得到0。

于 2013-07-22T20:41:48.073 回答