static int create_state_record_for (struct dwarf_cursor *c, dwarf_state_record_t *sr, unw_word_t ip) { int i, ret; assert (c->pi_valid); memset (sr, 0, sizeof (*sr)); for (i = 0; i < DWARF_NUM_PRESERVED_REGS + 2; ++i) set_reg (sr, i, DWARF_WHERE_SAME, 0); switch (c->pi.format) { case UNW_INFO_FORMAT_TABLE: case UNW_INFO_FORMAT_REMOTE_TABLE: ret = parse_fde (c, ip, sr); break; case UNW_INFO_FORMAT_DYNAMIC: ret = parse_dynamic (c, ip, sr); break; default: Debug (1, "Unexpected unwind-info format %d\n", c->pi.format); ret = -UNW_EINVAL; } return ret; }
static int parse_conf_dynamic(char *file, time_t mtime) { FILE *fp = fopen(file, "r"); if (!fp) { _pe("Failed opening %s", file); return 1; } while (!feof(fp)) { char line[LINE_SIZE] = ""; if (!fgets(line, sizeof(line), fp)) continue; chomp(line); _d("dyn conf: %s", line); parse_dynamic(line, mtime); } fclose(fp); return 0; }
static int link_elf_preload_file(const char *filename, linker_file_t *result) { caddr_t modptr, baseptr, sizeptr, dynptr; char *type; elf_file_t ef; linker_file_t lf; int error; vm_offset_t dp; /* * Look to see if we have the module preloaded. */ modptr = preload_search_by_name(filename); if (modptr == NULL) return ENOENT; /* It's preloaded, check we can handle it and collect information */ type = (char *)preload_search_info(modptr, MODINFO_TYPE); baseptr = preload_search_info(modptr, MODINFO_ADDR); sizeptr = preload_search_info(modptr, MODINFO_SIZE); dynptr = preload_search_info(modptr, MODINFO_METADATA|MODINFOMD_DYNAMIC); if (type == NULL || (strcmp(type, "elf" __XSTRING(__ELF_WORD_SIZE) " module") != 0 && strcmp(type, "elf module") != 0)) return (EFTYPE); if (baseptr == NULL || sizeptr == NULL || dynptr == NULL) return (EINVAL); ef = kmalloc(sizeof(struct elf_file), M_LINKER, M_WAITOK | M_ZERO); ef->modptr = modptr; ef->address = *(caddr_t *)baseptr; #ifdef SPARSE_MAPPING ef->object = NULL; #endif dp = (vm_offset_t)ef->address + *(vm_offset_t *)dynptr; ef->dynamic = (Elf_Dyn *)dp; lf = linker_make_file(filename, ef, &link_elf_module_ops); if (lf == NULL) { kfree(ef, M_LINKER); return ENOMEM; } lf->address = ef->address; lf->size = *(size_t *)sizeptr; error = parse_dynamic(lf); if (error) { linker_file_unload(lf); return error; } link_elf_reloc_local(lf); *result = lf; return (0); }
static void link_elf_init(void* arg) { Elf_Dyn *dp; caddr_t modptr, baseptr, sizeptr; elf_file_t ef; char *modname; #if ELF_TARG_CLASS == ELFCLASS32 linker_add_class("elf32", NULL, &link_elf_class_ops); #else linker_add_class("elf64", NULL, &link_elf_class_ops); #endif dp = (Elf_Dyn*) &_DYNAMIC; if (dp) { ef = kmalloc(sizeof(struct elf_file), M_LINKER, M_INTWAIT | M_ZERO); ef->address = NULL; #ifdef SPARSE_MAPPING ef->object = NULL; #endif ef->dynamic = dp; modname = NULL; modptr = preload_search_by_type("elf kernel"); if (modptr) modname = (char *)preload_search_info(modptr, MODINFO_NAME); if (modname == NULL) modname = "kernel"; linker_kernel_file = linker_make_file(modname, ef, &link_elf_file_ops); if (linker_kernel_file == NULL) panic("link_elf_init: Can't create linker structures for kernel"); parse_dynamic(linker_kernel_file); #if defined(__amd64__) && defined(_KERNEL_VIRTUAL) fprintf(stderr, "WARNING: KERNBASE being used\n"); #endif linker_kernel_file->address = (caddr_t) KERNBASE; linker_kernel_file->size = -(intptr_t)linker_kernel_file->address; if (modptr) { ef->modptr = modptr; baseptr = preload_search_info(modptr, MODINFO_ADDR); if (baseptr) linker_kernel_file->address = *(caddr_t *)baseptr; sizeptr = preload_search_info(modptr, MODINFO_SIZE); if (sizeptr) linker_kernel_file->size = *(size_t *)sizeptr; } parse_module_symbols(linker_kernel_file); linker_current_file = linker_kernel_file; linker_kernel_file->flags |= LINKER_FILE_LINKED; } }
static int parse_conf(char *file) { FILE *fp; char line[LINE_SIZE] = ""; char *x; fp = fopen(file, "r"); if (!fp) return 1; /* * If not standard finit.conf, then we want to show just the base name * Loading configuration ............. vs * Loading services configuration .... */ if (!string_match (file, FINIT_CONF)) { /* Remove leading path */ x = strrchr(file, '/'); if (!x) x = file; else x++; /* Remove ending .conf */ strlcpy(line, x, sizeof(line)); x = strstr(line, ".conf"); if (x) *x = 0; /* Add empty space. */ strcat(line, " "); } if (!silent) print(0, "Loading %sconfiguration", line); while (!feof(fp)) { if (!fgets(line, sizeof(line), fp)) continue; chomp(line); _d("conf: %s", line); parse_static(line); parse_dynamic(line, 0); } fclose(fp); return 0; }
static int link_elf_load_file(const char* filename, linker_file_t* result) { struct nlookupdata nd; struct thread *td = curthread; /* XXX */ struct proc *p = td->td_proc; struct vnode *vp; Elf_Ehdr *hdr; caddr_t firstpage; int nbytes, i; Elf_Phdr *phdr; Elf_Phdr *phlimit; Elf_Phdr *segs[2]; int nsegs; Elf_Phdr *phdyn; caddr_t mapbase; size_t mapsize; Elf_Addr base_vaddr; Elf_Addr base_vlimit; int error = 0; int resid; elf_file_t ef; linker_file_t lf; char *pathname; Elf_Shdr *shdr; int symtabindex; int symstrindex; int symcnt; int strcnt; /* XXX Hack for firmware loading where p == NULL */ if (p == NULL) { p = &proc0; } KKASSERT(p != NULL); if (p->p_ucred == NULL) { kprintf("link_elf_load_file: cannot load '%s' from filesystem" " this early\n", filename); return ENOENT; } shdr = NULL; lf = NULL; pathname = linker_search_path(filename); if (pathname == NULL) return ENOENT; error = nlookup_init(&nd, pathname, UIO_SYSSPACE, NLC_FOLLOW|NLC_LOCKVP); if (error == 0) error = vn_open(&nd, NULL, FREAD, 0); kfree(pathname, M_LINKER); if (error) { nlookup_done(&nd); return error; } vp = nd.nl_open_vp; nd.nl_open_vp = NULL; nlookup_done(&nd); /* * Read the elf header from the file. */ firstpage = kmalloc(PAGE_SIZE, M_LINKER, M_WAITOK); hdr = (Elf_Ehdr *)firstpage; error = vn_rdwr(UIO_READ, vp, firstpage, PAGE_SIZE, 0, UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &resid); nbytes = PAGE_SIZE - resid; if (error) goto out; if (!IS_ELF(*hdr)) { error = ENOEXEC; goto out; } if (hdr->e_ident[EI_CLASS] != ELF_TARG_CLASS || hdr->e_ident[EI_DATA] != ELF_TARG_DATA) { link_elf_error("Unsupported file layout"); error = ENOEXEC; goto out; } if (hdr->e_ident[EI_VERSION] != EV_CURRENT || hdr->e_version != EV_CURRENT) { link_elf_error("Unsupported file version"); error = ENOEXEC; goto out; } if (hdr->e_type != ET_EXEC && hdr->e_type != ET_DYN) { error = ENOSYS; goto out; } if (hdr->e_machine != ELF_TARG_MACH) { link_elf_error("Unsupported machine"); error = ENOEXEC; goto out; } /* * We rely on the program header being in the first page. This is * not strictly required by the ABI specification, but it seems to * always true in practice. And, it simplifies things considerably. */ if (!((hdr->e_phentsize == sizeof(Elf_Phdr)) && (hdr->e_phoff + hdr->e_phnum*sizeof(Elf_Phdr) <= PAGE_SIZE) && (hdr->e_phoff + hdr->e_phnum*sizeof(Elf_Phdr) <= nbytes))) link_elf_error("Unreadable program headers"); /* * Scan the program header entries, and save key information. * * We rely on there being exactly two load segments, text and data, * in that order. */ phdr = (Elf_Phdr *) (firstpage + hdr->e_phoff); phlimit = phdr + hdr->e_phnum; nsegs = 0; phdyn = NULL; while (phdr < phlimit) { switch (phdr->p_type) { case PT_LOAD: if (nsegs == 2) { link_elf_error("Too many sections"); error = ENOEXEC; goto out; } segs[nsegs] = phdr; ++nsegs; break; case PT_PHDR: break; case PT_DYNAMIC: phdyn = phdr; break; case PT_INTERP: error = ENOSYS; goto out; } ++phdr; } if (phdyn == NULL) { link_elf_error("Object is not dynamically-linked"); error = ENOEXEC; goto out; } /* * Allocate the entire address space of the object, to stake out our * contiguous region, and to establish the base address for relocation. */ base_vaddr = trunc_page(segs[0]->p_vaddr); base_vlimit = round_page(segs[1]->p_vaddr + segs[1]->p_memsz); mapsize = base_vlimit - base_vaddr; ef = kmalloc(sizeof(struct elf_file), M_LINKER, M_WAITOK | M_ZERO); ef->address = kmalloc(mapsize, M_LINKER, M_WAITOK); mapbase = ef->address; /* * Read the text and data sections and zero the bss. */ for (i = 0; i < 2; i++) { caddr_t segbase = mapbase + segs[i]->p_vaddr - base_vaddr; error = vn_rdwr(UIO_READ, vp, segbase, segs[i]->p_filesz, segs[i]->p_offset, UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &resid); if (error) { kfree(ef->address, M_LINKER); kfree(ef, M_LINKER); goto out; } bzero(segbase + segs[i]->p_filesz, segs[i]->p_memsz - segs[i]->p_filesz); } ef->dynamic = (const Elf_Dyn *) (mapbase + phdyn->p_vaddr - base_vaddr); lf = linker_make_file(filename, ef, &link_elf_file_ops); if (lf == NULL) { kfree(ef->address, M_LINKER); kfree(ef, M_LINKER); error = ENOMEM; goto out; } lf->address = ef->address; lf->size = mapsize; error = parse_dynamic(lf); if (error) goto out; link_elf_reloc_local(lf); error = linker_load_dependencies(lf); if (error) goto out; error = relocate_file(lf); if (error) goto out; /* Try and load the symbol table if it's present. (you can strip it!) */ nbytes = hdr->e_shnum * hdr->e_shentsize; if (nbytes == 0 || hdr->e_shoff == 0) goto nosyms; shdr = kmalloc(nbytes, M_LINKER, M_WAITOK | M_ZERO); error = vn_rdwr(UIO_READ, vp, (caddr_t)shdr, nbytes, hdr->e_shoff, UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &resid); if (error) goto out; symtabindex = -1; symstrindex = -1; for (i = 0; i < hdr->e_shnum; i++) { if (shdr[i].sh_type == SHT_SYMTAB) { symtabindex = i; symstrindex = shdr[i].sh_link; } } if (symtabindex < 0 || symstrindex < 0) goto nosyms; symcnt = shdr[symtabindex].sh_size; ef->symbase = kmalloc(symcnt, M_LINKER, M_WAITOK); strcnt = shdr[symstrindex].sh_size; ef->strbase = kmalloc(strcnt, M_LINKER, M_WAITOK); error = vn_rdwr(UIO_READ, vp, ef->symbase, symcnt, shdr[symtabindex].sh_offset, UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &resid); if (error) goto out; error = vn_rdwr(UIO_READ, vp, ef->strbase, strcnt, shdr[symstrindex].sh_offset, UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &resid); if (error) goto out; ef->ddbsymcnt = symcnt / sizeof(Elf_Sym); ef->ddbsymtab = (const Elf_Sym *)ef->symbase; ef->ddbstrcnt = strcnt; ef->ddbstrtab = ef->strbase; nosyms: *result = lf; out: if (error && lf) linker_file_unload(lf); if (shdr) kfree(shdr, M_LINKER); if (firstpage) kfree(firstpage, M_LINKER); vn_unlock(vp); vn_close(vp, FREAD, NULL); return error; }