Beispiel #1
0
void *
_libelf_getshdr(Elf_Scn *s, int ec)
{
        Elf *e;

        if (s == NULL || (e = s->s_elf) == NULL ||
            e->e_kind != ELF_K_ELF) {
                LIBELF_SET_ERROR(ARGUMENT, 0);
                return (NULL);
        }

        if (ec == ELFCLASSNONE)
                ec = e->e_class;

        if (ec != e->e_class) {
                LIBELF_SET_ERROR(CLASS, 0);
                return (NULL);
        }

        return ((void *) &s->s_shdr);
}
Beispiel #2
0
Elf_Data *
elf_newdata(Elf_Scn *s)
{
	Elf *e;
	Elf_Data *d;

	if (s == NULL || (e = s->s_elf) == NULL ||
	    e->e_kind != ELF_K_ELF) {
		LIBELF_SET_ERROR(ARGUMENT, 0);
		return (NULL);
	}

	/*
	 * elf_newdata() has to append a data descriptor, so
	 * bring in existing section data if not already present.
	 */
	if (e->e_rawfile && s->s_size > 0 && STAILQ_EMPTY(&s->s_data))
		if (elf_getdata(s, NULL) == NULL)
			return (NULL);

	if ((d = malloc(sizeof(Elf_Data))) == NULL) {
		LIBELF_SET_ERROR(RESOURCE, errno);
		return (NULL);
	}

	STAILQ_INSERT_TAIL(&s->s_data, d, d_next);
	d->d_flags = 0;
	d->d_scn = s;

	d->d_align = 1;
	d->d_buf = NULL;
	d->d_off = (uint64_t) ~0;
	d->d_size = 0;
	d->d_type = ELF_T_BYTE;
	d->d_version = LIBELF_PRIVATE(version);

	(void) elf_flagscn(s, ELF_C_SET, ELF_F_DIRTY);

	return (d);
}
Beispiel #3
0
Elf_Arhdr *
elf_getarhdr(Elf *e)
{
	if (e == NULL) {
		LIBELF_SET_ERROR(ARGUMENT, 0);
		return (NULL);
	}

	if (e->e_flags & LIBELF_F_AR_HEADER)
		return (e->e_hdr.e_arhdr);

	return (_libelf_ar_gethdr(e));
}
Elf_Arsym *
elf_getarsym(Elf *ar, size_t *ptr)
{
	size_t n;
	Elf_Arsym *symtab;

	n = 0;
	symtab = NULL;

	if (ar == NULL || ar->e_kind != ELF_K_AR)
		LIBELF_SET_ERROR(ARGUMENT, 0);
	else if ((symtab = ar->e_u.e_ar.e_symtab) != NULL)
		n = ar->e_u.e_ar.e_symtabsz;
	else if (ar->e_u.e_ar.e_rawsymtab)
		symtab = _libelf_ar_process_symtab(ar, &n);
	else
		LIBELF_SET_ERROR(ARCHIVE, 0);

	if (ptr)
		*ptr = n;
	return (symtab);
}
Beispiel #5
0
off_t
elf_getbase(Elf *e)
{
	if (e == NULL) {
		LIBELF_SET_ERROR(ARGUMENT, 0);
		return ((off_t) -1);
	}

	if (e->e_parent == NULL)
		return ((off_t) 0);

	return ((off_t) ((uintptr_t) e->e_rawfile -
	    (uintptr_t) e->e_parent->e_rawfile));
}
Beispiel #6
0
Elf_Data *
elf_rawdata(Elf_Scn *s, Elf_Data *d)
{
	Elf *e;
	uint32_t sh_type;
	int elf_class;
	uint64_t sh_align, sh_offset, sh_size;

	if (s == NULL || (e = s->s_elf) == NULL ||
	    e->e_kind != ELF_K_ELF || e->e_rawfile == NULL) {
		LIBELF_SET_ERROR(ARGUMENT, 0);
		return (NULL);
	}

	if (d == NULL && (d = STAILQ_FIRST(&s->s_rawdata)) != NULL)
		return (d);

	if (d != NULL)
		return (STAILQ_NEXT(d, d_next));

	elf_class = e->e_class;

	assert(elf_class == ELFCLASS32 || elf_class == ELFCLASS64);

	if (elf_class == ELFCLASS32) {
		sh_type   = s->s_shdr.s_shdr32.sh_type;
		sh_offset = (uint64_t) s->s_shdr.s_shdr32.sh_offset;
		sh_size   = (uint64_t) s->s_shdr.s_shdr32.sh_size;
		sh_align  = (uint64_t) s->s_shdr.s_shdr32.sh_addralign;
	} else {
		sh_type   = s->s_shdr.s_shdr64.sh_type;
		sh_offset = s->s_shdr.s_shdr64.sh_offset;
		sh_size   = s->s_shdr.s_shdr64.sh_size;
		sh_align  = s->s_shdr.s_shdr64.sh_addralign;
	}

	if ((d = _libelf_allocate_data(s)) == NULL)
		return (NULL);

	d->d_buf     = sh_type == SHT_NOBITS ? NULL : e->e_rawfile + sh_offset;
	d->d_off     = 0;
	d->d_align   = sh_align;
	d->d_size    = sh_size;
	d->d_type    = ELF_T_BYTE;
	d->d_version = e->e_version;

	STAILQ_INSERT_TAIL(&s->s_rawdata, d, d_next);

	return (d);
}
Beispiel #7
0
int
elf_setshstrndx(Elf *e, size_t strndx)
{
    void *eh;
    int ec;

    if (e == NULL || e->e_kind != ELF_K_ELF ||
            ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64) ||
            ((eh = _libelf_ehdr(e, ec, 0)) == NULL)) {
        LIBELF_SET_ERROR(ARGUMENT, 0);
        return (0);
    }

    return (_libelf_setshstrndx(e, eh, ec, strndx));
}
Beispiel #8
0
off_t
elf_rand(Elf *ar, off_t offset)
{
	struct ar_hdr *arh;

	if (ar == NULL || ar->e_kind != ELF_K_AR ||
	    (offset & 1) || offset < SARMAG ||
	    offset + sizeof(struct ar_hdr) >= ar->e_rawsize) {
		LIBELF_SET_ERROR(ARGUMENT, 0);
		return 0;
	}

	arh = (struct ar_hdr *) (ar->e_rawfile + offset);

	/* a too simple sanity check */
	if (arh->ar_fmag[0] != '`' || arh->ar_fmag[1] != '\n') {
		LIBELF_SET_ERROR(ARCHIVE, 0);
		return 0;
	}

	ar->e_u.e_ar.e_next = offset;

	return (offset);
}
Beispiel #9
0
Elf_Arhdr *
elf_getarhdr(Elf *e)
{
	Elf_Arhdr *arh;

	if (e == NULL) {
		LIBELF_SET_ERROR(ARGUMENT, 0);
		return (NULL);
	}

	if ((arh = e->e_arhdr) != NULL)
		return (arh);

	return (_libelf_ar_gethdr(e));
}
Beispiel #10
0
/*
 * Retrieve a string from a name field.  If `rawname' is set, leave
 * ar(1) control characters in.
 */
