Подключение встроенных библиотек Linux

Последнее обновление: 30.01.2024

Операционная система Linux имеет ряд встроенных общих библиотек, в частности, библиотеки языка Си, которые мы можем использовать в приложении ассемблере. Например, мы можем подключить функцию printf, какие-то другие функции, чтобы использовать их функционал в приложении.

По умолчанию разделяемые библиотеки начинаются с префикса lib имеют расширение .so. По умолчанию они расположены в папке usr/lib. В частности, библиотеки языка Си на архитектуре x86-64 можно найти в папке /usr/lib/x86_64-linux-gnu. Здесь нас прежде всего будет интересовать библиотека libc.so, которая содержит базовый функционал стандартной библиотеки языка Си и в частности функцию printf

Например, определим файл app.asm со следующим кодом:

global _start
extern printf   ; подключаем функцию printf
 
section .data 
message: db "Hello METANIT.COM",10, 0

section .text
_start:
    lea rdi, [rel message]      ; 1-й параметр функции printf - адрес строки
    call printf       ; вызываем функцию printf
    mov rax, 60    
    syscall 

В данном случае используем библиотечную функцию printf для вывода на консоль строки message.

Для подключения разделяемых библиотек компоновщику передается флаг -l, после которого указывается имя библиотеки без приставки "lib" и расширения ".so". Так, функция printf находится в библиотеке libc.so, поэтому, чтобы ее подключить, примется флаг -l c или -lc.

Итак, скомпилируем файл "app.asm" в объектный файл

nasm -felf64 app.asm -o app.o

Затем скомпонуем приложение в исполняемый файл "app":

ld --dynamic-linker=/lib64/ld-linux-x86-64.so.2 -lc app.o -o app

Опять же для загрузки библитеки и приложения устанавливается динамический загрузчик "/lib64/ld-linux-x86-64.so" Затем мы сможем запустить скомпонованное приложение:

root@Eugene:~/asm# nasm -felf64 app.asm -o app.o
root@Eugene:~/asm# ld --dynamic-linker=/lib64/ld-linux-x86-64.so.2 -lc app.o -o app
root@Eugene:~/asm# ./app
Hello METANIT.COM
root@Eugene:~/asm#

Мы можем проверить с помощью утилиты ldd список зависимостей приложения и увидеть в нем libc.so:

root@Eugene:~/asm# ldd app
	linux-vdso.so.1 (0x00007ffd23eac000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f6091e00000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f609209e000)
root@Eugene:~/asm# 

В данном случае содавалось стандартное исполняемое приложение. Если же мы создаем приложение, независимое от позиции (PIE), то при обращении к функциям библиотек применяется выражение

call функция wrt ..plt

А для обращения к глобальным объектам применяется выражение

call объект wrt ..got

То есть применяется адресация относительно таблиц PLT и GOT. Например, изменим код app.asm следующим образом:

global _start
extern printf
 
section .data 
message: db "Hello METANIT.COM",10, 0

section .text
_start:
    lea rdi, [rel message]
    call printf wrt ..plt       ; адресация относительно PLT
    mov rax, 60    
    syscall 

Далее скомпонуем приложение с использованием флага -pie:

root@Eugene:~/asm# nasm -felf64 app.asm -o app.o
root@Eugene:~/asm# ld --dynamic-linker=/lib64/ld-linux-x86-64.so.2 -pie -lc app.o -o app
root@Eugene:~/asm# ./app
Hello METANIT.COM
root@Eugene:~/asm#

Или другой пример - используем стандартную библиотечную функцию fprintf, которая имеет следующую сигнатуру:

int fprintf(FILE *stream, const char *format, ...)

В качестве первого параметра передается поток вывода, а далее параметры как у функции printf. По умолчанию библиотека Си предоставляет глобальный объект стандартного вывода на консоль - объект stdout. Для его использования определим следующую программу:

global _start
extern fprintf  ; подключаем глобальную функцию fprintf
extern stdout   ; глобальный объект
 
section .data 
message: db "Hello Work",10, 0

section .text
_start:
    mov rdi, [rel stdout wrt ..got]   ; загружаем адрес объекта stdout
    mov rdi, [rdi]              ; загружаем сам объект stdout
    lea rsi, [rel message]      ; второй параметр функции fprintf - выводимая строка
    call fprintf wrt ..plt      ; вызываем функцию fprintf

    mov rax, 60    
    syscall 

Пример компиляции и работы программы:

root@Eugene:~/asm# nasm -felf64 app.asm -o app.o
root@Eugene:~/asm# ld --dynamic-linker=/lib64/ld-linux-x86-64.so.2 -pie -lc app.o -o app
root@Eugene:~/asm# ./app
Hello Work
root@Eugene:~/asm# 
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850