Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 15310] ファイルの概要

このコミットは、Go言語のデバッグ情報フォーマットであるDWARFの処理に関連するものです。具体的には、debug/dwarfパッケージにformFlagPresentという新しい属性エンコーディングを追加し、それに対応する処理を実装しています。これにより、DWARFv4で導入された新しいフラグ形式を正しく解釈できるようになります。

コミット

commit 7fdaec6c2fbed0d4a5a52644e9198b5bbb4f8c6f
Author: Robin Eklind <r.eklind.87@gmail.com>
Date:   Wed Feb 20 00:58:31 2013 +0800

    debug/dwarf: add flag_present attribute encoding.
    
    ref: http://www.dwarfstd.org/doc/DWARF4.pdf
    
    Update #4829
    
    R=minux.ma, iant
    CC=dave, golang-dev
    https://golang.org/cl/7354043

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/7fdaec6c2fbed0d4a5a52644e9198b5bbb4f8c6f

元コミット内容

debug/dwarf: add flag_present attribute encoding.

ref: http://www.dwarfstd.org/doc/DWARF4.pdf

Update #4829

変更の背景

この変更は、DWARFデバッグ情報フォーマットのバージョン4(DWARFv4)で導入された新しい属性エンコーディングであるDW_FORM_flag_presentに対応するために行われました。DWARFは、コンパイラが生成する実行可能ファイルにデバッグ情報を埋め込むための標準フォーマットであり、デバッガがプログラムの実行状態を解析するために使用します。

以前のDWARFバージョンでは、ブール値のフラグ属性は通常DW_FORM_flag(1バイトの真偽値)としてエンコードされていました。しかし、DWARFv4では、属性が存在すること自体が真を意味し、値がエンコードされないDW_FORM_flag_presentという形式が追加されました。これは、属性の存在がその意味を伝える場合に、余分なバイトを節約するための最適化です。

Go言語のdebug/dwarfパッケージは、DWARFデバッグ情報を解析するためのライブラリであり、新しいDWARFv4の形式を正しく解釈できるように更新する必要がありました。このコミットは、その対応の一環として、DW_FORM_flag_presentのエンコーディングとデコードロジックを追加しています。

前提知識の解説

DWARF (Debugging With Attributed Record Formats)

DWARFは、ソースレベルデバッガがプログラムの実行を解析するために必要な情報を、コンパイルされたプログラムに埋め込むための標準的なデバッグ情報フォーマットです。主にC、C++、Goなどのコンパイル型言語で使用されます。

DWARFは、以下のような情報を提供します。

  • ソースファイルと行番号のマッピング: 実行中のコードがどのソースファイルのどの行に対応するか。
  • 変数情報: 変数の名前、型、メモリ上の位置。
  • 関数情報: 関数の名前、引数、戻り値、ローカル変数。
  • 型情報: 構造体、配列、ポインタなどの複雑なデータ型の定義。
  • スタックフレーム情報: 関数呼び出しスタックの構造。

DWARF情報は、実行可能ファイルの.debug_info.debug_abbrev.debug_lineなどのセクションに格納されます。

DWARFの属性とフォーム (Attributes and Forms)

DWARFでは、デバッグ情報エントリ(DIE: Debugging Information Entry)がプログラム要素(変数、関数、型など)を記述します。各DIEは、その要素に関する詳細情報を提供する一連の「属性(Attributes)」を持ちます。例えば、変数のDIEはDW_AT_name(名前)、DW_AT_type(型)、DW_AT_location(場所)などの属性を持つことができます。

各属性は、その値がどのようにエンコードされているかを示す「フォーム(Form)」を持ちます。フォームは、値のデータ型とサイズを定義します。例えば、DW_FORM_stringはNULL終端文字列、DW_FORM_data4は4バイトのデータ、DW_FORM_addrはアドレスを表します。

DW_FORM_flagDW_FORM_flag_present

  • DW_FORM_flag: これはDWARFの初期バージョンから存在するフォームで、ブール値(真/偽)の属性をエンコードするために使用されます。通常、1バイトのデータとして格納され、0は偽、1は真を表します。
  • DW_FORM_flag_present: DWARFv4で導入された新しいフォームです。このフォームは、属性が存在すること自体が「真」を意味し、属性値自体はデバッグ情報エントリにエンコードされません。つまり、このフォームを持つ属性は、その属性が存在するかどうかだけで意味を持ち、追加のデータは不要です。これにより、デバッグ情報のサイズを削減できます。

例えば、ある関数がインライン化されているかどうかを示すDW_AT_inline属性を考えてみましょう。もしDW_AT_inline属性がDW_FORM_flag_presentとして存在すれば、その関数はインライン化されていると解釈されます。属性が存在しなければ、インライン化されていないと解釈されます。

