Ejemplo n.º 1
0
/* Some initializations for characters, including initial skills
   If mode == 0, then act as though the character was entering the
   game for the first time.  Otherwise, act as though the character
   is being set to that level.
 */
void
do_start(struct creature *ch, int mode)
{
    void advance_level(struct creature *ch, int8_t keep_internal);
    int8_t new_player = 0;
    int i;
    struct obj_data *implant_save[NUM_WEARS];
    struct obj_data *tattoo_save[NUM_WEARS];

    // remove implant affects
    for (i = 0; i < NUM_WEARS; i++) {
        if (GET_IMPLANT(ch, i))
            implant_save[i] = raw_unequip_char(ch, i, EQUIP_IMPLANT);
        else
            implant_save[i] = NULL;
        if (GET_TATTOO(ch, i))
            tattoo_save[i] = raw_unequip_char(ch, i, EQUIP_TATTOO);
        else
            tattoo_save[i] = NULL;
    }

    if (GET_EXP(ch) == 0 && !IS_REMORT(ch) && !IS_VAMPIRE(ch))
        new_player = true;

    GET_LEVEL(ch) = 1;
    GET_EXP(ch) = 1;

    if (mode)
        roll_real_abils(ch);

    for (i = 1; i <= MAX_SKILLS; i++)
        SET_SKILL(ch, i, 0);

    if (IS_VAMPIRE(ch))
        GET_LIFE_POINTS(ch) = 1;
    else
        GET_LIFE_POINTS(ch) = 3 * (GET_WIS(ch) + GET_CON(ch)) / 40;

    ch->points.max_hit = 20;
    ch->points.max_mana = 100;
    ch->points.max_move = 82;

    if (IS_TABAXI(ch)) {
        SET_SKILL(ch, SKILL_CLAW, LEARNED(ch));
        SET_SKILL(ch, SKILL_BITE, LEARNED(ch));
    }
    if (IS_ELF(ch)) {
        SET_SKILL(ch, SKILL_ARCHERY, LEARNED(ch));
    }

    switch (GET_CLASS(ch)) {
    case CLASS_MAGIC_USER:
        SET_SKILL(ch, SKILL_PUNCH, 10);
        break;
    case CLASS_CLERIC:
        SET_SKILL(ch, SKILL_PUNCH, 10);
        break;
    case CLASS_THIEF:
        SET_SKILL(ch, SKILL_PUNCH, 15);
        SET_SKILL(ch, SKILL_SNEAK, 10);
        SET_SKILL(ch, SKILL_HIDE, 5);
        SET_SKILL(ch, SKILL_STEAL, 15);
        break;
    case CLASS_WARRIOR:
        SET_SKILL(ch, SKILL_PUNCH, 20);
        break;
    case CLASS_BARB:
        SET_SKILL(ch, SKILL_PUNCH, 15);
        break;
    case CLASS_PSIONIC:
        SET_SKILL(ch, SKILL_PUNCH, 10);
        break;
    case CLASS_PHYSIC:
        SET_SKILL(ch, SKILL_PUNCH, 10);
        break;
    case CLASS_CYBORG:
        SET_SKILL(ch, SKILL_PUNCH, 10);
        break;
    case CLASS_KNIGHT:
        SET_SKILL(ch, SKILL_PUNCH, 20);
        break;
    case CLASS_RANGER:
        SET_SKILL(ch, SKILL_PUNCH, 15);
        GET_MAX_MOVE(ch) += dice(4, 9);
        break;
    case CLASS_MONK:
        SET_SKILL(ch, SKILL_PUNCH, 20);
        break;
    case CLASS_MERCENARY:
        SET_SKILL(ch, SKILL_PUNCH, 20);
    case CLASS_BARD:
        SET_SKILL(ch, SKILL_PUNCH, 25);
        SET_SKILL(ch, SKILL_ARCHERY, 25);
        break;

    }

    if (new_player) {
        if (PAST_CLASS(GET_CLASS(ch))) {
            deposit_past_bank(ch->desc->account,
                8192 + number(256, 2048) + GET_INT(ch) + GET_WIS(ch));
            ch->points.gold =
                8192 + number(256, 2048) + GET_INT(ch) + GET_WIS(ch);
        } else if (FUTURE_CLASS(GET_CLASS(ch))) {
            deposit_future_bank(ch->desc->account,
                8192 + number(256, 2048) + GET_INT(ch) + GET_WIS(ch));
            ch->points.cash =
                8192 + number(256, 2048) + GET_INT(ch) + GET_WIS(ch);
        }

        // New players do not start with the gown at this point
        // This has been left in for reference for generic newbie starting gear for the future.
        // New players start with a hospital gown and items most dear to them
        /*
        struct obj_data *gown = read_object(33800);
        if (gown != NULL) {
            equip_char(ch, gown, WEAR_ABOUT, EQUIP_WORN);
        }
        */

        // Good clerics start with a holy symbol on neck
        if ((GET_CLASS(ch) == CLASS_CLERIC) && IS_GOOD(ch)) {
            struct obj_data *talisman = read_object(1280);
            if (talisman != NULL) {
                equip_char(ch, talisman, WEAR_NECK_1, EQUIP_WORN);
            }
        }

        // Evil clerics start with a holy symbol on hold
        if ((GET_CLASS(ch) == CLASS_CLERIC) && IS_EVIL(ch)) {
            struct obj_data *symbol = read_object(1260);
            if (symbol != NULL) {
                equip_char(ch, symbol, WEAR_HOLD, EQUIP_WORN);
            }
        }

        // Good knights start with a holy symbol on finger
        if ((GET_CLASS(ch) == CLASS_KNIGHT) && IS_GOOD(ch)) {
            struct obj_data *ring = read_object(1287);
            if (ring != NULL) {
                equip_char(ch, ring, WEAR_FINGER_L, EQUIP_WORN);
            }
        }

        // Evil knights start with a holy symbol on neck
        if ((GET_CLASS(ch) == CLASS_KNIGHT) && IS_EVIL(ch)) {
            struct obj_data *pendant = read_object(1270);
            if (pendant != NULL) {
                equip_char(ch, pendant, WEAR_NECK_1, EQUIP_WORN);
            }
        }

        // Bards start with a percussion instrument held, and stringed in inventory
        if (GET_CLASS(ch) == CLASS_BARD) {
            struct obj_data *lute = read_object(3218);
            if (lute != NULL) {
                obj_to_char(lute, ch);
            }
        }
   
        set_title(ch, "the complete newbie");
    }

    advance_level(ch, 0);

    GET_MAX_MOVE(ch) += GET_CON(ch);

    GET_HIT(ch) = GET_MAX_HIT(ch);
    GET_MANA(ch) = GET_MAX_MANA(ch);
    GET_MOVE(ch) = GET_MAX_MOVE(ch);

    GET_COND(ch, THIRST) = 24;
    GET_COND(ch, FULL) = 24;
    GET_COND(ch, DRUNK) = 0;

    if (new_player) {
        ch->player.time.played = 0;
        ch->player.time.logon = time(NULL);
    }

    for (i = 0; i < NUM_WEARS; i++) {
        if (implant_save[i])
            equip_char(ch, implant_save[i], i, EQUIP_IMPLANT);
        if (tattoo_save[i])
            equip_char(ch, tattoo_save[i], i, EQUIP_TATTOO);
    }
}
Ejemplo n.º 2
0
static void
load(void)
{
    union {
	struct exec ex;
	Elf32_Ehdr eh;
    } hdr;
    static Elf32_Phdr ep[2];
    static Elf32_Shdr es[2];
    caddr_t p;
    ufs_ino_t ino;
    uint32_t addr, x;
    int fmt, i, j;

    if (!(ino = lookup(kname))) {
	if (!ls) {
	    printf("%s: No %s on %u:%s(%up%u)\n", BOOTPROG,
		kname, dsk.drive & DRV_MASK, dev_nm[dsk.type], dsk.unit,
		dsk.part);
	}
	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, RB_BOOTINFO | (opts & RBX_MASK),
	   MAKEBOOTDEV(dev_maj[dsk.type], dsk.part + 1, dsk.unit, 0xff),
	   0, 0, 0, VTOP(&bootinfo));
}
Ejemplo n.º 3
0
/*
 * Attempt to load the file (file) as an ELF module.  It will be stored at
 * (dest), and a pointer to a module structure describing the loaded object
 * will be saved in (result).
 */
int
__elfN(obj_loadfile)(char *filename, u_int64_t dest,
    struct preloaded_file **result)
{
	struct preloaded_file *fp, *kfp;
	struct elf_file	ef;
	Elf_Ehdr *hdr;
	int err;
	ssize_t bytes_read;

	fp = NULL;
	bzero(&ef, sizeof(struct elf_file));

	/*
	 * Open the image, read and validate the ELF header
	 */
	if (filename == NULL)	/* can't handle nameless */
		return(EFTYPE);
	if ((ef.fd = open(filename, O_RDONLY)) == -1)
		return(errno);

	hdr = &ef.hdr;
	bytes_read = read(ef.fd, hdr, sizeof(*hdr));
	if (bytes_read != sizeof(*hdr)) {
		err = EFTYPE;	/* could be EIO, but may be small file */
		goto oerr;
	}

	/* Is it ELF? */
	if (!IS_ELF(*hdr)) {
		err = EFTYPE;
		goto oerr;
	}
	if (hdr->e_ident[EI_CLASS] != ELF_TARG_CLASS ||	/* Layout ? */
	    hdr->e_ident[EI_DATA] != ELF_TARG_DATA ||
	    hdr->e_ident[EI_VERSION] != EV_CURRENT ||	/* Version ? */
	    hdr->e_version != EV_CURRENT ||
	    hdr->e_machine != ELF_TARG_MACH ||		/* Machine ? */
	    hdr->e_type != ET_REL) {
		err = EFTYPE;
		goto oerr;
	}

	if (hdr->e_shnum * hdr->e_shentsize == 0 || hdr->e_shoff == 0 ||
	    hdr->e_shentsize != sizeof(Elf_Shdr)) {
		err = EFTYPE;
		goto oerr;
	}

	kfp = file_findfile(NULL, __elfN(obj_kerneltype));
	if (kfp == NULL) {
		printf("elf" __XSTRING(__ELF_WORD_SIZE)
		    "_obj_loadfile: can't load module before kernel\n");
		err = EPERM;
		goto oerr;
	}

	if (archsw.arch_loadaddr != NULL)
		dest = archsw.arch_loadaddr(LOAD_ELF, hdr, dest);
	else
		dest = roundup(dest, PAGE_SIZE);

	/*
	 * Ok, we think we should handle this.
	 */
	fp = file_alloc();
	if (fp == NULL) {
		printf("elf" __XSTRING(__ELF_WORD_SIZE)
		    "_obj_loadfile: cannot allocate module info\n");
		err = EPERM;
		goto out;
	}
	fp->f_name = strdup(filename);
	fp->f_type = strdup(__elfN(obj_moduletype));

	printf("%s ", filename);

	fp->f_size = __elfN(obj_loadimage)(fp, &ef, dest);
	if (fp->f_size == 0 || fp->f_addr == 0)
		goto ioerr;

	/* save exec header as metadata */
	file_addmetadata(fp, MODINFOMD_ELFHDR, sizeof(*hdr), hdr);

	/* Load OK, return module pointer */
	*result = (struct preloaded_file *)fp;
	err = 0;
	goto out;

ioerr:
	err = EIO;
oerr:
	file_discard(fp);
out:
	close(ef.fd);
	if (ef.e_shdr != NULL)
		free(ef.e_shdr);

