OSDN Git Service

buildsys: cache build flags in vars
[uclinux-h8/uClibc.git] / ldso / include / dl-elf.h
index de404ae..29d1a00 100644 (file)
 /* Forward declarations for stuff defined in ld_hash.h */
 struct dyn_elf;
 struct elf_resolve;
+struct r_scope_elem;
 
 #include <dl-defs.h>
 #ifdef __LDSO_CACHE_SUPPORT__
 extern int _dl_map_cache(void);
 extern int _dl_unmap_cache(void);
 #else
-static inline void _dl_map_cache(void) { }
-static inline void _dl_unmap_cache(void) { }
+static __inline__ void _dl_map_cache(void) { }
+static __inline__ void _dl_unmap_cache(void) { }
 #endif
 
+#define DL_RESOLVE_SECURE              0x0001
+#define DL_RESOLVE_NOLOAD              0x0002
 
 /* Function prototypes for non-static stuff in readelflib1.c */
 extern void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,
        unsigned long rel_addr, unsigned long rel_size);
 extern int _dl_parse_relocation_information(struct dyn_elf *rpnt,
-       unsigned long rel_addr, unsigned long rel_size);
-extern struct elf_resolve * _dl_load_shared_library(int secure,
+       struct r_scope_elem *scope, unsigned long rel_addr, unsigned long rel_size);
+extern struct elf_resolve * _dl_load_shared_library(unsigned rflags,
        struct dyn_elf **rpnt, struct elf_resolve *tpnt, char *full_libname,
        int trace_loaded_objects);
-extern struct elf_resolve * _dl_load_elf_shared_library(int secure,
-       struct dyn_elf **rpnt, char *libname);
+extern struct elf_resolve * _dl_load_elf_shared_library(unsigned rflags,
+       struct dyn_elf **rpnt, const char *libname);
 extern struct elf_resolve *_dl_check_if_named_library_is_loaded(const char *full_libname,
        int trace_loaded_objects);
 extern int _dl_linux_resolve(void);
-extern int _dl_fixup(struct dyn_elf *rpnt, int flag);
+extern int _dl_fixup(struct dyn_elf *rpnt, struct r_scope_elem *scope, int flag);
 extern void _dl_protect_relro (struct elf_resolve *l);
 
 /*
@@ -84,21 +87,58 @@ extern void _dl_protect_relro (struct elf_resolve *l);
 #endif
 
 /* OS and/or GNU dynamic extensions */
-#define OS_NUM 1
-#define DT_RELCONT_IDX DT_NUM
+
+#define OS_NUM_BASE 1                  /* for DT_RELOCCOUNT */
+
+#ifdef __LDSO_GNU_HASH_SUPPORT__
+# define OS_NUM_GNU_HASH       1   /* for DT_GNU_HASH entry */
+#else
+# define OS_NUM_GNU_HASH       0
+#endif
+
+#ifdef __LDSO_PRELINK_SUPPORT__
+# define OS_NUM_PRELINK                6   /* for DT_GNU_PRELINKED entry */
+#else
+# define OS_NUM_PRELINK        0
+#endif
+
+#define OS_NUM   (OS_NUM_BASE + OS_NUM_GNU_HASH + OS_NUM_PRELINK)
 
 #ifndef ARCH_DYNAMIC_INFO
   /* define in arch specific code, if needed */
 # define ARCH_NUM 0
 #endif
 
-#define DYNAMIC_SIZE (DT_NUM+OS_NUM+ARCH_NUM)
+#define DYNAMIC_SIZE (DT_NUM + OS_NUM + ARCH_NUM)
+/* Keep ARCH specific entries into dynamic section at the end of the array */
+#define DT_RELCONT_IDX (DYNAMIC_SIZE - OS_NUM - ARCH_NUM)
+
+#ifdef __LDSO_GNU_HASH_SUPPORT__
+/* GNU hash comes just after the relocation count */
+# define DT_GNU_HASH_IDX (DT_RELCONT_IDX + 1)
+#else
+# define DT_GNU_HASH_IDX DT_RELCONT_IDX
+#endif
+
+#ifdef __LDSO_PRELINK_SUPPORT__
+/* GNU prelink comes just after the GNU hash if present */
+#define DT_GNU_PRELINKED_IDX  (DT_GNU_HASH_IDX + 1)
+#define DT_GNU_CONFLICT_IDX   (DT_GNU_HASH_IDX + 2)
+#define DT_GNU_CONFLICTSZ_IDX (DT_GNU_HASH_IDX + 3)
+#define DT_GNU_LIBLIST_IDX    (DT_GNU_HASH_IDX + 4)
+#define DT_GNU_LIBLISTSZ_IDX  (DT_GNU_HASH_IDX + 5)
+#define DT_CHECKSUM_IDX       (DT_GNU_HASH_IDX + 6)
+#endif
 
-extern void _dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[], void *debug_addr, ElfW(Addr) load_off);
+extern unsigned int _dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[],
+                                           void *debug_addr, DL_LOADADDR_TYPE load_off);
 
 static __always_inline
