RPM z LUA

Artur Frysiak wiget w pld-linux.org
Nie, 21 Mar 2004, 23:22:15 CET


On Fri, Mar 19, 2004 at 01:04:54AM +0100, Jakub Bogusz wrote:
> On Thu, Mar 18, 2004 at 11:14:44PM +0100, Artur Frysiak wrote:
> > Witam.
> > Zabieram się za przygotowanie nowego snapa rpma ponieważ posiada on
> > wsparcie do wbudowanego języka skryptowego lua.
> > Korzyści płynące z lua to możliwość pisania skryptów %pre/%post które
> > nie będą wymagały sh. Może się to okazać bardzo przydatne w pakietach
> > typu FHS, setup, glibc itp.
> > 
> > Cały eksperyment zostanie przeprowadzony na branchu DEVEL.
> 
> Popatrzysz przy okazji, czy nie ma jakichś poprawek w readelf?
> W poprzednim snapie były błędy, ale po uaktualnieniu (z nowszego file)
> coś się sypie na amd64 i nie mam jak zdiagnozować bez dostępu do
> maszyny.

revision 1.4
date: 2004/03/16 17:13:25;  author: jbj;  state: Exp;  lines: +37 -14
- fix: grrr, skip notes on non-i386 entirely.
----------------------------
revision 1.3
date: 2004/03/13 13:34:45;  author: jbj;  state: Exp;  lines: +30 -31
- fix: handle elf64 note sections correctly.

i podobne zmiany w branczach rpm-4_3 oraz rpm-4_2.
Łatka w załączniku.

Pozdrawiam
-- 
Artur Frysiak
http://www.pld-linux.org/
-------------- następna część ---------
Index: file/src/readelf.c
===================================================================
RCS file: /cvs/devel/rpm/file/src/readelf.c,v
retrieving revision 1.2
retrieving revision 1.4
diff -u -r1.2 -r1.4
--- file/src/readelf.c	15 Apr 2003 15:19:30 -0000	1.2
+++ file/src/readelf.c	16 Mar 2004 17:13:25 -0000	1.4
@@ -88,6 +88,7 @@
 #define shs_type	(fm->cls == ELFCLASS32		\
 			 ? getu32(fm, sh32.sh_type)	\
 			 : getu32(fm, sh64.sh_type))
+
 #define ph_addr		(fm->cls == ELFCLASS32		\
 			 ? (void *) &ph32		\
 			 : (void *) &ph64)
@@ -103,9 +104,10 @@
 #define ph_align	(fm->cls == ELFCLASS32		\
 			 ? (ph32.p_align ? getu32(fm, ph32.p_align) : 4) \
 			 : (ph64.p_align ? getu64(fm, ph64.p_align) : 4))
-#define nh_size		(fm->cls == ELFCLASS32		\
-			 ? sizeof *nh32			\
-			 : sizeof *nh64)
+#define ph_filesz	(fm->cls == ELFCLASS32		\
+			 ? getu32(fm, ph32.p_filesz)	\
+			 : getu64(fm, ph64.p_filesz))
+
 #define nh_type		(fm->cls == ELFCLASS32		\
 			 ? getu32(fm, nh32->n_type)	\
 			 : getu32(fm, nh64->n_type))
@@ -170,8 +172,11 @@
 	char *linking_style = "statically";
 	char *shared_libraries = "";
 	char nbuf[BUFSIZ];
