2016-08-12 43 views
1

我在嵌入式系統(一個的Xtensa處理器),其中我需要手動覆蓋的碼元的情況,但符號恰好是另一碼元的中間。當我嘗試使用-Wl,--wrap=symbol時,它不起作用,因爲符號不是它自己的東西。如何爲GCC代碼指定手動重定位?

我需要做的就是指定(最好在GCC .S,雖然.C是好的),其中的代碼將結束。雖然實際的符號會被編譯器隨機的地方,但我會將代碼放在正確的位置。

40101388 <replacement_user_vect>: 40101388: 13d100 wsr.excsave1 a0 4010138b: 002020 esync 4010138e: 011fc5 call0 4010258c <_UserExceptionVector_1>

我的問題是GCC創建具有相對跳轉假定代碼將位於它在哪裏閃光燈,而最終位置將被固定在一箇中斷向量的組件。我如何告訴GCC/GNU「把代碼放在任何你想要的地方,但是,相信我它會從{here}執行」

雖然我的代碼是在0x40101388(GCC決定),它最終會駐留並執行從0x40100050。我怎麼騙GCC告訴它「把代碼放在這裏」,但假裝它位於「這裏」

編輯:我能夠解決這個問題,事實證明,我需要修改的功能在鏈接器腳本中,單獨。我能夠在鏈接器腳本中將其切換出來。雖然我仍然想知道答案,但我現在有一個解決方法。

+1

gcc或gas不會重定位任何代碼。他們不是連接器。 **相對**跳是根據定義與位置無關的。不清楚你的問題是什麼(以及「在另一個符號中間」是什麼意思)。看[問],提供足夠的信息。 – Olaf

+0

您可以在'''中定義一個特定的符號,即代碼中出現的地方。鏈接器不能重定位,但我不知道爲什麼。您似乎可以在我的測試中重新定位與函數完全獨立的符號,但如果它在函數中間看到某些東西,它將不會重新定位。不知道爲什麼。 –

+4

你的第一款是沒有意義的,但如果我忽略了,那麼你可以做你想做的通過將代碼,你要在它自己的部分其他地方複製,然後使用鏈接腳本,告訴它將被複制到鏈接。看來Linux內核並正是看到http://lxr.free-electrons.com/source/arch/xtensa/kernel/vmlinux.lds.S –

回答

3

在鏈接腳本每個輸出部具有兩個相關聯的地址:VMA和LMA - 爲其代碼鏈接到的地址,並且其中所述代碼將被加載的地址。

將需要重新定位到單獨的部分代碼,添加一個輸出部分,將鏈接腳本與所需的VMA和LMA,並把輸入部分匹配它裏面的代碼段的名稱。

E.g.在用下面的片LD腳本,與VMA與期望的目標代碼位置

SECTIONS { 
    ... 
    .some_section : { ... } 
    .relocatable1 VMA : AT(LOADADDR(.some_section) + SIZEOF(.some_section)) { 
    _relocatable1_vma_start = . ; 
    *(.relocatable1.literal .relocatable1.text) ; 
    _relocatable1_vma_end = . ; 
    } 
    _relocatable1_lma = LOADADDR(.relocatable1) ; 
    ... 
} 

應該做你想要什麼取代下面的C代碼

void f(void) __attribute__((section(".relocatable1.text"))) 
{ 
    ... 
} 

extern char _relocatable1_lma[]; 
extern char _relocatable1_vma_start[]; 
extern char _relocatable1_vma_end[]; 

void relocatable1_copy(void) 
{ 
     memcpy(_relocatable1_vma_start, _relocatable1_lma, 
       _relocatable1_vma_end - _relocatable1_vma_start); 
} 

一起。