-void __dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[], void *debug_addr, ElfW(Addr) load_off)
+unsigned int __dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[],
+                                     void *debug_addr, DL_LOADADDR_TYPE load_off)
 {
+       unsigned int rtld_flags = 0;
+
        for (; dpnt->d_tag; dpnt++) {
                if (dpnt->d_tag < DT_NUM) {
                        dynamic_info[dpnt->d_tag] = dpnt->d_un.d_val;
@@ -126,9 +166,30 @@ void __dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[], void
                } else if (dpnt->d_tag < DT_LOPROC) {
                        if (dpnt->d_tag == DT_RELOCCOUNT)
                                dynamic_info[DT_RELCONT_IDX] = dpnt->d_un.d_val;
-                       if (dpnt->d_tag == DT_FLAGS_1 &&
-                           (dpnt->d_un.d_val & DF_1_NOW))
-                               dynamic_info[DT_BIND_NOW] = 1;
+                       if (dpnt->d_tag == DT_FLAGS_1) {
+                               if (dpnt->d_un.d_val & DF_1_NOW)
+                                       dynamic_info[DT_BIND_NOW] = 1;
+                               if (dpnt->d_un.d_val & DF_1_NODELETE)
+                                       rtld_flags |= RTLD_NODELETE;
+                       }
+#ifdef __LDSO_GNU_HASH_SUPPORT__
+                       if (dpnt->d_tag == DT_GNU_HASH)
+                               dynamic_info[DT_GNU_HASH_IDX] = dpnt->d_un.d_ptr;
+#endif
+#ifdef __LDSO_PRELINK_SUPPORT__
+                       if (dpnt->d_tag == DT_GNU_PRELINKED)
+                               dynamic_info[DT_GNU_PRELINKED_IDX] = dpnt->d_un.d_val;
+                       if (dpnt->d_tag == DT_GNU_CONFLICT)
+                               dynamic_info[DT_GNU_CONFLICT_IDX] = dpnt->d_un.d_ptr;
+                       if (dpnt->d_tag == DT_GNU_CONFLICTSZ)
+                               dynamic_info[DT_GNU_CONFLICTSZ_IDX] = dpnt->d_un.d_val;
+                       if (dpnt->d_tag == DT_GNU_LIBLIST)
+                               dynamic_info[DT_GNU_LIBLIST_IDX] = dpnt->d_un.d_ptr;
+                       if (dpnt->d_tag == DT_GNU_LIBLISTSZ)
+                               dynamic_info[DT_GNU_LIBLISTSZ_IDX] = dpnt->d_un.d_val;
+                       if (dpnt->d_tag == DT_CHECKSUM)
+                               dynamic_info[DT_CHECKSUM_IDX] = dpnt->d_un.d_val;
+#endif
                }
 #ifdef ARCH_DYNAMIC_INFO
                else {
@@ -139,15 +200,36 @@ void __dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[], void
 #define ADJUST_DYN_INFO(tag, load_off) \
        do { \
                if (dynamic_info[tag]) \
-                       dynamic_info[tag] += load_off; \
-       } while(0)
-       ADJUST_DYN_INFO(DT_HASH, load_off);
-       ADJUST_DYN_INFO(DT_PLTGOT, load_off);
-       ADJUST_DYN_INFO(DT_STRTAB, load_off);
-       ADJUST_DYN_INFO(DT_SYMTAB, load_off);
-       ADJUST_DYN_INFO(DT_RELOC_TABLE_ADDR, load_off);
-       ADJUST_DYN_INFO(DT_JMPREL, load_off);
+                       dynamic_info[tag] = (unsigned long) DL_RELOC_ADDR(load_off, dynamic_info[tag]); \
+       } while (0)
+       /* Don't adjust .dynamic unnecessarily.  For FDPIC targets,
+          we'd have to walk all the loadsegs to find out if it was
+          actually unnecessary, so skip this optimization.  */
+#if !defined __FDPIC__ && !defined __DSBT__
+       if (load_off != 0)
+#endif
+       {
+               ADJUST_DYN_INFO(DT_HASH, load_off);
+               ADJUST_DYN_INFO(DT_PLTGOT, load_off);
+               ADJUST_DYN_INFO(DT_STRTAB, load_off);
+               ADJUST_DYN_INFO(DT_SYMTAB, load_off);
+               ADJUST_DYN_INFO(DT_RELOC_TABLE_ADDR, load_off);
+               ADJUST_DYN_INFO(DT_JMPREL, load_off);
+#ifdef __LDSO_GNU_HASH_SUPPORT__
+               ADJUST_DYN_INFO(DT_GNU_HASH_IDX, load_off);
+#endif
+       }
+#ifdef __DSBT__
+       /* Get the mapped address of the DSBT base.  */
+       ADJUST_DYN_INFO(DT_DSBT_BASE_IDX, load_off);
+
+       /* Initialize loadmap dsbt info.  */
+       load_off.map->dsbt_table = (void *)dynamic_info[DT_DSBT_BASE_IDX];
+       load_off.map->dsbt_size = dynamic_info[DT_DSBT_SIZE_IDX];
+       load_off.map->dsbt_index = dynamic_info[DT_DSBT_INDEX_IDX];
+#endif
 #undef ADJUST_DYN_INFO
+       return rtld_flags;
 }
 
 /* Reloc type classes as returned by elf_machine_type_class().
@@ -164,6 +246,11 @@ void __dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[], void
 #endif
 #define ELF_RTYPE_CLASS_PLT    (0x1)
 
+/* dlsym() calls _dl_find_hash with this value, that enables
+   DL_FIND_HASH_VALUE to return something different than the symbol
+   itself, e.g., a function descriptor.  */
+#define ELF_RTYPE_CLASS_DLSYM 0x80000000
+
 
 /* Convert between the Linux flags for page protections and the
    ones specified in the ELF standard. */