Преобразовать диапазон адресов памяти в запущенном процессе Linux в символы в объектном файле? - PullRequest
4 голосов
/ 21 октября 2008

Вот фрагмент файла / proc / self / smaps :

00af8000-00b14000 r-xp 00000000 fd:00 16417      /lib/ld-2.8.so
Size:                112 kB
Rss:                  88 kB
Pss:                   1 kB
Shared_Clean:         88 kB
Shared_Dirty:          0 kB
Private_Clean:         0 kB
Private_Dirty:         0 kB
Referenced:           88 kB
Swap:                  0 kB
00b14000-00b15000 r--p 0001c000 fd:00 16417      /lib/ld-2.8.so
Size:                  4 kB
Rss:                   4 kB
Pss:                   4 kB
Shared_Clean:          0 kB
Shared_Dirty:          0 kB
Private_Clean:         0 kB
Private_Dirty:         4 kB
Referenced:            4 kB
Swap:                  0 kB

Это показывает, что этот процесс (self) связан с / lib / ld-2.8.so и двумя (из множества) диапазонами байтов, отображенными в памяти.

Первый диапазон 88 КБ (22 страницы по 4 КБ) - общий и чистый , то есть он не был записан. Это, вероятно, код.

Второй диапазон 4 КБ (одна страница) не является общим, и он грязный - процесс записал в него, так как он был отображен в памяти из файла на диске. Это, вероятно, данные.

Но что в этой памяти?

Как преобразовать диапазон памяти 00b14000-00b15000 в полезную информацию, такую ​​как номер строки файла, в котором объявлена ​​большая статическая структура?

Метод должен учитывать предварительную связь и рандомизацию адресного пространства , например, execshield , а также отдельные символы отладки .

(Мотивация - определить популярные библиотеки, которые также создают грязную память, и исправить их, например, объявив структуры const).

Ответы [ 3 ]

5 голосов
/ 21 октября 2008

Формат smaps:

[Дно] - [TOP] [PERM] [FILE OFFSET]

b80e9000-b80ea000 rw-p 0001b000 08:05 605294 /lib/ld-2.8.90.so

Таким образом, фактическое содержимое файла '/lib/ld-2.8.90.so' со смещением файла 0x0001b000 отображается в 0xb80e9000 в памяти этой программы.

Чтобы извлечь номер строки или код C сопоставленного адреса, необходимо сопоставить его с разделом ELF исполняемого файла или файла библиотеки, а затем извлечь символы GDB (если они есть у указанного исполняемого файла или библиотеки).

Форматы файлов GDB документированы (поверхностно) на http://sourceware.org/gdb/current/onlinedocs/gdbint_7.html#SEC60

3 голосов
/ 21 октября 2008

Посмотрите на SymtabAPI из проекта ParaDyn (U. Wisc / U. Maryland). Он работает на нескольких платформах и поддерживает не только ELF-файлы (я думаю, что он также поддерживает COFF и некоторые другие). Здесь документация .

В частности, вы можете взглянуть на класс AddressLookup; Я думаю, что это именно то, что вы хотите. Существуют также некоторые средства (getLoadAddresses ()) для определения того, какие файлы .so загружаются в любой момент времени, и я считаю, что вы также можете извлечь размер разделов кода загруженных модулей, чтобы вы могли определить, что находится в определенных частях памяти .

Предостережение: я думаю, что оно будет правильно обрабатывать рандомизацию адресного пространства, но я не совсем уверен.

0 голосов
/ 21 октября 2008

Вам потребуется извлечь информацию из обработчика памяти Linux, чтобы определить, как карта виртуальной памяти приложения соотносится с указанными страницами. Это становится сложнее, если вы также хотите отслеживать информацию на страницах, которые были выгружены из памяти.

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

-Adam

...