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

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

このコミットは、Go言語のランタイムにおけるlibmach_amd64ライブラリに、32ビットのMach-O(macOSの実行ファイル形式)およびELF(Linuxなどの実行ファイル形式)バイナリのサポートを追加するものです。これにより、Goのデバッガやプロファイラが、これらの32ビットバイナリをより適切に解析・操作できるようになります。特に、Inferno OSのlibmachライブラリから派生したコードが導入され、386アーキテクチャのオブジェクトファイル解析能力が向上しています。

コミット

add .8 support to libmach_amd64 [sic].
add code to handle 32-bit Mach-O and ELF binaries.

R=r
DELTA=452  (365 added, 29 deleted, 58 changed)
OCL=26696
CL=26712

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

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

元コミット内容

add .8 support to libmach_amd64 [sic].
add code to handle 32-bit Mach-O and ELF binaries.

変更の背景

このコミットの主な背景は、Go言語のツールチェイン(特にデバッガやプロファイラ)が、異なるアーキテクチャやオペレーティングシステムで生成されたバイナリをより広範にサポートする必要があったためです。当時、Goはまだ初期段階にあり、クロスコンパイルや異なる環境でのデバッグの重要性が増していました。

具体的には、以下のニーズに対応しています。

  1. 32ビットバイナリのサポート強化: 64ビットシステム上で32ビットバイナリをデバッグしたり、その情報を解析したりする際に、libmach_amd64が適切に機能するようにするため。
  2. Mach-OとELF形式の拡張: macOS (Mach-O) とLinux (ELF) の両方で、32ビット版の実行ファイル形式を正確に解析する能力を向上させるため。
  3. Inferno OSの知見の活用: Inferno OSのlibmachは、様々なアーキテクチャのオブジェクトファイルを解析するための実績あるライブラリであり、そのコードベースをGoに導入することで、堅牢なバイナリ解析機能を実現しようとしています。特に、Plan 9由来のGoツールチェインにとって、8.out形式(386アーキテクチャのオブジェクトファイル形式)のサポートは自然な流れでした。

これらの変更により、Goのデバッグツールがより多様な実行環境に対応できるようになり、開発者がGoプログラムをより効率的にデバッグ・プロファイルできるようになることが期待されました。

前提知識の解説

このコミットを理解するためには、以下の技術的な概念を把握しておく必要があります。

1. libmach

libmachは、Plan 9およびInferno OSに由来するライブラリで、実行ファイルやオブジェクトファイルの内部構造を解析するための低レベルな機能を提供します。デバッガやプロファイラが、プログラムのシンボルテーブル、テキストセクション、データセクション、レジスタ情報などを読み取るために使用されます。Go言語のツールチェインは、初期の段階でPlan 9の設計思想やコードベースから多くの影響を受けており、libmachはその一例です。

2. Mach-O (Mach Object)

Mach-Oは、AppleのmacOS (旧OS X) およびiOSで使用される実行ファイル、オブジェクトコード、共有ライブラリ、およびコアダンプのファイル形式です。Mach-Oファイルは、ヘッダ、ロードコマンド、およびセグメント(セクションを含む)で構成されます。ロードコマンドは、カーネルがバイナリをメモリにロードする方法を記述し、セグメントはコード、データ、スタックなどの領域を定義します。

  • 32ビット Mach-O: 32ビットアーキテクチャ(例: Intel i386)向けのMach-Oファイル。
  • 64ビット Mach-O: 64ビットアーキテクチャ(例: Intel x86-64)向けのMach-Oファイル。

3. ELF (Executable and Linkable Format)

ELFは、Unix系オペレーティングシステム(Linux、FreeBSDなど)で広く使用されている実行ファイル、オブジェクトコード、共有ライブラリ、およびコアダンプの標準ファイル形式です。ELFファイルもヘッダ、プログラムヘッダテーブル(実行時情報)、セクションヘッダテーブル(リンク時情報)、およびセクションで構成されます。

  • 32ビット ELF: 32ビットアーキテクチャ向けのELFファイル。
  • 64ビット ELF: 64ビットアーキテクチャ向けのELFファイル。

4. 32ビットと64ビットアーキテクチャ

  • 32ビットアーキテクチャ: CPUが32ビットのレジスタとメモリアドレスを使用します。これにより、最大4GBのメモリ空間を直接アドレス指定できます。
  • 64ビットアーキテクチャ: CPUが64ビットのレジスタとメモリアドレスを使用します。これにより、理論上は非常に広大なメモリ空間(18エクサバイト)をアドレス指定できます。

