Ejemplo n.º 1
0
int
elf_errno(void)
{
	int old;

	old = LIBELF_PRIVATE(error);
	LIBELF_PRIVATE(error) = 0;
	return (old & LIBELF_ELF_ERROR_MASK);
}
Ejemplo n.º 2
0
const char *
elf_errmsg(int error)
{
	int oserr;

	if (error == 0 && (error = LIBELF_PRIVATE(error)) == 0)
	    return NULL;
	else if (error == -1)
	    error = LIBELF_PRIVATE(error);

	oserr = error >> LIBELF_OS_ERROR_SHIFT;
	error &= LIBELF_ELF_ERROR_MASK;

	if (error < 0 || error >= ELF_E_NUM)
		return _libelf_errors[ELF_E_NUM];
	if (oserr) {
		strlcpy(LIBELF_PRIVATE(msg), _libelf_errors[error],
		    sizeof(LIBELF_PRIVATE(msg)));
		strlcat(LIBELF_PRIVATE(msg), ": ", sizeof(LIBELF_PRIVATE(msg)));
		strlcat(LIBELF_PRIVATE(msg), strerror(oserr),
		    sizeof(LIBELF_PRIVATE(msg)));
		return (const char *)&LIBELF_PRIVATE(msg);
	}
	return _libelf_errors[error];
}
Ejemplo n.º 3
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:
		/*
		 * The ELF_C_WRITE command is required to ignore the
		 * descriptor passed in.
		 */
		a = NULL;
		break;

	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 descriptor `a' was opened
		 * using a valid file descriptor, we need to check if
		 * the passed in `fd' value matches the original one.
		 */
		if (a &&
		    ((a->e_fd != -1 && 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(a->e_fd, c, a);
	else
		(e = a)->e_activations++;

	return (e);
}
Ejemplo n.º 4
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);
}
Ejemplo n.º 5
0
Elf *
elf_memory(char *image, size_t sz)
{
	Elf *e;

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

	if (image == NULL || sz == 0) {
		LIBELF_SET_ERROR(ARGUMENT, 0);
		return (NULL);
	}

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

	e->e_cmd = ELF_C_READ;
	e->e_rawfile = image;
	e->e_rawsize = sz;

#undef	LIBELF_IS_ELF
#define	LIBELF_IS_ELF(P) ((P)[EI_MAG0] == ELFMAG0 && 		\
	(P)[EI_MAG1] == ELFMAG1 && (P)[EI_MAG2] == ELFMAG2 &&	\
	(P)[EI_MAG3] == ELFMAG3)

	if (sz > EI_NIDENT && LIBELF_IS_ELF(image)) {
		_libelf_init_elf(e, ELF_K_ELF);
		e->e_class = image[EI_CLASS];
		e->e_byteorder = image[EI_DATA];
		e->e_version = image[EI_VERSION];

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

		if ((e->e_byteorder != ELFDATA2LSB && e->e_byteorder !=
 		    ELFDATA2MSB) || (e->e_class != ELFCLASS32 && e->e_class !=
		    ELFCLASS64)) {
			e = _libelf_release_elf(e);
			LIBELF_SET_ERROR(HEADER, 0);
			return (NULL);
		}

	} else if (sz >= SARMAG &&
	    strncmp(image, ARMAG, (size_t) SARMAG) == 0) {
		_libelf_init_elf(e, ELF_K_AR);
		e = _libelf_ar_open(e);
	} else
		_libelf_init_elf(e, ELF_K_NONE);

	return (e);
}
Ejemplo n.º 6
0
Elf *
_libelf_memory(char *image, size_t sz, int reporterror)
{
	Elf *e;
	int e_class;
	enum Elf_Error error;
	unsigned int e_byteorder, e_version;

	assert(image != NULL);
	assert(sz > 0);

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

	e->e_cmd = ELF_C_READ;
	e->e_rawfile = image;
	e->e_rawsize = sz;

#undef	LIBELF_IS_ELF
#define	LIBELF_IS_ELF(P) ((P)[EI_MAG0] == ELFMAG0 && 		\
	(P)[EI_MAG1] == ELFMAG1 && (P)[EI_MAG2] == ELFMAG2 &&	\
	(P)[EI_MAG3] == ELFMAG3)

	if (sz > EI_NIDENT && LIBELF_IS_ELF(image)) {
		e_byteorder = image[EI_DATA];
		e_class     = image[EI_CLASS];
		e_version   = image[EI_VERSION];

		error = ELF_E_NONE;

		if (e_version > EV_CURRENT)
			error = ELF_E_VERSION;
		else if ((e_byteorder != ELFDATA2LSB && e_byteorder !=
 		    ELFDATA2MSB) || (e_class != ELFCLASS32 && e_class !=
		    ELFCLASS64))
			error = ELF_E_HEADER;

		if (error != ELF_E_NONE) {
			if (reporterror) {
				LIBELF_PRIVATE(error) = LIBELF_ERROR(error, 0);
				(void) _libelf_release_elf(e);
				return (NULL);
			}
		} else {
			_libelf_init_elf(e, ELF_K_ELF);

			e->e_byteorder = e_byteorder;
			e->e_class = e_class;
			e->e_version = e_version;
		}
	} else if (sz >= SARMAG &&
	    strncmp(image, ARMAG, (size_t) SARMAG) == 0)
		return (_libelf_ar_open(e, reporterror));

	return (e);
}
Ejemplo n.º 7
0
Elf *
elf_memory(char *image, size_t sz)
{
	if (LIBELF_PRIVATE(version) == EV_NONE) {
		LIBELF_SET_ERROR(SEQUENCE, 0);
		return (NULL);
	}

	if (image == NULL || sz == 0) {
		LIBELF_SET_ERROR(ARGUMENT, 0);
		return (NULL);
	}

	return (_libelf_memory(image, sz, 1));
}
Ejemplo n.º 8
0
const char *
elf_errmsg(int error)
{
	int oserr;

	if (error == ELF_E_NONE &&
	    (error = LIBELF_PRIVATE(error)) == 0)
	    return NULL;
	else if (error == -1)
	    error = LIBELF_PRIVATE(error);

	oserr = error >> LIBELF_OS_ERROR_SHIFT;
	error &= LIBELF_ELF_ERROR_MASK;

	if (error < ELF_E_NONE || error >= ELF_E_NUM)
		return _libelf_errors[ELF_E_NUM];
	if (oserr) {
		(void) snprintf(LIBELF_PRIVATE(msg),
		    sizeof(LIBELF_PRIVATE(msg)), "%s: %s",
		    _libelf_errors[error], strerror(oserr));
		return (const char *)&LIBELF_PRIVATE(msg);
	}
	return _libelf_errors[error];
}
Ejemplo n.º 9
0
/*
 * Retrieve counts for sections, phdrs and the section string table index
 * from section header #0 of the ELF object.
 */
