C语言中__attribute((section(name)))简单示例

[复制链接]
8345|2
手机看帖
扫描二维码
随时随地手机跟帖
keer_zu|  楼主 | 2021-7-19 10:24 | 显示全部楼层 |阅读模式
本帖最后由 keer_zu 于 2021-7-19 10:27 编辑

linux下使用readelf -S prog, 可以看到一张elf格式的表。表中以.开头的是一个一个的段。 __attribute((section(name)))的作用就是将被该属性修饰的符号都放到名为name的段中。

示例代码main.c中的_func1与_func2被__section宏修饰,最终都会被放到自定义的名为.app_init_sec段中。

#include <stdio.h>
#include <string.h>

#define __section __attribute((section(".app_init_sec")))

typedef struct init_t{
        int (*func)(void);
        char *name;
}_init_t;

_init_t __app_init_start__;
_init_t __app_init_end__;

static int func1(void)
{
        printf("call %s\n", __FUNCTION__);
        return 0;
}
_init_t _func1 __section = {func1, "func1"};


static int func2(void)
{
        printf("call %s\n", __FUNCTION__);
        return 0;
}
_init_t _func2 __section = {func2, "func2"};

int main(int argc, char **argv)
{
        _init_t *p;

        for(p = &__app_init_start__; p < &__app_init_end__; p++){
                printf("==%s\n", p->name);
                p->func();
        }

        return 0;
}

也许你已经注意到.app_init_sec段尚未定义,且__app_init_start__与__app_init_end__未做初始化就直接使用了。这是因为这些工作都是在一个.lds格式的文件中完成的。一个简单的.lds文件内容如下所示:


//script.lds
SECTIONS
{
    . = ALIGN(16);
    __app_init_start__ = .;
    .app_init_sec : { *(.app_init_sec) }
    __app_init_end__ = .;
}
INSERT AFTER .rodata

为了编译出可执行的文件,需要运行如下的命令:


gcc main.c -T script.lds -g -o prog



运行程序prog, 输出如下所示:


zkq@zkq-VirtualBox:~/src/test/src$ ./prog 
==func1
call func1
==func2
call func2

运行命令readelf -S prog查看elf表,可以在.rodata后找到自定义的.app_init_sec段:

