Как я могу создать объектный файл из исходного кода на ассемблере так же, как это делает clang -c main.c

Я хочу изучить детали файла obj, я создал файл main.S, когда я использую as main.S, я получаю взамен файл a.out, который можно запустить напрямую с помощью ./a.out, а ld -m elf_x86_64 a.out выдаст ошибку.

Я хочу создать объектный файл, тип файла которого совпадает с результатом clang -c main.c. Как я могу это сделать?


Возможно, я перепутал операцию, что привело к неправильной интерпретации. as не создает исполняемый файл, исполняемый файл является результатом clang. спасибо всем ответившим, мне очень жаль, что я вызвал путаницу, и я потратил ваше время впустую.


person Rui    schedule 22.03.2021    source источник
comment
Что вы сделали, чтобы собрать объектный файл? Вы можете сделать cc -c main.S, чтобы получить такой объектный файл. Или используйте clang или любой другой компилятор вместо cc.   -  person fuz    schedule 22.03.2021
comment
Я пытаюсь манипулировать средним результатом, чтобы увидеть, что получится в результате, чтобы изучить обратное проектирование.   -  person Rui    schedule 22.03.2021
comment
@Riu Ваш вопрос сформулирован правильно. Я хочу создать объектный файл, тип файла которого совпадает с результатом clang -c main.c. И вы попытались связать результирующий объектный файл с ld, поэтому не похоже, что вы неправильно поняли этапы preproc/asm/COFF/linking в процессе сборки исполняемого файла ^^   -  person Zilog80    schedule 22.03.2021
comment
@Riu Я предлагаю вам перефразировать заголовок вашего вопроса, указав что-то более точное с вашим намерением, например, как я могу создать объектный файл из источника на ассемблере так же, как это делает clang -c main.c   -  person Zilog80    schedule 22.03.2021
comment
Спасибо @zilog80, я изменил это.   -  person Rui    schedule 22.03.2021


Ответы (2)


as -o foo.o foo.s

Если у вас есть .S, обычно это означает, что вы хотите пропустить его через препроцессор C перед сборкой. Интерфейсы gcc и clang сделают это за вас: gcc -c foo.S (имя выходного файла по умолчанию foo.o вместо a.out). Однако, если ваш .S на самом деле не имеет каких-либо директив CPP, таких как #if или #define, вы можете просто собрать его с помощью as.


a.out — это имя по умолчанию для вывода as, но это это объектный файл, который вы получите от gcc -c foo.s, а не связанный исполняемый файл! GNU Binutils as не создает связанные исполняемые файлы.

(Имя выходного файла по умолчанию для ld foo.o или gcc / clang без -cтакже a.out, но пусть вас не смущает это имя.)

Вы можете использовать gcc -v -c foo.s, чтобы показать используемую командную строку as, включая параметр -o. (у clang есть встроенный ассемблер, поэтому он не будет запускать отдельную команду as, но интерфейс gcc действительно просто запускает as для сборки исходных файлов asm. А без -c затем запускает ld (через collect2) для связывания объектный файл в исполняемый файл.)

например в моей системе x86-64 GNU/Linux:

$ cat > foo.s
mov $231, %eax             # __NR_exit_group
syscall
$ as foo.s
$ file a.out
a.out: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped
$ ld a.out -o exit
ld: warning: cannot find entry symbol _start; defaulting to 0000000000401000
$ ls -l exit a.out 
-rw-r--r-- 1 peter peter  664 Mar 22 08:23 a.out
-rwxr-xr-x 1 peter peter 4632 Mar 22 08:23 exit
$ file exit
exit: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, not stripped

