调试器如何查看另一个进程的内存? [英] How does a debugger peek into another process' memory?

查看:32
本文介绍了调试器如何查看另一个进程的内存?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当每个进程都有自己的私有内存空间而没有外部进程访问时,调试器如何访问进程的内存空间?

When every process has its own private memory space that no external process has access to, how does a debugger access a process' memory space?

例如,我可以使用 gdb -p
将 gdb 附加到正在运行的进程我可以通过gdb访问这个进程的所有内存.

For eg, I can attach gdb to a running process using gdb -p <pid>
The I can access all the memory of this process via gdb.

gdb 是如何做到这一点的?

How is gdb able to do this?

我阅读了 SO 中的相关问题,似乎没有帖子回答这一点.

I read the relevant questions in SO and no post seems to answer this point.

推荐答案

由于问题被标记为 Linux 和 Unix,我将稍微扩展一下 David Scwartz 所说的内容,简而言之就是在操作系统".同样的基本原理也适用于 Windows,但实际实现是不同的,虽然我怀疑操作系统内部的实现做了同样的事情,但没有真正的方法知道这一点,因为我们无法检查 Windows 的源代码(然而,人们可以了解操作系统和处理器的工作原理,从而弄清楚必须发生什么!)

Since the question is tagged Linux and Unix, I'll expand a little on what David Scwartz says, which in short is "there is an API for that in the OS". The same basic principle applies in Windows as well, but the actual implementation is different, and although I suspect the implementation inside the OS does the same thing, there's no REAL way to know that, since we can't inspect the source code for Windows (one can, however, understanding how an OS and a processor works, sort of figure out what must be happening!)

Linux 有一个名为 ptrace 的函数,它允许一个进程(在一些权限检查之后)以各种方式检查另一个进程.这是一个调用,但第一个参数是你想做什么".以下是一些最基本的示例 - 还有几十个用于不太常见"的操作:

Linux has a function called ptrace, that allows one process (following some checking of privileges) to inspect another process in various ways. It is one call, but the first parameter is a "what do you want to do". Here are some of the most basic examples - there are a couple of dozen others for less "common" operations:

  • PTRACE_ATTACH - 连接到进程.
  • PTRACE_PEEKTEXT - 查看附加进程的代码内存(例如反汇编代码)
  • PTRACE_PEEKDATA - 查看附加进程的数据内存(以显示变量)
  • PTRACE_POKETEXT - 写入进程的代码内存
  • PTRACE_POKEDATA - 写入进程的数据内存.
  • PTRACE_GETREGS - 复制当前寄存器值.
  • PTRACE_SETREGS - 更改当前寄存器值(例如 set variable x = 7 的调试命令,如果 x 恰好在注册)
  • PTRACE_ATTACH - connect to the process.
  • PTRACE_PEEKTEXT - look at the attached process' code memory (for example to disassemble the code)
  • PTRACE_PEEKDATA - look at the attached process' data memory (to display variables)
  • PTRACE_POKETEXT - write to process' code memory
  • PTRACE_POKEDATA - write to process' data memory.
  • PTRACE_GETREGS - copy the current register values.
  • PTRACE_SETREGS - change the current register values (e.g. a debug command of set variable x = 7, if x happens to be in a register)

在Linux中,由于内存都一样",PTRACE_PEEKTEXTPTRACE_PEEKDATA实际上是相同的功能,所以你可以在代码中给一个地址PTRACE_PEEKDATA 和一个地址,比如说,PTRACE_PEEKTEXT 堆栈上的地址,它会很高兴地为你复制回来.区别在于操作系统/处理器组合,其中内存在数据内存和代码内存之间拆分".大多数现代操作系统和处理器都没有这种区别.显然同样适用于 PTRACE_POKEDATAPTRACE_POKETEXT.

In Linux, since memory is "all the same", PTRACE_PEEKTEXT and PTRACE_PEEKDATA are actually the same functionality, so you can give an address in code for PTRACE_PEEKDATA and an address, say, on the stack for PTRACE_PEEKTEXT and it will perfectly happily copy that back for you. The distinction is made for OS/processor combinations where memory is "split" between DATA memory and CODE memory. Most modern OS's and processors do not make that distinction. Same obviously applies to PTRACE_POKEDATA and PTRACE_POKETEXT.

所以,假设调试器进程"使用:

So, say that the "debugger process" uses:

long data = ptrace(PTRACE_PEEKDATA, pid, 0x12340128, NULL); 

当操作系统使用地址 0x12340128 的 PTRACE_PEEKDATA 调用时,它将查看"0x12340128 处内存的相应内存映射(页面对齐,使 0x12340000),如果存在,则将被映射到内核中,然后将数据从地址 0x12340128 复制到本地内存中,内存未映射,并将复制的数据作为返回值传回.

When the OS is called with a PTRACE_PEEKDATA for address 0x12340128 it will "look" at the corresponding memory mapping for the memory at 0x12340128 (page-aligned that makes 0x12340000), if it exists, it will get mapped into the kernel, the data is then copied out from address 0x12340128 into the local memory, the memory unmapped, and the copied data passed back as the return value.

手册将使用的启动说明为:

The manual states the initiating of the usage as:

父级可以通过调用 fork(2) 并让结果子进程执行 PTRACE_TRACEME,然后(通常)执行 exec(3).或者,父进程可以开始跟踪现有进程使用 PTRACE_ATTACH.

The parent can initiate a trace by calling fork(2) and having the resulting child do a PTRACE_TRACEME, followed (typically) by an exec(3). Alternatively, the parent may commence trace of an existing process using PTRACE_ATTACH.

要获得更多信息,请执行man ptrace.

For several pages more information do man ptrace.

这篇关于调试器如何查看另一个进程的内存?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