偏移lseek用于读取/ proc / pid / mem

时间:2013-07-22 20:40:03

标签: c linux

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

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

unsigned int start_stack, end_stack;

2)我使用lseek并读取读取堆栈地址的内存

当我尝试阅读时,我有一个问题:

  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,即堆栈的开头。

有什么建议吗?感谢

2 个答案:

答案 0 :(得分:4)

intunsigned int不足以描述64位Linux体系结构上的内存地址(因为它们都是LP64,而不是ILP64)。

请改用unsigned long。它足以容纳所有Linux架构上的任何内存地址。

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

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

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

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

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

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

答案 1 :(得分:0)

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