LoginSignup
32
30

More than 5 years have passed since last update.

Xcode7でのembed-bitcodeオプション

Last updated at Posted at 2015-09-05

こちらからの続きです。
LLVM bitcode基礎知識
http://qiita.com/gamako/items/f37dbb05de9d3832ce6b

Xcode7からデフォルトで有効になったembed-bitcodeオプションがどんな働きをしているか見てみましょう。

ふつうのoファイル

まず前回と同じHelloWorldのソースコードから、ふつうにoファイルを出力してみます。

clang -c sample.c -o sample.o

中身はバイナリなので、hexdumpしてみます。

% hexdump -C -v sample.o
00000000  cf fa ed fe 07 00 00 01  03 00 00 00 01 00 00 00  |................|
00000010  04 00 00 00 00 02 00 00  00 20 00 00 00 00 00 00  |......... ......|
00000020  19 00 00 00 88 01 00 00  00 00 00 00 00 00 00 00  |................|
00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000040  98 00 00 00 00 00 00 00  20 02 00 00 00 00 00 00  |........ .......|
00000050  98 00 00 00 00 00 00 00  07 00 00 00 07 00 00 00  |................|
00000060  04 00 00 00 00 00 00 00  5f 5f 74 65 78 74 00 00  |........__text..|

...

00000300  00 5f 6d 61 69 6e 00 5f  70 72 69 6e 74 66 00 4c  |._main._printf.L|
00000310  5f 2e 73 74 72 00 00 00                           |_.str...|
00000318

llvm-objdumpコマンドで、もう少し人間に優しい出力をしてくれます。当たり前ですが、この中にbitcodeの情報は含まれていません。

% /usr/local/Cellar/llvm/3.6.1/bin/llvm-objdump -private-headers -section-headers -disassemble -s sample.o

sample.o:   file format Mach-O 64-bit x86-64

Disassembly of section __TEXT,__text:
_main:
       0:   55                                              pushq   %rbp
       1:   48 89 e5                                        movq    %rsp, %rbp
       4:   48 83 ec 10                                     subq    $16, %rsp
       8:   48 8d 3d 00 00 00 00                            leaq    (%rip), %rdi
       f:   c7 45 fc 00 00 00 00                            movl    $0, -4(%rbp)
      16:   b0 00                                           movb    $0, %al
      18:   e8 00 00 00 00                                  callq   0
      1d:   31 c9                                           xorl    %ecx, %ecx
      1f:   89 45 f8                                        movl    %eax, -8(%rbp)
      22:   89 c8                                           movl    %ecx, %eax
      24:   48 83 c4 10                                     addq    $16, %rsp
      28:   5d                                              popq    %rbp
      29:   c3                                              retq
Sections:
Idx Name          Size      Address          Type
  0 __text        0000002a 0000000000000000 TEXT
  1 __cstring     0000000e 000000000000002a DATA
  2 __compact_unwind 00000020 0000000000000038 DATA
  3 __eh_frame    00000040 0000000000000058 DATA
Contents of section __text:
 0000 554889e5 4883ec10 488d3d00 000000c7  UH..H...H.=.....
 0010 45fc0000 0000b000 e8000000 0031c989  E............1..
 0020 45f889c8 4883c410 5dc3               E...H...].
Contents of section __cstring:
 002a 48656c6c 6f2c2057 6f726c64 0a00      Hello, World..
Contents of section __compact_unwind:
 0038 00000000 00000000 2a000000 00000001  ........*.......
 0048 00000000 00000000 00000000 00000000  ................
Contents of section __eh_frame:
 0058 14000000 00000000 037a5200 01781001  .........zR..x..
 0068 100c0708 90010000 24000000 1c000000  ........$.......
 0078 88ffffff ffffffff 2a000000 00000000  ........*.......
 0088 00410e10 8602430d 06000000 00000000  .A....C.........
Mach header
      magic cputype cpusubtype  caps    filetype ncmds sizeofcmds      flags
MH_MAGIC_64  X86_64        ALL  0x00      OBJECT     4        512 SUBSECTIONS_VIA_SYMBOLS
Load command 0

...

osxのotoolコマンドでも中身をみることができます。

% otool -hfavltVdoj sample.o
sample.o:
Mach header
      magic cputype cpusubtype  caps    filetype ncmds sizeofcmds      flags
MH_MAGIC_64  X86_64        ALL  0x00      OBJECT     4        512 SUBSECTIONS_VIA_SYMBOLS

...

embed-bitcodeでbitcodeを埋め込む

Xcode7 betaのclangで-fembed-bitcodeをつけてオブジェクトファイルを作ってみます

% /Applications/Xcode-beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -c -fembed-bitcode sample.c -o sample1.o

出力されたオブジェクトファイルのサイズは、先ほどのものに比べてかなり大きいようです。

% ls -al
...
-rw-r--r--   1 gamako  staff    75  9  4 13:43 sample.c
-rw-r--r--   1 gamako  staff   792  9  4 14:38 sample.o
-rw-r--r--   1 gamako  staff  2676  9  4 15:25 sample1.o

中身をダンプしてみましょう

