맨위로가기

Nm (유닉스)

"오늘의AI위키"는 AI 기술로 일관성 있고 체계적인 최신 지식을 제공하는 혁신 플랫폼입니다.
"오늘의AI위키"의 AI를 통해 더욱 풍부하고 폭넓은 지식 경험을 누리세요.

1. 개요

nm은 유닉스 운영체제에서 사용되는 명령어로서, 오브젝트 파일, 실행 파일, 라이브러리 파일 등에서 심볼 테이블 정보를 출력한다. nm은 주로 C 및 C++ 코드를 컴파일한 후 생성되는 오브젝트 파일(.o)의 심볼 정보를 확인하는 데 사용되며, 각 심볼의 이름, 주소, 유형 등을 보여준다. C++에서는 이름 맹글링으로 인해 C와 다른 출력 결과를 보이며, 심볼 유형은 전역 절대 심볼(A), 전역 bss 심볼(B), 전역 데이터 심볼(D), 전역 텍스트 심볼(T) 등과 같은 다양한 유형으로 분류된다.

더 읽어볼만한 페이지

  • 유닉스 프로그래밍 도구 -
    펄은 래리 월이 개발한 텍스트 조작에 강점을 가진 다목적 프로그래밍 언어이며, 1987년 펄 1.0이 처음 공개된 이후 여러 버전 업데이트를 거쳐 객체 지향 프로그래밍과 유니코드 지원 기능을 추가했고, 현재 펄 5가 널리 사용되며 CPAN을 통해 방대한 모듈 생태계를 제공한다.
  • 유닉스 프로그래밍 도구 - GNU 컴파일러 모음
    GNU 컴파일러 모음(GCC)은 리처드 스톨먼이 1987년 처음 출시한 자유 소프트웨어 컴파일러 시스템으로, C, C++, Fortran, Ada, Go 등 다양한 프로그래밍 언어를 지원하며 여러 명령어 집합 아키텍처와 플랫폼에서 널리 사용된다.
  • 유닉스 SUS2008 유틸리티 - AWK
    AWK는 1977년에 개발된 텍스트 처리 및 프로그래밍 언어로, 유닉스 환경에서 텍스트 처리를 위해 설계되었으며 정규 표현식 처리 기능을 통해 텍스트 분석, 데이터 추출, 보고서 생성 등 다양한 작업을 수행한다.
  • 유닉스 SUS2008 유틸리티 - 로케일
    로케일은 소프트웨어 국제화 및 지역화에서 사용자 문화적 배경에 맞춰 사용 환경을 조정하는 설정으로, 표시 언어, 숫자/날짜 형식, 문자 분류, 통화 형식 등을 포함한다.
Nm (유닉스) - [IT 관련 정보]에 관한 문서
개요
명칭nm (유닉스)
종류유닉스 명령어
영문 명칭nm (Unix)
소프트웨어 정보
이름nm
저자데니스 리치, 켄 톰슨 (AT&T 벨 연구소)
개발자다양한 오픈 소스 및 상용 개발자
출시일1971년 11월 3일
프로그래밍 언어C
운영 체제유닉스, 유닉스 계열, Plan 9
플랫폼크로스 플랫폼
장르명령어
라이선스Plan 9: MIT 라이선스
웹사이트나우루 공식 홈페이지

2. nm 출력 예제

`nm` 명령어는 오브젝트 파일이나 실행 파일에 포함된 심볼 테이블 정보를 출력하는 유닉스 및 유닉스 계열 운영체제의 표준 명령어이다. 개발 과정에서 특정 함수나 변수가 오브젝트 파일에 어떻게 기록되었는지, 또는 라이브러리 파일이 어떤 심볼들을 외부에 제공하는지 등을 확인할 때 유용하게 사용된다.