	return(err);
}
Ejemplo n.º 4
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);
	close(fd);
	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);
}
Ejemplo n.º 5
0
static int
link_elf_obj_load_file(const char *filename, linker_file_t * result)
{
	struct nlookupdata nd;
	struct thread  *td = curthread;	/* XXX */
	struct proc    *p = td->td_proc;
	char           *pathname;
	struct vnode   *vp;
	Elf_Ehdr       *hdr;
	Elf_Shdr       *shdr;
	Elf_Sym        *es;
	int		nbytes, i, j;
	vm_offset_t	mapbase;
	size_t		mapsize;
	int		error = 0;
	int		resid;
	elf_file_t	ef;
	linker_file_t	lf;
	int		symtabindex;
	int		symstrindex;
	int		shstrindex;
	int		nsym;
	int		pb, rl, ra;
	int		alignmask;

	/* XXX Hack for firmware loading where p == NULL */
	if (p == NULL) {
		p = &proc0;
	}

	KKASSERT(p != NULL);
	if (p->p_ucred == NULL) {
		kprintf("link_elf_obj_load_file: cannot load '%s' from filesystem"
			" this early\n", filename);
		return ENOENT;
	}
	shdr = NULL;
	lf = NULL;
	mapsize = 0;
	hdr = 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.
	 */
	hdr = kmalloc(sizeof(*hdr), M_LINKER, M_WAITOK);
	error = vn_rdwr(UIO_READ, vp, (void *)hdr, sizeof(*hdr), 0,
			UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &resid);
	if (error)
		goto out;
	if (resid != 0) {
		error = ENOEXEC;
		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_obj_error(filename, "Unsupported file layout");
		error = ENOEXEC;
		goto out;
	}
	if (hdr->e_ident[EI_VERSION] != EV_CURRENT
	    || hdr->e_version != EV_CURRENT) {
		link_elf_obj_error(filename, "Unsupported file version");
		error = ENOEXEC;
		goto out;
	}
	if (hdr->e_type != ET_REL) {
		error = ENOSYS;
		goto out;
	}
	if (hdr->e_machine != ELF_TARG_MACH) {
		link_elf_obj_error(filename, "Unsupported machine");
		error = ENOEXEC;
		goto out;
	}

	ef = kmalloc(sizeof(struct elf_file), M_LINKER, M_WAITOK | M_ZERO);
	lf = linker_make_file(filename, ef, &link_elf_obj_file_ops);
	if (lf == NULL) {
		kfree(ef, M_LINKER);
		error = ENOMEM;
		goto out;
	}
	ef->nprogtab = 0;
	ef->e_shdr = 0;
	ef->nreltab = 0;
	ef->nrelatab = 0;

	/* Allocate and read in the section header */
	nbytes = hdr->e_shnum * hdr->e_shentsize;
	if (nbytes == 0 || hdr->e_shoff == 0 ||
	    hdr->e_shentsize != sizeof(Elf_Shdr)) {
		error = ENOEXEC;
		goto out;
	}
	shdr = kmalloc(nbytes, M_LINKER, M_WAITOK);
	ef->e_shdr = shdr;
	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;
	if (resid) {
		error = ENOEXEC;
		goto out;
	}
	/* Scan the section header for information and table sizing. */
	nsym = 0;
	symtabindex = -1;
	symstrindex = -1;
	for (i = 0; i < hdr->e_shnum; i++) {
		switch (shdr[i].sh_type) {
		case SHT_PROGBITS:
		case SHT_NOBITS:
			ef->nprogtab++;
			break;
		case SHT_SYMTAB:
			nsym++;
			symtabindex = i;
			symstrindex = shdr[i].sh_link;
			break;
		case SHT_REL:
			ef->nreltab++;
			break;
		case SHT_RELA:
			ef->nrelatab++;
			break;
		case SHT_STRTAB:
			break;
		}
	}
	if (ef->nprogtab == 0) {
		link_elf_obj_error(filename, "file has no contents");
		error = ENOEXEC;
		goto out;
	}
	if (nsym != 1) {
		/* Only allow one symbol table for now */
		link_elf_obj_error(filename, "file has no valid symbol table");
		error = ENOEXEC;
		goto out;
	}
	if (symstrindex < 0 || symstrindex > hdr->e_shnum ||
	    shdr[symstrindex].sh_type != SHT_STRTAB) {
		link_elf_obj_error(filename, "file has invalid symbol strings");
		error = ENOEXEC;
		goto out;
	}
	/* Allocate space for tracking the load chunks */
	if (ef->nprogtab != 0)
		ef->progtab = kmalloc(ef->nprogtab * sizeof(*ef->progtab),
				      M_LINKER, M_WAITOK | M_ZERO);
	if (ef->nreltab != 0)
		ef->reltab = kmalloc(ef->nreltab * sizeof(*ef->reltab),
				     M_LINKER, M_WAITOK | M_ZERO);
	if (ef->nrelatab != 0)
		ef->relatab = kmalloc(ef->nrelatab * sizeof(*ef->relatab),
				      M_LINKER, M_WAITOK | M_ZERO);
	if ((ef->nprogtab != 0 && ef->progtab == NULL) ||
	    (ef->nreltab != 0 && ef->reltab == NULL) ||
	    (ef->nrelatab != 0 && ef->relatab == NULL)) {
		error = ENOMEM;
		goto out;
	}
	if (symtabindex == -1)
		panic("lost symbol table index");
	/* Allocate space for and load the symbol table */
	ef->ddbsymcnt = shdr[symtabindex].sh_size / sizeof(Elf_Sym);
	ef->ddbsymtab = kmalloc(shdr[symtabindex].sh_size, M_LINKER, M_WAITOK);
	if (ef->ddbsymtab == NULL) {
		error = ENOMEM;
		goto out;
	}
	error = vn_rdwr(UIO_READ, vp, (void *)ef->ddbsymtab,
			shdr[symtabindex].sh_size, shdr[symtabindex].sh_offset,
			UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &resid);
	if (error)
		goto out;
	if (resid != 0) {
		error = EINVAL;
		goto out;
	}
	if (symstrindex == -1)
		panic("lost symbol string index");
	/* Allocate space for and load the symbol strings */
	ef->ddbstrcnt = shdr[symstrindex].sh_size;
	ef->ddbstrtab = kmalloc(shdr[symstrindex].sh_size, M_LINKER, M_WAITOK);
	if (ef->ddbstrtab == NULL) {
		error = ENOMEM;
		goto out;
	}
	error = vn_rdwr(UIO_READ, vp, ef->ddbstrtab,
			shdr[symstrindex].sh_size, shdr[symstrindex].sh_offset,
			UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &resid);
	if (error)
		goto out;
	if (resid != 0) {
		error = EINVAL;
		goto out;
	}
	/* Do we have a string table for the section names?  */
	shstrindex = -1;
	if (hdr->e_shstrndx != 0 &&
	    shdr[hdr->e_shstrndx].sh_type == SHT_STRTAB) {
		shstrindex = hdr->e_shstrndx;
		ef->shstrcnt = shdr[shstrindex].sh_size;
		ef->shstrtab = kmalloc(shdr[shstrindex].sh_size, M_LINKER,
				       M_WAITOK);
		if (ef->shstrtab == NULL) {
			error = ENOMEM;
			goto out;
		}
		error = vn_rdwr(UIO_READ, vp, ef->shstrtab,
				shdr[shstrindex].sh_size, shdr[shstrindex].sh_offset,
				UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &resid);
		if (error)
			goto out;
		if (resid != 0) {
			error = EINVAL;
			goto out;
		}
	}
	/* Size up code/data(progbits) and bss(nobits). */
	alignmask = 0;
	for (i = 0; i < hdr->e_shnum; i++) {
		switch (shdr[i].sh_type) {
		case SHT_PROGBITS:
		case SHT_NOBITS:
			alignmask = shdr[i].sh_addralign - 1;
			mapsize += alignmask;
			mapsize &= ~alignmask;
			mapsize += shdr[i].sh_size;
			break;
		}
	}

	/*
	 * We know how much space we need for the text/data/bss/etc. This
	 * stuff needs to be in a single chunk so that profiling etc can get
	 * the bounds and gdb can associate offsets with modules
	 */
	ef->object = vm_object_allocate(OBJT_DEFAULT,
					round_page(mapsize) >> PAGE_SHIFT);
	if (ef->object == NULL) {
		error = ENOMEM;
		goto out;
	}
	vm_object_hold(ef->object);
	vm_object_reference_locked(ef->object);
	ef->address = (caddr_t) vm_map_min(&kernel_map);
	ef->bytes = 0;

	/*
	 * In order to satisfy x86_64's architectural requirements on the
	 * location of code and data in the kernel's address space, request a
	 * mapping that is above the kernel.
	 *
	 * vkernel64's text+data is outside the managed VM space entirely.
	 */
#if defined(__amd64__) && defined(_KERNEL_VIRTUAL)
	error = vkernel_module_memory_alloc(&mapbase, round_page(mapsize));
#else
	mapbase = KERNBASE;
	error = vm_map_find(&kernel_map, ef->object, 0, &mapbase,
			    round_page(mapsize), PAGE_SIZE,
			    TRUE, VM_MAPTYPE_NORMAL,
			    VM_PROT_ALL, VM_PROT_ALL, FALSE);
	vm_object_drop(ef->object);
	if (error) {
		vm_object_deallocate(ef->object);
		ef->object = NULL;
		goto out;
	}
	/* Wire the pages */
	error = vm_map_wire(&kernel_map, mapbase,
			    mapbase + round_page(mapsize), 0);
#endif
	if (error != KERN_SUCCESS) {
		error = ENOMEM;
		goto out;
	}
	/* Inform the kld system about the situation */
	lf->address = ef->address = (caddr_t) mapbase;
	lf->size = round_page(mapsize);
	ef->bytes = mapsize;

	/*
	 * Now load code/data(progbits), zero bss(nobits), allocate space for
	 * and load relocs
	 */
	pb = 0;
	rl = 0;
	ra = 0;
	alignmask = 0;
	for (i = 0; i < hdr->e_shnum; i++) {
		switch (shdr[i].sh_type) {
		case SHT_PROGBITS:
		case SHT_NOBITS:
			alignmask = shdr[i].sh_addralign - 1;
			mapbase += alignmask;
			mapbase &= ~alignmask;
			if (ef->shstrtab && shdr[i].sh_name != 0)
				ef->progtab[pb].name =
					ef->shstrtab + shdr[i].sh_name;
			else if (shdr[i].sh_type == SHT_PROGBITS)
				ef->progtab[pb].name = "<<PROGBITS>>";
			else
				ef->progtab[pb].name = "<<NOBITS>>";
#if 0
			if (ef->progtab[pb].name != NULL &&
			    !strcmp(ef->progtab[pb].name, "set_pcpu"))
				ef->progtab[pb].addr =
					dpcpu_alloc(shdr[i].sh_size);
#ifdef VIMAGE
			else if (ef->progtab[pb].name != NULL &&
				 !strcmp(ef->progtab[pb].name, VNET_SETNAME))
				ef->progtab[pb].addr =
					vnet_data_alloc(shdr[i].sh_size);
#endif
			else
#endif
				ef->progtab[pb].addr =
					(void *)(uintptr_t) mapbase;
			if (ef->progtab[pb].addr == NULL) {
				error = ENOSPC;
				goto out;
			}
			ef->progtab[pb].size = shdr[i].sh_size;
			ef->progtab[pb].sec = i;
			if (shdr[i].sh_type == SHT_PROGBITS) {
				error = vn_rdwr(UIO_READ, vp,
						ef->progtab[pb].addr,
						shdr[i].sh_size, shdr[i].sh_offset,
						UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred,
						&resid);
				if (error)
					goto out;
				if (resid != 0) {
					error = EINVAL;
					goto out;
				}
#if 0
				/* Initialize the per-cpu or vnet area. */
				if (ef->progtab[pb].addr != (void *)mapbase &&
				    !strcmp(ef->progtab[pb].name, "set_pcpu"))
					dpcpu_copy(ef->progtab[pb].addr,
						   shdr[i].sh_size);
#ifdef VIMAGE
				else if (ef->progtab[pb].addr !=
					 (void *)mapbase &&
					 !strcmp(ef->progtab[pb].name, VNET_SETNAME))
					vnet_data_copy(ef->progtab[pb].addr,
						       shdr[i].sh_size);
#endif
#endif
			} else
				bzero(ef->progtab[pb].addr, shdr[i].sh_size);

			/* Update all symbol values with the offset. */
			for (j = 0; j < ef->ddbsymcnt; j++) {
				es = &ef->ddbsymtab[j];
				if (es->st_shndx != i)
					continue;
				es->st_value += (Elf_Addr) ef->progtab[pb].addr;
			}
			mapbase += shdr[i].sh_size;
			pb++;
			break;
		case SHT_REL:
			ef->reltab[rl].rel = kmalloc(shdr[i].sh_size, M_LINKER, M_WAITOK);
			ef->reltab[rl].nrel = shdr[i].sh_size / sizeof(Elf_Rel);
			ef->reltab[rl].sec = shdr[i].sh_info;
			error = vn_rdwr(UIO_READ, vp,
					(void *)ef->reltab[rl].rel,
					shdr[i].sh_size, shdr[i].sh_offset,
					UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &resid);
			if (error)
				goto out;
			if (resid != 0) {
				error = EINVAL;
				goto out;
			}
			rl++;
			break;
		case SHT_RELA:
			ef->relatab[ra].rela = kmalloc(shdr[i].sh_size, M_LINKER, M_WAITOK);
			ef->relatab[ra].nrela = shdr[i].sh_size / sizeof(Elf_Rela);
			ef->relatab[ra].sec = shdr[i].sh_info;
			error = vn_rdwr(UIO_READ, vp,
					(void *)ef->relatab[ra].rela,
					shdr[i].sh_size, shdr[i].sh_offset,
					UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &resid);
			if (error)
				goto out;
			if (resid != 0) {
				error = EINVAL;
				goto out;
			}
			ra++;
			break;
		}
	}
	if (pb != ef->nprogtab)
		panic("lost progbits");
	if (rl != ef->nreltab)
		panic("lost reltab");
	if (ra != ef->nrelatab)
		panic("lost relatab");
	if (mapbase != (vm_offset_t) ef->address + mapsize)
		panic("mapbase 0x%lx != address %p + mapsize 0x%lx (0x%lx)\n",
		      mapbase, ef->address, mapsize,
		      (vm_offset_t) ef->address + mapsize);

	/* Local intra-module relocations */
	link_elf_obj_reloc_local(lf);

	/* Pull in dependencies */
	error = linker_load_dependencies(lf);
	if (error)
		goto out;

	/* External relocations */
	error = relocate_file(lf);
	if (error)
		goto out;

	*result = lf;

out:
	if (error && lf)
		linker_file_unload(lf /*, LINKER_UNLOAD_FORCE */);
	if (hdr)
		kfree(hdr, M_LINKER);
	vn_unlock(vp);
	vn_close(vp, FREAD);

	return error;
}
Ejemplo n.º 6
0
/*
 * Load the prototype boot sector (biosboot) into memory.
 */
