2010-05-30 14 views
6

Có cách nào để gcc tạo ra %pc địa chỉ tương đối của các hằng số không? Ngay cả khi chuỗi xuất hiện trong đoạn văn bản, arm-elf-gcc sẽ tạo ra một con trỏ liên tục đến dữ liệu, tải địa chỉ của con trỏ qua một địa chỉ tương đối %pc và sau đó dereference nó. Vì nhiều lý do, tôi cần phải bỏ qua bước giữa. Như một ví dụ, chức năng này rất đơn giản:Tạo% pc địa chỉ tương đối của dữ liệu không đổi

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

tạo (khi biên soạn với 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 

tôi sẽ mong đợi nó để tạo ra một cái gì đó giống như:

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

Mã trong câu hỏi cần phải là một phần vị trí độc lập vì nó sẽ được di chuyển trong bộ nhớ tại thời gian tải, nhưng cũng tích hợp với mã không được biên dịch -fPIC, do đó, ere không có bảng bù đắp toàn cầu.

công việc hiện tại của tôi xung quanh là để gọi một hàm phi inline (mà sẽ được thực hiện thông qua một địa chỉ tương đối %pc) để tìm được bù đắp từ vị trí biên soạn trong một kỹ thuật tương tự như cách -fPIC đang hoạt động:

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

Nhưng kỹ thuật này đòi hỏi tất cả tài liệu tham khảo dữ liệu được cố định bằng tay, do đó filename() chức năng trong ví dụ trên sẽ trở thành:

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

Trả lời

1

Hmmm, có thể bạn phải biên dịch nó thành -fPIC để lấy PIC. Hoặc đơn giản là viết nó vào trong assembler, assembler dễ hơn rất nhiều so với C bạn đang viết.

 
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 

Bạn có nhận được cảnh báo giống như tôi đang nhận được không?

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

Có, tôi cũng nhận được cảnh báo tương tự. Các hack đơn giản nhất xung quanh nó là thêm một dòng mới không có thật và nhận xét: __attribute __ ((phần (". Văn bản \ n #"))). Không thể biên dịch bằng -fPIC vì có các hàm trong ROM có địa chỉ rõ ràng. Công việc lắp ráp cho tôi, nhưng không dành cho những người dùng khác của hệ thống ... – Hudson

Các vấn đề liên quan