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()に戻る。
・・・まだまだ先は長そうだ。