2010-05-30 12 views
6

gcc'nin %pc sabit adreslerinin göreli adreslerini oluşturmasının bir yolu var mı? Dize metin segmentinde göründüğünde bile, arm-elf-gcc verilere sabit bir işaretçi oluşturacak, işaretçinin adresini bir %pc göreceli adres üzerinden yükleyecektir ve daha sonra bunu engelleyecektir. Çeşitli nedenlerle, orta adımı atlaman gerekiyor. Bir örnek olarak, bu basit işlevi: (arm-elf-gcc-4.3.2 -nostdlib -c -O3 -W -Wall logfile.c ile derlenmiş zaman)Sabit verilerin% pc göreli adresi üretiliyor

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

oluşturur:

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 
Ben daha böyle bir şey yaratması bekleniyor olurdu

:

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

kodu söz konusu olan, yükleme zamanında bellekte yeniden yerleştirileceği için, kısmen bağımsız konumlandırılmalı ve aynı zamanda -fPIC derlenmemiş kod ile entegre olacak, Küresel bir ofset tablosu yok.

: etrafında

Benim şu anki çalışma ( bir %pc göreli adresi üzerinden yapılacaktır) olmayan bir satır içi işlevi -fPIC kod çalışmasına benzeyen bir teknikle derlenmiş yerden ofset bulmak için çağırmaktır

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

Ama bu teknik tüm veri referansları elle yukarı sabit, yani yukarıdaki örnekte filename() işlevi olacağını gerekir:

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

cevap

1

Hmmm, belki de PIC almak için -fPIC olarak derlemelisiniz. Veya sadece assembler'a yaz, assembler yazmakta olduğunuz C'den çok daha kolay.

 
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 

Başlarken aynı uyarıyı alıyor musunuz?

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

Evet, aynı uyarıyı alıyorum. Etrafında en kolay kesmek, sahte bir satırsonu eklemek ve yorum yapmaktır: __attribute __ ((section (". Text \ n #"))). Açık adreslerde bulunan ROM'da işlevler bulunduğundan, -fPIC ile derlenemez. Meclis benim için çalışıyor, ama sistemin diğer kullanıcıları için değil ... – Hudson