hana_shinのLinux技術ブログ

Linuxの技術情報を掲載しています。特にネットワークをメインに掲載していきます。

readelfコマンドの使い方



1 readelfコマンドとは?

ELF(Executable and Linkable Format)ファイルの情報を表示するコマンドです。

ELFファイルかどうかはfileコマンドで確認することができます。
カーネルモジュールに対してfileコマンドを実行してみます。ELFファイルであることがわかります。

[root@server ~]#  file -z /lib/modules/3.10.0-1160.el7.x86_64/kernel/net/ipv4/netfilter/nf_conntrack_ipv4.ko.xz
/lib/modules/3.10.0-1160.el7.x86_64/kernel/net/ipv4/netfilter/nf_conntrack_ipv4.ko.xz: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV) (XZ compressed data)

次に実行ファイルに対して、readelfコマンドを実行してみます。ELFファイルであることがわかります。

[root@server ~]# file /usr/bin/bc
/usr/bin/bc: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=60e314fae84e986e67cc4b61986bdbfc108a1f86, stripped

最後に共有ライブラリに対して、readelfコマンドを実行してみます。ELFファイルであることがわかります。

[root@server ~]# file /lib64/libc-2.17.so
/lib64/libc-2.17.so: ELF 64-bit LSB shared object, x86-64, version 1 (GNU/Linux), dynamically linked (uses shared libs), BuildID[sha1]=f9fafde281e0e0e2af45911ad0fa115b64c2cea8, for GNU/Linux 2.6.32, not stripped

2 検証環境

CentOS版数は以下のとおりです。仮想マシンは最小構成で作成しました。

[root@server ~]# cat /etc/redhat-release
CentOS Linux release 7.9.2009 (Core)

カーネル版数は以下のとおりです。

[root@server ~]# uname -r
3.10.0-1160.el7.x86_64

readelfコマンドの版数は以下のとおりです。

[root@server ~]# readelf -v
GNU readelf version 2.27-44.base.el7
Copyright (C) 2016 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or (at your option) any later version.
This program has absolutely no warranty.

3 オプション一覧

[root@server ~]# readelf -h
readelf: 警告: 行なうべき事はありません。
使用法: readelf <option(s)> elf-file(s)
 ELF 形式のファイルの内容に関する情報を表示します
 Options are:
  -a --all               Equivalent to: -h -l -S -s -r -d -V -A -I
  -h --file-header       Display the ELF file header
  -l --program-headers   Display the program headers
     --segments          An alias for --program-headers
  -S --section-headers   Display the sections' header
     --sections          An alias for --section-headers
  -g --section-groups    Display the section groups
  -t --section-details   Display the section details
  -e --headers           Equivalent to: -h -l -S
  -s --syms              Display the symbol table
     --symbols           An alias for --syms
  --dyn-syms             Display the dynamic symbol table
  -n --notes             Display the core notes (if present)
  -r --relocs            Display the relocations (if present)
  -u --unwind            Display the unwind info (if present)
  -d --dynamic           Display the dynamic section (if present)
  -V --version-info      Display the version sections (if present)
  -A --arch-specific     Display architecture specific information (if any)
  -c --archive-index     Display the symbol/file index in an archive
  -D --use-dynamic       Use the dynamic section info when displaying symbols
  -x --hex-dump=<number|name>
                         Dump the contents of section <number|name> as bytes
  -p --string-dump=<number|name>
                         Dump the contents of section <number|name> as strings
  -R --relocated-dump=<number|name>
                         Dump the contents of section <number|name> as relocated bytes
  -z --decompress        Decompress section before dumping it
  -w[lLiaprmfFsoRt] or
  --debug-dump[=rawline,=decodedline,=info,=abbrev,=pubnames,=aranges,=macro,=frames,
               =frames-interp,=str,=loc,=Ranges,=pubtypes,
               =gdb_index,=trace_info,=trace_abbrev,=trace_aranges,
               =addr,=cu_index]
                         Display the contents of DWARF2 debug sections
  --dwarf-depth=N        N 以上の深さの DIE を表示しない
  --dwarf-start=N        N 以上の深さの DIE を表示する
  -I --histogram         Display histogram of bucket list lengths
  -W --wide              出力幅が 80 文字を超えることを許可する
  @<file>                オプションを <file> から読み込む
  -H --help              この情報を表示する
  -v --version           readelf のバージョン番号を表示する

