Если вы посмотрите на другие символы, вы можете найти индекс (или название раздела, если читатель выполняет сопоставление для вас) вместо *ABS*
. Это индекс раздела в таблице заголовков разделов. Он указывает на заголовок раздела, в котором определен символ (или SHN_UNDEF
(ноль), если он не определен в объекте, который вы просматриваете). Таким образом, значение (виртуальный адрес) символа будет корректироваться на то же значение, что его содержащий раздел корректируется во время загрузки. (Этот процесс называется перемещение .) Не так для абсолютных символов (имеющих специальное значение SHN_ABS
в качестве их st_shndx
). Абсолютные символы не перемещаются, их виртуальные адреса (0000000000000000
в приведенном вами примере) являются фиксированными.
Такие абсолютные символы иногда используются для хранения некоторой метаинформации. В частности, компилятор может создавать символы с именами символов, эквивалентными именам единиц перевода, которые он компилирует. Такие символы не нужны для связывания или запуска программы, они предназначены только для людей и инструментов двоичной обработки.
Что касается вашего вопроса с той причиной, по которой он не хранится в разделе .debug_info
(и почему эта информация выводится, даже если не были указаны переключатели отладки), ответ заключается в том, что это отдельная вещь; это просто таблица символов (.symtab
). Конечно, он также необходим для отладки, но его основная цель - связать файлы объектов (.o
). По умолчанию он сохраняется в связанных исполняемых файлах / библиотеках. Вы можете избавиться от него с помощью strip
.
Многое из того, что я написал здесь, находится в man 5 elf
.
Я не думаю, что выполнение того, что вы делаете (с --defsym
), поддерживается / должно работать с динамическим связыванием. Глядя на вывод компилятора (gcc -S -masm=intel
), я вижу это
lea rsi, foo[rip]
Или, если мы посмотрим на objdump -M intel -rD a.out
(связь с -q
для сохранения перемещений), мы увидим то же самое: rip
-относительная адресация используется для получения адреса foo
.
113d: 48 8d 35 ab ad 00 00 lea rsi,[rip+0xadab] # beef <foo>
1140: R_X86_64_PC32 foo-0x4
Компилятор не знает, что это будет абсолютный символ, поэтому он генерирует код, который он делает (как для обычного символа). rip
- указатель инструкции, поэтому он зависит от базового адреса сегмента, содержащего .text
после того, как программа отображается в память с помощью ld.so
.
Я нашел этот ответ , проливающий свет на правильный вариант использования абсолютных символов.