Skip to content

Latest commit

 

History

History
74 lines (58 loc) · 4.11 KB

File metadata and controls

74 lines (58 loc) · 4.11 KB

アプリケーション起動時の引数渡し仕様

SwiftCoreにおけるユーザープロセス起動時の引数(argc, argv)および環境変数(envp)の受け渡し仕様を定義する。 本仕様は System V ABI (x86-64) および Linux のプロセス起動処理に準拠する。

1. スタックレイアウト (初期状態)

カーネルはユーザーモードへ移行する直前に、ユーザースタックを以下のように構築する。 スタックは高位アドレスから低位アドレスに向かって伸長するため、図の上方が高位アドレスとなる。

|-------------------| <--- ユーザースタック領域の最大アドレス (Stack Top)
| 文字列データ領域  | 引数の文字列本体 ("arg0\0", "arg1\0"...)
|                   | 環境変数の文字列本体 ("KEY=VAL\0"...)
|-------------------|
| パディング        | 16バイト境界整列用 (必要に応じて)
|-------------------|
| 補助ベクトル      | (将来的な拡張用、終端は {0, 0})
| (Auxv)            |
|-------------------|
| NULL (8 bytes)    | envp 配列の終端
| envp[m]           | 環境変数ポインタ (8bytes)
| ...               |
| envp[0]           | 環境変数ポインタ配列の先頭
|-------------------|
| NULL (8 bytes)    | argv 配列の終端
| argv[n-1]         | 引数ポインタ (8bytes)
| ...               |
| argv[0]           | 引数ポインタ配列の先頭 (通常はプログラム名)
|-------------------|
| argc (8 bytes)    | 引数の数 (符号なし整数)
|-------------------| <--- 初期 RSP (エントリポイント実行開始時)

2. エントリポイント到達時のレジスタ状態

ユーザーモードの実行開始時点(_start 呼び出し時)でのレジスタの状態は以下の通りとする。

  • RSP: 上記スタックレイアウトの argc の位置を指していること。
  • RIP: アプリケーションのエントリポイント(ELFヘッダで指定されたアドレス)。
  • RFLAGS: 割り込み許可 (IF=1) などの適切な初期値。
  • その他の汎用レジスタ(RDI, RSI, RDX, RCX, R8, R9 等)は未定義(または 0 クリア)。

3. カーネル側の責務

exec システムコール等のプロセス生成処理において、以下の手順でスタックを構築する。

  1. スタック領域のマップ: ユーザースタック用のメモリページを確保・マップする。
  2. 文字列のコピー: 引数および環境変数の文字列データをスタックの高位アドレス側にコピーする。
  3. ポインタ配列の作成: コピーした文字列アドレスを指すポインタ配列 (argv, envp) をスタックにプッシュする。
  4. argc のプッシュ: 引数の数をスタックにプッシュする。
  5. RSP の決定: 最終的なスタックポインタの値を計算し、スレッドコンテキストの rsp に設定する。

4. ユーザーランド側の責務 (CRT / スタートアップコード)

アプリケーションのスタートアップコード(Rust の場合は crt.rs_start)は、スタック上のデータを引数として取得し、main 関数へ渡す。

Rust の main 関数シグネチャ

fn main(argc: i32, argv: *const *const u8) -> i32

_start での処理ロジック (x86_64 アセンブリ)

  1. argc の取得: スタックトップ ([rsp]) から値を取り出し、第1引数レジスタ rdi に格納する。
    • pop rdi
  2. argv の取得: argc をポップした直後のスタックポインタ (rsp) が argv[0] を指しているため、そのアドレスを第2引数レジスタ rsi に格納する。
    • mov rsi, rsp
  3. スタックアライメント: 必要に応じてスタックポインタを 16 バイト境界に整列させる(SSE 命令等を使用する場合)。
    • and rsp, -16
  4. main 呼び出し:
    • call main
  5. 終了処理: main の戻り値 (rax) を引数として exit システムコールを呼び出す。