Как я могу извлечь адреса констант, добавленные оптимизацией компилятора, из файла ELF?

Я пишу инструмент анализа размера кода для моей программы на C, используя выходной ELF файл.

Я использую readelf -debug-dump=info для создания Dwarf format file.

Я заметил, что Мой компилятор добавляет как часть оптимизации новые константы, которых нет в файле Dwarf, в раздел .rodata.

Итак, .rodata размер раздела включает их размеры, но у меня нет их размеров в Dwarf.

Вот пример файла карты:

*(.rodata)
 .rodata        0x10010000       0xc0 /<.o file0 path>
                0x10010000                const1
                0x10010040                const2

 .rodata        0x100100c0        0xa /<.o file1 path>

  fill         0x100100ca        0x6 

 .rodata        0x100100d0       0x6c /<.o file2 path>
                0x100100d0                const3
                0x100100e0                const4
                0x10010100                const5
                0x10010120                const6

    fill        0x1001013c        0x4 

В файле file1 выше, хотя я не объявлял переменную const - это делает компилятор, эта константа занимает место в .rodata, но для нее нет символа / имени.

Вот код внутри некоторой функции, которая его генерирует:

uint8 arr[3][2] = {{146,179},
                   {133, 166},
                   {108, 141}} ;

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

Как я могу извлечь эти скрытые дополнения из разделов данных?

Я хочу иметь возможность полностью охарактеризовать свой код - сколько места используется в каждом файле и т. Д.


person ramsis    schedule 22.03.2018    source источник
comment
Неясно, о чем вы имеете в виду, и, возможно, ваше предположение об этих константах ошибочно. Это определенно проблема XY. Включите в свой вопрос свои доказательства или то, что вы видите, и спросите, что это такое, вместо того, чтобы спрашивать, как вы можете увидеть скрытые данные - которых бритва Оккама предполагает, что на самом деле не существует. Более вероятно, что ваша интерпретация доказательств неверна.   -  person Clifford    schedule 22.03.2018
comment
Конечно, добавили пример.   -  person ramsis    schedule 23.03.2018
comment
Возможно, также код, который это сгенерировал? Возможно, они не просто постоянные инициализаторы для объявленных данных чтения / записи?   -  person Clifford    schedule 23.03.2018
comment
Добавлен пример кода!   -  person ramsis    schedule 24.03.2018
comment
Я хотел бы извлечь эти размеры дополнений компилятора в память.   -  person ramsis    schedule 24.03.2018
comment
Вы не помогаете - создайте маленький пример, опубликуйте весь код, затем опубликуйте содержимое файла карты, связанное с этим кодом. Невозможно связать предоставленный вами фрагмент с ранее опубликованным файлом карты. Более того, пока я не добавил ;, это был даже недопустимый код, поэтому я не уверен, что этот код имеет какое-либо отношение к файлу карты, поскольку он не будет компилироваться.   -  person Clifford    schedule 24.03.2018
comment
Кроме того, фрагмент кода не разъясняет область действия arr - это повлияет на то, как и когда происходит инициализация и как ведут себя компилятор и компоновщик - контекст - это все - вы предоставили небольшой контекст. Также избегайте публикации кода и текста с посторонним пустым пространством и жесткими вкладками - он плохо отображается на SO, и действительно использует разметку кода. Я исправил для вас _все_ ошибки разметки.   -  person Clifford    schedule 24.03.2018


Ответы (2)


Я предполагаю, что это будет зависеть от компоновщика, но когда у вас есть такой код, как:

uint8 arr[3][2] = {{146,179},
                   {133, 166},
                   {108, 141}} ;

arr во время выполнения существует в памяти чтения / записи, но его инициализатор будет находиться в памяти чтения / записи, чтобы быть скопированным в память чтения / записи при инициализации массива. Компоновщику нужно только предоставить адрес, потому что размер будет известен локально как константа времени компиляции, встроенная как литерал в инициализирующий код. Следовательно, информация о размере не отображается на карте, потому что компоновщик отбрасывает эту информацию.

Однако длина неявно определяется адресом смежных объектов для заполненного пространства. Так например:

Размер const1, например, равен const2 - const1, а для const6 это 0x1001013c - const6.

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

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

person Clifford    schedule 24.03.2018

чтобы получить размер файла elf в деталях, используйте

"Вы можете использовать нм и размер, чтобы получить размер функций и секций ELF.

Чтобы получить размер функций (и объектов со статической продолжительностью хранения):

$ nm --print-size --size-sort --radix = d tst.o Во втором столбце отображается десятичный размер функции и объектов.

Чтобы получить размер разделов:

$ size -A -d tst.o Во втором столбце отображается десятичный размер разделов. "

Инструмент для анализа размера разделов и символа ELF

person Ahmed Bakoush    schedule 22.03.2018