Go to:
Gentoo Home
Documentation
Forums
Lists
Bugs
Planet
Store
Wiki
Get Gentoo!
Gentoo's Bugzilla – Attachment 45006 Details for
Bug 72343
all packages which use libsdl break on configure (~x86 system)
Home
|
New
–
[Ex]
|
Browse
|
Search
|
Privacy Policy
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
glibc cvs diff from 1014
glibc-20041013.diff (text/plain), 90.42 KB, created by
Hanno Zysik (geki)
on 2004-11-30 10:46:09 UTC
(
hide
)
Description:
glibc cvs diff from 1014
Filename:
MIME Type:
Creator:
Hanno Zysik (geki)
Created:
2004-11-30 10:46:09 UTC
Size:
90.42 KB
patch
obsolete
>--- libc/elf/rtld.c 2004/10/06 03:17:28 1.333 >+++ libc/elf/rtld.c 2004/10/14 02:07:44 1.334 >@@ -269,6 +269,7 @@ > GL(dl_rtld_map).l_mach = info->l.l_mach; > #endif > _dl_setup_hash (&GL(dl_rtld_map)); >+ GL(dl_rtld_map).l_real = &GL(dl_rtld_map); > GL(dl_rtld_map).l_opencount = 1; > GL(dl_rtld_map).l_map_start = (ElfW(Addr)) _begin; > GL(dl_rtld_map).l_map_end = (ElfW(Addr)) _end; >@@ -585,14 +586,16 @@ > { > struct map_args *args = (struct map_args *) a; > args->map = _dl_map_object (args->loader, args->str, >- args->is_preloaded, lt_library, 0, args->mode); >+ args->is_preloaded, lt_library, 0, args->mode, >+ LM_ID_BASE); > } > > static void > version_check_doit (void *a) > { > struct version_check_args *args = (struct version_check_args *) a; >- if (_dl_check_all_versions (GL(dl_loaded), 1, args->dotrace) && args->doexit) >+ if (_dl_check_all_versions (GL(dl_ns)[LM_ID_BASE]._ns_loaded, 1, >+ args->dotrace) && args->doexit) > /* We cannot start the application. Abort now. */ > _exit (1); > } >@@ -601,11 +604,12 @@ > static inline struct link_map * > find_needed (const char *name) > { >- unsigned int n = GL(dl_loaded)->l_searchlist.r_nlist; >+ struct r_scope_elem *scope = &GL(dl_ns)[LM_ID_BASE]._ns_loaded->l_searchlist; >+ unsigned int n = scope->r_nlist; > > while (n-- > 0) >- if (_dl_name_match_p (name, GL(dl_loaded)->l_searchlist.r_list[n])) >- return GL(dl_loaded)->l_searchlist.r_list[n]; >+ if (_dl_name_match_p (name, scope->r_list[n])) >+ return scope->r_list[n]; > > /* Should never happen. */ > return NULL; >@@ -685,6 +689,7 @@ > enum mode mode; > struct link_map **preloads; > unsigned int npreloads; >+ struct link_map *main_map; > size_t file_size; > char *file; > bool has_interp = false; >@@ -860,31 +865,35 @@ > { > HP_TIMING_NOW (start); > _dl_map_object (NULL, rtld_progname, 0, lt_library, 0, >- __RTLD_OPENEXEC); >+ __RTLD_OPENEXEC, LM_ID_BASE); > HP_TIMING_NOW (stop); > > HP_TIMING_DIFF (load_time, start, stop); > } > >- phdr = GL(dl_loaded)->l_phdr; >- phnum = GL(dl_loaded)->l_phnum; >+ /* Now the map for the main executable is available. */ >+ main_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded; >+ >+ phdr = main_map->l_phdr; >+ phnum = main_map->l_phnum; > /* We overwrite here a pointer to a malloc()ed string. But since > the malloc() implementation used at this point is the dummy > implementations which has no real free() function it does not > makes sense to free the old string first. */ >- GL(dl_loaded)->l_name = (char *) ""; >- *user_entry = GL(dl_loaded)->l_entry; >+ main_map->l_name = (char *) ""; >+ *user_entry = main_map->l_entry; > } > else > { > /* Create a link_map for the executable itself. > This will be what dlopen on "" returns. */ >- _dl_new_object ((char *) "", "", lt_executable, NULL, 0); >- if (GL(dl_loaded) == NULL) >+ _dl_new_object ((char *) "", "", lt_executable, NULL, 0, LM_ID_BASE); >+ main_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded; >+ if (main_map == NULL) > _dl_fatal_printf ("cannot allocate memory for link map\n"); >- GL(dl_loaded)->l_phdr = phdr; >- GL(dl_loaded)->l_phnum = phnum; >- GL(dl_loaded)->l_entry = *user_entry; >+ main_map->l_phdr = phdr; >+ main_map->l_phnum = phnum; >+ main_map->l_entry = *user_entry; > > /* At this point we are in a bit of trouble. We would have to > fill in the values for l_dev and l_ino. But in general we >@@ -905,12 +914,14 @@ > information for the program. */ > } > >- GL(dl_loaded)->l_map_end = 0; >- GL(dl_loaded)->l_text_end = 0; >+ main_map->l_map_end = 0; >+ main_map->l_text_end = 0; > /* Perhaps the executable has no PT_LOAD header entries at all. */ >- GL(dl_loaded)->l_map_start = ~0; >+ main_map->l_map_start = ~0; > /* We opened the file, account for it. */ >- ++GL(dl_loaded)->l_opencount; >+ ++main_map->l_opencount; >+ /* And it was opened directly. */ >+ ++main_map->l_direct_opencount; > > /* Scan the program header table for the dynamic section. */ > for (ph = phdr; ph < &phdr[phnum]; ++ph) >@@ -918,12 +929,12 @@ > { > case PT_PHDR: > /* Find out the load address. */ >- GL(dl_loaded)->l_addr = (ElfW(Addr)) phdr - ph->p_vaddr; >+ main_map->l_addr = (ElfW(Addr)) phdr - ph->p_vaddr; > break; > case PT_DYNAMIC: > /* This tells us where to find the dynamic section, > which tells us everything we need to do. */ >- GL(dl_loaded)->l_ld = (void *) GL(dl_loaded)->l_addr + ph->p_vaddr; >+ main_map->l_ld = (void *) main_map->l_addr + ph->p_vaddr; > break; > case PT_INTERP: > /* This "interpreter segment" was used by the program loader to >@@ -932,7 +943,7 @@ > dlopen call or DT_NEEDED entry, for something that wants to link > against the dynamic linker as a shared library, will know that > the shared object is already loaded. */ >- _dl_rtld_libname.name = ((const char *) GL(dl_loaded)->l_addr >+ _dl_rtld_libname.name = ((const char *) main_map->l_addr > + ph->p_vaddr); > /* _dl_rtld_libname.next = NULL; Already zero. */ > GL(dl_rtld_map).l_libname = &_dl_rtld_libname; >@@ -968,17 +979,16 @@ > ElfW(Addr) allocend; > > /* Remember where the main program starts in memory. */ >- mapstart = (GL(dl_loaded)->l_addr >- + (ph->p_vaddr & ~(ph->p_align - 1))); >- if (GL(dl_loaded)->l_map_start > mapstart) >- GL(dl_loaded)->l_map_start = mapstart; >+ mapstart = (main_map->l_addr + (ph->p_vaddr & ~(ph->p_align - 1))); >+ if (main_map->l_map_start > mapstart) >+ main_map->l_map_start = mapstart; > > /* Also where it ends. */ >- allocend = GL(dl_loaded)->l_addr + ph->p_vaddr + ph->p_memsz; >- if (GL(dl_loaded)->l_map_end < allocend) >- GL(dl_loaded)->l_map_end = allocend; >- if ((ph->p_flags & PF_X) && allocend > GL(dl_loaded)->l_text_end) >- GL(dl_loaded)->l_text_end = allocend; >+ allocend = main_map->l_addr + ph->p_vaddr + ph->p_memsz; >+ if (main_map->l_map_end < allocend) >+ main_map->l_map_end = allocend; >+ if ((ph->p_flags & PF_X) && allocend > main_map->l_text_end) >+ main_map->l_text_end = allocend; > } > break; > #ifdef USE_TLS >@@ -989,18 +999,18 @@ > here since we read the PT_TLS entry already in > _dl_start_final. But the result is repeatable so do not > check for this special but unimportant case. */ >- GL(dl_loaded)->l_tls_blocksize = ph->p_memsz; >- GL(dl_loaded)->l_tls_align = ph->p_align; >+ main_map->l_tls_blocksize = ph->p_memsz; >+ main_map->l_tls_align = ph->p_align; > if (ph->p_align == 0) >- GL(dl_loaded)->l_tls_firstbyte_offset = 0; >+ main_map->l_tls_firstbyte_offset = 0; > else >- GL(dl_loaded)->l_tls_firstbyte_offset = (ph->p_vaddr >- & (ph->p_align - 1)); >- GL(dl_loaded)->l_tls_initimage_size = ph->p_filesz; >- GL(dl_loaded)->l_tls_initimage = (void *) ph->p_vaddr; >+ main_map->l_tls_firstbyte_offset = (ph->p_vaddr >+ & (ph->p_align - 1)); >+ main_map->l_tls_initimage_size = ph->p_filesz; >+ main_map->l_tls_initimage = (void *) ph->p_vaddr; > > /* This image gets the ID one. */ >- GL(dl_tls_max_dtv_idx) = GL(dl_loaded)->l_tls_modid = 1; >+ GL(dl_tls_max_dtv_idx) = main_map->l_tls_modid = 1; > } > break; > #endif >@@ -1009,21 +1019,21 @@ > break; > > case PT_GNU_RELRO: >- GL(dl_loaded)->l_relro_addr = ph->p_vaddr; >- GL(dl_loaded)->l_relro_size = ph->p_memsz; >+ main_map->l_relro_addr = ph->p_vaddr; >+ main_map->l_relro_size = ph->p_memsz; > break; > } > #ifdef USE_TLS > /* Adjust the address of the TLS initialization image in case > the executable is actually an ET_DYN object. */ >- if (GL(dl_loaded)->l_tls_initimage != NULL) >- GL(dl_loaded)->l_tls_initimage >- = (char *) GL(dl_loaded)->l_tls_initimage + GL(dl_loaded)->l_addr; >-#endif >- if (! GL(dl_loaded)->l_map_end) >- GL(dl_loaded)->l_map_end = ~0; >- if (! GL(dl_loaded)->l_text_end) >- GL(dl_loaded)->l_text_end = ~0; >+ if (main_map->l_tls_initimage != NULL) >+ main_map->l_tls_initimage >+ = (char *) main_map->l_tls_initimage + main_map->l_addr; >+#endif >+ if (! main_map->l_map_end) >+ main_map->l_map_end = ~0; >+ if (! main_map->l_text_end) >+ main_map->l_text_end = ~0; > if (! GL(dl_rtld_map).l_libname && GL(dl_rtld_map).l_name) > { > /* We were invoked directly, so the program might not have a >@@ -1038,9 +1048,9 @@ > if (! rtld_is_main) > { > /* Extract the contents of the dynamic section for easy access. */ >- elf_get_dynamic_info (GL(dl_loaded), NULL); >+ elf_get_dynamic_info (main_map, NULL); > /* Set up our cache of pointers into the hash table. */ >- _dl_setup_hash (GL(dl_loaded)); >+ _dl_setup_hash (main_map); > } > > if (__builtin_expect (mode, normal) == verify) >@@ -1049,7 +1059,7 @@ > executable using us as the program interpreter. Exit with an > error if we were not able to load the binary or no interpreter > is specified (i.e., this is no dynamically linked binary. */ >- if (GL(dl_loaded)->l_ld == NULL) >+ if (main_map->l_ld == NULL) > _exit (1); > > /* We allow here some platform specific code. */ >@@ -1072,16 +1082,16 @@ > found by the PT_INTERP name. */ > GL(dl_rtld_map).l_name = (char *) GL(dl_rtld_map).l_libname->name; > GL(dl_rtld_map).l_type = lt_library; >- GL(dl_loaded)->l_next = &GL(dl_rtld_map); >- GL(dl_rtld_map).l_prev = GL(dl_loaded); >- ++GL(dl_nloaded); >+ main_map->l_next = &GL(dl_rtld_map); >+ GL(dl_rtld_map).l_prev = main_map; >+ ++GL(dl_ns)[LM_ID_BASE]._ns_nloaded; > ++GL(dl_load_adds); > > /* If LD_USE_LOAD_BIAS env variable has not been seen, default > to not using bias for non-prelinked PIEs and libraries > and using it for executables or prelinked PIEs or libraries. */ > if (GLRO(dl_use_load_bias) == (ElfW(Addr)) -2) >- GLRO(dl_use_load_bias) = (GL(dl_loaded)->l_addr == 0) ? -1 : 0; >+ GLRO(dl_use_load_bias) = main_map->l_addr == 0 ? -1 : 0; > > /* Set up the program header information for the dynamic linker > itself. It is needed in the dl_iterate_phdr() callbacks. */ >@@ -1125,8 +1135,9 @@ > && (__builtin_expect (! INTUSE(__libc_enable_secure), 1) > || strchr (p, '/') == NULL)) > { >- struct link_map *new_map = _dl_map_object (GL(dl_loaded), p, 1, >- lt_library, 0, 0); >+ struct link_map *new_map = _dl_map_object (main_map, p, 1, >+ lt_library, 0, 0, >+ LM_ID_BASE); > if (++new_map->l_opencount == 1) > /* It is no duplicate. */ > ++npreloads; >@@ -1208,7 +1219,7 @@ > struct map_args args; > > args.str = p; >- args.loader = GL(dl_loaded); >+ args.loader = main_map; > args.is_preloaded = 1; > args.mode = 0; > >@@ -1231,8 +1242,9 @@ > if (problem != NULL) > { > char *p = strndupa (problem, file_size - (problem - file)); >- struct link_map *new_map = _dl_map_object (GL(dl_loaded), p, 1, >- lt_library, 0, 0); >+ struct link_map *new_map = _dl_map_object (main_map, p, 1, >+ lt_library, 0, 0, >+ LM_ID_BASE); > if (++new_map->l_opencount == 1) > /* It is no duplicate. */ > ++npreloads; >@@ -1272,7 +1284,7 @@ > We just want our data structures to describe it as if we had just > mapped and relocated it normally. */ > struct link_map *l = _dl_new_object ((char *) "", "", lt_library, NULL, >- 0); >+ 0, LM_ID_BASE); > if (__builtin_expect (l != NULL, 1)) > { > static ElfW(Dyn) dyn_temp[DL_RO_DYN_TEMP_CNT] attribute_relro; >@@ -1337,18 +1349,18 @@ > specified some libraries to load, these are inserted before the actual > dependencies in the executable's searchlist for symbol resolution. */ > HP_TIMING_NOW (start); >- _dl_map_object_deps (GL(dl_loaded), preloads, npreloads, mode == trace, 0); >+ _dl_map_object_deps (main_map, preloads, npreloads, mode == trace, 0); > HP_TIMING_NOW (stop); > HP_TIMING_DIFF (diff, start, stop); > HP_TIMING_ACCUM_NT (load_time, diff); > > /* Mark all objects as being in the global scope and set the open > counter. */ >- for (i = GL(dl_loaded)->l_searchlist.r_nlist; i > 0; ) >+ for (i = main_map->l_searchlist.r_nlist; i > 0; ) > { > --i; >- GL(dl_loaded)->l_searchlist.r_list[i]->l_global = 1; >- ++GL(dl_loaded)->l_searchlist.r_list[i]->l_opencount; >+ main_map->l_searchlist.r_list[i]->l_global = 1; >+ ++main_map->l_searchlist.r_list[i]->l_opencount; > } > > #ifndef MAP_ANON >@@ -1369,13 +1381,13 @@ > chain in symbol search order because gdb uses the chain's order as > its symbol search order. */ > i = 1; >- while (GL(dl_loaded)->l_searchlist.r_list[i] != &GL(dl_rtld_map)) >+ while (main_map->l_searchlist.r_list[i] != &GL(dl_rtld_map)) > ++i; >- GL(dl_rtld_map).l_prev = GL(dl_loaded)->l_searchlist.r_list[i - 1]; >+ GL(dl_rtld_map).l_prev = main_map->l_searchlist.r_list[i - 1]; > if (__builtin_expect (mode, normal) == normal) > { >- GL(dl_rtld_map).l_next = (i + 1 < GL(dl_loaded)->l_searchlist.r_nlist >- ? GL(dl_loaded)->l_searchlist.r_list[i + 1] >+ GL(dl_rtld_map).l_next = (i + 1 < main_map->l_searchlist.r_nlist >+ ? main_map->l_searchlist.r_list[i + 1] > : NULL); > #ifdef NEED_DL_SYSINFO > if (sysinfo_map != NULL >@@ -1459,7 +1471,7 @@ > GL(dl_tls_dtv_slotinfo_list)->next = NULL; > > /* Fill in the information from the loaded modules. */ >- for (l = GL(dl_loaded), i = 0; l != NULL; l = l->l_next) >+ for (l = main_map, i = 0; l != NULL; l = l->l_next) > if (l->l_tls_blocksize != 0) > /* This is a module with TLS data. Store the map reference. > The generation counter is zero. */ >@@ -1495,7 +1507,7 @@ > > if (GLRO(dl_debug_mask) & DL_DEBUG_PRELINK) > { >- struct r_scope_elem *scope = &GL(dl_loaded)->l_searchlist; >+ struct r_scope_elem *scope = &main_map->l_searchlist; > > for (i = 0; i < scope->r_nlist; i++) > { >@@ -1531,7 +1543,7 @@ > /* Look through the dependencies of the main executable > and determine which of them is not actually > required. */ >- struct link_map *l = GL(dl_loaded); >+ struct link_map *l = main_map; > > /* Relocate the main executable. */ > struct relocate_args args = { .l = l, .lazy = GLRO(dl_lazy) }; >@@ -1539,7 +1551,7 @@ > > /* This loop depends on the dependencies of the executable to > correspond in number and order to the DT_NEEDED entries. */ >- ElfW(Dyn) *dyn = GL(dl_loaded)->l_ld; >+ ElfW(Dyn) *dyn = main_map->l_ld; > bool first = true; > while (dyn->d_tag != DT_NULL) > { >@@ -1564,11 +1576,11 @@ > > _exit (first != true); > } >- else if (! GL(dl_loaded)->l_info[DT_NEEDED]) >+ else if (! main_map->l_info[DT_NEEDED]) > _dl_printf ("\tstatically linked\n"); > else > { >- for (l = GL(dl_loaded)->l_next; l; l = l->l_next) >+ for (l = main_map->l_next; l; l = l->l_next) > if (l->l_faked) > /* The library was not found. */ > _dl_printf ("\t%s => not found\n", l->l_libname->name); >@@ -1589,8 +1601,8 @@ > ElfW(Addr) loadbase; > lookup_t result; > >- result = _dl_lookup_symbol_x (INTUSE(_dl_argv)[i], GL(dl_loaded), >- &ref, GL(dl_loaded)->l_scope, NULL, >+ result = _dl_lookup_symbol_x (INTUSE(_dl_argv)[i], main_map, >+ &ref, main_map->l_scope, NULL, > ELF_RTYPE_CLASS_PLT, > DL_LOOKUP_ADD_DEPENDENCY, NULL); > >@@ -1613,7 +1625,7 @@ > > args.lazy = GLRO(dl_lazy); > >- l = GL(dl_loaded); >+ l = main_map; > while (l->l_next) > l = l->l_next; > do >@@ -1629,7 +1641,7 @@ > > if ((GLRO(dl_debug_mask) & DL_DEBUG_PRELINK) > && GL(dl_rtld_map).l_opencount > 1) >- _dl_relocate_object (&GL(dl_rtld_map), GL(dl_loaded)->l_scope, >+ _dl_relocate_object (&GL(dl_rtld_map), main_map->l_scope, > 0, 0); > } > >@@ -1639,9 +1651,9 @@ > /* Print more information. This means here, print information > about the versions needed. */ > int first = 1; >- struct link_map *map = GL(dl_loaded); >+ struct link_map *map; > >- for (map = GL(dl_loaded); map != NULL; map = map->l_next) >+ for (map = main_map; map != NULL; map = map->l_next) > { > const char *strtab; > ElfW(Dyn) *dyn = map->l_info[VERNEEDTAG]; >@@ -1709,28 +1721,27 @@ > _exit (0); > } > >- if (GL(dl_loaded)->l_info [ADDRIDX (DT_GNU_LIBLIST)] >+ if (main_map->l_info[ADDRIDX (DT_GNU_LIBLIST)] > && ! __builtin_expect (GLRO(dl_profile) != NULL, 0)) > { > ElfW(Lib) *liblist, *liblistend; > struct link_map **r_list, **r_listend, *l; >- const char *strtab = (const void *) D_PTR (GL(dl_loaded), >- l_info[DT_STRTAB]); >+ const char *strtab = (const void *) D_PTR (main_map, l_info[DT_STRTAB]); > >- assert (GL(dl_loaded)->l_info [VALIDX (DT_GNU_LIBLISTSZ)] != NULL); >+ assert (main_map->l_info[VALIDX (DT_GNU_LIBLISTSZ)] != NULL); > liblist = (ElfW(Lib) *) >- GL(dl_loaded)->l_info [ADDRIDX (DT_GNU_LIBLIST)]->d_un.d_ptr; >+ main_map->l_info[ADDRIDX (DT_GNU_LIBLIST)]->d_un.d_ptr; > liblistend = (ElfW(Lib) *) >- ((char *) liblist >- + GL(dl_loaded)->l_info [VALIDX (DT_GNU_LIBLISTSZ)]->d_un.d_val); >- r_list = GL(dl_loaded)->l_searchlist.r_list; >- r_listend = r_list + GL(dl_loaded)->l_searchlist.r_nlist; >+ ((char *) liblist + >+ main_map->l_info[VALIDX (DT_GNU_LIBLISTSZ)]->d_un.d_val); >+ r_list = main_map->l_searchlist.r_list; >+ r_listend = r_list + main_map->l_searchlist.r_nlist; > > for (; r_list < r_listend && liblist < liblistend; r_list++) > { > l = *r_list; > >- if (l == GL(dl_loaded)) >+ if (l == main_map) > continue; > > /* If the library is not mapped where it should, fail. */ >@@ -1767,9 +1778,7 @@ > /* Initialize _r_debug. */ > struct r_debug *r = _dl_debug_initialize (GL(dl_rtld_map).l_addr); > { >- struct link_map *l; >- >- l = GL(dl_loaded); >+ struct link_map *l = main_map; > > #ifdef ELF_MACHINE_DEBUG_SETUP > >@@ -1793,18 +1802,18 @@ > } > > /* Now set up the variable which helps the assembler startup code. */ >- GL(dl_main_searchlist) = &GL(dl_loaded)->l_searchlist; >- GL(dl_global_scope)[0] = &GL(dl_loaded)->l_searchlist; >+ GL(dl_ns)[LM_ID_BASE]._ns_main_searchlist = &main_map->l_searchlist; >+ GL(dl_ns)[LM_ID_BASE]._ns_global_scope[0] = &main_map->l_searchlist; > > /* Save the information about the original global scope list since > we need it in the memory handling later. */ >- GLRO(dl_initial_searchlist) = *GL(dl_main_searchlist); >+ GLRO(dl_initial_searchlist) = *GL(dl_ns)[LM_ID_BASE]._ns_main_searchlist; > > if (prelinked) > { > struct link_map *l; > >- if (GL(dl_loaded)->l_info [ADDRIDX (DT_GNU_CONFLICT)] != NULL) >+ if (main_map->l_info [ADDRIDX (DT_GNU_CONFLICT)] != NULL) > { > ElfW(Rela) *conflict, *conflictend; > #ifndef HP_TIMING_NONAVAIL >@@ -1813,20 +1822,20 @@ > #endif > > HP_TIMING_NOW (start); >- assert (GL(dl_loaded)->l_info [VALIDX (DT_GNU_CONFLICTSZ)] != NULL); >+ assert (main_map->l_info [VALIDX (DT_GNU_CONFLICTSZ)] != NULL); > conflict = (ElfW(Rela) *) >- GL(dl_loaded)->l_info [ADDRIDX (DT_GNU_CONFLICT)]->d_un.d_ptr; >+ main_map->l_info [ADDRIDX (DT_GNU_CONFLICT)]->d_un.d_ptr; > conflictend = (ElfW(Rela) *) > ((char *) conflict >- + GL(dl_loaded)->l_info [VALIDX (DT_GNU_CONFLICTSZ)]->d_un.d_val); >- _dl_resolve_conflicts (GL(dl_loaded), conflict, conflictend); >+ + main_map->l_info [VALIDX (DT_GNU_CONFLICTSZ)]->d_un.d_val); >+ _dl_resolve_conflicts (main_map, conflict, conflictend); > HP_TIMING_NOW (stop); > HP_TIMING_DIFF (relocate_time, start, stop); > } > > > /* Mark all the objects so we know they have been already relocated. */ >- for (l = GL(dl_loaded); l != NULL; l = l->l_next) >+ for (l = main_map; l != NULL; l = l->l_next) > { > l->l_relocated = 1; > if (l->l_relro_size) >@@ -1857,7 +1866,7 @@ > /* If we are profiling we also must do lazy reloaction. */ > GLRO(dl_lazy) |= consider_profiling; > >- l = GL(dl_loaded); >+ l = main_map; > while (l->l_next) > l = l->l_next; > >@@ -1906,7 +1915,7 @@ > /* There was an explicit ref to the dynamic linker as a shared lib. > Re-relocate ourselves with user-controlled symbol definitions. */ > HP_TIMING_NOW (start); >- _dl_relocate_object (&GL(dl_rtld_map), GL(dl_loaded)->l_scope, 0, 0); >+ _dl_relocate_object (&GL(dl_rtld_map), main_map->l_scope, 0, 0); > HP_TIMING_NOW (stop); > HP_TIMING_DIFF (add, start, stop); > HP_TIMING_ACCUM_NT (relocate_time, add); >@@ -2323,20 +2332,24 @@ > #endif > > unsigned long int num_relative_relocations = 0; >- struct r_scope_elem *scope = &GL(dl_loaded)->l_searchlist; >- unsigned int i; >- >- for (i = 0; i < scope->r_nlist; i++) >+ for (Lmid_t ns = 0; ns < DL_NNS; ++ns) > { >- struct link_map *l = scope->r_list [i]; >+ struct r_scope_elem *scope = &GL(dl_ns)[ns]._ns_loaded->l_searchlist; > >- if (!l->l_addr) >- continue; >+ for (unsigned int i = 0; i < scope->r_nlist; i++) >+ { >+ struct link_map *l = scope->r_list [i]; >+ >+ if (!l->l_addr) >+ continue; > >- if (l->l_info[VERSYMIDX (DT_RELCOUNT)]) >- num_relative_relocations += l->l_info[VERSYMIDX (DT_RELCOUNT)]->d_un.d_val; >- if (l->l_info[VERSYMIDX (DT_RELACOUNT)]) >- num_relative_relocations += l->l_info[VERSYMIDX (DT_RELACOUNT)]->d_un.d_val; >+ if (l->l_info[VERSYMIDX (DT_RELCOUNT)]) >+ num_relative_relocations >+ += l->l_info[VERSYMIDX (DT_RELCOUNT)]->d_un.d_val; >+ if (l->l_info[VERSYMIDX (DT_RELACOUNT)]) >+ num_relative_relocations >+ += l->l_info[VERSYMIDX (DT_RELACOUNT)]->d_un.d_val; >+ } > } > > _dl_debug_printf (" number of relocations: %lu\n" >--- libc/elf/do-lookup.h 2004/03/07 05:20:39 1.29 >+++ libc/elf/do-lookup.h 2004/10/14 02:06:51 1.30 >@@ -42,7 +42,7 @@ > int num_versions = 0; > const ElfW(Sym) *versioned_sym = NULL; > >- map = list[i]; >+ map = list[i]->l_real; > > /* Here come the extra test needed for `_dl_lookup_symbol_skip'. */ > if (skip != NULL && map == skip) >--- libc/elf/dl-support.c 2004/09/26 12:11:41 1.85 >+++ libc/elf/dl-support.c 2004/10/14 02:06:18 1.86 >@@ -67,10 +67,8 @@ > /* Nonzero if runtime lookup should not update the .got/.plt. */ > int _dl_bind_not; > >-/* Initially empty list of loaded objects. */ >-struct link_map *_dl_loaded; >-/* Number of object in the _dl_loaded list. */ >-unsigned int _dl_nloaded; >+/* Namespace information. */ >+struct link_namespaces _dl_ns[DL_NNS]; > > /* Incremented whenever something may have been added to dl_loaded. */ > unsigned long long _dl_load_adds; >@@ -79,12 +77,6 @@ > main application but here we don't have something like this. So > create a fake scope containing nothing. */ > struct r_scope_elem _dl_initial_searchlist; >-/* Variable which can be used in lookup to process the global scope. */ >-struct r_scope_elem *_dl_global_scope[2] = { &_dl_initial_searchlist, NULL }; >-/* This is a global pointer to this structure which is public. It is >- used by dlopen/dlclose to add and remove objects from what is regarded >- to be the global scope. */ >-struct r_scope_elem *_dl_main_searchlist = &_dl_initial_searchlist; > > #ifndef HAVE_INLINED_SYSCALLS > /* Nonzero during startup. */ >@@ -109,11 +101,6 @@ > void (*_dl_init_static_tls) (struct link_map *) = &_dl_nothread_init_static_tls; > #endif > >-/* This is zero at program start to signal that the global scope map is >- allocated by rtld. Later it keeps the size of the map. It might be >- reset if in _dl_close if the last global object is removed. */ >-size_t _dl_global_scope_alloc; >- > size_t _dl_pagesize; > > unsigned int _dl_osversion; >--- libc/elf/dl-open.c 2004/09/23 07:43:21 1.112 >+++ libc/elf/dl-open.c 2004/10/14 02:05:42 1.113 >@@ -72,6 +72,8 @@ > /* This is the caller if _dl_open(). */ > const void *caller_dl_open; > struct link_map *map; >+ /* Namespace ID. */ >+ Lmid_t nsid; > }; > > >@@ -101,15 +103,17 @@ > in an realloc() call. Therefore we allocate a completely new > array the first time we have to add something to the locale scope. */ > >- if (GL(dl_global_scope_alloc) == 0) >+ if (GL(dl_ns)[new->l_ns]._ns_global_scope_alloc == 0) > { > /* This is the first dynamic object given global scope. */ >- GL(dl_global_scope_alloc) = GL(dl_main_searchlist)->r_nlist + to_add + 8; >+ GL(dl_ns)[new->l_ns]._ns_global_scope_alloc >+ = GL(dl_ns)[new->l_ns]._ns_main_searchlist->r_nlist + to_add + 8; > new_global = (struct link_map **) >- malloc (GL(dl_global_scope_alloc) * sizeof (struct link_map *)); >+ malloc (GL(dl_ns)[new->l_ns]._ns_global_scope_alloc >+ * sizeof (struct link_map *)); > if (new_global == NULL) > { >- GL(dl_global_scope_alloc) = 0; >+ GL(dl_ns)[new->l_ns]._ns_global_scope_alloc = 0; > nomem: > GLRO(dl_signal_error) (ENOMEM, new->l_libname->name, NULL, > N_("cannot extend global scope")); >@@ -117,25 +121,26 @@ > } > > /* Copy over the old entries. */ >- memcpy (new_global, GL(dl_main_searchlist)->r_list, >- (GL(dl_main_searchlist)->r_nlist * sizeof (struct link_map *))); >- >- GL(dl_main_searchlist)->r_list = new_global; >+ GL(dl_ns)[new->l_ns]._ns_main_searchlist->r_list >+ = memcpy (new_global, >+ GL(dl_ns)[new->l_ns]._ns_main_searchlist->r_list, >+ (GL(dl_ns)[new->l_ns]._ns_main_searchlist->r_nlist >+ * sizeof (struct link_map *))); > } >- else if (GL(dl_main_searchlist)->r_nlist + to_add >- > GL(dl_global_scope_alloc)) >+ else if (GL(dl_ns)[new->l_ns]._ns_main_searchlist->r_nlist + to_add >+ > GL(dl_ns)[new->l_ns]._ns_global_scope_alloc) > { > /* We have to extend the existing array of link maps in the > main map. */ > new_global = (struct link_map **) >- realloc (GL(dl_main_searchlist)->r_list, >- ((GL(dl_global_scope_alloc) + to_add + 8) >+ realloc (GL(dl_ns)[new->l_ns]._ns_main_searchlist->r_list, >+ ((GL(dl_ns)[new->l_ns]._ns_global_scope_alloc + to_add + 8) > * sizeof (struct link_map *))); > if (new_global == NULL) > goto nomem; > >- GL(dl_global_scope_alloc) += to_add + 8; >- GL(dl_main_searchlist)->r_list = new_global; >+ GL(dl_ns)[new->l_ns]._ns_global_scope_alloc += to_add + 8; >+ GL(dl_ns)[new->l_ns]._ns_main_searchlist->r_list = new_global; > } > > /* Now add the new entries. */ >@@ -146,9 +151,9 @@ > if (map->l_global == 0) > { > map->l_global = 1; >- GL(dl_main_searchlist)->r_list[GL(dl_main_searchlist)->r_nlist] >+ GL(dl_ns)[new->l_ns]._ns_main_searchlist->r_list[GL(dl_ns)[new->l_ns]._ns_main_searchlist->r_nlist] > = map; >- ++GL(dl_main_searchlist)->r_nlist; >+ ++GL(dl_ns)[new->l_ns]._ns_main_searchlist->r_nlist; > } > } > >@@ -175,28 +180,34 @@ > GLRO(dl_signal_error) (0, "dlopen", NULL, N_("invalid caller")); > > /* Determine the caller's map if necessary. This is needed in case >- we have a DST or when the file name has no path in which case we >- need to look along the RUNPATH/RPATH of the caller. */ >+ we have a DST, when we don't know the namespace ID we have to put >+ the new object in, or when the file name has no path in which >+ case we need to look along the RUNPATH/RPATH of the caller. */ > const char *dst = strchr (file, '$'); >- if (dst != NULL || strchr (file, '/') == NULL) >+ if (dst != NULL || args->nsid == __LM_ID_CALLER >+ || strchr (file, '/') == NULL) > { > const void *caller_dlopen = args->caller_dlopen; > >- /* We have to find out from which object the caller is calling. */ >- call_map = NULL; >- for (l = GL(dl_loaded); l; l = l->l_next) >- if (caller_dlopen >= (const void *) l->l_map_start >- && caller_dlopen < (const void *) l->l_map_end) >- { >- /* There must be exactly one DSO for the range of the virtual >- memory. Otherwise something is really broken. */ >- call_map = l; >- break; >- } >+ /* We have to find out from which object the caller is calling. >+ By default we assume this is the main application. */ >+ call_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded; >+ >+ for (Lmid_t ns = 0; ns < DL_NNS; ++ns) >+ for (l = GL(dl_ns)[ns]._ns_loaded; l != NULL; l = l->l_next) >+ if (caller_dlopen >= (const void *) l->l_map_start >+ && caller_dlopen < (const void *) l->l_map_end) >+ { >+ /* There must be exactly one DSO for the range of the virtual >+ memory. Otherwise something is really broken. */ >+ assert (ns == l->l_ns); >+ call_map = l; >+ goto found_caller; >+ } > >- if (call_map == NULL) >- /* In this case we assume this is the main application. */ >- call_map = GL(dl_loaded); >+ found_caller: >+ if (args->nsid == __LM_ID_CALLER) >+ args->nsid = call_map->l_ns; > } > > /* Maybe we have to expand a DST. */ >@@ -238,7 +249,7 @@ > > /* Load the named object. */ > args->map = new = GLRO(dl_map_object) (call_map, file, 0, lt_loaded, 0, >- mode | __RTLD_CALLMAP); >+ mode | __RTLD_CALLMAP, args->nsid); > > /* If the pointer returned is NULL this means the RTLD_NOLOAD flag is > set and the object is not already loaded. */ >@@ -252,21 +263,30 @@ > /* This happens only if we load a DSO for 'sprof'. */ > return; > >+ /* This object is directly loaded. */ >+ ++new->l_direct_opencount; >+ > /* It was already open. */ > if (__builtin_expect (new->l_searchlist.r_list != NULL, 0)) > { > /* Let the user know about the opencount. */ > if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_FILES, 0)) >- GLRO(dl_debug_printf) ("opening file=%s; opencount == %u\n\n", >- new->l_name, new->l_opencount); >+ GLRO(dl_debug_printf) ("opening file=%s [%lu]; opencount=%u\n\n", >+ new->l_name, new->l_ns, new->l_opencount); > > /* If the user requested the object to be in the global namespace > but it is not so far, add it now. */ > if ((mode & RTLD_GLOBAL) && new->l_global == 0) > (void) add_to_global (new); > >- /* Increment just the reference counter of the object. */ >- ++new->l_opencount; >+ if (new->l_direct_opencount == 1) >+ /* This is the only direct reference. Increment all the >+ dependencies' reference counter. */ >+ for (i = 0; i < new->l_searchlist.r_nlist; ++i) >+ ++new->l_searchlist.r_list[i]->l_opencount; >+ else >+ /* Increment just the reference counter of the object. */ >+ ++new->l_opencount; > > return; > } >@@ -277,8 +297,9 @@ > > /* So far, so good. Now check the versions. */ > for (i = 0; i < new->l_searchlist.r_nlist; ++i) >- if (new->l_searchlist.r_list[i]->l_versions == NULL) >- (void) GLRO(dl_check_map_versions) (new->l_searchlist.r_list[i], 0, 0); >+ if (new->l_searchlist.r_list[i]->l_real->l_versions == NULL) >+ (void) GLRO(dl_check_map_versions) (new->l_searchlist.r_list[i]->l_real, >+ 0, 0); > > #ifdef SCOPE_DEBUG > show_scope (new); >@@ -295,7 +316,7 @@ > l = l->l_next; > while (1) > { >- if (! l->l_relocated) >+ if (! l->l_real->l_relocated) > { > #ifdef SHARED > if (GLRO(dl_profile) != NULL) >@@ -349,7 +370,7 @@ > loaded object to the scope. */ > for (i = 0; i < new->l_searchlist.r_nlist; ++i) > if (++new->l_searchlist.r_list[i]->l_opencount > 1 >- && new->l_searchlist.r_list[i]->l_type == lt_loaded) >+ && new->l_real->l_searchlist.r_list[i]->l_type == lt_loaded) > { > struct link_map *imap = new->l_searchlist.r_list[i]; > struct r_scope_elem **runp = imap->l_scope; >@@ -503,14 +524,14 @@ > > /* Let the user know about the opencount. */ > if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_FILES, 0)) >- GLRO(dl_debug_printf) ("opening file=%s; opencount == %u\n\n", >- new->l_name, new->l_opencount); >+ GLRO(dl_debug_printf) ("opening file=%s [%lu]; opencount=%u\n\n", >+ new->l_name, new->l_ns, new->l_opencount); > } > > > void * > internal_function >-_dl_open (const char *file, int mode, const void *caller_dlopen) >+_dl_open (const char *file, int mode, const void *caller_dlopen, Lmid_t nsid) > { > struct dl_open_args args; > const char *objname; >@@ -525,11 +546,29 @@ > /* Make sure we are alone. */ > __rtld_lock_lock_recursive (GL(dl_load_lock)); > >+ if (nsid == LM_ID_NEWLM) >+ { >+ /* Find a new namespace. */ >+ for (nsid = 1; nsid < DL_NNS; ++nsid) >+ if (GL(dl_ns)[nsid]._ns_loaded == NULL) >+ break; >+ >+ if (nsid == DL_NNS) >+ { >+ /* No more namespace available. */ >+ __rtld_lock_unlock_recursive (GL(dl_load_lock)); >+ >+ GLRO(dl_signal_error) (EINVAL, file, NULL, N_("\ >+no more namespaces available for dlmopen()")); >+ } >+ } >+ > args.file = file; > args.mode = mode; > args.caller_dlopen = caller_dlopen; > args.caller_dl_open = RETURN_ADDRESS (0); > args.map = NULL; >+ args.nsid = nsid; > errcode = GLRO(dl_catch_error) (&objname, &errstring, dl_open_worker, &args); > > #ifndef MAP_COPY >--- libc/elf/dl-object.c 2004/09/23 07:40:25 1.38 >+++ libc/elf/dl-object.c 2004/10/14 02:05:07 1.39 >@@ -32,7 +32,7 @@ > struct link_map * > internal_function > _dl_new_object (char *realname, const char *libname, int type, >- struct link_map *loader, int mode) >+ struct link_map *loader, int mode, Lmid_t nsid) > { > struct link_map *l; > int idx; >@@ -45,6 +45,7 @@ > if (new == NULL) > return NULL; > >+ new->l_real = new; > new->l_libname = newname = (struct libname_list *) (new + 1); > newname->name = (char *) memcpy (newname + 1, libname, libname_len); > /* newname->next = NULL; We use calloc therefore not necessary. */ >@@ -56,6 +57,7 @@ > #if defined USE_TLS && NO_TLS_OFFSET != 0 > new->l_tls_offset = NO_TLS_OFFSET; > #endif >+ new->l_ns = nsid; > > /* new->l_global = 0; We use calloc therefore not necessary. */ > >@@ -68,9 +70,9 @@ > /* Counter for the scopes we have to handle. */ > idx = 0; > >- if (GL(dl_loaded) != NULL) >+ if (GL(dl_ns)[nsid]._ns_loaded != NULL) > { >- l = GL(dl_loaded); >+ l = GL(dl_ns)[nsid]._ns_loaded; > while (l->l_next != NULL) > l = l->l_next; > new->l_prev = l; >@@ -78,11 +80,11 @@ > l->l_next = new; > > /* Add the global scope. */ >- new->l_scope[idx++] = &GL(dl_loaded)->l_searchlist; >+ new->l_scope[idx++] = &GL(dl_ns)[nsid]._ns_loaded->l_searchlist; > } > else >- GL(dl_loaded) = new; >- ++GL(dl_nloaded); >+ GL(dl_ns)[nsid]._ns_loaded = new; >+ ++GL(dl_ns)[nsid]._ns_nloaded; > ++GL(dl_load_adds); > > /* If we have no loader the new object acts as it. */ >--- libc/elf/dl-lookup.c 2004/09/18 06:46:15 1.116 >+++ libc/elf/dl-lookup.c 2004/10/14 02:04:37 1.117 >@@ -137,7 +137,7 @@ > reference is still available. There is a brief period in > which the object could have been removed since we found the > definition. */ >- runp = GL(dl_loaded); >+ runp = GL(dl_ns)[undef_map->l_ns]._ns_loaded; > while (runp != NULL && runp != map) > runp = runp->l_next; > >@@ -182,13 +182,18 @@ > for (list = map->l_initfini; *list != NULL; ++list) > ++(*list)->l_opencount; > >+ /* As if it is opened through _dl_open. */ >+ ++map->l_direct_opencount; >+ > /* Display information if we are debugging. */ > if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_FILES, 0)) > _dl_debug_printf ("\ >-\nfile=%s; needed by %s (relocation dependency)\n\n", >+\nfile=%s [%lu]; needed by %s [%lu] (relocation dependency)\n\n", > map->l_name[0] ? map->l_name : rtld_progname, >+ map->l_ns, > undef_map->l_name[0] >- ? undef_map->l_name : rtld_progname); >+ ? undef_map->l_name : rtld_progname, >+ undef_map->l_ns); > } > else > /* Whoa, that was bad luck. We have to search again. */ >@@ -408,8 +413,8 @@ > struct sym_val val = { NULL, NULL }; > > if ((GLRO(dl_trace_prelink_map) == NULL >- || GLRO(dl_trace_prelink_map) == GL(dl_loaded)) >- && undef_map != GL(dl_loaded)) >+ || GLRO(dl_trace_prelink_map) == GL(dl_ns)[LM_ID_BASE]._ns_loaded) >+ && undef_map != GL(dl_ns)[LM_ID_BASE]._ns_loaded) > { > const unsigned long int hash = _dl_elf_hash (undef_name); > >@@ -421,12 +426,12 @@ > conflict = 1; > } > >-#ifdef USE_TLS >+# ifdef USE_TLS > if (value->s > && (__builtin_expect (ELFW(ST_TYPE) (value->s->st_info) > == STT_TLS, 0))) > type_class = 4; >-#endif >+# endif > > if (conflict > || GLRO(dl_trace_prelink_map) == undef_map >--- libc/elf/dl-load.c 2004/09/23 07:44:34 1.250 >+++ libc/elf/dl-load.c 2004/10/14 02:03:20 1.251 >@@ -699,7 +699,7 @@ > > #ifdef SHARED > /* This points to the map of the main object. */ >- l = GL(dl_loaded); >+ l = GL(dl_ns)[LM_ID_BASE]._ns_loaded; > if (l != NULL) > { > assert (l->l_type != lt_loaded); >@@ -795,10 +795,10 @@ > if (l->l_prev == NULL) > /* No other module loaded. This happens only in the static library, > or in rtld under --verify. */ >- GL(dl_loaded) = NULL; >+ GL(dl_ns)[l->l_ns]._ns_loaded = NULL; > else > l->l_prev->l_next = NULL; >- --GL(dl_nloaded); >+ --GL(dl_ns)[l->l_ns]._ns_nloaded; > free (l); > } > free (realname); >@@ -815,7 +815,7 @@ > struct link_map * > _dl_map_object_from_fd (const char *name, int fd, struct filebuf *fbp, > char *realname, struct link_map *loader, int l_type, >- int mode, void **stack_endp) >+ int mode, void **stack_endp, Lmid_t nsid) > { > struct link_map *l = NULL; > const ElfW(Ehdr) *header; >@@ -839,7 +839,7 @@ > } > > /* Look again to see if the real name matched another already loaded. */ >- for (l = GL(dl_loaded); l; l = l->l_next) >+ for (l = GL(dl_ns)[nsid]._ns_loaded; l; l = l->l_next) > if (l->l_ino == st.st_ino && l->l_dev == st.st_dev) > { > /* The object is already loaded. >@@ -854,6 +854,31 @@ > return l; > } > >+#ifdef SHARED >+ /* When loading into a namespace other than the base one we must >+ avoid loading ld.so since there can only be one copy. Ever. */ >+ if (__builtin_expect (nsid != LM_ID_BASE, 0) >+ && ((st.st_ino == GL(dl_rtld_map).l_ino >+ && st.st_dev == GL(dl_rtld_map).l_dev) >+ || _dl_name_match_p (name, &GL(dl_rtld_map)))) >+ { >+ /* This is indeed ld.so. Create a new link_map which refers to >+ the real one for almost everything. */ >+ l = _dl_new_object (realname, name, l_type, loader, mode, nsid); >+ if (l == NULL) >+ goto fail_new; >+ >+ /* Refer to the real descriptor. */ >+ l->l_real = &GL(dl_rtld_map); >+ >+ /* No need to bump the refcount of the real object, ld.so will >+ never be unloaded. */ >+ __close (fd); >+ >+ return l; >+ } >+#endif >+ > if (mode & RTLD_NOLOAD) > /* We are not supposed to load the object unless it is already > loaded. So return now. */ >@@ -861,7 +886,7 @@ > > /* Print debugging message. */ > if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_FILES, 0)) >- _dl_debug_printf ("file=%s; generating link map\n", name); >+ _dl_debug_printf ("file=%s [%lu]; generating link map\n", name, nsid); > > /* This is the ELF header. We read it in `open_verify'. */ > header = (void *) fbp->buf; >@@ -881,9 +906,10 @@ > #endif > > /* Enter the new object in the list of loaded objects. */ >- l = _dl_new_object (realname, name, l_type, loader, mode); >- if (__builtin_expect (! l, 0)) >+ l = _dl_new_object (realname, name, l_type, loader, mode, nsid); >+ if (__builtin_expect (l == NULL, 0)) > { >+ fail_new: > errstring = N_("cannot create shared object descriptor"); > goto call_lose_errno; > } >@@ -1771,7 +1797,7 @@ > struct link_map * > internal_function > _dl_map_object (struct link_map *loader, const char *name, int preloaded, >- int type, int trace_mode, int mode) >+ int type, int trace_mode, int mode, Lmid_t nsid) > { > int fd; > char *realname; >@@ -1779,8 +1805,11 @@ > struct link_map *l; > struct filebuf fb; > >+ assert (nsid >= 0); >+ assert (nsid < DL_NNS); >+ > /* Look for this name among those already loaded. */ >- for (l = GL(dl_loaded); l; l = l->l_next) >+ for (l = GL(dl_ns)[nsid]._ns_loaded; l; l = l->l_next) > { > /* If the requested name matches the soname of a loaded object, > use that object. Elide this check for names that have not >@@ -1812,9 +1841,9 @@ > /* Display information if we are debugging. */ > if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_FILES, 0) > && loader != NULL) >- _dl_debug_printf ("\nfile=%s; needed by %s\n", name, >+ _dl_debug_printf ("\nfile=%s [%lu]; needed by %s [%lu]\n", name, nsid, > loader->l_name[0] >- ? loader->l_name : rtld_progname); >+ ? loader->l_name : rtld_progname, loader->l_ns); > > if (strchr (name, '/') == NULL) > { >@@ -1823,7 +1852,7 @@ > size_t namelen = strlen (name) + 1; > > if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_LIBS, 0)) >- _dl_debug_printf ("find library=%s; searching\n", name); >+ _dl_debug_printf ("find library=%s [%lu]; searching\n", name, nsid); > > fd = -1; > >@@ -1839,12 +1868,15 @@ > &realname, &fb); > > /* If dynamically linked, try the DT_RPATH of the executable >- itself. */ >- l = GL(dl_loaded); >- if (fd == -1 && l && l->l_type != lt_loaded && l != loader >- && l->l_rpath_dirs.dirs != (void *) -1) >- fd = open_path (name, namelen, preloaded, &l->l_rpath_dirs, >- &realname, &fb); >+ itself. NB: we do this for lookups in any namespace. */ >+ if (fd == -1) >+ { >+ l = GL(dl_ns)[LM_ID_BASE]._ns_loaded; >+ if (l && l->l_type != lt_loaded && l != loader >+ && l->l_rpath_dirs.dirs != (void *) -1) >+ fd = open_path (name, namelen, preloaded, &l->l_rpath_dirs, >+ &realname, &fb); >+ } > } > > /* Try the LD_LIBRARY_PATH environment variable. */ >@@ -1870,7 +1902,8 @@ > if (cached != NULL) > { > #ifdef SHARED >- l = loader ?: GL(dl_loaded); >+ // XXX Correct to unconditionally default to namespace 0? >+ l = loader ?: GL(dl_ns)[LM_ID_BASE]._ns_loaded; > #else > l = loader; > #endif >@@ -1920,7 +1953,7 @@ > > /* Finally, try the default path. */ > if (fd == -1 >- && ((l = loader ?: GL(dl_loaded)) == NULL >+ && ((l = loader ?: GL(dl_ns)[nsid]._ns_loaded) == NULL > || __builtin_expect (!(l->l_flags_1 & DF_1_NODEFLIB), 1)) > && rtld_search_dirs.dirs != (void *) -1) > fd = open_path (name, namelen, preloaded, &rtld_search_dirs, >@@ -1966,7 +1999,7 @@ > /* Enter the new object in the list of loaded objects. */ > if ((name_copy = local_strdup (name)) == NULL > || (l = _dl_new_object (name_copy, name, type, loader, >- mode)) == NULL) >+ mode, nsid)) == NULL) > _dl_signal_error (ENOMEM, name, NULL, > N_("cannot create shared object descriptor")); > /* Signal that this is a faked entry. */ >@@ -1987,7 +2020,7 @@ > > void *stack_end = __libc_stack_end; > return _dl_map_object_from_fd (name, fd, &fb, realname, loader, type, mode, >- &stack_end); >+ &stack_end, nsid); > } > > >@@ -2047,10 +2080,13 @@ > while (l != NULL); > > /* If dynamically linked, try the DT_RPATH of the executable itself. */ >- l = GL(dl_loaded); >- if (l != NULL && l->l_type != lt_loaded && l != loader) >- if (cache_rpath (l, &l->l_rpath_dirs, DT_RPATH, "RPATH")) >- add_path (&l->l_rpath_dirs, XXX_RPATH); >+ if (loader->l_ns == LM_ID_BASE) >+ { >+ l = GL(dl_ns)[LM_ID_BASE]._ns_loaded; >+ if (l != NULL && l->l_type != lt_loaded && l != loader) >+ if (cache_rpath (l, &l->l_rpath_dirs, DT_RPATH, "RPATH")) >+ add_path (&l->l_rpath_dirs, XXX_RPATH); >+ } > } > > /* Try the LD_LIBRARY_PATH environment variable. */ >--- libc/elf/dl-libc.c 2004/03/07 08:38:43 1.22 >+++ libc/elf/dl-libc.c 2004/10/14 02:02:33 1.23 >@@ -77,7 +77,7 @@ > { > struct do_dlopen_args *args = (struct do_dlopen_args *) ptr; > /* Open and relocate the shared object. */ >- args->map = _dl_open (args->name, args->mode, NULL); >+ args->map = _dl_open (args->name, args->mode, NULL, __LM_ID_CALLER); > } > > static void >@@ -217,18 +217,19 @@ > } > > /* Remove all additional names added to the objects. */ >- for (l = GL(dl_loaded); l != NULL; l = l->l_next) >- { >- struct libname_list *lnp = l->l_libname->next; >- >- l->l_libname->next = NULL; >- >- while (lnp != NULL) >- { >- struct libname_list *old = lnp; >- lnp = lnp->next; >- if (! old->dont_free) >+ for (Lmid_t ns = 0; ns < DL_NNS; ++ns) >+ for (l = GL(dl_ns)[ns]._ns_loaded; l != NULL; l = l->l_next) >+ { >+ struct libname_list *lnp = l->l_libname->next; >+ >+ l->l_libname->next = NULL; >+ >+ while (lnp != NULL) >+ { >+ struct libname_list *old = lnp; >+ lnp = lnp->next; >+ if (! old->dont_free) > free (old); >- } >- } >+ } >+ } > } > > >--- libc/elf/dl-iteratephdr.c 2004/01/27 21:29:22 1.11 >+++ libc/elf/dl-iteratephdr.c 2004/10/14 02:02:06 1.12 >@@ -42,14 +42,32 @@ > __rtld_lock_lock_recursive (GL(dl_load_lock)); > __libc_cleanup_push (cancel_handler, 0); > >- for (l = GL(dl_loaded); l != NULL; l = l->l_next) >+ /* We have to determine the namespace of the caller since this determines >+ which namespace is reported. */ >+ const void *caller = RETURN_ADDRESS (0); >+ size_t nloaded = GL(dl_ns)[0]._ns_nloaded; >+ Lmid_t ns = 0; >+ for (Lmid_t cnt = DL_NNS - 1; cnt > 0; --cnt) >+ for (struct link_map *l = GL(dl_ns)[cnt]._ns_loaded; l; l = l->l_next) >+ { >+ /* We have to count the total number of loaded objects. */ >+ nloaded += GL(dl_ns)[cnt]._ns_nloaded; >+ >+ if (caller >= (const void *) l->l_map_start >+ && caller < (const void *) l->l_map_end) >+ /* There must be exactly one DSO for the range of the virtual >+ memory. Otherwise something is really broken. */ >+ ns = cnt; >+ } >+ >+ for (l = GL(dl_ns)[ns]._ns_loaded; l != NULL; l = l->l_next) > { > info.dlpi_addr = l->l_addr; > info.dlpi_name = l->l_name; > info.dlpi_phdr = l->l_phdr; > info.dlpi_phnum = l->l_phnum; > info.dlpi_adds = GL(dl_load_adds); >- info.dlpi_subs = GL(dl_load_adds) - GL(dl_nloaded); >+ info.dlpi_subs = GL(dl_load_adds) - nloaded; > ret = callback (&info, sizeof (struct dl_phdr_info), data); > if (ret) > break; >@@ -87,7 +105,7 @@ > info.dlpi_phdr = _dl_phdr; > info.dlpi_phnum = _dl_phnum; > info.dlpi_adds = GL(dl_load_adds); >- info.dlpi_subs = GL(dl_load_adds) - GL(dl_nloaded); >+ info.dlpi_subs = GL(dl_load_adds) - GL(dl_ns)[LM_ID_BASE]._ns_nloaded; > ret = (*callback) (&info, sizeof (struct dl_phdr_info), data); > if (ret) > return ret; >--- libc/elf/dl-fini.c 2004/07/08 00:52:17 1.35 >+++ libc/elf/dl-fini.c 2004/10/14 02:01:39 1.36 >@@ -32,10 +32,10 @@ > _dl_fini (void) > { > /* Lots of fun ahead. We have to call the destructors for all still >- loaded objects. The problem is that the ELF specification now >- demands that dependencies between the modules are taken into account. >- I.e., the destructor for a module is called before the ones for any >- of its dependencies. >+ loaded objects, in all namespaces. The problem is that the ELF >+ specification now demands that dependencies between the modules >+ are taken into account. I.e., the destructor for a module is >+ called before the ones for any of its dependencies. > > To make things more complicated, we cannot simply use the reverse > order of the constructors. Since the user might have loaded objects >@@ -45,140 +45,179 @@ > unsigned int i; > unsigned int nloaded; > struct link_map *l; >- struct link_map **maps; >+ struct link_map **maps = NULL; >+ size_t maps_size = 0; > >- /* Protect against concurrent loads and unloads. */ >- __rtld_lock_lock_recursive (GL(dl_load_lock)); >- >- nloaded = GL(dl_nloaded); >- >- /* XXX Could it be (in static binaries) that there is no object loaded? */ >- assert (nloaded > 0); >- >- /* Now we can allocate an array to hold all the pointers and copy >- the pointers in. */ >- maps = (struct link_map **) alloca (nloaded * sizeof (struct link_map *)); >- for (l = GL(dl_loaded), i = 0; l != NULL; l = l->l_next) >+ /* We First run the destructors of the main namespaces, then the >+ other ones. The order should not matter since the namespace >+ content is supposed to be independent. But we can have auditing >+ code in a auxiliaty namespace and we want it to monitor the >+ destructors. */ >+ for (Lmid_t cnt = 0; cnt < DL_NNS; ++cnt) > { >- assert (i < nloaded); >+ /* Protect against concurrent loads and unloads. */ >+ __rtld_lock_lock_recursive (GL(dl_load_lock)); > >- maps[i++] = l; >+ nloaded = GL(dl_ns)[cnt]._ns_nloaded; > >- /* Bump l_opencount of all objects so that they are not dlclose()ed >- from underneath us. */ >- ++l->l_opencount; >- } >- assert (i == nloaded); >- >- /* Now we have to do the sorting. */ >- for (l = GL(dl_loaded)->l_next; l != NULL; l = l->l_next) >- { >- unsigned int j; >- unsigned int k; >+ /* XXX Could it be (in static binaries) that there is no object >+ loaded? */ >+ assert (cnt != LM_ID_BASE || nloaded > 0); >+ >+ /* Now we can allocate an array to hold all the pointers and copy >+ the pointers in. */ >+ if (maps_size < nloaded * sizeof (struct link_map *)) >+ { >+ if (maps_size == 0) >+ { >+ maps_size = nloaded * sizeof (struct link_map *); >+ maps = (struct link_map **) alloca (maps_size); >+ } >+ else >+ maps = (struct link_map **) >+ extend_alloca (maps, maps_size, >+ nloaded * sizeof (struct link_map *)); >+ } > >- /* Find the place in the 'maps' array. */ >- for (j = 1; maps[j] != l; ++j) >- ; >- >- /* Find all object for which the current one is a dependency and >- move the found object (if necessary) in front. */ >- for (k = j + 1; k < nloaded; ++k) >+ for (l = GL(dl_ns)[cnt]._ns_loaded, i = 0; l != NULL; l = l->l_next) > { >- struct link_map **runp = maps[k]->l_initfini; >- if (runp != NULL) >+ assert (i < nloaded); >+ >+ /* Do not handle ld.so in secondary namespaces. */ >+ if (l == l->l_real) > { >- while (*runp != NULL) >- if (*runp == l) >- { >- struct link_map *here = maps[k]; >- >- /* Move it now. */ >- memmove (&maps[j] + 1, >- &maps[j], >- (k - j) * sizeof (struct link_map *)); >- maps[j++] = here; >- >- break; >- } >- else >- ++runp; >+ maps[i++] = l; >+ >+ /* Bump l_opencount of all objects so that they are not >+ dlclose()ed from underneath us. */ >+ ++l->l_opencount; > } >+ } >+ assert (cnt != LM_ID_BASE || i == nloaded); >+ assert (cnt == LM_ID_BASE || i == nloaded || i == nloaded - 1); >+ unsigned int nmaps = i; > >- if (__builtin_expect (maps[k]->l_reldeps != NULL, 0)) >+ if (nmaps != 0) >+ { >+ /* Now we have to do the sorting. */ >+ l = GL(dl_ns)[cnt]._ns_loaded; >+ if (cnt == LM_ID_BASE) >+ /* The main executable always comes first. */ >+ l = l->l_next; >+ for (; l != NULL; l = l->l_next) > { >- unsigned int m = maps[k]->l_reldepsact; >- struct link_map **relmaps = maps[k]->l_reldeps; >+ unsigned int j; >+ unsigned int k; > >- while (m-- > 0) >+ /* Find the place in the 'maps' array. */ >+ for (j = 1; maps[j] != l; ++j) >+ ; >+ >+ /* Find all object for which the current one is a dependency and >+ move the found object (if necessary) in front. */ >+ for (k = j + 1; k < nmaps; ++k) > { >- if (relmaps[m] == l) >+ struct link_map **runp = maps[k]->l_initfini; >+ if (runp != NULL) > { >- struct link_map *here = maps[k]; >+ while (*runp != NULL) >+ if (*runp == l) >+ { >+ struct link_map *here = maps[k]; >+ >+ /* Move it now. */ >+ memmove (&maps[j] + 1, >+ &maps[j], >+ (k - j) * sizeof (struct link_map *)); >+ maps[j++] = here; >+ >+ break; >+ } >+ else >+ ++runp; >+ } > >- /* Move it now. */ >- memmove (&maps[j] + 1, >- &maps[j], >- (k - j) * sizeof (struct link_map *)); >- maps[j] = here; >+ if (__builtin_expect (maps[k]->l_reldeps != NULL, 0)) >+ { >+ unsigned int m = maps[k]->l_reldepsact; >+ struct link_map **relmaps = maps[k]->l_reldeps; > >- break; >+ while (m-- > 0) >+ { >+ if (relmaps[m] == l) >+ { >+ struct link_map *here = maps[k]; >+ >+ /* Move it now. */ >+ memmove (&maps[j] + 1, >+ &maps[j], >+ (k - j) * sizeof (struct link_map *)); >+ maps[j] = here; >+ >+ break; >+ } >+ } > } > } > } > } >- } > >- /* We do not rely on the linked list of loaded object anymore from >- this point on. We have our own list here (maps). The various >- members of this list cannot vanish since the open count is too >- high and will be decremented in this loop. So we release the >- lock so that some code which might be called from a destructor >- can directly or indirectly access the lock. */ >- __rtld_lock_unlock_recursive (GL(dl_load_lock)); >- >- /* 'maps' now contains the objects in the right order. Now call the >- destructors. We have to process this array from the front. */ >- for (i = 0; i < nloaded; ++i) >- { >- l = maps[i]; >- >- if (l->l_init_called) >+ /* We do not rely on the linked list of loaded object anymore from >+ this point on. We have our own list here (maps). The various >+ members of this list cannot vanish since the open count is too >+ high and will be decremented in this loop. So we release the >+ lock so that some code which might be called from a destructor >+ can directly or indirectly access the lock. */ >+ __rtld_lock_unlock_recursive (GL(dl_load_lock)); >+ >+ /* 'maps' now contains the objects in the right order. Now call the >+ destructors. We have to process this array from the front. */ >+ for (i = 0; i < nmaps; ++i) > { >- /* Make sure nothing happens if we are called twice. */ >- l->l_init_called = 0; >- >- /* Don't call the destructors for objects we are not supposed to. */ >- if (l->l_name[0] == '\0' && l->l_type == lt_executable) >- continue; >- >- /* Is there a destructor function? */ >- if (l->l_info[DT_FINI_ARRAY] == NULL && l->l_info[DT_FINI] == NULL) >- continue; >- >- /* When debugging print a message first. */ >- if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS, 0)) >- _dl_debug_printf ("\ncalling fini: %s\n\n", >- l->l_name[0] ? l->l_name : rtld_progname); >+ l = maps[i]; > >- /* First see whether an array is given. */ >- if (l->l_info[DT_FINI_ARRAY] != NULL) >+ if (l->l_init_called) > { >- ElfW(Addr) *array = >- (ElfW(Addr) *) (l->l_addr >- + l->l_info[DT_FINI_ARRAY]->d_un.d_ptr); >- unsigned int i = (l->l_info[DT_FINI_ARRAYSZ]->d_un.d_val >- / sizeof (ElfW(Addr))); >- while (i-- > 0) >- ((fini_t) array[i]) (); >+ /* Make sure nothing happens if we are called twice. */ >+ l->l_init_called = 0; >+ >+ /* Don't call the destructors for objects we are not >+ supposed to. */ >+ if (l->l_name[0] == '\0' && l->l_type == lt_executable) >+ continue; >+ >+ /* Is there a destructor function? */ >+ if (l->l_info[DT_FINI_ARRAY] == NULL >+ && l->l_info[DT_FINI] == NULL) >+ continue; >+ >+ /* When debugging print a message first. */ >+ if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS, >+ 0)) >+ _dl_debug_printf ("\ncalling fini: %s [%lu]\n\n", >+ l->l_name[0] ? l->l_name : rtld_progname, >+ cnt); >+ >+ /* First see whether an array is given. */ >+ if (l->l_info[DT_FINI_ARRAY] != NULL) >+ { >+ ElfW(Addr) *array = >+ (ElfW(Addr) *) (l->l_addr >+ + l->l_info[DT_FINI_ARRAY]->d_un.d_ptr); >+ unsigned int i = (l->l_info[DT_FINI_ARRAYSZ]->d_un.d_val >+ / sizeof (ElfW(Addr))); >+ while (i-- > 0) >+ ((fini_t) array[i]) (); >+ } >+ >+ /* Next try the old-style destructor. */ >+ if (l->l_info[DT_FINI] != NULL) >+ ((fini_t) DL_DT_FINI_ADDRESS (l, l->l_addr + l->l_info[DT_FINI]->d_un.d_ptr)) (); > } > >- /* Next try the old-style destructor. */ >- if (l->l_info[DT_FINI] != NULL) >- ((fini_t) DL_DT_FINI_ADDRESS (l, l->l_addr + l->l_info[DT_FINI]->d_un.d_ptr)) (); >+ /* Correct the previous increment. */ >+ --l->l_opencount; > } >- >- /* Correct the previous increment. */ >- --l->l_opencount; > } > > if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_STATISTICS, 0)) >--- libc/elf/dl-deps.c 2004/09/23 07:42:29 1.76 >+++ libc/elf/dl-deps.c 2004/10/14 02:01:14 1.77 >@@ -63,7 +63,8 @@ > args->aux = _dl_map_object (args->map, args->name, 0, > (args->map->l_type == lt_executable > ? lt_library : args->map->l_type), >- args->trace_mode, args->open_mode); >+ args->trace_mode, args->open_mode, >+ args->map->l_ns); > } > > static ptrdiff_t >@@ -510,7 +511,7 @@ > } > > if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_PRELINK, 0) != 0 >- && map == GL(dl_loaded)) >+ && map == GL(dl_ns)[LM_ID_BASE]._ns_loaded) > { > /* If we are to compute conflicts, we have to build local scope > for each library, not just the ultimate loader. */ >--- libc/elf/dl-close.c 2004/10/13 19:27:16 1.105 >+++ libc/elf/dl-close.c 2004/10/14 02:00:27 1.106 >@@ -130,6 +130,10 @@ > /* Acquire the lock. */ > __rtld_lock_lock_recursive (GL(dl_load_lock)); > >+ /* One less direct use. */ >+ assert (map->l_direct_opencount > 0); >+ --map->l_direct_opencount; >+ > /* Decrement the reference count. */ > if (map->l_opencount > 1 || map->l_type != lt_loaded) > { >@@ -141,6 +145,12 @@ > /* Decrement the object's reference counter, not the dependencies'. */ > --map->l_opencount; > >+ /* If the direct use counter reaches zero we have to decrement >+ all the dependencies' usage counter. */ >+ if (map->l_direct_opencount == 0) >+ for (i = 1; i < map->l_searchlist.r_nlist; ++i) >+ --map->l_searchlist.r_list[i]->l_opencount; >+ > __rtld_lock_unlock_recursive (GL(dl_load_lock)); > return; > } >@@ -167,12 +177,13 @@ > for (i = 1; list[i] != NULL; ++i) > if ((list[i]->l_flags_1 & DF_1_NODELETE) == 0 > /* Decrement counter. */ >- && --new_opencount[i] == 0) >+ && (assert (new_opencount[i] > 0), --new_opencount[i] == 0)) > { > void mark_removed (struct link_map *remmap) > { > /* Test whether this object was also loaded directly. */ >- if (remmap->l_searchlist.r_list != NULL) >+ if (remmap->l_searchlist.r_list != NULL >+ && remmap->l_direct_opencount > 0) > { > /* In this case we have to decrement all the dependencies of > this object. They are all in MAP's dependency list. */ >@@ -184,6 +195,7 @@ > || ! dep_list[j]->l_init_called) > { > assert (dep_list[j]->l_idx < map->l_searchlist.r_nlist); >+ assert (new_opencount[dep_list[j]->l_idx] > 0); > if (--new_opencount[dep_list[j]->l_idx] == 0) > { > assert (dep_list[j]->l_type == lt_loaded); >@@ -197,17 +209,53 @@ > unsigned int j; > for (j = 0; j < remmap->l_reldepsact; ++j) > { >+ struct link_map *depmap = remmap->l_reldeps[j]; >+ > /* Find out whether this object is in our list. */ >- if (remmap->l_reldeps[j]->l_idx < nopencount >- && (list[remmap->l_reldeps[j]->l_idx] >- == remmap->l_reldeps[j])) >- /* Yes, it is. */ >- if (--new_opencount[remmap->l_reldeps[j]->l_idx] == 0) >- { >- /* This one is now gone, too. */ >- assert (remmap->l_reldeps[j]->l_type == lt_loaded); >- mark_removed (remmap->l_reldeps[j]); >- } >+ if (depmap->l_idx < nopencount >+ && list[depmap->l_idx] == depmap) >+ { >+ /* Yes, it is. If is has a search list, make a >+ recursive call to handle this. */ >+ if (depmap->l_searchlist.r_list != NULL) >+ { >+ assert (new_opencount[depmap->l_idx] > 0); >+ if (--new_opencount[depmap->l_idx] == 0) >+ { >+ /* This one is now gone, too. */ >+ assert (depmap->l_type == lt_loaded); >+ mark_removed (depmap); >+ } >+ } >+ else >+ { >+ /* Otherwise we have to handle the dependency >+ deallocation here. */ >+ unsigned int k; >+ for (k = 0; depmap->l_initfini[k] != NULL; ++k) >+ { >+ struct link_map *rl = depmap->l_initfini[k]; >+ >+ if (rl->l_idx < nopencount >+ & list[rl->l_idx] == rl) >+ { >+ assert (new_opencount[rl->l_idx] > 0); >+ if (--new_opencount[rl->l_idx] == 0) >+ { >+ /* Another module to remove. */ >+ assert (rl->l_type == lt_loaded); >+ mark_removed (rl); >+ } >+ } >+ else >+ { >+ assert (rl->l_opencount > 0); >+ if (--rl->l_opencount == 0) >+ mark_removed (rl); >+ } >+ } >+ } >+ } > } > } > } >@@ -225,7 +273,8 @@ > { > /* When debugging print a message first. */ > if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS, 0)) >- GLRO(dl_debug_printf) ("\ncalling fini: %s\n\n", imap->l_name); >+ GLRO(dl_debug_printf) ("\ncalling fini: %s [%lu]\n\n", >+ imap->l_name, imap->l_ns); > > /* Call its termination function. Do not do it for > half-cooked objects. */ >@@ -340,18 +389,21 @@ > if (__builtin_expect (imap->l_global, 0)) > { > /* This object is in the global scope list. Remove it. */ >- unsigned int cnt = GL(dl_main_searchlist)->r_nlist; >+ unsigned int cnt >+ = GL(dl_ns)[imap->l_ns]._ns_main_searchlist->r_nlist; > > do > --cnt; >- while (GL(dl_main_searchlist)->r_list[cnt] != imap); >+ while (GL(dl_ns)[imap->l_ns]._ns_main_searchlist->r_list[cnt] >+ != imap); > > /* The object was already correctly registered. */ >- while (++cnt < GL(dl_main_searchlist)->r_nlist) >- GL(dl_main_searchlist)->r_list[cnt - 1] >- = GL(dl_main_searchlist)->r_list[cnt]; >+ while (++cnt >+ < GL(dl_ns)[imap->l_ns]._ns_main_searchlist->r_nlist) >+ GL(dl_ns)[imap->l_ns]._ns_main_searchlist->r_list[cnt - 1] >+ = GL(dl_ns)[imap->l_ns]._ns_main_searchlist->r_list[cnt]; > >- --GL(dl_main_searchlist)->r_nlist; >+ --GL(dl_ns)[imap->l_ns]._ns_main_searchlist->r_nlist; > } > > #ifdef USE_TLS >@@ -442,19 +494,18 @@ > DL_UNMAP (imap); > > /* Finally, unlink the data structure and free it. */ >-#ifdef SHARED >- /* We will unlink the first object only if this is a statically >- linked program. */ >- assert (imap->l_prev != NULL); >- imap->l_prev->l_next = imap->l_next; >-#else > if (imap->l_prev != NULL) > imap->l_prev->l_next = imap->l_next; > else >- GL(dl_loaded) = imap->l_next; >+ { >+#ifdef SHARED >+ assert (imap->l_ns != LM_ID_BASE); > #endif >- --GL(dl_nloaded); >- if (imap->l_next) >+ GL(dl_ns)[imap->l_ns]._ns_loaded = imap->l_next; >+ } >+ >+ --GL(dl_ns)[imap->l_ns]._ns_nloaded; >+ if (imap->l_next != NULL) > imap->l_next->l_prev = imap->l_prev; > > free (imap->l_versions); >@@ -528,7 +579,7 @@ > if (any_tls) > { > if (__builtin_expect (++GL(dl_tls_generation) == 0, 0)) >- __libc_fatal (_("TLS generation counter wrapped! Please send report as described in <http://www.gnu.org/software/libc/bugs.html>.")); >+ __libc_fatal (_("TLS generation counter wrapped! Please report as described in <http://www.gnu.org/software/libc/bugs.html>.")); > > if (tls_free_end == GL(dl_tls_static_used)) > GL(dl_tls_static_used) = tls_free_start; >@@ -596,22 +647,26 @@ > > libc_freeres_fn (free_mem) > { >- if (__builtin_expect (GL(dl_global_scope_alloc), 0) != 0 >- && (GL(dl_main_searchlist)->r_nlist >- == GLRO(dl_initial_searchlist).r_nlist)) >- { >- /* All object dynamically loaded by the program are unloaded. Free >- the memory allocated for the global scope variable. */ >- struct link_map **old = GL(dl_main_searchlist)->r_list; >- >- /* Put the old map in. */ >- GL(dl_main_searchlist)->r_list = GLRO(dl_initial_searchlist).r_list; >- /* Signal that the original map is used. */ >- GL(dl_global_scope_alloc) = 0; >+ for (Lmid_t ns = 0; ns < DL_NNS; ++ns) >+ if (__builtin_expect (GL(dl_ns)[ns]._ns_global_scope_alloc, 0) != 0 >+ && (GL(dl_ns)[ns]._ns_main_searchlist->r_nlist >+ // XXX Check whether we need NS-specific initial_searchlist >+ == GLRO(dl_initial_searchlist).r_nlist)) >+ { >+ /* All object dynamically loaded by the program are unloaded. Free >+ the memory allocated for the global scope variable. */ >+ struct link_map **old = GL(dl_ns)[ns]._ns_main_searchlist->r_list; >+ >+ /* Put the old map in. */ >+ GL(dl_ns)[ns]._ns_main_searchlist->r_list >+ // XXX Check whether we need NS-specific initial_searchlist >+ = GLRO(dl_initial_searchlist).r_list; >+ /* Signal that the original map is used. */ >+ GL(dl_ns)[ns]._ns_global_scope_alloc = 0; > >- /* Now free the old map. */ >- free (old); >- } >+ /* Now free the old map. */ >+ free (old); >+ } > > #ifdef USE_TLS > if (USE___THREAD || GL(dl_tls_dtv_slotinfo_list) != NULL) >--- libc/elf/Makefile 2004/09/23 07:44:59 1.285 >+++ libc/elf/Makefile 2004/10/14 01:59:45 1.286 >@@ -154,7 +154,7 @@ > circleload1 tst-tls3 tst-tls4 tst-tls5 tst-tls6 tst-tls7 tst-tls8 \ > tst-tls10 tst-tls11 tst-tls12 tst-tls13 tst-tls14 tst-align \ > $(tests-execstack-$(have-z-execstack)) tst-dlmodcount \ >- tst-dlopenrpath tst-deep1 >+ tst-dlopenrpath tst-deep1 tst-dlmopen1 tst-dlmopen2 > # reldep9 > test-srcs = tst-pathopt > tests-vis-yes = vismain >@@ -187,7 +187,8 @@ > reldep8mod1 reldep8mod2 reldep8mod3 \ > reldep9mod1 reldep9mod2 reldep9mod3 \ > tst-alignmod $(modules-execstack-$(have-z-execstack)) \ >- tst-dlopenrpathmod tst-deep1mod1 tst-deep1mod2 tst-deep1mod3 >+ tst-dlopenrpathmod tst-deep1mod1 tst-deep1mod2 tst-deep1mod3 \ >+ tst-dlmopen1mod > ifeq (yes,$(have-initfini-array)) > modules-names += tst-array2dep > endif >@@ -762,3 +763,10 @@ > $(objpfx)tst-deep1.out: $(objpfx)tst-deep1mod2.so > LDFLAGS-tst-deep1 += -rdynamic > tst-deep1mod3.so-no-z-defs = yes >+ >+$(objpfx)tst-dlmopen1mod.so: $(libdl) >+$(objpfx)tst-dlmopen1: $(libdl) >+$(objpfx)tst-dlmopen1.out: $(objpfx)tst-dlmopen1mod.so >+ >+$(objpfx)tst-dlmopen2: $(libdl) >+$(objpfx)tst-dlmopen2.out: $(objpfx)tst-dlmopen1mod.so >--- libc/elf/tst-dlmopen2.c >+++ libc/elf/tst-dlmopen2.c 2004-11-30 17:40:10.937455000 +0000 >@@ -0,0 +1,70 @@ >+#include <dlfcn.h> >+#include <stdio.h> >+#include <string.h> >+#include <gnu/lib-names.h> >+#include <ldsodefs.h> >+ >+ >+static int >+do_test (void) >+{ >+ int result = 0; >+ >+ for (int i = 1; i <= 10; ++i) >+ { >+ void *h[DL_NNS - 1]; >+ char used[DL_NNS]; >+ >+ printf ("round %d\n", i); >+ >+ memset (used, '\0', sizeof (used)); >+ used[LM_ID_BASE] = 1; >+ >+ for (int j = 0; j < DL_NNS - 1; ++j) >+ { >+ h[j] = dlmopen (LM_ID_NEWLM, "$ORIGIN/tst-dlmopen1mod.so", >+ RTLD_LAZY); >+ if (h[j] == NULL) >+ { >+ printf ("round %d, namespace %d: load failed: %s\n", >+ i, j, dlerror ()); >+ return 1; >+ } >+ Lmid_t ns; >+ if (dlinfo (h[j], RTLD_DI_LMID, &ns) != 0) >+ { >+ printf ("round %d, namespace %d: dlinfo failed: %s\n", >+ i, j, dlerror ()); >+ return 1; >+ } >+ if (ns < 0 || ns >= DL_NNS) >+ { >+ printf ("round %d, namespace %d: invalid namespace %ld", >+ i, j, (long int) ns); >+ result = 1; >+ } >+ else if (used[ns] != 0) >+ { >+ printf ("\ >+round %d, namespace %d: duplicate allocate of namespace %ld", >+ i, j, (long int) ns); >+ result = 1; >+ } >+ else >+ used[ns] = 1; >+ } >+ >+ for (int j = 0; j < DL_NNS - 1; ++j) >+ if (dlclose (h[j]) != 0) >+ { >+ printf ("round %d, namespace %d: close failed: %s\n", >+ i, j, dlerror ()); >+ return 1; >+ } >+ } >+ >+ return result; >+} >+ >+#define TEST_FUNCTION do_test () >+#include "../test-skeleton.c" >--- libc/elf/tst-dlmopen1mod.c >+++ libc/elf/tst-dlmopen1mod.c 2004-11-30 17:41:04.643439000 +0000 >@@ -0,0 +1,38 @@ >+#include <dlfcn.h> >+#include <stdio.h> >+#include <gnu/lib-names.h> >+ >+ >+int >+foo (Lmid_t ns2) >+{ >+ void *h = dlopen (LIBC_SO, RTLD_LAZY|RTLD_NOLOAD); >+ if (h == NULL) >+ { >+ printf ("cannot get handle for %s: %s\n", LIBC_SO, dlerror ()); >+ return 1; >+ } >+ >+ Lmid_t ns = -10; >+ if (dlinfo (h, RTLD_DI_LMID, &ns) != 0) >+ { >+ printf ("dlinfo for %s in %s failed: %s\n", >+ LIBC_SO, __func__, dlerror ()); >+ return 1; >+ } >+ >+ if (ns != ns2) >+ { >+ printf ("namespace for %s not LM_ID_BASE\n", LIBC_SO); >+ return 1; >+ } >+ >+ if (dlclose (h) != 0) >+ { >+ printf ("dlclose for %s in %s failed: %s\n", >+ LIBC_SO, __func__, dlerror ()); >+ return 1; >+ } >+ >+ return 0; >+} >--- libc/elf/tst-dlmopen1.c >+++ libc/elf/tst-dlmopen1.c 2004-11-30 17:41:30.989715000 +0000 >@@ -0,0 +1,80 @@ >+#include <dlfcn.h> >+#include <stdio.h> >+#include <gnu/lib-names.h> >+ >+ >+static int >+do_test (void) >+{ >+ void *h = dlopen (LIBC_SO, RTLD_LAZY|RTLD_NOLOAD); >+ if (h == NULL) >+ { >+ printf ("cannot get handle for %s: %s\n", LIBC_SO, dlerror ()); >+ return 1; >+ } >+ >+ Lmid_t ns = -10; >+ if (dlinfo (h, RTLD_DI_LMID, &ns) != 0) >+ { >+ printf ("dlinfo for %s in %s failed: %s\n", >+ LIBC_SO, __func__, dlerror ()); >+ return 1; >+ } >+ >+ if (ns != LM_ID_BASE) >+ { >+ printf ("namespace for %s not LM_ID_BASE\n", LIBC_SO); >+ return 1; >+ } >+ >+ if (dlclose (h) != 0) >+ { >+ printf ("dlclose for %s in %s failed: %s\n", >+ LIBC_SO, __func__, dlerror ()); >+ return 1; >+ } >+ >+ h = dlmopen (LM_ID_NEWLM, "$ORIGIN/tst-dlmopen1mod.so", RTLD_LAZY); >+ if (h == NULL) >+ { >+ printf ("cannot get handle for %s: %s\n", >+ "tst-dlmopen1mod.so", dlerror ()); >+ return 1; >+ } >+ >+ ns = -10; >+ if (dlinfo (h, RTLD_DI_LMID, &ns) != 0) >+ { >+ printf ("dlinfo for %s in %s failed: %s\n", >+ "tst-dlmopen1mod.so", __func__, dlerror ()); >+ return 1; >+ } >+ >+ if (ns == LM_ID_BASE) >+ { >+ printf ("namespace for %s is LM_ID_BASE\n", LIBC_SO); >+ return 1; >+ } >+ >+ int (*fct) (Lmid_t) = dlsym (h, "foo"); >+ if (fct == NULL) >+ { >+ printf ("could not find %s: %s\n", "foo", dlerror ()); >+ return 1; >+ } >+ >+ if (fct (ns) != 0) >+ return 1; >+ >+ if (dlclose (h) != 0) >+ { >+ printf ("dlclose for %s in %s failed: %s\n", >+ LIBC_SO, __func__, dlerror ()); >+ return 1; >+ } >+ >+ return 0; >+} >+ >+#define TEST_FUNCTION do_test () >+#include "../test-skeleton.c" >--- libc/include/link.h 2004/09/18 06:42:31 1.32 >+++ libc/include/link.h 2004/10/14 01:57:54 1.33 >@@ -129,6 +129,14 @@ > /* All following members are internal to the dynamic linker. > They may change without notice. */ > >+ /* This is an element which is only ever different from a pointer to >+ the very same copy of this type for ld.so when it is used in more >+ than one namespace. */ >+ struct link_map *l_real; >+ >+ /* Number of the namespace this link map belongs to. */ >+ Lmid_t l_ns; >+ > struct libname_list *l_libname; > /* Indexed pointers to dynamic section. > [0,DT_NUM) are indexed by the processor-independent tags. >@@ -169,7 +177,8 @@ > Elf_Symndx l_nbuckets; > const Elf_Symndx *l_buckets, *l_chain; > >- unsigned int l_opencount; /* Reference count for dlopen/dlclose. */ >+ unsigned int l_opencount; /* Counter for direct and indirect usage. */ >+ unsigned int l_direct_opencount; /* Reference count for dlopen/dlclose. */ > enum /* Where this object came from. */ > { > lt_executable, /* The main executable program. */ >--- libc/include/dlfcn.h 2004/08/09 06:38:03 1.17 >+++ libc/include/dlfcn.h 2004/10/14 01:57:25 1.18 >@@ -8,6 +8,8 @@ > #define __RTLD_OPENEXEC 0x20000000 > #define __RTLD_CALLMAP 0x10000000 > >+#define __LM_ID_CALLER -2 >+ > /* Now define the internal interfaces. */ > extern void *__dlvsym (void *__handle, __const char *__name, > __const char *__version); >@@ -31,7 +33,8 @@ > /* Open the shared object NAME, relocate it, and run its initializer if it > hasn't already been run. MODE is as for `dlopen' (see <dlfcn.h>). If > the object is already opened, returns its existing map. */ >-extern void *_dl_open (const char *name, int mode, const void *caller) >+extern void *_dl_open (const char *name, int mode, const void *caller, >+ Lmid_t nsid) > internal_function; > libc_hidden_proto (_dl_open) > >--- libc/malloc/malloc.c 2004/10/06 18:01:28 1.130 >+++ libc/malloc/malloc.c 2004/10/14 01:56:52 1.131 >@@ -24,7 +24,7 @@ > Doug Lea and adapted to multiple threads/arenas by Wolfram Gloger. > > * Version ptmalloc2-20011215 >- $Id: malloc.c,v 1.130 2004/10/06 18:01:28 drepper Exp $ >+ $Id: malloc.c,v 1.131 2004/10/14 01:56:52 drepper Exp $ > based on: > VERSION 2.7.0 Sun Mar 11 14:14:06 2001 Doug Lea (dl at gee) > >@@ -289,9 +289,13 @@ > > /* For writev and struct iovec. */ > #include <sys/uio.h> >- /* For syslog. */ >+/* For syslog. */ > #include <sys/syslog.h> > >+/* For various dynamic linking things. */ >+#include <dlfcn.h> >+ >+ > /* > Debugging: > >--- libc/malloc/arena.c 2004/10/04 02:27:14 1.10 >+++ libc/malloc/arena.c 2004/10/14 01:55:55 1.11 >@@ -18,7 +18,7 @@ > write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, > Boston, MA 02111-1307, USA. */ > >-/* $Id: arena.c,v 1.10 2004/10/04 02:27:14 drepper Exp $ */ >+/* $Id: arena.c,v 1.11 2004/10/14 01:55:55 drepper Exp $ */ > > /* Compile-time constants. */ > >@@ -339,7 +339,16 @@ > mp_.pagesize = malloc_getpagesize; > } > >+ > #ifdef _LIBC >+# ifdef SHARED >+static void * >+__failing_morecore (ptrdiff_t d) >+{ >+ return (void *) MORECORE_FAILURE; >+} >+# endif >+ > # if defined SHARED && defined USE_TLS && !USE___THREAD > # include <stdbool.h> > >@@ -419,6 +428,14 @@ > mutex_init(&main_arena.mutex); > main_arena.next = &main_arena; > >+#if defined _LIBC && defined SHARED >+ /* In case this libc copy is in a non-default namespace, never use brk. */ >+ Dl_info di; >+ struct link_map *l; >+ if (_dl_addr (ptmalloc_init, &di, &l, NULL) != 0 && l->l_ns != LM_ID_BASE) >+ __morecore = __failing_morecore; >+#endif >+ > mutex_init(&list_lock); > tsd_key_create(&arena_key, NULL); > tsd_setspecific(arena_key, (Void_t *)&main_arena); >--- libc/sysdeps/generic/dl-tls.c 2004/03/06 08:12:40 1.42 >+++ libc/sysdeps/generic/dl-tls.c 2004/10/14 01:55:20 1.43 >@@ -33,7 +33,7 @@ > > /* Amount of excess space to allocate in the static TLS area > to allow dynamic loading of modules defining IE-model TLS data. */ >-# define TLS_STATIC_SURPLUS 64 >+# define TLS_STATIC_SURPLUS 64 + DL_NNS * 100 > > /* Value used for dtv entries for which the allocation is delayed. */ > # define TLS_DTV_UNALLOCATED ((void *) -1l) >--- libc/sysdeps/generic/ldsodefs.h 2004/09/23 07:37:38 1.103 >+++ libc/sysdeps/generic/ldsodefs.h 2004/10/14 01:54:41 1.104 >@@ -216,18 +216,27 @@ > /* Don't change the order of the following elements. 'dl_loaded' > must remain the first element. Forever. */ > >- /* And a pointer to the map for the main map. */ >- EXTERN struct link_map *_dl_loaded; >- /* Number of object in the _dl_loaded list. */ >- EXTERN unsigned int _dl_nloaded; >- /* Array representing global scope. */ >- EXTERN struct r_scope_elem *_dl_global_scope[2]; >- /* Direct pointer to the searchlist of the main object. */ >- EXTERN struct r_scope_elem *_dl_main_searchlist; >- /* This is zero at program start to signal that the global scope map is >- allocated by rtld. Later it keeps the size of the map. It might be >- reset if in _dl_close if the last global object is removed. */ >- EXTERN size_t _dl_global_scope_alloc; >+/* Non-shared code has no support for multiple namespaces. */ >+#ifdef SHARED >+# define DL_NNS 16 >+#else >+# define DL_NNS 1 >+#endif >+ EXTERN struct link_namespaces >+ { >+ /* And a pointer to the map for the main map. */ >+ struct link_map *_ns_loaded; >+ /* Number of object in the _dl_loaded list. */ >+ unsigned int _ns_nloaded; >+ /* Array representing global scope. */ >+ struct r_scope_elem *_ns_global_scope[2]; >+ /* Direct pointer to the searchlist of the main object. */ >+ struct r_scope_elem *_ns_main_searchlist; >+ /* This is zero at program start to signal that the global scope map is >+ allocated by rtld. Later it keeps the size of the map. It might be >+ reset if in _dl_close if the last global object is removed. */ >+ size_t _ns_global_scope_alloc; >+ } _dl_ns[DL_NNS]; > > /* During the program run we must not modify the global data of > loaded shared object simultanously in two threads. Therefore we >@@ -477,7 +486,7 @@ > char *(*_dl_dst_substitute) (struct link_map *, const char *, char *, int); > struct link_map *(internal_function *_dl_map_object) (struct link_map *, > const char *, int, >- int, int, int); >+ int, int, int, Lmid_t); > void (internal_function *_dl_map_object_deps) (struct link_map *, > struct link_map **, > unsigned int, int, int); >@@ -658,7 +667,8 @@ > value to allow additional security checks. */ > extern struct link_map *_dl_map_object (struct link_map *loader, > const char *name, int preloaded, >- int type, int trace_mode, int mode) >+ int type, int trace_mode, int mode, >+ Lmid_t nsid) > internal_function attribute_hidden; > > /* Call _dl_map_object on the dependencies of MAP, and set up >@@ -723,7 +733,7 @@ > and enter it into the _dl_main_map list. */ > extern struct link_map *_dl_new_object (char *realname, const char *libname, > int type, struct link_map *loader, >- int mode) >+ int mode, Lmid_t nsid) > internal_function attribute_hidden; > > /* Relocate the given object (if it hasn't already been). >--- libc/sysdeps/unix/sysv/linux/i386/dl-librecon.h 2004/03/05 10:14:47 1.14 >+++ libc/sysdeps/unix/sysv/linux/i386/dl-librecon.h 2004/10/14 01:53:55 1.15 >@@ -28,15 +28,15 @@ > /* We have to find out whether the binary is linked against \ > libc 5 or glibc. We do this by looking at all the DT_NEEDED \ > entries. If one is libc.so.5 this is a libc 5 linked binary. */ \ >- if (GL(dl_loaded)->l_info[DT_NEEDED]) \ >+ if (main_map->l_info[DT_NEEDED]) \ > { \ > /* We have dependencies. */ \ > const ElfW(Dyn) *d; \ > const char *strtab; \ > \ >- strtab = (const char *) D_PTR (GL(dl_loaded), l_info[DT_STRTAB]); \ >+ strtab = (const char *) D_PTR (main_map, l_info[DT_STRTAB]); \ > \ >- for (d = GL(dl_loaded)->l_ld; d->d_tag != DT_NULL; ++d) \ >+ for (d = main_map->l_ld; d->d_tag != DT_NULL; ++d) \ > if (d->d_tag == DT_NEEDED \ > && strcmp (strtab + d->d_un.d_val, "libc.so.5") == 0) \ > break; \ >--- libc/elf/dl-version.c 2004/03/06 08:12:41 1.38 >+++ libc/elf/dl-version.c 2004/10/14 01:53:55 1.39 >@@ -59,7 +59,8 @@ > struct link_map *tmap; > unsigned int n; > >- for (tmap = GL(dl_loaded); tmap != NULL; tmap = tmap->l_next) >+ for (tmap = GL(dl_ns)[map->l_ns]._ns_loaded; tmap != NULL; >+ tmap = tmap->l_next) > if (_dl_name_match_p (name, tmap)) > return tmap; > >@@ -243,7 +244,7 @@ > ? map->l_name : rtld_progname), > aux->vna_hash, > strtab + aux->vna_name, >- needed, verbose, >+ needed->l_real, verbose, > aux->vna_flags & VER_FLG_WEAK); > > /* Compare the version index. */ >--- libc/elf/dl-sym.c 2004/10/11 07:10:47 1.23 >+++ libc/elf/dl-sym.c 2004/10/14 01:53:55 1.24 >@@ -69,17 +69,19 @@ > > /* If the address is not recognized the call comes from the main > program (we hope). */ >- struct link_map *match = GL(dl_loaded); >+ struct link_map *match = GL(dl_ns)[LM_ID_BASE]._ns_loaded; > > /* Find the highest-addressed object that CALLER is not below. */ >- for (struct link_map *l = GL(dl_loaded); l != NULL; l = l->l_next) >- if (caller >= l->l_map_start && caller < l->l_map_end) >- { >- /* There must be exactly one DSO for the range of the virtual >- memory. Otherwise something is really broken. */ >- match = l; >- break; >- } >+ for (Lmid_t ns = 0; ns < DL_NNS; ++ns) >+ for (struct link_map *l = GL(dl_ns)[ns]._ns_loaded; l != NULL; >+ l = l->l_next) >+ if (caller >= l->l_map_start && caller < l->l_map_end) >+ { >+ /* There must be exactly one DSO for the range of the virtual >+ memory. Otherwise something is really broken. */ >+ match = l; >+ break; >+ } > > if (handle == RTLD_DEFAULT) > /* Search the global scope. */ >@@ -88,7 +90,7 @@ > NULL); > else if (handle == RTLD_NEXT) > { >- if (__builtin_expect (match == GL(dl_loaded), 0)) >+ if (__builtin_expect (match == GL(dl_ns)[LM_ID_BASE]._ns_loaded, 0)) > { > if (match == NULL > || caller < match->l_map_start >--- libc/elf/dl-debug.c 2004/03/06 08:12:41 1.11 >+++ libc/elf/dl-debug.c 2004/10/14 01:53:55 1.12 >@@ -39,7 +39,9 @@ > /* Tell the debugger where to find the map of loaded objects. */ > _r_debug.r_version = 1 /* R_DEBUG_VERSION XXX */; > _r_debug.r_ldbase = ldbase; >- _r_debug.r_map = GL(dl_loaded); >+ // XXX This is problematic. It means we cannot tell the debugger >+ // XXX about namespaces other than the main one. >+ _r_debug.r_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded; > _r_debug.r_brk = (ElfW(Addr)) &_dl_debug_state; > } > >--- libc/elf/dl-conflict.c 2004/03/05 10:14:50 1.11 >+++ libc/elf/dl-conflict.c 2004/10/14 01:53:55 1.12 >@@ -54,8 +54,10 @@ > (map) = resolve_conflict_map; \ > } while (0) > >+ /* Prelinking makes no sense for anything but the main namespace. */ >+ assert (l->l_ns == LM_ID_BASE); > struct link_map *resolve_conflict_map __attribute__ ((__unused__)) >- = GL(dl_loaded); >+ = GL(dl_ns)[LM_ID_BASE]._ns_loaded; > > #include "dynamic-link.h" > >--- libc/elf/dl-caller.c 2004/03/27 03:14:19 1.1 >+++ libc/elf/dl-caller.c 2004/10/14 01:53:55 1.2 >@@ -35,44 +35,46 @@ > #endif > static const char expected4[] = LD_SO; > >- for (struct link_map *l = GL(dl_loaded); l != NULL; l = l->l_next) >- if (caller >= (const void *) l->l_map_start >- && caller < (const void *) l->l_text_end) >- { >- /* The address falls into this DSO's address range. Check the >- name. */ >- if ((mask & allow_libc) && strcmp (expected1, l->l_name) == 0) >- return 0; >- if ((mask & allow_libdl) && strcmp (expected2, l->l_name) == 0) >- return 0; >+ for (Lmid_t ns = 0; ns < DL_NNS; ++ns) >+ for (struct link_map *l = GL(dl_ns)[ns]._ns_loaded; l != NULL; >+ l = l->l_next) >+ if (caller >= (const void *) l->l_map_start >+ && caller < (const void *) l->l_text_end) >+ { >+ /* The address falls into this DSO's address range. Check the >+ name. */ >+ if ((mask & allow_libc) && strcmp (expected1, l->l_name) == 0) >+ return 0; >+ if ((mask & allow_libdl) && strcmp (expected2, l->l_name) == 0) >+ return 0; > #ifdef LIBPTHREAD_SO >- if ((mask & allow_libpthread) && strcmp (expected3, l->l_name) == 0) >- return 0; >+ if ((mask & allow_libpthread) && strcmp (expected3, l->l_name) == 0) >+ return 0; > #endif >- if ((mask & allow_ldso) && strcmp (expected4, l->l_name) == 0) >- return 0; >+ if ((mask & allow_ldso) && strcmp (expected4, l->l_name) == 0) >+ return 0; > >- struct libname_list *runp = l->l_libname; >+ struct libname_list *runp = l->l_libname; > >- while (runp != NULL) >- { >- if ((mask & allow_libc) && strcmp (expected1, runp->name) == 0) >- return 0; >- if ((mask & allow_libdl) && strcmp (expected2, runp->name) == 0) >- return 0; >+ while (runp != NULL) >+ { >+ if ((mask & allow_libc) && strcmp (expected1, runp->name) == 0) >+ return 0; >+ if ((mask & allow_libdl) && strcmp (expected2, runp->name) == 0) >+ return 0; > #ifdef LIBPTHREAD_SO >- if ((mask & allow_libpthread) >- && strcmp (expected3, runp->name) == 0) >- return 0; >+ if ((mask & allow_libpthread) >+ && strcmp (expected3, runp->name) == 0) >+ return 0; > #endif >- if ((mask & allow_ldso) && strcmp (expected4, runp->name) == 0) >- return 0; >+ if ((mask & allow_ldso) && strcmp (expected4, runp->name) == 0) >+ return 0; > >- runp = runp->next; >- } >+ runp = runp->next; >+ } > >- break; >- } >+ break; >+ } > > /* Maybe the dynamic linker is not yet on the list. */ > if ((mask & allow_ldso) != 0 >--- libc/elf/dl-addr.c 2004/10/11 07:08:08 1.22 >+++ libc/elf/dl-addr.c 2004/10/14 01:53:55 1.23 >@@ -38,26 +38,27 @@ > > /* Find the highest-addressed object that ADDRESS is not below. */ > match = NULL; >- for (struct link_map *l = GL(dl_loaded); l; l = l->l_next) >- if (addr >= l->l_map_start && addr < l->l_map_end) >- { >- /* We know ADDRESS lies within L if in any shared object. >- Make sure it isn't past the end of L's segments. */ >- size_t n = l->l_phnum; >- if (n > 0) >- { >- do >- --n; >- while (l->l_phdr[n].p_type != PT_LOAD); >- if (addr >= (l->l_addr + >- l->l_phdr[n].p_vaddr + l->l_phdr[n].p_memsz)) >- /* Off the end of the highest-addressed shared object. */ >- continue; >- } >- >- match = l; >- break; >- } >+ for (Lmid_t ns = 0; ns < DL_NNS; ++ns) >+ for (struct link_map *l = GL(dl_ns)[ns]._ns_loaded; l; l = l->l_next) >+ if (addr >= l->l_map_start && addr < l->l_map_end) >+ { >+ /* We know ADDRESS lies within L if in any shared object. >+ Make sure it isn't past the end of L's segments. */ >+ size_t n = l->l_phnum; >+ if (n > 0) >+ { >+ do >+ --n; >+ while (l->l_phdr[n].p_type != PT_LOAD); >+ if (addr >= (l->l_addr + >+ l->l_phdr[n].p_vaddr + l->l_phdr[n].p_memsz)) >+ /* Off the end of the highest-addressed shared object. */ >+ continue; >+ } >+ >+ match = l; >+ break; >+ } > > int result = 0; > if (match != NULL) >--- libc/dlfcn/dlopenold.c 2001/07/06 04:54:45 1.7 >+++ libc/dlfcn/dlopenold.c 2004/10/14 01:48:54 1.8 >@@ -1,5 +1,5 @@ > /* Load a shared object at run time. >- Copyright (C) 1995-1999, 2000 Free Software Foundation, Inc. >+ Copyright (C) 1995-1999, 2000, 2004 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 >@@ -37,13 +37,21 @@ > }; > > >+/* Non-shared code has no support for multiple namespaces. */ >+#ifdef SHARED >+# define NS __LM_ID_CALLER >+#else >+# define NS LM_ID_BASE >+#endif >+ >+ > static void > dlopen_doit (void *a) > { > struct dlopen_args *args = (struct dlopen_args *) a; > > args->new = _dl_open (args->file ?: "", args->mode | __RTLD_DLOPEN, >- args->caller); >+ args->caller, args->file == NULL ? LM_ID_BASE : NS); > } > > extern void *__dlopen_nocheck (const char *file, int mode); >--- libc/dlfcn/dlopen.c 2003/09/19 20:40:11 1.8 >+++ libc/dlfcn/dlopen.c 2004/10/14 01:48:54 1.9 >@@ -1,5 +1,5 @@ > /* Load a shared object at run time. >- Copyright (C) 1995,96,97,98,99,2000,2003 Free Software Foundation, Inc. >+ Copyright (C) 1995,96,97,98,99,2000,2003,2004 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 >@@ -31,13 +31,22 @@ > const void *caller; > }; > >+ >+/* Non-shared code has no support for multiple namespaces. */ >+#ifdef SHARED >+# define NS __LM_ID_CALLER >+#else >+# define NS LM_ID_BASE >+#endif >+ >+ > static void > dlopen_doit (void *a) > { > struct dlopen_args *args = (struct dlopen_args *) a; > > args->new = _dl_open (args->file ?: "", args->mode | __RTLD_DLOPEN, >- args->caller); >+ args->caller, args->file == NULL ? LM_ID_BASE : NS); > } > > >--- libc/dlfcn/dlinfo.c 2004/03/06 08:09:14 1.2 >+++ libc/dlfcn/dlinfo.c 2004/10/14 01:48:22 1.3 >@@ -55,12 +55,15 @@ > > switch (args->request) > { >- case RTLD_DI_LMID: > case RTLD_DI_CONFIGADDR: > default: > GLRO(dl_signal_error) (0, NULL, NULL, N_("unsupported dlinfo request")); > break; > >+ case RTLD_DI_LMID: >+ *(Lmid_t *) args->arg = l->l_ns; >+ break; >+ > case RTLD_DI_LINKMAP: > *(struct link_map **) args->arg = l; > break; >--- libc/dlfcn/dlfcn.h 2003/07/15 06:48:45 1.13 >+++ libc/dlfcn/dlfcn.h 2004/10/14 01:47:53 1.14 >@@ -1,5 +1,5 @@ > /* User functions for run-time dynamic loading. >- Copyright (C) 1995-1999,2000,2001,2003 Free Software Foundation, Inc. >+ Copyright (C) 1995-1999,2000,2001,2003,2004 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 >@@ -39,6 +39,14 @@ > the run-time address of the symbol called NAME in the global scope > is returned. */ > # define RTLD_DEFAULT ((void *) 0) >+ >+ >+/* Type for namespace indeces. */ >+typedef long int Lmid_t; >+ >+/* Special namespace ID values. */ >+# define LM_ID_BASE 0 /* Initial namespace. */ >+# define LM_ID_NEWLM -1 /* For dlmopen: request new namespace. */ > #endif > > >@@ -58,6 +66,9 @@ > __const char *__restrict __name) __THROW; > > #ifdef __USE_GNU >+/* Like `dlopen', but request object to be allocated in a new namespace. */ >+extern void *dlmopen (Lmid_t __nsid, __const char *__file, int __mode) __THROW; >+ > /* Find the run-time address in the shared object HANDLE refers to > of the symbol called NAME with VERSION. */ > extern void *dlvsym (void *__restrict __handle, >@@ -114,6 +125,9 @@ > /* These are the possible values for the REQUEST argument to `dlinfo'. */ > enum > { >+ /* Treat ARG as `lmid_t *'; store namespace ID for HANDLE there. */ >+ RTLD_DI_LMID = 1, >+ > /* Treat ARG as `struct link_map **'; > store the `struct link_map *' for HANDLE there. */ > RTLD_DI_LINKMAP = 2, >@@ -130,7 +144,6 @@ > expand $ORIGIN in this shared object's dependency file names. */ > RTLD_DI_ORIGIN = 6, > >- RTLD_DI_LMID = 1, /* Unsupported, defined by Solaris. */ > RTLD_DI_CONFIGADDR = 3 /* Unsupported, defined by Solaris. */ > }; > >--- libc/dlfcn/Versions 2003/03/15 23:14:44 1.3 >+++ libc/dlfcn/Versions 2004/10/14 01:47:20 1.4 >@@ -8,4 +8,7 @@ > GLIBC_2.3.3 { > dladdr1; dlinfo; > } >+ GLIBC_2.3.4 { >+ dlmopen; >+ } > } >--- libc/dlfcn/Makefile 2004/08/21 09:25:46 1.32 >+++ libc/dlfcn/Makefile 2004/10/14 01:46:57 1.33 >@@ -19,7 +19,8 @@ > subdir := dlfcn > headers := bits/dlfcn.h dlfcn.h > extra-libs := libdl >-libdl-routines := dlopen dlclose dlsym dlvsym dlerror dladdr dladdr1 dlinfo >+libdl-routines := dlopen dlclose dlsym dlvsym dlerror dladdr dladdr1 dlinfo \ >+ dlmopen > distribute := dlopenold.c glreflib1.c glreflib2.c failtestmod.c \ > defaultmod1.c defaultmod2.c errmsg1mod.c modatexit.c \ > modcxaatexit.c modstatic.c \ >--- libc/dlfcn/dlmopen.c >+++ libc/dlfcn/dlmopen.c 2004-11-30 17:48:32.586386000 +0000 >@@ -0,0 +1,69 @@ >+/* Load a shared object at run time. >+ Copyright (C) 1995,96,97,98,99,2000,2003,2004 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 >+ modify it under the terms of the GNU Lesser General Public >+ License as published by the Free Software Foundation; either >+ version 2.1 of the License, or (at your option) any later version. >+ >+ The GNU C Library is distributed in the hope that it will be useful, >+ but WITHOUT ANY WARRANTY; without even the implied warranty of >+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU >+ Lesser General Public License for more details. >+ >+ You should have received a copy of the GNU Lesser General Public >+ License along with the GNU C Library; if not, write to the Free >+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA >+ 02111-1307 USA. */ >+ >+#include <dlfcn.h> >+#include <errno.h> >+#include <libintl.h> >+#include <stddef.h> >+#include <ldsodefs.h> >+ >+struct dlmopen_args >+{ >+ /* Namespace ID. */ >+ Lmid_t nsid; >+ /* The arguments for dlopen_doit. */ >+ const char *file; >+ int mode; >+ /* The return value of dlopen_doit. */ >+ void *new; >+ /* Address of the caller. */ >+ const void *caller; >+}; >+ >+static void >+dlmopen_doit (void *a) >+{ >+ struct dlmopen_args *args = (struct dlmopen_args *) a; >+ >+ /* Non-shared code has no support for multiple namespaces. */ >+ if (args->nsid != LM_ID_BASE) >+#ifdef SHARED >+ /* If trying to open the link map for the main executable the namespace >+ must be the main one. */ >+ if (args->file == NULL) >+#endif >+ GLRO(dl_signal_error) (EINVAL, NULL, NULL, N_("invalid namespace")); >+ >+ args->new = _dl_open (args->file ?: "", args->mode | __RTLD_DLOPEN, >+ args->caller, args->nsid); >+} >+ >+ >+void * >+dlmopen (Lmid_t nsid, const char *file, int mode) >+{ >+ struct dlmopen_args args; >+ args.nsid = nsid; >+ args.file = file; >+ args.mode = mode; >+ args.caller = RETURN_ADDRESS (0); >+ >+ return _dlerror_run (dlmopen_doit, &args) ? NULL : args.new; >+} >+static_link_warning (dlmopen)
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 72343
:
44660
|
44918
| 45006 |
45073