ELFファイルを作る part2
part1では単純なELFファイルを作る際に埋め込む為の、極めて小さいアセンブラのコードを作りました。
なので、次はそのコードを入れる為の、ELFに則ったバイナリを作成する。
目標
ELFに則ったバイナリを作成し、その中にpart1で作成したコードを入れ、動作させてみる
実装
基本的にはこれも先の参考元と同様なコードを書く。
違いは64bit用にいくつかの値を変更してるだけ。
コード
db, dw, dd, dqは疑似命令(pseudo-instruction)で、それぞれが指定するバイト数だけの領域を確保してオペランドで指定した値を初期値として格納することになります。この辺りはこちらを参照
ELFヘッダーが各バイトへ格納するべき値を示す構造体の定義は/usr/include/linux/elf.hに記述されており、自分の環境では以下の通り。
typedef struct elf64_hdr { unsigned char e_ident[EI_NIDENT]; /* ELF "magic number" */ Elf64_Half e_type; Elf64_Half e_machine; Elf64_Word e_version; Elf64_Addr e_entry; /* Entry point virtual address */ Elf64_Off e_phoff; /* Program header table file offset */ Elf64_Off e_shoff; /* Section header table file offset */ Elf64_Word e_flags; Elf64_Half e_ehsize; Elf64_Half e_phentsize; Elf64_Half e_phnum; Elf64_Half e_shentsize; Elf64_Half e_shnum; Elf64_Half e_shstrndx; } Elf64_Ehdr;
コードの方にもコメントで対応が書いてあるので、特に説明は不要かと。
参考元と異なる所としては、e_machineの値がx86-64を示す0x3eになっているくらい。
セクションヘッダは無いのでe_shnumは0が入っており、後のコードにもセクションヘッダについての記述は無い。
プログラムヘッダの構造体についても同ファイルに記述がある。ELFヘッダは32bitと64bitでニーモニックの順番は変わらなかったけど、プログラムヘッダは順番が変わってる箇所があるので注意。
これらのヘッダに続いてpart1で作成したコードを挿入し、filesizeの値を指定して完了。
実行
$ nasm -f bin -o a.out elf64-base.s $ chmod +x a.out $ ./a.out $ echo $? 42
期待された値を得られた。