デバッガやバイナリ解析ツールは、対象となるバイナリが32ビットか64ビットかによって、レジスタのサイズ、メモリアドレスの解釈、ファイル形式の構造などを適切に処理する必要があります。

5. ptraceシステムコール

ptraceは、Unix系システムでプロセスをトレース(追跡)するためのシステムコールです。デバッガはこれを使用して、ターゲットプロセスの実行を制御したり、レジスタやメモリの内容を読み書きしたりします。ptraceは、デバッグ対象のプロセスのレジスタセットを、デバッガ自身のアーキテクチャとは異なる形式で提供することがあります。このコミットでは、64ビットデバッガが32ビットターゲットのレジスタを適切に解釈するためのマッピングが追加されています。

6. Plan 9 8.out形式

Plan 9オペレーティングシステムでは、各アーキテクチャに番号が割り当てられており、Intel 386アーキテクチャは「8」とされています。したがって、8.outは386アーキテクチャ向けのオブジェクトファイル形式を指します。このコミットで追加された8obj.cは、この形式のファイルを解析するためのものです。

7. バイトオーダー (Endianness)

バイトオーダーは、複数バイトで構成されるデータをメモリに格納する際のバイトの順序を指します。

  • リトルエンディアン (Little-endian): 最下位バイトが最も小さいアドレスに格納されます。Intel x86/x86-64アーキテクチャで一般的です。
  • ビッグエンディアン (Big-endian): 最上位バイトが最も小さいアドレスに格納されます。ネットワークプロトコルや一部のプロセッサで一般的です。 実行ファイル形式の解析では、ファイルのヘッダや構造体内の数値がどのバイトオーダーで格納されているかを正しく解釈する必要があります。このコミットのコードでは、leswal (little-endian swap long) や swav (swap value) といった関数が使われており、バイトオーダーの変換を適切に行っていることが伺えます。

技術的詳細

このコミットは、主にsrc/libmach_amd64ディレクトリ内のファイル群を変更し、32ビットのMach-OおよびELFバイナリの解析能力を向上させています。

1. src/libmach_amd64/8obj.c の新規追加

このファイルは、Inferno OSのlibmach/8obj.cから派生したもので、386アーキテクチャのオブジェクトファイル(Plan 9の8.out形式)を識別し、解析するためのロジックを含んでいます。

  • _is8(char *t): 与えられたバイト列が386オブジェクトファイルのシグネチャに一致するかを判定します。
  • _read8(Biobuf *bp, Prog* p): オブジェクトファイルからプログラム(Prog構造体)の情報を読み取ります。これには、シンボル名、タイプ(テキスト、データなど)、オフセットなどが含まれます。
  • addr(Biobuf *bp): アドレス情報を解析します。オフセット、シンボル参照、型情報などを処理します。
  • type2char(int t): 内部的な型定数を文字表現に変換します(例: D_EXTERN'U'に)。

このファイルの追加により、libmach_amd64は386アーキテクチャのオブジェクトファイルを直接理解できるようになりました。

2. src/libmach_amd64/Makefile の変更

新しく追加された8obj.cがビルドプロセスに含まれるように、OFILES変数に8obj.$Oが追加されています。これにより、8obj.cがコンパイルされ、libmach_amd64ライブラリの一部としてリンクされるようになります。

3. src/libmach_amd64/executable.c の変更

