Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 14 Aug 2006 20:03:09 GMT
From:      John Birrell <jb@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 103895 for review
Message-ID:  <200608142003.k7EK39YI024859@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=103895

Change 103895 by jb@jb_freebsd2 on 2006/08/14 20:02:32

	IFlibbsdelf

Affected files ...

.. //depot/projects/dtrace/src/lib/libelf/Makefile#3 integrate
.. //depot/projects/dtrace/src/lib/libelf/_libelf.h#2 integrate
.. //depot/projects/dtrace/src/lib/libelf/elf.3#2 integrate
.. //depot/projects/dtrace/src/lib/libelf/elf_allocate.c#2 integrate
.. //depot/projects/dtrace/src/lib/libelf/elf_begin.3#2 integrate
.. //depot/projects/dtrace/src/lib/libelf/elf_begin.c#2 integrate
.. //depot/projects/dtrace/src/lib/libelf/elf_end.3#2 integrate
.. //depot/projects/dtrace/src/lib/libelf/elf_end.c#2 integrate
.. //depot/projects/dtrace/src/lib/libelf/elf_memory.c#2 integrate
.. //depot/projects/dtrace/src/lib/libelf/elf_next.3#2 integrate
.. //depot/projects/dtrace/src/lib/libelf/elf_next.c#2 integrate
.. //depot/projects/dtrace/src/lib/libelf/elf_rand.c#2 integrate
.. //depot/projects/dtrace/src/lib/libelf/gelf_xlate.c#2 integrate
.. //depot/projects/dtrace/src/lib/libelf/libelf_msize.m4#1 branch

Differences ...

==== //depot/projects/dtrace/src/lib/libelf/Makefile#3 (text+ko) ====

@@ -5,6 +5,7 @@
 SRCS=	elf_allocate.c						\
 	elf_begin.c						\
 	elf_cntl.c						\
+	elf_dump.c elf_dump_argv.c				\
 	elf_end.c elf_errmsg.c elf_errno.c			\
 	elf_fill.c						\
 	elf_getbase.c						\
@@ -23,11 +24,11 @@
 	libelf.c
 INCS=	libelf.h gelf.h
 
-DPSRCS+=	libelf_fsize.c libelf_convert.c
-CLEANFILES+=	libelf_fsize.c libelf_convert.c
+DPSRCS+=	libelf_fsize.c libelf_msize.c libelf_convert.c
+CLEANFILES+=	libelf_fsize.c libelf_msize.c libelf_convert.c
 CFLAGS+=	-I${.OBJDIR} -I${.CURDIR}
 
-OBJS+=	libelf_convert.o
+OBJS+=	libelf_convert.o libelf_msize.o
 
 WARNS?=	9
 
@@ -114,8 +115,9 @@
 CFLAGS+=	-DLIBELF_TEST_HOOKS=1
 .endif
 
+libelf_convert.c:	elf_types.m4 libelf_convert.m4
 libelf_fsize.c:		elf_types.m4 libelf_fsize.m4
-libelf_convert.c:	elf_types.m4 libelf_convert.m4
+libelf_msize.c:		elf_types.m4 libelf_msize.m4
 
 .include <bsd.lib.mk>
 

==== //depot/projects/dtrace/src/lib/libelf/_libelf.h#2 (text+ko) ====

@@ -67,7 +67,8 @@
  * flags field.
  */
 
