2012-12-03 33 views
1

我想在我正在處理的iOS應用程序中調試EXC_BAD_ACCESS崩潰。基本上,我的代碼調用與某個組裝方法相對應的函數new_dyna_start()。下面是相關的彙編代碼:在iOS應用程序中的彙編代碼EXC_BAD_ACCESS

.align 4 
42430: 
.long _translation_cache_iphone 

.align 2 
.globl _new_dyna_start 
// .type new_dyna_start, %function 
_new_dyna_start: 
ldr r12, .dlptr 
mov r0, #0xa4000000 
stmia r12, {r4, r5, r6, r7, r8, r9, sl, fp, lr} 
sub fp, r12, #28 
add r0, r0, #0x40 
bl _new_recompile_block 
ldr r0, [fp, #64] 
ldr r10, [fp, #400+36] /* Count */ 
str r0, [fp, #72] 
sub r10, r10, r0 
ldr r0, 42430b 
ldr pc, [r0] 

從我的(有限)的理解,在方法的第6行,它調用C函數new_recompile_block()。此方法效果很好,而且我知道它完成,因爲在函數結束時,我有

printf("End of loop"); 

,然後出現在調試器。該方法完成後,我不完全確定我明白髮生了什麼,但似乎彙編方法獲得對C變量translation_cache_iphone的引用。然而,在最後一行,應用程序奇怪地崩潰。此消息出現在Xcode:http://imgur.com/dqKo0

但是,如果我在旁邊點擊叫最後的方法,我認爲是這樣的:http://imgur.com/M5h84

這似乎支持我的想法,這是translation_cache_iphone變量引起的崩潰,因爲EXC_BAD_ACCESS(0x401000)的內存地址與translation_cache_iphone相同。 translation_cache_iphone聲明爲:

unsigned char* translation_cache_iphone = NULL; 

,並通過初始化:

translation_cache_iphone = (unsigned char *)(((unsigned long) translation_cache_static_iphone + (4096)) & ~(4095)); 

我說得對不對的假設,這是什麼問題?是彙編代碼還是C代碼中的問題?我試過修改兩個,但無濟於事。上面的彙編代碼是原始代碼。

Here is a link to the full source on Github。用Xcode編譯和運行iDevice,你會看到我面對的確切問題。這樣調試可能會更容易。

+0

什麼是translation_cache_iphone?這是你分配的某個區域,是否填入代碼並跳到?如果是這樣,執行動態編寫的代碼有很多問題。包含代碼的內存必須標記爲可執行文件,並且指令緩存必須刷新(並且可能需要其他處理器同步指令)。此外,如果您想在App Store中發佈應用程序,則可能會違反執行解釋代碼的禁令。應用程序需要這樣做是非常罕見的。你試圖完成的實際目標是什麼? –

+0

根據[彙編程序參考](https://developer.apple.com/library/mac/documentation/DeveloperTools/Reference/Assembler/020-Assembly_Language_Syntax/asm_syntax.html#//apple_ref/doc/uid/TP30000821-TPXREF105) ,數字標籤只能是單個數字。我不希望'42430b'工作。這看起來並不是你的直接問題,彙編程序可能會接受它,但將'42430'和'42430b'更改爲'MyPointer'這樣的名稱會更好。 –

+0

要使存儲器可執行,請參閱mprotect系統調用。要使指令緩存無效,請參見[這個問題](http://stackoverflow.com/questions/11818928/flush-ios-instruction-cache)。除非沒有其他選擇,否則您應該避免在應用程序中使用它們。 –

回答

1

最後兩條指令形成間接跳轉到translation_cache_iphone,因此預期這是可執行代碼。驗證情況是否如此,並且內存權限是否合適 - 在許多系統中,默認情況下數據頁不可執行。

+0

如何驗證這一點並檢查內存權限?變量的聲明相當簡單:unsigned char * translation_cache_iphone = NULL; –

1

這似乎支持我的想法,這是translation_cache_iphone變量導致崩潰

是的,我相信這個變量是問題。

在你貼我可以看到一條線,可能會對內存的非法訪問的彙編代碼,它是:

ldr r0, 42430b 
ldr pc, [r0] 

第一行從標籤42430數據加載到寄存器R0 。然後,第二行將PC(程序計數器)指向r0的內容。

在你聲明的是標籤42430彙編代碼的開頭:

42430: 
    .long _translation_cache_iphone 

然後,當它試圖訪問這個值和執行是代碼,它崩潰。

+0

什麼是最好的方式去做這件事?我認爲42430的聲明是必不可少的。我應該宣佈它是別的嗎? –

+0

'ldr r0,42430b'不會將42430加載到r0,並且指令'.long _translation_cache_iphone'不在位置42430.'42430:'是標籤,'ldr r0,42430b'是嘗試加載數據在那個標籤。但是,數字標籤應該是單個數字;我不知道彙編程序在這種情況下會做什麼。另外,我不確定是否以這種方式支持來自某個位置的加載(由於可重定位問題),或者使用'.long _translation_cache_iphone'定義的數據將被正確填充(再次由於可重定位問題)。 –

+0

@Eric Postpischil,你是對的。這就是我的意思,但我以一種令人困惑的方式寫了這個。 我會糾正我的答案。 – KuramaYoko