LINUX.ORG.RU

Линковка

 ,


0

2

Не получается скомпоновать свой файл с библиотекой libc.so. в исходном файле есть ссылки на printf, putchar и т.п. использую команду

ld -I/lib/ld-linux.so.2 -lc $arg.o -o $arg --verbose

attempt to open /usr/x86_64-pc-linux-gnu/lib64/libc.so failed attempt to open /usr/x86_64-pc-linux-gnu/lib64/libc.a failed attempt to open /usr/lib64/binutils/x86_64-pc-linux-gnu/2.25.164/libc.so failed attempt to open /usr/lib64/binutils/x86_64-pc-linux-gnu/2.25.164/libc.a failed attempt to open /usr/local/lib64/libc.so failed attempt to open /usr/local/lib64/libc.a failed attempt to open /lib64/libc.so failed attempt to open /lib64/libc.a failed attempt to open /usr/lib64/libc.so succeeded opened script file /usr/lib64/libc.so opened script file /usr/lib64/libc.so attempt to open /lib64/libc.so.6 succeeded /lib64/libc.so.6 attempt to open /usr/lib64/libc_nonshared.a succeeded attempt to open /lib64/ld-linux-x86-64.so.2 succeeded /lib64/ld-linux-x86-64.so.2 /lib64/ld-linux-x86-64.so.2 attempt to open 05.03.14.o succeeded 05.03.14.o ld-linux-x86-64.so.2 needed by /lib64/libc.so.6 found ld-linux-x86-64.so.2 at /lib64/ld-linux-x86-64.so.2

lddtree $arg

05.03.14 => ./05.03.14 (interpreter => /lib/ld-linux.so.2) libc.so.6 => /lib64/libc.so.6 ld-linux-x86-64.so.2 => /lib64/ld-linux-x86-64.so.2

./$arg

bash: ./$arg: Обращение к поврежденной разделяемой библиотеке

не могу разобраться что я делаю не так, подскажите пожалуйста куда копать.

Ответ на: комментарий от SmilePlz

cmake + make VERBOSE=1 в помощь. Наизусть знать флаги линковки для всех платформ - голову сломаешь.

anonymous
()

/lib/ld-linux.so.2 не является обычной разделяемой библиотекой. Это динамический загрузчик, который умеет грузить остальные библиотеки.

Обычные библиотеки лежат в секциях DT_NEEDED (опция ld -l<lib>), интерпретатор лежит в специальной секции PT_INTERP (опция ld --dynamic-linker=<loader>).

// cat foo.c
#include <stdio.h>

int main() {
    printf("42\n");
}

Реальные опции линкеру можно подсмотреть так:

# gcc -Wl,-v foo.o -o foo

/usr/lib/gcc/x86_64-pc-linux-gnu/5.3.0/../../../../x86_64-pc-linux-gnu/bin/ld \
    -plugin /usr/libexec/gcc/x86_64-pc-linux-gnu/5.3.0/liblto_plugin.so \
    -plugin-opt=/usr/libexec/gcc/x86_64-pc-linux-gnu/5.3.0/lto-wrapper \
    -plugin-opt=-fresolution=/tmp/ccSHbUOP.res \
    -plugin-opt=-pass-through=-lgcc \
    -plugin-opt=-pass-through=-lgcc_s \
    -plugin-opt=-pass-through=-lc \
    -plugin-opt=-pass-through=-lgcc \
    -plugin-opt=-pass-through=-lgcc_s \
    --eh-frame-hdr -m elf_x86_64 \
    -dynamic-linker /lib64/ld-linux-x86-64.so.2 \
    -o foo \
    \
    /usr/lib/gcc/x86_64-pc-linux-gnu/5.3.0/../../../../lib64/crt1.o \
    /usr/lib/gcc/x86_64-pc-linux-gnu/5.3.0/../../../../lib64/crti.o \
    /usr/lib/gcc/x86_64-pc-linux-gnu/5.3.0/crtbegin.o \
    -L/usr/lib/gcc/x86_64-pc-linux-gnu/5.3.0 \
    -L/usr/lib/gcc/x86_64-pc-linux-gnu/5.3.0/../../../../lib64 \
    -L/lib/../lib64 \
    -L/usr/lib/../lib64 -L/usr/lib/gcc/x86_64-pc-linux-gnu/5.3.0/../../../../x86_64-pc-linux-gnu/lib \
    -L/usr/lib/gcc/x86_64-pc-linux-gnu/5.3.0/../../.. \
    -v foo.o \
    -lgcc \
    --as-needed \
    -lgcc_s \
    --no-as-needed \
    -lc \
    -lgcc \
    --as-needed \
    -lgcc_s \
    --no-as-needed \
    /usr/lib/gcc/x86_64-pc-linux-gnu/5.3.0/crtend.o \
    /usr/lib/gcc/x86_64-pc-linux-gnu/5.3.0/../../../../lib64/crtn.o

