代码自动初始化

代码自动初始化

说明:本文针对嵌入式开发编写,其他开发可作为参考

创作不易,转载请注明出处,您的点赞、关注+收藏是对开源创作的莫大支持,谢谢!

1. 概述

初始化代码如何做到自动化调用?

在我们开发程序过程中,往往需要对 bsp 部分进行外设配置,以及一些模块、参数进行初始化,比较常见的作法便是:

  • 将各个部分的初始化代码分别封装成一个单独的函数,然后再main函数刚开始的地方进行调用已实现初始化;

这种方法比较简单、常用,亦能解决问题,但是此类写法在一些方面仍然存在不足

  • 所有初始化均需要在main函数内调用,不能做到彻底解耦
  • 框架设计不友好,部分非业务部分初始化,如软件框架类的初始化,往往不希望还需要业务在main函数内调用初始化
  • 等…

那是否有比较完美的方式来解决此问题呢?

答案是肯定的,本文将向大家介绍一种自动初始化的实现方式,注意,此方案在不同的平台,由于链接器使用的链接脚本可能不一致,容易出现问题,需要大家重点注意,细节在下文中将详细介绍。

2. 方案分析

为了更好的阐述此方案的实现方式,接下来将通过给大家展示一个demo程序,之后对此demo进行细致讲解的方式来阐述此方案的实现,以下是此demo程序:

#include <stdint.h>

int a = 0;
int b = 0;
int c = 0;

typedef void (*init_func)(void);

//#define SECTION(x) __attribute__((used, section(x)))
//#define INIT_FUNC(fn, level) const func_test init_##fn SECTION(".duan."#level) = fn
#define INIT_PORT(fn, level)    const init_func init_##fn __attribute__((used, section(".init."level))) = fn

void start(void)
{
    
    
    a = 1;
    return;
}
INIT_PORT(start, "1");

void end(void)
{
    
    
    a = 2;
    return;
}
INIT_PORT(end, "3");

void test1(void)
{
    
    
    b = 1;
}
INIT_PORT(test1, "1");

void test2(void)
{
    
    
    b = 2;
}
INIT_PORT(test2, "2");

void system_init(void)
{
    
    
    const init_func *func_p;
    for (func_p = &init_start; func_p < &init_end; func_p ++) {
    
    
        (*func_p)();
    }
}

关于宏:#define INIT_PORT(fn, level) const init_func init_##fn __attribute__((used, section(".init."level))) = fn
代码分析如下:

  • 首先定义一个函数指针typedef void (*init_func)(void); ,所有初始化函数此指针类型
  • 之后定义宏#define INIT_PORT(fn, level) 作为一个接口,后续初始化函数可以通过此接口加入自动初始化列表内
    • const init_func init_##fn ,其中## 为连接符,假设参数fntest,则init_##fninit_testinit_func 为指针类型
    • const init_func init_##fnconst int *p 是同一概念,只不过指针类型不一样
  • const init_func init_##fn 定义了一个init_func 类型的指针变量,此指针还没有赋值,因此将参数fn赋值给此变量,宏定义可以简化为#define INIT_PORT(fn, level) const init_func init_##fn = fn(__attribute__先忽略)
  • __attribute__((used, section(".init."level))) 这也是一个关键字进行修饰用的,可以拆解为__attribute__((used))__attribute__((section(".init."level)))
    • __attribute__((used)) 用来告诉编译器,此函数如果没有被调用,也不要被优化
    • __attribute__((section(".init."level))) 用来将修饰的内容放入指定的段".init."level 中(编译器在你编译的时候帮你去完成的),注意这里level 为宏的第二个传入参数,传入进来的时候他是一个字符串,所用不用加# 进行拼接,两个字符串会自动拼接
    • 关于attribute的其他相关知识,可以参考:attribute((section(x))) 使用详解attribute((section(x))) 使用详解

综上分析,因此宏#define INIT_PORT(fn, level) const init_func init_##fn __attribute__((used, section(".init."level))) = fn ,其实就是定义了一个init_func类型的函数指针,并将此函数指针通过__attribute__((section(".init."level))) 指定存放到特定的段内。

Demo程序中定义了四个函数:

  • void start(void)
  • void end(void)
  • void test1(void)
  • void test2(void)

并分别通过宏INIT_PORT(fn, level) 添加到自动初始化段内

  • INIT_PORT(start, "1");
  • INIT_PORT(end, "3");
  • INIT_PORT(test1, "1");
  • INIT_PORT(test2, "2");

这里大家注意观察下,有几个注意点:

  1. level 参数是一个字符串,而不是数字
  2. 用户的自定义初始化函数test1test2level需要在startendlevel 值中间,这是由于编译器采用__attribute__((section(".init."level))) 指定放入到指定段的时候,还会针对其进行排序,keil默认采用根据名称的方式排序,因此需要放置在用户自定义的,放置在用 startend 中间,方便后续遍历 startend 中间部分进行完整初始化

说明下,顺带发现了一个可能出现的bugINIT_PORT(test1, "1");level建议不要设置为1,如果这么设置,在map文件里面排序是按照".init"level的值进行排序的,那么test1和start的顺序不能百分百确定,虽然这里侥幸没有出问题,但是建议大家不要这么操作

最后看到 system_init 初始化函数

void system_init(void)
{
    
    
    const init_func *func_p;
    for (func_p = &init_start; func_p < &init_end; func_p ++) {
    
    
        (*func_p)();
    }
}

此函数实现的便是通过 for 循环,遍历 startend 中间的段,并进行调用进行初始化

