このページの目次

ELFヘッダとセクションテーブル

Linuxの実行ファイル (ELF形式) は簡単なものでは次のような構造になっています。普通はリンカ (ld) がオブジェクトファイルをもとに構成してくれますが、rvtlc では自分で設定する必要があります。ここでは rvtlc がELF形式の実行ファイルを作成する部分を解説します。

    +---------------------------------+
    | ELF ヘッダ                      |
    +---------------------------------+
    | プログラムヘッダテーブル        |
    +---------------------------------+
    | .text セクション                |
    |                                 |
    +---------------------------------+
    | .data セクション                |
    |                                 |
    +---------------------------------+
    | .bss セクション (サイズ 0)      |
    +---------------------------------+
    | .shstrtabセクション (オプション)|
    +---------------------------------+
    | セクションテーブル (オプション) |
    +---------------------------------+

rvtlcが出力するファイルは .bss セクションを固定アドレスに配置するために .data セクションはありません。

ELFセクションテーブルの設定

ELFのセクションデータとセクションテーブルを設定します。ELF実行ファイルでは使われないため、省略可能ですが、一応設定しています。

10770   :---------------------
10780   : ELFの作成
10790   :---------------------
10800   H['Z']=P                        : section size
10810   !=^DataSection
10820   !=^SectionStr
10830   !=^SectionHeader
10840   Obj[17]=H['Z']+H['P']           : p_filesz
10850   Obj[18]=H['Z']+H['P']           : p_memsz

.dataセクション

初期化済みデータをおきますが、rvtlc では .dataセクションは使っていません。サイズを 0 にしています。

28660 :-------------------------------------------------
28670 : .data
28680 :-------------------------------------------------
28690 ^DataSection
28700    :P=(P+$FF)/$100*$100
28710    H['M']=P
28720    :@
28730    :  Obj(P)=0    : initialize
28740    :  P=P+1
28750    :@=(P=(H['M']+H['L']))
28760    H['Q']=P
28770 ]
28780 :

.shstrtabセクション

セクション名を示す文字列を設定します。

28790 :-------------------------------------------------
28800 : セクション文字列テーブルの設定
28810 :-------------------------------------------------
28820 ^SectionStr
28830    +q
28840    H['S']=P
28850    q=Obj+P
28860    q(0)=0 q=q+1
28870    H['T']=q-Obj-P
28880    q*=".text" q=q+%+1
28890    H['D']=q-Obj-P
28900    q*=".data" q=q+%+1
28910    H['E']=q-Obj-P
28920    q*=".bss" q=q+%+1
28930    H['H']=q-Obj-P
28940    q*=".shstrtab" q=q+%+1
28950    P=q-Obj
28960    H['Y']=P-H['S']      :
28970    ;=D>2 / $*=Obj+H['S']+H['T'] /
28980    ;=D>2 $*=Obj+H['S']+H['D'] /
28990    ;=D>2 $*=Obj+H['S']+H['E'] /
29000    ;=D>2 $*=Obj+H['S']+H['H'] /
29010    -q
29020  ]
29030 :

セクションテーブル

.text、.data、.bss、.shstrtabの各セクションの情報を設定します。

29040 :-------------------------------------------------
29050 : セクションテーブルの設定
29060 :-------------------------------------------------
29070 ^SectionHeader
29080    Obj[08]=P         :   e_shoff
29090    Obj{23}=40        :   e_shentsize
29100    Obj{24}=5         :   e_shnum
29110    : NULL
29120    E=Obj+P
29130    E[0]=0            : sh_name
29140    E[1]=0            : sh_type
29150    E[2]=0            : sh_flags
29160    E[3]=0            : sh_addr
29170    E[4]=0            : sh_offset
29180    E[5]=0            : sh_size
29190    E[6]=0            : sh_link
29200    E[7]=0            : sh_info
29210    E[8]=0            : sh_addralign
29220    E[9]=0            : sh_entsize
29230    P=P+40
29240    : .text
29250    E=Obj+P
29260    E[0]=H['T']       : sh_name
29270    E[1]=1            : sh_type  SHT_PROGBITS<1>
29280    E[2]=6            : sh_flags SHF_ALLOC<2> | SHF_EXECINSTR<4>
29290    E[3]=H['A']       : sh_addr
29300    E[4]=H['P']       : sh_offset
29310    E[5]=H['Z']       : sh_size
29320    E[6]=0            : sh_link
29330    E[7]=0            : sh_info
29340    E[8]=0            : sh_addralign
29350    E[9]=0            : sh_entsize
29360    P=P+40
29370    : .data
29380    E=Obj+P
29390    E[0]=H['D']       : sh_name
29400    E[1]=1            : sh_type  SHT_PROGBITS<1>
29410    E[2]=3            : sh_flags SHF_ALLOC<2> |  SHF_WRITE<1>
29420    E[3]=H['K']       : sh_addr     $080A0000
29430    E[4]=H['M']       : sh_offset
29440    E[5]=H['L']       : sh_size     0
29450    E[6]=0            : sh_link
29460    E[7]=0            : sh_info
29470    E[8]=$1000        : sh_addralign
29480    E[9]=0            : sh_entsize
29490    P=P+40
29500    : .bss
29510    E=Obj+P
29520    E[0]=H['E']       : sh_name
29530    E[1]=8            : sh_type  SHT_NOBITS<8>
29540    E[2]=3            : sh_flags SHF_ALLOC<2> | SHF_WRITE<1>
29550    E[3]=H['K']+H['L']  : sh_addr   $080A0000
29560    E[4]=H['M']+H['L']  : sh_offset
29570    E[5]=H['U']+H['O']  : sh_size   $4000+$40000
29580    E[6]=0            : sh_link
29590    E[7]=0            : sh_info
29600    E[8]=$1000        : sh_addralign
29610    E[9]=0            : sh_entsize
29620    P=P+40
29630    : .shstrtab
29640    E=Obj+P
29650    E[0]=H['H']       : sh_name
29660    E[1]=3            : sh_type  SHT_STRTAB<3>
29670    E[2]=0            : sh_flags
29680    E[3]=0            : sh_addr
29690    E[4]=H['S']       : sh_offset
29700    E[5]=H['Y']       : sh_size
29710    E[6]=0            : sh_link
29720    E[7]=0            : sh_info
29730    E[8]=16           : sh_addralign
29740    E[9]=0            : sh_entsize
29750    P=P+40
29760 ]
29770 :

