引言

开发第三方库时, 如果没有进行特殊处理, 很容易把其他第三方库的符号暴露出来, 导致链接时产生符号重复. 如下图所示

如果用户链接了其他版本的libjpeg, 会因为入口地址不正确让程序直接崩溃

本文就从这个问题入手, 简要介绍Mac OS X系统下几个常用二进制文件修改工具的使用

概述

我们都知道, 代码到可执行文件需要经过编译(compile)和链接(link)两个主要步骤. 编译是把程序语言转换为机器指令, 这个不在本文的讨论范围.

链接是把分块编译的对象文件(obj)合并成一个完整的程序, 主要解决函数入口重定向的问题. 其功能主要就是把所有的对象文件打个包, 生成一个导出符号表, 让其他程序可以知道本文件的结构.

而对于苹果系统来说, 丰富的设备包含了多种架构平台, armv7, arm64, i386, x86_64是最常见的指令集, 一个程序库为了兼容各个平台, 常常要把不同平台编译的程序合并起来, 生成所谓的胖文件(Fat File), 这样子开发者就不需要专门准备一套真机版本库和模拟器版本库了(在早期, 很多第三方库确实是提供了不同版本的二进制文件来减少库文件大小).

因此对于一个可执行文件, 其实包含了3层结构: Universal Fat File -> Single Architecture Binary File -> Mach-O Object.

本文将要介绍的lipo, ar, nm, strip, ld等工具的功能就是对这三层结构进行转换和修改.

本文以高德地图iOS SDK MAMapKit.framework 4.0.3为例, 演示如何从这个库文件里剔除暴露的png符号.

工具介绍

lipo

lipo是管理Fat File的工具, 可以查看平台列表, 提取特定平台, 重新打包.

首先运行 lipo -info MAMapKit

可以看出这个文件包含了4个平台的代码. 接下来的所有操作都是要针对单一平台进行的, 因此先提取出来armv7平台,

lipo -thin armv7 MAMapKit -output MAMapKit.armv7

可以看出单平台的程序文件要小得多.

接下来我们来查看一下这个文件的符号表

nm

nm用来显示一个程序包的符号表, 默认会显示入口地址, 符号类型, 符号名.

nm -j MAMapKit.armv7  | grep png > symbols 可以获得所有的libpng导出符号, 存入到symbols文件, 为接下来的工作做准备. -j 选项控制只输出符号名.

strip

strip用来删除程序里的符号表. -R 用来指定一个要删除的符号列表, 使用上述生成的symbols文件. 添加 -S 选项来保留其他符号.

strip -S -R symbols MAMapKit.armv7 -o MAMapKit.armv7.strip

可以验证生成的新文件已经没有了png符号.

我们用这个方法应用到其他所有平台.

ar

我们用上述方法处理arm64时遇到了问题

这个文件里的一些符号用作了重定向入口, strip命令不允许删除, 这时就需要更强力的工具ld登场了. ld 其实苹果系统下的链接器, 可以更精确的控制符号表的导出.

ld的操作对象是obj, 因此我们需要先用到ar打包工具. ar可以查看一个程序包里的对象文件列表, 解压出其中的对象文件并重新打包.

ar -t MAMapKit.arm64

可以看到整个包就包含了一个主对象文件.

使用 -x 解压出来, 接下来就要轮到 ld 上场了.

ld

本问题需要的ld功能和strip基本一致, 使用下述命令

ld -x -r -unexported_symbols_list symbols MAMapKit-arm64-master.o -o MAMapKit-arm64-master.o.strip

由此生成对象文件就剔除了png符号表

接下来要做的就是上述逆过程, 对象文件合并成程序文件

ar -r MAMapKit.arm64 MAMapKit-arm64-master.o.strip Pods-MAMapKit-dummy.o

最后是把各个平台的程序打包成Fat File即可.

终极大招

2016-09-02 更新

使用 Xcode 编译选项即可以完成上述任务!

1. Perform Single-Object Prelink

这个参数设置为 Yes

这一步, 把所有的object文件合并成一个object文件, 相当于进行预编译

这是最核心的操作, 因为该命令会触发Xcode调用 ld 命令

2. Single-Object Prelink Flags

这个参数设置 -unexported_symbols_list $(PROJECT_DIR)/symbol.txt

这就相当于给 ld 命令传递参数, 正式我们上文提到的操作

通过这两个选项的配置, 我们就在Xcode里设置好了符号删除的任务, 不用再在编译完成后手动删除.

其他的一些参数, 比如 Strip Style, 可以根据需要手动决定, 因为删除后就不能再断点调试了!

