浅谈bss段的作用

本文详细解释了在Linux下的ELF二进制文件中,BSS段的作用,包括作为未初始化全局变量和静态变量的存储区域,以及如何在目标文件和可执行文件中布局。BSS节在文件中仅标记数据大小,实际数据在运行时动态分配。
摘要由CSDN通过智能技术生成

浅谈bss段的作用

在Linux下面,一个ELF二进制文件通过许多的节组织起来,例如:

$ readelf -S main
There are 36 section headers, starting at offset 0x43e0:

Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .interp           PROGBITS         0000000000000318  00000318
       000000000000001c  0000000000000000   A       0     0     1
  [ ...]
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  l (large), p (processor specific)

对于这些节,作用简单描述如下:

  1. init节:程序初始化入口代码,在main() 之前运行。
  2. bss节:BSS段属于静态内存分配。通常是指用来存放程序中未初始化的全局变量和未初始化的局部静态变量。未初始化的全局变量和未初始化的局部静态变量默认值是0。程序在运行时,才会给BSS节里面的变量分配内存空间。 在目标文件(*.o)和可执行文件中,BSS段只是为未初始化的全局变量和未初始化的局部静态变量预留位置而已,它并没有内容,所以它不占据空间。
  3. data节:数据节,通常是指用来存放程序中已初始化的全局变量和已初始化的静态变量的一块内存区域。数据段属于静态内存分配。
  4. text节:代码节通常是指用来存放程序执行代码的一块内存区域。。
  5. rodata节:存放的是只读数据,比如字符串常量,全局const变量 和 #define定义的常量。

这里我们主要看一下BSS节的用途。

1. 目标文件布局

对于一个程序,数据存放的节如下:

#include <stdio.h>

int g_iInitVar = 100;  //.data
int g_iUnInitVar;    //.bss

//.text
void fun(int data)
{
	printf("data is %d.\n", data);
}

//.text
int main(int argc, char* argv[])
{
	static int s_iInitVar = 200; //.data
	static int s_iUnInitVar;    //.bss

	fun(s_iInitVar + s_iUnInitVar);
	fun(g_iInitVar + g_iUnInitVar);

	return 0;
}

在ELF的布局如下:

$ objdump -t main | grep Var
0000000000004014 l     O .data	0000000000000004              s_iInitVar.2322
000000000000401c l     O .bss	0000000000000004              s_iUnInitVar.2323
0000000000004010 g     O .data	0000000000000004              g_iInitVar
0000000000004020 g     O .bss	0000000000000004              g_iUnInitVar

2. 关于BSS节

由于这些未初始化的全局变量和静态变量默认都是初始化为0的,所以为了减小ELF文件的大小,这些数据并不编译放在ELF文件中,在ELF文件中使用一个节专门用来标记这些数据(并不存放数据,只是标记数据大小,相当占位符)。

很多情况下,我们可能想要看一看BSS节里面的数据,如下:

$ objdump -s --section=.data main

main:     file format elf64-x86-64

Contents of section .data:
 4000 00000000 00000000 08400000 00000000  .........@......
 4010 64000000 c8000000                    d.......        

$ objdump -s --section=.bss main

main:     file format elf64-x86-64

objdump: section '.bss' mentioned in a -j option, but not found in any input file


$ objdump -s --section=.text main

main:     file format elf64-x86-64

Contents of section .text:
 1060 f30f1efa 31ed4989 d15e4889 e24883e4  ....1.I..^H..H..
 1070 f050544c 8d05b601 0000488d 0d3f0100  .PTL......H..?..
 1080 00488d3d e9000000 ff15522f 0000f490  .H.=......R/....
 1090 488d3d81 2f000048 8d057a2f 00004839  H.=./..H..z/..H9
 10a0 f8741548 8b052e2f 00004885 c07409ff  .t.H.../..H..t..
 10b0 e00f1f80 00000000 c30f1f80 00000000  ................
 10c0 488d3d51 2f000048 8d354a2f 00004829  H.=Q/..H.5J/..H)
 10d0 fe4889f0 48c1ee3f 48c1f803 4801c648  .H..H..?H...H..H
 10e0 d1fe7414 488b0505 2f000048 85c07408  ..t.H.../..H..t.
 10f0 ffe0660f 1f440000 c30f1f80 00000000  ..f..D..........
 1100 f30f1efa 803d0d2f 00000075 2b554883  .....=./...u+UH.
 1110 3de22e00 00004889 e5740c48 8b3de62e  =.....H..t.H.=..
 1120 0000e819 ffffffe8 64ffffff c605e52e  ........d.......
 1130 0000015d c30f1f00 c30f1f80 00000000  ...]............
 1140 f30f1efa e977ffff fff30f1e fa554889  .....w.......UH.
 1150 e54883ec 10897dfc 8b45fc89 c6488d3d  .H....}..E...H.=
 1160 a00e0000 b8000000 00e8e2fe ffff90c9  ................
 1170 c3f30f1e fa554889 e54883ec 10897dfc  .....UH..H....}.
 1180 488975f0 8b158a2e 00008b05 8c2e0000  H.u.............
 1190 01d089c7 e8b0ffff ff8b1571 2e00008b  ...........q....
 11a0 057b2e00 0001d089 c7e89bff ffffb800  .{..............
 11b0 000000c9 c3662e0f 1f840000 00000090  .....f..........
 11c0 f30f1efa 41574c8d 3deb2b00 00415649  ....AWL.=.+..AVI
 11d0 89d64155 4989f541 544189fc 55488d2d  ..AUI..ATA..UH.-
 11e0 dc2b0000 534c29fd 4883ec08 e80ffeff  .+..SL).H.......
 11f0 ff48c1fd 03741f31 db0f1f80 00000000  .H...t.1........
 1200 4c89f24c 89ee4489 e741ff14 df4883c3  L..L..D..A...H..
 1210 014839dd 75ea4883 c4085b5d 415c415d  .H9.u.H...[]A\A]
 1220 415e415f c366662e 0f1f8400 00000000  A^A_.ff.........
 1230 f30f1efa c3                          .....     

objdump: section ‘.bss’ mentioned in a -j option, but not found in any input file 从上面,我们可以发现ELF文件中并没有BSS节,但是BSS确实是存在的,如下:

$ objdump -t main | grep .bss
0000000000004018 l    d  .bss	0000000000000000              .bss
0000000000004018 l     O .bss	0000000000000001              completed.8060
000000000000401c l     O .bss	0000000000000004              s_iUnInitVar.2323
0000000000004020 g     O .bss	0000000000000004              g_iUnInitVar
0000000000004028 g       .bss	0000000000000000              _end
0000000000004018 g       .bss	0000000000000000              __bss_start

为什么会这样呢?因为BSS节,并没有真正的节数据,只有一个BSS的 section 头部,如下:

$ objdump -h --section=.bss main

main:     file format elf64-x86-64

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
 25 .bss          00000010  0000000000004018  0000000000004018  00003018  2**2
                  ALLOC

在应用程序被装载的时候,装载器只需要根据这个大小来给BSS的数据分配相应大小的空间即可,因此在ELF文件中并没有BSS节的数据。

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值