2014-10-28 21 views
2

我有一個64位程序,它可以與VirtualBox COM接口一起使用並實現虛擬機的前端。最近我開始變得很奇怪,我至少想明白這個原因。據我瞭解堆棧需要16byte對齊,所以我認爲未對齊的堆棧指針可能會導致此問題。但事情是,因爲我所有的程序都是使用來自ATL的STDMETHOD宏來實現一些COM接口,它應該使用正確的調用約定,那麼我怎樣才能把這個堆棧搞亂呢?展開操作期間遇到無效或未對齊的堆棧

這裏是調用堆棧的一個例子,當出現問題:

ntdll.dll!00007ffe679ac0b4() Unknown 
ntdll.dll!00007ffe67913356() Unknown 
msvcrt.dll!__longjmp_internal() Unknown 
> VBoxREM.dll!000000006fb0f3c4() Unknown 

我試圖古爾的__longjmp_internal符號,但沒有發現任何有用的東西 - 它表明例外的展開是在進步嗎?

對如何處理這個問題的調試或者評論什麼事情搞砸棧對齊的歡迎,因爲據我所知,在這種情況下,這將是不可能的,因爲VirtualBox是涉及給出一個確切的解決方案的任何指針。

+0

我不禁大爲,但這是[longjmp的(http://www.cplusplus.com/reference/csetjmp/longjmp/) – ChrisWard1000 2014-10-28 09:46:32

+0

無效比非對齊更有可能。你有沒有證實對齊是問題還是隻是猜測?破壞堆棧的方法比世界上的程序員還要多。懸掛或未初始化的指針和緩衝區溢出可能是最常見的。你犯了哪一個是無法猜測的。 – molbdnilo 2014-10-28 10:00:33

+0

@molbdnilo我猜測,因爲我期望得到訪問衝突或類似的東西,如果我有一個懸掛的指針或做了內存溢出,但我當然不能排除這些。猜猜我必須做一些內存分析。 – 2014-10-28 10:06:38

回答

1

最近我遇到了這個莫名其妙的問題。

我知道這只是開始發生後,我從靜態C開關/ C++運行時DLL版本,所以這可能意味着靜態版本沒有做堆棧展開。

我然後跟蹤的彙編代碼爲longjmp()和注意到第一條件分支是上_JUMP_BUFFER.Frame之一。

如果它是0,那麼恢復一堆寄存器並返回。

啊哈!所以這意味着如果_JUMP_BUFFER.Frame = 0,展開被禁用。我嘗試了,事實上,問題解決了。

然後我試圖觀察setjmp()/ longjmp()對成功時應該是什麼Frame。我通常發現,frame = stack指針,但是當展開失敗時,frame!= SP。所以我嘗試將Frame設置爲SP,這也消除了異常。

我不知道這是爲什麼。我知道在SYSV x86-64 ABI中,幀指針是可選的。也許setjmp()需要一個適當的幀指針,並沒有得到一個?

+0

哇,如果真的有這個訣竅,它會非常棒:)謝謝,我會檢查這個。 – 2016-08-23 11:45:50

+0

「退繞失敗」的意思是什麼 - 退繞過程中的例外情況?如果發生這種事情,我會得到異常終止,甚至沒有達到跳躍的返回。 – 2016-08-23 13:04:42

+0

當我說「展開失敗」時,我引用了「RtlUnwindEx()中遇到無效或未對齊的堆棧」異常 – 2016-08-23 19:18:51

0

不知道這是否有幫助,但我遇到類似問題(沒有虛擬機)與longjmp結合x64 Windows。

原來,在與longjmp相同的作用域中,任何種類的對齊堆棧數據(與> = 32byte對齊)導致longjmp在爲x64編譯時出現0xC0000028。

#include <setjmpex.h> 

void doThe_0xC0000028 () 
{ 
    jmp_buf jp; 

    if (!setjmp (jp)) 
    { 
     // do some stuff ... 
     // ... then "revert" with longjmp. 
     longjmp (jp, 1); 
    } 

    // having any aligned data on stack (align > 16) in the same scope 
    // causes longjmp to go: 0xC0000028 
    //------------------------------------------------------------------ 
    __declspec(align(32)) char buffer[12]; 

    // just accessing buffer somehow - this is apparently needed to generate the faulty 0xC0000028 
    buffer[0];   
} 

我報告說,由於MSVC錯誤: https://connect.microsoft.com/VisualStudio/feedback/details/3136150/64bit-longjmp-causing-0xc0000028-with-aligned-stack-data