svn commit: r323071 - in vendor/ctfdump: . dist

Baptiste Daroussin bapt at FreeBSD.org
Thu Aug 31 21:22:20 UTC 2017


Author: bapt
Date: Thu Aug 31 21:22:18 2017
New Revision: 323071
URL: https://svnweb.freebsd.org/changeset/base/323071

Log:
  Import ctfdump from OpenBSD (ISC license)
  
  For now import it from my own github repository which is a fork
  of mpi at OpenBSD's version for portability issues. This will be switched
  to mpi's version once portability issues will have been addressed
  
  Discussed with:	mpi@
  Obtained from:	OpenBSD

Added:
  vendor/ctfdump/
  vendor/ctfdump/dist/
  vendor/ctfdump/dist/Makefile   (contents, props changed)
  vendor/ctfdump/dist/ctfdump.1   (contents, props changed)
  vendor/ctfdump/dist/ctfdump.c   (contents, props changed)
  vendor/ctfdump/dist/elf.c   (contents, props changed)

Added: vendor/ctfdump/dist/Makefile
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ vendor/ctfdump/dist/Makefile	Thu Aug 31 21:22:18 2017	(r323071)
@@ -0,0 +1,11 @@
+
+PROG=		ctfdump
+SRCS=		ctfdump.c elf.c
+
+CFLAGS+=	-W -Wall -Wstrict-prototypes -Wno-unused -Wunused-variable
+
+CFLAGS+=	-DZLIB
+LDADD+=		-lz
+DPADD+=		${LIBZ}
+
+.include <bsd.prog.mk>

Added: vendor/ctfdump/dist/ctfdump.1
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ vendor/ctfdump/dist/ctfdump.1	Thu Aug 31 21:22:18 2017	(r323071)
@@ -0,0 +1,53 @@
+.\"
+.\" Copyright (c) 2016 Martin Pieuchot <mpi at openbsd.org>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.Dd $Mdocdate$
+.Dt CTFDUMP 1
+.Os
+.Sh NAME
+.Nm ctfdump
+.Nd display CTF information
+.Sh SYNOPSIS
+.Nm ctfdump
+.Op Fl dfhlst
+file ...
+.Sh DESCRIPTION
+The
+.Nm
+utility display CTF information from the
+.Dv \.SUNW_ctf
+section of an
+.Xr elf 5
+file or from a raw CTF file.
+.Pp
+The options are as follows:
+.Bl -tag -width Ds
+.It Fl d
+Display the object section.
+.It Fl f
+Display the function section.
+.It Fl h
+Dump the CTF header.
+.It Fl l
+Display the label section.
+.It Fl s
+Display the string table.
+.It Fl t
+Display the type section.
+.El
+.Sh EXIT STATUS
+.Ex -std ctfdump
+.Sh SEE ALSO
+.Xr elf 5

