exec elfの続き

NetBSD Currentのkern/exec_elf.cのexec_elf_makecmdsを読んだ続き。

まずはELFヘッダのチェック。

671   if (epp->ep_hdrvalid < sizeof(Elf_Ehdr))
672     return ENOEXEC;
673 
674   is_dyn = elf_check_header(eh, ET_DYN) == 0;
675   /*
676    * XXX allow for executing shared objects. It seems silly
677    * but other ELF-based systems allow it as well.
678    */
679   if (elf_check_header(eh, ET_EXEC) != 0 && !is_dyn)
680     return ENOEXEC;
681 
682   if (eh->e_phnum > MAXPHNUM || eh->e_phnum == 0)
683     return ENOEXEC;
684 

次にELFヘッダ内から.interpセクションを見付だし、そこに入っている文字列(ELFインタプリタへのパス)を抜き出します。

708   for (i = 0; i < eh->e_phnum; i++) {
709     pp = &ph[i];
710     if (pp->p_type == PT_INTERP) {
711       if (pp->p_filesz >= MAXPATHLEN) {
712         error = ENOEXEC;
713         goto bad;
714       }
715       interp = PNBUF_GET();
716       interp[0] = '\0';
717       if ((error = exec_read_from(l, epp->ep_vp,
718           pp->p_offset, interp, pp->p_filesz)) != 0)
719         goto bad;
720       break;
721     }
722   }

次の処理・・・。これは何をしているのだろう。
おそらくinterpをロードか何かしているのか。

elf_probe_funcはsys/exec.h内でstruct execswのメンバとして定義されている。
execswでgrepをかけると、kern/exec_elf32.c内で引っかかる。
中を見ると、exec_elf32_execswという構造体定義があり、この中で「netbsd_elf32_probe」という関数が対応した位置に記述されている。

733   if (epp->ep_esch->u.elf_probe_func) {
734     vaddr_t startp = (vaddr_t)pos;
735 
736     error = (*epp->ep_esch->u.elf_probe_func)(l, epp, eh, interp,
737                 &startp);
738     if (error)
739       goto bad;
740     pos = (Elf_Addr)startp;
741   }

先に書いた記事と同様、netbsd_elf32_probeはnetbsd_elf_probeであるが、特にinterpをどうこうしている箇所はなさそうだ。
(netbsd_elf_probeでは確かにELF_MD_PROBE_FUNCという定義があれば何かinterpに対する操作をしていそうだが、この定義はどうやらmipsにのみ存在しているようだ)

次の処理はPT_LOADなセクションをロードする作業。ソースは長いので省略。
そしていよいよinterpなセクションに記述されたファイル(ELFインタプリタ)をロードする。
そして、エントリポイントも取り出しておく。

820   if (interp) {
821     int j = epp->ep_vmcmds.evs_used;
822     u_long interp_offset;
823 
824     if ((error = elf_load_file(l, epp, interp,
825         &epp->ep_vmcmds, &interp_offset, ap, &pos)) != 0) {
826       goto bad;
827     }
828     ap->arg_interp = epp->ep_vmcmds.evs_cmds[j].ev_addr;
829     epp->ep_entry = ap->arg_interp + interp_offset;
830     PNBUF_PUT(interp);
831   } else

さらにこの後check_exec()に戻る。
・・・まだまだ先は長そうだ。