static char *
loadproto(char *fname, long *size)
{
	int	fd;
	size_t	tdsize;		/* text+data size */
	char	*bp;
	Elf_Ehdr eh;
	Elf_Word phsize;
	Elf_Phdr *ph;

	if ((fd = open(fname, O_RDONLY)) < 0)
		err(1, "%s", fname);

	if (read(fd, &eh, sizeof(eh)) != sizeof(eh))
		errx(1, "%s: read failed", fname);

	if (!IS_ELF(eh))
		errx(1, "%s: bad magic: 0x%02x%02x%02x%02x", fname,
		    eh.e_ident[EI_MAG0], eh.e_ident[EI_MAG1],
		    eh.e_ident[EI_MAG2], eh.e_ident[EI_MAG3]);

	/*
	 * We have to include the exec header in the beginning of
	 * the buffer, and leave extra space at the end in case
	 * the actual write to disk wants to skip the header.
	 */

	/* Program load header. */
	if (eh.e_phnum != 1)
		errx(1, "%s: %u ELF load sections (only support 1)",
		    fname, eh.e_phnum);

	phsize = eh.e_phnum * sizeof(Elf_Phdr);
	ph = malloc(phsize);
	if (ph == NULL)
		err(1, NULL);

	lseek(fd, eh.e_phoff, SEEK_SET);

	if (read(fd, ph, phsize) != phsize)
		errx(1, "%s: can't read header", fname);

	tdsize = ph->p_filesz;

	/*
	 * Allocate extra space here because the caller may copy
	 * the boot block starting at the end of the exec header.
	 * This prevents reading beyond the end of the buffer.
	 */
	if ((bp = calloc(tdsize, 1)) == NULL)
		err(1, NULL);

	/* Read the rest of the file. */
	lseek(fd, ph->p_offset, SEEK_SET);
	if (read(fd, bp, tdsize) != (ssize_t)tdsize)
		errx(1, "%s: read failed", fname);

	*size = tdsize;	/* not aligned to DEV_BSIZE */

	close(fd);
	return bp;
}
core_obj_t*	core_new(char* path)
{
  struct stat	sb;
  int		fd;
  void*		data;
  core_obj_t*	ret;
  elfobj_t*	luse;
  int		i = 0;
  char*		ptr;

  /*
  ** Map the core.
  */
  if ((fd = open(path, O_RDONLY)) == -1)
    {
      return (NULL);
    }
  if (fstat(fd, &sb) == -1)
    {
      close(fd);
      return (NULL);
    }
  data = mmap(0, sb.st_size, PROT_READ, MAP_SHARED, fd, 0);
  close(fd);
  if (data == MAP_FAILED)
    return (NULL);
  /*
  ** Check if the core is really a elf.
  */
  if (!IS_ELF(*((Elf_Ehdr*)data)))
    {
      errno = EFTRACE;
      ftrace_errstr = "File is not an elf file.";
      munmap(data, sb.st_size);
      return (NULL);
    }
  /*
  ** Fill the return
  */
  ret = malloc(sizeof(core_obj_t));
  if (ret == NULL)
    {
      munmap(data, sb.st_size);
      return (NULL);
    }
  ret->path = strdup(path);
  ret->map = data;
  ret->fd = -1;
  ret->size = sb.st_size;
  ret->luse = NULL;
  /*
  ** Fill luse.
  */
  luse = malloc(sizeof(elfobj_t));
  if (luse == NULL)
    return (ret);
  luse->base = 0;
  luse->header = data;
  luse->program_headers = NULL;
  luse->section_headers = NULL;
  luse->section_str = NULL;
  /*
  ** Program headers.
  */
  luse->program_headers = malloc(sizeof(Elf_Phdr *) * (luse->header->e_phnum + 1));
  if (luse->program_headers == NULL)
    goto luse_fill_failed;
  for (ptr = (char*) luse->header + luse->header->e_phoff, i = 0; i < luse->header->e_phnum; i++)
    {
      luse->program_headers[i] = (Elf_Phdr *) ptr;
      ptr += luse->header->e_phentsize;
    }
  luse->program_headers[i] = NULL;
  /*
  ** Section headers.
  */
  luse->section_headers = malloc(sizeof(Elf_Shdr *) * (luse->header->e_shnum + 1));
  if (luse->section_headers == NULL)
    goto luse_fill_failed;
  for (ptr = (char*) luse->header + luse->header->e_shoff, i = 0; i < luse->header->e_shnum; i++)
    {
      luse->section_headers[i] = (Elf_Shdr *) ptr;
      ptr += luse->header->e_shentsize;
    }
  luse->section_headers[i] = NULL;
  /*
  ** Section strng.
  */
  if (luse->header->e_shstrndx != SHN_UNDEF)
    luse->section_str = data + luse->section_headers[luse->header->e_shstrndx]->sh_offset;
  else
    luse->section_str = NULL;
  ret->luse = luse;
  return (ret);
 luse_fill_failed:
  core_del(ret);
  if (luse->program_headers)
    free(luse->program_headers);
  if (luse->section_headers)
    free(luse->section_headers);
  free(luse);
  return (NULL);
}
Ejemplo n.º 8
0
Archivo: exec.c Proyecto: jmgc/noah
int
load_elf_interp(const char *path, ulong load_addr)
{
  char *data;
  Elf64_Ehdr *h;
  uint64_t map_top = 0;
  int fd;
  struct stat st;

  if ((fd = vkern_open(path, LINUX_O_RDONLY, 0)) < 0) {
    fprintf(stderr, "load_elf_interp, could not open file: %s\n", path);
    return -1;
  }

  fstat(fd, &st);

  data = mmap(0, st.st_size, PROT_READ | PROT_EXEC, MAP_PRIVATE, fd, 0);

  vkern_close(fd);

  h = (Elf64_Ehdr *)data;

  assert(IS_ELF(*h));

  if (! (h->e_type == ET_EXEC || h->e_type == ET_DYN)) {
    return -LINUX_ENOEXEC;
  }
  if (h->e_machine != EM_X86_64) {
    return -LINUX_ENOEXEC;
  }

  Elf64_Phdr *p = (Elf64_Phdr *)(data + h->e_phoff);

  for (int i = 0; i < h->e_phnum; i++) {
    if (p[i].p_type != PT_LOAD) {
      continue;
    }

    ulong p_vaddr = p[i].p_vaddr + load_addr;

    ulong mask = PAGE_SIZEOF(PAGE_4KB) - 1;
    ulong vaddr = p_vaddr & ~mask;
    ulong offset = p_vaddr & mask;
    ulong size = roundup(p[i].p_memsz + offset, PAGE_SIZEOF(PAGE_4KB));

    int prot = 0;
    if (p[i].p_flags & PF_X) prot |= LINUX_PROT_EXEC;
    if (p[i].p_flags & PF_W) prot |= LINUX_PROT_WRITE;
    if (p[i].p_flags & PF_R) prot |= LINUX_PROT_READ;

    assert(vaddr != 0);
    do_mmap(vaddr, size, PROT_READ | PROT_WRITE, prot, LINUX_MAP_PRIVATE | LINUX_MAP_FIXED | LINUX_MAP_ANONYMOUS, -1, 0);

    copy_to_user(vaddr + offset, data + p[i].p_offset, p[i].p_filesz);

    map_top = MAX(map_top, roundup(vaddr + size, PAGE_SIZEOF(PAGE_4KB)));
  }

  vmm_write_vmcs(VMCS_GUEST_RIP, load_addr + h->e_entry);
  proc.mm->start_brk = map_top;

  munmap(data, st.st_size);

  return 0;
}
Ejemplo n.º 9
0
int
main(int argc, char **argv)
{
	struct exec exec;
	int ch, cnt, efd, fd, sflag;
	char *binfile, *corefile;
	char fname[MAXPATHLEN + 1];

	sflag = 0;
	corefile = NULL;
        while ((ch = getopt(argc, argv, "c:s")) != -1) {
                switch (ch) {
                case 'c':
			corefile = optarg;
                        break;
		case 's':
			sflag = 1;
			break;
		default:
			usage();
			break;
		}
	}
	argv += optind;
	argc -= optind;

	/* XXX we should check that the pid argument is really a number */
	switch (argc) {
	case 1:
		pid = atoi(argv[0]);
		asprintf(&binfile, "/proc/%d/file", pid);
		if (binfile == NULL)
			errx(1, "allocation failure");
		break;
	case 2:
		pid = atoi(argv[1]);
		binfile = argv[0];
		break;
	default:
		usage();
	}

	efd = open(binfile, O_RDONLY, 0);
	if (efd < 0)
		err(1, "%s", binfile);

	cnt = read(efd, &exec, sizeof(exec));
	if (cnt != sizeof(exec))
		errx(1, "%s exec header: %s",
		    binfile, cnt > 0 ? strerror(EIO) : strerror(errno));
	if (IS_ELF(*(Elf_Ehdr *)&exec)) {
		close(efd);
	} else
		errx(1, "Invalid executable file");

	if (corefile == NULL) {
		(void)snprintf(fname, sizeof(fname), "core.%d", pid);
		corefile = fname;
	}
	fd = open(corefile, O_RDWR|O_CREAT|O_TRUNC, DEFFILEMODE);
	if (fd < 0)
		err(1, "%s", corefile);

	if (sflag) {
		signal(SIGHUP, killed);
		signal(SIGINT, killed);
		signal(SIGTERM, killed);
		if (kill(pid, SIGSTOP) == -1)
			err(1, "%d: stop signal", pid);
		atexit(restart_target);
	}

	elf_coredump(fd, pid);

	(void)close(fd);
	exit(0);
}
Ejemplo n.º 10
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;
    Elf_Phdr *phphdr;
    caddr_t mapbase;
    size_t mapsize;
    Elf_Off base_offset;
    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;
    phphdr = 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:
	    phphdr = 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_offset = trunc_page(segs[0]->p_offset);
    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);
#ifdef SPARSE_MAPPING
    ef->object = vm_object_allocate(OBJT_DEFAULT, mapsize >> PAGE_SHIFT);
    if (ef->object == NULL) {
	kfree(ef, M_LINKER);
	error = ENOMEM;
	goto out;
    }
    vm_object_hold(ef->object);
    vm_object_reference_locked(ef->object);
    ef->address = (caddr_t)vm_map_min(&kernel_map);
    error = vm_map_find(&kernel_map, ef->object, 0,
			(vm_offset_t *)&ef->address,
			mapsize, PAGE_SIZE,
			1, VM_MAPTYPE_NORMAL,
			VM_PROT_ALL, VM_PROT_ALL,
			0);
    vm_object_drop(ef->object);
    if (error) {
	vm_object_deallocate(ef->object);
	kfree(ef, M_LINKER);
	goto out;
    }
#else
    ef->address = kmalloc(mapsize, M_LINKER, M_WAITOK);
#endif
    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) {
#ifdef SPARSE_MAPPING
	    vm_map_remove(&kernel_map, (vm_offset_t) ef->address,
			  (vm_offset_t) ef->address
			  + (ef->object->size << PAGE_SHIFT));
	    vm_object_deallocate(ef->object);
#else
	    kfree(ef->address, M_LINKER);
#endif
	    kfree(ef, M_LINKER);
	    goto out;
	}
	bzero(segbase + segs[i]->p_filesz,
	      segs[i]->p_memsz - segs[i]->p_filesz);

#ifdef SPARSE_MAPPING
	/*
	 * Wire down the pages
	 */
	vm_map_wire(&kernel_map,
		    (vm_offset_t) segbase,
		    (vm_offset_t) segbase + segs[i]->p_memsz,
		    0);
#endif
    }

    ef->dynamic = (const Elf_Dyn *) (mapbase + phdyn->p_vaddr - base_vaddr);

    lf = linker_make_file(filename, ef, &link_elf_file_ops);
    if (lf == NULL) {
#ifdef SPARSE_MAPPING
	vm_map_remove(&kernel_map, (vm_offset_t) ef->address,
		      (vm_offset_t) ef->address
		      + (ef->object->size << PAGE_SHIFT));
	vm_object_deallocate(ef->object);
#else
	kfree(ef->address, M_LINKER);
#endif
	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);

    return error;
}
Ejemplo n.º 11
0
static int
is_executable(const char *fname, int fd, int *is_shlib, int *type)
{
	union {
		struct exec aout;
#if __ELF_WORD_SIZE > 32 && defined(ELF32_SUPPORTED)
		Elf32_Ehdr elf32;
#endif
		Elf_Ehdr elf;
	} hdr;
	int n;

	*is_shlib = 0;
	*type = TYPE_UNKNOWN;

	if ((n = read(fd, &hdr, sizeof(hdr))) == -1) {
		warn("%s: can't read program header", fname);
		return (0);
	}

	if ((size_t)n >= sizeof(hdr.aout) && !N_BADMAG(hdr.aout)) {
		/* a.out file */
		if ((N_GETFLAG(hdr.aout) & EX_DPMASK) != EX_DYNAMIC
#if 1 /* Compatibility */
		    || hdr.aout.a_entry < __LDPGSZ
#endif
			) {
			warnx("%s: not a dynamic executable", fname);
			return (0);
		}
		*type = TYPE_AOUT;
		return (1);
	}

#if __ELF_WORD_SIZE > 32 && defined(ELF32_SUPPORTED)
	if ((size_t)n >= sizeof(hdr.elf32) && IS_ELF(hdr.elf32) &&
	    hdr.elf32.e_ident[EI_CLASS] == ELFCLASS32) {
		/* Handle 32 bit ELF objects */
		Elf32_Phdr phdr;
		int dynamic, i;

		dynamic = 0;
		*type = TYPE_ELF32;

		if (lseek(fd, hdr.elf32.e_phoff, SEEK_SET) == -1) {
			warnx("%s: header too short", fname);
			return (0);
		}
		for (i = 0; i < hdr.elf32.e_phnum; i++) {
			if (read(fd, &phdr, hdr.elf32.e_phentsize) !=
			    sizeof(phdr)) {
				warnx("%s: can't read program header", fname);
				return (0);
			}
			if (phdr.p_type == PT_DYNAMIC) {
				dynamic = 1;
				break;
			}
		}

		if (!dynamic) {
			warnx("%s: not a dynamic ELF executable", fname);
			return (0);
		}
		if (hdr.elf32.e_type == ET_DYN) {
			if (hdr.elf32.e_ident[EI_OSABI] == ELFOSABI_FREEBSD) {
				*is_shlib = 1;
				return (1);
			}
			warnx("%s: not a FreeBSD ELF shared object", fname);
			return (0);
		}

		return (1);
	}
#endif

	if ((size_t)n >= sizeof(hdr.elf) && IS_ELF(hdr.elf) &&
	    hdr.elf.e_ident[EI_CLASS] == ELF_TARG_CLASS) {
		/* Handle default ELF objects on this architecture */
		Elf_Phdr phdr;
		int dynamic, i;

		dynamic = 0;
		*type = TYPE_ELF;

		if (lseek(fd, hdr.elf.e_phoff, SEEK_SET) == -1) {
			warnx("%s: header too short", fname);
			return (0);
		}
		for (i = 0; i < hdr.elf.e_phnum; i++) {
			if (read(fd, &phdr, hdr.elf.e_phentsize)
			   != sizeof(phdr)) {
				warnx("%s: can't read program header", fname);
				return (0);
			}
			if (phdr.p_type == PT_DYNAMIC) {
				dynamic = 1;
				break;
			}
		}

		if (!dynamic) {
			warnx("%s: not a dynamic ELF executable", fname);
			return (0);
		}
		if (hdr.elf.e_type == ET_DYN) {
			if (hdr.elf.e_ident[EI_OSABI] == ELFOSABI_FREEBSD) {
				*is_shlib = 1;
				return (1);
			}
			warnx("%s: not a FreeBSD ELF shared object", fname);
			return (0);
		}

		return (1);
	}

	warnx("%s: not a dynamic executable", fname);
	return (0);
}
Ejemplo n.º 12
0
/**
 * \brief Load ELF32 binary image into memory
 *
 * This function loads an ELF32 binary image, based at 'base' and of size
 * 'size' into the memory provided by 'allocate'
 *
 * \param em_machine    ELF machine type.
 * \param allocate      Memory allocation function.
 * \param state         Pointer to state for allocation function.
 * \param base          Base address of ELF32 binary image in memory.
 * \param size          Size of ELF32 binary image in bytes.
 * \param retentry      Used to return entry point address
 * \param ret_tlsbase   Used to return TLS block base address
 * \param ret_tlsinitlen Used to return length of initialised TLS data block
 * \param ret_tlstotallen Used to return total length of TLS data
 */
