こんにちは、ユーマと申します。
リンカスクリプトの実験をしていたところ、VMA(仮想アドレス)とLMA(物理アドレス)について混乱したので質問させていただきました。
まず確認なのですが、
VMA = プログラムが実際にメモリにロードされた時に動作するはずであるアドレス
LMA = プログラムが実際にロードされるアドレス
という認識でOKでしょうか?
つまり、僕はVMA = リンカに対して指定するアドレスでLMA = ローダに対して指定するアドレスだと思っています。
組み込みOSなどでは、ROMにプログラムを書き込んでおいて(このアドレスがLMA)、プログラム実行開始直後にRAMにコピーするという処理が行われているようなので(このアドレスがVMA)、僕の認識と一致すると思います
ですが、なんだかもやもやします。
VMAとLMAを分ける理由というのはなんなのでしょうか?
二つがなければ困る理由はあると思うのですが、理解が浅くいまいちピンときません。
また、最近Ubuntuの上でglibcに頼らずにCプログラミングしています。
その時にリンカスクリプトも自作していたのですが、その時にもVMAとLMAに対する不思議な現象(?)が起きました。
.text 0x8048000 : 0x8000000 { *(.text) } みたいな感じに指定してプログラムを実行していたのですが、実際に動作しているプログラムは8048000台のアドレスでした。
(実行しているアドレスを調べるために次のような関数をmain関数の中で使いました。返り値に呼び出し元のアドレスが返ります。)
コード:
search_eip:
pushl %ebp
movl %esp, %ebp
movl 0x4(%ebp), %eax
leave
ret
この指定ではVMA = 0x8048000、LMA = 0x8000000になるはずで、僕の予想は0x8000000に近いものになると思っていました。(LMAはローダがプログラムを読み込む番地のはずだから)
ですが、実際にプログラムが読み込まれているのは0x8048000。
LMAを基準にローダがプログラムをメモリに読み込んでいないような気がします。
VMAを基準にしてローダがプログラムを読み込むなら、そもそもLMAなどはいらないのでは?と思ってしまいます。
ここで指定しているVMA・LMAとは何なのでしょうか?
なにかとんでもない勘違いをしているのは決定的なのですが、自分ではよくわかりません。
僕がよくわかっていないので文章も読みずらいと思いますが、よろしくお願いいたします。