4 事前準備

readelfの動作確認のため、nf_conntrack_ipv4.koモジュールを使ってみます。/lib/modules配下から、カレントディレクトリにカーネルモジュールをコピーします。

[root@server ~]# cp /lib/modules/3.10.0-1160.el7.x86_64/kernel/net/ipv4/netfilter/nf_conntrack_ipv4.ko.xz .

カーネルモジュールを解凍します。

[root@server ~]# xz -d nf_conntrack_ipv4.ko.xz

解凍したカーネルモジュールを確認します。

[root@server ~]# ls -l nf_conntrack_ipv4.ko
-rw-r--r--. 1 root root 28973  4月  9 19:38 nf_conntrack_ipv4.ko

5 ELFヘッダを表示する方法(-h)

-hはELFヘッダを表示するオプションです。-hを使ってnf_conntrack_ipv4.koのELFヘッダを表示してみます。

[root@server ~]# readelf -h nf_conntrack_ipv4.ko
ELF ヘッダ:
  マジック:  7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
  クラス:                            ELF64
  データ:                            2 の補数、リトルエンディアン
  バージョン:                        1 (current)
  OS/ABI:                            UNIX - System V
  ABI バージョン:                    0
  型:                                REL (再配置可能ファイル)
  マシン:                            Advanced Micro Devices X86-64
  バージョン:                        0x1
  エントリポイントアドレス:          0x0
  プログラムの開始ヘッダ:            0 (バイト)
  セクションヘッダ始点:              26128 (バイト)
  フラグ:                            0x0
  このヘッダのサイズ:                64 (バイト)
  プログラムヘッダサイズ:            0 (バイト)
  プログラムヘッダ数:                0
  セクションヘッダ:                  64 (バイト)
  セクションヘッダサイズ:            37
  セクションヘッダ文字列表索引:      36

6 セクション一覧を表示する方法(-S)

-Sはセクション一覧を表示するオプションです。nf_conntrack_ipv4.koのセクション一覧を表示してみます。nf_conntrack_ipv4.koは、37個のセクションから構成されていることがわかります。

[root@server ~]# readelf -S nf_conntrack_ipv4.ko
37 個のセクションヘッダ、始点オフセット 0x6610:

