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

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

このコミットは、Go言語のリンカ (cmd/ld) における変更を扱っています。具体的には、OpenBSD 5.3/5.4 およびそれ以降のバージョンで、GoプログラムがネイティブのCコード(hostobj)とリンクする際に発生する問題を解決するためのものです。OpenBSDの新しいバージョンでは、Position-Independent Executable (PIE) がデフォルトで有効になっているため、Goリンカが生成するオブジェクトファイルとの互換性の問題が生じていました。

コミット

commit 0eaabf6452149ecbcc1caf40e22ae16cf73c768e
Author: Joel Sing <jsing@google.com>
Date:   Fri Dec 20 03:58:27 2013 +1100

    cmd/ld: make hostobj work on newer openbsd
    
    Make hostobj work on OpenBSD 5.3/5.4/-current - these have PIE
    enabled by default and linking fails since the Go linker generates
    objects that are neither PIC nor PIE.
    
    Fixes #5067
    
    R=golang-dev, rsc
    CC=golang-dev
    https://golang.org/cl/7572049

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

https://github.com/golang/go/commit/0eaabf6452149ecbcc1caf40e22ae16cf73c768e

元コミット内容

cmd/ld: make hostobj work on newer openbsd

Make hostobj work on OpenBSD 5.3/5.4/-current - these have PIE
enabled by default and linking fails since the Go linker generates
objects that are neither PIC nor PIE.

Fixes #5067

R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/7572049

変更の背景

この変更の背景には、OpenBSDオペレーティングシステムのセキュリティ強化があります。OpenBSDは、その堅牢なセキュリティで知られており、Position-Independent Executable (PIE) の採用はその一環です。PIEは、実行ファイルがメモリ上のランダムなアドレスにロードされることを可能にし、Address Space Layout Randomization (ASLR) と組み合わせて、バッファオーバーフローなどの攻撃を困難にします。

しかし、Go言語のリンカ (cmd/ld) は、当時(2013年頃)はPIEまたはPosition-Independent Code (PIC) に対応したオブジェクトファイルを生成していませんでした。そのため、OpenBSD 5.3/5.4以降でデフォルトでPIEが有効になっている環境では、GoプログラムがC言語で書かれたライブラリ(hostobj、つまりホストシステムが提供するオブジェクトファイル)とリンクしようとすると、リンカエラーが発生していました。このコミットは、この互換性の問題を解決し、GoプログラムがOpenBSDの新しいバージョンで正しく動作するようにすることを目的としています。

前提知識の解説

リンカ (Linker)

リンカは、コンパイラによって生成された複数のオブジェクトファイル(コンパイルされたソースコード)と、必要なライブラリを結合して、実行可能なプログラムまたはライブラリを作成するツールです。リンカの主な役割は、異なるオブジェクトファイル間で参照されるシンボル(関数や変数など)を解決し、それらをメモリ上の適切なアドレスに配置することです。

Position-Independent Code (PIC)

PICは、メモリ上の任意のアドレスにロードされても正しく実行されるように設計された機械語コードです。これは主に共有ライブラリ(ダイナミックリンクライブラリ)で使用されます。PICでは、絶対アドレスではなく、プログラムカウンタ相対アドレス指定やグローバルオフセットテーブル (GOT) を使用してデータや関数にアクセスします。これにより、ライブラリが複数のプロセスで共有される際に、各プロセスが異なるメモリ位置にロードされても問題なく動作します。

Position-Independent Executable (PIE)

PIEは、PICの原則を適用した実行可能ファイルです。PIEとしてコンパイルされた実行ファイルは、メモリ上のランダムなアドレスにロードされることが可能になります。これは、Address Space Layout Randomization (ASLR) と組み合わせて使用され、セキュリティを向上させます。攻撃者が特定の関数のアドレスを予測して悪用するのを困難にするため、バッファオーバーフローなどの脆弱性に対する防御策となります。