Added: vendor/ctfdump/dist/ctfdump.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ vendor/ctfdump/dist/ctfdump.c	Thu Aug 31 21:22:18 2017	(r323071)
@@ -0,0 +1,638 @@
+/*
+ * Copyright (c) 2016 Martin Pieuchot <mpi at openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/elf.h>
+#include <sys/mman.h>
+#include <sys/ctf.h>
+
+#include <err.h>
+#include <fcntl.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifdef ZLIB
+#include <zlib.h>
+#endif /* ZLIB */
+
+#ifndef nitems
+#define nitems(_a)	(sizeof((_a)) / sizeof((_a)[0]))
+#endif
+
+#ifndef ELF_STRTAB
+#define ELF_STRTAB ".strtab"
+#endif
+#ifndef ELF_CTF
+#define ELF_CTF ".SUNW_ctf"
+#endif
+
+#define DUMP_OBJECT	(1 << 0)
+#define DUMP_FUNCTION	(1 << 1)
+#define DUMP_HEADER	(1 << 2)
+#define DUMP_LABEL	(1 << 3)
+#define DUMP_STRTAB	(1 << 4)
+#define DUMP_STATISTIC	(1 << 5)
+#define DUMP_TYPE	(1 << 6)
+
+int		 dump(const char *, uint8_t);
+int		 isctf(const char *, size_t);
+__dead2 void	 usage(void);
+
+int		 ctf_dump(const char *, size_t, uint8_t);
+uint32_t	 ctf_dump_type(struct ctf_header *, const char *, off_t,
+		     uint32_t, uint32_t);
+const char	*ctf_kind2name(uint16_t);
+const char	*ctf_enc2name(uint16_t);
+const char	*ctf_off2name(struct ctf_header *, const char *, off_t,
+		     uint32_t);
+
+int		 elf_dump(char *, size_t, uint8_t);
+const char	*elf_idx2sym(size_t *, uint8_t);
+
+/* elf.c */
+int		 iself(const char *, size_t);
+int		 elf_getshstab(const char *, size_t, const char **, size_t *);
+ssize_t		 elf_getsymtab(const char *, const char *, size_t,
+		     const Elf_Sym **, size_t *);
+ssize_t		 elf_getsection(char *, const char *, const char *,
+		     size_t, const char **, size_t *);
+
+char		*decompress(const char *, size_t, size_t);
+
+int
+main(int argc, char *argv[])
+{
+	const char *filename;
+	uint8_t flags = 0;
+	int ch, error = 0;
+
+	setlocale(LC_ALL, "");
+
+	while ((ch = getopt(argc, argv, "dfhlst")) != -1) {
+		switch (ch) {
+		case 'd':
+			flags |= DUMP_OBJECT;
+			break;
+		case 'f':
+			flags |= DUMP_FUNCTION;
+			break;
+		case 'h':
+			flags |= DUMP_HEADER;
+			break;
+		case 'l':
+			flags |= DUMP_LABEL;
+			break;
+		case 's':
+			flags |= DUMP_STRTAB;
+			break;
+		case 't':
+			flags |= DUMP_TYPE;
+			break;
+		default:
+			usage();
+		}
+	}
+
+	argc -= optind;
+	argv += optind;
+
+	if (argc <= 0)
+		usage();
+
+	/* Dump everything by default */
+	if (flags == 0)
+		flags = 0xff;
+
+	while ((filename = *argv++) != NULL)
+		error |= dump(filename, flags);
+
+	return error;
+}
+
+int
+dump(const char *path, uint8_t flags)
+{
+	struct stat		 st;
+	int			 fd, error = 1;
+	char			*p;
+
+	fd = open(path, O_RDONLY);
+	if (fd == -1) {
+		warn("open");
+		return 1;
+	}
+	if (fstat(fd, &st) == -1) {
+		warn("fstat");
+		return 1;
+	}
+	if ((uintmax_t)st.st_size > SIZE_MAX) {
+		warnx("file too big to fit memory");
+		return 1;
+	}
+
+	p = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+	if (p == MAP_FAILED)
+		err(1, "mmap");
+
+	if (iself(p, st.st_size)) {
+		error = elf_dump(p, st.st_size, flags);
+	} else if (isctf(p, st.st_size)) {
+		error = ctf_dump(p, st.st_size, flags);
+	}
+
+	munmap(p, st.st_size);
+	close(fd);
+
+	return error;
+}
+
+const char		*strtab;
+const Elf_Sym		*symtab;
+size_t			 strtabsz, nsymb;
+
+const char *
+elf_idx2sym(size_t *idx, uint8_t type)
+{
+	const Elf_Sym	*st;
+	size_t		 i;
+
+	for (i = *idx + 1; i < nsymb; i++) {
+		st = &symtab[i];
+
+		if (ELF_ST_TYPE(st->st_info) != type)
+			continue;
+
+		*idx = i;
+		return strtab + st->st_name;
+	}
+
+	return NULL;
+}
+
+int
+elf_dump(char *p, size_t filesize, uint8_t flags)
+{
+	Elf_Ehdr		*eh = (Elf_Ehdr *)p;
+	Elf_Shdr		*sh;
+	const char		*shstab;
+	size_t			 i, shstabsz;
+
+	/* Find section header string table location and size. */
+	if (elf_getshstab(p, filesize, &shstab, &shstabsz))
+		return 1;
+
+	/* Find symbol table location and number of symbols. */
+	if (elf_getsymtab(p, shstab, shstabsz, &symtab, &nsymb) == -1)
+		warnx("symbol table not found");
+
+	/* Find string table location and size. */
+	if (elf_getsection(p, ELF_STRTAB, shstab, shstabsz, &strtab,
+	    &strtabsz) == -1)
+		warnx("string table not found");
+
+	/* Find CTF section and dump it. */
+	for (i = 0; i < eh->e_shnum; i++) {
+		sh = (Elf_Shdr *)(p + eh->e_shoff + i * eh->e_shentsize);
+
+		if ((sh->sh_link >= eh->e_shnum) ||
+		    (sh->sh_name >= shstabsz))
+			continue;
+
+		if (strncmp(shstab + sh->sh_name, ELF_CTF, strlen(ELF_CTF)))
+			continue;
+
+		if (!isctf(p + sh->sh_offset, sh->sh_size))
+			break;
+
+		return ctf_dump(p + sh->sh_offset, sh->sh_size, flags);
+	}
+
+	warnx("%s section not found", ELF_CTF);
+	return 1;
+}
+
+int
+isctf(const char *p, size_t filesize)
+{
+	struct ctf_header	*cth = (struct ctf_header *)p;
+	size_t 			 dlen;
+
+	if (filesize < sizeof(struct ctf_header)) {
+		warnx("file too small to be CTF");
+		return 0;
+	}
+
+	if (cth->cth_magic != CTF_MAGIC || cth->cth_version != CTF_VERSION)
+		return 0;
+
+	dlen = cth->cth_stroff + cth->cth_strlen;
+	if (dlen > filesize && !(cth->cth_flags & CTF_F_COMPRESS)) {
+		warnx("bogus file size");
+		return 0;
+	}
+
+	if ((cth->cth_lbloff & 3) || (cth->cth_objtoff & 1) ||
+	    (cth->cth_funcoff & 1) || (cth->cth_typeoff & 3)) {
+		warnx("wrongly aligned offset");
+		return 0;
+	}
+
+	if ((cth->cth_lbloff >= dlen) || (cth->cth_objtoff >= dlen) ||
+	    (cth->cth_funcoff >= dlen) || (cth->cth_typeoff >= dlen)) {
+		warnx("truncated file");
+		return 0;
+	}
+
+	if ((cth->cth_lbloff > cth->cth_objtoff) ||
+	    (cth->cth_objtoff > cth->cth_funcoff) ||
+	    (cth->cth_funcoff > cth->cth_typeoff) ||
+	    (cth->cth_typeoff > cth->cth_stroff)) {
+		warnx("corrupted file");
+		return 0;
+	}
+
+	return 1;
+}
+
+int
+ctf_dump(const char *p, size_t size, uint8_t flags)
+{
+	struct ctf_header	*cth = (struct ctf_header *)p;
+	off_t 			 dlen = cth->cth_stroff + cth->cth_strlen;
+	char			*data;
+
+	if (cth->cth_flags & CTF_F_COMPRESS) {
+		data = decompress(p + sizeof(*cth), size - sizeof(*cth), dlen);
+		if (data == NULL)
+			return 1;
+	} else {
+		data = (char *)p + sizeof(*cth);
+	}
+
+	if (flags & DUMP_HEADER) {
+		printf("  cth_magic    = 0x%04x\n", cth->cth_magic);
+		printf("  cth_version  = %d\n", cth->cth_version);
+		printf("  cth_flags    = 0x%02x\n", cth->cth_flags);
+		printf("  cth_parlabel = %s\n",
+		    ctf_off2name(cth, data, dlen, cth->cth_parname));
+		printf("  cth_parname  = %s\n",
+		    ctf_off2name(cth, data, dlen, cth->cth_parname));
+		printf("  cth_lbloff   = %d\n", cth->cth_lbloff);
+		printf("  cth_objtoff  = %d\n", cth->cth_objtoff);
+		printf("  cth_funcoff  = %d\n", cth->cth_funcoff);
+		printf("  cth_typeoff  = %d\n", cth->cth_typeoff);
+		printf("  cth_stroff   = %d\n", cth->cth_stroff);
+		printf("  cth_strlen   = %d\n", cth->cth_strlen);
+		printf("\n");
+	}
+
+	if (flags & DUMP_LABEL) {
+		uint32_t		 lbloff = cth->cth_lbloff;
+		struct ctf_lblent	*ctl;
+
+		while (lbloff < cth->cth_objtoff) {
+			ctl = (struct ctf_lblent *)(data + lbloff);
+
+			printf("  %5u %s\n", ctl->ctl_typeidx,
+			    ctf_off2name(cth, data, dlen, ctl->ctl_label));
+
+			lbloff += sizeof(*ctl);
+		}
+		printf("\n");
+	}
+
+	if (flags & DUMP_OBJECT) {
+		uint32_t		 objtoff = cth->cth_objtoff;
+		size_t			 idx = 0, i = 0;
+		uint16_t		*dsp;
+		const char		*s;
+		int			 l;
+
+		while (objtoff < cth->cth_funcoff) {
+			dsp = (uint16_t *)(data + objtoff);
+
+			l = printf("  [%zu] %u", i++, *dsp);
+			if ((s = elf_idx2sym(&idx, STT_OBJECT)) != NULL)
+				printf("%*s %s (%zu)\n", (14 - l), "", s, idx);
+			else
+				printf("\n");
+
+			objtoff += sizeof(*dsp);
+		}
+		printf("\n");
+	}
+
+	if (flags & DUMP_FUNCTION) {
+		uint16_t		*fsp, kind, vlen;
+		size_t			 idx = 0, i = -1;
+		const char		*s;
+		int			 l;
+
+		fsp = (uint16_t *)(data + cth->cth_funcoff);
+		while (fsp < (uint16_t *)(data + cth->cth_typeoff)) {
+			kind = CTF_INFO_KIND(*fsp);
+			vlen = CTF_INFO_VLEN(*fsp);
+			s = elf_idx2sym(&idx, STT_FUNC);
+			fsp++;
+			i++;
+
+			if (kind == CTF_K_UNKNOWN && vlen == 0)
+				continue;
+
+			l = printf("  [%zu] FUNC ", i);
+			if (s != NULL)
+				printf("(%s)", s);
+			printf(" returns: %u args: (", *fsp++);
+			while (vlen-- > 0)
+				printf("%u%s", *fsp++, (vlen > 0) ? ", " : "");
+			printf(")\n");
+		}
+		printf("\n");
+	}
+
+	if (flags & DUMP_TYPE) {
+		uint32_t		 idx = 1, offset = cth->cth_typeoff;
+
+		while (offset < cth->cth_stroff) {
+			offset += ctf_dump_type(cth, data, dlen, offset, idx++);
+		}
+		printf("\n");
+	}
+
+	if (flags & DUMP_STRTAB) {
+		uint32_t		 offset = 0;
+		const char		*str;
+
+		while (offset < cth->cth_strlen) {
+			str = ctf_off2name(cth, data, dlen, offset);
+
+			printf("  [%u] ", offset);
+			if (strcmp(str, "(anon)"))
+				offset += printf("%s\n", str);
+			else {
+				printf("\\0\n");
+				offset++;
+			}
+		}
+		printf("\n");
+	}
+
+	if (cth->cth_flags & CTF_F_COMPRESS)
+		free(data);
+
+	return 0;
+}
+
+uint32_t
+ctf_dump_type(struct ctf_header *cth, const char *data, off_t dlen,
+    uint32_t offset, uint32_t idx)
+{
+	const char		*p = data + offset;
+	const struct ctf_type	*ctt = (struct ctf_type *)p;
+	const struct ctf_array	*cta;
+	uint16_t		*argp, i, kind, vlen, root;
+	uint32_t		 eob, toff;
+	uint64_t		 size;
+	const char		*name, *kname;
+
+	kind = CTF_INFO_KIND(ctt->ctt_info);
+	vlen = CTF_INFO_VLEN(ctt->ctt_info);
+	root = CTF_INFO_ISROOT(ctt->ctt_info);
+	name = ctf_off2name(cth, data, dlen, ctt->ctt_name);
+
+	if (root)
+		printf("  <%u> ", idx);
+	else
+		printf("  [%u] ", idx);
+
+	if ((kname = ctf_kind2name(kind)) != NULL)
+		printf("%s %s", kname, name);
+
+	if (ctt->ctt_size <= CTF_MAX_SIZE) {
+		size = ctt->ctt_size;
+		toff = sizeof(struct ctf_stype);
+	} else {
+		size = CTF_TYPE_LSIZE(ctt);
+		toff = sizeof(struct ctf_type);
+	}
+
+	switch (kind) {
+	case CTF_K_UNKNOWN:
+	case CTF_K_FORWARD:
+		break;
+	case CTF_K_INTEGER:
+		eob = *((uint32_t *)(p + toff));
+		toff += sizeof(uint32_t);
+		printf(" encoding=%s offset=%u bits=%u",
+		    ctf_enc2name(CTF_INT_ENCODING(eob)), CTF_INT_OFFSET(eob),
+		    CTF_INT_BITS(eob));
+		break;
+	case CTF_K_FLOAT:
+		eob = *((uint32_t *)(p + toff));
+		toff += sizeof(uint32_t);
+		printf(" encoding=0x%x offset=%u bits=%u",
+		    CTF_FP_ENCODING(eob), CTF_FP_OFFSET(eob), CTF_FP_BITS(eob));
+		break;
+	case CTF_K_ARRAY:
+		cta = (struct ctf_array *)(p + toff);
+		printf(" content: %u index: %u nelems: %u\n", cta->cta_contents,
+		    cta->cta_index, cta->cta_nelems);
+		toff += sizeof(struct ctf_array);
+		break;
+	case CTF_K_FUNCTION:
+		argp = (uint16_t *)(p + toff);
+		printf(" returns: %u args: (%u", ctt->ctt_type, *argp);
+		for (i = 1; i < vlen; i++) {
+			argp++;
+			printf(", %u", *argp);
+		}
+		printf(")");
+		toff += (vlen + (vlen & 1)) * sizeof(uint16_t);
+		break;
+	case CTF_K_STRUCT:
+	case CTF_K_UNION:
+		printf(" (%lu bytes)\n", size);
+
+		if (size < CTF_LSTRUCT_THRESH) {
+			for (i = 0; i < vlen; i++) {
+				struct ctf_member	*ctm;
+
+				ctm = (struct ctf_member *)(p + toff);
+				toff += sizeof(struct ctf_member);
+
+				printf("\t%s type=%u off=%u\n",
+				    ctf_off2name(cth, data, dlen,
+					ctm->ctm_name),
+				    ctm->ctm_type, ctm->ctm_offset);
+			}
+		} else {
+			for (i = 0; i < vlen; i++) {
+				struct ctf_lmember	*ctlm;
+
+				ctlm = (struct ctf_lmember *)(p + toff);
+				toff += sizeof(struct ctf_lmember);
+
+				printf("\t%s type=%u off=%zu\n",
+				    ctf_off2name(cth, data, dlen,
+					ctlm->ctlm_name),
+				    ctlm->ctlm_type, CTF_LMEM_OFFSET(ctlm));
+			}
+		}
+		break;
+	case CTF_K_ENUM:
+		printf("\n");
+		for (i = 0; i < vlen; i++) {
+			struct ctf_enum	*cte;
+
+			cte = (struct ctf_enum *)(p + toff);
+			toff += sizeof(struct ctf_enum);
+
+			printf("\t%s = %d\n",
+			    ctf_off2name(cth, data, dlen, cte->cte_name),
+			    cte->cte_value);
+		}
+		break;
+	case CTF_K_POINTER:
+	case CTF_K_TYPEDEF:
+	case CTF_K_VOLATILE:
+	case CTF_K_CONST:
+	case CTF_K_RESTRICT:
+		printf(" refers to %u", ctt->ctt_type);
+		break;
+	default:
+		errx(1, "incorrect type %u at offset %u", kind, offset);
+	}
+
+	printf("\n");
+
+	return toff;
+}
+
+const char *
+ctf_kind2name(uint16_t kind)
+{
+	static const char *kind_name[] = { NULL, "INTEGER", "FLOAT", "POINTER",
+	   "ARRAY", "FUNCTION", "STRUCT", "UNION", "ENUM", "FORWARD",
+	   "TYPEDEF", "VOLATILE", "CONST", "RESTRICT" };
+
+	if (kind >= nitems(kind_name))
+		return NULL;
+
+	return kind_name[kind];
+}
+
+const char *
+ctf_enc2name(uint16_t enc)
+{
+	static const char *enc_name[] = { "SIGNED", "CHAR", "SIGNED CHAR",
+	    "BOOL", "SIGNED BOOL" };
+	static char invalid[7];
+
+	if (enc == CTF_INT_VARARGS)
+		return "VARARGS";
+
+	if (enc > 0 && enc < nitems(enc_name))
+		return enc_name[enc - 1];
+
+	snprintf(invalid, sizeof(invalid), "0x%x", enc);
+	return invalid;
+}
+
+const char *
+ctf_off2name(struct ctf_header *cth, const char *data, off_t dlen,
+    uint32_t offset)
+{
+	const char		*name;
+
+	if (CTF_NAME_STID(offset) != CTF_STRTAB_0)
+		return "external";
+
+	if (CTF_NAME_OFFSET(offset) >= cth->cth_strlen)
+		return "exceeds strlab";
+
+	if (cth->cth_stroff + CTF_NAME_OFFSET(offset) >= dlen)
+		return "invalid";
+
+	name = data + cth->cth_stroff + CTF_NAME_OFFSET(offset);
+	if (*name == '\0')
+		return "(anon)";
+
+	return name;
+}
+
+char *
+decompress(const char *buf, size_t size, size_t len)
+{
+#ifdef ZLIB
+	z_stream		 stream;
+	char			*data;
+	int			 error;
+
+	data = malloc(len);
+	if (data == NULL) {
+		warn(NULL);
+		return NULL;
+	}
+
+	memset(&stream, 0, sizeof(stream));
+	stream.next_in = (void *)buf;
+	stream.avail_in = size;
+	stream.next_out = (uint8_t *)data;
+	stream.avail_out = len;
+
+	if ((error = inflateInit(&stream)) != Z_OK) {
+		warnx("zlib inflateInit failed: %s", zError(error));
+		goto exit;
+	}
+
+	if ((error = inflate(&stream, Z_FINISH)) != Z_STREAM_END) {
+		warnx("zlib inflate failed: %s", zError(error));
+		inflateEnd(&stream);
+		goto exit;
+	}
+
+	if ((error = inflateEnd(&stream)) != Z_OK) {
+		warnx("zlib inflateEnd failed: %s", zError(error));
+		goto exit;
+	}
+
+	if (stream.total_out != len) {
+		warnx("decompression failed: %zu != %zu",
+		    stream.total_out, len);
+		goto exit;
+	}
+
+	return data;
+
+exit:
+	free(data);
+#endif /* ZLIB */
+	return NULL;
+}
+
+__dead2 void
+usage(void)
+{
+	fprintf(stderr, "usage: %s [-dfhlst] file ...\n",
+	    getprogname());
+	exit(1);
+}