zkq@zkq-VirtualBox:~/src/test/src$ readelf -S prog 
There are 37 section headers, starting at offset 0x202058:

Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .interp           PROGBITS         00000000004001c8  000001c8
       000000000000001c  0000000000000000   A       0     0     1
  [ 2] .note.ABI-tag     NOTE             00000000004001e4  000001e4
       0000000000000020  0000000000000000   A       0     0     4
  [ 3] .note.gnu.build-i NOTE             0000000000400204  00000204
       0000000000000024  0000000000000000   A       0     0     4
  [ 4] .gnu.hash         GNU_HASH         0000000000400228  00000228
       000000000000001c  0000000000000000   A       5     0     8
  [ 5] .dynsym           DYNSYM           0000000000400248  00000248
       0000000000000060  0000000000000018   A       6     1     8
  [ 6] .dynstr           STRTAB           00000000004002a8  000002a8
       000000000000003f  0000000000000000   A       0     0     1
  [ 7] .gnu.version      VERSYM           00000000004002e8  000002e8
       0000000000000008  0000000000000002   A       5     0     2
  [ 8] .gnu.version_r    VERNEED          00000000004002f0  000002f0
       0000000000000020  0000000000000000   A       6     1     8
  [ 9] .rela.dyn         RELA             0000000000400310  00000310
       0000000000000018  0000000000000018   A       5     0     8
  [10] .rela.plt         RELA             0000000000400328  00000328
       0000000000000030  0000000000000018  AI       5    25     8
  [11] .init             PROGBITS         0000000000400358  00000358
       000000000000001a  0000000000000000  AX       0     0     4
  [12] .plt              PROGBITS         0000000000400380  00000380
       0000000000000030  0000000000000010  AX       0     0     16
  [13] .plt.got          PROGBITS         00000000004003b0  000003b0
       0000000000000008  0000000000000000  AX       0     0     8
  [14] .text             PROGBITS         00000000004003c0  000003c0
       0000000000000202  0000000000000000  AX       0     0     16
  [15] .fini             PROGBITS         00000000004005c4  000005c4
       0000000000000009  0000000000000000  AX       0     0     4
  [16] .rodata           PROGBITS         00000000004005d0  000005d0
       000000000000002b  0000000000000000   A       0     0     4
  [17] .app_init_sec     PROGBITS         0000000000400600  00000600
       0000000000000020  0000000000000000  WA       0     0     16
  [18] .eh_frame_hdr     PROGBITS         0000000000400620  00000620
       0000000000000044  0000000000000000   A       0     0     4
  [19] .eh_frame         PROGBITS         0000000000400668  00000668
       0000000000000134  0000000000000000   A       0     0     8
  [20] .init_array       INIT_ARRAY       0000000000600e10  00200e10
       0000000000000008  0000000000000000  WA       0     0     8
  [21] .fini_array       FINI_ARRAY       0000000000600e18  00200e18
       0000000000000008  0000000000000000  WA       0     0     8
  [22] .jcr              PROGBITS         0000000000600e20  00200e20
       0000000000000008  0000000000000000  WA       0     0     8
  [23] .dynamic          DYNAMIC          0000000000600e28  00200e28
       00000000000001d0  0000000000000010  WA       6     0     8
  [24] .got              PROGBITS         0000000000600ff8  00200ff8
       0000000000000008  0000000000000008  WA       0     0     8
  [25] .got.plt          PROGBITS         0000000000601000  00201000
       0000000000000028  0000000000000008  WA       0     0     8
  [26] .data             PROGBITS         0000000000601028  00201028
       0000000000000010  0000000000000000  WA       0     0     8
  [27] .bss              NOBITS           0000000000601038  00201038
       0000000000000008  0000000000000000  WA       0     0     1
  [28] .comment          PROGBITS         0000000000000000  00201038
       0000000000000035  0000000000000001  MS       0     0     1
  [29] .debug_aranges    PROGBITS         0000000000000000  0020106d
       0000000000000030  0000000000000000           0     0     1
  [30] .debug_info       PROGBITS         0000000000000000  0020109d
       00000000000001e8  0000000000000000           0     0     1
  [31] .debug_abbrev     PROGBITS         0000000000000000  00201285
       00000000000000f2  0000000000000000           0     0     1
  [32] .debug_line       PROGBITS         0000000000000000  00201377
       0000000000000061  0000000000000000           0     0     1
  [33] .debug_str        PROGBITS         0000000000000000  002013d8
       0000000000000120  0000000000000001  MS       0     0     1
  [34] .shstrtab         STRTAB           0000000000000000  00201efe
       000000000000015a  0000000000000000           0     0     1
  [35] .symtab           SYMTAB           0000000000000000  002014f8
       0000000000000798  0000000000000018          36    57     8
  [36] .strtab           STRTAB           0000000000000000  00201c90
       000000000000026e  0000000000000000           0     0     1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), l (large)
  I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
  O (extra OS processing required) o (OS specific), p (processor specific)

使用特权

评论回复

相关帖子

keer_zu|  楼主 | 2021-7-19 10:35 | 显示全部楼层
一个rt-thread中的实例:

components.c
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date           Author       Notes
* 2012-09-20     Bernard      Change the name to components.c
*                             And all components related header files.
* 2012-12-23     Bernard      fix the pthread initialization issue.
* 2013-06-23     Bernard      Add the init_call for components initialization.
* 2013-07-05     Bernard      Remove initialization feature for MS VC++ compiler
* 2015-02-06     Bernard      Remove the MS VC++ support and move to the kernel
* 2015-05-04     Bernard      Rename it to components.c because compiling issue
*                             in some IDEs.
* 2015-07-29     Arda.Fu      Add support to use RT_USING_USER_MAIN with IAR
*/

#include <rthw.h>
#include <rtthread.h>

#ifdef RT_USING_USER_MAIN
#ifndef RT_MAIN_THREAD_STACK_SIZE
#define RT_MAIN_THREAD_STACK_SIZE     2048
#endif
#ifndef RT_MAIN_THREAD_PRIORITY
#define RT_MAIN_THREAD_PRIORITY       (RT_THREAD_PRIORITY_MAX / 3)
#endif
#endif