hostobj

Go言語の文脈におけるhostobjは、Goのツールチェインではなく、ホストシステム(オペレーティングシステム)のCコンパイラやリンカによって生成されたオブジェクトファイルを指します。GoプログラムがC言語で書かれたライブラリ(例えば、cgoを使ってCコードを呼び出す場合)とリンクする必要がある場合、これらのhostobjがGoのリンカによって取り込まれます。

HEADTYPE

Goのリンカ (cmd/ld) において、HEADTYPEはターゲットとなる実行ファイルのヘッダタイプ、つまりターゲットOSの種類を示す内部変数です。例えば、HdarwinはmacOS、HopenbsdはOpenBSDを指します。この変数は、リンカが特定のOSに特化した処理を行う際に使用されます。

技術的詳細

このコミットの技術的な核心は、OpenBSDのリンカに対して、Goリンカが生成するオブジェクトファイルがPIEではないことを明示的に伝える点にあります。OpenBSD 5.3/5.4以降では、デフォルトでPIEが有効になっているため、リンカはすべてのオブジェクトファイルがPIE互換であることを期待します。しかし、当時のGoリンカはPIE互換のオブジェクトを生成していなかったため、この期待が満たされず、リンクエラーが発生していました。

解決策として、GoリンカはOpenBSDをターゲットとする場合に、外部リンカ(通常はgccなど)に-Wl,-nopieというフラグを渡すように変更されました。

  • -Wl,:これは、gccなどのコンパイラドライバに対して、続く引数をリンカに直接渡すように指示するフラグです。
  • -nopie:これは、OpenBSDのリンカ(ld)に対するフラグで、生成される実行ファイルがPIEではないことを明示的に指定します。これにより、リンカはPIE互換性のチェックを緩和し、Goリンカが生成した非PIEオブジェクトファイルとのリンクを許可します。

この変更により、GoリンカはOpenBSDの新しいバージョンでhostobjと正しくリンクできるようになり、GoプログラムがOpenBSD環境で問題なくビルドおよび実行されるようになりました。

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

変更はsrc/cmd/ld/lib.cファイルにあります。

--- a/src/cmd/ld/lib.c
+++ b/src/cmd/ld/lib.c
@@ -574,6 +574,8 @@ hostlink(void)
 	}
 	if(HEADTYPE == Hdarwin)
 		argv[argc++] = "-Wl,-no_pie,-pagezero_size,4000000";
+	if(HEADTYPE == Hopenbsd)
+		argv[argc++] = "-Wl,-nopie";
 	
 	if(iself && AssumeGoldLinker)
 		argv[argc++] = "-Wl,--rosegment";

コアとなるコードの解説

hostlink関数は、GoプログラムがC言語のオブジェクトファイル(hostobj)とリンクする際に、外部リンカを呼び出すための引数を構築する役割を担っています。

変更前のコードでは、HEADTYPE == Hdarwin(macOSをターゲットとする場合)にのみ、特定のリンカフラグ(-Wl,-no_pie,-pagezero_size,4000000)が追加されていました。これは、macOSのリンカに対する特定の要件に対応するためのものです。

このコミットでは、以下の行が追加されました。

	if(HEADTYPE == Hopenbsd)
		argv[argc++] = "-Wl,-nopie";

このコードは、GoリンカがOpenBSDをターゲットとしてビルドを行う場合にのみ実行されます。HEADTYPEHopenbsdであると判断された場合、argv配列(外部リンカに渡される引数のリスト)に"-Wl,-nopie"が追加されます。

  • argv[argc++]:これは、argv配列の現在の末尾に新しい引数を追加し、argc(引数の数)をインクリメントするC言語の一般的なイディオムです。

このシンプルな追加により、OpenBSDのリンカは、Goリンカが生成するオブジェクトファイルがPIEではないことを認識し、リンクプロセスを正常に完了できるようになります。

関連リンク

参考にした情報源リンク

