ELFを解析してみる(3)

64bit版で動いた

やった。プログラムヘッダの部分が 32bit 版と順番ちょいと違いましたね。以下はカレントディレクトリを表示して、なおかつ返り値を69とするプログラム。カレントディレクトリは表示にゴミが混じったり、階層が深い場合は文字数不足でセグフォが起きるかもしれません。

bits 64
; org 0x08048000
org 0x114514000
; e_ident[]
elf_header:
db 0x7F,"ELF" ; magic numbers
db 2, 1, 1 ; 64bit, little endian, current ELF version
db 0, 0 ; No ABI, ABI version 0
db 0, 0, 0, 0, 0, 0, 0 ; zero-padding
dw 2, 62 ; executable file, x64 machine
dd 1 ; current object version
dq _start
dq program_header - $$ ; program header offset
dq 0 ; section header offset
dd 0 ; flags(zero)
dw elf_header_size
dw program_header_size
dw 1 ; progra header number
dw 0, 0, 0 ; section header(none)

elf_header_size equ $ - elf_header

program_header:
dd 1 ; loadable segment
dq 5 ; readable & executable segment NOTE: The location of this segment differs in x86.
dd 0 ; segment offset
dq $$ ; first segment virtual address
dq 0 ; reserved
dq filesize, filesize
dq 0x1000 ; align(what!?)

program_header_size equ $ - program_header

_WRITE equ 1
_EXIT equ 60
_GETCWD equ 79

SP_SHIFT equ 50

LF: db 0xA

_start:
    ; getcwdの為にメモリ領域確保
    sub rsp, SP_SHIFT ; 決め打ちで50byte確保

    mov rax, _GETCWD
    mov rdi, rsp ; 文字列格納先の先頭アドレス
    mov rsi, SP_SHIFT ; 50文字分
    syscall

    mov rax, _WRITE
    mov rsi, rdi
    mov rdi, 1
    mov rdx, SP_SHIFT
    syscall ; よく分からんが、実行後に各種レジスタ値は変化する
    add rsp, SP_SHIFT ; スタックを戻す

    mov rax, _WRITE
    mov rsi, LF
    mov rdi, 1
    mov rdx, 1
    syscall

    mov rax, _EXIT
    mov rdi, 69
    syscall

filesize equ $ - $$

という訳で短いですが以上です。セクションヘッダ等も時間があったらやってみたい。ともかくも今はモチベがちょいと低いので一旦おしまいですかね〜〜