使用自定义链接描述文件了解分段错误,用于简单的 'Hello World' - 64k 以下的段名称或基址
Understanding Segmentation Faults with a custom linker script for a simple 'Hello World' - section names or base address below 64k
之前在 x86_64 上多次看到的基本 Hello World Linux:
global my_start_symbol
section .text
my_start_symbol:
mov rax, 1
mov rdi, 1
mov rsi, msg
mov rdx, msg_len
syscall
mov rax, 60
xor rdi, rdi
syscall
section .rodata:
msg: db "Hello, world!", 10
msg_len: equ $ - msg
我的工作 ld
链接描述文件:
ENTRY(my_start_symbol)
SECTIONS
{
. = 0x10000;
.text : { *(.text*) }
.rodata : { *(.rodata*) }
}
调用方式:
nasm -f elf64 assembly.asm -o assembly.o
ld -T linker.ld assembly.o -o assembly
当我尝试进行以下更改时遇到各种分段错误:
- 如果我删除链接描述文件中的
. = 0x10000
或使其小于 0x10000
,我会遇到段错误。我认为这可能是由于页面大小,但是 getconf PAGE_SIZE
returns 4K,所以我不知道为什么需要 8K。
- 如果我将汇编文件中的
.text
部分更改为 .my_section_name
并将链接器更新为 .my_section_name : { *(.my_section_name*) }
我会遇到段错误。我认为 .text
、.data
等部分名称是约定俗成的,您可以根据需要随意命名。如果我错了,为什么 .text : { *(.my_section_name*) }
也会给出段错误?
0x10000
最小值可能是由于 vm.mmap_min_addr = 65536
(https://wiki.debian.org/mmap_min_addr) 的默认设置,阻止 user-space 映射任何 low-address 页面来制作确保 NULL-deref 会大声出错,即使对于像 ptr[i]
这样带有一些 medium-sized 索引的代码也是如此。
一些像 .text
这样的名字是特殊的(对于 NASM and/or ld),并且有一组默认的权限(在本例中为 read + exec)。一些随机名称可能是 read + write without exec。检查 readelf -a a.out
,特别是程序 Headers(它管理内核如何将可执行文件映射到内存)。
查看 readelf -a hello.o
以检查 NASM 输出中的 headers 部分也可能很有趣。
之前在 x86_64 上多次看到的基本 Hello World Linux:
global my_start_symbol
section .text
my_start_symbol:
mov rax, 1
mov rdi, 1
mov rsi, msg
mov rdx, msg_len
syscall
mov rax, 60
xor rdi, rdi
syscall
section .rodata:
msg: db "Hello, world!", 10
msg_len: equ $ - msg
我的工作 ld
链接描述文件:
ENTRY(my_start_symbol)
SECTIONS
{
. = 0x10000;
.text : { *(.text*) }
.rodata : { *(.rodata*) }
}
调用方式:
nasm -f elf64 assembly.asm -o assembly.o
ld -T linker.ld assembly.o -o assembly
当我尝试进行以下更改时遇到各种分段错误:
- 如果我删除链接描述文件中的
. = 0x10000
或使其小于0x10000
,我会遇到段错误。我认为这可能是由于页面大小,但是getconf PAGE_SIZE
returns 4K,所以我不知道为什么需要 8K。 - 如果我将汇编文件中的
.text
部分更改为.my_section_name
并将链接器更新为.my_section_name : { *(.my_section_name*) }
我会遇到段错误。我认为.text
、.data
等部分名称是约定俗成的,您可以根据需要随意命名。如果我错了,为什么.text : { *(.my_section_name*) }
也会给出段错误?
0x10000
最小值可能是由于 vm.mmap_min_addr = 65536
(https://wiki.debian.org/mmap_min_addr) 的默认设置,阻止 user-space 映射任何 low-address 页面来制作确保 NULL-deref 会大声出错,即使对于像 ptr[i]
这样带有一些 medium-sized 索引的代码也是如此。
一些像 .text
这样的名字是特殊的(对于 NASM and/or ld),并且有一组默认的权限(在本例中为 read + exec)。一些随机名称可能是 read + write without exec。检查 readelf -a a.out
,特别是程序 Headers(它管理内核如何将可执行文件映射到内存)。
查看 readelf -a hello.o
以检查 NASM 输出中的 headers 部分也可能很有趣。