源于systemd的例子
先看bus-error.h中的一个宏:
#define BUS_ERROR_MAP_ELF_REGISTER \
__attribute__ ((__section__("BUS_ERROR_MAP"))) \
__attribute__ ((__used__)) \
__attribute__ ((aligned(8)))
意思是将数据定义在BUS_ERROR_MAP段,8字节对齐,标记为已使用的
bus-error.c中定义了一个数组:
BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_standard_errors[] = {
SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.Failed", EACCES),
SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.NoMemory", ENOMEM),
......
SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.ObjectPathInUse", EBUSY),
SD_BUS_ERROR_MAP_END
};
test-bus-error.c中定义了两个数组:
BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map test_errors[] = {
SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error", 5),
SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error-2", 52),
SD_BUS_ERROR_MAP_END
};
BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map test_errors2[] = {
SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error-3", 33),
SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error-4", 44),
SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error-33", 333),
SD_BUS_ERROR_MAP_END
};
如果将bus-error.c编译到动态库,然后test-bus-error.c去连接该动态库,bus-error.c在.so中,有一个BUS_ERROR_MAP段;test-bus-error.c在.exe中,有另一个BUS_ERROR_MAP段,里面只有两个数组。
当使用如下代码打印数组时,就会发现动态连接的输出会少很多(只打印了test-bus-error.c中的两个数组):
extern const sd_bus_error_map __start_BUS_ERROR_MAP[];
extern const sd_bus_error_map __stop_BUS_ERROR_MAP[];
static void dump_mapping_table(void) {
const sd_bus_error_map *m;
printf("----- errno mappings ------\n");
m = __start_BUS_ERROR_MAP;
while (m < __stop_BUS_ERROR_MAP) {
if (m->code == BUS_ERROR_MAP_END_MARKER) {
m = ALIGN8_PTR(m+1);
continue;
}
printf("%s -> %i/%s\n", strna(m->name), m->code, strna(errno_to_name(m->code)));
m ++;
}
printf("---------------------------\n");
}
__start_BUS_ERROR_MAP和__stop_BUS_ERROR_MAP分别是段BUS_ERROR_MAP的起始和结尾地址,由GCC负责处理。