diff options
Diffstat (limited to 'elf/dl-sysdep.c')
-rw-r--r-- | elf/dl-sysdep.c | 50 |
1 files changed, 42 insertions, 8 deletions
diff --git a/elf/dl-sysdep.c b/elf/dl-sysdep.c index d06ce1754e..68e08f480a 100644 --- a/elf/dl-sysdep.c +++ b/elf/dl-sysdep.c @@ -1,5 +1,5 @@ /* Operating system support for run-time dynamic linker. Generic Unix version. - Copyright (C) 1995-1998, 2000-2005, 2006 Free Software Foundation, Inc. + Copyright (C) 1995-1998, 2000-2005, 2007 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 @@ -405,8 +405,25 @@ _dl_important_hwcaps (const char *platform, size_t platform_len, size_t *sz, } #endif +#ifdef USE_TLS /* For TLS enabled builds always add 'tls'. */ ++cnt; +#else + if (cnt == 0) + { + /* If we no have platform name and no important capability we only + have the base directory to search. */ + result = (struct r_strlenpair *) malloc (sizeof (*result)); + if (result == NULL) + goto no_memory; + + result[0].str = (char *) result; /* Does not really matter. */ + result[0].len = 0; + + *sz = 1; + return result; + } +#endif /* Create temporary data structure to generate result table. */ temp = (struct r_strlenpair *) alloca (cnt * sizeof (*temp)); @@ -448,11 +465,11 @@ _dl_important_hwcaps (const char *platform, size_t platform_len, size_t *sz, temp[m].len = platform_len; ++m; } - +#ifdef USE_TLS temp[m].str = "tls"; temp[m].len = 3; ++m; - +#endif assert (m == cnt); /* Determine the total size of all strings together. */ @@ -460,9 +477,21 @@ _dl_important_hwcaps (const char *platform, size_t platform_len, size_t *sz, total = temp[0].len + 1; else { - total = (1UL << (cnt - 2)) * (temp[0].len + temp[cnt - 1].len + 2); - for (n = 1; n + 1 < cnt; ++n) - total += (1UL << (cnt - 3)) * (temp[n].len + 1); + total = temp[0].len + temp[cnt - 1].len + 2; + if (cnt > 2) + { + total <<= 1; + for (n = 1; n + 1 < cnt; ++n) + total += temp[n].len + 1; + if (cnt > 3 + && (cnt >= sizeof (size_t) * 8 + || total + (sizeof (*result) << 3) + >= (1UL << (sizeof (size_t) * 8 - cnt + 3)))) + _dl_signal_error (ENOMEM, NULL, NULL, + N_("cannot create capability list")); + + total <<= cnt - 3; + } } /* The result structure: we use a very compressed way to store the @@ -470,8 +499,13 @@ _dl_important_hwcaps (const char *platform, size_t platform_len, size_t *sz, *sz = 1 << cnt; result = (struct r_strlenpair *) malloc (*sz * sizeof (*result) + total); if (result == NULL) - _dl_signal_error (ENOMEM, NULL, NULL, - N_("cannot create capability list")); + { +#ifndef USE_TLS + no_memory: +#endif + _dl_signal_error (ENOMEM, NULL, NULL, + N_("cannot create capability list")); + } if (cnt == 1) { |