ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [컴파일] 네임 맹글링 (Name Mangling, =Name Decoration)
    Legacy/C&C++ 2015. 5. 4. 10:30
    728x90

    [출처] [컴파일] 네임 맹글링 (Name Mangling, =Name Decoration) - http://blog.naver.com/PostView.nhn?blogId=no1rogue&logNo=30095521394


    * 네임 맹글링(Name Mangling)

     ; 프로그램에서 함수나 변수를 선언했을 때, 선언시 사용했던 이름을 컴파일러가 컴파일 단계에서 일정한 규칙을 가지고 변형하는 것으로, 네임 데코레이션(Name Decoration)이라고도 한다.

     네임 맹글링은 주로 C++에서 종종 듣게 되는데, 이 작업은 링커가 다른 범위(Scope)에 있는 '같은 이름의 함수 및 변수'들에 대해 구별을 가능하게 해준다. 다른 범위라는 것의 예를 들면 다른 파일이나 다른 네임 스페이스가 다른 경우를 들 수 있으며, 같은 범위 내에서는 함수 오버로딩의 예를 들 수 있다. 객체 지향에서 오버로딩 시 같은 함수명도 어떻게 구별되는 원리는 인자의 형식과 갯수가 다를 경우 네임 맹글링을 통해 함수나 변수명 뒤에 추가정보가 붙어 구별이 되는 것이다. 그 덕분에 네임 맹글링에 의해 새로 생성된 함수 및 변수명에서 역으로 원래의 함수나 변수 타입이 확인 가능하다.

     이 네임 맹글링은 C 컴파일러와 C++ 컴파일러가 다를 뿐더러 C++ 컴파일러끼리도 회사마다 네임 맹글링 규칙이 다르다. 그래서 정형화된 규칙이 없다. 리버스 엔지니어링을 비롯한 역어셈블리 작업중 네임 맹글링된 변수명의 원형을 알아보기 위해 규칙에 대한 자료가 필요할 수 있는데 그 때는 각 컴파일러 문서를 구해야 할 경우가 생길지도 모른다. 하지만 이런 경우를 대비해서인지 컴파일러 자체에서 디맹글링을 해주는 유틸리티가 존재한다. 대표적인 컴파일러로 예를 들면 MS의 VC++은 'undname'을, 리눅스 계열에서 주로 사용하는 GNU 컴파일러는 'nm'에 '--demangle' 옵션을 줘서 함수의 원래 형태를 확인 가능하다.

     

    cf) 디맹글링 형식 : VC++ ->  'undname 맹글링된 함수 및 변수명'

                                              GNU   ->  'nm --demangle 목적파일(.o)'

     

    ex) VC++에서  

                     void __cdecl TestFunc(char*)  <-> ?TestFunc@@YAXPAD@Z

            Y는 함수호출 거리가 가깝다는 것을 나타내고, A는 콜링 컨벤션이 __cdecl이고....이런 식의

            정보를 나타내는 것이다.

     

    DLL과 같이 C와 각기 다른 컴파일러로 컴파일된 이미지를 상호 간에 사용해야 할 경우 C, C++ 컴파일러의 차이로 인해 생성되는 네임맹글링이 다른 이유로 extern "C" linkage Secifier를 선언해서 C언어 디폴트 네임 맹글링 형식으로 만들어 서로 호환되게 사용한다.

     

     

    * C언어 (디폴트) 네임 맹글링

     ; C에서는 네임 맹글링이라는 표현보다 네임 데코레이션이라는 용어가 더 익숙하다. C도 네임 맹글링을 하기는 하지만 C++에 비하면 상당히 단순하다. 콜링 컨벤션에 따른 차이 밖에 없기 때문이다.

     - __cdecl

     ; 디폴트 콜링 컨벤션이다. 함수 앞에 '_'만 추가 된다.

       ex> void TestFunc(int a)         <->     _TestFunc

     - stdcall

     ; 주로 윈도우즈에서 사용되는 형식이다. (매크로 'WINAPI', 'CALLBACK'이 바로 __stdcall을

       #define 한 것이다...) 함수 이름앞에 '_'를 붙이고 마지막에 @과 인자의 바이트 합 숫자를 붙인다.

       ex> void TestFunc(int a, char *b)    <->   _TestFunc@8    //int 4바이트, char 포인터형 4바이트

     

    => extern "C"를 사용하고 __declspec(dllexport) 지시어를 사용하여 DLL을 만든 경우 주의 할 점이 있다. 윈도우용으로 제작할 경우 WINAPI 매크로를 붙일 경우가 생기는데 이 경우 __stdcall 방식이 되므로 @와 바이트 합이 붙어져서 함수 포인터를 이용하는 명시적 연결시 함수명이 맞지 않게 된다. 즉 함수명뒤에 인자의 바이트 합이 붙게되어 함수명 만으로 접근이 않된다. 그러므로 extern "C"를 사용하고 __declspec(dllexport) 지시어를 사용하여 DLL을 만든 경우 명시적 연결을 할 때는 'dumpbin /exports 연결할 DLL파일명'을 이용해DLL에 실질적으로 생성된 함수명을 확인한 후 연결해야 할 것이다.


    [출처] [컴파일] 네임 맹글링 (Name Mangling, =Name Decoration)|작성자 깡


Designed by Tistory.