5日目 メモリのセグメント化
あー、明日は学校でセンター試験とかなきゃいけないらしいです。特に国語は不可だと思います。
初めに記しますがこの章結構長くなりそう
改めて本題に入ると、
セグメントとは領域という意味らしい
コンパイルされたプログラムを実行するとき、
メモリ空間がテキスト、データ、ヒープ、スタック、bssという5つのセグメントに分割されるとのこと。(bssってなんや
それぞれのセグメントには目的があるらしい
1.テキストセグメント
別名コードセグメント。
機械語が格納される。高水準言語の制御構造とか関数はアセンブリのbranch,jump,call命令にコンパイルされるから、命令処理の実行は非線形になる(日本語でおk。
非線形って直接的な意味は分からんけど、最初から全て決まった順で処理をしないということかな?わかんない
実行時にテキストセグメントの先頭の命令を指すようにeipが設定される
そのあとeipが指すメモリから命令を読み込む、その命令のバイト長をeipに加算、読み込んだ命令を実行の繰り返し。
jump,callのときはeipを書き換えるだけだそう。
因みにテキストセグメントは書き込み禁止で、これは何故かというとセグメントサイズの固定とプロセス間のコード共有のため。
プロセス間のコード共有ってなんじゃろ?
2.データセグメントとbssセグメント
データセグメントは初期化された大域変数や静的変数、一方、bssセグメントには初期化されていない大域、静的変数が格納される。
両方のセグメントは書き込み可能だけど、サイズが固定。
大域変数や静的変数は関数コンテキストに関係なく永続的。これは固有のメモリセグメントに格納されるから。
なるほど納得。
3.ヒープセグメント
プログラマが直接制御できる。
どんな目的にもつかえる。
実行時動的に割り当てられる。
サイズは大きくも小さくもなる。
アロケータとデアロケータというアルゴリズムによって管理されてる。
それぞれ、ヒープ中のメモリを切り出してプログラムで使えるように割り当てる、割り当てたメモリを回収して再利用できるようにするというアルゴリズムです。だからサイズが可変
要するにヒープ割り当て関数でプログラム実行時にメモリを動的に確保、解放できるということ。
あと、ヒープの成長はメモリアドレスの上位に向かう
あー長い。けどそんなに複雑じゃないですね
4.スタックセグメント
局所変数や関数呼び出し中のコンテキストを格納するとこ。一時的なメモ帳。
サイズは可変。
GDBのbacktraceで参照するやつ。
関数が呼び出されるときeipが移行するのと共に呼び出される関数側で使う変数が用意される。
だからスタックセグメントを使って引数の受け渡し、復元するeipの値の保存、関数が使う全ての局所変数の割り当てが行われる。
これらの情報はスタックフレームという纏まりにされて、スタック上に格納される。
余談である抽象的なデータ構造のこともスタックというらしい。
それは先入れ後出し(FILO)という構造で最初にに入れたのは最後にでてくる、その逆もしかるもの。
スタックに値を入れるのをプッシュ、取り出すのをポップという。
スタックセグメントはスタックフレームを保持するスタックを実現するためのもの。
スタックは下位に成長する。
確かに関数が入れ子になってた時に便利そうかも。
スタックの末端アドレスを管理するためのespレジスタというのがある。
プッシュ、ポップの度に値が変わる。
関数の呼び出し時には色んな情報がスタックフレームとしてスタックにプッシュされる。
現在のスタックフレームに格納された局所変数を参照するためにebpレジスタ(フレームポインタ(FP)、ローカルベース(LB)ポインタ)が用いられる。
それぞれのスタックフレームには関数に引き渡すパラメータ、該当関数の局所変数の他、呼び出し元に戻るために必要な、退避されたフレームポインタ(SFP)と戻りアドレスという二つのポインタが保持されている。
SFPは呼び出し元のコンテキストのスタックフレームを復元する、つまりebpレジスタの値を元に戻すために使われる。
これで直前のスタックフレームの関数のコンテキストを復元する。
要約するとスタックセグメントは関数ごとに情報を纏めてスタックにプッシュして、ポップしてコンテキストを復元するという感じですかね。あたまいたい
なんかセグメント同士の作用をまだ理解してない気がします
メモリのセグメントまだまだ続きます
あとはサンプルプログラムをGDBで眺めたり弄ったりするみたいです
この章が終わったらファイルアクセス、uid、構造体、関数ポインタ、擬似乱数やっておさらいやってお終いみたいです。
そこからは脆弱性攻撃です楽しみ。
CTFもやってみたいので、本があったら買って、同時進行でやりたいです。
おやすみなせ