コード例 #1
0
ファイル: begin.c プロジェクト: Leon555/Mac-src-essentials
/*
 * Initialize archive member
 */
Elf *
_elf_member(int fd, Elf * ref, unsigned flags)
{
	register Elf	*elf;
	Member		*mh;
	size_t		base;

	if (ref->ed_nextoff >= ref->ed_fsz)
		return (0);
	if (ref->ed_fd == -1)		/* disabled */
		fd = -1;
	if (flags & EDF_WRITE) {
		_elf_seterr(EREQ_ARRDWR, 0);
		return (0);
	}
	if (ref->ed_fd != fd) {
		_elf_seterr(EREQ_ARMEMFD, 0);
		return (0);
	}
	if ((_elf_vm(ref, ref->ed_nextoff, sizeof (struct ar_hdr)) !=
	    OK_YES) || ((mh = _elf_armem(ref,
	    ref->ed_ident + ref->ed_nextoff, ref->ed_fsz)) == 0))
		return (0);

	base = ref->ed_nextoff + sizeof (struct ar_hdr);
	if (ref->ed_fsz - base < mh->m_hdr.ar_size) {
		_elf_seterr(EFMT_ARMEMSZ, 0);
		return (0);
	}
	if ((elf = (Elf *)calloc(1, sizeof (Elf))) == 0) {
		_elf_seterr(EMEM_ELF, errno);
		return (0);
	}
	++ref->ed_activ;
	elf->ed_parent = ref;
	elf->ed_fd = fd;
	elf->ed_myflags |= flags;
	elf->ed_armem = mh;
	elf->ed_fsz = mh->m_hdr.ar_size;
	elf->ed_baseoff = ref->ed_baseoff + base;
	elf->ed_memoff = base - mh->m_slide;
	elf->ed_siboff = base + elf->ed_fsz + (elf->ed_fsz & 1);
	ref->ed_nextoff = elf->ed_siboff;
	elf->ed_image = ref->ed_image;
	elf->ed_imagesz = ref->ed_imagesz;
	elf->ed_vm = ref->ed_vm;
	elf->ed_vmsz = ref->ed_vmsz;
	elf->ed_ident = ref->ed_ident + base - mh->m_slide;

	/*
	 * If this member is the archive string table,
	 * we've already altered the bytes.
	 */

	if (ref->ed_arstroff == ref->ed_nextoff)
		elf->ed_status = ES_COOKED;
	return (elf);
}
コード例 #2
0
ファイル: getarsym.c プロジェクト: madhavsuresh/illumos-gate
Elf_Arsym *
elf_getarsym(Elf *elf, size_t *ptr)
{
	Byte		*as;
	size_t		sz;
	Elf_Arsym	*rc;
	int		is64;

	if (ptr != 0)
		*ptr = 0;
	if (elf == NULL)
		return (0);
	ELFRLOCK(elf);
	if (elf->ed_kind != ELF_K_AR) {
		ELFUNLOCK(elf);
		_elf_seterr(EREQ_AR, 0);
		return (0);
	}
	if ((as = (Byte *)elf->ed_arsym) == 0) {
		ELFUNLOCK(elf);
		return (0);
	}
	if (elf->ed_myflags & EDF_ASALLOC) {
		if (ptr != 0)
			*ptr = elf->ed_arsymsz;
		ELFUNLOCK(elf);
		/* LINTED */
		return ((Elf_Arsym *)as);
	}
	is64 = (elf->ed_myflags & EDF_ARSYM64) != 0;

	/*
	 * We're gonna need a write lock.
	 */
	ELFUNLOCK(elf)
	ELFWLOCK(elf)
	sz = elf->ed_arsymsz;
	if (_elf_vm(elf, (size_t)(as - (Byte *)elf->ed_ident), sz) !=
	    OK_YES) {
		ELFUNLOCK(elf);
		return (0);
	}
	if ((elf->ed_arsym = arsym(as, sz, &elf->ed_arsymsz, is64)) == 0) {
		ELFUNLOCK(elf);
		return (0);
	}
	elf->ed_myflags |= EDF_ASALLOC;
	if (ptr != 0)
		*ptr = elf->ed_arsymsz;
	rc = (Elf_Arsym *)elf->ed_arsym;
	ELFUNLOCK(elf);
	return (rc);
}
コード例 #3
0
ファイル: cook.c プロジェクト: Leon555/Mac-src-essentials
int
_elf_slide(Elf * elf)
{
	NOTE(ASSUMING_PROTECTED(*elf))
	Elf		*par = elf->ed_parent;
	size_t		sz, szof;
	register char	*dst;
	register char	*src = elf->ed_ident;

	if (par == 0 || par->ed_kind != ELF_K_AR)
		return (0);

	/*
	 * This code relies on other code to ensure
	 * the ar_hdr is big enough to move into.
	 */
	if (elf->ed_ident[EI_CLASS] == ELFCLASS64)
		szof = sizeof (Elf64);
	else
		szof = sizeof (Elf32);
	if ((sz = (size_t)(src - (char *)elf->ed_image) % szof) == 0)
		return (0);
	dst = src - sz;
	elf->ed_ident -= sz;
	elf->ed_memoff -= sz;
	elf->ed_armem->m_slide = sz;
	if (_elf_vm(par, elf->ed_memoff, sz + elf->ed_fsz) != OK_YES)
		return (-1);

	/*
	 * If the archive has been mmaped in, and we're going to slide it,
	 * and it wasn't open for write in the first place, and we've never
	 * done the mprotect() operation before, then do it now.
	 */
	if ((elf->ed_vm == 0) && ((elf->ed_myflags & EDF_WRITE) == 0) &&
	    ((elf->ed_myflags & EDF_MPROTECT) == 0)) {
		if (mprotect((char *)elf->ed_image, elf->ed_imagesz,
		    PROT_READ|PROT_WRITE) == -1) {
			_elf_seterr(EIO_VM, errno);
			return (-1);
		}
		elf->ed_myflags |= EDF_MPROTECT;
	}

	if (memmove((void *)dst, (const void *)src, elf->ed_fsz) != (void *)dst)
		return (-1);
	else
		return (0);
}
コード例 #4
0
ファイル: rawfile.c プロジェクト: andreiw/polaris
char *
elf_rawfile(Elf * elf, size_t * ptr)
{
	register size_t	sz;
	char		*p = 0;

	if (elf == 0) {
		if (ptr != 0)
			*ptr = 0;
		return (0);
	}

	ELFWLOCK(elf)
	if ((sz = elf->ed_fsz) == 0) {
		if (ptr != 0)
			*ptr = 0;
		ELFUNLOCK(elf)
		return (0);
	}

	if (elf->ed_raw != 0)
		p = elf->ed_raw;
	else if (elf->ed_status == ES_COOKED) {
		if ((p = _elf_read(elf->ed_fd, elf->ed_baseoff, sz)) != 0) {
			elf->ed_raw = p;
			elf->ed_myflags |= EDF_RAWALLOC;
		} else
			sz = 0;
	} else {
		p = elf->ed_raw = elf->ed_ident;
		elf->ed_status = ES_FROZEN;
		if (_elf_vm(elf, (size_t)0, elf->ed_fsz) != OK_YES) {
			p = 0;
			sz = 0;
		}
	}
	if (ptr != 0)
		*ptr = sz;
	ELFUNLOCK(elf)
	return (p);
}
コード例 #5
0
ファイル: begin.c プロジェクト: Leon555/Mac-src-essentials
Elf *
_elf_config(Elf * elf)
{
	char *		base;
	unsigned	encode;

	ELFRWLOCKINIT(&elf->ed_rwlock);

	/*
	 * Determine if this is a ELF file.
	 */
	base = elf->ed_ident;
	if ((elf->ed_fsz >= EI_NIDENT) &&
	    (_elf_vm(elf, (size_t)0, (size_t)EI_NIDENT) == OK_YES) &&
	    (base[EI_MAG0] == ELFMAG0) &&
	    (base[EI_MAG1] == ELFMAG1) &&
	    (base[EI_MAG2] == ELFMAG2) &&
	    (base[EI_MAG3] == ELFMAG3)) {
		elf->ed_kind = ELF_K_ELF;
		elf->ed_class = base[EI_CLASS];
		elf->ed_encode = base[EI_DATA];
		if ((elf->ed_version = base[EI_VERSION]) == 0)
			elf->ed_version = 1;
		elf->ed_identsz = EI_NIDENT;

		/*
		 * Allow writing only if originally specified read only.
		 * This is only necessary if the file must be translating
		 * from one encoding to another.
		 */
		ELFACCESSDATA(encode, _elf_encode)
		if ((elf->ed_vm == 0) && ((elf->ed_myflags & EDF_WRITE) == 0) &&
		    (elf->ed_encode != encode)) {
			if (mprotect((char *)elf->ed_image, elf->ed_imagesz,
			    PROT_READ|PROT_WRITE) == -1) {
				_elf_seterr(EIO_VM, errno);
				return (0);
			}
		}
		return (elf);
	}
コード例 #6
0
static size_t
wrt(Elf * elf, Xword outsz, unsigned fill, int update_cmd)
{
	NOTE(ASSUMING_PROTECTED(*elf))
	Elf_Data	dst, src;
	unsigned	flag;
	Xword		hi, sz;
	char		*image;
	Elf_Scn		*s;
	Ehdr		*eh = elf->ed_ehdr;
	unsigned	ver = eh->e_version;
	unsigned	encode;
	int		byte;

	/*
	 * If this is an ELF_C_WRIMAGE write, then we encode into the
	 * byte order of the system we are running on rather than that of
	 * of the object. For ld.so.1, this is the same order, but
	 * for 'ld', it might not be in the case where we are cross
	 * linking an object for a different target. In this later case,
	 * the linker-host byte order is necessary so that the linker can
	 * manipulate the resulting  image. It is expected that the linker
	 * will call elf_swap_wrimage() if necessary to convert the image
	 * to the target byte order.
	 */
	encode = (update_cmd == ELF_C_WRIMAGE) ? _elf_sys_encoding() :
	    eh->e_ident[EI_DATA];

	/*
	 * Two issues can cause trouble for the output file.
	 * First, begin() with ELF_C_RDWR opens a file for both
	 * read and write.  On the write update(), the library
	 * has to read everything it needs before truncating
	 * the file.  Second, using mmap for both read and write
	 * is too tricky.  Consequently, the library disables mmap
	 * on the read side.  Using mmap for the output saves swap
	 * space, because that mapping is SHARED, not PRIVATE.
	 *
	 * If the file is write-only, there can be nothing of
	 * interest to bother with.
	 *
	 * The following reads the entire file, which might be
	 * more than necessary.  Better safe than sorry.
	 */

	if ((elf->ed_myflags & EDF_READ) &&
	    (_elf_vm(elf, (size_t)0, elf->ed_fsz) != OK_YES))
		return (0);

	flag = elf->ed_myflags & EDF_WRALLOC;
	if ((image = _elf_outmap(elf->ed_fd, outsz, &flag)) == 0)
		return (0);

	if (flag == 0)
		elf->ed_myflags |= EDF_IMALLOC;

	/*
	 * If an error occurs below, a "dirty" bit may be cleared
	 * improperly.  To save a second pass through the file,
	 * this code sets the dirty bit on the elf descriptor
	 * when an error happens, assuming that will "cover" any
	 * accidents.
	 */

	/*
	 * Hi is needed only when 'fill' is non-zero.
	 * Fill is non-zero only when the library
	 * calculates file/section/data buffer offsets.
	 * The lib guarantees they increase monotonically.
	 * That guarantees proper filling below.
	 */


	/*
	 * Ehdr first
	 */

	src.d_buf = (Elf_Void *)eh;
	src.d_type = ELF_T_EHDR;
	src.d_size = sizeof (Ehdr);
	src.d_version = EV_CURRENT;
	dst.d_buf = (Elf_Void *)image;
	dst.d_size = eh->e_ehsize;
	dst.d_version = ver;
	if (elf_xlatetof(&dst, &src, encode) == 0)
		return (0);
	elf->ed_ehflags &= ~ELF_F_DIRTY;
	hi = eh->e_ehsize;

	/*
	 * Phdr table if one exists
	 */

	if (eh->e_phnum != 0) {
		unsigned	work;
		/*
		 * Unlike other library data, phdr table is
		 * in the user version.  Change src buffer
		 * version here, fix it after translation.
		 */

		src.d_buf = (Elf_Void *)elf->ed_phdr;
		src.d_type = ELF_T_PHDR;
		src.d_size = elf->ed_phdrsz;
		ELFACCESSDATA(work, _elf_work)
		src.d_version = work;
		dst.d_buf = (Elf_Void *)(image + eh->e_phoff);
		dst.d_size = eh->e_phnum * eh->e_phentsize;
		hi = (Xword)(eh->e_phoff + dst.d_size);
		if (elf_xlatetof(&dst, &src, encode) == 0) {
			elf->ed_uflags |= ELF_F_DIRTY;
			return (0);
		}
		elf->ed_phflags &= ~ELF_F_DIRTY;
		src.d_version = EV_CURRENT;
	}

	/*
	 * Loop through sections
	 */

	ELFACCESSDATA(byte, _elf_byte);
	for (s = elf->ed_hdscn; s != 0; s = s->s_next) {
		register Dnode	*d, *prevd;
		Xword		off = 0;
		Shdr		*sh = s->s_shdr;
		char		*start = image + sh->sh_offset;
		char		*here;

		/*
		 * Just "clean" DIRTY flag for "empty" sections.  Even if
		 * NOBITS needs padding, the next thing in the
		 * file will provide it.  (And if this NOBITS is
		 * the last thing in the file, no padding needed.)
		 */
		if ((sh->sh_type == SHT_NOBITS) ||
		    (sh->sh_type == SHT_NULL)) {
			d = s->s_hdnode, prevd = 0;
			for (; d != 0; prevd = d, d = d->db_next)
				d->db_uflags &= ~ELF_F_DIRTY;
			continue;
		}
		/*
		 * Clear out the memory between the end of the last
		 * section and the begining of this section.
		 */
		if (fill && (sh->sh_offset > hi)) {
			sz = sh->sh_offset - hi;
			(void) memset(start - sz, byte, sz);
		}


		for (d = s->s_hdnode, prevd = 0;
		    d != 0; prevd = d, d = d->db_next) {
			d->db_uflags &= ~ELF_F_DIRTY;
			here = start + d->db_data.d_off;

			/*
			 * Clear out the memory between the end of the
			 * last update and the start of this data buffer.
			 */
			if (fill && (d->db_data.d_off > off)) {
				sz = (Xword)(d->db_data.d_off - off);
				(void) memset(here - sz, byte, sz);
			}

			if ((d->db_myflags & DBF_READY) == 0) {
				SCNLOCK(s);
				if (_elf_locked_getdata(s, &prevd->db_data) !=
				    &d->db_data) {
					elf->ed_uflags |= ELF_F_DIRTY;
					SCNUNLOCK(s);
					return (0);
				}
				SCNUNLOCK(s);
			}
			dst.d_buf = (Elf_Void *)here;
			dst.d_size = d->db_osz;

			/*
			 * Copy the translated bits out to the destination
			 * image.
			 */
			if (elf_xlatetof(&dst, &d->db_data, encode) == 0) {
				elf->ed_uflags |= ELF_F_DIRTY;
				return (0);
			}

			off = (Xword)(d->db_data.d_off + dst.d_size);
		}
		hi = sh->sh_offset + sh->sh_size;
	}

	/*
	 * Shdr table last
	 */

	if (fill && (eh->e_shoff > hi)) {
		sz = eh->e_shoff - hi;
		(void) memset(image + hi, byte, sz);
	}

	src.d_type = ELF_T_SHDR;
	src.d_size = sizeof (Shdr);
	dst.d_buf = (Elf_Void *)(image + eh->e_shoff);
	dst.d_size = eh->e_shentsize;
	for (s = elf->ed_hdscn; s != 0; s = s->s_next) {
		assert((uintptr_t)dst.d_buf < ((uintptr_t)image + outsz));
		s->s_shflags &= ~ELF_F_DIRTY;
		s->s_uflags &= ~ELF_F_DIRTY;
		src.d_buf = s->s_shdr;

		if (elf_xlatetof(&dst, &src, encode) == 0) {
			elf->ed_uflags |= ELF_F_DIRTY;
			return (0);
		}

		dst.d_buf = (char *)dst.d_buf + eh->e_shentsize;
	}
	/*
	 * ELF_C_WRIMAGE signifyes that we build the memory image, but
	 * that we do not actually write it to disk.  This is used
	 * by ld(1) to build up a full image of an elf file and then
	 * to process the file before it's actually written out to
	 * disk.  This saves ld(1) the overhead of having to write
	 * the image out to disk twice.
	 */
	if (update_cmd == ELF_C_WRIMAGE) {
		elf->ed_uflags &= ~ELF_F_DIRTY;
		elf->ed_wrimage = image;
		elf->ed_wrimagesz = outsz;
		return (outsz);
	}

	if (_elf_outsync(elf->ed_fd, image, outsz,
	    ((elf->ed_myflags & EDF_IMALLOC) ? 0 : 1)) != 0) {
		elf->ed_uflags &= ~ELF_F_DIRTY;
		elf->ed_myflags &= ~EDF_IMALLOC;
		return (outsz);
	}

	elf->ed_uflags |= ELF_F_DIRTY;
	return (0);
}
コード例 #7
0
ファイル: ar.c プロジェクト: AlainODea/illumos-gate
/*
 * Initial archive processing
 *	An archive may have two special members.
 *
 *	A symbol table, named / or /SYM64/, must be first if it is present.
 *	Both forms use the same layout differing in the width of the
 *	integer type used (32 or 64-bit respectively).
 *
 *	A long name string table, named //, must precede all "normal"
 *	members. This string table is used to hold the names of archive
 *	members with names that are longer than 15 characters. It should not
 *	be confused with the string table found at the end of the symbol
 *	table, which is used to hold symbol names.
 *
 *	This code "peeks" at headers but doesn't change them.
 *	Later processing wants original headers.
 *
 *	String table is converted, changing '/' name terminators
 *	to nulls.  The last byte in the string table, which should
 *	be '\n', is set to nil, guaranteeing null termination.  That
 *	byte should be '\n', but this code doesn't check.
 *
 *	The symbol table conversion is delayed until needed.
 */
void
_elf_arinit(Elf * elf)
{
	char				*base = elf->ed_ident;
	register char			*end = base + elf->ed_fsz;
	register struct ar_hdr		*a;
	register char			*hdr = base + SARMAG;
	register char			*mem;
	int				j;
	size_t				sz = SARMAG;

	elf->ed_status = ES_COOKED;
	elf->ed_nextoff = SARMAG;
	for (j = 0; j < 2; ++j)	 {	/* 2 special members */
		unsigned long	n;

		if (((end - hdr) < sizeof (struct ar_hdr)) ||
		    (_elf_vm(elf, (size_t)(SARMAG),
		    sizeof (struct ar_hdr)) != OK_YES))
			return;

		a = (struct ar_hdr *)hdr;
		mem = (char *)a + sizeof (struct ar_hdr);
		n = _elf_number(a->ar_size, &a->ar_size[ARSZ(ar_size)], 10);
		if ((end - mem < n) || (a->ar_name[0] != '/') ||
		    ((sz = n) != n)) {
			return;
		}

		hdr = mem + sz;
		if (a->ar_name[1] == ' ') {	/* 32-bit symbol table */
			elf->ed_arsym = mem;
			elf->ed_arsymsz = sz;
			elf->ed_arsymoff = (char *)a - base;
		} else if (a->ar_name[1] == '/' && a->ar_name[2] == ' ') {
						/* Long name string table */
			int	k;

			if (_elf_vm(elf, (size_t)(mem - elf->ed_ident),
			    sz) != OK_YES)
				return;
			if (elf->ed_vm == 0) {
				char	*nmem;
				if ((nmem = malloc(sz)) == 0) {
					_elf_seterr(EMEM_ARSTR, errno);
					return;
				}
				(void) memcpy(nmem, mem, sz);
				elf->ed_myflags |= EDF_ASTRALLOC;
				mem = nmem;
			}

			elf->ed_arstr = mem;
			elf->ed_arstrsz = sz;
			elf->ed_arstroff = (char *)a - base;
			for (k = 0; k < sz; k++) {
				if (*mem == '/')
					*mem = '\0';
				++mem;
			}
			*(mem - 1) = '\0';
		} else if (a->ar_name[1] == 'S' && a->ar_name[2] == 'Y' &&
		    a->ar_name[3] == 'M' && a->ar_name[4] == '6' &&
		    a->ar_name[5] == '4' && a->ar_name[6] == '/' &&
		    a->ar_name[7] == ' ') {
						/* 64-bit symbol table */
			elf->ed_arsym = mem;
			elf->ed_arsymsz = sz;
			elf->ed_arsymoff = (char *)a - base;
			elf->ed_myflags |= EDF_ARSYM64;
		} else {
			return;
		}
		hdr += sz & 1;
	}
}