Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Xcode中和symbols有关的几个设置

Xcode中和symbols有关的几个设置

作者头像
且行且珍惜_iOS
发布于 2022-05-13 05:40:13
发布于 2022-05-13 05:40:13
2.1K00
代码可运行
举报
运行总次数:0
代码可运行

其实被这个问题困扰了好久,不过秉承着三分钟热度的新年新气象,还是要多弄懂一点(⊙_⊙)ゞ

Symbols是什么东西呢?虽然我对它没有深入的了解,但是大概知道它的作用。摘抄《深入理解计算机系统》里的一些描述:

一个典型的ELF可重定位目标文件包含下面几个节: ... ... .symtab:一个符号表,它存放在程序中定义和引用的函数和全局变量信息。一些程序员错误地认为必须通过-g选项来编译程序才能得到符号表信息。实际上,每个可重定位目标文件在.symtab中都有一张符号表。然而,和编译器中的符号表不同,.symtab符号表不包含局部变量的条目。 ... ... .debug:一个调试符号表,其条目是程序中定义的局部变量和类型定义,程序中定义和引用的全局变量,以及原始的C源文件。只有以-g选项调用编译驱动程序时才会得到这张表。 ... ...

为了构造可执行文件,链接器必须完成两个主要任务:

  • 符号解析(symbol resolution)。目标文件定义和引用符号。符号解析的目的是将每个符号引用刚好和一个符号定义联系起来。
  • 重定位(relocation)。编译器和汇编器生成从地址0开始的代码和数据节。链接器通过把每个符号定义与一个存储器位置联系起来,然后修改所有对这些符号的引用,使得它们指向这个存储器位置,从而重定位这些节。

Objective-C有一些自己的生成符号的规则,比如文档中有提到:

The dynamic nature of Objective-C complicates things slightly. Because the code that implements a method is not determined until the method is actually called, Objective-C does not define linker symbols for methods. Linker symbols are only defined for classes.

Objective-C不会为方法定义链接符号,只会为类定义链接符号。

可以在终端中用nm命令查看一个可重定位文件或可执行文件的符号表,其中加上-a参数可以显示包括调试符号在内的所有符号。

合理的选择与symbols有关的设置选项,可以缩减app的大小,一定程度上能阻碍与源代码有关的信息被攻击者获得。Xcode的build setting中,有不少与symbols有关,现在我来依次试验这几个设置选项,了解一下它们的具体作用。

刚开始的时候,我使用Xcode7.2.1新建了一个工程,以下试验均在run和DEBUG模式下进行。

Generate Debug Symbols [GCC_GENERATE_DEBUGGING_SYMBOLS] 在Xcode7.2.1中,Generate Debug Symbols这个设置在DEBUG和RELEASE下均默认为YES

官方文档对这个设置的说明:

Enables or disables generation of debug symbols. When debug symbols are enabled, the level of detail can be controlled by the build 'Level of Debug Symbols' setting.

调试符号是在编译时生成的。在Xcode中查看构建过程,可以发现,当Generate Debug Symbols选项设置为YES时,每个源文件在编译成.o文件时,编译参数多了-g-gmodules两项。但链接等其他的过程没有变化。

Clang文档对-g的描述是:

Generate complete debug info.

Generate Debug Symbols设置为YES时,编译产生的.o文件会大一些,当然最终生成的可执行文件也大一些。

Generate Debug Symbols设置为NO的时候,在Xcode中设置的断点不会中断。但是在程序中打印[NSThread callStackSymbols],依然可以看到类名和方法名,比如:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
** 0   XSQSymbolsDemo                      0x00000001000667f4 -[ViewController viewDidLoad] + 100**

在程序崩溃时,也可以得到带有类名和方法名的函数调用栈

现在把Generate Debug Symbols设置回YES,开始试验下一个设置。

Debug Information Level [CLANG_DEBUG_INFORMATION_LEVEL] 在Xcode 7.2.1中,Debug Information Level的默认值为Compiler default,还有一个选项是Line tables only

官方文档的描述是:

Toggles the amount of debug information emitted when debug symbols are enabled. This can impact the size of the generated debug information, which can matter in some cases for large projects (such as when using LTO).

当我把Debug Information Level设置为Line tables only的时候,然后构建app,每个源文件在编译时,都多了一个编译参数:-gline-tables-only

