2012-05-22 3 views
1

Я использую плату разработки (snowball) с процессором ARM cortex_A9_MPCORE, работающим под Linux с ядром 3.0.8+. Я использую GDB и openocd для отладки.ARM linux: адресное пространство процесса

Я ищу способ найти адресное пространство процесса пользовательского режима, особенно текстовый сегмент и стек пользовательского режима.

первый я смотрел в/Proc/«PID»/карты, например, я получаю этот выход для одного из запущенных процессов:

# 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, для каждой задачи он получает значение mm_struct, найденное в task_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, тогда как в поле start_stack в mm_struct он равен bee63df0, а область памяти, на которую указывает vm_struct, указывает bee42000. Может ли кто-нибудь объяснить разницу в этих значениях?

Мой второй вопрос касается значений первой области памяти между 00008000 и 000d5000, которая соответствует текстовому разделу процесса. Я заметил, что многие процессы разделяют эти адреса. Как ядро ​​удается получить реальный адрес области текстовой памяти?

ответ

1

На ARM стек растет. Это означает, что стек начинается с более высоких адресов. Это видно в vm_flags для стека vma, который имеет бит VM_GROWSDOWN.

Стек vma имеет vm_end из 0xbee64000, который точно 528 байт больше, чем start_stack из 0xbee63df0. Это происходит потому, что в одном и том же VMA есть несколько вещей выше вершины стека: командной строки, среды и вспомогательных векторов.

Я не знаю, почему стек (и только он) находится на другом адресе в /proc/<pid>/maps. Глядя на исходный код ядра, я вижу vma может проявляться как [stack] тогда и только тогда, когда start_stack находится внутри него, так что если start_stack было то же самое, когда вы смотрели на /proc/<pid>/maps, что vma не могли быть отмечены как [stack]. Единственное объяснение, о котором я могу думать, это то, что он выполняется с другого запуска вашего исполняемого файла и что рандомизация расположения адресов отключена для всего, кроме стека.


Теперь второй вопрос.

Пока ваш процесс запущен, аппаратное обеспечение использует таблицы страниц для сопоставления с виртуального адреса (например, 0x8000) на физический адрес страницы. Ядро может сделать то же самое; он имеет указатель на таблицы корневой страницы (pgd) для процесса в своем mm_struct.Как только у него есть номер физической страницы (pfn), он может перейти к соответствующему struct page. Для выполнения всех этих манипуляций существует большой набор макросов и функций.

Возможно, страница может отсутствовать. Например, одна из страниц вашего исполняемого файла, возможно, еще не была обнаружена. Запись для этой страницы в таблицах страниц покажет ее как отсутствующую. Затем ядро ​​обращается к соответствующему vma, которому присваивается смещение в пределах vma, и у него достаточно информации, чтобы получить страницу откуда-то и вставить ее в таблицы страниц.

Смежные вопросы