V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
kkkbbb
V2EX  ›  C

c 语言中自定义 section 段问题请教

  •  
  •   kkkbbb · 2023-11-22 14:05:08 +08:00 · 1460 次点击
    这是一个创建于 395 天前的主题,其中的信息可能已经有所发展或是发生改变。

    看到一个代码自定义段实现如下:

    typedef void (*myown_call)(void);
    
    #define func_init(func)                                                        \
      __attribute__((section("myown"), aligned(__alignof__(myown_call))))          \
      myown_call _fn_##func = func
      
    extern myown_call __start_myown;
    extern myown_call __stop_myown;
    
    void do_initcalls(void) {
      myown_call *pfun = &__start_myown;
      do {
        (*pfun)();
        ++pfun;
      } while (pfun < &__stop_myown);
    }
    

    上面的代码是实现初始化逻辑的,我在网上看到要想实现自定义的段数据加载,需要在链接脚本中指定__start_myown 和__stop_myown 的地址位置,但是在代码的编译过程中没有看到相关的设置,不太清楚__start_myown 、__stop_myown 的地址编译器是如何分配的,又懂得大佬可以给解释下么?

    20 条回复    2023-11-24 09:45:25 +08:00
    lechain
        1
    lechain  
       2023-11-22 14:35:06 +08:00
    __start_myown ,__stop_myown 地址是编译器自动分配的,根据链接脚本里面为自定义的 section 节设置起始和结束地址来决定,如果不设置编译器则会自动按预设的规则选择和调整起始地址,

    话说你的需求是在程序开始前只调用一次自定义初始化还是需要为多个函数的进入设置不同的初始化函数,如果是前者的话,其实 gcc 的拓展可以很容易满足需求,使用 __attribute((constructor)) 修饰函数即可。

    https://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Function-Attributes.html

    没必要重复一遍 gcc 已经做过的工作(除非是出于学习的目的)。
    kkkbbb
        2
    kkkbbb  
    OP
       2023-11-22 14:54:16 +08:00
    @lechain 编译器就是根据__start_myown 、__stop_myown 这两个变量的先后顺序,把首地址和尾地址进行分配的?变量名也可以随便起?
    kkkbbb
        3
    kkkbbb  
    OP
       2023-11-22 16:42:30 +08:00
    @lechain 我可能上面没说清楚,我现在没有看到环境里有自定义的链接脚本,但是我看到网上都是先通过自定义链接脚本,定义好首尾地址的位置使用的,所以我才会有疑惑,这个收尾地址编译器可以自动分配?但是它怎么知道分配给那个变量,还有首尾地址的先后顺序如何确定的?
    kkkbbb
        4
    kkkbbb  
    OP
       2023-11-22 16:48:35 +08:00
    我刚写了个 demo 试了下,变量改变名称就会有问题,感觉应该是利用了编译器编译过程的默认变量处理实现的,有没有大佬懂为啥呢?
    colorglass
        5
    colorglass  
       2023-11-22 17:12:34 +08:00
    可能它编译使用的链接脚本中主动加了相关 symbol,可以在编译时加上 -Wl,--verbose 看看它编译过程中使用的连接脚本。或者如果这两个 symbol 是 gcc 自动加入的,可以在编译时加上 -v 来看看编译时使用了哪些相关的 flag 。我个人测试使用默认 flag 与链接脚本的情况下 gcc 会在.text 后自动添加自定义的 section,但不会添加对应的头尾 symbol 。
    colorglass
        6
    colorglass  
       2023-11-22 17:16:24 +08:00
    @colorglass 感觉应该是自定义的链接脚本,gcc 对 section 头尾 symbol 名称的格式一般是 "__section_start, __section_end",不会用"stop"。
    sbldehanhan
        7
    sbldehanhan  
       2023-11-22 17:26:47 +08:00
    一只菜鸡纯路过。只想说太硬核了。
    kkkbbb
        8
    kkkbbb  
    OP
       2023-11-22 17:38:33 +08:00
    @sbldehanhan 一样,看有没有大佬了解
    kkkbbb
        9
    kkkbbb  
    OP
       2023-11-22 17:40:23 +08:00
    @colorglass 没有,你可以用这段代码自己试下,就是自动生成的 symbol
    kkkbbb
        10
    kkkbbb  
    OP
       2023-11-22 17:57:24 +08:00
    @colorglass 刚才回的不太准确,如果你只定义了 section ,确实不会自动生成 symbol ,但是如果使用了__start_myown ,就会生成了
    lechain
        11
    lechain  
       2023-11-22 18:03:16 +08:00
    在链接脚本导出一下就好了,

    ```link
    SECTIONS
    {
    /* .... */
    .myown : {
    PROVIDE(__start_myown = .);
    *(.myown)
    PROVIDE(__stop_myown = .);
    }
    /* .... */
    }
    ```

    如果一个东西不确定工具软件会不会帮你生成,你就当作不会,然后自己写,这是最快的
    koebehshian
        12
    koebehshian  
       2023-11-22 18:07:50 +08:00
    我看 RT-Thread  ( https://club.rt-thread.org/ask/article/d686458bbba864f4.html) 是用不同的段名表示 start 与 end ,以及执行的初始化函数,也就是有 3 个 section ,按 ASCII 排序的。
    koebehshian
        13
    koebehshian  
       2023-11-22 22:05:36 +08:00
    我测试了一下,是按定义的顺序排的,并不是名称的 ASCII 码,RT-Thread 的链接脚本把段排序了:
    https://github.com/RT-Thread/rt-thread/blob/896b1fe2dac161a24281cb0b0de92ede3f462778/bsp/stm32/libraries/templates/stm32f10x/board/linker_scripts/link.lds#L42
    icyalala
        14
    icyalala  
       2023-11-22 22:34:39 +08:00   ❤️ 2
    这东西一般叫 linker magic, 由编译器 linker 实现的,有些人会拿来做编译期的注册制。
    MSVC: https://devblogs.microsoft.com/oldnewthing/20181107-00/?p=100155
    GCC/Clang: https://sourceware.org/binutils/docs/ld/Input-Section-Example.html
    zhdi
        15
    zhdi  
       2023-11-23 03:46:31 +08:00 via iPhone
    @lechain 正确的,上面的全在不知道说什么东西(

    另外题主问这种问题请把所有代码都放出来以供参考,这种底层的东西经常是一个 shit 糊另一个 shit ,并且没有那么明显的糊的痕迹,如果你的能力并不足以锁定代码位置就把相关的全扔出来,起码搞个链接
    kkkbbb
        16
    kkkbbb  
    OP
       2023-11-23 09:40:33 +08:00
    @zhdi 这个 demo 足以说明问题,为什么这个代码可以正常编过,并且执行:
    https://imgur.com/ABhMYYV.png
    kkkbbb
        17
    kkkbbb  
    OP
       2023-11-23 09:41:24 +08:00
    kkkbbb
        18
    kkkbbb  
    OP
       2023-11-23 09:47:00 +08:00
    @icyalala 多谢,大概了解了
    zhdi
        19
    zhdi  
       2023-11-23 17:28:38 +08:00
    @kkkbbb sry 之前看错了 attribute 的名称,如果 attribute 的自定义 sectionname 是不带.的,linker 会自动 PROVIDE 这俩变量,但是生产中很少有人这么用,大家都是自己的 link script 然后去定义更详细的起始位置
    kkkbbb
        20
    kkkbbb  
    OP
       2023-11-24 09:45:25 +08:00
    @zhdi 嗯嗯 学习了~
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2565 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 11:30 · PVG 19:30 · LAX 03:30 · JFK 06:30
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.