static long load_text_data(int fd, struct exec *hdrp, int bss, long disp) { int size; unsigned char* addr; lseek(fd, disp + N_TXTOFF(*hdrp), 0); size = hdrp->a_text + hdrp->a_data; if (bss == -1) size += hdrp->a_bss; else if (bss > 1) size += bss; addr = (unsigned char*)xmalloc(size); if (addr == NULL) { dln_errno = errno; return 0; } if (read(fd, addr, size) != size) { dln_errno = errno; free(addr); return 0; } if (bss == -1) { memset(addr + hdrp->a_text + hdrp->a_data, 0, hdrp->a_bss); } else if (bss > 0) { memset(addr + hdrp->a_text + hdrp->a_data, 0, bss); } return (long)addr; }
BOOL CoffLoader::load() { size_t filesz; size_t memsz; vaddr_t kv; off_t fileofs; /* start tag chain */ _load_segment_start(); /* text */ filesz = memsz = _ah->a_tsize; kv = _ah->a_tstart; fileofs = COFF_ROUND(N_TXTOFF(_fh, _ah), 16); DPRINTF((TEXT("[text]"))); _load_segment(kv, memsz, fileofs, filesz); /* data */ fileofs += filesz; filesz = memsz = _ah->a_dsize; kv = _ah->a_dstart; DPRINTF((TEXT("[data]"))); _load_segment(kv, memsz, fileofs, filesz); /* bss */ filesz = 0; memsz = _ah->a_bsize; kv = _ah->a_dstart + _ah->a_dsize; fileofs = 0; DPRINTF((TEXT("[bss ]"))); _load_segment(kv, memsz, fileofs, filesz); /* tag chain still opening */ return _load_success(); }
static bfd_boolean aout_adobe_set_section_contents (bfd *abfd, asection *section, const void * location, file_ptr offset, bfd_size_type count) { file_ptr section_start; sec_ptr sect; /* Set by bfd.c handler. */ if (! abfd->output_has_begun) { /* Assign file offsets to sections. Text sections are first, and are contiguous. Then data sections. Everything else at the end. */ section_start = N_TXTOFF (0); for (sect = abfd->sections; sect; sect = sect->next) { if (sect->flags & SEC_CODE) { sect->filepos = section_start; /* FIXME: Round to alignment. */ section_start += sect->size; } } for (sect = abfd->sections; sect; sect = sect->next) { if (sect->flags & SEC_DATA) { sect->filepos = section_start; /* FIXME: Round to alignment. */ section_start += sect->size; } } for (sect = abfd->sections; sect; sect = sect->next) { if (sect->flags & SEC_HAS_CONTENTS && !(sect->flags & (SEC_CODE | SEC_DATA))) { sect->filepos = section_start; /* FIXME: Round to alignment. */ section_start += sect->size; } } } /* Regardless, once we know what we're doing, we might as well get going. */ if (bfd_seek (abfd, section->filepos + offset, SEEK_SET) != 0) return FALSE; if (count == 0) return TRUE; return bfd_bwrite (location, count, abfd) == count; }
int load_aout(const char *filename, uint8_t *addr) { int fd, size, ret; struct exec e; uint32_t magic; fd = open(filename, O_RDONLY | O_BINARY); if (fd < 0) return -1; size = read(fd, &e, sizeof(e)); if (size < 0) goto fail; bswap_ahdr(&e); magic = N_MAGIC(e); switch (magic) { case ZMAGIC: case QMAGIC: case OMAGIC: lseek(fd, N_TXTOFF(e), SEEK_SET); size = read(fd, addr, e.a_text + e.a_data); if (size < 0) goto fail; break; case NMAGIC: lseek(fd, N_TXTOFF(e), SEEK_SET); size = read(fd, addr, e.a_text); if (size < 0) goto fail; ret = read(fd, addr + N_DATADDR(e), e.a_data); if (ret < 0) goto fail; size += ret; break; default: goto fail; } close(fd); return size; fail: close(fd); return -1; }
/* Set parameters about this a.out file that are machine-dependent. This routine is called from some_aout_object_p just before it returns. */ static const bfd_target * MY (callback) (bfd *abfd) { struct internal_exec *execp = exec_hdr (abfd); /* Calculate the file positions of the parts of a newly read aout header */ obj_textsec (abfd)->size = N_TXTSIZE (*execp); /* The virtual memory addresses of the sections */ obj_textsec (abfd)->vma = N_TXTADDR (*execp); obj_datasec (abfd)->vma = N_DATADDR (*execp); obj_bsssec (abfd)->vma = N_BSSADDR (*execp); obj_textsec (abfd)->lma = obj_textsec (abfd)->vma; obj_datasec (abfd)->lma = obj_datasec (abfd)->vma; obj_bsssec (abfd)->lma = obj_bsssec (abfd)->vma; /* The file offsets of the sections */ obj_textsec (abfd)->filepos = N_TXTOFF (*execp); obj_datasec (abfd)->filepos = N_DATOFF (*execp); /* The file offsets of the relocation info */ obj_textsec (abfd)->rel_filepos = N_TRELOFF (*execp); obj_datasec (abfd)->rel_filepos = N_DRELOFF (*execp); /* The file offsets of the string table and symbol table. */ obj_sym_filepos (abfd) = N_SYMOFF (*execp); obj_str_filepos (abfd) = N_STROFF (*execp); /* Determine the architecture and machine type of the object file. */ #ifdef SET_ARCH_MACH SET_ARCH_MACH (abfd, *execp); #else bfd_default_set_arch_mach (abfd, DEFAULT_ARCH, 0); #endif if (obj_aout_subformat (abfd) == gnu_encap_format) { /* The file offsets of the relocation info */ obj_textsec (abfd)->rel_filepos = N_GNU_TRELOFF (*execp); obj_datasec (abfd)->rel_filepos = N_GNU_DRELOFF (*execp); /* The file offsets of the string table and symbol table. */ obj_sym_filepos (abfd) = N_GNU_SYMOFF (*execp); obj_str_filepos (abfd) = (obj_sym_filepos (abfd) + execp->a_syms); abfd->flags |= HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS; bfd_get_symcount (abfd) = execp->a_syms / 12; obj_symbol_entry_size (abfd) = 12; obj_reloc_entry_size (abfd) = RELOC_STD_SIZE; } return abfd->xvec; }
/* deref a pointer to kernel text */ u_int kv_dref_t(struct kernel *kp, u_int adr){ u_int tadr; if(!kp->incore){ struct exec *ep; ep=(struct exec *)kp->core; tadr=*(u_int*)((adr - ep->a_entry) + N_TXTOFF(*ep) + (u_int)kp->core); } else { lseek(kp->fd, adr, SEEK_SET); read(kp->fd, &tadr, sizeof(tadr)); } return(tadr); }
static unsigned long load_aout_interp(struct exec * interp_ex, int interpreter_fd) { unsigned long text_data, offset, elf_entry = ~0UL; char * addr; int retval; printf("WARNING: load_aout_interp() has not been tested at all!\n"); current->end_code = interp_ex->a_text; text_data = interp_ex->a_text + interp_ex->a_data; current->end_data = text_data; current->brk = interp_ex->a_bss + text_data; switch (N_MAGIC(*interp_ex)) { case OMAGIC: offset = 32; addr = (char *) 0; break; case ZMAGIC: case QMAGIC: offset = N_TXTOFF(*interp_ex); addr = (char *) N_TXTADDR(*interp_ex); break; default: goto out; } if ((unsigned long)addr + text_data < text_data) goto out; do_mmap(-1, 0, text_data, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, 0); retval = read_exec(interpreter_fd, offset, addr, text_data, 0); if (retval < 0) goto out; #if 0 flush_icache_range((unsigned long)addr, (unsigned long)addr + text_data); #endif do_mmap(-1, ELF_PAGESTART(text_data + ELF_EXEC_PAGESIZE - 1), interp_ex->a_bss, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, 0); elf_entry = interp_ex->a_entry; out: return elf_entry; }
//-------------------------------------------------------------------------- int get_aout_file_format_index(linput_t *li) { exec ex; register int i = 0; if(qlread(li, &ex, sizeof(ex)) != sizeof(ex)) return false; if(N_BADMAG(ex)) { ex.a_info = swap32(ex.a_info); switch(N_MACHTYPE(ex)) { case M_386_NETBSD: case M_68K_NETBSD: case M_68K4K_NETBSD: case M_532_NETBSD: case M_SPARC_NETBSD: case M_PMAX_NETBSD: case M_VAX_NETBSD: case M_ALPHA_NETBSD: case M_ARM6_NETBSD: break; default: return false; } } switch(N_MAGIC(ex)) { case NMAGIC: ++i; case CMAGIC: ++i; case ZMAGIC: ++i; case OMAGIC: ++i; case QMAGIC: // msg("text=%d data=%d symsize=%d txtoff=%d sum=%d\n", ex.a_text, ex.a_data, // N_SYMSIZE(ex), N_TXTOFF(ex), ex.a_text + ex.a_data + N_SYMSIZE(ex) + N_TXTOFF(ex)); if ( qlsize(li) >= ex.a_text + ex.a_data + N_SYMSIZE(ex) + N_TXTOFF(ex) ) break; if ( N_MAGIC(ex) == ZMAGIC && qlsize(li) >= ex.a_text + ex.a_data + N_SYMSIZE(ex) ) { i = 5; // OpenBSD demand-paged break; } default: return false; } return i+1; }
// Обработчик #PF для A.OUT-процессов // Аргумент - адрес, по которому программа попыталась обратиться // Результат - адрес загруженной страницы + флаги, или 0, если процесс "ошибся адресом" ulong aout_pf(uint address) { TaskStruct *task = Task[Current]; // Наибольшая страница, которая будет загружаться из файла // (я все время предполагаю, что размеры секций кратны странице) uint filepages = task->header.a_text + task->header.a_data; // Объем АП процесса uint maxpage = filepages + PAGE_ADDR(task->header.a_bss + 0xfff) + USER_STACK_PAGES * PAGE_SIZE; bool ok = 0; // Преобразуем адрес в адрес страницы ulong pageaddr = PAGE_ADDR(address); ulong *tmppage = 0; // Если это страница должна грузиться из файла if (address < filepages) { // Выделяем страницу... tmppage = (ulong*)alloc_first_page(); // ... и загружаем ее. Пользуемся тем, что LoadPart остановится // на конце файла. LoadPart(&task->file, tmppage, pageaddr+N_TXTOFF(task->header), PAGE_SIZE); ok = 1; } // Если это страница bss или стека if (address >= filepages && address < maxpage) { // Выделяем страницу... tmppage = (ulong*)alloc_first_page(); // ... и обнуляем ее memset(tmppage, 0, PAGE_SIZE); ok = 1; } if (ok) return (ulong)tmppage + PAGE_ATTR; else return 0; }
static unsigned long load_aout_interp(struct exec * interp_ex, struct file * interpreter) { unsigned long text_data, elf_entry = ~0UL; char * addr; loff_t offset; current->mm->end_code = interp_ex->a_text; text_data = interp_ex->a_text + interp_ex->a_data; current->mm->end_data = text_data; current->mm->brk = interp_ex->a_bss + text_data; switch (N_MAGIC(*interp_ex)) { case OMAGIC: offset = 32; addr = (char *) 0; break; case ZMAGIC: case QMAGIC: offset = N_TXTOFF(*interp_ex); addr = (char *) N_TXTADDR(*interp_ex); break; default: goto out; } down_write(¤t->mm->mmap_sem); do_brk(0, text_data); up_write(¤t->mm->mmap_sem); if (!interpreter->f_op || !interpreter->f_op->read) goto out; if (interpreter->f_op->read(interpreter, addr, text_data, &offset) < 0) goto out; flush_icache_range((unsigned long)addr, (unsigned long)addr + text_data); down_write(¤t->mm->mmap_sem); do_brk(ELF_PAGESTART(text_data + ELF_MIN_ALIGN - 1), interp_ex->a_bss); up_write(¤t->mm->mmap_sem); elf_entry = interp_ex->a_entry; out: return elf_entry; }
/* * read in the text space of an a.out file */ static void gettextspace(FILE *nfile) { textspace = (u_char *) malloc( xbuf.a_text ); if ( textspace == 0 ) { warnx("no room for %lu bytes of text space: can't do -c" , xbuf.a_text ); return; } (void) fseek( nfile , N_TXTOFF( xbuf ) , 0 ); if ( fread( textspace , 1 , xbuf.a_text , nfile ) != xbuf.a_text ) { warnx("couldn't read text space: can't do -c"); free( textspace ); textspace = 0; return; } }
/* * "Load" an a.out-format executable. */ static int ld_aout(const struct iodesc * idi, const struct iodesc * ido, struct kgz_hdr * kh, const struct exec * a) { size_t load, addr; load = addr = N_TXTADDR(*a); xcopy(idi, ido, le32toh(a->a_text), N_TXTOFF(*a)); addr += le32toh(a->a_text); if (N_DATADDR(*a) != addr) return -1; xcopy(idi, ido, le32toh(a->a_data), N_DATOFF(*a)); addr += le32toh(a->a_data); kh->dload = load; kh->dsize = addr - load; kh->isize = kh->dsize + le32toh(a->a_bss); kh->entry = le32toh(a->a_entry); return 0; }
static unsigned long load_aout_interp(struct exec * interp_ex, struct dentry * interpreter_dentry) { unsigned long text_data, offset, elf_entry = ~0UL; char * addr; int retval; current->mm->end_code = interp_ex->a_text; text_data = interp_ex->a_text + interp_ex->a_data; current->mm->end_data = text_data; current->mm->brk = interp_ex->a_bss + text_data; switch (N_MAGIC(*interp_ex)) { case OMAGIC: offset = 32; addr = (char *) 0; break; case ZMAGIC: case QMAGIC: offset = N_TXTOFF(*interp_ex); addr = (char *) N_TXTADDR(*interp_ex); break; default: goto out; } do_mmap(NULL, 0, text_data, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_FIXED|MAP_PRIVATE, 0); retval = read_exec(interpreter_dentry, offset, addr, text_data, 0); if (retval < 0) goto out; flush_icache_range((unsigned long)addr, (unsigned long)addr + text_data); do_mmap(NULL, ELF_PAGESTART(text_data + ELF_EXEC_PAGESIZE - 1), interp_ex->a_bss, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_FIXED|MAP_PRIVATE, 0); elf_entry = interp_ex->a_entry; out: return elf_entry; }
static void dump_segs(void) { printf(" Text segment starts at address %lx\n", origin + N_TXTOFF(*ex)); if (N_GETFLAG(*ex) & EX_DYNAMIC) { printf(" rel starts at %lx\n", sdt->sdt_rel); printf(" hash starts at %lx\n", sdt->sdt_hash); printf(" nzlist starts at %lx\n", sdt->sdt_nzlist); printf(" strings starts at %lx\n", sdt->sdt_strings); } printf(" Data segment starts at address %lx\n", origin + N_DATOFF(*ex)); if (N_GETFLAG(*ex) & EX_DYNAMIC) { printf(" _dynamic starts at %lx\n", origin + N_DATOFF(*ex)); printf(" so_debug starts at %lx\n", (unsigned long) dyn->d_debug); printf(" sdt starts at %lx\n", (unsigned long) dyn->d_un.d_sdt); printf(" got starts at %lx\n", sdt->sdt_got); printf(" plt starts at %lx\n", sdt->sdt_plt); printf(" rest of stuff starts at %lx\n", sdt->sdt_plt + sdt->sdt_plt_sz); } }
static struct relocation_info * load_reloc(int fd, struct exec *hdrp, long disp) { struct relocation_info *reloc; int size; lseek(fd, disp + N_TXTOFF(*hdrp) + hdrp->a_text + hdrp->a_data, 0); size = hdrp->a_trsize + hdrp->a_drsize; reloc = (struct relocation_info*)xmalloc(size); if (reloc == NULL) { dln_errno = errno; return NULL; } if (read(fd, reloc, size) != size) { dln_errno = errno; free(reloc); return NULL; } return reloc; }
void * a_out_mod_load(int fd) { struct exec info_buf; size_t b; ssize_t n; char buf[10 * BUFSIZ]; /* * Get the load module post load size... do this by reading the * header and doing page counts. */ if (a_out_read_header(fd, &info_buf) < 0) return NULL; /* * Seek to the text offset to start loading... */ if (lseek(fd, N_TXTOFF(info_buf), 0) == -1) err(12, "lseek"); /* * Transfer the relinked module to kernel memory in chunks of * MODIOBUF size at a time. */ b = info_buf.a_text + info_buf.a_data; while (b) { n = read(fd, buf, MIN(b, sizeof(buf))); if (n < 0) err(1, "while reading from prelinked module"); if (n == 0) errx(1, "EOF while reading from prelinked module"); loadbuf(buf, n); b -= n; } return (void *)info_buf.a_entry; }
static unsigned int load_aout_interp(struct exec * interp_ex, struct inode * interpreter_inode) { int retval; unsigned int elf_entry; current->mm->brk = interp_ex->a_bss + (current->mm->end_data = interp_ex->a_data + (current->mm->end_code = interp_ex->a_text)); elf_entry = interp_ex->a_entry; if (N_MAGIC(*interp_ex) == OMAGIC) { do_mmap(NULL, 0, interp_ex->a_text+interp_ex->a_data, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_FIXED|MAP_PRIVATE, 0); retval = read_exec(interpreter_inode, 32, (char *) 0, interp_ex->a_text+interp_ex->a_data); } else if (N_MAGIC(*interp_ex) == ZMAGIC || N_MAGIC(*interp_ex) == QMAGIC) { do_mmap(NULL, 0, interp_ex->a_text+interp_ex->a_data, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_FIXED|MAP_PRIVATE, 0); retval = read_exec(interpreter_inode, N_TXTOFF(*interp_ex) , (char *) N_TXTADDR(*interp_ex), interp_ex->a_text+interp_ex->a_data); } else retval = -1; if(retval >= 0) do_mmap(NULL, (interp_ex->a_text + interp_ex->a_data + 0xfff) & 0xfffff000, interp_ex->a_bss, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_FIXED|MAP_PRIVATE, 0); if(retval < 0) return 0xffffffff; return elf_entry; }
setsym() { off_t loc; struct exec hdr; register struct nlist *sp; int ssiz; char *strtab; fsym = getfile(symfil, 1); txtmap.ufd = fsym; if (read(fsym, (char *)&hdr, sizeof hdr) != sizeof hdr || N_BADMAG(hdr)) { txtmap.e1 = MAXFILE; return; } filhdr = hdr; loc = filhdr.a_text+filhdr.a_data; txtmap.f1 = txtmap.f2 = N_TXTOFF(filhdr); txtmap.b1 = 0; switch (filhdr.a_magic) { case OMAGIC: txtmap.b1 = txtmap.e1 = 0; txtmap.b2 = datbas = 0; txtmap.e2 = loc; break; case ZMAGIC: case NMAGIC: txtmap.e1 = filhdr.a_text; txtmap.b2 = datbas = round(filhdr.a_text, PAGSIZ); txtmap.e2 = datbas + filhdr.a_data; txtmap.f2 += txtmap.e1; } loc = N_SYMOFF(filhdr); symtab = (struct nlist *) malloc(filhdr.a_syms); esymtab = &symtab[filhdr.a_syms / sizeof (struct nlist)]; if (symtab == NULL) goto nospac; lseek(fsym, loc, L_SET); if (filhdr.a_syms == 0) goto nosymt; /* SHOULD SQUISH OUT STABS HERE!!! */ if (read(fsym, symtab, filhdr.a_syms) != filhdr.a_syms) goto readerr; if (read(fsym, &ssiz, sizeof (ssiz)) != sizeof (ssiz)) goto oldfmt; strtab = (char *) malloc(ssiz); if (strtab == 0) goto nospac; *(int *)strtab = ssiz; ssiz -= sizeof (ssiz); if (read(fsym, strtab + sizeof (ssiz), ssiz) != ssiz) goto readerr; for (sp = symtab; sp < esymtab; sp++) if (sp->n_strx) /* SHOULD PERFORM RANGE CHECK HERE */ sp->n_un.n_name = strtab + sp->n_un.n_strx; nosymt: if (INKERNEL(filhdr.a_entry)) { txtmap.b1 += KERNOFF; txtmap.e1 += KERNOFF; txtmap.b2 += KERNOFF; txtmap.e2 += KERNOFF; } return; readerr: printf("Error reading symbol|string table\n"); exit(1); nospac: printf("Not enough space for symbol|string table\n"); exit(1); oldfmt: printf("Old format a.out - no string table\n"); exit(1); }
int aout_load(struct sys_info *info, ihandle_t dev) { int retval = -1; struct exec ehdr; unsigned long start, size; unsigned int offset; image_name = image_version = NULL; /* Mark the saved-program-state as invalid */ feval("0 state-valid !"); fd = open_ih(dev); if (fd == -1) { goto out; } for (offset = 0; offset < 16 * 512; offset += 512) { seek_io(fd, offset); if (read_io(fd, &ehdr, sizeof ehdr) != sizeof ehdr) { debug("Can't read a.out header\n"); retval = LOADER_NOT_SUPPORT; goto out; } if (is_aout(&ehdr)) break; } if (!is_aout(&ehdr)) { debug("Not a bootable a.out image\n"); retval = LOADER_NOT_SUPPORT; goto out; } if (ehdr.a_text == 0x30800007) ehdr.a_text=64*1024; if (N_MAGIC(ehdr) == NMAGIC) { size = addr_fixup(N_DATADDR(ehdr)) + addr_fixup(ehdr.a_data); } else { size = addr_fixup(ehdr.a_text) + addr_fixup(ehdr.a_data); } if (size < 7680) size = 7680; fword("load-base"); start = POP(); // N_TXTADDR(ehdr); memcpy((void *)start, &ehdr, sizeof(ehdr)); if (!check_mem_ranges(info, start, size)) goto out; printf("Loading a.out %s...\n", image_name ? image_name : "image"); seek_io(fd, offset + N_TXTOFF(ehdr)); if (N_MAGIC(ehdr) == NMAGIC) { if ((size_t)read_io(fd, (void *)(start + N_TXTOFF(ehdr)), ehdr.a_text) != ehdr.a_text) { printf("Can't read program text segment (size 0x" FMT_aout_ehdr ")\n", ehdr.a_text); goto out; } if ((size_t)read_io(fd, (void *)(start + N_DATADDR(ehdr)), ehdr.a_data) != ehdr.a_data) { printf("Can't read program data segment (size 0x" FMT_aout_ehdr ")\n", ehdr.a_data); goto out; } } else { if ((size_t)read_io(fd, (void *)(start + N_TXTOFF(ehdr)), size) != size) { printf("Can't read program (size 0x" FMT_sizet ")\n", size); goto out; } } debug("Loaded %lu bytes\n", size); debug("entry point is %#lx\n", start); // Initialise saved-program-state PUSH(size); feval("load-state >ls.file-size !"); feval("aout load-state >ls.file-type !"); out: close_io(fd); return retval; }
/* N.B. Move to .h file and use code in fs/binfmt_aout.c? */ static int load_aout32_library(struct file *file) { struct inode * inode; unsigned long bss, start_addr, len; unsigned long error; int retval; struct exec ex; inode = file->f_path.dentry->d_inode; retval = -ENOEXEC; error = kernel_read(file, 0, (char *) &ex, sizeof(ex)); if (error != sizeof(ex)) goto out; /* We come in here for the regular a.out style of shared libraries */ if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != QMAGIC) || N_TRSIZE(ex) || N_DRSIZE(ex) || ((ex.a_entry & 0xfff) && N_MAGIC(ex) == ZMAGIC) || inode->i_size < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) { goto out; } if (N_MAGIC(ex) == ZMAGIC && N_TXTOFF(ex) && (N_TXTOFF(ex) < inode->i_sb->s_blocksize)) { printk("N_TXTOFF < BLOCK_SIZE. Please convert library\n"); goto out; } if (N_FLAGS(ex)) goto out; /* For QMAGIC, the starting address is 0x20 into the page. We mask this off to get the starting address for the page */ start_addr = ex.a_entry & 0xfffff000; /* Now use mmap to map the library into memory. */ down_write(¤t->mm->mmap_sem); error = do_mmap(file, start_addr, ex.a_text + ex.a_data, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE, N_TXTOFF(ex)); up_write(¤t->mm->mmap_sem); retval = error; if (error != start_addr) goto out; len = PAGE_ALIGN(ex.a_text + ex.a_data); bss = ex.a_text + ex.a_data + ex.a_bss; if (bss > len) { down_write(¤t->mm->mmap_sem); error = do_brk(start_addr + len, bss - len); up_write(¤t->mm->mmap_sem); retval = error; if (error != start_addr + len) goto out; } retval = 0; out: return retval; }
static int load_aout32_binary(struct linux_binprm * bprm, struct pt_regs * regs) { struct exec ex; unsigned long error; unsigned long fd_offset; unsigned long rlim; unsigned long orig_thr_flags; int retval; ex = *((struct exec *) bprm->buf); /* exec-header */ if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC && N_MAGIC(ex) != QMAGIC && N_MAGIC(ex) != NMAGIC) || N_TRSIZE(ex) || N_DRSIZE(ex) || bprm->file->f_path.dentry->d_inode->i_size < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) { return -ENOEXEC; } fd_offset = N_TXTOFF(ex); /* Check initial limits. This avoids letting people circumvent * size limits imposed on them by creating programs with large * arrays in the data or bss. */ rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur; if (rlim >= RLIM_INFINITY) rlim = ~0; if (ex.a_data + ex.a_bss > rlim) return -ENOMEM; /* Flush all traces of the currently running executable */ retval = flush_old_exec(bprm); if (retval) return retval; /* OK, This is the point of no return */ set_personality(PER_SUNOS); current->mm->end_code = ex.a_text + (current->mm->start_code = N_TXTADDR(ex)); current->mm->end_data = ex.a_data + (current->mm->start_data = N_DATADDR(ex)); current->mm->brk = ex.a_bss + (current->mm->start_brk = N_BSSADDR(ex)); current->mm->free_area_cache = current->mm->mmap_base; current->mm->cached_hole_size = 0; current->mm->mmap = NULL; compute_creds(bprm); current->flags &= ~PF_FORKNOEXEC; if (N_MAGIC(ex) == NMAGIC) { loff_t pos = fd_offset; /* F**k me plenty... */ down_write(¤t->mm->mmap_sem); error = do_brk(N_TXTADDR(ex), ex.a_text); up_write(¤t->mm->mmap_sem); bprm->file->f_op->read(bprm->file, (char __user *)N_TXTADDR(ex), ex.a_text, &pos); down_write(¤t->mm->mmap_sem); error = do_brk(N_DATADDR(ex), ex.a_data); up_write(¤t->mm->mmap_sem); bprm->file->f_op->read(bprm->file, (char __user *)N_DATADDR(ex), ex.a_data, &pos); goto beyond_if; } if (N_MAGIC(ex) == OMAGIC) { loff_t pos = fd_offset; down_write(¤t->mm->mmap_sem); do_brk(N_TXTADDR(ex) & PAGE_MASK, ex.a_text+ex.a_data + PAGE_SIZE - 1); up_write(¤t->mm->mmap_sem); bprm->file->f_op->read(bprm->file, (char __user *)N_TXTADDR(ex), ex.a_text+ex.a_data, &pos); } else { static unsigned long error_time; if ((ex.a_text & 0xfff || ex.a_data & 0xfff) && (N_MAGIC(ex) != NMAGIC) && (jiffies-error_time) > 5*HZ) { printk(KERN_NOTICE "executable not page aligned\n"); error_time = jiffies; } if (!bprm->file->f_op->mmap) { loff_t pos = fd_offset; down_write(¤t->mm->mmap_sem); do_brk(0, ex.a_text+ex.a_data); up_write(¤t->mm->mmap_sem); bprm->file->f_op->read(bprm->file, (char __user *)N_TXTADDR(ex), ex.a_text+ex.a_data, &pos); goto beyond_if; } down_write(¤t->mm->mmap_sem); error = do_mmap(bprm->file, N_TXTADDR(ex), ex.a_text, PROT_READ | PROT_EXEC, MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE, fd_offset); up_write(¤t->mm->mmap_sem); if (error != N_TXTADDR(ex)) { send_sig(SIGKILL, current, 0); return error; } down_write(¤t->mm->mmap_sem); error = do_mmap(bprm->file, N_DATADDR(ex), ex.a_data, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE, fd_offset + ex.a_text); up_write(¤t->mm->mmap_sem); if (error != N_DATADDR(ex)) { send_sig(SIGKILL, current, 0); return error; } } beyond_if: set_binfmt(&aout32_format); set_brk(current->mm->start_brk, current->mm->brk); /* Make sure STACK_TOP returns the right thing. */ orig_thr_flags = current_thread_info()->flags; current_thread_info()->flags |= _TIF_32BIT; retval = setup_arg_pages(bprm, STACK_TOP, EXSTACK_DEFAULT); if (retval < 0) { current_thread_info()->flags = orig_thr_flags; /* Someone check-me: is this error path enough? */ send_sig(SIGKILL, current, 0); return retval; } current->mm->start_stack = (unsigned long) create_aout32_tables((char __user *)bprm->p, bprm); tsb_context_switch(current->mm); start_thread32(regs, ex.a_entry, current->mm->start_stack); if (current->ptrace & PT_PTRACED) send_sig(SIGTRAP, current, 0); return 0; }
/* End of test binpatch variables */ int main(int argc, char *argv[]) { struct exec e; int c; u_long addr = 0, offset = 0; u_long index = 0;/* Related to offset */ u_long replace = 0, do_replace = 0; char *symbol = 0; char size = 4; /* default to long */ char size_opt = 0; /* Flag to say size option was set, used with index */ char *fname; char *pgname = argv[0]; /* Program name */ int fd; int type, off; u_long lval; u_short sval; u_char cval; while ((c = getopt (argc, argv, "H:a:bwlr:s:o:")) != -1) switch (c) { case 'H': Usage(argv[0]); break; case 'a': if (addr || symbol) error ("only one address/symbol allowed"); if (! strncmp (optarg, "0x", 2)) sscanf (optarg, "%x", &addr); else addr = atoi (optarg); if (! addr) error ("invalid address"); break; case 'b': size = 1; size_opt = 1; break; case 'w': size = 2; size_opt = 1; break; case 'l': size = 4; size_opt = 1; break; case 'r': do_replace = 1; if (! strncmp (optarg, "0x", 2)) sscanf (optarg, "%x", &replace); else replace = atoi (optarg); break; case 's': if (addr || symbol) error ("only one address/symbol allowed"); symbol = optarg; break; case 'o': if (offset) error ("only one offset allowed"); if (! strncmp (optarg, "0x", 2)) sscanf (optarg, "%x", &offset); else offset = atoi (optarg); break; }/* while switch() */ if (argc > 1) { if (addr || symbol) { argv += optind; argc -= optind; if (argc < 1) error ("No file to patch."); fname = argv[0]; if ((fd = open (fname, 0)) < 0) error ("Can't open file"); if (read (fd, &e, sizeof (e)) != sizeof (e) || N_BADMAG (e)) error ("Not a valid executable."); /* fake mid, so the N_ macros work on the amiga.. */ e.a_midmag |= 127 << 16; if (symbol) { struct nlist nl[2]; if (offset == 0) { u_long new_do_replace = 0; new_do_replace = FindAssign(symbol,&replace); if (new_do_replace && do_replace) error("Cannot use both '=' and '-r' option!"); FindOffset(symbol,&index); if (size_opt) offset = index*size; /* Treat like an index */ else offset = index; /* Treat index like an offset */ if (new_do_replace) do_replace = new_do_replace; } nl[0].n_un.n_name = symbol; nl[1].n_un.n_name = 0; if (nlist (fname, nl) != 0) { fprintf(stderr,"Symbol is %s ",symbol); error ("Symbol not found."); } addr = nl[0].n_value; type = nl[0].n_type & N_TYPE; } else { type = N_UNDF; if (addr >= N_TXTADDR(e) && addr < N_DATADDR(e)) type = N_TEXT; else if (addr >= N_DATADDR(e) && addr < N_DATADDR(e) + e.a_data) type = N_DATA; } addr += offset; /* if replace-mode, have to reopen the file for writing. Can't do that from the beginning, or nlist() will not work (at least not under AmigaDOS) */ if (do_replace) { close (fd); if ((fd = open (fname, 2)) == -1) error ("Can't reopen file for writing."); } if (type != N_TEXT && type != N_DATA) error ("address/symbol is not in text or data section."); if (type == N_TEXT) off = addr - N_TXTADDR(e) + N_TXTOFF(e); else off = addr - N_DATADDR(e) + N_DATOFF(e); if (lseek (fd, off, 0) == -1) error ("lseek"); /* not beautiful, but works on big and little endian machines */ switch (size) { case 1: if (read (fd, &cval, 1) != 1) error ("cread"); lval = cval; break; case 2: if (read (fd, &sval, 2) != 2) error ("sread"); lval = sval; break; case 4: if (read (fd, &lval, 4) != 4) error ("lread"); break; }/* switch size */ if (symbol) printf ("%s(0x%x): %d (0x%x)\n", symbol, addr, lval, lval); else printf ("0x%x: %d (0x%x)\n", addr, lval, lval); if (do_replace) { if (lseek (fd, off, 0) == -1) error ("write-lseek"); switch (size) { case 1: cval = replace; if (cval != replace) error ("byte-value overflow."); if (write (fd, &cval, 1) != 1) error ("cwrite"); break; case 2: sval = replace; if (sval != replace) error ("word-value overflow."); if (write (fd, &sval, 2) != 2) error ("swrite"); break; case 4: if (write (fd, &replace, 4) != 4) error ("lwrite"); break; }/* switch(size) */ }/* if (do_replace) */ close (fd); }/* if(addr || symbol ) */ else { error("Must specify either address or symbol."); } }/* if argc < 1 */ else { Synopsis(pgname); } return(0); }/* main () */
static int load_aout_library(struct file *file) { struct inode * inode; unsigned long bss, start_addr, len; unsigned long error; int retval; struct exec ex; inode = file->f_dentry->d_inode; retval = -ENOEXEC; error = kernel_read(file, 0, (char *) &ex, sizeof(ex)); if (error != sizeof(ex)) goto out; /* We come in here for the regular a.out style of shared libraries */ if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != QMAGIC) || N_TRSIZE(ex) || N_DRSIZE(ex) || ((ex.a_entry & 0xfff) && N_MAGIC(ex) == ZMAGIC) || inode->i_size < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) { goto out; } if (N_FLAGS(ex)) goto out; /* For QMAGIC, the starting address is 0x20 into the page. We mask this off to get the starting address for the page */ #ifndef __arm__ start_addr = ex.a_entry & 0xfffff000; #else start_addr = ex.a_entry & 0xffff8000; #endif if ((N_TXTOFF(ex) & ~PAGE_MASK) != 0) { static unsigned long error_time; loff_t pos = N_TXTOFF(ex); if ((jiffies-error_time) > 5*HZ) { printk(KERN_WARNING "N_TXTOFF is not page aligned. Please convert library: %s\n", file->f_dentry->d_name.name); error_time = jiffies; } do_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss); file->f_op->read(file, (char *)start_addr, ex.a_text + ex.a_data, &pos); flush_icache_range((unsigned long) start_addr, (unsigned long) start_addr + ex.a_text + ex.a_data); retval = 0; goto out; } /* Now use mmap to map the library into memory. */ down_write(¤t->mm->mmap_sem); error = do_mmap(file, start_addr, ex.a_text + ex.a_data, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE, N_TXTOFF(ex)); up_write(¤t->mm->mmap_sem); retval = error; if (error != start_addr) goto out; len = PAGE_ALIGN(ex.a_text + ex.a_data); bss = ex.a_text + ex.a_data + ex.a_bss; if (bss > len) { error = do_brk(start_addr + len, bss - len); retval = error; if (error != start_addr + len) goto out; } retval = 0; out: return retval; }
static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs) { struct exec ex; unsigned long error; unsigned long fd_offset; unsigned long rlim; int retval; ex = *((struct exec *) bprm->buf); /* exec-header */ if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC && N_MAGIC(ex) != QMAGIC && N_MAGIC(ex) != NMAGIC) || N_TRSIZE(ex) || N_DRSIZE(ex) || bprm->file->f_dentry->d_inode->i_size < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) { return -ENOEXEC; } fd_offset = N_TXTOFF(ex); /* Check initial limits. This avoids letting people circumvent * size limits imposed on them by creating programs with large * arrays in the data or bss. */ rlim = current->rlim[RLIMIT_DATA].rlim_cur; if (rlim >= RLIM_INFINITY) rlim = ~0; if (ex.a_data + ex.a_bss > rlim) return -ENOMEM; /* Flush all traces of the currently running executable */ retval = flush_old_exec(bprm); if (retval) return retval; /* OK, This is the point of no return */ #if defined(__alpha__) SET_AOUT_PERSONALITY(bprm, ex); #elif defined(__sparc__) set_personality(PER_SUNOS); #if !defined(__sparc_v9__) memcpy(¤t->thread.core_exec, &ex, sizeof(struct exec)); #endif #else set_personality(PER_LINUX); #endif current->mm->end_code = ex.a_text + (current->mm->start_code = N_TXTADDR(ex)); current->mm->end_data = ex.a_data + (current->mm->start_data = N_DATADDR(ex)); current->mm->brk = ex.a_bss + (current->mm->start_brk = N_BSSADDR(ex)); current->mm->rss = 0; current->mm->mmap = NULL; #ifdef CONFIG_ARM_FASS arch_new_mm(current, current->mm); #endif compute_creds(bprm); current->flags &= ~PF_FORKNOEXEC; #ifdef __sparc__ if (N_MAGIC(ex) == NMAGIC) { loff_t pos = fd_offset; /* F**k me plenty... */ /* <AOL></AOL> */ error = do_brk(N_TXTADDR(ex), ex.a_text); bprm->file->f_op->read(bprm->file, (char *) N_TXTADDR(ex), ex.a_text, &pos); error = do_brk(N_DATADDR(ex), ex.a_data); bprm->file->f_op->read(bprm->file, (char *) N_DATADDR(ex), ex.a_data, &pos); goto beyond_if; } #endif if (N_MAGIC(ex) == OMAGIC) { unsigned long text_addr, map_size; loff_t pos; text_addr = N_TXTADDR(ex); #if defined(__alpha__) || defined(__sparc__) pos = fd_offset; map_size = ex.a_text+ex.a_data + PAGE_SIZE - 1; #else pos = 32; map_size = ex.a_text+ex.a_data; #endif error = do_brk(text_addr & PAGE_MASK, map_size); if (error != (text_addr & PAGE_MASK)) { send_sig(SIGKILL, current, 0); return error; } error = bprm->file->f_op->read(bprm->file, (char *)text_addr, ex.a_text+ex.a_data, &pos); if ((signed long)error < 0) { send_sig(SIGKILL, current, 0); return error; } flush_icache_range(text_addr, text_addr+ex.a_text+ex.a_data); } else { static unsigned long error_time, error_time2; if ((ex.a_text & 0xfff || ex.a_data & 0xfff) && (N_MAGIC(ex) != NMAGIC) && (jiffies-error_time2) > 5*HZ) { printk(KERN_NOTICE "executable not page aligned\n"); error_time2 = jiffies; } if ((fd_offset & ~PAGE_MASK) != 0 && (jiffies-error_time) > 5*HZ) { printk(KERN_WARNING "fd_offset is not page aligned. Please convert program: %s\n", bprm->file->f_dentry->d_name.name); error_time = jiffies; } if (!bprm->file->f_op->mmap||((fd_offset & ~PAGE_MASK) != 0)) { loff_t pos = fd_offset; do_brk(N_TXTADDR(ex), ex.a_text+ex.a_data); bprm->file->f_op->read(bprm->file,(char *)N_TXTADDR(ex), ex.a_text+ex.a_data, &pos); flush_icache_range((unsigned long) N_TXTADDR(ex), (unsigned long) N_TXTADDR(ex) + ex.a_text+ex.a_data); goto beyond_if; } down_write(¤t->mm->mmap_sem); error = do_mmap(bprm->file, N_TXTADDR(ex), ex.a_text, PROT_READ | PROT_EXEC, MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE, fd_offset); up_write(¤t->mm->mmap_sem); if (error != N_TXTADDR(ex)) { send_sig(SIGKILL, current, 0); return error; } down_write(¤t->mm->mmap_sem); error = do_mmap(bprm->file, N_DATADDR(ex), ex.a_data, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE, fd_offset + ex.a_text); up_write(¤t->mm->mmap_sem); if (error != N_DATADDR(ex)) { send_sig(SIGKILL, current, 0); return error; } } beyond_if: set_binfmt(&aout_format); set_brk(current->mm->start_brk, current->mm->brk); retval = setup_arg_pages(bprm); if (retval < 0) { /* Someone check-me: is this error path enough? */ send_sig(SIGKILL, current, 0); return retval; } current->mm->start_stack = (unsigned long) create_aout_tables((char *) bprm->p, bprm); #ifdef __alpha__ regs->gp = ex.a_gpvalue; #endif start_thread(regs, ex.a_entry, current->mm->start_stack); if (current->ptrace & PT_PTRACED) send_sig(SIGTRAP, current, 0); #ifndef __arm__ return 0; #else return regs->ARM_r0; #endif }
int main (int argc, char** argv) { struct exec my_exec; int page_size; char * target; char * arch = "unknown"; FILE * file; target = argv[1]; if (target == NULL) { fprintf (stderr, "Usage: gen-aout target_name\n"); exit (1); } file = fopen ("gen-aout", "r"); if (file == NULL) { fprintf (stderr, "Cannot open gen-aout!\n"); return -1; } if (fread (&my_exec, sizeof (struct exec), 1, file) != 1) { fprintf(stderr, "Cannot read gen-aout!\n"); return -1; } fclose (file); #ifdef N_TXTOFF page_size = N_TXTOFF(my_exec); if (page_size == 0) printf ("#define N_HEADER_IN_TEXT(x) 1\n"); else printf ("#define N_HEADER_IN_TEXT(x) 0\n"); #endif printf("#define BYTES_IN_WORD %d\n", sizeof (int)); if (my_exec.a_entry == 0) { printf ("#define ENTRY_CAN_BE_ZERO\n"); printf ("#define N_SHARED_LIB(x) 0 /* Avoids warning */\n"); } else { printf ("/*#define ENTRY_CAN_BE_ZERO*/\n"); printf ("/*#define N_SHARED_LIB(x) 0*/\n"); } printf ("#define TEXT_START_ADDR %d\n", my_exec.a_entry); #ifdef PAGSIZ if (page_size == 0) page_size = PAGSIZ; #endif if (page_size != 0) printf ("#define TARGET_PAGE_SIZE %d\n", page_size); else printf ("/* #define TARGET_PAGE_SIZE ??? */\n"); printf ("#define SEGMENT_SIZE TARGET_PAGE_SIZE\n"); #ifdef vax arch = "vax"; #endif #ifdef m68k arch = "m68k"; #endif if (arch[0] == '1') { fprintf (stderr, _("warning: preprocessor substituted architecture name inside string;")); fprintf (stderr, _(" fix DEFAULT_ARCH in the output file yourself\n")); arch = "unknown"; } printf ("#define DEFAULT_ARCH bfd_arch_%s\n\n", arch); printf ("/* Do not \"beautify\" the CONCAT* macro args. Traditional C will not"); printf (" remove whitespace added here, and thus will fail to concatenate"); printf (" the tokens. */"); printf ("\n#define MY(OP) CONCAT2 (%s_,OP)\n\n", target); printf ("#define TARGETNAME \"a.out-%s\"\n\n", target); printf ("#include \"sysdep.h\"\n"); printf ("#include \"bfd.h\"\n"); printf ("#include \"libbfd.h\"\n"); printf ("#include \"libaout.h\"\n"); printf ("\n#include \"aout-target.h\"\n"); return 0; }
static long loadprog(long *hsize) { long addr; /* physical address.. not directly useable */ long hmaddress; unsigned long pad; long i; static int (*x_entry)() = 0; ufs_read(&head, (long) sizeof(head)); if (N_BADMAG(head)) { printf("Invalid format!\n"); exit(0); } startaddr = (long)head.a_entry; addr = (startaddr & 0x00ffffffl); /* some MEG boundary */ printf("Booting @ 0x%lx\n", addr); if(addr < 0x100000l) { printf("Start address too low!\n"); exit(0); } poff = N_TXTOFF(head)+head.a_text+head.a_data+head.a_syms; ufs_read((void *)&i, sizeof(long)); *hsize = head.a_text+head.a_data+head.a_bss; *hsize = (*hsize+NBPG-1)&~(NBPG-1); *hsize += i+4+head.a_syms; addr=hmaddress=get_high_memory(*hsize); if (!hmaddress) { printf("Sorry, can't allocate enough memory!\n"); exit(0); } poff = N_TXTOFF(head); /********************************************************/ /* LOAD THE TEXT SEGMENT */ /********************************************************/ printf("text=0x%lx ", head.a_text); xread(addr, head.a_text); addr += head.a_text; /********************************************************/ /* Load the Initialised data after the text */ /********************************************************/ while (addr & CLOFSET) pm_copy("\0", addr++, 1); printf("data=0x%lx ", head.a_data); xread(addr, head.a_data); addr += head.a_data; /********************************************************/ /* Skip over the uninitialised data */ /* (but clear it) */ /********************************************************/ printf("bss=0x%lx ", head.a_bss); pbzero(addr, head.a_bss); addr += head.a_bss; /* Pad to a page boundary. */ pad = (unsigned long)(addr-hmaddress+(startaddr & 0x00ffffffl)) % NBPG; if (pad != 0) { pad = NBPG - pad; addr += pad; } bootinfo.bi_symtab = addr-hmaddress+(startaddr & 0x00ffffffl); /********************************************************/ /* Copy the symbol table size */ /********************************************************/ pm_copy((char *)&head.a_syms, addr, sizeof(head.a_syms)); addr += sizeof(head.a_syms); /********************************************************/ /* Load the symbol table */ /********************************************************/ printf("symbols=[+0x%lx+0x%lx+0x%lx", pad, (long) sizeof(head.a_syms), (long) head.a_syms); xread(addr, head.a_syms); addr += head.a_syms; /********************************************************/ /* Load the string table size */ /********************************************************/ ufs_read((void *)&i, sizeof(long)); pm_copy((char *)&i, addr, sizeof(long)); i -= sizeof(long); addr += sizeof(long); /********************************************************/ /* Load the string table */ /********************************************************/ printf("+0x%x+0x%lx] ", sizeof(long), i); xread(addr, i); addr += i; bootinfo.bi_esymtab = addr-hmaddress+(startaddr & 0x00ffffffl); /* * For backwards compatibility, use the previously-unused adaptor * and controller bitfields to hold the slice number. */ printf("total=0x%lx entry point=0x%lx\n", addr-hmaddress+(startaddr & 0x00ffffffl), startaddr & 0x00ffffffl); return hmaddress; }
/* * LoadForeign(ofiles,libs,proc_name,init_proc) dynamically loads foreign * code files and libraries and locates an initialization routine */ static Int LoadForeign(StringList ofiles, StringList libs, char *proc_name, YapInitProc *init_proc) { char command[2*MAXPATHLEN]; char o_files[1024]; /* list of objects we want to load */ char l_files[1024]; /* list of libraries we want to load */ char tmp_buff[32] = "/tmp/YAP_TMP_XXXXXX"; /* used for mktemp */ char *tfile; /* name of temporary file */ int fildes; /* temp file descriptor */ struct aouthdr sysHeader; struct filehdr fileHeader; struct scnhdr sectionHeader[MAXSECTIONS]; struct exec header; /* header for loaded file */ unsigned long loadImageSize, firstloadImSz; /* size of image we will load */ char *FCodeBase; /* where we load foreign code */ /* * put in a string the names of the files you want to load and of any * libraries you want to use */ /* files first */ *o_files = '\0'; { StringList tmp = ofiles; while(tmp != NULL) { strcat(o_files," "); strcat(o_files,tmp->s); tmp = tmp->next; } } /* same_trick for libraries */ *l_files = '\0'; { StringList tmp = libs; while(tmp != NULL) { strcat(l_files," "); strcat(l_files,tmp->s); tmp = tmp->next; } } /* next, create a temp file to serve as loader output */ tfile = mktemp(tmp_buff); /* prepare the magic */ if (strlen(o_files) + strlen(l_files) + strlen(proc_name) + strlen(YapExecutable) > 2*MAXPATHLEN) { strcpy(Yap_ErrorSay, " too many parameters in load_foreign/3 "); return LOAD_FAILLED; } sprintf(command, "/usr/bin/ld -N -A %s -o %s %s %s -lc", YapExecutable, tfile, o_files, l_files); /* now, do the magic */ if (system(command) != 0) { unlink(tfile); strcpy(Yap_ErrorSay," ld returned error status in load_foreign_files "); return LOAD_FAILLED; } /* now check the music has played */ if ((fildes = open(tfile, O_RDONLY)) < 0) { strcpy(Yap_ErrorSay," unable to open temp file in load_foreign_files "); return LOAD_FAILLED; } /* it did, get the mice */ /* first, get the header */ read(fildes, (char *) &fileHeader, sizeof(fileHeader)); read(fildes, (char *) &sysHeader, sizeof(sysHeader)); { int i; for (i = 0; i < fileHeader.f_nscns; i++) read(fildes, (char *) §ionHeader[i], sizeof(*sectionHeader)); } close(fildes); /* get the full size of what we need to load */ loadImageSize = sysHeader.tsize + sysHeader.dsize + sysHeader.bsize; #ifdef mips /* add an extra page in mips machines */ loadImageSize += 4095 + 16; #else /* add 16 just to play it safe */ loadImageSize += 16; #endif /* keep this copy */ firstloadImSz = loadImageSize; /* now fetch the space we need */ if (!(FCodeBase = Yap_AllocCodeSpace((int) loadImageSize)) #ifdef pyr || activate_code(ForeignCodeBase, u1) #endif /* pyr */ ) { strcpy(Yap_ErrorSay," unable to allocate space for external code "); return LOAD_FAILLED; } #ifdef mips FCodeBase = (char *) (Unsigned(FCodeBase + PAGESIZE - 1) & ~(PAGESIZE - 1)); #endif /* now, a new incantation to load the new foreign code */ #ifdef convex /* No -N flag in the Convex loader */ /* -T option does not want MallocBase bit set */ sprintf(command, "ld -x -A %s -T %lx -o %s -u %s %s %s -lc", ostabf, ((unsigned long) (((unsigned long) (ForeignCodeBase)) & ((unsigned long) (~Yap_HeapBase)) ) ), tfile, entry_point, o_files, l_files); #else #ifdef mips sprintf(command, "ld -systype bsd43 -N -A %s -T %lx -o %s -u %s %s %s -lc", ostabf, (unsigned long) ForeignCodeBase, tfile, entry_point, o_files, l_files); #else sprintf(command, "ld -N -A %s -T %lx -o %s -e %s -u _%s %s -lc", ostabf, (unsigned long) ForeignCodeBase, tfile, entry_point, o_files, l_files); #endif /* mips */ #endif /* convex */ /* and do it */ if (system(command) != 0) { unlink(tfile); strcpy(Yap_ErrorSay," ld returned error status in load_foreign_files "); return LOAD_FAILLED; } if ((fildes = open(tfile, O_RDONLY)) < 0) { strcpy(Yap_ErrorSay," unable to open temp file in load_foreign_files "); return LOAD_FAILLED; } read(fildes, (char *) &fileHeader, sizeof(fileHeader)); read(fildes, (char *) &sysHeader, sizeof(sysHeader)); { int i; for (i = 0; i < fileHeader.f_nscns; i++) read(fildes, (char *) §ionHeader[i], sizeof(*sectionHeader)); } loadImageSize = sysHeader.tsize + sysHeader.dsize + sysHeader.bsize; if (firstloadImSz < loadImageSize) { strcpy(Yap_ErrorSay," miscalculation in load_foreign/3 "); return LOAD_FAILLED; } /* now search for our init function */ { char entry_fun[256]; struct nlist func_info[2]; #if defined(mips) || defined(I386) char NAME1[128], NAME2[128]; func_info[0].n_name = NAME1; func_info[1].n_name = NAME2; #endif /* COFF */ sprintf(entry_fun, "_%s", proc_name); func_info[0].n_name = entry_fun; func_info[1].n_name = NULL; if (nlist(tfile, func_info) == -1) { strcpy(Yap_ErrorSay," in nlist(3) "); return LOAD_FAILLED; } if (func_info[0].n_type == 0) { strcpy(Yap_ErrorSay," in nlist(3) "); return LOAD_FAILLED; } *init_proc = (YapInitProc)(func_info[0].n_value); } /* ok, we got our init point */ /* now read our text */ lseek(fildes, (long)(N_TXTOFF(header)), 0); { unsigned int u1 = header.a_text + header.a_data; read(fildes, (char *) FCodeBase, u1); /* zero the BSS segment */ while (u1 < loadImageSize) FCodeBase[u1++] = 0; } close(fildes); unlink(tfile); return LOAD_SUCCEEDED; }
int main (int argc, char *argv[]) { size_t nwritten, tocopy, n, mem_size, fil_size, pad = 0; int fd, ofd, i, j, verbose = 0, primary = 0; char buf[8192], *inname; struct exec * aout; /* includes file & aout header */ long offset; #ifdef __ELF__ struct elfhdr *elf; struct elf_phdr *elf_phdr; /* program header */ unsigned long long e_entry; #endif prog_name = argv[0]; for (i = 1; i < argc && argv[i][0] == '-'; ++i) { for (j = 1; argv[i][j]; ++j) { switch (argv[i][j]) { case 'v': verbose = ~verbose; break; case 'b': pad = BLOCK_SIZE; break; case 'p': primary = 1; /* make primary bootblock */ break; } } } if (i >= argc) { usage(); } inname = argv[i++]; fd = open(inname, O_RDONLY); if (fd == -1) { perror("open"); exit(1); } ofd = 1; if (i < argc) { ofd = open(argv[i++], O_WRONLY | O_CREAT | O_TRUNC, 0666); if (ofd == -1) { perror("open"); exit(1); } } if (primary) { /* generate bootblock for primary loader */ unsigned long bb[64], sum = 0; struct stat st; off_t size; int i; if (ofd == 1) { usage(); } if (fstat(fd, &st) == -1) { perror("fstat"); exit(1); } size = (st.st_size + BLOCK_SIZE - 1) & ~(BLOCK_SIZE - 1); memset(bb, 0, sizeof(bb)); strcpy((char *) bb, "Linux SRM bootblock"); bb[60] = size / BLOCK_SIZE; /* count */ bb[61] = 1; /* starting sector # */ bb[62] = 0; /* flags---must be 0 */ for (i = 0; i < 63; ++i) { sum += bb[i]; } bb[63] = sum; if (write(ofd, bb, sizeof(bb)) != sizeof(bb)) { perror("boot-block write"); exit(1); } printf("%lu\n", size); return 0; } /* read and inspect exec header: */ if (read(fd, buf, sizeof(buf)) < 0) { perror("read"); exit(1); } #ifdef __ELF__ elf = (struct elfhdr *) buf; if (elf->e_ident[0] == 0x7f && strncmp((char *)elf->e_ident + 1, "ELF", 3) == 0) { if (elf->e_type != ET_EXEC) { fprintf(stderr, "%s: %s is not an ELF executable\n", prog_name, inname); exit(1); } if (!elf_check_arch(elf)) { fprintf(stderr, "%s: is not for this processor (e_machine=%d)\n", prog_name, elf->e_machine); exit(1); } if (elf->e_phnum != 1) { fprintf(stderr, "%s: %d program headers (forgot to link with -N?)\n", prog_name, elf->e_phnum); } e_entry = elf->e_entry; lseek(fd, elf->e_phoff, SEEK_SET); if (read(fd, buf, sizeof(*elf_phdr)) != sizeof(*elf_phdr)) { perror("read"); exit(1); } elf_phdr = (struct elf_phdr *) buf; offset = elf_phdr->p_offset; mem_size = elf_phdr->p_memsz; fil_size = elf_phdr->p_filesz; /* work around ELF bug: */ if (elf_phdr->p_vaddr < e_entry) { unsigned long delta = e_entry - elf_phdr->p_vaddr; offset += delta; mem_size -= delta; fil_size -= delta; elf_phdr->p_vaddr += delta; } if (verbose) { fprintf(stderr, "%s: extracting %#016lx-%#016lx (at %lx)\n", prog_name, (long) elf_phdr->p_vaddr, elf_phdr->p_vaddr + fil_size, offset); } } else #endif { aout = (struct exec *) buf; if (!(aout->fh.f_flags & COFF_F_EXEC)) { fprintf(stderr, "%s: %s is not in executable format\n", prog_name, inname); exit(1); } if (aout->fh.f_opthdr != sizeof(aout->ah)) { fprintf(stderr, "%s: %s has unexpected optional header size\n", prog_name, inname); exit(1); } if (N_MAGIC(*aout) != OMAGIC) { fprintf(stderr, "%s: %s is not an OMAGIC file\n", prog_name, inname); exit(1); } offset = N_TXTOFF(*aout); fil_size = aout->ah.tsize + aout->ah.dsize; mem_size = fil_size + aout->ah.bsize; if (verbose) { fprintf(stderr, "%s: extracting %#016lx-%#016lx (at %lx)\n", prog_name, aout->ah.text_start, aout->ah.text_start + fil_size, offset); } } if (lseek(fd, offset, SEEK_SET) != offset) { perror("lseek"); exit(1); } if (verbose) { fprintf(stderr, "%s: copying %lu byte from %s\n", prog_name, (unsigned long) fil_size, inname); } tocopy = fil_size; while (tocopy > 0) { n = tocopy; if (n > sizeof(buf)) { n = sizeof(buf); } tocopy -= n; if ((size_t) read(fd, buf, n) != n) { perror("read"); exit(1); } do { nwritten = write(ofd, buf, n); if ((ssize_t) nwritten == -1) { perror("write"); exit(1); } n -= nwritten; } while (n > 0); } if (pad) { mem_size = ((mem_size + pad - 1) / pad) * pad; } tocopy = mem_size - fil_size; if (tocopy > 0) { fprintf(stderr, "%s: zero-filling bss and aligning to %lu with %lu bytes\n", prog_name, pad, (unsigned long) tocopy); memset(buf, 0x00, sizeof(buf)); do { n = tocopy; if (n > sizeof(buf)) { n = sizeof(buf); } nwritten = write(ofd, buf, n); if ((ssize_t) nwritten == -1) { perror("write"); exit(1); } tocopy -= nwritten; } while (tocopy > 0); } return 0; }
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); }
/* os_strings: List the strings of a binary and * check if the regex given is there. */ int os_string(char *file, char *regex) { int ch, cnt; unsigned char *C; unsigned char *bfr; char line[OS_SIZE_1024 +1]; char *buf; EXEC *head; os_strings oss; /* Return didn't match */ if(!file || !regex) { return(0); } /* Allocating for the buffer */ bfr = calloc(STR_MINLEN + 2, sizeof(char *)); if (!bfr) { merror(MEM_ERROR, ARGV0); return(0); } /* Opening the file */ oss.fp = fopen(file, "r"); if(!oss.fp) { free(bfr); return(0); } /* cleaning the line */ memset(line, '\0', OS_SIZE_1024 +1); /* starting .. (from old strings.c) */ oss.foff = 0; oss.head_len = 0; oss.read_len = -1; head = (EXEC *)oss.hbfr; if ((oss.head_len = read(fileno(oss.fp), head, sizeof(EXEC))) == -1) { oss.head_len = 0; oss.read_len = -1; } else if (oss.head_len == sizeof(EXEC) && !N_BADMAG(*head)) { oss.foff = N_TXTOFF(*head); if (fseek(stdin, oss.foff, SEEK_SET) == -1) { oss.read_len = -1; } else { #ifdef AIX oss.read_len = head->tsize + head->dsize; #else oss.read_len = head->a_text + head->a_data; #endif } oss.head_len = 0; } else { oss.hcnt = 0; } /* Read the file and perform the regex comparison */ for (cnt = 0; (ch = os_getch(&oss)) != EOF;) { if (ISSTR(ch)) { if (!cnt) C = bfr; *C++ = ch; if (++cnt < STR_MINLEN) continue; strncpy(line, (char *)bfr, STR_MINLEN +1); buf = line; buf+=strlen(line); while ((ch = os_getch(&oss)) != EOF && ISSTR(ch)) { if(cnt < OS_SIZE_1024) { *buf = (char)ch; buf++; } else { *buf = '\0'; break; } cnt++; } *buf = '\0'; if(OS_PRegex(line, regex)) { if(oss.fp) fclose(oss.fp); free(bfr); return(1); } } cnt = 0; } if(oss.fp) fclose(oss.fp); free(bfr); return(0); }