Deprecated: The each() function is deprecated. This message will be suppressed on further calls in /home/zhenxiangba/zhenxiangba.com/public_html/phproxy-improved-master/index.php on line 456
【学習メモ#5th】12ステップで作る組込みOS自作入門 | PDF
[go: Go Back, main page]

12ステップで作る組込みOS自作入門
      5thステップ




                @sandai
【参考書籍】
12ステップで作る組込みOS自作入門
【内容】
1ステップずつ、実際に動かしながらプログラムを発展さ
せていく方式で無理なく学べる。OSやハードウェアに詳
しくない方にも理解できるよう
に十分な説明を提供

坂井 弘亮(著)
カットシステム(2010/5)

【税込価格】
4,410円

【サポートページ】
http://kozos.jp/books/makeos/
もくじ
1.ELF形式
2.各種ヘッダ解説
3.プログラムの修正と追加と実行
4.まとめ
1.ELF形式
オブジェクト・ファイル・フォー
          マット
●   これまで作成してきた実行形式ファイルは単な
    るベタバイナリになっているわけではなく、内
    部は特定のフォーマットで記述されている
    –   これを一般にオブジェクト・ファイル・フォーマッ
        トと呼ぶ
●   オブジェクト・ファイル・フォーマットはいく
    つか種類があり、a.out形式やEXE形式、COFF形
    式など存在するが、一般的なのはELF形式
ELF形式
●   gccは標準でコンパイル・リンクで出力する
    ファイルはELF形式で作成する
●   ELF形式が一番扱いやすく問題ない形式らしい
リンクとリンカ
●   複数のオブジェクト・ファイルを結合して実行
    形式ファイルを生成するのをリンクと言う
    –   リンクはリンカによって行われる
●   個々のオブジェクト・ファイルもELF形式で内
    部のセクションの種類は実行形式ファイルと同
    じ。
    –   それぞれが.dataや.textを持っている
●   つまりリンクとは、そういった個々のオブジェ
    クト・ファイルのセクションをまとめてひとつ
    の実行形式ファイルにするやつ
セグメントとローダ
●   セグメントはリンク後に生成される
    –   実行形式ファイルになったときに生成される
●   セグメントはローダで利用
●   ローダとは、実行形式ファイルのイメージをメ
    モリ上に展開する作業を行うプログラム
●   ローダはメモリ上に展開するときに、セグメン
    情報を見てその通りにメモリ上に展開する
    –   展開するときはもちろんセグメント単位で行う
セクションとセグメントの違い
●   セクションは実行形式ファイルを作成するリン
    カのためにある
    –   個々のオブジェクト・ファイルを結合して実行形式
        ファイルを作成するために、といった方が良いかも
        しれない
●   セグメントはローダのためにある
    –   メモリ上に展開するときにセグメント情報の通りに
        行う
    –   あとメモリ管理の方式の1つとしても利用されてい
        ると思ったけどこれは汎用OSだけ?それともそれと
        は違うセグメントのことか?調べてもわからんかっ
        た
ELF形式の内部構造
●   ELF形式のファイルは先頭にELFヘッダを持ち、
    内部はセクションとセグメントでそれぞれ独立
    した単位で分割されている
●   セクションとセグメントの情報はセクション・
    ヘッダ、プログラム・ヘッダというヘッダで管
    理されている
    –   具体的なイメージ図は次ページを参照
ELF形式の内部構造の図




169頁 図5.1 ELF形式の内部構造 より
ELF形式のヘッダ情報
●   ファイルの先頭はELFヘッダ
    –   プログラム・ヘッダ・テーブルやセクション・ヘッ
        ダ・テーブルのアドレス位置やヘッダの個数などを
        知ることができる
●   その次にセグメントの情報を管理しているプロ
    グラム・ヘッダ・テーブル
●   終端にセクション情報を管理しているセクショ
    ン・ヘッダ・テーブル
セクション・ヘッダとプログラム・
      ヘッダ