char *
_libelf_ar_get_string(const char *buf, size_t bufsize, int rawname)
{
	const char *q;
	char *r;
	size_t sz;

	if (rawname)
		sz = bufsize + 1;
	else {
		/* Skip back over trailing blanks. */
		for (q = buf + bufsize - 1; q >= buf && *q == ' '; --q)
			;

		if (q < buf) {
			/*
			 * If the input buffer only had blanks in it,
			 * return a zero-length string.
			 */
			buf = "";
			sz = 1;
		} else {
			/*
			 * Remove the trailing '/' character, but only
			 * if the name isn't one of the special names
			 * "/" and "//".
			 */
			if (q > buf + 1 ||
			    (q == (buf + 1) && *buf != '/'))
				q--;

			sz = q - buf + 2; /* Space for a trailing NUL. */
		}
	}

	if ((r = malloc(sz)) == NULL) {
		LIBELF_SET_ERROR(RESOURCE, 0);
		return (NULL);
	}

	(void) strncpy(r, buf, sz);
	r[sz - 1] = '\0';

	return (r);
}
Beispiel #11
0
unsigned int
elf_version(unsigned int v)
{
	unsigned int old;

	if ((old = LIBELF_PRIVATE(version)) == EV_NONE)
		old = EV_CURRENT;

	if (v == EV_NONE)
		return old;
	if (v > EV_CURRENT) {
		LIBELF_SET_ERROR(VERSION, 0);
		return EV_NONE;
	}

	LIBELF_PRIVATE(version) = v;
	return (old);
}
Beispiel #12
0
GElf_Ehdr *
gelf_getehdr(Elf *e, GElf_Ehdr *d)
{
	int ec;
	Elf32_Ehdr *eh32;
	Elf64_Ehdr *eh64;

	if (d == NULL || e == NULL ||
	    ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) {
		LIBELF_SET_ERROR(ARGUMENT, 0);
		return (NULL);
	}

	if (ec == ELFCLASS32) {
		if ((eh32 = _libelf_ehdr(e, ELFCLASS32, 0)) == NULL)
			return (NULL);

		(void) memcpy(d->e_ident, eh32->e_ident,
		    sizeof(eh32->e_ident));
		d->e_type		= eh32->e_type;
		d->e_machine		= eh32->e_machine;
		d->e_version		= eh32->e_version;
		d->e_entry		= eh32->e_entry;
		d->e_phoff		= eh32->e_phoff;
		d->e_shoff		= eh32->e_shoff;
		d->e_flags		= eh32->e_flags;
		d->e_ehsize		= eh32->e_ehsize;
		d->e_phentsize		= eh32->e_phentsize;
		d->e_phnum		= eh32->e_phnum;
		d->e_shentsize		= eh32->e_shentsize;
		d->e_shnum		= eh32->e_shnum;
		d->e_shstrndx		= eh32->e_shstrndx;

		return (d);
	}

	assert(ec == ELFCLASS64);

	if ((eh64 = _libelf_ehdr(e, ELFCLASS64, 0)) == NULL)
		return (NULL);
	*d = *eh64;

	return (d);
}
static int
_libelf_getshdrnum(Elf *e, size_t *shnum)
{
	void *eh;
	int ec;

	if (e == NULL || e->e_kind != ELF_K_ELF ||
	    ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) {
		LIBELF_SET_ERROR(ARGUMENT, 0);
		return (-1);
	}

	if ((eh = _libelf_ehdr(e, ec, 0)) == NULL)
		return (-1);

	*shnum = e->e_u.e_elf.e_nscn;

	return (0);
}
Beispiel #14
0
Elf *
_libelf_ar_open_member(int fd, Elf_Cmd c, Elf *elf)
{
	Elf *e;
	off_t next;
	struct ar_hdr *arh;
	size_t sz;

	assert(elf->e_kind == ELF_K_AR);

	next = elf->e_u.e_ar.e_next;

	/*
	 * `next' is only set to zero by elf_next() when the last
	 * member of an archive is processed.
	 */
	if (next == (off_t) 0)
		return (NULL);

	assert((next & 1) == 0);

	arh = (struct ar_hdr *) (elf->e_rawfile + next);

	if (_libelf_ar_get_number(arh->ar_size, sizeof(arh->ar_size), 10, &sz) == 0) {
		LIBELF_SET_ERROR(ARCHIVE, 0);
		return (NULL);
	}

	assert(sz > 0);

	arh++;	/* skip over archive member header */

	if ((e = elf_memory((char *) arh, sz)) == NULL)
		return (NULL);

	e->e_fd = fd;
	e->e_cmd = c;

	elf->e_u.e_ar.e_nchildren++;
	e->e_parent = elf;

	return (e);
}
Beispiel #15
0
unsigned int
elf_flagscn(Elf_Scn *s, Elf_Cmd c, unsigned int flags)
{
	int r;

	if (s == NULL)
		return (0);

	if ((c != ELF_C_SET && c != ELF_C_CLR) ||
	    (flags & ~ELF_F_DIRTY) != 0) {
		LIBELF_SET_ERROR(ARGUMENT, 0);
		return (0);
	}

	if (c == ELF_C_SET)
		r = s->s_flags |= flags;
	else
		r = s->s_flags &= ~flags;
	return (r);
}
Beispiel #16
0
unsigned int
elf_flagelf(Elf *e, Elf_Cmd c, unsigned int flags)
{
	int r;

	if (e == NULL)
		return (0);

	if ((c != ELF_C_SET && c != ELF_C_CLR) ||
	    (e->e_kind != ELF_K_ELF) ||
	    (flags & ~(ELF_F_DIRTY|ELF_F_LAYOUT)) != 0) {
		LIBELF_SET_ERROR(ARGUMENT, 0);
		return (0);
	}

	if (c == ELF_C_SET)
		r = e->e_flags |= flags;
	else
		r = e->e_flags &= ~flags;
	return (r);
}
Beispiel #17
0
unsigned int
elf_flagarhdr(Elf_Arhdr *a, Elf_Cmd c, unsigned int flags)
{
	unsigned int r;

	if (a == NULL)
		return (0);

	if ((c != ELF_C_SET && c != ELF_C_CLR) ||
	    (flags & ~ELF_F_DIRTY) != 0) {
		LIBELF_SET_ERROR(ARGUMENT, 0);
		return (0);
	}

	if (c == ELF_C_SET)
		r = a->ar_flags |= flags;
	else
		r = a->ar_flags &= ~flags;

	return (r & LIBELF_F_API_MASK);
}
Beispiel #18
0
GElf_Shdr *
gelf_getshdr(Elf_Scn *s, GElf_Shdr *d)
{
	int ec;
	void *sh;
	Elf32_Shdr *sh32;
	Elf64_Shdr *sh64;

	if (d == NULL) {
		LIBELF_SET_ERROR(ARGUMENT, 0);
		return (NULL);
	}

	if ((sh = _libelf_getshdr(s, ELFCLASSNONE)) == NULL)
		return (NULL);

	ec = s->s_elf->e_class;
	assert(ec == ELFCLASS32 || ec == ELFCLASS64);

	if (ec == ELFCLASS32) {
		sh32 = (Elf32_Shdr *) sh;

		d->sh_name      = sh32->sh_name;
		d->sh_type      = sh32->sh_type;
		d->sh_flags     = (Elf64_Xword) sh32->sh_flags;
		d->sh_addr      = (Elf64_Addr) sh32->sh_addr;
		d->sh_offset    = (Elf64_Off) sh32->sh_offset;
		d->sh_size      = (Elf64_Xword) sh32->sh_size;
		d->sh_link      = sh32->sh_link;
		d->sh_info      = sh32->sh_info;
		d->sh_addralign = (Elf64_Xword) sh32->sh_addralign;
		d->sh_entsize   = (Elf64_Xword) sh32->sh_entsize;
	} else {
		sh64 = (Elf64_Shdr *) sh;
		*d = *sh64;
	}

	return (d);
}
Elf_Data *
elf_newdata(Elf_Scn *s)
{
	Elf *e;
	struct _Libelf_Data *d;

	if (s == NULL || (e = s->s_elf) == NULL) {
		LIBELF_SET_ERROR(ARGUMENT, 0);
		return (NULL);
	}

	assert(e->e_kind == ELF_K_ELF);

	/*
	 * elf_newdata() has to append a data descriptor, so
	 * bring in existing section data if not already present.
	 */
	if (e->e_rawfile && s->s_size > 0 && STAILQ_EMPTY(&s->s_data))
		if (elf_getdata(s, NULL) == NULL)
			return (NULL);

	if ((d = _libelf_allocate_data(s)) == NULL)
		return (NULL);

	STAILQ_INSERT_TAIL(&s->s_data, d, d_next);

	d->d_data.d_align = 1;
	d->d_data.d_buf = NULL;
	d->d_data.d_off = (uint64_t) ~0;
	d->d_data.d_size = 0;
	d->d_data.d_type = ELF_T_BYTE;
	d->d_data.d_version = LIBELF_PRIVATE(version);

	(void) elf_flagscn(s, ELF_C_SET, ELF_F_DIRTY);

	return (&d->d_data);
}
Beispiel #20
0
unsigned int
elf_flagdata(Elf_Data *d, Elf_Cmd c, unsigned int flags)
{
	unsigned int r;
	struct _Libelf_Data *ld;

	if (d == NULL)
		return (0);

	if ((c != ELF_C_SET && c != ELF_C_CLR) ||
	    (flags & ~ELF_F_DIRTY) != 0) {
		LIBELF_SET_ERROR(ARGUMENT, 0);
		return (0);
	}

	ld = (struct _Libelf_Data *) d;

	if (c == ELF_C_SET)
		r = ld->d_flags |= flags;
	else
		r = ld->d_flags &= ~flags;

	return (r & LIBELF_F_API_MASK);
}
Beispiel #21
0
unsigned int
elf_flagdata(Elf_Data *d, Elf_Cmd c, unsigned int flags)
{
	Elf *e;
	Elf_Scn *scn;
	unsigned int r;

	if (d == NULL)
		return (0);

	if ((c != ELF_C_SET && c != ELF_C_CLR) || (scn = d->d_scn) == NULL ||
	    (e = scn->s_elf) == NULL || e->e_kind != ELF_K_ELF ||
	    (flags & ~ELF_F_DIRTY) != 0) {
		LIBELF_SET_ERROR(ARGUMENT, 0);
		return (0);
	}

	if (c == ELF_C_SET)
	    r = scn->s_flags |= flags;
	else
	    r = scn->s_flags &= ~flags;

	return (r);
}
Beispiel #22
0
void *
_libelf_ehdr(Elf *e, int ec, int allocate)
{
    void *ehdr;
    size_t fsz, msz;
    uint16_t phnum, shnum, strndx;
    uint64_t shoff;
    int (*xlator)(unsigned char *_d, size_t _dsz, unsigned char *_s,
                  size_t _c, int _swap);

    assert(ec == ELFCLASS32 || ec == ELFCLASS64);

    if (e == NULL || e->e_kind != ELF_K_ELF) {
        LIBELF_SET_ERROR(ARGUMENT, 0);
        return (NULL);
    }

    if (e->e_class != ELFCLASSNONE && e->e_class != ec) {
        LIBELF_SET_ERROR(CLASS, 0);
        return (NULL);
    }

    if (e->e_version != EV_CURRENT) {
        LIBELF_SET_ERROR(VERSION, 0);
        return (NULL);
    }

    if (e->e_class == ELFCLASSNONE)
        e->e_class = ec;

    if (ec == ELFCLASS32)
        ehdr = (void *) e->e_u.e_elf.e_ehdr.e_ehdr32;
    else
        ehdr = (void *) e->e_u.e_elf.e_ehdr.e_ehdr64;

    if (ehdr != NULL)	/* already have a translated ehdr */
        return (ehdr);

    fsz = _libelf_fsize(ELF_T_EHDR, ec, e->e_version, (size_t) 1);
    assert(fsz > 0);

    if (e->e_cmd != ELF_C_WRITE && e->e_rawsize < fsz) {
        LIBELF_SET_ERROR(HEADER, 0);
        return (NULL);
    }

    msz = _libelf_msize(ELF_T_EHDR, ec, EV_CURRENT);

    assert(msz > 0);

    if ((ehdr = calloc((size_t) 1, msz)) == NULL) {
        LIBELF_SET_ERROR(RESOURCE, 0);
        return (NULL);
    }

    if (ec == ELFCLASS32) {
        e->e_u.e_elf.e_ehdr.e_ehdr32 = ehdr;
        EHDR_INIT(ehdr,32);
    } else {
        e->e_u.e_elf.e_ehdr.e_ehdr64 = ehdr;
        EHDR_INIT(ehdr,64);
    }

    if (allocate)
        e->e_flags |= ELF_F_DIRTY;

    if (e->e_cmd == ELF_C_WRITE)
        return (ehdr);

    xlator = _libelf_get_translator(ELF_T_EHDR, ELF_TOMEMORY, ec);
    (*xlator)((unsigned char*) ehdr, msz, e->e_rawfile, (size_t) 1,
              e->e_byteorder != LIBELF_PRIVATE(byteorder));

    if (ec == ELFCLASS32) {
        phnum = ((Elf32_Ehdr *) ehdr)->e_phnum;
        shnum = ((Elf32_Ehdr *) ehdr)->e_shnum;
        shoff = ((Elf32_Ehdr *) ehdr)->e_shoff;
        strndx = ((Elf32_Ehdr *) ehdr)->e_shstrndx;
    } else {
        phnum = ((Elf64_Ehdr *) ehdr)->e_phnum;
        shnum = ((Elf64_Ehdr *) ehdr)->e_shnum;
        shoff = ((Elf64_Ehdr *) ehdr)->e_shoff;
        strndx = ((Elf64_Ehdr *) ehdr)->e_shstrndx;
    }

    if (shnum >= SHN_LORESERVE ||
            (shoff == 0LL && (shnum != 0 || phnum == PN_XNUM ||
                              strndx == SHN_XINDEX))) {
        LIBELF_SET_ERROR(HEADER, 0);
        return (NULL);
    }

    /*
     * If extended numbering is being used, read the correct
     * number of sections and program header entries.
     */
    if ((shnum == 0 && shoff != 0) || phnum == PN_XNUM || strndx == SHN_XINDEX) {
        if (_libelf_load_extended(e, ec, shoff, phnum, strndx) == 0)
            return (NULL);
    } else {
        /* not using extended numbering */
        e->e_u.e_elf.e_nphdr = phnum;
        e->e_u.e_elf.e_nscn = shnum;
        e->e_u.e_elf.e_strndx = strndx;
    }

    return (ehdr);
}
Elf_Data *
elf_getdata(Elf_Scn *s, Elf_Data *ed)
{
	Elf *e;
	unsigned int sh_type;
	int elfclass, elftype;
	size_t fsz, msz, count;
	struct _Libelf_Data *d;
	uint64_t sh_align, sh_offset, sh_size;
	int (*xlate)(char *_d, size_t _dsz, char *_s, size_t _c, int _swap);

	d = (struct _Libelf_Data *) ed;

	if (s == NULL || (e = s->s_elf) == NULL ||
	    (d != NULL && s != d->d_scn)) {
		LIBELF_SET_ERROR(ARGUMENT, 0);
		return (NULL);
	}

	assert(e->e_kind == ELF_K_ELF);

	if (d == NULL && (d = STAILQ_FIRST(&s->s_data)) != NULL)
		return (&d->d_data);

	if (d != NULL)
		return (&STAILQ_NEXT(d, d_next)->d_data);

	if (e->e_rawfile == NULL) {
		/*
		 * In the ELF_C_WRITE case, there is no source that
		 * can provide data for the section.
		 */
		LIBELF_SET_ERROR(ARGUMENT, 0);
		return (NULL);
	}

	elfclass = e->e_class;

	assert(elfclass == ELFCLASS32 || elfclass == ELFCLASS64);

	if (elfclass == ELFCLASS32) {
		sh_type   = s->s_shdr.s_shdr32.sh_type;
		sh_offset = (uint64_t) s->s_shdr.s_shdr32.sh_offset;
		sh_size   = (uint64_t) s->s_shdr.s_shdr32.sh_size;
		sh_align  = (uint64_t) s->s_shdr.s_shdr32.sh_addralign;
	} else {
		sh_type   = s->s_shdr.s_shdr64.sh_type;
		sh_offset = s->s_shdr.s_shdr64.sh_offset;
		sh_size   = s->s_shdr.s_shdr64.sh_size;
		sh_align  = s->s_shdr.s_shdr64.sh_addralign;
	}

	if (sh_type == SHT_NULL) {
		LIBELF_SET_ERROR(SECTION, 0);
		return (NULL);
	}

	if ((elftype = _libelf_xlate_shtype(sh_type)) < ELF_T_FIRST ||
	    elftype > ELF_T_LAST || (sh_type != SHT_NOBITS &&
	    sh_offset + sh_size > (uint64_t) e->e_rawsize)) {
		LIBELF_SET_ERROR(SECTION, 0);
		return (NULL);
	}

	if ((fsz = (elfclass == ELFCLASS32 ? elf32_fsize : elf64_fsize)
            (elftype, (size_t) 1, e->e_version)) == 0) {
		LIBELF_SET_ERROR(UNIMPL, 0);
		return (NULL);
	}

	if (sh_size % fsz) {
		LIBELF_SET_ERROR(SECTION, 0);
		return (NULL);
	}

	count = sh_size / fsz;

	msz = _libelf_msize(elftype, elfclass, e->e_version);

	assert(msz > 0);

	if ((d = _libelf_allocate_data(s)) == NULL)
		return (NULL);

	d->d_data.d_buf     = NULL;
	d->d_data.d_off     = 0;
	d->d_data.d_align   = sh_align;
	d->d_data.d_size    = msz * count;
	d->d_data.d_type    = elftype;
	d->d_data.d_version = e->e_version;

	if (sh_type == SHT_NOBITS || sh_size == 0) {
	        STAILQ_INSERT_TAIL(&s->s_data, d, d_next);
		return (&d->d_data);
        }

	if ((d->d_data.d_buf = malloc(msz*count)) == NULL) {
		(void) _libelf_release_data(d);
		LIBELF_SET_ERROR(RESOURCE, 0);
		return (NULL);
	}

	d->d_flags  |= LIBELF_F_DATA_MALLOCED;

	xlate = _libelf_get_translator(elftype, ELF_TOMEMORY, elfclass);
	if (!(*xlate)(d->d_data.d_buf, d->d_data.d_size,
	    e->e_rawfile + sh_offset, count,
	    e->e_byteorder != LIBELF_PRIVATE(byteorder))) {
		_libelf_release_data(d);
		LIBELF_SET_ERROR(DATA, 0);
		return (NULL);
	}

	STAILQ_INSERT_TAIL(&s->s_data, d, d_next);

	return (&d->d_data);
}
Beispiel #24
0
Elf_Data *
_libelf_xlate(Elf_Data *dst, const Elf_Data *src, unsigned int encoding,
              int elfclass, int direction)
{
    int byteswap;
    size_t cnt, dsz, fsz, msz;
    uintptr_t sb, se, db, de;

    if (encoding == ELFDATANONE)
        encoding = LIBELF_PRIVATE(byteorder);

    if ((encoding != ELFDATA2LSB && encoding != ELFDATA2MSB) ||
            dst == NULL || src == NULL || dst == src)	{
        LIBELF_SET_ERROR(ARGUMENT, 0);
        return (NULL);
    }

    assert(elfclass == ELFCLASS32 || elfclass == ELFCLASS64);
    assert(direction == ELF_TOFILE || direction == ELF_TOMEMORY);

    if (dst->d_version != src->d_version) {
        LIBELF_SET_ERROR(UNIMPL, 0);
        return (NULL);
    }

    if  (src->d_buf == NULL || dst->d_buf == NULL) {
        LIBELF_SET_ERROR(DATA, 0);
        return (NULL);
    }

    if ((int) src->d_type < 0 || src->d_type >= ELF_T_NUM) {
        LIBELF_SET_ERROR(DATA, 0);
        return (NULL);
    }

    if ((fsz = (elfclass == ELFCLASS32 ? elf32_fsize : elf64_fsize)
               (src->d_type, (size_t) 1, src->d_version)) == 0)
        return (NULL);

    msz = _libelf_msize(src->d_type, elfclass, src->d_version);

    assert(msz > 0);

    if (src->d_size % (direction == ELF_TOMEMORY ? fsz : msz)) {
        LIBELF_SET_ERROR(DATA, 0);
        return (NULL);
    }

    /*
     * Determine the number of objects that need to be converted, and
     * the space required for the converted objects in the destination
     * buffer.
     */
    if (direction == ELF_TOMEMORY) {
        cnt = src->d_size / fsz;
        dsz = cnt * msz;
    } else {
        cnt = src->d_size / msz;
        dsz = cnt * fsz;
    }

    if (dst->d_size  <  dsz) {
        LIBELF_SET_ERROR(DATA, 0);
        return (NULL);
    }

    sb = (uintptr_t) src->d_buf;
    se = sb + src->d_size;
    db = (uintptr_t) dst->d_buf;
    de = db + dst->d_size;

    /*
     * Check for overlapping buffers.  Note that db == sb is
     * allowed.
     */
    if (db != sb && de > sb && se > db) {
        LIBELF_SET_ERROR(DATA, 0);
        return (NULL);
    }

    if ((direction == ELF_TOMEMORY ? db : sb) %
            _libelf_malign(src->d_type, elfclass)) {
        LIBELF_SET_ERROR(DATA, 0);
        return (NULL);
    }

    dst->d_type = src->d_type;
    dst->d_size = dsz;

    byteswap = encoding != LIBELF_PRIVATE(byteorder);

    if (src->d_size == 0 ||
            (db == sb && !byteswap && fsz == msz))
        return (dst);	/* nothing more to do */

    if (!(_libelf_get_translator(src->d_type, direction, elfclass))
            (dst->d_buf, dsz, src->d_buf, cnt, byteswap)) {
        LIBELF_SET_ERROR(DATA, 0);
        return (NULL);
    }

    return (dst);
}
Beispiel #25
0
Elf *
elf_begin(int fd, Elf_Cmd c, Elf *a)
{
        Elf *e;

        e = NULL;

        if (LIBELF_PRIVATE(version) == EV_NONE) {
                LIBELF_SET_ERROR(SEQUENCE, 0);
                return (NULL);
        }

        switch (c) {
        case ELF_C_NULL:
                return (NULL);

        case ELF_C_WRITE:

                if (a != NULL) { /* not allowed for ar(1) archives. */
                        LIBELF_SET_ERROR(ARGUMENT, 0);
                        return (NULL);
                }

                /*
                 * Check writeability of `fd' immediately and fail if
                 * not writeable.
                 */
                if (ftruncate(fd, (off_t) 0) < 0) {
                        LIBELF_SET_ERROR(IO, errno);
                        return (NULL);
                }

                if ((e = _libelf_allocate_elf()) != NULL) {
                        _libelf_init_elf(e, ELF_K_ELF);
                        e->e_byteorder = LIBELF_PRIVATE(byteorder);
                        e->e_fd = fd;
                        e->e_cmd = c;
                }
                return (e);

        case ELF_C_RDWR:
                if (a != NULL) { /* not allowed for ar(1) archives. */
                        LIBELF_SET_ERROR(ARGUMENT, 0);
                        return (NULL);
                }
                /*FALLTHROUGH*/
        case ELF_C_READ:
                /*
                 * Descriptor `a' could be for a regular ELF file, or
                 * for an ar(1) archive.
                 */
                if (a && (a->e_fd != fd || c != a->e_cmd)) {
                        LIBELF_SET_ERROR(ARGUMENT, 0);
                        return (NULL);
                }

                break;

        default:
                LIBELF_SET_ERROR(ARGUMENT, 0);
                return (NULL);

        }

        if (a == NULL)
                e = _libelf_open_object(fd, c);
        else if (a->e_kind == ELF_K_AR)
                e = _libelf_ar_open_member(fd, c, a);
        else
                (e = a)->e_activations++;

        return (e);
}
Beispiel #26
0
void *
_libelf_getphdr(Elf *e, int ec)
{
	size_t phnum;
	size_t fsz, msz;
	uint64_t phoff;
	Elf32_Ehdr *eh32;
	Elf64_Ehdr *eh64;
	void *ehdr, *phdr;
	void (*xlator)(char *_d, char *_s, size_t _c, int _swap);

	assert(ec == ELFCLASS32 || ec == ELFCLASS64);

	if (e == NULL) {
		LIBELF_SET_ERROR(ARGUMENT, 0);
		return (NULL);
	}

	if ((phdr = (ec == ELFCLASS32 ?
		 (void *) e->e_u.e_elf.e_phdr.e_phdr32 :
		 (void *) e->e_u.e_elf.e_phdr.e_phdr64)) != NULL)
		return (phdr);

	/*
	 * Check the PHDR related fields in the EHDR for sanity.
	 */

	if ((ehdr = _libelf_ehdr(e, ec, 0)) == NULL)
		return (NULL);

	phnum = e->e_u.e_elf.e_nphdr;

	if (ec == ELFCLASS32) {
		eh32      = (Elf32_Ehdr *) ehdr;
		phoff     = (uint64_t) eh32->e_phoff;
	} else {
		eh64      = (Elf64_Ehdr *) ehdr;
		phoff     = (uint64_t) eh64->e_phoff;
	}

	fsz = gelf_fsize(e, ELF_T_PHDR, phnum, e->e_version);

	assert(fsz > 0);

	if ((uint64_t) e->e_rawsize < (phoff + fsz)) {
		LIBELF_SET_ERROR(HEADER, 0);
		return (NULL);
	}

	msz = _libelf_msize(ELF_T_PHDR, ec, EV_CURRENT);

	assert(msz > 0);

	if ((phdr = calloc(phnum, msz)) == NULL) {
		LIBELF_SET_ERROR(RESOURCE, 0);
		return (NULL);
	}

	if (ec == ELFCLASS32)
		e->e_u.e_elf.e_phdr.e_phdr32 = phdr;
	else
		e->e_u.e_elf.e_phdr.e_phdr64 = phdr;


	xlator = _libelf_get_translator(ELF_T_PHDR, ELF_TOMEMORY, ec);
	(*xlator)(phdr, e->e_rawfile + phoff, phnum,
	    e->e_byteorder != _libelf_host_byteorder());

	return (phdr);
}
Beispiel #27
0
/*
 * Read from a device file, pipe or socket.
 */
