2013-10-28 43 views
4

我試圖在Cortex-M3處理器(ARMv7-M架構)上構建調用堆棧,沒有OS(裸機)。但是,這個ABI沒有幀指針寄存器。因此,當我沒有幀指針時,我正在努力生成調用堆棧。ARM:無幀指針的調用堆棧生成

無論使用-mapcs-frame,-fno-omit-frame-pointer-O0選項與GCC,都不保留幀指針。我想知道是否有不同的ABI我可以強制GCC使用,所以我有一個幀指針/堆棧幀?如果沒有,是否還有其他可靠的方法來生成調用堆棧?

在此先感謝。

+0

爲什麼你需要一個調用堆棧的幀指針寄存器?我很困惑。幀指針寄存器是一個懶惰的解決方案,只需使用堆棧指針而不浪費其他寄存器。只需編譯一些C代碼,看看編譯器是如何模仿它的。 –

+0

其實拇指與armv7m拇指2擴展(約140-150附加說明),這意味着你可以使用手臂式解決方案。 –

+0

我不能只使用堆棧指針,因爲我不知道調用函數中每個堆棧幀的大小。同樣在浪費寄存器方面,GCC的ARM彙編輸出非常奇怪,因爲它使用一個寄存器作爲堆棧指針的近似副本(儘管我正在使用'-OO'編譯) – Saul

回答

2

關於上述註釋,ARM調用標準與Thumb相同,請參閱(AAPCS Arm calling standard)指令集不同,但CPU寄存器設置不同。

我寧願在評論中提問,但至今我沒有足夠的分數。 考慮到這一點....

你有一個二進制成功構建和執行,但你試圖轉儲某種調用跟蹤?我的困惑是'無幀指針寄存器'語句 - r13是堆棧幀指針。我認爲你指的是存儲幀指針。

它已經有一段時間,但我認爲這些是我用

臂-NONE-EABI-GCC選項 - -nostdlib -ggdb -mthumb -mcpu =皮質-M3 -mtpcs幀 - mtpcs葉幀myfile.c文件

這是在gcc-arm-none downloaded from linaro. GDB能夠做的回溯與愛特梅爾SAM3X這些選項。 Thumb ABI與ARM EABI相同,或者至少似乎是通過objdump -D查看彙編程序。

前一幀指針被存儲在r7中當指定-fno-省略幀指針(或暗示)

void test2(int i) {} 
void main() { test(0); 

編譯時-fomit幀指針

00008000 <test2>: 
    8000: b082  sub sp, #8 
    8002: 9001  str r0, [sp, #4] 
    8004: b002  add sp, #8 
    8006: 4770  bx lr 

00008008 <main>: 
    8008: b508  push {r3, lr} 
    800a: f04f 0000 mov.w r0, #0 
    800e: f7ff fff7 bl 8000 <test2> 
    8012: bd08  pop {r3, pc} 

編譯與-fno-omit-幀指針

00008000 <test2>: 
    8000: b480  push {r7} 
    8002: b083  sub sp, #12 
    8004: af00  add r7, sp, #0 
    8006: 6078  str r0, [r7, #4] 
    8008: f107 070c add.w r7, r7, #12 
    800c: 46bd  mov sp, r7 
    800e: bc80  pop {r7} 
    8010: 4770  bx lr 
    8012: bf00  nop 

00008014 <main>: 
    8014: b580  push {r7, lr} 
    8016: af00  add r7, sp, #0 
    8018: f04f 0000 mov.w r0, #0 
    801c: f7ff fff0 bl 8000 <test2> 
    8020: bd80  pop {r7, pc} 
    8022: bf00  nop 

所以使用r7來到前一個堆棧幀,然後得到來自該位置的下一個r7等等。

+0

如何告訴GCC使用EABI?另外,堆棧指針是否指向不適合寄存器的局部變量的開始? – Saul

+0

正確,sp將指向進入'功能'的第5個參數,例如foo(1,2,3,4,5)調用者將在sp位置存儲'5',r0..r4將包含1,2,3,4被調用者將從sp位置讀取'5'。請注意,堆棧是'在寫入之前減少' – SilverCode

+0

我無法使用GDB,因爲我沒有操作系統,並且在MBED板上運行的映像不是ELF,只是二進制機器代碼。您說我正在嘗試生成呼叫跟蹤是正確的。沒有幀指針,這是不可能的,因爲我不能走棧。因此我的問題是我如何強制GCC使用幀指針(因爲'-fno-omit-frame-pointer'似乎沒有任何效果),或者說,我怎樣才能找到調用函數的地址,並在此之前調用函數的地址,無限。 – Saul