Генерация библиотеки и двоичного файла из одного источника C - PullRequest
0 голосов
/ 24 декабря 2018

У меня есть исходный файл C с основной функцией и некоторыми другими функциями.Что-то вроде:

#include "stdlib.h"

int program(int argc, char ** argv)
{
    int a = atoi(argv[1]);
    int b = atoi(argv[2]);
    return a + b;
}

int main(int argc, char ** argv)
{
    return program(argc, argv);
}

Я знаю, как скомпилировать это для получения двоичного файла.

Есть ли способ скомпилировать это в объектный файл с символом main /функция опущена?

Я понимаю, что могу достичь своей цели, разбив main на собственный файл, но предположим, что я не хочу этого делать.

Ответы [ 4 ]

0 голосов
/ 24 декабря 2018

Есть ли способ скомпилировать это в объектный файл с опущенным основным символом / функцией?

То есть вы не хотите, чтобы символ main был в ваших объектных файлах.Это может быть одним из способов.

file.c

#include "stdlib.h"

int program(int argc, char ** argv)
{
    int a = atoi(argv[1]);
    int b = atoi(argv[2]);
    return a + b;
}

int not_main(int argc, char ** argv)
{
    exit(0);
}

и затем скомпилировать [gcc]

gcc file.c -o файл -e not_main -nostartfiles

ТАБЛИЦА СИМВОЛОВ:

0000000000000238 l    d  .interp                0000000000000000              .interp
0000000000000254 l    d  .note.gnu.build-id     0000000000000000              .note.gnu.build-id
0000000000000278 l    d  .gnu.hash              0000000000000000              .gnu.hash
0000000000000298 l    d  .dynsym                0000000000000000              .dynsym
00000000000002e0 l    d  .dynstr                0000000000000000              .dynstr
0000000000000302 l    d  .gnu.version           0000000000000000              .gnu.version
0000000000000308 l    d  .gnu.version_r         0000000000000000              .gnu.version_r
0000000000000328 l    d  .rela.plt              0000000000000000              .rela.plt
0000000000000360 l    d  .plt                   0000000000000000              .plt
0000000000000390 l    d  .text                  0000000000000000              .text
00000000000003f0 l    d  .eh_frame_hdr          0000000000000000              .eh_frame_hdr
0000000000000418 l    d  .eh_frame              0000000000000000              .eh_frame
0000000000200e78 l    d  .dynamic               0000000000000000              .dynamic
0000000000200fd8 l    d  .got                   0000000000000000              .got
0000000000000000 l    d  .comment               0000000000000000              .comment
0000000000000000 l    df *ABS*                  0000000000000000              file.c
0000000000000000 l    df *ABS*                  0000000000000000              
0000000000200e78 l     O .dynamic               0000000000000000              _DYNAMIC
00000000000003f0 l       .eh_frame_hdr          0000000000000000              __GNU_EH_FRAME_HDR
0000000000200fd8 l     O .got                   0000000000000000              _GLOBAL_OFFSET_TABLE_
0000000000201000 g       .got                   0000000000000000              _edata
00000000000003d5 g     F .text                  0000000000000019              not_main
0000000000000390 g     F .text                  0000000000000045              program
0000000000201000 g       .got                   0000000000000000              _end
0000000000201000 g       .got                   0000000000000000              __bss_start
0000000000000000       F *UND*                  0000000000000000              atoi@@GLIBC_2.2.5
0000000000000000       F *UND*                  0000000000000000              exit@@GLIBC_2.2.5
0 голосов
/ 24 декабря 2018

Есть ли способ скомпилировать это в объектный файл с опущенным основным символом / функцией?

Да, используя препроцессор трюки и / или опции препроцессора для компилятора.

Измените ваш код C (в вашем файле mycode.c), чтобы он содержал:

#ifdef HAVE_MAIN
int main(int argc, char ** argv)
{
    return program(argc, argv);
}
#endif 

Затем, чтобы получить только объектный файл mycode.o, скомпилируйте как gcc -Wall -Wextra -g mycode.c -c -o mycode.o (при использовании GCC )

Чтобы получить всю программу myprog, скомпилируйте ее как gcc -Wall -Wextra -g -DHAVE_MAIN mycode.c -o myprog

Вы можете (избегаялюбой #ifdef HAVE_MAIN) даже скомпилировать с помощью gcc -Wall -Wextra -g -Dmain=mymain -c mycode.c, чтобы переименовать функцию main, предварительно обработав ее как mymain (а затем он теряет свой магический статус «точки входа»).

ОднакоДелать это считается дурным тоном (не очень читаемый код).Вам лучше поместить main в другой модуль перевода и скомпилировать его только тогда, когда вам нужна целая программа.И довольно часто библиотека (или исполняемый файл ) состоит из нескольких блоков перевода (каждый из которых скомпилирован в некоторый объектный файл ;набор объектных файлов связывается вместе).Вы практически будете использовать какой-нибудь инструмент для автоматизации сборки (например, make или ninja и т. Д.) Для его сборки.

0 голосов
/ 24 декабря 2018

Обычно определение main() в библиотеке не является проблемой, поскольку компоновщик будет использовать его, только если в любом небиблиотечном двоичном файле не было main().Это может даже использоваться для получения преимущества, включая значение по умолчанию main().См., Например, стандартную библиотеку Posix -ll, используемую с lex (или -lfl, если вы используете flex).

Если вы действительно хотите убедиться, что символ недоступен для разрешения, выможете удалить символ из библиотеки.Существуют инструменты для манипулирования бинарными файлами, которые варьируются от системы к системе.Например, посмотрите на параметр --strip-symbol objcopy .(Это не удаляет скомпилированный код; оно просто делает его неразрешимым.)

0 голосов
/ 24 декабря 2018

Библиотека - это просто архив объектных модулей - чтобы пропустить main(), она должна быть либо в отдельном объектном модуле, который вы затем просто пропускаете в сборке библиотеки, либо использовать условную компиляцию, чтобы она опускалась при время компиляции .

На самом деле, если бы main находилось в отдельном объектном модуле, не имело бы значения, не было ли оно опущено, так как любое определение в объекте, непосредственно связанном с модулем, переопределило бы любое определение статической библиотеки,поэтому определение библиотеки будет использоваться только в том случае, если оно не будет переопределено.Я не уверен, сработает ли это, если main() определено в модуле, содержащем другие символы, на которые есть ссылки в двоичном файле, но ничего плохого не произойдет, если вы попробуете это, кроме ошибки дублирующегося символа.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...