実行形式ファイルの情報はどこにあるかというと、先ほど確認したところオブジェクトファイルにあるようです。

しかし、オブジェクトファイルごとに情報は散らばっている状態。

実行形式ファイル(ELF形式)は、リンクのときにオブジェクトファイルから情報を収集しまとめる処理を実施しているように推測できます。

実はどのオブジェクトファイルからどんな情報を収集するかを示すファイルが存在し、それがリンカスクリプトといわれるもの。

Mafefile中ですとgccのオプションで-Tで指定されているld.scrというファイルになります。

リンカスクリプトをいい感じで説明しているサイトはこここれもいいかんじ。


リンカ・スクリプトをどんな感じで記述したかを確認。


/* OUTPUT_FORMAT("elf32-h8300") */
OUTPUT_ARCH(h8300h)
ENTRY("_start")

MEMORY
{
romall(rx) : o = 0x000000, l = 0x080000 /* 512KB */
vectors(r) : o = 0x000000, l = 0x000100 /* top of ROM */
rom(rx) : o = 0x000100, l = 0x07ff00

ramall(rwx) : o = 0xffbf20, l = 0x004000 /* 16KB */
data(rwx) : o = 0xfffc20, l = 0x000300
stack(rw) : o = 0xffff00, l = 0x000000 /* end of RAM */
}

SECTIONS
{
.vectors : {
vector.o(.data)
} > vectors

.text : {
_text_start = . ;
*(.text)
_etext = . ;
} > rom

.rodata : {
_rodata_start = . ;
*(.strings)
*(.rodata)
*(.rodata.*)
_erodata = . ;
} > rom

.data : {
_data_start = . ;
*(.data)
_edata = . ;
} > data AT> rom

.bss : {
_bss_start = . ;
*(.bss)
*(COMMON)
_ebss = . ;
} > data AT> rom

. = ALIGN(4);
_end = . ;

.stack : {
_stack = . ;
} > stack
}

■MEMORY
H8のメモリには『領域』が定義されていると以前に書きましたが、その定義はこちらで指定するものでMEMORYのなかに記述された内容がそうだということです。

少なくともROMやRAMのハード制約を十分に人が認識してあげて、メモリの『領域』を定義してあげているようです。

しかも、そこには領域をメモリ上のどのアドレスを領域とするかの数字レベルの記述もされています。

ROM/RAMの中でさらに細かく分けていて、ROM側ではvectorsとrom、RAM側ではdataとstackが定義されています。

なぜこのように細かく分類する必要があるかは今のところよくわかりません。

僕的にはハードの制約だけを考慮して、ROM領域RAM領域だけ定義してあげれば良いように思うのですが。。

CPUなどのハードの動きとか処理効率などの問題でいろいろメモリの使う領域を混在させないで分けて扱えれば有利なのかなぁ。stackとか名前ついているし。

とりあえずメモリに展開されたプログラムが有利に実行するためにメモリ上に設ける領域の設定をMEMORYの中の記述の『領域』という単位で扱うと記憶しておくことにしておきます。


■SECTION
以下の記述に注目してみます。
.vectors : {
vector.o(.data)
} > vectors

①『.vectors : {』の行はセクションを定義しています。
実効形式ファイルはいくつかのこれまた領域によって分類されているようですが、それをセクションと呼びました。とにかくMEMORYの領域の分類とは違うので別の観点で分類が必要のようです。

②『vector.o(.data)』の行は、vector.oのオブジェクトファイルの.dataセクションの内容を気にするという意味だそうです。

③『} > vectors』の行は、MEMORYのところで定義したvectors領域に{}で囲まれた内容を配置するという意味だそうです。


オブジェクトファイル中の.dataセクションがどうやって命名されてつくられるのかはよくわからないのですが、それが恐らくELFという形式なのでしょう。とりあえずこの観点は置いておきます。


で、注目すべきは『vector.o(.data)』の記述の意味するところです。
これはオブジェクトファイルの中身を取得している記述です。
この記述があるから実行形式ファイル中にオブジェクトファイルの内容が取り込めたのですね。
また、.dataセクションだけ取り出すということもしているようです。
以下はvector.oをreadelfで取り出したSection Headersの所なのですが[ 2]の.dataの部分です。
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .text PROGBITS 00000000 000034 000000 00 AX 0 0 1
[ 2] .data PROGBITS 00000000 000034 000100 00 WA 0 0 4


これは、③でどのメモリに情報を置くかを指定してあげないといけないわけですが、オブジェクトファイルの内容を全て置く訳にはいかない。なかにはRAMに配置したい変数などの情報もオブジェクトファイルに含まれています。そこで.dataセクションだけ持ってくるという記述をしているようです。


それと、セクションの意味についてもいろいろ推測。
少なくとも、MEMORYで定義されているものよりネーミングからしてより処理内容に関する論理的な内容の傾向があるかもしれないです。ただセクション単位で扱う内容はROMに配置すべきかRAMに配置すべきかを意識した情報の集まりになっているようですので、セクションの設計はROMとRAMの制約からは逃れられないようです。
※テーマの静的変数の読み書きの観点でおもしろい話があるのでそれは別途扱います


これによってオブジェクトファイルから(セクション単位で)情報が収集されている裏付けがとれたことになります。
しかし、このリンカスクリプトの役割はオブジェクトファイルからの情報収集だけに留まらないようです。(つづく)