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