Подтвердить что ты не робот

Условия, при которых переход в общую библиотеку должен работать в gdb?

Есть много вопросов, связанных с конкретными ошибками, почему вхождение в общую библиотеку с gdb не работает. Ни один из них не дает систематического ответа о том, как подтвердить, где причина. Эти вопросы касаются способов диагностики установки.

Пример установки

main.c

#include <stdio.h>
#include "myshared.h"

int main(void)
{
    int a = 3;
    print_from_lib();
    return 0;
}

myshared.h

void print_from_lib();

myshared.c

#include <stdio.h>

void print_from_lib()
{
    printf("Printed from shared library\n");
}

Поместите все файлы в один каталог.

export LIBRARY_PATH=$PWD:$LIBRARY_PATH
export LD_LIBRARY_PATH=$PWD:$LD_LIBRARY_PATH
gcc -ggdb -c -Wall -Werror -fpic myshared.c -o myshared-ggdb.o
gcc -ggdb -shared -o libmyshared-ggdb.so myshared-ggdb.o
gcc -ggdb main.c -lmyshared-ggdb -o app-ggdb

Получение ошибки

$ gdb ./app-ggdb 
GNU gdb (Ubuntu 7.12.50.20170314-0ubuntu1) 7.12.50.20170314-git
...### GDB STARTING TEXT
Reading symbols from app-ggdb...done.
(gdb) break 7
Breakpoint 1 at 0x78f: file main.c, line 7.
(gdb) run
Starting program: /home/user/share-lib-example/app-ggdb 

Breakpoint 1, main () at main.c:7
7       print_from_lib();
(gdb) s
Printed from shared library
8       return 0;

gdb не входит в функцию

Необходимые, но не достаточные проверки

Отладка символов в двоичных файлах

$ objdump --syms libmyshared-ggdb.so | grep debug
0000000000000000 l    d  .debug_aranges 0000000000000000              .debug_aranges
0000000000000000 l    d  .debug_info    0000000000000000              .debug_info
0000000000000000 l    d  .debug_abbrev  0000000000000000              .debug_abbrev
0000000000000000 l    d  .debug_line    0000000000000000              .debug_line
0000000000000000 l    d  .debug_str     0000000000000000              .debug_str

Символы, распознанные gdb

$ gdb ./app-ggdb
...### GDB STARTING TEXT
Reading symbols from app-ggdb...done.
(gdb) break 7
Breakpoint 1 at 0x78f: file main.c, line 7.
(gdb) run
Starting program: /home/user/share-lib-example/app-ggdb 

Breakpoint 1, main () at main.c:7
7       print_from_lib();
(gdb)(gdb) info sharedlibrary
From                To                  Syms Read   Shared Object Library
0x00007ffff7dd7aa0  0x00007ffff7df55c0  Yes         /lib64/ld-linux-x86-64.so.2
0x00007ffff7bd5580  0x00007ffff7bd5693  Yes         /home/user/share-lib-example/libmyshared-ggdb.so
0x00007ffff782d9c0  0x00007ffff797ed43  Yes         /lib/x86_64-linux-gnu/libc.so.6

Подтвердить .gdbinit не является причиной

~/.gdbinit содержит команды, автоматически выполняемые при запуске gdb. ref.

Запуск gdb с флагами -nx может исключить .gdbinit в качестве источника проблемы.

Вопрос

Ищем предложения для заполнения списка Necessary but not sufficient checks.

Текущая проблема [Обновление от Mark Plotnick]

Эта ошибка шага воспроизводится на Ubuntu 17.04 amd64 с 64- и 32-разрядным исполняемым файлом и библиотекой.

Ошибка не воспроизводится на Ubuntu 17.04 i386. (gcc 6.3.0-12ubuntu2, gdb 7.12.50 и 8.0, no.gdbinit.).

Возможно, актуально: gcc 17.04 amd64 был создан (от Canonical) для генерации исполняемых файлов pie по умолчанию.

Вопрос

Могут ли флаги, с которыми была построена gcc, вмешиваться в отладку? Как вы можете определить, является ли причиной вашего gcc?

4b9b3361

Ответ 1

Ваша проблема связана с самим собой: не делайте этого: set step-mode on и step будут работать так, как вы ожидаете.

Из руководства GDB :

set step-mode
set step-mode on
The set step-mode on command causes the step command to stop at the first
instruction of a function which contains no debug line information
rather than stepping over it.

This is useful in cases where you may be interested in inspecting the machine
instructions of a function which has no symbolic info and do not want
GDB to automatically skip over this function.

Вы заинтересованы в обратном вышесказанном - вы хотите войти в функцию print_from_lib и не останавливаться внутри PLT-перехода и функции разрешения символа динамического загрузчика.

Ответ 2

GDB 7.11 не может воспроизвести эту проблему. Это мои шаги. Надеюсь, это поможет вам:

1.gcc -ggdb -c -Wall -Werror -fpic myshared.c -o myshared-ggdb.o
2.gcc -ggdb -shared -o libmyshared-ggdb.so myshared-ggdb.o
3.gcc -ggdb main.c -lmyshared-ggdb -o app-ggdb -L.
4.gdb ./app-ggdb

В GDB

(gdb) set env LD_LIBRARY_PATH=.
(gdb) b main.c:7
Breakpoint 1 at 0x4006a5: file main.c, line 7.
(gdb) r
Starting program: /home/haolee/tmp/app-ggdb 

Breakpoint 1, main () at main.c:7
7       print_from_lib();
(gdb) s
print_from_lib () at myshared.c:5
5       printf("Printed from shared library\n");
(gdb) 

Я успешно вхожу в функцию print_from_lib.

Ответ 3

Еще несколько тестов, которые вы можете сделать для встроенной общей библиотеки:

  • file libmyshared-ggdb.so должен сообщить, что библиотека имеет отладочную информацию и не лишена.
  • nm libmyshared-ggdb.so | grep print_from_lib должен найти символ для функции print_from_lib.

Если все вышеперечисленные тесты прошли, попробуйте загрузить библиотеку непосредственно в gdb и найдите функцию:

gdb libmyshared-ggdb.so
(gdb) info functions print_from_lib

Имя функции print_from_lib должно быть напечатано. Если нет, что-то не так с gdb или gcc.