Вероятно, существует бесчисленное множество способов сделать это, но, надеюсь, это даст вам некоторые боеприпасы для начала, чтобы посмотреть, что происходит.
boot.s
.thumb
.globl _start
_start:
reset:
mov r0,pc
ldr r1,=0xFFFF0000
and r0,r1
ldr r1,gotbase
add r0,r1
bl centry
b .
.align
gotbase:
.word _GLOBAL_OFFSET_TABLE_-(_start)
.word _start
.word _GLOBAL_OFFSET_TABLE_
.word _GLOBAL_OFFSET_TABLE_
так.c
extern unsigned int fun ( unsigned int );
unsigned int x;
unsigned int y;
unsigned int z;
void centry ( void )
{
x=5;
y=6;
z=fun(77);
}
fun.c
unsigned int fun ( unsigned int x )
{
return(x+3);
}
flash.ld
MEMORY
{
rom : ORIGIN = 0x08020000, LENGTH = 0x1000
ram : ORIGIN = 0x20000000, LENGTH = 0x1000
}
SECTIONS
{
.text : { *(.text*) } > rom
.rodata : { *(.rodata*) } > rom
.bss : { *(.bss*) } > ram
}
build
arm-none-eabi-as --warn boot.s -o boot.o
arm-none-eabi-gcc -Wall -O2 -mthumb -fpic -mthumb -c so.c -o so.o
arm-none-eabi-gcc -Wall -O2 -mthumb -fpic -mthumb -c fun.c -o fun.o
arm-none-eabi-ld -o so.elf -T flash.ld boot.o so.o fun.o
arm-none-eabi-objdump -D so.elf > so.list
arm-none-eabi-objcopy --srec-forceS3 so.elf -O srec so.srec
arm-none-eabi-objcopy so.elf so.bin -O binary
дизассемблирование
Disassembly of section .text:
08020000 <_start>:
8020000: 4678 mov r0, pc
8020002: 4907 ldr r1, [pc, #28] ; (8020020 <gotbase+0x10>)
8020004: 4008 ands r0, r1
8020006: 4902 ldr r1, [pc, #8] ; (8020010 <gotbase>)
8020008: 1840 adds r0, r0, r1
802000a: f000 f80b bl 8020024 <centry>
802000e: e7fe b.n 802000e <_start+0xe>
08020010 <gotbase>:
8020010: 00000060
8020014: 08020000
8020018: 00000048
802001c: 00000044
8020020: ffff0000
08020024 <centry>:
8020024: 2205 movs r2, #5
8020026: b510 push {r4, lr}
8020028: 4c08 ldr r4, [pc, #32] ; (802004c <centry+0x28>)
802002a: 4b09 ldr r3, [pc, #36] ; (8020050 <centry+0x2c>)
802002c: 447c add r4, pc
802002e: 58e3 ldr r3, [r4, r3]
8020030: 601a str r2, [r3, #0]
8020032: 4b08 ldr r3, [pc, #32] ; (8020054 <centry+0x30>)
8020034: 58e3 ldr r3, [r4, r3]
8020036: 3201 adds r2, #1
8020038: 204d movs r0, #77 ; 0x4d
802003a: 601a str r2, [r3, #0]
802003c: f000 f80e bl 802005c <fun>
8020040: 4b05 ldr r3, [pc, #20] ; (8020058 <centry+0x34>)
8020042: 58e3 ldr r3, [r4, r3]
8020044: 6018 str r0, [r3, #0]
8020046: bc10 pop {r4}
8020048: bc01 pop {r0}
802004a: 4700 bx r0
802004c: 00000030
8020050: 00000000
8020054: 00000008
8020058: 00000004
0802005c <fun>:
802005c: 3003 adds r0, #3
802005e: 4770 bx lr
Disassembly of section .got:
08020060 <.got>:
8020060: 20000000
8020064: 20000004
8020068: 20000008
Disassembly of section .got.plt:
0802006c <_GLOBAL_OFFSET_TABLE_>:
...
Disassembly of section .bss:
20000000 <x>:
20000000: 00000000
20000004 <z>:
20000004: 00000000
20000008 <y>:
20000008: 00000000
Это намеренно несколько, ну очень много, минимально.Первый и самый интересный элемент в отношении независимости позиции:
Разборка секции .got:
08020060 <.got>:
8020060: 20000000
8020064: 20000004
8020068: 20000008
И что это, очевидно, три глобальных элемента данных, которые мы имеем впрограмма.Если вы добавите больше элементов, вы увидите это изменение.
Если вы измените адреса в скрипте компоновщика
rom : ORIGIN = 0x08010000, LENGTH = 0x1000
ram : ORIGIN = 0x30000000, LENGTH = 0x1000
хотя бы для этой простой программы с инструментами, которые я использовал, машинный код не изменится(технически это возможно с оптимизацией, но предполагается, что она не зависит от позиции, поэтому вам не нужно заботиться о расположении кода с указанием причины), но полученное значение отражает адрес 0x30000000.
Быть большим пальцем (вероятно, не имеет значения) и все встроенные позиции независимы и мигания относительно невелики (по сравнению с диапазоном инструкций ветвления и ветвления), у компоновщика не должно быть никаких проблем или магического создания относительных ветвей, поэтому я надеюсь, что нет математики счетчика программ, хотя, если вы действительноЯ действительно постарался поспорить, что вы могли бы сделать это, и я бы предположил, но вы найдете, если вы нажмете, если это так.И, вероятно, если вы нажмете на это, возможно, у вас получится .text или другие смещения на основе здесь:
Disassembly of section .got.plt:
0802006c <_GLOBAL_OFFSET_TABLE_>:
...
Так что, если ваши альтернативные местоположения для ваших программ также включают альтернативные местоположения для данных, то вам нужно исправитьвверх по глобальной таблице смещений.
Мой бутстрап более чем минимален, возился с одним грубым способом добраться до адреса ПОЛУЧЕНО.Нет никаких сомнений в том, что скрипт компоновщика и / или код ghee whiz позволяют получить эту информацию.Точно так же вы можете использовать скрипт компоновщика для принудительного / размещения GOT.
8020024: 2205 movs r2, #5
8020028: 4c08 ldr r4, [pc, #32] ; (802004c <centry+0x28>)
802002c: 447c add r4, pc
8020032: 4b08 ldr r3, [pc, #32] ; (8020054 <centry+0x30>)
8020034: 58e3 ldr r3, [r4, r3]
8020036: 3201 adds r2, #1
802003a: 601a str r2, [r3, #0]
эти элементы делают независимую от позиции версию y = 6;они вычисляют смещение для полученного значения, затем смещение в это и используют его для адресации в памяти, удаляют параметры командной строки pic и видят, как это изменяется.
То же машинный код зависит от полученного значения для полученного значения.фактический адрес для элемента.
если у нас есть 0x20000004, тогда это то место, где живет y, если в таблице 0x30000004, то это место, где живет y.
как закодировано и построено выше
08020060 <.got>:
8020060: 20000000
8020064: 20000004
8020068: 20000008
таблица живет во флэш-памяти, поэтому код, который вы используете для помещения этой программы во флэш-память, должен будет исправить эту таблицу при записи во флэш-память.если вы играете в игры с компоновщиками, чтобы поместить таблицу в оперативную память, но во флэш-памяти, например, .data, это байты в оперативной памяти, которые куда-то идут, но во флэш-памяти затем копируются с помощью начальной загрузки, комбинации начальной загрузки и кода сценария компоновщика.
В любом случае я не понимаю, как это возможно, чтобы любой стандартный загрузчик знал, где вы хотите, чтобы он находился.Предполагается, что код .text можно перемещать с некоторыми предположениями о выравнивании, но предполагается, что .data и другие находятся не в одном и том же пространстве памяти и не перемещаются линейно с .text (нельзя просто взять некоторый связанный адрес .text и обнаруженный адрес .textи скорректируйте смещения данных на эту величину, поскольку предполагается, что эти два значения разделены и в этом случае (микроконтроллер cortex-m))
Таким образом, я бы (кроме ответов здесь никогда не нуждался в этом) начинать с приведенных выше боеприпасов, будь то просто знание того, как разобрать и прочитать код и / или часть кода выше, и изучить, чтоинструменты строят для вас, куда они кладут вещи.Я бы предположил, что вы создаете саму программу (если хотите, .text) как один большой двоичный объект, так что инструменты должны собрать его с относительной адресацией для доступа в этом разделе.Если вы не написали загрузчик, то это не инструментальная цепочка, а библиотека C или другая (RTOS, HAL и т. Д.), И я не ожидал бы, что она будет иметь независимый от позиции глобальный код исправления таблицы смещений, как откуда загрузчик узнаеткуда вы хотите переместить файл .data / .bss?Обдумайте это немного.Еще хуже в этом случае, если GOT находится во флэш-памяти, тогда он должен быть исправлен ДО выполнения, а не во время, поэтому некоторые другие программы должны делать это.Вероятно, поэтому формат файла elf содержит расположение / размер GOT, чтобы загрузчик, операционная система или другой инструмент загружали эту программу перед ее запуском.могу найти и исправить это.
Если вы хотите, чтобы ваши программы загружались в одно из двух разных флеш-пространств, вам нужно решить эту проблему с любой загрузкой.Снова очень грубая грубая сила, способ начать:
.thumb
.globl _start
_start:
reset:
b skip
.align
.word _GLOBAL_OFFSET_TABLE_-(_start)
skip:
08020000 <_start>:
8020000: e002 b.n 8020008 <skip>
8020002: 46c0 nop ; (mov r8, r8)
8020004: 00000068 andeq r0, r0, r8, rrx
08020008 <skip>:
ваш загрузчик может найти смещение в месте, которое вы оставили (смещение 0x4 в двоичный файл), но, конечно, вам нужно выяснить (магия линкера)и поместите размер глобальной таблицы смещений в известное место.или поддерживает полноформатные файлы эльфов или других форматов и анализирует их.
EDIT:
08020068 <.got>:
8020068: 20000000
802006c: 20000004
8020070: 20000008
08020068 <.got>:
8020068: 30000000
802006c: 30000004
8020070: 30000008
GOT не / не может перемещаться, он должен быть относительным к ПК, поэтому код, скомпилированный в.text может найти это.На что он указывает, на что должна быть изменена вся идея, если / когда вы переместитесь туда, где вы хотите, чтобы эти предметы.Таким образом, как показано выше, если он был связан таким образом, что x, y, z имеют значения 0x20000000, 0x20000004, 0x20000008.Но если вы хотите работать с x, y, z в 0x30000000, переместить в основном, то вам нужно изменить сам GOT, чтобы он указывал на эти элементы, как во втором примере выше.Потому что значение есть в .text, так что это pc относительно кода (как показано выше, как код создается с использованием опции командной строки, которую я использовал), и это mcu, и если у вас есть .text во флэш-памяти, то получаетсядолжен быть изменен перед помещением во флэш-память, которая не выполняется во время выполнения этого кода.Таким образом, ваш загрузчик или все, что помещает эту программу во флэш-память, должно будет сделать этот патч, ЕСЛИ вы хотите, чтобы .data / .bss находились где-то, кроме связанных.
08020068 <.got>:
8020068: 20000000
802006c: 20000004
8020070: 20000008
08020068 <.got>:
8020068: 30000000
802006c: 30000004
8020070: 30000008
GOT не может / не может двигаться, он долженбыть относительным к ПК, чтобы код, скомпилированный в .text, мог его найтиНа что он указывает, на что должна быть изменена вся идея, если / когда вы переместитесь туда, где вы хотите, чтобы эти предметы.Таким образом, как показано выше, если он был связан таким образом, что x, y, z имеют значения 0x20000000, 0x20000004, 0x20000008.Но если вы хотите работать с x, y, z в 0x30000000, переместить в основном, то вам нужно изменить сам GOT, чтобы он указывал на эти элементы, как во втором примере выше.Потому что значение есть в .text, так что это pc относительно кода (как показано выше, как код создается с использованием опции командной строки, которую я использовал), и это mcu, и если у вас есть .text во флэш-памяти, то получаетсядолжен быть изменен перед помещением во флэш-память, которая не выполняется во время выполнения этого кода.Таким образом, ваш загрузчик или все, что помещает эту программу во флэш-память, должно будет сделать этот патч, ЕСЛИ вы хотите, чтобы .data / .bss находились где-то, кроме связанных.
Использование флагов вашего компилятора
Disassembly of section .text:
08020000 <_start>:
8020000: e002 b.n 8020008 <skip>
8020002: 46c0 nop ; (mov r8, r8)
8020004: 00000064 andeq r0, r0, r4, rrx
08020008 <skip>:
8020008: 4678 mov r0, pc
802000a: 4907 ldr r1, [pc, #28] ; (8020028 <gotbase+0x10>)
802000c: 4008 ands r0, r1
802000e: 4902 ldr r1, [pc, #8] ; (8020018 <gotbase>)
8020010: 1840 adds r0, r0, r1
8020012: f000 f80b bl 802002c <centry>
8020016: e7fe b.n 8020016 <skip+0xe>
08020018 <gotbase>:
8020018: 00000064 andeq r0, r0, r4, rrx
802001c: 08020000 stmdaeq r2, {} ; <UNPREDICTABLE>
8020020: 00000044 andeq r0, r0, r4, asr #32
8020024: 00000040 andeq r0, r0, r0, asr #32
8020028: ffff0000 ; <UNDEFINED> instruction: 0xffff0000
0802002c <centry>:
802002c: b510 push {r4, lr}
802002e: 4654 mov r4, r10
8020030: 2205 movs r2, #5
8020032: 4b08 ldr r3, [pc, #32] ; (8020054 <centry+0x28>)
8020034: 58e3 ldr r3, [r4, r3]
8020036: 601a str r2, [r3, #0]
8020038: 4b07 ldr r3, [pc, #28] ; (8020058 <centry+0x2c>)
802003a: 58e3 ldr r3, [r4, r3]
802003c: 3201 adds r2, #1
802003e: 204d movs r0, #77 ; 0x4d
8020040: 601a str r2, [r3, #0]
8020042: f000 f80d bl 8020060 <fun>
8020046: 4b05 ldr r3, [pc, #20] ; (802005c <centry+0x30>)
8020048: 58e3 ldr r3, [r4, r3]
802004a: 6018 str r0, [r3, #0]
802004c: bc10 pop {r4}
802004e: bc01 pop {r0}
8020050: 4700 bx r0
8020052: 46c0 nop ; (mov r8, r8)
8020054: 00000000 andeq r0, r0, r0
8020058: 00000008 andeq r0, r0, r8
802005c: 00000004 andeq r0, r0, r4
08020060 <fun>:
8020060: 3003 adds r0, #3
8020062: 4770 bx lr
Disassembly of section .got:
08020064 <.got>:
8020064: 20000000 andcs r0, r0, r0
8020068: 20000004 andcs r0, r0, r4
802006c: 20000008 andcs r0, r0, r8
который меняет его, чтобы использовать это
802002e: 4654 mov r4, r10
, но обратите внимание, что инструменты не устанавливают r10, вы должны добавить код к точке r10 в GOT, чтобы это работало вообще даже на связанном адресе.
Итак, опять же, GOT сам не перемещается, вот и весь смысл, содержимое меняется на точку в перемещенном месте для .data / .bss.См. Последний пример выше. GOT находится в том же месте, но адреса для x, y, z были изменены, чтобы отразить их новое местоположение.Разборка показывает адреса на основе связанных адресов, но если вы связываетесь с другим адресом и сравниваете только машинный код, вы увидите, что он не меняется, используемые инструкции относятся к ПК.