セクションヘッダ:
  [番] 名前              タイプ           アドレス          オフセット
       サイズ            EntSize          フラグ Link  情報  整列
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .note.gnu.build-i NOTE             0000000000000000  00000040
       0000000000000024  0000000000000000   A       0     0     4
  [ 2] .text             PROGBITS         0000000000000000  00000070
       0000000000000fa2  0000000000000000  AX       0     0     16
  [ 3] .rela.text        RELA             0000000000000000  00001018
       0000000000000cc0  0000000000000018   I      33     2     8
  [ 4] .init.text        PROGBITS         0000000000000000  00001cd8
       00000000000000f8  0000000000000000  AX       0     0     1
  [ 5] .rela.init.text   RELA             0000000000000000  00001dd0
       00000000000002a0  0000000000000018   I      33     4     8
  [ 6] .exit.text        PROGBITS         0000000000000000  00002070
       0000000000000051  0000000000000000  AX       0     0     1
  [ 7] .rela.exit.text   RELA             0000000000000000  000020c8
       0000000000000108  0000000000000018   I      33     6     8
  [ 8] __ksymtab_gpl     PROGBITS         0000000000000000  000021d0
       0000000000000010  0000000000000000   A       0     0     16
  [ 9] .rela__ksymtab_gp RELA             0000000000000000  000021e0
       0000000000000030  0000000000000018   I      33     8     8
  [10] __kcrctab_gpl     PROGBITS         0000000000000000  00002210
       0000000000000008  0000000000000000   A       0     0     8
  [11] .rela__kcrctab_gp RELA             0000000000000000  00002218
       0000000000000018  0000000000000018   I      33    10     8
  [12] .rodata           PROGBITS         0000000000000000  00002240
       00000000000001d3  0000000000000000   A       0     0     32
  [13] .rodata.str1.1    PROGBITS         0000000000000000  00002413
       00000000000000c4  0000000000000001 AMS       0     0     1
  [14] .rodata.str1.8    PROGBITS         0000000000000000  000024d8
       00000000000002cd  0000000000000001 AMS       0     0     8
  [15] .smp_locks        PROGBITS         0000000000000000  000027a8
       0000000000000004  0000000000000000   A       0     0     4
  [16] .rela.smp_locks   RELA             0000000000000000  000027b0
       0000000000000018  0000000000000018   I      33    15     8
  [17] __ksymtab_strings PROGBITS         0000000000000000  000027c8
       0000000000000014  0000000000000000   A       0     0     1
  [18] .modinfo          PROGBITS         0000000000000000  000027e0
       00000000000000e9  0000000000000000   A       0     0     32
  [19] __param           PROGBITS         0000000000000000  000028d0
       0000000000000020  0000000000000000   A       0     0     8
  [20] .rela__param      RELA             0000000000000000  000028f0
       0000000000000048  0000000000000018   I      33    19     8
  [21] __mcount_loc      PROGBITS         0000000000000000  00002938
       00000000000000f0  0000000000000000   A       0     0     8
  [22] .rela__mcount_loc RELA             0000000000000000  00002a28
       00000000000002d0  0000000000000018   I      33    21     8
  [23] __versions        PROGBITS         0000000000000000  00002d00
       0000000000000d80  0000000000000000   A       0     0     32
  [24] .data             PROGBITS         0000000000000000  00003a80
       0000000000000180  0000000000000000  WA       0     0     32
  [25] .rela.data        RELA             0000000000000000  00003c00
       0000000000000150  0000000000000018   I      33    24     8
  [26] __verbose         PROGBITS         0000000000000000  00003d50
       0000000000000168  0000000000000000  WA       0     0     8
  [27] .rela__verbose    RELA             0000000000000000  00003eb8
       0000000000000360  0000000000000018   I      33    26     8
  [28] .data..read_mostl PROGBITS         0000000000000000  00004220
       00000000000003a4  0000000000000000  WA       0     0     32
  [29] .rela.data..read_ RELA             0000000000000000  000045c8
       00000000000003c0  0000000000000018   I      33    28     8
  [30] .gnu.linkonce.thi PROGBITS         0000000000000000  000049a0
       0000000000000238  0000000000000000  WA       0     0     32
  [31] .rela.gnu.linkonc RELA             0000000000000000  00004bd8
       0000000000000030  0000000000000018   I      33    30     8
  [32] .bss              NOBITS           0000000000000000  00004c08
       0000000000000000  0000000000000000  WA       0     0     1
  [33] .symtab           SYMTAB           0000000000000000  00004c08
       0000000000000e88  0000000000000018          34    95     8
  [34] .strtab           STRTAB           0000000000000000  00005a90
       00000000000009fe  0000000000000000           0     0     1
  [35] .gnu_debuglink    PROGBITS         0000000000000000  00006490
       0000000000000020  0000000000000000           0     0     4
  [36] .shstrtab         STRTAB           0000000000000000  000064b0
       000000000000015f  0000000000000000           0     0     1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  l (large), p (processor specific)
セクション 意味
.text 実行コードを格納するセクションです
.data 初期化済データを格納するセクションです
.bss 未初期化の変数を格納するセクションです
.nodata リードオンリーのセクションで、書き込みはできません。定数か固定文字列を格納するセクションです

