- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
我一直在为我的期末作业编写一个程序,我发现了以下奇怪的行为。
我编写了一个跟踪程序,以便能够从子进程读取/写入内存。我的目的是在给定点读取当前执行的指令,然后反汇编它以获得有关内存操作数等的一些信息。
出于测试目的,使用了一个用 C 语言编写的简单 HelloWorld。
我编写的跟踪器代码是这样的:
size_t tracer::readMem(ADDR_t offset, char *buff, size_t len) {
REQUIRE(_state != TRCS_UNINITIALISED);
if (_memsdescr < 0 || fcntl(_memsdescr, F_GETFL) < 0) {
_memsdescr = open(("/proc/" + to_string(_child_pid_t) + "/mem").c_str(), O_LARGEFILE);
if (_memsdescr < 0) {
logmanager::getInstance ().emplaceBasicLogger ("tracer")
.log ( SLVL_ERROR, "Process\' memory could not be "
" opened. \n");
PANIC;
} else {
logmanager::getInstance ().emplaceBasicLogger ("tracer")
.logfmt ( SLVL_DEBUG, "Opened process' memory. %lx bytes long\n",
lseek(_memsdescr, 0, SEEK_END));
}
}
ASSERT(offset <= lseek(_memsdescr, 0, SEEK_END));
int ret = pread(_memsdescr, buff, len, offset);
if (ret < 0) {
logmanager::getInstance ().emplaceBasicLogger ("tracer")
.logfmt( SLVL_ERROR, "Error reading from memory descriptor: %s\n", sys_errlist[errno]);
}
return ret;
}
控制执行的代码如下。基本上它所做的就是从/proc/mem 中读取 15 个字节的 block 。这些 block 的地址是通过在调用 ptrace(PTRACE_SINGLESTEP) 后获取 RIP(指令指针)的值来获得的。这意味着我尝试读取的所有内存都应该映射到进程的内存空间中。
trc.load (filename);
trc.launchProgram();
cout << " Started with pid " << trc.getChildPid() << endl << endl;
//memspacy::memory_map::printSystemProcVmap(trc.getChildPid());
//inj.prop_setTraceSyscalls (true);
while (trc.prop_getState () != memspacy::TRCS_STOPPED) {
//if (trc.isSyscall()){
// trc.showSyscall();
//}
//HERE IS WHERE THE DISASSEMBLY takes place
if (trc.readMem(trc.peekReg(a_RIP), inst_buff, MAX_ARCH_INST_LEN)
&& dec.disassemble()) {
dec.printFormatted();
}
trc.singleStep();
}
HelloWorld 应该由几千条指令组成,但我得到的输出是这样的。
mov %rsp, %rdi
add %al, (%rax)
push %rdi
push %rsi
push %rsp
mov %edi, %ebx
in %dx, %al
xor %ecx, -0x3f(%rax)
invalid
似乎在几条指令之后,读取函数停止获取所有数据。 没有抛出错误,唯一的问题是读取内存返回 0 字节。这意味着根据 read() 联机帮助页中的信息到达了 EOF,但 lseek() 返回的大小为 0xFFFFFFFFFFFF,因此在这一端应该没有问题。 Aso,所有读取都落在映射区域内,因为我使用程序计数器作为偏移量。
我真的想不出除了页面权限之外的任何东西,但它们都设置了读取权限,否则它甚至不会执行。 过程被正确跟踪,并且执行运行良好,具有预期的行为,甚至寄存器与控制测试(用于检查原始行为的测试)中的完全相同。
我目前的猜测是,在某个时候它到达了映射区域的末尾,这使得描述符变得无用,因此末尾的“无效”指令,但即使在每次读取时打开文件,结果也不会改变。
这里是内存映射和最后一次有效读取的读取偏移量。
00400000-00401000 r-xp 00000000 08:06 7602542 /home/amontes/workspace/memspacy_build/assets/test/test
00600000-00602000 rw-p 00000000 08:06 7602542 /home/amontes/workspace/memspacy_build/assets/test/test
**7fe3eb602000-7fe3eb625000 r-xp 00000000 08:11 657171 /lib/x86_64-linux-gnu/ld-2.19.so**
7fe3eb824000-7fe3eb826000 rw-p 00022000 08:11 657171 /lib/x86_64-linux-gnu/ld-2.19.so
7fe3eb826000-7fe3eb827000 rw-p 00000000 00:00 0
7fff57783000-7fff577a4000 rw-p 00000000 00:00 0 [stack]
7fff577fe000-7fff57800000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
最后一个有效偏移量 7fe3eb606a7c -> 这显示了无效指令
第一个无效偏移量 7fe3eb606a7d -> 这将返回 EOF
任何帮助或任何想法将不胜感激。谢谢。
最佳答案
好吧,我不知道这是某个更新引起的错误,还是一个非常特定的内核版本或任何您想调用它的错误。 全新安装操作系统后,一切正常。我可以获得指令流,并且读取函数始终返回数据。
在删除 HD 之前和安装之前,我尝试了 ptrace(PTRACE_PEEKDATA) 但没有成功。现在一切正常。
我真的不相信这个问题会对任何人有帮助,但有时一个干净的开始是可行的方法。尽管我不愿意承认,但它时常发生在我身上,并不总是与编码软件有关。
关于linux - 从 ptraced 进程读取/proc/pid/mem 返回 EOF,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25202996/
读取文件时,我知道提供的最后一个字符是 EOF。现在,当我有 EOF 时会发生什么?该文件中的字符? 如何区分文件的“真实”结尾和 EOF特点? 最佳答案 我决定将我的评论移至答案。 您的文件中不能有
GNU Bash - 3.6.6 Here Documents [n]<<[-]word here-document delimiter If any part of word is
试图查看论坛但无法重新访问。 我正在尝试阅读文本。文字是:“给 b” 但是在使用 fgetc() 时,没有达到 EOF,最后我得到 '\n',然后是无穷大的 'y' 样本。 这是我的代码: Node*
我正在做一个非常简单的作业,需要输出文件的内容,但在做任何事情之前我意外地到达了 EOF。该文件仅包含单词“pig”,并且由于某种原因 EOF 返回 16。我正在使用 Dev-Cpp 并且该程序是用
我的 kubectl 无法读取文件,每次都返回 'error: unexpected EOF'。 kubectl apply -f service.yaml > error: unexpected E
我想知道什么时候使用 cat Hello world! () { setopt localoptions shnullcmd test-nullcmd } # nothing will be
我试图找出我正在向其中写入特定数据的文件中不需要的尾随结束数据的原因,并且不相信我在写入文件时出错。 输出如下: building room_numbr capacity packard
考虑下面的简单例子 #include #include #include using namespace std; int main() { string str = "string";
我在一个程序中有这个片段(在 Visual Studio 2005 中): if(_eof(fp->_file)) { break; } 当达到 eof 时,它打破了封闭循环。但是程序无法解析
我正在尝试为 Typed Racket 中的以下函数定义类型注释: (define (neof x) (if (eof-object? x) #f x)) 不加注释给出了类型: (Any ->
我正在为 Linux 构建系统的模块编写 .spec 文件,遇到一个小问题并想分享它。 用于编写脚本文件: cat /path/to/somewhere/script #blah blah EOF
我有一个 C++ 程序,它从一个文件中读取我希望有一堆格式相同的记录。如果遇到意外情况,无论是记录格式不正确还是输入失败,我都想停止阅读,我想区分这些不同的情况。 我看过 this answer并查看
我注意到它们之间的几个区别: 在 <
预期我正在生成子进程并执行“ssh”远程框。从最近几天开始它工作正常,现在突然间,每当我尝试生成子进程时,它都会抛出错误。不确定发生了什么。 直到现在我一直在使用 pexpect 3.1,我遇到了这个
这个问题已经有答案了: Why two EOF needed as input? [duplicate] (2 个回答) Why do I require multiple EOF (CTRL+Z)
我正在浏览一个文件来寻找特定的词 Char[50]=getline(file,/n) 使用 getline 将每一行存储到一个 char 数组中以与我要查找的字符串进行比较 If( “”==char[
引用两个问题: Incorrect output from C++ Primer 1.4.4 Confused by control flow execution in C++ Primer exam
我刚刚在 this 中找到一条评论回答说在循环条件中使用 iostream::eof “几乎肯定是错误的”。我通常使用类似 while(cin>>n) 的东西——我猜它会隐式检查 EOF。 为什么使用
我刚刚在 this 中找到一条评论回答说在循环条件中使用 iostream::eof “几乎肯定是错误的”。我通常使用类似 while(cin>>n) 的东西——我猜它会隐式检查 EOF。 为什么使用
我刚刚在 this 中找到一条评论回答说在循环条件中使用 iostream::eof “几乎肯定是错误的”。我通常使用类似 while(cin>>n) 的东西——我猜它会隐式检查 EOF。 为什么使用
我是一名优秀的程序员,十分优秀!