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
26struct dlinfo_args
27{
28 void *handle;
29 int request;
30 void *arg;
31};
32
33static void
34dlinfo_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
81static int
82dlinfo_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
89int
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}
97versioned_symbol (libc, ___dlinfo, dlinfo, GLIBC_2_34);
98
99# if OTHER_SHLIB_COMPAT (libdl, GLIBC_2_3_3, GLIBC_2_34)
100compat_symbol (libc, ___dlinfo, dlinfo, GLIBC_2_3_3);
101# endif
102#else /* !SHARED */
103/* Also used with _dlfcn_hook. */
104int
105__dlinfo (void *handle, int request, void *arg)
106{
107 return dlinfo_implementation (handle, request, arg);
108}
109weak_alias (__dlinfo, dlinfo)
110#endif
111