Esempio n. 1
0
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;
}
Esempio n. 2
0
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;
}
Esempio n. 3
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);
}
Esempio n. 4
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;
    }
}
Esempio n. 5
0
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;
}
Esempio n. 6
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;
}