rtld: properly handle root directory in load path (bug 30435)
[platform/upstream/glibc.git] / elf / dl-debug.c
1 /* Communicate dynamic linker state to the debugger at runtime.
2    Copyright (C) 1996-2023 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 <ldsodefs.h>
20
21
22 /* These are the members in the public `struct link_map' type.
23    Sanity check that the internal type and the public type match.  */
24 #define VERIFY_MEMBER(name) \
25   (offsetof (struct link_map_public, name) == offsetof (struct link_map, name))
26 extern const int verify_link_map_members[(VERIFY_MEMBER (l_addr)
27                                           && VERIFY_MEMBER (l_name)
28                                           && VERIFY_MEMBER (l_ld)
29                                           && VERIFY_MEMBER (l_next)
30                                           && VERIFY_MEMBER (l_prev))
31                                          ? 1 : -1];
32
33 /* Update the `r_map' member and return the address of `struct r_debug'
34    of the namespace NS. */
35
36 struct r_debug *
37 _dl_debug_update (Lmid_t ns)
38 {
39   struct r_debug_extended *r;
40   if (ns == LM_ID_BASE)
41     r = &_r_debug_extended;
42   else
43     r = &GL(dl_ns)[ns]._ns_debug;
44   if (r->base.r_map == NULL)
45     atomic_store_release (&r->base.r_map,
46                           (void *) GL(dl_ns)[ns]._ns_loaded);
47   return &r->base;
48 }
49
50 /* Initialize _r_debug_extended for the namespace NS.  LDBASE is the
51    run-time load address of the dynamic linker, to be put in
52    _r_debug_extended.r_ldbase.  Return the address of _r_debug.  */
53
54 struct r_debug *
55 _dl_debug_initialize (ElfW(Addr) ldbase, Lmid_t ns)
56 {
57   struct r_debug_extended *r, **pp = NULL;
58
59   if (ns == LM_ID_BASE)
60     {
61       r = &_r_debug_extended;
62       /* Initialize r_version to 1.  */
63       if (_r_debug_extended.base.r_version == 0)
64         _r_debug_extended.base.r_version = 1;
65     }
66   else if (DL_NNS > 1)
67     {
68       r = &GL(dl_ns)[ns]._ns_debug;
69       if (r->base.r_brk == 0)
70         {
71           /* Add the new namespace to the linked list.  After a namespace
72              is initialized, r_brk becomes non-zero.  A namespace becomes
73              empty (r_map == NULL) when it is unused.  But it is never
74              removed from the linked list.  */
75           struct r_debug_extended *p;
76           for (pp = &_r_debug_extended.r_next;
77                (p = *pp) != NULL;
78                pp = &p->r_next)
79             ;
80
81           r->base.r_version = 2;
82         }
83     }
84
85   if (r->base.r_brk == 0)
86     {
87       /* Tell the debugger where to find the map of loaded objects.
88          This function is called from dlopen.  Initialize the namespace
89          only once.  */
90       r->base.r_ldbase = ldbase ?: _r_debug_extended.base.r_ldbase;
91       r->base.r_brk = (ElfW(Addr)) &_dl_debug_state;
92       r->r_next = NULL;
93     }
94
95   if (r->base.r_map == NULL)
96     atomic_store_release (&r->base.r_map,
97                           (void *) GL(dl_ns)[ns]._ns_loaded);
98
99   if (pp != NULL)
100     {
101       atomic_store_release (pp, r);
102       /* Bump r_version to 2 for the new namespace.  */
103       atomic_store_release (&_r_debug_extended.base.r_version, 2);
104     }
105
106   return &r->base;
107 }
108
109
110 /* This function exists solely to have a breakpoint set on it by the
111    debugger.  The debugger is supposed to find this function's address by
112    examining the r_brk member of struct r_debug, but GDB 4.15 in fact looks
113    for this particular symbol name in the PT_INTERP file.  */
114 void
115 _dl_debug_state (void)
116 {
117 }
118 rtld_hidden_def (_dl_debug_state)