Русские Блоги
Как получить динамическую библиотеку linux-gate.so.1
фронт«Начало работы с приложением для Linux Helloworld»Было упомянуто, что каждый исполняемый файл в Linux зависит от нескольких основных динамических библиотек, одна из которых — linux-gate.so.1.
Из результатов, предоставленных ldd выше, можно увидеть, что эта динамическая библиотека linux-gate.so.1 немного отличается. Фактический путь к динамической библиотеке libc.so.6 — /lib/tls/i686/cmov/libc.so.6 , И ld-linux.so.2 находится в /lib/ld-linux.so.2. Тогда не могу не задать вопрос, а каков путь к динамической библиотеке linux-gate.so.1, какой файл находится в файловой системе? Фактически, этот файл отображается ядром, а файла динамической библиотеки нет.Для этой конкретной проблемы мы проведем подробный анализ позже, здесь только как получить динамическую библиотеку linux-gate.so.1.
Обычно, например, в системах suse10 и suse11 linux-gate.so.1 отображается в сегмент высокопроизводительной памяти ffffe000-fffff000. В настоящее время относительно просто экспортировать эту память в файл. Для этого можно использовать следующий сценарий:
#!/bin/bash VDSO_FILE_NAME=linux-gate.dso cat /proc/self/maps|grep «vdso» VDSO_ADDR=`cat /proc/self/maps|grep «vdso» |awk -F ‘-‘ ‘
Результат выполнения в системе suse:
> ./cat_linux_gate_so.sh ffffe000-fffff000 — p 00000000 00:00 0 [vdso] Текущий адрес VDSO — 0xffffe000 У нас есть 1048574 блока перед библиотекой VDSO Готов сгенерировать linux-gate.dso из блока 1048574 1 + 0 записей в 1 + 0 записей из скопировано 4096 байт (4,1 кБ), 4,2e-05 секунды, 97,5 МБ / с Создать linux-gate.dso Готово
> file -b linux-gate.dso 32-разрядный общий объект LSB ELF, Intel 80386, версия 1 (SYSV), лишенный
> objdump -T linux-gate.dso linux-gate.dso: формат файла elf32-i386 ТАБЛИЦА ДИНАМИЧНЫХ СИМВОЛОВ: ffffe400 ld .text 00000000 .text ffffe478 ld .eh_frame_hdr 00000000 .eh_frame_hdr ffffe49c ld .eh_frame 00000000 .eh_frame ffffe620 ld .useless 00000000 .useless ffffe400 g DF .text 00000014 LINUX_2. 5 __kernel_vsyscall 00000000 g DO * ABS * 00000000 LINUX_2.5 LINUX_2.5 ffffe440 g DF .text 00000007 LINUX_2.5 __kernel_rt_sigreturn ffffe420 g DF .text 00000008 LINUX_2.5 __kernel_sigreturn
В ubuntu ситуация более сложная, и здесь было отложено много времени, потому что адрес памяти, отображаемый в ubuntu, не фиксирован, а расположение каждого отображения процесса отличается.
cat /proc/self/maps|grep «vdso»
b7f47000-b7f48000 r-xp b7f47000 00:00 0 [vdso]
b7f5f000-b7f60000 r-xp b7f5f000 00:00 0 [vdso]
b7f54000-b7f55000 r-xp b7f54000 00:00 0 [vdso]
Следовательно, приведенный выше сценарий не может реализовать экспорт отображаемой памяти в одном процессе. Чтобы реализовать экспорт в том же процессе, здесь используется простой метод программирования на C.
Основной принцип такой же, как и в приведенном выше сценарии, первый проход / proc / self / maps находит адрес отображаемой памяти vsdo, а затем экспортирует отображенную память в файл linux-gate.dso.
int main (int argc, char ** argv) < FILE * pFile = NULL; void * paddr = NULL; буфер символов [BUFFER_SIZE]; адрес символа [BUFFER_SIZE]; блок символов [BLOCK_SIZE]; char c; int i, ineedreset, iblocks, iSize; pFile = fopen ("/ proc / self / maps", "r" ); if (NULL == pFile) < printf ("/ proc / self / maps fopen не удалось, ошибка! \ r \ n "); return 1; >/ * Найти местоположение памяти сопоставления динамической библиотеки vdso * / i = 0; ineedreset = 1; memset (buffer, 0, BUFFER_SIZE); while (1) < c = fgetc (pFile); if (c! = EOF) < printf ("% c", c); if (c == '\ r' || c == '\ n') < i = 0; ineedreset = 1; >else < if (ineedreset) < if (NULL! = strstr (buffer, "vdso")) < printf ("У меня есть vdso section. \ r \ n"); break; >memset (buffer, 0, BUFFER_SIZE); ineedreset = 0; > buffer [i ++] = c; > > else < break; >> printf («строка vsdo:% s \ r \ n», буфер); fclose (pFile); pFile = NULL; / * Получить начальный адрес * / memset (адрес, 0, BUFFER_SIZE); for (i = 0; buffer [i]! = ‘-‘; i ++) < address [i] = buffer [i]; if (buffer [i] == '-') break ; >paddr = (void *) Hex2Ulong (адрес); printf («Текущий адрес VDSO равен 0x% x \ r \ n», paddr); iblocks = (unsigned long) paddr / BLOCK_SIZE; code> printf («У нас есть% d блоков до библиотеки VDSO \ r \ n», iblocks); printf («Готов сгенерировать linux-gate.dso из блока% d \ r \ n «, iblocks); / * Экспорт динамического файла vdso * / pFile = fopen («. /linux-gate.dso «,» w «); if (NULL == pFile) < printf ("Ошибка fopen linux-gate.dso, выход! \ r \ n"); return 1; >printf («Head: 0x% x-% c-% c-% c \ r \ n», * ((char *) paddr + 0), * ((char *) paddr + 1), * ((char *) paddr + 2), * ((char *) paddr + 3)); memcpy (блок , paddr, BLOCK_SIZE); iSize = fwrite (block, 1, BLOCK_SIZE, pFile); if (BLOCK_SIZE! = iSize) < perror ("fwrite error: \ r \ n"); >printf («копировать% d /% d байтов из 0x% x в файл \ r \ n», iSize, BLOCK_SIZE, paddr); fclose (pFile); printf («Создать linux-gate.dso Done \ r \ n»); return 0; >
Затем посмотрите на результат экспорта:
Таким образом, мы можем экспортировать динамическую библиотеку в случае динамического сопоставления. Если app_linux_gate_so.c изменяется соответствующим образом, все отображенные библиотеки динамической памяти можно экспортировать для DEBUG и проверки.
Источник
Программы и библиотеки Linux
Процессы операционной системы в большинстве случаев отождествляются с выполняющимися программами, что не совсем верно, точнее — совсем не верно. В современных операционных системах, включая Linux, между программой и процессом есть очевидная взаимосвязь, но далеко не такая непосредственная, как кажется на первый взгляд.
Программа представляет собой алгоритм, записанный на определенном языке, понятном исполнителю программы (программа политической партии и программа научной конференции имеют тот же смысл, что и компьютерная программа, но предназначены для других исполнителей).
Различают машинный язык, понятный центральному процессору, и языки более высоких уровней (алгоритмические), понятные составителю программы — программисту.
Программы, составленные на языке высокого уровня, в любом случае перед исполнением должны быть транслированы (переведены) на язык исполнителя, что реализуется при помощи специальных средств — трансляторов.
Различают два вида трансляторов программ — компиляторы и интерпретаторы. Компилятор транслирует в машинный код сразу всю программу целиком и не участвует в ее исполнении. Интерпретатор, наоборот, пошагово транслирует отдельные инструкции программы и немедленно выполняет их.
Например, командный интерпретатор при интерактивном режиме пошагово, выполняет команды, вводимые пользователем, а в пакетном режиме так же пошагово выполняет команды, записанные в файле сценария.
Алгоритм, в свою очередь, есть некоторый набор инструкций, выполнение которых приводит к решению некоторой задачи.
В большинстве случаев, инструкции алгоритма имеют причинно-следственные зависимости и выполняются исполнителем последовательно. Однако если выделить «независимые» поднаборы инструкций (независимые ветви), то их можно выполнять несколькими исполнителями одновременно — параллельно.
Поэтому различают последовательные и параллельные алгоритмы и соответствующие им последовательные и параллельные программы.
Некоторые программы реализуют алгоритмы общего назначения, например алгоритмы сжатия или шифрования информации, алгоритмы сетевых протоколов и т. д. Такие программы, востребованные не столько конечными пользователями, сколько другими программами, называют библиотеками.
Согласно hier, откомпилированные до машинного языка программы размещаются в каталогах /bin, /sbin, /usr/bin, /usr/sbin, /usr/local/bin, /usr/local/sbin, а библиотеки — в каталогах /lib, /usr/lib, /usr/local/lib.
Программы имеют специальный бинарный «запускаемый» формат W:[ELF] executable и зависят от библиотек, что проиллюстрировано в листинге ниже при помощи команды ldd (loader dependencies). Каждая зависимость отображается именем библиотеки (SONAME, shared object name), Найденным в системе файлом библиотеки и адресом (для противодействия эксплуатации уязвимости в программах адрес выбирается случайным образом, см. W:[ASLR]). в памяти процесса (32- или 48-битным, в зависимости от платформы), куда библиотека будет загружена.
Программы и библиотеки
$ which ls
$ file /bin/ls
/bin/ls: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[shal]=0x83531f308flfal8221be53eaf399303400cl4638, stripped
$ ldd /bin/ls
libselinux.so.l => /lib/i386-linux-gnu/libselinux.so.1 (0xb7708000) librt.so.l => /lib/i386-linux-gnu/librt.so.l (0xb76ff000) libacl.so.l => /lib/i386-linux-gnu/libacl.so.l (0xb76f5000)
libc.so.6 => /lib/1386-linux-gnu/libc. so.6 (0xb754b000)
libdl.so,.2 => /lib/i386- linux — gnu/libdl. so. 2 (0xb7546000)
libpthread.so.0 => /lib/i386-linux-gnu/libpthread.so.0 (0xb752b000) libattr.so.l => /lib/i386-linux-gnu/libattr.so.l (0xb7525000)
$ file lib/i386-linux-gnu/libc.so.6
/lib/i386-linux-gnu/libc.so.6: symbolic link to ‘libc-2.15.so’
Нужно заметить, что файла библиотеки linux-gate.so.1 (реализующей интерфейс системных вызовов к ядру) не существует, т. к. она является виртуальной (VDSO, virtual dynamic shared object), т. e. предоставляется и отображается в память процесса самим ядром, «как будто» является настоящей библиотекой.
Кроме того, библиотека ld-llnux.so.2 указана абсолютным путевым именем, поэтому поиск ее файла не производится.
Для большинства библиотек зависимость устанавливается при помощи SONAME вида libNAME.so.x где lib — стандартный префикс (библиотека), .so — суффикс (разделяемый объект), NAME — имя «собственное», а .X — номер версии ее интерфейса. По имени SONAME в определенных (конфигурацией компоновщика — ld.so и ldconfig) каталогах производится поиск одноименного файла библиотеки, который на самом деле оказывается символической ссылкой на «настоящий» файл библиотеки.
Например, для 6-й версии интерфейса динамической библиотеки языка с (libc.so.6) настоящий файл библиотеки называется libc-2.15.so, что указывает на версию самой библиотеки как 2.15.
Версии библиотек
$ file /lib/1386-linux-gnu/libacl.so. 1
/lib/1386-linux-gnu/libacl.so.1: symbolic link to ‘libacl.so.1.1.0’
Аналогично, в листинге выше показано, что для 1-й версии интерфейса динамической библиотеки списков контроля доступа acl (libacl.so. 1) настоящий файл библиотеки называется libacl.so.1.1.0, а это указывает на версию самой библиотеки как 1.1.0.
Такой подход позволяет заменять (исправлять ошибки, исправлять неэффективные алгоритмы и пр.) библиотеки (при условии неизменности их интерфейсов) отдельно от программ, зависящих от них.
При обновлении библиотеки libc-2.15.so, например, до libc-2.i8.so достаточно установить символическую SONAME-ссылку libc.so.6 на libc-2.18.so, в результате чего ее начнут использовать все программы с зависимостями от libc.so.6.
Более того, в системе может быть одновременно установлено любое количество версий одной и той же библиотеки, реализующих одинаковые или разные версии интерфейсов, выбор которых будет указан соответствующими SONAME-ссылками.
Библиотеки- это незапускаемые программы
$ file /lib/i386-linux-gnu/libc-2.15.so
/lib/i386-linux-gnu/libc-2.15.so: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs),
BuildID[shal]=0x87bb99bc34Ofl345950611a3d9cfeclcb49532dc, for GNU/Linux 2.6.24, stripped
$: file /llb/i386-linux-gnu/libacl.so.1.1.0
/llb/1386-llnux-gnu/llbacl.so.1.1.0: ELF 32-blt LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, BulldID[shal]=0xd48c066c7c7deba7c88505fe434d4601e3e91f50, stripped
$: ldd /llb/l386-llnux-gnu/llbacl.so.1.1.0
libattr.so.l => /lib/1386-linux-gnu/llbattr.so.1 (0xb76ca000)
libc.so.6 => /lib/i386-ltnux-gnu/libc.so.6 (0xb7520000)
Библиотеки имеют тот же бинарный формат W:[ELF], что и «запускаемые» программы, но не «запускаемый» executable, а «совместно используемый» shared object.
Библиотеки, являясь пусть и незапускаемыми, но программами, естественным образом тоже зависят от Других библиотек, что показано в листинге выше.
Практически, «запускаемость» ELF-файлов зависит не от их типа, а от прав доступа и осмысленности точки входа адреса первой инструкции, которой передается управление при попытке, запуска. Например, библиотеку libc-2.15.so можно запустить, в результате чего будет выведена статусная информация.
Запускаемые библиотеки
$ Is -l lib/l386-linux-gnu/libc-2.15.so
-rwxr-xr-x 1 root root 1730024 окт. 6 2018 /lib/i386-linux-gnu/libc-2.15.so
$ lib/l386-linux-gnu/libc-2.15.so
GNU C Library (Ubuntu EGLIBC 2.15-0ubuntu10.3) stable release version 2.15, by Roland McGrath et al.
crypt add-on version 2.1 by Michael Glad and others GNU Libidn by Simon Josefsson
★ Native POSIX Threads Library by Ulrich Drepper et al
Выполняющиеся программы являются основными активными сущностями, инструкции которых при помощи механизма системных вызовов потребляют ресурсы, находящиеся под управлением операционной системы. Распределением этих ресурсов и занимаются подсистемы управления процессами, управления памятью и ввода-вывода, в достаточно детальной мере рассмотренные в этой главе.
Основной задачей этих подсистем является организация эффективного распределения ресурсов между массой их потребителей — процессами и нитями.
Фактическая эффективность их работы при прочих равных будет во многом зависеть от понимания пользователем их внутренних алгоритмов и значений конфигурационных параметров этих алгоритмов, в зависимости от характеристик самих потребителей и желаемых результатов. Например, эффективность распределения процессорного времени будет напрямую зависеть от свойств процессов и нитей, их приоритетов, их классов и процессорных привязок.
Кроме того, понимание алгоритмов работы подсистем может ответить на многие вопросы о количестве потребляемых ресурсов и дать ответ об их достаточности или недостатке. Например, важно понимать, что недостаток ресурса оперативной памяти вовсе не определяется суммарными размерами виртуальной памяти, потребленной процессами, а напрямую связан с суммарными размерами их резидентной памяти.
Навыки мониторинга и трассировки потребления ресурсов процессами помогут сделать массу полезнейших выводов о свойствах выполняющихся в них программ, что чрезвычайно полезно при разработке качественного программного обеспечения.
Не лишними эти навыки будут и при выборе качественного программного обеспечения для эксплуатации в заданных условиях и с требуемыми характеристиками.
Источник