Contenu connexe
Similaire à 【学習メモ#5th】12ステップで作る組込みOS自作入門 (20)
【学習メモ#5th】12ステップで作る組込みOS自作入門
- 5. オブジェクト・ファイル・フォー
マット
● これまで作成してきた実行形式ファイルは単な
るベタバイナリになっているわけではなく、内
部は特定のフォーマットで記述されている
– これを一般にオブジェクト・ファイル・フォーマッ
トと呼ぶ
● オブジェクト・ファイル・フォーマットはいく
つか種類があり、a.out形式やEXE形式、COFF形
式など存在するが、一般的なのはELF形式
- 6. ELF形式
● gccは標準でコンパイル・リンクで出力する
ファイルはELF形式で作成する
● ELF形式が一番扱いやすく問題ない形式らしい
- 7. リンクとリンカ
● 複数のオブジェクト・ファイルを結合して実行
形式ファイルを生成するのをリンクと言う
– リンクはリンカによって行われる
● 個々のオブジェクト・ファイルもELF形式で内
部のセクションの種類は実行形式ファイルと同
じ。
– それぞれが.dataや.textを持っている
● つまりリンクとは、そういった個々のオブジェ
クト・ファイルのセクションをまとめてひとつ
の実行形式ファイルにするやつ
- 8. セグメントとローダ
● セグメントはリンク後に生成される
– 実行形式ファイルになったときに生成される
● セグメントはローダで利用
● ローダとは、実行形式ファイルのイメージをメ
モリ上に展開する作業を行うプログラム
● ローダはメモリ上に展開するときに、セグメン
情報を見てその通りにメモリ上に展開する
– 展開するときはもちろんセグメント単位で行う
- 9. セクションとセグメントの違い
● セクションは実行形式ファイルを作成するリン
カのためにある
– 個々のオブジェクト・ファイルを結合して実行形式
ファイルを作成するために、といった方が良いかも
しれない
● セグメントはローダのためにある
– メモリ上に展開するときにセグメント情報の通りに
行う
– あとメモリ管理の方式の1つとしても利用されてい
ると思ったけどこれは汎用OSだけ?それともそれと
は違うセグメントのことか?調べてもわからんかっ
た
- 10. ELF形式の内部構造
● ELF形式のファイルは先頭にELFヘッダを持ち、
内部はセクションとセグメントでそれぞれ独立
した単位で分割されている
● セクションとセグメントの情報はセクション・
ヘッダ、プログラム・ヘッダというヘッダで管
理されている
– 具体的なイメージ図は次ページを参照
- 12. ELF形式のヘッダ情報
● ファイルの先頭はELFヘッダ
– プログラム・ヘッダ・テーブルやセクション・ヘッ
ダ・テーブルのアドレス位置やヘッダの個数などを
知ることができる
● その次にセグメントの情報を管理しているプロ
グラム・ヘッダ・テーブル
● 終端にセクション情報を管理しているセクショ
ン・ヘッダ・テーブル
- 13. セクション・ヘッダとプログラム・
ヘッダ
● ファイル内部ではセクション・ヘッダとプログ
ラム・ヘッダによってセクションとセグメント
はそれぞれ独立して区分けされ管理している
– 当然ヘッダ同士も独立している
● しかし先ほどの図を見る限りではセクションは
セグメントに含まれる構成となっている
● これは複数のセクションをひとつのセグメント
に含めることで、似た役割をもつセクションを
まとめてメモリ上に展開することができるから
– 必ずしもセクションがセグメントに含まれる必要は
ないが、こっちの方が便利ね
- 14. セクションとセグメントのまとめ
● セクションはリンカが、セグメントはローダが
参照するもの
● リンク前のオブジェクト・ファイルはセグメン
トを持たないし、プログラム・ヘッダもない
● リンク後の実行形式ファイルではセクションも
セグメントもあるが、この状態でセクションを
削っても実行に問題はない
● どっちも区分けしている感じが似ているけれ
ど、それぞれ役割や目的が違う
- 16. ELFヘッダ
● readelf -a kzload.elfで解析した結果を次の
ページに掲載
– 「ELF Header:」の部分がヘッダ領域
● ELFファイルの先頭に付加されるヘッダなので
ELFヘッダと呼ぶ
- 17. ELFヘッダ解析部分
ELF Header:
Magic: 7f 45 4c 46 01 02 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, big endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: Renesas H8/300
Version: 0x1
Entry point address: 0x282
Start of program headers: 52 (bytes into file)
Start of section headers: 2352 (bytes into file)
Flags: 0x810000
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 3
Size of section headers: 40 (bytes)
Number of section headers: 10
Section header string table index: 7
- 18. マジック・ナンバ
● ヘッダの先頭にある16バイトの識別領域である
Magicは、ELFフォーマットのバージョンやOSの
種別などが格納されている
– ファイルやデータの種別するために先頭に付加され
る数値データを一般にマジック・ナンバと呼ぶ
● 先頭4バイトには必ず「7f 45 4c 46」(0x7f
'E' 'L' 'F')というデータが格納されていて、
これを見ることでそのファイルがELF形式であ
ると判断することができる
- 20. マジック・ナンバがある理由
● 識別情報として最初に確認できるように先頭に
バイト単位で配置している
– これらの情報を識別した後でないとデータを正しく
読むことができないから
● 9~15のバイトは予約領域、リザーブ領域などと
呼ぶ
– 将来的にELF形式が拡張されて何か情報が追加され
ても問題ないように用意されている
- 22. セクション・ヘッダ・テーブル
● セクションの情報を管理しているヘッダの配列
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .vectors PROGBITS 00000000 000094 000100 00 WA 0 0 4
[ 2] .text PROGBITS 00000100 000194 000654 00 AX 0 0 2
[ 3] .rodata PROGBITS 00000754 0007e8 0000a4 00 A 0 0 4
[ 4] .data PROGBITS 00fffc20 00088c 000004 00 WA 0 0 4
[ 5] .bss NOBITS 00fffc24 000890 000014 00 WA 0 0 4
[ 6] .comment PROGBITS 00000000 000890 00005a 00 0 0 1
[ 7] .shstrtab STRTAB 00000000 0008ea 000046 00 0 0 1
[ 8] .symtab SYMTAB 00000000 000ac0 0006c0 10 9 76 4
[ 9] .strtab STRTAB 00000000 001180 000250 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings)
I (info), L (link order), G (group), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)
- 24. セクション・ヘッダ解説
● セクション名は可変長なのでヘッダにそのまま
格納されていない
– .shstrtabセクションにまとめて格納
● 重要なのはアドレス(Addr)、セクションの位置
(Off)、セクションのサイズ(size)
● アドレスはセクションが配置されている位置
– いわゆるVAにあたる。.dataや.bssはRAM上に配置さ
れているアドレス
● セクションの位置やサイズは、ELFファイル内
でどの部分がそのセクションとなるかを表して
いる
- 25. プログラム・ヘッダ・テーブル
● セグメントの情報を管理しているヘッダの配列
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000094 0x00000000 0x00000000 0x00100 0x00100 RW 0x1
LOAD 0x000194 0x00000100 0x00000100 0x006f8 0x006f8 R E 0x1
LOAD 0x00088c 0x00fffc20 0x000007f8 0x00004 0x00018 RW 0x1
Section to Segment mapping:
Segment Sections...
00 .vectors
01 .text .rodata
02 .data .bss
- 27. プログラム・ヘッダ解説
● Type
– LOADはメモリ上にロードされるセグメントというこ
と。他に、動的リンク情報やプログラム・ヘッダ自
身がある
● Offset
– ELFファイルの内部でのセグメント位置
● FilSiz、MemSiz
– ファイル中のサイズと、メモリ上のサイズ
– 必ずしも同じ大きさではない
- 29. プログラムの修正と追加
● 追加ファイル
– elf.h、elf.c...ELF形式の解析
● 修正ファイル
– main.c...ELF形式の解析コマンド追加
– Makefile...elf.oをコンパイル対象にする
● 修正部分はrunコマンド追加しただけ
– ELFファイルのうち、セグメント情報を表示するコ
マンド
- 30. elf.c
● 今回はkzload.elfのセグメント情報をターミナ
ルに表示するプログラムになっている
● 構造体が大きいのでわかりにくい
– 構造体はELFヘッダの部分と、プログラムヘッダの
部分を取得する感じになっている
– その構造体のデータを表示するだけ
● たぶん次からELFファイルをメモリに展開する
プログラムになるんだと思う
- 31. セクション・ヘッダが末尾の理由
● プログラム・ヘッダがELFファイルの先頭付近
にあるのは、ファイルをダウンロードしながら
メモリにロードできるようにするため
– バッファ領域が小さいときはこういった形になる
● メモリの配置先情報を最初に確認できるように
してるわけ
● セクション・ヘッダが末尾なのはロードに必要
ないから。サイズ節約やメモリ節約のときに、
セクション・ヘッダを捨てやすくしてる
– 末尾にあったらオフセットを計算しなおしたり、面
倒なことせずにすむ
- 33. まとめ
● ELF形式のファイルの内部構造を解析できるよ
うになった
● 具体的には内部におけるそれぞれのヘッダを操
作できるようになった
● セグメント・ヘッダの取得はできるようになっ
たので、それを元に内容をメモリ上に展開する
プログラムを書くことになるのかな
● あ、あと書籍では論理回路について解説してい
るページがあるけど、ここでは省く