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. 使用Python读取图片

    一.Python学习两大道具 1. dir()工具 作用:支持打开package,看到里面的工具函数 示例: (1) 输出torch库包含的函数 dir(torch) (2) 输出torch.AVG函 ...

  2. == 与 equals 的区别?

    一. 介绍: Java中的 "=="  是一个运算符,是用于比较两个对象地址值或基本数据类型之间的值是否相等.它的来源可以追溯到C语言,以及受C语言影响的许多其他编程语言. Jav ...

  3. ROS的通信机制

    通信机制 节点--执行单元 执行具体任务的进程.独立运行的可执行文件: 不同节点可以使用不同的编程语言,可分布式运行在不同的主机上. 节点在系统中的名称是必须是唯一的. 节点管理器(ROS Maste ...

  4. (转) [Android测试] AS+Appium+Java+Win自动化测试之三: 基础知识和Appium界面

    一.把上一章的demo先看懂 AndroidContactsTest.Java public class AndroidContactsTest { //Driver private AppiumDr ...

  5. 1.创建一个类,类A中定义了一个方法,该方法能接受3个参数根据参数判断是做加法还是减法并返回计算结果;

    class A: def cal(self,x,y,z): if z=='+': return x+y if z=='-': return x-y else: print('error') a=A() ...

  6. Vu3+Element-Plus根据路由配置生成菜单导航栏

    先看效果,整体界面结构如下 点击左侧菜单栏,右侧切换显示不同页面内容. Vue3使用路由–南河小站 1 路由配置 路由配置如下: const routes = [ { path: "&quo ...

  7. BUGKU逆向reverse 1-8题

    练习IDA两年半 打开尘封已久的bugku,从题目中练习使用,现在都已经是新版本了 orz 入门逆向 运行baby.exe将解压后的baby.exe拖到IDA里面主函数中找到mov指令 可以看到这里就 ...

  8. 《Kali渗透基础》13. 无线渗透(三)

    @ 目录 1:无线通信过程 1.1:Open 认证 1.2:PSK 认证 1.3:关联请求 2:加密 2.1:Open 无加密网络 2.2:WEP 加密系统 2.3:WPA 安全系统 2.3.1:WP ...

  9. The Missing Semester - 第五讲 学习笔记(二)

    第五讲(二) SSH入门 介绍完命令行环境后,这半节主要介绍的是ssh的有关入门知识.SSH是Secure Shell的简称. 课程视频地址:https://www.bilibili.com/vide ...

  10. 4399 Flash游戏专用浏览器, 无需安装Flash插件

    目前所有的主流浏览器都已经不再支持Flash了,即使有一些国内浏览器还支持flash,但只能安装国内特供版Flash Player. 但问题的关键在于,这个国内特供版跟 Adobe 海外发行的版本是两 ...