errval_t elf32_load(uint16_t em_machine, elf_allocator_fn allocate_func,
                    void *state, lvaddr_t base, size_t size,
                    genvaddr_t *retentry,
                    genvaddr_t *ret_tlsbase, size_t *ret_tlsinitlen,
                    size_t *ret_tlstotallen)
{
    struct Elf32_Ehdr *head = (struct Elf32_Ehdr *)base;
    errval_t err;
    int i;

    // Check for valid file size
    if (size < sizeof(struct Elf32_Ehdr)) {
        return ELF_ERR_FILESZ;
    }

    // Stage 1: Check for compatible ELF32 header: check endianess
    if(is_big_endian() && head->e_ident[EI_DATA] != ELFDATA2MSB){
        return ELF_ERR_HEADER;
    } else if(!is_big_endian() && head->e_ident[EI_DATA] != ELFDATA2LSB){
        return ELF_ERR_HEADER;
    }

    // Stage 2: Check for compatible ELF32 header
    if (!IS_ELF(*head)
        || head->e_ident[EI_CLASS] != ELFCLASS32
//        || head->e_ident[EI_DATA] != ELFDATA2MSB   //Enhanced with a function to check machine endianess
        || head->e_ident[EI_VERSION] != EV_CURRENT
        || head->e_ident[EI_OSABI] != ELFOSABI_SYSV
        || head->e_ident[EI_ABIVERSION] != 0
        || (head->e_type != ET_EXEC && head->e_type != ET_DYN)
        || head->e_machine != em_machine
        || head->e_version != EV_CURRENT) {
        return ELF_ERR_HEADER;
    }

    // More sanity checks
    if (head->e_phoff + head->e_phentsize * head->e_phnum > size
        || head->e_phentsize != sizeof(struct Elf32_Phdr)) {
        return ELF_ERR_PROGHDR;
    }

    struct Elf32_Shdr *shead =
        (struct Elf32_Shdr *)(base + (uintptr_t)head->e_shoff);
    struct Elf32_Shdr *rela =
        elf32_find_section_header_type(shead, head->e_shnum, SHT_REL);
    struct Elf32_Shdr *symtab =
        elf32_find_section_header_type(shead, head->e_shnum, SHT_SYMTAB);

    size_t rela_size = rela ? rela->sh_size : 0, new_rela_size = 0;
    struct Elf32_Shdr *new_rela = NULL;

    // Find dynamic program header, if any
    struct Elf32_Phdr *phead =
        (struct Elf32_Phdr *)(base + (uintptr_t)head->e_phoff);
    for (i = 0; i < head->e_phnum; i++) {
        struct Elf32_Phdr *p = &phead[i];

        if (p->p_type == PT_DYNAMIC) {
            struct Elf32_Dyn *dynamic = (void *)(base + (uintptr_t)p->p_offset);
            int n_dynamic = p->p_filesz / sizeof(struct Elf32_Dyn);
            for (int j = 0; j < n_dynamic; j++) {
                switch (dynamic[j].d_tag) {
                case DT_RELA:
                    // virtual address of relocations, look for matching section
                    new_rela =
                        elf32_find_section_header_vaddr(shead, head->e_shnum,
                                                        dynamic[j].d_un.d_val);
                    break;

                case DT_RELASZ:
                    // store size of relocations, as they may cover more than
                    // one section
                    new_rela_size = dynamic[j].d_un.d_val;
                    break;

                case DT_SYMTAB:
                    // virtual address of symtab, look for matching section
                    symtab =
                        elf32_find_section_header_vaddr(shead, head->e_shnum,
                                                        dynamic[j].d_un.d_val);
                    break;

                case DT_SYMENT:
                    assert(dynamic[j].d_un.d_val == sizeof(struct Elf32_Sym));
                    break;
                }
            }

            if (new_rela != NULL) {
                assert(new_rela_size != 0);
                rela = new_rela;
                rela_size = new_rela_size;
            }
            break;
        }
    }

    genvaddr_t tls_base = 0;
    size_t tls_init_len = 0, tls_total_len = 0;

    // Process program headers to load file
    for (i = 0; i < head->e_phnum; i++) {
        struct Elf32_Phdr *p = &phead[i];

        if (p->p_type == PT_LOAD) {
            // Map segment in user-space memory
            void *dest = NULL;
            err = allocate_func(state, p->p_vaddr, p->p_memsz, p->p_flags, &dest);
            if (err_is_fail(err)) {
                return err_push(err, ELF_ERR_ALLOCATE);
            }
            assert(dest != NULL);

            // Copy file segment into memory
            memcpy(dest, (void *)(base + (uintptr_t)p->p_offset), p->p_filesz);

            // Initialize rest of memory segment (ie. BSS) with all zeroes
            memset((char *)dest + p->p_filesz, 0, p->p_memsz - p->p_filesz);

            // Apply relocations
            if (rela != NULL && symtab != NULL) {
                elf32_relocate(p->p_vaddr, p->p_vaddr,
                               (struct Elf32_Rel *)
                               (base + (uintptr_t)rela->sh_offset),
                               rela_size,
                               (struct Elf32_Sym *)
                               (base + (uintptr_t)symtab->sh_offset),
                               symtab->sh_size, p->p_vaddr, dest);
            }
        } else if (p->p_type == PT_TLS) {
            assert(p->p_vaddr != 0);
            assert(tls_base == 0); // if not we have multiple TLS sections!
            tls_base = p->p_vaddr;
            tls_init_len = p->p_filesz;
            tls_total_len = p->p_memsz;
        }
    }

    if (retentry != NULL) {
        *retentry = head->e_entry;
    }

    if (ret_tlsbase != NULL) {
        *ret_tlsbase = tls_base;
    }

    if (ret_tlsinitlen != NULL) {
        *ret_tlsinitlen = tls_init_len;
    }

    if (ret_tlstotallen != NULL) {
        *ret_tlstotallen = tls_total_len;
    }

    return SYS_ERR_OK;
}
Ejemplo n.º 13
0
uint32_t
elf32_count_symbol_by_name(genvaddr_t elf_base, size_t elf_bytes,
                          const char *name, uint8_t contains, uint8_t type,
                          size_t *ret_bytes)
{
    struct Elf32_Sym *sym = NULL;
    struct Elf32_Shdr *shead;
    struct Elf32_Shdr *symtab;
    const char *symname;

    lvaddr_t elfbase = (lvaddr_t)elf_base;
    struct Elf32_Ehdr *head = (struct Elf32_Ehdr *)elfbase;

    // just a sanity check
    if (!IS_ELF(*head) || head->e_ident[EI_CLASS] != ELFCLASS64) {
        return 0;
    }

    uint32_t count = 0;
    size_t bytes = 0;

    shead = (struct Elf32_Shdr *)(elfbase + (uintptr_t)head->e_shoff);

    symtab = elf32_find_section_header_type(shead, head->e_shnum, SHT_SYMTAB);

    uintptr_t symbase = elfbase + (uintptr_t)symtab->sh_offset;

    for (uintptr_t i = 0; i < symtab->sh_size; i += sizeof(struct Elf32_Sym)) {
        // getting the symbol
        sym = (struct Elf32_Sym *)(symbase + i);

        // check for matching type
        if ((sym->st_info & 0x0F) != type) {
            continue;
        }

        // find the section of the associacted string table
        struct Elf32_Shdr *strtab = shead+symtab->sh_link;

        // get the pointer to the symbol name from string table + string index
        symname = (const char *)elfbase + strtab->sh_offset + sym->st_name;

        if (!contains) {
            if (strcmp(symname, name)==0) {
                /* we have a match */
                count++;
                bytes += strlen(symname)+1;
            }
        } else {
            if (strstr(symname,name) != 0) {
                count++;
                bytes += strlen(symname)+1;
            }
        }
    }

    if (ret_bytes) {
        *ret_bytes = bytes;
    }

    return count;
}
Ejemplo n.º 14
0
int
main(int argc, char **argv)
{
	int ch, fd, n, xflag = 0, found = 0, phsize;
	u_int32_t *ip;
	Elf_Ehdr eh;
	Elf_Phdr *ph;

	while ((ch = getopt(argc, argv, "x")) != -1) {
		switch (ch) {
		case 'x':
			xflag = 1;
			break;
		default:
			usage();
		}
	}
	argc -= optind;
	argv += optind;

	if (argc != 1)
		usage();
	file = argv[0];

	fd = open(file, O_RDWR, 0644);
	if (fd < 0) {
		perror(file);
		exit(1);
	}

	n = read(fd, &eh, sizeof(eh));
	if (n < sizeof(eh)) {
		printf("%s: reading header\n", file);
		exit(1);
	}

	if (!IS_ELF(eh)) {
		printf("%s: not elf\n", file);
		exit(1);
	}

	phsize = eh.e_phnum * sizeof(Elf_Phdr);
	ph = (Elf_Phdr *)malloc(phsize);
	lseek(fd, eh.e_phoff, SEEK_SET);
	if (read(fd, (char *)ph, phsize) != phsize) {
		printf("%s: can't read phdr area\n", file);
		exit(1);
	}

	for (n = 0; n < eh.e_phnum && !found; n++) {
		if (ph[n].p_type == PT_LOAD)
			found = find_rd_root_image(file, &eh, &ph[n], n);
	}
	if (!found) {
		printf("%s: can't locate space for rd_root_image!\n", file);
		exit(1);
	}

	/*
	 * Map in the whole data segment.
	 * The file offset needs to be page aligned.
	 */
	dataseg = mmap(NULL, mmap_size, PROT_READ | PROT_WRITE,
	    MAP_SHARED, fd, mmap_offs);
	if (dataseg == MAP_FAILED) {
		printf("%s: can not map data seg\n", file);
		perror(file);
		exit(1);
	}

	/*
	 * Find value in the location: rd_root_size
	 */
	ip = (u_int32_t*) (dataseg + rd_root_size_off);
	rd_root_size_val = *ip;
#ifdef	DEBUG
	printf("rd_root_size  val: 0x%08X (%d blocks)\n",
	    (u_int32_t)rd_root_size_val,
	    (u_int32_t)(rd_root_size_val >> 9));
#endif

	/*
	 * Copy the symbol table and string table.
	 */
#ifdef	DEBUG
	printf("copying root image...\n");
#endif
	if (xflag) {
		n = write(STDOUT_FILENO, dataseg + rd_root_image_off,
		    rd_root_size_val);
		if (n != rd_root_size_val) {
			perror("write");
			exit(1);
		}
	} else {
		struct stat sstat;

		if (fstat(STDIN_FILENO, &sstat) == -1) {
			perror("fstat");
			exit(1);
		}
		if (S_ISREG(sstat.st_mode) &&
		    sstat.st_size > rd_root_size_val) {
			fprintf(stderr, "ramdisk too small\n");
			exit(1);
		}
		n = read(STDIN_FILENO, dataseg + rd_root_image_off,
		    rd_root_size_val);
		if (n < 0) {
			perror("read");
			exit(1);
		}

		msync(dataseg, mmap_size, 0);
	}

#ifdef	DEBUG
	printf("...copied %d bytes\n", n);
#endif
	close(fd);
	exit(0);
}
Ejemplo n.º 15
0
uintptr_t linkmap_addr(struct ps_prochandle *ph) {
  uintptr_t ehdr_addr, phdr_addr, dyn_addr, dmap_addr, lmap_addr;
  ELF_EHDR ehdr;
  ELF_PHDR *phdrs, *phdr;
  ELF_DYN *dyns, *dyn;
  struct r_debug dmap;
  unsigned long hdrs_size;
  unsigned int i;

  /* read ELF_EHDR at TEXT_START_ADDR and validate */

  ehdr_addr = (uintptr_t)TEXT_START_ADDR;

  if (process_read_data(ph, ehdr_addr, (char *)&ehdr, sizeof(ehdr)) != true) {
    print_debug("process_read_data failed for ehdr_addr %p\n", ehdr_addr);
    return (0);
  }

  if (!IS_ELF(ehdr) ||
        ehdr.e_ident[EI_CLASS] != ELF_TARG_CLASS ||
        ehdr.e_ident[EI_DATA] != ELF_TARG_DATA ||
        ehdr.e_ident[EI_VERSION] != EV_CURRENT ||
        ehdr.e_phentsize != sizeof(ELF_PHDR) ||
        ehdr.e_version != ELF_TARG_VER ||
        ehdr.e_machine != ELF_TARG_MACH) {
    print_debug("not an ELF_EHDR at %p\n", ehdr_addr);
    return (0);
  }

  /* allocate space for all ELF_PHDR's and read */

  phdr_addr = ehdr_addr + ehdr.e_phoff;
  hdrs_size = ehdr.e_phnum * sizeof(ELF_PHDR);

  if ((phdrs = malloc(hdrs_size)) == NULL)
    return (0);

  if (process_read_data(ph, phdr_addr, (char *)phdrs, hdrs_size) != true) {
    print_debug("process_read_data failed for phdr_addr %p\n", phdr_addr);
    return (0);
  }

  /* find PT_DYNAMIC section */

  for (i = 0, phdr = phdrs; i < ehdr.e_phnum; i++, phdr++) {
    if (phdr->p_type == PT_DYNAMIC)
      break;
  }

  if (i >= ehdr.e_phnum) {
    print_debug("PT_DYNAMIC section not found!\n");
    free(phdrs);
    return (0);
  }

  /* allocate space and read in ELF_DYN headers */

  dyn_addr = phdr->p_vaddr;
  hdrs_size = phdr->p_memsz;
  free(phdrs);

  if ((dyns = malloc(hdrs_size)) == NULL)
    return (0);

  if (process_read_data(ph, dyn_addr, (char *)dyns, hdrs_size) != true) {
    print_debug("process_read_data failed for dyn_addr %p\n", dyn_addr);
    free(dyns);
    return (0);
  }

  /* find DT_DEBUG */

  dyn = dyns;
  while (dyn->d_tag != DT_DEBUG && dyn->d_tag != DT_NULL) {
    dyn++;
  }

  if (dyn->d_tag != DT_DEBUG) {
    print_debug("failed to find DT_DEBUG\n");
    free(dyns);
    return (0);
  }

  /* read struct r_debug into dmap */

  dmap_addr = (uintptr_t)dyn->d_un.d_ptr;
  free(dyns);

  if (process_read_data(ph, dmap_addr, (char *)&dmap, sizeof(dmap)) != true) {
    print_debug("process_read_data failed for dmap_addr %p\n", dmap_addr);
    return (0);
  }

  lmap_addr = (uintptr_t)dmap.r_map;

  return (lmap_addr);
}
Ejemplo n.º 16
0
/*
 * elf to a.out converter for freebsd/sparc64 bootblocks.
 */