这样用户初始化函数只需要调用宏 INIT_PORT(fn, level) 即可完成自动初始化,当然 system_init 函数肯定是需要在main里面调用的

此方案的好处是将各模块的初始化顺利实现了解耦,不用每个初始化都去动main函数了,此外系统框架类的初始化也可以做到不让业务感知!

针对不同类型的初始化,可以在此基础上稍微改动点,将start和end之间距离拉大点,一部分做外设初始化,一部分做参数初始化,直接挂代码吧

INIT_PORT(start, "1");
INIT_PORT(end, "4");

再对外开放接口宏

#define INIT_BSP_PORT(func)		INIT_PORT(func, "2");
#define INIT_DATA_PORT(func)	INIT_PORT(func, "3");

用户通过调用 BSP_INIT_PORTDATA_INIT_PORT 进行注册

3. 检查MAP文件

在上述方法中,我们使用 __attribute__((section(".init."level))) 将数据存入指定的段内,那么是否成功了呢,以及排序方式是否符合我们的预期呢?接下来我们需要通过检查map文件进行确认

3.1 keil / MDK 环境检查

keil/mdk编译完程序之后,双击工程栏处的工程,可以查看map文件,还不知道的可以网上搜下

以下是上述demo的map文件中关键字段,我们可以看到我们需要的数据存放在正确的段内,并且排序也是正常的,注意一定要检查排序和字段是否完整!

在这里插入图片描述
大家也可以尝试下修改,把 __attribute__((used, section(".init."level))) 修改为 __attribute__(( section(".init."level))) 去掉used,看看有什么不一样,条件允许的话,还可以单步调试下,看下程序怎么跑的,加深下理解

3.2 gcc环境检查

auto_init.c 源文件:

#include <stdio.h>

typedef void (*func_test)(void);

//#define SECTION(x) __attribute__((used, section(x)))
//#define INIT_FUNC(fn, level) const func_test test_##fn SECTION(".duan."#level) = fn
//#define INIT_FUNC(fn, level) const func_test test_##fn __attribute__((used, section(".duan."level))) = fn
#define INIT_FUNC(fn, level) __attribute__((used)) const func_test test_##fn __attribute__((section(".duan."level))) = fn

#define STRING(level) ("string"#level)

//__attribute__((used, section(".duan")))void start(void)
void start(void)
{
    
    
    printf("start\n");
    return;
}
INIT_FUNC(start, "1");

void end(void)
{
    
    
    return;
}
INIT_FUNC(end, "6");

void test1(void)
{
    
    
    printf("test1");
}
INIT_FUNC(test1, "1");

void test2(void)
{
    
    
    printf("test2");
}
INIT_FUNC(test2, "2");

int main()
{
    
    
    func_test a = NULL;
    a = start;
    a();
    printf("Hello world\n");
    return 0;
}
  • 生成map文件命令:gcc auto_init.c -Wl,-Map=auto_init.map
  • 查看链接文件命令:gcc auto_init.c -Wl,--verbose

生成的Map文件如下:

Archive member included to satisfy reference by file (symbol)

/usr/lib/x86_64-linux-gnu/libc_nonshared.a(elf-init.oS)
                              /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o (__libc_csu_init)

Merging program properties


As-needed library included to satisfy reference by file (symbol)

libc.so.6                     /tmp/ccDz4GV7.o (puts@@GLIBC_2.2.5)

Discarded input sections

 .note.GNU-stack
                0x0000000000000000        0x0 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o
 .note.gnu.property
                0x0000000000000000       0x20 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crti.o
 .note.GNU-stack
                0x0000000000000000        0x0 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crti.o
 .note.GNU-stack
                0x0000000000000000        0x0 /usr/lib/gcc/x86_64-linux-gnu/9/crtbeginS.o
 .note.gnu.property
                0x0000000000000000       0x20 /usr/lib/gcc/x86_64-linux-gnu/9/crtbeginS.o
 .note.GNU-stack
                0x0000000000000000        0x0 /tmp/ccDz4GV7.o
 .note.gnu.property
                0x0000000000000000       0x20 /tmp/ccDz4GV7.o
 .note.GNU-stack
                0x0000000000000000        0x0 /usr/lib/x86_64-linux-gnu/libc_nonshared.a(elf-init.oS)
 .note.gnu.property
                0x0000000000000000       0x20 /usr/lib/x86_64-linux-gnu/libc_nonshared.a(elf-init.oS)
 .note.GNU-stack
                0x0000000000000000        0x0 /usr/lib/gcc/x86_64-linux-gnu/9/crtendS.o
 .note.gnu.property
                0x0000000000000000       0x20 /usr/lib/gcc/x86_64-linux-gnu/9/crtendS.o
 .note.gnu.property
                0x0000000000000000       0x20 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crtn.o
 .note.GNU-stack
                0x0000000000000000        0x0 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crtn.o

Memory Configuration

Name             Origin             Length             Attributes
*default*        0x0000000000000000 0xffffffffffffffff

Linker script and memory map

