Exemple #1
0
int coff_syms(FILE *in)
{
	struct coff_header hdr;
	char *strtab;
	uint8_t *symtab;
	int strtab_len;
	int i;
	int ret = 0;

	if (read_header(in, &hdr) < 0)
		return -1;

	strtab_len = read_strtab(in, &hdr, &strtab);
	if (strtab_len < 0)
		return -1;

	if (read_symtab(in, &hdr, &symtab) < 0) {
		if (strtab)
			free(strtab);
		return -1;
	}

	for (i = 0; i < hdr.stab_count; i++) {
		uint8_t *entry = symtab + i * STAB_ENTRY_SIZE;
		uint32_t value = LE_LONG(entry, 8);
		int storage_class = entry[16];
		char namebuf[9];
		const char *name = NULL;

		if (LE_LONG(entry, 0)) {
			memcpy(namebuf, entry, 8);
			namebuf[8] = 0;
			name = namebuf;
		} else {
			uint32_t offset = LE_LONG(entry, 4);

			if (offset >= 4 && offset < strtab_len)
				name = strtab + offset;
		}

		if (name &&
		    (storage_class == C_EXT || storage_class == C_LABEL) &&
		    stab_set(name, value) < 0) {
			printc_err("coff: failed to insert symbol\n");
			ret = -1;
			break;
		}

		/* Skip auxiliary entries */
		i += entry[17];
	}

	if (symtab)
		free(symtab);
	if (strtab)
		free(strtab);

	return ret;
}
Exemple #2
0
int
main(int argc, char *argv[])
{
	const char *filename = NULL;
	const char *ufile = NULL;
	int error = 0;
	int c, fd, ufd;

	ctf_data_t cd;
	const ctf_preamble_t *pp;
	ctf_header_t *hp;
	Elf *elf;
	GElf_Ehdr ehdr;

	(void) elf_version(EV_CURRENT);

	for (opterr = 0; optind < argc; optind++) {
		while ((c = getopt(argc, argv, "dfhlsStu:")) != (int)EOF) {
			switch (c) {
			case 'd':
				flags |= F_DATA;
				break;
			case 'f':
				flags |= F_FUNC;
				break;
			case 'h':
				flags |= F_HDR;
				break;
			case 'l':
				flags |= F_LABEL;
				break;
			case 's':
				flags |= F_STR;
				break;
			case 'S':
				flags |= F_STATS;
				break;
			case 't':
				flags |= F_TYPES;
				break;
			case 'u':
				ufile = optarg;
				break;
			default:
				if (optopt == '?')
					return (print_usage(stdout, 1));
				warn("illegal option -- %c\n", optopt);
				return (print_usage(stderr, 0));
			}
		}

		if (optind < argc) {
			if (filename != NULL)
				return (print_usage(stderr, 0));
			filename = argv[optind];
		}
	}

	if (filename == NULL)
		return (print_usage(stderr, 0));

	if (flags == 0 && ufile == NULL)
		flags = F_ALLMSK;

	if ((fd = open(filename, O_RDONLY)) == -1)
		die("failed to open %s", filename);

	if ((elf = elf_begin(fd, ELF_C_READ, NULL)) != NULL &&
	    gelf_getehdr(elf, &ehdr) != NULL) {

		Elf_Data *dp;
		Elf_Scn *ctfscn = findelfscn(elf, &ehdr, ".SUNW_ctf");
		Elf_Scn *symscn;
		GElf_Shdr ctfshdr;

		if (ctfscn == NULL || (dp = elf_getdata(ctfscn, NULL)) == NULL)
			die("%s does not contain .SUNW_ctf data\n", filename);

		cd.cd_ctfdata = dp->d_buf;
		cd.cd_ctflen = dp->d_size;

		/*
		 * If the sh_link field of the CTF section header is non-zero
		 * it indicates which section contains the symbol table that
		 * should be used. We default to the .symtab section if sh_link
		 * is zero or if there's an error reading the section header.
		 */
		if (gelf_getshdr(ctfscn, &ctfshdr) != NULL &&
		    ctfshdr.sh_link != 0) {
			symscn = elf_getscn(elf, ctfshdr.sh_link);
		} else {
			symscn = findelfscn(elf, &ehdr, ".symtab");
		}

		/* If we found a symbol table, find the corresponding strings */
		if (symscn != NULL) {
			GElf_Shdr shdr;
			Elf_Scn *symstrscn;

			if (gelf_getshdr(symscn, &shdr) != NULL) {
				symstrscn = elf_getscn(elf, shdr.sh_link);

				cd.cd_nsyms = shdr.sh_size / shdr.sh_entsize;
				cd.cd_symdata = elf_getdata(symscn, NULL);
				cd.cd_strdata = elf_getdata(symstrscn, NULL);
			}
		}
	} else {
		struct stat st;

		if (fstat(fd, &st) == -1)
			die("failed to fstat %s", filename);

		cd.cd_ctflen = st.st_size;
		cd.cd_ctfdata = mmap(NULL, cd.cd_ctflen, PROT_READ,
		    MAP_PRIVATE, fd, 0);
		if (cd.cd_ctfdata == MAP_FAILED)
			die("failed to mmap %s", filename);
	}

	/*
	 * Get a pointer to the CTF data buffer and interpret the first portion
	 * as a ctf_header_t.  Validate the magic number and size.
	 */

	if (cd.cd_ctflen < sizeof (ctf_preamble_t))
		die("%s does not contain a CTF preamble\n", filename);

	/* LINTED - pointer alignment */
	pp = (const ctf_preamble_t *)cd.cd_ctfdata;

	if (pp->ctp_magic != CTF_MAGIC)
		die("%s does not appear to contain CTF data\n", filename);

	if (pp->ctp_version == CTF_VERSION) {
		/* LINTED - pointer alignment */
		hp = (ctf_header_t *)cd.cd_ctfdata;
		cd.cd_ctfdata = (caddr_t)cd.cd_ctfdata + sizeof (ctf_header_t);

		if (cd.cd_ctflen < sizeof (ctf_header_t)) {
			die("%s does not contain a v%d CTF header\n", filename,
			    CTF_VERSION);
		}

	} else {
		die("%s contains unsupported CTF version %d\n", filename,
		    pp->ctp_version);
	}

	/*
	 * If the data buffer is compressed, then malloc a buffer large enough
	 * to hold the decompressed data, and use zlib to decompress it.
	 */
	if (hp->cth_flags & CTF_F_COMPRESS) {
		z_stream zstr;
		void *buf;
		int rc;

		if ((buf = malloc(hp->cth_stroff + hp->cth_strlen)) == NULL)
			die("failed to allocate decompression buffer");

		bzero(&zstr, sizeof (z_stream));
		zstr.next_in = (void *)cd.cd_ctfdata;
		zstr.avail_in = cd.cd_ctflen;
		zstr.next_out = buf;
		zstr.avail_out = hp->cth_stroff + hp->cth_strlen;

		if ((rc = inflateInit(&zstr)) != Z_OK)
			die("failed to initialize zlib: %s\n", zError(rc));

		if ((rc = inflate(&zstr, Z_FINISH)) != Z_STREAM_END)
			die("failed to decompress CTF data: %s\n", zError(rc));

		if ((rc = inflateEnd(&zstr)) != Z_OK)
			die("failed to finish decompression: %s\n", zError(rc));

		if (zstr.total_out != hp->cth_stroff + hp->cth_strlen)
			die("CTF data is corrupt -- short decompression\n");

		cd.cd_ctfdata = buf;
		cd.cd_ctflen = hp->cth_stroff + hp->cth_strlen;
	}

	if (flags & F_HDR)
		error |= print_header(hp, &cd);
	if (flags & (F_LABEL))
		error |= print_labeltable(hp, &cd);
	if (flags & (F_DATA | F_STATS))
		error |= read_data(hp, &cd);
	if (flags & (F_FUNC | F_STATS))
		error |= read_funcs(hp, &cd);
	if (flags & (F_TYPES | F_STATS))
		error |= read_types(hp, &cd);
	if (flags & (F_STR | F_STATS))
		error |= read_strtab(hp, &cd);
	if (flags & F_STATS)
		error |= print_stats();

	/*
	 * If the -u option is specified, write the uncompressed CTF data to a
	 * raw CTF file.  CTF data can already be extracted compressed by
	 * applying elfdump -w -N .SUNW_ctf to an ELF file, so we don't bother.
	 */
	if (ufile != NULL) {
		ctf_header_t h;

		bcopy(hp, &h, sizeof (h));
		h.cth_flags &= ~CTF_F_COMPRESS;

		if ((ufd = open(ufile, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0 ||
		    write(ufd, &h, sizeof (h)) != sizeof (h) ||
		    write(ufd, cd.cd_ctfdata, cd.cd_ctflen) != cd.cd_ctflen) {
			warn("failed to write CTF data to '%s'", ufile);
			error |= E_ERROR;
		}

		(void) close(ufd);
	}

	if (elf != NULL)
		(void) elf_end(elf);

	(void) close(fd);
	return (error);
}