●   ファイル内部ではセクション・ヘッダとプログ
    ラム・ヘッダによってセクションとセグメント
    はそれぞれ独立して区分けされ管理している
    –   当然ヘッダ同士も独立している
●   しかし先ほどの図を見る限りではセクションは
    セグメントに含まれる構成となっている
●   これは複数のセクションをひとつのセグメント
    に含めることで、似た役割をもつセクションを
    まとめてメモリ上に展開することができるから
    –   必ずしもセクションがセグメントに含まれる必要は
        ないが、こっちの方が便利ね
セクションとセグメントのまとめ
●   セクションはリンカが、セグメントはローダが
    参照するもの
●   リンク前のオブジェクト・ファイルはセグメン
    トを持たないし、プログラム・ヘッダもない
●   リンク後の実行形式ファイルではセクションも
    セグメントもあるが、この状態でセクションを
    削っても実行に問題はない
●   どっちも区分けしている感じが似ているけれ
    ど、それぞれ役割や目的が違う
2.各種ヘッダ解説
ELFヘッダ
●   readelf -a kzload.elfで解析した結果を次の
    ページに掲載
    –   「ELF Header:」の部分がヘッダ領域
●   ELFファイルの先頭に付加されるヘッダなので
    ELFヘッダと呼ぶ
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
マジック・ナンバ
●   ヘッダの先頭にある16バイトの識別領域である
    Magicは、ELFフォーマットのバージョンやOSの
    種別などが格納されている
    –   ファイルやデータの種別するために先頭に付加され
        る数値データを一般にマジック・ナンバと呼ぶ
●   先頭4バイトには必ず「7f 45 4c 46」(0x7f
    'E' 'L' 'F')というデータが格納されていて、
    これを見ることでそのファイルがELF形式であ
    ると判断することができる
マジック・ナンバの識別情報
●   それぞれのバイトデータの意味は以下の通り




     171頁 図5.1 先頭16バイトの識別情報 より
マジック・ナンバがある理由
●   識別情報として最初に確認できるように先頭に
    バイト単位で配置している
    –   これらの情報を識別した後でないとデータを正しく
        読むことができないから
●   9~15のバイトは予約領域、リザーブ領域などと
    呼ぶ
    –   将来的にELF形式が拡張されて何か情報が追加され
        ても問題ないように用意されている
その他のELFヘッダの意味




172頁 表5.2 ELFヘッダの意味 より
セクション・ヘッダ・テーブル
 ●   セクションの情報を管理しているヘッダの配列
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)
セクション・ヘッダの項目




174頁 表5.3 セクション・ヘッダの意味 より
セクション・ヘッダ解説
●   セクション名は可変長なのでヘッダにそのまま
    格納されていない
    –   .shstrtabセクションにまとめて格納
●   重要なのはアドレス(Addr)、セクションの位置
    (Off)、セクションのサイズ(size)
●   アドレスはセクションが配置されている位置
    –   いわゆるVAにあたる。.dataや.bssはRAM上に配置さ
        れているアドレス
●   セクションの位置やサイズは、ELFファイル内
    でどの部分がそのセクションとなるかを表して
    いる
プログラム・ヘッダ・テーブル
 ●   セグメントの情報を管理しているヘッダの配列
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
プログラム・ヘッダの項目




176頁 表5.4 プログラム・ヘッダの意味 より
プログラム・ヘッダ解説
●   Type
    –   LOADはメモリ上にロードされるセグメントというこ
        と。他に、動的リンク情報やプログラム・ヘッダ自
        身がある
●   Offset
    –   ELFファイルの内部でのセグメント位置
●   FilSiz、MemSiz
    –   ファイル中のサイズと、メモリ上のサイズ
    –   必ずしも同じ大きさではない
3.プログラムの修正と追加と実行
プログラムの修正と追加
●   追加ファイル
    –   elf.h、elf.c...ELF形式の解析
●   修正ファイル
    –   main.c...ELF形式の解析コマンド追加
    –   Makefile...elf.oをコンパイル対象にする
●   修正部分はrunコマンド追加しただけ
    –   ELFファイルのうち、セグメント情報を表示するコ
        マンド