% hexdump -C -v sample1.o
00000000  cf fa ed fe 07 00 00 01  03 00 00 00 01 00 00 00  |................|
00000010  04 00 00 00 a0 02 00 00  00 20 00 00 00 00 00 00  |......... ......|
00000020  19 00 00 00 28 02 00 00  00 00 00 00 00 00 00 00  |....(...........|
00000030  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|

...

00000a40  00 5f 6d 61 69 6e 00 5f  70 72 69 6e 74 66 00 5f  |._main._printf._|
00000a50  6c 6c 76 6d 2e 63 6d 64  6c 69 6e 65 00 5f 6c 6c  |llvm.cmdline._ll|
00000a60  76 6d 2e 65 6d 62 65 64  64 65 64 2e 6d 6f 64 75  |vm.embedded.modu|
00000a70  6c 65 00 00                                       |le..|
00000a74

llvm-objdumpで中身を見てみると、bitcodeとcmdlineのセクションが増えているのがわかります。

% /usr/local/Cellar/llvm/3.6.1/bin/llvm-objdump -private-headers -section-headers -disassemble -s sample1.o

sample1.o:  file format Mach-O 64-bit x86-64

Disassembly of section __TEXT,__text:
_main:
       0:   55                                           

...

Sections:
Idx Name          Size      Address          Type
  0 __text        0000002a 0000000000000000 TEXT
  1 __cstring     0000000e 000000000000002a DATA
  2 __bitcode     00000640 0000000000000040 DATA
  3 __cmdline     00000042 0000000000000680 DATA
  4 __compact_unwind 00000020 00000000000006c8 DATA
  5 __eh_frame    00000040 00000000000006e8 DATA
Contents of section __text:
 0000 554889e5 4883ec10 488d3d1b 000000c7  UH..H...H.=.....
 0010 45fc0000 0000b000 e8000000 0031c989  E............1..
 0020 45f889c8 4883c410 5dc3               E...H...].
Contents of section __cstring:
 002a 48656c6c 6f2c2057 6f726c64 0a00      Hello, World..
Contents of section __bitcode:
 0040 dec0170b 00000000 14000000 28060000  ............(...
 0050 07000001 4243c0de 210c0000 87010000  ....BC..!.......
 0060 0b822000 02000000 12000000 07812391  .. ...........#.
 0070 41c80449 06103239 9201840c 25050819  A..I..29....%...
 0080 1e048b62 80104502 42920b42 84103214  ...b..E.B..B..2.

...

 0640 14010000 61200000 0b000000 1304412c  ....a ........A,
 0650 10000000 03000000 34230064 43190230  ........4#.dC..0
 0660 18830100 3311ca40 0c8311c1 00002306  ....3..@......#.
 0670 04001c42 12000000 00000000 00000000  ...B............
Contents of section __cmdline:
 0680 2d747269 706c6500 7838365f 36342d61  -triple.x86_64-a
 0690 70706c65 2d6d6163 6f737831 302e3130  pple-macosx10.10
 06a0 2e30002d 656d6974 2d6f626a 002d6469  .0.-emit-obj.-di
 06b0 7361626c 652d6c6c 766d2d6f 70747a6e  sable-llvm-optzn
 06c0 7300                                 s.
Contents of section __compact_unwind:
 06c8 00000000 00000000 2a000000 00000001  ........*.......
 06d8 00000000 00000000 00000000 00000000  ................
Contents of section __eh_frame:
 06e8 14000000 00000000 037a5200 01781001  .........zR..x..
 06f8 100c0708 90010000 24000000 1c000000  ........$.......
 0708 f8f8ffff ffffffff 2a000000 00000000  ........*.......
 0718 00410e10 8602430d 06000000 00000000  .A....C.........
Mach header
      magic cputype cpusubtype  caps    filetype ncmds sizeofcmds      flags
MH_MAGIC_64  X86_64        ALL  0x00      OBJECT     4        672 SUBSECTIONS_VIA_SYMBOLS
Load command 0

...

Section
  sectname __bitcode
   segname __LLVM
      addr 0x0000000000000040
      size 0x0000000000000640
    offset 768
     align 2^4 (16)
    reloff 0
    nreloc 0
      type S_REGULAR
attributes (none)
 reserved1 0
 reserved2 0
Section
  sectname __cmdline
   segname __LLVM
      addr 0x0000000000000680
      size 0x0000000000000042
    offset 2368
     align 2^4 (16)
    reloff 0
    nreloc 0
      type S_REGULAR
attributes (none)
 reserved1 0
 reserved2 0
Section
  sectname __compact_unwind
...

bitcodeの抜き出し

bitcodeのセクションはoffsetが768でsizeが0x640とあるので、この部分をファイルに抜き出してみましょう。ddコマンドでできます。

% dd if=sample1.o bs=1 skip=768 count=0x640  of=sample1.bc
1600+0 records in
1600+0 records out
1600 bytes transferred in 0.002806 secs (570217 bytes/sec)
% hexdump -C -v sample1.bc
00000000  de c0 17 0b 00 00 00 00  14 00 00 00 28 06 00 00  |............(...|
00000010  07 00 00 01 42 43 c0 de  21 0c 00 00 87 01 00 00  |....BC..!.......|
00000020  0b 82 20 00 02 00 00 00  12 00 00 00 07 81 23 91  |.. ...........#.|

...

00000620  18 83 01 00 33 11 ca 40  0c 83 11 c1 00 00 23 06  |....3..@......#.|
00000630  04 00 1c 42 12 00 00 00  00 00 00 00 00 00 00 00  |...B............|
00000640

抜き出した部分はllvm-disコマンドでLLVM IRのテキストに変換できます。

% /usr/local/Cellar/llvm/3.6.1/bin/llvm-dis sample1.bc
% cat sample1.ll
; ModuleID = 'sample1.bc'
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx10.10.0"

@.str = private unnamed_addr constant [14 x i8] c"Hello, World\0A\00", align 1

; Function Attrs: nounwind ssp uwtable
define i32 @main() #0 {
  %1 = alloca i32, align 4
  store i32 0, i32* %1
  %2 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([14 x i8]* @.str, i32 0, i32 0))
  ret i32 0
}

