How do you get the start and end addresses of a custom ELF section?

前端 未结 5 568
粉色の甜心
粉色の甜心 2020-12-05 02:57

I\'m working in C on Linux. I\'ve seen the usage of of the gcc __section__ attribute (especially in the Linux kernel) to collect data (usually function pointers) into custom

相关标签:
5条回答
  • 2020-12-05 03:32

    As long as the section name results in a valid C variable name, gcc (ld, rather) generates two magic variables: __start_SECTION and __stop_SECTION. Those can be used to retrieve the start and end addresses of a section, like so:

    /**
     * Assuming you've tagged some stuff earlier with:
     * __attribute((__section__("my_custom_section")))
     */
    
    struct thing *iter = &__start_my_custom_section;
    
    for ( ; iter < &__stop_my_custom_section; ++iter) {
        /* do something with *iter */
    }
    

    I couldn’t find any formal documentation for this feature, only a few obscure mailing list references. If you know where the docs are, drop a comment!

    If you're using your own linker script (as the Linux kernel does) you'll have to add the magic variables yourself (see vmlinux.lds.[Sh] and this SO answer).

    See here for another example of using custom ELF sections.

    0 讨论(0)
  • 2020-12-05 03:32

    So the answer above, __start_SECTION and __stop_SECTION will work, however for the program to be able to use the information from the linker you to need to declare those variables as extern char* __start_SECTION. Enjoy!

    extern char * __start_blobby;
    
    ...
    printf("This section starts at %p\n", (unsigned int)&__start_blobby);
    ...
    
    0 讨论(0)
  • 2020-12-05 03:40

    Linker can use the symbols defined in the code, and can assign their initial values if you use the exact name in the linker script:

    _smysection = .;
    *(.mysection)
    *(.mysection*)
    _emysection = .;
    

    Just define a variable in C code:

    const void * _smysection;
    

    And then you can access that as a regular variable.

    u32 someVar = (u32)&_smysection;
    
    0 讨论(0)
  • 2020-12-05 03:44

    HI: like this.

    extern const struct pseudo_ta_head __start_ta_head_section;
    extern const struct pseudo_ta_head __stop_ta_head_section;    
    
    const struct pseudo_ta_head *start = &__start_ta_head_section;
    const struct pseudo_ta_head *end = &__stop_ta_head_section;
    
    0 讨论(0)
  • 2020-12-05 03:52

    Collecting the information together from various answers, here is a working example of how to collect information into a custom linker section and then read the information from that section using the magic variables __start_SECTION and __stop_SECTION in your C program, where SECTION is the name of the section in the link map.

    The __start_SECTION and __stop_SECTION variables are made available by the linker so explicit extern references need to be created for these variables when they are used from C code.

    There are also some problems if the alignment used by the compiler for calculating pointer/array offsets is different than the alignment of the objects packed in each section by the linker. One solution (used in this example) is to store only a pointer to the data in the linker section.

    #include <stdio.h>
    
    struct thing {
        int val;
        const char* str;
        int another_val;
    };
    struct thing data1 = {1, "one"};
    struct thing data2 = {2, "two"};
    
    /* The following two pointers will be placed in "my_custom_section".
     * Store pointers (instead of structs) in "my_custom_section" to ensure
     * matching alignment when accessed using iterator in main(). */
    struct thing *p_one __attribute__((section("my_custom_section"))) = &data1; 
    struct thing *p_two __attribute__((section("my_custom_section"))) = &data2;
    
    /* The linker automatically creates these symbols for "my_custom_section". */
    extern struct thing *__start_my_custom_section;
    extern struct thing *__stop_my_custom_section;
    
    int main(void) {
        struct thing **iter = &__start_my_custom_section;
        for ( ; iter < &__stop_my_custom_section; ++iter) {
            printf("Have thing %d: '%s'\n", (*iter)->val, (*iter)->str);
        }
        return 0;
    }
    
    0 讨论(0)
提交回复
热议问题