packaging: Enable memcpy in sysdeps/arm/memcpy.S for ARM
[platform/upstream/glibc.git] / dlfcn / dlinfo.c
1 /* dlinfo -- Get information from the dynamic linker.
2    Copyright (C) 2003-2024 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   /* This is the value that is returned from dlinfo if no error is
33      signaled.  */
34   int result;
35 };
36
37 static void
38 dlinfo_doit (void *argsblock)
39 {
40   struct dlinfo_args *const args = argsblock;
41   struct link_map *l = args->handle;
42
43   switch (args->request)
44     {
45     case RTLD_DI_CONFIGADDR:
46     default:
47       args->result = -1;
48       _dl_signal_error (0, NULL, NULL, N_("unsupported dlinfo request"));
49       break;
50
51     case RTLD_DI_LMID:
52       *(Lmid_t *) args->arg = l->l_ns;
53       break;
54
55     case RTLD_DI_LINKMAP:
56       *(struct link_map **) args->arg = l;
57       break;
58
59     case RTLD_DI_SERINFO:
60       _dl_rtld_di_serinfo (l, args->arg, false);
61       break;
62     case RTLD_DI_SERINFOSIZE:
63       _dl_rtld_di_serinfo (l, args->arg, true);
64       break;
65
66     case RTLD_DI_ORIGIN:
67       strcpy (args->arg, l->l_origin);
68       break;
69
70     case RTLD_DI_TLS_MODID:
71       *(size_t *) args->arg = 0;
72       *(size_t *) args->arg = l->l_tls_modid;
73       break;
74
75     case RTLD_DI_TLS_DATA:
76       {
77         void *data = NULL;
78         if (l->l_tls_modid != 0)
79           data = GLRO(dl_tls_get_addr_soft) (l);
80         *(void **) args->arg = data;
81         break;
82       }
83
84     case RTLD_DI_PHDR:
85       *(const ElfW(Phdr) **) args->arg = l->l_phdr;
86       args->result = l->l_phnum;
87       break;
88     }
89 }
90
91 static int
92 dlinfo_implementation (void *handle, int request, void *arg)
93 {
94   struct dlinfo_args args = { handle, request, arg };
95   _dlerror_run (&dlinfo_doit, &args);
96   return args.result;
97 }
98
99 #ifdef SHARED
100 int
101 ___dlinfo (void *handle, int request, void *arg)
102 {
103   if (GLRO (dl_dlfcn_hook) != NULL)
104     return GLRO (dl_dlfcn_hook)->dlinfo (handle, request, arg);
105   else
106     return dlinfo_implementation (handle, request, arg);
107 }
108 versioned_symbol (libc, ___dlinfo, dlinfo, GLIBC_2_34);
109
110 # if OTHER_SHLIB_COMPAT (libdl, GLIBC_2_3_3, GLIBC_2_34)
111 compat_symbol (libc, ___dlinfo, dlinfo, GLIBC_2_3_3);
112 # endif
113 #else /* !SHARED */
114 /* Also used with _dlfcn_hook.  */
115 int
116 __dlinfo (void *handle, int request, void *arg)
117 {
118   return dlinfo_implementation (handle, request, arg);
119 }
120 weak_alias (__dlinfo, dlinfo)
121 #endif