近日在调试uboot时,发现了一个现象,即在relocate_code前如果给未初始化或者初始化值为0的变量赋值的话,则在relocate_code后程序无法正常执行.经过学习,恶补如下知识

BSS段:BSS段(bss segment)通常是指用来存放程序中未初始化的全局变量的一块内存区域。BSS是英文Block Started by Symbol的简称。BSS段属于静态内存分配。

数据段:数据段(data segment)通常是指用来存放程序中已初始化的全局变量的一块内存区域。数据段属于静态内存分配。

代码段:代码段(code segment/text segment)通常是指用来存放程序执行代码的一块内存区域。这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于只读, 某些架构也允许代码段为可写,即允许修改程序。在代码段中,也有可能包含一些只读的常数变量,例如字符串常量等。

堆(heap):堆是用于存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减。当进程调用malloc等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张);当利用free等函数释放内存时,被释放的内存从堆中被剔除(堆被缩减)
栈(stack):栈又称堆栈, 是用户存放程序临时创建的局部变量,也就是说我们函数括弧“{}”中定义的变量(但不包括static声明的变量,static意味着在数据段中存放变量)。除此以外,在函数被调用时,其参数也会被压入发起调用的进程栈中,并且待到调用结束后,函数的返回值也会被存放回栈中。由于栈的先进先出特点,所以栈特别方便用来保存/恢复调用现场。从这个意义上讲,我们可以把堆栈看成一个寄存、交换临时数据的内存区。

在实际分析代码时发现,
未初始化或者初始化值为0的变量 都是被分配在bss段,包括static标记的,
只是如果是int aaaa;则在bss段中会明确标记出aaaa;
但是如果使用static,则在bss段中不会明确标记,但是会预留出位置

使用int aaaa;
给出u-boot.map相应内容如下:
.bss            0x00000000e00540cc       0x1c
                0x00000000e00540cc                __bss_start = .
 *(.bss)
 .bss           0x00000000e00540cc        0x0 arch/arm/cpu/armv7/start.o
 .bss           0x00000000e00540cc        0x0 arch/arm/cpu/armv7/comip/libcomip.o
 .bss           0x00000000e00540cc        0x0 arch/arm/cpu/armv7/libarmv7.o
 .bss           0x00000000e00540cc        0x8 arch/arm/lib/libarm.o
                0x00000000e00540d0                monitor_flash_len
 .bss           0x00000000e00540d4        0x0 common/libcommon.o
 .bss           0x00000000e00540d4        0x0 drivers/gpio/libgpio.o
 .bss           0x00000000e00540d4        0x0 drivers/i2c/libi2c.o
 .bss           0x00000000e00540d4        0x0 drivers/keypad/libkeypad.o
 .bss           0x00000000e00540d4        0x0 drivers/mfp/libmfp.o
 .bss           0x00000000e00540d4        0x0 drivers/misc/libmisc.o
 .bss           0x00000000e00540d4        0x8 drivers/mmc/libmmc.o
 .bss           0x00000000e00540dc        0x0 drivers/pmic/libpmic.o
 .bss           0x00000000e00540dc        0x0 drivers/serial/libserial.o
 .bss           0x00000000e00540dc        0x0 drivers/timer/libtimer.o
 .bss           0x00000000e00540dc        0x8 lib/libgeneric.o
                0x00000000e00540dc                ___strtok
 .bss           0x00000000e00540e4        0x4 board/leadcore/lc186x/liblc186x.o
                0x00000000e00540e4                aaaa
 .bss           0x00000000e00540e8        0x0 /home/lengyansong/android-kitkat-4.4/bootable/bootloader/uboot/arch/arm/lib/eabi_compat.o
 .bss           0x00000000e00540e8        0x0 /opt/prebuild/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/../lib/gcc/arm-eabi/4.6.x-google/libgcc.a(_udivsi3.o)
 .bss           0x00000000e00540e8        0x0 /opt/prebuild/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/../lib/gcc/arm-eabi/4.6.x-google/libgcc.a(_divsi3.o)
 .bss           0x00000000e00540e8        0x0 /opt/prebuild/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/../lib/gcc/arm-eabi/4.6.x-google/libgcc.a(_dvmd_tls.o)
 .bss           0x00000000e00540e8        0x0 /opt/prebuild/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/../lib/gcc/arm-eabi/4.6.x-google/libgcc.a(_lshrdi3.o)
 .bss           0x00000000e00540e8        0x0 /opt/prebuild/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/../lib/gcc/arm-eabi/4.6.x-google/libgcc.a(_ashldi3.o)
                0x00000000e00540e8                . = ALIGN (0x4)
                0x00000000e00540e8                __bss_end__ = .

