bin/74471: [PATCH] library mapping via $LD_LIBMAP
Dan Nelson
dnelson at allantgroup.com
Sat Nov 27 21:40:25 PST 2004
>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 at 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:
More information about the freebsd-bugs
mailing list