int
main(int ac, char **av)
{
	Elf64_Half phentsize;
	Elf64_Half machine;
	Elf64_Half phnum;
	Elf64_Xword filesz;
	Elf64_Xword memsz;
	Elf64_Addr entry;
	Elf64_Off offset;
	Elf64_Off phoff;
	Elf64_Word type;
	unsigned char data;
	struct stat sb;
	struct exec a;
	Elf64_Phdr *p;
	Elf64_Ehdr *e;
	void *v;
	int efd;
	int fd;
	int c;
	int i;

	fd = STDIN_FILENO;
	while ((c = getopt(ac, av, "o:")) != -1)
		switch (c) {
		case 'o':
			if ((fd = open(optarg, O_CREAT|O_RDWR, 0644)) < 0)
				err(1, "%s", optarg);
			break;
		case '?':
		default:
			usage();
		}
	ac -= optind;
	av += optind;
	if (ac == 0)
		usage();

	if ((efd = open(*av, O_RDONLY)) < 0 || fstat(efd, &sb) < 0)
		err(1, NULL);
	v = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, efd, 0);
	if ((e = v) == MAP_FAILED)
		err(1, NULL);

	if (!IS_ELF(*e))
		errx(1, "not an elf file");
	if (e->e_ident[EI_CLASS] != ELFCLASS64)
		errx(1, "wrong class");
	data = e->e_ident[EI_DATA];
	if (data != ELFDATA2MSB && data != ELFDATA2LSB)
		errx(1, "wrong data format");
	if (e->e_ident[EI_VERSION] != EV_CURRENT)
		errx(1, "wrong elf version");
	machine = xe16toh(e->e_machine);
	if (machine != EM_SPARCV9 && machine != EM_ALPHA)
		errx(1, "wrong machine type");
	phentsize = xe16toh(e->e_phentsize);
	if (phentsize != sizeof(*p))
		errx(1, "phdr size mismatch");

	entry = xe64toh(e->e_entry);
	phoff = xe64toh(e->e_phoff);
	phnum = xe16toh(e->e_phnum);
	p = (Elf64_Phdr *)((char *)e + phoff);
	bzero(&a, sizeof(a));
	for (i = 0; i < phnum; i++) {
		type = xe32toh(p[i].p_type);
		switch (type) {
		case PT_LOAD:
			if (a.a_magic != 0)
				errx(1, "too many loadable segments");
			filesz = xe64toh(p[i].p_filesz);
			memsz = xe64toh(p[i].p_memsz);
			offset = xe64toh(p[i].p_offset);
			a.a_magic = htoxe32(A_MAGIC);
			a.a_text = htoxe32(filesz);
			a.a_bss = htoxe32(memsz - filesz);
			a.a_entry = htoxe32(entry);
			if (write(fd, &a, sizeof(a)) != sizeof(a) ||
			    write(fd, (char *)e + offset, filesz) != (ssize_t)filesz)
				err(1, NULL);
			break;
		default:
			break;
		}
	}

	return (0);
}
Ejemplo n.º 17
0
int
main(int ac, char **av)
{
	cap_rights_t rights;
	u_int64_t phoff;
	u_int64_t shoff;
	u_int64_t phentsize;
	u_int64_t phnum;
	u_int64_t shentsize;
	u_int64_t shnum;
	u_int64_t shstrndx;
	u_int64_t offset;
	u_int64_t name;
	u_int64_t type;
	struct stat sb;
	u_int flags;
	Elf32_Ehdr *e;
	void *p;
	void *sh;
	void *v;
	int fd;
	int ch;
	int i;

	out = stdout;
	flags = 0;
	while ((ch = getopt(ac, av, "acdeiGhnprsw:")) != -1)
		switch (ch) {
		case 'a':
			flags = ED_ALL;
			break;
		case 'c':
			flags |= ED_SHDR;
			break;
		case 'd':
			flags |= ED_DYN;
			break;
		case 'e':
			flags |= ED_EHDR;
			break;
		case 'i':
			flags |= ED_INTERP;
			break;
		case 'G':
			flags |= ED_GOT;
			break;
		case 'h':
			flags |= ED_HASH;
			break;
		case 'n':
			flags |= ED_NOTE;
			break;
		case 'p':
			flags |= ED_PHDR;
			break;
		case 'r':
			flags |= ED_REL;
			break;
		case 's':
			flags |= ED_SYMTAB;
			break;
		case 'w':
			if ((out = fopen(optarg, "w")) == NULL)
				err(1, "%s", optarg);
			cap_rights_init(&rights, CAP_FSTAT, CAP_WRITE);
			if (cap_rights_limit(fileno(out), &rights) < 0 && errno != ENOSYS)
				err(1, "unable to limit rights for %s", optarg);
			break;
		case '?':
		default:
			usage();
		}
	ac -= optind;
	av += optind;
	if (ac == 0 || flags == 0)
		usage();
	if ((fd = open(*av, O_RDONLY)) < 0 ||
	    fstat(fd, &sb) < 0)
		err(1, "%s", *av);
	cap_rights_init(&rights, CAP_MMAP_R);
	if (cap_rights_limit(fd, &rights) < 0 && errno != ENOSYS)
		err(1, "unable to limit rights for %s", *av);
	cap_rights_init(&rights);
	if ((cap_rights_limit(STDIN_FILENO, &rights) < 0 && errno != ENOSYS) ||
	    caph_limit_stdout() < 0 || caph_limit_stderr() < 0) {
                err(1, "unable to limit rights for stdio");
	}
	if (cap_enter() < 0 && errno != ENOSYS)
		err(1, "unable to enter capability mode");
	e = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, fd, 0);
	if (e == MAP_FAILED)
		err(1, NULL);
	if (!IS_ELF(*(Elf32_Ehdr *)e))
		errx(1, "not an elf file");
	phoff = elf_get_off(e, e, E_PHOFF);
	shoff = elf_get_off(e, e, E_SHOFF);
	phentsize = elf_get_quarter(e, e, E_PHENTSIZE);
	phnum = elf_get_quarter(e, e, E_PHNUM);
	shentsize = elf_get_quarter(e, e, E_SHENTSIZE);
	p = (char *)e + phoff;
	if (shoff > 0) {
		sh = (char *)e + shoff;
		shnum = elf_get_shnum(e, sh);
		shstrndx = elf_get_shstrndx(e, sh);
		offset = elf_get_off(e, (char *)sh + shstrndx * shentsize,
		    SH_OFFSET);
		shstrtab = (char *)e + offset;
	} else {
		sh = NULL;
		shnum = 0;
		shstrndx = 0;
		shstrtab = NULL;
	}
	for (i = 0; (u_int64_t)i < shnum; i++) {
		name = elf_get_word(e, (char *)sh + i * shentsize, SH_NAME);
		offset = elf_get_off(e, (char *)sh + i * shentsize, SH_OFFSET);
		if (strcmp(shstrtab + name, ".strtab") == 0)
			strtab = (char *)e + offset;
		if (strcmp(shstrtab + name, ".dynstr") == 0)
			dynstr = (char *)e + offset;
	}
	if (flags & ED_EHDR)
		elf_print_ehdr(e, sh);
	if (flags & ED_PHDR)
		elf_print_phdr(e, p);
	if (flags & ED_SHDR)
		elf_print_shdr(e, sh);
	for (i = 0; (u_int64_t)i < phnum; i++) {
		v = (char *)p + i * phentsize;
		type = elf_get_word(e, v, P_TYPE);
		switch (type) {
		case PT_INTERP:
			if (flags & ED_INTERP)
				elf_print_interp(e, v);
			break;
		case PT_NULL:
		case PT_LOAD:
		case PT_DYNAMIC:
		case PT_NOTE:
		case PT_SHLIB:
		case PT_PHDR:
			break;
		}
	}
	for (i = 0; (u_int64_t)i < shnum; i++) {
		v = (char *)sh + i * shentsize;
		type = elf_get_word(e, v, SH_TYPE);
		switch (type) {
		case SHT_SYMTAB:
			if (flags & ED_SYMTAB)
				elf_print_symtab(e, v, strtab);
			break;
		case SHT_DYNAMIC:
			if (flags & ED_DYN)
				elf_print_dynamic(e, v);
			break;
		case SHT_RELA:
			if (flags & ED_REL)
				elf_print_rela(e, v);
			break;
		case SHT_REL:
			if (flags & ED_REL)
				elf_print_rel(e, v);
			break;
		case SHT_NOTE:
			name = elf_get_word(e, v, SH_NAME);
			if (flags & ED_NOTE &&
			    strcmp(shstrtab + name, ".note.ABI-tag") == 0)
				elf_print_note(e, v);
			break;
		case SHT_DYNSYM:
			if (flags & ED_SYMTAB)
				elf_print_symtab(e, v, dynstr);
			break;
		case SHT_PROGBITS:
			name = elf_get_word(e, v, SH_NAME);
			if (flags & ED_GOT &&
			    strcmp(shstrtab + name, ".got") == 0)
				elf_print_got(e, v);
			break;
		case SHT_HASH:
			if (flags & ED_HASH)
				elf_print_hash(e, v);
			break;
		case SHT_NULL:
		case SHT_STRTAB:
		case SHT_NOBITS:
		case SHT_SHLIB:
			break;
		}
	}

	return 0;
}
Ejemplo n.º 18
0
Archivo: exec.c Proyecto: jmgc/noah
int
load_elf(Elf64_Ehdr *ehdr, int argc, char *argv[], char **envp)
{
  uint64_t map_top = 0;

  assert(IS_ELF(*ehdr));

  if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN) {
    fprintf(stderr, "not an executable file");
    fflush(stderr);
    return -LINUX_ENOEXEC;
  }
  if (ehdr->e_machine != EM_X86_64) {
    fprintf(stderr, "not an x64 executable");
    fflush(stderr);
    return -LINUX_ENOEXEC;
  }

  Elf64_Phdr *p = (Elf64_Phdr *)((char *)ehdr + ehdr->e_phoff);

  uint64_t load_base = 0;
  bool load_base_set = false;

  ulong global_offset = 0;
  if (ehdr->e_type == ET_DYN) {
    /* NB: Program headers in elf files of ET_DYN can have 0 as their own p_vaddr. */
    global_offset = 0x400000;   /* default base address */
  }

  for (int i = 0; i < ehdr->e_phnum; i++) {
    if (p[i].p_type != PT_LOAD) {
      continue;
    }

    ulong p_vaddr = p[i].p_vaddr + global_offset;

    ulong mask = PAGE_SIZEOF(PAGE_4KB) - 1;
    ulong vaddr = p_vaddr & ~mask;
    ulong offset = p_vaddr & mask;
    ulong size = roundup(p[i].p_memsz + offset, PAGE_SIZEOF(PAGE_4KB));

    int prot = 0;
    if (p[i].p_flags & PF_X) prot |= LINUX_PROT_EXEC;
    if (p[i].p_flags & PF_W) prot |= LINUX_PROT_WRITE;
    if (p[i].p_flags & PF_R) prot |= LINUX_PROT_READ;

    assert(vaddr != 0);
    do_mmap(vaddr, size, PROT_READ | PROT_WRITE, prot, LINUX_MAP_PRIVATE | LINUX_MAP_FIXED | LINUX_MAP_ANONYMOUS, -1, 0);

    copy_to_user(vaddr + offset, (char *)ehdr + p[i].p_offset, p[i].p_filesz);

    if (! load_base_set) {
      load_base = p[i].p_vaddr - p[i].p_offset + global_offset;
      load_base_set = true;
    }
    map_top = MAX(map_top, roundup(vaddr + size, PAGE_SIZEOF(PAGE_4KB)));
  }

  assert(load_base_set);

  int i;
  bool interp = false;
  for (i = 0; i < ehdr->e_phnum; i++) {
    if (p[i].p_type == PT_INTERP) {
      interp = true;
      break;
    }
  }
  if (interp) {
    char interp_path[p[i].p_filesz + 1];
    memcpy(interp_path, (char *)ehdr + p[i].p_offset, p[i].p_filesz);
    interp_path[p[i].p_filesz] = 0;

    if (load_elf_interp(interp_path, map_top) < 0) {
      return -1;
    }
  }
  else {
    vmm_write_vmcs(VMCS_GUEST_RIP, ehdr->e_entry + global_offset);
    proc.mm->start_brk = map_top;
  }

  init_userstack(argc, argv, envp, load_base, ehdr, global_offset, interp ? map_top : 0);

  return 1;
}
int
ELFNAMEEND(check)(int fd, const char *fn)
{
	Elf_Ehdr eh;
	struct stat sb;
	unsigned char data;

	/*
	 * Check the header to maek sure it's an ELF file (of the
	 * appropriate size).
	 */
	if (fstat(fd, &sb) == -1)
		return 0;
	if (sb.st_size < (off_t)(sizeof eh))
		return 0;
	if (read(fd, &eh, sizeof eh) != sizeof eh)
		return 0;

	if (IS_ELF(eh) == 0)
                return 0;

	data = eh.e_ident[EI_DATA];

	switch (xe16toh(eh.e_machine)) {
	case EM_386: break;
	case EM_ALPHA: break;
#ifndef EM_ARM
#define EM_ARM		40
#endif
	case EM_ARM: break;
#ifndef EM_MIPS
#define EM_MIPS		8
#endif
#ifndef EM_MIPS_RS4_BE		/* same as EM_MIPS_RS3_LE */
#define EM_MIPS_RS4_BE	10
#endif
	case EM_MIPS: break;
	case /* EM_MIPS_RS3_LE */ EM_MIPS_RS4_BE: break;
#ifndef EM_IA_64
#define	EM_IA_64	50
#endif
	case EM_IA_64: break;
#ifndef EM_PPC
#define	EM_PPC		20
#endif
	case EM_PPC: break;
#ifndef EM_PPC64
#define	EM_PPC64	21
#endif
	case EM_PPC64: break;
#ifndef EM_SPARCV9
#define	EM_SPARCV9	43
#endif
	case EM_SPARCV9: break;
#ifndef EM_X86_64
#define	EM_X86_64	62
#endif
	case EM_X86_64: break;
/*        ELFDEFNNAME(MACHDEP_ID_CASES) */

        default:
                return 0;
        }

	return 1;
}
Ejemplo n.º 20
0
static void
boot_fromfs(void)
{
    union {
	Elf64_Ehdr eh;
    } hdr;
    static Elf64_Phdr ep[2];
#if 0
    static Elf64_Shdr es[2];
#endif
    caddr_t p;
    ufs_ino_t ino;
    uint64_t addr;
    int i, j;

    if (!(ino = lookup(kname))) {
	if (!ls)
	    printf("No %s\n", kname);
	return;
    }
    if (xfsread(ino, &hdr, sizeof(hdr)))
	return;

    if (IS_ELF(hdr.eh)) {
	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 = (caddr_t)ep[i].p_paddr;
	    fs_off = ep[i].p_offset;
	    if (xfsread(ino, p, ep[i].p_filesz))
		return;
	}
	p += roundup2(ep[1].p_memsz, PAGE_SIZE);
#if 0
	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++) {
		*(Elf32_Word *)p = 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;
	    }
	}
