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