Загружаемый Bash Builtin - PullRequest
       5

Загружаемый Bash Builtin

7 голосов
/ 31 августа 2011

Я пишу встроенный strcmp bash. Он компилируется нормально, но когда я пытаюсь включить его, я получаю:

$ enable -f ./strcmp strcmp
bash: enable: cannot open shared object ./strcmp: ./strcmp: only ET_DYN and ET_EXEC can be loaded

Большие части моего встроенного:

strcmp_builtin (list)
WORD_LIST *list;

char *strcmp_doc[] = {
    (char *)NULL
};

struct builtin strcmp_struct = {
    "strcmp", /* builtin name */
    strcmp_builtin, /* function implementing the builtin */
    BUILTIN_ENABLED, /* initial flags for builtin */
    strcmp_doc, /* array of long documentation strings. */
    "strcmp 'string 1' 'string 2'", /* usage synopsis; becomes short_doc */
    0 /* reserved for internal use */
};

Строка компиляции (из расширенного файла make):

~/bash-4.2/examples/loadables $ gcc -fPIC -DHAVE_CONFIG_H -DSHELL \
-g -O2 -I. -I.. -I../.. -I../../lib -I../../builtins -I../../include \
-I~/bash-4.2 -I~/bash-4.2/lib -I~/bash-4.2/builtins  -c \
-o strcmp strcmp.c

Я гуглил ET_DYN и ET_EXEC и нашел только ссылки на подобные вопросы.

Ответы [ 3 ]

10 голосов
/ 31 августа 2011

Вы заметили флаг -c?Это удерживает его от ссылок.Замените это на -shared, как @shr упомянул

7 голосов
/ 31 августа 2011

Немного продолжения ответа на мой конкретный вопрос (ET_DYN и ET_EXEC), а также расширение ответа WHY @ stanparker является правильным.

ET_DYN и ET_EXEC являются исполняемыми типами ELF.В заголовке ELF есть поле Elf32_Half e_type или Elf64_Half e_type с несколькими, возможно, ET_ * перечислениями.Я предполагаю, что ET "Исполняемый тип", исполняемый файл EXEC и DYN Dynamic.Этого должно быть достаточно, чтобы показать, что испускаемый артефакт на самом деле не является исполняемым объектом любого рода и должен был побуждать присмотреться к флагам GCC.(Подробнее о заголовках ELF: http://www.sco.com/developers/gabi/1998-04-29/ch4.eheader.html)

Теперь, когда мы видим, что мы не связываемся, давайте уберем флаг -c. Затем мы получим вторую ошибку (на этот раз где-то в компиляции),

$ gcc [...] -o strcmp.o strcmp.c
/usr/lib/gcc/i686-redhat-linux/4.6.0/../../../crt1.o: In function `_start':
(.text+0x18): undefined reference to `main'
/tmp/ccaiMtdc.o: In function `strcmp_builtin':
~/bash-4.2/examples/loadables/strcmp.c:32: undefined reference to `make_builtin_argv'
collect2: ld returned 1 exit status

Здесь на самом деле две ошибки: первая - «неопределенная ссылка на« main »», вторая - «неопределенная ссылка на« make_builtin_argv »» (внутренняя функция bash). ПоследняяСтрока достаточно, чтобы показать нам, что GCC умирает во время компоновки. Функция _start - это общая точка входа, определенная glibc, которая на самом деле сама вызывает main в программе. На данный момент, мы делаем не исполняемый файл, а разделяемыйlib. Добавление -shared в командную строку дает нам идеальную компиляцию.

Итак, почему же make make не дал мне «правильную» командную строку? Makefile.in не выполняет динамическую проверку исходных файлов, поэтомуЯ должен был добавить цели .c и .o вручную, а затем повторно запустить ./configure. После этого мы получим

$ make strcmp 
gcc [...] -c -o strcmp.o strcmp.c
gcc -shared -Wl,-soname,strcmp  -L./lib/termcap  -o strcmp strcmp.o 

Работает ли это?

$ enable -f ./strcmp strcmp
$ strcmp "hi" "ho"
$ echo $?
2
$ strcmp "hi" "ha"
$ echo $?
1
$ strcmp "hi" "hi"
$ echo $?
0

Вот чтоЯ ожидаю, что это так, кажетсяэто работает.

В любом случае, смысл в том, что я это пишу, заключается в том, что я не впервые запутался в компиляции GCC и C вообще.Это не первый раз, когда я вижу, что у кого-то вообще есть такие проблемы.Для успешной компиляции Си требуется огромный объем работы, и каждый этап важен.Итак, я пишу это, чтобы напомнить себе, что именно делали GCC (cc, ld и elf libs), почему важен один маленький персонаж здесь и там, и весь процесс обнаружения.Я не видел, чтобы это напечатали где-нибудь еще, так вот что у меня есть.

PS.Для тех, кто заинтересован в этом встроенном, это будет на моем сайте, http://davidsouther.com/2011/08/bash-strcmp-builtin/

2 голосов
/ 31 августа 2011

Я не уверен, но ... Вы когда-нибудь пробовали gcc -shared?

...