objcopy удаляет раздел, если я не объявил статическую переменную volatile в этом разделе (используя атрибут) - PullRequest
0 голосов
/ 22 февраля 2019

У меня есть скрипт компоновщика, в котором я определил раздел для хранения контрольной суммы образа программного обеспечения.Что-то вроде:

...
.my_checksum :
  {
    __checksum_is_here = .;
    KEEP (*(.my_checksum))
    . = ALIGN(4);
    _sw_image_code_end = .;  
  } > IMAGE
...

Контрольная сумма помещается в этот раздел с помощью objcopy --update-section.

Я создаю файл elf с помощью компилятора arm gcc, и я вижуэтот раздел и его значение в нем:

> arm-none-eabu-objdumph -h my_elf_file.elf
...
0 .text         0001496c  08010000  08010000  00010000  2**4
...
7 .my_checksum     00000004  080250c0  080250c0  000350c0  2**2
...

// Notice that 000350c0 is the file offset and 080250c0 is the LMA.
// The starting LMA is 08010000

И я могу получить его значение:

> xxd -s 0x000350c0 -l 4 my_elf_file.elf
000350c0: 015e 028e // I have checked this value and it is correct.

Теперь я генерирую bin файл, выполнив

> arm-none-eabi-objcopy -O binary --gap-fill 0xFF -S my_elf_file.elf my_elf_file.bin

Теперь, если я попытаюсь снова прочитать значение контрольной суммы, используя разницу между контрольной суммой LMA и первым разделом LMA (см. Выше):

> xxd -s 0x150c0 -l 4 my_elf_file.bin

Полученный здесь результат отличается отполученный в файле elf, то есть раздел контрольной суммы был удален с помощью objcopy.(Это то, что я думаю, по крайней мере).

Тем не менее, если я определю это в моем main.c файле:

static volatile unsigned int __aux_checksum __attribute__((section(".my_checksum")));
...
int main() {
  ...
  ((void)__aux_checksum); // Avoid compiler/linker optimizations.
  ...
}

Теперь, если я повторю те же шаги, что и выше, с *Файлы 1028 * и bin (используя правильные смещения), я могу получить контрольную сумму из файла bin (elf и bin дают тот же результат).

Вопросы

Мой первый вопрос: Я знаю, что вы можете определить раздел, используя __attribute__((section)), но если вы используете раздел, уже определенный в скрипте компоновщика, эта команда изменит свое поведение для помещения переменной враздел вместо создания нового?

Мой второй вопрос: Это единственный способ предотвратить objcopy удаление этого конкретного раздела?

1 Ответ

0 голосов
/ 22 февраля 2019

Давайте сначала ответим на ваш 2-й вопрос,

Является ли это единственным способом предотвращения удаления данного конкретного раздела?

Вам нужна концепция, описанная в GNU LD manual в разделе РАЗДЕЛЫ .


4.6.8.1.Тип секции вывода

Каждая секция вывода может иметь тип.Тип является ключевым словом в скобках.Определены следующие типы:

NOLOAD

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

DSECT, COPY, INFO, OVERLAY

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

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

SECTIONS {
  ROM 0 (NOLOAD) : { … }
  …
}

Так что это значит?Скажем, у вас есть отладочная информация в ваших объектах.Если вы записываете образ ROM, вы, вероятно, не хотите помещать отладочную информацию в объект.Кроме того, сегмент BSS равен нулю, и нет необходимости сохранять его в ПЗУ, но вам нужно очистить нашу ОЗУ (по адресу загрузки), чтобы освободить ее.'Значение инициализации' для секции .data инициализируется из ПЗУ, но находится в ОЗУ.Концепции являются «загружаемыми» и «выделяемыми», и для них есть флаги в файле ELF.По умолчанию ваш .my_checksum не получает флагов.Т.е. не распределяется и не загружается, как отладочная информация.

Я знаю, что вы можете определить раздел, используя attribute ((section)), но если вы используете уже определенный разделВ скрипте компоновщика эта команда изменяет свое поведение для размещения переменной в разделе вместо создания новой?

Исходя из вышесказанного,

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

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

Я бы посоветовал вам просто поставить контрольную сумму в конце либо .text, либо .data.Например, входные разделы .rodata (постоянные значения) обычно помещаются с выводом .text.Обычно нет необходимости изобретать другие выходные разделы, если вы не хотите вести бухгалтерский учет, который не дойдет до окончательного изображения.Ваша метка __checksum_is_here достаточна, чтобы найти ее, и вы можете посмотреть этот вопрос на CRC.

...