Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 27 Nov 2004 23:39:58 -0600 (CST)
From:      Dan Nelson <dnelson@allantgroup.com>
To:        FreeBSD-gnats-submit@FreeBSD.org
Subject:   bin/74471: [PATCH] library mapping via $LD_LIBMAP
Message-ID:  <200411280539.iAS5dwnc094400@dan.emsphone.com>
Resent-Message-ID: <200411280540.iAS5ePkl019607@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         74471
>Category:       bin
>Synopsis:       [PATCH] library mapping via $LD_LIBMAP
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Sun Nov 28 05:40:24 GMT 2004
>Closed-Date:
>Last-Modified:
>Originator:     Dan Nelson
>Release:        FreeBSD 5.3-STABLE i386
>Organization:
The Allant Group
>Environment:
System: FreeBSD dan.emsphone.com 5.3-STABLE FreeBSD 5.3-STABLE #373: Fri Nov 26 21:49:32 CST 2004 zsh@dan.emsphone.com:/usr/src/sys/i386/compile/DANSMP i386


	
>Description:

I miss the ability to do one-off library mappings during debugging. 
It's handy to run with libc_r for just one execution, etc.

	
>How-To-Repeat:
	
>Fix:

The diff looks longer than it really is because a large chunk of
lm_init gets indented one more level.  The only real code change is to
make the code loop through multiple FILE*'s.  $LD_LIBMAP is read via
funopen and two helper functions.

Newer versions may be available at http://dan.allantgroup.com/libmap2.diff

Index: libmap.c
===================================================================
RCS file: /home/ncvs/src/libexec/rtld-elf/libmap.c,v
retrieving revision 1.12
diff -u -d -r1.12 libmap.c
--- libmap.c	24 May 2004 01:24:13 -0000	1.12
+++ libmap.c	21 Nov 2004 05:36:58 -0000
@@ -44,6 +44,8 @@
 static struct lm_list *	lmp_find	(const char *);
 static struct lm_list *	lmp_init	(char *);
 static const char * quickbasename	(const char *);
+static int readstrfn(void * cookie, char *buf, int len);
+static int closestrfn(void * cookie);
 
 #define	iseol(c)	(((c) == '#') || ((c) == '\0') || \
 			 ((c) == '\n') || ((c) == '\r'))
@@ -51,7 +53,8 @@
 int
 lm_init (void)
 {
-	FILE	*fp;
+	FILE	*fp[3];
+	int 	fp_num = 0;
 	char	*cp;
 	char	*f, *t, *p, *c;
 	char	prog[MAXPATHLEN];
@@ -61,80 +64,112 @@
 
 	TAILQ_INIT(&lmp_head);
 
-	if ((fp = fopen(_PATH_LIBMAP_CONF, "r")) == NULL)
-		return (1);
+	if ((fp[fp_num++] = fopen(_PATH_LIBMAP_CONF, "r")) == NULL)
+		fp_num--;
 
-	p = NULL;
-	while ((cp = fgets(line, MAXPATHLEN + 1, fp)) != NULL) {
-		t = f = c = NULL;
+	if (libmap_override)
+	{
+		/* do some character replacement to make $LIBMAP look like a
+		   text file, then "open" it with funopen */
+		if (libmap_override)
+			libmap_override = xstrdup(libmap_override);
 
-		/* Skip over leading space */
-		while (isspace(*cp)) cp++;
+		for (p = libmap_override; *p; p++)
+		{
+			switch (*p) {
+				case '=':
+					*p = ' '; break;
+				case ',':
+					*p = '\n'; break;
+			}
+		}
+		fp[fp_num++] = funopen(libmap_override, readstrfn, NULL, NULL, closestrfn);
+	}
 
-		/* Found a comment or EOL */
-		if (iseol(*cp)) continue;
+	if (fp_num == 0)
+	{
+		/* don't bother with libmap stuff if we have nothing to process */
+		return 1;
+	}
 
-		/* Found a constraint selector */
-		if (*cp == '[') {
-			cp++;
+	fp[fp_num] = NULL;
+	fp_num = 0;
 
-			/* Skip leading space */
+	while (fp[fp_num])
+	{
+		p = NULL;
+		while ((cp = fgets(line, MAXPATHLEN + 1, fp[fp_num])) != NULL) {
+			t = f = c = NULL;
+
+			/* Skip over leading space */
 			while (isspace(*cp)) cp++;
 
-			/* Found comment, EOL or end of selector */
-			if  (iseol(*cp) || *cp == ']')
-				continue;
+			/* Found a comment or EOL */
+			if (iseol(*cp)) continue;
 
-			c = cp++;
-			/* Skip to end of word */
-			while (!isspace(*cp) && !iseol(*cp) && *cp != ']')
+			/* Found a constraint selector */
+			if (*cp == '[') {
 				cp++;
 
-			/* Skip and zero out trailing space */
-			while (isspace(*cp)) *cp++ = '\0';
+				/* Skip leading space */
+				while (isspace(*cp)) cp++;
 
-			/* Check if there is a closing brace */
-			if (*cp != ']') continue;
+				/* Found comment, EOL or end of selector */
+				if  (iseol(*cp) || *cp == ']')
+					continue;
 
-			/* Terminate string if there was no trailing space */
-			*cp++ = '\0';
+				c = cp++;
+				/* Skip to end of word */
+				while (!isspace(*cp) && !iseol(*cp) && *cp != ']')
+					cp++;
 
-			/*
-			 * There should be nothing except whitespace or comment
-			  from this point to the end of the line.
-			 */
-			while(isspace(*cp)) cp++;
-			if (!iseol(*cp)) continue;
+				/* Skip and zero out trailing space */
+				while (isspace(*cp)) *cp++ = '\0';
 
-			strcpy(prog, c);
-			p = prog;
-			continue;
-		}
+				/* Check if there is a closing brace */
+				if (*cp != ']') continue;
 
-		/* Parse the 'from' candidate. */
-		f = cp++;
-		while (!isspace(*cp) && !iseol(*cp)) cp++;
+				/* Terminate string if there was no trailing space */
+				*cp++ = '\0';
 
-		/* Skip and zero out the trailing whitespace */
-		while (isspace(*cp)) *cp++ = '\0';
+				/*
+				 * There should be nothing except whitespace or comment
+				  from this point to the end of the line.
+				 */
+				while(isspace(*cp)) cp++;
+				if (!iseol(*cp)) continue;
 
-		/* Found a comment or EOL */
-		if (iseol(*cp)) continue;
+				strcpy(prog, c);
+				p = prog;
+				continue;
+			}
 
-		/* Parse 'to' mapping */
-		t = cp++;
-		while (!isspace(*cp) && !iseol(*cp)) cp++;
+			/* Parse the 'from' candidate. */
+			f = cp++;
+			while (!isspace(*cp) && !iseol(*cp)) cp++;
 
-		/* Skip and zero out the trailing whitespace */
-		while (isspace(*cp)) *cp++ = '\0';
+			/* Skip and zero out the trailing whitespace */
+			while (isspace(*cp)) *cp++ = '\0';
 
-		/* Should be no extra tokens at this point */
-		if (!iseol(*cp)) continue;
+			/* Found a comment or EOL */
+			if (iseol(*cp)) continue;
 
-		*cp = '\0';
-		lm_add(p, f, t);
+			/* Parse 'to' mapping */
+			t = cp++;
+			while (!isspace(*cp) && !iseol(*cp)) cp++;
+
+			/* Skip and zero out the trailing whitespace */
+			while (isspace(*cp)) *cp++ = '\0';
+
+			/* Should be no extra tokens at this point */
+			if (!iseol(*cp)) continue;
+
+			*cp = '\0';
+			lm_add(p, f, t);
+		}
+		fclose(fp[fp_num]);
+		fp_num++;
 	}
-	fclose(fp);
 	return (0);
 }
 
@@ -305,3 +340,29 @@
 	}
 	return p;
 }