LOAD /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o
LOAD /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crti.o
LOAD /usr/lib/gcc/x86_64-linux-gnu/9/crtbeginS.o
LOAD /tmp/ccDz4GV7.o
LOAD /usr/lib/gcc/x86_64-linux-gnu/9/libgcc.a
LOAD /usr/lib/gcc/x86_64-linux-gnu/9/libgcc_s.so
START GROUP
LOAD /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libgcc_s.so.1
LOAD /usr/lib/gcc/x86_64-linux-gnu/9/libgcc.a
END GROUP
LOAD /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libc.so
START GROUP
LOAD /lib/x86_64-linux-gnu/libc.so.6
LOAD /usr/lib/x86_64-linux-gnu/libc_nonshared.a
LOAD /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
END GROUP
LOAD /usr/lib/gcc/x86_64-linux-gnu/9/libgcc.a
LOAD /usr/lib/gcc/x86_64-linux-gnu/9/libgcc_s.so
START GROUP
LOAD /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libgcc_s.so.1
LOAD /usr/lib/gcc/x86_64-linux-gnu/9/libgcc.a
END GROUP
LOAD /usr/lib/gcc/x86_64-linux-gnu/9/crtendS.o
LOAD /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crtn.o
                [!provide]                        PROVIDE (__executable_start = SEGMENT_START ("text-segment", 0x0))
                0x0000000000000318                . = (SEGMENT_START ("text-segment", 0x0) + SIZEOF_HEADERS)

.interp         0x0000000000000318       0x1c
 *(.interp)
 .interp        0x0000000000000318       0x1c /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o

.note.gnu.property
                0x0000000000000338       0x20
 .note.gnu.property
                0x0000000000000338       0x20 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o

.note.gnu.build-id
                0x0000000000000358       0x24
 *(.note.gnu.build-id)
 .note.gnu.build-id
                0x0000000000000358       0x24 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o

.note.ABI-tag   0x000000000000037c       0x20
 .note.ABI-tag  0x000000000000037c       0x20 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o

.hash
 *(.hash)

.gnu.hash       0x00000000000003a0       0x24
 *(.gnu.hash)
 .gnu.hash      0x00000000000003a0       0x24 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o

.dynsym         0x00000000000003c8       0xc0
 *(.dynsym)
 .dynsym        0x00000000000003c8       0xc0 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o

.dynstr         0x0000000000000488       0x89
 *(.dynstr)
 .dynstr        0x0000000000000488       0x89 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o

.gnu.version    0x0000000000000512       0x10
 *(.gnu.version)
 .gnu.version   0x0000000000000512       0x10 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o

.gnu.version_d  0x0000000000000528        0x0
 *(.gnu.version_d)
 .gnu.version_d
                0x0000000000000528        0x0 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o

.gnu.version_r  0x0000000000000528       0x20
 *(.gnu.version_r)
 .gnu.version_r
                0x0000000000000528       0x20 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o

.rela.dyn       0x0000000000000548      0x120
 *(.rela.init)
 *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
 .rela.text     0x0000000000000548        0x0 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o
 *(.rela.fini)
 *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
 *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)
 .rela.data.rel.ro
                0x0000000000000548        0x0 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o
 .rela.data.rel.local
                0x0000000000000548       0x18 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o
 *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)
 *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)
 *(.rela.ctors)
 *(.rela.dtors)
 *(.rela.got)
 .rela.got      0x0000000000000560       0x78 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o
 *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
 .rela.bss      0x00000000000005d8        0x0 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o
 *(.rela.ldata .rela.ldata.* .rela.gnu.linkonce.l.*)
 *(.rela.lbss .rela.lbss.* .rela.gnu.linkonce.lb.*)
 *(.rela.lrodata .rela.lrodata.* .rela.gnu.linkonce.lr.*)
 *(.rela.ifunc)
 .rela.ifunc    0x00000000000005d8        0x0 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o
 .rela.fini_array
                0x00000000000005d8       0x18 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o
 .rela.init_array
                0x00000000000005f0       0x18 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o
 .rela.duan.1   0x0000000000000608       0x30 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o
 .rela.duan.6   0x0000000000000638       0x18 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o
 .rela.duan.2   0x0000000000000650       0x18 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o

.rela.plt       0x0000000000000668       0x30
 *(.rela.plt)
 .rela.plt      0x0000000000000668       0x30 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o
 *(.rela.iplt)
                0x0000000000001000                . = ALIGN (CONSTANT (MAXPAGESIZE))

.init           0x0000000000001000       0x1b
 *(SORT_NONE(.init))
 .init          0x0000000000001000       0x16 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crti.o
                0x0000000000001000                _init
 .init          0x0000000000001016        0x5 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crtn.o

.plt            0x0000000000001020       0x30
 *(.plt)
 .plt           0x0000000000001020       0x30 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o
 *(.iplt)

.plt.got        0x0000000000001050       0x10
 *(.plt.got)
 .plt.got       0x0000000000001050       0x10 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o
                0x0000000000001050                __cxa_finalize@@GLIBC_2.2.5

.plt.sec        0x0000000000001060       0x20
 *(.plt.sec)
 .plt.sec       0x0000000000001060       0x20 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o
                0x0000000000001060                puts@@GLIBC_2.2.5
                0x0000000000001070                printf@@GLIBC_2.2.5

.text           0x0000000000001080      0x1f5
 *(.text.unlikely .text.*_unlikely .text.unlikely.*)
 *(.text.exit .text.exit.*)
 *(.text.startup .text.startup.*)
 *(.text.hot .text.hot.*)
 *(SORT_BY_NAME(.text.sorted.*))
 *(.text .stub .text.* .gnu.linkonce.t.*)
 .text          0x0000000000001080       0x2f /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o
                0x0000000000001080                _start
 .text          0x00000000000010af        0x0 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crti.o
 *fill*         0x00000000000010af        0x1 
 .text          0x00000000000010b0       0xb9 /usr/lib/gcc/x86_64-linux-gnu/9/crtbeginS.o
 .text          0x0000000000001169       0x92 /tmp/ccDz4GV7.o
                0x0000000000001169                start
                0x0000000000001180                end
                0x000000000000118b                test1
                0x00000000000011a7                test2
                0x00000000000011c3                main
 *fill*         0x00000000000011fb        0x5 
 .text          0x0000000000001200       0x75 /usr/lib/x86_64-linux-gnu/libc_nonshared.a(elf-init.oS)
                0x0000000000001200                __libc_csu_init
                0x0000000000001270                __libc_csu_fini
 .text          0x0000000000001275        0x0 /usr/lib/gcc/x86_64-linux-gnu/9/crtendS.o
 .text          0x0000000000001275        0x0 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crtn.o
 *(.gnu.warning)

