zoukankan      html  css  js  c++  java
  • 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 ",_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 ",_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了.

  • 相关阅读:
    电赛菜鸟营培训(五)——OLED屏幕的使用
    网站构建学习笔记(0)——基本概念了解及资源学习(copy自w3school)
    AppInventor学习笔记(五)——瓢虫快跑应用学习
    电赛菜鸟营培训(四)——STM32F103CB之ADC转换
    电赛菜鸟营培训(三)——STM32F103CB之串口通信
    [I2C]pca9555(i2c-gpio扩展)应用层测试代码
    [shell]简单的shell提示和参数脚本
    [Busybox]Busybox制作文件系统
    [boostrap]debian下为arm创建debian和emdebian文件系统
    [debootstrap]制作基于arm平台的debian文件系统
  • 原文地址:https://www.cnblogs.com/idyllcheung/p/11956552.html
Copyright © 2011-2022 走看看