Nm (유닉스)
"오늘의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` 명령어의 출력을 보여주기 위한 예시이다.
/*
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