ELF文件头

时间:2008-10-24 12:44:23

标签: linux unix embedded

关于elf文件头的快速问题,我似乎无法找到有关如何在elf头中添加/更改字段的任何有用信息。我希望能够更改幻数并在标题中添加构建日期,以及其他一些内容。

据我所知,链接器会创建头信息,但我没有在LD脚本中看到任何引用它的内容(虽然我是ld脚本的新手)。

我正在使用gcc并为ARM构建。

谢谢!

更新

  • 好吧也许我的第一个问题应该是:是否可以在链接时创建/编辑头文件?

9 个答案:

答案 0 :(得分:7)

我不知道可以执行此操作的链接描述文件命令,但您可以使用 objcopy 命令进行后链接。 - add-section 选项可用于将包含任意数据的部分添加到ELF文件。如果ELF标题不包含您想要的字段,只需创建一个新部分并将其添加到那里。

答案 1 :(得分:7)

This link (teensy elf binary)是某人对另一个问题的回答,但它更详细地介绍了ELF标题的复杂性。

答案 2 :(得分:2)

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

另一方面,elfsh可以很容易地对精灵物体进行各种操作,所以给它一个旋转。

答案 3 :(得分:1)

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

识别

例如,作为构建过程的一部分,您可以生成包含一个或多个info.c指令的 - { - 1}}:

#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) 。请注意,默认情况下,GCC也会编写自己的注释。

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

objdump -s --section .comment info.o

评论部分

在C转换单元中使用$ 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 基本上等同于在汇编程序文件中创建#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被其他工具使用和理解。 GNU也理解.comment指令,这就是GCC将.ident翻译成的内容。

带符号

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

objcopy把

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

#ident

使用GNU objcopy转换为目标文件:

$ cat magic.bin 
2342

检查符号:

$ 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;
}

GNU ld

GNU ld还可以使用objcopy兼容的命名方案将数据文件转换为目标文件:

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

与objcopy不同,它会将符号放入$ ld -r -b binary magic.bin -o magic-ld.o 而不是.data部分(参见.rodata)。

INCBIN

如果GNU objcopy不可用,可以使用GNU as .incbin directive创建目标文件(使用objdump -h magic.o汇编):

gcc -c incbin.s

XXD

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

    .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

答案 4 :(得分:0)

您可以使用libmelf,一个关于新鲜肉类的死项目,但可以从LOPI获得 - http://www.ipd.bth.se/ska/lopi.html

否则,你可以自己编写规范和(over)写标题。

答案 5 :(得分:0)

我暂时没有这样做,但你不能只是将任意数据附加到可执行文件中。如果你总是附加固定大小的数据,恢复你追加的任何东西都是微不足道的。可变大小不会太难。可能比弄乱w / elf标题更容易,并可能破坏你的可执行文件。

答案 6 :(得分:0)

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

答案 7 :(得分:0)

我没有完成这本书,但是iirc Linkers and Loaders by John Levine有了你需要能够做到的血腥细节。

答案 8 :(得分:-1)

在Linux控制台中:

$ man ld

$ ld --verbose

HTH