gcc 확장기능 이용하기 - __builtin_return_address
gcc의 확장기능에는 대표적인 세가지 기능이 있습니다.
builtin , attribute, lable 이렇게 세가지인데 한가지씩 살펴보도록 알아보도록 합니다.
void *__builtin_return_address(unsigned int LEVEL)
이 함수는 리턴수소, 즉 자신을 호출한 함수의 반환 위치 주소를 돌려 줍니다.
arm 으로 하면 현재 상태에서의 lr 을 반환해 주는 것입니다.
매개 변수 LEVEL 은 호출 지점을 몇번 거슬러 올라갈지를 지정합니다.
예제를 봅니다.
 1 #include <stdio.h>
 2 
 3 void depth_0(void)
 4 {
 5     void *where;
 6 
 7     where = __builtin_return_address(0);
 8 
 9     printf("%s where %p\n", __FUNCTION__, where);
10 }
11 
12 void depth_1(void)
13 {
14     void *where;
15 
16     where = __builtin_return_address(1);
17 
18     printf("%s where %p\n", __FUNCTION__, where);
19 }
20 
21 int main(void)
22 {
23     void *where;
24 
25     printf("main address %p\n", main);
26 
27     depth_0();
28 
29     return 0;
30 }
31 
실행 결과는 아래와 같습니다.
root@boggle70-desktop:tmp# gcc d0409.c ; ./a.out 
main address 0x804843b
depth_0 where 0x804845e
보시는 것처럼 main 의 주소는 0x804843b  이고 depth_0 를 호출한 지점은 0x804845e 입니다.
검증을 위해 objdump 로 살펴봅니다.
0804843b <main>:
804843b: 55                   push   %ebp
804843c: 89 e5                 mov    %esp,%ebp
804843e: 83 e4 f0             and    $0xfffffff0,%esp
8048441: 83 ec 20             sub    $0x20,%esp
8048444: b8 3d 85 04 08       mov    $0x804853d,%eax
8048449: c7 44 24 04 3b 84 04 movl   $0x804843b,0x4(%esp)
8048450: 08 
8048451: 89 04 24             mov    %eax,(%esp)
8048454: e8 c3 fe ff ff       call   804831c <printf@plt>
8048459: e8 86 ff ff ff       call   80483e4 <depth_0>
804845e: b8 00 00 00 00       mov    $0x0,%eax
8048463: c9                   leave  
8048464: c3                   ret  

main 의 주소는 0804843b 이고
depth_0 의 호출 위치는 8048459
그곳에서 +4 되어 있는 복귀 주소는 804845e 입니다.

위의 소스를 arm 으로 컴파일 하면 에러가 납니다.
__builtin_return_address 를 1이상 줄수 없도록 gcc 가 cross compiler 를 생성했기 때문입니다.
특정 라이브러리가 문제를 일으키는데 어떤 함수에서 호출되었는지 모르는 경우 위의 코드를 사용하여
호출한 함수를 확인하여 break point 를 잡는다면 디버깅에 도움이 될수 있을 것 같습니다.
참조및 출처  : Binary Hacks - O'REILLY