Esempio n. 1
0
/*
 * Return the archive member's name.
 *
 * entry:
 *	name - Name of archive
 *	arelf - ELF descriptor for archive member.
 *	ofl - output descriptor
 *
 * exit:
 *	Returns pointer to archive member name on success, NULL on error.
 */
static const char *
ar_member_name(const char *name, Elf *arelf, Ofl_desc *ofl)
{
	Elf_Arhdr	*arhdr;

	if ((arhdr = elf_getarhdr(arelf)) == NULL) {
		ld_eprintf(ofl, ERR_ELF, MSG_INTL(MSG_ELF_GETARHDR), name);
		return (NULL);
	}
	return (arhdr->ar_name);
}
Esempio n. 2
0
static int
read_archive(int fd, Elf *elf, char *file, char *label, read_cb_f *func,
    void *arg, int require_ctf)
{
	Elf *melf;
	Elf_Cmd cmd = ELF_C_READ;
	Elf_Arhdr *arh;
	int secnum = 1, found = 0;

	while ((melf = elf_begin(fd, cmd, elf)) != NULL) {
		int rc = 0;

		if ((arh = elf_getarhdr(melf)) == NULL) {
			elfterminate(file, "Can't get archive header for "
			    "member %d", secnum);
		}

		/* skip special sections - their names begin with "/" */
		if (*arh->ar_name != '/') {
			size_t memlen = strlen(file) + 1 +
			    strlen(arh->ar_name) + 1 + 1;
			char *memname = xmalloc(memlen);

			snprintf(memname, memlen, "%s(%s)", file, arh->ar_name);

			switch (elf_kind(melf)) {
			case ELF_K_AR:
				rc = read_archive(fd, melf, memname, label,
				    func, arg, require_ctf);
				break;
			case ELF_K_ELF:
				rc = read_file(melf, memname, label,
				    func, arg, require_ctf);
				break;
			default:
				terminate("%s: Unknown elf kind %d\n",
				    memname, elf_kind(melf));
			}

			free(memname);
		}

		cmd = elf_next(melf);
		(void) elf_end(melf);
		secnum++;

		if (rc < 0)
			return (rc);
		else
			found += rc;
	}

	return (found);
}
Esempio n. 3
0
/*
 * Process member files of an archive.  This function provides
 * a loop through an archive equivalent the processing of
 * each_file for individual object files.
 */
static void
print_ar_files(int fd, Elf * elf_file, char *filename)
{
	Elf_Arhdr  *p_ar;
	Elf	*arf;
	Elf_Cmd    cmd;
	Elf_Kind   file_type;


	cmd = ELF_C_READ;
	archive_name = filename;
	while ((arf = elf_begin(fd, cmd, elf_file)) != 0) {
		p_ar = elf_getarhdr(arf);
		if (p_ar == NULL) {
			(void) fprintf(stderr, "%s: %s: %s\n",
			    prog_name, filename, elf_errmsg(-1));
			return;
		}
		if (p_ar->ar_name[0] == '/') {
			cmd = elf_next(arf);
			(void) elf_end(arf);
			continue;
		}

		if (!h_flag & !P_flag) {
			if (p_flag)
				(void) printf("\n\n%s[%s]:\n",
				    filename, p_ar->ar_name);
			else {
				if (A_flag != 0)
					(void) printf("\n\n%s%s[%s]:\n",
					    A_header, filename, p_ar->ar_name);
				else
					(void) printf("\n\n%s[%s]:\n",
					    filename, p_ar->ar_name);
			}
		}
		file_type = elf_kind(arf);
		if (file_type == ELF_K_ELF) {
			process(arf, p_ar->ar_name);
		} else {
			(void) fprintf(stderr, gettext(
			    "%s: %s: invalid file type\n"),
			    prog_name, p_ar->ar_name);
			cmd = elf_next(arf);
			(void) elf_end(arf);
			errflag++;
			continue;
		}

		cmd = elf_next(arf);
		(void) elf_end(arf);
	} /* end while */
}
Esempio n. 4
0
static void
process_elf(Elf *elf, char *file, int fd, int member)
{
	Elf_Cmd	cmd;
	Elf	*_elf;

	switch (elf_kind(elf)) {
	case ELF_K_ELF:
		/*
		 * This is an ELF file, now attempt to find it's
		 * .comment section and to display it.
		 */
		print_symtab(elf, file);
		break;
	case ELF_K_AR:
		/*
		 * Archives contain multiple ELF files, which can each
		 * in turn be examined with libelf.
		 *
		 * The below loop will iterate over each member of the
		 * archive and recursively call process_elf().
		 */
		cmd = ELF_C_READ;
		while ((_elf = elf_begin(fd, cmd, elf)) != NULL) {
			Elf_Arhdr	*arhdr;
			char		buffer[1024];

			arhdr = elf_getarhdr(_elf);

			/*
			 * Build up file names based off of
			 * 'archivename(membername)'.
			 */
			(void) snprintf(buffer, 1024, "%s(%s)",
			    file, arhdr->ar_name);

			/*
			 * Recursively process the ELF members.
			 */
			process_elf(_elf, buffer, fd, 1);
			cmd = elf_next(_elf);
			(void) elf_end(_elf);
		}
		break;
	default:
		if (!member)
			(void) fprintf(stderr,
			    "%s: unexpected elf_kind(): 0x%x\n",
			    file, elf_kind(elf));
		return;
	}
}
Esempio n. 5
0
/*
 * Given an elf object,ar(1) filename, and based on the output style
 * and radix format the various sections and their length will be printed
 * or the size of the text, data, bss sections will be printed out.
 */