このファイルは、様々な実行ファイル形式を識別し、そのヘッダ情報を解析するための中心的なロジックを含んでいます。

  • ExecTableの更新:
    • MACH_MAGMACH64_MAGにリネームされ、64ビットMach-Oを明示的に指すようになりました。
    • 新しくMACH32_MAGが追加され、32ビットMach-Oバイナリの識別と解析がサポートされました。これには、FI386(386アーキテクチャのファイルタイプ)とmi386(386アーキテクチャの機械情報)が関連付けられています。
  • elf64dotoutの変更:
    • ELF64バイナリの解析において、特定のCPUタイプ(I386, MIPS, SPARC64, POWER, ARM)に対するmachfp->typeの設定ロジックが削除されました。これは、elf64dotoutがAMD64に特化し、他のアーキテクチャのELF64バイナリは別のパスで処理されるか、あるいはこの関数がより汎用的なELF64解析に集中するように変更されたことを示唆しています。
    • シンボルテーブルの処理において、sh(セクションヘッダ)がph(プログラムヘッダ)の代わりに使われるようになりました。これは、ELFファイルのシンボル情報がプログラムヘッダではなくセクションヘッダに格納されることが一般的であるため、より正確な解析を行うための修正です。
  • elfdotoutの変更:
    • 32ビットELFバイナリの解析において、セクションヘッダテーブル(Shdr32)を読み込むロジックが追加されました。これにより、.gosymtab.gopclntabといったGo固有のセクションを正確に特定し、シンボル情報やPC-Lineテーブル(プログラムカウンタとソースコード行のマッピング)を抽出できるようになりました。
    • エラーハンドリングが改善され、sh(セクションヘッダ)の解放が適切に行われるようになりました。
  • machdotoutの変更:
    • Mach-Oファイルの解析において、32ビットと64ビットのMach-Oヘッダを区別するためのロジックが追加されました。mp->magic(マジックナンバー)に基づいて、0xFEEDFACE(32ビットMach-O)と0xFEEDFACF(64ビットMach-O)を識別します。
    • 32ビットMach-O (MACH_SEGMENT_32) と64ビットMach-O (MACH_SEGMENT_64) のセグメント(MachSeg32, MachSeg64)とセクション(MachSect32, MachSect64)の解析ロジックが分岐されました。これにより、それぞれのアーキテクチャに応じた構造体のオフセットやサイズが正しく処理されます。
    • テキストセクションとデータセクションの仮想アドレス (textva, datava) とファイルオフセット (textoff, dataoff) の取得方法が、32ビットと64ビットの両方に対応するように修正されました。
    • settextsetdata関数への引数が、セグメント構造体へのポインタから、直接計算された仮想アドレス、サイズ、オフセットに変更されました。これにより、コードがより汎用的になり、32ビットと64ビットの両方のセグメント情報を統一的に扱えるようになりました。

4. src/libmach_amd64/fakeobj.c の変更

このファイルは、特定のオブジェクトファイル形式のサポートが有効になっていない場合に、ダミーの関数を提供するものです。_is8_read8関数が削除されました。これは、8obj.cが新しく追加され、386オブジェクトファイルの実際のサポートが提供されるようになったため、これらのダミー関数が不要になったことを意味します。

5. src/libmach_amd64/linux.c の変更

このファイルは、Linux環境でのデバッグやプロセス操作に関連するロジックを含んでいます。

  • 32ビットレジスタマッピングの追加:
    • go32tolinux64tabという配列が追加されました。これは、Goの32ビットレジスタのオフセットを、Linuxの64ビットuser_regs_struct内の対応するレジスタのオフセットにマッピングするためのものです。
    • go32tolinux64(uvlong addr)関数が追加され、Goの32ビットレジスタアドレスをLinuxの64ビットレジスタセット内のオフセットに変換します。
    • go2linux(uvlong addr)関数内で、mach == &mi386(386アーキテクチャの場合)にこの新しい32ビットマッピングを使用するロジックが追加されました。
  • Ureg構造体の扱い:
    • Uregマクロが一時的にUreg32に定義され、その後Ureg64に再定義されることで、32ビットと64ビットのレジスタ構造体を適切に扱うための準備がされています。
  • エラーメッセージの改善: ptraceregrw関数で、エラーメッセージにn(バイト数)が追加され、デバッグ情報がより詳細になりました。

これらの変更により、64ビットのデバッガが32ビットのLinuxプロセスをデバッグする際に、レジスタ情報を正しく読み書きできるようになります。

6. src/libmach_amd64/macho.h の変更

このヘッダファイルは、Mach-Oファイル形式に関連する構造体と定数を定義しています。

  • 32ビットMach-O構造体の追加:
    • MachSeg32構造体が追加されました。これは、32ビットMach-Oバイナリのセグメント情報を定義します。vmaddrvmsizefileofffilesizeなどが32ビット幅になっています。
    • MachSect32構造体が追加されました。これは、32ビットMach-Oバイナリのセクション情報を定義します。
  • 新しい定数の追加:
    • MACH_CPU_TYPE_X86 (7): 32ビットx86 CPUタイプ。
    • MACH_SEGMENT_32 (1): 32ビットマップされたセグメントのロードコマンドタイプ。
    • MACH32_MAG: 32ビットMach-Oのマジックナンバー (0xFEEDFACE)。
    • MACH64_MAG: 64ビットMach-Oのマジックナンバー (0xFEEDFACF) が明示的に定義されました(以前はMACH_MAG)。

