生成纯(或平面)二进制文件

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 -lhexdump 的输出来确认)。我们不想要标头,所以只需使用 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

【讨论】:

以上是关于生成纯(或平面)二进制文件的主要内容,如果未能解决你的问题,请参考以下文章

django 动态生成CSV文件

第二章:视图层 - 9:动态生成CSV文件

第二章:视图层 - 9:动态生成CSV文件

在Linux下执行平面二进制文件

Qt生成CSV 文件

如何检测 MIME 文件中的纯文本?