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

5

1
可能与https://dev59.com/0V7Va4cB1Zd3GeqPHzkO重复。 - Jens Björnhager
在我回答之前,请告诉我们您打算如何处理这个纯/平的二进制文件? - Michael Slade
@jensbjörnhager 我在UNIX系统上使用AT&T语法;考虑到那里唯一的答案是使用另一个汇编器,我认为以不同的方式提出这个问题是值得的。 - Hawken
可能是重复的问题:https://dev59.com/CWw15IYBdhLWcg3wGn9c - Ciro Santilli OurBigBook.com
5个回答

4

这是我完成它的方式。使用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 -lhexdump的输出来确认)。我们不需要头文件,所以只需使用dd复制出所需的字节即可:

dd if=code.bin of=code_stripped.bin ibs=240 skip=1

我将块大小设置为偏移量,并跳过一个块。


3
你不需要这样做。你需要让链接器生成一个纯二进制文件。为此,你需要编写一个带有OUTPUT_FORMAT(binary)的链接器脚本文件。如果我没记错的话,你还需要指定一些关于如何合并节(sections)的内容,但我不记得具体细节了。

2
有没有任何想法如何应用链接器脚本?我的手册在ld下没有显示该选项。(Mac OS 10.6) - Hawken
@Hawken:至少在常规版本的ld中,它是-T <filename>--script=<filename> - Jerry Coffin
1
ld: 未知选项:-T,这不是个好兆头,但我想我会把它放在另一个问题下。 - Hawken

1

我认为你不一定需要这样做。一些引导加载程序可以加载更复杂的可执行文件格式。例如,GRUB可以直接加载ELF。我相信你可以通过某种方式让它或其他引导加载程序加载Mach-O文件。


嘿,Hawken。我看到这个问题链接到另一个问题,并且很感兴趣。无论如何,我认为你不需要为 grub 编写任何内容。这里有一个安装指南:http://wiki.osdev.org/GRUB。看了一下,我不认为它支持 mach-o。但是它确实支持 ELF,并将处理器置于保护模式。 - user377628
1
@Hawken 哦哦..你怎么写GRUB本身。哦,我不知道。:) 这真的很复杂。这里有一种编写引导程序的方法:http://www.osdever.net/tutorials/view/hello-world-boot-loader,但它与GRUB完全不同,要简单得多。而且我很确定它只能加载平面二进制文件。加载更复杂的格式会更加困难。 - user377628
事实上,该链接并未描述引导加载程序,而是一个简单的程序,用于显示字符串“Hello World”。虽然有一些在线加载简单二进制文件的引导加载程序。我曾经经常涉足这方面的东西,并且使用过许多引导加载程序。如果我找到了一个,我会发布链接的。 - user377628
太棒了,我的确是指任何类型的“独立环境”(stackoverflow.com/questions/10274513),而不仅仅是引导加载程序。 - Hawken
好的,那只是一个例子。此外,请查看该网站上的所有出色资源(http://www.osdever.net/tutorials/index)。它有很多有用的东西,我认为你会感兴趣的。 - user377628

0

我不知道有什么简单的方法。

曾经我需要创建一个纯二进制文件,该文件将由另一个程序加载和执行。然而,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


0

你可以尝试使用 nasm 汇编器 -- 它有一个选项来控制输出的二进制格式,包括 -f bin 用于生成平面二进制文件。

请注意,你不能轻易地将 C 代码编译成平面二进制文件,因为几乎所有的 C 代码都需要二进制特性(如外部符号和重定位),这些特性无法在平面二进制文件中表示。


抱歉,我太喜欢AT&T语法了,所以不想转换到NASM,并且我也不信任每个文件都通过Intel-AT&T转换器运行我的所有代码。不过还是谢谢你的建议。 - Hawken

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接