Попытка загрузить независимый от позиции код на cortex-m3

У меня есть встроенное приложение, в котором будет загрузчик, который решит запустить одно из двух приложений непосредственно из внутренней флэш-памяти. Я пытаюсь сделать эти приложения независимыми от позиции, чтобы их можно было скомпилировать для одного и того же базового адреса. Операционная система отсутствует, поэтому динамический компоновщик недоступен. До сих пор я пытался построить с параметром -fpie (используя gcc) без особого успеха. Вызовы функций кажутся правильными, но глобальные данные не имеют правильного адреса. Локально определенные глобальные данные, по-видимому, имеют адрес, смещенный на величину, на которую приложение смещено от своего исходного базового адреса. Глобальные данные, которые объявлены в других файлах, имеют совершенно неправильный адрес (и если я создам с -fpic, то и локально объявленные глобальные данные, и глобальные данные в других файлах будут совершенно неправильными). Я подозреваю, что мне нужно выполнить некоторые манипуляции с разделом GOT при запуске моего приложения, но я не уверен.


person Dan    schedule 17.02.2011    source источник


Ответы (2)


Наконец-то я заработал. Похоже, мне нужно сделать следующее: Весь код должен соответствовать -fpic (ранее я пробовал -fpie)

Также мне потребовалась модификация скрипта компоновщика. Я принудительно вставил GOT в раздел sram, и он был расположен после динамического раздела, который был во флэш-памяти. Похоже, все работает правильно, если раздел GOT расположен перед динамическим разделом во флэш-памяти. Не уверен, почему это имеет значение, но, похоже, все исправлено - до этого казалось, что код не нашел GOT должным образом, поскольку в GOT были сохранены правильные значения, но адреса всех моих переменных были неправильными.

person Dan    schedule 22.02.2011
comment
Не могли бы вы подробнее описать, что вы делаете со сценарием компоновщика? Я сталкиваюсь с той же проблемой прямо сейчас - person VIPPER; 01.06.2018

Код PIE (и PIC) нуждается в процессе перемещения после загрузки по какому-то адресу (отличному от адреса по умолчанию) и до того, как он будет запущен. Я предлагаю вам ознакомиться с кодом ld.so. Кроме того, вы должны проверить таблицу перемещений в вашем двоичном файле (например, используя readelf -r).

Вот хорошая презентация по PIE (она про OpenBSD, но процесс такой же). http://www.openbsd.org/papers/nycbsdcon08-pie/ или http://www.dcbsdcon.org/speakers/slides/miller_dcbsdcon2009.pdf

Я думаю, вам нужно не только изменить GOT, но и найти все Relocations и сделать их.

По сути, обработка бинарника PIE с помощью ld.so почти не отличается от обработки динамической библиотеки с помощью PIC, только с перемещением не библиотеки, а самого исполняемого образа.

«Неправильные адреса», которые вы видите, - это место, где фактическое значение будет записано при решении проблемы перемещения. Что касается i386, http://books.google.com/books?id=Id9cYsIdjIwC&pg=PA174 есть релокации:

  • R_386_GOTPC
  • R_386_GOT32
  • R_386_GOTOFF
  • R_386_ОТНОСИТЕЛЬНЫЙ

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

Пример Readelf -r:

Динамически связанный

$ readelf -r fdyn

Relocation section '.rel.dyn' at offset 0x27c contains 1 entries:
 Offset     Info    Type            Sym.Value  Sym. Name
08049ff0  00000106 R_386_GLOB_DAT    00000000   __gmon_start__

Relocation section '.rel.plt' at offset 0x284 contains 2 entries:
 Offset     Info    Type            Sym.Value  Sym. Name
0804a000  00000107 R_386_JUMP_SLOT   00000000   __gmon_start__
0804a004  00000207 R_386_JUMP_SLOT   00000000   __libc_start_main

ПИРОГ:

$ readelf -r fPIE

Relocation section '.rel.dyn' at offset 0x388 contains 6 entries:
 Offset     Info    Type            Sym.Value  Sym. Name
00001fe8  00000008 R_386_RELATIVE
00001ff0  00000008 R_386_RELATIVE
00002010  00000008 R_386_RELATIVE
00001fe0  00000106 R_386_GLOB_DAT    00000000   __gmon_start__
00001fe4  00000206 R_386_GLOB_DAT    00000000   _Jv_RegisterClasses
00001fec  00000406 R_386_GLOB_DAT    00000000   __cxa_finalize

Relocation section '.rel.plt' at offset 0x3b8 contains 3 entries:
 Offset     Info    Type            Sym.Value  Sym. Name
00002000  00000107 R_386_JUMP_SLOT   00000000   __gmon_start__
00002004  00000307 R_386_JUMP_SLOT   00000000   __libc_start_main
00002008  00000407 R_386_JUMP_SLOT   00000000   __cxa_finalize
person osgx    schedule 17.02.2011
comment
Если я связываюсь с параметрами -pie и -q, компоновщик создает раздел .rel.dyn, но я не уверен, как его анализировать. Кроме того, согласно readelf, есть раздел .rel.text (даже если -pie не указан), но он не отображается в файле карты. Вот (укороченный) снимок экрана readelf -r: Раздел перемещения '.rel.dyn' по смещению 0x8818 содержит 78 записей: Offset Info Type Sym. Значение Имя символа 00000018 00000017 R_ARM_RELATIVE 0000001c 00000017 R_ARM_RELATIVE 00000020 00000017 R_ARM_RELATIVE 00000000 00000402 R_ARM_ABS32 00000a88 _etext - person Dan; 17.02.2011