.fini           0x0000000000001278        0xd
 *(SORT_NONE(.fini))
 .fini          0x0000000000001278        0x8 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crti.o
                0x0000000000001278                _fini
 .fini          0x0000000000001280        0x5 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crtn.o
                [!provide]                        PROVIDE (__etext = .)
                [!provide]                        PROVIDE (_etext = .)
                [!provide]                        PROVIDE (etext = .)
                0x0000000000002000                . = ALIGN (CONSTANT (MAXPAGESIZE))
                0x0000000000002000                . = SEGMENT_START ("rodata-segment", (ALIGN (CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 0x1))))

.rodata         0x0000000000002000       0x22
 *(.rodata .rodata.* .gnu.linkonce.r.*)
 .rodata.cst4   0x0000000000002000        0x4 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o
                0x0000000000002000                _IO_stdin_used
 .rodata        0x0000000000002004       0x1e /tmp/ccDz4GV7.o

.rodata1
 *(.rodata1)

.eh_frame_hdr   0x0000000000002024       0x64
 *(.eh_frame_hdr)
 .eh_frame_hdr  0x0000000000002024       0x64 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o
                0x0000000000002024                __GNU_EH_FRAME_HDR
 *(.eh_frame_entry .eh_frame_entry.*)

.eh_frame       0x0000000000002088      0x188
 *(.eh_frame)
 .eh_frame      0x0000000000002088       0x30 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o
                                         0x2c (size before relaxing)
 *fill*         0x00000000000020b8        0x0 
 .eh_frame      0x00000000000020b8       0x28 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o
                                         0x40 (size before relaxing)
 .eh_frame      0x00000000000020e0       0x18 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o
                                         0x30 (size before relaxing)
 .eh_frame      0x00000000000020f8       0x18 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o
                                         0x30 (size before relaxing)
 .eh_frame      0x0000000000002110       0xa0 /tmp/ccDz4GV7.o
                                         0xb8 (size before relaxing)
 .eh_frame      0x00000000000021b0       0x5c /usr/lib/x86_64-linux-gnu/libc_nonshared.a(elf-init.oS)
                                         0x78 (size before relaxing)
 .eh_frame      0x000000000000220c        0x4 /usr/lib/gcc/x86_64-linux-gnu/9/crtendS.o
 *(.eh_frame.*)

.gcc_except_table
 *(.gcc_except_table .gcc_except_table.*)

.gnu_extab
 *(.gnu_extab*)

.exception_ranges
 *(.exception_ranges*)
                0x0000000000003db0                . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE))

.eh_frame
 *(.eh_frame)
 *(.eh_frame.*)

.gnu_extab
 *(.gnu_extab)

.gcc_except_table
 *(.gcc_except_table .gcc_except_table.*)

.exception_ranges
 *(.exception_ranges*)

.tdata          0x0000000000003db0        0x0
                [!provide]                        PROVIDE (__tdata_start = .)
 *(.tdata .tdata.* .gnu.linkonce.td.*)

.tbss
 *(.tbss .tbss.* .gnu.linkonce.tb.*)
 *(.tcommon)

.preinit_array  0x0000000000003db0        0x0
                [!provide]                        PROVIDE (__preinit_array_start = .)
 *(.preinit_array)
                [!provide]                        PROVIDE (__preinit_array_end = .)

.init_array     0x0000000000003db0        0x8
                0x0000000000003db0                PROVIDE (__init_array_start = .)
 *(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))
 *(.init_array EXCLUDE_FILE(*crtend?.o *crtend.o *crtbegin?.o *crtbegin.o) .ctors)
 .init_array    0x0000000000003db0        0x8 /usr/lib/gcc/x86_64-linux-gnu/9/crtbeginS.o
                0x0000000000003db8                PROVIDE (__init_array_end = .)

.fini_array     0x0000000000003db8        0x8
                [!provide]                        PROVIDE (__fini_array_start = .)
 *(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))
 *(.fini_array EXCLUDE_FILE(*crtend?.o *crtend.o *crtbegin?.o *crtbegin.o) .dtors)
 .fini_array    0x0000000000003db8        0x8 /usr/lib/gcc/x86_64-linux-gnu/9/crtbeginS.o
                [!provide]                        PROVIDE (__fini_array_end = .)

.ctors
 *crtbegin.o(.ctors)
 *crtbegin?.o(.ctors)
 *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
 *(SORT_BY_NAME(.ctors.*))
 *(.ctors)

.dtors
 *crtbegin.o(.dtors)
 *crtbegin?.o(.dtors)
 *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
 *(SORT_BY_NAME(.dtors.*))
 *(.dtors)

.jcr
 *(.jcr)

.data.rel.ro    0x0000000000003dc0        0x0
 *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*)
 *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*)
 .data.rel.ro   0x0000000000003dc0        0x0 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o

.dynamic        0x0000000000003dc0      0x1f0
 *(.dynamic)
 .dynamic       0x0000000000003dc0      0x1f0 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o
                0x0000000000003dc0                _DYNAMIC

