生成纯(或平面)二进制文件
Posted
技术标签:
【中文标题】生成纯(或平面)二进制文件【英文标题】:Generating a pure (or flat) binary 【发布时间】:2012-05-03 16:56:45 【问题描述】:如何生成可直接在 CPU 上运行的平面二进制文件? 也就是说,没有操作系统;也称为独立环境代码(参见What is the name for a program running directly without an OS?)。
我注意到我正在使用的汇编程序,来自 OS-X 开发工具包的as
,不断生成 Mach-O 文件,而不是平面二进制文件。
【问题讨论】:
可能与***.com/questions/8482059/…重复 在我回答之前,告诉我们你打算用这个纯/扁平的二进制文件做什么? @jensbjörnhager 我在 UNIX 系统上使用 AT&T 语法;看到唯一的答案是使用另一个汇编程序,我认为这个问题值得以不同的方式提出。 可能重复:***.com/questions/6828631/… 【参考方案1】:我就是这样做的。使用 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
我将块大小设置为偏移量并跳过一个块。
【讨论】:
【参考方案2】:你没有。你得到 linker 来生成一个平面(纯)二进制文件。为此,您必须使用OUTPUT_FORMAT(binary)
编写链接描述文件。如果没记错的话,您还需要指定有关部分如何合并的一些信息,但我不记得任何细节。
【讨论】:
知道如何应用链接描述文件吗?我的手册页没有显示ld
下的选项。 (Mac OS 10.6)
@Hawken:至少对于普通版本的 ld,它的 -T <filename>
或 --script=<filename>
。
ld: unknown option: -T
这不是好兆头,但我会在另一个我认为的问题下坚持下去。【参考方案3】:
我认为您不一定需要这样做。一些引导加载程序可以加载更复杂的可执行格式。例如,GRUB 可以立即加载 ELF。我相信您可以通过某种方式获得它或其他一些引导加载程序来加载 Mach-O 文件。
【讨论】:
嘿,霍肯。我看到这个问题与另一个问题相关联,并且有兴趣看到它。无论如何,我认为你不需要为 grub 写任何东西。这里有安装指南:wiki.osdev.org/GRUB。看着那个,我认为它不支持 mach-o。不过,它确实支持 ELF,并将处理器置于保护模式。 @Hawken Ohhh.. 你如何编写 GRUB 本身。哦,我不知道。 :) 这真的很复杂。这是编写引导加载程序的一种方法:osdever.net/tutorials/view/hello-world-boot-loader,但它与 GRUB 完全不同,它要简单得多。而且我很确定它只会加载平面二进制文件。加载更复杂的格式更加困难。 事实上,该链接并没有描述引导加载程序,而是一个显示字符串“Hello World”的简单程序。不过,有些在线加载简单的二进制文件。我以前经常修补这些东西,而且我用过很多。如果我找到了,我会发布一个链接。 太棒了,我实际上是指任何类型的“独立环境”(***.com/questions/10274513),而不仅仅是引导加载程序。 好的,这就是一个例子。另外,请查看该站点上的所有重要资源 (osdever.net/tutorials/index)。它有很多有用的东西,我想你会感兴趣的。【参考方案4】:您可能想尝试使用nasm
汇编器——它有一个控制输出二进制格式的选项,包括用于平面二进制文件的-f bin
。
请注意,您无法轻松地将 C 代码编译为平面二进制文件,因为几乎所有 C 代码都需要无法在平面二进制文件中表示的二进制特性(如外部符号和重定位)。
【讨论】:
抱歉,我太喜欢 AT&T 语法而无法切换到 nasm,而且我不相信我的所有代码都通过 intel-at&t 转换器运行每个文件。不过感谢您的建议。【参考方案5】:我知道没有简单的方法。
曾经我需要创建一个普通的二进制文件,该文件将被另一个程序加载和执行。但是,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 转储文件:.ascii "./dump" .byte 0 输出文件描述符:.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 系统调用
.align 3
开始转储: .include “dump.s” 结束转储: .quad 0
必须保存为原始二进制文件的代码包含在dump.s
中
【讨论】:
以上是关于生成纯(或平面)二进制文件的主要内容,如果未能解决你的问题,请参考以下文章