elf.c
●   今回はkzload.elfのセグメント情報をターミナ
    ルに表示するプログラムになっている
●   構造体が大きいのでわかりにくい
    –   構造体はELFヘッダの部分と、プログラムヘッダの
        部分を取得する感じになっている
    –   その構造体のデータを表示するだけ
●   たぶん次からELFファイルをメモリに展開する
    プログラムになるんだと思う
セクション・ヘッダが末尾の理由
●   プログラム・ヘッダがELFファイルの先頭付近
    にあるのは、ファイルをダウンロードしながら
    メモリにロードできるようにするため
    –   バッファ領域が小さいときはこういった形になる
●   メモリの配置先情報を最初に確認できるように
    してるわけ
●   セクション・ヘッダが末尾なのはロードに必要
    ないから。サイズ節約やメモリ節約のときに、
    セクション・ヘッダを捨てやすくしてる
    –   末尾にあったらオフセットを計算しなおしたり、面
        倒なことせずにすむ
4.まとめ
まとめ
●   ELF形式のファイルの内部構造を解析できるよ
    うになった
●   具体的には内部におけるそれぞれのヘッダを操
    作できるようになった
●   セグメント・ヘッダの取得はできるようになっ
    たので、それを元に内容をメモリ上に展開する
    プログラムを書くことになるのかな
●   あ、あと書籍では論理回路について解説してい
    るページがあるけど、ここでは省く

