OSDN Git Service

Bernd Schmidt writes: abstract away addresses so we can support FDPIC ELFs
authorMike Frysinger <vapier@gentoo.org>
Fri, 30 Jun 2006 02:55:57 +0000 (02:55 -0000)
committerMike Frysinger <vapier@gentoo.org>
Fri, 30 Jun 2006 02:55:57 +0000 (02:55 -0000)
ldso/include/dl-defs.h
ldso/include/dl-elf.h
ldso/include/dl-hash.h
ldso/include/ldso.h
ldso/ldso/dl-elf.c
ldso/ldso/dl-hash.c
ldso/ldso/dl-startup.c
ldso/ldso/ldso.c
ldso/libdl/libdl.c

index 878ebc3..dc6531d 100644 (file)
@@ -66,4 +66,70 @@ typedef struct {
 
 #endif
 
+/* Machines in which different sections may be relocated by different
+   amounts should define this and LD_RELOC_ADDR.  If you change this,
+   make sure you change struct link_map in include/link.h accordingly
+   such that it matches a prefix of struct elf_resolve.  */
+#ifndef DL_LOADADDR_TYPE
+# define DL_LOADADDR_TYPE ElfW(Addr)
+#endif
+
+/* When DL_LOADADDR_TYPE is not a scalar value, or some different
+   computation is needed to relocate an address, define this.  */
+#ifndef DL_RELOC_ADDR
+# define DL_RELOC_ADDR(ADDR, LOADADDR) \
+  ((void*)((intptr_t)(ADDR) + (intptr_t)(LOADADDR)))
+#endif
+
+/* Define if any declarations/definitions of local variables are
+   needed in a function that calls DT_INIT_LOADADDR or
+   DL_INIT_LOADADDR_HDR.  Declarations must be properly terminated
+   with a semicolon, and non-declaration statements are forbidden.  */
+#ifndef DL_INIT_LOADADDR_EXTRA_DECLS
+# define DL_INIT_LOADADDR_EXTRA_DECLS /* int i; */
+#endif
+
+/* Prepare a DL_LOADADDR_TYPE data structure for incremental
+   initialization with DL_INIT_LOADADDR_HDR, given pointers to a base
+   load address and to program headers.  */
+#ifndef DL_INIT_LOADADDR
+# define DL_INIT_LOADADDR(LOADADDR, BASEADDR, PHDR, PHDRCNT) \
+  ((LOADADDR) = (BASEADDR))
+#endif
+
+/* Convert a DL_LOADADDR_TYPE to an identifying pointer.  Used mostly
+   for debugging.  */
+#ifndef DL_LOADADDR_BASE
+# define DL_LOADADDR_BASE(LOADADDR) (LOADADDR)
+#endif
+
+/* Initialize a LOADADDR representing the loader itself.  It's only
+   called from DL_BOOT, so additional arguments passed to it may be
+   referenced.  */
+#ifndef DL_INIT_LOADADDR_BOOT
+# define DL_INIT_LOADADDR_BOOT(LOADADDR, BASEADDR) \
+  ((LOADADDR) = (BASEADDR))
+#endif
+
+/* Initialize a LOADADDR representing the program.  It's called from
+   DL_BOOT only.  */
+#ifndef DL_INIT_LOADADDR_PROG
+# define DL_INIT_LOADADDR_PROG(LOADADDR, BASEADDR) \
+  ((LOADADDR) = (BASEADDR))
+#endif
+
+/* Test whether a given ADDR is more likely to be within the memory
+   region mapped to TPNT (a struct elf_resolve *) than to TFROM.
+   Everywhere that this is used, TFROM is initially NULL, and whenever
+   a potential match is found, it's updated.  One might want to walk
+   the chain of elf_resolve to locate the best match and return false
+   whenever TFROM is non-NULL, or use an exact-matching algorithm
+   using additional information encoded in DL_LOADADDR_TYPE to test
+   for exact containment.  */
+#ifndef DL_ADDR_IN_LOADADDR
+# define DL_ADDR_IN_LOADADDR(ADDR, TPNT, TFROM) \
+  ((void*)(TPNT)->loadaddr < (void*)(ADDR)                     \
+   && (! (TFROM) || (TFROM)->loadaddr < (TPNT)->loadaddr))
+#endif
+
 #endif /* _LD_DEFS_H */
index de404ae..9e364d6 100644 (file)
@@ -94,10 +94,12 @@ extern void _dl_protect_relro (struct elf_resolve *l);
 
 #define DYNAMIC_SIZE (DT_NUM+OS_NUM+ARCH_NUM)
 
-extern void _dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[], void *debug_addr, ElfW(Addr) load_off);
+extern void _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)
+void __dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[], void *debug_addr,
+                            DL_LOADADDR_TYPE load_off)
 {
        for (; dpnt->d_tag; dpnt++) {
                if (dpnt->d_tag < DT_NUM) {
@@ -139,7 +141,8 @@ 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; \
+                       dynamic_info[tag] = (unsigned long)DL_RELOC_ADDR (dynamic_info[tag], \
+                                                                         load_off); \
        } while(0)
        ADJUST_DYN_INFO(DT_HASH, load_off);
        ADJUST_DYN_INFO(DT_PLTGOT, load_off);
index b12b36f..26fb334 100644 (file)
@@ -28,7 +28,7 @@ struct dyn_elf{
 struct elf_resolve{
   /* These entries must be in this order to be compatible with the interface used
      by gdb to obtain the list of symbols. */
-  ElfW(Addr) loadaddr;         /* Base address shared object is loaded at.  */
+  DL_LOADADDR_TYPE loadaddr;   /* Base address shared object is loaded at.  */
   char *libname;               /* Absolute file name object was found in.  */
   ElfW(Dyn) *dynamic_addr;     /* Dynamic section of the shared object.  */
   struct elf_resolve * next;
@@ -77,7 +77,7 @@ extern struct elf_resolve * _dl_loaded_modules;
 extern struct dyn_elf    * _dl_handles;
 
 extern struct elf_resolve * _dl_add_elf_hash_table(const char * libname, 
-       char * loadaddr, unsigned long * dynamic_info, 
+       DL_LOADADDR_TYPE loadaddr, unsigned long * dynamic_info, 
        unsigned long dynamic_addr, unsigned long dynamic_size);
 
 extern char * _dl_find_hash(const char * name, struct dyn_elf * rpnt1, 
index 0a3f706..573652e 100644 (file)
@@ -88,7 +88,7 @@ extern void _dl_unsetenv(const char *symbol, char **envp);
 extern char *_dl_strdup(const char *string);
 extern void _dl_dprintf(int, const char *, ...);
 
-extern void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr,
+extern void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,
                ElfW(auxv_t) auxvt[AT_EGID + 1], char **envp, char **argv);
 
 #endif /* _LDSO_H_ */
index d0ea4da..f98d76b 100644 (file)
@@ -118,10 +118,10 @@ int _dl_unmap_cache(void)
 void
 _dl_protect_relro (struct elf_resolve *l)
 {
-       ElfW(Addr) start = ((l->loadaddr + l->relro_addr)
-                           & ~(_dl_pagesize - 1));
-       ElfW(Addr) end = ((l->loadaddr + l->relro_addr + l->relro_size)
-                         & ~(_dl_pagesize - 1));
+       ElfW(Addr) base = (ElfW(Addr)) DL_RELOC_ADDR (l->relro_addr,
+                                                     l->loadaddr);
+       ElfW(Addr) start = (base & ~(_dl_pagesize - 1));
+       ElfW(Addr) end = ((base + l->relro_size) & ~(_dl_pagesize - 1));
        _dl_if_debug_dprint("RELRO protecting %s:  start:%x, end:%x\n", l->libname, start, end);
        if (start != end &&
            _dl_mprotect ((void *) start, end - start, PROT_READ) < 0) {
@@ -262,7 +262,8 @@ struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt,
 #ifdef __LDSO_RUNPATH__
        pnt = (tpnt ? (char *)tpnt->dynamic_info[DT_RUNPATH] : NULL);
        if (pnt) {
-               pnt += (unsigned long) tpnt->dynamic_info[DT_STRTAB];
+               pnt += (intptr_t) DL_RELOC_ADDR (tpnt->dynamic_info[DT_STRTAB],
+                                                tpnt->loadaddr);
                _dl_if_debug_dprint("\tsearching RUNPATH='%s'\n", pnt);
                if ((tpnt1 = search_for_named_library(libname, secure, pnt, rpnt)) != NULL)
                        return tpnt1;
@@ -352,6 +353,8 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
        ElfW(Addr) relro_addr = 0;
        size_t relro_size = 0;
        struct stat st;
+       DL_LOADADDR_TYPE lib_loadaddr;
+       DL_INIT_LOADADDR_EXTRA_DECLS
 
        libaddr = 0;
        infile = _dl_open(libname, O_RDONLY, 0);
@@ -467,7 +470,10 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
        }
        libaddr = (unsigned long) status;
        flags |= MAP_FIXED;
-
+       DL_INIT_LOADADDR (lib_loadaddr, libaddr,
+                         (Elf32_Phdr *)& header[epnt->e_phoff],
+                         epnt->e_phnum);
+       
        /* Get the memory to store the library */
        ppnt = (ElfW(Phdr) *)(intptr_t) & header[epnt->e_phoff];
 
@@ -547,7 +553,8 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 
        /* For a non-PIC library, the addresses are all absolute */
        if (piclib) {
-               dynamic_addr += (unsigned long) libaddr;
+               dynamic_addr = (unsigned long) DL_RELOC_ADDR (dynamic_addr,
+                                                             lib_loadaddr);
        }
 
        /*
@@ -567,7 +574,7 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 
        dpnt = (ElfW(Dyn) *) dynamic_addr;
        _dl_memset(dynamic_info, 0, sizeof(dynamic_info));
-       _dl_parse_dynamic_info(dpnt, dynamic_info, NULL, libaddr);
+       _dl_parse_dynamic_info(dpnt, dynamic_info, NULL, lib_loadaddr);
        /* If the TEXTREL is set, this means that we need to make the pages
           writable before we perform relocations.  Do this now. They get set
           back again later. */
@@ -588,13 +595,14 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 #endif
        }
 
-       tpnt = _dl_add_elf_hash_table(libname, (char *) libaddr, dynamic_info,
+       tpnt = _dl_add_elf_hash_table(libname, lib_loadaddr, dynamic_info,
                        dynamic_addr, 0);
        tpnt->relro_addr = relro_addr;
        tpnt->relro_size = relro_size;
        tpnt->st_dev = st.st_dev;
        tpnt->st_ino = st.st_ino;
-       tpnt->ppnt = (ElfW(Phdr) *)(intptr_t) (tpnt->loadaddr + epnt->e_phoff);
+       tpnt->ppnt = (ElfW(Phdr) *) DL_RELOC_ADDR (epnt->e_phoff,
+                                                  tpnt->loadaddr);
        tpnt->n_phent = epnt->e_phnum;
 
        /*
@@ -625,9 +633,11 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
        }
 
        _dl_if_debug_dprint("\n\tfile='%s';  generating link map\n", libname);
-       _dl_if_debug_dprint("\t\tdynamic: %x  base: %x\n", dynamic_addr, libaddr);
+       _dl_if_debug_dprint("\t\tdynamic: %x  base: %x\n", dynamic_addr,
+                           DL_LOADADDR_BASE (libaddr));
        _dl_if_debug_dprint("\t\t  entry: %x  phdr: %x  phnum: %x\n\n",
-                       epnt->e_entry + libaddr, tpnt->ppnt, tpnt->n_phent);
+                           DL_RELOC_ADDR (epnt->e_entry, lib_loadaddr),
+                           tpnt->ppnt, tpnt->n_phent);
 
        _dl_munmap(header, _dl_pagesize);
 
@@ -801,7 +811,7 @@ char *_dl_strdup(const char *string)
        return retval;
 }
 
-void _dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[], void *debug_addr, ElfW(Addr) load_off)
+void _dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[], void *debug_addr, DL_LOADADDR_TYPE load_off)
 {
        __dl_parse_dynamic_info(dpnt, dynamic_info, debug_addr, load_off);
 }
@@ -818,7 +828,7 @@ __dl_iterate_phdr (int (*callback) (struct dl_phdr_info *info, size_t size, void
        int ret = 0;
 
        for (l = _dl_loaded_modules; l != NULL; l = l->next) {
-               info.dlpi_addr = l->loadaddr;
+               info.dlpi_addr = (ElfW(Addr))DL_LOADADDR_BASE (l->loadaddr);
                info.dlpi_name = l->libname;
                info.dlpi_phdr = l->ppnt;
                info.dlpi_phnum = l->n_phent;
index ed55031..85b2b40 100644 (file)
@@ -83,7 +83,7 @@ static inline Elf_Symndx _dl_elf_hash(const char *name)
  * externals properly.
  */
 struct elf_resolve *_dl_add_elf_hash_table(const char *libname,
-       char *loadaddr, unsigned long *dynamic_info, unsigned long dynamic_addr,
+       DL_LOADADDR_TYPE loadaddr, unsigned long *dynamic_info, unsigned long dynamic_addr,
        attribute_unused unsigned long dynamic_size)
 {
        Elf_Symndx *hash_addr;
@@ -117,7 +117,7 @@ struct elf_resolve *_dl_add_elf_hash_table(const char *libname,
                hash_addr += tpnt->nbucket;
                tpnt->chains = hash_addr;
        }
-       tpnt->loadaddr = (ElfW(Addr))loadaddr;
+       tpnt->loadaddr = loadaddr;
        for (i = 0; i < DYNAMIC_SIZE; i++)
                tpnt->dynamic_info[i] = dynamic_info[i];
        return tpnt;
@@ -163,8 +163,10 @@ char *_dl_find_hash(const char *name, struct dyn_elf *rpnt, struct elf_resolve *
 
                /* Avoid calling .urem here. */
                do_rem(hn, elf_hash_number, tpnt->nbucket);
-               symtab = (ElfW(Sym) *) (intptr_t) (tpnt->dynamic_info[DT_SYMTAB]);
-               strtab = (char *) (tpnt->dynamic_info[DT_STRTAB]);
+               symtab = (ElfW(Sym) *) DL_RELOC_ADDR (tpnt->dynamic_info[DT_SYMTAB],
+                                                     tpnt->loadaddr);
+               strtab = (char *) DL_RELOC_ADDR (tpnt->dynamic_info[DT_STRTAB],
+                                                tpnt->loadaddr);
 
                for (si = tpnt->elf_buckets[hn]; si != STN_UNDEF; si = tpnt->chains[si]) {
                        sym = &symtab[si];
@@ -184,11 +186,13 @@ char *_dl_find_hash(const char *name, struct dyn_elf *rpnt, struct elf_resolve *
 /* Perhaps we should support old style weak symbol handling
  * per what glibc does when you export LD_DYNAMIC_WEAK */
                                if (!weak_result)
-                                       weak_result = (char *)tpnt->loadaddr + sym->st_value;
+                                       weak_result = (char *) DL_RELOC_ADDR (sym->st_value,
+                                                                             tpnt->loadaddr);
                                break;
 #endif
                        case STB_GLOBAL:
-                               return (char*)tpnt->loadaddr + sym->st_value;
+                               return (char*) DL_RELOC_ADDR (sym->st_value,
+                                                             tpnt->loadaddr);
                        default:        /* Local symbols not handled here */
                                break;
                        }
index 96a7364..908ba7c 100644 (file)
@@ -114,7 +114,7 @@ static void * __attribute_used__ _dl_start(unsigned long args)
 {
        unsigned int argc;
        char **argv, **envp;
-       unsigned long load_addr;
+       DL_LOADADDR_TYPE load_addr;
        ElfW(Addr) got;
        unsigned long *aux_dat;
        ElfW(Ehdr) *header;
@@ -168,7 +168,7 @@ static void * __attribute_used__ _dl_start(unsigned long args)
         * (esp since SEND_STDERR() needs this on some platforms... */
        if (!auxvt[AT_BASE].a_un.a_val)
                auxvt[AT_BASE].a_un.a_val = elf_machine_load_address();
-       load_addr = auxvt[AT_BASE].a_un.a_val;
+       DL_INIT_LOADADDR_BOOT(load_addr, auxvt[AT_BASE].a_un.a_val);
        header = (ElfW(Ehdr) *) auxvt[AT_BASE].a_un.a_val;
 
        /* Check the ELF header to make sure everything looks ok.  */
@@ -186,14 +186,14 @@ static void * __attribute_used__ _dl_start(unsigned long args)
                _dl_exit(0);
        }
        SEND_STDERR_DEBUG("ELF header=");
-       SEND_ADDRESS_STDERR_DEBUG(load_addr, 1);
+       SEND_ADDRESS_STDERR_DEBUG(DL_LOADADDR_BASE (load_addr), 1);
 
        /* Locate the global offset table.  Since this code must be PIC
         * we can take advantage of the magic offset register, if we
         * happen to know what that is for this architecture.  If not,
         * we can always read stuff out of the ELF file to find it... */
        got = elf_machine_dynamic();
-       dpnt = (ElfW(Dyn) *) (got + load_addr);
+       dpnt = (ElfW(Dyn) *) DL_RELOC_ADDR (got, load_addr);
        SEND_STDERR_DEBUG("First Dynamic section entry=");
        SEND_ADDRESS_STDERR_DEBUG(dpnt, 1);
        _dl_memset(tpnt, 0, sizeof(struct elf_resolve));
@@ -259,9 +259,10 @@ static void * __attribute_used__ _dl_start(unsigned long args)
                                rel_addr += relative_count * sizeof(ELF_RELOC);
                        }
 
-                       rpnt = (ELF_RELOC *) (rel_addr + load_addr);
+                       rpnt = (ELF_RELOC *) DL_RELOC_ADDR (rel_addr, load_addr);
                        for (i = 0; i < rel_size; i += sizeof(ELF_RELOC), rpnt++) {
-                               reloc_addr = (unsigned long *) (load_addr + (unsigned long) rpnt->r_offset);
+                               reloc_addr = (unsigned long *) DL_RELOC_ADDR ((unsigned long) rpnt->r_offset,
+                                                                             load_addr);
                                symtab_index = ELF_R_SYM(rpnt->r_info);
                                symbol_addr = 0;
                                sym = NULL;
@@ -272,7 +273,7 @@ static void * __attribute_used__ _dl_start(unsigned long args)
                                        symtab = (ElfW(Sym) *) tpnt->dynamic_info[DT_SYMTAB];
                                        strtab = (char *) tpnt->dynamic_info[DT_STRTAB];
                                        sym = &symtab[symtab_index];
-                                       symbol_addr = load_addr + sym->st_value;
+                                       symbol_addr = (unsigned long) DL_RELOC_ADDR (sym->st_value, load_addr);
 
                                        SEND_STDERR_DEBUG("relocating symbol: ");
                                        SEND_STDERR_DEBUG(strtab + sym->st_name);
index 2234623..2afd977 100644 (file)
@@ -102,17 +102,18 @@ uintptr_t __guard attribute_relro;
 #endif
 
 static void _dl_run_array_forward(unsigned long array, unsigned long size,
-                                 ElfW(Addr) loadaddr)
+                                 DL_LOADADDR_TYPE loadaddr)
 {
        if (array != 0) {
                unsigned int j;
                unsigned int jm;
                ElfW(Addr) *addrs;
                jm = size / sizeof (ElfW(Addr));
-               addrs = (ElfW(Addr) *) (array + loadaddr);
+               addrs = (ElfW(Addr) *) DL_RELOC_ADDR (array, loadaddr);
                for (j = 0; j < jm; ++j) {
                        void (*dl_elf_func) (void);
-                       dl_elf_func = (void (*)(void)) (intptr_t) addrs[j];
+                       dl_elf_func = (void (*)(void)) DL_RELOC_ADDR (addrs[j],
+                                                                     loadaddr);
                        (*dl_elf_func) ();
                }
        }
@@ -136,11 +137,13 @@ void _dl_run_fini_array(struct elf_resolve *tpnt);
 void _dl_run_fini_array(struct elf_resolve *tpnt)
 {
        if (tpnt->dynamic_info[DT_FINI_ARRAY]) {
-               ElfW(Addr) *array = (ElfW(Addr) *) (tpnt->loadaddr + tpnt->dynamic_info[DT_FINI_ARRAY]);
+               ElfW(Addr) *array = (ElfW(Addr) *) DL_RELOC_ADDR (tpnt->dynamic_info[DT_FINI_ARRAY],
+                                                                 tpnt->loadaddr);
                unsigned int i = (tpnt->dynamic_info[DT_FINI_ARRAYSZ] / sizeof(ElfW(Addr)));
                while (i-- > 0) {
                        void (*dl_elf_func) (void);
-                       dl_elf_func = (void (*)(void)) (intptr_t) array[i];
+                       dl_elf_func = (void (*)(void)) DL_RELOC_ADDR (array[i],
+                                                                     tpnt->loadaddr);
                        (*dl_elf_func) ();
                }
        }
@@ -166,14 +169,15 @@ static void __attribute__ ((destructor)) __attribute_used__ _dl_fini(void)
                if (tpnt->dynamic_info[DT_FINI]) {
                        void (*dl_elf_func) (void);
 
-                       dl_elf_func = (void (*)(void)) (intptr_t) (tpnt->loadaddr + tpnt->dynamic_info[DT_FINI]);
+                       dl_elf_func = (void (*)(void)) DL_RELOC_ADDR (tpnt->dynamic_info[DT_FINI],
+                                                                     tpnt->loadaddr);
                        _dl_if_debug_dprint("\ncalling FINI: %s\n\n", tpnt->libname);
                        (*dl_elf_func) ();
                }
        }
 }
 
-void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr,
+void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,
                          ElfW(auxv_t) auxvt[AT_EGID + 1], char **envp,
                          char **argv)
 {
@@ -295,13 +299,13 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr,
 
                for (idx = 0; idx < auxvt[AT_PHNUM].a_un.a_val; idx++, phdr++)
                        if (phdr->p_type == PT_PHDR) {
-                               app_tpnt->loadaddr = (ElfW(Addr)) (auxvt[AT_PHDR].a_un.a_val - phdr->p_vaddr);
+                               DL_INIT_LOADADDR_PROG (app_tpnt->loadaddr, (ElfW(Addr)) (auxvt[AT_PHDR].a_un.a_val - ppnt->p_vaddr));
                                break;
                        }
 
-               if (app_tpnt->loadaddr)
+               if (DL_LOADADDR_BASE (app_tpnt->loadaddr))
                        _dl_debug_early("Position Independent Executable: "
-                                       "app_tpnt->loadaddr=%x\n", app_tpnt->loadaddr);
+                                       "app_tpnt->loadaddr=%x\n", DL_LOADADDR_BASE (app_tpnt->loadaddr));
        }
 
        /*
@@ -318,7 +322,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr,
                        relro_size = ppnt->p_memsz;
                }
                if (ppnt->p_type == PT_DYNAMIC) {
-                       dpnt = (ElfW(Dyn) *) (ppnt->p_vaddr + app_tpnt->loadaddr);
+                       dpnt = (ElfW(Dyn) *) DL_RELOC_ADDR (ppnt->p_vaddr, app_tpnt->loadaddr);
                        _dl_parse_dynamic_info(dpnt, app_tpnt->dynamic_info, debug_addr, app_tpnt->loadaddr);
 #ifndef __FORCE_SHAREABLE_TEXT_SEGMENTS__
                        /* Ugly, ugly.  We need to call mprotect to change the
@@ -331,11 +335,11 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr,
                        if (app_tpnt->dynamic_info[DT_TEXTREL]) {
                                ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_val;
                                for (i = 0; i < auxvt[AT_PHNUM].a_un.a_val; i++, ppnt++) {
-                                       if (ppnt->p_type == PT_LOAD && !(ppnt->p_flags & PF_W))
-                                               _dl_mprotect((void *) ((ppnt->p_vaddr + app_tpnt->loadaddr) & PAGE_ALIGN),
-                                                            ((ppnt->p_vaddr + app_tpnt->loadaddr) & ADDR_ALIGN) +
-                                                            (unsigned long) ppnt->p_filesz,
+                                       if (ppnt->p_type == PT_LOAD && !(ppnt->p_flags & PF_W)) {
+                                               void *base =  DL_RELOC_ADDR (ppnt->p_vaddr & PAGE_ALIGN, app_tpnt->loadaddr);
+                                               _dl_mprotect(base, (ppnt->p_vaddr & ADDR_ALIGN) + (unsigned long) ppnt->p_filesz,
                                                             PROT_READ | PROT_WRITE | PROT_EXEC);
+                                       }
                                }
                        }
 #endif
@@ -346,8 +350,10 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr,
                                continue;
 #endif
                        /* OK, we have what we need - slip this one into the list. */
-                       app_tpnt = _dl_add_elf_hash_table(_dl_progname, (char *)app_tpnt->loadaddr,
-                                       app_tpnt->dynamic_info, ppnt->p_vaddr + app_tpnt->loadaddr, ppnt->p_filesz);
+                       app_tpnt = _dl_add_elf_hash_table(_dl_progname, app_tpnt->loadaddr,
+                                                         app_tpnt->dynamic_info,
+                                                         (unsigned long) DL_RELOC_ADDR (ppnt->p_vaddr, app_tpnt->loadaddr),
+                                                         ppnt->p_filesz);
                        _dl_loaded_modules->libtype = elf_executable;
                        _dl_loaded_modules->ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_val;
                        _dl_loaded_modules->n_phent = auxvt[AT_PHNUM].a_un.a_val;
@@ -368,7 +374,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr,
                if (ppnt->p_type == PT_INTERP) {
                        char *ptmp;
 
-                       tpnt->libname = (char *) ppnt->p_vaddr + app_tpnt->loadaddr;
+                       tpnt->libname = (char *) DL_RELOC_ADDR (ppnt->p_vaddr, app_tpnt->loadaddr);
 
                        /* Store the path where the shared lib loader was found
                         * for later use
@@ -378,7 +384,8 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr,
                        if (ptmp != _dl_ldsopath)
                                *ptmp = '\0';
 
-                       _dl_debug_early("Lib Loader: (%x) %s\n", tpnt->loadaddr, tpnt->libname);
+                       _dl_debug_early("Lib Loader: (%x) %s\n", (unsigned) DL_LOADADDR_BASE (tpnt->loadaddr),
+                                       tpnt->libname);
                }
        }
        app_tpnt->relro_addr = relro_addr;
@@ -450,7 +457,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr,
         */
        debug_addr->r_map = (struct link_map *) _dl_loaded_modules;
        debug_addr->r_version = 1;
-       debug_addr->r_ldbase = load_addr;
+       debug_addr->r_ldbase = (ElfW(Addr)) DL_LOADADDR_BASE (load_addr);
        debug_addr->r_brk = (unsigned long) &_dl_debug_state;
        _dl_debug_addr = debug_addr;
 
@@ -497,7 +504,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr,
                                } else {
                                        tpnt1->rtld_flags = unlazy | RTLD_GLOBAL;
 
-                                       _dl_debug_early("Loading: (%x) %s\n", tpnt1->loadaddr, tpnt1->libname);
+                                       _dl_debug_early("Loading: (%x) %s\n", (unsigned) DL_LOADADDR_BASE (tpnt1->loadaddr), tpnt1->libname);
 
 #ifdef __LDSO_LDD_SUPPORT__
                                        if (trace_loaded_objects &&
@@ -509,7 +516,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr,
                                                 */
                                                if (_dl_strcmp(_dl_progname, str) != 0)
                                                        _dl_dprintf(1, "\t%s => %s (%x)\n", str, tpnt1->libname,
-                                                                   tpnt1->loadaddr);
+                                                                   (unsigned) DL_LOADADDR_BASE (tpnt1->loadaddr));
                                        }
 #endif
                                }
@@ -588,14 +595,14 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr,
                        } else {
                                tpnt1->rtld_flags = unlazy | RTLD_GLOBAL;
 
-                               _dl_debug_early("Loading: (%x) %s\n", tpnt1->loadaddr, tpnt1->libname);
+                               _dl_debug_early("Loading: (%x) %s\n", (unsigned) DL_LOADADDR_BASE (tpnt1->loadaddr), tpnt1->libname);
 
 #ifdef __LDSO_LDD_SUPPORT__
                                if (trace_loaded_objects &&
                                    tpnt1->usage_count == 1) {
                                        _dl_dprintf(1, "\t%s => %s (%x)\n",
                                                    cp2, tpnt1->libname,
-                                                   (unsigned)tpnt1->loadaddr);
+                                                   (unsigned) DL_LOADADDR_BASE (tpnt1->loadaddr));
                                }
 #endif
                        }
@@ -647,14 +654,14 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr,
 
                                tpnt1->rtld_flags = unlazy | RTLD_GLOBAL;
 
-                               _dl_debug_early("Loading: (%x) %s\n", tpnt1->loadaddr, tpnt1->libname);
+                               _dl_debug_early("Loading: (%x) %s\n", (unsigned) DL_LOADADDR_BASE (tpnt1->loadaddr), tpnt1->libname);
 
 #ifdef __LDSO_LDD_SUPPORT__
                                if (trace_loaded_objects &&
                                    tpnt1->usage_count == 1) {
                                        _dl_dprintf(1, "\t%s => %s (%x)\n",
                                                    lpntstr, tpnt1->libname,
-                                                   (unsigned)tpnt1->loadaddr);
+                                                   (unsigned) DL_LOADADDR_BASE (tpnt1->loadaddr));
                                }
 #endif
                        }
@@ -715,10 +722,10 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr,
         */
        if (tpnt) {
                ElfW(Ehdr) *epnt = (ElfW(Ehdr) *) auxvt[AT_BASE].a_un.a_val;
-               ElfW(Phdr) *myppnt = (ElfW(Phdr) *) (load_addr + epnt->e_phoff);
+               ElfW(Phdr) *myppnt = (ElfW(Phdr) *) DL_RELOC_ADDR (epnt->e_phoff, load_addr);
                int j;
 
-               tpnt = _dl_add_elf_hash_table(tpnt->libname, (char *)load_addr,
+               tpnt = _dl_add_elf_hash_table(tpnt->libname, load_addr,
                                              tpnt->dynamic_info,
                                              (unsigned long)tpnt->dynamic_addr,
                                              0);
@@ -765,7 +772,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr,
        if (trace_loaded_objects) {
                _dl_dprintf(1, "\t%s => %s (%x)\n",
                            rpnt->dyn->libname + _dl_strlen(_dl_ldsopath) + 1,
-                           rpnt->dyn->libname, rpnt->dyn->loadaddr);
+                           rpnt->dyn->libname, (unsigned) DL_LOADADDR_BASE (rpnt->dyn->loadaddr));
                _dl_exit(0);
        }
 #endif
@@ -817,8 +824,10 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr,
                for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {
                        for (myppnt = tpnt->ppnt, j = 0; j < tpnt->n_phent; j++, myppnt++) {
                                if (myppnt->p_type == PT_LOAD && !(myppnt->p_flags & PF_W) && tpnt->dynamic_info[DT_TEXTREL]) {
-                                       _dl_mprotect((void *) (tpnt->loadaddr + (myppnt->p_vaddr & PAGE_ALIGN)),
-                                                       (myppnt->p_vaddr & ADDR_ALIGN) + (unsigned long) myppnt->p_filesz, LXFLAGS(myppnt->p_flags));
+                                       void *base = DL_RELOC_ADDR (myppnt->p_vaddr & PAGE_ALIGN, tpnt->loadaddr);
+                                       _dl_mprotect(base,
+                                                    (myppnt->p_vaddr & ADDR_ALIGN) + (unsigned long) myppnt->p_filesz,
+                                                    LXFLAGS(myppnt->p_flags));
                                }
                        }
                }
@@ -846,7 +855,7 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr,
                if (tpnt->dynamic_info[DT_INIT]) {
                        void (*dl_elf_func) (void);
 
-                       dl_elf_func = (void (*)(void)) (intptr_t) (tpnt->loadaddr + tpnt->dynamic_info[DT_INIT]);
+                       dl_elf_func = (void (*)(void)) DL_RELOC_ADDR (tpnt->dynamic_info[DT_INIT], tpnt->loadaddr);
 
                        _dl_if_debug_dprint("calling INIT: %s\n\n", tpnt->libname);
 
index 3222308..b533a2d 100644 (file)
@@ -175,8 +175,7 @@ void *dlopen(const char *libname, int flag)
                tfrom = NULL;
                for (dpnt = _dl_symbol_tables; dpnt; dpnt = dpnt->next) {
                        tpnt = dpnt->dyn;
-                       if (tpnt->loadaddr < from
-                                       && (tfrom == NULL || tfrom->loadaddr < tpnt->loadaddr))
+                       if (DL_ADDR_IN_LOADADDR (from, tpnt, tfrom))
                                tfrom = tpnt;
                }
        }
@@ -378,7 +377,7 @@ void *dlopen(const char *libname, int flag)
 
                if (tpnt->dynamic_info[DT_INIT]) {
                        void (*dl_elf_func) (void);
-                       dl_elf_func = (void (*)(void)) (tpnt->loadaddr + tpnt->dynamic_info[DT_INIT]);
+                       dl_elf_func = (void (*)(void)) DL_RELOC_ADDR (tpnt->dynamic_info[DT_INIT], tpnt->loadaddr);
                        if (dl_elf_func && *dl_elf_func != NULL) {
                                _dl_if_debug_print("running ctors for library %s at '%p'\n",
                                                tpnt->libname, dl_elf_func);
@@ -436,8 +435,7 @@ void *dlsym(void *vhandle, const char *name)
                tfrom = NULL;
                for (rpnt = _dl_symbol_tables; rpnt; rpnt = rpnt->next) {
                        tpnt = rpnt->dyn;
-                       if (tpnt->loadaddr < from
-                                       && (tfrom == NULL || tfrom->loadaddr < tpnt->loadaddr)) {
+                       if (DL_ADDR_IN_LOADADDR (from, tpnt, tfrom)) {
                                tfrom = tpnt;
                                handle = rpnt->next;
                        }
@@ -512,7 +510,7 @@ static int do_dlclose(void *vhandle, int need_fini)
 #endif
 
                                if (tpnt->dynamic_info[DT_FINI]) {
-                                       dl_elf_fini = (int (*)(void)) (tpnt->loadaddr + tpnt->dynamic_info[DT_FINI]);
+                                   dl_elf_fini = (int (*)(void)) DL_RELOC_ADDR (tpnt->dynamic_info[DT_FINI], tpnt->loadaddr);
                                        _dl_if_debug_print("running dtors for library %s at '%p'\n",
                                                        tpnt->libname, dl_elf_fini);
                                        (*dl_elf_fini) ();
@@ -622,7 +620,7 @@ int dlinfo(void)
        /* First start with a complete list of all of the loaded files. */
        for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {
                fprintf(stderr, "\t%p %p %p %s %d %s\n",
-                       tpnt->loadaddr, tpnt, tpnt->symbol_scope,
+                       DL_LOADADDR_BASE (tpnt->loadaddr), tpnt, tpnt->symbol_scope,
                        type[tpnt->libtype],
                        tpnt->usage_count, tpnt->libname);
        }
@@ -662,12 +660,10 @@ int dladdr(const void *__address, Dl_info * __info)
                tpnt = rpnt;
 #if 0
                fprintf(stderr, "Module \"%s\" at %p\n",
-                               tpnt->libname, tpnt->loadaddr);
+                       tpnt->libname, DL_LOADADDR_BASE (tpnt->loadaddr));
 #endif
-               if (tpnt->loadaddr < (ElfW(Addr)) __address
-                               && (pelf == NULL || pelf->loadaddr < tpnt->loadaddr)) {
+               if (DL_ADDR_IN_LOADADDR ((ElfW(Addr)) __address,  tpnt, pelf))
                        pelf = tpnt;
-               }
        }
 
        if (!pelf) {
@@ -693,7 +689,7 @@ int dladdr(const void *__address, Dl_info * __info)
                        for (si = pelf->elf_buckets[hn]; si; si = pelf->chains[si]) {
                                ElfW(Addr) symbol_addr;
 
-                               symbol_addr = pelf->loadaddr + symtab[si].st_value;
+                               symbol_addr = (ElfW(Addr)) DL_RELOC_ADDR (symtab[si].st_value, pelf->loadaddr);
                                if (symbol_addr <= (ElfW(Addr))__address && (!sf || sa < symbol_addr)) {
                                        sa = symbol_addr;
                                        sn = si;
@@ -708,7 +704,7 @@ int dladdr(const void *__address, Dl_info * __info)
 
                if (sf) {
                        __info->dli_fname = pelf->libname;
-                       __info->dli_fbase = (void *)pelf->loadaddr;
+                       __info->dli_fbase = DL_LOADADDR_BASE (pelf->loadaddr);
                        __info->dli_sname = strtab + symtab[sn].st_name;
                        __info->dli_saddr = (void *)sa;
                }