【Linux】nmコマンドとは?ファイルのシンボルを確認する

【Linux】nmコマンドとは?ファイルのシンボルを確認する

PR Amazonのアソシエイトとして、ITナレッジライフは適格販売により収入を得ています。

記事の文字数:3,212 / 総アクセス数:1 views

Linuxのnmコマンドの使い方をわかりやすく解説します。オブジェクトファイルや実行ファイルからシンボル(関数や変数)の情報を表示する基本的な使い方や、C++のデマングル、未定義シンボルの特定など、デバッグでの実践的な活用例まで詳しく紹介します。

Linuxユーザにお勧めの本 ↗

最新版

ゼロからはじめるLinuxサーバー構築・運用ガイド 第2版 動かしながら学ぶWebサーバーの作り方

難易度
実用性
最新度

Rocky Linux対応。実際にWebサーバーを公開するまでのプロセスを体験できる、最も確実で実践的なガイドブックです。

初心者向け

わかばちゃんと学ぶ サーバー監視

難易度
実用性
読みやすさ

マンガと図解が中心で圧倒的に読みやすい。負荷調査の手法がスッと理解できるようになります。

新しいLinuxの教科書 第2版

難易度
実用性
読みやすさ

一生モノの基礎知識が身につく定番書です。

ゼロからわかる Linuxコマンド200本ノック―基礎知識と頻出コマンドを無理なく記憶に焼きつけよう!

難易度
実用性
習得度

アウトプット重視で記憶に定着しやすい。反復練習でLinux操作が自由自在になります。

エンジニア1年生のための世界一わかりやすいLinuxコマンドの教科書

難易度
実用性
読みやすさ

プログラムをコンパイルして作成されたオブジェクトファイルや実行ファイル、ライブラリファイルの中に、「どんな関数や変数が含まれているのか」「どの関数が外部から参照されているのか」を確認したい場面があります。

そのようなときに便利なのが nm コマンドです。本記事では、nmコマンドの基本的な使い方から、出力されるシンボルタイプの見方、C++プログラムのデマングル、そしてトラブルシューティングでの実践的な活用例までをわかりやすく解説します。

nmコマンドとは?

nm コマンドは、オブジェクトファイル(.o)、実行可能ファイル、静的ライブラリ(.a)、共有ライブラリ(.so)などに含まれる「シンボル」のリストを表示するコマンドです。

シンボルとは、プログラム内の関数や変数などを識別するための名前や情報です。コンパイラやリンカがどのようにファイルを処理したかを確認できるため、開発中のデバッグや、「未定義の参照(undefined reference)」エラーを解決するための調査に欠かせないツールです。

nmコマンドの基本的な使い方

ターミナルで nm コマンドの後に調べたいファイルパスを指定して実行します。

書式
nm [オプション] [ファイル名]

シンボル情報を表示する

例えば、コンパイル済みの実行ファイル hello のシンボルを確認するには、以下のように実行します。

実行例
nm hello
実行結果(一部抜粋)
00000000004005b6 T main
U printf@@GLIBC_2.2.5
0000000000601038 B uninitialized_var
0000000000601030 D initialized_var

※補足(バージョン付きシンボルの表示について)
printf@@GLIBC_2.2.5 のようにシンボルにバージョン情報が付与されて表示されるかどうかは、システムにインストールされている binutils のバージョンやビルド設定(--with-symbol-versions が有効かなど)に依存します。古い環境や無効化されている環境では、単に printf と表示されることもあります。

出力は左から順に以下の3つの情報で構成されます。

  1. シンボルの値: シンボルに関連付けられた値。多くの場合はアドレスとして表示されますが、シンボルの種類によって意味が異なります。未定義シンボルの場合は通常空白になります。
  2. シンボルのクラス(タイプ): シンボルの種類や状態を表す1文字のアルファベット(大文字はグローバル、小文字はローカル)。
  3. シンボル名: 関数名や変数名。

シンボルクラス(タイプ)の見方

出力される中央の1文字のアルファベットは、そのシンボルがどのような性質のものかを表しています。特によく見る重要なものをいくつか紹介します。

文字意味(大文字はグローバル、小文字はローカル)
T / tText(テキスト)セクション
Text(コード)セクションにあるシンボルを示します。通常、関数などの実行コードが該当します。大文字の T はグローバル(external)シンボル、小文字の t は通常ローカルシンボルを表します。
UUndefined(未定義)
このファイル内では定義されておらず、外部のライブラリや他のオブジェクトファイルからリンクされる予定の関数や変数です(例:printfなど)。
D / dData(データ)セクション
初期値が設定されているグローバル変数や静的変数を示します。
B / bBSSセクション
ゼロ初期化または未初期化のデータを格納するBSSセクションにあるシンボルを示します。
R / rRead-only(読み取り専用)セクション
Read-only data(読み取り専用データ)セクションにあるシンボルを示します。文字列リテラルや読み取り専用データなどが該当することがあります。

