Генерация% pc относительного адреса постоянных данных - PullRequest
6 голосов
/ 31 мая 2010

Есть ли способ заставить gcc генерировать %pc относительные адреса констант? Даже когда строка появляется в текстовом сегменте, arm-elf-gcc будет генерировать постоянный указатель на данные, загружать адрес указателя через относительный адрес %pc и затем разыменовывать его. По разным причинам мне нужно пропустить средний шаг. Как пример, эта простая функция:

const char * filename(void)
{
    static const char _filename[]
            __attribute__((section(".text")))
            = "logfile";
    return _filename;
}

генерирует (при компиляции с arm-elf-gcc-4.3.2 -nostdlib -c -O3 -W -Wall logfile.c):

00000000 <filename>:
   0:   e59f0000        ldr     r0, [pc, #0]    ; 8 <filename+0x8>
   4:   e12fff1e        bx      lr
   8:   0000000c        .word   0x0000000c

0000000c <_filename.1175>:
   c:   66676f6c        .word   0x66676f6c
  10:   00656c69        .word   0x00656c69

Я бы ожидал, что это сгенерирует что-то похожее на:

filename:
    add r0, pc, #0
    bx lr
_filename.1175:
    .ascii "logfile\000"

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

Моя текущая работа заключается в том, чтобы вызвать не встроенную функцию (которая будет выполняться через относительный адрес %pc), чтобы найти смещение от скомпилированного местоположения в методике, аналогичной тому, как -fPIC код работает:

static intptr_t
__attribute__((noinline))
find_offset( void )
{
    uintptr_t pc;
    asm __volatile__ (
            "mov %0, %%pc" : "=&r"(pc)
    );

    return pc - 8 - (uintptr_t) find_offset;
}

Но этот метод требует, чтобы все ссылки на данные были исправлены вручную, поэтому функция filename() в приведенном выше примере будет иметь вид:

const char * filename(void)
{
    static const char _filename[]
            __attribute__((section(".text")))
            = "logfile";
    return _filename + find_offset();
}

1 Ответ

1 голос
/ 31 мая 2010

Хммм, может быть, вам нужно скомпилировать его как -fPIC, чтобы получить PIC. Или просто напишите это на ассемблере, ассемблер намного проще, чем тот, на котором вы пишете.

00000000 :
   0:   e59f300c    ldr r3, [pc, #12]   ; 14 
   4:   e59f000c    ldr r0, [pc, #12]   ; 18 
   8:   e08f3003    add r3, pc, r3
   c:   e0830000    add r0, r3, r0
  10:   e12fff1e    bx  lr
  14:   00000004    andeq   r0, r0, r4
  18:   00000000    andeq   r0, r0, r0

0000001c :
  1c:   66676f6c    strbtvs r6, [r7], -ip, ror #30
  20:   00656c69    rsbeq   r6, r5, r9, ror #24

Получаете ли вы то же предупреждение, что и я?

/tmp/ccySyaUE.s: Assembler messages:
/tmp/ccySyaUE.s:35: Warning: ignoring changed section attributes for .text
...