Posts Tagged ‘gcc’

함수의 리턴 주소 알아내기

월요일, 3월 23rd, 2009

프로파일링이나 함수 래핑으로 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    $0×0,%eax

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

실행해보면

backtrace test
main: 0×8048403
my_func0: 0×80483d1
my_func1: 0×80483a4
hello 0
0’s caller 0×8048461
1’s caller 0×8048401
hello 1

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

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

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

 

관련 포스트 :

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

컴파일러에서 제공하는 기본 설정 매크로 한 번에 보기

화요일, 11월 18th, 2008

gcc -v -E -dM - < /dev/null

이 명령치면 기본 설정된 매크로 가 한 번에 보입니다

http://kldp.org/node/99917

-v는 불필요합니다.

본문과 관련이 있을 것 같은 URL 올립니다.

* http://predef.sourceforge.net/
* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccelng/htm/prepr_18.asp

image

gcc 매크로의 가변 인자 사용하기

일요일, 4월 6th, 2008

춮처 : http://developer.apple.com/documentation/DeveloperTools/gcc-4.0.1/cpp/Variadic-Macros.html

#define DEBUG
#ifdef DEBUG
#define DBG(…)    fprintf(stderr, __VA_ARGS__)
#else
#define DBG(…)    do{}while(0)
#endif

이런식으로 사용합니다.

C99 표준이라고 돼 있고 gcc 4.0부터는 확실히 이렇게 쓰는 것 같습니다.

gcc가 이전부터 사용하는 것과 맞추려면(C99표준은 아닌 것 같습니다)

#define eprintf(format, args…) fprintf (stderr, format , ##args)

이런식으로 쓰라는군요

## args 전에는 콤마(,)와 빈칸이 꼭 있어야 한답니다.