これらの定義により、Mach-Oファイルのヘッダを正確に解析し、32ビットと64ビットの構造体の違いをコードで区別できるようになります。

7. src/libmach_amd64/8.c の変更

このファイルは、386アーキテクチャの機械情報(mi386構造体)を定義しています。

  • mi386構造体のuser stack topの値が0x7FFFFFFFULLから0xFFFFFFFFULLに変更されました。
    • 0x7FFFFFFFULLは、符号付き32ビット整数の最大値であり、32ビットアドレス空間の上限の半分を示唆している可能性があります。
    • 0xFFFFFFFFULLは、符号なし32ビット整数の最大値であり、32ビットアドレス空間の全体(4GB)を示します。 この変更は、32ビット環境におけるユーザースタックの最大アドレスを、より広範な32ビットアドレス空間の最上位に設定し、潜在的なスタックオーバーフローやアドレス計算の不整合を解消することを目的としていると考えられます。

これらの変更全体として、Goのツールチェインが32ビットのMach-OおよびELFバイナリをより正確かつ堅牢に解析・操作できるようになり、クロスアーキテクチャデバッグの能力が向上しました。

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

1. src/libmach_amd64/8obj.c (新規ファイル)

// Inferno libmach/8obj.c
// ... (copyright and license) ...

/*
 * 8obj.c - identify and parse a 386 object file
 */
#include <u.h>
#include <libc.h>
#include <bio.h>
#include <mach_amd64.h>
#include "../cmd/8l/8.out.h" // Plan 9 386 assembler/linker output format
#include "obj.h"

// ... (typedef struct Addr, static Addr addr, static char type2char, static void skip) ...

int
_is8(char *t)
{
	uchar *s = (uchar*)t;

	return  s[0] == (ANAME&0xff)
		&& s[1] == ((ANAME>>8)&0xff)
		&& s[2] == D_FILE
		&& s[3] == 1
		&& s[4] == '<'; // name of file
}

int
_read8(Biobuf *bp, Prog* p)
{
	int as, n, c;
	Addr a;

	as = Bgetc(bp); // as(low)
	if(as < 0)
		return 0;
	c = Bgetc(bp); // as(high)
	if(c < 0)
		return 0;
	as |= ((c & 0xff) << 8);
	p->kind = aNone;
	p->sig = 0;
	if(as == ANAME || as == ASIGNAME){
		// ... (name and signature parsing) ...
		return 1;
	}
	if(as == ATEXT)
		p->kind = aText;
	if(as == AGLOBL)
		p->kind = aData;
	skip(bp, 4); // lineno(4)
	a = addr(bp);
	addr(bp);
	if(!(a.flags & T_SYM))
		p->kind = aNone;
	p->sym = a.sym;
	return 1;
}

2. src/libmach_amd64/executable.cmachdotout 関数内

// ... (previous code) ...

	hdrsize = 0;

	switch(mp->magic) {
	case 0xFEEDFACE:	// 32-bit mach
		if (mp->cputype != MACH_CPU_TYPE_X86) {
			werrstr("bad MACH cpu type - not 386");
			return 0;
		}
		// ... (other checks) ...
		mach = &mi386;
		fp->type = FI386;
		hdrsize = 28;
		break;

	case 0xFEEDFACF:	// 64-bit mach
		if (mp->cputype != MACH_CPU_TYPE_X86_64) {
			werrstr("bad MACH cpu type - not amd64");
			return 0;
		}
		// ... (other checks) ...
		mach = &mamd64;
		fp->type = FAMD64;
		hdrsize = 32;
		break;

	default:
		werrstr("not mach %#ux", mp->magic);
		return 0;
	}

	// ... (command buffer allocation and reading) ...

	for(i = 0; i < mp->ncmds; i++) {
		cmd[i] = (MachCmd*)cmdp;
		c = cmd[i];
		c->type = swal(c->type);
		c->size = swal(c->size);
		switch(c->type) {
		case MACH_SEGMENT_32:
			if(mp->magic != 0xFEEDFACE) {
				werrstr("segment 32 in mach 64");
				goto bad;
			}
			seg32 = (MachSeg32*)c;
			// ... (32-bit segment parsing) ...
			break;

		case MACH_SEGMENT_64:
			if(mp->magic != 0xFEEDFACF) {
				werrstr("segment 32 in mach 64"); // This error message seems to be a copy-paste error, should be "segment 64 in mach 32"
				goto bad;
			}
			seg = (MachSeg64*)c;
			// ... (64-bit segment parsing) ...
			break;
		// ... (other cases) ...
		}
		cmdp += c->size;
	}
	// ... (settext, setdata, setsym calls) ...

