VOOZH about

URL: https://qiita.com/gamako/items/4ebfd048c5aed4f68595

⇱ Xcode7でのembed-bitcodeオプション #LLVM - Qiita


👁 Image
32

Go to list of users who liked

30

Share on X(Twitter)

Share on Facebook

Add to Hatena Bookmark

More than 5 years have passed since last update.

@gamako

Xcode7でのembed-bitcodeオプション

32
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

Go to list of users who liked

30
0

Go to list of comments

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

Go to list of users who liked

30