7 80文字以上を表示する方法(-W)

-Wは1行に表示する文字数を指定するオプションです。デフォルトは80文字までしか表示しません。 -Wを使うことで、80文字以上の文字を表示することができます。

[root@server ~]# readelf -S -W nf_conntrack_ipv4.ko
37 個のセクションヘッダ、始点オフセット 0x6610:

セクションヘッダ:
  [番] 名前              型              アドレス         Off    サイズ ES Flg Lk Inf Al
  [ 0]                   NULL            0000000000000000 000000 000000 00      0   0  0
  [ 1] .note.gnu.build-id NOTE            0000000000000000 000040 000024 00   A  0   0  4
  [ 2] .text             PROGBITS        0000000000000000 000070 000fa2 00  AX  0   0 16
  [ 3] .rela.text        RELA            0000000000000000 001018 000cc0 18   I 33   2  8
  [ 4] .init.text        PROGBITS        0000000000000000 001cd8 0000f8 00  AX  0   0  1
  [ 5] .rela.init.text   RELA            0000000000000000 001dd0 0002a0 18   I 33   4  8
  [ 6] .exit.text        PROGBITS        0000000000000000 002070 000051 00  AX  0   0  1
  [ 7] .rela.exit.text   RELA            0000000000000000 0020c8 000108 18   I 33   6  8
  [ 8] __ksymtab_gpl     PROGBITS        0000000000000000 0021d0 000010 00   A  0   0 16
  [ 9] .rela__ksymtab_gpl RELA            0000000000000000 0021e0 000030 18   I 33   8  8
  [10] __kcrctab_gpl     PROGBITS        0000000000000000 002210 000008 00   A  0   0  8
  [11] .rela__kcrctab_gpl RELA            0000000000000000 002218 000018 18   I 33  10  8
  [12] .rodata           PROGBITS        0000000000000000 002240 0001d3 00   A  0   0 32
  [13] .rodata.str1.1    PROGBITS        0000000000000000 002413 0000c4 01 AMS  0   0  1
  [14] .rodata.str1.8    PROGBITS        0000000000000000 0024d8 0002cd 01 AMS  0   0  8
  [15] .smp_locks        PROGBITS        0000000000000000 0027a8 000004 00   A  0   0  4
  [16] .rela.smp_locks   RELA            0000000000000000 0027b0 000018 18   I 33  15  8
  [17] __ksymtab_strings PROGBITS        0000000000000000 0027c8 000014 00   A  0   0  1
  [18] .modinfo          PROGBITS        0000000000000000 0027e0 0000e9 00   A  0   0 32
  [19] __param           PROGBITS        0000000000000000 0028d0 000020 00   A  0   0  8
  [20] .rela__param      RELA            0000000000000000 0028f0 000048 18   I 33  19  8
  [21] __mcount_loc      PROGBITS        0000000000000000 002938 0000f0 00   A  0   0  8
  [22] .rela__mcount_loc RELA            0000000000000000 002a28 0002d0 18   I 33  21  8
  [23] __versions        PROGBITS        0000000000000000 002d00 000d80 00   A  0   0 32
  [24] .data             PROGBITS        0000000000000000 003a80 000180 00  WA  0   0 32
  [25] .rela.data        RELA            0000000000000000 003c00 000150 18   I 33  24  8
  [26] __verbose         PROGBITS        0000000000000000 003d50 000168 00  WA  0   0  8
  [27] .rela__verbose    RELA            0000000000000000 003eb8 000360 18   I 33  26  8
  [28] .data..read_mostly PROGBITS        0000000000000000 004220 0003a4 00  WA  0   0 32
  [29] .rela.data..read_mostly RELA            0000000000000000 0045c8 0003c0 18   I 33  28  8
  [30] .gnu.linkonce.this_module PROGBITS        0000000000000000 0049a0 000238 00  WA  0   0 32
  [31] .rela.gnu.linkonce.this_module RELA            0000000000000000 004bd8 000030 18   I 33  30  8
  [32] .bss              NOBITS          0000000000000000 004c08 000000 00  WA  0   0  1
  [33] .symtab           SYMTAB          0000000000000000 004c08 000e88 18     34  95  8
  [34] .strtab           STRTAB          0000000000000000 005a90 0009fe 00      0   0  1
  [35] .gnu_debuglink    PROGBITS        0000000000000000 006490 000020 00      0   0  4
  [36] .shstrtab         STRTAB          0000000000000000 0064b0 00015f 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  l (large), p (processor specific)

