如何生成可以直接在 CPU 上运行的平面二进制文件?
也就是说,没有操作系统;也称为独立环境代码(请参阅在没有操作系统的情况下直接运行的程序的名称是什么?)。
我注意到我正在使用的汇编程序(as
来自 OS-X 开发人员工具包)不断生成 Mach-O 文件,而不是平面二进制文件。
如何生成可以直接在 CPU 上运行的平面二进制文件?
也就是说,没有操作系统;也称为独立环境代码(请参阅在没有操作系统的情况下直接运行的程序的名称是什么?)。
我注意到我正在使用的汇编程序(as
来自 OS-X 开发人员工具包)不断生成 Mach-O 文件,而不是平面二进制文件。
我就是这样做的。使用 XCode 命令行工具附带的链接器,您可以使用以下方式组合目标文件:
ld code1.o code2.o -o code.bin -r -U start
-r
要求仅将ld
目标文件组合在一起而不创建库,-U
告诉ld
忽略缺少的定义_start
(通常由 C 标准库提供)。
这会创建一个仍然有一些头字节的二进制文件,但这很容易识别为
otool -l code.bin
在输出中查找__text
部分:
Section
sectname __text
segname __TEXT
addr 0x00000000
size 0x0000003b
offset 240
align 2^4 (16)
reloff 300
nreloc 1
flags 0x80000400
reserved1 0
reserved2 0
注意偏移量(您可以通过比较 和 的输出来确认otool -l
)hexdump
。我们不想要标头,所以只需使用dd
复制出您需要的字节:
dd if=code.bin of=code_stripped.bin ibs=240 skip=1
我将块大小设置为偏移量并跳过一个块。
你没有。您让链接器生成一个平面(纯)二进制文件。为此,您必须使用OUTPUT_FORMAT(binary)
. 如果没记错的话,您还需要指定有关部分如何合并的信息,但我不记得任何细节。
我认为您不一定需要这样做。一些引导加载程序可以加载更复杂的可执行格式。例如,GRUB 可以立即加载 ELF。我相信您可以通过某种方式获得它或其他一些引导加载程序来加载 Mach-O 文件。
您可能想尝试使用nasm
汇编器——它有一个控制输出二进制格式的选项,包括-f bin
平面二进制文件。
请注意,您不能轻松地将 C 代码编译为平面二进制文件,因为几乎所有 C 代码都需要无法在平面二进制文件中表示的二进制特性(如外部符号和重定位)。
我知道没有简单的方法。
一旦我需要创建将由另一个程序加载和执行的纯二进制文件。但是,as
不允许我这样做。我尝试使用gobjcopy
将目标文件转换为原始二进制文件,但它无法正确转换如下代码:
.quad LinkName2 - LinkName1
在它生成的二进制文件中gobjcopy
看起来像
.quad 0
我最终编写了特殊的转储程序,该程序是可执行的,可以将部分内存保存在磁盘上:
.set SYS_EXIT, 0x2000001 .set SYS_READ, 0x2000003 .set SYS_WRITE, 0x2000004 .set SYS_OPEN, 0x2000005 .set SYS_CLOSE, 0x2000006必须保存为原始二进制文件的代码包含在。数据 转储文件:.ascii "./dump" .byte 0 输出文件描述符:.quad 0
.section __TEXT,__text,regular .globl _main
_主要的:
movl $0644, %edx # file mode movl $0x601, %esi # O_CREAT | O_TRUNC | O_WRONLY leaq dumpfile(%rip), %rdi movl $SYS_OPEN, %eax syscall movq %rax, OutputFileDescriptor(%rip) movq $EndDump - BeginDump, %rdx leaq BeginDump(%rip), %rsi movq OutputFileDescriptor(%rip), %rdi movl $SYS_WRITE, %eax syscall movq OutputFileDescriptor(%rip), %rdi movl $SYS_CLOSE, %eax syscall
完毕: movq %rax, %rdi movl $SYS_EXIT, %eax 系统调用
.align 3
开始转储: .include “dump.s” 结束转储: .quad 0
dump.s