-#define	LIBELF_F_ALLOCED	0x10000	/* whether rawdata is malloc'ed */
+#define	LIBELF_F_ALLOCED	0x10000	/* whether e_rawfile is malloc'ed */
+#define	LIBELF_F_MMAP		0x20000	/* whether e_rawfile was mmap'ed by us */
 
 struct _Elf {
 	int		e_activations;	/* activation count */
@@ -82,9 +83,13 @@
 	size_t		e_rawsize;	/* size of uninterpreted bytes */
 	unsigned int	e_version;	/* file version */
 
+	Elf32_Ehdr	e_eh32;		/* 32-bit ELF header */
+	Elf64_Ehdr	e_eh64;		/* 64-bit ELF header */
+
 	union {
-		struct {		/* archive files */
+		struct {		/* ar(1) archives */
 			off_t	e_next;
+			int	e_nchildren;
 		} e_ar;
 		struct {		/* regular ELF files */
 		} e_elf;
@@ -105,11 +110,15 @@
  */
 
 Elf	*_libelf_allocate_elf(void);
+int	_libelf_dump32(Elf *_elf, const char *_name, const char *_outfile,
+	    unsigned int _flags);
+int	_libelf_dump64(Elf *_elf, const char *_name, const char *_outfile,
+	    unsigned int _flags);
 void	*libelf_ehdr(Elf *_e, int _elfclass, int _allocate);
 void	(*_libelf_get_translator(Elf_Type _t, int _direction, int _elfclass))
 	    (char *_dst, char *_src, int _cnt, int _byteswap);
 int	_libelf_malign(Elf_Type _t, int _elfclass);
-size_t	_libelf_msize(Elf_Type _t, unsigned int _version);
+size_t	_libelf_msize(Elf_Type _t, int _elfclass, unsigned int _version);
 void	_libelf_release_elf(Elf *_e);
 
 #endif	/* __LIBELF_H_ */

==== //depot/projects/dtrace/src/lib/libelf/elf.3#2 (text+ko) ====

@@ -45,3 +45,5 @@
 . \" Memory management discipline: Note that no ELF data structure should
 . \" be explicitly free()'ed by the application.  All free'ing happens when
 . \" an elf_end() is done, after which pointers go stale.
+. \" Describe all prefixes used by the library and namespace use by <libelf.h>
+. \" and <gelf.h> (in gelf.3).

==== //depot/projects/dtrace/src/lib/libelf/elf_allocate.c#2 (text+ko) ====

@@ -67,6 +67,5 @@
 void
 _libelf_release_elf(Elf *e)
 {
-	assert(e->e_activations == 1);
 	free(e);
 }

==== //depot/projects/dtrace/src/lib/libelf/elf_begin.3#2 (text+ko) ====

@@ -244,6 +244,19 @@
 differs from the value specified when ELF descriptor
 .Ar elf
 was created.
+.It Bq Er ELF_E_ARGUMENT
+Argument
+.Ar elf
+was not a descriptor for an
+.Xr ar 1
+archive.
+.It Bq Er ELF_E_MODE
+An
+.Xr ar 1
+archive was opened with with
+.Ar cmd
+set to
+.Dv ELF_C_RDWR .
 .It Bq Er ELF_E_RESOURCE
 An out of memory condition was encountered.
 .It Bq Er ELF_E_SEQUENCE
@@ -265,4 +278,4 @@
 .Xr elf_next 3 ,
 .Xr elf_rand 3 ,
 .Xr elf_update 3 ,
-.Xr gelf 3+.Xr gelf 3

==== //depot/projects/dtrace/src/lib/libelf/elf_begin.c#2 (text+ko) ====

@@ -27,106 +27,166 @@
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
+#include <sys/types.h>
 #include <sys/errno.h>
 #include <sys/mman.h>
 #include <sys/stat.h>
 
+#include <ar.h>
 #include <assert.h>
+#include <ctype.h>
 #include <libelf.h>
 
 #include "_libelf.h"
 
-Elf *
-elf_begin(int fd, Elf_Cmd c, Elf *ar)
+static Elf *
+libelf_open_object(int fd, Elf_Cmd c)
 {
 	Elf *e;
 	void *m;
 	struct stat sb;
 
+	/*
+	 * 'Raw' files are always mapped with 'PROT_READ'.  At
+	 * elf_update(3) time for files opened with ELF_C_RDWR the
+	 * mapping is unmapped, file data is written to using write(2)
+	 * and then the raw data is immediately mapped back in.
+	 */
+	if (fstat(fd, &sb) < 0) {
+		LIBELF_SET_ERROR(STAT, errno);
+		return (NULL);
+	}
+
+	m = NULL;
+	if ((m = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd,
+	    (off_t) 0)) == MAP_FAILED) {
+		LIBELF_SET_ERROR(MMAP, errno);
+		return (NULL);
+	}
+
+	if ((e = elf_memory(m, sb.st_size)) == NULL) {
+		(void) munmap(m, sb.st_size);
+		return (NULL);
+	}
+
+	e->e_flags |= LIBELF_F_MMAP;
+	e->e_fd = fd;
+	e->e_cmd = c;
+
+	if (c == ELF_C_RDWR && e->e_kind == ELF_K_AR) {
+		(void) elf_end(e);
+		LIBELF_SET_ERROR(MODE, 0);
+		return (NULL);
+	}
+
+	return (e);
+}
+
+static Elf *
+libelf_open_member(int fd, Elf_Cmd c, Elf *elf)
+{
+	Elf *e;
+	struct ar_hdr *arh;
+	int i, ch, sz;
+
+	assert(elf->e_kind == ELF_K_AR);
+
+	/*
+	 * TODO: The following code is incorrect for archives using
+	 * the new extended header scheme.
+	 */
+	arh = (struct ar_hdr *) (elf->e_rawfile + elf->e_u.e_ar.e_next);
+	for (i = sz = 0; i < 10; i++) {
+		ch = arh->ar_size[i];
+		if (isdigit(ch)) {
+			sz *= 10;
+			sz += ch;
+		} else {
+			LIBELF_SET_ERROR(ARCHIVE, 0);
+			return (NULL);
+		}
+	}
+
+	assert(sz > 0);
+
+	arh++;	/* skip over archive member header */
+
+	if ((e = elf_memory((char *) arh, sz)) == NULL) {
+		LIBELF_SET_ERROR(RESOURCE, 0);
+		return (NULL);
+	}
+
+	e->e_fd = fd;
+	e->e_cmd = c;
+
+	elf->e_u.e_ar.e_nchildren++;
+	e->e_parent = elf;
+
+	return (e);
+}
+
+Elf *
+elf_begin(int fd, Elf_Cmd c, Elf *elf)
+{
+	Elf *e;
+
+	e = NULL;
+
 	if (LIBELF_PRIVATE(version) == EV_NONE) {
 		LIBELF_SET_ERROR(SEQUENCE, 0);
 		return (NULL);
 	}
 
-	if (c == ELF_C_NULL)
+	switch (c) {
+	case ELF_C_NULL:
 		return (NULL);
 
-	if (c == ELF_C_WRITE) {
+	case ELF_C_WRITE:
+
+		/*
+		 * Check writeability of `fd' immediately and fail if
+		 * not writeable.
+		 */
 		if (ftruncate(fd, (off_t) 0) < 0) {
 			LIBELF_SET_ERROR(TRUNCATE, errno);
 			return (NULL);
 		}
 
 		if ((e = _libelf_allocate_elf()) != NULL) {
-			LIBELF_SET_ERROR(NONE, 0);
 			e->e_byteorder = LIBELF_PRIVATE(byteorder);
 			e->e_class = LIBELF_PRIVATE(class);
 			e->e_fd = fd;
 			e->e_kind = ELF_K_ELF;
+			e->e_cmd = c;
 		}
 		return (e);
-	}
 
-	if (c != ELF_C_READ && c != ELF_C_RDWR) {
-		LIBELF_SET_ERROR(ARGUMENT, 0);
-		return (NULL);
-	}
-
-	if (c == ELF_C_RDWR && ar != NULL) {
-		LIBELF_SET_ERROR(ARGUMENT, 0);
-		return (NULL);
-	}
-
-	if (ar != NULL) {
-
-		if (c != ar->e_cmd || fd != e->e_fd) {
+	case ELF_C_RDWR:
+		if (elf != NULL) {
 			LIBELF_SET_ERROR(ARGUMENT, 0);
 			return (NULL);
 		}
-
-		if (ar->e_kind != ELF_K_AR) {
-			ar->e_activations++;
-			return (ar);
+		/*FALLTHROUGH*/
+	case ELF_C_READ:
+		if (elf && (elf->e_fd != fd || c != elf->e_cmd)) {
+			LIBELF_SET_ERROR(ARGUMENT, 0);
+			return (NULL);
 		}
 
-		/* XXX todo 'ar' handling */
-		return (NULL);
-	}
+		break;
 
-	/*
-	 * Determine the type of the file (ar), or (ELF).
-	 * For AR archives, read the symbol table and
-	 * move the 'next' pointer to the first normal
-	 * file in the archive.
-	 * For ELF files, get mmap and hand over the
-	 * pointer to elf_memory for further processing.
-	 */
-
-	if (fstat(fd, &sb) < 0) {
-		LIBELF_SET_ERROR(STAT, errno);
+	default:
+		LIBELF_SET_ERROR(ARGUMENT, 0);
 		return (NULL);
-	}
 
-	/*
-	 * 'Raw' files are always mapped with 'PROT_READ'.  At elf_update(3)
-	 * time these are unmapped, file data is written to using write(2)
-	 * and then remapped.
-	 */
-	m = NULL;
-	if ((m = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd,
-	    (off_t) 0)) == MAP_FAILED) {
-		LIBELF_SET_ERROR(MMAP, errno);
-		return (NULL);
 	}
 
-	e = elf_memory(m, sb.st_size);
-
-	if ((e = elf_memory(m, sb.st_size)) == NULL) {
-		(void) munmap(m, sb.st_size);
-		return (NULL);
-	}
-
-	e->e_fd = fd;
+	if (elf == NULL)
+		e = libelf_open_object(fd, c);
+	else if (elf->e_kind == ELF_K_AR)
+		e = libelf_open_member(fd, c, elf);
+	else
+		(e = elf)->e_activations++;
 
 	return (e);
 }

==== //depot/projects/dtrace/src/lib/libelf/elf_end.3#2 (text+ko) ====

@@ -45,23 +45,32 @@
 .Xr elf_begin 3
 or
 .Xr elf_memory 3 .
-For convenience a NULL value is permitted for argument
+For programming convenience, a NULL value is permitted for argument
 .Ar elf .
 .Pp
 A call to
 .Fn elf_end
 decrements the activation count for descriptor
 .Ar elf
-by 1.
+by one.
 The resources associated with the descriptor are only released
 with its activation count goes to zero.
+.Pp
+Once function
+.Fn elf_end
+returns zero, the ELF descriptor
+.Ar elf
+will no longer be valid and should not be used further.
 .Sh RETURN VALUES
 Function
 .Fn elf_end
-returns the current value of the ELF descriptor's activation count.
+returns the current value of the ELF descriptor
+.Ar elf Ap s
+activation count, or zero if argument
+.Ar elf
+was NULL.
 .Sh SEE ALSO
 .Xr elf 3 ,
 .Xr elf_begin 3 ,
 .Xr elf_memory 3 ,
 .Xr gelf 3
-

==== //depot/projects/dtrace/src/lib/libelf/elf_end.c#2 (text+ko) ====

@@ -27,23 +27,56 @@
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
+#include <sys/mman.h>
+
 #include <assert.h>
 #include <libelf.h>
+#include <stdlib.h>
 
 #include "_libelf.h"
 
 int
 elf_end(Elf *e)
 {
-	if (e == NULL || e->e_activations <= 0)
+	Elf *sv;
+
+	if (e == NULL || e->e_activations == 0)
 		return (0);
+
 	if (--e->e_activations > 0)
 		return (e->e_activations);
 
 	assert(e->e_activations == 0);
 
-	/* TODO release ELF descriptor's resources */
+	while (e && e->e_activations == 0) {
+		switch (e->e_kind) {
+		case ELF_K_AR:
+			/*
+			 * If we still have open child descriptors, we
+			 * need to defer reclaiming resources till all
+			 * the child descriptors for the archive are
+			 * closed.
+			 */
+			if (e->e_u.e_ar.e_nchildren > 0)
+				return (0);
+			break;
+		case ELF_K_ELF:
+			break;
+		case ELF_K_NUM:
+			assert(0);
+		default:
+			break;
+		}
+
+		if (e->e_flags & LIBELF_F_MMAP)
+			(void) munmap(e->e_rawfile, e->e_rawsize);
+
+		sv = e;
+		if ((e = e->e_parent) != NULL)
+			e->e_u.e_ar.e_nchildren--;
+		_libelf_release_elf(sv);
+	}
 
-	return 0;
+	return (0);
 }
 

==== //depot/projects/dtrace/src/lib/libelf/elf_memory.c#2 (text+ko) ====

@@ -28,6 +28,7 @@
 __FBSDID("$FreeBSD$");
 
 #include <ar.h>
+#include <gelf.h>
 #include <libelf.h>
 #include <string.h>
 
@@ -37,6 +38,7 @@
 elf_memory(char *image, size_t sz)
 {
 	Elf *e;
+	Elf_Data dst, src;
 
 	if (LIBELF_PRIVATE(version) == EV_NONE) {
 		LIBELF_SET_ERROR(SEQUENCE, 0);
@@ -71,6 +73,8 @@
 		}
 	} else if (sz >= SARMAG && strncmp(image, ARMAG, SARMAG) == 0) {
 		e->e_kind = ELF_K_AR;
+		e->e_u.e_ar.e_nchildren = 0;
+		e->e_u.e_ar.e_next = (off_t) -1;	/* XXX set to first element */
 	} else
 		e->e_kind = ELF_K_NONE;
 
@@ -78,6 +82,35 @@
 	e->e_rawfile = image;
 	e->e_rawsize = sz;
 
+	if (e->e_kind == ELF_K_ELF) {
+		src.d_buf	= image;
+		src.d_off	= 0;
+		src.d_align	= 0;
+		src.d_type	= ELF_T_EHDR;
+		src.d_version	= EV_CURRENT;
+
+		dst.d_off	= 0;
+		dst.d_align	= 0;
+		dst.d_type	= ELF_T_EHDR;
+		dst.d_version	= EV_CURRENT;
+
+		if (e->e_class == ELFCLASS32) {
+			dst.d_buf	= &e->e_eh32;
+			dst.d_size	= sizeof(e->e_eh32);
+			src.d_size	= sizeof(e->e_eh32);
+		} else if (e->e_class == ELFCLASS64) {
+			dst.d_buf	= &e->e_eh64;
+			dst.d_size	= sizeof(e->e_eh64);
+			src.d_size	= sizeof(e->e_eh64);
+		} else {
+			LIBELF_SET_ERROR(CLASS, e->e_class);
+			return (NULL);
+		}
+
+		if (gelf_xlatetom(e, &dst, &src, e->e_byteorder) == NULL)
+			return (NULL);
+	}
+
 	return (e);
 }
 

==== //depot/projects/dtrace/src/lib/libelf/elf_next.3#2 (text+ko) ====

@@ -81,4 +81,4 @@
 .Xr elf 3 ,
 .Xr elf_begin 3 ,
 .Xr elf_end 3 ,
-.Xr gelf 3
+.Xr elf_rand 3

==== //depot/projects/dtrace/src/lib/libelf/elf_next.c#2 (text+ko) ====

@@ -29,25 +29,34 @@
 
 #include <sys/types.h>
 
+#include <ar.h>
+#include <assert.h>
 #include <libelf.h>
 
 #include "_libelf.h"
 
 Elf_Cmd
-elf_next(Elf *elf)
+elf_next(Elf *e)
 {
-	Elf *parent, *next;
+#ifdef DOODAD
+	off_t next;
+	Elf *parent;
+#endif
 
-	if (elf == NULL || elf->e_parent == NULL)
+	if (e == NULL || (parent = e->e_parent) == NULL)
 		return (ELF_C_NULL);
 
-	if ((next = LIST_NEXT(&elf->e_u.e_member, e_sibling)) == NULL)
-		return (ELF_C_NULL);
+#ifdef DOODAD
+	assert (parent->e_kind == ELF_K_AR);
+	assert (parent->e_cmd == ELF_C_READ);
+	assert((uintptr_t) e->e_rawfile % 2 == 0);
+	assert(e->e_rawfile > parent->e_rawfile);
 
-	if ((parent = elf->e_u.e_member.e_parent) == NULL)
-		return (ELF_C_NULL);
+	next = e->e_rawfile - parent->e_rawfile + e->e_rawsize;
+	next = (next + 1) & ~1;	/* round up to next 2-byte offset */
 
-	parent->e_u.e_ar.e_next = next;
+	parent->e_u.e_ar.e_next = (next >= parent->e_rawsize) ? (off_t) -1 : next;
+#endif
 
 	return (ELF_C_READ);
 }

==== //depot/projects/dtrace/src/lib/libelf/elf_rand.c#2 (text+ko) ====

@@ -33,26 +33,26 @@
 #include "_libelf.h"
 
 off_t
-elf_rand(Elf *archive, off_t offset)
+elf_rand(Elf *ar, off_t offset)
 {
-	struct ar_hdr *ar;
+	struct ar_hdr *arh;
 
-	if (archive == NULL || archive->e_kind != ELF_K_AR ||
-	    offset & 1 ||
-	    offset < SARMAG || offset + sizeof(struct ar_hdr) > archive->e_rawsize) {
+	if (ar == NULL || ar->e_kind != ELF_K_AR ||
+	    offset & 1 || offset < SARMAG ||
+	    offset + sizeof(struct ar_hdr) >= ar->e_rawsize) {
 		LIBELF_SET_ERROR(ARGUMENT, 0);
 		return 0;
 	}
 
-	ar = (struct ar_hdr *) (archive->e_rawfile + offset);
+	arh = (struct ar_hdr *) (ar->e_rawfile + offset);
 
 	/* a too simple sanity check */
-	if (ar->ar_fmag[0] != '`' || ar->ar_fmag[1] != '\n') {
+	if (arh->ar_fmag[0] != '`' || arh->ar_fmag[1] != '\n') {
 		LIBELF_SET_ERROR(ARGUMENT, 0);
 		return 0;
 	}
 
-	archive->e_u.e_ar.e_next = offset;
+	ar->e_u.e_ar.e_next = offset;
 
 	return (offset);
 }

==== //depot/projects/dtrace/src/lib/libelf/gelf_xlate.c#2 (text+ko) ====

@@ -82,7 +82,7 @@
 		 1, src->d_version)) == 0)
 		return (NULL);
 
-	msz = _libelf_msize(src->d_type, src->d_version);
+	msz = _libelf_msize(src->d_type, elfclass, src->d_version);
 
 	assert(msz > 0);
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200608142003.k7EK39YI024859>