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

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

このコミットは、Go言語のsyscallパッケージ内のsyscall_linux_arm.goファイルに対する変更です。このファイルは、Linux ARMアーキテクチャに特化したシステムコール関連の機能を提供します。具体的には、プロセスをトレースする際に使用されるレジスタ情報(PtraceRegs構造体)の操作に関する機能が追加されています。

コミット

  • コミットハッシュ: 7c412e962c1cf5de4e128c0ca2caed14f9b87003
  • 作者: Shenghou Ma minux.ma@gmail.com
  • 日付: 2012年10月25日 木曜日 13:41:04 +0800

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

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

元コミット内容

    syscall: implement (*PtraceRegs).PC() and SetPC()
    
    R=golang-dev, rsc
    CC=golang-dev
    https://golang.org/cl/6763043

変更の背景

このコミットの背景には、Go言語のsyscallパッケージがLinux ARMアーキテクチャ上でのプロセスデバッグやトレース機能をより完全にサポートする必要があったことが挙げられます。

変更前のsrc/pkg/syscall/syscall_linux_arm.goファイルには、PtraceRegs構造体に対するPC()メソッドとSetPC()メソッドが定義されていましたが、これらはそれぞれreturn 0と空の関数として実装されていました。これは、これらの機能がまだ実装されておらず、将来的な対応が期待されていたことを示唆しています(コード内の// TODO(kaib): add support for tracingコメントからも明らかです)。

PC(プログラムカウンタ)は、CPUが次に実行する命令のアドレスを保持する非常に重要なレジスタです。デバッガなどのツールがプロセスの実行状態を制御したり、スタックトレースを生成したりする際には、このプログラムカウンタの値を読み書きする機能が不可欠です。

このコミットは、ARM Linux環境において、PtraceRegsからプログラムカウンタの値を正確に取得し、また設定できるようにすることで、Go言語のランタイムやデバッグツールがより高度なプロセス制御を行えるようにするために行われました。

前提知識の解説

syscallパッケージ

Go言語のsyscallパッケージは、オペレーティングシステムが提供する低レベルなシステムコールへのインターフェースを提供します。これにより、Goプログラムからファイル操作、プロセス管理、ネットワーク通信など、OSカーネルの機能に直接アクセスできます。OSやアーキテクチャに依存する機能は、syscall_linux_arm.goのように特定のファイルに分離して実装されることが一般的です。

PtraceRegs構造体

PtraceRegsは、ptraceシステムコールを通じて取得されるプロセスのCPUレジスタの状態を保持するための構造体です。ptraceは、デバッガが別のプロセスの実行を監視・制御するために使用するシステムコールです。この構造体には、汎用レジスタ、プログラムカウンタ、スタックポインタなどの情報が含まれます。

PC (Program Counter)

プログラムカウンタ(PC)は、CPUの内部レジスタの一つで、次に実行される機械語命令のアドレスを指し示します。CPUはPCが指すアドレスから命令をフェッチし、実行します。デバッグ時には、このPCの値を操作することで、プログラムの実行フローを制御したり、特定の命令から実行を再開させたりすることが可能になります。

ARMアーキテクチャとUregs[15]

ARM(Advanced RISC Machine)は、モバイルデバイスや組み込みシステムで広く使用されているCPUアーキテクチャです。ARMプロセッサには、汎用レジスタ(R0-R12)、スタックポインタ(SP、R13)、リンクレジスタ(LR、R14)、プログラムカウンタ(PC、R15)などがあります。

PtraceRegs構造体内のUregsフィールドは、これらの汎用レジスタや特殊レジスタの値を配列として保持していることが一般的です。ARMアーキテクチャでは、プログラムカウンタは通常R15レジスタに対応します。したがって、Uregs[15]はプログラムカウンタの値を表します。

技術的詳細

このコミットは、PtraceRegs構造体のPC()メソッドとSetPC()メソッドの実装を修正することで、Linux ARM環境におけるプロセスデバッグの基盤を強化しています。

  • PC()メソッド: このメソッドは、PtraceRegs構造体から現在のプログラムカウンタの値を読み出す役割を担います。ARMアーキテクチャの慣例に従い、Uregs配列のインデックス15(Uregs[15])がプログラムカウンタ(R15)に対応するため、その値をuint64型にキャストして返します。
  • SetPC()メソッド: このメソッドは、指定されたpc(プログラムカウンタ)の値をPtraceRegs構造体に書き込む役割を担います。これにより、デバッガはトレース対象プロセスの次に実行される命令のアドレスを変更できます。pcの値はuint32型にキャストされ、Uregs[15]に格納されます。ARMのレジスタは通常32ビット幅であるため、uint32へのキャストが適切です。

これらの変更により、Go言語のランタイムやデバッグツールは、ARM Linux上で実行されているプロセスのプログラムカウンタを正確に読み書きできるようになり、ブレークポイントの設定、ステップ実行、レジスタの検査といったデバッグ機能の実装が可能になります。

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

--- a/src/pkg/syscall/syscall_linux_arm.go
+++ b/src/pkg/syscall/syscall_linux_arm.go
@@ -170,10 +170,9 @@ func Setrlimit(resource int, rlim *Rlimit) (err error) {
 	return setrlimit(resource, &rl)
 }
 
-// TODO(kaib): add support for tracing
-func (r *PtraceRegs) PC() uint64 { return 0 }
+func (r *PtraceRegs) PC() uint64 { return uint64(r.Uregs[15]) }
 
-func (r *PtraceRegs) SetPC(pc uint64) {}
+func (r *PtraceRegs) SetPC(pc uint64) { r.Uregs[15] = uint32(pc) }
 
 func (iov *Iovec) SetLen(length int) {
 	iov.Len = uint32(length)

コアとなるコードの解説

  • func (r *PtraceRegs) PC() uint64 { return 0 } から func (r *PtraceRegs) PC() uint64 { return uint64(r.Uregs[15]) } への変更:

    • 変更前は、PC()メソッドは常に0を返していました。これは、プログラムカウンタの実際の値を取得する機能が未実装であったことを意味します。
    • 変更後は、r.Uregs[15]の値をuint64にキャストして返すようになりました。UregsPtraceRegs構造体内のレジスタ値を保持する配列であり、ARMアーキテクチャではインデックス15がプログラムカウンタ(R15)に対応します。これにより、実際のプログラムカウンタの値が取得できるようになりました。
  • func (r *PtraceRegs) SetPC(pc uint64) {} から func (r *PtraceRegs) SetPC(pc uint64) { r.Uregs[15] = uint32(pc) } への変更:

    • 変更前は、SetPC()メソッドは何も処理を行わない空の関数でした。これは、プログラムカウンタの値を設定する機能が未実装であったことを意味します。
    • 変更後は、引数として渡されたpc(プログラムカウンタの値)をuint32にキャストし、r.Uregs[15]に代入するようになりました。これにより、トレース対象プロセスのプログラムカウンタを外部から設定できるようになりました。ARMのレジスタが32ビット幅であることを考慮し、uint32へのキャストが行われています。

これらの変更により、Go言語のsyscallパッケージは、Linux ARM環境において、ptraceシステムコールを通じてプロセスのプログラムカウンタを正確に操作する能力を獲得しました。

関連リンク

参考にした情報源リンク

  • Go言語のソースコード (特にsrc/pkg/syscall/syscall_linux_arm.goの周辺コード)
  • ARMアーキテクチャのレジスタに関する一般的な知識
  • Linux ptraceシステムコールに関する一般的な知識
  • https://golang.org/cl/6763043 (Go Gerrit Code Review)

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

このコミットは、Go言語のsyscallパッケージ内のsyscall_linux_arm.goファイルに対する変更です。このファイルは、Linux ARMアーキテクチャに特化したシステムコール関連の機能を提供します。具体的には、プロセスをトレースする際に使用されるレジスタ情報(PtraceRegs構造体)の操作に関する機能が追加されています。

コミット

  • コミットハッシュ: 7c412e962c1cf5de4e128c0ca2caed14f9b87003
  • 作者: Shenghou Ma minux.ma@gmail.com
  • 日付: 2012年10月25日 木曜日 13:41:04 +0800

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

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

元コミット内容

    syscall: implement (*PtraceRegs).PC() and SetPC()
    
    R=golang-dev, rsc
    CC=golang-dev
    https://golang.org/cl/6763043

変更の背景

このコミットの背景には、Go言語のsyscallパッケージがLinux ARMアーキテクチャ上でのプロセスデバッグやトレース機能をより完全にサポートする必要があったことが挙げられます。

変更前のsrc/pkg/syscall/syscall_linux_arm.goファイルには、PtraceRegs構造体に対するPC()メソッドとSetPC()メソッドが定義されていましたが、これらはそれぞれreturn 0と空の関数として実装されていました。これは、これらの機能がまだ実装されておらず、将来的な対応が期待されていたことを示唆しています(コード内の// TODO(kaib): add support for tracingコメントからも明らかです)。

PC(プログラムカウンタ)は、CPUが次に実行する命令のアドレスを保持する非常に重要なレジスタです。デバッガなどのツールがプロセスの実行状態を制御したり、スタックトレースを生成したりする際には、このプログラムカウンタの値を読み書きする機能が不可欠です。

このコミットは、ARM Linux環境において、PtraceRegsからプログラムカウンタの値を正確に取得し、また設定できるようにすることで、Go言語のランタイムやデバッグツールがより高度なプロセス制御を行えるようにするために行われました。

前提知識の解説

syscallパッケージ

Go言語のsyscallパッケージは、オペレーティングシステムが提供する低レベルなシステムコールへのインターフェースを提供します。これにより、Goプログラムからファイル操作、プロセス管理、ネットワーク通信など、OSカーネルの機能に直接アクセスできます。OSやアーキテクチャに依存する機能は、syscall_linux_arm.goのように特定のファイルに分離して実装されることが一般的です。

PtraceRegs構造体

PtraceRegsは、ptraceシステムコールを通じて取得されるプロセスのCPUレジスタの状態を保持するための構造体です。ptraceは、デバッガが別のプロセスの実行を監視・制御するために使用するシステムコールです。この構造体には、汎用レジスタ、プログラムカウンタ、スタックポインタなどの情報が含まれます。

PC (Program Counter)

プログラムカウンタ(PC)は、CPUの内部レジスタの一つで、次に実行される機械語命令のアドレスを指し示します。CPUはPCが指すアドレスから命令をフェッチし、実行します。デバッグ時には、このPCの値を操作することで、プログラムの実行フローを制御したり、特定の命令から実行を再開させたりすることが可能になります。

ARMアーキテクチャとUregs[15]

ARM(Advanced RISC Machine)は、モバイルデバイスや組み込みシステムで広く使用されているCPUアーキテクチャです。ARMプロセッサには、汎用レジスタ(R0-R12)、スタックポインタ(SP、R13)、リンクレジスタ(LR、R14)、プログラムカウンタ(PC、R15)などがあります。

PtraceRegs構造体内のUregsフィールドは、これらの汎用レジスタや特殊レジスタの値を配列として保持していることが一般的です。ARMアーキテクチャでは、プログラムカウンタは通常R15レジスタに対応します。したがって、Uregs[15]はプログラムカウンタの値を表します。

技術的詳細

このコミットは、PtraceRegs構造体のPC()メソッドとSetPC()メソッドの実装を修正することで、Linux ARM環境におけるプロセスデバッグの基盤を強化しています。

  • PC()メソッド: このメソッドは、PtraceRegs構造体から現在のプログラムカウンタの値を読み出す役割を担います。ARMアーキテクチャの慣例に従い、Uregs配列のインデックス15(Uregs[15])がプログラムカウンタ(R15)に対応するため、その値をuint64型にキャストして返します。
  • SetPC()メソッド: このメソッドは、指定されたpc(プログラムカウンタ)の値をPtraceRegs構造体に書き込む役割を担います。これにより、デバッガはトレース対象プロセスの次に実行される命令のアドレスを変更できます。pcの値はuint32型にキャストされ、Uregs[15]に格納されます。ARMのレジスタは通常32ビット幅であるため、uint32へのキャストが適切です。

これらの変更により、Go言語のランタイムやデバッグツールは、ARM Linux上で実行されているプロセスのプログラムカウンタを正確に読み書きできるようになり、ブレークポイントの設定、ステップ実行、レジスタの検査といったデバッグ機能の実装が可能になります。

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

--- a/src/pkg/syscall/syscall_linux_arm.go
+++ b/src/pkg/syscall/syscall_linux_arm.go
@@ -170,10 +170,9 @@ func Setrlimit(resource int, rlim *Rlimit) (err error) {
 	return setrlimit(resource, &rl)
 }
 
-// TODO(kaib): add support for tracing
-func (r *PtraceRegs) PC() uint64 { return 0 }
+func (r *PtraceRegs) PC() uint64 { return uint64(r.Uregs[15]) }
 
-func (r *PtraceRegs) SetPC(pc uint64) {}
+func (r *PtraceRegs) SetPC(pc uint64) { r.Uregs[15] = uint32(pc) }
 
 func (iov *Iovec) SetLen(length int) {
 	iov.Len = uint32(length)

コアとなるコードの解説

  • func (r *PtraceRegs) PC() uint64 { return 0 } から func (r *PtraceRegs) PC() uint64 { return uint64(r.Uregs[15]) } への変更:

    • 変更前は、PC()メソッドは常に0を返していました。これは、プログラムカウンタの実際の値を取得する機能が未実装であったことを意味します。
    • 変更後は、r.Uregs[15]の値をuint64にキャストして返すようになりました。UregsPtraceRegs構造体内のレジスタ値を保持する配列であり、ARMアーキテクチャではインデックス15がプログラムカウンタ(R15)に対応します。これにより、実際のプログラムカウンタの値が取得できるようになりました。
  • func (r *PtraceRegs) SetPC(pc uint64) {} から func (r *PtraceRegs) SetPC(pc uint64) { r.Uregs[15] = uint32(pc) } への変更:

    • 変更前は、SetPC()メソッドは何も処理を行わない空の関数でした。これは、プログラムカウンタの値を設定する機能が未実装であったことを意味します。
    • 変更後は、引数として渡されたpc(プログラムカウンタの値)をuint32にキャストし、r.Uregs[15]に代入するようになりました。これにより、トレース対象プロセスのプログラムカウンタを外部から設定できるようになりました。ARMのレジスタが32ビット幅であることを考慮し、uint32へのキャストが行われています。

これらの変更により、Go言語のsyscallパッケージは、Linux ARM環境において、ptraceシステムコールを通じてプロセスのプログラムカウンタを正確に操作する能力を獲得しました。

関連リンク

参考にした情報源リンク

  • Go言語のソースコード (特にsrc/pkg/syscall/syscall_linux_arm.goの周辺コード)
  • ARMアーキテクチャのレジスタに関する一般的な知識
  • Linux ptraceシステムコールに関する一般的な知識
  • https://golang.org/cl/6763043 (Go Gerrit Code Review)
  • Web検索: "ARM architecture Uregs[15] program counter"