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

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

このコミットは、Go言語の debug/macho パッケージにおいて、Mach-O実行ファイル形式で利用されるCPUタイプ定数に、OS XおよびiOSで一般的に使用される他のアーキテクチャ(ARM, PowerPC, PowerPC64)を追加するものです。これにより、GoのデバッグツールがこれらのプラットフォームおよびアーキテクチャのMach-Oファイルをより適切に解析できるようになります。

コミット

commit a9600502bbaace43792e3f00a8f23286ba8a1667
Author: Robert Sesek <rsesek@google.com>
Date:   Thu Feb 27 19:11:03 2014 -0800

    debug/macho: Define CPU constants for other common architectures for OS X/iOS.
    
    LGTM=iant
    R=golang-codereviews, iant
    CC=golang-codereviews
    https://golang.org/cl/69100045

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

https://github.com/golang/go/commit/a9600502bbaace43792e3f00a8f23286ba8a1667

元コミット内容

debug/macho: Define CPU constants for other common architectures for OS X/iOS.

LGTM=iant
R=golang-codereviews, iant
CC=golang-codereviews
https://golang.org/cl/69100045

変更の背景

この変更が行われた2014年当時、AppleのエコシステムはIntelベースのMacとARMベースのiOSデバイスが主流でした。しかし、Mach-O形式はそれ以前のPowerPCアーキテクチャもサポートしており、また将来的なARMベースのMac(Apple Silicon)への移行を見越した、あるいは既存のiOS開発におけるクロスコンパイルやデバッグのニーズに対応するための準備として、GoのデバッグツールがこれらのアーキテクチャのMach-Oファイルを正しく識別できるようにする必要がありました。

debug/macho パッケージは、GoのツールチェインがMach-O形式の実行ファイルやライブラリを解析するために使用されます。これには、デバッガ、プロファイラ、あるいはバイナリ解析ツールなどが含まれます。これらのツールが異なるCPUアーキテクチャでビルドされたMach-Oファイルを正確に処理するためには、そのファイルがどのCPUタイプを対象としているかを識別する定数が必要不可欠です。

既存の Cpu386CpuAmd64 に加えて、ARM、PowerPC、PowerPC64の定数を追加することで、Goのツールがより広範なAppleプラットフォームのバイナリに対応できるようになり、クロスプラットフォーム開発やデバッグの利便性が向上します。特に、iOSデバイス向けのARMバイナリの解析能力は、モバイル開発において重要です。

前提知識の解説

Mach-O (Mach Object)

Mach-Oは、macOS (旧称 OS X)、iOS、watchOS、tvOSなどのApple製オペレーティングシステムで使用される実行ファイル、オブジェクトコード、共有ライブラリ、ダイナミックロード可能バンドル、およびコアダンプのファイル形式です。WindowsのPE (Portable Executable) やLinuxのELF (Executable and Linkable Format) に相当します。

Mach-Oファイルは、ヘッダ、ロードコマンド、セグメント、セクションなど、複数の論理的なブロックで構成されています。ヘッダには、ファイルのタイプ(実行ファイル、ライブラリなど)、CPUアーキテクチャ、フラグなどの基本的な情報が含まれます。

CPUタイプ (CPU Type)

Mach-Oヘッダには、そのバイナリがどのCPUアーキテクチャ向けにビルドされたかを示す「CPUタイプ」フィールドが含まれています。これは通常、32ビットの整数値で表現され、特定のアーキテクチャ(例: Intel x86, ARM, PowerPC)を一意に識別します。

CPUサブタイプ (CPU Subtype)

CPUタイプと組み合わせて使用される「CPUサブタイプ」は、同じCPUタイプ内でのより具体的なバリアント(例: ARMv7, ARM64)を識別します。これにより、特定のCPUの機能セットや命令セットに最適化されたバイナリを区別できます。

debug/macho パッケージ

Go言語の標準ライブラリに含まれる debug/macho パッケージは、Mach-O形式のバイナリファイルを解析するためのAPIを提供します。このパッケージを使用することで、GoプログラムはMach-Oファイルのヘッダ情報、ロードコマンド、セグメント、セクションなどを読み取り、バイナリの構造を理解することができます。これは、デバッガ、プロファイラ、シンボルツール、あるいはカスタムのバイナリ解析ツールをGoで実装する際に利用されます。

ビット幅の表現 cpuArch64

Mach-OのCPUタイプでは、32ビットアーキテクチャと64ビットアーキテクチャを区別するために、CPUタイプ値に特定のビット(通常は最上位ビットの一つ)を立てる慣習があります。このコミットで導入された cpuArch64 は、この64ビットアーキテクチャを示すフラグを表しています。例えば、CpuAmd64Cpu386 (Intel x86 32-bit) に cpuArch64 をOR演算することで、Intel x86 64-bit (AMD64) を表現しています。同様に、CpuPpc64CpuPpccpuArch64 をOR演算することで表現されます。

技術的詳細

