Comments 16
Я не готов изменять сигнатуру main(), на зато вставлю asm(" ")...
Неужели нет методов статически скомпоновать libc, оставив только puts() и exit() ?
Если пойти в сторону исследования вызовов библиотеки, то там тоже много всего интересного:
А unsigned long используется вместо int для обеспечения соответствия размеру 64-битных регистров r__.
Если хочется гарантированно ровно 64 бита, надо юзать uint64_t.
Плюсую. А то окажется, что long всё равно 32 бита
Слишком много моделей данных (LLP64 например), что бы не использовать типы с указанием разрядности.
Если хочется гарантированно ровно 64 бита, надо юзать uint64_t.
Тот же unsigned long, но с ещё одним long.
Не гарантировано.
Ожидал, что в конце получим минималистичный файл, а вместо этого добавили ненужных секций.
Кому интересно, в скрипте линковщика можно удалить все секции кроме .text. Правда, у меня компилятор добавлял какую-то свою .note.gnu.property.
От нее избавился с помощью:
strip --remove-section=.note.gnu.property hello-data
Получилось 4505 байта (обычный hello - 15456).
То есть, на ARM это уже не скомпилировать, а упрощения эльфа сводится к заточке кода под конкретную архитектуру)
Но статья всё равно хорошая!
разве просто заменить системные вызовы на соответствующие для нужной архитектуры - не подойдёт?
Я всегда думал что системные вызовы это ОС зависимые функции, в то время как asm код является архитектурно зависимым.
Например в этой статье asm вставки соответствуют x86_64 архитектуре. То есть, на ARM компиляция должно сломаться.
Я ошибаюсь?)
На Linux для каждой архитектуры свои системные вызовы. Потому код работать будет на любой архитектуре, если знаешь правильные вызовы для этой архитектуры.
Не совсем понимаю. Допустим вот этот сниппет кода из статьи:
asm volatile("mov $1, %%rax\n" // номер системного вызова write (0x01)
"mov $1, %%rdi\n" // Файловый дескриптор stdout (0x01)
"mov %0, %%rsi\n" // Буфер сообщений
"mov %1, %%rdx\n" // Длина буфера
"syscall" // Выполнение syscall
: // Операндов вывода нет
: "r"(message), "r"(length) // Входные операнды
: "%rax", "%rdi", "%rsi", "%rdx" // Используемые регистры
Регистры rax
, rdi
, rsi
, rdx
отсутствуют на arm архитектуре. Как в таком случае этот код скомпилируется на ARM платформе?
Касательно системных вызовов - допустим их номера совпадают на всех Linux дистрибутивах, но я не на всех unix-like осях. Уже не помню точно где читал, но на FreeBSD порядок передачи аргументов отличный от большинства Linux дистрибутивов, но при формат исполняемого файла такой-же - ELF.
Упрощаем «простой» ELF