1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
|
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright (c) 1988 AT&T
* All Rights Reserved
*
* Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, Joyent, Inc. All rights reserved.
*/
#include <sys/types.h>
#include <sys/mman.h>
#include <signal.h>
#include <dlfcn.h>
#include <synch.h>
#include <debug.h>
#include "_rtld.h"
/*
* Declarations of global variables used in ld.so.
*/
Rt_lock rtldlock;
int thr_flg_nolock = 0;
int thr_flg_reenter = 0;
/*
* Major link-map lists.
*/
Lm_list lml_main = { 0 }; /* the `main's link map list */
Lm_list lml_rtld = { 0 }; /* rtld's link map list */
/*
* Entrance count. Each time ld.so.1 is entered following initial process
* setup, this count is bumped. This value serves to identify the present
* ld.so.1 operation.
*
* An ld.so.1 operation can result in many symbol lookup requests (i.e., loading
* objects and relocating all symbolic bindings). This count is used to protect
* against attempting to re-load a failed lazy load within a single call to
* ld.so.1, while allowing such attempts across calls. Should a lazy load fail,
* the present operation identifier is saved in the current symbol lookup data
* block (Slookup). Should a lazy load fall back operation be triggered, the
* identifier in the symbol lookup block is compared to the current ld.so.1
* entry count, and if the two are equal the fall back is skipped.
*
* With this count, there is a danger of wrap-around, although as an unsigned
* 32-bit value, it is highly unlikely that any application could usefully make
* 4.3 giga-calls into ld.so.1. The worst that can occur is that a fall back
* lazy load isn't triggered. However, most lazy loads that fail typically
* continue to fail unless the user takes corrective action (adds the necessary
* (fixed) dependencies to the system).
*/
ulong_t ld_entry_cnt = 1;
/*
* BEGIN: Exposed to rtld_db, don't change without a coordinated handshake with
* librtld_db (remembering that librtld_db must be able to read old as well as
* current core files).
*/
APlist *dynlm_list = NULL; /* dynamic list of link-maps */
/*
* END: Exposed to rtld_db
*/
Reglist *reglist = NULL; /* list of register symbols */
/*
* Set of integers to track how many of what type of PLT's have been bound.
* This is only really interesting for SPARC since ia32 has only one PLT.
*/
uint32_t pltcnt21d = 0;
uint32_t pltcnt24d = 0;
uint32_t pltcntu32 = 0;
uint32_t pltcntu44 = 0;
uint32_t pltcntfull = 0;
uint32_t pltcntfar = 0;
/*
* AVL tree pointers.
*/
avl_tree_t *capavl = NULL; /* capabilities files */
avl_tree_t *nfavl = NULL; /* not-found path names */
avl_tree_t *spavl = NULL; /* secure path names */
/*
* Various other global data.
*/
uint_t rtld_flags = 0;
uint_t rtld_flags2 = 0;
Lc_desc glcs[CI_MAX]; /* global external interfaces */
const char *procname = NULL;
const char *rtldname = MSG_ORIG(MSG_FIL_RTLD);
char *lasterr = NULL; /* string describing last error */
/* cleared by each dlerror() */
Interp *interp = NULL; /* ELF interpreter info */
APlist *hdl_alp[HDLIST_SZ+2]; /* dlopen() handle list */
size_t syspagsz = 0; /* system page size */
ulong_t at_flags = 0; /* machine specific file flags */
Uts_desc *uts = NULL; /* utsname descriptor */
Isa_desc *isa = NULL; /* isalist descriptor */
uint_t audit_argcnt = 64; /* no. of stack args to copy (default */
/* is all) */
Audit_desc *auditors = NULL; /* global auditors (LD_AUDIT) */
APlist *aud_preinit = NULL; /* list of objects defining local */
APlist *aud_activity = NULL; /* preinit and activity auditors */
const char *rpl_audit = NULL; /* replaceable LD_AUDIT string */
const char *rpl_debug = NULL; /* replaceable LD_DEBUG string */
const char *rpl_ldflags = NULL; /* replaceable LD_FLAGS string */
const char *rpl_libpath = NULL; /* replaceable LD_LIBRARY_PATH string */
Alist *rpl_libdirs = NULL; /* and associated Pdesc list */
const char *rpl_preload = NULL; /* replaceable LD_PRELOAD string */
const char *rpl_ldtoxic = NULL; /* replaceable LD_TOXIC string */
Alist *rpl_toxdirs = NULL; /* and associated Pdesc list */
const char *prm_audit = NULL; /* permanent LD_AUDIT string */
const char *prm_debug = NULL; /* permanent LD_DEBUG string */
const char *prm_ldflags = NULL; /* permanent LD_FLAGS string */
const char *prm_libpath = NULL; /* permanent LD_LIBRARY_PATH string */
Alist *prm_libdirs = NULL; /* and associated Pdesc list */
const char *prm_preload = NULL; /* permanent LD_PRELOAD string */
uint_t env_info = 0; /* information regarding environment */
/* variables */
int killsig = SIGKILL; /* signal sent on fatal exit */
APlist *free_alp = NULL; /* defragmentation list */
/*
* Capabilities are provided by the system. However, users can define an
* alternative set of system capabilities, where they can add, subtract, or
* override the system capabilities for testing purposes. Furthermore, these
* alternative capabilities can be specified such that they only apply to
* specified files rather than to all objects.
*
* The org_scapset is relied upon by the amd64 version of elf_rtbndr to
* determine whether or not AVX registers are present in the system.
*/
static Syscapset scapset = { 0 };
Syscapset *org_scapset = &scapset; /* original system and */
Syscapset *alt_scapset = &scapset; /* alternative system */
/* capabilities */
const char *rpl_hwcap = NULL; /* replaceable hwcap str */
const char *rpl_sfcap = NULL; /* replaceable sfcap str */
const char *rpl_machcap = NULL; /* replaceable machcap str */
const char *rpl_platcap = NULL; /* replaceable platcap str */
const char *rpl_cap_files = NULL; /* associated files */
const char *prm_hwcap = NULL; /* permanent hwcap str */
const char *prm_sfcap = NULL; /* permanent sfcap str */
const char *prm_machcap = NULL; /* permanent machcap str */
const char *prm_platcap = NULL; /* permanent platcap str */
const char *prm_cap_files = NULL; /* associated files */
/*
* Note, the debugging descriptor interposes on the default definition provided
* by liblddbg. This is required as ld.so.1 must only have outstanding relative
* relocations.
*/
static Dbg_desc _dbg_desc = {0, 0, 0};
Dbg_desc *dbg_desc = &_dbg_desc; /* debugging descriptor */
const char *dbg_file = NULL; /* debugging directed to file */
#pragma weak environ = _environ /* environ for PLT tracing - we */
char **_environ = NULL; /* supply the pair to satisfy any */
/* libc requirements (hwmuldiv) */
const char *profile_name = NULL; /* object being profiled */
const char *profile_out = NULL; /* profile output file */
const char *profile_lib = NULL; /* audit library to perform profile */
uchar_t search_rules[] = { /* dependency search rules */
RPLENV, /* replaceable LD_LIBRARY_PATH */
PRMENV, /* permanent LD_LIBRARY_PATH */
RUNPATH, /* callers runpath */
DEFAULT, /* default library path */
0
};
Dl_argsinfo argsinfo = { 0 }; /* process argument, environment and */
/* auxv information. */
/*
* Frequently used messages are cached here to reduce _dgettext() overhead and
* also provide for resetting should the locale change (see _ld_libc()).
*/
const char *err_strs[ERR_NUM] = { NULL };
const char *nosym_str = NULL;
/*
* Rejection error message tables.
*/
const Msg
ldd_reject[SGS_REJ_NUM] = {
MSG_STR_EMPTY,
MSG_LDD_REJ_MACH, /* MSG_INTL(MSG_LDD_REJ_MACH) */
MSG_LDD_REJ_CLASS, /* MSG_INTL(MSG_LDD_REJ_CLASS) */
MSG_LDD_REJ_DATA, /* MSG_INTL(MSG_LDD_REJ_DATA) */
MSG_LDD_REJ_TYPE, /* MSG_INTL(MSG_LDD_REJ_TYPE) */
MSG_LDD_REJ_BADFLAG, /* MSG_INTL(MSG_LDD_REJ_BADFLAG) */
MSG_LDD_REJ_MISFLAG, /* MSG_INTL(MSG_LDD_REJ_MISFLAG) */
MSG_LDD_REJ_VERSION, /* MSG_INTL(MSG_LDD_REJ_VERSION) */
MSG_LDD_REJ_HAL, /* MSG_INTL(MSG_LDD_REJ_HAL) */
MSG_LDD_REJ_US3, /* MSG_INTL(MSG_LDD_REJ_US3) */
MSG_LDD_REJ_STR, /* MSG_INTL(MSG_LDD_REJ_STR) */
MSG_LDD_REJ_UNKFILE, /* MSG_INTL(MSG_LDD_REJ_UNKFILE) */
MSG_LDD_REJ_UNKCAP, /* MSG_INTL(MSG_LDD_REJ_UNKCAP) */
MSG_LDD_REJ_HWCAP_1, /* MSG_INTL(MSG_LDD_REJ_HWCAP_1) */
MSG_LDD_REJ_SFCAP_1, /* MSG_INTL(MSG_LDD_REJ_SFCAP_1) */
MSG_LDD_REJ_MACHCAP, /* MSG_INTL(MSG_LDD_REJ_MACHCAP) */
MSG_LDD_REJ_PLATCAP, /* MSG_INTL(MSG_LDD_REJ_PLATCAP) */
MSG_LDD_REJ_HWCAP_2, /* MSG_INTL(MSG_LDD_REJ_HWCAP_2) */
MSG_LDD_REJ_ARCHIVE, /* MSG_INTL(MSG_LDD_REJ_ARCHIVE) */
MSG_LDD_REJ_KMOD /* MSG_INTL(MSG_LDD_REJ_KMOD) */
};
#if SGS_REJ_NUM != (SGS_REJ_KMOD + 1)
#error SGS_REJ_NUM has changed
#endif
const Msg
err_reject[SGS_REJ_NUM] = {
MSG_STR_EMPTY,
MSG_ERR_REJ_MACH, /* MSG_INTL(MSG_ERR_REJ_MACH) */
MSG_ERR_REJ_CLASS, /* MSG_INTL(MSG_ERR_REJ_CLASS) */
MSG_ERR_REJ_DATA, /* MSG_INTL(MSG_ERR_REJ_DATA) */
MSG_ERR_REJ_TYPE, /* MSG_INTL(MSG_ERR_REJ_TYPE) */
MSG_ERR_REJ_BADFLAG, /* MSG_INTL(MSG_ERR_REJ_BADFLAG) */
MSG_ERR_REJ_MISFLAG, /* MSG_INTL(MSG_ERR_REJ_MISFLAG) */
MSG_ERR_REJ_VERSION, /* MSG_INTL(MSG_ERR_REJ_VERSION) */
MSG_ERR_REJ_HAL, /* MSG_INTL(MSG_ERR_REJ_HAL) */
MSG_ERR_REJ_US3, /* MSG_INTL(MSG_ERR_REJ_US3) */
MSG_ERR_REJ_STR, /* MSG_INTL(MSG_ERR_REJ_STR) */
MSG_ERR_REJ_UNKFILE, /* MSG_INTL(MSG_ERR_REJ_UNKFILE) */
MSG_ERR_REJ_UNKCAP, /* MSG_INTL(MSG_ERR_REJ_UNKCAP) */
MSG_ERR_REJ_HWCAP_1, /* MSG_INTL(MSG_ERR_REJ_HWCAP_1) */
MSG_ERR_REJ_SFCAP_1, /* MSG_INTL(MSG_ERR_REJ_SFCAP_1) */
MSG_ERR_REJ_MACHCAP, /* MSG_INTL(MSG_ERR_REJ_MACHCAP) */
MSG_ERR_REJ_PLATCAP, /* MSG_INTL(MSG_ERR_REJ_PLATCAP) */
MSG_ERR_REJ_HWCAP_2, /* MSG_INTL(MSG_ERR_REJ_HWCAP_2) */
MSG_ERR_REJ_ARCHIVE, /* MSG_INTL(MSG_ERR_REJ_ARCHIVE) */
MSG_ERR_REJ_KMOD, /* MSG_INTL(MSG_ERR_REJ_KMOD) */
};
#if SGS_REJ_NUM != (SGS_REJ_KMOD + 1)
#error SGS_REJ_NUM has changed
#endif
const Msg
ldd_warn[SGS_REJ_NUM] = {
MSG_STR_EMPTY,
MSG_STR_EMPTY,
MSG_STR_EMPTY,
MSG_STR_EMPTY,
MSG_STR_EMPTY,
MSG_STR_EMPTY,
MSG_STR_EMPTY,
MSG_STR_EMPTY,
MSG_STR_EMPTY,
MSG_STR_EMPTY,
MSG_STR_EMPTY,
MSG_STR_EMPTY,
MSG_LDD_WARN_UNKCAP, /* MSG_INTL(MSG_LDD_WARN_UNKCAP) */
MSG_LDD_WARN_HWCAP_1, /* MSG_INTL(MSG_LDD_WARN_HWCAP_1) */
MSG_LDD_WARN_SFCAP_1, /* MSG_INTL(MSG_LDD_WARN_SFCAP_1) */
MSG_LDD_WARN_MACHCAP, /* MSG_INTL(MSG_LDD_WARN_MACHCAP) */
MSG_LDD_WARN_PLATCAP, /* MSG_INTL(MSG_LDD_WARN_PLATCAP) */
MSG_LDD_WARN_HWCAP_2, /* MSG_INTL(MSG_LDD_WARN_HWCAP_2) */
MSG_STR_EMPTY,
MSG_STR_EMPTY,
};
#if SGS_REJ_NUM != (SGS_REJ_KMOD + 1)
#error SGS_REJ_NUM has changed
#endif
|