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>