static int
_libelf_load_extended(Elf *e, int ec, uint64_t shoff, uint16_t phnum,
                      uint16_t strndx)
{
    Elf_Scn *scn;
    size_t fsz;
    int (*xlator)(unsigned char *_d, size_t _dsz, unsigned char *_s,
                  size_t _c, int _swap);
    uint32_t shtype;

    assert(STAILQ_EMPTY(&e->e_u.e_elf.e_scn));

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

    if (e->e_rawsize < shoff + fsz) { /* raw file too small */
        LIBELF_SET_ERROR(HEADER, 0);
        return (0);
    }

    if ((scn = _libelf_allocate_scn(e, (size_t) 0)) == NULL)
        return (0);

    xlator = _libelf_get_translator(ELF_T_SHDR, ELF_TOMEMORY, ec);
    (*xlator)((unsigned char *) &scn->s_shdr, sizeof(scn->s_shdr),
              (unsigned char *) e->e_rawfile + shoff, (size_t) 1,
              e->e_byteorder != LIBELF_PRIVATE(byteorder));

#define	GET_SHDR_MEMBER(M) ((ec == ELFCLASS32) ? scn->s_shdr.s_shdr32.M : \
		scn->s_shdr.s_shdr64.M)

    if ((shtype = GET_SHDR_MEMBER(sh_type)) != SHT_NULL) {
        LIBELF_SET_ERROR(SECTION, 0);
        return (0);
    }

    e->e_u.e_elf.e_nscn = (size_t) GET_SHDR_MEMBER(sh_size);
    e->e_u.e_elf.e_nphdr = (phnum != PN_XNUM) ? phnum :
                           GET_SHDR_MEMBER(sh_info);
    e->e_u.e_elf.e_strndx = (strndx != SHN_XINDEX) ? strndx :
                            GET_SHDR_MEMBER(sh_link);
