Mach-O Inside: BSS Section
1 BSS 起源
BSS(Block Started by Symbol)这个词最初是 UA-SAP 汇编器(United Aircraft Symbolic Assembly Program)中的一个伪指令,用于为符号预留一块内存空间。该汇编器由美国联合航空公司于 20 世纪 50 年代中期为 IBM 704 大型机所开发。
后来,BSS 这个词被作为关键字引入了 IBM 709 和 7090/94 机型上的标准汇编器 FAP(Fortran Assembly Program),用于定义符号并且为该符号预留给定数量的未初始化空间。
Unix FAQ section1.3 里面有 Unix 和 C 语言支付 Dennis Rithcie 对 BSS 这个词由来的解释。
2 Macho-O 里的 __bss
一般对 BSS Section 的介绍会说里面存放的是未初始化的全局变量和未初始化的局部静态变量,但是实际对 Mach-O 目标文件(.o 文件)进行查看,发现情况并不是这样。
假设有a.h和a.m文件,a.h里面声明了一个函数 test(),代码如下:
void test();
a.m里面定义了 2 个全局变量和 2 个静态变量:
global_init_var 全局变量初始化为 84,global_uninit_var全局变量未进行初始化。
static_init_var 静态变量初始化为 85,static_uninit_var静态变量未进行初始化。
// 1. 初始化全局变量
int global_init_var = 84;
// 2. 未初始化全局变量
int global_uninit_var;
void test(void) {
// 3. 初始化静态变量
static int static_init_var = 85;
// 4. 未初始化静态变量
static int static_uninit_var;
// 5. 打印所有变量之和
printf("%d", global_init_var + global_uninit_var + static_init_var + static_uninit_var);
}
创建一个 iOS 工程,将a.h和a.m文件拖入到工程,并且进行编译。编译成功之后在工程 DevivedData 目录下找到a.o文件,并将这个文件拖入到 MachOView 工具中进行查看:

上图右侧 Size 字段代表 __bss Section 在虚拟内存中所占用的大小,其值为 4 字节,刚好是一个 int 类型的大小,表明为初始化的全局变量global_uninit_var和未初始化的静态变量static_uninit_var只有一个位于 __bss section 中。
offset 字段代表在 Macho-O 目标文件 a.o 中,__bss Section 距离 a.0 目标文件的起始位置偏移量为 0,而在目标文件 a.o 的起始位置是文件头 Header,文件头和 __bss Section 不可能重合,所以这表明 __bss Section 在 Mach-O 文件里面不会占用任何磁盘空间,只有在虚拟内存中,才会为 __bss Section 分配指定的空间。
flags 字段值为S_ZEROFILL,这表明当在虚拟内存里为 __bss Section 分配空间时,这个空间会全部被初始化为 0。
通过查看a.o的符号表,可以发现未初始化的全局global_uninit_var变量位于 __DATA Segment 的 __common Section 中:

只有未初始化的局部静态变量static_uninit_var 位于 __DATA Segment 的 __bss Section:

同样可以通过 MachOView 查看 __data Section Header,可以看到这个 Section 在虚拟内存中占用的大小为 8 个字节,刚好是 2 个 int 类型的大小。同时,这个 Section 位于距离 Mach-O 目标文件 a.o 起始位置 1944 字节处:

使用 MachOView 查看这个 Section 如下:

上图右侧pFile字段代表当前 Section 在 Mach-O 文件中的偏移量,其值是 16 进制 0x798,换算成 10 进制刚好是 1944,整好复合 __data Section Header 中的偏移量offset。
在Data LO字段存储了 8 个字节的数据,每 4 个字节代表一个整数。由于 ARM 字节序列是小端在前(Little-Endian),这两个整数的值应该是 0x00000054 和 0x00000055,换算成 10 进制就是 84 和 85,正好是全局变量global_init_var 和static_init_var的值。
3 Mach-O 里的 __common
上面提到未初始化的全局变量global_uninit_var并不位于 __bss Section,而是位于 __common Section。
通过 MachOView 查看 __common Section Header 如下图所示:

