PERFORCE change 109209 for review

John Birrell jb at FreeBSD.org
Sat Nov 4 03:27:02 UTC 2006


http://perforce.freebsd.org/chv.cgi?CH=109209

Change 109209 by jb at jb_freebsd8 on 2006/11/04 03:26:42

	IFlibbsdelf

Affected files ...

.. //depot/projects/dtrace/src/lib/libelf/Makefile#17 integrate
.. //depot/projects/dtrace/src/lib/libelf/_libelf.h#11 integrate
.. //depot/projects/dtrace/src/lib/libelf/elf_getscn.3#3 integrate
.. //depot/projects/dtrace/src/lib/libelf/elf_scn.c#6 integrate
.. //depot/projects/dtrace/src/lib/libelf/elf_shnum.c#2 integrate
.. //depot/projects/dtrace/src/lib/libelf/elf_update.c#6 integrate
.. //depot/projects/dtrace/src/lib/libelf/gelf_getshdr.c#5 integrate
.. //depot/projects/dtrace/src/lib/libelf/libelf_shdr.c#1 branch

Differences ...

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

@@ -43,6 +43,7 @@
 	libelf_data.c						\
 	libelf_ehdr.c						\
 	libelf_phdr.c						\
+	libelf_shdr.c						\
 	libelf_xlate.c
 INCS=	libelf.h gelf.h
 

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

@@ -148,7 +148,8 @@
 void	(*_libelf_get_translator(Elf_Type _t, int _direction, int _elfclass))
 	    (char *_dst, char *_src, size_t _cnt, int _byteswap);
 void	*_libelf_getphdr(Elf *_e, int _elfclass);
-int	_libelf_getshnum(void *_eh, int _elfclass, size_t *_shnum);
+void	*_libelf_getshdr(Elf_Scn *_scn, int _elfclass);
+int	_libelf_getshnum(Elf *_e, void *_eh, int _elfclass, size_t *_shnum);
 int	_libelf_getshstrndx(void *_eh, int _elfclass, size_t *_shstrndx);
 void	_libelf_init_elf(Elf *_e, Elf_Kind _kind);
 int	_libelf_malign(Elf_Type _t, int _elfclass);
@@ -157,7 +158,7 @@
 Elf_Data *_libelf_release_data(Elf_Data *_d);
 Elf	*_libelf_release_elf(Elf *_e);
 Elf_Scn	*_libelf_release_scn(Elf_Scn *_s);
-int	_libelf_setshnum(void *_eh, int _elfclass, size_t _shnum);
+int	_libelf_setshnum(Elf *_e, void *_eh, int _elfclass, size_t _shnum);
 int	_libelf_setshstrndx(void *_eh, int _elfclass, size_t _shstrndx);
 Elf_Data *_libelf_xlate(Elf_Data *_d, const Elf_Data *_s,
     unsigned int _encoding, int _elfclass, int _direction);

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

@@ -133,6 +133,14 @@
 Descriptor
 .Ar elf
 was of an unknown ELF class.
+.It Bq Er ELF_E_SECTION
+Argument
+.Ar elf
+specified extended section numbering in the ELF header with the section header at
+index
+.Dv SHN_UNDEF
+not being of type
+.Dv SHT_NULL .
 .El
 .Sh SEE ALSO
 .Xr elf 3 ,

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