Clang的文档中这样解释-gline-tables-only

Generate line number tables only. This kind of debug info allows to obtain stack traces with function names, file names and line numbers (by such tools as gdb or addr2line). It doesn’t contain any other data (e.g. description of local variables or function parameters).

这种类型的调试信息允许获得带有函数名、文件名和行号的函数调用栈,但是不包含其他数据(比如局部变量和函数参数)。

所以当Debug Information Level设置为Line tables only的时候,断点依然会中断,但是无法在调试器中查看局部变量的值:

现在把Debug Information Level设置回Compiler default,然后试验下一个设置。

Strip Linked Product [STRIP_INSTALLED_PRODUCT] 在Xcode7.2.1中,Strip Linked Product在DEBUG和RELEASE下均默认为YES

这是一个让我困惑了很久的设置选项。当我把这一设置选项改为NO的时候,最终构建生成的app大小没有任何变化,这让我觉得很奇怪。

原来,Strip Linked Product也受到Deployment Postprocessing设置选项的影响。在Build Settings中,我们可以看到,Strip Linked Product是在Deployment这栏中的,而Deployment Postprocessing相当于是Deployment的总开关。 Xcode7.2.1中,Deployment Postprocessing在DEBUG和RELEASE下均默认为NO

现在我们把Deployment Postprocessing设置为YES,对比Strip Linked Product设为YESNO的这两种情况,发现当Strip Linked Product设为YES的时候,app的构建过程多了这样两步:

  1. 在app构建的开始,会生成一些.hmap辅助文件;(为什么会多出这一步我好像还不太清楚)
  2. 在app构建的末尾,会执行Strip操作。
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
** 0   XSQSymbolsDemo                      0x000000010001a7f4 XSQSymbolsDemo + 26612**

而在程序崩溃时,函数调用栈中也无法看到类名和方法名,注意右上角变成了unnamed_function:

继续保持Strip Linked ProductDeployment PostprocessingYES,下面来看看Strip Style设置选项。

Strip Style [STRIP_STYLE] 在Xcode7.2.1中,Strip Style在DEBUG和RELEASE下均默认All Symbols

官方文档中对Strip Style的描述:

Defines the level of symbol stripping to be performed on the linked product of the build. The default value is defined by the target's product type. [STRIP_STYLE]

All Symbols - Completely strips the binary, removing the symbol table and relocation information. [all, -s] Non-Global Symbols - Strips non-global symbols, but saves external symbols. [non-global, -x] Debugging Symbols - Strips debugging symbols, but saves local and global symbols. [debugging, -S]

选择不同的Strip Style时,app构建末尾的Strip操作会被带上对应的参数。

如果选择debugging symbols的话,函数调用栈中,类名和方法名还是可以看到的。

如果我们构建的不是一个app,而是一个静态库,需要注意,静态库是不可以strip all的。这时构建会失败。想想符号在重定位时的作用,如果构建的静态库真的能剥离所有符号,那么它也就没法被链接了。

现在我们保持Deployment PostprocessingYESStrip Linked Product改回NOStrip Style改回All Symbols,接下来看下一个设置。

Strip Debug Symbols During Copy [COPY_PHASE_STRIP] 网上有很多文章,以为Strip Debug Symbols During Copy开启的时候,app中的调试符号会被剥离掉。我感觉他们混淆了Strip Linked ProductStrip Debug Symbols During Copy的用法。

文档上的描述是:

Activating this setting causes binary files which are copied during the build (e.g., in a Copy Bundle Resources or Copy Files build phase) to be stripped of debugging symbols. It does not cause the linked product of a target to be stripped (use Strip Linked Product for that).

Strip Debug Symbols During Copy中的During Copy是什么意思呢?我觉得可能是app中引入的某些类型的库,在app的构建过程中需要被复制一次。虽然我暂时没找全究竟什么样的“库”需要在app构建时被复制,但是我发现,当app中包含extension或者watch app的时候,构建过程中会有Copy的步骤:

当我将app(而非extension)的Strip Debug Symbols During Copy设置为YES之后,在这句copy的命令中会多出-strip-debug-symbols参数。

但是这里,strip并不能成功,并且出现了warning:

warning: skipping copy phase strip, binary is code signed: /Users/xsq/Library/Developer/Xcode/DerivedData/XSQSymbolsDemo-cysszdsykroyyddkvvyffgboglvo/Build/Products/Debug-iphoneos/Today.appex/Today

这似乎是由于app中的today extention已经经过了code sign,导致无法被篡改引起的警告。

那么如果略过code sign的过程,是否就能成功strip呢?我想使用模拟器调试可以略过code sign过程,于是便在模拟器上试了试。果然这个warning消失了。

Strip Debug Symbols During Copy设置为YES时,打开对应.app文件的“显式包内容”,可以看到,/PlugIns/Today.appex文件的大小变小了。(不过这些只能在使用模拟器时奏效)

Strip Debug Symbols During Copy置为YES的时候,today extension中的断点将不会中断,但是打印[NSThread callStackSymbols]时的类名和方法名还是可以看见的。

现在我们把Strip Debug Symbols During Copy设置回NO,来看看下一个设置。

Debug Information Format [DEBUG_INFORMATION_FORMAT] Xcode7.2.1中,Debug Information Format在DEBUG下默认为DWARF,在RELEASE下默认为DWARF with dSYM File

官方文档的解释是:

This setting controls the format of debug information used by the developer tools. [DEBUG_INFORMATION_FORMAT]

DWARF - Object files and linked products will use DWARF as the debug information format. [dwarf] DWARF with dSYM File - Object files and linked products will use DWARF as the debug information format, and Xcode will also produce a dSYM file containing the debug information from the individual object files (except that a dSYM file is not needed and will not be created for static library or object file products). [dwarf-with-dsym]

Debug Information FormatDWARF with dSYM File的时候,构建过程中多了一步Generate dSYM File:

最终产出的文件也多了一个dSYM文件。

不过,既然这个设置叫做Debug Information Format,所以首先得有调试信息。如果此时Generate Debug Symbols选择的是NO的话,是没法产出dSYM文件的。

dSYM文件的生成,是在Strip等命令执行之前。所以无论Strip Linked Product是否开启,生成的dSYM文件都不会受影响。

不过正如文档中所说,无法为静态库生成dSYM文件。即便为给一个静态库的Debug Information Format设置为DWARF with dSYM File,构建过程中依然不会有生成dSYM文件的步骤。