このコミットの主要な変更点は、src/pkg/debug/macho/macho.go ファイル内の Cpu 型に関連する定数の追加と修正です。

  1. cpuArch64 定数の導入: const cpuArch64 = 0x01000000 が新しく定義されました。この定数は、Mach-OのCPUタイプにおいて、64ビットアーキテクチャを示すために使用されるビットマスクです。この値は、CPUタイプの上位ビットに設定されることで、そのアーキテクチャが64ビットであることを示します。

  2. CpuAmd64 の定義変更: CpuAmd64 Cpu = Cpu386 + 1<<24 から CpuAmd64 Cpu = Cpu386 | cpuArch64 に変更されました。 以前の 1<<24 も実質的に 0x01000000 と同じ値ですが、cpuArch64 という名前付き定数を使用することで、コードの意図がより明確になりました。これは、Cpu386 (Intel x86 32-bit) に64ビットアーキテクチャのフラグをOR演算することで、CpuAmd64 (Intel x86 64-bit) を表現するというMach-Oの慣習に沿ったものです。

  3. 新しいCPU定数の追加: 以下のCPUタイプ定数が追加されました。

    • CpuArm Cpu = 12: ARMアーキテクチャ(主に32ビットARM)のCPUタイプです。iOSデバイスで広く使用されています。
    • CpuPpc Cpu = 18: PowerPCアーキテクチャ(主に32ビットPowerPC)のCPUタイプです。かつてのMacintoshコンピュータで使用されていました。
    • CpuPpc64 Cpu = CpuPpc | cpuArch64: PowerPC 64ビットアーキテクチャのCPUタイプです。CpuPpccpuArch64 をOR演算することで、64ビット版のPowerPCを表現しています。
  4. cpuStrings マップの更新: cpuStrings は、Cpu 型の数値とそれに対応する文字列名をマッピングするためのスライスです。新しく追加されたCPU定数 (CpuArm, CpuPpc, CpuPpc64) がこのスライスに追加され、String() メソッドがこれらの新しいCPUタイプを正しく文字列として表現できるようになりました。

これらの変更により、debug/macho パッケージは、Intel x86 (32/64ビット)、ARM (32ビット)、PowerPC (32/64ビット) のMach-Oバイナリを識別し、解析する能力が向上しました。これは、GoのツールがAppleのエコシステムにおける多様なハードウェアとソフトウェアに対応するために不可欠なステップです。

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

--- a/src/pkg/debug/macho/macho.go
+++ b/src/pkg/debug/macho/macho.go
@@ -44,14 +44,22 @@ const (
 // A Cpu is a Mach-O cpu type.
 type Cpu uint32
 
+const cpuArch64 = 0x01000000
+
 const (
  	Cpu386   Cpu = 7
 -	CpuAmd64 Cpu = Cpu386 + 1<<24
 +	CpuAmd64 Cpu = Cpu386 | cpuArch64
 +	CpuArm   Cpu = 12
 +	CpuPpc   Cpu = 18
 +	CpuPpc64 Cpu = CpuPpc | cpuArch64
  )
  
  var cpuStrings = []intName{
  	{uint32(Cpu386), "Cpu386"},
  	{uint32(CpuAmd64), "CpuAmd64"},
 +	{uint32(CpuArm), "CpuArm"},
 +	{uint32(CpuPpc), "CpuPpc"},
 +	{uint32(CpuPpc64), "CpuPpc64"},
  }
  
  func (i Cpu) String() string   { return stringName(uint32(i), cpuStrings, false) }

コアとなるコードの解説

const cpuArch64 = 0x01000000

この行は、64ビットアーキテクチャを示すためのビットマスク cpuArch64 を定義しています。Mach-OのCPUタイプでは、特定のビットがセットされているかどうかで32ビットと64ビットを区別します。0x01000000 は、この区別のためのフラグ値です。

CpuAmd64 Cpu = Cpu386 | cpuArch64

CpuAmd64 の定義が変更されました。以前は Cpu386 + 1<<24 でしたが、これは Cpu386 | cpuArch64 と同等です。この変更は、cpuArch64 という名前付き定数を使用することで、コードの可読性と意図を向上させています。Cpu386 (Intel x86 32-bit) に cpuArch64 フラグをOR演算することで、Intel x86 64-bit (AMD64) のCPUタイプを表現しています。これは、Mach-OのCPUタイプ値のエンコーディング規則に則ったものです。

CpuArm Cpu = 12

ARMアーキテクチャのCPUタイプ定数 CpuArm が追加されました。値 12 は、Mach-Oの仕様でARM CPUタイプに割り当てられている数値です。これは、iOSデバイスや、将来のApple Silicon Macで利用されるARMバイナリを識別するために使用されます。

CpuPpc Cpu = 18

PowerPCアーキテクチャのCPUタイプ定数 CpuPpc が追加されました。値 18 は、Mach-Oの仕様でPowerPC CPUタイプに割り当てられている数値です。これは、かつてのMacintoshコンピュータで使用されていたPowerPCバイナリを識別するために使用されます。

CpuPpc64 Cpu = CpuPpc | cpuArch64

PowerPC 64ビットアーキテクチャのCPUタイプ定数 CpuPpc64 が追加されました。これは、CpuPpc (32ビットPowerPC) に cpuArch64 フラグをOR演算することで定義されています。これにより、64ビット版のPowerPCバイナリを識別できるようになります。

var cpuStrings = []intName{...} の更新

cpuStrings スライスは、Cpu 型の数値とそれに対応する人間が読める文字列名をマッピングするために使用されます。新しく追加された CpuArm, CpuPpc, CpuPpc64 の各定数とその文字列表現がこのスライスに追加されました。これにより、Cpu 型の String() メソッドがこれらの新しいCPUタイプを正しく文字列として返すことができるようになります。

これらの変更は、Goの debug/macho パッケージが、Appleプラットフォームで利用される多様なCPUアーキテクチャのMach-Oバイナリをより正確に識別し、解析するための基盤を強化するものです。

関連リンク

参考にした情報源リンク