about summary refs log tree commit diff
path: root/elf/dl-support.c
diff options
context:
space:
mode:
authorMaciej W. Rozycki <macro@codesourcery.com>2013-06-28 16:20:26 +0100
committerMaciej W. Rozycki <macro@codesourcery.com>2013-06-28 16:22:20 +0100
commitf91f1c0fb89056995f1c9c6a06c361efdf5139e7 (patch)
tree67db98c499e8dbd72bc5b49e654706d375384c0f /elf/dl-support.c
parented0257f7d3378ec4a72e297f0dcba5159f2dd138 (diff)
downloadglibc-f91f1c0fb89056995f1c9c6a06c361efdf5139e7.tar.gz
glibc-f91f1c0fb89056995f1c9c6a06c361efdf5139e7.tar.xz
glibc-f91f1c0fb89056995f1c9c6a06c361efdf5139e7.zip
[BZ #15022] Correct global-scope dlopen issues in static executables.
This change creates a link map in static executables to serve as the
global search list for dlopen.  It fixes a problem with the inability
to access the global symbol object and a crash on an attempt to map a
DSO into the global scope.  Some code that has become dead after the
addition of this link map is removed too and test cases are provided.
Diffstat (limited to 'elf/dl-support.c')
-rw-r--r--elf/dl-support.c51
1 files changed, 44 insertions, 7 deletions
diff --git a/elf/dl-support.c b/elf/dl-support.c
index b3ab9560ad..76752f33f3 100644
--- a/elf/dl-support.c
+++ b/elf/dl-support.c
@@ -70,17 +70,52 @@ const char *_dl_origin_path;
 /* Nonzero if runtime lookup should not update the .got/.plt.  */
 int _dl_bind_not;
 
+/* A dummy link map for the executable, used by dlopen to access the global
+   scope.  We don't export any symbols ourselves, so this can be minimal.  */
+static struct link_map _dl_main_map =
+  {
+    .l_name = (char *) "",
+    .l_real = &_dl_main_map,
+    .l_ns = LM_ID_BASE,
+    .l_libname = &(struct libname_list) { .name = "", .dont_free = 1 },
+    .l_searchlist =
+      {
+	.r_list = &(struct link_map *) { &_dl_main_map },
+	.r_nlist = 1,
+      },
+    .l_symbolic_searchlist = { .r_list = &(struct link_map *) { NULL } },
+    .l_type = lt_executable,
+    .l_scope_mem = { &_dl_main_map.l_searchlist },
+    .l_scope_max = (sizeof (_dl_main_map.l_scope_mem)
+		    / sizeof (_dl_main_map.l_scope_mem[0])),
+    .l_scope = _dl_main_map.l_scope_mem,
+    .l_local_scope = { &_dl_main_map.l_searchlist },
+    .l_used = 1,
+    .l_tls_offset = NO_TLS_OFFSET,
+    .l_serial = 1,
+  };
+
 /* Namespace information.  */
-struct link_namespaces _dl_ns[DL_NNS];
-size_t _dl_nns;
+struct link_namespaces _dl_ns[DL_NNS] =
+  {
+    [LM_ID_BASE] =
+      {
+	._ns_loaded = &_dl_main_map,
+	._ns_nloaded = 1,
+	._ns_main_searchlist = &_dl_main_map.l_searchlist,
+      }
+  };
+size_t _dl_nns = 1;
 
 /* Incremented whenever something may have been added to dl_loaded. */
-unsigned long long _dl_load_adds;
+unsigned long long _dl_load_adds = 1;
 
-/* Fake scope.  In dynamically linked binaries this is the scope of the
-   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;
+/* Fake scope of the main application.  */
+struct r_scope_elem _dl_initial_searchlist =
+  {
+    .r_list = &(struct link_map *) { &_dl_main_map },
+    .r_nlist = 1,
+  };
 
 #ifndef HAVE_INLINED_SYSCALLS
 /* Nonzero during startup.  */
@@ -265,6 +300,8 @@ void
 internal_function
 _dl_non_dynamic_init (void)
 {
+  _dl_main_map.l_origin = _dl_get_origin ();
+
   if (HP_TIMING_AVAIL)
     HP_TIMING_NOW (_dl_cpuclock_offset);