[英]MCU/embedded: Position independent code, max size for .got section?
我試圖讓我的項目“獨立於職位”,但它不會給...
一些背景:
當我將更改應用到我的“真實”項目時,只要我注釋掉絕大多數 c++ 靜態構造函數,它就可以正常工作。
當我在 main.cpp 中包含一個(任何)更多構造函數時,將發生以下情況:
ResetHandler
將開始設置 R9(用於 .got 的寄存器)= OKResetHandler
將跳轉到Startup
= hard faults,檢查 CPU 中的寄存器,我可以看到 LR(鏈接寄存器)有一個虛假值(0xfffffff9),很明顯出了點問題。我驗證了:
Startup
函數的地址。 它與 .got 部分中的條目匹配。當我通過注釋掉一些東西來減少代碼量時,除了硬故障和 LR 中的損壞值之外,一切的行為都完全相同。
是否有一些(官方?!)文檔確認在為 ARM(Cortex m7)進行交叉編譯時對 .got 部分存在硬性限制?
有沒有人可以通過給出可能的提示來以任何方式做出貢獻?
作為參考,當 .got 大小達到“一些奇怪的閾值”時啟動代碼會彈出(我的假設當然可能是錯誤的)。
extern void Startup(unsigned int flash_start, unsigned int flash_end, unsigned int lma_offset);
extern unsigned int __flash_start__;
extern unsigned int __flash_end__;
extern unsigned int __global_offset_table_flash_start__;
extern unsigned int __global_offset_table_sram_start__;
extern unsigned int __global_offset_table_sram_end__;
//*****************************************************************************
// Reset entry point for your code.
// Sets up a simple runtime environment and initializes the C/C++
// library.
//*****************************************************************************
__attribute__ ((naked))
void ResetISR(void)
{
__asm ("MOV R11, #1");
// Disable interrupts
__asm volatile ("cpsid i");
unsigned int lma_offset;
unsigned int *global_offset_table_flash_start;
// Before doing anything else related to variables in sram, setup r9 for position independent code first.
// And correct the firmware offset which is stored in r10 (add it to r9)
// Finally grab the updated global offset table address from r9
__asm volatile ("LDR r9, = __global_offset_table_flash_start__");
__asm volatile ("ADD r9, r9, r10");
__asm ("MOV %[result], R9"
: [result] "=r" (global_offset_table_flash_start) );
// Grab the lma offset defined in bootloader from r10
__asm ("MOV %[result], R10"
: [result] "=r" (lma_offset) );
unsigned int flash_start = reinterpret_cast<unsigned int>(&__flash_start__);
unsigned int flash_end = reinterpret_cast<unsigned int>(&__flash_end__);
unsigned int *flash;
unsigned int *sram;
unsigned int *sram_end;
__asm ("MOV R11, #2");
//
// Copy global offset table to sram
//
flash = const_cast<unsigned int*>(global_offset_table_flash_start);
sram = const_cast<unsigned int*>(&__global_offset_table_sram_start__);
sram_end = const_cast<unsigned int*>(&__global_offset_table_sram_end__);
for (int i = 0u; i < (sram_end - sram); ++i)
{
sram[i] = flash[i];
if (sram[i] >= flash_start && sram[i] <= flash_end)
{
sram[i] += lma_offset;
}
}
// Update R9, as of now, all functions should be resolvable through the got
__asm volatile ("LDR r9, = __global_offset_table_sram_start__");
__asm ("MOV R11, #3");
unsigned int address = reinterpret_cast<unsigned int>(&Startup);
__asm__ volatile ("MOV R12, %[input]"
: : [input] "r" (address)
);
// Jump to regular startup code
Startup(flash_start, flash_end, lma_offset);
}
PS:我知道 -fPIC 在 linux 中被廣泛使用。 那里不存在這樣的限制。 也許這是 ARM 特定的東西,甚至是 CPU(皮質 m7)特定的東西)。 也許一些 Linux -fPIC 大師可能有一些想法可以幫助我……
PPS:如果我需要分享其他任何內容,請說...
我會將它保持打開狀態,作為為同樣事情苦苦掙扎的人們提供參考。 沒有依賴性。 沒有問題,除了你真正介紹的那些:我自己。
對我來說,主要問題是在重新定位時無法調試我的應用程序。 這可以通過發出 GDB 命令add-symbol-file <path-to-elf-file> <address-to-text-section>
例如:
arm-none-eabi-readelf -WS myapp.axf
讀取 elf 文件時,我可以讀到文本部分的偏移量為 0x2120。當我在調試器中啟動引導加載程序時,在跳轉到重新定位的應用程序之前,我發出命令:
add-symbol-file myapp.axf 0x60032120
這會加載符號,gbd 會將 0x2120 的偏移量添加到 .text 部分中的所有符號。 這樣我就可以調試了。
一旦我的調試器運行起來,我就可以看到幾個編程錯誤。 最關鍵的是在 sram 中使用 .got 部分的基礎設置 r9后讀取鏈接器符號。 我仍然在這些鏈接器符號中添加了 LMA 偏移量,而這會在幕后“自動”發生。 因此,在某些情況下,我正在讀取垃圾內存,並將其存儲在要由libc_init_array
初始化的部分中。
修復這些后,我遇到了另一個奇怪的問題。 一個 nxp 驅動程序聲明了一個包含所有指向GPIO
的指針的static const array
。 當我編譯源文件並通過arm-none-eabi-objdump
將其拉出時,我可以看到 .text 中的數組,完美地設置了 GPIO1..GPIO5 的地址。 但是,在通過 objdump 再次鏈接和轉儲內容之后,我注意到同一個數組被更改了。 對 GPIO5 外設的引用以某種方式設置為 0x0。
現在,我不知道為什么會這樣,但我想如果我刪除const
部分,那么數組將被映射到 sram,也許我可以擺脫這個問題。 我有一次很幸運,它解決了這個問題。 並不是一個完美的解決方案,因為現在我必須非常厭倦聲明static const
內容的代碼。 我稍后會調查它,但現在,我很高興這個故事結束了。 我用 -fPIC 編譯了我的 c++ 應用程序,我可以在閃存中的任何位置(4 字節對齊)上運行它,最重要的是,我還可以通過它進行調試。
所以對於下一個在這個“位置無關代碼”旅程中發瘋的人:不要放棄,痛苦已經結束了;-)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.