-	int bufsize;
-	size_t offset, nameoffset;
+	int nb;
+	size_t nbufsize, offset, end, noff, doff;
+	size_t align = (fm->cls == ELFCLASS32 ? 4 : 8);
+#define ALIGNED_LEN(len) (((len) + align - 1) & ~(align - 1))
+	int printed;
 
 	if (size != ph_size) {
 		error(EXIT_FAILURE, 0, "corrupted program header size.\n");
@@ -184,11 +189,19 @@
 	}
 
   	for ( ; num; num--) {
-  		if (read(fm->fd, ph_addr, size) == -1) {
+		/* Read the program header data. */
+		nb = read(fm->fd, ph_addr, size);
+  		if (nb == -1) {
   			error(EXIT_FAILURE, 0, "read failed (%s).\n", strerror(errno));
 			/*@notreached@*/
 		}
 
+		/* XXX Elf64 notes cannot be read, so don't attempt for now. */
+#if !defined(__i386__)
+		if (ph_type == PT_NOTE) 
+			break;          
+#endif
+
 		switch (ph_type) {
 		case PT_DYNAMIC:
 			linking_style = "dynamically";
@@ -205,50 +218,56 @@
 				error(EXIT_FAILURE, 0, "lseek failed (%s).\n", strerror(errno));
 				/*@notreached@*/
 			}
-			bufsize = read(fm->fd, nbuf, sizeof(nbuf));
-			if (bufsize == -1) {
+
+			/* XXX Read only the notes section. */
+			nbufsize = (ph_filesz < sizeof(nbuf)
+					? ph_filesz : sizeof(nbuf));
+			nb = read(fm->fd, nbuf, nbufsize);
+			if (nb == -1) {
 				error(EXIT_FAILURE, 0, ": " "read failed (%s).\n",
 				    strerror(errno));
 				/*@notreached@*/
 			}
 			offset = 0;
+			printed = 0;
 			for (;;) {
-				if (offset >= bufsize)
+				end = offset + 12;
+				if (end >= nb)
 					/*@innerbreak@*/ break;
+
 				if (fm->cls == ELFCLASS32)
 					nh32 = (Elf32_Nhdr *)&nbuf[offset];
 				else
 					nh64 = (Elf64_Nhdr *)&nbuf[offset];
-				offset += nh_size;
-	
-				if (offset + nh_namesz >= bufsize) {
-					/*
-					 * We're past the end of the buffer.
-					 */
-					/*@innerbreak@*/ break;
-				}
 
-				nameoffset = offset;
-				offset += nh_namesz;
-				offset = ((offset+ph_align-1)/ph_align)*ph_align;
+				offset = end;	/* skip note header. */
 
-				if ((nh_namesz == 0) && (nh_descsz == 0)) {
-					/*
-					 * We're out of note headers.
-					 */
+				/* XXX Avoid notes that are not 1-16 bytes */
+				if (nh_namesz <= 0 || nh_descsz <= 0)
+					break;
+				if (nh_namesz  > 16 || nh_descsz > 16)
+					break;
+
+				end = offset	+ ALIGNED_LEN (nh_namesz)
+						+ ALIGNED_LEN (nh_descsz);
+				if (end > nb)
 					/*@innerbreak@*/ break;
-				}
 
-				if (offset + nh_descsz >= bufsize)
-					/*@innerbreak@*/ break;
+				noff = offset;
+				doff = ALIGNED_LEN(offset + nh_namesz);
+				offset = end;
+
+				if (printed)
+					continue;
 
 				if (nh_namesz == 4 &&
-				    strcmp(&nbuf[nameoffset], "GNU") == 0 &&
+				    strcmp(&nbuf[noff], "GNU") == 0 &&
 				    nh_type == NT_GNU_VERSION &&
 				    nh_descsz == 16) {
 					uint32_t *desc =
-					    (uint32_t *)&nbuf[offset];
+					    (uint32_t *)&nbuf[doff];
 
+					if (!printed)
 					file_printf(fm, ", for GNU/");
 					switch (getu32(fm, desc[0])) {
 					case GNU_OS_LINUX:
@@ -268,10 +287,11 @@
 					    getu32(fm, desc[1]),
 					    getu32(fm, desc[2]),
 					    getu32(fm, desc[3]));
+					printed = 1;
 				}
 
 				if (nh_namesz == 7 &&
-				    strcmp(&nbuf[nameoffset], "NetBSD") == 0 &&
+				    strcmp(&nbuf[noff], "NetBSD") == 0 &&
 				    nh_type == NT_NETBSD_VERSION &&
 				    nh_descsz == 4) {
 					file_printf(fm, ", for NetBSD");
@@ -279,14 +299,15 @@
 					 * Version number is stuck at 199905,
 					 * and hence is basically content-free.
 					 */
+					printed = 1;
 				}
 
 				if (nh_namesz == 8 &&
-				    strcmp(&nbuf[nameoffset], "FreeBSD") == 0 &&
+				    strcmp(&nbuf[noff], "FreeBSD") == 0 &&
 				    nh_type == NT_FREEBSD_VERSION &&
 				    nh_descsz == 4) {
 					uint32_t desc = getu32(fm,
-					    *(uint32_t *)&nbuf[offset]);
+					    *(uint32_t *)&nbuf[doff]);
 					file_printf(fm, ", for FreeBSD");
 					/*
 					 * Contents is __FreeBSD_version,
@@ -303,14 +324,16 @@
 					if (desc / 1000 % 10 > 0)
 						file_printf(fm, ".%d",
 						    desc / 1000 % 10);
+					printed = 1;
 				}
 
 				if (nh_namesz == 8 &&
-				    strcmp(&nbuf[nameoffset], "OpenBSD") == 0 &&
+				    strcmp(&nbuf[noff], "OpenBSD") == 0 &&
 				    nh_type == NT_OPENBSD_VERSION &&
 				    nh_descsz == 4) {
 					file_printf(fm, ", for OpenBSD");
 					/* Content of note is always 0 */
+					printed = 1;
 				}
 			}
 			if ((lseek(fm->fd, ph_offset + offset, SEEK_SET)) == -1) {
@@ -389,7 +412,7 @@
 	unsigned char c;
 	int i, j;
 	char nbuf[BUFSIZ];
-	int bufsize;
+	int nb;
 	int os_style = -1;
 
 	if (size != ph_size) {
@@ -421,26 +444,26 @@
 			error(EXIT_FAILURE, 0, "lseek failed (%s).\n", strerror(errno));
 			/*@notreached@*/
 		}
-		bufsize = read(fm->fd, nbuf, BUFSIZ);
-		if (bufsize == -1) {
+		nb = read(fm->fd, nbuf, BUFSIZ);
+		if (nb == -1) {
 			error(EXIT_FAILURE, 0, ": " "read failed (%s).\n", strerror(errno));
 			/*@notreached@*/
 		}
 		offset = 0;
 		for (;;) {
-			if (offset >= bufsize)
+			if (offset >= nb)
 				/*@innerbreak@*/ break;
 			if (fm->cls == ELFCLASS32)
 				nh32 = (Elf32_Nhdr *)&nbuf[offset];
 			else
 				nh64 = (Elf64_Nhdr *)&nbuf[offset];
-			offset += nh_size;
+			offset += 12;
 
 			/*
 			 * Check whether this note has the name "CORE" or
 			 * "FreeBSD", or "NetBSD-CORE".
 			 */
-			if (offset + nh_namesz >= bufsize) {
+			if (offset + nh_namesz >= nb) {
 				/*
 				 * We're past the end of the buffer.
 				 */
@@ -529,7 +552,7 @@
 						 * the end of the buffer; if
 						 * we are, just give up.
 						 */
-						if (noffset >= bufsize)
+						if (noffset >= nb)
 							goto tryanother;
 
 						/*
@@ -615,7 +638,6 @@
 	    || fm->buf[EI_MAG2] != ELFMAG2 || fm->buf[EI_MAG3] != ELFMAG3)
 	    return;
 
-
 	fm->cls = fm->buf[EI_CLASS];
 
 	if (fm->cls == ELFCLASS32) {


Więcej informacji o liście dyskusyjnej pld-devel-pl