.got            0x0000000000003fb0       0x50
 *(.got.plt)
 .got.plt       0x0000000000003fb0       0x28 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o
                0x0000000000003fb0                _GLOBAL_OFFSET_TABLE_
 *(.igot.plt)
 *(.got)
 .got           0x0000000000003fd8       0x28 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o
 *(.igot)
                0x0000000000004000                . = DATA_SEGMENT_RELRO_END (., 0x0)

.data           0x0000000000004000       0x10
 *(.data .data.* .gnu.linkonce.d.*)
 .data          0x0000000000004000        0x4 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o
                0x0000000000004000                data_start
                0x0000000000004000                __data_start
 .data          0x0000000000004004        0x0 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crti.o
 .data          0x0000000000004004        0x0 /usr/lib/gcc/x86_64-linux-gnu/9/crtbeginS.o
 *fill*         0x0000000000004004        0x4 
 .data.rel.local
                0x0000000000004008        0x8 /usr/lib/gcc/x86_64-linux-gnu/9/crtbeginS.o
                0x0000000000004008                __dso_handle
 .data          0x0000000000004010        0x0 /tmp/ccDz4GV7.o
 .data          0x0000000000004010        0x0 /usr/lib/x86_64-linux-gnu/libc_nonshared.a(elf-init.oS)
 .data          0x0000000000004010        0x0 /usr/lib/gcc/x86_64-linux-gnu/9/crtendS.o
 .data          0x0000000000004010        0x0 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crtn.o

.tm_clone_table
                0x0000000000004010        0x0
 .tm_clone_table
                0x0000000000004010        0x0 /usr/lib/gcc/x86_64-linux-gnu/9/crtbeginS.o
 .tm_clone_table
                0x0000000000004010        0x0 /usr/lib/gcc/x86_64-linux-gnu/9/crtendS.o

.duan.1         0x0000000000004010       0x10
 .duan.1        0x0000000000004010       0x10 /tmp/ccDz4GV7.o
                0x0000000000004010                test_start
                0x0000000000004018                test_test1

.duan.6         0x0000000000004020        0x8
 .duan.6        0x0000000000004020        0x8 /tmp/ccDz4GV7.o
                0x0000000000004020                test_end

.duan.2         0x0000000000004028        0x8
 .duan.2        0x0000000000004028        0x8 /tmp/ccDz4GV7.o
                0x0000000000004028                test_test2

.data1
 *(.data1)
                0x0000000000004030                _edata = .
                [!provide]                        PROVIDE (edata = .)
                0x0000000000004030                . = .
                0x0000000000004030                __bss_start = .

.bss            0x0000000000004030        0x8
 *(.dynbss)
 .dynbss        0x0000000000004030        0x0 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o
 *(.bss .bss.* .gnu.linkonce.b.*)
 .bss           0x0000000000004030        0x0 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o
 .bss           0x0000000000004030        0x0 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crti.o
 .bss           0x0000000000004030        0x1 /usr/lib/gcc/x86_64-linux-gnu/9/crtbeginS.o
 .bss           0x0000000000004031        0x0 /tmp/ccDz4GV7.o
 .bss           0x0000000000004031        0x0 /usr/lib/x86_64-linux-gnu/libc_nonshared.a(elf-init.oS)
 .bss           0x0000000000004031        0x0 /usr/lib/gcc/x86_64-linux-gnu/9/crtendS.o
 .bss           0x0000000000004031        0x0 /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crtn.o
 *(COMMON)
                0x0000000000004038                . = ALIGN ((. != 0x0)?0x8:0x1)
 *fill*         0x0000000000004031        0x7 

.lbss
 *(.dynlbss)
 *(.lbss .lbss.* .gnu.linkonce.lb.*)
 *(LARGE_COMMON)
                0x0000000000004038                . = ALIGN (0x8)
                0x0000000000004038                . = SEGMENT_START ("ldata-segment", .)

.lrodata
 *(.lrodata .lrodata.* .gnu.linkonce.lr.*)

.ldata          0x0000000000006038        0x0
 *(.ldata .ldata.* .gnu.linkonce.l.*)
                0x0000000000006038                . = ALIGN ((. != 0x0)?0x8:0x1)
                0x0000000000006038                . = ALIGN (0x8)
                0x0000000000004038                _end = .
                [!provide]                        PROVIDE (end = .)
                0x0000000000006038                . = DATA_SEGMENT_END (.)

.stab
 *(.stab)

.stabstr
 *(.stabstr)

.stab.excl
 *(.stab.excl)

.stab.exclstr
 *(.stab.exclstr)

.stab.index
 *(.stab.index)

.stab.indexstr
 *(.stab.indexstr)

.comment        0x0000000000000000       0x2b
 *(.comment)
 .comment       0x0000000000000000       0x2b /usr/lib/gcc/x86_64-linux-gnu/9/crtbeginS.o
                                         0x2c (size before relaxing)
 .comment       0x000000000000002b       0x2c /tmp/ccDz4GV7.o
 .comment       0x000000000000002b       0x2c /usr/lib/gcc/x86_64-linux-gnu/9/crtendS.o

.gnu.build.attributes
 *(.gnu.build.attributes .gnu.build.attributes.*)

.debug
 *(.debug)

.line
 *(.line)

.debug_srcinfo
 *(.debug_srcinfo)

.debug_sfnames
 *(.debug_sfnames)

.debug_aranges
 *(.debug_aranges)

.debug_pubnames
 *(.debug_pubnames)

.debug_info
 *(.debug_info .gnu.linkonce.wi.*)

.debug_abbrev
 *(.debug_abbrev)

.debug_line
 *(.debug_line .debug_line.* .debug_line_end)