3. src/libmach_amd64/linux.cgo2linux 関数内

// ... (previous code) ...

uint go32tolinux64tab[] = {
	14, 13, 4, 19, 5, 12, 11, 10, 26, 25, 24, 23, -1, -1, 16, 17, 18, 19, 20
};
static int
go32tolinux64(uvlong addr)
{
	int r;

	if(addr%4 || addr/4 >= nelem(go32tolinux64tab))
		return -1;
	r = go32tolinux64tab[addr/4];
	if(r < 0)
		return -1;
	return r*8;
}

extern Mach mi386; // Declaration for mi386 from 8.c

static int
go2linux(uvlong addr)
{
	// TODO(rsc): If this file is being compiled in 32-bit mode,
	// need to use the go32tolinux32 table instead.

	if(mach == &mi386) // Check if the target architecture is 386
		return go32tolinux64(addr);

	switch(addr){
	case offsetof(Ureg64, ax):
		return offsetof(struct user_regs_struct, rax);
	// ... (other 64-bit register mappings) ...
	}
	return -1;
}

4. src/libmach_amd64/macho.h

// ... (previous definitions) ...

typedef struct  {
	MachCmd	cmd;
	char		segname[16];	/* segment name */
	uint32	vmaddr;		/* memory address of this segment */
	uint32	vmsize;		/* memory size of this segment */
	uint32	fileoff;	/* file offset of this segment */
	uint32	filesize;	/* amount to map from the file */
	uint32	maxprot;	/* maximum VM protection */
	uint32	initprot;	/* initial VM protection */
	uint32	nsects;		/* number of sections in segment */
	uint32	flags;		/* flags */
} MachSeg32; /* for 32-bit architectures */

// ... (MachSeg64, MachSymSeg) ...

typedef struct  {
	char		sectname[16];	/* name of this section */
	char		segname[16];	/* segment this section goes in */
	uint32	addr;		/* memory address of this section */
	uint32	size;		/* size in bytes of this section */
	uint32	offset;		/* file offset of this section */
	uint32	align;		/* section alignment (power of 2) */
	uint32	reloff;		/* file offset of relocation entries */
	uint32	nreloc;		/* number of relocation entries */
	uint32	flags;		/* flags (section type and attributes)*/
	uint32	reserved1;	/* reserved (for offset or index) */
	uint32	reserved2;	/* reserved (for count or sizeof) */
} MachSect32; /* for 32-bit architectures */

// ... (MachSect64) ...

enum {
	MACH_CPU_TYPE_X86_64 = (1<<24)|7,
	MACH_CPU_TYPE_X86 = 7, // New: 32-bit x86 CPU type
	MACH_CPU_SUBTYPE_X86 = 3,
	MACH_EXECUTABLE_TYPE = 2,
	MACH_SEGMENT_32 = 1,	/* New: 32-bit mapped segment */
	MACH_SEGMENT_64 = 0x19,	/* 64-bit mapped segment */
	MACH_SYMSEG = 3,
	MACH_UNIXTHREAD = 0x5,
};

#define	MACH64_MAG		((0xcf<<24) | (0xfa<<16) | (0xed<<8) | 0xfe) // Renamed from MACH_MAG
#define	MACH32_MAG		((0xce<<24) | (0xfa<<16) | (0xed<<8) | 0xfe) // New: 32-bit Mach-O magic number

コアとなるコードの解説

1. src/libmach_amd64/8obj.c

このファイルは、Plan 9の386アーキテクチャ(通称.8)のオブジェクトファイルを解析するためのものです。

  • _is8関数は、ファイルの先頭数バイトをチェックして、それが386オブジェクトファイルであるかどうかを識別します。具体的には、ANAMEというシンボルタイプとD_FILEというデータタイプ、そしてファイル名の開始を示す'<'文字の組み合わせを期待しています。これは、Plan 9のオブジェクトファイルが持つ独特のヘッダ形式です。
  • _read8関数は、識別された386オブジェクトファイルから、個々のプログラム要素(Prog構造体)を読み取ります。これには、アセンブリ命令の種類(ATEXTAGLOBLなど)、行番号、シンボル情報などが含まれます。この関数は、オブジェクトファイル内のバイト列を解析し、Goの内部表現に変換する役割を担っています。

