iOS--编译连接的过程_2

news2024/11/26 5:24:29

文章目录

  • iOS编译
      • (一)编译器前端
  • 编译器后端
    • 执行一次XCode build的流程
  • IPA包的内容
  • 二进制文件的内容
    • iOS Link Map File文件说明
      • 1. Link Map File 是什么
      • 2. Link Map File 有什么用
      • 3. 生成 Link Map File
      • 查看Link Map File
        • 1)路径部分
        • 计算机系统知识
          • a. __TEXT段中的 Section
          • b. __DATA段中的 Section
          • (4) Symbols 部分
          • (5)二进制重排

一般可以将编程语言分为两种,编译语言和直译式语言。

像C++,Objective C都是编译语言。编译语言在执行的时候,必须先通过编译器生成机器码,机器码可以直接在CPU上执行,所以执行效率较高。

像JavaScript,Python都是直译式语言。直译式语言不需要经过编译的过程,而是在执行的时候通过一个中间的解释器将代码解释为CPU可以执行的代码。所以,较编译语言来说,直译式语言效率低一些,但是编写的更灵活

iOS编译

Objective C采用Clang(swift采用swiftc)作为编译器前端,LLVM作为编译器后端。

简单的编译过程如图
在这里插入图片描述

(一)编译器前端

编译器前端的任务是进行:词法分析,语法分析,语义分析,生成中间代码(intermediate representation )。在这个过程中,会进行类型检查,如果发现错误或者警告会标注出来在哪一行。
在这里插入图片描述

编译器后端

编译器后端会进行机器无关的代码优化,生成机器语言,并且进行机器相关的代码优化。iOS的编译过程,后端的处理如下

  • LVVM优化器会进行BitCode的生成,链接期优化等等

  • 在这里插入图片描述

  • LLVM机器码生成器会针对不同的架构,比如arm64等生成不同的机器码

  • 在这里插入图片描述

执行一次XCode build的流程

当你在XCode中,选择build的时候(快捷键command+B),会执行如下过程

编译信息写入辅助文件,创建编译后的文件架构(name.app)
处理文件打包信息,例如在debug环境下

Entitlements:
{
“application-identifier” = “app的bundleid”;
“aps-environment” = development;
}

执行CocoaPod编译前脚本
例如对于使用CocoaPod的工程会执行CheckPods Manifest.lock
编译各个.m文件,使用CompileC和clang命令。

CompileC ClassName.o ClassName.m normal x86_64 objective-c com.apple.compilers.llvm.clang.1_0.compiler
export LANG=en_US.US-ASCII
export PATH=“…”
clang -x objective-c -arch x86_64 -fmessage-length=0 -fobjc-arc… -Wno-missing-field-initializers … -DDEBUG=1 … -isysroot iPhoneSimulator10.1.sdk -fasm-blocks … -I 上文提到的文件 -F 所需要的Framework -iquote 所需要的Framework … -c ClassName.c -o ClassName.o

通过这个编译的命令,我们可以看到

clang是实际的编译命令
-x objective-c 指定了编译的语言
-arch x86_64制定了编译的架构,类似还有arm7等
-fobjc-arc 一些列-f开头的,指定了采用arc等信息。这个也就是为什么你可以对单独的一个.m文件采用非ARC编程。
-Wno-missing-field-initializers 一系列以-W开头的,指的是编译的警告选项,通过这些你可以定制化编译选项
-DDEBUG=1 一些列-D开头的,指的是预编译宏,通过这些宏可以实现条件编译
-iPhoneSimulator10.1.sdk 制定了编译采用的iOS SDK版本
-I 把编译信息写入指定的辅助文件
-F 链接所需要的Framework
-c ClassName.c 编译文件
-o ClassName.o 编译产物

  • 链接需要的Framework,例如Foundation.framework,AFNetworking.framework,ALiPay.fframework
  • 编译xib文件
  • 拷贝xib,图片等资源文件到结果目录
  • 编译ImageAssets
  • 处理info.plist
  • 执行CocoaPod脚本
  • 拷贝Swift标准库
  • 创建.app文件和对其签名

