Name mangling에 대한 포스트는 참 많이 있습니다. 하하
오늘한 개삽질을 Demangling 으로 인해 풀게 되어, demangling 팁을 포스팅합니다.
Name mangling이란, 함수의 리턴값, 인자의 개수, 형식을 일정한 형식으로 함수 이름에 편입시키는 일종의 프로토콜입니다.
name mangling으로 인해, c++에서는 (소스상에서)같은 이름을 가진 다른 함수가 존재할 수 있죠.
즉 하나의 소스에
bool function1( int arg1 );
bool function1( int arg1, int arg2 );
void function1( char *arg1 );
void function1( char *arg1, int arg2, int arg3 = 0 );
function1이란 이름을 갖는 네 개의 함수가 공존할 수 있는겁니다.
왜냐하면, 컴파일러가 name mangling을 하고 난 뒤에 저 함수들의 이름은 function1이 아니기 때문입니다.
인자갯수, type, 리턴type, calling convention등이 이름에 포함됩니다.
즉 bool function1( int arg1 ) -> "bool_function1_int" 이렇게 이름 자체가 정보를 갖는다는거죠
저 위 네 개의 함수가 name mangling 되고 나면 각각 함수이름들이 아래와 같이 됩니다.
?function1@@YA_NH@Z
?function1@@YA_NHH@Z
?function1@@YAXPAD@Z
?function1@@YAXPADHH@Z
즉 소스상에선 같은 이름인 것처럼 보였지만 사실은 전혀 다른 이름을 가진 함수가 되는 것입니다.
그럼 우리가 dll을 열어서 export function을 볼 때, name들이 mangling 돼있다면 저런 지저분한 형태로 보이지만,
사실은 함수의 호출규격을 통째로 알려주는 것이나 다름이 없습니다.
그럼 mangling된 함수의 원형을 어떻게 복구할까요?
visual studio에서 demangling tool을 제공합니다.
vs6의 경우 설치폴더\Common\Tools\undname.exe ,
vs2005(vs8)의 경우 설치폴더\vc\bin\undname.exe 에 제공됩니다.
나머지버전은 확인안해봐서 모릅니다. ㅎㅎ undname.exe으로 찾아보세요.
사용법은 간단합니다.
단순 이름만 얻으려면
undname.exe mangled함수명
full 호출 규격을 얻으려면(우리가 원하는바죠)
undname.exe -f mangled함수명
해볼까요?
(mangling하기 싫다면 함수 선언부를 extern "C"{}로 감싸면 컴파일러는 그 곳을 mangling 하지 않습니다.)
그나저나 오늘 한 삽질이란건,
작업하다가 링크에러가 났는데, 원인 파악을 demangle까지 해서 겨우 알아냈습니다.
제가 제작한 라이브러리 헤더에는 인자하나를 DWORD, 즉 unsigned long로 선언했는데,
구현부에서는 int로 쓰고 구현해버린거였습니다 ㅡㅡ;;
코딩시 선언부를 그대로 복사/붙여넣기 하고 수정하는데, 아마 스펙을 바꾸면서 한쪽만 바뀐 것 같습니다.
근데 컴파일이 잘 되더군요. -_-; (error level 최고로 해놓고 쓰는데 warning조차 없습니다)
[DWORD받는 애는 구현안된거고, int 받는 애는 아무도 안쓴거고 이런 상황이겠지만..]
그래서 헤더파일만 보면서 "타입 똑같은데 왜안되는거야" 갑갑해하다가,
답답해서 demangle까지 해봤더니 함수 인자가 int로 돼있는 겁니다.
그래서 원인을 찾게 됐죠.... (대강대강 코딩하는거 들켰군요)
하하
오늘 서울은 첫눈이 내렸습니다. 내일은 출근 안합니다(아싸) 즐거운 주말 되시길