Beispiel #1
0
/*
 * Retrieve the full name of the archive member.
 */
char *
_libelf_ar_get_name(char *buf, size_t bufsize, Elf *e)
{
	char c, *q, *r, *s;
	size_t len;
	size_t offset;

	assert(e->e_kind == ELF_K_AR);

	if (buf[0] == '/' && (c = buf[1]) >= '0' && c <= '9') {
		/*
		 * The value in field ar_name is a decimal offset into
		 * the archive string table where the actual name
		 * resides.
		 */
		if (_libelf_ar_get_number(buf + 1, bufsize - 1, 10,
		    &offset) == 0) {
			LIBELF_SET_ERROR(ARCHIVE, 0);
			return (NULL);
		}

		if (offset > e->e_u.e_ar.e_rawstrtabsz) {
			LIBELF_SET_ERROR(ARCHIVE, 0);
			return (NULL);
		}

		s = q = e->e_u.e_ar.e_rawstrtab + offset;
		r = e->e_u.e_ar.e_rawstrtab + e->e_u.e_ar.e_rawstrtabsz;

		for (s = q; s < r && *s != '/'; s++)
			;
		len = s - q + 1; /* space for the trailing NUL */

		if ((s = malloc(len)) == NULL) {
			LIBELF_SET_ERROR(RESOURCE, 0);
			return (NULL);
		}

		(void) strncpy(s, q, len);
		s[len - 1] = '\0';

		return (s);
	}

	/*
	 * Normal 'name'
	 */
	return (_libelf_ar_get_string(buf, bufsize, 0));
}
Beispiel #2
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 #3
0
Elf_Arhdr *
_libelf_ar_gethdr(Elf *e)
{
	Elf *parent;
	struct ar_hdr *arh;
	Elf_Arhdr *eh;
	size_t n;

	if ((parent = e->e_parent) == NULL) {
		LIBELF_SET_ERROR(ARGUMENT, 0);
		return (NULL);
	}

	arh = (struct ar_hdr *) ((uintptr_t) e->e_rawfile - sizeof(struct ar_hdr));

	assert((uintptr_t) arh >= (uintptr_t) parent->e_rawfile + SARMAG);
	assert((uintptr_t) arh <= (uintptr_t) parent->e_rawfile + parent->e_rawsize -
	    sizeof(struct ar_hdr));

	if ((eh = malloc(sizeof(Elf_Arhdr))) == NULL) {
		LIBELF_SET_ERROR(RESOURCE, 0);
		return (NULL);
	}

	e->e_arhdr = eh;
	eh->ar_name = eh->ar_rawname = NULL;

	if ((eh->ar_name = _libelf_ar_get_name(arh->ar_name, sizeof(arh->ar_name),
		 parent)) == NULL)
		goto error;

	if (_libelf_ar_get_number(arh->ar_uid, sizeof(arh->ar_uid), 10, &n) == 0)
		goto error;
	eh->ar_uid = (uid_t) n;

	if (_libelf_ar_get_number(arh->ar_gid, sizeof(arh->ar_gid), 10, &n) == 0)
		goto error;
	eh->ar_gid = (gid_t) n;

	if (_libelf_ar_get_number(arh->ar_mode, sizeof(arh->ar_mode), 8, &n) == 0)
		goto error;
	eh->ar_mode = (mode_t) n;

	if (_libelf_ar_get_number(arh->ar_size, sizeof(arh->ar_size), 10, &n) == 0)
		goto error;
	eh->ar_size = n;

	if ((eh->ar_rawname = _libelf_ar_get_string(arh->ar_name,
		 sizeof(arh->ar_name), 1)) == NULL)
		goto error;

	return (eh);

 error:
	if (eh) {
		if (eh->ar_name)
			free(eh->ar_name);
		if (eh->ar_rawname)
			free(eh->ar_rawname);
		free(eh);
	}
	e->e_arhdr = NULL;

	return (NULL);
}
Beispiel #4
0
Elf *
_libelf_ar_open_member(int fd, Elf_Cmd c, Elf *elf)
{
	Elf *e;
	char *member, *namelen;
	size_t nsz, sz;
	off_t next;
	struct ar_hdr *arh;

	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);

	/*
	 * Retrieve the size of the member.
	 */
	if (_libelf_ar_get_number(arh->ar_size, sizeof(arh->ar_size), 10,
	    &sz) == 0) {
		LIBELF_SET_ERROR(ARCHIVE, 0);
		return (NULL);
	}

	/*
	 * Adjust the size field for members in BSD archives using
	 * extended naming.
	 */
	if (IS_EXTENDED_BSD_NAME(arh->ar_name)) {
		namelen = arh->ar_name +
		    LIBELF_AR_BSD_EXTENDED_NAME_PREFIX_SIZE;
		if (_libelf_ar_get_number(namelen, sizeof(arh->ar_name) -
		    LIBELF_AR_BSD_EXTENDED_NAME_PREFIX_SIZE, 10, &nsz) == 0) {
			LIBELF_SET_ERROR(ARCHIVE, 0);
			return (NULL);
		}

		member = (char *) (arh + 1) + nsz;
		sz -= nsz;
	} else
		member = (char *) (arh + 1);


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

	e->e_fd = fd;
	e->e_cmd = c;
	e->e_hdr.e_rawhdr = (char *) arh;

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

	return (e);
}
Beispiel #5
0
Elf_Arhdr *
_libelf_ar_gethdr(Elf *e)
{
	Elf *parent;
	char *namelen;
	Elf_Arhdr *eh;
	size_t n, nlen;
	struct ar_hdr *arh;

	if ((parent = e->e_parent) == NULL) {
		LIBELF_SET_ERROR(ARGUMENT, 0);
		return (NULL);
	}

	assert((e->e_flags & LIBELF_F_AR_HEADER) == 0);

	arh = (struct ar_hdr *) (uintptr_t) e->e_hdr.e_rawhdr;

	assert((uintptr_t) arh >= (uintptr_t) parent->e_rawfile + SARMAG);
	assert((uintptr_t) arh <= (uintptr_t) parent->e_rawfile +
	    parent->e_rawsize - sizeof(struct ar_hdr));

	if ((eh = malloc(sizeof(Elf_Arhdr))) == NULL) {
		LIBELF_SET_ERROR(RESOURCE, 0);
		return (NULL);
	}

	e->e_hdr.e_arhdr = eh;
	e->e_flags |= LIBELF_F_AR_HEADER;

	eh->ar_name = eh->ar_rawname = NULL;

	if ((eh->ar_name = _libelf_ar_get_translated_name(arh, parent)) ==
	    NULL)
		goto error;

	if (_libelf_ar_get_number(arh->ar_uid, sizeof(arh->ar_uid), 10,
	    &n) == 0)
		goto error;
	eh->ar_uid = (uid_t) n;

	if (_libelf_ar_get_number(arh->ar_gid, sizeof(arh->ar_gid), 10,
	    &n) == 0)
		goto error;
	eh->ar_gid = (gid_t) n;

	if (_libelf_ar_get_number(arh->ar_mode, sizeof(arh->ar_mode), 8,
	    &n) == 0)
		goto error;
	eh->ar_mode = (mode_t) n;

	if (_libelf_ar_get_number(arh->ar_size, sizeof(arh->ar_size), 10,
	    &n) == 0)
		goto error;

	/*
	 * Get the true size of the member if extended naming is being used.
	 */
	if (IS_EXTENDED_BSD_NAME(arh->ar_name)) {
		namelen = arh->ar_name +
		    LIBELF_AR_BSD_EXTENDED_NAME_PREFIX_SIZE;
		if (_libelf_ar_get_number(namelen, sizeof(arh->ar_name) -
		    LIBELF_AR_BSD_EXTENDED_NAME_PREFIX_SIZE, 10, &nlen) == 0)
			goto error;
		n -= nlen;
	}

	eh->ar_size = n;

	if ((eh->ar_rawname = _libelf_ar_get_raw_name(arh)) == NULL)
		goto error;

	eh->ar_flags = 0;

	return (eh);

 error:
	if (eh) {
		if (eh->ar_name)
			free(eh->ar_name);
		if (eh->ar_rawname)
			free(eh->ar_rawname);
		free(eh);
	}

	e->e_flags &= ~LIBELF_F_AR_HEADER;
	e->e_hdr.e_rawhdr = (char *) arh;

	return (NULL);
}
Beispiel #6
0
/*
 * Open an 'ar' archive.
 */