#ifdef RT_USING_COMPONENTS_INIT
/*
* Components Initialization will initialize some driver and components as following
* order:
* rti_start         --> 0
* BOARD_EXPORT      --> 1
* rti_board_end     --> 1.end
*
* DEVICE_EXPORT     --> 2
* COMPONENT_EXPORT  --> 3
* FS_EXPORT         --> 4
* ENV_EXPORT        --> 5
* APP_EXPORT        --> 6
*
* rti_end           --> 6.end
*
* These automatically initialization, the driver or component initial function must
* be defined with:
* INIT_BOARD_EXPORT(fn);
* INIT_DEVICE_EXPORT(fn);
* ...
* INIT_APP_EXPORT(fn);
* etc.
*/
static int rti_start(void)
{
    return 0;
}
INIT_EXPORT(rti_start, "0");

static int rti_board_start(void)
{
    return 0;
}
INIT_EXPORT(rti_board_start, "0.end");

static int rti_board_end(void)
{
    return 0;
}
INIT_EXPORT(rti_board_end, "1.end");

static int rti_end(void)
{
    return 0;
}
INIT_EXPORT(rti_end, "6.end");

/**
* RT-Thread Components Initialization for board
*/
void rt_components_board_init(void)
{
#if RT_DEBUG_INIT
    int result;
    const struct rt_init_desc *desc;
    for (desc = &__rt_init_desc_rti_board_start; desc < &__rt_init_desc_rti_board_end; desc ++)
    {
        rt_kprintf("initialize %s", desc->fn_name);
        result = desc->fn();
        rt_kprintf(":%d done\n", result);
    }
#else
    const init_fn_t *fn_ptr;

    for (fn_ptr = &__rt_init_rti_board_start; fn_ptr < &__rt_init_rti_board_end; fn_ptr++)
    {
        (*fn_ptr)();
    }
#endif
}

/**
* RT-Thread Components Initialization
*/
void rt_components_init(void)
{
#if RT_DEBUG_INIT
    int result;
    const struct rt_init_desc *desc;

    rt_kprintf("do components initialization.\n");
    for (desc = &__rt_init_desc_rti_board_end; desc < &__rt_init_desc_rti_end; desc ++)
    {
        rt_kprintf("initialize %s", desc->fn_name);
        result = desc->fn();
        rt_kprintf(":%d done\n", result);
    }
#else
    const init_fn_t *fn_ptr;

    for (fn_ptr = &__rt_init_rti_board_end; fn_ptr < &__rt_init_rti_end; fn_ptr ++)
    {
        (*fn_ptr)();
    }
#endif
}

#ifdef RT_USING_USER_MAIN

void rt_application_init(void);
void rt_hw_board_init(void);
int rtthread_startup(void);

#if defined(__CC_ARM) || defined(__CLANG_ARM)
extern int $Super$main(void);
/* re-define main function */
int $Sub$main(void)
{
    rtthread_startup();
    return 0;
}
#elif defined(__ICCARM__)
extern int main(void);
/* __low_level_init will auto called by IAR cstartup */
extern void __iar_data_init3(void);
int __low_level_init(void)
{
    // call IAR table copy function.
    __iar_data_init3();
    rtthread_startup();
    return 0;
}
#elif defined(__GNUC__)
extern int main(void);
/* Add -eentry to arm-none-eabi-gcc argument */
int entry(void)
{
    rtthread_startup();
    return 0;
}
#endif

#ifndef RT_USING_HEAP
/* if there is not enable heap, we should use static thread and stack. */
ALIGN(8)
static rt_uint8_t main_stack[RT_MAIN_THREAD_STACK_SIZE];
struct rt_thread main_thread;
#endif

/* the system main thread */
void main_thread_entry(void *parameter)
{
    extern int main(void);
    extern int $Super$main(void);

    /* RT-Thread components initialization */
    rt_components_init();

    /* invoke system main function */
#if defined(__CC_ARM) || defined(__CLANG_ARM)
    $Super$main(); /* for ARMCC. */
#elif defined(__ICCARM__) || defined(__GNUC__)
    main();
#endif
}

