Проблемы со статическими локальными переменными с перемещаемым кодом - PullRequest
3 голосов
/ 23 февраля 2011

Я строю проект с перемещаемым кодом на голом металле. Это встроенное приложение Cortex M3. У меня нет динамического компоновщика, и я реализовал все перемещения в своем коде запуска.

В основном это работает, но мои локальные статические переменные, похоже, неправильно расположены. Их адрес смещен на величину, с которой мой исполняемый файл смещен в памяти - т.е. я компилирую свой код так, как будто он загружен в ячейку памяти 0, но фактически загружаю его в память, расположенную в 0x8000. Статические локальные переменные имеют смещение адреса памяти на 0x8000, что не очень хорошо.

Мои глобальные переменные правильно расположены GOT, но статические локальные переменные вообще не находятся в GOT (по крайней мере, они не появляются, когда я запускаю readelf -r). Я компилирую свой код с помощью -fpic, а для компоновщика указаны -fpic и -pie. Я думаю, что мне не хватает опции компиляции и / или ссылки, чтобы либо указать gcc использовать GOT для статических локальных переменных, либо указать абсолютную адресацию для них.

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

Ответы [ 2 ]

3 голосов
/ 25 июня 2014

Эта проблема также обсуждается здесь: https://answers.launchpad.net/gcc-arm-embedded/+question/236744

Начиная с gcc 4.8 (ARM), есть переключатель командной строки с именем -mpic-data-is-text-relative, который вызывает статические переменные, которые также обрабатываются через GOT.

3 голосов
/ 24 февраля 2011

Мне кажется, я повторил то, что вы видите:

statloc.c

unsigned int glob;

unsigned int fun ( unsigned int a )
{
    static unsigned int loc;

    if(a==0) loc=7;
    return(a+glob+loc);
}

arm-none-linux-gnueabi-gcc -mcpu=cortex-m3 -Wall -Werror -O2 -nostdlib -nostartfiles -ffreestanding -mthumb -fpic -pie -S statloc.c

Что дает:

    .cpu cortex-m3
    .fpu softvfp
    .thumb
    .text
    .align  2
    .global fun
    .thumb
    .thumb_func
fun:
    ldr r3, .L6
.LPIC2:
    add r3, pc
    cbnz    r0, .L5
    ldr r1, .L6+4
    movs    r2, #7
.LPIC1:
    add r1, pc
    ldr ip, .L6+8
    str r2, [r1, #0]
    ldr r1, [r3, ip]
    ldr r3, [r1, #0]
    adds    r0, r0, r3
    adds    r0, r0, r2
    bx  lr
.L5:
    ldr ip, .L6+8
    ldr r2, .L6+12
    ldr r1, [r3, ip]
.LPIC0:
    add r2, pc
    ldr r2, [r2]
    ldr r3, [r1, #0]
    adds    r0, r0, r3
    adds    r0, r0, r2
    bx  lr
.L7:
    .align  2
.L6:
    .word   _GLOBAL_OFFSET_TABLE_-(.LPIC2+4)
    .word   .LANCHOR0-(.LPIC1+4)
    .word   glob(GOT)
    .word   .LANCHOR0-(.LPIC0+4)
    .size   fun, .-fun
    .comm   glob,4,4
    .bss
    .align  2
.LANCHOR0 = . + 0
    .type   loc.823, %object
    .size   loc.823, 4
loc.823:
    .space  4

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

this is the offset from the pc to the .got
    ldr r3, .L6  
add pc so r3 holds a position independent offset to the .got
    add r3, pc   
offset in the got for the address of the glob 
    ldr ip, .L6+8 
read the absolute address for the global variable from the got
    ldr r1, [r3, ip] 
finally read the global variable into r3
    ldr r3, [r1, #0] 


this is the offset from the pc to the static local in .bss
    ldr r2, .L6+12
add pc so that r2 holds a position independent offset to the static local
in .bss    
    add r2, pc
read the static local in .bss    
    ldr r2, [r2]

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

если вам нужно изменить место загрузки .text, оставьте .bss там, где его разместил компоновщик, и переместите .got относительно .text. тогда глобальный будет вытащен из правильного места, а локальный не будет

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

Так что загрузчик и gcc / ld должны быть синхронизированы. Моя непосредственная рекомендация - не использовать статический локальный, а просто использовать глобальный. Это или не беспокоиться о позиционно-независимом коде, это все-таки cortex-m3 и несколько ограниченный ресурс, просто определите карту памяти заранее. Я предполагаю, что вопрос заключается в том, как заставить gcc использовать .got для локального глобала, и на который я не знаю ответа, но на простом примере, подобном приведенному выше, вы можете работать с множеством параметров командной строки, пока не найдете тот, который изменяет вывод.

...