$ ./a.out
bash: ./a.out: Permission denied
$ ./exit
$ strace ./exit 
execve("./exit", ["./exit"], 0x7ffc72823fc0 /* 55 vars */) = 0
exit_group(0)                           = ?
+++ exited with 0 +++
$ as --version
GNU assembler (GNU Binutils) 2.35.1
...
This assembler was configured for a target of `x86_64-pc-linux-gnu'.
$ ld --version
GNU ld (GNU Binutils) 2.35.1
...
person Peter Cordes    schedule 22.03.2021
comment
Я предположил, что это связанный файл, потому что файл результатов a.out можно запустить с помощью ./a.out. - person Rui; 22.03.2021
comment
@Rui: Как я уже продемонстрировал, в моей системе Arch GNU/Linux это не так. У него нет разрешения на выполнение, и это перемещаемый ELF, а не исполняемый файл или исполняемый файл общего объекта/PIE. Даже если я chmod его, я получаю Exec format error при попытке запустить его. Какая у вас система? - person Peter Cordes; 22.03.2021
comment
Я тоже вижу relocatable в file a.out, но в моем случае это работает. Я на убунту. Это потому, что формат relocatable и executable настолько близок, что иногда relocatable также работает? - person Rui; 22.03.2021
comment
@Rui: они оба ELF, но перемещаемый объект не запускается ни одним известным мне механизмом: он еще не связан, поэтому он не готов к запуску. Единственное, о чем я могу думать, это какая-то binfmt_misc установка, которая прозрачно связывает ее с исполняемым файлом на лету. - person Peter Cordes; 22.03.2021
comment
@Rui: Вы уверены, что случайно не запускаете какой-то другой a.out, который является связанным исполняемым файлом? Показывает ли readelf -a a.out какие-либо заголовки программ? Заголовки программ ELF необходимы загрузчику программ ядра для сопоставления их с виртуальным адресным пространством процесса. В моем a.out я вижу There are no program headers in this file. (только заголовки разделов, поэтому он работает как ввод компоновщика.) - person Peter Cordes; 22.03.2021
comment
Извините, я не помню точного результата file a.out, это исполняемый файл. gcc -v -c hello.s помог мне узнать as --64 -o hello.o hello.s результат. Я сомневаюсь, проверил результат, я уверен, что этот ответ правильный. Спасибо за помощь. - person Rui; 22.03.2021
comment
О, вы совершенно правы, я перепутал результат!!!! Мне очень жаль. as не создает исполняемый файл!!! - person Rui; 22.03.2021
comment
@Rui: as по умолчанию равно --64 -o a.out, поэтому GCC просто явно указывает на это и устанавливает другое имя выходного файла. Если у вас был исполняемый, а не перемещаемый файл a.out, возможно, он остался от запуска gcc hello.s (без -c) или от запуска ld a.out, который считывает a.out (объектный файл) и записывает новый a.out (исполняемый файл). (За исключением того, что это не работает, потому что ld a.out усекает a.out до того, как он его прочитает, поэтому вы получаете исполняемый файл без .text) - person Peter Cordes; 22.03.2021
comment
Обратите внимание, что файл OP называется main.S, поэтому может потребоваться запуск препроцессора. - person fuz; 22.03.2021

Самый простой способ, использовать clang -v -fno-integrated-as -c main.c и получить из его вывода командную строку газа.

person Zilog80    schedule 22.03.2021
comment
Он показывает командную строку clang, я не вижу, чтобы командная строка начиналась с as. - person Rui; 22.03.2021
comment
@Rui: это будет работать только с gcc -v -c foo.s (или foo.c), а не с clang. clang имеет встроенный ассемблер, поэтому ему не нужно запускать as на нем. - person Peter Cordes; 22.03.2021
comment
Если у вас есть llvm clang, вы можете запретить ему использовать встроенную AS с -fno-integrated-as. По умолчанию LLVM использует собственный интегрированный ассемблер. - person Zilog80; 22.03.2021
comment
@ Zilog80: ОП ищет команду для сборки .s в .o. Итак, clang -S — это ответ на другой вопрос. clang -c foo.s является допустимым ответом (учитывая встроенный ассемблер clang, он работает сам по себе, без необходимости разветвления as). - person Peter Cordes; 22.03.2021
comment
@Peter Cordes clang -S здесь показывает способ получить исходный код на ассемблере из исходного кода C с выбором синтаксиса. Но это правда, что -llvm не имеет прямого отношения к вопросу, я удалю свое редактирование. - person Zilog80; 22.03.2021
comment
Да, я знаю, что делает -S, поэтому я знаю, что это не ответ на вопрос, как собрать существующий .s. Да, это полезная вещь, которую вы можете оставить в своем ответе, если объясните, что именно она делает, хотя это рассматривается в вопросах и ответах, таких как Как удалить шум от вывода сборки GCC/clang? и Как сгенерировать ассемблерный код с clang в синтаксисе Intel? - person Peter Cordes; 22.03.2021
comment
@PeterCordes Как уже говорилось в других вопросах и ответах, -llvm тогда был просто шумом в ответе. - person Zilog80; 22.03.2021
comment
Хорошее решение. no-integrated-as немного сложно найти в море предлагаемых вариантов clang. - person Rui; 22.03.2021