Некоторые опции не нужны для минимального примера :)

При запуске этой программы первым управление получает /lib/ld-linux.so.2 : символ _start -> _dl_start

sf ★★★
()
Ответ на: комментарий от sf

спасибо большое за ответ. я поменял параметр --dynamic-linker с ld-linux.so.2 на ld-linux-x86-64.so.2. И все начало нормально линковаться. Интересно что если линковать напрямую в конце (после ret) не дописывается

mov rdi, rax
call exit
и выдает ошибку Segmentation fault. Cannot access memory at address 0x1...

SmilePlz
() автор топика
Ответ на: комментарий от SmilePlz

Один загрузчик является 32-битным, второй 64-битным:

for f in /lib/ld-linux*; do echo -n "$f -> "; file $(readlink -f $f); done
/lib/ld-linux-x86-64.so.2 -> /lib64/ld-2.22.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, stripped
/lib/ld-linux.so.2 -> /lib32/ld-2.22.so: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, stripped

При линковке без crt* (C runtime) объектников символ точки входа вместо отсутствующего _start резолвится в первый попавшийся символ (можно поменять через ld --entry=):

ld foo.o -o foo -lc -dynamic-linker /lib/ld-linux-x86-64.so.2 
ld: warning: cannot find entry symbol _start; defaulting to 00000000004002f0

«Правильный» _start сидит здесь:

$ objdump -r -d /usr/lib/gcc/x86_64-pc-linux-gnu/5.3.0/../../../../lib64/crt1.o

Дизассемблирование раздела .text:

0000000000000000 <_start>:
   0:   31 ed                   xor    %ebp,%ebp
   2:   49 89 d1                mov    %rdx,%r9
   5:   5e                      pop    %rsi
   6:   48 89 e2                mov    %rsp,%rdx
   9:   48 83 e4 f0             and    $0xfffffffffffffff0,%rsp
   d:   50                      push   %rax
   e:   54                      push   %rsp
   f:   49 c7 c0 00 00 00 00    mov    $0x0,%r8
                        12: R_X86_64_32S        __libc_csu_fini
  16:   48 c7 c1 00 00 00 00    mov    $0x0,%rcx
                        19: R_X86_64_32S        __libc_csu_init
  1d:   48 c7 c7 00 00 00 00    mov    $0x0,%rdi
                        20: R_X86_64_32S        main
  24:   e8 00 00 00 00          callq  29 <_start+0x29>
                        25: R_X86_64_PC32       __libc_start_main-0x4
  29:   f4                      hlt 

__libc_start_main определен в /lib/libc.so.6 и вызывается exit.

__libc_start_main: https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/x86/libc-start.c;h=3...

generic_start_main (он же LIBC_START_MAIN через #define): https://sourceware.org/git/?p=glibc.git;a=blob;f=csu/libc-start.c;h=f4aa01a98...

В самом конце есть exit() :)

Если вызова exit() нет вообще, то процесс не завершится пока не упадет.

sf ★★★
()
Ответ на: комментарий от sf

Если вызова exit() нет вообще, то процесс не завершится пока не упадет.

Нет. Вместо exit процесс может еще отправить SIGKILL своему же PID

SZT ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.