Basic Hello World as seen many times before on x86_64 Linux:
global my_start_symbol section .my_section 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
My current ld
linker script:
__linux_mmap_min_addr = 0x10000; ENTRY(my_start_symbol) MEMORY { rom (rx) : ORIGIN = 0, LENGTH = 512K } SECTIONS { . = __linux_mmap_min_addr; .my_section : { *(.my_section*) } > rom .rodata : { *(.rodata*) } > rom }
Invoked with:
nasm -f elf64 assembly.asm -o assembly.o ld -T linker.ld assembly.o -o assembly
I’m currently getting a segfault. Inspecting the output of readelf -a
I can see that my_section
does not have executable permissions. I believe this is causing the segfault. If I replace it with .text : { *(.my_section*) } > rom
it still does not get set as executable. Only if I revert to using .text
everywhere as is convention, does it set it as executable.
Advertisement
Answer
My assessments (at least on x86_64 Linux with NASM):
- The flags set in
ld
MEMORY
definition are irrelevant in setting the section to executable. The NASM ELF Section extensions are what matter, i.e.section .my_section exec
will work even ifMEMORY
does not havex
flag (thanks to @peter-cordes). - If you have specific
ld
MEMORY
definitions that you are using, the origin cannot be0
, but must be at least0x10000
(see this S.O q&a for more info) Using. = 0x10000;
at the start of the section is not sufficient.