代码之家  ›  专栏  ›  技术社区  ›  OlivierM

将库中的专用ELF部分合并到应用程序专用ELF部分

  •  0
  • OlivierM  · 技术社区  · 6 年前

    这是我的测验。我有一个 main 由源组成的应用程序 main.c misc.c 以及一个静态库 lib.c .

    目标: 我想把我所有的 struct module .modules .

    问题: 结构体模块 来自主应用程序的声明。下面是我可以用以下代码看到的输出:

    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)
      
    • #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;
      }
      
    • 杂项成本

      #include "module.h"
      
      struct module __attribute__ ((section (".modules"))) module_b = {
          .name = "module_b",
      };
      
    • 模块h

      #include <stdio.h>
      
      struct module {
          const char* name;
      };
      
    • #include "module.h"
      
      struct module __attribute__ ((section (".modules"))) __attribute__ ((used)) module_lib = {
          .name = "module_lib",
      };
      
      int my_lib(void) {
          puts("MyLib");
          return 0;
      }
      
    • 链接器.ld

      SECTIONS
      {
          .modules : {
              modules_start = .;
              KEEP(*(.modules))
              modules_end = .;
          }
      }
      INSERT AFTER .rodata;
      

    以下是一些精灵信息:

    $ 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
    
    1 回复  |  直到 6 年前
        1
  •  2
  •   Florian Weimer    6 年前

    如果静态库中没有对对象文件的引用,则默认情况下链接中不包含该对象文件。使用binutils链接器,可以使用 --whole-archive option