8 セクションヘッダの中身を情報を表示する方法

8.1 HEXで表示する方法(-x)

nf_conntrack_ipv4.koには全部で37個のセクションがありました。その中に、modinfoというセクションがあります。ここでは、modinfoセクションの中身を表示してみます。

[root@server ~]# readelf -S nf_conntrack_ipv4.ko|grep modinfo
  [18] .modinfo          PROGBITS         0000000000000000  000027e0

-xオプションに18を指定して、modinfoセクションの情報を表示します。

[root@server ~]# readelf -x 18 nf_conntrack_ipv4.ko

セクション '.modinfo' の 十六進数ダンプ:
  0x00000000 6c696365 6e73653d 47504c00 616c6961 license=GPL.alia
  0x00000010 733d6970 5f636f6e 6e747261 636b0061 s=ip_conntrack.a
  0x00000020 6c696173 3d6e665f 636f6e6e 74726163 lias=nf_conntrac
  0x00000030 6b2d3200 00000000 00000000 00000000 k-2.............
  0x00000040 72657470 6f6c696e 653d5900 7268656c retpoline=Y.rhel
  0x00000050 76657273 696f6e3d 372e3900 73726376 version=7.9.srcv
  0x00000060 65727369 6f6e3d31 41354537 44414634 ersion=1A5E7DAF4
  0x00000070 41413144 41363546 33353838 30320000 AA1DA65F358802..
  0x00000080 64657065 6e64733d 6e665f63 6f6e6e74 depends=nf_connt
  0x00000090 7261636b 2c6e665f 64656672 61675f69 rack,nf_defrag_i
  0x000000a0 70763400 696e7472 65653d59 00766572 pv4.intree=Y.ver
  0x000000b0 6d616769 633d332e 31302e30 2d313136 magic=3.10.0-116
  0x000000c0 302e656c 372e7838 365f3634 20534d50 0.el7.x86_64 SMP
  0x000000d0 206d6f64 5f756e6c 6f616420 6d6f6476  mod_unload modv
  0x000000e0 65727369 6f6e7320 00                ersions .

8.2 文字列で表示する方法(-p)

-pはセクションの情報を文字列で表示するオプションです。セクション番号18を指定して、modinfoセクションの情報を表示します。modinfoのセクション情報が文字列で表示されたことがわかります。

[root@server ~]# readelf -p 18 nf_conntrack_ipv4.ko

セクション '.modinfo' の文字列ダンプ:
  [     0]  license=GPL
  [     c]  alias=ip_conntrack
  [    1f]  alias=nf_conntrack-2
  [    40]  retpoline=Y
  [    4c]  rhelversion=7.9
  [    5c]  srcversion=1A5E7DAF4AA1DA65F358802
  [    80]  depends=nf_conntrack,nf_defrag_ipv4
  [    a4]  intree=Y
  [    ad]  vermagic=3.10.0-1160.el7.x86_64 SMP mod_unload modversions

-pオプションで表示した情報は、modinfoコマンドで表示したものと同じであることがわかります。

