현재 실행되고 있는 함수이름을 알고 싶은데...

bugger의 이미지

안녕하세여..

예를 들어..

------------------------------------------
void sub_test()
{
}
void test()
{
sub_test();
}
int main()
{

test();

}
-------------------------------------
이런 프로그램이 실행되고 있고 실행하고 있는 지점이 sub_test라는 펑션에서 실행되고 있다고 가정하면스택에는 main- test-sub_test 네임이
있을것입니다..

스텍에 있는 main-test-sub_test라는 값을 얻어오는 방법이 없다요?

-.-;;

좋은 하루보네세요

bugiii의 이미지

OS, 컴파일러를 알려주시면 많은 분들이 답해주시리라 믿습니다.

bugger의 이미지

OS는 리눅스, 솔라리스이고 컴파일러는 gcc 또는 g++입니다.

아.. OS나 컴파일러의 차이도 있군여... -.-;;

pynoos의 이미지

$ cat dumpstack.c
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>

struct _functions
{
        void * addr;
        char name[512];
        struct _functions * next;
};
static struct _functions * s_funcs;

static void release_funcs()
{
        struct _functions * p = 0;
        struct _functions * q = 0;
        if( !s_funcs )
        {
                return;
        }
        for( p = q = s_funcs; p; p = q )
        {
                q = p->next;
                free( p );
        }
}void build_symbols()
{
        char buf[4096];
        FILE *f;
        struct _functions * p = 0;
        snprintf( buf, sizeof buf, "ps | grep %d | awk '{print \"nm -Cn\", $NF}' | sh", getpid() );
        f = popen( buf, "r" );
        while( fgets( buf, sizeof buf, f ) )
        {       
                char func[4096];
                long addr;
                char type;

                if( buf[0] == ' ' )
                {       
                        continue;
                }       

                sscanf( buf, "%lx %c", & addr, &type );
                strncpy(func, buf + 11, sizeof func ); 
                func[strlen(func)-1] = '\0'; 

                if( type != 't' && type != 'T' )
                {       
                        continue;
                }       
                if( !s_funcs )
                {       
                        s_funcs = ( struct _functions * ) calloc( 1, sizeof( struct _functions ));
                        p = s_funcs;
                }       
                p->addr = (void *) addr;
                strncpy( p->name, func, sizeof p->name );
                p->next = ( struct _functions * ) calloc( 1, sizeof( struct _functions ));
                p = p->next;
        }       
        pclose(f);
        atexit( release_funcs );
}

static const char * get_func_name( void * addr )
{
        struct _functions * p = 0;
        for( p = s_funcs; p->next; p = p->next )
        {
                if( p->addr <= addr && p->next->addr >= addr )
                {
                        return p->name;
                }
        }
        return "????";
}

void dump_stack()
{
        int stackcount = 0;
        unsigned long * addr;

        system("set");
        if( !s_funcs )
        {
                build_symbols();
        }
        if( !s_funcs )
        {
                abort();
        }
        asm 
        (
                "mov %%ebp, %0"
                : "=r" (addr)
                :
        );
        for( stackcount = 0; ; stackcount++ )
        {
                const char * func = get_func_name((void *)*(addr+1));
                printf( "%d: %s\n", stackcount, func );
                addr = (unsigned long *)(*addr);
                if( strcmp( func, "_start" ) == 0 )
                {
                        return;
                }
        }
}

저도 평소에 필요해서 만들어 볼까도 했는데, 문제를 보고 한번 살짝 구현해보았습니다.

Linux 에서만 됩니다. inline asm 있어서...

사용법은 main 들어가자마자 build_symbols() 한번 호출해주고, 원하는 곳에서 dump_stack(); 을 호출하면 됩니다.

외부 프로그램으로 nm을 사용하는 것에 의존하므로, libc의 함수등은 trace되지 않습니다.

참고로 header는 없는데,
void build_symbols();
void dump_stack();

을 만드시고, C++ 이라면, Name mangling을 피하기 위해 앞에 extern "C" 등을넣어 주시면 됩니다.

근데 이게 원하는 답인가요?

dhjung의 이미지

원하시는 용도정도라면, target os가 리눅스와 솔라리스이니.. 오히려, 간단하게 pstack 명령어로 하는게 낫지 않을까요??


--------------------------
Donghyun Jung

pynoos의 이미지

pstack .. 이런 좋은것이 있었군요.. 8)
아.. 시간낭비.. 아까워라..

choissi의 이미지

제가 이전에 작성한 글인데,
아마 이거면 될듯하네요..

이지도움에 글이 있는데 저것은 12월 12일 이후에나 보일껍니다..

Quote:

디버거에서 사용하는 기능들이 직접 프로그램이 필요할 때가 있지요..
그런것중에 하나가 바로 backtrace information가 아닐까 싶네요

라이브러리 소스를 찬찬히 뜯어보면,
binary에서 elf 포맷을 읽어 드려서 디버깅 정보를
가공하는 부분과.. backtrace 정보를 캐내는 것이 볼만하죠..

http://freshmeat.net/projects/libbtrace

http://www.ezdoum.com/stories.php?story=02/10/04/0839023

울랄라~ 호기심 천국~!!
http://www.ezdoum.com

bugger의 이미지

움..

pynoos 님... 역시 대단합니다. 존경~~

예효.. 난 언제나... 될까... -.-;;

for1003의 이미지

간단히 함수 이름을 아는 방법이 있습니다.

C99 표준 문서를 보면요.. 6.4.2.2에.. 미리 정의된 식별자 이야기 가 있는데요...

static const char __func__[] = "함수이름";

#include <stdio.h>
void myfunc(void)
{
printf("%s\n", __func__);
/* ... */
}

위의 결과로..
myfunc
가 출력됩니다.

간단하죠?? ^^;;

버려진의 이미지

그 질문이 아닌거 같은데요..?

wooix의 이미지

오.. 멋지네요.

유용한 팁이군요. :)

평온하다~

purewell의 이미지

printf("Function name is \"%s\"\n", __FUNCTION__);

* VC6에서 안 먹습니다.

_____________________________
언제나 맑고픈 샘이가...
http://purewell.biz

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.