Кодирование pmap в Solaris
В настоящее время я пытаюсь написать свою собственную программу, которая отражает команду pmap, особенно в Solaris 9. У меня проблемы с разрешением имен и путей библиотек. Вывод команды Solaris выглядит примерно так из оболочки bash:
bash-2.05# pmap $$
2427: bash
00010000 496K r-x-- /usr/bin/bash
0009A000 80K rwx-- /usr/bin/bash
000AE000 120K rwx-- [ heap ]
FF100000 688K r-x-- /usr/lib/libc.so.1
FF1BC000 24K rwx-- /usr/lib/libc.so.1
FF1C2000 8K rwx-- /usr/lib/libc.so.1
FF200000 568K r-x-- /usr/lib/libnsl.so.1
FF29E000 32K rwx-- /usr/lib/libnsl.so.1
FF2A6000 32K rwx-- /usr/lib/libnsl.so.1
FF2F0000 8K rwx-- [ anon ]
FF300000 16K r-x-- /usr/lib/libmp.so.2
FF314000 8K rwx-- /usr/lib/libmp.so.2
FF320000 8K r-x-- /usr/platform/sun4u-us3/lib/libc_psr.so.1
FF330000 40K r-x-- /usr/lib/libsocket.so.1
FF34A000 8K rwx-- /usr/lib/libsocket.so.1
FF350000 168K r-x-- /usr/lib/libcurses.so.1
FF38A000 32K rwx-- /usr/lib/libcurses.so.1
FF392000 8K rwx-- /usr/lib/libcurses.so.1
FF3A0000 8K r-x-- /usr/lib/libdl.so.1
FF3B0000 8K rwx-- [ anon ]
FF3C0000 152K r-x-- /usr/lib/ld.so.1
FF3F6000 8K rwx-- /usr/lib/ld.so.1
FFBFC000 16K rw--- [ stack ]
total 2536K
Чаще всего я могу продублировать основные функции программы, прочитав / proc / $$ / map, но остаётся выяснить, как разрешить имена библиотек, показанные справа. /proc/$$/map дает только имена файлов в /proc/$$/object, которые являются просто общими именами. В Solaris 10 (окно у меня есть) я, кажется, могу использовать / proc / $$ / path, который содержит символические ссылки, но в окне, над которым я работаю, их нет. Есть ли у кого-нибудь простые идеи о том, как получить эти имена библиотек? Когда я запускаю программу, она, кажется, открывает / proc / $$ / as, просматривает память и каким-то образом находит их, но я пока не могу понять, где она выглядит и почему.
1 ответ
Внедрение Solaris pmap
на самом деле доступен в виде исходного кода через OpenSolaris, pmap.c
, Но это очень сложная вещь; основы проще достичь.
Солярис имеет три /proc
ручки для карт:
/proc/<PID>/map
который содержитstruct prmap
данные, которые отражают "обычный" размер рабочего набора/proc/<PID>/rmap
который также содержитstruct prmap
данные, но для размера виртуального набора (VSZ), то есть отражающие диапазоны VA, даже если отображение не зафиксировано./proc/<PID>/xmap
который содержитstruct prxmap
данные, которые фактически тралят адресное пространство для идентификации резидентных областей памяти.
pmap
утилита смотрит на них, когда вы передаете либо без аргументов (map
), -r
(rmap
) или же -x
(xmap
), но, как вы обнаружили, это намного больше, чем просто открытие / чтение файлов с картами. Это в значительной степени делает исходный код сложным для анализа.
Тем не менее, вы можете построить тривиальный солярис [rx]map
(использование struct prxmap
вместо struct prmap
если вы получите доступ xmap
конечно) парсер через код вроде:
char mappath[MAXPATHLEN];
sprintf(mappath, "/proc/%d/map", getpid());
int fd = open(mappath, O_RDONLY);
size_t nread;
size_t mapsz = (1 << 20); /* start at 1MB */
struct prmap *cur*mapbuf = malloc(mapsz);
while ((nread = pread(fd, mapbuf, mapsz, 0)) == mapsz) {
free(mapbuf);
mapsz *= 2;
mapbuf = malloc(mapsz);
}
for (cur = mapbuf; nread; cur++, nread -= sizeof(*mapbuf))
prettyprint(cur);
free(mapbuf);
Несколько подсказок:
- не пытайся
mmap()
map
файл, который не будет работать (procfs не позволяет) - не пытайтесь последовательно читать его части; вышеупомянутое (перечитывание целого с начала в измененный размер буфера) быстрее, чем выполнение непрерывной последовательности
read()
, Всегда читайте с самого начала (используйтеpread
как в примере, илиlseek(..., 0, SEEK_SET)
перед любымread
).
Наслаждайтесь экспериментами!
Редактировать:
Поскольку вы решили найти имена путей для сопоставлений, это одна из действительно сложных задач. pmap
не занимается этим сам, но использует возможности libproc
разрешить эти имена, которые, как вы нашли truss
, может перетаскивать адресное пространство процесса, чтобы извлечь их, но также использует несколько других методов. Это по сути "итер" функции в libproc/Psymtab.c
которые делают это. Также есть различия между Solaris 9 и более поздними версиями... не помню, слишком давно...