我注意到我正在使用的汇编器
as
来自OS-X开发人员工具包,会生成Mach-O文件,而不是平面二进制文件。as
来自OS-X开发人员工具包,会生成Mach-O文件,而不是平面二进制文件。这是我完成它的方式。使用XCode命令行工具提供的链接器,您可以使用以下命令组合目标文件:
ld code1.o code2.o -o code.bin -r -U start
使用-r
选项告诉ld
仅将目标文件合并而不生成库文件,-U
选项告诉ld
忽略_start
的缺失定义(正常情况下由C stdlib提供)。
这将创建一个二进制文件,它仍然具有一些头字节,但可以使用以下命令轻松识别:
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)
的链接器脚本文件。如果我没记错的话,你还需要指定一些关于如何合并节(sections)的内容,但我不记得具体细节了。ld
下没有显示该选项。(Mac OS 10.6) - Hawken-T <filename>
或--script=<filename>
。 - Jerry Coffin我认为你不一定需要这样做。一些引导加载程序可以加载更复杂的可执行文件格式。例如,GRUB可以直接加载ELF。我相信你可以通过某种方式让它或其他引导加载程序加载Mach-O文件。
我不知道有什么简单的方法。
曾经我需要创建一个纯二进制文件,该文件将由另一个程序加载和执行。然而,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
.data dumpfile: .ascii "./dump" .byte 0 OutputFileDescriptor: .quad 0
.section __TEXT,__text,regular
.globl _main
_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 syscall
.align 3
开始转储:
.include "dump.s"
结束转储:
.quad 0
需要保存为原始二进制文件的代码包含在dump.s
中
你可以尝试使用 nasm
汇编器 -- 它有一个选项来控制输出的二进制格式,包括 -f bin
用于生成平面二进制文件。
请注意,你不能轻易地将 C 代码编译成平面二进制文件,因为几乎所有的 C 代码都需要二进制特性(如外部符号和重定位),这些特性无法在平面二进制文件中表示。