2017-02-16 37 views
1

我已經構建了一個靜態庫(* .a代表gcc,* .lib代表keil)。編譯到庫中的一個源文件包含RADIO_IRQHandler的定義。從這個源文件的摘錄,被稱爲「ral_irq_handlers.c」,低於:在靜態庫中定義的IRQ符號不會覆蓋來自ARM/GCC啓動的弱IRQ定義

... 
void ral_symbol_import(void) //dummy function 
{ 
    return; 
} 
... 
void RADIO_IRQHandler(void) 
{ 
    ... 
} 
... 

該IRQ符號定義應該重寫它在啓動文件中聲明的弱定義。啓動文件不會編譯到任何靜態庫中,只是項目中的常規文件。

arm_startup_xxx.s文件(keil的工具鏈)的摘錄低於:

Default_Handler PROC 
       ... 
       EXPORT RADIO_IRQHandler [WEAK] 
       ... 
... 
RADIO_IRQHandler 
... 
       B . 
       ENDP 
       ALIGN 

類似gcc_startup_xxx.s文件(gcc工具)的摘錄低於:

.globl Default_Handler 
.type Default_Handler, %function 
Default_Handler: 
    b  . 
    .size Default_Handler, . - Default_Handler 

    .macro IRQ handler 
    .weak \handler 
    .set \handler, Default_Handler 
    .endm  
    ... 
    IRQ RADIO_IRQHandler 
    ... 
    .end 

然後我觀察到一個奇怪的行爲。當我在其中一個項目源文件中使用來自「ral_irq_handlers.c」源文件(編譯爲庫)的任何API函數時,鏈接都會正確完成。例如:

... 
int main(void) 
{ 
    ral_symbol_import(); 
    ... 
} 
... 

但是,如果我不使用「ral_irq_handlers.c」源文件的任何API函數,鏈接器不能找到我的庫中定義的RADIO_IRQHandler符號。我可以以某種方式做到這一點沒有這個醜陋的黑客(調用虛擬函數強制正確的鏈接)?

我想只修改庫代碼而不接觸啓動文件。

回答

1

據我所知,你不能輕易做到這一點,因爲鏈接器只會搜索你的庫,如果它找不到處理程序的符號。正如它可以找到它(在啓動時的弱定義),它不會再看。

但是您可以通過連接您的圖書館一樣,解決這個問題:

... -Wl,--whole-archive -l:path/to/our/library.a -Wl,--no-whole-archive ...

而且你實際上並不需要調用虛函數,使模塊的連接。您需要的僅僅是告訴您需要它的連接器,例如:

void ral_symbol_import(void); 
void (* const variable)() = &ral_symbol_import; 
+0

連接標誌工作得很好,但它非常有創意。你可以以某種方式聲明無效的RADIO_IRQHandler(void)函數在庫中更加可見(某些特殊語句)嗎?或者可能以這種特殊符號正確鏈接的方式構建庫? – aldarel

+1

@aldarel - 對不起,我不知道可以從圖書館「內部」工作的其他選項......我擁有的所有解決方案都針對使用圖書館的項目。您還可以通過鏈接器腳本(或鏈接器命令行)強制鏈接某個符號,但這是同樣的事情。我曾經有類似的問題,這些都是我從這裏得到的 - https://sourceware.org/ml/binutils/2015-09/msg00272.html –