このコミットは、Go言語のリンカ (cmd/ld) における変更を扱っています。具体的には、OpenBSD 5.3/5.4 およびそれ以降のバージョンで、GoプログラムがネイティブのCコード(hostobj)とリンクする際に発生する問題を解決するためのものです。OpenBSDの新しいバージョンでは、Position-Independent Executable (PIE) がデフォルトで有効になっているため、Goリンカが生成するオブジェクトファイルとの互換性の問題が生じていました。

コミット

commit 0eaabf6452149ecbcc1caf40e22ae16cf73c768e
Author: Joel Sing <jsing@google.com>
Date:   Fri Dec 20 03:58:27 2013 +1100

    cmd/ld: make hostobj work on newer openbsd
    
    Make hostobj work on OpenBSD 5.3/5.4/-current - these have PIE
    enabled by default and linking fails since the Go linker generates
    objects that are neither PIC nor PIE.
    
    Fixes #5067
    
    R=golang-dev, rsc
    CC=golang-dev
    https://golang.org/cl/7572049

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

https://github.com/golang/go/commit/0eaabf6452149ecbcc1caf40e22ae16cf73c768e

元コミット内容

cmd/ld: make hostobj work on newer openbsd

Make hostobj work on OpenBSD 5.3/5.4/-current - these have PIE
enabled by default and linking fails since the Go linker generates
objects that are neither PIC nor PIE.

Fixes #5067

R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/7572049

変更の背景

この変更の背景には、OpenBSDオペレーティングシステムのセキュリティ強化があります。OpenBSDは、その堅牢なセキュリティで知られており、Position-Independent Executable (PIE) の採用はその一環です。PIEは、実行ファイルがメモリ上のランダムなアドレスにロードされることを可能にし、Address Space Layout Randomization (ASLR) と組み合わせて、バッファオーバーフローなどの攻撃を困難にします。

しかし、Go言語のリンカ (cmd/ld) は、当時(2013年頃)はPIEまたはPosition-Independent Code (PIC) に対応したオブジェクトファイルを生成していませんでした。そのため、OpenBSD 5.3/5.4以降でデフォルトでPIEが有効になっている環境では、GoプログラムがC言語で書かれたライブラリ(hostobj、つまりホストシステムが提供するオブジェクトファイル)とリンクしようとすると、リンカエラーが発生していました。このコミットは、この互換性の問題を解決し、GoプログラムがOpenBSDの新しいバージョンで正しく動作するようにすることを目的としています。

前提知識の解説

リンカ (Linker)

リンカは、コンパイラによって生成された複数のオブジェクトファイル(コンパイルされたソースコード)と、必要なライブラリを結合して、実行可能なプログラムまたはライブラリを作成するツールです。リンカの主な役割は、異なるオブジェクトファイル間で参照されるシンボル(関数や変数など)を解決し、それらをメモリ上の適切なアドレスに配置することです。

Position-Independent Code (PIC)

PICは、メモリ上の任意のアドレスにロードされても正しく実行されるように設計された機械語コードです。これは主に共有ライブラリ(ダイナミックリンクライブラリ)で使用されます。PICでは、絶対アドレスではなく、プログラムカウンタ相対アドレス指定やグローバルオフセットテーブル (GOT) を使用してデータや関数にアクセスします。これにより、ライブラリが複数のプロセスで共有される際に、各プロセスが異なるメモリ位置にロードされても問題なく動作します。

Position-Independent Executable (PIE)

PIEは、PICの原則を適用した実行可能ファイルです。PIEとしてコンパイルされた実行ファイルは、メモリ上のランダムなアドレスにロードされることが可能になります。これは、Address Space Layout Randomization (ASLR) と組み合わせて使用され、セキュリティを向上させます。攻撃者が特定の関数のアドレスを予測して悪用するのを困難にするため、バッファオーバーフローなどの脆弱性に対する防御策となります。

hostobj

