2010-05-30 9 views
6

Gibt es eine Möglichkeit, gcc %pc relative Adressen von Konstanten generieren zu lassen? Selbst wenn die Zeichenfolge im Textsegment erscheint, generiert arm-elf-gcc einen konstanten Zeiger auf die Daten, lädt die Adresse des Zeigers über eine relative Adresse %pc und dereferenziert sie dann. Aus verschiedenen Gründen muss ich den mittleren Schritt überspringen. Als Beispiel diese einfache Funktion:% pc relative Adresse von konstanten Daten generieren

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

erzeugt (bei arm-elf-gcc-4.3.2 -nostdlib -c -O3 -W -Wall logfile.c kompiliert):

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 

Ich würde es so etwas mehr zu generieren erwarten:

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

Der Code in Frage muss teilweise positionsunabhängig sein, da es im Speicher zur Ladezeit verschoben wird, aber auch mit Code integriert wird, der nicht kompiliert wurde -fPIC, also th Es gibt keine globale Offset-Tabelle.

Meine aktuelle Arbeit ist um eine nicht-Inline-Funktion aufzurufen (die wird über eine %pc relative Adresse erfolgen) den Offset von der kompilierten Lage in einer Technik zu finden, ähnlich wie bei -fPIC Code funktioniert:

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; 
} 

Aber diese Technik erfordert, dass alle Datenreferenzen manuell festgelegt werden, so dass die filename() Funktion in dem obigen Beispiel würde:

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

Antwort

1

Hmmm, vielleicht musst du es als -fPIC kompilieren, um PIC zu bekommen. Oder schreiben Sie es einfach in Assembler, Assembler ist viel einfacher als das C, das Sie schreiben.

 
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 

Erhalten Sie die gleiche Warnung, die ich bekomme?

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

Ja, ich bekomme die gleiche Warnung. Der einfachste Hack ist es, einen falschen Zeilenumbruch und einen Kommentar hinzuzufügen: __attribute __ ((Abschnitt (". Text \ n #"))). Es kann nicht mit -fPIC kompiliert werden, da es Funktionen im ROM gibt, die sich an expliziten Adressen befinden. Montage funktioniert für mich, aber nicht für die anderen Benutzer des Systems ... – Hudson

Verwandte Themen