【发布时间】:2014-03-29 04:35:24
【问题描述】:
来自 Portable Executable 和 Windows 我正在尝试在 Linux (Ubuntu AMD64) 中使用 NASM 创建一个小型 ELF 可执行文件。我的一小段代码如下所示:
BITS 64
; The default virtual address where the executable is linked
_START_VAD equ 0x400000
; Here I write the header byte by byte
ELF_HEADER:
.ident_magic db 0x7f, "ELF"
.ident_class db 2
.ident_data db 1
.ident_version db 1
.ident_osabi db 0
.ident_abiversion db 0
; Pad with zeros until we have 16 bytes for the identifier
times 16-$+ELF_HEADER db 0
.object_type dw 2
.machine dw 0x3e
.version dd 1
.entry_point dq _START_VAD + START
.progr_header dq PROGRAM_HEADER
.sect_header dq SECTIONS_HEADER
.proc_flags dd 0
.header_size dw ELF_HEADER_END - ELF_HEADER
.progr_header_size dw 56
.progr_header_entries dw 3
.sect_header_size dw 64
.sect_header_entries dw 4
.sect_header_index dw 3
ELF_HEADER_END:
PROGRAM_HEADER:
HEADER_SEGMENT_HEADER:
HEADER_SEGMENT_SIZE equ PROGRAM_HEADER_END - PROGRAM_HEADER
.header_segment_type dd 6
.header_segment_flag dd 0x1 | 0x4
.header_segment_offs dq PROGRAM_HEADER
.header_segment_vadr dq _START_VAD + PROGRAM_HEADER
.header_segment_padr dq _START_VAD + PROGRAM_HEADER
.header_segment_file dq HEADER_SEGMENT_SIZE
.header_segment_mems dq HEADER_SEGMENT_SIZE
.header_segment_alig dq 8
INTEPRETER_SEGMENT_HEADER:
INTERP_SEGMENT_SIZE equ INTERPRETER_SEGMENT_END - INTERPRETER_SEGMENT
.interp_segment_type dd 3
.interp_segment_flag dd 0x4
.interp_segment_offs dq INTERPRETER_SEGMENT
.interp_segment_vadr dq _START_VAD + INTERPRETER_SEGMENT
.interp_segment_padr dq _START_VAD + INTERPRETER_SEGMENT
.interp_segment_file dq INTERP_SEGMENT_SIZE
.interp_segment_mems dq INTERP_SEGMENT_SIZE
.interp_segment_alig dq 1
CODE_SEGMENT_HEADER:
CODE_SEGMENT_SIZE equ START_END - ELF_HEADER
.code_segment_type dd 1
.code_segment_flag dd 0x1 | 0x4
.code_segment_offs dq 0
.code_segment_vadr dq _START_VAD
.code_segment_padr dq _START_VAD
.code_segment_file dq CODE_SEGMENT_SIZE
.code_segment_mems dq CODE_SEGMENT_SIZE
.code_segment_alig dq 0x200000
PROGRAM_HEADER_END:
INTERPRETER_SEGMENT:
.intepreter_path db "/lib64/ld-linux-x86-64.so.2", 0
INTERPRETER_SEGMENT_END:
START:
mov rax, 1 ; sys_write
mov rdi, 1 ; stdout
mov rsi, _START_VAD + message ; message address
mov rdx, length ; message string length
syscall
mov rax, 60 ; sys_exit
mov rdi, 0 ; return 0 (success)
syscall
message:
db 'Hello, world!',0x0A ; message and newline
length: equ $-message ; message length calculation
START_END:
SECTIONS_STRING_TABLE:
NULL_SECTION_NAME: db 0
STR_TABLE_SECTION_NAME: db ".shstrtab", 0
INTERP_SECTION_NAME: db ".interp", 0
TEXT_SECTION_NAME: db ".text", 0
SECTIONS_STRING_TABLE_END:
SECTIONS_HEADER:
RESERVED_SECTION:
.reserved_sh_name dd 0
.reserved_type dd 0
.reserved_flags dq 0
.reserved_vaddr dq 0
.reserved_offs dq 0
.reserved_size dq 0
.reserved_link dd 0
.reserved_info dd 0
.reserved_alig dq 0
.reserved_ents dq 0
INTERPRETER_SECTION:
.reserved_sh_name dd INTERP_SECTION_NAME - SECTIONS_STRING_TABLE
.reserved_type dd 1
.reserved_flags dq 0x2
.reserved_vaddr dq _START_VAD + INTERPRETER_SEGMENT
.reserved_offs dq INTERPRETER_SEGMENT
.reserved_size dq INTERPRETER_SEGMENT_END - INTERPRETER_SEGMENT
.reserved_link dd 0
.reserved_info dd 0
.reserved_alig dq 1
.reserved_ents dq 0
TEXT_SECTION:
.reserved_sh_name dd TEXT_SECTION_NAME - SECTIONS_STRING_TABLE
.reserved_type dd 1
.reserved_flags dq 0x2 | 0x4
.reserved_vaddr dq _START_VAD + START
.reserved_offs dq START
.reserved_size dq START_END - START
.reserved_link dd 0
.reserved_info dd 0
.reserved_alig dq 16
.reserved_ents dq 0
STRINGTABLE_SECTION:
.reserved_sh_name dd STR_TABLE_SECTION_NAME - SECTIONS_STRING_TABLE
.reserved_type dd 3
.reserved_flags dq 0
.reserved_vaddr dq 0
.reserved_offs dq SECTIONS_STRING_TABLE
.reserved_size dq SECTIONS_STRING_TABLE_END - SECTIONS_STRING_TABLE
.reserved_link dd 0
.reserved_info dd 0
.reserved_alig dq 1
.reserved_ents dq 0
SECTIONS_HEADER_END:
我使用 NASM 将其转换为 ELF 文件并使用 READELF 获取此信息:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x400104
Start of program headers: 64 (bytes into file)
Start of section headers: 363 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 3
Size of section headers: 64 (bytes)
Number of section headers: 4
Section header string table index: 3
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .interp PROGBITS 00000000004000e8 000000e8
000000000000001c 0000000000000000 A 0 0 1
[ 2] .text PROGBITS 0000000000400104 00000104
000000000000004e 0000000000000000 AX 0 0 16
[ 3] .shstrtab STRTAB 0000000000000000 00000152
0000000000000019 0000000000000000 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), l (large)
I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)
There are no section groups in this file.
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
PHDR 0x0000000000000040 0x0000000000400040 0x0000000000400040
0x00000000000000a8 0x00000000000000a8 R E 8
INTERP 0x00000000000000e8 0x00000000004000e8 0x00000000004000e8
0x000000000000001c 0x000000000000001c R 1
[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000
0x0000000000000152 0x0000000000000152 R E 200000
Section to Segment mapping:
Segment Sections...
00
01 .interp
02 .interp .text
There is no dynamic section in this file.
There are no relocations in this file.
There are no unwind sections in this file.
No version information found in this file.
我不确定其中是否正确,特别是 LOAD 段及其大小。
当我运行它时,我得到Segmentation Fault (core dumped)。调试器会告诉我更多信息:
warning: no loadable sections found in added symbol-file system-supplied DSO at 0x7ffff7ffa000
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7de5be2 in ?? () from /lib64/ld-linux-x86-64.so.2
(gdb)
我不知道缺少哪些段或部分,或者哪些偏移量/地址有误。也许在 ELF 和 Linux 加载器方面有更多经验的人会给我一点推动,因为我真的被卡住了。
【问题讨论】:
-
你读过Linux Assembly HowTo吗?一般来说,避免使用手写汇编程序进行编码。编译器优化得比你我都好。
-
我知道,但这只是为了教育目的。如果我要构建一些严肃的应用程序,我当然会使用 C++(或其他一些高级语言)
标签: linux debugging build segmentation-fault elf