2. src/libmach_amd64/executable.cmachdotout 関数

machdotout関数は、Mach-O形式の実行ファイルを解析し、その構造(テキストセクション、データセクション、シンボルテーブルなど)をGoの内部表現にマッピングします。

  • マジックナンバーによる分岐: mp->magic(Mach-Oヘッダのマジックナンバー)をチェックすることで、32ビットMach-O (0xFEEDFACE) と64ビットMach-O (0xFEEDFACF) を区別します。これにより、それぞれのアーキテクチャに応じたCPUタイプ (MACH_CPU_TYPE_X86 vs MACH_CPU_TYPE_X86_64) とファイルタイプ (FI386 vs FAMD64) が設定されます。
  • ロードコマンドの解析: Mach-Oファイルは「ロードコマンド」と呼ばれる構造体群を持っており、これらがバイナリのセグメント、シンボルテーブル、スレッド情報などを記述しています。このコードでは、各ロードコマンドのタイプ (c->type) をチェックし、MACH_SEGMENT_32またはMACH_SEGMENT_64であるかによって、対応する32ビット (MachSeg32) または64ビット (MachSeg64) のセグメント構造体として解析します。これにより、テキストセクションやデータセクションの仮想アドレス、ファイルオフセット、サイズなどを正確に抽出できます。

3. src/libmach_amd64/linux.cgo2linux 関数

go2linux関数は、Goの内部的なレジスタオフセットを、Linuxのptraceシステムコールが使用するuser_regs_struct内の対応するレジスタオフセットに変換する役割を担います。

  • 32ビットターゲットのサポート: if(mach == &mi386)という条件文が追加されました。これは、現在解析しているバイナリが386アーキテクチャ(32ビット)である場合に、特別なレジスタマッピングを行うことを意味します。
  • go32tolinux64tab: この配列は、Goの32ビットレジスタの論理的なオフセット(例えば、axが0、bxが4など)を、64ビットLinuxカーネルが提供するuser_regs_struct内の対応するレジスタのオフセットに変換するためのマッピングテーブルです。例えば、Goの32ビットDIレジスタがLinuxの64ビットrdiレジスタの下位32ビットに対応する場合、そのオフセットがこのテーブルに格納されます。go32tolinux64関数は、このテーブルを使って実際のバイトオフセットを計算します。
  • 64ビットターゲットのサポート: switch(addr)ブロックは、64ビットGoプログラムのレジスタオフセットを、64ビットLinuxのuser_regs_struct内の対応するレジスタオフセットに変換します。

このロジックにより、64ビットのGoデバッガが32ビットのGoプログラムをLinux上でデバッグする際に、レジスタの値を正しく読み書きできるようになります。

4. src/libmach_amd64/macho.h

このヘッダファイルは、Mach-Oバイナリの構造をC言語の構造体として定義することで、プログラムがMach-Oファイルをバイトレベルで解析できるようにします。

  • MachSeg32MachSect32: これらの新しい構造体は、32ビットMach-Oバイナリのセグメントとセクションのレイアウトを正確に反映しています。例えば、アドレスやサイズを示すフィールドがuint32型である点が64ビット版 (MachSeg64, MachSect64) と異なります。
  • マジックナンバーとCPUタイプの定数: MACH32_MAGMACH_CPU_TYPE_X86といった定数は、Mach-Oファイルのヘッダを読み込んだ際に、それが32ビットのx86アーキテクチャ向けであるかを迅速に判断するために使用されます。

これらの定義は、executable.cなどのファイルがMach-Oバイナリを正しく解釈するための基盤となります。

関連リンク

参考にした情報源リンク

  • コミット情報: commit_data/1884.txt
  • GitHub上のコミットページ: https://github.com/golang/go/commit/fcd536d801a60ed0a00152851d42b88c7947a4ce
  • Inferno OSのソースコード (特にutils/libmach/8obj.c): http://code.google.com/p/inferno-os/source/browse/utils/libmach/8obj.c (これは古いGoogle Codeのリンクですが、Inferno OSのコードベースは現在も利用可能です)
  • Go言語の初期の設計に関する議論やドキュメント (Goの歴史的背景を理解するため)
  • x86およびx86-64アーキテクチャのレジスタセットとメモリモデルに関する一般的な情報
  • Mach-OおよびELFファイル形式の仕様に関する一般的な情報
  • ptraceシステムコールの動作に関する一般的な情報
  • バイトオーダー (Endianness) に関する一般的な情報