#endif
	addr = hdr.eh.e_entry;
#if 0
	bootinfo.bi_esymtab = VTOP(p);
#endif
    } else {
	printf("Invalid %s\n", "format");
	return;
    }
    boot((void *)addr, beri_argc, beri_argv, beri_envv);
}
list_t*	proc_get_depends_list(proc_obj_t* obj)
{
  Elf_Ehdr		ehdr;
  Elf_Phdr		phdr;
  Elf_Dyn		dyn;
  struct link_map	lmap;
  unsigned long		phdr_addr, dyn_addr, addr;
  struct r_debug	rdebug;
  char			buf[PATH_MAX + 1];
  list_t*		ret = NULL;
  depend_t*		cur = NULL;

  /*
  ** Get elf header.
  */
  if (proc_read(obj, 0x10000, sizeof(Elf32_Ehdr), (char*) &ehdr) == -1)
    return (NULL);
  if (!IS_ELF(ehdr))
    {
      errno = EFTRACE;
      ftrace_errstr = "Not Elf ?!";
      exit(1);
      return (NULL);
    }
  /*
  ** Get program Headers and find the Dynamic program header..
  */
  phdr_addr = 0x10000 + ehdr.e_phoff;
  if (proc_read(obj, phdr_addr, sizeof(Elf32_Phdr), (char*) &phdr) == -1)
    return (NULL);
  while (phdr.p_type != PT_DYNAMIC)
    {
      if (proc_read(obj, phdr_addr += sizeof(Elf32_Phdr),
		    sizeof(Elf32_Phdr), (char*) &phdr) == -1)
	return (NULL);
    }
  if  (phdr.p_type != PT_DYNAMIC)
    return (NULL);
  /*
  ** Browse evrey dyn and find {DT_PLTGOT|DT_DEBUG}
  */
  if (proc_read(obj, phdr.p_vaddr, sizeof(Elf32_Dyn), (char*) &dyn) == -1)
    return (NULL);
  dyn_addr = phdr.p_vaddr;
  /*
  ** ---------------------------
  ** Retrieve with the DT_DEBUG
  */
  while (dyn.d_tag != DT_DEBUG)
    {
      if (proc_read(obj, dyn_addr += sizeof(Elf32_Dyn), sizeof(Elf32_Dyn), (char*) &dyn) == -1)
	return (NULL);
    }
  if (dyn.d_tag != DT_DEBUG)
    return (NULL);
  /* printf("struct rdebug found @ 0x%x\n", dyn.d_un.d_ptr); */
  /*
  ** Get addresse's struct rdebug
  */
  if (proc_read(obj, dyn.d_un.d_ptr, sizeof(struct r_debug), (char*) &rdebug) == -1)
    return (NULL);
  /*
  ** Here we have the link_map addr.
  ** Create the depend list...
  */
  for (addr = (unsigned long) rdebug.r_map; addr; addr = (unsigned long) lmap.l_next)
    {
      if (proc_read(obj, addr, sizeof(struct link_map), (char*) &lmap) == -1)
	goto proc_get_depends_list_failed;
      if (lmap.l_name == 0)
	continue;
      if (proc_read(obj, (long) lmap.l_name, PATH_MAX, (char*) buf) == -1)
	goto proc_get_depends_list_failed;
      cur = malloc(sizeof(depend_t));
      if (cur == NULL)
	goto proc_get_depends_list_failed;
      cur->path = strdup(buf);
      cur->base_addr = (addr_t) lmap.l_addr;
      ret = list_add(ret, cur);
      if (ret == NULL)
	goto proc_get_depends_list_failed;
    }
  return (ret);
  /*
  ** If failed, free list And return NULL.
  */
 proc_get_depends_list_failed:
  for (; ret; )
    {
      cur = (depend_t*) ret->value;
      ret = list_del(ret, cur);
      if (cur && cur->path)
	free(cur->path);
      free(cur);
    }
  return (NULL);
}
Ejemplo n.º 22
0
/*
 * Read information about /boot's inode, then put this and filesystem
 * parameters from the superblock into pbr_symbols.
 */
