강좌 & 팁
글 수 2,412
2011.04.09 18:31:19 (*.138.143.120)
48030
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