【发布时间】:2021-08-19 16:15:10
【问题描述】:
我一直在使用 NASM 编写 ELF 二进制文件,并且我创建了一个打开了只读标志的段。运行程序会导致段错误。我在 replit 中测试了该程序,它运行得很好,那么问题是什么?我用 .rodata 部分中的 hello world 字符串创建了一个常规的 NASM hello world 程序,并且运行良好。我用 readelf 检查了二进制文件以确保字符串在只读段中。
我想出的唯一解决方案是在rodata 段中设置可执行标志,使其具有读取/执行权限,但这很麻烦,我希望rodata 段是只读的。
这是 ELF-64 hello world 的代码。
; hello.asm
[bits 64]
[org 0x400000]
fileHeader:
db 0x7F, "ELF"
db 2 ; ELF-64
db 1 ; little endian
db 1 ; ELF version
db 0 ; System V ABI
db 0 ; ABI version
db 0, 0, 0, 0, 0, 0, 0 ; unused
dw 2 ; executable object file
dw 0x3E ; x86-64
dd 1 ; ELF version
dq text ; entry point
dq 64 ; program header table offset
dq nullSection - $$ ; section header table offset
dd 0 ; flags
dw 64 ; size of file header
dw 56 ; size of program header
dw 3 ; program header count
dw 64 ; size of section header
dw 4 ; section header count
dw 3 ; section header string table index
nullSegment:
times 56 db 0
textSegment:
dd 1 ; loadable segment
dd 0x4 ; read / execute permissions
dq text - $$ ; segment offset
dq text ; virtual address of segment
dq 0 ; physical address of segment
dq textSize ; size of segment in file
dq textSize ; size of segment in memory
dq 0x1000 ; alignment
rodataSegment:
dd 1 ; loadable segment
dd 0x4 ; read permission (setting this flag to 0x5 causes the program to run just fine)
dq rodata - $$ ; segment offset
dq rodata ; virtual address of segment
dq 0 ; physical address of segment
dq rodataSize ; size of segment in file
dq rodataSize ; size of segment in memory
dq 0x1000 ; alignment
text:
mov rax, 1
mov rdi, 1
mov rsi, message
mov rdx, messageLength
syscall
mov rax, 60
xor rdi, rdi
syscall
textSize equ $ - text
rodata:
message db "Hello world!", 0xA, 0
messageLength equ $ - message
rodataSize equ $ - rodata
stringTable:
db 0
db ".text", 0
db ".rodata", 0
db ".shstrtab", 0
stringTableSize equ $ - stringTable
nullSection:
times 64 db 0
textSection:
dd 1 ; index into string table
dd 1 ; program data
dq 0x6 ; occupies memory & executable
dq text ; virtual address of section
dq text - $$ ; offset of section in file
dq textSize ; size of section in file
dq 0 ; unused
dq 0x1000 ; alignment
dq 0 ; unused
rodataSection:
dd 7 ; index into string table
dd 1 ; program data
dq 0x2 ; occupies memory
dq rodata ; virtual address of section
dq rodata - $$ ; offset of section in file
dq rodataSize ; size of section in file
dq 0 ; unused
dq 0x1000 ; no alignment
dq 0 ; unused
stringTableSection:
dd 15 ; index into string table
dd 3 ; string table
dq 0 ; no attributes
dq stringTable ; virtual address of section
dq stringTable - $$ ; offset of section in file
dq stringTableSize ; size of section in file
dq 0 ; unused
dq 0 ; no alignment
dq 0 ; unused
replitHello.asm: https://hastebin.com/ujanoguveq.properties // 它应该是几乎同一行
这是最小的 nasm hello world 程序。
; helloNasm.asm
section .text
global _start
_start:
mov rax, 1
mov rdi, 1
mov rsi, message
mov rdx, messageLength
syscall
mov rax, 60
xor rdi, rdi
syscall
section .rodata
message db "Hello NASM!", 0xA, 0
messageLength equ $ - message
【问题讨论】:
-
“呃,0000000000400000 处的精灵段已请求但内存已映射”
-
@Jester 我不明白你在说什么。
-
这就是内核所说的:) 无论如何,看起来您尝试将rodata 和文本映射到具有不同权限的同一页面。将rodata移到虚拟地址空间中。
-
请创建一个minimal reproducible example 并在此处发布所有代码。人们不会点击外部链接,并且这些链接容易发生链接失效,从而使问题无效
-
@phuclv 我在这里内联了代码,我仍然把a留给replit代码,因为它基本上是一样的,这是我能得到的最小的。