ELF インタプリタ

BINARY HACKS 出版はもう六年も前のことなんですね。ld-linux.so のソースを確認するために以下から download できるスライドも確認させて頂きました。

そのうちこのスライドを使って云々、ってこともしてみたいな、と思いつつ。

エントリポイント

sysdeps/i386/dl-machine.h にて定義とのこと。確かに以下なコメントがあります。

/* Initial entry point code for the dynamic linker.
   The C function `_dl_start' is the real entry point;
   its return value is the user program's entry point.  */

コメントにある通り、_dl_start は C で書かれた関数で elf/rtld.c で定義されているとのこと。で、どう見てもアレな _dl_start 手続きの定義の最後らへんが以下なんですが、

  {
#ifdef DONT_USE_BOOTSTRAP_MAP
    ElfW(Addr) entry = _dl_start_final (arg);
#else
    ElfW(Addr) entry = _dl_start_final (arg, &info);
#endif

#ifndef ELF_MACHINE_START_ADDRESS
# define ELF_MACHINE_START_ADDRESS(map, start) (start)
#endif

    return ELF_MACHINE_START_ADDRESS (GL(dl_ns)[LM_ID_BASE]._ns_loaded, entry);
  }

なんとなく上のコメントの通り、user program's entry point を戻していそうげに見えますね。_dl_start_final という手続きから戻されているのは

  start_addr = _dl_sysdep_start (arg, &dl_main);

で取得した start_addr な模様。

  return start_addr;
}

課題

こないだも書いた通り、以下の部分の理解が必要不可欠。

  • カーネルにおける do_execve 以降の処理
  • ELF インタプリタにおける dl_main 以降の処理

もう少し

ちなみに crt1.o になる sysdeps/i386/elf/start.S が上のコメントで言う user program's entry point になるんですが、末端あたりで以下な処理。

	pushl %ecx		/* Push second argument: argv.  */
	pushl %esi		/* Push first argument: argc.  */

	pushl $BP_SYM (main)

	/* Call the user's main function, and exit with its value.
	   But let the libc call main.    */
	call BP_SYM (__libc_start_main)

__libc_start_main なる手続きが資料では sysdeps/generic/libc-start.c とのことでしたが、手元にあるソレ的には csu/libc-start.c になっている模様。
末端部分で以下な記述になっているのですが
# ここを通過するかどうかはアレ (ぇ

  /* Nothing fancy, just call the function.  */
  result = main (argc, argv, __environ MAIN_AUXVEC_PARAM);
#endif

  exit (result);
}

exit に渡される main の戻りはどこに行くんだったか。
# shell に、は知ってるんですがその経路がアレ