.debug_frame
 *(.debug_frame)

.debug_str
 *(.debug_str)

.debug_loc
 *(.debug_loc)

.debug_macinfo
 *(.debug_macinfo)

.debug_weaknames
 *(.debug_weaknames)

.debug_funcnames
 *(.debug_funcnames)

.debug_typenames
 *(.debug_typenames)

.debug_varnames
 *(.debug_varnames)

.debug_pubtypes
 *(.debug_pubtypes)

.debug_ranges
 *(.debug_ranges)

.debug_macro
 *(.debug_macro)

.debug_addr
 *(.debug_addr)

.gnu.attributes
 *(.gnu.attributes)

/DISCARD/
 *(.note.GNU-stack)
 *(.gnu_debuglink)
 *(.gnu.lto_*)
OUTPUT(a.out elf64-x86-64)

检查上述map文件,我们可以发现段 段排序和Keil采用的方式不一样,因此在gcc环境下直接使用会存在问题
在这里插入图片描述

这是由于采用gcc编译.c文件时,默认通过链接文件生成链接脚本,生成的这个链接脚本,对于数据段采用的排序方式未采用按照名称排序的方式,我们可以通过指令查看采用的gcc auto_init.c -Wl,--verbose链接脚本内容,如下所示:

GNU ld (GNU Binutils for Ubuntu) 2.34
  Supported emulations:
   elf_x86_64
   elf32_x86_64
   elf_i386
   elf_iamcu
   elf_l1om
   elf_k1om
   i386pep
   i386pe
using internal linker script:
==================================================
/* Script for -pie -z combreloc -z separate-code -z relro -z now */
/* Copyright (C) 2014-2020 Free Software Foundation, Inc.
   Copying and distribution of this script, with or without modification,
   are permitted in any medium without royalty provided the copyright
   notice and this notice are preserved.  */
OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64",
	      "elf64-x86-64")
OUTPUT_ARCH(i386:x86-64)
ENTRY(_start)
SEARCH_DIR("=/usr/local/lib/x86_64-linux-gnu"); SEARCH_DIR("=/lib/x86_64-linux-gnu"); SEARCH_DIR("=/usr/lib/x86_64-linux-gnu"); SEARCH_DIR("=/usr/lib/x86_64-linux-gnu64"); SEARCH_DIR("=/usr/local/lib64"); SEARCH_DIR("=/lib64"); SEARCH_DIR("=/usr/lib64"); SEARCH_DIR("=/usr/local/lib"); SEARCH_DIR("=/lib"); SEARCH_DIR("=/usr/lib"); SEARCH_DIR("=/usr/x86_64-linux-gnu/lib64"); SEARCH_DIR("=/usr/x86_64-linux-gnu/lib");
SECTIONS
{
  PROVIDE (__executable_start = SEGMENT_START("text-segment", 0)); . = SEGMENT_START("text-segment", 0) + SIZEOF_HEADERS;
  .interp         : { *(.interp) }
  .note.gnu.build-id  : { *(.note.gnu.build-id) }
  .hash           : { *(.hash) }
  .gnu.hash       : { *(.gnu.hash) }
  .dynsym         : { *(.dynsym) }
  .dynstr         : { *(.dynstr) }
  .gnu.version    : { *(.gnu.version) }
  .gnu.version_d  : { *(.gnu.version_d) }
  .gnu.version_r  : { *(.gnu.version_r) }
  .rela.dyn       :
    {
      *(.rela.init)
      *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
      *(.rela.fini)
      *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
      *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)
      *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)
      *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)
      *(.rela.ctors)
      *(.rela.dtors)
      *(.rela.got)
      *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
      *(.rela.ldata .rela.ldata.* .rela.gnu.linkonce.l.*)
      *(.rela.lbss .rela.lbss.* .rela.gnu.linkonce.lb.*)
      *(.rela.lrodata .rela.lrodata.* .rela.gnu.linkonce.lr.*)
      *(.rela.ifunc)
    }
  .rela.plt       :
    {
      *(.rela.plt)
      *(.rela.iplt)
    }
  . = ALIGN(CONSTANT (MAXPAGESIZE));
  .init           :
  {
    KEEP (*(SORT_NONE(.init)))
  }
  .plt            : { *(.plt) *(.iplt) }
