함수의 리턴 주소 알아내기

Posted at 2009/03/23 11:16 // in Programming // by Daniel

프로파일링이나 함수 래핑으로 lock등의 작업을 가로채서 로깅할 때 호출한 쪽의 PC값을 알고 싶을 경우가 있습니다.

현재실행되는 함수 입장에서 보면 리턴 주소이죠

이 때 쓸 수 있는 함수가 gcc의 builtin함수로 __builtin_return_address() 입니다.

__builtin_return_address(level)

여기서 level은 call stack 에서 몇번째를 리턴할 것인지에 대한 값입니다.

__builtin_return_address(0) 하면 현재함수의 리턴주소가 나옵니다.

__builtin_return_address(1) 하면 나를 호출한 함수의 리턴주소가 나옵니다...

예제 코드를 짜봤습니다.

#include <stdio.h>
#include <stdlib.h>

int my_func1()
{
    void *addr;
    addr = __builtin_return_address(0);
    printf("1's caller %p\n",addr);
    printf("hello 1\n");
}
int my_func0()
{
    void *addr;
    printf("hello 0\n");
    addr = __builtin_return_address(0);
    printf("0's caller %p\n",addr);
    my_func1();
}

int main(void)
{
    printf("backtrace test\n");
    printf("main: %p\n", (void *)main);
    printf("my_func0: %p\n", (void *)my_func0);
    printf("my_func1: %p\n", (void *)my_func1);
    my_func0();
    return 0;
}


이 소스코드를 컴파일해서 objdump해보면

080483d1 <my_func0>:
...
80483fc:   e8 a3 ff ff ff          call   80483a4 <my_func1>
8048401:   c9                      leave
8048402:   c3                      ret

08048403 <main>:
...

804845c:   e8 70 ff ff ff          call   80483d1 <my_func0>
8048461:   b8 00 00 00 00          mov    $0x0,%eax
...

이와 같이 호출하게 되어있고

실행해보면

backtrace test
main: 0x8048403
my_func0: 0x80483d1
my_func1: 0x80483a4
hello 0
0's caller 0x8048461
1's caller 0x8048401
hello 1

이렇게 나옵니다. call 바로 다음 주소--리턴 주소가 나오지요.

이외에도 몇가지 builtin함수들이 있습니다.

예를 들어 __builtin_frame_address(level)은 프레임 포인터를 반환합니다.


관련 포스트 :

gcc 컴파일 옵션으로 커스텀 프로파일 해서 실행 트레이스 뽑기

크리에이티브 커먼즈 라이센스
Creative Commons License