summary refs log tree commit diff
path: root/sysdeps
diff options
context:
space:
mode:
authorFlorian Weimer <fweimer@redhat.com>2020-12-04 09:13:43 +0100
committerFlorian Weimer <fweimer@redhat.com>2020-12-04 09:16:30 +0100
commit84ba719b260551918965d0a433914de683087645 (patch)
tree2a3e5e634f104e0ef2f8592f1925955d8ce63db4 /sysdeps
parentdad90d528259b669342757c37dedefa8577e2636 (diff)
downloadglibc-84ba719b260551918965d0a433914de683087645.tar.gz
glibc-84ba719b260551918965d0a433914de683087645.tar.xz
glibc-84ba719b260551918965d0a433914de683087645.zip
elf: Add endianness markup to ld.so.cache (bug 27008)
Use a reserved byte in the new format cache header to indicate whether
the file is in little endian or big endian format.  Eventually, this
information could be used to provide a unified cache for qemu-user
and similiar scenarios.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
Diffstat (limited to 'sysdeps')
-rw-r--r--sysdeps/generic/dl-cache.h64
1 files changed, 63 insertions, 1 deletions
diff --git a/sysdeps/generic/dl-cache.h b/sysdeps/generic/dl-cache.h
index 4ddd96b005..4c77cd0c1b 100644
--- a/sysdeps/generic/dl-cache.h
+++ b/sysdeps/generic/dl-cache.h
@@ -16,6 +16,11 @@
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
+#ifndef _DL_CACHE_H
+#define _DL_CACHE_H
+
+#include <endian.h>
+#include <stdbool.h>
 #include <stdint.h>
 
 #ifndef _DL_CACHE_DEFAULT_ID
@@ -92,17 +97,72 @@ struct file_entry_new
   uint64_t hwcap;		/* Hwcap entry.	 */
 };
 
+/* See flags member of struct cache_file_new below.  */
+enum
+  {
+    /* No endianness information available.  An old ldconfig version
+       without endianness support wrote the file.  */
+    cache_file_new_flags_endian_unset = 0,
+
+    /* Cache is invalid and should be ignored.  */
+    cache_file_new_flags_endian_invalid = 1,
+
+    /* Cache format is little endian.  */
+    cache_file_new_flags_endian_little = 2,
+
+    /* Cache format is big endian.  */
+    cache_file_new_flags_endian_big = 3,
+
+    /* Bit mask to extract the cache_file_new_flags_endian_*
+       values.  */
+    cache_file_new_flags_endian_mask = 3,
+
+    /* Expected value of the endian bits in the flags member for the
+       current architecture.  */
+    cache_file_new_flags_endian_current
+      = (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+	 ? cache_file_new_flags_endian_little
+	 : cache_file_new_flags_endian_big),
+  };
+
 struct cache_file_new
 {
   char magic[sizeof CACHEMAGIC_NEW - 1];
   char version[sizeof CACHE_VERSION - 1];
   uint32_t nlibs;		/* Number of entries.  */
   uint32_t len_strings;		/* Size of string table. */
-  uint32_t unused[5];		/* Leave space for future extensions
+
+  /* flags & cache_file_new_flags_endian_mask is one of the values
+     cache_file_new_flags_endian_unset, cache_file_new_flags_endian_invalid,
+     cache_file_new_flags_endian_little, cache_file_new_flags_endian_big.
+
+     The remaining bits are unused and should be generated as zero and
+     ignored by readers.  */
+  uint8_t flags;
+
+  uint8_t padding_unsed[3];	/* Not used, for future extensions.  */
+
+  uint32_t unused[4];		/* Leave space for future extensions
 				   and align to 8 byte boundary.  */
   struct file_entry_new libs[0]; /* Entries describing libraries.  */
   /* After this the string table of size len_strings is found.	*/
 };
+_Static_assert (sizeof (struct cache_file_new) == 48,
+		"size of struct cache_file_new");
+
+/* Returns false if *CACHE has the wrong endianness for this
+   architecture, and true if the endianness matches (or is
+   unknown).  */
+static inline bool
+cache_file_new_matches_endian (const struct cache_file_new *cache)
+{
+  /* A zero value for cache->flags means that no endianness
+     information is available.  */
+  return cache->flags == 0
+    || ((cache->flags & cache_file_new_flags_endian_big)
+	== cache_file_new_flags_endian_current);
+}
+
 
 /* Used to align cache_file_new.  */
 #define ALIGN_CACHE(addr)				\
@@ -110,3 +170,5 @@ struct cache_file_new
  & (~(__alignof__ (struct cache_file_new) - 1)))
 
 extern int _dl_cache_libcmp (const char *p1, const char *p2) attribute_hidden;
+
+#endif /* _DL_CACHE_H */