1 /* Communicate dynamic linker state to the debugger at runtime.
2    Copyright (C) 1996-2022 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 *
_dl_debug_update(Lmid_t ns)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 *
_dl_debug_initialize(ElfW (Addr)ldbase,Lmid_t ns)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
_dl_debug_state(void)115 _dl_debug_state (void)
116 {
117 }
118 rtld_hidden_def (_dl_debug_state)
119