【问题标题】:ARM linux: Process address spaceARM linux:进程地址空间
【发布时间】:2012-05-22 07:42:00
【问题描述】:

我正在使用带有 ARM cortex_A9_MPCORE 处理器的开发板(雪球),运行带有 3.0.8+ 内核的 linux。 我使用 GDB 和 openocd 进行调试。

我正在寻找一种方法来查找用户模式进程的地址空间,尤其是文本段和用户模式堆栈。

首先我查看了 /proc/"PID"/maps,例如,我正在为其中一个正在运行的进程获取此输出:

# cat /proc/1124/maps
00008000-000d5000 r-xp 00000000 b3:02 181        /system/bin/lbsd
000d5000-000f8000 rw-p 000cd000 b3:02 181        /system/bin/lbsd
000f8000-0014a000 rw-p 00000000 00:00 0          [heap]
0014a000-0014c000 rw-p 00000000 00:00 0          [heap]
.
.
.
b0001000-b0009000 r-xp 00001000 b3:02 183        /system/bin/linker
b0009000-b000a000 rw-p 00009000 b3:02 183        /system/bin/linker
b000a000-b0015000 rw-p 00000000 00:00 0 
bea00000-bea21000 rw-p 00000000 00:00 0          [stack]
ffff0000-ffff1000 r-xp 00000000 00:00 0          [vectors]

然后我使用 GDB 编写了一个脚本,该脚本从 init_task 开始解析板上运行的任务列表,对于每个任务,它获取在 task_struct 中找到的 mm_struct 的值,然后提取 start_code、end_code 和 start_stack 的值。最后,脚本解析 mmap 指向的不同内存区域。 该脚本在开发板处于调试状态时运行,cortex a9 的两个内核都已停止

这是与上述相同进程的 GDB 脚本的输出:

taskaddr 0xdf29f140
Name: lbsd
mm start text 8000
mm end text d4ba4
mm start stack bee63df0
####MEMORY REGIONS#####
vm_start 0x8000
vm_end 0xd5000
vm_flags 0x8001875
-----------------------
vm_start 0xd5000
vm_end 0xf8000
vm_flags 0x8101873
-----------------------
vm_start 0xf8000
vm_end 0x14a000
vm_flags 0x100073
-----------------------
vm_start 0x14a000
vm_end 0x14c000
vm_flags 0x100073
-----------------------
.
.
.
-----------------------
vm_start 0xb0001000
vm_end 0xb0009000
vm_flags 0x8000875
-----------------------
vm_start 0xb0009000
vm_end 0xb000a000
vm_flags 0x8100873
-----------------------
vm_start 0xb000a000
vm_end 0xb0015000
vm_flags 0x100073
-----------------------
vm_start 0xbee42000
vm_end 0xbee64000
vm_flags 0x100173
-----------------------
vm_start 0xffff0000
vm_end 0xffff1000
vm_flags 0x40c0055
-----------------------

内存区域匹配除了堆栈之外的两种方法,在/proc方法的输出中它从bea00000开始,而在mm_struct的start_stack字段中它位于bee63df0,vm_struct指向的内存区域表示bee42000 . 有人可以解释一下这些值的区别吗?

我的第二个问题是关于 00008000 和 000d5000 之间的第一个内存区域的值,它对应于进程的文本部分。我注意到很多进程共享这些地址。内核如何获取文本内存区域的真实地址?

【问题讨论】:

    标签: linux-kernel arm embedded-linux


    【解决方案1】:

    在 ARM 上,堆栈向下增长。这意味着堆栈从更高的地址开始。这在堆栈vmavm_flags 中可见,该堆栈设置了VM_GROWSDOWN 位。

    堆栈vma 有一个vm_end0xbee64000,正好比start_stack0xbee63df0 高528 个字节。发生这种情况是因为在同一个 VMA 的堆栈顶部之上还有一些东西:命令行、环境和辅助向量。

    我不知道为什么堆栈(只有它)位于/proc/<pid>/maps 的不同地址。查看内核源代码,我看到vma 可以显示为[stack] 当且仅当start_stack 在其中,所以如果start_stack/proc/<pid>/maps 相同,则@ 987654335@ 无法标记为 [stack]。我能想到的唯一解释是它来自您的可执行文件的不同运行,并且地址布局随机化对除堆栈之外的所有内容都禁用。


    现在是第二个问题。

    当您的进程运行时,硬件使用页表从虚拟地址(例如0x8000)映射到页面的物理地址。内核也可以这样做;它有一个指向其mm_struct 中进程的根页表(pgd) 的指针。一旦它有了物理页码(pfn),就可以到达对应的struct page。有大量的宏和函数可以完成所有这些操作。

    但是可能缺少一个页面。例如,您的可执行文件的其中一个页面可能还没有出错。页表中该页的条目将显示为缺失。然后内核查看相应的vma,它给定vma 内的偏移量,有足够的信息从某处获取页面,并将其插入到页表中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-09-29
      • 2012-01-22
      • 2012-08-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多