#undef	GET_SHDR_MEMBER

    return (1);
}
Ejemplo n.º 10
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);
}
Ejemplo n.º 11
0
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);
}
Ejemplo n.º 12
0
void
elf_fill(int fill)
{
	LIBELF_PRIVATE(fillchar) = fill;
}
Ejemplo n.º 13
0
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);
}
Ejemplo n.º 14
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);
}
Ejemplo n.º 15
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);
}
Ejemplo n.º 16
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);
}
Ejemplo n.º 17
0
void
_libelf_set_error(int error)
{
	LIBELF_PRIVATE(error) = error;
}
Ejemplo n.º 18
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;
    int (*xlator)(unsigned char *_d, size_t _dsz, unsigned 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, phnum * msz, e->e_rawfile + phoff, phnum,
              e->e_byteorder != LIBELF_PRIVATE(byteorder));

    return (phdr);
}
Ejemplo n.º 19
0
/*
 * Load an ELF section table and create a list of Elf_Scn structures.
 */
static int
_libelf_load_scn(Elf *e, void *ehdr)
{
        int ec, swapbytes;
        size_t fsz, i, shnum;
        uint64_t shoff;
        char *src;
        Elf32_Ehdr *eh32;
        Elf64_Ehdr *eh64;
        Elf_Scn *scn;
        void (*xlator)(char *_d, char *_s, size_t _c, int _swap);

        assert(e != NULL);
        assert(ehdr != NULL);
        assert((e->e_flags & LIBELF_F_SHDRS_LOADED) == 0);

#define	CHECK_EHDR(E,EH)	do {				\
                if (fsz != (EH)->e_shentsize ||			\
                    shoff + fsz * shnum > e->e_rawsize) {	\
                        LIBELF_SET_ERROR(HEADER, 0);		\
                        return (0);				\
                }						\
        } while (0)

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

        shnum = e->e_u.e_elf.e_nscn;

        if (ec == ELFCLASS32) {
                eh32 = (Elf32_Ehdr *) ehdr;
                shoff = (uint64_t) eh32->e_shoff;
                CHECK_EHDR(e, eh32);
        } else {
                eh64 = (Elf64_Ehdr *) ehdr;
                shoff = eh64->e_shoff;
                CHECK_EHDR(e, eh64);
        }

        xlator = _libelf_get_translator(ELF_T_SHDR, ELF_TOMEMORY, ec);

        swapbytes = e->e_byteorder != LIBELF_PRIVATE(byteorder);
        src = e->e_rawfile + shoff;

        /*
         * If the file is using extended numbering then section #0
         * would have already been read in.
         */

        i = 0;
        if (!STAILQ_EMPTY(&e->e_u.e_elf.e_scn)) {
                assert(STAILQ_FIRST(&e->e_u.e_elf.e_scn) ==
                    STAILQ_LAST(&e->e_u.e_elf.e_scn, _Elf_Scn, s_next));

                i = 1;
                src += fsz;
        }

        for (; i < shnum; i++, src += fsz) {
                if ((scn = _libelf_allocate_scn(e, i)) == NULL)
                        return (0);

                (*xlator)((char *) &scn->s_shdr, src, (size_t) 1, swapbytes);

                if (ec == ELFCLASS32) {
                        scn->s_offset = scn->s_rawoff =
                            scn->s_shdr.s_shdr32.sh_offset;
                        scn->s_size = scn->s_shdr.s_shdr32.sh_size;
                } else {
                        scn->s_offset = scn->s_rawoff =
                            scn->s_shdr.s_shdr64.sh_offset;
                        scn->s_size = scn->s_shdr.s_shdr64.sh_size;
                }
        }

        e->e_flags |= LIBELF_F_SHDRS_LOADED;

        return (1);
}
Ejemplo n.º 20
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);
}
Ejemplo n.º 21
0
Elf_Data *
elf_getdata(Elf_Scn *s, Elf_Data *d)
{
        Elf *e;
        char *dst;
        size_t fsz, msz, count;
        int elfclass, elftype;
        unsigned int sh_type;
        uint64_t sh_align, sh_offset, sh_size;
        void (*xlate)(char *_d, char *_s, size_t _c, int _swap);

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

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

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

        if (e->e_rawfile == NULL) {
                LIBELF_SET_ERROR(SEQUENCE, 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 ((elftype = _libelf_xlate_shtype(sh_type)) < ELF_T_FIRST ||
            elftype > ELF_T_LAST ||
            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 ((dst = malloc(msz*count)) == NULL) {
                LIBELF_SET_ERROR(RESOURCE, 0);
                return (NULL);
        }

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

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

        d->d_flags  |= LIBELF_F_MALLOCED;
        STAILQ_INSERT_TAIL(&s->s_data, d, d_next);

        xlate = _libelf_get_translator(elftype, ELF_TOMEMORY, elfclass);
        (*xlate)(d->d_buf, e->e_rawfile + sh_offset, count, e->e_byteorder !=
            LIBELF_PRIVATE(byteorder));

        return (d);
}