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>