2013-07-10 3 views
3

빌드 디버그에서) (주 함수의 주소를 취득합니다 : 주()의
주소 : 0x00401000나는 이런 식으로) (주 기능의 주소를 얻으려고

이 디버거에서이다

00401000 /$ 68 00104000 PUSH GetMain.00401000 ; Entry address 
00401005 |. 68 50A14000 PUSH GetMain.0040A150 ; ASCII "0x%p \n" 
0040100A |. E8 8B000000 CALL GetMain.0040109A 

B ut /Zi 옵션으로 컴파일하거나 디버그 빌드를 사용하는 경우 주소가 리디렉션됩니다.
주 주소() : 0x0041178A.

00412530 /> \55      PUSH EBP 
... 
00412539 |. C745 FC 8A174100  MOV [LOCAL.1],GetMain.0041178A ; Entry address 
00412540 |. 8B45 FC     MOV EAX,[LOCAL.1] 
00412543 |. 50      PUSH EAX               
00412544 |. 68 5CEC4200    PUSH GetMain.0042EC5C   ; ASCII "0x%p \n" 

왜 hapenes : 이 주소는 unconditional jump을 행함으로써 얻어지는 실제 주소 0x00412530

이 디버거하에인가?
디버그 빌드에서 코드를 컴파일하면 main() 함수의 실제 주소 (위의 예에서 0x00412530)를 얻는 방법은 무엇입니까?

편집 :
왜 이런 일이 발생합니까? 이미 여기에 답변 : strange level of indirection of a function call

아래의 기능은 내 대답을 해결, Here 내가 답변을 썼습니다.

void *GetMainAddress(void) 
{ 
    void *pMainAddress=(void*)&main;/* address in main() function */ 
    unsigned long calculateJump=0; 
    unsigned char *ptrJump; 
    printf("Address of main() : 0x%08X\n", pMainAddress); 


    ptrJump=(unsigned char*)pMainAddress;/* get pointer to main address */ 
    if(*(unsigned char*)ptrJump == 0xE9)/* address point to jmp opcode ? */ 
    { 
     calculateJump = (*(unsigned long *)(ptrJump+1)); /* get address after 0xe9 */ 
     pMainAddress = ptrJump + calculateJump + 5; /* calculate real address */ 
     printf("Unconditional jump is performed\n"); 
     printf("Actual sddress of main() is: 0x%08X \n", pMainAddress); 
    } 
    else 
    { 
     printf("Unconditional jump is not performed\n"); 
    } 
    return pMainAddress; 
} 
+0

[함수 호출의 간접적 인 수준의] 가능한 복제본 (http://stackoverflow.com/questions/7221855/strange-level-of-indirection-of-function-call) –

+0

나는 생각한다. C++과 달리 C와는 달리'main()'은 재귀 적으로 호출 될 수 없으며 주소를 가져올 수 없습니다. C와 C++ 코드 또는 컴파일러를 혼합하는 경우 조심하십시오 (어쨌든 믹싱이 좋지 않으므로 다른 많은 차이점이 있지만). –

+0

@ VladLazarenko Lazarenko 당신 말이 맞아요,하지만 제 경우에는'main()'을 호출하지 않고 포인터를 그 주소로 가져 가면됩니다. 코드가'/ ZI'로 컴파일되면,'pMainAddress'는 점프 연산 코드에 대한 포인터입니다. 그렇지 않으면 (* Release Build *) -'main() '의 실제 주소입니다. 또한 게시하기 전에 테스트했습니다. 그것은 언어 C와 C++ 모두에서 작동합니다. – boleto

답변

3

기능 주소를 알아야하는 경우 괄호를 생략하십시오. 예를 들어

는 :

int main(){ 
    printf("main is at %p\n", main); 
    return 0; 
} 
+2

엄밀히 말하면'% p'를 사용하여 함수 포인터를 출력해서는 안됩니다. –

+0

왜 안 되니? % p와 % x 사이에 차이가 나는 것 같지 않습니다. – none

+4

정의되지 않은 동작입니다. 하지만 거의 모든 합리적인 기계에서 작동합니다. 관련 표준 : http://stackoverflow.com/questions/2741683/how-to-format-a-function-pointer –

0

Debug Information Format는 비주얼 스튜디오에서 프로젝트 구성에 /ZI로 설정 한 경우 main() 함수의 실제 주소를 얻을 수있는 방법 솔루션입니다.

void *GetMainAddress(void) 
{ 
    void* pMainAddress = (void*)&main; 
    unsigned long calculateJump = 0; 
    unsigned char* ptrJump; 

    ptrJump = (unsigned char*)pMainAddress; 
    if(*(unsigned char*)ptrJump == 0xE9) 
    { 
     calculateJump = (*(unsigned long*)(ptrJump + 1)); 
     pMainAddress = (ptrJump + calculateJump + 5); 
     printf("Unconditional jump is performed\n"); 
     printf("Address of main() : %#x \n", pMainAddress); 
    } 
    else 
    { 
     printf("Unconditional jump is not performed\n"); 
     printf("Address of main() : %#x \n", pMainAddress);  
    } 
    return pMainAddress; 
} 

콘솔 응용 프로그램를 작성하고 솔루션 구성에서 Debug 또는 Release 중 하나를 선택하려면 Visual Studio를 사용하여, 테스트하려면 :
여기 내 기능입니다.
int main()GetAddressOfMain()을 넣고 솔루션을 작성하십시오.

기능은 64 비트 프로젝트 구성에서도 작동하지만 주소를 올바르게 인쇄하려면 적절한 형식 지정자를 사용해야합니다.

관련 문제