.plt.got        : { *(.plt.got) }
.plt.sec        : { *(.plt.sec) }
  .text           :
  {
    *(.text.unlikely .text.*_unlikely .text.unlikely.*)
    *(.text.exit .text.exit.*)
    *(.text.startup .text.startup.*)
    *(.text.hot .text.hot.*)
    *(SORT(.text.sorted.*))
    *(.text .stub .text.* .gnu.linkonce.t.*)
    /* .gnu.warning sections are handled specially by elf.em.  */
    *(.gnu.warning)
  }
  .fini           :
  {
    KEEP (*(SORT_NONE(.fini)))
  }
  PROVIDE (__etext = .);
  PROVIDE (_etext = .);
  PROVIDE (etext = .);
  . = ALIGN(CONSTANT (MAXPAGESIZE));
  /* Adjust the address for the rodata segment.  We want to adjust up to
     the same address within the page on the next page up.  */
  . = SEGMENT_START("rodata-segment", ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)));
  .rodata         : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
  .rodata1        : { *(.rodata1) }
  .eh_frame_hdr   : { *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) }
  .eh_frame       : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) }
  .gcc_except_table   : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) }
  .gnu_extab   : ONLY_IF_RO { *(.gnu_extab*) }
  /* These sections are generated by the Sun/Oracle C++ compiler.  */
  .exception_ranges   : ONLY_IF_RO { *(.exception_ranges*) }
  /* Adjust the address for the data segment.  We want to adjust up to
     the same address within the page on the next page up.  */
  . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
  /* Exception handling  */
  .eh_frame       : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) }
  .gnu_extab      : ONLY_IF_RW { *(.gnu_extab) }
  .gcc_except_table   : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
  .exception_ranges   : ONLY_IF_RW { *(.exception_ranges*) }
  /* Thread Local Storage sections  */
  .tdata	  :
   {
     PROVIDE_HIDDEN (__tdata_start = .);
     *(.tdata .tdata.* .gnu.linkonce.td.*)
   }
  .tbss		  : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
  .preinit_array    :
  {
    PROVIDE_HIDDEN (__preinit_array_start = .);
    KEEP (*(.preinit_array))
    PROVIDE_HIDDEN (__preinit_array_end = .);
  }
  .init_array    :
  {
    PROVIDE_HIDDEN (__init_array_start = .);
    KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
    KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
    PROVIDE_HIDDEN (__init_array_end = .);
  }
  .fini_array    :
  {
    PROVIDE_HIDDEN (__fini_array_start = .);
    KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
    KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
    PROVIDE_HIDDEN (__fini_array_end = .);
  }
  .ctors          :
  {
    /* gcc uses crtbegin.o to find the start of
       the constructors, so we make sure it is
       first.  Because this is a wildcard, it
       doesn't matter if the user does not
       actually link against crtbegin.o; the
       linker won't look for a file to match a
       wildcard.  The wildcard also means that it
       doesn't matter which directory crtbegin.o
       is in.  */
    KEEP (*crtbegin.o(.ctors))
    KEEP (*crtbegin?.o(.ctors))
    /* We don't want to include the .ctor section from
       the crtend.o file until after the sorted ctors.
       The .ctor section from the crtend file contains the
       end of ctors marker and it must be last */
    KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
    KEEP (*(SORT(.ctors.*)))
    KEEP (*(.ctors))
  }
  .dtors          :
  {
    KEEP (*crtbegin.o(.dtors))
    KEEP (*crtbegin?.o(.dtors))
    KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
    KEEP (*(SORT(.dtors.*)))
    KEEP (*(.dtors))
  }
  .jcr            : { KEEP (*(.jcr)) }
  .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) }
  .dynamic        : { *(.dynamic) }
  .got            : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) }
  . = DATA_SEGMENT_RELRO_END (0, .);
  .data           :
  {
    *(.data .data.* .gnu.linkonce.d.*)
    SORT(CONSTRUCTORS)
  }
  .data1          : { *(.data1) }
  _edata = .; PROVIDE (edata = .);
  . = .;
  __bss_start = .;
  .bss            :
  {
   *(.dynbss)
   *(.bss .bss.* .gnu.linkonce.b.*)
   *(COMMON)
   /* Align here to ensure that the .bss section occupies space up to
      _end.  Align after .bss to ensure correct alignment even if the
      .bss section disappears because there are no input sections.
      FIXME: Why do we need it? When there is no .bss section, we do not
      pad the .data section.  */
   . = ALIGN(. != 0 ? 64 / 8 : 1);
  }
  .lbss   :
  {
    *(.dynlbss)
    *(.lbss .lbss.* .gnu.linkonce.lb.*)
    *(LARGE_COMMON)
  }
  . = ALIGN(64 / 8);
  . = SEGMENT_START("ldata-segment", .);
  .lrodata   ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
  {
    *(.lrodata .lrodata.* .gnu.linkonce.lr.*)
  }
  .ldata   ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
  {
    *(.ldata .ldata.* .gnu.linkonce.l.*)
    . = ALIGN(. != 0 ? 64 / 8 : 1);
  }
  . = ALIGN(64 / 8);
  _end = .; PROVIDE (end = .);
  . = DATA_SEGMENT_END (.);
  /* Stabs debugging sections.  */
  .stab          0 : { *(.stab) }
  .stabstr       0 : { *(.stabstr) }
  .stab.excl     0 : { *(.stab.excl) }
  .stab.exclstr  0 : { *(.stab.exclstr) }
  .stab.index    0 : { *(.stab.index) }
  .stab.indexstr 0 : { *(.stab.indexstr) }
  .comment       0 : { *(.comment) }
  .gnu.build.attributes : { *(.gnu.build.attributes .gnu.build.attributes.*) }
  /* DWARF debug sections.
     Symbols in the DWARF debugging sections are relative to the beginning
     of the section so we begin them at 0.  */
  /* DWARF 1 */
  .debug          0 : { *(.debug) }
  .line           0 : { *(.line) }
  /* GNU DWARF 1 extensions */
  .debug_srcinfo  0 : { *(.debug_srcinfo) }
  .debug_sfnames  0 : { *(.debug_sfnames) }
  /* DWARF 1.1 and DWARF 2 */
  .debug_aranges  0 : { *(.debug_aranges) }
  .debug_pubnames 0 : { *(.debug_pubnames) }
  /* DWARF 2 */
  .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.*) }
  .debug_abbrev   0 : { *(.debug_abbrev) }
  .debug_line     0 : { *(.debug_line .debug_line.* .debug_line_end) }
  .debug_frame    0 : { *(.debug_frame) }
  .debug_str      0 : { *(.debug_str) }
  .debug_loc      0 : { *(.debug_loc) }
  .debug_macinfo  0 : { *(.debug_macinfo) }
  /* SGI/MIPS DWARF 2 extensions */
  .debug_weaknames 0 : { *(.debug_weaknames) }
  .debug_funcnames 0 : { *(.debug_funcnames) }
  .debug_typenames 0 : { *(.debug_typenames) }
  .debug_varnames  0 : { *(.debug_varnames) }
  /* DWARF 3 */
  .debug_pubtypes 0 : { *(.debug_pubtypes) }
  .debug_ranges   0 : { *(.debug_ranges) }
  /* DWARF Extension.  */
  .debug_macro    0 : { *(.debug_macro) }
  .debug_addr     0 : { *(.debug_addr) }
  .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
  /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }
}