static int
getbootparams(char *boot, int devfd, struct disklabel *dl)
{
	int		fd;
	struct stat	dsb, fsb;
	struct statfs	fssb;
	struct partition *pp;
	struct fs	*fs;
	char		*buf;
	u_int		blk, *ap;
	struct ufs1_dinode *ip1;
	struct ufs2_dinode *ip2;
	int		ndb;
	int		mib[3];
	size_t		size;
	dev_t		dev;
	int		skew;

	/*
	 * Open 2nd-level boot program and record enough details about
	 * where it is on the filesystem represented by `devfd'
	 * (inode block, offset within that block, and various filesystem
	 * parameters essentially taken from the superblock) for biosboot
	 * to be able to load it later.
	 */

	/* Make sure the (probably new) boot file is on disk. */
	sync(); sleep(1);

	if ((fd = open(boot, O_RDONLY)) < 0)
		err(1, "open: %s", boot);

	if (fstatfs(fd, &fssb) != 0)
		err(1, "statfs: %s", boot);

	if (strncmp(fssb.f_fstypename, "ffs", MFSNAMELEN) &&
	    strncmp(fssb.f_fstypename, "ufs", MFSNAMELEN) )
		errx(1, "%s: not on an FFS filesystem", boot);

#if 0
	if (read(fd, &eh, sizeof(eh)) != sizeof(eh))
		errx(1, "read: %s", boot);

	if (!IS_ELF(eh)) {
		errx(1, "%s: bad magic: 0x%02x%02x%02x%02x",
		    boot,
		    eh.e_ident[EI_MAG0], eh.e_ident[EI_MAG1],
		    eh.e_ident[EI_MAG2], eh.e_ident[EI_MAG3]);
	}
#endif

	if (fsync(fd) != 0)
		err(1, "fsync: %s", boot);

	if (fstat(fd, &fsb) != 0)
		err(1, "fstat: %s", boot);

	if (fstat(devfd, &dsb) != 0)
		err(1, "fstat: %d", devfd);

	/* Check devices. */
	mib[0] = CTL_MACHDEP;
	mib[1] = CPU_CHR2BLK;
	mib[2] = dsb.st_rdev;
	size = sizeof(dev);
	if (sysctl(mib, 3, &dev, &size, NULL, 0) >= 0) {
		if (fsb.st_dev / MAXPARTITIONS != dev / MAXPARTITIONS)
			errx(1, "cross-device install");
	}

	pp = &dl->d_partitions[DISKPART(fsb.st_dev)];
	close(fd);

	sbread(devfd, DL_SECTOBLK(dl, DL_GETPOFFSET(pp)), &fs);

	/* Read inode. */
	if ((buf = malloc(fs->fs_bsize)) == NULL)
		err(1, NULL);

	blk = fsbtodb(fs, ino_to_fsba(fs, fsb.st_ino));

	/*
	 * Have the inode.  Figure out how many filesystem blocks (not disk
	 * sectors) there are for biosboot to load.
	 */
	devread(devfd, buf, DL_SECTOBLK(dl, pp->p_offset) + blk,
	    fs->fs_bsize, "inode");
	if (fs->fs_magic == FS_UFS2_MAGIC) {
		ip2 = (struct ufs2_dinode *)(buf) +
		    ino_to_fsbo(fs, fsb.st_ino);
		ndb = howmany(ip2->di_size, fs->fs_bsize);
		ap = (u_int *)ip2->di_db;
		skew = sizeof(u_int32_t);
	} else {
		ip1 = (struct ufs1_dinode *)(buf) +
		    ino_to_fsbo(fs, fsb.st_ino);
		ndb = howmany(ip1->di_size, fs->fs_bsize);
		ap = (u_int *)ip1->di_db;
		skew = 0;
	}
	if (ndb <= 0)
		errx(1, "No blocks to load");

	/*
	 * Now set the values that will need to go into biosboot
	 * (the partition boot record, a.k.a. the PBR).
	 */
	sym_set_value(pbr_symbols, "_fs_bsize_p", (fs->fs_bsize / 16));
	sym_set_value(pbr_symbols, "_fs_bsize_s", (fs->fs_bsize / 
	    dl->d_secsize));

	/*
	 * fs_fsbtodb is the shift to convert fs_fsize to DEV_BSIZE. The
	 * ino_to_fsba() return value is the number of fs_fsize units.
	 * Calculate the shift to convert fs_fsize into physical sectors,
	 * which are added to p_offset to get the sector address BIOS
	 * will use.
	 *
	 * N.B.: ASSUMES fs_fsize is a power of 2 of d_secsize.
	 */
	sym_set_value(pbr_symbols, "_fsbtodb",
	    ffs(fs->fs_fsize / dl->d_secsize) - 1);

	if (pp->p_offseth != 0)
		errx(1, "partition offset too high");
	sym_set_value(pbr_symbols, "_p_offset", pp->p_offset);
	sym_set_value(pbr_symbols, "_inodeblk",
	    ino_to_fsba(fs, fsb.st_ino));
	sym_set_value(pbr_symbols, "_inodedbl",
	    ((((char *)ap) - buf) + INODEOFF));
	sym_set_value(pbr_symbols, "_nblocks", ndb);
	sym_set_value(pbr_symbols, "_blkskew", skew);

	if (verbose) {
		fprintf(stderr, "%s is %d blocks x %d bytes\n",
		    boot, ndb, fs->fs_bsize);
		fprintf(stderr, "fs block shift %u; part offset %llu; "
		    "inode block %lld, offset %u\n",
		    ffs(fs->fs_fsize / dl->d_secsize) - 1,
		    DL_GETPOFFSET(pp), ino_to_fsba(fs, fsb.st_ino),
		    (unsigned int)((((char *)ap) - buf) + INODEOFF));
		fprintf(stderr, "expecting %d-bit fs blocks (skew %d)\n",
		    skew ? 64 : 32, skew);
	}

	return 0;
}
Ejemplo n.º 23
0
TEE_Result elf_load_head(struct elf_load_state *state, size_t head_size,
			void **head, size_t *vasize)
{
	TEE_Result res;
	size_t n;
	void *p;
	Elf32_Ehdr *ehdr;

	/*
	 * The ELF resides in shared memory, to avoid attacks based on
	 * modifying the ELF while we're parsing it here we only read each
	 * byte from the ELF once. We're also hashing the ELF while reading
	 * so we're limited to only read the ELF sequentially from start to
	 * end.
	 */

	res = alloc_and_copy_to(&p, state, 0, sizeof(Elf32_Ehdr));
	if (res != TEE_SUCCESS)
		return res;
	ehdr = p;
	state->ehdr = ehdr;

	if (!IS_ELF(*ehdr) ||
	    ehdr->e_ident[EI_VERSION] != EV_CURRENT ||
	    ehdr->e_ident[EI_CLASS] != ELFCLASS32 ||
	    ehdr->e_ident[EI_DATA] != ELFDATA2LSB ||
	    ehdr->e_ident[EI_OSABI] != ELFOSABI_NONE ||
	    ehdr->e_type != ET_DYN || ehdr->e_machine != EM_ARM ||
	    (ehdr->e_flags & EF_ARM_ABIMASK) != EF_ARM_ABI_VERSION ||
	    (ehdr->e_flags & EF_ARM_ABI_FLOAT_HARD) ||
	    ehdr->e_phentsize != sizeof(Elf32_Phdr) ||
	    ehdr->e_shentsize != sizeof(Elf32_Shdr))
		return TEE_ERROR_BAD_FORMAT;

	/*
	 * Program headers are supposed to be arranged as:
	 * PT_LOAD [0] : .ta_head ...
	 * ...
	 * PT_LOAD [n]
	 *
	 * .ta_head must be located first in the first program header,
	 * which also has to be of PT_LOAD type.
	 *
	 * A PT_DYNAMIC segment may appear, but is ignored. Any other
	 * segment except PT_LOAD and PT_DYNAMIC will cause an error. All
	 * sections not included by a PT_LOAD segment are ignored.
	 */
	if (ehdr->e_phnum < 1)
		return TEE_ERROR_BAD_FORMAT;
	res = alloc_and_copy_to(&p, state, ehdr->e_phoff,
				ehdr->e_phnum * sizeof(Elf32_Phdr));
	if (res != TEE_SUCCESS)
		return res;
	state->phdr = p;

	/*
	 * Check that the first program header is a PT_LOAD (not strictly
	 * needed but our link script is supposed to arrange it that way)
	 * and that it starts at virtual address 0.
	 */
	if (state->phdr[0].p_type != PT_LOAD || state->phdr[0].p_vaddr != 0)
		return TEE_ERROR_BAD_FORMAT;

	/*
	 * Calculate amount of required virtual memory for TA. Find the max
	 * address used by a PT_LOAD type. Note that last PT_LOAD type
	 * dictates the total amount of needed memory. Eventual holes in
	 * the memory will also be allocated.
	 *
	 * Note that this loop will terminate at n = 0 if not earlier
	 * as we already know from above that state->phdr[0].p_type == PT_LOAD
	 */
	n = ehdr->e_phnum - 1;
	while (state->phdr[n].p_type != PT_LOAD)
		n--;
	state->vasize = state->phdr[n].p_vaddr + state->phdr[n].p_memsz;

	/*
	 * Read .ta_head from first segment, make sure the segment is large
	 * enough. We're only interested in seeing that the
	 * TA_FLAG_EXEC_DDR flag is set. If that's true we set that flag in
	 * the TA context to enable mapping the TA. Later when this
	 * function has returned and the hash has been verified the flags
	 * field will be updated with eventual other flags.
	 */
	if (state->phdr[0].p_filesz < head_size)
		return TEE_ERROR_BAD_FORMAT;
	res = alloc_and_copy_to(&p, state, state->phdr[0].p_offset, head_size);
	if (res != TEE_SUCCESS)
		return res;
	state->ta_head = p;
	state->ta_head_size = head_size;

	*head = state->ta_head;
	*vasize = state->vasize;
	return TEE_SUCCESS;
}
Ejemplo n.º 24
0
int
putfile(char *from_file, int to)
{
	struct exec ex;
	register int n, total;
	char buf[2048];
	int from, check_sum = 0;
	struct lif_load load;

	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_Ehdr *)&ex)) {
		Elf32_Ehdr elf_header;
		Elf32_Phdr *elf_segments;
		int i, header_count, memory_needed, elf_load_image_segment;

		(void) lseek(from, 0, SEEK_SET);
		n = read(from, &elf_header, sizeof(elf_header));
		if (n != sizeof (elf_header))
			err(1, "%s: reading ELF header", from_file);
		header_count = ntohs(elf_header.e_phnum);
		elf_segments = reallocarray(NULL, header_count,
		    sizeof(*elf_segments));
		if (elf_segments == NULL)
			err(1, "malloc");
		memory_needed = header_count * sizeof(*elf_segments);
		(void) lseek(from, ntohl(elf_header.e_phoff), SEEK_SET);
		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 (elf_segments[i].p_filesz &&
			    ntohl(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 = ntohl(elf_header.e_entry) +
			ntohl(elf_segments[elf_load_image_segment].p_offset) -
			ntohl(elf_segments[elf_load_image_segment].p_vaddr);
		free(elf_segments);
	} else if (*(u_char *)&ex == 0x1f && ((u_char *)&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, 0); ; n = sizeof(buf)) {
		bzero(buf, 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);

	bzero(buf, 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;
}
Ejemplo n.º 25
0
static int
link_elf_ctf_get(linker_file_t lf, linker_ctf_t *lc)
{
#ifdef DDB_CTF
	Elf_Ehdr *hdr = NULL;
	Elf_Shdr *shdr = NULL;
	caddr_t ctftab = NULL;
	caddr_t raw = NULL;
	caddr_t shstrtab = NULL;
	elf_file_t ef = (elf_file_t) lf;
	int flags;
	int i;
	int nbytes;
	int resid;
	int vfslocked;
	size_t sz;
	struct nameidata nd;
	struct thread *td = curthread;
	uint8_t ctf_hdr[CTF_HDR_SIZE];
#endif
	int error = 0;

	if (lf == NULL || lc == NULL)
		return (EINVAL);

	/* Set the defaults for no CTF present. That's not a crime! */
	bzero(lc, sizeof(*lc));

#ifdef DDB_CTF
	/*
	 * First check if we've tried to load CTF data previously and the
	 * CTF ELF section wasn't found. We flag that condition by setting
	 * ctfcnt to -1. See below.
	 */
	if (ef->ctfcnt < 0)
		return (0);

	/* Now check if we've already loaded the CTF data.. */
	if (ef->ctfcnt > 0) {
		/* We only need to load once. */
		lc->ctftab = ef->ctftab;
		lc->ctfcnt = ef->ctfcnt;
		lc->symtab = ef->ddbsymtab;
		lc->strtab = ef->ddbstrtab;
		lc->strcnt = ef->ddbstrcnt;
		lc->nsym   = ef->ddbsymcnt;
		lc->ctfoffp = (uint32_t **) &ef->ctfoff;
		lc->typoffp = (uint32_t **) &ef->typoff;
		lc->typlenp = &ef->typlen;
		return (0);
	}

	/*
	 * We need to try reading the CTF data. Flag no CTF data present
	 * by default and if we actually succeed in reading it, we'll
	 * update ctfcnt to the number of bytes read.
	 */
	ef->ctfcnt = -1;

	NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE, UIO_SYSSPACE, lf->pathname, td);
	flags = FREAD;
	error = vn_open(&nd, &flags, 0, NULL);
	if (error)
		return (error);
	vfslocked = NDHASGIANT(&nd);
	NDFREE(&nd, NDF_ONLY_PNBUF);

	/* Allocate memory for the FLF header. */
	if ((hdr = malloc(sizeof(*hdr), M_LINKER, M_WAITOK)) == NULL) {
		error = ENOMEM;
		goto out;
	}

	/* Read the ELF header. */
	if ((error = vn_rdwr(UIO_READ, nd.ni_vp, hdr, sizeof(*hdr),
	    0, UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED, &resid,
	    td)) != 0)
		goto out;

	/* Sanity check. */
	if (!IS_ELF(*hdr)) {
		error = ENOEXEC;
		goto out;
	}

	nbytes = hdr->e_shnum * hdr->e_shentsize;
	if (nbytes == 0 || hdr->e_shoff == 0 ||
	    hdr->e_shentsize != sizeof(Elf_Shdr)) {
		error = ENOEXEC;
		goto out;
	}

	/* Allocate memory for all the section headers */
	if ((shdr = malloc(nbytes, M_LINKER, M_WAITOK)) == NULL) {
		error = ENOMEM;
		goto out;
	}

	/* Read all the section headers */
	if ((error = vn_rdwr(UIO_READ, nd.ni_vp, (caddr_t)shdr, nbytes,
	    hdr->e_shoff, UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED,
	    &resid, td)) != 0)
		goto out;

	/*
	 * We need to search for the CTF section by name, so if the
	 * section names aren't present, then we can't locate the
	 * .SUNW_ctf section containing the CTF data.
	 */
	if (hdr->e_shstrndx == 0 || shdr[hdr->e_shstrndx].sh_type != SHT_STRTAB) {
		printf("%s(%d): module %s e_shstrndx is %d, sh_type is %d\n",
		    __func__, __LINE__, lf->pathname, hdr->e_shstrndx,
		    shdr[hdr->e_shstrndx].sh_type);
		error = EFTYPE;
		goto out;
	}

	/* Allocate memory to buffer the section header strings. */
	if ((shstrtab = malloc(shdr[hdr->e_shstrndx].sh_size, M_LINKER,
	    M_WAITOK)) == NULL) {
		error = ENOMEM;
		goto out;
	}

	/* Read the section header strings. */
	if ((error = vn_rdwr(UIO_READ, nd.ni_vp, shstrtab,
	    shdr[hdr->e_shstrndx].sh_size, shdr[hdr->e_shstrndx].sh_offset,
	    UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred, NOCRED, &resid,
	    td)) != 0)
		goto out;

	/* Search for the section containing the CTF data. */
	for (i = 0; i < hdr->e_shnum; i++)
		if (strcmp(".SUNW_ctf", shstrtab + shdr[i].sh_name) == 0)
			break;

	/* Check if the CTF section wasn't found. */
	if (i >= hdr->e_shnum) {
		printf("%s(%d): module %s has no .SUNW_ctf section\n",
		    __func__, __LINE__, lf->pathname);
		error = EFTYPE;
		goto out;
	}

	/* Read the CTF header. */
	if ((error = vn_rdwr(UIO_READ, nd.ni_vp, ctf_hdr, sizeof(ctf_hdr),
	    shdr[i].sh_offset, UIO_SYSSPACE, IO_NODELOCKED, td->td_ucred,
	    NOCRED, &resid, td)) != 0)
		goto out;

	/* Check the CTF magic number. (XXX check for big endian!) */
	if (ctf_hdr[0] != 0xf1 || ctf_hdr[1] != 0xcf) {
		printf("%s(%d): module %s has invalid format\n",
		    __func__, __LINE__, lf->pathname);
		error = EFTYPE;
		goto out;
	}

	/* Check if version 2. */
	if (ctf_hdr[2] != 2) {
		printf("%s(%d): module %s CTF format version is %d "
		    "(2 expected)\n",
		    __func__, __LINE__, lf->pathname, ctf_hdr[2]);
		error = EFTYPE;
		goto out;
	}

	/* Check if the data is compressed. */
	if ((ctf_hdr[3] & 0x1) != 0) {
		uint32_t *u32 = (uint32_t *) ctf_hdr;

		/*
		 * The last two fields in the CTF header are the offset
		 * from the end of the header to the start of the string
		 * data and the length of that string data. se this
		 * information to determine the decompressed CTF data
		 * buffer required.
		 */
		sz = u32[CTF_HDR_STRTAB_U32] + u32[CTF_HDR_STRLEN_U32] +
		    sizeof(ctf_hdr);

		/*
		 * Allocate memory for the compressed CTF data, including
		 * the header (which isn't compressed).
		 */
		if ((raw = malloc(shdr[i].sh_size, M_LINKER, M_WAITOK)) == NULL) {
			error = ENOMEM;
			goto out;
		}
	} else {
		/*
		 * The CTF data is not compressed, so the ELF section
		 * size is the same as the buffer size required.
		 */
		sz = shdr[i].sh_size;
	}

	/*
	 * Allocate memory to buffer the CTF data in it's decompressed
	 * form.
	 */
	if ((ctftab = malloc(sz, M_LINKER, M_WAITOK)) == NULL) {
		error = ENOMEM;
		goto out;
	}

	/*
	 * Read the CTF data into the raw buffer if compressed, or
	 * directly into the CTF buffer otherwise.
	 */
	if ((error = vn_rdwr(UIO_READ, nd.ni_vp, raw == NULL ? ctftab : raw,
	    shdr[i].sh_size, shdr[i].sh_offset, UIO_SYSSPACE, IO_NODELOCKED,
	    td->td_ucred, NOCRED, &resid, td)) != 0)
		goto out;

	/* Check if decompression is required. */
	if (raw != NULL) {
		z_stream zs;
		int ret;

		/*
		 * The header isn't compressed, so copy that into the
		 * CTF buffer first.
		 */
		bcopy(ctf_hdr, ctftab, sizeof(ctf_hdr));

		/* Initialise the zlib structure. */
		bzero(&zs, sizeof(zs));
		zs.zalloc = z_alloc;
		zs.zfree = z_free;

		if (inflateInit(&zs) != Z_OK) {
			error = EIO;
			goto out;
		}

		zs.avail_in = shdr[i].sh_size - sizeof(ctf_hdr);
		zs.next_in = ((uint8_t *) raw) + sizeof(ctf_hdr);
		zs.avail_out = sz - sizeof(ctf_hdr);
		zs.next_out = ((uint8_t *) ctftab) + sizeof(ctf_hdr);
		if ((ret = inflate(&zs, Z_FINISH)) != Z_STREAM_END) {
			printf("%s(%d): zlib inflate returned %d\n", __func__, __LINE__, ret);
			error = EIO;
			goto out;
		}
	}

	/* Got the CTF data! */
	ef->ctftab = ctftab;
	ef->ctfcnt = shdr[i].sh_size;

	/* We'll retain the memory allocated for the CTF data. */
	ctftab = NULL;

	/* Let the caller use the CTF data read. */
	lc->ctftab = ef->ctftab;
	lc->ctfcnt = ef->ctfcnt;
	lc->symtab = ef->ddbsymtab;
	lc->strtab = ef->ddbstrtab;
	lc->strcnt = ef->ddbstrcnt;
	lc->nsym   = ef->ddbsymcnt;
	lc->ctfoffp = (uint32_t **) &ef->ctfoff;
	lc->typoffp = (uint32_t **) &ef->typoff;
	lc->typlenp = &ef->typlen;

out:
	VOP_UNLOCK(nd.ni_vp, 0);
	vn_close(nd.ni_vp, FREAD, td->td_ucred, td);
	VFS_UNLOCK_GIANT(vfslocked);

	if (hdr != NULL)
		free(hdr, M_LINKER);
	if (shdr != NULL)
		free(shdr, M_LINKER);
	if (shstrtab != NULL)
		free(shstrtab, M_LINKER);
	if (ctftab != NULL)
		free(ctftab, M_LINKER);
	if (raw != NULL)
		free(raw, M_LINKER);
#else
	error = EOPNOTSUPP;
#endif

	return (error);
}
Ejemplo n.º 26
0
int
ef_obj_open(const char *filename, struct elf_file *efile, int verbose)
{
	elf_file_t ef;
	Elf_Ehdr *hdr;
	Elf_Shdr *shdr;
	Elf_Sym *es;
	char *mapbase;
	void *vtmp;
	size_t mapsize, alignmask, max_addralign;
	int error, fd, pb, ra, res, rl;
	int i, j, nbytes, nsym, shstrindex, symstrindex, symtabindex;

	if (filename == NULL)
		return EFTYPE;
	if ((fd = open(filename, O_RDONLY)) == -1)
		return errno;

	ef = calloc(1, sizeof(*ef));
	if (ef == NULL) {
		close(fd);
		return (ENOMEM);
	}

	efile->ef_ef = ef;
	efile->ef_ops = &ef_obj_file_ops;

	ef->ef_verbose = verbose;
	ef->ef_fd = fd;
	ef->ef_name = strdup(filename);
	ef->ef_efile = efile;
	hdr = (Elf_Ehdr *)&ef->ef_hdr;

	res = read(fd, hdr, sizeof(*hdr));
	error = EFTYPE;
	if (res != sizeof(*hdr))
		goto out;
	if (!IS_ELF(*hdr))
		goto out;
	if (hdr->e_ident[EI_CLASS] != ELF_TARG_CLASS ||
	    hdr->e_ident[EI_DATA] != ELF_TARG_DATA ||
	    hdr->e_ident[EI_VERSION] != EV_CURRENT ||
	    hdr->e_version != EV_CURRENT || hdr->e_machine != ELF_TARG_MACH ||
	    hdr->e_type != ET_REL)
		goto out;

	nbytes = hdr->e_shnum * hdr->e_shentsize;
	if (nbytes == 0 || hdr->e_shoff == 0 ||
	    hdr->e_shentsize != sizeof(Elf_Shdr))
		goto out;

	if (ef_obj_read_entry(ef, hdr->e_shoff, nbytes, &vtmp) != 0) {
		printf("ef_read_entry failed\n");
		goto out;
	}
	ef->e_shdr = shdr = vtmp;

	/* Scan the section header for information and table sizing. */
	nsym = 0;
	symtabindex = -1;
	symstrindex = -1;
	for (i = 0; i < hdr->e_shnum; i++) {
		switch (shdr[i].sh_type) {
		case SHT_PROGBITS:
		case SHT_NOBITS:
			ef->nprogtab++;
			break;
		case SHT_SYMTAB:
			nsym++;
			symtabindex = i;
			symstrindex = shdr[i].sh_link;
			break;
		case SHT_REL:
			ef->nrel++;
			break;
		case SHT_RELA:
			ef->nrela++;
			break;
		case SHT_STRTAB:
			break;
		}
	}

	if (ef->nprogtab == 0) {
		warnx("%s: file has no contents", filename);
		goto out;
	}
	if (nsym != 1) {
		warnx("%s: file has no valid symbol table", filename);
		goto out;
	}
	if (symstrindex < 0 || symstrindex > hdr->e_shnum ||
	    shdr[symstrindex].sh_type != SHT_STRTAB) {
		warnx("%s: file has invalid symbol strings", filename);
		goto out;
	}

	/* Allocate space for tracking the load chunks */
	if (ef->nprogtab != 0)
		ef->progtab = calloc(ef->nprogtab, sizeof(*ef->progtab));
	if (ef->nrel != 0)
		ef->reltab = calloc(ef->nrel, sizeof(*ef->reltab));
	if (ef->nrela != 0)
		ef->relatab = calloc(ef->nrela, sizeof(*ef->relatab));
	if ((ef->nprogtab != 0 && ef->progtab == NULL) ||
	    (ef->nrel != 0 && ef->reltab == NULL) ||
	    (ef->nrela != 0 && ef->relatab == NULL)) {
		printf("malloc failed\n");
		error = ENOMEM;
		goto out;
	}

	ef->ddbsymcnt = shdr[symtabindex].sh_size / sizeof(Elf_Sym);
	if (ef_obj_read_entry(ef, shdr[symtabindex].sh_offset,
	    shdr[symtabindex].sh_size, (void**)&ef->ddbsymtab) != 0) {
		printf("ef_read_entry failed\n");
		goto out;
	}

	ef->ddbstrcnt = shdr[symstrindex].sh_size;
	if (ef_obj_read_entry(ef, shdr[symstrindex].sh_offset,
	    shdr[symstrindex].sh_size, (void**)&ef->ddbstrtab) != 0) {
		printf("ef_read_entry failed\n");
		goto out;
	}

	/* Do we have a string table for the section names?  */
	shstrindex = -1;
	if (hdr->e_shstrndx != 0 &&
	    shdr[hdr->e_shstrndx].sh_type == SHT_STRTAB) {
		shstrindex = hdr->e_shstrndx;
		ef->shstrcnt = shdr[shstrindex].sh_size;
		if (ef_obj_read_entry(ef, shdr[shstrindex].sh_offset,
		    shdr[shstrindex].sh_size, (void**)&ef->shstrtab) != 0) {
			printf("ef_read_entry failed\n");
			goto out;
		}
	}

	/* Size up code/data(progbits) and bss(nobits). */
	alignmask = 0;
	max_addralign = 0;
	mapsize = 0;
	for (i = 0; i < hdr->e_shnum; i++) {
		switch (shdr[i].sh_type) {
		case SHT_PROGBITS:
		case SHT_NOBITS:
			alignmask = shdr[i].sh_addralign - 1;
			if (shdr[i].sh_addralign > max_addralign)
				max_addralign = shdr[i].sh_addralign;
			mapsize += alignmask;
			mapsize &= ~alignmask;
			mapsize += shdr[i].sh_size;
			break;
		}
	}

	/* We know how much space we need for the text/data/bss/etc. */
	ef->size = mapsize;
	if (posix_memalign((void **)&ef->address, max_addralign, mapsize)) {
		printf("posix_memalign failed\n");
		goto out;
	}
	mapbase = ef->address;

	/*
	 * Now load code/data(progbits), zero bss(nobits), allocate
	 * space for and load relocs
	 */
	pb = 0;
	rl = 0;
	ra = 0;
	alignmask = 0;
	for (i = 0; i < hdr->e_shnum; i++) {
		switch (shdr[i].sh_type) {
		case SHT_PROGBITS:
		case SHT_NOBITS:
			alignmask = shdr[i].sh_addralign - 1;
			mapbase += alignmask;
			mapbase  = (char *)((uintptr_t)mapbase & ~alignmask);
			ef->progtab[pb].addr = (void *)(uintptr_t)mapbase;
			if (shdr[i].sh_type == SHT_PROGBITS) {
				ef->progtab[pb].name = "<<PROGBITS>>";
				if (ef_obj_read(ef, shdr[i].sh_offset,
				    shdr[i].sh_size,
				    ef->progtab[pb].addr) != 0) {
					printf("failed to read progbits\n");
					goto out;
				}
			} else {
				ef->progtab[pb].name = "<<NOBITS>>";
				bzero(ef->progtab[pb].addr, shdr[i].sh_size);
			}
			ef->progtab[pb].size = shdr[i].sh_size;
			ef->progtab[pb].sec = i;
			if (ef->shstrtab && shdr[i].sh_name != 0)
				ef->progtab[pb].name =
				    ef->shstrtab + shdr[i].sh_name;

			/* Update all symbol values with the offset. */
			for (j = 0; j < ef->ddbsymcnt; j++) {
				es = &ef->ddbsymtab[j];
				if (es->st_shndx != i)
					continue;
				es->st_value += (Elf_Addr)ef->progtab[pb].addr;
			}
			mapbase += shdr[i].sh_size;
			pb++;
			break;
		case SHT_REL:
			ef->reltab[rl].nrel = shdr[i].sh_size / sizeof(Elf_Rel);
			ef->reltab[rl].sec = shdr[i].sh_info;
			if (ef_obj_read_entry(ef, shdr[i].sh_offset,
			    shdr[i].sh_size, (void**)&ef->reltab[rl].rel) !=
			    0) {
				printf("ef_read_entry failed\n");
				goto out;
			}
			rl++;
			break;
		case SHT_RELA:
			ef->relatab[ra].nrela =
			    shdr[i].sh_size / sizeof(Elf_Rela);
			ef->relatab[ra].sec = shdr[i].sh_info;
			if (ef_obj_read_entry(ef, shdr[i].sh_offset,
			    shdr[i].sh_size, (void**)&ef->relatab[ra].rela) !=
			    0) {
				printf("ef_read_entry failed\n");
				goto out;
			}
			ra++;
			break;
		}
	}
	error = 0;
out:
	if (error)
		ef_obj_close(ef);
	return error;
}
Ejemplo n.º 27
0
int
elf_getnfile(const char *filename, char ***defaultEs)
{
    int fd;
    Elf_Ehdr h;
    struct stat s;
    void *mapbase;
    const char *base;
    const Elf_Shdr *shdrs;
    const Elf_Shdr *sh_symtab;
    const Elf_Shdr *sh_strtab;
    const char *strtab;
    const Elf_Sym *symtab;
    int symtabct;
    int i;

    if ((fd = open(filename, O_RDONLY)) == -1)
	err(1, "%s", filename);
    if (read(fd, &h, sizeof h) != sizeof h || !IS_ELF(h)) {
	close(fd);
	return -1;
    }
    if (fstat(fd, &s) == -1)
	err(1, "cannot fstat %s", filename);
    if ((mapbase = mmap(0, s.st_size, PROT_READ, MAP_SHARED, fd, 0)) ==
      MAP_FAILED)
	err(1, "cannot mmap %s", filename);
    close(fd);

    base = (const char *)mapbase;
    shdrs = (const Elf_Shdr *)(base + h.e_shoff);

    /* Find the symbol table and associated string table section. */
    for (i = 1;  i < h.e_shnum;  i++)
	if (shdrs[i].sh_type == SHT_SYMTAB)
	    break;
    if (i == h.e_shnum)
	errx(1, "%s has no symbol table", filename);
    sh_symtab = &shdrs[i];
    sh_strtab = &shdrs[sh_symtab->sh_link];

    symtab = (const Elf_Sym *)(base + sh_symtab->sh_offset);
    symtabct = sh_symtab->sh_size / sh_symtab->sh_entsize;
    strtab = (const char *)(base + sh_strtab->sh_offset);

    /* Count the symbols that we're interested in. */
    nname = 0;
    for (i = 1;  i < symtabct;  i++)
	if (wantsym(&symtab[i], strtab))
	    nname++;

    /* Allocate memory for them, plus a terminating entry. */
    if ((nl = (nltype *)calloc(nname + 1, sizeof(nltype))) == NULL)
	errx(1, "insufficient memory for symbol table");

    /* Read them in. */
    npe = nl;
    for (i = 1;  i < symtabct;  i++) {
	const Elf_Sym *sym = &symtab[i];

	if (wantsym(sym, strtab)) {
	    npe->value = sym->st_value;
	    npe->name = strtab + sym->st_name;
	    npe++;
	}
    }
    npe->value = -1;

    *defaultEs = excludes;
    return 0;
}