Задачи в пользовательском пространстве
Точка входа и Header
На прмиере предыдущего задания readelf -h build/asm_example:
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: DYN (Position-Independent Executable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x10c0
Start of program headers: 64 (bytes into file)
Start of section headers: 13984 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 13
Size of section headers: 64 (bytes)
Number of section headers: 31
Section header string table index: 30
Entry point address: 0x10c0, это start nm build/asm_example:
...
0000000000001060 T main
U __printf_chk@GLIBC_2.3.4
0000000000001120 t register_tm_clones
00000000000010c0 T _start
...
При objdump -d build/asm_example видно, что из _start вычисляется адрес целевого main относительно текущей инструкции регистра и вызывается уже сам main:
...
0000000000001060 <main>:
1060: f3 0f 1e fa endbr64
...
00000000000010c0 <_start>:
...
10d8: 48 8d 3d 81 ff ff ff lea -0x7f(%rip),%rdi # 1060 <main>
10df: ff 15 f3 2e 00 00 call *0x2ef3(%rip) # 3fd8 <__libc_start_main@GLIBC_2.34>
...
Статические и динамические библиотеки
Статическая библиотека — это архив (ar) объектных файлов.
Создать статическую библиотеку из объектных файлов и использовать в сборке приложения:
ar rc libfoo_static.a libfoo_static_a.o libfoo_static_b.o
gcc app.o -lfoo_static -o app
Посмотреть тип библиотеки при помощи утилиты file, просмотреть входящие библиотеки ar -t
$ file libfoo_static.a
libfoo_static.a: current ar archive
$ ar -t libfoo_static.a
libfoo_static_a.o
libfoo_static_b.o
Динамическая библиотека - хранятся отдельно (загружается по запросу или после запуска) и имеет расширение *.so.
Создание разделяемой библиотеки и сборка программы с ней:
gcc -Wall -fPIC -c foo_a.c
gcc -Wall -fPIC -c foo_b.c
gcc -shared -Wl,-soname,libctest.so.1 -o libctest.so.1.0 foo_a.o foo_a.b
mv libctest.so.1.0 /opt/lib # перенос в область всех библиотек
ln -sf /opt/lib/libctest.so.1.0 /opt/lib/libctest.so.1
ln -sf /opt/lib/libctest.so.1.0 /opt/lib/libctest.so
gcc -Wall -L/opt/lib app.o -lctest -o app
Пример
make clean && make all
./build/userspace_example
my pid: 951085, message from 951084: message from parent
my pid: 951084, message from 951084: message from child
Выполнение задания
Разработать API для работы с логами dbgwrite, dbginit, dbgwrite dbgclose. API должно позволять записывать отладочные сообщения в циклический буфер в разделяемой памятьи (SHM).
Вероятно, имелось ввиду dbgread.
Статический анализ:
cppcheck --enable=all --suppress=missingIncludeSystem .
missingIncludeSystem - отключает проверку зависимых файлов Сборка приложения:
make allформирует следующие файлы:
- libdbg.so - динамическая библиотека, содержащая функции инициализации, чтения и записи в разделенную память
dbg_log_shm.build/libdbg.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked - writer - бинарный файл "писателя" логов.
- reader - бинарный файл "читателя" логов.
При инициализации писателя создается dbg_log_shm с правами 0666. Подробнее про shm_open.
Запись в кольцевой буфер осуществляется побайтовым заполнением через указатель на область с отраженными данными shm_ptr.
Чтение осуществляется сначала ожиданием сигнала в семафоре через sem_trywait. Если в семафоре появился сигнал - выполняется побайтовое чтение из shm_ptr пока не появится байт \n.
Проверка вызова библиотеки:
ldd build/writer
linux-vdso.so.1 (0x00007ffe7e500000)
libdbg.so => .../build/libdbg.so (0x00007fe1af0d6000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fe1aeea5000)
/lib64/ld-linux-x86-64.so.2 (0x00007fe1af0e2000)
Также через readelf
readelf -d build/writer
Dynamic section at offset 0x2d78 contains 29 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libdbg.so]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
...