技術的詳細

このコミットは、Go言語のdebug/dwarfパッケージにおいて、DW_FORM_flag_presentという新しいDWARFフォームを認識し、処理できるようにするための変更です。

  1. src/pkg/debug/dwarf/const.goの変更:

    • formFlagPresentという新しい定数が追加されています。この定数には、DWARF仕様で定義されているDW_FORM_flag_presentの数値(0x19)が割り当てられています。これにより、Goのコード内でこの新しいフォームを識別できるようになります。
  2. src/pkg/debug/dwarf/entry.goの変更:

    • buf構造体のentryメソッド内に、formFlagPresentを処理するための新しいcase文が追加されています。
    • case formFlagPresent:ブロックでは、val = trueと設定されています。これは、DW_FORM_flag_present属性の場合、その属性が存在すること自体が真を意味するため、明示的な値を読み込む必要がなく、常にtrueとして解釈されることを示しています。
    • コメントで「The attribute is implicitly indicated as present, and no value is encoded in the debugging information entry itself.」と説明されており、このフォームの特性が明確に示されています。

この変更により、GoのデバッガやツールがDWARFv4形式のデバッグ情報を含むバイナリを解析する際に、DW_FORM_flag_present属性を正しく解釈し、対応するブール値として扱うことができるようになります。

コアとなるコードの変更箇所

src/pkg/debug/dwarf/const.go

--- a/src/pkg/debug/dwarf/const.go
+++ b/src/pkg/debug/dwarf/const.go
@@ -207,6 +207,7 @@ const (
 	formRef8        format = 0x14
 	formRefUdata    format = 0x15
 	formIndirect    format = 0x16
+	formFlagPresent format = 0x19
 )
 
 // A Tag is the classification (the type) of an Entry.

src/pkg/debug/dwarf/entry.go

--- a/src/pkg/debug/dwarf/entry.go
+++ b/src/pkg/debug/dwarf/entry.go
@@ -185,6 +185,10 @@ func (b *buf) entry(atab abbrevTable, ubase Offset) *Entry {
 		// flag
 		case formFlag:
 			val = b.uint8() == 1
+		case formFlagPresent:
+			// The attribute is implicitly indicated as present, and no value is
+			// encoded in the debugging information entry itself.
+			val = true
 
 		// reference to other entry
 		case formRefAddr:

コアとなるコードの解説

src/pkg/debug/dwarf/const.go

このファイルは、DWARFの様々な定数(タグ、フォーム、属性など)を定義しています。 formFlagPresent format = 0x19 の行は、formFlagPresentという新しい定数を定義し、その値を0x19に設定しています。この0x19は、DWARFv4仕様でDW_FORM_flag_presentに割り当てられている公式な値です。これにより、GoのコードがDWARFデータストリームからこの値を見つけたときに、それがDW_FORM_flag_presentであることを認識できるようになります。

src/pkg/debug/dwarf/entry.go

このファイルには、DWARFエントリ(DIE)を解析し、その属性を読み取るためのロジックが含まれています。buf構造体のentryメソッドは、DWARFのバイトストリームからDIEを読み取り、その属性を解析する主要な関数です。

変更箇所は、switch文の中に新しいcase formFlagPresent:ブロックが追加された点です。

  • case formFlag:: 既存のDW_FORM_flagを処理する部分です。ここでは、1バイトを読み込み、それが1であればtrue、そうでなければfalseとしてvalに設定します。
  • case formFlagPresent:: 新しく追加された部分です。
    • val = true: ここが重要なポイントです。DW_FORM_flag_presentの場合、属性値はデータストリームにエンコードされていないため、何も読み込む必要がありません。属性が存在すること自体が「真」を意味するため、valは直接trueに設定されます。
    • コメント: 「The attribute is implicitly indicated as present, and no value is encoded in the debugging information entry itself.」このコメントは、DW_FORM_flag_presentの動作原理を明確に説明しており、属性が存在するだけでその値が真であることを示しています。

この変更により、debug/dwarfパッケージはDWARFv4で導入されたDW_FORM_flag_present形式の属性を正しくデコードし、Goのプログラム内でブール値として利用できるようになります。

関連リンク

  • DWARF Standard: DWARFの公式仕様書は、DWARFのウェブサイトで公開されています。このコミットで参照されているのはDWARFv4のPDFです。
  • Go Issue #4829: このコミットが解決したGoのイシュートラッカーのエントリです。
  • Go CL 7354043: このコミットに対応するGoのコードレビューシステム(Gerrit)のチェンジリストです。

参考にした情報源リンク