IPA包的内容

例如,我们通过iTunes Store下载微信,然后获得ipa安装包,然后实际看看其安装包的内容。
在这里插入图片描述

二进制文件的内容

通过XCode的Link Map File,我们可以窥探二进制文件中布局。 在XCode -> Build Settings -> 搜索map -> 开启Write Link Map File
![

iOS Link Map File文件说明

1. Link Map File 是什么

Link Map File 直译为 链接映射文件,是 Xcode 生成可执行文件时一起生成的文本,用于记录链接相关信息。

可执行文件的路径
CPU架构
.o目标路径
方法符号

2. Link Map File 有什么用

查看代码加载顺序
理解内存分段分区
Crash 时通过 Symbols 定位源码的机制
分析可执行文件中类或库体积,优化包体积

3. 生成 Link Map File

Xcode 在生成可执行文件的时候默认情况下不生成该文件。 在Xcode的配置中 Target -> Build Setting -> Linking 将Write Link Map File设置为YES来生成Link Map File,运行代码即可生成Link Map File在这里插入图片描述

查看Link Map File

主要分为三个部分

  • 路径部分,展示生成的相关文件路径
  • Section部分,展示相关地址段
  • Symbols部分,方法符号段

1)路径部分

  • Path是.app文件路径
  • Object files是.o文件路径
  • 在这里插入图片描述

计算机系统知识

a. text 段
这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于只读(某些架构也允许代码段为可写,即允许修改程序)。
代码段(code segment/text segment)通常是指用来存放程序执行代码的一块内存区域。

在代码段中,也有可能包含一些只读的常数变量,例如字符串常量等。

b. data 段

数据段(data segment)通常是指用来存放程序中已初始化的全局变量的一块内存区域。

c. bss 段

bss段(bss segment)通常是指用来存放程序中未初始化的全局变量的一块内存区域。

bss是英文Block Started by Symbol的简称。

d. 堆(heap)

堆是用于存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减。

当进程调用malloc等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张);

当利用free等函数释放内存时,被释放的内存从堆中被剔除(堆被缩减)。

e. 栈(stack)

栈又称堆栈,是用户存放程序临时创建的局部变量,

也就是说我们函数括弧“{}”中定义的变量(但不包括static声明的变量,static意味着在数据段中存放变量)。

除此以外,在函数被调用时,其参数也会被压入发起调用的进程栈中,并且待到调用结束后,函数的返回值也会被存放回栈中。

由于栈的先进先出(FIFO)特点,所以栈特别方便用来保存/恢复调用现场。

从这个意义上讲,我们可以把堆栈看成一个寄存、交换临时数据的内存区。

(3)Section 部分

Mach-O 文件中的虚拟地址最终会映射到物理地址上。这些地址被分成不同的Segement: TEXT段、DATA段、__LINKEDIT段。

__TEXT 包含 Mach header,被执行的代码和只读常量(如C 字符串),只读可执行(r-x)。
__DATA 包含全局变量,静态变量等,可读写(rw-)。
__LINKEDIT 包含了加载程序的元数据,比如函数的名称和地址,只读(r–)。

Segement 划分成了不同的 Section,不同的 Section 存储着不同的信息,下面是一些常用的 Section 的介绍。

a. __TEXT段中的 Section

在这里插入图片描述

b. __DATA段中的 Section

在这里插入图片描述
在这里插入图片描述

(4) Symbols 部分
  • Address:方法代码的地址
  • Size:方法占用的空间
  • File:文件的编号
  • Name:.o文件里面的方法符号
(5)二进制重排

二进制重排 就是要重新排列这些 方法符号的顺序 ,中心思想就是把启动用到的代码挪到前面的位置加载!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/782309.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux进程间通信(fifo有名管道)