@@ -41,10 +41,11 @@
 static int
 _libelf_load_scn(Elf *e, void *ehdr)
 {
-	int ec;
+	int ec, swapbytes;
 	size_t fsz, i, shnum;
 	uint64_t shoff;
-	char *src, *dst;
+	uint32_t shtype;
+	char *src;
 	Elf32_Ehdr *eh32;
 	Elf64_Ehdr *eh64;
 	Elf_Scn *scn;
@@ -79,20 +80,43 @@
 
 	xlator = _libelf_get_translator(ELF_T_SHDR, ELF_TOMEMORY, ec);
 
+	swapbytes = e->e_byteorder != LIBELF_PRIVATE(byteorder);
 	src = e->e_rawfile + shoff;
+	i = 0;
+
+	if (shnum == (size_t) 0 && shoff != 0LL) {
+		/* Extended section numbering */
+		if ((scn = _libelf_allocate_scn(e, (size_t) 0)) == NULL)
+			return (0);
+
+		(*xlator)((char *) &scn->s_shdr, src, (size_t) 1, swapbytes);
+
+		if (ec == ELFCLASS32) {
+			shtype = scn->s_shdr.s_shdr32.sh_type;
+			shnum = scn->s_shdr.s_shdr32.sh_size;
+		} else {
+			shtype = scn->s_shdr.s_shdr64.sh_type;
+			shnum = scn->s_shdr.s_shdr64.sh_size;
+		}
+
+		if (shtype != SHT_NULL) {
+			LIBELF_SET_ERROR(SECTION, 0);
+			return (0);
+		}
+
+		scn->s_size = 0LL;
+		scn->s_offset = scn->s_rawoff = 0LL;
 
-	for (i = 0; i < shnum; i++, src += fsz) {
+		i++;
+		src += fsz;
+	}
+
+	for (; i < shnum; i++, src += fsz) {
 		if ((scn = _libelf_allocate_scn(e, i)) == NULL)
 			return (0);
 
-		if (ec == ELFCLASS32)
-			dst = (char *) &scn->s_shdr.s_shdr32;
-		else
-			dst = (char *) &scn->s_shdr.s_shdr64;
+		(*xlator)((char *) &scn->s_shdr, src, (size_t) 1, swapbytes);
 
-		(*xlator)(dst, src, (size_t) 1,
-		    e->e_byteorder != LIBELF_PRIVATE(byteorder));
-
 		if (ec == ELFCLASS32) {
 			scn->s_offset = scn->s_rawoff =
 			    scn->s_shdr.s_shdr32.sh_offset;
@@ -112,7 +136,6 @@
 {
 	int ec;
 	void *ehdr;
-	uint16_t *pshnum;
 	Elf_Scn *s;
 
 	if (e == NULL || e->e_kind != ELF_K_ELF ||
@@ -124,16 +147,6 @@
 	if ((ehdr = _libelf_ehdr(e, ec, 0)) == NULL)
 		return (NULL);
 
-	if (ec == ELFCLASS32)
-		pshnum = &((Elf32_Ehdr *) ehdr)->e_shnum;
-	else
-		pshnum = &((Elf64_Ehdr *) ehdr)->e_shnum;
-
-	if (index >= *pshnum) {
-		LIBELF_SET_ERROR(ARGUMENT, 0);
-		return (NULL);
-	}
-
 	if (e->e_cmd != ELF_C_WRITE && STAILQ_EMPTY(&e->e_u.e_elf.e_scn) &&
 	    _libelf_load_scn(e, ehdr) == 0)
 		return (NULL);
@@ -142,6 +155,7 @@
 		if (s->s_ndx == index)
 			return (s);
 
+	LIBELF_SET_ERROR(ARGUMENT, 0);
 	return (NULL);
 }
 
@@ -190,7 +204,7 @@
 	    _libelf_load_scn(e, ehdr) == 0)
 		return (NULL);
 
-	if (_libelf_getshnum(ehdr, ec, &shnum) == 0)
+	if (_libelf_getshnum(e, ehdr, ec, &shnum) == 0)
 		return (NULL);
 
 	if (STAILQ_EMPTY(&e->e_u.e_elf.e_scn)) {
@@ -208,7 +222,7 @@
 
 	shnum++;
 
-	if (_libelf_setshnum(ehdr, ec, shnum) == 0)
+	if (_libelf_setshnum(e, ehdr, ec, shnum) == 0)
 		return (NULL);
 
 	(void) elf_flagscn(scn, ELF_C_SET, ELF_F_DIRTY);

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

@@ -36,54 +36,75 @@
 #include "_libelf.h"
 
 int
-_libelf_getshnum(void *eh, int ec, size_t *shnum)
+_libelf_getshnum(Elf *e, void *eh, int ec, size_t *shnum)
 {
-	Elf32_Ehdr *eh32;
-	Elf64_Ehdr *eh64;
 	Elf64_Off off;
+	Elf_Scn *scn;
+	void *sh;
 	size_t n;
 
-	eh32 = eh;
-	eh64 = eh;
 	if (ec == ELFCLASS32) {
-		n = eh32->e_shnum;
-		off = (Elf64_Off) eh32->e_shoff;
+		n = ((Elf32_Ehdr *) eh)->e_shnum;
+		off = (Elf64_Off) ((Elf32_Ehdr *) eh)->e_shoff;
 	} else {
-		n = eh64->e_shnum;
-		off = eh64->e_shoff;
+		n = ((Elf64_Ehdr *) eh)->e_shnum;
+		off = ((Elf64_Ehdr *) eh)->e_shoff;
+	}
+
+	if (n != 0) {
+		*shnum = n;
+		return (1);
+	}
+
+	if (off == 0L) {
+		*shnum = (size_t) 0;
+		return (1);
 	}
 
-	if (n == 0)
-		if (off != 0) {
-			/* TODO */
-			LIBELF_SET_ERROR(UNIMPL, 0);
-			return (0);
-		} else
-			*shnum = 0;
+	/*
+	 * If 'e_shnum' is zero and 'e_shoff' is non-zero, the file is
+	 * using extended section numbering, and the true section
+	 * number is kept in the 'sh_size' field of the section header
+	 * at offset SHN_UNDEF.
+	 */
+	if ((scn = elf_getscn(e, SHN_UNDEF)) == NULL)
+		return (0);
+	if ((sh = _libelf_getshdr(scn, ec)) == NULL)
+		return (0);
+
+	if (ec == ELFCLASS32)
+		*shnum = ((Elf32_Shdr *) sh)->sh_size;
 	else
-		*shnum = n;
+		*shnum = ((Elf64_Shdr *) sh)->sh_size;
 
 	return (1);
 }
 
 int
-_libelf_setshnum(void *eh, int ec, size_t shnum)
+_libelf_setshnum(Elf *e, void *eh, int ec, size_t shnum)
 {
-	Elf32_Ehdr *eh32;
-	Elf64_Ehdr *eh64;
+	Elf_Scn *scn;
+	void *sh;
 
-	eh32 = eh;
-	eh64 = eh;
+	if (shnum < SHN_LORESERVE) {
+		if (ec == ELFCLASS32)
+			((Elf32_Ehdr *) eh)->e_shnum = shnum;
+		else
+			((Elf64_Ehdr *) eh)->e_shnum = shnum;
+		return (1);
+	}
 
-	if (shnum >= SHN_XINDEX) {
-		LIBELF_SET_ERROR(UNIMPL, 0);
+	if ((scn = elf_getscn(e, SHN_UNDEF)) == NULL)
+		return (0);
+	if ((sh = _libelf_getshdr(scn, ec)) == NULL)
 		return (0);
-	}
-	if (ec == ELFCLASS32) {
-		eh32->e_shnum = shnum;
-	} else {
-		eh64->e_shnum = shnum;
-	}
+
+	if (ec == ELFCLASS32)
+		((Elf32_Shdr *) sh)->sh_size = shnum;
+	else
+		((Elf64_Shdr *) sh)->sh_size = shnum;
+
+	(void) elf_flagshdr(scn, ELF_C_SET, ELF_F_DIRTY);
 
 	return (1);
 }
@@ -101,5 +122,5 @@
 		return (0);
 	}
 
-	return (_libelf_getshnum(eh, ec, shnum));
+	return (_libelf_getshnum(e, eh, ec, shnum));
 }

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

@@ -76,6 +76,7 @@
 	int ec;
 	Elf_Data *d, *td;
 	unsigned int elftype;
+	uint32_t sh_type;
 	uint64_t sh_align, sh_entsize, sh_offset, sh_size;
 	uint64_t scn_size, scn_alignment;
 
@@ -101,19 +102,23 @@
 	ec = e->e_class;
 
 	if (ec == ELFCLASS32) {
-		elftype    = _libelf_xlate_shtype(s->s_shdr.s_shdr32.sh_type);
+		sh_type    = s->s_shdr.s_shdr32.sh_type;
 		sh_align   = (uint64_t) s->s_shdr.s_shdr32.sh_addralign;
 		sh_entsize = (uint64_t) s->s_shdr.s_shdr32.sh_entsize;
 		sh_offset  = (uint64_t) s->s_shdr.s_shdr32.sh_offset;
 		sh_size    = (uint64_t) s->s_shdr.s_shdr32.sh_size;
 	} else {
-		elftype    = _libelf_xlate_shtype(s->s_shdr.s_shdr64.sh_type);
+		sh_type    = s->s_shdr.s_shdr64.sh_type;
 		sh_align   = s->s_shdr.s_shdr64.sh_addralign;
 		sh_entsize = s->s_shdr.s_shdr64.sh_entsize;
 		sh_offset  = s->s_shdr.s_shdr64.sh_offset;
 		sh_size    = s->s_shdr.s_shdr64.sh_size;
 	}
 
+	if (sh_type == SHT_NULL || sh_type == SHT_NOBITS)
+		return (1);
+
+	elftype = _libelf_xlate_shtype(sh_type);
 	if (elftype > ELF_T_LAST) {
 		LIBELF_SET_ERROR(SECTION, 0);
 		return (0);
@@ -356,7 +361,7 @@
 		return ((off_t) -1);
 	}
 
-	if (_libelf_getshnum(ehdr, ec, &shnum) == 0)
+	if (_libelf_getshnum(e, ehdr, ec, &shnum) == 0)
 		return ((off_t) -1);
 
 	e->e_byteorder = eh_byteorder;

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

@@ -36,69 +36,36 @@
 Elf32_Shdr *
 elf32_getshdr(Elf_Scn *s)
 {
-	int ec;
-	Elf *e;
-
-	if (s == NULL || (e = s->s_elf) == NULL ||
-	    e->e_kind != ELF_K_ELF) {
-		LIBELF_SET_ERROR(ARGUMENT, 0);
-		return (NULL);
-	}
-
-	ec = e->e_class;
-
-	assert(ec == ELFCLASS32 || ec == ELFCLASS64);
-
-	if (ec != ELFCLASS32) {
-		LIBELF_SET_ERROR(CLASS, 0);
-		return (NULL);
-	}
-
-	return (&s->s_shdr.s_shdr32);
+	return (_libelf_getshdr(s, ELFCLASS32));
 }
 
 Elf64_Shdr *
 elf64_getshdr(Elf_Scn *s)
 {
-	int ec;
-	Elf *e;
-
-	if (s == NULL || (e = s->s_elf) == NULL ||
-	    e->e_kind != ELF_K_ELF) {
-		LIBELF_SET_ERROR(ARGUMENT, 0);
-		return (NULL);
-	}
-
-	ec = e->e_class;
-
-	assert(ec == ELFCLASS32 || ec == ELFCLASS64);
-
-	if (ec != ELFCLASS64) {
-		LIBELF_SET_ERROR(CLASS, 0);
-		return (NULL);
-	}
-
-	return (&s->s_shdr.s_shdr64);
+	return (_libelf_getshdr(s, ELFCLASS64));
 }
 
 GElf_Shdr *
 gelf_getshdr(Elf_Scn *s, GElf_Shdr *d)
 {
 	int ec;
-	Elf *e;
+	void *sh;
 	Elf32_Shdr *sh32;
+	Elf64_Shdr *sh64;
 
-	if (s == NULL || d == NULL ||
-	    (e = s->s_elf) == NULL || e->e_kind != ELF_K_ELF) {
+	if (d == NULL) {
 		LIBELF_SET_ERROR(ARGUMENT, 0);
 		return (NULL);
 	}
 
-	ec = e->e_class;
+	if ((sh = _libelf_getshdr(s, ELFCLASSNONE)) == NULL)
+		return (NULL);
+
+	ec = s->s_elf->e_class;
 	assert(ec == ELFCLASS32 || ec == ELFCLASS64);
 
 	if (ec == ELFCLASS32) {
-		sh32 = &s->s_shdr.s_shdr32;
+		sh32 = (Elf32_Shdr *) sh;
 
 		d->sh_name      = sh32->sh_name;
 		d->sh_type      = sh32->sh_type;
@@ -110,8 +77,10 @@
 		d->sh_info      = sh32->sh_info;
 		d->sh_addralign = (Elf64_Xword) sh32->sh_addralign;
 		d->sh_entsize   = (Elf64_Xword) sh32->sh_entsize;
-	} else
-		*d = s->s_shdr.s_shdr64;
+	} else {
+		sh64 = (Elf64_Shdr *) sh;
+		*d = *sh64;
+	}
 
 	return (d);
 }


More information about the p4-projects mailing list