3

我试图在二进制文件的部分(如__attribute((__section__("counters"))))中存储一些变量并对其进行迭代,但我找不到如何获得该部分的起始方向。

阅读 GCC 的文档,我发现(自动?)在我的情况下创建了两个变量__start_counters__stop_counters,但是迭代该内存段似乎不包含我正在寻找的数据。

我的问题是:如何在一个部分中存储一些变量然后获取这些变量?

编辑:

显示我想要实现的目标的最小可编译代码。

#include <stdio.h>

char a, b, c;

struct counter_info {
    int counter;
    char *name;
} __attribute__((packed));

#define __PUT_STUFF_IN_SECTION(name)                    \
do{                                                     \
    static struct counter_info __counter_info_##name    \
    __attribute((__section__("counters")))              \
    __attribute((__used__)) = {                         \
        .name = #name,                                  \   <--------- this line causes *a lot of* errors, remove to actually compile the code
        .counter = 0,                                   \
    };                                                  \
}while(0)

extern struct counter_info __start_counters;
extern struct counter_info __stop_counters;

int main(int argc, char **argv){
    printf("Start!\n");

    __PUT_STUFF_IN_SECTION(a);
    __PUT_STUFF_IN_SECTION(b);
    __PUT_STUFF_IN_SECTION(c);

    struct counter_info *iter = &__start_counters;
    for(; iter < &__stop_counters; ++iter){
        printf("Name: %s | Counter: %d.\n", &iter->name, &iter->counter);
    }
    printf("End!\n");

    return 0;
}
4

3 回答 3

2

刚刚使您的代码编译并按预期工作:

--- foo.c       2013-09-06 19:43:28.025027688 +0200
+++ bar.c       2013-09-06 19:44:07.273028621 +0200
@@ -7,12 +7,12 @@
     char *name;
 } __attribute__((packed));

-#define __PUT_STUFF_IN_SECTION(name)                    \
+#define __PUT_STUFF_IN_SECTION(_name)                    \
 do{                                                     \
-    static struct counter_info __counter_info_##name    \
+    static struct counter_info __counter_info_##_name    \
     __attribute((__section__("counters")))              \
     __attribute((__used__)) = {                         \
-        .name = #name,                                  \
+        .name = #_name,                                  \
         .counter = 0,                                   \
     };                                                  \
 }while(0)
@@ -29,7 +29,7 @@

     struct counter_info *iter = &__start_counters;
     for(; iter < &__stop_counters; ++iter){
-        printf("Name: %s | Counter: %d.\n", &iter->name, &iter->counter);
+        printf("Name: %s | Counter: %d.\n", iter->name, iter->counter);
     }
     printf("End!\n");
于 2013-09-06T17:48:38.367 回答
1

该手册的示例非常不错。对于这个答案,我已经将其最小化了一点:

char stack[10000] __attribute__ ((section ("STACK"))) = { 0 };

main()
{
    /* Initialize stack pointer */
    init_sp (stack + sizeof (stack));
}

请注意引用的代码如何stack不必“遍历内存段”,它只处理stack,并且编译器/链接器将确保访问位于正确的位置,具体取决于该部分的结束位置。

通常,您不必知道或做任何特别的事情来访问变量;它们被放在特定段中的事实低于语言的抽象级别,其中范围内的所有变量通常都像往常一样按名称访问。

于 2013-09-06T08:05:30.817 回答
0

你说得很对。带节的属性会将数据放在正确的节中,而 gcc(或者更确切地说是链接器)将创建__startand__stop符号。

由于您没有发布您的代码,我真的不能说它有什么问题,所以我会给您我的概念实现。代码在 github 上

有代码可以处理 ELF、a.out 和任何 Apple 在 MacOS 上调用其二进制格式的代码。里面还有测试代码。

于 2013-09-06T08:05:42.177 回答