Gcc 附加到组件末尾的说明

Gcc 附加到组件末尾的说明,gcc,assembly,x86,nasm,ld,Gcc,Assembly,X86,Nasm,Ld,我试图按照教程创建一个二进制文件,但链接器似乎在程序集的末尾附加了额外的指令。我想这是操作系统的拆卸过程 本教程试图在Linux上编译一个简单的32位C程序: int main() { } 使用以下命令: gcc -c test.c ld -o test -Ttext 0x0 -e main test.o objcopy -R .note -R .comment -S -O binary test test.bin ndisasm -b 32 test.bin 我正在运行64位Linux,

我试图按照教程创建一个二进制文件,但链接器似乎在程序集的末尾附加了额外的指令。我想这是操作系统的拆卸过程


本教程试图在Linux上编译一个简单的32位C程序:

int main() {
}
使用以下命令:

gcc -c test.c
ld -o test -Ttext 0x0 -e main test.o
objcopy -R .note -R .comment -S -O binary test test.bin
ndisasm -b 32 test.bin
我正在运行64位Linux,因此将编译步骤修改为:

gcc -m32 -c test.c 
ld -m elf_i386 -o test -Ttext 0x0 -e main test.o
objcopy -R .note -R .comment -S -O binary test test.bin
ndisasm -b 32 test.bin
;; START expected output
00000000  55                push bp
00000001  89E5              mov bp,sp
00000003  5D                pop bp
00000004  C3                ret
;; END expected output
00000005  0000              add [eax],al
00000007  001400            add [eax+eax],dl
0000000A  0000              add [eax],al
0000000C  0000              add [eax],al
0000000E  0000              add [eax],al
00000010  017A52            add [edx+0x52],edi
00000013  0001              add [ecx],al
00000015  7C08              jl 0x1f
00000017  011B              add [ebx],ebx
00000019  0C04              or al,0x4
0000001B  0488              add al,0x88
0000001D  0100              add [eax],eax
0000001F  001C00            add [eax+eax],bl
00000022  0000              add [eax],al
00000024  1C00              sbb al,0x0
00000026  0000              add [eax],al
00000028  D8FF              fdivr st7
0000002A  FF                db 0xff
0000002B  FF0500000000      inc dword [dword 0x0]
00000031  41                inc ecx
00000032  0E                push cs
00000033  088502420D05      or [ebp+0x50d4202],al
00000039  41                inc ecx
0000003A  C50C04            lds ecx,[esp+eax]
0000003D  0400              add al,0x0
0000003F  00                db 0x00
预期产出为:

00000000 55            push ebp
00000001 89E5          mov ebp,esp
00000003 C9            leave
00000004 C3            ret
我的输出如下:

gcc -m32 -c test.c 
ld -m elf_i386 -o test -Ttext 0x0 -e main test.o
objcopy -R .note -R .comment -S -O binary test test.bin
ndisasm -b 32 test.bin
;; START expected output
00000000  55                push bp
00000001  89E5              mov bp,sp
00000003  5D                pop bp
00000004  C3                ret
;; END expected output
00000005  0000              add [eax],al
00000007  001400            add [eax+eax],dl
0000000A  0000              add [eax],al
0000000C  0000              add [eax],al
0000000E  0000              add [eax],al
00000010  017A52            add [edx+0x52],edi
00000013  0001              add [ecx],al
00000015  7C08              jl 0x1f
00000017  011B              add [ebx],ebx
00000019  0C04              or al,0x4
0000001B  0488              add al,0x88
0000001D  0100              add [eax],eax
0000001F  001C00            add [eax+eax],bl
00000022  0000              add [eax],al
00000024  1C00              sbb al,0x0
00000026  0000              add [eax],al
00000028  D8FF              fdivr st7
0000002A  FF                db 0xff
0000002B  FF0500000000      inc dword [dword 0x0]
00000031  41                inc ecx
00000032  0E                push cs
00000033  088502420D05      or [ebp+0x50d4202],al
00000039  41                inc ecx
0000003A  C50C04            lds ecx,[esp+eax]
0000003D  0400              add al,0x0
0000003F  00                db 0x00

附加指令的目的是什么,如何从目标文件和二进制文件中删除它们

编辑:

  • 键入
    objcopy
    args(commet->comment)。更新了反汇编输出

通常,当您在输出文件中看到其他数据/说明时,问题的根源可能是出现在预期代码之后的部分。处理这个问题的一种方法是查询ELF可执行文件,查看它定义了哪些部分。只需使用
-x
参数查询节即可。使用此命令:

objdump -x test
在大多数现代版本的GCC中,应使用默认参数生成与此类似(不精确)的输出:

人们应该首先寻找意外的部分。在输出到文件
test.bin
之前,您的命令使用
-R
从ELF对象中删除节。你做到了:

objcopy -R .note -R .comment -S -O binary test test.bin
如果排除
.note
.comment
部分,则上述OBJDUMP输出中剩下的明显部分是
.eh_frame
.eh_frame
被放置在文件
test.bin
.text
部分之后。这包含异常解除信息。这不是实际的指示。正在将非代码作为指令转储,因为二进制文件不区分代码和数据。NDISAM盲目地将所有数据转换为指令

有两种方法可以解决这个问题。您可以像处理其他两个部分一样排除
.eh_frame
部分。您可以使用:

objcopy -R .note -R .comment -R .eh_frame -S -O binary test test.bin
您还可以告诉GCC不要在代码中生成异步异常展开表。这可以通过GCC选项完成:

这与我的评论有点不同,因为我建议禁用所有异常。您只需禁用异步展开表以抑制
.eh\u frame
部分。本节讨论了本节的有用性(或不足)。gcc的手册页(
mangcc
)讨论了选项
-fasynchronous unwind tables

这是目前大多数GCC的默认设置。使用
-fno异步展开表
可关闭此功能



您链接到的是2000年制作的。GCC及其选项(以及发行版使用的默认值)多年来发生了变化。可能在创建该教程时,异步展开表还不存在。这就解释了为什么你观察到的结果与本教程不同。

@IgnacioVazquez Abrams我试图在
.comment
部分找到信息,但没有找到太多。它是什么,为什么你认为它是那个部分?如果你使用
objdump-x test.o
来转储所有elf头/部分,你可能会发现你有一个
.eh\u frame
部分。由于不排除,因此会占用文件中的空间。如果不打算使用异常处理,请将其添加到GCC命令行
-fno exceptions-fno asynchronous unwind tables
。因此,
gcc-m32-c test.c-fno异常-fno异步展开表
应该可以解决您的问题。它们实际上不是指令,而是异常帧数据,在转换为二进制平面文件时直接放在代码之后
ndisam
碰巧将数据解码为指令,因为它不知道区别。@MichaelPetch谢谢,它已经工作了。您想将您的评论作为答案吗?您对本教程的看法是正确的。我不得不进行许多标志修改,以显示与示例中显示的相同的一般行为。我知道
\u start
部分,但在遇到教程之前,我不知道所有注入到对象文件中的附加部分。
   -fasynchronous-unwind-tables
       Generate unwind table in DWARF 2 format, if supported by target machine.  The table is exact at each
       instruction boundary, so it can be used for stack unwinding from asynchronous events (such as debugger or
       garbage collector).