靜態庫改爲動態庫後,可以影響到程序的執行結果

源於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和test-bus-error.c中定義的BUS_ERROR_MAP段中的數據會合併到同一個ELF的BUS_ERROR_MAP段中,裏面有三個數組;

如果將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負責處理。



發佈了31 篇原創文章 · 獲贊 11 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章