static int
handle_elf(char const *name)
{
	GElf_Ehdr elfhdr;
	GElf_Shdr shdr;
	Elf *elf, *elf1;
	Elf_Arhdr *arhdr;
	Elf_Scn *scn;
	Elf_Cmd elf_cmd;
	int exit_code, fd;

	if (name == NULL)
		return (RETURN_NOINPUT);

	if ((fd = open(name, O_RDONLY, 0)) < 0)
		return (RETURN_NOINPUT);

	elf_cmd = ELF_C_READ;
	elf1 = elf_begin(fd, elf_cmd, NULL);
	while ((elf = elf_begin(fd, elf_cmd, elf1)) != NULL) {
		arhdr = elf_getarhdr(elf);
		if (elf_kind(elf) == ELF_K_NONE && arhdr == NULL) {
			(void) elf_end(elf);
			(void) elf_end(elf1);
			(void) close(fd);
			return (RETURN_DATAERR);
		}
		if (elf_kind(elf) != ELF_K_ELF ||
		    (gelf_getehdr(elf, &elfhdr) == NULL)) {
			elf_cmd = elf_next(elf);
			(void) elf_end(elf);
			warnx("%s: File format not recognized",
			    arhdr->ar_name);
			continue;
		}
		/* Core dumps are handled seperately */
		if (elfhdr.e_shnum == 0 && elfhdr.e_type == ET_CORE) {
			exit_code = handle_core(name, elf, &elfhdr);
			(void) elf_end(elf);
			(void) elf_end(elf1);
			(void) close(fd);
			return (exit_code);
		} else {
			scn = NULL;
			if (style == STYLE_BERKELEY) {
				berkeley_header();
				while ((scn = elf_nextscn(elf, scn)) != NULL) {
					if (gelf_getshdr(scn, &shdr) != NULL)
						berkeley_calc(&shdr);
				}
			} else {
				sysv_header(name, arhdr);
				scn = NULL;
				while ((scn = elf_nextscn(elf, scn)) != NULL) {
					if (gelf_getshdr(scn, &shdr) !=	NULL)
						sysv_calc(elf, &elfhdr, &shdr);
				}
			}
			if (style == STYLE_BERKELEY) {
				if (arhdr != NULL) {
					berkeley_footer(name, arhdr->ar_name,
					    "ex");
				} else {
					berkeley_footer(name, NULL, "ex");
				}
			} else {
				sysv_footer();
			}
		}
		elf_cmd = elf_next(elf);
		(void) elf_end(elf);
	}
	(void) elf_end(elf1);
	(void) close(fd);
	return (RETURN_OK);
}
Esempio n. 6
0
bool ElfArchiveFile::Load(const char* pName)
{
	// Load the elf file
	Elf* elf;

	m_filedes = open(pName, O_RDONLY);
	if (m_filedes == -1)
	{
		printf("Could not open %s\n", pName);
		return false;
	}

	elf_version(EV_CURRENT);
	m_arf = elf_begin(m_filedes, ELF_C_READ, (Elf*)0);
	if (elf_kind(m_arf) != ELF_K_AR)
	{
		printf("Error - %s is not an archive (.a) file\n", pName);
		return false;
	}

	// Load the symbol table. We assume that each member has at
	// least one symbol.
	// We want a map from symbol to index; to do this, we need to know
	// the current index and last offset seen
	int iLastOffset = 0;
	int iOffset = 0;
	unsigned int uNumSyms;
	int iIndex = -1;		// 0,1,2... for 1st,2nd,3rd... member

    Elf_Arsym* asym;
    asym = elf_getarsym(m_arf, &uNumSyms);
	uNumSyms--;
    if (asym == 0)
    {
        printf("Get archive symbol table failed\n");
        return false;
    }

	for (unsigned u=0; u < uNumSyms; u++)
	{
		iOffset = asym[u].as_off;
		// Last entry is null, but should never see it
		if (iOffset == 0) break;
		if (iOffset != iLastOffset)
		{
			// This is a new member. Use a new index
			iIndex++;
			iLastOffset = iOffset;

			// Seek to that member
			if (elf_rand(m_arf, iOffset) == 0)
			{
				printf("Could not seek to offset %d\n", iOffset);
				return false;
			}
			if ((elf = elf_begin(m_filedes, ELF_C_READ, m_arf)) == 0)
			{
				printf("Could not begin member at offset %d\n", iOffset);
				return false;
			}
			Elf_Arhdr* ahdr;
			ahdr = elf_getarhdr(elf);
			if (ahdr == 0)
			{
				printf("Could not get header information "
					"for member at offset %d\n", iOffset);
				return false;
			}
			// Add the name to the map
			m_FileMap[ahdr->ar_name] = iIndex;
			// And to the vector of pointers to file names
			m_FileNames.push_back(ahdr->ar_name);
			// Also add the offset. These are supposed to be relatively
			// implementation independant
			m_Offsets.push_back(iOffset);
		}
		// Add an entry to the symbol->offset map
		m_SymMap[asym[u].as_name] = iIndex;
	}

	// Now we know the correct size for the vector of members.
	// Ugh - can't call constructor any more
	//m_Members.vector(GetNumMembers(), (BinaryFile*)0);
	m_Members.reserve(GetNumMembers());

	return true;
}
Esempio n. 7
0
int
each_file(char *cur_file, Cmd_Info *cmd_info)
{
	Elf *elf = 0;
	Elf_Cmd cmd;
	Elf *arf = 0;
	Elf_Arhdr *mem_header;
	char *cur_filenm = NULL;
	int code = 0;
	int error = 0, err = 0;
	int ar_file = 0;
	int fdartmp;
	int fd;
	int oflag;

	if (cmd_info->flags & MIGHT_CHG)
		oflag = O_RDWR;
	else
		oflag = O_RDONLY;

	if ((fd = open(cur_file, oflag)) == -1) {
		error_message(OPEN_ERROR,
		SYSTEM_ERROR, strerror(errno), prog, cur_file);
		return (FAILURE);
	}

	/*
	 * Note, elf_begin requires ELF_C_READ even if MIGHT_CHK is in effect.
	 * libelf does not allow elf_begin() with ELF_C_RDWR when processing
	 * archive file members.  Because we are limited to ELF_C_READ use, any
	 * ELF data modification must be provided by updating a copy of
	 * the data, rather than updating the original file data.
	 */
	cmd = ELF_C_READ;
	if ((arf = elf_begin(fd, cmd, (Elf *)0)) == 0) {
		error_message(LIBELF_ERROR,
		LIBelf_ERROR, elf_errmsg(-1), prog);
		(void) elf_end(arf);
		(void) close(fd);   /* done processing this file */
		return (FAILURE);
	}

	if ((elf_kind(arf) == ELF_K_AR)) {
		ar_file = 1;
		if (CHK_OPT(cmd_info, MIGHT_CHG)) {
			artmpfile = tempnam(TMPDIR, "mcs2");
			if ((fdartmp = open(artmpfile,
			    O_WRONLY | O_APPEND | O_CREAT,
			    (mode_t)0666)) == NULL) {
				error_message(OPEN_TEMP_ERROR,
				SYSTEM_ERROR, strerror(errno),
				prog, artmpfile);
				(void) elf_end(arf);
				(void) close(fd);
				exit(FAILURE);
			}
			/* write magic string to artmpfile */
			if ((write(fdartmp, ARMAG, SARMAG)) != SARMAG) {
				error_message(WRITE_ERROR,
				SYSTEM_ERROR, strerror(errno),
				prog, artmpfile, cur_file);
				mcs_exit(FAILURE);
			}
		}
	} else {
		ar_file = 0;
		cur_filenm = cur_file;
	}

	/*
	 * Holds temporary file;
	 * if archive, holds the current member file if it has an ehdr,
	 * and there were no errors in
	 * processing the object file.
	 */
	elftmpfile = tempnam(TMPDIR, "mcs1");

	while ((elf = elf_begin(fd, cmd, arf)) != 0) {
		if (ar_file) /* get header info */ {
			size_t	len;

			if ((mem_header = elf_getarhdr(elf)) == NULL) {
				error_message(GETARHDR_ERROR,
				LIBelf_ERROR, elf_errmsg(-1),
				prog, cur_file, elf_getbase(elf));
				(void) elf_end(elf);
				(void) elf_end(arf);
				(void) close(fd);
				(void) unlink(artmpfile);
				return (FAILURE);
			}

			if (cur_filenm != NULL)
				free(cur_filenm);

			len = (strlen(cur_file) + 3 +
			    strlen(mem_header->ar_name));

			if ((cur_filenm = malloc(len)) == NULL) {
				error_message(MALLOC_ERROR,
				PLAIN_ERROR, (char *)0,
				prog);
				mcs_exit(FAILURE);
			}

			(void) snprintf(cur_filenm, len, "%s[%s]",
				cur_file, mem_header->ar_name);
		}

		if (elf_kind(elf) == ELF_K_ELF) {
			if ((code = process_file(elf, cur_filenm, cmd_info)) ==
			    FAILURE) {
				if (!ar_file) {
					(void) elf_end(arf);
					(void) elf_end(elf);
					(void) close(fd);
					return (FAILURE);
				} else {
					copy_non_elf_to_temp_ar(
					fd, elf, fdartmp, mem_header,
					cur_file, cmd_info);
					error++;
				}
			} else if (ar_file && CHK_OPT(cmd_info, MIGHT_CHG)) {
				if (code == DONT_BUILD)
					copy_non_elf_to_temp_ar(
					fd, elf, fdartmp, mem_header,
					cur_file, cmd_info);
				else
					copy_elf_file_to_temp_ar_file(
						fdartmp, mem_header, cur_file);
			}
		} else {
			/*
			 * decide what to do with non-ELF file
			 */
			if (!ar_file) {
				error_message(FILE_TYPE_ERROR,
				PLAIN_ERROR, (char *)0,
				prog, cur_filenm);
				(void) close(fd);
				return (FAILURE);
			} else {
				if (CHK_OPT(cmd_info, MIGHT_CHG))
					copy_non_elf_to_temp_ar(
					fd, elf, fdartmp, mem_header,
					cur_file, cmd_info);
			}
		}
		cmd = elf_next(elf);
		(void) elf_end(elf);
	}

	err = elf_errno();
	if (err != 0) {
		error_message(LIBELF_ERROR,
		LIBelf_ERROR, elf_errmsg(err), prog);
		error_message(NOT_MANIPULATED_ERROR,
		PLAIN_ERROR, (char *)0,
		prog, cur_file);
		return (FAILURE);
	}

	(void) elf_end(arf);

	if (ar_file && CHK_OPT(cmd_info, MIGHT_CHG)) {
		(void) close(fdartmp); /* done writing to ar_temp_file */
		/* copy ar_temp_file to FILE */
		copy_file(fd, cur_file, artmpfile);
	} else if (code != DONT_BUILD && CHK_OPT(cmd_info, MIGHT_CHG))
		copy_file(fd, cur_file, elftmpfile);
	(void) close(fd);   /* done processing this file */
	return (error);
}
Esempio n. 8
0
static int
archive(const char *file, int fd, Elf *elf, uint_t flags,
    const char *wname, int wfd, uchar_t osabi)
{
	Elf_Cmd		cmd = ELF_C_READ;
	Elf_Arhdr	*arhdr;
	Elf		*_elf = NULL;
	size_t		ptr;
	Elf_Arsym	*arsym = NULL;

	/*
	 * Determine if the archive symbol table itself is required.
	 */
	if ((flags & FLG_SHOW_SYMBOLS) &&
	    match(MATCH_F_NAME, MSG_ORIG(MSG_ELF_ARSYM), 0, 0)) {
		/*
		 * Get the archive symbol table.
		 */
		if (((arsym = elf_getarsym(elf, &ptr)) == 0) && elf_errno()) {
			/*
			 * The arsym could be 0 even though there was no error.
			 * Print the error message only when there was
			 * real error from elf_getarsym().
			 */
			failure(file, MSG_ORIG(MSG_ELF_GETARSYM));
			return (0);
		}
	}

	/*
	 * Print the archive symbol table only when the archive symbol
	 * table exists and it was requested to print.
	 */
	if (arsym) {
		size_t		cnt;
		char		index[MAXNDXSIZE];
		size_t		offset = 0, _offset = 0;
		const char	*fmt_arsym1, *fmt_arsym2;

		/*
		 * Print out all the symbol entries. The format width used
		 * corresponds to whether the archive symbol table is 32
		 * or 64-bit. We see them via Elf_Arhdr as size_t values
		 * in either case with no information loss (see the comments
		 * in libelf/getarsym.c) so this is done simply to improve
		 * the user presentation.
		 */
		if (_elf_getarsymwordsize(elf) == 8) {
			dbg_print(0, MSG_INTL(MSG_ARCHIVE_SYMTAB_64));
			dbg_print(0, MSG_INTL(MSG_ARCHIVE_FIELDS_64));

			fmt_arsym1 = MSG_ORIG(MSG_FMT_ARSYM1_64);
			fmt_arsym2 = MSG_ORIG(MSG_FMT_ARSYM2_64);
		} else {
			dbg_print(0, MSG_INTL(MSG_ARCHIVE_SYMTAB_32));
			dbg_print(0, MSG_INTL(MSG_ARCHIVE_FIELDS_32));

			fmt_arsym1 = MSG_ORIG(MSG_FMT_ARSYM1_32);
			fmt_arsym2 = MSG_ORIG(MSG_FMT_ARSYM2_32);
		}

		for (cnt = 0; cnt < ptr; cnt++, arsym++) {
			/*
			 * For each object obtain an elf descriptor so that we
			 * can establish the members name.  Note, we have had
			 * archives where the archive header has not been
			 * obtainable so be lenient with errors.
			 */
			if ((offset == 0) || ((arsym->as_off != 0) &&
			    (arsym->as_off != _offset))) {

				if (_elf)
					(void) elf_end(_elf);

				if (elf_rand(elf, arsym->as_off) !=
				    arsym->as_off) {
					failure(file, MSG_ORIG(MSG_ELF_RAND));
					arhdr = NULL;
				} else if ((_elf = elf_begin(fd,
				    ELF_C_READ, elf)) == 0) {
					failure(file, MSG_ORIG(MSG_ELF_BEGIN));
					arhdr = NULL;
				} else if ((arhdr = elf_getarhdr(_elf)) == 0) {
					failure(file,
					    MSG_ORIG(MSG_ELF_GETARHDR));
					arhdr = NULL;
				}

				_offset = arsym->as_off;
				if (offset == 0)
					offset = _offset;
			}

			(void) snprintf(index, MAXNDXSIZE,
			    MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(cnt));
			if (arsym->as_off)
				dbg_print(0, fmt_arsym1, index,
				    EC_XWORD(arsym->as_off),
				    arhdr ? arhdr->ar_name :
				    MSG_INTL(MSG_STR_UNKNOWN), (arsym->as_name ?
				    demangle(arsym->as_name, flags) :
				    MSG_INTL(MSG_STR_NULL)));
			else
				dbg_print(0, fmt_arsym2, index,
				    EC_XWORD(arsym->as_off));
		}

		if (_elf)
			(void) elf_end(_elf);

		/*
		 * If we only need the archive symbol table return.
		 */
		if ((flags & FLG_SHOW_SYMBOLS) &&
		    match(MATCH_F_STRICT | MATCH_F_NAME,
		    MSG_ORIG(MSG_ELF_ARSYM), -1, -1))
			return (0);

		/*
		 * Reset elf descriptor in preparation for processing each
		 * member.
		 */
		if (offset)
			(void) elf_rand(elf, offset);
	}

	/*
	 * Process each object within the archive.
	 */
	while ((_elf = elf_begin(fd, cmd, elf)) != NULL) {
		char	name[MAXPATHLEN];

		if ((arhdr = elf_getarhdr(_elf)) == NULL) {
			failure(file, MSG_ORIG(MSG_ELF_GETARHDR));
			return (0);
		}
		if (*arhdr->ar_name != '/') {
			(void) snprintf(name, MAXPATHLEN,
			    MSG_ORIG(MSG_FMT_ARNAME), file, arhdr->ar_name);
			dbg_print(0, MSG_ORIG(MSG_FMT_NLSTR), name);

			switch (elf_kind(_elf)) {
			case ELF_K_AR:
				if (archive(name, fd, _elf, flags,
				    wname, wfd, osabi) == 1)
					return (1);
				break;
			case ELF_K_ELF:
				if (decide(name, fd, _elf, flags,
				    wname, wfd, osabi) == 1)
					return (1);
				break;
			default:
				(void) fprintf(stderr,
				    MSG_INTL(MSG_ERR_BADFILE), name);
				break;
			}
		}

		cmd = elf_next(_elf);
		(void) elf_end(_elf);
	}

	return (0);
}