gpt4 book ai didi

linker - 如何将文本文件的内容添加为 ELF 文件中的一个部分?

转载 作者:行者123 更新时间:2023-12-04 09:13:35 31 4
gpt4 key购买 nike

我有一个正在组装和链接的 NASM 组装文件(在 Intel-64 Linux 上)。

有一个文本文件,我希望文本文件的内容出现在生成的二进制文件中(基本上是一个字符串)。二进制文件是一个 ELF 可执行文件。

我的计划是在 ELF 文件中创建一个新的只读数据部分(相当于传统的 .rodata 部分)。

理想情况下,应该有一个工具可以将文件逐字添加为 elf 文件中的新部分,或者有一个链接器选项可以逐字添加文件。

这可能吗?

最佳答案

使用 OBJCOPY 可以并且最容易地做到这一点在 BINUTILS 中找到。您可以有效地将数据文件作为二进制输入,然后将其输出为可以链接到您的程序的目标文件格式。

OBJCOPY 甚至会生成开始和结束符号以及数据区的大小,以便您可以在代码中引用它们。基本思想是你要告诉它你的输入文件是二进制的(即使它是文本);您将针对 x86-64 目标文件;指定输入文件名和输出文件名。

假设我们有一个名为 myfile.txt 的输入文件内容:

the
quick
brown
fox
jumps
over
the
lazy
dog

像这样的事情将是一个起点:
objcopy --input binary \
--output elf64-x86-64 \
--binary-architecture i386:x86-64 \
myfile.txt myfile.o

如果要生成 32 位对象,可以使用:
objcopy --input binary \
--output elf32-i386 \
--binary-architecture i386 \
myfile.txt myfile.o

输出将是一个名为 myfile.o 的目标文件.如果我们使用 OBJDUMP 和类似 objdump -x myfile.o 的命令查看目标文件的头文件我们会看到这样的事情:
myfile.o:     file format elf64-x86-64
myfile.o
architecture: i386:x86-64, flags 0x00000010:
HAS_SYMS
start address 0x0000000000000000

Sections:
Idx Name Size VMA LMA File off Algn
0 .data 0000002c 0000000000000000 0000000000000000 00000040 2**0
CONTENTS, ALLOC, LOAD, DATA
SYMBOL TABLE:
0000000000000000 l d .data 0000000000000000 .data
0000000000000000 g .data 0000000000000000 _binary_myfile_txt_start
000000000000002c g .data 0000000000000000 _binary_myfile_txt_end
000000000000002c g *ABS* 0000000000000000 _binary_myfile_txt_size

默认情况下,它会创建一个 .data包含文件内容的部分,它创建了许多可用于引用数据的符号。
_binary_myfile_txt_start
_binary_myfile_txt_end
_binary_myfile_txt_size

这实际上是从文件 myfile.txt 放入对象的起始字节、结束字节和数据大小的地址。 . OBJCOPY 将基于输入文件名的符号。 myfile.txt被破坏成 myfile_txt并用于创建符号。

一个问题是 .data创建的部分是读/写/数据,如下所示:
Idx Name          Size      VMA               LMA               File off  Algn
0 .data 0000002c 0000000000000000 0000000000000000 00000040 2**0
CONTENTS, ALLOC, LOAD, DATA

您特别要求提供 .rodata也将指定 READONLY 标志的部分。您可以使用 --rename-section更改选项 .data.rodata并指定所需的标志。您可以将其添加到命令行:
--rename-section .data=.rodata,CONTENTS,ALLOC,LOAD,READONLY,DATA

当然,如果您想将该部分称为 .rodata 以外的其他内容使用与只读部分相同的标志,您可以更改 .rodata在要用于该部分的名称的上面的行中。

应生成所需对象类型的命令的最终版本是:
objcopy --input binary \
--output elf64-x86-64 \
--binary-architecture i386:x86-64 \
--rename-section .data=.rodata,CONTENTS,ALLOC,LOAD,READONLY,DATA \
myfile.txt myfile.o

现在您有了一个目标文件,您如何在 C 代码中使用它(作为示例)。生成的符号有点不正常,在 OS Dev Wiki上有合理的解释:

A common problem is getting garbage data when trying to use a value defined in a linker script. This is usually because they're dereferencing the symbol. A symbol defined in a linker script (e.g. _ebss = .;) is only a symbol, not a variable. If you access the symbol using extern uint32_t _ebss; and then try to use _ebss the code will try to read a 32-bit integer from the address indicated by _ebss.

The solution to this is to take the address of _ebss either by using it as &_ebss or by defining it as an unsized array (extern char _ebss[];) and casting to an integer. (The array notation prevents accidental reads from _ebss as arrays must be explicitly dereferenced)



记住这一点,我们可以创建一个名为 main.c 的 C 文件。 :
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>

/* These are external references to the symbols created by OBJCOPY */
extern char _binary_myfile_txt_start[];
extern char _binary_myfile_txt_end[];
extern char _binary_myfile_txt_size[];

int main()
{
char *data_start = _binary_myfile_txt_start;
char *data_end = _binary_myfile_txt_end;
size_t data_size = (size_t)_binary_myfile_txt_size;

/* Print out the pointers and size */
printf ("data_start %p\n", data_start);
printf ("data_end %p\n", data_end);
printf ("data_size %zu\n", data_size);

/* Print out each byte until we reach the end */
while (data_start < data_end)
printf ("%c", *data_start++);

return 0;
}

您可以编译和链接:
gcc -O3 main.c myfile.o

输出应该类似于:
data_start 0x4006a2
data_end 0x4006ce
data_size 44
the
quick
brown
fox
jumps
over
the
lazy
dog

NASM 的用法示例本质上类似于 C 代码。以下汇编程序名为 nmain.asm使用 Linux x86-64 System Calls 将相同的字符串写入标准输出:
bits 64
global _start

extern _binary_myfile_txt_start
extern _binary_myfile_txt_end
extern _binary_myfile_txt_size

section .text

_start:
mov eax, 1 ; SYS_Write system call
mov edi, eax ; Standard output FD = 1
mov rsi, _binary_myfile_txt_start ; Address to start of string
mov rdx, _binary_myfile_txt_size ; Length of string
syscall

xor edi, edi ; Return value = 0
mov eax, 60 ; SYS_Exit system call
syscall

这可以组装并链接到:
nasm -f elf64 -o nmain.o nmain.asm
gcc -m64 -nostdlib nmain.o myfile.o

输出应显示为:
the
quick
brown
fox
jumps
over
the
lazy
dog

关于linker - 如何将文本文件的内容添加为 ELF 文件中的一个部分?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42235175/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com