文章目录 前言一、有名管道概念讲解二、命令行创建fifo三、非命令行创建fifo四、fifo和管道对比总结 前言 上篇文章我们讲解了无名管道,这篇文章我们就来讲解一下有名管道。 一、有名管道概念讲解 有名管道(fifo) 有名管道(FIFO)是一种命…

jmeter请求重试实现思路

文章目录 一、背景二、尝试的解决方案三、最终解决方案:jmeter retrier插件! 一、背景 最近系统需要压测一些活动,场景是新建抽奖活动之后,每隔2s查询1次(最多3次,3次后还是失败就算失败)&…

linux学成之路(基础篇)(二十)rsync服务器

目录 前言 一、概述 监听端口 二、特点 快捷 安全 三、数据的同步方式 四、rsync传输方式 本地传输 远程传输 守护进程 五、命令 作为远程命令 作为rsync服务 选项 六、配置文件 全局配置 模块配置 守护进程传输 七、rsyncinotfy实时同步 一、服务端 二、…

Qgis二次开发-QgsMapLayer(加载矢量、栅格图层)

1.简介 QgsMapLayer是所有地图层类型的基类,这是所有地图层类型(矢量,栅格)的基类,首先定义一个QgsMapCanvas地图画布,然后画布上添加图层,使用以下方法设置图层集合。 //设置当前图层集合 void setLayers (const QL…

算法提高-动态规划-单调队列优化DP

单调队列优化DP AcWing 135. 最大子序和AcWing 1087. 修剪草坪AcWing 1089. 烽火传递AcWing 1090. 绿色通道 关于单调队列的初始化 AcWing 135. 最大子序和 注意hh 0,tt -1 tt 0初始化的时候队列有什么不同&#xff0c;主要还是要理解队列的实际意义 #include <iostre…

利用python绘制二维向量图

为了实现地层数据的变化趋势的可视化模拟&#xff0c;最近研究了python环境下的可视化方案&#xff0c;为后续的流体运动的仿真模拟做好储备&#xff0c;主要采用matplotlib中的quiver函数&#xff0c;实现二维等值线数据的随深度或者地层数据的变化趋势绘制。 一、运行环境&a…

MySQL--主从复制

目录 1.理解MySQL主从复制原理。 2.完成MySQL主从复制。 1.理解MySQL主从复制原理。 1.主要基于MySQL二进制日志 2.主要包括三个线程&#xff08;2个I/O线程&#xff0c;1个SQL线程&#xff09; 概括&#xff1a; 1、MySQL将数据变化记录到二进制日志中&#xff1b; 2、Slave…

【前端动画】点击移动放大出现蒙版,点击蒙版原路返回 css动画animation

<template><div><!-- 蒙版 Mask--><divv-if"isShowTableMask":class"${maskClass}"click"closeTableMask"></div><div style"" class"table-dialog" :class"${centerTableClass} …

Pytorch从入门到精通:二、dataset与datalodar

数据是深度学习的基础&#xff0c;一般来说&#xff0c;数据量越大&#xff0c;训练出来的模型也越强大。如果现在有了一些数据&#xff0c;该怎么把这些数据加到模型中呢&#xff1f;Pytorch中提供了dataset和dataloader&#xff0c;让我们一起来学习一下吧&#xff0c;datase…

AcWing 237. 程序自动分析

输入样例&#xff1a; 2 2 1 2 1 1 2 0 2 1 2 1 2 1 1输出样例&#xff1a; NO YES 解析&#xff1a; 并查集&#xff0c;由于 i, j 数据量为1e9&#xff0c;所以需要离散化。 数组要开2e5个&#xff0c;由于可能每条“约束条件”的数据都不一样。 #include<bits/stdc.h&…

Python-Go python模块与包 - GO问题 - GO容量测试

