aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog12
-rw-r--r--elf/dl-load.c60
-rw-r--r--elf/rtld.c55
-rw-r--r--sysdeps/generic/dl-environ.c35
4 files changed, 100 insertions, 62 deletions
diff --git a/ChangeLog b/ChangeLog
index cfedf5d..8632fba 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2002-02-02 Ulrich Drepper <drepper@redhat.com>
+
+ * sysdeps/generic/dl-environ.c (unsetenv): Optimize. Don't use
+ strncmp.
+ * elf/dl-load.c (is_dst): Optimize. Don't call strncmp twice.
+ * elf/rtld.c (process_dl_debug): Optimize. Avoid calls to strncmp,
+ strspn, and strcspn.
+ (process_envvars): Don't use strcspn.
+
+ * elf/dl-load.c (_dl_dst_count): Fix possible endless loop.
+ (_dl_dst_substitute): Likewise.
+
2002-02-01 Ulrich Drepper <drepper@redhat.com>
* elf/do-rel.h (elf_dynamic_do_rel): Help the compiler recognize
diff --git a/elf/dl-load.c b/elf/dl-load.c
index cd568d2..ebaccfc 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -21,6 +21,7 @@
#include <errno.h>
#include <fcntl.h>
#include <libintl.h>
+#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
@@ -147,22 +148,38 @@ local_strdup (const char *s)
static size_t
-is_dst (const char *start, const char *name, const char *str, size_t cmplen,
+is_dst (const char *start, const char *name, const char *str,
int is_path, int secure)
{
size_t len;
+ bool is_curly = false;
- if (strncmp (name, str, cmplen) == 0)
- len = cmplen + 1;
- else if (strncmp (name, str + 1, cmplen - 2) == 0
- && (name[cmplen - 2] == '\0' || name[cmplen - 2] == '/'
- || (is_path && name[cmplen - 2] == ':')))
- len = cmplen - 1;
- else
+ if (name[0] == '{')
+ {
+ is_curly = true;
+ ++name;
+ }
+
+ len = 0;
+ while (name[len] == str[len] && name[len] != '\0')
+ ++len;
+
+ if (is_curly)
+ {
+ if (name[len] != '}')
+ return 0;
+
+ /* Point again at the beginning of the name. */
+ --name;
+ /* Skip over closing curly brace and adjust for the --name. */
+ len += 2;
+ }
+ else if (name[len] != '\0' && name[len] != '/'
+ && (!is_path || name[len] != ':'))
return 0;
if (__builtin_expect (secure, 0)
- && ((name[len - 1] != '\0' && (!is_path || name[len - 1] != ':'))
+ && ((name[len] != '\0' && (!is_path || name[len] != ':'))
|| (name != start + 1 && (!is_path || name[-2] != ':'))))
return 0;
@@ -178,17 +195,14 @@ _dl_dst_count (const char *name, int is_path)
do
{
- size_t len = 1;
+ size_t len;
/* $ORIGIN is not expanded for SUID/GUID programs (except if it
- is $ORIGIN alone) and it must always appear first in path.
-
- Note that it is no bug that the string in the second and
- fourth `strncmp' call is longer than the sequence which is
- actually tested. */
- if ((len = is_dst (start, name + 1, "{ORIGIN}", 8, is_path,
+ is $ORIGIN alone) and it must always appear first in path. */
+ ++name;
+ if ((len = is_dst (start, name, "ORIGIN", is_path,
__libc_enable_secure)) != 0
- || ((len = is_dst (start, name + 1, "{PLATFORM}", 10, is_path, 0))
+ || ((len = is_dst (start, name, "PLATFORM", is_path, 0))
!= 0))
++cnt;
@@ -218,15 +232,13 @@ _dl_dst_substitute (struct link_map *l, const char *name, char *result,
if (__builtin_expect (*name == '$', 0))
{
const char *repl = NULL;
- size_t len = 1;
+ size_t len;
- /* Note that it is no bug that the string in the second and
- fourth `strncmp' call is longer than the sequence which
- is actually tested. */
- if ((len = is_dst (start, name + 1, "{ORIGIN}", 8, is_path,
+ ++name;
+ if ((len = is_dst (start, name, "ORIGIN", is_path,
__libc_enable_secure)) != 0)
repl = l->l_origin;
- else if ((len = is_dst (start, name + 1, "{PLATFORM}", 10, is_path,
+ else if ((len = is_dst (start, name, "PLATFORM", is_path,
0)) != 0)
repl = GL(dl_platform);
@@ -246,7 +258,7 @@ _dl_dst_substitute (struct link_map *l, const char *name, char *result,
}
else
/* No DST we recognize. */
- *wp++ = *name++;
+ *wp++ = '$';
}
else
{
diff --git a/elf/rtld.c b/elf/rtld.c
index 58d61e7..1efe38b 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -1286,49 +1286,50 @@ process_dl_debug (const char *dl_debug)
is correctly handled in the LD_DEBUG_HELP code below. */
static const struct
{
- const char name[11];
+ unsigned char len;
+ const char name[10];
const char helptext[41];
unsigned short int mask;
} debopts[] =
{
- { "libs", "display library search paths",
+#define LEN_AND_STR(str) sizeof (str) - 1, str
+ { LEN_AND_STR ("libs"), "display library search paths",
DL_DEBUG_LIBS | DL_DEBUG_IMPCALLS },
- { "reloc", "display relocation processing",
+ { LEN_AND_STR ("reloc"), "display relocation processing",
DL_DEBUG_RELOC | DL_DEBUG_IMPCALLS },
- { "files", "display progress for input file",
+ { LEN_AND_STR ("files"), "display progress for input file",
DL_DEBUG_FILES | DL_DEBUG_IMPCALLS },
- { "symbols", "display symbol table processing",
+ { LEN_AND_STR ("symbols"), "display symbol table processing",
DL_DEBUG_SYMBOLS | DL_DEBUG_IMPCALLS },
- { "bindings", "display information about symbol binding",
+ { LEN_AND_STR ("bindings"), "display information about symbol binding",
DL_DEBUG_BINDINGS | DL_DEBUG_IMPCALLS },
- { "versions", "display version dependencies",
+ { LEN_AND_STR ("versions"), "display version dependencies",
DL_DEBUG_VERSIONS | DL_DEBUG_IMPCALLS },
- { "all", "all previous options combined",
+ { LEN_AND_STR ("all"), "all previous options combined",
DL_DEBUG_LIBS | DL_DEBUG_RELOC | DL_DEBUG_FILES | DL_DEBUG_SYMBOLS
| DL_DEBUG_BINDINGS | DL_DEBUG_VERSIONS | DL_DEBUG_IMPCALLS },
- { "statistics", "display relocation statistics",
+ { LEN_AND_STR ("statistics"), "display relocation statistics",
DL_DEBUG_STATISTICS },
- { "help", "display this help message and exit",
+ { LEN_AND_STR ("help"), "display this help message and exit",
DL_DEBUG_HELP },
};
#define ndebopts (sizeof (debopts) / sizeof (debopts[0]))
- size_t len;
-#define separators " ,:"
- do
+ /* Skip separating white spaces and commas. */
+ while (*dl_debug != '\0')
{
- len = 0;
- /* Skip separating white spaces and commas. */
- dl_debug += strspn (dl_debug, separators);
- if (*dl_debug != '\0')
+ if (*dl_debug != ' ' && *dl_debug != ',' && *dl_debug != ':')
{
size_t cnt;
+ size_t len = 1;
- len = strcspn (dl_debug, separators);
+ while (dl_debug[len] != '\0' && dl_debug[len] != ' '
+ && dl_debug[len] != ',' && dl_debug[len] != ':')
+ ++len;
for (cnt = 0; cnt < ndebopts; ++cnt)
- if (strncmp (dl_debug, debopts[cnt].name, len) == 0
- && debopts[cnt].name[len] == '\0')
+ if (debopts[cnt].len == len
+ && memcmp (dl_debug, debopts[cnt].name, len) == 0)
{
GL(dl_debug_mask) |= debopts[cnt].mask;
any_debug = 1;
@@ -1342,11 +1343,14 @@ process_dl_debug (const char *dl_debug)
char *copy = strndupa (dl_debug, len);
_dl_error_printf ("\
warning: debug option `%s' unknown; try LD_DEBUG=help\n", copy);
- break;
- }
+ }
+
+ dl_debug += len;
+ continue;
}
+
+ ++dl_debug;
}
- while (*(dl_debug += len) != '\0');
if (GL(dl_debug_mask) & DL_DEBUG_HELP)
{
@@ -1387,7 +1391,10 @@ process_envvars (enum mode *modep)
while ((envline = _dl_next_ld_env_entry (&runp)) != NULL)
{
- size_t len = strcspn (envline, "=");
+ size_t len = 0;
+
+ while (envline[len] != '\0' && envline[len] != '=')
+ ++len;
if (envline[len] != '=')
/* This is a "LD_" variable at the end of the string without
diff --git a/sysdeps/generic/dl-environ.c b/sysdeps/generic/dl-environ.c
index 7a3da0c..e13bb5d 100644
--- a/sysdeps/generic/dl-environ.c
+++ b/sysdeps/generic/dl-environ.c
@@ -1,5 +1,5 @@
/* Environment handling for dynamic loader.
- Copyright (C) 1995-1998, 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 1995-1998, 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -53,23 +53,30 @@ _dl_next_ld_env_entry (char ***position)
int
unsetenv (const char *name)
{
- const size_t len = strlen (name);
char **ep;
ep = __environ;
while (*ep != NULL)
- if (!strncmp (*ep, name, len) && (*ep)[len] == '=')
- {
- /* Found it. Remove this pointer by moving later ones back. */
- char **dp = ep;
-
- do
- dp[0] = dp[1];
- while (*dp++);
- /* Continue the loop in case NAME appears again. */
- }
- else
- ++ep;
+ {
+ size_t cnt;
+
+ while ((*ep)[cnt] == name[cnt] && name[cnt] != '\0')
+ ++cnt;
+
+ if ((*ep)[cnt] == '=')
+ {
+ /* Found it. Remove this pointer by moving later ones to
+ the front. */
+ char **dp = ep;
+
+ do
+ dp[0] = dp[1];
+ while (*dp++);
+ /* Continue the loop in case NAME appears again. */
+ }
+ else
+ ++ep;
+ }
return 0;
}