+
+static int readstrfn(void * cookie, char *buf, int len)
+{
+	static char *current;
+	static int left;
+	int copied = 0;
+	if (!current)
+	{
+		current = cookie;
+		left = strlen(cookie);
+	}
+	while (*current && left && len)
+	{
+		*buf++ = *current++;
+		left--;
+		len--;
+		copied++;
+	}
+	return copied;
+}
+
+static int closestrfn(void * cookie)
+{
+	free(cookie);
+	return 0;
+}
Index: libmap.h
===================================================================
RCS file: /home/ncvs/src/libexec/rtld-elf/libmap.h,v
retrieving revision 1.3
diff -u -d -r1.3 libmap.h
--- libmap.h	21 Mar 2004 01:21:26 -0000	1.3
+++ libmap.h	21 Nov 2004 04:31:36 -0000
@@ -8,3 +8,4 @@
 #ifdef COMPAT_32BIT
 char *	lm_findn (const char *, const char *, const int);
 #endif
+char *	libmap_override;
Index: rtld.1
===================================================================
RCS file: /home/ncvs/src/libexec/rtld-elf/rtld.1,v
retrieving revision 1.38
diff -u -d -r1.38 rtld.1
--- rtld.1	19 Jun 2003 04:34:09 -0000	1.38
+++ rtld.1	21 Nov 2004 05:02:13 -0000
@@ -93,9 +93,22 @@
 .Nm
 will print a table containing all relocations before symbol
 binding and relocation.
+.It Ev LD_LIBMAP
+A library replacement list in the same format as
+.Xr libmap.conf 5 .
+For convenience, the characters
+.Ql =
+and
+.Ql \&,
+can be used instead of a space and a newline.
+This variable is parsed after 
+.Xr libmap.conf 5 ,
+and will override its entries.
 .It Ev LD_LIBMAP_DISABLE
 If set, disables the use of
-.Xr libmap.conf 5 .
+.Xr libmap.conf 5 
+and
+.Ev LD_LIBMAP .
 .It Ev LD_LIBRARY_PATH
 A colon separated list of directories, overriding the default search path
 for shared libraries.
Index: rtld.c
===================================================================
RCS file: /home/ncvs/src/libexec/rtld-elf/rtld.c,v
retrieving revision 1.99
diff -u -d -r1.99 rtld.c
--- rtld.c	4 Aug 2004 19:12:14 -0000	1.99
+++ rtld.c	21 Nov 2004 04:44:41 -0000
@@ -137,6 +137,7 @@
 static char *error_message;	/* Message for dlerror(), or NULL */
 struct r_debug r_debug;		/* for GDB; */
 static bool libmap_disable;	/* Disable libmap */
+char *libmap_override;		/* Maps to use instead of libmap.conf */
 static bool trust;		/* False for setuid and setgid programs */
 static char *ld_bind_now;	/* Environment variable for immediate binding */
 static char *ld_debug;		/* Environment variable for debugging */
@@ -289,6 +290,7 @@
     if (trust) {
 	ld_debug = getenv(LD_ "DEBUG");
 	libmap_disable = getenv(LD_ "LIBMAP_DISABLE") != NULL;
+	libmap_override = getenv(LD_ "LIBMAP");
 	ld_library_path = getenv(LD_ "LIBRARY_PATH");
 	ld_preload = getenv(LD_ "PRELOAD");
     }


	


>Release-Note:
>Audit-Trail:
>Unformatted:



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