将库中的专用 ELF 部分合并到应用程序专用 ELF 部分
Merging dedicated ELF sections from libraries into application dedicated ELF section
这是我的测试。我有一个由 main.c
和 misc.c
源组成的 main
应用程序和一个由 lib.c
.
组成的静态库
目标: 我想在 ELF 部分 .modules
.
中声明我所有的 struct module
声明
问题: 我只能看到来自主应用程序的 struct module
声明。这是我可以使用以下代码看到的输出:
Hello World
- module:module_a
- module:module_b
如果我将 my_lib()
调用到 main()
那么我会看到:
Hello World
MyLib
- module:module_a
- module:module_b
- module:module_lib
但我对直接调用模块的功能到我的主应用程序不感兴趣。
CMakeLists.txt
add_executable(main main.c misc.c)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffunction-sections -fdata-sections")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections")
set(LINKER_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/linker.ld")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -T ${LINKER_SCRIPT}")
add_library(static_lib STATIC lib.c)
target_link_libraries(main static_lib)
main.c
#include "module.h"
extern const struct module modules_start[];
extern const struct module modules_end[];
struct module __attribute__ ((section (".modules"))) module_a = {
.name = "module_a",
};
int main(void) {
puts("Hello World");
const struct module *m = modules_start;
while (m < modules_end) {
printf("- module:%s\n", m->name);
m++;
}
return 0;
}
misc.c
#include "module.h"
struct module __attribute__ ((section (".modules"))) module_b = {
.name = "module_b",
};
module.h
#include <stdio.h>
struct module {
const char* name;
};
lib.c
#include "module.h"
struct module __attribute__ ((section (".modules"))) __attribute__ ((used)) module_lib = {
.name = "module_lib",
};
int my_lib(void) {
puts("MyLib");
return 0;
}
linker.ld
SECTIONS
{
.modules : {
modules_start = .;
KEEP(*(.modules))
modules_end = .;
}
}
INSERT AFTER .rodata;
以下是ELF的一些资料:
$ readelf --sections libstatic_lib.a | grep -A 1 modules
[ 5] .modules PROGBITS 0000000000000000 00000058
0000000000000008 0000000000000000 WA 0 0 8
[ 6] .rela.modules RELA 0000000000000000 00000278
0000000000000018 0000000000000018 I 13 5 8
$ readelf --sections main | grep -A 1 modules
[17] .modules PROGBITS 00000000000009c0 000009c0
0000000000000010 0000000000000000 WA 0 0 8
$ nm libstatic_lib.a | grep module
0000000000000000 D module_lib
$ nm main | grep module
00000000000009c0 D module_a
00000000000009c8 D module_b
00000000000009d0 D modules_end
00000000000009c0 D modules_start
如果静态库中没有对目标文件的引用,则默认情况下该目标文件不包含在 link 中。使用 binutils linker,您可以使用 --whole-archive
option.
禁用此优化
这是我的测试。我有一个由 main.c
和 misc.c
源组成的 main
应用程序和一个由 lib.c
.
目标: 我想在 ELF 部分 .modules
.
struct module
声明
问题: 我只能看到来自主应用程序的 struct module
声明。这是我可以使用以下代码看到的输出:
Hello World
- module:module_a
- module:module_b
如果我将 my_lib()
调用到 main()
那么我会看到:
Hello World
MyLib
- module:module_a
- module:module_b
- module:module_lib
但我对直接调用模块的功能到我的主应用程序不感兴趣。
CMakeLists.txt
add_executable(main main.c misc.c) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffunction-sections -fdata-sections") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") set(LINKER_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/linker.ld") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -T ${LINKER_SCRIPT}") add_library(static_lib STATIC lib.c) target_link_libraries(main static_lib)
main.c
#include "module.h" extern const struct module modules_start[]; extern const struct module modules_end[]; struct module __attribute__ ((section (".modules"))) module_a = { .name = "module_a", }; int main(void) { puts("Hello World"); const struct module *m = modules_start; while (m < modules_end) { printf("- module:%s\n", m->name); m++; } return 0; }
misc.c
#include "module.h" struct module __attribute__ ((section (".modules"))) module_b = { .name = "module_b", };
module.h
#include <stdio.h> struct module { const char* name; };
lib.c
#include "module.h" struct module __attribute__ ((section (".modules"))) __attribute__ ((used)) module_lib = { .name = "module_lib", }; int my_lib(void) { puts("MyLib"); return 0; }
linker.ld
SECTIONS { .modules : { modules_start = .; KEEP(*(.modules)) modules_end = .; } } INSERT AFTER .rodata;
以下是ELF的一些资料:
$ readelf --sections libstatic_lib.a | grep -A 1 modules
[ 5] .modules PROGBITS 0000000000000000 00000058
0000000000000008 0000000000000000 WA 0 0 8
[ 6] .rela.modules RELA 0000000000000000 00000278
0000000000000018 0000000000000018 I 13 5 8
$ readelf --sections main | grep -A 1 modules
[17] .modules PROGBITS 00000000000009c0 000009c0
0000000000000010 0000000000000000 WA 0 0 8
$ nm libstatic_lib.a | grep module
0000000000000000 D module_lib
$ nm main | grep module
00000000000009c0 D module_a
00000000000009c8 D module_b
00000000000009d0 D modules_end
00000000000009c0 D modules_start
如果静态库中没有对目标文件的引用,则默认情况下该目标文件不包含在 link 中。使用 binutils linker,您可以使用 --whole-archive
option.