如何控制ELF文件中的段映射?

时间:2013-10-08 22:14:32

标签: c elf

所以我知道我们可以为ELF文件添加一个自定义部分,并强制执行功能和结构以映射到自定义部分。 这可以通过__atribute__ section("sectionname")来完成 这是我当前ELF的readelf输出,其自定义部分名称为.my_custom_section,其中包含名为ver_info的结构

结构:

typedef struct version_info
{
  int     dd ;
  int      mm;
  int    yy;
  int      hr;
  int      min;
  char      *software_type;
  char   *software_version;
  char    *hex_tools_version;
} version_info;

version_info ver_info __attribute__ ((section(".my_custom_section"))) = {7, 10, 2013, 17, 17, "some_type", "some_sw_version", "some_version"} ;

以下是精灵阅读的内容:

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .hash             HASH            000000d4 0000d4 00003c 04   A  2   0  4
  [ 2] .dynsym           DYNSYM          00000110 000110 0000a0 10   A  3   5  4
  [ 3] .dynstr           STRTAB          000001b0 0001b0 000026 00   A  0   0  1
  [ 4] .rela.dyn         RELA            000001d8 0001d8 000024 0c   A  2   0  4
  [ 5] .plt              PROGBITS        00001000 001000 000000 00  AX  0   0 16
  [ 6] .text             PROGBITS        00001000 001000 00001c 00  AX  0   0  4
  [ 7] .rodata           PROGBITS        00002000 002000 000027 00   A  0   0  1
  [ 8] .dynamic          DYNAMIC         00004000 003000 000078 08  WA  3   0  4
  [ 9] .got              PROGBITS        00004078 003078 000000 00  WA  0   0  4
  [10] .got.plt          PROGBITS        00004078 003078 000010 04  WA  0   0  8
  [11] .my_custom_sectio PROGBITS        00004088 003088 000020 00  WA  0   0  4
  [12] .bss              NOBITS          000040c0 0030a8 000000 00  WA  0   0  1
  [13] .comment          PROGBITS        00000000 0030a8 000028 01  MS  0   0  1
  [14] .shstrtab         STRTAB          00000000 0030d0 000081 00      0   0  1
  [15] .symtab           SYMTAB          00000000 0033fc 000180 10     16  19  4
  [16] .strtab           STRTAB          00000000 00357c 000075 00      0   0  1

Program Headers:

  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x000000 0x00000000 0x00000000 0x001fc 0x001fc R   0x1000
  LOAD           0x001000 0x00001000 0x00001000 0x0001c 0x0001c R E 0x1000
  LOAD           0x002000 0x00002000 0x00002000 0x00027 0x00027 R   0x1000
  LOAD           0x003000 0x00004000 0x00004000 0x000a8 0x000c0 RW  0x1000
  DYNAMIC        0x003000 0x00004000 0x00004000 0x00078 0x00078 RW  0x4

 Section to Segment mapping:
  Segment Sections...
   00     .hash .dynsym .dynstr .rela.dyn
   01     .text
   02     .rodata
   03     .dynamic .got.plt .my_custom_section
   04     .dynamic

在这种情况下,我的自定义部分会使用.dynamic.got.plt部分进行分组并映射到第03段。我想将此部分映射为独立的部分。

我们可以控制将某个部分映射到细分吗?你会怎么做呢?

编辑:
1.为什么不dlsym这个结构符号:我不是那么热衷于将这个结构添加为动态符号的原因是我正在编写一个API来读取版本信息(我打算将其包含在一个单独的段),这将最终确定我是否应该dlopen这个SO文件。避免打开过时的SO是安全措施的一部分。

2.使用自定义链接描述文件:我现在使用自定义链接描述文件添加以下部分:

.my_custom_section() :
  {
    KEEP (*version_info.o (.rodata* ))
  }

这允许我创建一个所需名称的部分并将我的数据放入其中。但我仍然在努力避免这一部分与.rodata或其他部分进行联系。

我确信通过在链接描述文件中指定一些配置,我可以将此部分映射为一个独立的部分,但这正是我想要弄清楚的。

1 个答案:

答案 0 :(得分:2)

这是您必须提供给链接器的指令。具体如何执行此操作取决于您使用的链接器。

使用GNU ld,"对"方法是使用自定义链接描述文件,您可以使用-T选项提供该脚本。您可以通过键入ld --verbose来查看默认链接描述文件。它与其他链接器类似:BSD链接器(由Mac OSX使用)使用订单文件(使用-order_file指定),Solaris链接器使用映射文件(使用{{1}指定) }), 等等。他们都做了同样的事情。

请注意,每个平台和每个CPU系列通常都有自己的链接规范,因此在x86_64目标上运行的GNU ld链接器脚本可能无法在ARM上运行,即使它们都是Linux。对于BSD家族来说,这是一个类似的故事。一般来说,您应该获取平台的链接器脚本并根据需要进行修改。如果是自定义平台(例如它的固件,你正在编写自己的操作系统,或者你有什么),你应该只从头开始编写自己的链接描述文件。

如果这是需要跨平台的代码,那么就没有好的解决方案。有一些"错误"这样做的方法可行,例如使用-M进行黑客攻击,但我不推荐它们。

话虽如此,你应该问问自己这是不是你想要的。如果您需要的是一些自定义工具或框架(例如动态链接加载器)可以轻松找到的数据,您是否可以使用objcopy或等效的?