【学習メモ#5th】12ステップで作る組込みOS自作入門

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
    オブジェクト・ファイル・フォー マット ● これまで作成してきた実行形式ファイルは単な るベタバイナリになっているわけではなく、内 部は特定のフォーマットで記述されている – これを一般にオブジェクト・ファイル・フォーマッ トと呼ぶ ● オブジェクト・ファイル・フォーマットはいく つか種類があり、a.out形式やEXE形式、COFF形 式など存在するが、一般的なのはELF形式
  • 6.
    ELF形式 ● gccは標準でコンパイル・リンクで出力する ファイルはELF形式で作成する ● ELF形式が一番扱いやすく問題ない形式らしい
  • 7.
    リンクとリンカ ● 複数のオブジェクト・ファイルを結合して実行 形式ファイルを生成するのをリンクと言う – リンクはリンカによって行われる ● 個々のオブジェクト・ファイルもELF形式で内 部のセクションの種類は実行形式ファイルと同 じ。 – それぞれが.dataや.textを持っている ● つまりリンクとは、そういった個々のオブジェ クト・ファイルのセクションをまとめてひとつ の実行形式ファイルにするやつ
  • 8.
    セグメントとローダ ● セグメントはリンク後に生成される – 実行形式ファイルになったときに生成される ● セグメントはローダで利用 ● ローダとは、実行形式ファイルのイメージをメ モリ上に展開する作業を行うプログラム ● ローダはメモリ上に展開するときに、セグメン 情報を見てその通りにメモリ上に展開する – 展開するときはもちろんセグメント単位で行う
  • 9.
    セクションとセグメントの違い ● セクションは実行形式ファイルを作成するリン カのためにある – 個々のオブジェクト・ファイルを結合して実行形式 ファイルを作成するために、といった方が良いかも しれない ● セグメントはローダのためにある – メモリ上に展開するときにセグメント情報の通りに 行う – あとメモリ管理の方式の1つとしても利用されてい ると思ったけどこれは汎用OSだけ?それともそれと は違うセグメントのことか?調べてもわからんかっ た
  • 10.
    ELF形式の内部構造 ● ELF形式のファイルは先頭にELFヘッダを持ち、 内部はセクションとセグメントでそれぞれ独立 した単位で分割されている ● セクションとセグメントの情報はセクション・ ヘッダ、プログラム・ヘッダというヘッダで管 理されている – 具体的なイメージ図は次ページを参照
  • 11.
  • 12.
    ELF形式のヘッダ情報 ● ファイルの先頭はELFヘッダ – プログラム・ヘッダ・テーブルやセクション・ヘッ ダ・テーブルのアドレス位置やヘッダの個数などを 知ることができる ● その次にセグメントの情報を管理しているプロ グラム・ヘッダ・テーブル ● 終端にセクション情報を管理しているセクショ ン・ヘッダ・テーブル
  • 13.
    セクション・ヘッダとプログラム・ ヘッダ ● ファイル内部ではセクション・ヘッダとプログ ラム・ヘッダによってセクションとセグメント はそれぞれ独立して区分けされ管理している – 当然ヘッダ同士も独立している ● しかし先ほどの図を見る限りではセクションは セグメントに含まれる構成となっている ● これは複数のセクションをひとつのセグメント に含めることで、似た役割をもつセクションを まとめてメモリ上に展開することができるから – 必ずしもセクションがセグメントに含まれる必要は ないが、こっちの方が便利ね
  • 14.
    セクションとセグメントのまとめ ● セクションはリンカが、セグメントはローダが 参照するもの ● リンク前のオブジェクト・ファイルはセグメン トを持たないし、プログラム・ヘッダもない ● リンク後の実行形式ファイルではセクションも セグメントもあるが、この状態でセクションを 削っても実行に問題はない ● どっちも区分けしている感じが似ているけれ ど、それぞれ役割や目的が違う
  • 15.
  • 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形式であ ると判断することができる
  • 19.
    マジック・ナンバの識別情報 ● それぞれのバイトデータの意味は以下の通り 171頁 図5.1 先頭16バイトの識別情報 より
  • 20.
    マジック・ナンバがある理由 ● 識別情報として最初に確認できるように先頭に バイト単位で配置している – これらの情報を識別した後でないとデータを正しく 読むことができないから ● 9~15のバイトは予約領域、リザーブ領域などと 呼ぶ – 将来的にELF形式が拡張されて何か情報が追加され ても問題ないように用意されている
  • 21.
  • 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)
  • 23.
  • 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
  • 26.
  • 27.
    プログラム・ヘッダ解説 ● Type – LOADはメモリ上にロードされるセグメントというこ と。他に、動的リンク情報やプログラム・ヘッダ自 身がある ● Offset – ELFファイルの内部でのセグメント位置 ● FilSiz、MemSiz – ファイル中のサイズと、メモリ上のサイズ – 必ずしも同じ大きさではない
  • 28.
  • 29.
    プログラムの修正と追加 ● 追加ファイル – elf.h、elf.c...ELF形式の解析 ● 修正ファイル – main.c...ELF形式の解析コマンド追加 – Makefile...elf.oをコンパイル対象にする ● 修正部分はrunコマンド追加しただけ – ELFファイルのうち、セグメント情報を表示するコ マンド
  • 30.
    elf.c ● 今回はkzload.elfのセグメント情報をターミナ ルに表示するプログラムになっている ● 構造体が大きいのでわかりにくい – 構造体はELFヘッダの部分と、プログラムヘッダの 部分を取得する感じになっている – その構造体のデータを表示するだけ ● たぶん次からELFファイルをメモリに展開する プログラムになるんだと思う
  • 31.
    セクション・ヘッダが末尾の理由 ● プログラム・ヘッダがELFファイルの先頭付近 にあるのは、ファイルをダウンロードしながら メモリにロードできるようにするため – バッファ領域が小さいときはこういった形になる ● メモリの配置先情報を最初に確認できるように してるわけ ● セクション・ヘッダが末尾なのはロードに必要 ないから。サイズ節約やメモリ節約のときに、 セクション・ヘッダを捨てやすくしてる – 末尾にあったらオフセットを計算しなおしたり、面 倒なことせずにすむ
  • 32.
  • 33.
    まとめ ● ELF形式のファイルの内部構造を解析できるよ うになった ● 具体的には内部におけるそれぞれのヘッダを操 作できるようになった ● セグメント・ヘッダの取得はできるようになっ たので、それを元に内容をメモリ上に展開する プログラムを書くことになるのかな ● あ、あと書籍では論理回路について解説してい るページがあるけど、ここでは省く