void rt_application_init(void)
{
    rt_thread_t tid;

#ifdef RT_USING_HEAP
    tid = rt_thread_create("main", main_thread_entry, RT_NULL,
                           RT_MAIN_THREAD_STACK_SIZE, RT_MAIN_THREAD_PRIORITY, 20);
    RT_ASSERT(tid != RT_NULL);
#else
    rt_err_t result;

    tid = &main_thread;
    result = rt_thread_init(tid, "main", main_thread_entry, RT_NULL,
                            main_stack, sizeof(main_stack), RT_MAIN_THREAD_PRIORITY, 20);
    RT_ASSERT(result == RT_EOK);
       
    /* if not define RT_USING_HEAP, using to eliminate the warning */
    (void)result;
#endif

    rt_thread_startup(tid);
}

int rtthread_startup(void)
{
    rt_hw_interrupt_disable();

    /* board level initialization
     * NOTE: please initialize heap inside board initialization.
     */
    rt_hw_board_init();

    /* show RT-Thread version */
    rt_show_version();

    /* timer system initialization */
    rt_system_timer_init();

    /* scheduler system initialization */
    rt_system_scheduler_init();

#ifdef RT_USING_SIGNALS
    /* signal system initialization */
    rt_system_signal_init();
#endif

    /* create init_thread */
    rt_application_init();

    /* timer thread initialization */
    rt_system_timer_thread_init();

    /* idle thread initialization */
    rt_thread_idle_init();

    /* start scheduler */
    rt_system_scheduler_start();

    /* never reach here */
    return 0;
}
#endif
#endif

使用特权

评论回复
keer_zu|  楼主 | 2021-7-19 10:35 | 显示全部楼层
本帖最后由 keer_zu 于 2021-7-19 10:36 编辑

一个rt-thread中的实例:

components.c:

/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date           Author       Notes
* 2012-09-20     Bernard      Change the name to components.c
*                             And all components related header files.
* 2012-12-23     Bernard      fix the pthread initialization issue.
* 2013-06-23     Bernard      Add the init_call for components initialization.
* 2013-07-05     Bernard      Remove initialization feature for MS VC++ compiler
* 2015-02-06     Bernard      Remove the MS VC++ support and move to the kernel
* 2015-05-04     Bernard      Rename it to components.c because compiling issue
*                             in some IDEs.
* 2015-07-29     Arda.Fu      Add support to use RT_USING_USER_MAIN with IAR
*/

#include <rthw.h>
#include <rtthread.h>

#ifdef RT_USING_USER_MAIN
#ifndef RT_MAIN_THREAD_STACK_SIZE
#define RT_MAIN_THREAD_STACK_SIZE     2048
#endif
#ifndef RT_MAIN_THREAD_PRIORITY
#define RT_MAIN_THREAD_PRIORITY       (RT_THREAD_PRIORITY_MAX / 3)
#endif
#endif

#ifdef RT_USING_COMPONENTS_INIT
/*
* Components Initialization will initialize some driver and components as following
* order:
* rti_start         --> 0
* BOARD_EXPORT      --> 1
* rti_board_end     --> 1.end
*
* DEVICE_EXPORT     --> 2
* COMPONENT_EXPORT  --> 3
* FS_EXPORT         --> 4
* ENV_EXPORT        --> 5
* APP_EXPORT        --> 6
*
* rti_end           --> 6.end
*
* These automatically initialization, the driver or component initial function must
* be defined with:
* INIT_BOARD_EXPORT(fn);
* INIT_DEVICE_EXPORT(fn);
* ...
* INIT_APP_EXPORT(fn);
* etc.
*/
static int rti_start(void)
{
    return 0;
}
INIT_EXPORT(rti_start, "0");

static int rti_board_start(void)
{
    return 0;
}
INIT_EXPORT(rti_board_start, "0.end");

static int rti_board_end(void)
{
    return 0;
}
INIT_EXPORT(rti_board_end, "1.end");

static int rti_end(void)
{
    return 0;
}
INIT_EXPORT(rti_end, "6.end");

/**
* RT-Thread Components Initialization for board
*/
void rt_components_board_init(void)
{
#if RT_DEBUG_INIT
    int result;
    const struct rt_init_desc *desc;
    for (desc = &__rt_init_desc_rti_board_start; desc < &__rt_init_desc_rti_board_end; desc ++)
    {
        rt_kprintf("initialize %s", desc->fn_name);
        result = desc->fn();
        rt_kprintf(":%d done\n", result);
    }
#else
    const init_fn_t *fn_ptr;

    for (fn_ptr = &__rt_init_rti_board_start; fn_ptr < &__rt_init_rti_board_end; fn_ptr++)
    {
        (*fn_ptr)();
    }
#endif
}