ELFヘッダ

ELF形式の実行ファイルの先頭部分にはELFヘッダと呼ぶデータが必要です。ELFの型(オブジェクト、実行ファイル)、CPUの種類、エントリーポイント、プログラムヘッダテーブルの位置、セクションヘッダテーブルの位置などの情報を設定します。実行ファイルのイメージ(配列Obj)の先頭部分にELFヘッダとELFプログラムヘッダテーブルを書き込んだ後、ランタイムライブラリのコード部分をコピーします。

29780 :-------------------------------------------------
29790 : Setup ELF Header and Runtime Library
29800 :-------------------------------------------------
29810 ^SetUpLib
29820    : Elf32_Header
29830    Obj[00]=$464c457f
29840    Obj[01]=$00010101
29850    Obj[02]=0
29860    Obj[03]=0
29870    Obj{08}=2             :   e_type    ET_EXEC<2>
29880    Obj{09}=3             :   e_machine EM_386<3>
29890    Obj[05]=1             :   e_version EV_CURRENT<1>
29900    Obj[06]=H['A']        :   e_entry
29910    Obj[07]=13*4          :   e_phoff
29920    Obj[08]=0             :   e_shoff
29930    Obj[09]=0             :   e_flags
29940    Obj{20}=52            :   e_ehsize
29950    Obj{21}=32            :   e_phentsize
29960    Obj{22}=2             :   e_phnum
29970    Obj{23}=0             :   e_shentsize
29980    Obj{24}=0             :   e_shnum
29990    Obj{25}=4             :   e_shstrndx

プログラムヘッダテーブル

プログラムヘッダテーブルは.text用と.bss用の2つを登録します。今回は初期化済みデータを格納する .data は使用せず、.bss用には初期化のためのデータは不要なため、ファイル中のデータサイズを指定する p_filesz は 0 でも問題ないはずですが、カーネル中で mmap が失敗するため Obj[25]=$100の部分で適当に256バイトを指定しています。

30000    : Elf32_ProgramHeader .text
30010    Obj[13]=1             :   p_type    PT_LOAD<1>
30020    Obj[14]=0             :   p_offset
30030    Obj[15]=H['B']        :   p_vaddr
30040    Obj[16]=H['B']        :   p_paddr
30050    Obj[17]=100           :   p_filesz
30060    Obj[18]=100           :   p_memsz
30070    Obj[19]=5             :   p_flags   PF_X<1> + PF_R<4>
30080    Obj[20]=$100          :   p_align
30090    :  Elf32_ProgramHeader .data .bss
30100    Obj[21]=1             :   p_type    PT_LOAD<1>
30110    Obj[22]=0             :   p_offset
30120    Obj[23]=H['K']        :   p_vaddr
30130    Obj[24]=H['K']        :   p_paddr
30140    Obj[25]=$100          :   p_filesz
30150    Obj[26]=H['L']+H['U']+H['O'] :   p_memsz
30160    Obj[27]=6             :   p_flags   PF_W<2> + PF_R<4>
30170    Obj[28]=$100          :   p_align
30180    : _start jump main
30190    Obj[029]=$90909090
30200    Obj[030]=$90909090
30210    Obj[031]=$90909090

ランタイムライブラリのコピー

ランタイムライブラリを Obj 配列に書き込みます。ランタイムライブラリのバイナリファイル (rt.bin) は次の形式になっています。

        +------------------------------------+
 F[0]   | ELFヘッダ                          |
        +------------------------------------+
        | プログラムヘッダテーブル           |
        +------------------------------------+
 F[32]  | プログラム本体へのジャンプ命令     |
        +------------------------------------+
 F[34]  | ライブラリのサイズ(dword単位)      |
        +------------------------------------+
        | ライブラリルーチン0の先頭アドレス  |
        +------------------------------------+
        | ライブラリルーチン1の先頭アドレス  |
        +------------------------------------+
        :             :                      :
        +------------------------------------+
        | ライブラリ本体                     |
        :                                    :
        +------------------------------------+

ランタイムライブラリのバイナリファイル (rt.bin) を読み込んでいる配列 F の必要な部分、F[32]からライブラリ本体の最終までを Obj 配列にコピーしています。

30220    Obj[032]=$0013EFE9    : ここ以降はrt.binに上書きされる
30230    Obj[033]=$90909000
30240    : ?=F[034] /          : ライブラリサイズ(word)
30250    : Jump Table         lib#
30260    : Library
30270    i=32
30280    @
30290      Obj[i]=F[i]
30300      i=i+1
30310    @=(i>=F[34])
30320    :
30330    P=F[34]*4
30340 ]
30350 :

[前] [目次] [次]