使用自定义链接描述文件了解简单的"Hello World"的分段错误-段名称或基址低于64k [英] Understanding Segmentation Faults with a custom linker script for a simple 'Hello World' - section names or base address below 64k

查看:58
本文介绍了使用自定义链接描述文件了解简单的"Hello World"的分段错误-段名称或基址低于64k的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

x86_64 Linux上多次见过的基本Hello World:

Basic Hello World as seen many times before on x86_64 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 链接描述文件:

My working ld linker script:

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

尝试以下更改时会遇到各种细分错误:

I get various segmentation faults when I experiment with the following changes:

  1. 如果我删除了.= 0x10000 在我的链接描述文件中,或者使其小于 0x10000 的任何值,我都会遇到段错误.我以为这可能是由于页面大小所致,但是 getconf PAGE_SIZE 返回4K,所以我不知道为什么8K是必要的.
  2. 如果我在程序集文件中将 .text 部分更改为 .my_section_name 并更新链接器以显示 .my_section_name:{*(.my_section_name *)} 我遇到了段错误.我认为像 .text .data 等这样的节名称是按惯例编写的,您可以根据需要将其设置为任意名称.如果我错了,为什么 .text:{*(.my_section_name *)} 也会出现段错误?
  1. If I remove the . = 0x10000 inside of my linker script or make it anything less than 0x10000 I get a segfault. I thought this may be due to page size, however getconf PAGE_SIZE returns 4K, so I don't know why 8K is necessary.
  2. If I change the .text section in my assembly file to say .my_section_name and update the linker to say .my_section_name : { *(.my_section_name*) } I get a segfault. I thought the section names like .text, .data etc. were by convention, and that you could make them anything you wanted. If I'm wrong, why would .text : { *(.my_section_name*) } give a segfault also?

推荐答案

0x10000 的最小值可能是由于 vm.mmap_min_addr = 65536 ( https://wiki.debian.org/mmap_min_addr ),以防止用户空间映射任何低地址页面确保即使在 ptr [i] 之类的代码具有中等索引的情况下,也能确保NULL-deref发出错误的声音.

The 0x10000 minimum is probably due to the default setting of vm.mmap_min_addr = 65536 (https://wiki.debian.org/mmap_min_addr), preventing user-space from mapping any low-address pages to make sure that NULL-deref faults noisily, even for code like ptr[i] with some medium-sized index.

一些名称,例如 .text 是特殊的(对于NASM和/或ld),并且具有一组默认的权限(在这种情况下为read + exec).一些随机名称可能是不带exec的读写.检查 readelf -a a.out ,尤其是程序标头(控制内核如何将可执行程序映射到内存中).

A few names like .text are special (for NASM and/or ld), and have a default set of permissions (in this case read + exec). Some random name is probably read + write without exec. Check with readelf -a a.out, epsecially the Program Headers (which govern how an executable is mapped into memory by the kernel).

看看 readelf -a hello.o 来检查NASM输出中的节头可能也很有趣.

Also probably interesting to have a look at readelf -a hello.o to check the section headers in the NASM output.

这篇关于使用自定义链接描述文件了解简单的"Hello World"的分段错误-段名称或基址低于64k的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