一种配置方案 了解了每个设置的意思,个人觉得对于一个普通的app来说可以这样配置这些设置:

  • Generate Debug Symbols:DEBUG和RELEASE下均设为YES(和Xcode默认一致);
  • Debug Information Level:DEBUG和RELEASE下均设为Compiler default(和Xcode默认一致);
  • Deployment Postprocessing:DEBUG下设为NO,RELEASE下设为YES,这样RELEASE模式下就可以去除符号缩减app的大小(但是似乎设置为YES后,会牵涉一些和bitcode有关的设置,对于bitcode暂时还不太了解(´・_・`));
  • Strip Linked Product:DEBUG下设为NO,RELEASE下设为YES,用于RELEASE模式下缩减app的大小;
  • Strip Style:DEBUG和RELEASE下均设为All Symbols(和Xcode默认一致);
  • Strip Debug Symbols During Copy:DEBUG下设为NO,RELEASE下设为YES
  • Debug Information Format:DEBUG下设为DWARF,RELEASE下设为DWARF with dSYM File,dSYM文件需要用于符号化crash log(和Xcode默认一致);
参考

深入理解计算机系统 Build Setting Reference Skipping Copy Phase Strip xcode build settings for debug symbol Clang Compiler User’s Manual Symbolification: Shipping Symbols Technical Q&A QA1490

2016.04.17更新

某天,我看了公司的项目的设置,发现Deployment Postprocessing这项在DEBUG和RELEASE下均为NO,让我有些奇怪,难道公司的项目没有滤去调试符号? 于是我archive了一下,发现,在archive的过程中,其实是跑了strip的命令的,让我有点吃惊。这说明run和archive的构建过程是不同的。

查了官方文档,暂时没能查到run和archive到底有哪里不同,但是这里对ACTION的解释让我有些在意。对ACTION的设置会影响到Deployment Postprocessing的默认值,即当$ACTION = install的时候,Deployment Postprocessing默认为YES

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-05-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

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

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

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Xcode编译疾如风-3.浅谈 dwarf 和 dSYM
小菜:本文是《Xcode编译疾如风-4.BuildSettings》的其中的Debug Information Format 配置项的背景知识前置科普文。
ChildhoodAndy
2021/05/11
4.5K0
正经分析iOS包大小优化
包大小优化是项目开发中不可避免会遇到的,网上关于包大小优化的文章很多,每篇文章说的都不尽相同,笔者曾经根据网上的文章做过包大小优化,但效果不尽人意;因此笔者想根据已有的文章、知识结合自己的理解、实践,做一份总结梳理,整理自己的包大小优化逻辑,不光要知道怎么做可以让包大小变化,还要知道为什么这么做能产生效果,所以就有了这篇文章。
莫空9081
2021/05/28
6.1K0
CMake脚本中如何修改XCode工程属性?
以下的所有属性列表(https://help.apple.com/xcode/mac/current/#/itcaec37c2a6): Active Build Action (ACTION)
24K纯开源
2020/09/01
5.5K0
Bugly iOS自动导入符号表
      最近在处理Bugly问题的时候顺便解决了下符号表上传的问题,使用最新的上传工具包,也是顺便整理了下可以使用的脚本添加到了项目中,把这个过程中遇到的问题总结出来,脚本也会给出来,实测是没有问题的,希望可以帮助到有需要的小伙伴。首先关于什么是符号表,符号表是用来干什么的,在哪里找自己的符号表这些问题我们不在这里说,Bugly文档里面说的很详细也很清楚,需要的小伙伴直接去看官方文档。
Mr.RisingSun
2022/10/05
1.5K0
Bugly iOS自动导入符号表
iOS 优化 - 瘦身
iOS 优化将是一个专题,其中会包括包体积优化(瘦身)、启动时间优化、UI 优化等等。那么这个专题的开篇就从瘦身开始吧。
CoderStar
2022/08/24
2.7K0
iOS 优化 - 瘦身
XCode日常使用备忘录
0. Introduction        XCode是macOS上开发app不可缺少的开发者工具,不管是开发macOS上的应用,还是iOS上的应用,都离不开XCode环境。尽管其易用性广受诟病,但由于苹果app开发的封闭性,众多开发者也不有苦不能言。近年来微软针对macOS平台发布了Visual Studio Code和Visual Studio for Mac这两款开发工具,但是其目的显然只是作为XCode的一种补充,要全盘替代XCode目前还不太现实。平时工作中由于负责开发维护Windows和Mac
24K纯开源
2018/01/18
1.8K0
XCode日常使用备忘录
Xcode 常见 CLI 工具
在咱们日常开发中,或多或少都会用到 Xcode 内置的一些CLI工具,但是大部分小伙伴可能只是会用到一些具体的命令,今天我们就一起来聊一聊 Xcode 内置的常见Command Lines Tool。
CoderStar
2022/09/23
3.6K0
减包-删除无用的代码
使用开源工具 LSUnusedResources 检查重复图片,但是可能会有误报,比如 [@”image%d”, index] 这种引用方式无法检查到,需要人工在核对一边。
Helloted
2022/06/08
1.5K0
减包-删除无用的代码
iOS_crash文件的获取及符号化(解析)
稍等一会,就会输出路径,然后将路径复制,右键 Finder -> 前往文件夹 -> 粘贴 -> 回车,就能找到symbolicatecrash,将symbolicatecrash拷贝出来备用
mikimo
2023/10/18
2.5K1
iOS崩溃堆栈符号化,定位问题分分钟搞定!
最近一段时间,在跟开发者沟通过程中,萝莉发觉有些开发者对iOS的应用符号表还不是很清楚,除了咨询关于符号表生成、配置的问题以外,对Bugly崩溃分析需要配置符号表也存在疑问。 在这里,萝莉就给大家分享下关于iOS符号表的一些内容。 首先,进行常识“脑补”。 1. 符号表是什么? 符号表就是指在Xcode项目编译后,在编译生成的二进制文件.app的同级目录下生成的同名的.dSYM文件。 .dSYM文件其实是一个目录,在子目录中包含了一个16进制的保存函数地址映射信息的中转文件,所有Debug的symbols都
腾讯Bugly
2018/03/22
4.9K0
iOS符号化浅析
十一去云南(丽江、大理、昆明)玩了一趟,怎么说呢,可能我想象中的云南是西双版纳、香格里拉那样子的,所以这次云南之行跟想象中还是有一定差异的。
CoderStar
2022/09/23
2K0
iOS符号化浅析
Unix系统中nm命令展示目标文件符号的方法
在unix系统中,通过gnu开源gcc或者g++工具生成的目标文件(object file),可以用nm、objdump和readelf这三个命令来查看。
typecodes
2024/03/29
2060
编译与链接过程的思考
前言 最近遇到一个错误,如下 在解决过程中,回顾了很多知识,于是有了这篇文章。 关键词:预处理、编译、汇编、链接、动态链接库、静态链接库、真机调试。 正文 以.c文件的编译流程为例,如下图
落影
2018/04/27
1.3K1
编译与链接过程的思考
iOS开发笔记(三)
前言 日常开发遇到的问题记录。 JSON Invalid type in JSON write (NSConcreteMutableData) 合法的json对象: 1、顶层对象必须是NSArray或者NSDictionary; 2、所有的对象必须是NSString/NSNumber/NSArray/NSDictionary/NSNull的实例; 3、所有NSDictionary的key必须是NSString类型; 4、数字对象不能是非数值或无穷; 内购 1、银行cnaps code查询 http:
落影
2018/04/27
2.2K0
iOS开发笔记(三)
ARM 之七 主流编译器(armcc、iar、gcc for arm、LLVM(clang))详细介绍[通俗易懂]
  在讲解各编译器之前,必须先了解一下以下这些文件。这些文件在编译器目录下或者编译生成目标平台的可执行程序时经常见到。此外,还需要注意区分 Windows 平台 和 Linux 平台的文件。
全栈程序员站长
2022/06/28
16.8K0
ARM 之七 主流编译器(armcc、iar、gcc for arm、LLVM(clang))详细介绍[通俗易懂]
有赞crash平台符号化实践
有赞在基础保障平台的实践中完成了 Crash平台 的建设,但是iOS的崩溃日志未经符号化,排查问题比较困难。为了降低iOS App的crash率,快速排查线上crash,疑难crash的跟踪处理,符号化崩溃日志显得尤为重要!
有赞coder
2020/09/21
1.5K0
有赞crash平台符号化实践
​iOS Class Guard github用法、工作原理和安装详解及使用经验总结
iOS Class Guard是一个用于OC类、协议、属性和方法名混淆的命令行工具。它是class-dump的扩展。这个工具会生成一个symbol table,这个table在编译期间会包含进工程中。iOS-Class-Guard能有效的隐藏绝大多数的类、协议、方法、属性和 实例变量 名。iOS-Class-Guard不是应用安全的最终解决方案,但是它绝对能让攻击者更难读懂你的程序。iOS-Class-Guard会加大代码分析和runtime检查的难度,这个工具可以认为是一个简单基础的混淆方法。由于OC的架构决定了iOS应用程序的剖析相当简单,check out一下链接就知晓了:
iOS Magician
2023/12/02
3640
​iOS Class Guard github用法、工作原理和安装详解及使用经验总结
了解和分析iOS Crash Report
翻译自苹果官方文档:Understanding and Analyzing Application Crash Reports
nimomeng
2018/09/13
1.8K0
了解和分析iOS Crash Report
iOS逆向之Mach-O文件
阅读笔者的其他文章,我们了解了编译过程中的预处理、词法分析、语法分析、编译、链接等步骤。经常和编译型语言打交道的开发者对于可执行文件的编译过程肯定不陌生。我们用 Xcode 构建一个程序的过程中,会把源文件 (.m 和 .h) 文件转换为一个可执行文件。这个可执行文件中包含的字节码将会被 CPU (iOS 设备中的 ARM 处理器或 Mac 上的 Intel 处理器) 执行。
VV木公子
2021/03/07
11.1K0
iOS逆向之Mach-O文件
Sentry-CLI 使用详解(2021 Sentry v21.8.x)
内容源于:https://docs.sentry.io/platforms/javascript/guides/vue/
为少
2021/09/17
3K0
相关推荐
Xcode编译疾如风-3.浅谈 dwarf 和 dSYM
更多 >
领券
💥开发者 MCP广场重磅上线!
精选全网热门MCP server,让你的AI更好用 🚀
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验