static int is_aout_shared_lib(const char *name) { struct exec ex; struct stat st; int fd; if (stat(name, &st) < 0) return 0; if ((st.st_mode & (S_IFREG|S_IFLNK)) == 0) return 0; fd = open(name, O_RDONLY); if (fd < 0) { return 0; } if (read(fd, &ex, sizeof ex) - sizeof ex != 0) { close(fd); return 0; } close(fd); if (N_GETMAGIC(ex) != ZMAGIC || (N_GETFLAG(ex) & EX_DYNAMIC) == 0) return 0; return 1; }
static int exec_simple(int fd, const char *path, char *const argv[], char *const envp[], struct Env *e, u_int flags) { struct exec hdr; int r; if (lseek(fd, 0, SEEK_SET) == -1 || read(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) return 0; if (N_GETMAGIC(hdr) == EXOS_MAGIC) { int ret; ret = __do_simple_load (fd, e); if (ret < 0) { fprintf (stderr, "Could not load EXOS_MAGIC executable\n"); if (!(flags & _EXEC_USE_FD)) close(fd); return -ENOEXEC; } if ((r = setup_new_stack_simple(argv,envp,e->env_id,&e->env_tf.tf_esp)<0)) return r; return 1; } return 0; }
/* * Make encoded (compressed) data. */ static void mk_data(const struct iodesc * idi, const struct iodesc * ido, struct kgz_hdr * kh, size_t off) { union { struct exec ex; Elf32_Ehdr ee; } hdr; struct stat sb; struct iodesc idp; int fd[2]; pid_t pid; size_t n; int fmt, status, e; n = xread(idi, &hdr, sizeof(hdr), 0); fmt = 0; if (n >= sizeof(hdr.ee) && IS_ELF(hdr.ee)) fmt = F_ELF; else if (n >= sizeof(hdr.ex) && N_GETMAGIC(hdr.ex) == ZMAGIC) fmt = F_AOUT; if (!fmt) errx(1, "%s: Format not supported", idi->fname); xseek(ido, off); if (pipe(fd)) err(1, NULL); switch (pid = fork()) { case -1: err(1, NULL); case 0: close(fd[1]); dup2(fd[0], STDIN_FILENO); close(fd[0]); close(idi->fd); dup2(ido->fd, STDOUT_FILENO); close(ido->fd); execlp("gzip", "gzip", "-9n", (char *)NULL); warn(NULL); _exit(1); default: close(fd[0]); idp.fname = "(pipe)"; idp.fd = fd[1]; e = fmt == F_ELF ? ld_elf(idi, &idp, kh, &hdr.ee) : fmt == F_AOUT ? ld_aout(idi, &idp, kh, &hdr.ex) : -1; close(fd[1]); if ((pid = waitpid(pid, &status, 0)) == -1) err(1, NULL); if (WIFSIGNALED(status) || WEXITSTATUS(status)) exit(1); } if (e) errx(1, "%s: Invalid format", idi->fname); if (fstat(ido->fd, &sb)) err(1, "%s", ido->fname); kh->nsize = sb.st_size - off; }
/* * Link KGZ file and loader. */ void kgzld(struct kgz_hdr * kh, const char *f1, const char *f2) { char addr[16]; struct iodesc idi; pid_t pid; size_t n; int status; if (strcmp(kh->ident, "KGZ")) { if ((idi.fd = open(idi.fname = f1, O_RDONLY)) == -1) err(1, "%s", idi.fname); if (!format) { union { struct exec ex; Elf32_Ehdr ee; } hdr; n = xread(&idi, &hdr, sizeof(hdr), 0); if (n >= sizeof(hdr.ee) && IS_ELF(hdr.ee)) format = F_ELF; else if (n >= sizeof(hdr.ex) && N_GETMAGIC(hdr.ex) == OMAGIC) format = F_AOUT; if (!format) errx(1, "%s: Format not supported", idi.fname); } n = xread(&idi, kh, sizeof(*kh), format == F_AOUT ? sizeof(struct kgz_aouthdr0) : sizeof(struct kgz_elfhdr)); xclose(&idi); if (n != sizeof(*kh) || strcmp(kh->ident, "KGZ")) errx(1, "%s: Invalid format", idi.fname); } sprintf(addr, "%#x", align(kh->dload + kh->dsize, 0x1000)); switch (pid = fork()) { case -1: err(1, NULL); case 0: if (format == F_AOUT) execlp("ld", "ld", "-aout", "-Z", "-T", addr, "-o", f2, loader, f1, (char *)NULL); else execlp("ld", "ld", "-Ttext", addr, "-o", f2, loader, f1, (char *)NULL); warn(NULL); _exit(1); default: if ((pid = waitpid(pid, &status, 0)) == -1) err(1, NULL); if (WIFSIGNALED(status) || WEXITSTATUS(status)) exit(1); } }
static int is_exos_aout(int fd) { struct exec hdr; u_int dynamic; if (lseek(fd, 0, SEEK_SET) == -1 || read(fd, &hdr, sizeof(hdr)) != sizeof(hdr) || lseek(fd, sizeof(hdr) + hdr.a_text, SEEK_SET) == -1 || read(fd, &dynamic, sizeof(dynamic)) != sizeof(dynamic)) return 0; if (N_GETMAGIC(hdr) != OMAGIC || N_GETMID(hdr) != MID_I386 || N_GETFLAG(hdr) != 0) return 0; return 1; }
void run_header(struct exec *exhdr, int extended_info) { char *id = NULL; assert(NULL != exhdr); /* print raw values */ printf( "\ta_midmag 0x%08x (mid %d, magic 0%o, flag 0x%x)\n" "\ta_text 0x%08x\n" "\ta_data 0x%08x\n" "\ta_bss 0x%08x\n" "\ta_syms 0x%08x\n" "\ta_entry 0x%08x\n" "\ta_trsize 0x%08x\n" "\ta_drsize 0x%08x\n", exhdr->a_midmag, N_GETMID(*exhdr), N_GETMAGIC(*exhdr), N_GETFLAG(*exhdr), exhdr->a_text, exhdr->a_data, exhdr->a_bss, exhdr->a_syms, exhdr->a_entry, exhdr->a_trsize, exhdr->a_drsize ); printf( "magic number %04o: %s\n", N_GETMAGIC(*exhdr), N_GETMAGIC(*exhdr) == OMAGIC ? "old impure format" : N_GETMAGIC(*exhdr) == NMAGIC ? "read-only text" : N_GETMAGIC(*exhdr) == ZMAGIC ? "demand load format" : N_GETMAGIC(*exhdr) == QMAGIC ? "deprecated format" : "totally funky" ); switch (N_GETMID(*exhdr)) { case MID_ZERO: id = "unknown - implementation dependent"; break; case MID_SUN010: id = "sun 68010/68020 binary"; break; case MID_SUN020: id = "sun 68020-only binary"; break; case MID_PC386: id = "386 PC binary. (so quoth BFD)"; break; case MID_HP200: id = "hp200 (68010) BSD binary"; break; case MID_I386: id = "i386 BSD binary"; break; case MID_M68K: id = "m68k BSD binary with 8K page sizes"; break; case MID_M68K4K: id = "m68k BSD binary with 4K page sizes"; break; case MID_NS32532: id = "ns32532"; break; case MID_SPARC: id = "sparc"; break; case MID_PMAX: id = "pmax"; break; case MID_VAX: id = "vax"; break; case MID_ALPHA: id = "Alpha BSD binary"; break; case MID_MIPS: id = "big-endian MIPS"; break; case MID_ARM6: id = "ARM6"; break; case MID_HP300: id = "hp300 (68020+68881) BSD binary"; break; case MID_HPUX: id = "hp200/300 HP-UX binary"; break; case MID_HPUX800: id = "hp800 HP-UX binary"; break; default: id = "don't know"; break; } printf("type %d, %s\n", N_GETMID(*exhdr), id); /* this left shift seems a bit bogus */ switch((N_GETFLAG(*exhdr) & EX_DPMASK)>>4) { case 0: id = "traditional executable or object file"; break; case 1: id = "object file contains PIC code"; break; case 2: id = "dynamic executable"; break; case 3: id = "position independent executable image"; break; default: id = NULL; } if (NULL != id) printf("flags: 0x%x, %s\n", N_GETFLAG(*exhdr), id); else printf("flags: 0x%x\n", N_GETFLAG(*exhdr)); if (extended_info) { unsigned long txt_addr; unsigned long dat_addr; unsigned long bss_addr; /* N_TXTADDR and N_DATADDR macros DON'T WORK */ if (N_GETMAGIC(*exhdr) == ZMAGIC) { txt_addr = __LDPGSZ; dat_addr = ((txt_addr + exhdr->a_text + __LDPGSZ - 1) & ~(__LDPGSZ - 1)); } else if (N_GETMAGIC(*exhdr) == OMAGIC) { txt_addr = 0; dat_addr = txt_addr + exhdr->a_text; } else { txt_addr = 0xdeadbeef; dat_addr = 0xcafebabe; } bss_addr = dat_addr + exhdr->a_data; printf(" text segment size = 0x%lx, text segment file offset = %ld\n", exhdr->a_text, N_TXTOFF(*exhdr)); printf(" data segment size = 0x%lx, data segment file offset = %ld\n", exhdr->a_data, N_DATOFF(*exhdr)); printf(" bss segment size = 0x%lx\n", exhdr->a_bss); printf(" text segment relocation size = 0x%lx, file offset = %ld, %d text relocations\n", exhdr->a_trsize, N_TRELOFF(*exhdr), exhdr->a_trsize/sizeof(struct relocation_info)); printf(" data segment relocation size = 0x%lx, file offset = %ld, %d data relocations\n", exhdr->a_drsize, N_DRELOFF(*exhdr), exhdr->a_drsize/sizeof(struct relocation_info)); printf(" symbol table size = 0x%lx, symbol table file offset = %ld (%d symbols)\n", exhdr->a_syms, N_SYMOFF(*exhdr), exhdr->a_syms/sizeof(struct nlist)); printf(" string table file offset = 0x%lx (%d)\n", N_STROFF(*exhdr), N_STROFF(*exhdr)); printf(" entry point = 0x%lx\n", exhdr->a_entry); printf(" text address = 0x%lx\n\tdata address = 0x%lx\n" "\tbss address = 0x%lx\n", txt_addr, dat_addr, bss_addr /* N_TXTADDR(*exhdr), N_DATADDR(*exhdr), N_BSSADDR(*exhdr) */ ); } }
/* * Get file size and read a.out or ELF header. */ static void gethdr(int fd, struct hdr *hdr) { struct stat sb; const struct exec *ex; const Elf32_Ehdr *ee; const Elf32_Phdr *ep; void *p; unsigned int fmt, x, n, i; memset(hdr, 0, sizeof(*hdr)); if (fstat(fd, &sb)) err(2, "%s", fname); if (sb.st_size > MAXU32) errx(1, "%s: Too big", fname); hdr->size = sb.st_size; if (!hdr->size) return; if ((p = mmap(NULL, hdr->size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) err(2, "%s", fname); for (fmt = F_CNT - 1; !hdr->fmt && fmt; fmt--) switch (fmt) { case F_AOUT: ex = p; if (hdr->size >= sizeof(struct exec) && !N_BADMAG(*ex)) { hdr->fmt = fmt; x = N_GETMAGIC(*ex); if (x == OMAGIC || x == NMAGIC) { if (x == NMAGIC) Warn(fname, "Treating %s NMAGIC as OMAGIC", fmtlist[fmt]); hdr->flags |= IMPURE; } hdr->text = le32toh(ex->a_text); hdr->data = le32toh(ex->a_data); hdr->bss = le32toh(ex->a_bss); hdr->entry = le32toh(ex->a_entry); if (le32toh(ex->a_entry) >= BTX_PGSIZE) hdr->org = BTX_PGSIZE; } break; case F_ELF: ee = p; if (hdr->size >= sizeof(Elf32_Ehdr) && IS_ELF(*ee)) { hdr->fmt = fmt; for (n = i = 0; i < le16toh(ee->e_phnum); i++) { ep = (void *)((uint8_t *)p + le32toh(ee->e_phoff) + le16toh(ee->e_phentsize) * i); if (le32toh(ep->p_type) == PT_LOAD) switch (n++) { case 0: hdr->text = le32toh(ep->p_filesz); hdr->org = le32toh(ep->p_paddr); if (le32toh(ep->p_flags) & PF_W) hdr->flags |= IMPURE; break; case 1: hdr->data = le32toh(ep->p_filesz); hdr->bss = le32toh(ep->p_memsz) - le32toh(ep->p_filesz); break; case 2: Warn(fname, "Ignoring extra %s PT_LOAD segments", fmtlist[fmt]); } } hdr->entry = le32toh(ee->e_entry); } } if (munmap(p, hdr->size)) err(2, "%s", fname); }
/* * Read in program from the given file descriptor. * Return error code (0 on success). * Fill in marks. */ int fdloadfile(int fd, u_long *marks, int flags) { union { #ifdef BOOT_ECOFF struct ecoff_exechdr coff; #endif #ifdef BOOT_ELF32 Elf32_Ehdr elf32; #endif #ifdef BOOT_ELF64 Elf64_Ehdr elf64; #endif #ifdef BOOT_AOUT struct exec aout; #endif } hdr; ssize_t nr; int rval; /* Read the exec header. */ if (lseek(fd, 0, SEEK_SET) == (off_t)-1) goto err; nr = read(fd, &hdr, sizeof(hdr)); if (nr == -1) { WARN(("read header failed")); goto err; } if (nr != sizeof(hdr)) { WARN(("read header short")); errno = EFTYPE; goto err; } #ifdef BOOT_ECOFF if (!ECOFF_BADMAG(&hdr.coff)) { rval = loadfile_coff(fd, &hdr.coff, marks, flags); } else #endif #ifdef BOOT_ELF32 if (memcmp(hdr.elf32.e_ident, ELFMAG, SELFMAG) == 0 && hdr.elf32.e_ident[EI_CLASS] == ELFCLASS32) { netbsd_elf_class = ELFCLASS32; rval = loadfile_elf32(fd, &hdr.elf32, marks, flags); } else #endif #ifdef BOOT_ELF64 if (memcmp(hdr.elf64.e_ident, ELFMAG, SELFMAG) == 0 && hdr.elf64.e_ident[EI_CLASS] == ELFCLASS64) { netbsd_elf_class = ELFCLASS64; rval = loadfile_elf64(fd, &hdr.elf64, marks, flags); } else #endif #ifdef BOOT_AOUT if (OKMAGIC(N_GETMAGIC(hdr.aout)) #ifndef NO_MID_CHECK && N_GETMID(hdr.aout) == MID_MACHINE #endif ) { rval = loadfile_aout(fd, &hdr.aout, marks, flags); } else #endif { rval = 1; errno = EFTYPE; } if (rval == 0) { if ((flags & LOAD_ALL) != 0) PROGRESS(("=0x%lx\n", marks[MARK_END] - marks[MARK_START])); return 0; } err: return errno; }
static void load(void) { union { struct exec ex; Elf32_Ehdr eh; } hdr; Elf32_Phdr ep[2]; Elf32_Shdr es[2]; caddr_t p; ino_t ino; uint32_t addr, x; int fmt, i, j; if (!(ino = lookup(kname))) { if (!ls) printf("No %s\n", kname); return; } if (xfsread(ino, &hdr, sizeof(hdr))) return; if (N_GETMAGIC(hdr.ex) == ZMAGIC) fmt = 0; else if (IS_ELF(hdr.eh)) fmt = 1; else { printf("Invalid %s\n", "format"); return; } if (fmt == 0) { addr = hdr.ex.a_entry & 0xffffff; p = PTOV(addr); fs_off = PAGE_SIZE; if (xfsread(ino, p, hdr.ex.a_text)) return; p += roundup2(hdr.ex.a_text, PAGE_SIZE); if (xfsread(ino, p, hdr.ex.a_data)) return; p += hdr.ex.a_data + roundup2(hdr.ex.a_bss, PAGE_SIZE); bootinfo.bi_symtab = VTOP(p); memcpy(p, &hdr.ex.a_syms, sizeof(hdr.ex.a_syms)); p += sizeof(hdr.ex.a_syms); if (hdr.ex.a_syms) { if (xfsread(ino, p, hdr.ex.a_syms)) return; p += hdr.ex.a_syms; if (xfsread(ino, p, sizeof(int))) return; x = *(uint32_t *)p; p += sizeof(int); x -= sizeof(int); if (xfsread(ino, p, x)) return; p += x; } } else { fs_off = hdr.eh.e_phoff; for (j = i = 0; i < hdr.eh.e_phnum && j < 2; i++) { if (xfsread(ino, ep + j, sizeof(ep[0]))) return; if (ep[j].p_type == PT_LOAD) j++; } for (i = 0; i < 2; i++) { p = PTOV(ep[i].p_paddr & 0xffffff); fs_off = ep[i].p_offset; if (xfsread(ino, p, ep[i].p_filesz)) return; } p += roundup2(ep[1].p_memsz, PAGE_SIZE); bootinfo.bi_symtab = VTOP(p); if (hdr.eh.e_shnum == hdr.eh.e_shstrndx + 3) { fs_off = hdr.eh.e_shoff + sizeof(es[0]) * (hdr.eh.e_shstrndx + 1); if (xfsread(ino, &es, sizeof(es))) return; for (i = 0; i < 2; i++) { memcpy(p, &es[i].sh_size, sizeof(es[i].sh_size)); p += sizeof(es[i].sh_size); fs_off = es[i].sh_offset; if (xfsread(ino, p, es[i].sh_size)) return; p += es[i].sh_size; } } addr = hdr.eh.e_entry & 0xffffff; } bootinfo.bi_esymtab = VTOP(p); bootinfo.bi_kernelname = VTOP(kname); bootinfo.bi_bios_dev = dsk.drive; __exec((caddr_t)addr, opts & RBX_MASK, MAKEBOOTDEV(dev_maj[dsk.type], 0, dsk.slice, dsk.unit, dsk.part), 0, 0, 0, VTOP(&bootinfo)); }
/* * Open 'filename', read in program and and return 0 if ok 1 on error. * Fill in marks */ int loadfile(const char *fname, u_long *marks, int flags) { union { #ifdef BOOT_ECOFF struct ecoff_exechdr coff; #endif #ifdef BOOT_ELF Elf_Ehdr elf; #endif #ifdef BOOT_AOUT struct exec aout; #endif } hdr; ssize_t nr; int fd, rval; /* Open the file. */ if ((fd = open(fname, 0)) < 0) { WARN(("open %s", fname ? fname : "<default>")); return -1; } /* Read the exec header. */ if ((nr = read(fd, &hdr, sizeof(hdr))) != sizeof(hdr)) { WARN(("read header")); goto err; } #ifdef BOOT_ECOFF if (!ECOFF_BADMAG(&hdr.coff)) { rval = coff_exec(fd, &hdr.coff, marks, flags); } else #endif #ifdef BOOT_ELF if (memcmp(hdr.elf.e_ident, ELFMAG, SELFMAG) == 0 && hdr.elf.e_ident[EI_CLASS] == ELFCLASS) { #ifdef BOOT_ZBOOT rval = zboot_exec(fd, marks, flags); #else rval = elf_exec(fd, &hdr.elf, marks, flags); #endif } else #endif #ifdef BOOT_AOUT if (OKMAGIC(N_GETMAGIC(hdr.aout)) #ifndef NO_MID_CHECK && N_GETMID(hdr.aout) == MID_MACHINE #endif ) { rval = aout_exec(fd, &hdr.aout, marks, flags); } else #endif { rval = 1; errno = EFTYPE; WARN(("%s", fname ? fname : "<default>")); } if (rval == 0) { PROGRESS(("=0x%lx\n", marks[MARK_END] - marks[MARK_START])); return fd; } err: (void)close(fd); return -1; }
static int aout_exec(int fd, struct exec *aout, vaddr_t *entryp) { caddr_t addr = (caddr_t)LOADADDR; int strtablen; char *strtab; vaddr_t entry = (vaddr_t)LOADADDR; int i; printf("%d", aout->a_text); if (N_GETMAGIC(*aout) == ZMAGIC) { entry = (vaddr_t)(addr+sizeof(struct exec)); addr += sizeof(struct exec); } /* we can't lseek() here - we may be booting off tape */ bcopy((char *)aout + sizeof(struct exec), addr, sizeof(hdr) - sizeof(struct exec)); if (read(fd, (char *)addr + sizeof(hdr) - sizeof(struct exec), aout->a_text - (sizeof(hdr) - sizeof(struct exec))) != aout->a_text - (sizeof(hdr) - sizeof(struct exec))) goto shread; addr += aout->a_text; if (N_GETMAGIC(*aout) == ZMAGIC || N_GETMAGIC(*aout) == NMAGIC) while ((int)addr & __LDPGSZ) *addr++ = 0; printf("+%d", aout->a_data); if (read(fd, addr, aout->a_data) != aout->a_data) goto shread; addr += aout->a_data; printf("+%d", aout->a_bss); for (i = aout->a_bss; i ; --i) *addr++ = 0; if (aout->a_syms != 0) { bcopy(&aout->a_syms, addr, sizeof(aout->a_syms)); addr += sizeof(aout->a_syms); printf("+[%d", aout->a_syms); if (read(fd, addr, aout->a_syms) != aout->a_syms) goto shread; addr += aout->a_syms; if (read(fd, &strtablen, sizeof(int)) != sizeof(int)) goto shread; bcopy(&strtablen, addr, sizeof(int)); if (i = strtablen) { i -= sizeof(int); addr += sizeof(int); if (read(fd, addr, i) != i) goto shread; addr += i; } printf("+%d]", i); esym = ((u_int)aout->a_entry - (u_int)LOADADDR) + (((int)addr + sizeof(int) - 1) & ~(sizeof(int) - 1)); } printf("=0x%x\n", addr); close(fd); *entryp = entry; return (0); shread: printf("boot: short read\n"); return (1); }
long AOutParser::Read(Stream* stream) { m_pStream = stream; ULONG filesize = stream->GetSize(); if (stream->Read(&exec_header, sizeof(exec)) != sizeof(exec)) { // printf("AOut read error\n"); return -1; } switch (N_GETMAGIC(&exec_header)) { case A_MAGIC: //printf("68020"); break; case I_MAGIC: //printf("intel 386"); break; case J_MAGIC:// printf("intel 960"); break; case K_MAGIC:// printf("sparc"); break; case V_MAGIC:// printf("mips 3000"); break; case X_MAGIC:// printf("att dsp 3210"); break; case M_MAGIC:// printf("mips 4000"); break; case D_MAGIC:// printf("amd 29000"); break; case E_MAGIC:// printf("arm 7-something"); break; case Q_MAGIC:// printf("powerpc"); break; case N_MAGIC:// printf("mips 4000-le"); break; case L_MAGIC:// printf("dec alpha"); break; break; default: // printf("AOut: Unknown magic\n"); return -2; } exec_header.a_text = BigEndian32(exec_header.a_text); exec_header.a_data = BigEndian32(exec_header.a_data); exec_header.a_bss = BigEndian32(exec_header.a_bss); exec_header.a_trsize = BigEndian32(exec_header.a_trsize); exec_header.a_drsize = BigEndian32(exec_header.a_drsize); exec_header.a_syms = BigEndian32(exec_header.a_syms); m_numberOfSections = 0; m_Sections[0] = -1; m_Sections[1] = -1; m_Sections[2] = -1; if (exec_header.a_text) m_Sections[m_numberOfSections++] = 0; if (exec_header.a_data) m_Sections[m_numberOfSections++] = 1; if (exec_header.a_bss) m_Sections[m_numberOfSections++] = 2; m_nsymbols = exec_header.a_syms / sizeof(nlist); #if 0 printf("text size: %d\n", exec_header.a_text); printf("data size: %d\n", exec_header.a_data); printf("bss size: %d\n", exec_header.a_bss); printf("text reloc size: %d\n", exec_header.a_trsize); printf("data reloc size: %d\n", exec_header.a_drsize); printf("symbol size: %d\n", exec_header.a_syms); printf("number of symbols: %d\n", nsymbols); #endif m_TextOffset = sizeof(exec); m_DataOffset = sizeof(exec) + exec_header.a_text; m_TextRelocOffset = m_DataOffset + exec_header.a_data; m_DataRelocOffset = m_TextRelocOffset + exec_header.a_trsize; m_SymbolTableOffset = m_DataRelocOffset + exec_header.a_drsize; m_StringTableOffset = m_SymbolTableOffset + exec_header.a_syms; { int count = exec_header.a_trsize / sizeof(relocation_info); // fprintf(stdout, "nrelocs: %d\n", count); if (count) { stream->Seek(m_TextRelocOffset, System::IO::STREAM_SEEK_SET); m_tr = new Relocation[count]; for (int i = 0; i < count; i++) { relocation_info relocinfo;// = &m_tr[i]; stream->Read(&relocinfo, sizeof(relocation_info)); m_tr[i].r_address = BigEndian32(relocinfo.r_address); // ((DWORD*)&relocinfo)[1] = BigEndian32(((DWORD*)&relocinfo)[1]); // fprintf(stdout, "r_address: %d, ", m_tr[i].r_address); uint8* bf = (uint8*)(((uint32*)&relocinfo)+1); bool r_pcrel = (bf[3] >> 7) & 0x1; int r_length = (bf[3] >> 5) & 0x3; bool r_extern = (bf[3] >> 4) & 0x1; bool r_baserel = (bf[3] >> 3) & 0x1; bool r_jmptable = (bf[3] >> 2) & 0x1; bool r_relative = (bf[3] >> 1) & 0x1; bool r_copy = (bf[3] >> 0) & 0x1; // TODO, support other values on these VERIFY(r_length == 2); VERIFY(r_baserel == 0); VERIFY(r_jmptable == 0); VERIFY(r_relative == 0); VERIFY(r_copy == 0); m_tr[i].r_extern = r_extern; m_tr[i].r_pcrel = r_pcrel; //TRACE("pcrel: %d, baserel: %d, relative: %d, copy: %d\n", r_pcrel, r_baserel, r_relative, r_copy); uint32 symbolnum = (bf[0]<<16) | (bf[1]<<8) | (bf[2]); //printf("symbolnum: %d, r_baserel: %d, r_extern: %d\n", symbolnum, r_baserel, r_extern); // relocinfo->r_symbolnum = symbolnum; // hm.. m_tr[i].r_symbolnum = symbolnum; // fprintf(stdout, "symbolnum: %d", m_tr[i].r_symbolnum); // printf("Text Reloc(addr=%d, symbol=%d)\n", relocinfo->r_address - m_TextOffset, symbolnum); // fprintf(stdout, "\n"); } } } { int count = exec_header.a_drsize / sizeof(relocation_info); // fprintf(stdout, "nrelocs: %d\n", count); if (count) { stream->Seek(m_DataRelocOffset, System::IO::STREAM_SEEK_SET); m_dr = new Relocation[count]; for (int i = 0; i < count; i++) { relocation_info relocinfo;// = &m_tr[i]; stream->Read(&relocinfo, sizeof(relocation_info)); m_dr[i].r_address = BigEndian32(relocinfo.r_address); // ((DWORD*)&relocinfo)[1] = BigEndian32(((DWORD*)&relocinfo)[1]); // fprintf(stdout, "r_address: %d, ", m_tr[i].r_address); uint8* bf = (uint8*)(((uint32*)&relocinfo)+1); bool r_pcrel = (bf[3] >> 7) & 0x1; int r_length = (bf[3] >> 5) & 0x3; bool r_extern = (bf[3] >> 4) & 0x1;; bool r_baserel = (bf[3] >> 3) & 0x1; bool r_jmptable = (bf[3] >> 2) & 0x1; bool r_relative = (bf[3] >> 1) & 0x1; bool r_copy = (bf[3] >> 0) & 0x1; // ASSERT(r_pcrel == 0); ASSERT(r_length == 2); ASSERT(r_baserel == 0); ASSERT(r_jmptable == 0); ASSERT(r_relative == 0); ASSERT(r_copy == 0); m_dr[i].r_extern = r_extern; m_dr[i].r_pcrel = r_pcrel; //TRACE("pcrel: %d, baserel: %d, relative: %d, copy: %d\n", r_pcrel, r_baserel, r_relative, r_copy); uint32 symbolnum = (bf[0]<<16) | (bf[1]<<8) | (bf[2]); //printf("symbolnum: %d, r_baserel: %d, r_extern: %d\n", symbolnum, r_baserel, r_extern); // relocinfo->r_symbolnum = symbolnum; // hm.. m_dr[i].r_symbolnum = symbolnum; // fprintf(stdout, "symbolnum: %d", m_tr[i].r_symbolnum); // printf("Text Reloc(addr=%d, symbol=%d)\n", relocinfo->r_address - m_TextOffset, symbolnum); // fprintf(stdout, "\n"); } } } // Symbols if (m_nsymbols) { m_nlistSymbols = new nlist[m_nsymbols]; long StringTableLen = filesize - m_StringTableOffset; stream->position = m_StringTableOffset; m_StringData = new char[StringTableLen]; int n = stream->Read(m_StringData, StringTableLen); ASSERT(n == StringTableLen); stream->position = m_SymbolTableOffset; for (int i = 0; i < m_nsymbols; i++) { nlist& symbol = m_nlistSymbols[i]; stream->Read(&symbol, sizeof(nlist)); symbol.n_un.n_strx = BigEndian32(symbol.n_un.n_strx); symbol.n_value = BigEndian32(symbol.n_value); symbol.n_desc = BigEndian16(symbol.n_desc); // Convert offset into string table to pointer symbol.n_un.n_name = m_StringData + symbol.n_un.n_strx; if ((symbol.n_type & N_TYPE) == N_DATA) { symbol.n_value -= exec_header.a_text; } /* printf("%d, %s, value=%d, type=%d", i+1, symbol.n_un.n_name, symbol.n_value, symbol.n_type); printf("\n"); */ } } #if 0 { uint8* text = new uint8[exec_header.a_text]; if (text == NULL) { printf("Out of memory"); return -1; } fseek(fp, m_TextOffset, SEEK_SET); fread(text, 1, exec_header.a_text, fp); // Text Code if (N_GETMAGIC(&exec_header) == A_MAGIC) // // 68020 { pass2_CODE(text, exec_header.a_text, m_nsymbols, Symbols); } else if (N_GETMAGIC(&exec_header) == I_MAGIC) // intel 386 { ReadCode_x86(text, exec_header.a_text); } else if (N_GETMAGIC(&exec_header) == Q_MAGIC) // powerpc { dasm_powerpc(text, exec_header.a_text); } else { } delete[] text; } #endif return 0; }
static int exec_exos_aout(int fd, const char *path, char *const argv[], char *const envp[], struct Env *e, u_int flags) { u_int envid = e->env_id; struct exec hdr; u_int dynamic; int r; struct _exos_exec_args eea; if (lseek(fd, 0, SEEK_SET) == -1 || read(fd, &hdr, sizeof(hdr)) != sizeof(hdr) || lseek(fd, sizeof(hdr) + hdr.a_text, SEEK_SET) == -1 || read(fd, &dynamic, sizeof(dynamic)) != sizeof(dynamic)) return 0; if (N_GETMAGIC(hdr) != OMAGIC || N_GETMID(hdr) != MID_I386 || N_GETFLAG(hdr) != 0) return 0; if (!(flags & _EXEC_USE_FD)) { close(fd); fd = -1; } else if (lseek(fd, 0, SEEK_SET) == -1) return 0; if (dynamic < SHARED_LIBRARY_START) dynamic = 0; if (dynamic == 0 && (flags & _EXEC_SHLIB_ONLY)) { r = -EINVAL; goto err; } /* if static, then read in entire program... */ if (!dynamic) { u_int start_text_addr; if (flags & _EXEC_USE_FD) start_text_addr = __load_prog_fd(fd, 1, envid); else start_text_addr = __load_prog(path, argv[0], 1, envid); if (!start_text_addr) { r = -ENOEXEC; goto err; } /* set start address */ e->env_tf.tf_eip = start_text_addr; } /* if dynamic, then make sure shared library is available */ else if (dynamic) { struct stat sb; /* If flag so indicates, then require RO copy and use in mem version */ if (!(flags & _EXEC_SHLIB_ONLY)) { /* if the shared library is not already in memory, or if it's old */ /* then we need to (re)read it in */ if (stat(PATH_LIBEXOS, &sb)) { r = -errno; kprintf("error stat'ing sl: %d\n", errno); goto err; } /* if we don't have a RO copy or it's out of date... */ if (!isvamapped(SHARED_LIBRARY_START_RODATA) || memcmp(&sl_data->mod_time, &sb.st_mtimespec, sizeof(sb.st_mtimespec))) { int slfd; /* if it's out of date, then unmap it */ if (isvamapped(SHARED_LIBRARY_START_RODATA)) munmap((void*)SHARED_LIBRARY_START_RODATA, (sl_data->text_pages + sl_data->data_pages) * NBPG); slfd = open (PATH_LIBEXOS, O_RDONLY); if (slfd < 0) { r = -errno; kprintf("could not open shared library " PATH_LIBEXOS "\n"); goto err; } if ((r = __load_sl_image (slfd)) < 0) { kprintf("could not load library\n"); close(slfd); goto err; } *((struct timespec*)&sl_data->mod_time) = sb.st_mtimespec; assert(sys_self_mod_pte_range(0, PG_RO, PG_W, SHARED_LIBRARY_START_RODATA, 1) == 0); close (slfd); } } else { if (!isvamapped(SHARED_LIBRARY_START_RODATA)) { r = -EINVAL; goto err; } } /* share the text region read only/exec into child */ if (__vm_share_region(SHARED_LIBRARY_START_RODATA, sl_data->text_pages * NBPG, 0, 0, envid, SHARED_LIBRARY_START)) { kprintf ("__vm_share_region failed for text region\n"); r = -ENOEXEC; goto err; } /* share the read only data region into child cow */ if (__vm_share_region(SHARED_LIBRARY_START_RODATA + sl_data->text_pages * NBPG, sl_data->data_pages * NBPG, 0, 0, envid, SHARED_LIBRARY_START + sl_data->text_pages * NBPG)) { kprintf ("__vm_share_region failed for cow data region\n"); r = -ENOEXEC; goto err; } if (sys_mod_pte_range(0, PG_COW, PG_RO | PG_SHARED, SHARED_LIBRARY_START + sl_data->text_pages * NBPG, sl_data->data_pages, 0, envid) < 0) { kprintf ("sys_mod_pte_range failed for cow data region\n"); r = -ENOEXEC; goto err; } /* share the RO copy of the shared library */ if (__vm_share_region(SHARED_LIBRARY_START_RODATA, (sl_data->text_pages + sl_data->data_pages) * NBPG, 0, 0, envid, SHARED_LIBRARY_START_RODATA)) { kprintf ("__vm_share_region failed for read only text/data region\n"); r = -ENOEXEC; goto err; } /* demand alloc bss for sl or no? */ if (getenv("NO_BSS_DEMAND_ALLOC")) { /* zero the bss */ if (__zero_segment (envid, SHARED_LIBRARY_START + (sl_data->text_pages + sl_data->data_pages) * NBPG, sl_data->bss_pages * NBPG) < 0) { kprintf("could not create bss segment\n"); r = -ENOEXEC; goto err; } } /* otherwise the fault handler will deal with it */ /* set start address */ e->env_tf.tf_eip = SHARED_LIBRARY_START + sizeof(struct exec); } /* take care of args, etc */ if (flags & _EXEC_USE_FD) eea.eea_prog_fd = fd; else eea.eea_prog_fd = -1; if ((r = setup_new_stack(argv, envp, envid, &e->env_tf.tf_esp, &eea)) < 0) goto err; return 1; err: return r; }
/* * It should be responsible for setting up everything that must be * in place when main is called. * This includes: * Initializing the physical console so characters can be printed. * Setting up page tables for the kernel. */ u_int init_sa11x0(int argc, char **argv, struct bootinfo *bi) { u_int kerneldatasize, symbolsize; u_int l1pagetable; vaddr_t freemempos; vsize_t pt_size; int loop; #if NKSYMS || defined(DDB) || defined(MODULAR) Elf_Shdr *sh; #endif #ifdef DEBUG_BEFOREMMU /* * At this point, we cannot call real consinit(). * Just call a faked up version of consinit(), which does the thing * with MMU disabled. */ fakecninit(); #endif /* * XXX for now, overwrite bootconfig to hardcoded values. * XXX kill bootconfig and directly call uvm_physload */ bootconfig.dram[0].address = 0xc0000000; bootconfig.dram[0].pages = DRAM_PAGES; bootconfig.dramblocks = 1; kerneldatasize = (uint32_t)&end - (uint32_t)KERNEL_TEXT_BASE; symbolsize = 0; #if NKSYMS || defined(DDB) || defined(MODULAR) if (!memcmp(&end, "\177ELF", 4)) { sh = (Elf_Shdr *)((char *)&end + ((Elf_Ehdr *)&end)->e_shoff); loop = ((Elf_Ehdr *)&end)->e_shnum; for (; loop; loop--, sh++) if (sh->sh_offset > 0 && (sh->sh_offset + sh->sh_size) > symbolsize) symbolsize = sh->sh_offset + sh->sh_size; } #endif printf("kernsize=0x%x\n", kerneldatasize); kerneldatasize += symbolsize; kerneldatasize = ((kerneldatasize - 1) & ~(PAGE_SIZE * 4 - 1)) + PAGE_SIZE * 8; /* * hpcboot has loaded me with MMU disabled. * So create kernel page tables and enable MMU. */ /* * Set up the variables that define the availability of physcial * memory. */ physical_start = bootconfig.dram[0].address; physical_freestart = physical_start + (KERNEL_TEXT_BASE - KERNEL_BASE) + kerneldatasize; physical_end = bootconfig.dram[bootconfig.dramblocks - 1].address + bootconfig.dram[bootconfig.dramblocks - 1].pages * PAGE_SIZE; physical_freeend = physical_end; for (loop = 0; loop < bootconfig.dramblocks; ++loop) physmem += bootconfig.dram[loop].pages; /* XXX handle UMA framebuffer memory */ /* Use the first 256kB to allocate things */ freemempos = KERNEL_BASE; memset((void *)KERNEL_BASE, 0, KERNEL_TEXT_BASE - KERNEL_BASE); /* * Right. We have the bottom meg of memory mapped to 0x00000000 * so was can get at it. The kernel will occupy the start of it. * After the kernel/args we allocate some of the fixed page tables * we need to get the system going. * We allocate one page directory and NUM_KERNEL_PTS page tables * and store the physical addresses in the kernel_pt_table array. * Must remember that neither the page L1 or L2 page tables are the * same size as a page ! * * Ok, the next bit of physical allocate may look complex but it is * simple really. I have done it like this so that no memory gets * wasted during the allocate of various pages and tables that are * all different sizes. * The start address will be page aligned. * We allocate the kernel page directory on the first free 16KB * boundary we find. * We allocate the kernel page tables on the first 1KB boundary we * find. We allocate at least 9 PT's (12 currently). This means * that in the process we KNOW that we will encounter at least one * 16KB boundary. * * Eventually if the top end of the memory gets used for process L1 * page tables the kernel L1 page table may be moved up there. */ #ifdef VERBOSE_INIT_ARM printf("Allocating page tables\n"); #endif /* Define a macro to simplify memory allocation */ #define valloc_pages(var, np) \ alloc_pages((var).pv_pa, (np)); \ (var).pv_va = KERNEL_BASE + (var).pv_pa - physical_start; #define alloc_pages(var, np) \ (var) = freemempos; \ freemempos += (np) * PAGE_SIZE; valloc_pages(kernel_l1pt, L1_TABLE_SIZE / PAGE_SIZE); for (loop = 0; loop < NUM_KERNEL_PTS; ++loop) { alloc_pages(kernel_pt_table[loop].pv_pa, L2_TABLE_SIZE / PAGE_SIZE); kernel_pt_table[loop].pv_va = kernel_pt_table[loop].pv_pa; } /* This should never be able to happen but better confirm that. */ if (!kernel_l1pt.pv_pa || (kernel_l1pt.pv_pa & (L1_TABLE_SIZE-1)) != 0) panic("initarm: Failed to align the kernel page directory"); /* * Allocate a page for the system page mapped to V0x00000000 * This page will just contain the system vectors and can be * shared by all processes. */ valloc_pages(systempage, 1); pt_size = round_page(freemempos) - physical_start; /* Allocate stacks for all modes */ valloc_pages(irqstack, IRQ_STACK_SIZE); valloc_pages(abtstack, ABT_STACK_SIZE); valloc_pages(undstack, UND_STACK_SIZE); valloc_pages(kernelstack, UPAGES); #ifdef VERBOSE_INIT_ARM printf("IRQ stack: p0x%08lx v0x%08lx\n", irqstack.pv_pa, irqstack.pv_va); printf("ABT stack: p0x%08lx v0x%08lx\n", abtstack.pv_pa, abtstack.pv_va); printf("UND stack: p0x%08lx v0x%08lx\n", undstack.pv_pa, undstack.pv_va); printf("SVC stack: p0x%08lx v0x%08lx\n", kernelstack.pv_pa, kernelstack.pv_va); #endif alloc_pages(msgbufphys, round_page(MSGBUFSIZE) / PAGE_SIZE); /* * XXX Actually, we only need virtual space and don't need * XXX physical memory for sa110_cc_base and sa11x0_idle_mem. */ /* * XXX totally stuffed hack to work round problems introduced * in recent versions of the pmap code. Due to the calls used there * we cannot allocate virtual memory during bootstrap. */ for (;;) { alloc_pages(sa1_cc_base, 1); if (!(sa1_cc_base & (CPU_SA110_CACHE_CLEAN_SIZE - 1))) break; } alloc_pages(sa1_cache_clean_addr, CPU_SA110_CACHE_CLEAN_SIZE / PAGE_SIZE - 1); sa1_cache_clean_addr = sa1_cc_base; sa1_cache_clean_size = CPU_SA110_CACHE_CLEAN_SIZE / 2; alloc_pages(sa11x0_idle_mem, 1); /* * Ok, we have allocated physical pages for the primary kernel * page tables. */ #ifdef VERBOSE_INIT_ARM printf("Creating L1 page table\n"); #endif /* * Now we start construction of the L1 page table. * We start by mapping the L2 page tables into the L1. * This means that we can replace L1 mappings later on if necessary. */ l1pagetable = kernel_l1pt.pv_pa; /* Map the L2 pages tables in the L1 page table */ pmap_link_l2pt(l1pagetable, 0x00000000, &kernel_pt_table[KERNEL_PT_SYS]); #define SAIPIO_BASE 0xd0000000 /* XXX XXX */ pmap_link_l2pt(l1pagetable, SAIPIO_BASE, &kernel_pt_table[KERNEL_PT_IO]); for (loop = 0; loop < KERNEL_PT_KERNEL_NUM; ++loop) pmap_link_l2pt(l1pagetable, KERNEL_BASE + loop * 0x00400000, &kernel_pt_table[KERNEL_PT_KERNEL + loop]); for (loop = 0; loop < KERNEL_PT_VMDATA_NUM; ++loop) pmap_link_l2pt(l1pagetable, KERNEL_VM_BASE + loop * 0x00400000, &kernel_pt_table[KERNEL_PT_VMDATA + loop]); /* update the top of the kernel VM */ pmap_curmaxkvaddr = KERNEL_VM_BASE + (KERNEL_PT_VMDATA_NUM * 0x00400000); #ifdef VERBOSE_INIT_ARM printf("Mapping kernel\n"); #endif /* Now we fill in the L2 pagetable for the kernel code/data */ /* * XXX there is no ELF header to find RO region. * XXX What should we do? */ #if 0 if (N_GETMAGIC(kernexec[0]) == ZMAGIC) { logical = pmap_map_chunk(l1pagetable, KERNEL_TEXT_BASE, physical_start, kernexec->a_text, VM_PROT_READ, PTE_CACHE); logical += pmap_map_chunk(l1pagetable, KERNEL_TEXT_BASE + logical, physical_start + logical, kerneldatasize - kernexec->a_text, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); } else #endif pmap_map_chunk(l1pagetable, KERNEL_TEXT_BASE, KERNEL_TEXT_BASE - KERNEL_BASE + physical_start, kerneldatasize, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); #ifdef VERBOSE_INIT_ARM printf("Constructing L2 page tables\n"); #endif /* Map the stack pages */ pmap_map_chunk(l1pagetable, irqstack.pv_va, irqstack.pv_pa, IRQ_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); pmap_map_chunk(l1pagetable, abtstack.pv_va, abtstack.pv_pa, ABT_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); pmap_map_chunk(l1pagetable, undstack.pv_va, undstack.pv_pa, UND_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); pmap_map_chunk(l1pagetable, kernelstack.pv_va, kernelstack.pv_pa, UPAGES * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); pmap_map_chunk(l1pagetable, kernel_l1pt.pv_va, kernel_l1pt.pv_pa, L1_TABLE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_PAGETABLE); /* Map page tables */ pmap_map_chunk(l1pagetable, KERNEL_BASE, physical_start, pt_size, VM_PROT_READ|VM_PROT_WRITE, PTE_PAGETABLE); /* Map a page for entering idle mode */ pmap_map_entry(l1pagetable, sa11x0_idle_mem, sa11x0_idle_mem, VM_PROT_READ|VM_PROT_WRITE, PTE_NOCACHE); /* Map the vector page. */ pmap_map_entry(l1pagetable, vector_page, systempage.pv_pa, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); /* Map the statically mapped devices. */ pmap_devmap_bootstrap(l1pagetable, sa11x0_devmap); pmap_map_chunk(l1pagetable, sa1_cache_clean_addr, 0xe0000000, CPU_SA110_CACHE_CLEAN_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); /* * Now we have the real page tables in place so we can switch to them. * Once this is done we will be running with the REAL kernel page * tables. */ #ifdef VERBOSE_INIT_ARM printf("done.\n"); #endif /* * Pages were allocated during the secondary bootstrap for the * stacks for different CPU modes. * We must now set the r13 registers in the different CPU modes to * point to these stacks. * Since the ARM stacks use STMFD etc. we must set r13 to the top end * of the stack memory. */ #ifdef VERBOSE_INIT_ARM printf("init subsystems: stacks "); #endif set_stackptr(PSR_IRQ32_MODE, irqstack.pv_va + IRQ_STACK_SIZE * PAGE_SIZE); set_stackptr(PSR_ABT32_MODE, abtstack.pv_va + ABT_STACK_SIZE * PAGE_SIZE); set_stackptr(PSR_UND32_MODE, undstack.pv_va + UND_STACK_SIZE * PAGE_SIZE); #ifdef PMAP_DEBUG if (pmap_debug_level >= 0) printf("kstack V%08lx P%08lx\n", kernelstack.pv_va, kernelstack.pv_pa); #endif /* PMAP_DEBUG */ /* * Well we should set a data abort handler. * Once things get going this will change as we will need a proper * handler. Until then we will use a handler that just panics but * tells us why. * Initialization of the vectors will just panic on a data abort. * This just fills in a slightly better one. */ #ifdef VERBOSE_INIT_ARM printf("vectors "); #endif data_abort_handler_address = (u_int)data_abort_handler; prefetch_abort_handler_address = (u_int)prefetch_abort_handler; undefined_handler_address = (u_int)undefinedinstruction_bounce; #ifdef DEBUG printf("%08x %08x %08x\n", data_abort_handler_address, prefetch_abort_handler_address, undefined_handler_address); #endif /* Initialize the undefined instruction handlers */ #ifdef VERBOSE_INIT_ARM printf("undefined\n"); #endif undefined_init(); /* Set the page table address. */ #ifdef VERBOSE_INIT_ARM printf("switching to new L1 page table @%#lx...\n", kernel_l1pt.pv_pa); #endif cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT); cpu_setttb(kernel_l1pt.pv_pa, true); cpu_tlb_flushID(); cpu_domains(DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)); /* * Moved from cpu_startup() as data_abort_handler() references * this during uvm init. */ uvm_lwp_setuarea(&lwp0, kernelstack.pv_va); #ifdef BOOT_DUMP dumppages((char *)0xc0000000, 16 * PAGE_SIZE); dumppages((char *)0xb0100000, 64); /* XXX */ #endif /* Enable MMU, I-cache, D-cache, write buffer. */ cpufunc_control(0x337f, 0x107d); arm32_vector_init(ARM_VECTORS_LOW, ARM_VEC_ALL); consinit(); #ifdef VERBOSE_INIT_ARM printf("bootstrap done.\n"); #endif #ifdef VERBOSE_INIT_ARM printf("freemempos=%08lx\n", freemempos); printf("MMU enabled. control=%08x\n", cpu_get_control()); #endif /* Load memory into UVM. */ uvm_setpagesize(); /* initialize PAGE_SIZE-dependent variables */ for (loop = 0; loop < bootconfig.dramblocks; loop++) { paddr_t dblk_start = (paddr_t)bootconfig.dram[loop].address; paddr_t dblk_end = dblk_start + (bootconfig.dram[loop].pages * PAGE_SIZE); if (dblk_start < physical_freestart) dblk_start = physical_freestart; if (dblk_end > physical_freeend) dblk_end = physical_freeend; uvm_page_physload(atop(dblk_start), atop(dblk_end), atop(dblk_start), atop(dblk_end), VM_FREELIST_DEFAULT); } /* Boot strap pmap telling it where the kernel page table is */ pmap_bootstrap(KERNEL_VM_BASE, KERNEL_VM_BASE + KERNEL_VM_SIZE); #ifdef BOOT_DUMP dumppages((char *)kernel_l1pt.pv_va, 16); #endif #ifdef DDB db_machine_init(); #endif #if NKSYMS || defined(DDB) || defined(MODULAR) ksyms_addsyms_elf(symbolsize, ((int *)&end), ((char *)&end) + symbolsize); #endif printf("kernsize=0x%x", kerneldatasize); printf(" (including 0x%x symbols)\n", symbolsize); #ifdef DDB if (boothowto & RB_KDB) Debugger(); #endif /* DDB */ /* We return the new stack pointer address */ return (kernelstack.pv_va + USPACE_SVC_STACK_TOP); }
void exec(char *path, void *loadaddr, int howto) { int io; #ifndef INSECURE struct stat sb; #endif struct exec x; u_int i; ssize_t sz; char *addr; #ifdef EXEC_DEBUG char *daddr, *etxt; #endif io = open(path, 0); if (io < 0) return; (void) fstat(io, &sb); if (sb.st_mode & 2) printf("non-secure file, check permissions!\n"); sz = read(io, (char *)&x, sizeof(x)); if (sz != sizeof(x) || N_BADMAG(x)) { close(io); errno = EFTYPE; return; } #ifdef EXEC_DEBUG printf("\nstruct exec {%x, %x, %x, %x, %x, %x, %x, %x}\n", x.a_midmag, x.a_text, x.a_data, x.a_bss, x.a_syms, x.a_entry, x.a_trsize, x.a_drsize); #endif /* Text */ printf("%u", x.a_text); addr = loadaddr; sz = x.a_text; if (N_GETMAGIC(x) == ZMAGIC) { bcopy((char *)&x, addr, sizeof x); addr += sizeof x; sz -= sizeof x; } if (read(io, (char *)addr, sz) != sz) goto shread; addr += sz; #ifdef EXEC_DEBUG printf("\ntext {%x, %x, %x, %x}\n", addr[0], addr[1], addr[2], addr[3]); etxt = addr; #endif if (N_GETMAGIC(x) == NMAGIC) while ((long)addr & (N_PAGSIZ(x) - 1)) *addr++ = 0; /* Data */ #ifdef EXEC_DEBUG daddr = addr; #endif printf("+%u", x.a_data); if (read(io, addr, x.a_data) != (ssize_t)x.a_data) goto shread; addr += x.a_data; /* Bss */ printf("+%u", x.a_bss); for (i = 0; i < x.a_bss; i++) *addr++ = 0; /* Symbols */ if (x.a_syms) { ssym = addr; bcopy(&x.a_syms, addr, sizeof(x.a_syms)); addr += sizeof(x.a_syms); printf("+[%u", x.a_syms); if (read(io, addr, x.a_syms) != (ssize_t)x.a_syms) goto shread; addr += x.a_syms; if (read(io, &i, sizeof(u_int)) != sizeof(u_int)) goto shread; bcopy(&i, addr, sizeof(u_int)); if (i) { sz = i - sizeof(int); addr += sizeof(int); if (read(io, addr, sz) != sz) goto shread; addr += sz; } /* and that many bytes of string table */ printf("+%d]", sz); esym = addr; } else { ssym = 0; esym = 0; } close(io); /* and note the end address of all this */ printf(" total=0x%lx", (u_long)addr); /* XXX - Hack alert! This is no good, loadaddr is passed into machdep_start(), and it should do whatever is needed. x.a_entry += (long)loadaddr; */ printf(" start=0x%x\n", x.a_entry); #ifdef EXEC_DEBUG printf("loadaddr=%p etxt=%p daddr=%p ssym=%p esym=%p\n", loadaddr, etxt, daddr, ssym, esym); printf("\n\nReturn to boot...\n"); getchar(); #endif machdep_start((char *)((register_t)x.a_entry), howto, loadaddr, ssym, esym); /* exec failed */ errno = ENOEXEC; return; shread: close(io); errno = EIO; return; }
static #endif void dump_file(const char *fname) { int fd; struct stat sb; caddr_t objbase; if (stat(fname, &sb) == -1) { warnx("cannot stat \"%s\"", fname); ++error_count; return; } if ((sb.st_mode & S_IFMT) != S_IFREG) { warnx("\"%s\" is not a regular file", fname); ++error_count; return; } if ((fd = open(fname, O_RDONLY, 0)) == -1) { warnx("cannot open \"%s\"", fname); ++error_count; return; } objbase = mmap(0, sb.st_size, PROT_READ, MAP_SHARED, fd, 0); if (objbase == (caddr_t) -1) { warnx("cannot mmap \"%s\"", fname); ++error_count; close(fd); return; } close(fd); file_base = (const char *) objbase; /* Makes address arithmetic easier */ if (IS_ELF(*(const Elf32_Ehdr*) align_struct(file_base))) { warnx("%s: this is an ELF program; use objdump to examine", fname); ++error_count; munmap(objbase, sb.st_size); return; } ex = (const struct exec *) align_struct(file_base); printf("%s: a_midmag = 0x%lx\n", fname, (long)ex->a_midmag); printf(" magic = 0x%lx = 0%lo, netmagic = 0x%lx = 0%lo\n", (long)N_GETMAGIC(*ex), (long)N_GETMAGIC(*ex), (long)N_GETMAGIC_NET(*ex), (long)N_GETMAGIC_NET(*ex)); if (N_BADMAG(*ex)) { warnx("%s: bad magic number", fname); ++error_count; munmap(objbase, sb.st_size); return; } printf(" a_text = 0x%lx\n", (long)ex->a_text); printf(" a_data = 0x%lx\n", (long)ex->a_data); printf(" a_bss = 0x%lx\n", (long)ex->a_bss); printf(" a_syms = 0x%lx\n", (long)ex->a_syms); printf(" a_entry = 0x%lx\n", (long)ex->a_entry); printf(" a_trsize = 0x%lx\n", (long)ex->a_trsize); printf(" a_drsize = 0x%lx\n", (long)ex->a_drsize); text_base = file_base + N_TXTOFF(*ex); data_base = file_base + N_DATOFF(*ex); rel_base = (const struct relocation_info *) align_struct(file_base + N_RELOFF(*ex)); sym_base = (const struct nlist *) align_struct(file_base + N_SYMOFF(*ex)); str_base = file_base + N_STROFF(*ex); rel_count = (ex->a_trsize + ex->a_drsize) / sizeof rel_base[0]; assert(rel_count * sizeof rel_base[0] == ex->a_trsize + ex->a_drsize); sym_count = ex->a_syms / sizeof sym_base[0]; assert(sym_count * sizeof sym_base[0] == ex->a_syms); if (sym_count != 0) { sym_used = (unsigned char *) calloc(sym_count, sizeof(unsigned char)); assert(sym_used != NULL); } printf(" Entry = 0x%lx\n", (long)ex->a_entry); printf(" Text offset = %x, address = %lx\n", N_TXTOFF(*ex), (long)N_TXTADDR(*ex)); printf(" Data offset = %lx, address = %lx\n", (long)N_DATOFF(*ex), (long)N_DATADDR(*ex)); /* * In an executable program file, everything is relocated relative to * the assumed run-time load address, i.e., N_TXTADDR(*ex), i.e., 0x1000. * * In a shared library file, everything is relocated relative to the * start of the file, i.e., N_TXTOFF(*ex), i.e., 0. * * The way to tell the difference is by looking at ex->a_entry. If it * is >= 0x1000, then we have an executable program. Otherwise, we * have a shared library. * * When a program is executed, the entire file is mapped into memory, * including the a.out header and so forth. But it is not mapped at * address 0; rather it is mapped at address 0x1000. The first page * of the user's address space is left unmapped in order to catch null * pointer dereferences. * * In this program, when we map in an executable program, we have to * simulate the empty page by decrementing our assumed base address by * a pagesize. */ text_addr = text_base; data_addr = data_base; origin = 0; if (ex->a_entry >= PAGE_SIZE) { /* Executable, not a shared library */ /* * The fields in the object have already been relocated on the * assumption that the object will be loaded at N_TXTADDR(*ex). * We have to compensate for that. */ text_addr -= PAGE_SIZE; data_addr -= PAGE_SIZE; origin = PAGE_SIZE; printf(" Program, origin = %lx\n", origin); } else if (N_GETFLAG(*ex) & EX_DYNAMIC) printf(" Shared library, origin = %lx\n", origin); else printf(" Object file, origin = %lx\n", origin); if (N_GETFLAG(*ex) & EX_DYNAMIC) { dyn = (const struct _dynamic *) align_struct(data_base); printf(" Dynamic version = %d\n", dyn->d_version); sdt = (const struct section_dispatch_table *) align_struct(text_addr + (unsigned long) dyn->d_un.d_sdt); rtrel_base = (const struct relocation_info *) align_struct(text_addr + sdt->sdt_rel); rtrel_count = (sdt->sdt_hash - sdt->sdt_rel) / sizeof rtrel_base[0]; assert(rtrel_count * sizeof rtrel_base[0] == (size_t)(sdt->sdt_hash - sdt->sdt_rel)); rtsym_base = (const struct nzlist *) align_struct(text_addr + sdt->sdt_nzlist); rtsym_count = (sdt->sdt_strings - sdt->sdt_nzlist) / sizeof rtsym_base[0]; assert(rtsym_count * sizeof rtsym_base[0] == (size_t)(sdt->sdt_strings - sdt->sdt_nzlist)); if (rtsym_count != 0) { rtsym_used = (unsigned char *) calloc(rtsym_count, sizeof(unsigned char)); assert(rtsym_used != NULL); } rtstr_base = text_addr + sdt->sdt_strings; } dump_segs(); dump_sods(); dump_rels("Relocations", rel_base, rel_count, sym_name, sym_used); dump_syms(); dump_rels("Run-time relocations", rtrel_base, rtrel_count, rtsym_name, rtsym_used); dump_rtsyms(); if (rtsym_used != NULL) { free(rtsym_used); rtsym_used = NULL; } if (sym_used != NULL) { free(sym_used); sym_used = NULL; } munmap(objbase, sb.st_size); }
int GetAOutFileInfo(struct dllist *dl) { #ifdef NOAOUT return(-1); #else struct exec ex, ex_swap; u_int32_t mid = -1; u_int32_t magic, clbytes, clofset; if (read(dl->ldfd, (char *)&ex, sizeof(ex)) != sizeof(ex)) return(-1); (void)lseek(dl->ldfd, (off_t) 0, SEEK_SET); if (read(dl->ldfd, (char *)&ex_swap, sizeof(ex_swap)) != sizeof(ex_swap)) return(-1); mopFileSwapX((u_char *)&ex_swap, 0, 4); mid = getMID(mid, N_GETMID (ex)); if (mid == (uint32_t)-1) { mid = getMID(mid, N_GETMID (ex_swap)); if (mid != (uint32_t)-1) { mopFileSwapX((u_char *)&ex, 0, 4); } } if (mid == (uint32_t)-1) { return(-1); } if (N_BADMAG (ex)) { return(-1); } switch (mid) { case MID_I386: #ifdef MID_NS32532 case MID_NS32532: #endif #ifdef MID_PMAX case MID_PMAX: #endif #ifdef MID_VAX case MID_VAX: #endif #ifdef MID_ALPHA case MID_ALPHA: #endif #ifdef MID_ARM6 case MID_ARM6: #endif ex.a_text = mopFileGetLX((u_char *)&ex_swap, 4, 4); ex.a_data = mopFileGetLX((u_char *)&ex_swap, 8, 4); ex.a_bss = mopFileGetLX((u_char *)&ex_swap, 12, 4); ex.a_syms = mopFileGetLX((u_char *)&ex_swap, 16, 4); ex.a_entry = mopFileGetLX((u_char *)&ex_swap, 20, 4); ex.a_trsize= mopFileGetLX((u_char *)&ex_swap, 24, 4); ex.a_drsize= mopFileGetLX((u_char *)&ex_swap, 28, 4); break; #ifdef MID_M68K case MID_M68K: #endif #ifdef MID_M68K4K case MID_M68K4K: #endif case MID_SPARC: #ifdef MID_MIPS case MID_MIPS: #endif ex.a_text = mopFileGetBX((u_char *)&ex_swap, 4, 4); ex.a_data = mopFileGetBX((u_char *)&ex_swap, 8, 4); ex.a_bss = mopFileGetBX((u_char *)&ex_swap, 12, 4); ex.a_syms = mopFileGetBX((u_char *)&ex_swap, 16, 4); ex.a_entry = mopFileGetBX((u_char *)&ex_swap, 20, 4); ex.a_trsize= mopFileGetBX((u_char *)&ex_swap, 24, 4); ex.a_drsize= mopFileGetBX((u_char *)&ex_swap, 28, 4); break; default: break; } printf("a.out image ("); switch (N_GETMID (ex)) { case MID_I386: printf("i386"); break; #ifdef MID_M68K case MID_M68K: printf("m68k"); break; #endif #ifdef MID_M68K4K case MID_M68K4K: printf("m68k 4k"); break; #endif #ifdef MID_NS32532 case MID_NS32532: printf("pc532"); break; #endif case MID_SPARC: printf("sparc"); break; #ifdef MID_PMAX case MID_PMAX: printf("pmax"); break; #endif #ifdef MID_VAX case MID_VAX: printf("vax"); break; #endif #ifdef MID_ALPHA case MID_ALPHA: printf("alpha"); break; #endif #ifdef MID_MIPS case MID_MIPS: printf("mips"); break; #endif #ifdef MID_ARM6 case MID_ARM6: printf("arm32"); break; #endif default: break; } printf(") Magic: "); switch (N_GETMAGIC (ex)) { case OMAGIC: printf("OMAGIC"); break; case NMAGIC: printf("NMAGIC"); break; case ZMAGIC: printf("ZMAGIC"); break; case QMAGIC: printf("QMAGIC"); break; default: printf("Unknown %ld", (long) N_GETMAGIC (ex)); } printf("\n"); printf("Size of text: %08lx\n", (long)ex.a_text); printf("Size of data: %08lx\n", (long)ex.a_data); printf("Size of bss: %08lx\n", (long)ex.a_bss); printf("Size of symbol tab: %08lx\n", (long)ex.a_syms); printf("Transfer Address: %08lx\n", (long)ex.a_entry); printf("Size of reloc text: %08lx\n", (long)ex.a_trsize); printf("Size of reloc data: %08lx\n", (long)ex.a_drsize); magic = N_GETMAGIC (ex); clbytes = getCLBYTES(mid); clofset = clbytes - 1; dl->image_type = IMAGE_TYPE_AOUT; dl->loadaddr = 0; dl->xferaddr = ex.a_entry; dl->a_text = ex.a_text; if (magic == ZMAGIC || magic == NMAGIC) { dl->a_text_fill = clbytes - (ex.a_text & clofset); if (dl->a_text_fill == clbytes) dl->a_text_fill = 0; } else dl->a_text_fill = 0; dl->a_data = ex.a_data; if (magic == ZMAGIC || magic == NMAGIC) { dl->a_data_fill = clbytes - (ex.a_data & clofset); if (dl->a_data_fill == clbytes) dl->a_data_fill = 0; } else dl->a_data_fill = 0; dl->a_bss = ex.a_bss; if (magic == ZMAGIC || magic == NMAGIC) { dl->a_bss_fill = clbytes - (ex.a_bss & clofset); if (dl->a_bss_fill == clbytes) dl->a_bss_fill = 0; } else { dl->a_bss_fill = clbytes - ((ex.a_text+ex.a_data+ex.a_bss) & clofset); if (dl->a_bss_fill == clbytes) dl->a_bss_fill = 0; } dl->a_mid = mid; return(0); #endif /* NOAOUT */ }
/*ARGSUSED*/ void exec_aout(char *file, const char *args, int bootdev, int bootunit, int bootpart) { char *loadaddr; int io; struct exec x; int cc, magic; void (*entry)(); char *cp; int *ip; io = open(file, 0); if (io < 0) return; /* * Read in the exec header, and validate it. */ if (read(io, (char *)&x, sizeof(x)) != sizeof(x)) goto shread; if (N_BADMAG(x)) { errno = EFTYPE; goto closeout; } /* * note: on the mvme ports, the kernel is linked in such a way that * its entry point is the first item in .text, and thus a_entry can * be used to determine both the load address and the entry point. * (also note that we make use of the fact that the kernel will live * in a VA == PA range of memory ... otherwise we would take * loadaddr as a parameter and let the kernel relocate itself!) * * note that ZMAGIC files included the a.out header in the text area * so we must mask that off (has no effect on the other formats) */ loadaddr = (void *)(x.a_entry & ~sizeof(x)); cp = loadaddr; magic = N_GETMAGIC(x); if (magic == ZMAGIC) cp += sizeof(x); entry = (void (*)())cp; /* * Read in the text segment. */ printf("%d", x.a_text); cc = x.a_text; if (magic == ZMAGIC) cc = cc - sizeof(x); /* a.out header part of text in zmagic */ if (read(io, cp, cc) != cc) goto shread; cp += cc; /* * NMAGIC may have a gap between text and data. */ if (magic == NMAGIC) { register int mask = N_PAGSIZ(x) - 1; while ((int)cp & mask) *cp++ = 0; } /* * Read in the data segment. */ printf("+%d", x.a_data); if (read(io, cp, x.a_data) != x.a_data) goto shread; cp += x.a_data; /* * Zero out the BSS section. */ printf("+%d", x.a_bss); cc = x.a_bss; while ((int)cp & 3) { *cp++ = 0; --cc; } ip = (int *)cp; cp += cc; while ((char *)ip < cp) *ip++ = 0; /* * Read in the symbol table and strings. * (Always set the symtab size word.) */ *ip++ = x.a_syms; cp = (char *) ip; if (x.a_syms > 0) { /* Symbol table and string table length word. */ cc = x.a_syms; printf("+[%d", cc); cc += sizeof(int); /* strtab length too */ if (read(io, cp, cc) != cc) goto shread; cp += x.a_syms; ip = (int *)cp; /* points to strtab length */ cp += sizeof(int); /* String table. Length word includes itself. */ cc = *ip; printf("+%d]", cc); cc -= sizeof(int); if (cc <= 0) goto shread; if (read(io, cp, cc) != cc) goto shread; cp += cc; } printf("=0x%lx\n", cp - loadaddr); close(io); (*entry)(args, bootdev, bootunit, bootpart, SYM_MAGIC, cp); printf("exec: kernel returned!\n"); return; shread: printf("exec: short read\n"); errno = EIO; closeout: close(io); return; }
static int aout_exec(int fd, struct exec *x, u_long *marks, int flags) { u_long entry = x->a_entry; paddr_t aoutp = 0; paddr_t minp, maxp; int cc; paddr_t offset = marks[MARK_START]; u_long magic = N_GETMAGIC(*x); int sub; /* In OMAGIC and NMAGIC, exec header isn't part of text segment */ if (magic == OMAGIC || magic == NMAGIC) sub = 0; else sub = sizeof(*x); minp = maxp = ALIGNENTRY(entry); if (lseek(fd, sizeof(*x), SEEK_SET) == -1) { WARN(("lseek text")); return 1; } /* * Leave a copy of the exec header before the text. * The kernel may use this to verify that the * symbols were loaded by this boot program. */ if (magic == OMAGIC || magic == NMAGIC) { if (flags & LOAD_HDR && maxp >= sizeof(*x)) BCOPY(x, maxp - sizeof(*x), sizeof(*x)); } else { if (flags & LOAD_HDR) BCOPY(x, maxp, sizeof(*x)); if (flags & (LOAD_HDR|COUNT_HDR)) maxp += sizeof(*x); } /* * Read in the text segment. */ if (flags & LOAD_TEXT) { PROGRESS(("%ld", x->a_text)); if (READ(fd, maxp, x->a_text - sub) != x->a_text - sub) { WARN(("read text")); return 1; } } else { if (lseek(fd, x->a_text - sub, SEEK_CUR) == -1) { WARN(("seek text")); return 1; } } if (flags & (LOAD_TEXT|COUNT_TEXT)) maxp += x->a_text - sub; /* * Provide alignment if required */ if (magic == ZMAGIC || magic == NMAGIC) { int size = -(unsigned int)maxp & (__LDPGSZ - 1); if (flags & LOAD_TEXTA) { PROGRESS(("/%d", size)); BZERO(maxp, size); } if (flags & (LOAD_TEXTA|COUNT_TEXTA)) maxp += size; } /* * Read in the data segment. */ if (flags & LOAD_DATA) { PROGRESS(("+%ld", x->a_data)); if (READ(fd, maxp, x->a_data) != x->a_data) { WARN(("read data")); return 1; } } else { if (lseek(fd, x->a_data, SEEK_CUR) == -1) { WARN(("seek data")); return 1; } } if (flags & (LOAD_DATA|COUNT_DATA)) maxp += x->a_data; /* * Zero out the BSS section. * (Kernel doesn't care, but do it anyway.) */ if (flags & LOAD_BSS) { PROGRESS(("+%ld", x->a_bss)); BZERO(maxp, x->a_bss); } if (flags & (LOAD_BSS|COUNT_BSS)) maxp += x->a_bss; /* * Read in the symbol table and strings. * (Always set the symtab size word.) */ if (flags & LOAD_SYM) BCOPY(&x->a_syms, maxp, sizeof(x->a_syms)); if (flags & (LOAD_SYM|COUNT_SYM)) { maxp += sizeof(x->a_syms); aoutp = maxp; } if (x->a_syms > 0) { /* Symbol table and string table length word. */ if (flags & LOAD_SYM) { PROGRESS(("+[%ld", x->a_syms)); if (READ(fd, maxp, x->a_syms) != x->a_syms) { WARN(("read symbols")); return 1; } } else { if (lseek(fd, x->a_syms, SEEK_CUR) == -1) { WARN(("seek symbols")); return 1; } } if (flags & (LOAD_SYM|COUNT_SYM)) maxp += x->a_syms; if (read(fd, &cc, sizeof(cc)) != sizeof(cc)) { WARN(("read string table")); return 1; } if (flags & LOAD_SYM) { BCOPY(&cc, maxp, sizeof(cc)); /* String table. Length word includes itself. */ PROGRESS(("+%d]", cc)); } if (flags & (LOAD_SYM|COUNT_SYM)) maxp += sizeof(cc); cc -= sizeof(int); if (cc <= 0) { WARN(("symbol table too short")); return 1; } if (flags & LOAD_SYM) { if (READ(fd, maxp, cc) != cc) { WARN(("read strings")); return 1; } } else { if (lseek(fd, cc, SEEK_CUR) == -1) { WARN(("seek strings")); return 1; } } if (flags & (LOAD_SYM|COUNT_SYM)) maxp += cc; } marks[MARK_START] = LOADADDR(minp); marks[MARK_ENTRY] = LOADADDR(entry); marks[MARK_NSYM] = x->a_syms; marks[MARK_SYM] = LOADADDR(aoutp); marks[MARK_END] = LOADADDR(maxp); return 0; }
/* * Load an a.out image. * Exit codes: * -1 : Not an a.outfile * 0 : OK * error# : Error during load (*errp might contain error string). */ int aout_load(int fd, osdsc_t *od, char **errp, int loadsyms) { long textsz, stringsz; struct exec ehdr; int err; *errp = NULL; lseek(fd, (off_t)0, SEEK_SET); if (read(fd, (char *)&ehdr, sizeof(ehdr)) != sizeof(ehdr)) return -1; #ifdef TOSTOOLS if ((ehdr.a_magic & 0xffff) != NMAGIC) return -1; #else if ((N_GETMAGIC(ehdr) != NMAGIC) && (N_GETMAGIC(ehdr) != OMAGIC)) return -1; #endif /* * Extract various sizes from the kernel executable */ textsz = (ehdr.a_text + AOUT_LDPGSZ - 1) & ~(AOUT_LDPGSZ - 1); od->k_esym = 0; od->ksize = textsz + ehdr.a_data + ehdr.a_bss; od->kentry = ehdr.a_entry; if (loadsyms && ehdr.a_syms) { err = 1; if (lseek(fd, ehdr.a_text+ehdr.a_data+ehdr.a_syms+sizeof(ehdr), 0) <= 0) goto error; err = 2; if (read(fd, (char *)&stringsz, sizeof(long)) != sizeof(long)) goto error; err = 3; if (lseek(fd, sizeof(ehdr), 0) <= 0) goto error; od->ksize += ehdr.a_syms + sizeof(long) + stringsz; } err = 4; if ((od->kstart = (u_char *)MALLOC(od->ksize)) == NULL) goto error; /* * Read text & data, clear bss */ err = 5; if ((read(fd, (char *)(od->kstart), ehdr.a_text) != ehdr.a_text) ||(read(fd,(char *)(od->kstart+textsz),ehdr.a_data) != ehdr.a_data)) goto error; bzero(od->kstart + textsz + ehdr.a_data, ehdr.a_bss); /* * Read symbol and string table */ if (loadsyms && ehdr.a_syms) { long *p; p = (long *)((od->kstart) + textsz + ehdr.a_data + ehdr.a_bss); *p++ = ehdr.a_syms; err = 6; if (read(fd, (char *)p, ehdr.a_syms) != ehdr.a_syms) goto error; p = (long *)((char *)p + ehdr.a_syms); err = 7; if (read(fd, (char *)p, stringsz) != stringsz) goto error; od->k_esym = (long)((char *)p-(char *)od->kstart +stringsz); } return 0; error: #ifdef TOSTOOLS { static char *errs[] = { /* 1 */ "Cannot seek to string table", /* 2 */ "Cannot read string-table size", /* 3 */ "Cannot seek back to text start", /* 4 */ "Cannot malloc kernel image space", /* 5 */ "Unable to read kernel image", /* 6 */ "Cannot read symbol table", /* 7 */ "Cannot read string table" }; *errp = errs[err]; } #endif /* TOSTOOLS */ return err; }
int putfile(char *from_file, int to) { struct exec ex; char buf[2048]; int n, total; int from, check_sum = 0; struct hppa_lifload load; Elf32_External_Ehdr elf_header; Elf32_External_Phdr *elf_segments; int i, header_count, memory_needed, elf_load_image_segment; if ((from = open(from_file, O_RDONLY)) < 0) err(1, "%s", from_file); n = read(from, &ex, sizeof(ex)); if (n != sizeof(ex)) err(1, "%s: reading file header", from_file); entry = ex.a_entry; if (N_GETMAGIC(ex) == OMAGIC || N_GETMAGIC(ex) == NMAGIC) entry += sizeof(ex); else if (IS_ELF(*(Elf32_External_Ehdr *)&ex)) { if (lseek(from, 0, SEEK_SET) < 0) err(1, "lseek"); n = read(from, &elf_header, sizeof (elf_header)); if (n != sizeof (elf_header)) err(1, "%s: reading ELF header", from_file); header_count = ELFGET16(elf_header.e_phnum); memory_needed = header_count * sizeof (Elf32_External_Phdr); elf_segments = malloc(memory_needed); if (elf_segments == NULL) err(1, "malloc"); if (lseek(from, ELFGET32(elf_header.e_phoff), SEEK_SET) < 0) err(1, "lseek"); n = read(from, elf_segments, memory_needed); if (n != memory_needed) err(1, "%s: reading ELF segments", from_file); elf_load_image_segment = -1; for (i = 0; i < header_count; i++) { if (ELFGET32(elf_segments[i].p_filesz) && ELFGET32(elf_segments[i].p_flags) & PF_X) { if (elf_load_image_segment != -1) errx(1, "%s: more than one ELF program " "segment", from_file); elf_load_image_segment = i; } } if (elf_load_image_segment == -1) errx(1, "%s: no suitable ELF program segment", from_file); entry = ELFGET32(elf_header.e_entry) + ELFGET32(elf_segments[elf_load_image_segment].p_offset) - ELFGET32(elf_segments[elf_load_image_segment].p_vaddr); } else if (*(uint8_t *)&ex == 0x1f && ((uint8_t *)&ex)[1] == 0x8b) { entry = 0; } else errx(1, "%s: bad magic number", from_file); entry += sizeof(load); lseek(to, sizeof(load), SEEK_CUR); total = 0; n = sizeof(buf) - sizeof(load); /* copy the whole file */ for (lseek(from, 0, SEEK_SET); ; n = sizeof(buf)) { memset(buf, 0, sizeof(buf)); if ((n = read(from, buf, n)) < 0) err(1, "%s", from_file); else if (n == 0) break; if (write(to, buf, n) != n) err(1, "%s", to_file); total += n; check_sum = cksum(check_sum, (int *)buf, n); } /* load header */ load.address = htobe32(loadpoint + sizeof(load)); load.count = htobe32(4 + total); check_sum = cksum(check_sum, (int *)&load, sizeof(load)); if (verbose) warnx("wrote %d bytes of file \'%s\'", total, from_file); total += sizeof(load); /* insert the header */ lseek(to, -total, SEEK_CUR); if (write(to, &load, sizeof(load)) != sizeof(load)) err(1, "%s", to_file); lseek(to, total - sizeof(load), SEEK_CUR); memset(buf, 0, sizeof(buf)); /* pad to int */ n = sizeof(int) - total % sizeof(int); if (total % sizeof(int)) { if (write(to, buf, n) != n) err(1, "%s", to_file); else total += n; } /* pad to the blocksize */ n = sizeof(buf) - total % sizeof(buf); if (n < sizeof(int)) { n += sizeof(buf); total += sizeof(buf); } else total += n; /* TODO should pad here to the 65k boundary for tape boot */ if (verbose) warnx("checksum is 0x%08x", -check_sum); check_sum = htobe32(-check_sum); if (write(to, &check_sum, sizeof(int)) != sizeof(int)) err(1, "%s", to_file); n -= sizeof(int); if (write(to, buf, n) != n) err(1, "%s", to_file); if (close(from) < 0) err(1, "%s", from_file); return total; }
int main(int argc, char *argv[]) { struct exec head; struct ecoff_exechdr ehead; struct ecoff_scnhdr escn[3]; int infd, outfd; int n; if (argc != 3) usage(); infd = open(argv[1], O_RDONLY); if (infd < 0) err(1, argv[1]); outfd = open(argv[2], O_WRONLY | O_TRUNC | O_CREAT, 0644); if (outfd < 0) err(1, argv[2]); n = read(infd, &head, sizeof(head)); if (n < sizeof(head)) err(1, "read"); if (N_BADMAG(head)) { printf("%s: bad magic number\n", argv[1]); exit(1); } if (head.a_trsize || head.a_drsize) { printf("%s: has relocations\n", argv[1]); exit(1); } /* * Header */ ehead.f.f_magic = 0x016d; /* MC88OMAGIC */ ehead.f.f_nscns = 3; ehead.f.f_timdat = 0; /* ignored */ ehead.f.f_symptr = 0; /* ignored */ ehead.f.f_nsyms = 0; /* ignored */ ehead.f.f_opthdr = sizeof ehead.a; ehead.f.f_flags = 0x020f; /* F_RELFLG | F_EXEC | F_LNNO | 8 | F_AR16WR */ ehead.a.magic = N_GETMAGIC(head); ehead.a.vstamp = 0; /* ignored */ ehead.a.tsize = head.a_text; /* ignored */ ehead.a.dsize = head.a_data; /* ignored */ ehead.a.bsize = head.a_bss; /* ignored */ ehead.a.entry = head.a_entry; ehead.a.text_start = N_TXTADDR(head); /* ignored */ ehead.a.data_start = N_DATADDR(head); /* ignored */ n = write(outfd, &ehead, sizeof(ehead)); if (n != sizeof(ehead)) err(1, "write"); /* * Sections. * Note that we merge .bss into .data since the PROM will not * clear it and locore does not do this either. */ strncpy(escn[0].s_name, ".text", sizeof escn[0].s_name); escn[0].s_paddr = N_TXTADDR(head); /* ignored, 1:1 mapping */ escn[0].s_size = round(head.a_text, 8); escn[0].s_scnptr = round(sizeof(ehead) + sizeof(escn), 0x10); escn[0].s_relptr = 0; escn[0].s_lnnoptr = 0; escn[0].s_nlnno = 0; escn[0].s_flags = 0x20; /* STYP_TEXT */ strncpy(escn[1].s_name, ".data", sizeof escn[1].s_name); escn[1].s_paddr = N_DATADDR(head); /* ignored, 1:1 mapping */ escn[1].s_scnptr = escn[0].s_scnptr + escn[0].s_size; escn[1].s_size = round(head.a_data + head.a_bss, 8); escn[1].s_relptr = 0; escn[1].s_lnnoptr = 0; escn[1].s_nlnno = 0; escn[1].s_flags = 0x40; /* STYP_DATA */ strncpy(escn[2].s_name, ".bss", sizeof escn[2].s_name); escn[2].s_paddr = N_BSSADDR(head) + head.a_bss; /* ignored, 1:1 mapping */ escn[2].s_scnptr = 0; /* nothing in the file */ escn[2].s_size = 0; escn[2].s_relptr = 0; escn[2].s_lnnoptr = 0; escn[2].s_nlnno = 0; escn[2].s_flags = 0x80; /* STYP_BSS */ /* adjust load addresses */ escn[0].s_paddr += (head.a_entry & ~(__LDPGSZ - 1)) - __LDPGSZ; escn[1].s_paddr += (head.a_entry & ~(__LDPGSZ - 1)) - __LDPGSZ; escn[2].s_paddr += (head.a_entry & ~(__LDPGSZ - 1)) - __LDPGSZ; escn[0].s_vaddr = escn[0].s_paddr; escn[1].s_vaddr = escn[1].s_paddr; escn[2].s_vaddr = escn[2].s_paddr; n = write(outfd, &escn, sizeof(escn)); if (n != sizeof(escn)) err(1, "write"); /* * Copy text section */ #ifdef DEBUG printf("copying %s: source %lx dest %lx size %x\n", escn[0].s_name, N_TXTOFF(head), escn[0].s_scnptr, head.a_text); #endif lseek(outfd, escn[0].s_scnptr, SEEK_SET); lseek(infd, N_TXTOFF(head), SEEK_SET); copybits(infd, outfd, head.a_text); /* * Copy data section */ #ifdef DEBUG printf("copying %s: source %lx dest %lx size %x\n", escn[1].s_name, N_DATOFF(head), escn[1].s_scnptr, head.a_data); #endif lseek(outfd, escn[1].s_scnptr, SEEK_SET); lseek(infd, N_DATOFF(head), SEEK_SET); copybits(infd, outfd, head.a_data); /* * ``Copy'' bss section */ #ifdef DEBUG printf("copying %s: size %lx\n", escn[2].s_name, round(head.a_data + head.a_bss, 8) - head.a_data); #endif zerobits(outfd, round(head.a_data + head.a_bss, 8) - head.a_data); close(infd); close(outfd); exit(0); }