将u-boot反汇编后给出
Disassembly of section .rel.dyn:
e00540cc <__rel_dyn_start>:
e00540cc: e0040020 and r0, r4, r0, lsr #32
e00540d0: 00000017 andeq r0, r0, r7, lsl r0
e00540d4: e0040024 and r0, r4, r4, lsr #32
e00540d8: 00000017 andeq r0, r0, r7, lsl r0
e00540dc: e0040028 and r0, r4, r8, lsr #32
e00540e0: 00000017 andeq r0, r0, r7, lsl r0
e00540e4: e004002c and r0, r4, ip, lsr #32
e00540e8: 00000017 andeq r0, r0, r7, lsl r0
e00540ec: e0040030 and r0, r4, r0, lsr r0

注意,aaaa的地址,是在e00540e4,包括bss段的首地址e00540cc是和__rel_dyn_start重叠的,也就是说,在代码中根本就没有给bss段分配空间!
进一步检查u-boot.lds,发现的确如此
.bss __rel_dyn_start (OVERLAY) : {
__bss_start = .;
*(.bss)
. = ALIGN(4);
__bss_end__ = .;
}

可以看到,配置文件中,两个部分的确是放在一起了,可能设计者是为了节省boot ram的空间吧,所以没有给bss段分配空间,
而是在relocate_code时才给bss段分配空间并初始化为0!
start.S中relocate_code后面初始化bss段部分
clear_bss:
#ifdef CONFIG_SPL_BUILD
/* No relocation for SPL */
ldr r0, =__bss_start
ldr r1, =__bss_end__
#else
ldr r0, _bss_start_ofs
ldr r1, _bss_end_ofs
mov r4, r6 /* reloc addr */
add r0, r0, r4
add r1, r1, r4
#endif
mov r2, #0x00000000 /* clear    */

clbss_l:str r2, [r0] /* clear loop...    */
add r0, r0, #4
cmp r0, r1
bne clbss_l

对应的反汇编代码如下
e0040040 <_TEXT_BASE>:
e0040040: e0040000 and r0, r4, r0

e0040044 <_bss_start_ofs>:
e0040044: 000140cc andeq r4, r1, ip, asr #1

e0040048 <_image_copy_end_ofs>:
e0040048: 000140cc andeq r4, r1, ip, asr #1

e004004c <_bss_end_ofs>:
e004004c: 000140e8 andeq r4, r1, r8, ror #1

e0040050 <_end_ofs>:
e0040050: 00014cfc strdeq r4, [r1], -ip

