1 /* Look up a symbol in a shared object loaded by `dlopen'.
2 Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
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.
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.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
30 _dl_sym (void *handle
, const char *name
, void *who
)
32 const ElfW(Sym
) *ref
= NULL
;
34 ElfW(Addr
) caller
= (ElfW(Addr
)) who
;
35 struct link_map
*match
;
38 /* If the address is not recognized the call comes from the main
40 match
= GL(dl_loaded
);
42 /* Find the highest-addressed object that CALLER is not below. */
43 for (l
= GL(dl_loaded
); l
!= NULL
; l
= l
->l_next
)
44 if (caller
>= l
->l_map_start
&& caller
< l
->l_map_end
)
46 /* There must be exactly one DSO for the range of the virtual
47 memory. Otherwise something is really broken. */
52 if (handle
== RTLD_DEFAULT
)
53 /* Search the global scope as seen in the caller object. */
54 result
= _dl_lookup_symbol (name
, match
, &ref
, match
->l_scope
, 0,
55 DL_LOOKUP_RETURN_NEWEST
56 | DL_LOOKUP_ADD_DEPENDENCY
);
59 if (handle
!= RTLD_NEXT
)
61 /* Search the scope of the given object. */
62 struct link_map
*map
= handle
;
64 result
= _dl_lookup_symbol (name
, match
, &ref
, map
->l_local_scope
,
65 0, DL_LOOKUP_RETURN_NEWEST
);
69 if (__builtin_expect (match
== GL(dl_loaded
), 0))
72 || caller
< GL(dl_loaded
)->l_map_start
73 || caller
>= GL(dl_loaded
)->l_map_end
)
74 _dl_signal_error (0, NULL
, NULL
, N_("\
75 RTLD_NEXT used in code not dynamically loaded"));
79 while (l
->l_loader
!= NULL
)
82 result
= _dl_lookup_symbol_skip (name
, l
, &ref
, l
->l_local_scope
,
89 #if defined USE_TLS && defined SHARED
90 if (ELFW(ST_TYPE
) (ref
->st_info
) == STT_TLS
)
91 /* The found symbol is a thread-local storage variable.
92 Return the address for to the current thread. */
93 return _dl_tls_symaddr (result
, ref
);
96 return DL_SYMBOL_ADDRESS (result
, ref
);
104 _dl_vsym (void *handle
, const char *name
, const char *version
, void *who
)
106 const ElfW(Sym
) *ref
= NULL
;
107 struct r_found_version vers
;
109 ElfW(Addr
) caller
= (ElfW(Addr
)) who
;
110 struct link_map
*match
;
113 /* Compute hash value to the version string. */
116 vers
.hash
= _dl_elf_hash (version
);
117 /* We don't have a specific file where the symbol can be found. */
118 vers
.filename
= NULL
;
120 /* If the address is not recognized the call comes from the main
121 program (we hope). */
122 match
= GL(dl_loaded
);
124 /* Find the highest-addressed object that CALLER is not below. */
125 for (l
= GL(dl_loaded
); l
!= NULL
; l
= l
->l_next
)
126 if (caller
>= l
->l_map_start
&& caller
< l
->l_map_end
)
128 /* There must be exactly one DSO for the range of the virtual
129 memory. Otherwise something is really broken. */
134 if (handle
== RTLD_DEFAULT
)
135 /* Search the global scope. */
136 result
= _dl_lookup_versioned_symbol (name
, match
, &ref
, match
->l_scope
,
137 &vers
, 0, DL_LOOKUP_ADD_DEPENDENCY
);
138 else if (handle
== RTLD_NEXT
)
140 if (__builtin_expect (match
== GL(dl_loaded
), 0))
143 || caller
< GL(dl_loaded
)->l_map_start
144 || caller
>= GL(dl_loaded
)->l_map_end
)
145 _dl_signal_error (0, NULL
, NULL
, N_("\
146 RTLD_NEXT used in code not dynamically loaded"));
150 while (l
->l_loader
!= NULL
)
153 result
= _dl_lookup_versioned_symbol_skip (name
, l
, &ref
,
159 /* Search the scope of the given object. */
160 struct link_map
*map
= handle
;
161 result
= _dl_lookup_versioned_symbol (name
, map
, &ref
,
162 map
->l_local_scope
, &vers
, 0, 0);
167 #if defined USE_TLS && defined SHARED
168 if (ELFW(ST_TYPE
) (ref
->st_info
) == STT_TLS
)
169 /* The found symbol is a thread-local storage variable.
170 Return the address for to the current thread. */
171 return _dl_tls_symaddr (result
, ref
);
174 return DL_SYMBOL_ADDRESS (result
, ref
);