Согласно документам:
Это дает указание компоновщику добавить все символы, не только используемые, в таблицу динамических символов.
Это не символы отладки, это символы динамического компоновщика.Они не удаляются strip
, поскольку это (в большинстве случаев) нарушает исполняемый файл - они используются компоновщиком среды выполнения для выполнения финальной стадии соединения вашего исполняемого файла.
Пример:
$ cat t.c
void foo() {}
int main() { foo(); return 0; }
Компиляция и связывание без -rdynamic
(и без оптимизации, очевидно)
$ gcc -O0 -o t t.c
$ readelf -s t
Symbol table '.dynsym' contains 3 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.2.5 (2)
2: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
Symbol table '.symtab' contains 50 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000400270 0 SECTION LOCAL DEFAULT 1
....
27: 0000000000000000 0 FILE LOCAL DEFAULT ABS t.c
28: 0000000000600e14 0 NOTYPE LOCAL DEFAULT 18 __init_array_end
29: 0000000000600e40 0 OBJECT LOCAL DEFAULT 21 _DYNAMIC
Таким образом, исполняемый файл имеет .symtab
со всем.Но обратите внимание, что .dynsym
вообще не упоминает foo
- там есть самое необходимое.Этой информации недостаточно для backtrace_symbols
для работы.Он использует информацию, представленную в этом разделе, для сопоставления адресов кодов с именами функций.
Теперь скомпилируйте с -rdynamic
:
$ gcc -O0 -o t t.c -rdynamic
$ readelf -s t
Symbol table '.dynsym' contains 17 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.2.5 (2)
2: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
3: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _Jv_RegisterClasses
4: 0000000000601018 0 NOTYPE GLOBAL DEFAULT ABS _edata
5: 0000000000601008 0 NOTYPE GLOBAL DEFAULT 24 __data_start
6: 0000000000400734 6 FUNC GLOBAL DEFAULT 13 foo
7: 0000000000601028 0 NOTYPE GLOBAL DEFAULT ABS _end
8: 0000000000601008 0 NOTYPE WEAK DEFAULT 24 data_start
9: 0000000000400838 4 OBJECT GLOBAL DEFAULT 15 _IO_stdin_used
10: 0000000000400750 136 FUNC GLOBAL DEFAULT 13 __libc_csu_init
11: 0000000000400650 0 FUNC GLOBAL DEFAULT 13 _start
12: 0000000000601018 0 NOTYPE GLOBAL DEFAULT ABS __bss_start
13: 000000000040073a 16 FUNC GLOBAL DEFAULT 13 main
14: 0000000000400618 0 FUNC GLOBAL DEFAULT 11 _init
15: 00000000004007e0 2 FUNC GLOBAL DEFAULT 13 __libc_csu_fini
16: 0000000000400828 0 FUNC GLOBAL DEFAULT 14 _fini
Symbol table '.symtab' contains 50 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000400270 0 SECTION LOCAL DEFAULT 1
....
27: 0000000000000000 0 FILE LOCAL DEFAULT ABS t.c
28: 0000000000600e14 0 NOTYPE LOCAL DEFAULT 18 __init_array_end
29: 0000000000600e40 0 OBJECT LOCAL DEFAULT 21 _DYNAMIC
То же самое для символов в .symtab
, но теперьУ foo
есть символ в секции динамических символов (и там теперь появляется куча других символов).Это заставляет backtrace_symbols
работать - теперь у него достаточно информации (в большинстве случаев) для сопоставления адресов кода с именами функций.
Обрезать, что:
$ strip --strip-all t
$ readelf -s t
Symbol table '.dynsym' contains 17 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.2.5 (2)
2: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
3: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _Jv_RegisterClasses
4: 0000000000601018 0 NOTYPE GLOBAL DEFAULT ABS _edata
5: 0000000000601008 0 NOTYPE GLOBAL DEFAULT 24 __data_start
6: 0000000000400734 6 FUNC GLOBAL DEFAULT 13 foo
7: 0000000000601028 0 NOTYPE GLOBAL DEFAULT ABS _end
8: 0000000000601008 0 NOTYPE WEAK DEFAULT 24 data_start
9: 0000000000400838 4 OBJECT GLOBAL DEFAULT 15 _IO_stdin_used
10: 0000000000400750 136 FUNC GLOBAL DEFAULT 13 __libc_csu_init
11: 0000000000400650 0 FUNC GLOBAL DEFAULT 13 _start
12: 0000000000601018 0 NOTYPE GLOBAL DEFAULT ABS __bss_start
13: 000000000040073a 16 FUNC GLOBAL DEFAULT 13 main
14: 0000000000400618 0 FUNC GLOBAL DEFAULT 11 _init
15: 00000000004007e0 2 FUNC GLOBAL DEFAULT 13 __libc_csu_fini
16: 0000000000400828 0 FUNC GLOBAL DEFAULT 14 _fini
$ ./t
$
Нет .symtab
пропало,но таблица динамических символов все еще там, и исполняемый файл запускается.Так что backtrace_symbols
все еще работает.
Уберите динамическую таблицу символов:
$ strip -R .dynsym t
$ ./t
./t: relocation error: ./t: symbol , version GLIBC_2.2.5 not defined in file libc.so.6 with link time reference
... и вы получите испорченный исполняемый файл.
Интересное прочтение того, что.symtab
и .dynsym
используются здесь: Внутри таблиц символов ELF .Следует отметить, что .symtab
не требуется во время выполнения, поэтому он отбрасывается загрузчиком.Этот раздел не остается в памяти процесса..dynsym
, с другой стороны, - это , необходимый во время выполнения, поэтому он сохраняется в образе процесса.Таким образом, такие вещи, как backtrace_symbols
, могут собирать информацию о текущем процессе изнутри себя.
Короче говоря:
- динамические символы не удаляются
strip
, посколькучто сделает исполняемый файл не загружаемым backtrace_symbols
нужны динамические символы, чтобы выяснить, к какому коду относится какая функция backtrace_symbols
не использует символы отладки
Отсюда и поведение, которое вы заметили.
Для ваших конкретных вопросов:
gdb
- это отладчик.Он использует отладочную информацию в исполняемом файле и библиотеках для отображения соответствующей информации.Он намного более сложен, чем backtrace_symbols
, и проверяет фактические файлы на вашем диске в дополнение к оперативному процессу.backtrace_symbols
нет, он полностью находится в процессе - поэтому он не может получить доступ к разделам, которые не загружены в исполняемый образ.Разделы отладки не загружаются в образ среды выполнения, поэтому он не может их использовать. .dynsym
не является разделом отладки.Это раздел, используемый динамическим компоновщиком..symbtab
также не является разделом отладки, но может использоваться отладчиком, имеющим доступ к исполняемым (и библиотечным) файлам.-rdynamic
не не создает разделы отладки, только эту расширенную динамическую таблицу символов.Увеличение размера исполняемого файла от -rdynamic
полностью зависит от количества символов в этом исполняемом файле (а также от соображений выравнивания / заполнения).Оно должно быть значительно меньше, чем -g
. - За исключением статически связанных двоичных файлов, исполняемым файлам необходимо разрешать внешние зависимости во время загрузки.Например, связывание
printf
и некоторые процедуры запуска приложения из библиотеки C.Эти внешние символы должны быть указаны где-то в исполняемом файле: для этого используется .dynsym
, и поэтому у exe есть .dynsym
, даже если вы не указали -rdynamic
.Когда вы указываете это, компоновщик добавляет другие символы, которые не нужны для работы процесса, но могут использоваться такими вещами, как backtrace_symbols
. backtrace_symbols
не будет разрешать имена функций, если вы статическиссылка на сайт.Даже если вы укажете -rdynamic
, секция .dynsym
не будет отправлена в исполняемый файл.Таблицы символов не загружаются в исполняемый образ, поэтому backtrace_symbols
не может сопоставить адреса кода с символами.