【C/C++】macOS + Clang 環境でASLRを無効にしてコンパイルする

MacOSではLeopard以降、ASLRによりメモリ空間がランダム化されているため、gdbスタックトレースする際に、実行毎にスタックのアドレスが変わり内容を追いにくい場合があります。

ここではASLRを無効にしてコンパイルする方法を記載します。

【確認環境】
macOS High Sierra
LLVM-9.0 / Clang-900.0

 

  • ASLRが有効なモジュールか確認する

 実行バイナリのMach-OヘッダにあるflagsにMH_PIE(下記参照)が立っている場合、モジュールロード時のアドレスがランダム化されます。
※PIE(Position Independent Executable)

#define MH_PIE 0x200000   /* When this bit is set, the OS will
             
load the main executable at a
             
random address. Only used in
             
MH_EXECUTE filetypes. */

 (mach-o/loader.hで定義)

otoolコマンドで実行バイナリのMachヘッダを参照すると、MH_PIEが立っているか確認する事ができます。

$ otool -h aslr_enable_mod
Mach header
magic cputype cpusubtype caps filetype ncmds sizeofcmds flags
0xfeedfacf 16777223 3 0x80 2 16 1248 0x00200085

上記例ではflags列に0x200000が立っているため、ASLRが有効なモジュールである事が解ります。
なお、otool "-hv"を指定する事で、 フラグ値を定義名で表示可能です。
(PIEが表示されます)

$ otool -hv aslr_enable_mod
Mach header
magic cputype cpusubtype caps filetype ncmds sizeofcmds flags
MH_MAGIC_64 X86_64 ALL LIB64 EXECUTE 16 1248 NOUNDEFS DYLDLINK TWOLEVEL PIE
  • モジュールのASLRを無効化する

コンパイル時に"-no_pie"オプションを指定する事で、モジュールロード時のASLRを無効化できます。

$ g++ -o aslr_disable_mod aslr_disable.cpp -Wl,-no_pie
$
$ otool -hv aslr_disable_mod
Mach header
magic cputype cpusubtype caps filetype ncmds sizeofcmds flags
MH_MAGIC_64 X86_64 ALL LIB64 EXECUTE 16 1248 NOUNDEFS DYLDLINK TWOLEVEL


これにより、自モジュールやリンクしている共有ライブラリが固定アドレスでロードされるようになります。

なお、ASLRを無効化した状態はセキュリティ上危険なため、リリースモジュールでは必ずASLRを有効化してコンパイルしてください。