u-boot中bss段的使用
近日在调试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段的使用的更多相关文章
- 程序运行中(BSS段、数据段、代码段、堆栈)
程序运行中(BSS段.数据段.代码段.堆栈) BSS段:(bss segment)通常是指用来存放程序中未初始化的全局变量的一块内存区域.BSS是英文Block Started by Symbol的简 ...
- 内存模型 Memory model 内存分布及程序运行中(BSS段、数据段、代码段、堆栈
C语言中内存分布及程序运行中(BSS段.数据段.代码段.堆栈) - 秦宝艳的个人页面 - 开源中国 https://my.oschina.net/pollybl1255/blog/140323 Mem ...
- C语言中内存分布及程序运行中(BSS段、数据段、代码段、堆栈)
BSS段:(bss segment)通常是指用来存放程序中未初始化的全局变量的一块内存区域.BSS是英文Block Started by Symbol的简称.BSS段属于静态内存分配. 数据段 : ...
- linux代码段,数据段,BSS段, 堆,栈(二)
//main.cpp int a = 0; 全局初始化区 char *p1; 全局未初始化区 main() { int b; 栈 char s[] = "abc"; 栈 char ...
- 【转】linux代码段,数据段,BSS段, 堆,栈
转载自 http://blog.csdn.net/wudebao5220150/article/details/12947445 linux代码段,数据段,BSS段, 堆,栈 网上摘抄了一些,自己组 ...
- 数据段、代码段、堆栈段、BSS段
在linux中,进程在内存中一般会分为5个段,用来存放从磁盘载入的程序代码,等. 这五个段分别是: BSS段: 通常用来存放程序中未初始化的全局变量的一块内存区域.属于静态内存分配. 问题:全局变量不 ...
- stm32中.bss和.data段是在哪里初始化的
https://segmentfault.com/q/1010000004829859/a-1020000004850311 Q: STM32的启动文件startup_stm32f10x_hd.s中的 ...
- Linux中的段管理,bss段,data段,
Linux 的段管理, BSS段(bss segment)通常是指用来存放程序中未初始化的全局变量的一块内存区域.BSS是英文Block Started by Symbol的简称.BSS段属于静态内存 ...
- 代码中函数、变量、常量 / bss段、data段、text段 /sct文件、.map文件的关系[实例分析arm代码(mdk)]
函数代码://demo.c #include<stdio.h> #include<stdlib.h> , global2 = , global3 = ; void functi ...
随机推荐
- 【flask】flask项目配置 app.config
[理论] 在很多情况下,你需要设置程序的某些行为,这时你就需要使用配置变量.在Flask中,配置变量就是一些大写形式的Python变量, 你也可以称之为配置参数或配置键.使用统一的配置变量可以避免在程 ...
- [SPSS]学习笔记--数据分布形状描述
以下内容摘自:公众号- SPSS生活统计学 保存做复习之用. 峰度(Kurtosis) 峰度是描述总体(样本)中所有取值分布形态陡缓程度的统计量.通过计算可以得到峰度系数,峰度系数与分布形态的关系是: ...
- 安装 Genymotion及其破解版 测试能用的方法
第一,照下面的教程 先安装 https://blog.csdn.net/sxk874890728/article/details/82721746 安装 Genymotion及其破解版 2018年0 ...
- Spring容器启动源码分析
1. 前言 最近搭建的工程都是基于SpringBoot,简化配置的感觉真爽.但有个以前的项目还是用SpringMvc写的,看到满满的配置xml文件,却有一种想去深入了解的冲动.折腾了好几天,决心去写这 ...
- Altera DDR2 IP核学习总结2-----------DDR2 IP核的生成
打开IP核工具,然后选择Verilog HDL选项,填写路径,写入文件名DDR2_IP.V,点击next PLL reference clock frequency填入板子晶振的频率50MHZ,这里设 ...
- #Java学习之路——基础阶段二(第十二篇)
我的学习阶段是跟着CZBK黑马的双源课程,学习目标以及博客是为了审查自己的学习情况,毕竟看一遍,敲一遍,和自己归纳总结一遍有着很大的区别,在此期间我会参杂Java疯狂讲义(第四版)里面的内容. 前言: ...
- selenium.common.exceptions.WebDriverException: Message: ‘geckodriver’ executable needs to be in PATH
问题,找不到’geckodriver’ 的环境path,解决方案 下载geckodriver.exe 放到Firefox的安装目录下,如:(D:\火狐\Mozilla Firefox): 将火狐安装目 ...
- 一、Kubernetes_V1.10集群部署-master-生成证书
一.证书生成 1.下载cfssl mkdir -p /etc/kubernetes/sslwget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 wget ...
- python中导入模块的注意点
1.import 和 from import 的区别 import module导入模块:语句执行完后会创建一个新的命名空间,在该命名空间中执行相应的函数.执行时,需要的变量.函数和类名前需要加 ...
- Leetcode 35.搜索插入位置 By Python
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引.如果目标值不存在于数组中,返回它将会被按顺序插入的位置. 你可以假设数组中无重复元素. 示例 1: 输入: [1,3,5,6], 5 输 ...