[root@server ~]# modinfo nf_conntrack_ipv4.ko
filename:       /root/nf_conntrack_ipv4.ko
license:        GPL
alias:          ip_conntrack
alias:          nf_conntrack-2
retpoline:      Y
rhelversion:    7.9
srcversion:     1A5E7DAF4AA1DA65F358802
depends:        nf_conntrack,nf_defrag_ipv4
intree:         Y
vermagic:       3.10.0-1160.el7.x86_64 SMP mod_unload modversions
signer:         CentOS Linux kernel signing key
sig_key:        E1:FD:B0:E2:A7:E8:61:A1:D1:CA:80:A2:3D:CF:0D:BA:3A:A4:AD:F5
sig_hashalgo:   sha256

9 シンボルテーブルを表示する方法(-s)

-sはシンボルテーブルを表示するオプションです。シンボルテーブルは、変数名、関数名、ファイル名を含んだセクションになります。以下の実行結果では、FUNCは関数名、OBJECTは変数名、FILE はファイル名を表しています。

[root@server ~]# readelf -s nf_conntrack_ipv4.ko

シンボルテーブル '.symtab' は 155 個のエントリから構成されています:
  番号:      値         サイズ タイプ  Bind   Vis      索引名
-snip-
    26: 0000000000000110    28 FUNC    LOCAL  DEFAULT    2 ipv4_nlattr_tuple_size
    27: 0000000000000040    80 OBJECT  LOCAL  DEFAULT   12 ipv4_nla_policy
    28: 0000000000000130   140 FUNC    LOCAL  DEFAULT    2 ipv4_tuple_to_nlattr
-snip-
    60: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS nf_conntrack_proto_icmp.c
-snip-

10 プログラムヘッダを表示する方法(-l)

-lはプログラムヘッダを表示するオプションです。ここでは、tcpdumpコマンドのプログラムヘッダを表示してみます。

[root@server ~]# readelf -l /usr/sbin/tcpdump

Elf ファイルタイプは EXEC (実行可能ファイル) です
エントリポイント 0x406f65
9 個のプログラムヘッダ、始点オフセット 64

プログラムヘッダ:
  タイプ        オフセット          仮想Addr           物理Addr
            ファイルサイズ        メモリサイズ         フラグ 整列
  PHDR           0x0000000000000040 0x0000000000400040 0x0000000000400040
                 0x00000000000001f8 0x00000000000001f8  R E    8
  INTERP         0x0000000000000238 0x0000000000400238 0x0000000000400238
                 0x000000000000001c 0x000000000000001c  R      1
      [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
  LOAD           0x0000000000000000 0x0000000000400000 0x0000000000400000
                 0x00000000000dfa74 0x00000000000dfa74  R E    200000
  LOAD           0x00000000000dfde0 0x00000000006dfde0 0x00000000006dfde0
                 0x0000000000003cb8 0x0000000000162bf0  RW     200000
  DYNAMIC        0x00000000000dfdf8 0x00000000006dfdf8 0x00000000006dfdf8
                 0x0000000000000200 0x0000000000000200  RW     8
  NOTE           0x0000000000000254 0x0000000000400254 0x0000000000400254
                 0x0000000000000044 0x0000000000000044  R      4
  GNU_EH_FRAME   0x00000000000d2d08 0x00000000004d2d08 0x00000000004d2d08
                 0x000000000000135c 0x000000000000135c  R      4
  GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000000 0x0000000000000000  RW     10
  GNU_RELRO      0x00000000000dfde0 0x00000000006dfde0 0x00000000006dfde0
                 0x0000000000000220 0x0000000000000220  R      1

 セグメントマッピングへのセクション:
  セグメントセクション...
   00
   01     .interp
   02     .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame
   03     .init_array .fini_array .jcr .dynamic .got .got.plt .data .bss
   04     .dynamic
   05     .note.ABI-tag .note.gnu.build-id
   06     .eh_frame_hdr
   07
   08     .init_array .fini_array .jcr .dynamic .got

Z 参考情報

私が業務や記事執筆で参考にした書籍を以下のページに記載します。
Linux技術のスキルアップをしよう! - hana_shinのLinux技術ブログ


https://docs.oracle.com/cd/E19253-01/819-0391/chapter6-79797/index.html