我正在尝试读取进程的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,即堆栈的开头。
有什么建议吗?感谢
答案 0 :(得分:4)
int
或unsigned 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。