※Tips(大文字と小文字の違い)
同じ文字でも、基本的には大文字が外部に公開されている(グローバルな)シンボル小文字がファイル内でのみ有効な(ローカルな)シンボル(C言語の static 関数など)を表します。
ただし、u(unique global symbol)や v(weak object)、w(weak symbol)など、小文字であっても例外的にグローバルシンボルを表す特殊なケースも存在します。

よく使う便利なオプション

nm コマンドには、出力を絞り込んだり見やすくしたりするための強力なオプションが用意されています。

-g(—extern-only):グローバルシンボルのみ表示

外部シンボル(external symbols)のみを表示します。ライブラリなどが外部に提供しているシンボルを確認するときに便利です。

実行例
nm -g libexample.so

-u(—undefined-only):未定義シンボルのみ表示

そのファイル内で参照されているが、定義が存在しないシンボル(U)のみをリストアップします。「このライブラリを使うには、他にどんな外部関数が必要か」を調べる際に役立ちます。

実行例
nm -u program.o

-C(—demangle):C++のシンボル名を人間に読みやすくする

C++で書かれたプログラムをコンパイルすると、オーバーロードや名前空間の情報を保持するために、関数名が「マングリング(名前修飾)」され、複雑な文字列(例:_Z4funcid など)に変換されます。 -C オプションを付けると、これを元の読みやすいC++の関数名(デマングル)に復元して表示してくれます。

実行例(マングルされた状態)
nm program | grep func
# 出力例: 0000000000401122 T _Z4funcid
実行例(-Cでデマングルした状態)
nm -C program | grep func
# 出力例: 0000000000401122 T func(int, double)

-A(—print-file-name):ファイル名を行の先頭に付与する

複数のファイルを対象に nm を実行する際、どのシンボルがどのファイルに含まれているのか分かりにくくなります。-A オプション(-o--print-file-name も同じ意味)を付けると、各シンボルの行の先頭にファイル名が付与されるため、grepコマンドで検索する際にどこでヒットしたか一目で分かります。

実行例
nm -A *.o | grep "main"

トラブルシューティングでの実践的な活用例

実務において、nmコマンドは主にビルドエラーの調査やライブラリの依存関係チェックで活躍します。

「未定義の参照(undefined reference)」エラーの調査

C/C++プログラムのリンク時に undefined reference to 'hoge_function' というエラーが出た場合、指定したライブラリの中に本当に hoge_function が含まれているか(実装されているか)を nm で確認します。

調査コマンド
nm -g libtest.a | grep hoge_function

もし何も出力されなければ、そのライブラリには関数が含まれていないため、リンクするライブラリが間違っているか、ソースコードが正しくコンパイルされていません。出力されても U(未定義)となっていれば、そのシンボルを別のオブジェクトファイルやライブラリなどから解決する必要があります。

特定の関数がどのライブラリに含まれているかを探す

システム上に複数のライブラリ(.so や .a)が存在し、目的の関数(例:SSL_connect)がどのファイルで提供されているか分からない場合、ディレクトリ内のすべてのライブラリに対して検索をかけます。

Terminal window
nm -D -A /usr/lib/*.so 2>/dev/null | grep " T SSL_connect"

※これにより、SSL_connect というシンボルを定義している共有ライブラリを検索できます。T はText(コード)セクションにあるシンボルを示します。-A オプションでファイル名を行頭に表示し、2>/dev/null で標準エラー出力を破棄しています。

まとめ

nm コマンドのポイントは以下の通りです。

  • オブジェクトファイルやライブラリから、関数や変数などの「シンボル」情報を抽出して表示する。
  • シンボルのタイプを確認することで、そのシンボルが定義されているか(例:T、**未定義で外部から解決する必要があるか(U)**を確認できる。
  • C++プログラムを解析する場合は、-C オプションでシンボル名を読みやすく(デマングル)できる。
  • リンク時のエラー調査や、特定の関数を提供するライブラリを探す際に非常に重宝する。

コンパイラが裏側で何を行っているのかを覗き見ることができる強力なコマンドです。C/C++の開発だけでなく、他の言語で作成されたバイナリやネイティブ拡張の挙動を調査する際にもぜひ活用してみてください。


以上で本記事の解説を終わります。
よいITライフを!
ITナレッジライフ 運営者
この記事を書いた人

Z (ITナレッジライフ)

現役のITエンジニア。Linux、プログラミング、IT用語など、日々の業務で得た「痒いところに手が届く」技術情報を発信しています。

プロフィールと編集ポリシーを見る

Linuxユーザにお勧めの本 ↗

最新版

ゼロからはじめるLinuxサーバー構築・運用ガイド 第2版 動かしながら学ぶWebサーバーの作り方

難易度
実用性
最新度

Rocky Linux対応。実際にWebサーバーを公開するまでのプロセスを体験できる、最も確実で実践的なガイドブックです。

人気記事


記事を評価

Thanks!
目次
Scroll to Top