Go言語の文脈におけるhostobjは、Goのツールチェインではなく、ホストシステム(オペレーティングシステム)のCコンパイラやリンカによって生成されたオブジェクトファイルを指します。GoプログラムがC言語で書かれたライブラリ(例えば、cgoを使ってCコードを呼び出す場合)とリンクする必要がある場合、これらのhostobjがGoのリンカによって取り込まれます。

HEADTYPE

Goのリンカ (cmd/ld) において、HEADTYPEはターゲットとなる実行ファイルのヘッダタイプ、つまりターゲットOSの種類を示す内部変数です。例えば、HdarwinはmacOS、HopenbsdはOpenBSDを指します。この変数は、リンカが特定のOSに特化した処理を行う際に使用されます。

技術的詳細

このコミットの技術的な核心は、OpenBSDのリンカに対して、Goリンカが生成するオブジェクトファイルがPIEではないことを明示的に伝える点にあります。OpenBSD 5.3/5.4以降では、デフォルトでPIEが有効になっているため、リンカはすべてのオブジェクトファイルがPIE互換であることを期待します。しかし、当時のGoリンカはPIE互換のオブジェクトを生成していなかったため、この期待が満たされず、リンクエラーが発生していました。

解決策として、GoリンカはOpenBSDをターゲットとする場合に、外部リンカ(通常はgccなど)に-Wl,-nopieというフラグを渡すように変更されました。

  • -Wl,:これは、gccなどのコンパイラドライバに対して、続く引数をリンカに直接渡すように指示するフラグです。
  • -nopie:これは、OpenBSDのリンカ(ld)に対するフラグで、生成される実行ファイルがPIEではないことを明示的に指定します。これにより、リンカはPIE互換性のチェックを緩和し、Goリンカが生成した非PIEオブジェクトファイルとのリンクを許可します。

この変更により、GoリンカはOpenBSDの新しいバージョンでhostobjと正しくリンクできるようになり、GoプログラムがOpenBSD環境で問題なくビルドおよび実行されるようになりました。

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

変更はsrc/cmd/ld/lib.cファイルにあります。

--- a/src/cmd/ld/lib.c
+++ b/src/cmd/ld/lib.c
@@ -574,6 +574,8 @@ hostlink(void)
 	}
 	if(HEADTYPE == Hdarwin)
 		argv[argc++] = "-Wl,-no_pie,-pagezero_size,4000000";
+	if(HEADTYPE == Hopenbsd)
+		argv[argc++] = "-Wl,-nopie";
 	
 	if(iself && AssumeGoldLinker)
 		argv[argc++] = "-Wl,--rosegment";

コアとなるコードの解説

hostlink関数は、GoプログラムがC言語のオブジェクトファイル(hostobj)とリンクする際に、外部リンカを呼び出すための引数を構築する役割を担っています。

変更前のコードでは、HEADTYPE == Hdarwin(macOSをターゲットとする場合)にのみ、特定のリンカフラグ(-Wl,-no_pie,-pagezero_size,4000000)が追加されていました。これは、macOSのリンカに対する特定の要件に対応するためのものです。

このコミットでは、以下の行が追加されました。

	if(HEADTYPE == Hopenbsd)
		argv[argc++] = "-Wl,-nopie";

このコードは、GoリンカがOpenBSDをターゲットとしてビルドを行う場合にのみ実行されます。HEADTYPEHopenbsdであると判断された場合、argv配列(外部リンカに渡される引数のリスト)に"-Wl,-nopie"が追加されます。

  • argv[argc++]:これは、argv配列の現在の末尾に新しい引数を追加し、argc(引数の数)をインクリメントするC言語の一般的なイディオムです。

このシンプルな追加により、OpenBSDのリンカは、Goリンカが生成するオブジェクトファイルがPIEではないことを認識し、リンクプロセスを正常に完了できるようになります。

関連リンク

参考にした情報源リンク