2010-05-30 17 views
6

Existe-t-il un moyen pour que gcc génère des adresses relatives de constantes %pc? Même lorsque la chaîne apparaît dans le segment de texte, arm-elf-gcc génère un pointeur constant sur les données, charge l'adresse du pointeur via une adresse relative %pc, puis la déréférence. Pour diverses raisons, je dois passer l'étape intermédiaire. À titre d'exemple, cette fonction simple:Génération de l'adresse relative% pc des données constantes

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

génère (lorsqu'il est compilé avec 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 

Je me serais attendu à générer quelque chose comme:

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

Le code en question doit être partiellement indépendant de la position car il sera déplacé en mémoire au moment du chargement, mais aussi intégrer avec du code qui n'a pas été compilé -fPIC, donc Il n'y a pas de table de compensation globale.

Mon travail actuel est autour d'appeler une fonction non-ligne (qui sera se fait via une %pc adresse relative) pour trouver le décalage par rapport à l'emplacement compilé dans une technique similaire à la façon dont -fPIC code fonctionne:

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

Mais cette technique exige que toutes les références de données fixés manuellement, de sorte que la fonction filename() dans l'exemple ci-dessus deviendraient:

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

Répondre

1

Hmmm, peut-être que vous devez le compiler comme -fPIC pour obtenir PIC. Ou simplement l'écrire en assembleur, l'assembleur est beaucoup plus facile que le C que vous écrivez.

 
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 

Recevez-vous le même avertissement que je reçois?

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

Oui, j'obtiens le même avertissement. Le hack le plus facile à contourner est d'ajouter une nouvelle ligne fictive et de commenter: __attribute __ ((section (". Text \ n #"))). Il ne peut pas être compilé avec -fPIC car il existe des fonctions dans la ROM qui sont à des adresses explicites. L'assemblage fonctionne pour moi, mais pas pour les autres utilisateurs du système ... – Hudson