/**
* RT-Thread Components Initialization
*/
void rt_components_init(void)
{
#if RT_DEBUG_INIT
    int result;
    const struct rt_init_desc *desc;

    rt_kprintf("do components initialization.\n");
    for (desc = &__rt_init_desc_rti_board_end; desc < &__rt_init_desc_rti_end; desc ++)
    {
        rt_kprintf("initialize %s", desc->fn_name);
        result = desc->fn();
        rt_kprintf(":%d done\n", result);
    }
#else
    const init_fn_t *fn_ptr;

    for (fn_ptr = &__rt_init_rti_board_end; fn_ptr < &__rt_init_rti_end; fn_ptr ++)
    {
        (*fn_ptr)();
    }
#endif
}

#ifdef RT_USING_USER_MAIN

void rt_application_init(void);
void rt_hw_board_init(void);
int rtthread_startup(void);

#if defined(__CC_ARM) || defined(__CLANG_ARM)
extern int $Super$main(void);
/* re-define main function */
int $Sub$main(void)
{
    rtthread_startup();
    return 0;
}
#elif defined(__ICCARM__)
extern int main(void);
/* __low_level_init will auto called by IAR cstartup */
extern void __iar_data_init3(void);
int __low_level_init(void)
{
    // call IAR table copy function.
    __iar_data_init3();
    rtthread_startup();
    return 0;
}
#elif defined(__GNUC__)
extern int main(void);
/* Add -eentry to arm-none-eabi-gcc argument */
int entry(void)
{
    rtthread_startup();
    return 0;
}
#endif

#ifndef RT_USING_HEAP
/* if there is not enable heap, we should use static thread and stack. */
ALIGN(8)
static rt_uint8_t main_stack[RT_MAIN_THREAD_STACK_SIZE];
struct rt_thread main_thread;
#endif

/* the system main thread */
void main_thread_entry(void *parameter)
{
    extern int main(void);
    extern int $Super$main(void);

    /* RT-Thread components initialization */
    rt_components_init();

    /* invoke system main function */
#if defined(__CC_ARM) || defined(__CLANG_ARM)
    $Super$main(); /* for ARMCC. */
#elif defined(__ICCARM__) || defined(__GNUC__)
    main();
#endif
}

void rt_application_init(void)
{
    rt_thread_t tid;

#ifdef RT_USING_HEAP
    tid = rt_thread_create("main", main_thread_entry, RT_NULL,
                           RT_MAIN_THREAD_STACK_SIZE, RT_MAIN_THREAD_PRIORITY, 20);
    RT_ASSERT(tid != RT_NULL);
#else
    rt_err_t result;

    tid = &main_thread;
    result = rt_thread_init(tid, "main", main_thread_entry, RT_NULL,
                            main_stack, sizeof(main_stack), RT_MAIN_THREAD_PRIORITY, 20);
    RT_ASSERT(result == RT_EOK);
       
    /* if not define RT_USING_HEAP, using to eliminate the warning */
    (void)result;
#endif

    rt_thread_startup(tid);
}

int rtthread_startup(void)
{
    rt_hw_interrupt_disable();

    /* board level initialization
     * NOTE: please initialize heap inside board initialization.
     */
    rt_hw_board_init();

    /* show RT-Thread version */
    rt_show_version();

    /* timer system initialization */
    rt_system_timer_init();

    /* scheduler system initialization */
    rt_system_scheduler_init();

#ifdef RT_USING_SIGNALS
    /* signal system initialization */
    rt_system_signal_init();
#endif

    /* create init_thread */
    rt_application_init();

    /* timer thread initialization */
    rt_system_timer_thread_init();

    /* idle thread initialization */
    rt_thread_idle_init();

    /* start scheduler */
    rt_system_scheduler_start();

    /* never reach here */
    return 0;
}
#endif
#endif



使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:qq群:49734243 Email:zukeqiang@gmail.com

1287

主题

12161

帖子

53

粉丝