Суть вопроса - как сравнить версию динамической либы, которая загружена в память программы с той, которая имеется на диске? Если подразумевается, что в пути к либе версия не указана.
Итак, обычно версия либы закодирована в пути, то есть для Bind:
cat /proc/29743/maps |grep xml7f074fdfc000-7f074ff43000 r-xp 00000000 08:03 7782687 /usr/lib/libxml2.so.2.7.87f074ff43000-7f0750142000 ---p 00147000 08:03 7782687 /usr/lib/libxml2.so.2.7.87f0750142000-7f075014b000 rw-p 00146000 08:03 7782687 /usr/lib/libxml2.so.2.7.8
Тут все очевидно, загружена нужная нам версия.
Но как быть, если версия не указана в пути?
Каждая динамическая либа ммапнута три раза, нас интересует тот ммап, в котором содержится бинарный код библиотеки, его легко узнать по r правам досутпа:
cat /proc/29743/maps |grep xml|grep 'r-xp'7f074fdfc000-7f074ff43000 r-xp 00000000 08:03 7782687 /usr/lib/libxml2.so.2.7.8
Тут 7f074fdfc000-7f074ff43000 - соотвественно, адреса начала и конца областей памяти в которые ммапнута либа в конкретном процессе (от процесса к процессу они различные).
7782687 - это айнод на диске.
Айнод - первый способ проверить, перегрузилась либа при апгрейде или нет. Если айнод совпадает с тем, что на диске, то все ок:
ls -li /usr/lib/libxml2.so.2.7.87782687 -rw-r--r-- 1 root root 1374168 Oct 13 09:43 /usr/lib/libxml2.so.2.7.8
Как мы видим - совпало!
Но как быть, если библиотека была исправлена без замены айнода? Тут сложнее, продолжаем изыскания.
Тут нам поможет gdb, им можно снять нужные нам области памяти.
gdb --batch --pid 29743 --ex "dump memory /root/memory_new.dat 0x7f074fdfc000 0x7f074ff43000"
Как видите, мы указали пид процесса и диапазоны памяти ммапинга снабженные префиксом 0x (указываем на 16 ричный формат).
В итоге мы поулчаем файл примерно равный по объему изначальному файлу на диске:
ls -al /root/memory.dat-rwxr-xr-x 1 root root 1339392 Jan 3 15:58 /root/memory.datroot@stat:~# ls -la /usr/lib/libxml2.so.2.7.8-rw-r--r-- 1 root root 1374168 Oct 13 09:43 /usr/lib/libxml2.so.2.7.8
Почему объем иной - я сказать не могу, скоее всего ммапинг наичнается с определенного адреса памяти.
Но это полноценный эльф файл:
file /root/memory.dat/root/memory.dat: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), statically linked, stripped
Правда, при запуске он сегфолтится.
Теперь мы можем эвристичеки проанализировать содержимое файла силами команды strings и попытаться извлечь версию из дампа памяти.
strings /root/memory.dat |egrep '^[0-9\.\-]+$'1.2.3.4207080000001050
Как можно догадаться, версия тут 20708, это закодированный формат 2/7/8.
Теперь проверить, какая версия у либы на диске:
strings /usr/lib/libxml2.so.2.7.8 |egrep '^[0-9\.\-]+$'1.2.3.4207080000001050
Как мы видим - совпадение полное!!! ура!!!!!
Для понимания разницы приведу пример выдачи команды при версии 2/8/0:
strings /usr/lib/x86_64-linux-gnu/libxml2.so.2.8.0 |egrep '^[0-9\.\-]+$'1.2.7208000000001050
Можно углубить анализ далее.
xxd /usr/lib/libxml2.so.2.7.8 lib.hexxxd /root/memory_new.dat mem.hex
Теперь првоерим, в чем их отличия:
diff -u mem.hex lib.hex |wc -l2180
Как видим 2180 строк отличий.
Но!!! Это не отличия, это лишь сигнализация о том, что mem.hex усечен относительно самой либы (не знаю по каким причинам):
Убедимся в этом:
diff -u mem.hex lib.hex |egrep '^+' |wc -l2180
Вот так мы подтверждаем факт идентичныости 99% данных либ.
Есть еще вариант: проверить наличие либы в страничном кэше после его обнуления.
wget https://raw.github.com/hoytech/vmtouch/master/vmtouch.cgcc -Wall -O3 -o vmtouch vmtouch.c
Обнулим страничный кэш, чтобы все последствия компиляции/копирования были выкинуты из памяти.
echo 3 > /proc/sys/vm/drop_caches
./vmtouch /usr/lib/libxml2.so.2.7.8Files: 1Directories: 0Resident Pages: 336/336 1M/1M 100%Elapsed: 7.4e-05 seconds
No comments :
Post a Comment
Note: only a member of this blog may post a comment.