소프트웨어 크리에이티비티 2.0

Posted at 2009/05/25 14:47 // in Programming // by Daniel

http://jhrogue.blogspot.com/2009/05/20.html

소개받은책.

살까나

크리에이티브 커먼즈 라이센스
Creative Commons License
  1. 비밀방문자

    2010/01/27 01:49 [수정/삭제] [답글]

    관리자만 볼 수 있는 댓글입니다.

댓글을 남겨주세요.

[로그인][오픈아이디란?]

함수의 리턴 주소 알아내기

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
  1. 비밀방문자

    2010/01/29 00:47 [수정/삭제] [답글]

    관리자만 볼 수 있는 댓글입니다.

댓글을 남겨주세요.

[로그인][오픈아이디란?]

코드에서 glibc 버전 알아내기

Posted at 2008/08/21 21:19 // in Programming // by Daniel

http://www.technovelty.org/linux/tips/glibc-version.html

실행중에 libc 버전을 봐야 할 경우, contstr을 쓰면 된다고 합니다

#include <stdio.h>

#include <unistd.h>

#include <alloca.h>

#include <string.h>


int main (void)

{

    size_t n = confstr (_CS_GNU_LIBC_VERSION, NULL, 0);

    if (n > 0)

    {

        char *buf = alloca (n);

        confstr (_CS_GNU_LIBC_VERSION, buf, n);

        printf("%s\n", buf);

    }

    return 0;

}

 

실행해 보면
 $ ./a.out
glibc 2.7

이렇게 나옵니다.
또는 돌리는 코드상에서가 아니고 콘솔에서 보고 싶다면 /lib/libc.so.6 파일을 실행해봐도 됩니다.
$ /lib/libc.so.6
GNU C Library stable release version 2.7, by Roland McGrath et al.
Copyright (C) 2007 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 4.2.3 (Ubuntu 4.2.3-2ubuntu7).
Compiled on a Linux >>2.6.24-14-server<< system on 2008-04-04.
Available extensions:
    crypt add-on version 2.1 by Michael Glad and others
    GNU Libidn by Simon Josefsson
    Native POSIX Threads Library by Ulrich Drepper et al
    BIND-8.2.3-T5B
For bug reporting instructions, please see:
<http://www.gnu.org/software/libc/bugs.html>.

그리고 LD_DEBUG를 이용하면 많은 정보를 볼 수 있습니다.

$ LD_DEBUG=help ls
Valid options for the LD_DEBUG environment variable are:

  libs        display library search paths
  reloc       display relocation processing
  files       display progress for input file
  symbols     display symbol table processing
  bindings    display information about symbol binding
  versions    display version dependencies
  all         all previous options combined
  statistics  display relocation statistics
  unused      determined unused DSOs
  help        display this help message and exit

To direct the debugging output into a file instead of standard output
a filename can be specified using the LD_DEBUG_OUTPUT environment variable.


예를 들어 아까의 a.out을 실행하면

$ LD_DEBUG=versions ./a.out
      1565:     checking for version `GLIBC_2.4' in file /lib/tls/i686/cmov/libc.so.6 [0] required by file ./a.out [0]
      1565:     checking for version `GLIBC_2.0' in file /lib/tls/i686/cmov/libc.so.6 [0] required by file ./a.out [0]
      1565:     checking for version `GLIBC_PRIVATE' in file /lib/ld-linux.so.2 [0] required by file /lib/tls/i686/cmov/libc.so.6 [0]
      1565:     checking for version `GLIBC_2.3' in file /lib/ld-linux.so.2 [0] required by file /lib/tls/i686/cmov/libc.so.6 [0]
      1565:     checking for version `GLIBC_2.1' in file /lib/ld-linux.so.2 [0] required by file /lib/tls/i686/cmov/libc.so.6 [0]
      1565:
      1565:     calling init: /lib/tls/i686/cmov/libc.so.6
      1565:
      1565:
      1565:     initialize program: ./a.out
      1565:
      1565:
      1565:     transferring control: ./a.out
      1565:
glibc 2.7
      1565:
      1565:     calling fini: ./a.out [0]
      1565:
      1565:
      1565:     calling fini: /lib/tls/i686/cmov/libc.so.6 [0]
      1565:

이런 식으로 나옵니다.
크리에이티브 커먼즈 라이센스
Creative Commons License
  1. gamilla

    2008/08/22 10:36 [수정/삭제] [답글]

    ^^ 알고싶던 정보였는데... 감사합니다~

  2. Daniel

    2008/08/24 02:16 [수정/삭제] [답글]

    댓글 감사합니다.
    뭘요 제가 필요해서 적은건데,, 도움이 됐다니 좋네요

댓글을 남겨주세요.

[로그인][오픈아이디란?]