This is the mail archive of the
libc-alpha@sourceware.cygnus.com
mailing list for the glibc project.
Re: Problem with new ld.so.cache format on 64-bit machines
>>>>> David Huggins-Daines writes:
David> Andreas Jaeger <aj@suse.de> writes:
>> Can you send a patch that works for you on alpha, please?
David> No problem...
Thanks a lot! I've started with my own patch also and have merged
yours and mine. I prefer to use a macro for the alignment and align
to struct cache_file_new instead of long.
David> One other thing I noticed when writing this patch is that it appears
David> that _dl_load_cache_lookup() would not actually have worked in the
David> case where there is only the new-style index in the cache, because
David> cache_data was always calculated using 'cache' (which would be NULL in
David> the case where no old-style cache index was present). I think (but
David> I'm not sure) that this should fix that as well.
This looks fine. I've also fixed another patch with using only the
new format - I hope it's working now.
Can you check the appended patch and tell me, if it's ok? I've tested
it only briefly on i686.
I'm not changing the version number - nobody should have used this
format, and we're still compatible to the old format.
Thanks,
Andreas
2000-05-13 Andreas Jaeger <aj@suse.de>,
David Huggins-Daines <dhd@linuxcare.com>
* sysdeps/generic/dl-cache.c (_dl_load_cache_lookup): Set
cache_data in case of only new cache format correctly.
* sysdeps/generic/dl-cache.c (_dl_load_cache_lookup): Align struct
cache_file_new.
* sysdeps/generic/dl-cache.h (ALIGN_CACHE): New macro to align
struct cache_file_new.
* elf/cache.c (save_cache): Fix str_offset if only new cache is
present.
* elf/cache.c (save_cache): Align struct new_file_cache.
(print_cache): Likewise.
============================================================
Index: sysdeps/generic/dl-cache.c
--- sysdeps/generic/dl-cache.c 2000/05/07 21:23:20 1.21
+++ sysdeps/generic/dl-cache.c 2000/05/13 16:54:39
@@ -52,7 +52,7 @@
right = cache->nlibs - 1; \
middle = (left + right) / 2; \
cmpres = 1; \
- \
+ \
while (left <= right) \
{ \
/* Make sure string table indices are not bogus before using \
@@ -121,7 +121,7 @@
{ \
HWCAP_CHECK; \
best = cache_data + cache->libs[middle].value; \
- \
+ \
if (flags == _dl_correct_cache_id) \
/* We've found an exact match for the shared \
object and no general `ELF' release. Stop \
@@ -166,14 +166,16 @@
if (file && cachesize > sizeof *cache &&
!memcmp (file, CACHEMAGIC, sizeof CACHEMAGIC - 1))
{
+ size_t offset;
/* Looks ok. */
cache = file;
/* Check for new version. */
- cache_new = (struct cache_file_new *) &cache->libs[cache->nlibs];
- if (cachesize <
- (sizeof (struct cache_file) + cache->nlibs * sizeof (struct file_entry)
- + sizeof (struct cache_file_new))
+ offset = ALIGN_CACHE (sizeof (struct cache_file)
+ + cache->nlibs * sizeof (struct file_entry));
+
+ cache_new = (struct cache_file_new *) ((void *)cache + offset);
+ if (cachesize < (offset + sizeof (struct cache_file_new))
|| memcmp (cache_new->magic, CACHEMAGIC_NEW,
sizeof CACHEMAGIC_NEW - 1)
|| memcmp (cache_new->version, CACHE_VERSION,
@@ -202,9 +204,6 @@
/* Previously looked for the cache file and didn't find it. */
return NULL;
- /* This is where the strings start. */
- cache_data = (const char *) &cache->libs[cache->nlibs];
-
best = NULL;
if (cache_new != (void *) -1)
@@ -213,6 +212,9 @@
unsigned long int *hwcap;
weak_extern (_dl_hwcap);
+ /* This is where the strings start. */
+ cache_data = (const char *) cache_new;
+
hwcap = &_dl_hwcap;
#define HWCAP_CHECK \
@@ -221,9 +223,13 @@
SEARCH_CACHE (cache_new);
}
else
+ {
+ /* This is where the strings start. */
+ cache_data = (const char *) &cache->libs[cache->nlibs];
#undef HWCAP_CHECK
#define HWCAP_CHECK do {} while (0)
- SEARCH_CACHE (cache);
+ SEARCH_CACHE (cache);
+ }
/* Print our result if wanted. */
if (_dl_debug_libs && best != NULL)
============================================================
Index: sysdeps/generic/dl-cache.h
--- sysdeps/generic/dl-cache.h 2000/05/07 21:23:35 1.2
+++ sysdeps/generic/dl-cache.h 2000/05/13 16:54:39
@@ -32,7 +32,7 @@
/* libc5 and glibc 2.0/2.1 use the same format. For glibc 2.2 another
format has been added in a compatible way:
The beginning of the string table is used for the new table:
- old_magic
+ old_magic
nlibs
libs[0]
...
@@ -81,6 +81,11 @@
struct file_entry_new libs[0]; /* Entries describing libraries. */
/* After this the string table of size len_strings is found. */
};
+
+/* Used to align cache_file_new. */
+#define ALIGN_CACHE(addr) \
+(((addr) + __alignof__ (struct cache_file_new) -1) \
+ & (~(__alignof__ (struct cache_file_new) - 1)))
static int
_dl_cache_libcmp (const char *p1, const char *p2)
============================================================
Index: elf/cache.c
--- elf/cache.c 2000/05/07 21:19:22 1.4
+++ elf/cache.c 2000/05/13 16:54:40
@@ -49,7 +49,6 @@
static const char *flag_descr[] =
{ "libc4", "ELF", "libc5", "libc6"};
-
/* Print a single entry. */
static void
print_entry (const char *lib, int flag, unsigned long int hwcap, const char *key)
@@ -130,20 +129,21 @@
error (EXIT_FAILURE, 0, _("File is not a cache file.\n"));
format = 1;
/* This is where the strings start. */
- cache_data = (const char *) cache;
+ cache_data = (const char *) cache_new;
}
else
{
+ size_t offset = ALIGN_CACHE (sizeof (struct cache_file)
+ + cache->nlibs * sizeof (struct file_entry));
/* This is where the strings start. */
cache_data = (const char *) &cache->libs[cache->nlibs];
/* Check for a new cache embedded in the old format. */
if (cache_size >
- (sizeof (struct cache_file)
- + cache->nlibs * sizeof (struct file_entry)
- + sizeof (struct cache_file_new)))
+ (offset + sizeof (struct cache_file_new)))
{
- cache_new = (struct cache_file_new *) cache_data;
+
+ cache_new = (struct cache_file_new *) ((void *)cache + offset);
if (!memcmp (cache_new->magic, CACHEMAGIC_NEW, sizeof CACHEMAGIC_NEW - 1)
&& !memcmp (cache_new->version, CACHE_VERSION,
@@ -284,8 +284,8 @@
/* If we have both formats, we hide the new format in the strings
table, we have to adjust all string indices for this so that
old libc5/glibc 2 dynamic linkers just ignore them. */
- if (opt_format == 1)
- str_offset = file_entries_new_size;
+ if (opt_format != 0)
+ str_offset = ALIGN_CACHE (file_entries_new_size);
else
str_offset = 0;
@@ -354,6 +354,14 @@
}
if (opt_format != 0)
{
+ /* Align cache. */
+ if (opt_format != 2)
+ {
+ size_t align = ALIGN_CACHE(file_entries_size) - file_entries_size;
+ char zero [align];
+ if (write (fd, zero, align) != (ssize_t)align)
+ error (EXIT_FAILURE, errno, _("Writing of cache data failed"));
+ }
if (write (fd, file_entries_new, file_entries_new_size)
!= (ssize_t)file_entries_new_size)
error (EXIT_FAILURE, errno, _("Writing of cache data failed"));
--
Andreas Jaeger
SuSE Labs aj@suse.de
private aj@arthur.inka.de