Условия, при которых переход в общую библиотеку должен работать в 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?
Ответы
Ответ 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.