Home | History | Annotate | Line # | Download | only in common
exec_sub.c revision 1.3.92.1
      1  1.3.92.1      jym /*	$NetBSD: exec_sub.c,v 1.3.92.1 2009/05/13 17:18:43 jym Exp $ */
      2       1.1    isaki 
      3       1.1    isaki #include <sys/cdefs.h>
      4       1.1    isaki 
      5       1.1    isaki #include "execkern.h"
      6       1.1    isaki #include <a.out.h>
      7       1.1    isaki #include <sys/param.h>
      8       1.1    isaki 
      9       1.1    isaki #ifdef BOOT
     10  1.3.92.1      jym void B_PRINT(const unsigned char *p);
     11       1.1    isaki #endif
     12       1.1    isaki 
     13  1.3.92.1      jym static inline void bzero4(void *ptr, size_t siz);
     14  1.3.92.1      jym static void xk_aout(struct execkern_arg *xarg, struct exec *hdr);
     15  1.3.92.1      jym static void xk_elf(struct execkern_arg *xarg, Elf32_Ehdr *hdr);
     16       1.1    isaki 
     17       1.1    isaki #ifdef LOADBSD
     18  1.3.92.1      jym static void DPRINT_SEC(const char *ident,
     19  1.3.92.1      jym 			    const struct execkern_section *sec);
     20       1.1    isaki extern int opt_v;
     21       1.1    isaki extern const char *kernel_fn;
     22       1.1    isaki 
     23       1.1    isaki static void
     24  1.3.92.1      jym DPRINT_SEC(const char *ident, const struct execkern_section *sec)
     25       1.1    isaki {
     26       1.1    isaki 
     27       1.1    isaki 	if (opt_v)
     28       1.1    isaki 		xwarnx("section (%s): img %p, sz %d, pad %d", ident,
     29       1.1    isaki 			sec->sec_image, sec->sec_size, sec->sec_pad);
     30       1.1    isaki }
     31       1.1    isaki 
     32       1.1    isaki #define ERRX(arg)		xerrx arg
     33       1.1    isaki 
     34       1.1    isaki #else
     35       1.1    isaki #define DPRINT_SEC(ident, sec)	/**/
     36       1.1    isaki #define ERRX(arg)		return 1
     37       1.1    isaki #endif
     38       1.1    isaki 
     39       1.1    isaki /*
     40       1.1    isaki  * This code is size-hacked version of
     41       1.1    isaki  *
     42       1.1    isaki  *	sec->sec_image = (image);
     43       1.1    isaki  *	sec->sec_size = (size);
     44       1.1    isaki  *	sec->sec_pad = (pad);
     45       1.1    isaki  *	DPRINT_SEC((ident), sec);
     46       1.1    isaki  *	sec++;
     47       1.1    isaki  */
     48       1.1    isaki #define SECTION(sec, ident, image, size, pad)	\
     49       1.1    isaki 	do {					\
     50       1.1    isaki 		u_long *wp = (void *) sec;	\
     51       1.1    isaki 		*(void **)wp++ = (image);	\
     52       1.1    isaki 		*wp++ = (size);			\
     53       1.1    isaki 		*wp++ = (pad);			\
     54       1.1    isaki 		DPRINT_SEC((ident), sec);	\
     55       1.1    isaki 		sec = (void *) wp;		\
     56       1.1    isaki 	} while (0)
     57       1.1    isaki 
     58       1.1    isaki #define SECTION_NOPAD(sec, ident, image, size)	\
     59       1.1    isaki 		SECTION(sec, (ident), (image), (size), 0)
     60       1.1    isaki 
     61       1.3    perry static inline void
     62  1.3.92.1      jym bzero4(void *ptr, size_t siz)
     63       1.1    isaki {
     64       1.1    isaki 	u_long *p;
     65       1.1    isaki 	u_short s;
     66       1.1    isaki 
     67       1.1    isaki 	p = ptr;
     68       1.1    isaki 	s = siz >> 2;
     69       1.1    isaki 
     70       1.1    isaki 	while (s--)
     71       1.1    isaki 		*p++ = 0;
     72       1.1    isaki }
     73       1.1    isaki 
     74       1.1    isaki /*
     75       1.1    isaki  * fill in loading information from an a.out executable
     76       1.1    isaki  */
     77       1.1    isaki static void
     78  1.3.92.1      jym xk_aout(struct execkern_arg *xarg, struct exec *hdr)
     79       1.1    isaki {
     80       1.1    isaki 	unsigned u;
     81       1.1    isaki 	char *s;
     82       1.1    isaki 	struct execkern_section *sec;
     83       1.1    isaki 
     84       1.1    isaki 	xarg->entry_addr = hdr->a_entry;
     85       1.1    isaki 	sec = xarg->sec;
     86       1.1    isaki 
     87       1.1    isaki 	/* text section and padding between data section */
     88       1.1    isaki 	s = (void *) (hdr + 1);
     89       1.2  thorpej 	SECTION(sec, "text", s, hdr->a_text, -hdr->a_text & (AOUT_LDPGSZ-1));
     90       1.1    isaki 
     91       1.1    isaki 	/* data and bss sections */
     92       1.1    isaki 	s += hdr->a_text;
     93       1.1    isaki 	SECTION(sec, "data/bss", s, hdr->a_data, hdr->a_bss);
     94       1.1    isaki 
     95       1.1    isaki 	/* size of symbol table */
     96       1.1    isaki 	SECTION_NOPAD(sec, "symtab size", &sec[1].sec_size, sizeof(u_long));
     97       1.1    isaki 
     98       1.1    isaki 	/* symbol table section */
     99       1.1    isaki 	s += hdr->a_data;
    100       1.1    isaki 	SECTION_NOPAD(sec, "symbol", s, u = hdr->a_syms);
    101       1.1    isaki 
    102       1.1    isaki 	/* string table section */
    103       1.1    isaki 	if (u) {
    104       1.1    isaki #ifdef LOADBSD
    105       1.1    isaki 		if (opt_v)
    106       1.1    isaki 			xwarnx("symbol table found");
    107       1.1    isaki #endif
    108       1.1    isaki 		s += u;
    109       1.1    isaki 		SECTION_NOPAD(sec, "string", s, *(u_long *) s);
    110       1.1    isaki 	}
    111       1.1    isaki }
    112       1.1    isaki 
    113       1.1    isaki /*
    114       1.1    isaki  * fill in loading information from an ELF executable
    115       1.1    isaki  */
    116       1.1    isaki static void
    117  1.3.92.1      jym xk_elf(struct execkern_arg *xarg, Elf32_Ehdr *hdr)
    118       1.1    isaki {
    119       1.1    isaki 	char *top = (void *) hdr;
    120       1.1    isaki 	struct execkern_section *sec;
    121       1.1    isaki 	Elf32_Phdr *ph;
    122       1.1    isaki 	Elf32_Shdr *sh, *sym, *str, *stab, *shstr;
    123       1.1    isaki 	const char *shstrtab, *shname;
    124       1.1    isaki 	unsigned u, dpos, pd;
    125       1.1    isaki 	const char *const shstrtab_new = SHSTRTAB_FAKE;
    126       1.1    isaki 
    127       1.1    isaki 	xarg->entry_addr = hdr->e_entry;
    128       1.1    isaki 
    129       1.1    isaki 	/*
    130       1.1    isaki 	 * text, data, bss
    131       1.1    isaki 	 */
    132       1.1    isaki 	ph = (void *) (top + hdr->e_phoff);
    133       1.1    isaki 	xarg->load_addr = ph->p_vaddr;
    134       1.1    isaki 
    135       1.1    isaki 	sec = xarg->sec;
    136       1.1    isaki 	sec->sec_image = top + ph->p_offset;
    137       1.1    isaki 	sec->sec_size = ph->p_filesz;
    138       1.1    isaki 
    139       1.1    isaki 	if (hdr->e_phnum != 1) {
    140       1.1    isaki 		sec->sec_pad = ph[1].p_vaddr - (ph->p_vaddr + ph->p_filesz);
    141       1.1    isaki 		DPRINT_SEC("program (text)", sec);
    142       1.1    isaki 		sec++;
    143       1.1    isaki 		ph++;
    144       1.1    isaki 		sec->sec_image = top + ph->p_offset;
    145       1.1    isaki 		sec->sec_size = ph->p_filesz;
    146       1.1    isaki 	}
    147       1.1    isaki 
    148       1.1    isaki 	sec->sec_pad = ph->p_memsz - ph->p_filesz;
    149       1.1    isaki 	DPRINT_SEC("program (data/bss)", sec);
    150       1.1    isaki 	sec++;
    151       1.1    isaki 
    152       1.1    isaki 	/*
    153       1.1    isaki 	 * symbol size
    154       1.1    isaki 	 */
    155       1.1    isaki 	xarg->elfsymsiz = 0;		/* no symbol */
    156       1.1    isaki 	SECTION_NOPAD(sec, "symtab size", &xarg->elfsymsiz, sizeof(int));
    157       1.1    isaki 
    158       1.1    isaki 	/*
    159       1.1    isaki 	 * ELF header
    160       1.1    isaki 	 */
    161       1.1    isaki 	xarg->ehdr = *hdr;
    162       1.1    isaki 	xarg->ehdr.e_shstrndx = 0;	/* .shstrtab will be the 1st section */
    163       1.1    isaki 	SECTION_NOPAD(sec, "ELF header", &xarg->ehdr, sizeof(Elf32_Ehdr));
    164       1.1    isaki 
    165       1.1    isaki 	sh = (void *) (top + hdr->e_shoff);		/* section header */
    166       1.1    isaki 	shstr = sh + hdr->e_shstrndx;			/* .shstrtab */
    167       1.1    isaki 	shstrtab = top + shstr->sh_offset;
    168       1.1    isaki 
    169       1.1    isaki 	sym = str = stab = 0;
    170       1.1    isaki 	for (u = 0; sh++, ++u < hdr->e_shnum; ) {
    171       1.1    isaki 		shname = shstrtab + sh->sh_name;
    172       1.1    isaki 		if (!strcmp(shname, shstrtab_new + SHNAME_OFF_SYMTAB))
    173       1.1    isaki 			sym = sh;				/* .symtab */
    174       1.1    isaki 		if (!strcmp(shname, shstrtab_new + SHNAME_OFF_STRTAB))
    175       1.1    isaki 			str = sh;				/* .strtab */
    176       1.1    isaki 		if (!strcmp(shname, shstrtab_new + SHNAME_OFF_STAB))
    177       1.1    isaki 			stab = sh;				/* .stab */
    178       1.1    isaki 	}
    179       1.1    isaki 
    180       1.1    isaki 	if (shstr == 0 || sym == 0 || str == 0)
    181       1.1    isaki 		xarg->ehdr.e_shnum = 0;		/* no symbol */
    182       1.1    isaki 	else {
    183       1.1    isaki #ifdef LOADBSD
    184       1.1    isaki 		if (opt_v) {
    185       1.1    isaki 			xwarnx("symbol table found");
    186       1.1    isaki 			if (stab)
    187       1.1    isaki 				xwarnx("debugging information found");
    188       1.1    isaki 		}
    189       1.1    isaki #endif
    190       1.1    isaki 		xarg->elfsymsiz = 1;		/* has symbol */
    191       1.1    isaki 		xarg->ehdr.e_shnum = 3;
    192       1.1    isaki 		xarg->ehdr.e_shoff = sizeof(Elf32_Ehdr);
    193       1.1    isaki 
    194       1.1    isaki 		SECTION_NOPAD(sec, "section header (shstrtab)",
    195       1.1    isaki 				shstr, sizeof(Elf32_Shdr));
    196       1.1    isaki 
    197       1.1    isaki 		SECTION_NOPAD(sec, "section header (symbol)",
    198       1.1    isaki 				sym, sizeof(Elf32_Shdr));
    199       1.1    isaki 
    200       1.1    isaki 		SECTION_NOPAD(sec, "section header (string)",
    201       1.1    isaki 				str, sizeof(Elf32_Shdr));
    202       1.1    isaki 
    203       1.1    isaki 		dpos = sizeof(Elf32_Ehdr) + sizeof(Elf32_Shdr) * 3;
    204       1.1    isaki 		u = SIZE_SHSTRTAB_FAKE;
    205       1.1    isaki 
    206       1.1    isaki 		if (stab) {
    207       1.1    isaki 			xarg->ehdr.e_shnum++;
    208       1.1    isaki 			SECTION_NOPAD(sec, "section header (stab)",
    209       1.1    isaki 					stab, sizeof(Elf32_Shdr));
    210       1.1    isaki 			dpos += sizeof(Elf32_Shdr);
    211       1.1    isaki 			u = SIZE_SHSTRTAB_FAKE_WITH_STAB;
    212       1.1    isaki 		}
    213       1.1    isaki 
    214       1.1    isaki 		/* new .shstrtab section */
    215       1.1    isaki 		memcpy(xarg->shstrtab_fake, shstrtab_new, u);
    216       1.1    isaki 		/*
    217       1.1    isaki 		 * DDB requires symtab be aligned.
    218       1.1    isaki 		 */
    219       1.1    isaki 		pd = -u & ALIGNBYTES;
    220       1.1    isaki 		SECTION(sec, "shstrtab", &xarg->shstrtab_fake, u, pd);
    221       1.1    isaki 		shstr->sh_name = SHNAME_OFF_SHSTRTAB;
    222       1.1    isaki 		shstr->sh_offset = dpos;
    223       1.1    isaki 		dpos += u + pd;
    224       1.1    isaki 
    225       1.1    isaki 		SECTION_NOPAD(sec, "symtab",
    226       1.1    isaki 				top + sym->sh_offset, sym->sh_size);
    227       1.1    isaki 		sym->sh_name = SHNAME_OFF_SYMTAB;
    228       1.1    isaki 		sym->sh_offset = dpos;
    229       1.1    isaki 		dpos += sym->sh_size;
    230       1.1    isaki 
    231       1.1    isaki 		SECTION_NOPAD(sec, "strtab",
    232       1.1    isaki 				top + str->sh_offset, str->sh_size);
    233       1.1    isaki 		str->sh_name = SHNAME_OFF_STRTAB;
    234       1.1    isaki 		str->sh_offset = dpos;
    235       1.1    isaki 		dpos += str->sh_size;
    236       1.1    isaki 
    237       1.1    isaki 		if (stab) {
    238       1.1    isaki 			SECTION_NOPAD(sec, "stab",
    239       1.1    isaki 					top + stab->sh_offset, stab->sh_size);
    240       1.1    isaki 			stab->sh_name = SHNAME_OFF_STAB;
    241       1.1    isaki 			stab->sh_offset = dpos;
    242       1.1    isaki 		}
    243       1.1    isaki 	}
    244       1.1    isaki }
    245       1.1    isaki 
    246       1.1    isaki 
    247       1.1    isaki int
    248  1.3.92.1      jym xk_load(struct execkern_arg *xarg, void *buf, u_long loadaddr)
    249  1.3.92.1      jym 	/* loadaddr:	 for a.out */
    250       1.1    isaki {
    251       1.1    isaki 	struct exec *ahdr;
    252       1.1    isaki 	Elf32_Ehdr *ehdr;
    253       1.1    isaki 	unsigned u;
    254       1.1    isaki 
    255       1.1    isaki 	/* Unused section entries should be cleared to zero. */
    256       1.1    isaki 	bzero4(xarg->sec, sizeof xarg->sec);
    257       1.1    isaki 
    258       1.1    isaki 	xarg->load_addr = loadaddr;
    259       1.1    isaki 
    260       1.1    isaki 	/*
    261       1.1    isaki 	 * check exec header
    262       1.1    isaki 	 */
    263       1.1    isaki 	ahdr = buf;
    264       1.1    isaki 	ehdr = buf;
    265       1.1    isaki 
    266       1.1    isaki 	if (N_GETMAGIC(*ahdr) == NMAGIC) {
    267       1.1    isaki 		/*
    268       1.1    isaki 		 * this is an a.out
    269       1.1    isaki 		 */
    270       1.1    isaki #ifdef LOADBSD
    271       1.1    isaki 		if (opt_v)
    272       1.1    isaki 			xwarnx("%s: is an a.out", kernel_fn);
    273       1.1    isaki #endif
    274       1.1    isaki #ifdef BOOT
    275       1.1    isaki B_PRINT("This is an a.out\r\n");
    276       1.1    isaki #endif
    277       1.1    isaki 
    278       1.1    isaki 		if ((u = N_GETMID(*ahdr)) != MID_M68K)
    279       1.1    isaki 			ERRX((1, "%s: Wrong architecture (mid %u)",
    280       1.1    isaki 					kernel_fn, u));
    281       1.1    isaki 
    282       1.1    isaki 		/*
    283       1.1    isaki 		 * fill in loading information
    284       1.1    isaki 		 */
    285       1.1    isaki 		xk_aout(xarg, ahdr);
    286       1.1    isaki 
    287       1.1    isaki 	} else {
    288       1.1    isaki 
    289       1.1    isaki 		/*
    290       1.1    isaki 		 * check ELF header
    291       1.1    isaki 		 */
    292       1.1    isaki 		if (*(u_int32_t *)&ehdr->e_ident[EI_MAG0] !=
    293       1.1    isaki 			(ELFMAG0<<24 | ELFMAG1<<16 | ELFMAG2<<8 | ELFMAG3) ||
    294       1.1    isaki 		    *(u_int16_t *)&ehdr->e_ident[EI_CLASS] !=
    295       1.1    isaki 			(ELFCLASS32 << 8 | ELFDATA2MSB))
    296       1.1    isaki 			ERRX((1, "%s: Not an NMAGIC a.out or a 32bit BE ELF",
    297       1.1    isaki 					kernel_fn));
    298       1.1    isaki 
    299       1.1    isaki 		/*
    300       1.1    isaki 		 * this is an ELF
    301       1.1    isaki 		 */
    302       1.1    isaki #ifdef LOADBSD
    303       1.1    isaki 		if (opt_v)
    304       1.1    isaki 			xwarnx("%s: is an ELF", kernel_fn);
    305       1.1    isaki #endif
    306       1.1    isaki #ifdef BOOT
    307       1.1    isaki B_PRINT("This is an ELF\r\n");
    308       1.1    isaki #endif
    309       1.1    isaki 
    310       1.1    isaki 		if (ehdr->e_ident[EI_VERSION] != EV_CURRENT ||
    311       1.1    isaki 		    ehdr->e_version != EV_CURRENT)
    312       1.1    isaki 			ERRX((1, "%s: Unsupported ELF version", kernel_fn));
    313       1.1    isaki 
    314       1.1    isaki 		if ((u = ehdr->e_machine) != EM_68K)
    315       1.1    isaki 			ERRX((1, "%s: Wrong architecture (mid %u)",
    316       1.1    isaki 					kernel_fn, u));
    317       1.1    isaki 		if (ehdr->e_type != ET_EXEC)
    318       1.1    isaki 			ERRX((1, "%s: Not an executable", kernel_fn));
    319       1.1    isaki 		if ((u = ehdr->e_phnum) != 1 && u != 2)
    320       1.1    isaki 			ERRX((1, "%s: Wrong number (%u) of loading sections",
    321       1.1    isaki 					kernel_fn, u));
    322       1.1    isaki 
    323       1.1    isaki 		/*
    324       1.1    isaki 		 * fill in loading information
    325       1.1    isaki 		 */
    326       1.1    isaki 		xk_elf(xarg, ehdr);
    327       1.1    isaki 	}
    328       1.1    isaki 
    329       1.1    isaki 	return 0;
    330       1.1    isaki }
    331