declare i32 @printf(i8*, ...) #1

attributes #0 = { nounwind ssp uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="core2" "target-features"="+ssse3,+cx16,+sse,+sse2,+sse3" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="core2" "target-features"="+ssse3,+cx16,+sse,+sse2,+sse3" "unsafe-fp-math"="false" "use-soft-float"="false" }

!llvm.module.flags = !{!0}
!llvm.ident = !{!1}

!0 = !{i32 1, !"PIC Level", i32 2}
!1 = !{!"Apple LLVM version 7.0.0 (clang-700.0.72)"}

ソースからコンパイルしたbitcodeとの比較

これをxcode7 betaのclangで出力したbitcodeと比較してみましょう。

% /Applications/Xcode-beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -c -emit-llvm sample.c
% hexdump -C -v sample.bc
00000000  de c0 17 0b 00 00 00 00  14 00 00 00 38 06 00 00  |............8...|
00000010  07 00 00 01 42 43 c0 de  21 0c 00 00 8b 01 00 00  |....BC..!.......|
00000020  0b 82 20 00 02 00 00 00  12 00 00 00 07 81 23 91  |.. ...........#.|

...

00000630  04 00 1c 42 12 21 31 00  02 00 00 00 0b 0a 60 08  |...B.!1.......`.|
00000640  04 03 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000650
% /usr/local/Cellar/llvm/3.6.1/bin/llvm-dis sample.bc
% cat sample.ll
; ModuleID = 'sample.bc'
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx10.10.0"

@.str = private unnamed_addr constant [14 x i8] c"Hello, World\0A\00", align 1

; Function Attrs: nounwind ssp uwtable
define i32 @main() #0 {
  %1 = alloca i32, align 4
  store i32 0, i32* %1
  %2 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([14 x i8]* @.str, i32 0, i32 0))
  ret i32 0
}

declare i32 @printf(i8*, ...) #1

attributes #0 = { nounwind ssp uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="core2" "target-features"="+ssse3,+cx16,+sse,+sse2,+sse3" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="core2" "target-features"="+ssse3,+cx16,+sse,+sse2,+sse3" "unsafe-fp-math"="false" "use-soft-float"="false" }

!llvm.module.flags = !{!0}
!llvm.ident = !{!1}

!0 = !{i32 1, !"PIC Level", i32 2}
!1 = !{!"Apple LLVM version 7.0.0 (clang-700.0.72)"}

bitcodeの中身とサイズは若干違うようですが、、、

% ls -al
...
-rw-r--r--   1 gamako  staff  1616  9  4 15:38 sample.bc
-rw-r--r--   1 gamako  staff  1268  9  4 15:43 sample.ll
-rw-r--r--   1 gamako  staff  1600  9  4 15:47 sample1.bc
-rw-r--r--   1 gamako  staff  1269  9  4 15:55 sample1.ll

llファイルのdiffをとってみるとわかるように、中の情報はほぼ同一であることがわかります。

% diff sample.ll sample1.ll
1c1
< ; ModuleID = 'sample.bc'
---
> ; ModuleID = 'sample1.bc'

__cmdlineセクション

一方__cmdlineセクションは以下のようになっていました。ビルド時のオプションが格納されているようにみえます。これをヒントにストア側での再最適化が行われるのでしょう。

Contents of section __cmdline:
 0680 2d747269 706c6500 7838365f 36342d61  -triple.x86_64-a
 0690 70706c65 2d6d6163 6f737831 302e3130  pple-macosx10.10
 06a0 2e30002d 656d6974 2d6f626a 002d6469  .0.-emit-obj.-di
 06b0 7361626c 652d6c6c 766d2d6f 70747a6e  sable-llvm-optzn
 06c0 7300                                 s.

最後に

Xcodeでのビルドについては、こちらも参考にどうぞ

XcodeでArchive以外のビルド結果にはbitcodeが埋め込まれない
http://qiita.com/gamako/items/66d3a8164678e525a26e

32
30
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
32
30