2013-11-27 18 views
2

爲了模擬包含靜態變量初始化的應用程序(GNU C版本4.1.2(arm-linux-gnueabi))的完全重新啓動,我嘗試根據請求將setjmp/longjmp設置爲gcc pre_init掛鉤函數。 longjmp實際上可以達到.preinit_array函數,但是隨後通過SIGSEGV執行崩潰。是否可以在靜態變量初始化之前對gcc pre_init函數執行longjmp?

任何想法,爲什麼這可能出錯?這通常應該可能嗎?在gdbserver的控制下,是否有其他方法將Linux應用程序恢復到初始狀態?

新增來源:

static jmp_buf reset_simulation_jumpbuf __attribute__ ((section (".noinit"))); 
int preinit(int argc, char **argv, char **envp) 
{ 
    // at this point no static variables shall be initialized 
    setjmp(reset_simulation_jumpbuf); 
} 
// gcc standard linker scripts are calling this function before initialization 
__attribute__((section(".preinit_array"))) typeof(preinit) *__preinit = preinit; 

int main(void) 
{ 
    // at this point all static variables are initialized 
    do_something(); 
    if (reset) 
    longjmp(reset_simulation_jumpbuf,1); 
} 
+0

我寧願建議你'執行'的程序。這將與從「scratch」重新啓動程序相同。破壞機會的可能性較小,並且它仍然是一個相同的過程,因此希望可以在gdbserver上正常工作。 –

+0

你怎麼把'setjmp'放在那裏? –

+1

我添加了一段代碼來顯示我的方法。 – Marcel

回答

0

很難完全確定,但我最好的猜測是,你的跳躍點是靜態變量已經被初始化之前,但它是潛在的C堆棧已經成立後可能是段寄存器和其他ARM內部我不太熟悉。

在這一點上,有幾個潛在的問題可能會導致你的問題。預先初始化代碼可能與前一個具有不同權限的代碼位於不同的段中,從而導致SIGSEGV。堆棧可能處於與正在運行的代碼不兼容的狀態(剩餘的用戶數據過多,沒有足夠的空間存放某個init結構),並且分配一些跨越段邊界的內容。你的處理器初始化代碼可能已經在代碼中的這一點之後保護了一些寄存器,但是假設它現在還沒有被保護,並且你的longjmp沒有對它進行解除保護。而這些只是我頭頂的幾個。

簡而言之,嘗試使用init代碼玩遊戲的方式有很多方法可以在腳中自拍。這並不是說你的代碼不能工作,而只是做一些非常不尋常的事情,系統無法應付。我建議採用不同的方式強制重置軟件,如果軟件具有該功能,可能會導致軟件重置。

相關問題