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.ha.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.ha.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_varstatic_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的更多相关文章

  1. [转] .bss段和.data段的区别

    PS:http://stackoverflow.com/questions/16557677/difference-between-data-section-and-the-bss-section-i ...

  2. bss 概念

    BSS段 在采用段式内存管理的架构中,BSS段(bss segment)通常是指用来存放程序中未初始化的全局变量的一块内存区域.BSS是英文Block Started by Symbol的简称.BSS ...

  3. Linker Special Section Types

    转载自http://processors.wiki.ti.com/index.php/Linker_Special_Section_Types#NOLOAD_Sections_2 Introducti ...

  4. 《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 ...

  5. 嵌入式C语言自我修养 06:U-boot镜像自拷贝分析:section属性

    6.1 GNU C 的扩展关键字:attribute GNU C 增加一个 __atttribute__ 关键字用来声明一个函数.变量或类型的特殊属性.声明这个特殊属性有什么用呢?主要用途就是指导编译 ...

  6. 深入理解BSS(Block Started by Symbol)

    理解ELF的BSS section, 可以概括为: Uninitialized global/static data "Block Started by Symbol" " ...

  7. 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 ...

  8. android中的Section ListView

    前几天,和ios开发的同事扯淡时发现iphone里有个section listview,分章节的列表.android中的联系人也有这种效果,首字母相同的联系人会被分在一个章节中. 后来搜了一下,and ...

  9. (转)__attribute__之section 分析详解

    原文地址:__attribute__之section详解 前言 第一次接触 "section" 是在公司的一个STM32的项目代码中,前工程师将所有的初始化函数都使用的" ...

  10. YASM User Manual

    This document is the user manual for the Yasm assembler. It is intended as both an introduction and ...

随机推荐

  1. Day14_Java_作业

    编程题: 1:获取10个1-20之间的随机数,要求不能重复 答: package StudentWork; import java.util.ArrayList; /** * * 需求: 1:获取10 ...

  2. H5用canvas放烟花

    很久很久以前的一个很流行的java Applet放烟花效果,当初移到android过,这次摸鱼时间翻译成js代码,用canvas实现这么多年,终于能大致看懂这代码了, 已经实现透明效果,只需要给bod ...

  3. Python实现商城购物经典案例

    代码分步骤思路: 商城添加商品:opea_db = [{'store_name': '手机','num': 1}] while True: store_name=input('请输入需要存放的商品(按 ...

  4. MySQL高级9-锁

    一.简介 锁是计算机协调多个进程或线程并发访问某一资源的机制.在数据库中,除了传统的计算资源(CPU.RAM.i/O)的挣用以外,数据也是一种供许多用户共享的资源.如何保证数据并发访问的一致性,有效性 ...

  5. 解决SVN死锁问题

    svn执行clean up后出现提示:svn cleanup failed–previous operation has not finished; run cleanup if it was int ...

  6. mysql8关闭binlog并清空Binlog

    编辑my.ini或者my.cnf文件 清空binlog信息 #查看现存的binlog文件列表 show master logs; #重置清空binlog文件 reset master; #重置清空后 ...

  7. SQL查询中的小技巧:SELECT 1 和 LIMIT 1 替代 count(*)

    前言 在写SQL查询时,常规做法是使用SELECT count(*)来统计符合条件的记录数. 然而,在某些情况下,我们只关心是否存在符合条件的记录,而不需要知道具体的记录数. 为了优化性能,可以改用使 ...

  8. 「codeforces - 1633F」Perfect Matching

    link. 首先所有的 activated nodes 组合成了一棵以 \(1\) 为根的有根树.询问即求由 activated nodes 组成的树的最大匹配.对于树上最大匹配有一个贪心策略:自底向 ...

  9. Solution -「CF 1477A」Nezzar and Board

    Description Link. $ n $ distinct integers $ x_1,x_2,\ldots,x_n $ are written on the board. Nezzar ca ...

  10. vscode编写markdown

    1. 需求分析 2. 环境搭建 1. 需求分析 最近在网上折腾了好久Markdown的写作环境,作为一个普通用户,总结一下个人对于Markdown写作环境的几点需求.由于本人刚接触Markdown不久 ...