Mac系统下lipo, ar, nm等工具的使用简介的更多相关文章

  1. 在Linux系统下运行微信Web开发者工具

    微信Web开发者工具只有window版本和mac版本,如果想要在Linux系统下运行微信Web开发者工具,需要花费很大周折. 注:带 * 的步骤或文件为不确定是否管用的步骤或文件.本人系统为Linux ...

  2. Mac系统下React Native环境搭建

    这里记录一下在Mac系统下搭建React Native开发环境的过程: 1. 安装HomeBrew: /usr/bin/ruby -e "$(curl -fsSL https://raw.g ...

  3. (转载)Mac系统下利用ADB命令连接android手机并进行文件操作

    Mac系统下利用ADB命令连接android手机并进行文件操作 标签: Mac adb android 2016-03-14 10:09 5470人阅读 评论(1) 收藏 举报  分类: Androi ...

  4. MAC系统下,删除.svn文件

    MAC系统下,.svn文件是隐藏的. 如果项目是非export导出的,那么项目中会有很多的.svn文件. 如果项目的体积非常庞大,我们如何快速的批量删除.svn文件呢?下面是操作方法: 打开终端,cd ...

  5. Mac系统下使用VirtualBox虚拟机安装win7--第一步 安装vbox虚拟机

    Mac系统下使用VirtualBox虚拟机安装win7操作步骤: 第一步 安装vbox虚拟机 1.先下载vbox,下载地址:: https://www.virtualbox.org/wiki/Down ...

  6. 曲线救国,解决Mac系统下,Android sdk下载失败的问题

    Mac下翻_墙的问题 话说GFW屏蔽谷歌已经有一阵子了,最近打算在Mac系统下折腾个Android应用,备好了IDE,只欠SDK,无奈下载时因为GFW的缘故,总是失败,我心痛哉! 由于本人偏爱Mac系 ...

  7. MAC系统下Sublime Text3 配置Python3详细教程

    MAC系统下Sublime Text3 配置Python3详细教程(亲测有效) https://blog.csdn.net/weixin_41768008/article/details/798590 ...

  8. Mac系统下编译支持Android平台的最新X264编码器

    Mac系统下编译支持Android平台的最新X264编码器 原文来自 http://www.mingjianhua.com,转载请注明出处 1.首先去官网下载最新的x264源代码,解压到任意目录 ht ...

  9. mac系统下ionic环境配置

    本人是在mac环境下进行配置的: 下载nodejs:https://nodejs.org/download/ 并双击安装 Cordova and Ionic command-line tools 安装 ...

随机推荐

  1. Jmeter之逻辑控制器(Logic Controller)

    Jmeter之逻辑控制器(Logic Controller) 前言: 1. Jmeter官网对逻辑控制器的解释是:“Logic Controllers determine the order in w ...

  2. bash脚本编程之一 变量、变量类型等

    变量的内容 1.变量命名:            1.只能包含字母.数字和下划线,并且不能以数字开头,    2.不应该跟系统中已有的环境变量重名    3.最好能见名知意 2.变量赋值: 设置变量: ...

  3. 4.Mybatis的输入映射(parameterType类型解析)

    前面提到过Mybatis可以对输入的参数进行映射,那么现在我们来看一下输入映射,关于输入映射大概可以分为几种情况来学习: 1.基本的类型 2.实体类 3.包装类 1.参数是基本的类型(int,Stri ...

  4. php 文件读取

    整理了一下PHP中读取文件的几个方法,方便以后查阅. 1.fread string fread ( int $handle , int $length ) fread() 从 handle 指向的文件 ...

  5. oracle根据分隔符将字符串分割成数组函数

    --创建表类型 create or replace type mytype as table of number;--如果定义成varchar--CREATE OR REPLACE type myty ...

  6. (八) 一起学 Unix 环境高级编程 (APUE) 之 信号

    . . . . . 目录 (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO (三) 一起学 Unix 环境高级编 ...

  7. Bridge(桥接)-对象结构型模式

    1.意图 将抽象部分与它的实现部分分离,使它们都可以独立地变化. 2.动机 在抽象类与它的实现之间起到桥梁作用,使它们可以独立地变化. 3.适用性 不希望在抽象和它的实现部分之间有一个固定的绑定关系. ...

  8. 集合框架之 List

    集合框架就是Java中解决数组长度固定的问题,相当于动态数组,随时用,随时建立,内存释放  这个问题还不知道? 整个集合框架 概括为   List  Set Map 这三个接口以及他们的实现类之间的应 ...

  9. 团队项目作业:利用NABCD模型进行竞争性需求分析

    NABC正是这样的一套框架,当你试图提出一项崭新的提案之际,它能够提供四个思维基点,令你的商业策划具备天马行空的基础. 具体来说,NABC是四个关键词的首字母缩写- Need(需求)-现在市场上未被满 ...

  10. Python学习笔记第七天(列表解析)

    列表解析: 根据已有列表,高效生成列表的方式,它的执行效率要快很多,比for循环的速度要快很多 示例如下: 生成器表达式 生成器表达式并不真正创建数字列表,而是返回一个生成器对象,此对象在每次计算出一 ...