gpt4 book ai didi

使用链接器部分创建全局注册表

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:35:30 26 4
gpt4 key购买 nike

我见过几个项目使用特定的链接器部分来创建处理程序注册表(以下示例来自 ahttpd 集成在 eCos 中)。

这个想法是必须有可能从不同的条目中插入条目编译统一到同一个全局注册表中。

下面是一个简单的例子,我试图制作这个图案工作,但显然有问题,因为程序退出代码为 0,而我预计它是 3。

代码不需要可移植,唯一的目标是 Linux 下的 GCC。

这是我尝试过的:

#define HANDLER_TABLE_ENTRY(__var, __name, __val)          \
handler_table_entry __var \
__attribute__((section (".my.handler_table.data"))) \
__attribute__((used)) = { __name, __val }

struct handler_table_entry {
const char *name;
int val;
} __attribute__((aligned(8)));

// Beginning of section
__asm__(".section \".my.handler_table.data\",\"aw\"\n"
".globl handler_table\n"
".type handler_table,object\n"
".p2align 3\n"
"handler_table:\n"
".previous\n" );

// End of section
__asm__(".section \".my.handler_table.data\",\"aw\"\n"
".globl handler_table_end\n"
".type handler_table_end,object\n"
".p2align 3\n"
"handler_table_end:\n"
".previous\n" );

// Making the sections accessible from C
extern "C" handler_table_entry handler_table[];
extern "C" handler_table_entry handler_table_end[];

// Adding entries to the different sections. This may be done from different
// compilations unites
HANDLER_TABLE_ENTRY(entry_a, "entry_a", 10);
HANDLER_TABLE_ENTRY(entry_b, "entry_b", 20);
HANDLER_TABLE_ENTRY(entry_c, "entry_c", 30);

int main() {
// Count the number of entries and return the value
int cnt = 0;
for (handler_table_entry *entry = handler_table;
entry != handler_table_end; entry++)
cnt ++;

return cnt; // returns 0, but I expected 3
}

编译:

g++ foo.cxx -o foo

运行和测试:

$ ./foo && echo $?
0

问题 1:我做错了什么,一个简单的工作示例如何看起来像?

问题 2: 是否有任何陷阱或无法使用此模式的场景?用过的? (例如共享库)

更新:

我在尝试调试此问题的过程中添加了以下行(并包含 stdio.h)

printf("0x%p 0x%p\n", (void *)handler_table, (void *)handler_table_end);

我将编译命令更改为:

gcc -static -O0 -g -o foo foo.c

当我运行程序时,我得到以下输出:

$ ./foo
0x0x6b7650 0x0x6b7650

objdump 的内容如下:

$ objdump -d --section=.my.handler_table.data foo

foo: file format elf64-x86-64

Disassembly of section .my.handler_table.data:

00000000006b7650 <__TMC_END__>:
6b7650: 64 a1 48 00 00 00 00 00 10 00 00 00 00 00 00 00 d.H.............

00000000006b7660 <entry_2>:
6b7660: 6c a1 48 00 00 00 00 00 20 00 00 00 00 00 00 00 l.H..... .......

00000000006b7670 <entry_3>:
6b7670: 74 a1 48 00 00 00 00 00 30 00 00 00 00 00 00 00 t.H.....0.......

很明显问题是handler_tablehandler_table_end指向同一个位置,但这是为什么呢?

最佳答案

更改放置 handler_table_end 的部分的名称可以解决问题。

完整代码如下:

#include <stdio.h>

#define HANDLER_TABLE_ENTRY(__var, __name, __val) \
handler_table_entry __var \
__attribute__((section (".my.handler_table.data"))) \
__attribute__((used)) = { __name, __val }

struct handler_table_entry {
const char *name;
int val;
} __attribute__((aligned(8)));

// Beginning of section
__asm__(".section \".my.handler_table.data\",\"aw\"\n"
".globl handler_table\n"
".type handler_table,object\n"
".p2align 3\n"
"handler_table:\n"
".previous\n" );

// End of section. NOW IN A NEW SECTION
__asm__(".section \".my.handler_table.data.end\",\"aw\"\n"
".globl handler_table_end\n"
".type handler_table_end,object\n"
".p2align 3\n"
"handler_table_end:\n"
".previous\n" );

// Making the sections accessible from C
extern "C" handler_table_entry handler_table[];
extern "C" handler_table_entry handler_table_end[];

// Adding entries to the different sections. This may be done from different
// compilations unites
HANDLER_TABLE_ENTRY(entry_a, "entry_a", 10);
HANDLER_TABLE_ENTRY(entry_b, "entry_b", 20);
HANDLER_TABLE_ENTRY(entry_c, "entry_c", 30);

int main() {
for (handler_table_entry *entry = handler_table;
entry != handler_table_end; entry++)
printf("%s -> %d\n", entry->name, entry->val);

return 0;
}

关于使用链接器部分创建全局注册表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19975580/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com