上图右侧size字段、offset字段与S_ZEROFILL代表的意义与 __bss Section Header 中的一样,从 offset 的值为 0 可知,__common Section 在 Macho-O 目标文件 a.o 中也不占用空间,只会在虚拟内存中为其分配大小为 4 字节的空间,并且全部初始化为 0。
为什么要把未初始化的全局变量和未初始化的静态变量分开放置?
这和具体的语言与编译器的实现有关,有的编译器会将未初始化的全局变量和未初始化的静态变量一起放在 __bss Section,有的编译器会像这样分开放置。
参考资料
程序员的自我修养-链接、装载与库
Mach-O Inside: BSS Section的更多相关文章
- [转] .bss段和.data段的区别
PS:http://stackoverflow.com/questions/16557677/difference-between-data-section-and-the-bss-section-i ...
- bss 概念
BSS段 在采用段式内存管理的架构中,BSS段(bss segment)通常是指用来存放程序中未初始化的全局变量的一块内存区域.BSS是英文Block Started by Symbol的简称.BSS ...
- Linker Special Section Types
转载自http://processors.wiki.ti.com/index.php/Linker_Special_Section_Types#NOLOAD_Sections_2 Introducti ...
- 《Peering Inside the PE: A Tour of the Win32 Portable Executable File Format》阅读笔记二
Common Sections The .text section is where all general-purpose code emitted by the compiler or assem ...
- 嵌入式C语言自我修养 06:U-boot镜像自拷贝分析:section属性
6.1 GNU C 的扩展关键字:attribute GNU C 增加一个 __atttribute__ 关键字用来声明一个函数.变量或类型的特殊属性.声明这个特殊属性有什么用呢?主要用途就是指导编译 ...
- 深入理解BSS(Block Started by Symbol)
理解ELF的BSS section, 可以概括为: Uninitialized global/static data "Block Started by Symbol" " ...
- MSP430之section(1)
1 Intro The smallest unit of an object file is a section. A section is a block of code or data that ...
- android中的Section ListView
前几天,和ios开发的同事扯淡时发现iphone里有个section listview,分章节的列表.android中的联系人也有这种效果,首字母相同的联系人会被分在一个章节中. 后来搜了一下,and ...
- (转)__attribute__之section 分析详解
原文地址:__attribute__之section详解 前言 第一次接触 "section" 是在公司的一个STM32的项目代码中,前工程师将所有的初始化函数都使用的" ...
- YASM User Manual
This document is the user manual for the Yasm assembler. It is intended as both an introduction and ...
随机推荐
- BugKu-Misc-Photo的自我修养
下载附件 打开002文件夹,发现一张照片 看到PNG右下疑似有半个字符,怀疑PNG宽高被修改 拿到测PNG宽高的脚本 点击查看代码 import binascii import struct crcb ...
- 2023-7-27WPF的ContextMenu的传参绑定方式
WPF的ContextMenu的绑定方式 [作者]长生 ContextMenu为何不能正常绑定 在wpf中ContextMenu和ToolTip一样都是弹出层,与VisualTree已经分离了,只不过 ...
- 面试再也不怕问ThreadLocal了
要解决多线程并发问题,常见的手段无非就几种.加锁,如使用synchronized,ReentrantLock,加锁可以限制资源只能被一个线程访问:CAS机制,如AtomicInterger,Atomi ...
- 【笔记】- 【美团1万台 Hadoop 集群 YARN 的调优之路】
原文:美团1万台 Hadoop 集群 YARN 的调优之路 背景 架构 YARN架构 资源抽象 YARN调度架构 资源抽象 调度流程 作业的组织方式 核心调度流程 指标 业务指标:有效调度 系统性能指 ...
- croc-文件传输工具
前言 croc是一款用go语言开发的命令行文件传输工具,该工具允许两台计算机设备以一种简单和安全的方式来传输文件. GitHub项目地址 环境信息 IP 系统版本 croc版本 说明 192.168. ...
- [prometheus]基于influxdb2实现远端存储
前言 Prometheus自带的时序数据库胜在使用方便,缺点在于难以维护,如果数据有问题,可能需要删除存储目录.重建目录再重启Prometheus,才能恢复正常.而且Prometheus自带的时序数据 ...
- 使用kafka自带脚本进行压力测试
前言 kafka官方自带压力测试脚本: 消费者压力测试:kafka-consumer-perf-test.sh 生产者压力测试:kafka-producer-perf-test.sh 测试节点: 17 ...
- [kafka]部署安装单节点
前言 kafka 3.0之前的版本需要依赖zookeeper,3.0版本之后可不依赖zookeeper. 基于zookeeper的安装步骤 节点IP:172.50.13.103 kafka版本:2.7 ...
- 清理MySQL的binlog历史文件
前言 系统版本:centos 7 MySQL版本:5.7 mysql的binlog文件最好不要手动删,避免删错导致bin log同步异常. 步骤 查看当前的binlog文件 show binary l ...
- 记通过mysql数据库成功入侵到服务器内部的渗透实战
1,在成功进入mysql到数据库之后,可以使用select user();命令,查看当前的用户,如果为root,则可以执行下一步操作.不为root,则需要通过其他方法提权. 2, 使用show var ...