e0040154 :
e0040154: e51f0118 ldr r0, [pc, #-280] ; e0040044 <_end+0xfffeb348>
e0040158: e51f1114 ldr r1, [pc, #-276] ; e004004c <_end+0xfffeb350>
e004015c: e1a04006 mov r4, r6
e0040160: e0800004 add r0, r0, r4
e0040164: e0811004 add r1, r1, r4
e0040168: e3a02000 mov r2, #0

e004016c :
e004016c: e5802000 str r2, [r0]
e0040170: e2800004 add r0, r0, #4
e0040174: e1500001 cmp r0, r1
e0040178: 1afffffb bne e004016c
这个也和实际log一致
void print_info(void)
{
extern ulong _start;
printf("_bss_start_ofs:%lx, _bss_end_ofs:%lx, length:%lx\n",_bss_start_ofs,_bss_end_ofs,_bss_end_ofs-_bss_start_ofs);
printf("start:%lx, _TEXT_BASE:%lx, aaaa:%p, aaaa-start=%lx,aaaa=%x\n",_start, _TEXT_BASE, &aaaa, &aaaa-_start,aaaa);
}
分别在relocate_code前后调用,输出log如下
[  149704]{    3328}_bss_start_ofs:140cc, _bss_end_ofs:140e8, length:1c
[  156793]{    7089}start:ea000014, _TEXT_BASE:e0040000, aaaa:e00540e4, aaaa-start=38054094,aaaa=e004002c

[  185762]{    2597}addr_sp:0x3ffb0cb0, id:3ffb0cc0, addr:0x3ffdb000
relocate_code...
[  196513]{   13348}_bss_start_ofs:140cc, _bss_end_ofs:140e8, length:1c
[  203449]{    6936}start:ea000014, _TEXT_BASE:e0040000, aaaa:3ffef0e4, aaaa-start=97fef094,aaaa=0

删除上述黑体部分配置后变成如下形式:
.bss   : {
__bss_start = .;
*(.bss)
. = ALIGN(4);
__bss_end__ = .;
}
可以看到反汇编后的bss已经单独分配了地址,和__rel_dyn_start分开了
e0040040 <_TEXT_BASE>:
e0040040: e0040000 and r0, r4, r0

e0040044 <_bss_start_ofs>:
e0040044: 00014cfc strdeq r4, [r1], -ip

e0040048 <_image_copy_end_ofs>:
e0040048: 000140cc andeq r4, r1, ip, asr #1

e004004c <_bss_end_ofs>:
e004004c: 00014d18 andeq r4, r1, r8, lsl sp

e0040050 <_end_ofs>:
e0040050: 00014cfc strdeq r4, [r1], -ip
Disassembly of section .rel.dyn:

e00540cc <__rel_dyn_start>:
e00540cc: e0040020 and r0, r4, r0, lsr #32
e00540d0: 00000017 andeq r0, r0, r7, lsl r0
...
...
e0054c30: 00000017 andeq r0, r0, r7, lsl r0
e0054c34: e005307c and r3, r5, ip, ror r0
e0054c38: 00000017 andeq r0, r0, r7, lsl r0

Disassembly of section .bss:

e0054cfc <__bss_start>:
e0054cfc: 00000000 andeq r0, r0, r0

e0054d00 :
e0054d00: 00000000 andeq r0, r0, r0

e0054d04 :
...

e0054d0c <___strtok>:
e0054d0c: 00000000 andeq r0, r0, r0

e0054d10 :
e0054d10: 00000000 andeq r0, r0, r0

e0054d14 :
e0054d14: 00000000 andeq r0, r0, r0

在relocat之前调用
print_info();
aaaa=1;
print_info();
则输出log如下:
[  149678]{    3328}_bss_start_ofs:14d1c, _bss_end_ofs:14d38, length:1c
[  156767]{    7089}start:ea000014, _TEXT_BASE:e0040000, aaaa:e0054d34, aaaa-start=38054ce4,aaaa=5ed75762  //这里bss还没有初始化过
[  167158]{   10391}_bss_start_ofs:14d1c, _bss_end_ofs:14d38, length:1c
[  174247]{    7089}start:ea000014, _TEXT_BASE:e0040000, aaaa:e0054d34, aaaa-start=38054ce4,aaaa=1   //这里赋值为1
[  202533]{    2597}addr_sp:0x3ffb0cb0, id:3ffb0cc0, addr:0x3ffdb000
relocate_code...
[  213281]{   13345}_bss_start_ofs:14d1c, _bss_end_ofs:14d38, length:1c
[  220218]{    6937}start:ea000014, _TEXT_BASE:e0040000, aaaa:3ffefd34, aaaa-start=97fefce4,aaaa=0  // 这里在relocate时被清0了.

u-boot中bss段的使用的更多相关文章

  1. 程序运行中(BSS段、数据段、代码段、堆栈)

    程序运行中(BSS段.数据段.代码段.堆栈) BSS段:(bss segment)通常是指用来存放程序中未初始化的全局变量的一块内存区域.BSS是英文Block Started by Symbol的简 ...

  2. 内存模型 Memory model 内存分布及程序运行中(BSS段、数据段、代码段、堆栈

    C语言中内存分布及程序运行中(BSS段.数据段.代码段.堆栈) - 秦宝艳的个人页面 - 开源中国 https://my.oschina.net/pollybl1255/blog/140323 Mem ...

  3. C语言中内存分布及程序运行中(BSS段、数据段、代码段、堆栈)

      BSS段:(bss segment)通常是指用来存放程序中未初始化的全局变量的一块内存区域.BSS是英文Block Started by Symbol的简称.BSS段属于静态内存分配. 数据段 : ...

  4. linux代码段,数据段,BSS段, 堆,栈(二)

    //main.cpp int a = 0; 全局初始化区  char *p1; 全局未初始化区 main() { int b; 栈 char s[] = "abc"; 栈 char ...

  5. 【转】linux代码段,数据段,BSS段, 堆,栈

    转载自 http://blog.csdn.net/wudebao5220150/article/details/12947445  linux代码段,数据段,BSS段, 堆,栈 网上摘抄了一些,自己组 ...

  6. 数据段、代码段、堆栈段、BSS段

    在linux中,进程在内存中一般会分为5个段,用来存放从磁盘载入的程序代码,等. 这五个段分别是: BSS段: 通常用来存放程序中未初始化的全局变量的一块内存区域.属于静态内存分配. 问题:全局变量不 ...

  7. stm32中.bss和.data段是在哪里初始化的

    https://segmentfault.com/q/1010000004829859/a-1020000004850311 Q: STM32的启动文件startup_stm32f10x_hd.s中的 ...

  8. Linux中的段管理,bss段,data段,

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

  9. 代码中函数、变量、常量 / bss段、data段、text段 /sct文件、.map文件的关系[实例分析arm代码(mdk)]

    函数代码://demo.c #include<stdio.h> #include<stdlib.h> , global2 = , global3 = ; void functi ...

随机推荐

  1. 内网每一台电脑的外网ip是一样吗

    内网每一台电脑上网的IP地址是一样的,因为公网地址的稀缺性,所以内部上网是通过映射或者说叫端口复用将内部私有地址转换为公有地址进行上网的. 公有地址就是网关设备出口的地址,也可以说是路由器的出口地址, ...

  2. OpenStack 2018 年终盘点

    目录 文章目录 目录 前言 OpenStack 一年来的成长 Nova Cinder Neutron Ironic Cyborg Octavia Kolla Magnum Zun Kuryr 从 Op ...

  3. Oracle 笔记(二)

    Oracle的sql语言: Sql全称:struct query language 结构化查询语言 五大类: DDL:数据定义语言  create  alter  drop DQL:数据查询语言sel ...

  4. 利用jquery的淡入淡出函数(fadeIn和fadeOut)--实现轮播

    首先说下,我在网上找的例子全是用的UL 实现,其实大可不必,只要是能包含img标签的HTML标签都可以做轮播效果.利用jquery的淡入淡出函数(fadeIn和fadeOut).废话也不多说,边上代码 ...

  5. cocos2dx基础篇(4) 标签CCLabel

    [本节内容] cocos2dx三种文字字体的显示:CCLabelTTF(一般字体).CCLabelAtlas(自定义字体).CCLabelBMFont(自定义字体) CCLabelTTF CCLabe ...

  6. AspNet Core Swagger4.0 生成请求model描述

    今天给大家分享 swagger 俩个冷门的小技巧 获取控制器描述 将 IncludeXmlComments 方法第二个参数设置为 true 即可 public static void IncludeX ...

  7. WM_RBUTTONUP消息收不到问题

    今天遇到了个问题,对某窗口进行右键弹出菜单,发现没弹出来,然后打断点发现WM_RBUTTONUP消息收不到 捣鼓了下,找到了原因. 在Duilib中,当设置了Caption后,Duilib处理鼠标点击 ...

  8. 从零开始学习GDI+ (三) 画笔与画刷

  9. [Python3] 027 常用模块 time

    目录 time 1. 时间戳 2. UTC 时间 3. 夏令时 4. 时间元组 5. 举例 5.1 例子1 例子2 例子3 例子4 例子5 例子6 例子7 time 1. 时间戳 一个时间表示,根据不 ...

  10. HDU 1257 最少拦截系统 最长递增子序列

    HDU 1257 最少拦截系统 最长递增子序列 题意 这个题的意思是说给你\(n\)个数,让你找到他最长的并且递增的子序列\((LIS)\).这里和最长公共子序列一样\((LCS)\)一样,子序列只要 ...