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. 图扑 AR 技术应用与管理:施工建造、机柜扫描、办公室导航解决方案

    随着科技的不断革新和创新,越来越多的行业开始迎来数字化时代的变革.建筑行业作为人类历史上最重要的产业之一,在数字化转型方面同样也在不断推进.图扑软件结合 AR 技术的应用,为建筑行业带来了更加便捷高效 ...

  2. 我用numpy实现了VIT,手写vision transformer, 可在树莓派上运行,在hugging face上训练模型保存参数成numpy格式,纯numpy实现

    先复制一点知乎上的内容 按照上面的流程图,一个ViT block可以分为以下几个步骤 (1) patch embedding:例如输入图片大小为224x224,将图片分为固定大小的patch,patc ...

  3. ES插入数据(JAVA代码)

    创建ES连接 // 初始化api客户端 public static RestHighLevelClient client = new RestHighLevelClient( RestClient.b ...

  4. Day14_Java_作业

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

  5. Java实现数组去重复的18种写法

    说明 数组(含List)去重复在日常工作中经常遇到,很多时候用到Set数据结构,但有时候我们需要针对数据进行干预,这时候就需要用其他的实现方式了.以下列出各种的去重方式,基本含括了所有情况. 源码下载 ...

  6. MAUI Blazor如何隐藏滚动条

    MAUI Blazor如何隐藏滚动条 Windows 在Windows上是最简单的,改css就可以了,把下面这段添加到app.css中 ::-webkit-scrollbar { display: n ...

  7. MAUI Blazor项目中如何添加一个返回服务,并支持安卓返回键

    前言 MAUI Blazor中,安卓项目的返回键体验很不好,只能如同浏览器一样返回上一页.但很多时候,我们想让他返回的上一页,不一定就是实际上的上一页.而且也想让返回键去支持一些事件,按下返回键触发, ...

  8. 记一次 zabbix item became not supported 问题处理

    现象 配置了一个自定义监控项,超过 5m nodata 就会告警,最近触发了两次.通过日志查看,有一对相隔10分钟的告警: 时间t0: item xxx became not support: Tim ...

  9. js的一些小问题集合

    1.等于号的应用 function reverse(){ var checkbox = document.getElementsByName("hobby"); for (let ...

  10. 给你推荐一款快速通过 typescript 生成 jsonschema 的包处理器

    theme: github fast-typescript-to-jsonschema Typescript 生成 jsonschema 数据插件 性能 案例 interface AAA { a: n ...