2012-12-03 3 views
1

iOS 앱에서 EXC_BAD_ACCESS 크래시를 디버깅하려고합니다. 기본적으로, 내 코드는 특정 어셈블리 메서드에 해당하는 new_dyna_start() 함수를 호출합니다. 여기에 관련 어셈블리 코드이다 : 방법의 라인 6에서, 그것은 C 함수 new_recompile_block를 호출, 내 (제한적) 이해에서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] 

(). 이 방법은 정상적으로 작동하며, 기능이 끝날 때

printf("End of loop"); 

이 디버거에 나타납니다. 메서드가 완료된 후에는 어떤 일이 발생하는지 완전히 모르겠지만 어셈블리 메서드가 C 변수 translation_cache_iphone에 대한 참조를 얻는 것으로 보입니다. 그러나 최종 행에서 앱이 이상하게 작동하지 않습니다. http://imgur.com/M5h84

이는 원인이되는 translation_cache_iphone 변수임을 내 생각을지지하는 것 같다 내가 마지막으로 호출 방법에 측면을 클릭하면 http://imgur.com/dqKo0

그러나, 나는 그것이 이것이다 참조 :이 메시지는 엑스 코드에 나타납니다 충돌, 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)); 

암 I? 어셈블리 코드 또는 C 코드의 문제입니까? 나는 둘 다 수정하려고했지만 아무 소용이 없습니다. 위의 어셈블리 코드는 원본입니다.

Here is a link 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'가 작동하는 것을 기대하지 않을 것이다. 이것은 당장 문제가되지 않는 것처럼 보입니다. 어셈블러가 그것을 받아들이 겠지만,'MyPointer'와 같이'42430'과'42430b'을 이름으로 바꾸는 것이 더 낫습니다. –

+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] 

첫 번째 줄은 레지스터 R0에 라벨 42,430에서 데이터를로드 . 그런 다음 두 번째 줄은 PC (프로그램 카운터)에서 r0의 내용을 가리 킵니다. 당신이 레이블 42,430 무엇 선언 한 어셈블리 코드의 시작 부분에서

: 그것은이 값을 액세스하고 실행하려고

다음
42430: 
    .long _translation_cache_iphone 

는, 코드로, 그것은 충돌합니다.

+0

이 문제를 해결하는 가장 좋은 방법은 무엇입니까? 나는 42430의 선언이 필수라고 생각했다. 나는 그것을 다른 것으로 선언해야합니까? –

+0

'ldr r0, 42430b'는 r0에 42430을로드하지 않고,'.long _translation_cache_iphone' 지시자는 42430 위치에 있지 않습니다.'42430 :'은 레이블이고,'ldr r0, 42430b'는 데이터를로드하려고 시도합니다 그 레이블에. 그러나 숫자 레이블은 한 자릿수 여야합니다. 나는이 경우 어셈블러가 무엇을 할 것인지 모른다. 또한 위치에서의 로딩이 (재배치 가능성 문제로 인해) 이런 식으로 지원되는지 또는'.long _translation_cache_iphone'으로 정의 된 데이터가 (재배치 가능성 문제로 인해) 올바르게 채워지는지 확신 할 수 없습니다. –

+0

@Eric Postpischil, 당신 말이 맞아요. 그것이 내가 의미하는 바 였지만 혼란스러운 방식으로 썼습니다. 나는 내 대답을 바로 잡을 것이다. – KuramaYoko