ELF文件标题

关于精灵文件标题的一个简短的问题,我似乎无法find任何有用的如何添加/更改精灵标题中的字段。 我希望能够改变魔术数字,并添加一个生成date头,可能还有一些其他的东西。

据我了解,链接器创build标题信息,但我没有看到任何引用它的LD脚本(虽然我是新的ld脚本)。

我正在使用gcc和ARM构build。

谢谢!

更新:

  • 好的,也许我的第一个问题应该是:有可能在链接时创build/编辑头文件?

Solutions Collecting From Web of "ELF文件标题"

我不知道可以做到这一点的链接器脚本命令,但是可以使用objcopy命令进行后链接。 –add-section选项可用于将包含任意数据的节添加到ELF文件。 如果ELF标题不包含所需的字段,只需创建一个新的部分并将其添加到那里。

这个链接(teensy elf binary)是别人对另外一个问题的回答,但是它更详细地描述了ELF头文件的复杂性。

我相当确定一个足够复杂的ld脚本可以做你想做的事情。 但是,我不知道如何。

另一方面, elfsh可以轻松地对精灵对象进行各种操作,所以给它一个旋转。

你也许可以使用libmelf,这是一个鲜活的项目,但是可以从LOPI获得 – http://www.ipd.bth.se/ska/lopi.html

否则,你可以得到规范和(自己)写头。

我一段时间没有这样做,但不能只是将任意数据附加到可执行文件。 如果你总是追加固定大小的数据,那么恢复你所追加的任何东西都是微不足道的。 可变大小不会更难。 可能比搞糟的elf标题更容易,并可能毁了你的可执行文件。

我没有完成这本书,但约翰列文的 iirc 连接器和装载机有血淋淋的细节,你需要能够做到这一点。

在Linux控制台中:

$ man ld

$ ld –verbose

HTH

在Solaris中,您可以使用elfedit,但是我认为您确实在为Linux寻求解决方案。 Linux不是UniX:P

您可以创建一个具有信息字段(如版本号)的对象文件,并链接该文件,使其包含在生成的ELF二进制文件中。

IDENT

例如,作为构建过程的一部分,您可以生成 – say – info.c ,其中包含一个或多个#ident指令:

 #ident "Build: 1.2.3 (Halloween)" #ident "Environment: example.org" 

编译它:

 $ gcc -c info.c 

检查是否包含信息:

 $ readelf -p .comment info.o String dump of section '.comment': [ 1] Build: 1.2.3 (Halloween) [ 1a] Environment: example.org [ 33] GCC: (GNU) 7.2.1 20170915 (Red Hat 7.2.1-2) 

或者,您可以使用objdump -s --section .comment info.o 请注意,默认情况下,GCC也会写入自己的注释。

链接ELF可执行文件后检查信息:

 $ gcc -o main main.o info.o $ readelf -p .comment main String dump of section '.comment': [ 0] GCC: (GNU) 7.2.1 20170915 (Red Hat 7.2.1-2) [ 2c] Build: 1.2.3 (Halloween) [ 45] Environment: example.org 

评论部分

在C翻译单元中使用#ident基本上等同于在汇编程序文件中创建.comment部分。 例:

 $ cat info.s .section .comment .string "Build: 1.2.3 (Halloween)" .string "Environment: example.org" $ gcc -c info.s String dump of section '.comment': [ 0] Build: 1.2.3 (Halloween) [ 19] Environment: example.org 

使用一个不常见的部分名称也起作用(例如.section .blahblah )。 但.comment被其他工具使用和理解。 GNU也理解.ident指令,这就是GCC翻译#ident

与符号

对于您也想从ELF可执行文件本身访问的数据,您需要创建符号。

objcopy把

假设你想包含一些存储在数据文件中的魔术字节:

 $ cat magic.bin 2342 

用GNU objcopy转换成一个目标文件:

 $ objcopy -I binary -O elf64-x86-64 -B i386 \ --rename-section .data=.rodata,alloc,load,readonly,data,contents \ magic.bin magic.o 

检查符号:

 $ nm magic.o 0000000000000005 R _binary_magic_bin_end 0000000000000005 A _binary_magic_bin_size 0000000000000000 R _binary_magic_bin_start 

用法示例:

 #include <stdio.h> #include <string.h> #include <inttypes.h> extern const char _binary_magic_bin_start[]; extern const char _binary_magic_bin_end[]; extern const unsigned char _binary_magic_bin_size; static const size_t magic_bin_size = (uintptr_t) &_binary_magic_bin_size; int main() { char s[23]; memcpy(s, _binary_magic_bin_start, _binary_magic_bin_end - _binary_magic_bin_start); s[magic_bin_size] = 0; puts(s); return 0; } 

链接在一起:

 $ gcc -g -o main_magic main_magic.c magic.o 

GNU ld

GNU ld也能够使用objcopy兼容的命名方案将数据文件转换为目标文件:

 $ ld -r -b binary magic.bin -o magic-ld.o 

与objcopy不同的是,它将符号放入.data而不是.rodata节中(参考objdump -h magic.o )。

INCBIN

如果GNU objcopy不可用,可以使用GNU作为 .incbin指令来创建目标文件(用gcc -c incbin.s汇编):

  .section .rodata .global _binary_magic_bin_start .type _binary_magic_bin_start, @object _binary_magic_bin_start: .incbin "magic.bin" .size _binary_magic_bin_start, . - _binary_magic_bin_start .global _binary_magic_bin_size .type _binary_magic_bin_size, @object .set _binary_magic_bin_size, . - _binary_magic_bin_start .global _binary_magic_bin_end .type _binary_magic_bin_end, @object .set _binary_magic_bin_end, _binary_magic_bin_start + _binary_magic_bin_size ; an alternate way to include the size .global _binary_magic_bin_len .type _binary_magic_bin_len, @object .size _binary_magic_bin_len, 8 _binary_magic_bin_len: .quad _binary_magic_bin_size 

XXD

一个更便携的替代品,不需要GNU objcopy也不需要GNU来创建一个中间的C文件并编译和链接它。 例如使用xxd :

 $ xxd -i magic.bin | sed 's/\(unsigned\)/const \1/' > magic.c $ gcc -c magic.c $ nm magic.o 0000000000000000 R magic_bin 0000000000000008 R magic_bin_len $ cat magic.c const unsigned char magic_bin[] = { 0x32, 0x33, 0x34, 0x32, 0x0a }; const unsigned int magic_bin_len = 5;