汇编节.code和.text的行为不同 [英] Assembly section .code and .text behave differently
问题描述
我是汇编语言的新手,从中学到的 .code
与 .text
相同,但是下面的代码将使用 .code崩溃
.
I'm new to assembly and from what I learned the .code
is same with .text
, but the code below will crash using the .code
.
segment .data
msg db "hello, world", 0xa
len equ $ - msg
section .text
global _start
_start:
mov edx, len
mov ecx, msg
mov ebx, 1
mov eax, 4
int 0x80
mov ebx, 0
mov eax, 1
int 0x80
nasm -f elf64 -o hello.o hello.s
ld -s -o hello hello.o
hello, world
sed -i s/.text/.code/ ./hello.s
nasm -f elf64 -o hello.o hello.s
ld -s -o hello hello.o
./stack.sh: line 8: 4621 Segmentation fault (core dumped) ./hello
实际上,我认为没有什么不同.为什么会这样?
Actually, I don't think it's different. Why this happen ?
推荐答案
在带有标准工具链(GNU Binutils ld
)的Linux上, .text
是特殊"的;节名称得到特殊处理(默认情况下具有执行权限),但 .code
不是.(其他特殊部分包括 .data
(可写)和 .bss
(可写点),且所有默认对齐方式均为> 1.)
On Linux with the standard toolchain (GNU Binutils ld
), .text
is a "special" section name that gets special treatment (exec permission by default), but .code
isn't. (Other special sections include .data
(writeable) and .bss
(writable nobits), and all with a default alignment > 1.)
section .text
是Windows MASM .code
指令的NASM ELF/Linux等效项,但这 not 并不意味着Linux工具可以识别 .code
指令或节名称 1 .
section .text
is the NASM ELF/Linux equivalent of Windows MASM .code
directive, but that does not mean that Linux tools recognize a .code
directive or section name1.
部分.code
与部分xyz123
相同;它只使用默认值 noexec
nowrite
.请参见
section .code
is no different from section xyz123
; it just uses the defaults which are noexec
nowrite
. See the other
entry at the bottom of the table in the NASM docs.
使用 readelf -a hello
查看section(链接)和segment(程序加载器)属性,而在任何地方都明显缺少 X
.
Use readelf -a hello
to see the section (linking) and segment (program-loader) attributes, with a distinct lack of an X
anywhere.
脚注1:实际上,我认为Windows可执行文件仍使用实际的节名称 .text
.至少GNU objdump -d
仍然说代码在 .text
部分中.因此,MASM .code
指令是切换到 .text
部分的快捷方式.
Footnote 1: In fact, I think Windows executables still use the actual section name .text
. At least GNU objdump -d
still says the code is in the .text
section.
So the MASM .code
directive is a shortcut for switching to the .text
section.
有趣的事实:这确实是偶然"正确运行的.如果您将其构建为32位代码(您应该这种情况在错误地从16位MASM代码移植到Linux时使用了 section .code
NASM.
或者,如果您要在较旧的内核上运行64位代码.
Fun fact: this does happen to run correctly "by accident" if you build it as 32-bit code (which you should because it's using only 32-bit int 0x80
system calls), like in this case that used section .code
when incorrectly porting from 16-bit MASM code to Linux NASM.
Or if you'd run your 64-bit code on an older kernel.
原因是,在没有显式指定 PT_GNU_STACK
注释的情况下,内核对32位可执行文件使用了向后兼容的假设,并使用了影响每个页面的 READ_IMPLIES_EXEC
: Linux可执行文件的默认行为.data部分在5.4和5.9之间更改?.即使是64位可执行文件,较旧的内核也会执行此操作,在这种情况下,较新的内核只会使堆栈本身可执行.
The reason is that without explicitly specifying a PT_GNU_STACK
note, the kernel uses backwards-compat assumptions for 32-bit executables and uses READ_IMPLIES_EXEC
which affects every single page: Linux default behavior of executable .data section changed between 5.4 and 5.9?. Older kernels do this even for 64-bit executables, newer kernels only make the stack itself executable in this case.
在源代码中添加 section .note.GNU-stack noalloc noexec noexec progbits
可以使它像段错误那样出现,即使内置到32位可执行文件中也是如此.( nasm -felf32
/ ld -melf_i386 -o foo foo.o
).参见此答案.
Adding section .note.GNU-stack noalloc noexec nowrite progbits
to your source makes it segfault as it should, even when build into a 32-bit executable. (nasm -felf32
/ ld -melf_i386 -o foo foo.o
). See this answer.
另请参见>意外的exec权限从mmap中获取有关旧情况的项目中的程序集文件时.
这篇关于汇编节.code和.text的行为不同的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!