1 1.6 dsl /* $NetBSD: exec_sub.c,v 1.6 2009/03/14 21:04:17 dsl 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.4 dsl void B_PRINT(const unsigned char *p); 11 1.1 isaki #endif 12 1.1 isaki 13 1.4 dsl static inline void bzero4(void *ptr, size_t siz); 14 1.4 dsl static void xk_aout(struct execkern_arg *xarg, struct exec *hdr); 15 1.4 dsl static void xk_elf(struct execkern_arg *xarg, Elf32_Ehdr *hdr); 16 1.1 isaki 17 1.1 isaki #ifdef LOADBSD 18 1.4 dsl static void DPRINT_SEC(const char *ident, 19 1.4 dsl 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.5 dsl 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.5 dsl 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.5 dsl 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.5 dsl 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.6 dsl xk_load(struct execkern_arg *xarg, void *buf, u_long loadaddr) 249 1.6 dsl /* 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