Как получить указатели и размеры переменных из компилятора - извне скомпилированного кода? - PullRequest
0 голосов
/ 01 июля 2010

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

Возможно ли это? Есть ли способ сделать это в любом компиляторе c?

Ответы [ 4 ]

3 голосов
/ 01 июля 2010

Что-то вроде файла карты?Это покажет, где расположены глобалы и статика, но не то, на что они указывают.Большинство компиляторов (компоновщиков) будут выводить один автоматически или с простым оператором.Просто найдите файл карты в вашей документации.

1 голос
/ 01 июля 2010

Эта информация доступна в таблице символов двоичного файла, хотя она может не означать того, чего вы ожидаете.

Компилятор берет один или несколько исходных файлов, компилирует код в объектный код и генерируетобъектный файл (.o в Unix, .obj в Windows).Все переменные и функции, на которые есть ссылки в исходном файле, упоминаются в таблице символов.Переменные и функции, определенные в исходном файле, имеют определенные адреса и размеры, в то время как символы, не определенные в исходном файле, помечаются как неопределенные и должны быть связаны позже.Все символы перечислены относительно определенного раздела.Общими разделами являются «.text» для исполняемого кода, «.bss» для переменных, которые инициализируются нулями при запуске программы, и «.data» для переменных, инициализированных ненулевыми значениями.

Компоновщик принимаетодин или несколько объектных файлов, объединяет разделы (помещая весь код и данные из каждого объектного файла в один большой раздел для кода и данных) и записывает выходной файл.Этот выходной файл может быть исполняемым или общей библиотекой.Исполняемый файл на диске все еще не имеет указателя для каждой переменной;он по-прежнему сохраняет смещение от начала раздела к переменной.

При запуске исполняемого файла динамический загрузчик операционной системы считывает исполняемый файл, находит каждый раздел и выделяет память для этого раздела.(Он также может устанавливать различные разрешения для каждого раздела - сегмент «.text» часто помечается как доступный только для чтения, и (на процессорах, которые его поддерживают) сегменты данных иногда помечаются как неисполняемые.) Только тогдапеременная get указатель - когда код должен получить доступ к определенной переменной, он добавляет адрес начала раздела к смещению от начала раздела, чтобы получить указатель.

Вы можете использовать различныеинструменты для исследования таблицы символов каждого двоичного файла.GNU toolchain objdump (используется в Linux) является одним из таких инструментов.

Для простой программы hello-world на C:

#include <stdio.h>

const char message[] = "Hello world!\n";

int main(int argc, char ** argv) {
        printf(message);
        return 0;
}

Я ее компилирую (но не связываю)в моем окне Linux:

$ gcc -c hello.c -o hello.o

Теперь я могу посмотреть на таблицу символов:

$ objdump -t hello.o
hello.o:     file format elf32-i386

SYMBOL TABLE:
00000000 l    df *ABS*  00000000 hello.c
00000000 l    d  .text  00000000 .text
00000000 l    d  .data  00000000 .data
00000000 l    d  .bss   00000000 .bss
00000000 l    d  .rodata        00000000 .rodata
00000000 l    d  .note.GNU-stack        00000000 .note.GNU-stack
00000000 l    d  .comment       00000000 .comment
00000000 g     O .rodata        0000000e message
00000000 g     F .text  0000002b main
00000000         *UND*  00000000 puts

Первый столбец - это адрес каждого символа относительно начала раздела.Каждый символ имеет различные флаги, и некоторые символы используются в качестве подсказок для остальной части цепочки инструментов и отладчика.(Если бы я создавал символы отладки, я бы также увидел много записей, посвященных им.) Моя простая программа имеет только одну переменную:

00000000 g     O .rodata        0000000e message

В пятом столбце указано, что символ message - это размер0xe - 14 байтов.

1 голос
/ 01 июля 2010

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

1 голос
/ 01 июля 2010

Хотя для вывода этих данных не требуется компилятор, большинство компоновщиков могут выгружать эту информацию. Например, компоновочный файл-файл Microsoft содержит все общедоступные символы в исполняемом файле / dll, а также их адрес относительно раздела (только чтение, чтение-запись, код, инициализация нуля и т. Д.), В который они вставлены. Размеры могут быть получены это, хотя это в основном приближение.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...