前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >检查第三方库是否包含 bitcode 信息

检查第三方库是否包含 bitcode 信息

作者头像
酷酷的哀殿
发布2020-11-20 09:34:03
1.5K0
发布2020-11-20 09:34:03
举报
文章被收录于专栏:酷酷的哀殿酷酷的哀殿

前言

bitcode 是一种从源码到汇编中间的中间码。

iOS 9 发布后,开发者可以提交包含 bitcode 的程序到APPStore。当 llvm 更新或者新款手机使用了新的cpu命令集架构时,苹果可以使用最新的llvm版本重新将bitcode编译为安装包,确保能够充分利用新的llvm的最新优化或者适配最新的cpu命令集架构,避免了开发者手动提交新安装包的繁琐过程。

规模较大的APP都会包含众多的内部库和外部库。比如,一个浏览器包含了图片识别功能、语音识别功能。开发者通常会将浏览器当做“宿主”,图片识别、语音识别当做(闭源或开源)第三方库的方式合入。

当需要将第三方库以非源码的形式引入,则需要校验第三方库是否包含bitcode

在iOS的环境中,第三方库通常可以编译为两种格式:

  • <span
  • <span

对两种库不熟悉的同学,可以通过搜索引擎检索一下,本文不再做过多的说明。

architecture

根据iPhone手机处理器型号的不同,源码可以被编译为不同的架构,常见的架构包括 arm-v7、arm64架构。

胖文件

同一份源码可以编译为多个架构的文件。我们提交给Apple审核的程序通常包含多个架构的文件。包含多个架构的文件通常被称之为胖文件(又被称作 universal binary)

file

file 是 Apple 提供的一个内置程序,存储路径为 /usr/bin/file 。通过它,可以快速地识别文件的类型

  • <span
代码语言:javascript
复制
file lib/iphoneos/libMockLibrary.a
代码语言:javascript
复制
lib/iphoneos/libMockLibrary.a: Mach-O universal binary with 2 architectures: [arm_v7:current ar archive random library] [arm64:current ar archive random library]
lib/iphoneos/libMockLibrary.a (for architecture armv7):    current ar archive random library
lib/iphoneos/libMockLibrary.a (for architecture arm64):    current ar archive random library
  • <span
代码语言:javascript
复制
file MockFrameWork.framework/MockFrameWork

输出:

代码语言:javascript
复制
MockFrameWork.framework/MockFrameWork: Mach-O universal binary with 2 architectures: [arm_v7:Mach-O dynamically linked shared library arm_v7] [arm64:Mach-O 64-bit dynamically linked shared library arm64]
MockFrameWork.framework/MockFrameWork (for architecture armv7):    Mach-O dynamically linked shared library arm_v7
MockFrameWork.framework/MockFrameWork (for architecture arm64):    Mach-O 64-bit dynamically linked shared library arm64

lipo

lipo 是Apple提供的针对“胖文件”进行查看、合并、切割、替换等操作的工具。

针对多个静态库组成的胖文件,我们可以通过以下命令转储一份单架构的文件

代码语言:javascript
复制
lipo ../libMockLibrary.a -thin armv7 -output tmp-armv7.a

验证静态库是否包含 bitcode

首先,我们需要先验证文件类型是否是为静态库(archive 文件)

代码语言:javascript
复制
file ./tmp-armv7.a
./tmp-armv7.a: current ar archive random library

.a 文件通常由多个 Mach-O 文件通过特殊算法压缩的,所以,我们可以通过 tar 命令进行解压缩。

该命令会产出多个 Mach-O object 文件,每个文件对应一个源码文件(.c 或 .m )

代码语言:javascript
复制
tar -xf  tmp-armv7.a

在进行后续的校验前,我们先验证产出文件的类型是否为 Mach-O object 类型

代码语言:javascript
复制
file MockLibrary.o
MockLibrary.o: Mach-O object arm_v7

每个 Mach-O 包含很多份不同用途的 data。bitcode 信息就存储在 __LLVM __bitcode

segedit

segedit 可以转储或者替换 Mach-O object 文件中sections的一部分

通过 -extract 参数转储bitcode部分

代码语言:javascript
复制
segedit MockLibrary.o -extract "__LLVM" "__bitcode" bitcode.bc

验证bitcode格式是否正确

代码语言:javascript
复制
llvm-bcanalyzer -dump  bitcode.bc

下面是部分的输出内容,通过开头可以看到,转储文件确实是 bitcode 文件。