아래 하위 섹션에서는 동일한 소스 코드를 C 컴파일러(gcc)와 C++ 컴파일러(g++)로 각각 컴파일한 후, 생성된 오브젝트 파일(`test.o`)에 대해 `nm` 명령어를 실행했을 때의 출력 결과를 보여준다. 이를 통해 C와 C++ 컴파일러가 심볼을 처리하는 방식의 차이점, 특히 C++의 이름 맹글링(Name Mangling) 현상을 확인할 수 있다. 또한, `nm` 출력 결과에 나타나는 다양한 심볼 유형(예: `T`, `D`, `B`, `U` 등)의 의미에 대해서도 설명한다.

2. 1. C 코드 예제 및 nm 출력

wikitext



/*

  • 파일 이름: test.c
  • C 코드의 경우 다음 명령어로 컴파일:
  • gcc -c test.c

  • C++ 코드의 경우 다음 명령어로 컴파일:
  • g++ -c test.cpp
  • /


int global_var;

int global_var_init = 26;

static int static_var;

static int static_var_init = 25;

static int static_function()

{

return 0;

}

int global_function(int p)

{

static int local_static_var;

static int local_static_var_init=5;

local_static_var = p;

return local_static_var_init + local_static_var;

}

int global_function2()

{

int x;

int y;

return x+y;

}

#ifdef __cplusplus

extern "C"

#endif

void non_mangled_function()

{

// 아무것도 하지 않음

}

int main(void)

{

global_var = 1;

static_var = 2;

return 0;

}



위 C 코드를 gcc C 컴파일러로 컴파일(`gcc -c test.c`)하면, `nm` 명령(`nm test.o`)의 출력은 다음과 같다.



# nm test.o

0000000a T global_function

00000025 T global_function2

00000004 C global_var

00000000 D global_var_init

00000004 b local_static_var.1255

00000008 d local_static_var_init.1256

0000003b T main

00000036 T non_mangled_function

00000000 t static_function

00000000 b static_var

00000004 d static_var_init



반면, C++ 컴파일러(`g++ -c test.cpp`)를 사용하면 이름 맹글링(Name mangling) 때문에 출력 결과가 달라진다.



# nm test.o

0000000a T _Z15global_functioni

00000025 T _Z16global_function2v

00000004 b _ZL10static_var

00000000 t _ZL15static_functionv

00000004 d _ZL15static_var_init

00000008 b _ZZ15global_functioniE16local_static_var

00000008 d _ZZ15global_functioniE21local_static_var_init

U __gxx_personality_v0

00000000 B global_var

00000000 D global_var_init

0000003b T main

00000036 T non_mangled_function



C++ 코드에서 `non_mangled_function` 함수는 `extern "C"` 선언 덕분에 이름 맹글링이 적용되지 않아 C 컴파일러 결과와 동일한 심볼 이름(`non_mangled_function`)을 유지하는 것을 볼 수 있다. 이는 C와 C++ 코드를 함께 사용할 때 링킹 오류를 방지하고 호환성을 유지하기 위한 중요한 기법이다.

`nm` 출력에서 각 심볼 앞의 영문자는 심볼 유형을 나타낸다. 주요 심볼 유형과 그 의미는 다음과 같다.

심볼 유형
심볼 유형설명
A전역 절대 심볼 (Global absolute symbol): 주소가 변경되지 않는 전역 심볼.
a지역 절대 심볼 (Local absolute symbol): 주소가 변경되지 않는 지역(정적) 심볼.
B전역 BSS 심볼 (Global BSS symbol): 초기화되지 않은 데이터 섹션(BSS segment)에 위치하는 전역 심볼.
b지역 BSS 심볼 (Local BSS symbol): 초기화되지 않은 데이터 섹션에 위치하는 지역(정적) 심볼.
D전역 데이터 심볼 (Global data symbol): 초기화된 데이터 섹션(Data segment)에 위치하는 전역 심볼.
d지역 데이터 심볼 (Local data symbol): 초기화된 데이터 섹션에 위치하는 지역(정적) 심볼.
f소스 파일 이름 심볼 (Source file name symbol): 디버깅 정보에 사용되는 소스 파일 이름.
L전역 스레드 로컬 심볼 (Global Thread-Local Storage symbol): 스레드 지역 저장소(Thread-Local Storage, TLS)를 사용하는 전역 심볼.
l정적 스레드 로컬 심볼 (Static Thread-Local Storage symbol): 스레드 지역 저장소를 사용하는 정적(지역) 심볼.
R전역 읽기 전용 심볼 (Global read-only symbol): 읽기 전용 데이터 섹션(Rodata)에 위치하는 전역 심볼.
r지역 읽기 전용 심볼 (Local read-only symbol): 읽기 전용 데이터 섹션에 위치하는 지역(정적) 심볼.
T전역 텍스트(코드) 심볼 (Global text symbol): 코드 섹션(Text segment)에 위치하는 전역 함수 또는 기타 코드 심볼.
t지역 텍스트(코드) 심볼 (Local text symbol): 코드 섹션에 위치하는 지역(정적) 함수 또는 기타 코드 심볼.
U정의되지 않은 심볼 (Undefined symbol): 현재 파일 외부(다른 파일이나 라이브러리)에 정의된 심볼. 링커가 해결해야 한다.


2. 2. C++ 코드 예제 및 nm 출력

아래 코드를 g++ C++ 컴파일러로 컴파일할 경우, C 컴파일러와 다른 결과가 나타난다.

```c

/*

  • 파일 이름: test.c (C++ 컴파일 시 test.cpp로 사용 가능)
  • C 코드의 경우 다음 명령어로 컴파일:
  • gcc -c test.c

  • C++ 코드의 경우 다음 명령어로 컴파일:
  • g++ -c test.cpp
  • /


int global_var;

int global_var_init = 26;

static int static_var;

static int static_var_init = 25;

static int static_function()

{

return 0;

}

int global_function(int p)

{

static int local_static_var;

static int local_static_var_init=5;

local_static_var = p;

return local_static_var_init + local_static_var;

}

int global_function2()

{

int x;

int y;

return x+y;

}

#ifdef __cplusplus

extern "C"

#endif

void non_mangled_function()

{

// 아무것도 하지 않음

}

int main(void)

{

global_var = 1;

static_var = 2;

return 0;

}

```

만약 위 코드를 C 컴파일러(gcc)로 컴파일하면 (`gcc -c test.c`), `nm` 명령의 출력은 다음과 같다.

```console

# nm test.o

0000000a T global_function

00000025 T global_function2

00000004 C global_var

00000000 D global_var_init

00000004 b local_static_var.1255

00000008 d local_static_var_init.1256

0000003b T main

00000036 T non_mangled_function

00000000 t static_function

00000000 b static_var

00000004 d static_var_init

```

그러나 C++ 컴파일러(g++)를 사용하여 컴파일하면 (`g++ -c test.cpp`), 출력 결과는 아래와 같이 달라진다.

```console

# nm test.o

0000000a T _Z15global_functioni

00000025 T _Z16global_function2v

00000004 b _ZL10static_var

00000000 t _ZL15static_functionv

00000004 d _ZL15static_var_init

00000008 b _ZZ15global_functioniE16local_static_var

00000008 d _ZZ15global_functioniE21local_static_var_init

U __gxx_personality_v0

00000000 B global_var

00000000 D global_var_init

0000003b T main

00000036 T non_mangled_function

```

이러한 출력 결과의 차이는 C++의 이름 맹글링(Name Mangling) 때문이다. C++는 함수 오버로딩과 같은 기능을 지원하기 위해 컴파일 시 함수나 변수의 이름을 내부적으로 변경하는데, 이 과정을 이름 맹글링이라고 한다. `_Z15global_functioni`와 같은 심볼 이름이 그 예시다.

코드 예제의 `non_mangled_function` 함수는 `#ifdef __cplusplus`와 `extern "C"` 블록 안에 선언되어 있어 C++ 컴파일러를 사용하더라도 이름 맹글링이 적용되지 않고 C 방식의 심볼 이름(`non_mangled_function`)을 유지하는 것을 볼 수 있다. 이는 C와 C++ 코드를 함께 사용할 때 호환성을 유지하기 위한 일반적인 방법이다.

2. 3. 이름 맹글링과 extern "C"

C++에서는 함수 오버로딩과 같은 기능을 지원하기 위해 컴파일러가 함수나 변수의 이름을 특정 규칙에 따라 변경하는 이름 맹글링(Name Mangling) 과정을 거친다. 이는 같은 이름을 가진 여러 함수를 구별할 수 있게 해주지만, C 코드와의 호환성 문제 등을 일으킬 수 있다.

아래는 간단한 C/C++ 코드 예시이다.



/*

  • 파일 이름: test.c
  • C 코드의 경우 다음 명령어로 컴파일:
  • gcc -c test.c

  • C++ 코드의 경우 다음 명령어로 컴파일:
  • g++ -c test.cpp
  • /


int global_var;

int global_var_init = 26;

static int static_var;

static int static_var_init = 25;

static int static_function()

{

return 0;

}

int global_function(int p)

{

static int local_static_var;

static int local_static_var_init=5;

local_static_var = p;

return local_static_var_init + local_static_var;

}

int global_function2()

{

int x;

int y;

return x+y;

}

#ifdef __cplusplus

extern "C"

#endif

void non_mangled_function()

{

// 아무것도 하지 않음

}

int main(void)

{

global_var = 1;

static_var = 2;

return 0;

}



이 코드를 gcc C 컴파일러로 컴파일한 후 `nm` 명령어로 심볼 테이블을 확인하면 다음과 같은 결과를 얻을 수 있다.



# nm test.o

0000000a T global_function

00000025 T global_function2

00000004 C global_var

00000000 D global_var_init

00000004 b local_static_var.1255

00000008 d local_static_var_init.1256

0000003b T main

00000036 T non_mangled_function

00000000 t static_function

00000000 b static_var

00000004 d static_var_init



하지만 동일한 코드를 C++ 컴파일러(예: g++)로 컴파일하면 이름 맹글링이 적용되어 심볼 이름이 달라진다.



# nm test.o

0000000a T _Z15global_functioni

00000025 T _Z16global_function2v

00000004 b _ZL10static_var

00000000 t _ZL15static_functionv

00000004 d _ZL15static_var_init

00000008 b _ZZ15global_functioniE16local_static_var

00000008 d _ZZ15global_functioniE21local_static_var_init

U __gxx_personality_v0

00000000 B global_var

00000000 D global_var_init

0000003b T main

00000036 T non_mangled_function



C 컴파일 결과와 비교해보면, `global_function`은 `_Z15global_functioni`로, `global_function2`는 `_Z16global_function2v`로 이름이 변경된 것을 확인할 수 있다. 이는 C++ 컴파일러가 함수의 인자 타입 정보 등을 포함하여 이름을 재구성했기 때문이다.

C++ 코드에서 이름 맹글링을 방지하고 C 방식의 심볼 이름을 사용하고 싶을 때는 `extern "C"` 선언을 사용한다. 예제 코드의 `non_mangled_function` 함수는 `#ifdef __cplusplus` 조건문과 함께 `extern "C"`로 선언되었기 때문에, C++ 컴파일러로 컴파일해도 C 컴파일 결과와 동일하게 `non_mangled_function`이라는 원래 이름을 유지한다. 이는 C와 C++ 코드를 함께 사용하거나, C 라이브러리를 C++ 프로젝트에서 링크할 때 중요한 역할을 한다.

3. 심볼 유형

아래 코드는 `nm` 명령어의 출력을 보여주기 위한 예시이다.



/*


  • 파일 이름: test.c
  • C 코드의 경우 다음 명령어로 컴파일:
  • gcc -c test.c

  • C++ 코드의 경우 다음 명령어로 컴파일:
  • g++ -c test.cpp
  • /


int global_var;

int global_var_init = 26;

static int static_var;

static int static_var_init = 25;

static int static_function()

{

return 0;

}

int global_function(int p)

{

static int local_static_var;

static int local_static_var_init=5;

local_static_var = p;

return local_static_var_init + local_static_var;

}

int global_function2()

{

int x;

int y;

return x+y;

}

#ifdef __cplusplus

extern "C"

#endif

void non_mangled_function()

{

// 아무것도 하지 않음

}

int main(void)

{

global_var = 1;

static_var = 2;

return 0;

}



위 코드를 gcc C 컴파일러로 컴파일하면, `nm` 명령의 출력은 다음과 같다. 각 줄의 첫 번째 문자가 심볼 유형을 나타낸다.



# nm test.o

0000000a T global_function

00000025 T global_function2

00000004 C global_var

00000000 D global_var_init

00000004 b local_static_var.1255

00000008 d local_static_var_init.1256

0000003b T main

00000036 T non_mangled_function

00000000 t static_function

00000000 b static_var

00000004 d static_var_init



반면, C++ 컴파일러(g++)를 사용하면 이름 맹글링 때문에 심볼 이름이 다르게 표시된다. `extern "C"`를 사용한 `non_mangled_function`은 이름 맹글링이 적용되지 않은 것을 확인할 수 있다.



# nm test.o

0000000a T _Z15global_functioni

00000025 T _Z16global_function2v

00000004 b _ZL10static_var

00000000 t _ZL15static_functionv

00000004 d _ZL15static_var_init

00000008 b _ZZ15global_functioniE16local_static_var

00000008 d _ZZ15global_functioniE21local_static_var_init

U __gxx_personality_v0

00000000 B global_var

00000000 D global_var_init

0000003b T main

00000036 T non_mangled_function



`nm` 출력에 나타나는 심볼 유형 문자와 그 의미는 다음과 같다.

심볼 유형
심볼 유형설명
A전역 절대 심볼 (Global absolute symbol). 심볼의 값은 재배치 과정에서 변경되지 않는다.
a지역 절대 심볼 (Local absolute symbol). 위와 같으나, 심볼의 가시성은 해당 파일을 컴파일한 결과물로 제한된다.
B전역 BSS 심볼 (Global BSS symbol). 초기화되지 않은 데이터 섹션(BSS 세그먼트)에 위치한다.
b지역 BSS 심볼 (Local BSS symbol). 전역 BSS 심볼과 같으나, 지역(local) 가시성을 가진다.
D전역 데이터 심볼 (Global data symbol). 초기화된 데이터 섹션에 위치한다.
d지역 데이터 심볼 (Local data symbol). 전역 데이터 심볼과 같으나, 지역 가시성을 가진다.
f소스 파일 이름 심볼 (Source file name symbol).
L전역 스레드 로컬 심볼 (Global thread-local symbol, TLS). 스레드별 데이터 영역에 위치하며 전역 가시성을 가진다.
l정적 스레드 로컬 심볼 (Static thread-local symbol, TLS). 스레드별 데이터 영역에 위치하며 정적(static) 가시성을 가진다.
R전역 읽기 전용 심볼 (Global read-only symbol). 읽기 전용 데이터 섹션에 위치한다.
r지역 읽기 전용 심볼 (Local read-only symbol). 전역 읽기 전용 심볼과 같으나, 지역 가시성을 가진다.
T전역 텍스트 심볼 (Global text symbol). 코드(텍스트) 섹션에 위치한다.
t지역 텍스트 심볼 (Local text symbol). 전역 텍스트 심볼과 같으나, 지역 가시성을 가진다.
U정의되지 않은 심볼 (Undefined symbol). 해당 파일 외부에서 정의된 심볼을 의미한다.




본 사이트는 AI가 위키백과와 뉴스 기사,정부 간행물,학술 논문등을 바탕으로 정보를 가공하여 제공하는 백과사전형 서비스입니다.
모든 문서는 AI에 의해 자동 생성되며, CC BY-SA 4.0 라이선스에 따라 이용할 수 있습니다.
하지만, 위키백과나 뉴스 기사 자체에 오류, 부정확한 정보, 또는 가짜 뉴스가 포함될 수 있으며, AI는 이러한 내용을 완벽하게 걸러내지 못할 수 있습니다.
따라서 제공되는 정보에 일부 오류나 편향이 있을 수 있으므로, 중요한 정보는 반드시 다른 출처를 통해 교차 검증하시기 바랍니다.

문의하기 : help@durumis.com