static void *
_libelf_read_special_file(int fd, size_t *fsz)
{
	ssize_t readsz;
	size_t bufsz, datasz;
	unsigned char *buf, *t;

	datasz = 0;
	readsz = 0;
	bufsz = _LIBELF_INITSIZE;
	if ((buf = malloc(bufsz)) == NULL)
		goto resourceerror;

	/*
	 * Read data from the file descriptor till we reach EOF, or
	 * till an error is encountered.
	 */
	do {
		/* Check if we need to expand the data buffer. */
		if (datasz == bufsz) {
			bufsz *= 2;
			if ((t = realloc(buf, bufsz)) == NULL)
				goto resourceerror;
			buf = t;
		}

		do {
			readsz = bufsz - datasz;
			t = buf + datasz;
			if ((readsz = read(fd, t, readsz)) <= 0)
				break;
			datasz += readsz;
		} while (datasz < bufsz);

	} while (readsz > 0);

	if (readsz < 0) {
		LIBELF_SET_ERROR(IO, errno);
		goto error;
	}

	assert(readsz == 0);

	/*
	 * Free up extra buffer space.
	 */
	if (bufsz > datasz) {
		if (datasz > 0) {
			if ((t = realloc(buf, datasz)) == NULL)
				goto resourceerror;
			buf = t;
		} else {	/* Zero bytes read. */
			LIBELF_SET_ERROR(ARGUMENT, 0);
			free(buf);
			buf = NULL;
		}
	}

	*fsz = datasz;
	return (buf);

resourceerror:
	LIBELF_SET_ERROR(RESOURCE, 0);
error:
	if (buf != NULL)
		free(buf);
	return (NULL);
}
Beispiel #28
0
Elf *
_libelf_open_object(int fd, Elf_Cmd c, int reporterror)
{
	Elf *e;
	void *m;
	mode_t mode;
	size_t fsize;
	struct stat sb;
	unsigned int flags;

	assert(c == ELF_C_READ || c == ELF_C_RDWR || c == ELF_C_WRITE);

	if (fstat(fd, &sb) < 0) {
		LIBELF_SET_ERROR(IO, errno);
		return (NULL);
	}

	mode = sb.st_mode;
	fsize = (size_t) sb.st_size;

	/*
	 * Reject unsupported file types.
	 */
	if (!S_ISREG(mode) && !S_ISCHR(mode) && !S_ISFIFO(mode) &&
	    !S_ISSOCK(mode)) {
		LIBELF_SET_ERROR(ARGUMENT, 0);
		return (NULL);
	}

	/*
	 * For ELF_C_WRITE mode, allocate and return a descriptor.
	 */
	if (c == ELF_C_WRITE) {
		if ((e = _libelf_allocate_elf()) != NULL) {
			_libelf_init_elf(e, ELF_K_ELF);
			e->e_byteorder = LIBELF_PRIVATE(byteorder);
			e->e_fd = fd;
			e->e_cmd = c;
			if (!S_ISREG(mode))
				e->e_flags |= LIBELF_F_SPECIAL_FILE;
		}

		return (e);
	}


	/*
	 * ELF_C_READ and ELF_C_RDWR mode.
	 */
	m = NULL;
	flags = 0;
	if (S_ISREG(mode)) {

		/*
		 * Reject zero length files.
		 */
		if (fsize == 0) {
			LIBELF_SET_ERROR(ARGUMENT, 0);
			return (NULL);
		}

#if	ELFTC_HAVE_MMAP
		/*
		 * Always map regular files in with 'PROT_READ'
		 * permissions.
		 *
		 * For objects opened in ELF_C_RDWR mode, when
		 * elf_update(3) is called, we remove this mapping,
		 * write file data out using write(2), and map the new
		 * contents back.
		 */
		m = mmap(NULL, fsize, PROT_READ, MAP_PRIVATE, fd, (off_t) 0);

		if (m == MAP_FAILED)
			m = NULL;
		else
			flags = LIBELF_F_RAWFILE_MMAP;
#endif

		/*
		 * Fallback to a read() if the call to mmap() failed,
		 * or if mmap() is not available.
		 */
		if (m == NULL) {
			if ((m = malloc(fsize)) == NULL) {
				LIBELF_SET_ERROR(RESOURCE, 0);
				return (NULL);
			}

			if (read(fd, m, fsize) != (ssize_t) fsize) {
				LIBELF_SET_ERROR(IO, errno);
				free(m);
				return (NULL);
			}

			flags = LIBELF_F_RAWFILE_MALLOC;
		}
	} else if ((m = _libelf_read_special_file(fd, &fsize)) != NULL)
		flags = LIBELF_F_RAWFILE_MALLOC | LIBELF_F_SPECIAL_FILE;
	else
		return (NULL);

	if ((e = _libelf_memory(m, fsize, reporterror)) == NULL) {
		assert((flags & LIBELF_F_RAWFILE_MALLOC) ||
		    (flags & LIBELF_F_RAWFILE_MMAP));
		if (flags & LIBELF_F_RAWFILE_MALLOC)
			free(m);
#if	ELFTC_HAVE_MMAP
		else
			(void) munmap(m, fsize);
#endif
		return (NULL);
	}

	/* ar(1) archives aren't supported in RDWR mode. */
	if (c == ELF_C_RDWR && e->e_kind == ELF_K_AR) {
		(void) elf_end(e);
		LIBELF_SET_ERROR(ARGUMENT, 0);
		return (NULL);
	}

	e->e_flags |= flags;
	e->e_fd = fd;
	e->e_cmd = c;

	return (e);
}
Beispiel #29
0
GElf_Sym *
gelf_getsym(Elf_Data *ed, int ndx, GElf_Sym *dst)
{
    int ec;
    Elf *e;
    size_t msz;
    Elf_Scn *scn;
    uint32_t sh_type;
    Elf32_Sym *sym32;
    Elf64_Sym *sym64;
    struct _Libelf_Data *d;

    d = (struct _Libelf_Data *) ed;

    if (d == NULL || ndx < 0 || dst == NULL ||
            (scn = d->d_scn) == NULL ||
            (e = scn->s_elf) == NULL) {
        LIBELF_SET_ERROR(ARGUMENT, 0);
        return (NULL);
    }

    ec = e->e_class;
    assert(ec == ELFCLASS32 || ec == ELFCLASS64);

    if (ec == ELFCLASS32)
        sh_type = scn->s_shdr.s_shdr32.sh_type;
    else
        sh_type = scn->s_shdr.s_shdr64.sh_type;

    if (_libelf_xlate_shtype(sh_type) != ELF_T_SYM) {
        LIBELF_SET_ERROR(ARGUMENT, 0);
        return (NULL);
    }

    msz = _libelf_msize(ELF_T_SYM, ec, e->e_version);

    assert(msz > 0);
    assert(ndx >= 0);

    if (msz * (size_t) ndx >= d->d_data.d_size) {
        LIBELF_SET_ERROR(ARGUMENT, 0);
        return (NULL);
    }

    if (ec == ELFCLASS32) {
        sym32 = (Elf32_Sym *) d->d_data.d_buf + ndx;

        dst->st_name  = sym32->st_name;
        dst->st_value = (Elf64_Addr) sym32->st_value;
        dst->st_size  = (Elf64_Xword) sym32->st_size;
        dst->st_info  = sym32->st_info;
        dst->st_other = sym32->st_other;
        dst->st_shndx = sym32->st_shndx;
    } else {
        sym64 = (Elf64_Sym *) d->d_data.d_buf + ndx;

        *dst = *sym64;
    }

    return (dst);
}
Beispiel #30
0
int
gelf_update_sym(Elf_Data *ed, int ndx, GElf_Sym *gs)
{
    int ec;
    Elf *e;
    size_t msz;
    Elf_Scn *scn;
    uint32_t sh_type;
    Elf32_Sym *sym32;
    Elf64_Sym *sym64;
    struct _Libelf_Data *d;

    d = (struct _Libelf_Data *) ed;

    if (d == NULL || ndx < 0 || gs == NULL ||
            (scn = d->d_scn) == NULL ||
            (e = scn->s_elf) == NULL) {
        LIBELF_SET_ERROR(ARGUMENT, 0);
        return (0);
    }

    ec = e->e_class;
    assert(ec == ELFCLASS32 || ec == ELFCLASS64);

    if (ec == ELFCLASS32)
        sh_type = scn->s_shdr.s_shdr32.sh_type;
    else
        sh_type = scn->s_shdr.s_shdr64.sh_type;

    if (_libelf_xlate_shtype(sh_type) != ELF_T_SYM) {
        LIBELF_SET_ERROR(ARGUMENT, 0);
        return (0);
    }

    msz = _libelf_msize(ELF_T_SYM, ec, e->e_version);

    assert(msz > 0);
    assert(ndx >= 0);

    if (msz * (size_t) ndx >= d->d_data.d_size) {
        LIBELF_SET_ERROR(ARGUMENT, 0);
        return (0);
    }

    if (ec == ELFCLASS32) {
        sym32 = (Elf32_Sym *) d->d_data.d_buf + ndx;

        sym32->st_name  = gs->st_name;
        sym32->st_info  = gs->st_info;
        sym32->st_other = gs->st_other;
        sym32->st_shndx = gs->st_shndx;

        LIBELF_COPY_U32(sym32, gs, st_value);
        LIBELF_COPY_U32(sym32, gs, st_size);
    } else {
        sym64 = (Elf64_Sym *) d->d_data.d_buf + ndx;

        *sym64 = *gs;
    }

    return (1);
}