代码语言:javascript
复制
<BITCODE_WRAPPER_HEADER Magic=0x0b17c0de Version=0x00000000 Offset=0x00000014 Size=0x00001d40 CPUType=0x0000000c/>
<IDENTIFICATION_BLOCK_ID NumWords=7 BlockCodeSize=5>
  <STRING abbrevid=4 op0=65 op1=80 op2=80 op3=76 op4=69 op5=95 op6=49 op7=95 op8=49 op9=48 op10=48 op11=48 op12=46 op13=49 op14=49 op15=46 op16=52 op17=53 op18=46 op19=53 op20=95 op21=48/> record string = 'APPLE_1_1000.11.45.5_0'
  <EPOCH abbrevid=5 op0=0/>
</IDENTIFICATION_BLOCK_ID>
<MODULE_BLOCK NumWords=1336 BlockCodeSize=3>
  <VERSION op0=2/>
  <BLOCKINFO_BLOCK/>

  …………

验证动态库是否包含 bitcode

编译器对静态库和动态库的处理流程有些不同,所以,动态库需要通过另外的方式进行校验。

首先,我们还是先验证输入文件是否为动态库。

和之前一样,我们使用 file 进行验证。

代码语言:javascript
复制
file tmp-armv7.a

我们可以从输出信息看到,动态库已经是 Mach-O 格式的文件。(静态库是:current ar archive random library)

代码语言:javascript
复制
tmp-armv7.a: Mach-O dynamically linked shared library arm_v7

动态库的 __LLVM __bundle 包含被压缩为 xar 格式的文件 bitcode 数据。通过 segedit 导出 __LLVM __bundle

代码语言:javascript
复制
segedit tmp-armv7.a -extract "__LLVM" "__bundle" bitcode.xar

验证 xar 文件

xar 是专门针对xml优化的压缩格式

代码语言:javascript
复制
file bitcode.xar
bitcode.xar: xar archive version 1, SHA-1 checksum

通过 xar 命令进行解压缩

代码语言:javascript
复制
xar -xf bitcode.xar

xar 命令会产出多个bitcode文件,任选一个文件进行验证

代码语言:javascript
复制
llvm-bcanalyzer -dump  1
代码语言:javascript
复制
<BITCODE_WRAPPER_HEADER Magic=0x0b17c0de Version=0x00000000 Offset=0x00000014 Size=0x00001934 CPUType=0x0000000c/>
<IDENTIFICATION_BLOCK_ID NumWords=7 BlockCodeSize=5>
  <STRING abbrevid=4 op0=65 op1=80 op2=80 op3=76 op4=69 op5=95 op6=49 op7=95 op8=49 op9=48 op10=48 op11=48 op12=46 op13=49 op14=49 op15=46 op16=52 op17=53 op18=46 op19=53 op20=95 op21=48/> record string = 'APPLE_1_1000.11.45.5_0'
  <EPOCH abbrevid=5 op0=0/>
</IDENTIFICATION_BLOCK_ID>
<MODULE_BLOCK NumWords=1120 BlockCodeSize=3>
  <VERSION op0=2/>
  <BLOCKINFO_BLOCK/>
  <PARAMATTR_GROUP_BLOCK_ID NumWords=302 BlockCodeSize=3>


…………
…………

One more thing

很多人会说,根本不需要这么麻烦的检测,只需要通过以下命令就可以检测是否包含 bitcode。

代码语言:javascript
复制
otool -arch arm64 -l  库 |grep bitcode | wc -l
otool -arch arm64 -l  库 |grep LLVM | wc -l

但是,根据苹果的官方文档,Xcode 有一个特殊的优化,我们正常开发时,不需要上传 bitcode 信息,所以,__LLVM__bitcode 虽然存在,但是它们的责任是“站位”, data部分的实际长度是1。只有当我们使用 Archive 提交审核包时或者通过一些特殊的操作,才会产生真正包括 bitcode 的二进制文件。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-11-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 酷酷的哀殿 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
      • architecture
      • 胖文件
      • file
      • lipo
    • 验证静态库是否包含 bitcode
      • segedit
    • 验证动态库是否包含 bitcode
      • One more thing
      相关产品与服务
      语音识别
      腾讯云语音识别(Automatic Speech Recognition,ASR)是将语音转化成文字的PaaS产品,为企业提供精准而极具性价比的识别服务。被微信、王者荣耀、腾讯视频等大量业务使用,适用于录音质检、会议实时转写、语音输入法等多个场景。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档