Вызов функции libc из сборки

У меня есть функция, определенная в сборке, которая вызывает функцию libc (swapcontext). Я вызываю эту функцию из моего кода C. Чтобы создать воспроизводимый пример, я использую вместо этого "put":

foo.S:

.globl foo 
foo:
    call puts
    ret

test.c:

void foo(char *str);

int main() {
    foo("Hello World\n");
    return 0;
}

Скомпилировать:

gcc test.c foo.S  -o test

Это нормально компилируется. Однако разборка двоичного файла результата показывает, что компоновщик не вставил действительную инструкцию вызова:

objdump -dR:

0000000000000671 <foo>:
 671:   e8 00 00 00 00          callq  676 <foo+0x5>
            672: R_X86_64_PC32  puts@GLIBC_2.2.5-0x4
 676:   c3                      retq   
 677:   66 0f 1f 84 00 00 00    nopw   0x0(%rax,%rax,1)
 67e:   00 00 

0000000000000530 <puts@plt>:
 530:   ff 25 9a 0a 20 00       jmpq   *0x200a9a(%rip)        # 200fd0 <puts@GLIBC_2.2.5>
 536:   68 00 00 00 00          pushq  $0x0
 53b:   e9 e0 ff ff ff          jmpq   520 <.plt>

Исполнение:

./test1: Symbol `puts' causes overflow in R_X86_64_PC32 relocation
Segmentation fault

Есть идеи, почему?


person cradical    schedule 28.08.2019    source источник
comment
objdump -dR test может быть поучительным. Кроме того, разве вам не нужен ret в определении foo? Кроме того, swapcontext имеет ненормальный поток управления, вам нужно позаботиться о его безопасном вызове.   -  person zwol    schedule 28.08.2019
comment
Похоже, вы OBJDUMP'ed объектный файл, который имеет перемещения. Попробуйте OBJDUMP загрузить окончательный исполняемый файл или OBJDUMP файл .o, используя параметр -r, чтобы показать записи о перемещении.   -  person Michael Petch    schedule 28.08.2019
comment
Пожалуйста, минимальный воспроизводимый пример. Это не воспроизводит поведение и не работает при запуске.   -  person S.S. Anne    schedule 29.08.2019
comment
... Что тогда # 200fd0 <swapcontext@GLIBC_2.2.5>?   -  person S.S. Anne    schedule 29.08.2019
comment
Я обновил исходный пример, чтобы сделать его действительным, используя put с аргументом, хранящимся в% rdi. Я также указал на сбой при запуске.   -  person cradical    schedule 29.08.2019
comment
Интересно - когда я добавляю «-no-pie» к аргументу компиляции, он работает нормально. Есть идеи, почему?   -  person cradical    schedule 29.08.2019


Ответы (2)


Для вашего обновленного совершенно отдельного вопроса, который заменил ваш вопрос о разборке .o:

частично связанные: Неожиданное значение локальной переменной указателя функции упоминает тот факт, что компоновщик преобразует ссылки на puts в puts@plt для вас в не-PIE (потому что это позволяет вам получить эффективный код при статическом связывании), но не в PIE.

libc отображается на расстоянии более 2 ГБ от основного исполняемого файла, поэтому call rel32 не может до него добраться.

См. Также Может » • вызвать стандартную библиотечную функцию C в 64-битном Linux из кода сборки (yasm), который показывает синтаксис AT&T и NASM для вызова функций libc из исполняемого файла PIE через стиль PLT call puts@plt или gcc -fno-plt с call *puts@gotpcrel(%rip).

person Peter Cordes    schedule 28.08.2019
comment
Спасибо за те ссылки, которые полностью и лаконично объяснили! - person cradical; 29.08.2019
comment
Что касается обновления исходного сообщения, я пытался создать действительный пример (в отличие от того, который у меня изначально вызывал контекст подкачки), и предоставить не только дизассемблированный вывод, но и возможный сбой, с которым я столкнулся с ним. Спасибо за ваше терпение! - person cradical; 29.08.2019

Кажется, вы разбираете объектный файл с перемещениями.

Перемещения - это заглушки, которые компоновщик должен разрешить при загрузке файла.

Чтобы правильно просмотреть перемещения и имена символов, используйте objdump -dr test или objdump -dR test.

Результат будет примерно таким:

0000000000000000 <foo>:
   0:   e8 00 00 00 00          callq  5 <foo+0x5>
                        1: R_X86_64_PLT32       swapcontext-0x4

Вы также можете рассмотреть возможность добавления инструкции ret в конец foo на всякий случай swapcontext ошибок.

Как показано в вашем выводе objdump -dR, оба они относятся к функциям libc:

            670: R_X86_64_PC32  swapcontext@GLIBC_2.2.5-0x4
        # 200fd0 <swapcontext@GLIBC_2.2.5>
person S.S. Anne    schedule 28.08.2019