gdbをデフォルトでintel記法にする | 初期化処理の仕組み

gdbシンタックスをデフォルトでintel記法にする方法と、その仕組みを調べます。



Introduction

GNUデバッガgdbのアセンブラ表記は、AT&T記法とintel記法の2つがあり、それぞれ見た目は次のような感じになっています。

AT&T記法

Dump of assembler code for function main:
   0x00000000000006da <+0>:  push   %rbp
   0x00000000000006db <+1>:  mov    %rsp,%rbp
   0x00000000000006de <+4>:  sub    $0x10,%rsp
   0x00000000000006e2 <+8>:  mov    %edi,-0x4(%rbp)
   0x00000000000006e5 <+11>: mov    %rsi,-0x10(%rbp)
   0x00000000000006e9 <+15>: cmpl   $0x2,-0x4(%rbp)


intel記法

Dump of assembler code for function main:
   0x00000000000006da <+0>:  push   rbp
   0x00000000000006db <+1>:  mov    rbp,rsp
   0x00000000000006de <+4>:  sub    rsp,0x10
   0x00000000000006e2 <+8>:  mov    DWORD PTR [rbp-0x4],edi
   0x00000000000006e5 <+11>: mov    QWORD PTR [rbp-0x10],rsi
   0x00000000000006e9 <+15>: cmp    DWORD PTR [rbp-0x4],0x2

intel記法のほうが右の部分がスッキリしていて見やすいので、私はintel記法のほうが好きです。

しかし、gdbはデフォルトではAT&T記法に設定されているため、intel記法に変更するには次のコマンドを打つ必要があります1

(gdb) set disassembly-flavor intel

gdbを立ち上げるたびに毎回このコマンドを打つのは面倒です。 そこで、デフォルトでintel記法に設定する方法と、その仕組みを調べました。


Material

Ubuntu18.04.1 LTS を
Windows10の上に、VMwareによって構築した仮想環境で起動しています。
www.bioerrorlog.work


Results

ホームディレクトリ直下で".gdbinit"にコマンドを書き込む

やり方を検索してみると、すでに多くの方々が解決策を示していました。 bttb.s1.valueserver.jp

ホームディレクトリに".gdbinit"というファイルを作成し、そこに実行させたいコマンドを書き込むだけでいいようです。 さっそく".gdbinit"を作成し、

set disassembly-flavor intel

とだけ書き込みました。 これを保存し、gdbで確認すると、

(gdb) disas main
Dump of assembler code for function main:
   0x00000000000006da <+0>:  push   rbp
   0x00000000000006db <+1>:  mov    rbp,rsp
   0x00000000000006de <+4>:  sub    rsp,0x10
   0x00000000000006e2 <+8>:  mov    DWORD PTR [rbp-0x4],edi
   0x00000000000006e5 <+11>: mov    QWORD PTR [rbp-0x10],rsi
   0x00000000000006e9 <+15>: cmp    DWORD PTR [rbp-0x4],0x2

たしかにデフォルトでintel記法になっており、ひとまず目的を達成しました。

しかし、なぜ".gdbinit"というファイル名が認識され、コマンドが自動で実行されるのでしょうか。

まるで見当がつきません。 ここを調べていきます。

"."からはじまるドットファイルの意味

まずは、"."からはじまるファイル(ドットファイル)の意味について。

前々から、lsコマンドではドットファイルは表示されず、ls -aとしなければ表示されないことは経験として認識していましたが、その意味はいまいち分かりませんでした。 このドットファイルが隠しファイルである理由については、面白い情報があったので添えておきます。 qiita.com


次に、ドットファイルの役割について調べてみました。 すると、ドットファイルは設定を書き込んで読み込ませるためのファイルとして利用されるようです2。 まさに今回".gdbinit"で行ったような用途で使われるというわけです。

しかし、このドット自体に何か特別な機能が付与されているわけではなく、あくまで設定ファイルを取り扱うための表記のようです。 これだけでは、".gdbinit"というファイルがgdbによって実行される理由にはなりません。

gdbドキュメントから調べる

わからなくなったときは、公式のドキュメントやマニュアルを読むのが結局一番早い、というのが私の経験則です。 gdbについては、オンラインドキュメントがありました。

sourceware.org

これを調べてみると、gdbの初期化処理についての記述がありました。 まとめると、次のように39つの初期化処理が順番に実行されるようです。

2.1.3 What GDB Does During Startup
Here’s the description of what GDB does during session startup:

1. Sets up the command interpreter as specified by the command line.
2. Reads the system-wide init file and executes all the commands in that file.
3. Reads the init file in your home directory and executes all the commands in that file.
4. Executes commands and command files specified by the ‘-iex’ and ‘-ix’ options in their specified order.
5. Processes command line options and operands.
6. Reads and executes the commands from init file in the current working directory.
7. If the command line specified a program to debug, or a process to attach to, or a core file, GDB loads any auto-loaded scripts provided for the program or for its loaded shared libraries.
8. Executes commands and command files specified by the ‘-ex’ and ‘-x’ options in their specified order.
9. Reads the command history recorded in the history file.

ここで着目すべきは3番目の処理です。

3. Reads the init file in your home directory and executes all the commands in that file.

ホームディレクトリにある初期化ファイルを読み込み、コマンドをすべて実行する、とあります。 まさしく、今回私は".gdbinit"をホームディレクトリに置いたので、この処理過程において実行されたというのであれば、納得がいきます。 あとは、".gdbinit"が初期化ファイルとしてgdbに認識されていればいい訳です。

初期化ファイルの定義について調べてみると、いくつか記述を見つけました。

2.1.3 What GDB Does During Startup
~
The GDB init files are normally called .gdbinit.

または、

2.1.2 Choosing Modes
~
~/.gdbinit
This is the init file in your home directory.

など。

ここまでわかってくれば、さすがに納得できます。

まとめると、
・gdb初期化処理は9つのステップが用意されている。
・そのうち3つ目のステップではホームディレクトリ直下の初期化ファイルが処理される。
・ホームディレクトリ直下の初期化ファイルは".gdbinit"という名前を持つことになっている。

ということになります。


Discussion

gdbをデフォルトでintel記法にする方法と、その仕組みを記録しました。

今回行った方法はホームディレクトリ直下に".gdbinit"を置くやり方ですが、面白いのはこれ以外にも8つの初期化ステップがgdbに用意されているということです。 Google検索でヒットする解決策が概ねひとつの方法に収束されている今回のような場合でも、ドキュメントを辿ってみるとそれ以外の多くのやり方が開発者から用意されている、というのはなかなか奥ゆかしいことです。

とはいえ、多くの方々が実践しているやり方というのが、最も効率的な方法である場合がほとんどでしょう。 効率性と好奇心のバランスを、上手いこと回すのが大切かもしれません。


  1. 逆アセンブル解析 - gdb | はじめてのリバースエンジニアリング#2 - 生物系がゼロから始めるIT技術も参考に。

  2. DotFiles - Debian WikiまたはDotfiles - ArchWikiなど

  3. 原文からここで不要と思われる部分をカットして載せています。