Elf *
_libelf_ar_open(Elf *e)
{
	int i;
	char *s, *end;
	size_t sz;
	struct ar_hdr arh;

	e->e_kind = ELF_K_AR;
	e->e_u.e_ar.e_nchildren = 0;
	e->e_u.e_ar.e_next = (off_t) -1;

	/*
	 * Look for special members.
	 */

	s = e->e_rawfile + SARMAG;
	end = e->e_rawfile + e->e_rawsize;

	assert(e->e_rawsize > 0);

	/*
	 * Look for magic names "/ " and "// " in the first two entries
	 * of the archive.
	 */
	for (i = 0; i < 2; i++) {

		if (s + sizeof(arh) > end) {
			LIBELF_SET_ERROR(ARCHIVE, 0);
			return (NULL);
		}

		(void) memcpy(&arh, s, sizeof(arh));

		if (arh.ar_fmag[0] != '`' || arh.ar_fmag[1] != '\n') {
			LIBELF_SET_ERROR(ARCHIVE, 0);
			return (NULL);
		}

		if (arh.ar_name[0] != '/')	/* not a special symbol */
			break;

		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);

		s += sizeof(arh);

		if (arh.ar_name[1] == ' ') {	/* "/ " => symbol table */

			e->e_u.e_ar.e_rawsymtab = s;
			e->e_u.e_ar.e_rawsymtabsz = sz;

		} else if (arh.ar_name[1] == '/' && arh.ar_name[2] == ' ') {

			/* "// " => string table for long file names */
			e->e_u.e_ar.e_rawstrtab = s;
			e->e_u.e_ar.e_rawstrtabsz = sz;
		}

		sz = LIBELF_ADJUST_AR_SIZE(sz);

		s += sz;
	}

	e->e_u.e_ar.e_next = (off_t) (s - e->e_rawfile);

	return (e);
}