1 /* dlinfo -- Get information from the dynamic linker.
2    Copyright (C) 2003-2021 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4 
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9 
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14 
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, see
17    <https://www.gnu.org/licenses/>.  */
18 
19 #include <dlfcn.h>
20 #include <link.h>
21 #include <ldsodefs.h>
22 #include <libintl.h>
23 #include <dl-tls.h>
24 #include <shlib-compat.h>
25 
26 struct dlinfo_args
27 {
28   void *handle;
29   int request;
30   void *arg;
31 };
32 
33 static void
dlinfo_doit(void * argsblock)34 dlinfo_doit (void *argsblock)
35 {
36   struct dlinfo_args *const args = argsblock;
37   struct link_map *l = args->handle;
38 
39   switch (args->request)
40     {
41     case RTLD_DI_CONFIGADDR:
42     default:
43       _dl_signal_error (0, NULL, NULL, N_("unsupported dlinfo request"));
44       break;
45 
46     case RTLD_DI_LMID:
47       *(Lmid_t *) args->arg = l->l_ns;
48       break;
49 
50     case RTLD_DI_LINKMAP:
51       *(struct link_map **) args->arg = l;
52       break;
53 
54     case RTLD_DI_SERINFO:
55       _dl_rtld_di_serinfo (l, args->arg, false);
56       break;
57     case RTLD_DI_SERINFOSIZE:
58       _dl_rtld_di_serinfo (l, args->arg, true);
59       break;
60 
61     case RTLD_DI_ORIGIN:
62       strcpy (args->arg, l->l_origin);
63       break;
64 
65     case RTLD_DI_TLS_MODID:
66       *(size_t *) args->arg = 0;
67       *(size_t *) args->arg = l->l_tls_modid;
68       break;
69 
70     case RTLD_DI_TLS_DATA:
71       {
72 	void *data = NULL;
73 	if (l->l_tls_modid != 0)
74 	  data = GLRO(dl_tls_get_addr_soft) (l);
75 	*(void **) args->arg = data;
76 	break;
77       }
78     }
79 }
80 
81 static int
dlinfo_implementation(void * handle,int request,void * arg)82 dlinfo_implementation (void *handle, int request, void *arg)
83 {
84   struct dlinfo_args args = { handle, request, arg };
85   return _dlerror_run (&dlinfo_doit, &args) ? -1 : 0;
86 }
87 
88 #ifdef SHARED
89 int
___dlinfo(void * handle,int request,void * arg)90 ___dlinfo (void *handle, int request, void *arg)
91 {
92   if (!rtld_active ())
93     return GLRO (dl_dlfcn_hook)->dlinfo (handle, request, arg);
94   else
95     return dlinfo_implementation (handle, request, arg);
96 }
97 versioned_symbol (libc, ___dlinfo, dlinfo, GLIBC_2_34);
98 
99 # if OTHER_SHLIB_COMPAT (libdl, GLIBC_2_3_3, GLIBC_2_34)
100 compat_symbol (libc, ___dlinfo, dlinfo, GLIBC_2_3_3);
101 # endif
102 #else /* !SHARED */
103 /* Also used with _dlfcn_hook.  */
104 int
__dlinfo(void * handle,int request,void * arg)105 __dlinfo (void *handle, int request, void *arg)
106 {
107   return dlinfo_implementation (handle, request, arg);
108 }
109 weak_alias (__dlinfo, dlinfo)
110 #endif
111