目录 go 模块与包复习&#xff08;Init函数 - go mod&#xff09; init函数有什么用&#xff1f;init函数是什么&#xff1f; go.mod文件是什么&#xff1f;有什么作用&#xff1f; python的模块与包 python中包的分类 1、内置模块&#xff1a;不需要安装&#xff0c;直接…

和chatgpt学架构04-路由开发

目录 1 什么是路由2 如何设置路由2.1 安装依赖2.2 创建路由文件2.3 创建首页2.4 编写HomePage2.5 更新路由配置2.6 让路由生效 3 测试总结 要想使用vue实现页面的灵活跳转&#xff0c;其中路由配置是必不可少的&#xff0c;我们在做开发的时候&#xff0c;先需要了解知识点&…

lwip-2.1.3自带的httpd网页服务器使用教程(四)POST类型表单的解析和文件上传

上一篇&#xff1a;lwip-2.1.3自带的httpd网页服务器使用教程&#xff08;三&#xff09;使用CGI获取URL参数&#xff08;GET类型表单&#xff09; 在阅读本篇内容之前&#xff0c;请修改httpd.c文件&#xff0c;修复lwip自带httpd服务器里面关于post的一个bug&#xff1a;bug…

系统集成|第一章(笔记)

目录 第一章 信息化知识1.1 信息与信息化1.1.1 信息1.1.2 信息系统1.1.3 信息化1.1.4 国家信息化体系要素 1.2 国家信息化战略和规划1.3 电子政务1.4 企业信息化和两化深度融合1.4.1 企业信息化1.4.2 企业应用集成1.4.2.1 电子商务系统1.4.2.2 企业资源规划系统1.4.2.3 客户关系…

【Java】 服务器cpu过高如何排查和解决?

文章目录 前言一、常见能够引起CPU100%异常的情况都有哪些&#xff1f;二、服务器CPU使用率飙升异常&#xff0c;黄金4步排查法三、排查 CPU 故障的常用命令四、什么场景会造成 CPU 低而负载确很高呢&#xff1f;五、监控发现线上机器内存占用率居高不下&#xff0c;如何分析进…

两个数组的dp问题--动态规划

一)最长公共子序列: 1143. 最长公共子序列 - 力扣&#xff08;LeetCode&#xff09; 一)定义一个状态表示:根据经验题目要求 1)选取第一个字符串[0&#xff0c;i]区间以及第二个字符串[0&#xff0c;j]区间作为研究对象&#xff0c;先选取两段区间研究问题&#xff0c;先求出[0…

redis(8):java连接redis

1 Jedis所需要的jar包依赖 <dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>3.1.0</version></dependency> 2 Jedis常用操作 2.1 测试连通性 package com.example.demo;import redis.…

手写Spring,理解SpringBean生命周期

按照Spring使用习惯&#xff0c;准备环境 ​ 首先&#xff0c;写一个TigerApplicationContext&#xff0c;模拟Spring的Annotation Application。然后写一个config&#xff0c;接着写一个UserService。 由于Spring需要扫描bean&#xff0c;所以我们得定义一个扫描注解Componen…

【C++】-priority_queue(优先级队列的具体使用和模拟实现)以及仿函数的简单介绍

&#x1f496;作者&#xff1a;小树苗渴望变成参天大树&#x1f388; &#x1f389;作者宣言&#xff1a;认真写好每一篇博客&#x1f4a4; &#x1f38a;作者gitee:gitee✨ &#x1f49e;作者专栏&#xff1a;C语言,数据结构初阶,Linux,C 动态规划算法&#x1f384; 如 果 你 …

ubuntu 开启 ssh 服务 设置root远程登录

设置root用户密码 sudo passwd root安装ssh服务和vim编辑器 sudo apt -y install openssh-server vim开启ssh服务 sudo vim /etc/ssh/ssh_config去掉 配置文件中 Port 22 的注释后保存退出 设置root用户远程登录 sudo vim /etc/ssh/sshd_config将 PermitRootLogin prohibit-pas…