==================================================
/usr/bin/ld: mode elf_x86_64
attempt to open /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o succeeded
/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o
attempt to open /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crti.o succeeded
/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crti.o
attempt to open /usr/lib/gcc/x86_64-linux-gnu/9/crtbeginS.o succeeded
/usr/lib/gcc/x86_64-linux-gnu/9/crtbeginS.o
attempt to open /tmp/cc86xswz.o succeeded
/tmp/cc86xswz.o
attempt to open /usr/lib/gcc/x86_64-linux-gnu/9/libgcc.so failed
attempt to open /usr/lib/gcc/x86_64-linux-gnu/9/libgcc.a succeeded
/usr/lib/gcc/x86_64-linux-gnu/9/libgcc.a
attempt to open /usr/lib/gcc/x86_64-linux-gnu/9/libgcc_s.so succeeded
opened script file /usr/lib/gcc/x86_64-linux-gnu/9/libgcc_s.so
/usr/lib/gcc/x86_64-linux-gnu/9/libgcc_s.so
opened script file /usr/lib/gcc/x86_64-linux-gnu/9/libgcc_s.so
attempt to open libgcc_s.so.1 failed
attempt to open /usr/lib/gcc/x86_64-linux-gnu/9/libgcc_s.so.1 failed
attempt to open /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libgcc_s.so.1 succeeded
/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libgcc_s.so.1
attempt to open /usr/lib/gcc/x86_64-linux-gnu/9/libgcc.so failed
attempt to open /usr/lib/gcc/x86_64-linux-gnu/9/libgcc.a succeeded
/usr/lib/gcc/x86_64-linux-gnu/9/libgcc.a
attempt to open /usr/lib/gcc/x86_64-linux-gnu/9/libc.so failed
attempt to open /usr/lib/gcc/x86_64-linux-gnu/9/libc.a failed
attempt to open /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libc.so succeeded
opened script file /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libc.so
/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libc.so
opened script file /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libc.so
attempt to open /lib/x86_64-linux-gnu/libc.so.6 succeeded
/lib/x86_64-linux-gnu/libc.so.6
attempt to open /usr/lib/x86_64-linux-gnu/libc_nonshared.a succeeded
/usr/lib/x86_64-linux-gnu/libc_nonshared.a
(/usr/lib/x86_64-linux-gnu/libc_nonshared.a)elf-init.oS
attempt to open /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 succeeded
/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
/usr/lib/x86_64-linux-gnu/libc_nonshared.a
/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
attempt to open /usr/lib/gcc/x86_64-linux-gnu/9/libgcc.so failed
attempt to open /usr/lib/gcc/x86_64-linux-gnu/9/libgcc.a succeeded
/usr/lib/gcc/x86_64-linux-gnu/9/libgcc.a
attempt to open /usr/lib/gcc/x86_64-linux-gnu/9/libgcc_s.so succeeded
opened script file /usr/lib/gcc/x86_64-linux-gnu/9/libgcc_s.so
/usr/lib/gcc/x86_64-linux-gnu/9/libgcc_s.so
opened script file /usr/lib/gcc/x86_64-linux-gnu/9/libgcc_s.so
attempt to open libgcc_s.so.1 failed
attempt to open /usr/lib/gcc/x86_64-linux-gnu/9/libgcc_s.so.1 failed
attempt to open /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libgcc_s.so.1 succeeded
/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libgcc_s.so.1
attempt to open /usr/lib/gcc/x86_64-linux-gnu/9/libgcc.so failed
attempt to open /usr/lib/gcc/x86_64-linux-gnu/9/libgcc.a succeeded
/usr/lib/gcc/x86_64-linux-gnu/9/libgcc.a
attempt to open /usr/lib/gcc/x86_64-linux-gnu/9/crtendS.o succeeded
/usr/lib/gcc/x86_64-linux-gnu/9/crtendS.o
attempt to open /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crtn.o succeeded
/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crtn.o
ld-linux-x86-64.so.2 needed by /lib/x86_64-linux-gnu/libc.so.6
found ld-linux-x86-64.so.2 at /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2

关键描述字段如下:
在这里插入图片描述
在这里插入图片描述
其中 text 段由于配置了*(SORT(.text.sorted.*)),因此采用了按名称排序的方式,而 data 段没有采用此排序方式,而我们定义的函数指针实际上是存放在data数据段,所以才会出现上述问题

如果要实现data段也采用按照名称大小的排序方式,大家可以将此链接脚本保存在工程路径下,之后修改.data段的描述,之后gcc编译的时候指定此链接脚本即可

4. 补充

定义宏的时候注意 const int *pint *const p 的区别:

  • const int *p const修饰的是int *p ,表明指针指向的对象不可以修改,但是指针可以修改,称之为指针常量
  • int *const p const修饰的是p,表明指针不可以修改,但是指向的内容可以被修改,称之为常量指针
  • const int *pint const *p 一致

5. 参考

参考RT-thread内核代码初始化设计,如果大家直接上手rtthread的自动初始化部分代码,可能会是一头雾水,那么现在再去看应该就很清楚了哈
在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_43332314/article/details/126033631