Added: vendor/ctfdump/dist/elf.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ vendor/ctfdump/dist/elf.c	Thu Aug 31 21:22:18 2017	(r323071)
@@ -0,0 +1,287 @@
+/*
+ * Copyright (c) 2016 Martin Pieuchot <mpi at openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/elf.h>
+
+#include <machine/reloc.h>
+
+#include <assert.h>
+#include <err.h>
+#include <string.h>
+
+#define ELF_SYMTAB	".symtab"
+#define Elf_RelA	__CONCAT(__CONCAT(Elf,__ELF_WORD_SIZE),_Rela)
+
+static int	elf_reloc_size(unsigned long);
+static void	elf_reloc_apply(const char *, const char *, size_t, ssize_t,
+		    char *, size_t);
+
+int
+iself(const char *p, size_t filesize)
+{
+	Elf_Ehdr		*eh = (Elf_Ehdr *)p;
+
+	if (filesize < (off_t)sizeof(Elf_Ehdr)) {
+		warnx("file too small to be ELF");
+		return 0;
+	}
+
+	if (eh->e_ehsize < sizeof(Elf_Ehdr) || !IS_ELF(*eh))
+		return 0;
+
+	if (eh->e_ident[EI_CLASS] != ELF_CLASS) {
+		warnx("unexpected word size %u", eh->e_ident[EI_CLASS]);
+		return 0;
+	}
+	if (eh->e_ident[EI_VERSION] != ELF_TARG_VER) {
+		warnx("unexpected version %u", eh->e_ident[EI_VERSION]);
+		return 0;
+	}
+	if (eh->e_ident[EI_DATA] > ELFDATA2MSB) {
+		warnx("unexpected data format %u", eh->e_ident[EI_DATA]);
+		return 0;
+	}
+	if (eh->e_shoff > filesize) {
+		warnx("bogus section table offset 0x%lx", (off_t)eh->e_shoff);
+		return 0;
+	}
+	if (eh->e_shentsize < sizeof(Elf_Shdr)) {
+		warnx("bogus section header size %u", eh->e_shentsize);
+		return 0;
+	}
+	if (eh->e_shnum > (filesize - eh->e_shoff) / eh->e_shentsize) {
+		warnx("bogus section header count %u", eh->e_shnum);
+		return 0;
+	}
+	if (eh->e_shstrndx >= eh->e_shnum) {
+		warnx("bogus string table index %u", eh->e_shstrndx);
+		return 0;
+	}
+
+	return 1;
+}
+
+int
+elf_getshstab(const char *p, size_t filesize, const char **shstab,
+    size_t *shstabsize)
+{
+	Elf_Ehdr		*eh = (Elf_Ehdr *)p;
+	Elf_Shdr		*sh;
+
+	sh = (Elf_Shdr *)(p + eh->e_shoff + eh->e_shstrndx * eh->e_shentsize);
+	if (sh->sh_type != SHT_STRTAB) {
+		warnx("unexpected string table type");
+		return -1;
+	}
+	if (sh->sh_offset > filesize) {
+		warnx("bogus string table offset");
+		return -1;
+	}
+	if (sh->sh_size > filesize - sh->sh_offset) {
+		warnx("bogus string table size");
+		return -1;
+	}
+	if (shstab != NULL)
+		*shstab = p + sh->sh_offset;
+	if (shstabsize != NULL)
+		*shstabsize = sh->sh_size;
+
+	return 0;
+}
+
+ssize_t
+elf_getsymtab(const char *p, const char *shstab, size_t shstabsz,
+    const Elf_Sym **symtab, size_t *nsymb)
+{
+	Elf_Ehdr	*eh = (Elf_Ehdr *)p;
+	Elf_Shdr	*sh;
+	size_t		 snlen;
+	ssize_t		 i;
+
+	snlen = strlen(ELF_SYMTAB);
+
+	for (i = 0; i < eh->e_shnum; i++) {
+		sh = (Elf_Shdr *)(p + eh->e_shoff + i * eh->e_shentsize);
+
+		if (sh->sh_type != SHT_SYMTAB)
+			continue;
+
+		if ((sh->sh_link >= eh->e_shnum) || (sh->sh_name >= shstabsz))
+			continue;
+
+		if (strncmp(shstab + sh->sh_name, ELF_SYMTAB, snlen) == 0) {
+			if (symtab != NULL)
+				*symtab = (Elf_Sym *)(p + sh->sh_offset);
+			if (nsymb != NULL)
+				*nsymb = (sh->sh_size / sh->sh_entsize);
+
+			return i;
+		}
+	}
+
+	return -1;
+}
+
+ssize_t
+elf_getsection(char *p, const char *sname, const char *shstab,
+    size_t shstabsz, const char **psdata, size_t *pssz)
+{
+	Elf_Ehdr	*eh = (Elf_Ehdr *)p;
+	Elf_Shdr	*sh;
+	char		*sdata = NULL;
+	size_t		 snlen, ssz = 0;
+	ssize_t		 sidx, i;
+
+	snlen = strlen(sname);
+	if (snlen == 0)
+		return -1;
+
+	/* Find the given section. */
+	for (i = 0; i < eh->e_shnum; i++) {
+		sh = (Elf_Shdr *)(p + eh->e_shoff + i * eh->e_shentsize);
+
+		if ((sh->sh_link >= eh->e_shnum) || (sh->sh_name >= shstabsz))
+			continue;
+
+		if (strncmp(shstab + sh->sh_name, sname, snlen) == 0) {
+			sidx = i;
+			sdata = p + sh->sh_offset;
+			ssz = sh->sh_size;
+			elf_reloc_apply(p, shstab, shstabsz, sidx, sdata, ssz);
+			break;
+		}
+	}
+
+	if (sdata == NULL)
+		return -1;
+
+	if (psdata != NULL)
+		*psdata = sdata;
+	if (pssz != NULL)
+		*pssz = ssz;
+
+	return sidx;
+}
+
+static int
+elf_reloc_size(unsigned long type)
+{
+	switch (type) {
+#ifdef R_X86_64_64
+	case R_X86_64_64:
+		return sizeof(uint64_t);
+#endif
+#ifdef R_X86_64_32
+	case R_X86_64_32:
+		return sizeof(uint32_t);
+#endif
+#ifdef RELOC_32
+	case RELOC_32:
+		return sizeof(uint32_t);
+#endif
+	default:
+		break;
+	}
+
+	return -1;
+}
+
+#define ELF_WRITE_RELOC(buf, val, rsize)				\
+do {									\
+	if (rsize == 4) {						\
+		uint32_t v32 = val;					\
+		memcpy(buf, &v32, sizeof(v32));				\
+	} else {							\
+		uint64_t v64 = val;					\
+		memcpy(buf, &v64, sizeof(v64));				\
+	}								\
+} while (0)
+
+static void
+elf_reloc_apply(const char *p, const char *shstab, size_t shstabsz,
+    ssize_t sidx, char *sdata, size_t ssz)
+{
+	Elf_Ehdr	*eh = (Elf_Ehdr *)p;
+	Elf_Shdr	*sh;
+	Elf_Rel		*rel = NULL;
+	Elf_RelA	*rela = NULL;
+	const Elf_Sym	*symtab, *sym;
+	ssize_t		 symtabidx;
+	size_t		 nsymb, rsym, rtyp, roff;
+	size_t		 i, j;
+	uint64_t	 value;
+	int		 rsize;
+
+	/* Find symbol table location and number of symbols. */
+	symtabidx = elf_getsymtab(p, shstab, shstabsz, &symtab, &nsymb);
+	if (symtabidx == -1) {
+		warnx("symbol table not found");
+		return;
+	}
+
+	/* Apply possible relocation. */
+	for (i = 0; i < eh->e_shnum; i++) {
+		sh = (Elf_Shdr *)(p + eh->e_shoff + i * eh->e_shentsize);
+
+		if (sh->sh_size == 0)
+			continue;
+
+		if ((sh->sh_info != sidx) || (sh->sh_link != symtabidx))
+			continue;
+
+		switch (sh->sh_type) {
+		case SHT_RELA:
+			rela = (Elf_RelA *)(p + sh->sh_offset);
+			for (j = 0; j < (sh->sh_size / sizeof(Elf_RelA)); j++) {
+				rsym = ELF_R_SYM(rela[j].r_info);
+				rtyp = ELF_R_TYPE(rela[j].r_info);
+				roff = rela[j].r_offset;
+				if (rsym >= nsymb)
+					continue;
+				sym = &symtab[rsym];
+				value = sym->st_value + rela[j].r_addend;
+
+				rsize = elf_reloc_size(rtyp);
+				if (rsize == -1 || roff + rsize >= ssz)
+					continue;
+
+				ELF_WRITE_RELOC(sdata + roff, value, rsize);
+			}
+			break;
+		case SHT_REL:
+			rel = (Elf_Rel *)(p + sh->sh_offset);
+			for (j = 0; j < (sh->sh_size / sizeof(Elf_Rel)); j++) {
+				rsym = ELF_R_SYM(rel[j].r_info);
+				rtyp = ELF_R_TYPE(rel[j].r_info);
+				roff = rel[j].r_offset;
+				if (rsym >= nsymb)
+					continue;
+				sym = &symtab[rsym];
+				value = sym->st_value;
+
+				rsize = elf_reloc_size(rtyp);
+				if (rsize == -1 || roff + rsize >= ssz)
+					continue;
+
+				ELF_WRITE_RELOC(sdata + roff, value, rsize);
+			}
+			break;
+		default:
+			continue;
+		}
+	}

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-all mailing list