Вы смотрите на перемещения, , а не символы. Перемещения - это то, что генерирует ассемблер, когда хочет обратиться к символу, значение которого неизвестно;это инструкция для компоновщика, чтобы заполнить правильное значение во время ссылки.Перемещения не являются типами символов;на каждый символ можно ссылаться через произвольное количество перемещений произвольного типа.Также обратите внимание, что таблица символов не знает, к какому типу данных относится символ, если вообще существует.Символ - это просто адрес и имя.
Тип перемещения R_386_32
просто означает «вставьте здесь значение символа как 32-битное». Невозможно сказать, используется ли символ для данных.или текст.Это используется, например, если вы загружаете адрес символа или выполняете абсолютный доступ к памяти.Обе эти инструкции генерируют перемещение R_386_32
:
mov $foo, %eax # move value of symbol to register
mov foo, %eax # perform absolute memory access
С другой стороны, тип перемещения R_386_PC32
вычитает значение указателя инструкции ( p rogram c Унтер) от символа и вставляет его.Этот тип перемещения в основном используется для прямого перехода и инструкций вызова:
jmp foo # jump to foo
call foo # call foo
В общем, нет способа угадать, в каком разделе определен символ, по просмотру перемещений.Действительно, перемещения вообще не дают никакой информации об этом, и объектный файл не может требовать, чтобы внешний символ ссылался на данные или текст.Для определенных символов вы можете узнать, в каком разделе они находятся, запустив утилиту nm
.Символы, отмеченные t
или T
, представляют собой текст, d
или D
представляют собой данные, r
или R
представляют собой данные только для чтения, а b
или B
представляют собой BSS.
На ваш второй вопрос: да, вы можете.Используйте код C, как это, чтобы напечатать значение _Jv_RegisterClasses
.Обратите внимание, что значение символа является адресом переменной, к которой он относится.
extern const void _Jv_RegisterClasses; /* or any other type */
printf("%p\n", &_Jv_RegisterClasses); /* print value of symbol */