Вопрос по macos, unix, c++, linker – Смещение в значении символа в нм?

7

Просто чтобы дать вам некоторый контекст, вот что я пытаюсь достичь: Я встраиваю const char * в общий объектный файл, чтобы иметь строку версии в самом файле .so. Я делаю анализ данных, и эта строка позволяет мне узнать, какая версия программного обеспечения произвела его. Это все отлично работает.

У меня возникает проблема, когда я пытаюсь прочитать строку непосредственно из библиотеки .so. Я пытался использовать

<code>nm libSMPselection.so | grep _version_info
</code>

и получить

<code>000000000003d968 D __SMPselection_version_info
</code>

это все нормально и, как и ожидалось (char * называется _SMPselection_version_info). Однако я ожидал, что теперь смогу открыть файл, найти 0x3d968 и начать читать мою строку, но все, что я получаю, это мусор.

Когда я открываю файл .so и просто ищу содержимое строки (я знаю, как он начинается), я могу найти его по адресу 0x2e0b4. По этому адресу он нулевой, и, как и ожидалось, завершен. (Я использую этот метод сейчас.)

Я не информатик. Может ли кто-нибудь объяснить мне, почему значение символа, отображаемое с помощью nm, не является правильным или по-другому, каково значение символа, если оно не является адресом символа?

(Кстати, я работаю на Mac с OSX 10.7)

Ваш Ответ

4   ответа
2

создать двоичный файл, который динамически загружает вашу библиотеку (дает ей имя в командной строке) и выполняет dlsym () для вашего символа (или он также может получить это в командной строке), приводить его к строковому указателю и печатает его на стандартный вывод.

Error: User Rate Limit Exceeded Simon
Error: User Rate Limit Exceeded Simon
1

Почему вы ожидаете смещение, отображаемоеnm быть смещением в .so файл?.so файлы не просто образы памяти; они содержат много другой информации, а также более или менее сложный формат. В Unix (по крайней мере, в большинстве Unices) общие объекты используют Эльфийский формат. Чтобы найти информацию, вам придется интерпретировать различные поля в файле, чтобы найти, где находится символ, который вы хотите находится, в каком сегменте и где этот сегмент начинается в файле. (Вы, вероятно, можете найти библиотеку, которая упростит их чтение.)

Кроме того, если вы правильно сказали, что вы ввелиchar const*, i.e. that your code contained something like:

char const* version = "...";

тогда адрес или смещениеversion адрес или смещение указатель, а не строковые данные, на которые он указывает. Определяя это как:

char const version[] = "...";

решит это.

Наконец, самое простое решение - просто убедиться, что строка имеет какой-то хорошо идентифицируемый шаблон и сканирует весь файл линейно ищем эту схему.

Error: User Rate Limit ExceededisError: User Rate Limit Exceededextern char const version[] = "..."Error: User Rate Limit ExceededexternError: User Rate Limit Exceeded
Error: User Rate Limit Exceeded Simon
Error: User Rate Limit ExceededexternError: User Rate Limit ExceedednmError: User Rate Limit Exceedednm! Simon
7

что это ELF или двоичный файл с аналогичной структурой, вы должны принять во внимание адрес, куда загружается материал, на который влияют вещи в заголовке ELF.

С помощьюobjdump -Fd в вашем двоичном файле дизассемблер также может показывать точное смещение файла символа.

С помощьюobjdump -x Вы можете найти этот адрес загрузчика, обычно 0x400000 для стандартных исполняемых файлов Linux.

Следующее, с чем вы должны быть осторожны, это посмотреть, является ли это косвенной строкой, это проще всего сделать, используяobjdump -g, Когда строка найдена как косвенная строка, в позиции, выведеннойobjdump -Fd Вы не найдете строку, но адрес. Из этого вам нужно снова вычесть адрес загрузчика. Позвольте мне показать вам пример для одного из моих двоичных файлов:

objdump -Fd BIN | grep VersionString
  45152f:       48 8b 1d 9a df 87 00    mov    0x87df9a(%rip),%rbx        # ccf4d0 <acVersionString> (File Offset: 0x8cf4d0)

objdump -x BIN
...
LOAD off    0x0000000000000000 vaddr 0x0000000000400000 paddr 0x0000000000400000 align 2**12
...

Итак, мы смотрим на 0x8cf4d0 в файле и находим в hexeditor:

008C:F4D0 D8 C1 89 00  00 00 00 00  01 00 00 00  FF FF FF FF

Таким образом, мы берем 0x89C1D8, вычитаем 0x400000 и имеем 0x49c1d8, и когда мы смотрим туда в гекседиторе, мы находим:

0049:C1D0 FF FF 7F 7F  FF FF 7F FF  74 72 75 6E  6B 5F 38 30
0049:C1E0 34 33 00 00  00 00 00 00  00 00 00 00  00 00 00 00

Что означает «хобот_8043».

YMMV, особенно когда это какой-то другой формат файла, но это общий способ структурирования этих вещей, с множеством бородавок и деталей, которые отличаются для особых случаев.

Error: User Rate Limit Exceeded Simon
Error: User Rate Limit Exceeded0x400000Error: User Rate Limit Exceeded0xccf4d0Error: User Rate Limit Exceeded
1

которая поможет вам извлечь строки из двоичных файлов.

http://linux.about.com/library/cmd/blcmdl1_strings.htm

В HPUX (и я думаю, что и в других версиях Unix) есть аналогичная команда под названием «what». Он извлекает только те строки, которые начинаются с «@ (#)», но если вы контролируете содержимое строки, это не проблема.

Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded Simon

Похожие вопросы