[インデックス 19483] ファイルの概要
このコミットは、Go言語のcmd/objdump
ツールにARMアーキテクチャ用の逆アセンブラ機能を追加するものです。これにより、ARMバイナリの機械語命令を人間が読めるアセンブリコードに変換できるようになります。
コミット
commit 9f2dfb856e89a8847ff2b1fc6ad95917093f3e28
Author: Russ Cox <rsc@golang.org>
Date: Sun Jun 1 18:53:59 2014 -0400
cmd/objdump: add arm disassembler
Fixes #7452.
LGTM=minux, iant
R=minux, iant
CC=golang-codereviews
https://golang.org/cl/104770046
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/9f2dfb856e89a8847ff2b1fc6ad95917093f3e28
元コミット内容
cmd/objdump: add arm disassembler
このコミットは、cmd/objdump
ツールにARM逆アセンブラを追加します。
関連するIssueは #7452 です。
変更の背景
この変更の背景には、Go言語のプロファイリングツールであるpprof
やweblist
が、Darwin (macOS) 環境でARMアーキテクチャのバイナリを扱う際に問題が発生していたことがあります。具体的には、これらのツールが内部で逆アセンブラを必要とするにもかかわらず、cmd/objdump
にARM用の逆アセンブラが実装されていなかったため、list
コマンドなどが正常に機能しませんでした。
Issue #7452 は、この問題に対処するためにARM逆アセンブラの追加を要求しており、このコミットはその解決策として導入されました。これにより、GoツールチェインがARMアーキテクチャのバイナリをより適切に分析・デバッグできるようになり、特にクロスプラットフォーム開発やARMベースのデバイス上でのGoアプリケーションのデバッグ能力が向上しました。
前提知識の解説
- 逆アセンブラ (Disassembler): 機械語(CPUが直接実行するバイナリコード)を、人間が読めるアセンブリ言語のニーモニック(命令の略語)に変換するツールです。これにより、プログラムの低レベルな動作を理解したり、デバッグやリバースエンジニアリングを行ったりすることが可能になります。
cmd/objdump
: Go言語の標準ツールの一つで、オブジェクトファイルや実行可能ファイルの情報を表示するためのコマンドラインツールです。一般的なUnix系のobjdump
コマンドに似ており、シンボルテーブル、セクション情報、そして逆アセンブルされたコードなどを表示できます。- ARMアーキテクチャ: Advanced RISC Machineの略で、モバイルデバイス、組み込みシステム、サーバーなど、幅広い分野で利用されているCPUアーキテクチャです。低消費電力と高性能を両立している点が特徴です。ARM命令セットは、固定長の32ビット命令(ARMモード)と可変長の16/32ビット命令(Thumbモード)など、複数の命令セットをサポートしています。
pprof
: Go言語のプロファイリングツールで、CPU使用率、メモリ割り当て、ゴルーチンブロックなどのパフォーマンスデータを収集・可視化します。pprof
は、実行中のプログラムのパフォーマンスボトルネックを特定するのに役立ちます。list
コマンドは、特定の関数のアセンブリコードを表示するために逆アセンブラを利用します。rsc.io/arm/armasm
: このコミットで導入されたARM逆アセンブラの基盤となっている外部パッケージです。Russ Cox氏が開発したもので、ARM命令のデコードとアセンブリ表現への変換ロジックを提供します。
技術的詳細
このコミットの主要な技術的変更は、cmd/objdump
にARM命令のデコードとフォーマットを行うための新しいGoパッケージarmasm
を統合したことです。
armasm.go
の追加: コミットの大部分を占めるsrc/cmd/objdump/armasm.go
は、rsc.io/arm/armasm
パッケージのコードをバンドルしたものです。このファイルは、ARM命令のバイナリ表現を解析し、対応するアセンブリ命令(ニーモニックとオペランド)に変換するためのロジックを含んでいます。具体的には、arm_instFormat
構造体で命令のフォーマットを定義し、arm_Decode
関数でバイト列から命令をデコードします。また、arm_GNUSyntax
とarm_plan9Syntax
関数は、それぞれGNUアセンブラ形式とPlan 9アセンブラ形式で命令を文字列として表現する機能を提供します。- ビルドプロセスの更新:
src/cmd/objdump/Makefile
が更新され、armasm.go
を生成するためのルールが追加されました。これは、bundle
ツール(code.google.com/p/rsc/cmd/bundle
)を使用してrsc.io/arm/armasm
パッケージをarmasm.go
に組み込むことを示しています。これにより、armasm
パッケージがobjdump
ツールの一部としてビルドされるようになります。 main.go
の変更:src/cmd/objdump/main.go
が修正され、ARMアーキテクチャがターゲットの場合に新しいARM逆アセンブラを使用するようにロジックが追加されました。これにより、objdump
ツールが実行時に適切な逆アセンブラを選択できるようになります。- テストの追加:
src/cmd/objdump/objdump_test.go
にARM逆アセンブラの機能を確認するための基本的なテストが追加されました。
この変更により、objdump
はARMバイナリを正確に解析し、その内容をアセンブリレベルで表示できるようになりました。特に、armasm.go
内のarm_Decode
関数は、ARM命令の複雑なエンコーディングを解釈し、レジスタ、即値、メモリアドレスなどのオペランドを抽出する中心的な役割を担っています。
コアとなるコードの変更箇所
このコミットのコアとなるコードの変更は、主に以下のファイルに集中しています。
src/cmd/objdump/armasm.go
:- このファイルは新規追加されたもので、
rsc.io/arm/armasm
パッケージのコードをバンドルしたものです。 - ARM命令のデコードロジック(
arm_Decode
関数)と、命令の引数を解析するarm_decodeArg
関数が含まれています。 - 命令のフォーマット定義(
arm_instFormat
)や、レジスタ、シフト、メモリ参照などの引数型定義(arm_Reg
,arm_Shift
,arm_Mem
など)が含まれます。 - GNUアセンブラ形式とPlan 9アセンブラ形式で命令を文字列化する関数(
arm_GNUSyntax
,arm_plan9Syntax
)も含まれています。
- このファイルは新規追加されたもので、
src/cmd/objdump/Makefile
:armasm.go
を生成するためのビルドルールが追加されました。armasm.go: bundle
./bundle -p main -x arm_ rsc.io/arm/armasm | gofmt >armasm.go
src/cmd/objdump/main.go
:objdump
のメインロジックに、ARMアーキテクチャのバイナリを扱う際にarmasm
パッケージの逆アセンブラを使用するための条件分岐が追加されました。
src/cmd/objdump/objdump_test.go
:- ARM逆アセンブラの基本的な動作を検証するためのテストケースが追加されました。
コアとなるコードの解説
armasm.go
は、ARM命令のバイナリ表現を解析し、構造化されたGoのデータ型(arm_Inst
)に変換する中心的な役割を担っています。
arm_instFormat
: ARM命令のエンコーディングパターンを定義する構造体です。mask
とvalue
を使って命令のビットパターンを照合し、opBits
でオペコードの一部を抽出し、args
で命令の引数をどのようにデコードするかを指定します。arm_Decode(src []byte, mode arm_Mode) (inst arm_Inst, err error)
: この関数が、実際の逆アセンブル処理の入り口です。入力バイト列src
から32ビットのARM命令を読み取り、定義されたarm_instFormats
テーブルを走査して、命令に一致するフォーマットを探します。一致するフォーマットが見つかると、そのフォーマットの定義に基づいて命令のオペコードと引数を抽出し、arm_Inst
構造体として返します。条件付き命令の処理や、特殊な命令(例:BKPT
)のハンドリングも行われます。arm_decodeArg(aop arm_instArg, x uint32) arm_Arg
:arm_Decode
関数から呼び出され、個々の命令引数(レジスタ、即値、メモリ参照など)を、命令のビットパターンx
と引数の種類aop
に基づいてデコードします。例えば、arm_arg_R_0
は命令のビット0-3からレジスタ番号を抽出し、arm_arg_imm12
は12ビットの即値を抽出します。arm_GNUSyntax(inst arm_Inst) string
/arm_plan9Syntax(inst arm_Inst, pc uint64, symname func(uint64) (string, uint64), text io.ReaderAt) string
: これらの関数は、デコードされたarm_Inst
構造体を、それぞれGNUアセンブラ形式またはPlan 9アセンブラ形式の文字列に整形します。これにより、objdump
コマンドの出力が、開発者にとって馴染みのあるアセンブリ表記で表示されるようになります。特にarm_plan9Syntax
は、Goのツールチェインで一般的に使用されるアセンブリ構文に準拠しており、PC相対アドレスの解決や、特定の命令(例:LDR
)の特殊なフォーマット変換も行います。
これらのコンポーネントが連携することで、Goのobjdump
ツールはARMバイナリを正確に逆アセンブルし、その内容を詳細に分析できるようになります。
関連リンク
- Go Issue #7452: https://github.com/golang/go/issues/7452
- Go CL 104770046: https://golang.org/cl/104770046
rsc.io/arm/armasm
(おそらくこのコミット時点でのコードベース): https://pkg.go.dev/rsc.io/arm/armasm (現在のGo Modulesのパス)
参考にした情報源リンク
- GitHub Issue #7452 の検索結果: https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQGspbucqGOHBJOpb3WRyoiIbBAavMabbaUtYtwtA258QNX-1T6D81mdwm_ycY8KABlvBvpfdk2QtsRgCHecwNX00Rz84_HLF-TlJTxLWwS0B8bWem5TuPxGcYXWoBsumooH_hk=
- Go言語の
objdump
ツールに関する一般的な情報 - ARMアーキテクチャおよびアセンブリ言語に関する一般的な知識
- Go言語のツールチェインとビルドシステムに関する一般的な知識
rsc.io/arm/armasm
パッケージのコード構造 (コミット内容から推測)