name mangling, android ndk jni symbol name problem

간혹 android ndk 를 만들다 보면 name mangling 때문에 문제를 만나게 된다.

Linux 혹은 Android 에서 ndk 를 만들기 위해 library 를 빌드할 일이 있을 경우 symbol name 을 주의해야 한다.

 

해당 library source 는 c 혹은 cpp 형태로 작성할 수 있다.

그런데 Android NDK 를 위해서는 cpp 구조가 아닌 c 구조가 되어야 하며, 함수는 1:1 매칭을 위해 원자화 되어야한다.

만약 cpp 로 코드를 작성하였다면, 빌드된 library 를 살펴보면 symbol name 이 다음과 같은 형태로 나온다.

( library 의 symbol 을 살펴보는 명령어는 nm -D xxx.so , objdump -T xxx.so 이다, 여기서 -D, -T 는 dynamic link 옵션이다 )

 

ndk1

함수 이름은 sendCommand 이다.

하지만 cpp 형태로 빌드된 library의 이름은 _Z11sendCommandxxxx 처럼 변경되어 있다.

이와 같으면 JNI 작업을 할 때 함수명을 찾지 못하는 경우가 발생한다.

위 문제를 해결하기 위해서는 cpp 형식을 c 형식으로 변경해 주어야 한다.

 

방법은 의외로 간단한다.

header 파일의 함수가 기술되어 있는 부분을 extern “C” 로 감싸주기만 하면 된다.

 

ndk2

그 후 library를 살펴보면 함수명이 변경되어있지 않다.

 

이와 같은 현상은 “name mangling” 이라고 한다.

“name mangling” 이란 compiler 가 함수들의 이름을 임의로 변경하는 것을 의미한다.

c++ 에서는 function overloading 등의 기능이 추가되었는데, 이를 지원하기 위해서 compiler 는 내부적으로 함수 이름을 변경하는 것이다.

 

각 컴파일러 별로 mane mangling 하는 규칙은 wiki 에 잘 정리되어 있다. (https://en.wikipedia.org/wiki/Name_mangling)

Compiler void h(int) void h(int, char) void h(void)
Intel C++ 8.0 for Linux _Z1hi _Z1hic _Z1hv
HP aC++ A.05.55 IA-64
IAR EWARM C++ 5.4 ARM
GCC 3.x and higher
IAR EWARM C++ 7.4 ARM _Z<number>hi _Z<number>hic _Z<number>hv
GCC 2.9x h__Fi h__Fic h__Fv
HP aC++ A.03.45 PA-RISC
Microsoft Visual C++ v6-v10 (mangling details) ?h@@YAXH@Z ?h@@YAXHD@Z ?h@@YAXXZ
Digital Mars C++
Borland C++ v3.1 @h$qi @h$qizc @h$qv
OpenVMS C++ V6.5 (ARM mode) H__XI H__XIC H__XV
OpenVMS C++ V6.5 (ANSI mode) CXX$__7H__FIC26CDH77 CXX$__7H__FV2CB06E8
OpenVMS C++ X7.1 IA-64 CXX$_Z1HI2DSQ26A CXX$_Z1HIC2NP3LI4 CXX$_Z1HV0BCA19V
SunPro CC __1cBh6Fi_v_ __1cBh6Fic_v_ __1cBh6F_v_
Tru64 C++ V6.5 (ARM mode) h__Xi h__Xic h__Xv
Tru64 C++ V6.5 (ANSI mode) __7h__Fi __7h__Fic __7h__Fv
Watcom C++ 10.6 W?h$n(i)v W?h$n(ia)v W?h$n()v

 


ps. wiki 에 아직 name mangling 에 대한 한글 페이지가 없다. (일어 페이지는 있다..)

분발하자