Print this page
11057 hidden undefined weak symbols should not leave relocations
11058 libld entrance descriptor assertions get NDEBUG check backwards
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/sgs/libld/common/entry.c
+++ new/usr/src/cmd/sgs/libld/common/entry.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright (c) 1988 AT&T
24 24 * All Rights Reserved
25 25 *
26 26 * Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
27 27 */
28 28
29 29 #define ELF_TARGET_AMD64
30 30
31 31 #include <stdio.h>
32 32 #include <memory.h>
33 33 #include <debug.h>
34 34 #include "msg.h"
35 35 #include "_libld.h"
36 36
37 37 /*
38 38 * The link-editor uses a segment descriptor list to describe the program
39 39 * headers, and related output segments, it can potentially create. This
40 40 * list is initially seeded using the templates contained in the sg_desc
41 41 * array below. Additional segments may be added using a mapfile.
42 42 *
43 43 * The entries in sg_desc must be put in the order defined by the
44 44 * Segment_id enum.
45 45 *
46 46 * The entries in sg_desc are initialized using the SG_DESC_INIT macro
47 47 * for two reasons:
48 48 *
49 49 * 1) The first field of the Sg_desc struct is a program header
50 50 * entry. ELF32_Phdr and ELF64_Phdr have the same fields,
51 51 * but their order is different. Use of a macro allows us
52 52 * to handle this transparently.
53 53 * 2) Most of the fields in the Sg_desc entries are set to 0.
54 54 * Use of a macro allows us to hide the clutter.
55 55 *
56 56 * If a given program header can be referenced via an entrance criteria
57 57 * (i.e. can serve as a segment), then it must be given a unique sg_name.
58 58 * Program headers that cannot be a segment (PHDR, INTERP, DYNAMIC, etc)
59 59 * must have a NULL sg_name --- their program header type identifies them.
60 60 */
61 61 #ifdef _ELF64
62 62 #define SG_DESC_INIT(id, p_type, p_flags, sg_name, sg_flags) \
63 63 { id, { p_type, p_flags, 0, 0, 0, 0, 0, 0}, \
64 64 sg_name, 0, 0, NULL, NULL, NULL, sg_flags, NULL, 0, NULL}
65 65 #else
66 66 #define SG_DESC_INIT(id, p_type, p_flags, sg_name, sg_flags) \
67 67 { id, { p_type, 0, 0, 0, 0, 0, p_flags, 0}, \
68 68 sg_name, 0, 0, NULL, NULL, NULL, sg_flags, NULL, 0, NULL}
69 69 #endif
70 70
71 71 /*
72 72 * Predefined segment descriptors:
73 73 *
74 74 * The C language guarantees that a structure containing only fields of
75 75 * identical type is indistinguishable from a simple array containing
76 76 * the same number of items of the same type. They will have the same
77 77 * size, alignment, and internal layout:
78 78 *
79 79 * - A pointer to one is equivalent to a pointer to the other, and you
80 80 * can cast safely between them.
81 81 *
82 82 * - You can put both into a union, and access the elements within
83 83 * either way (by index, or by name).
84 84 *
85 85 * We use this fact here to create an "array" of predefined segment
86 86 * descriptors, assigning each one a mnemonic name that can be used to point
87 87 * at it from a predefined entrance criteria descriptor (below). These
88 88 * segments are positioned in the default order that will result in the
89 89 * output object, unless a mapfile alters things.
90 90 */
91 91 typedef struct {
92 92 Sg_desc psg_phdr;
93 93 Sg_desc psg_interp;
94 94 Sg_desc psg_sunwcap;
95 95 Sg_desc psg_text;
96 96 Sg_desc psg_data;
97 97 Sg_desc psg_bss;
98 98 #if defined(_ELF64)
99 99 Sg_desc psg_lrodata; /* (amd64-only) */
100 100 Sg_desc psg_ldata; /* (amd64-only) */
101 101 #endif
102 102 Sg_desc psg_dynamic;
103 103 Sg_desc psg_sunwdtrace;
104 104 Sg_desc psg_tls;
105 105 Sg_desc psg_unwind;
106 106 Sg_desc psg_sunwstack;
107 107 Sg_desc psg_note;
108 108 Sg_desc psg_extra;
109 109 } predef_seg_t;
110 110
111 111 static const size_t predef_seg_nelts =
112 112 (sizeof (predef_seg_t) / sizeof (Sg_desc));
113 113
114 114 static predef_seg_t sg_desc = {
115 115 /* psg_phdr */
116 116 SG_DESC_INIT(SGID_PHDR, PT_PHDR, PF_R + PF_X, NULL,
117 117 (FLG_SG_P_TYPE | FLG_SG_P_FLAGS)),
118 118
119 119 /* psg_interp */
120 120 SG_DESC_INIT(SGID_INTERP, PT_INTERP, PF_R, NULL,
121 121 (FLG_SG_P_TYPE | FLG_SG_P_FLAGS)),
122 122
123 123 /* psg_sunwcap */
124 124 SG_DESC_INIT(SGID_SUNWCAP, PT_SUNWCAP, PF_R, NULL,
125 125 (FLG_SG_P_TYPE | FLG_SG_P_FLAGS)),
126 126
127 127 /* psg_text */
128 128 SG_DESC_INIT(SGID_TEXT, PT_LOAD, PF_R + PF_X, MSG_ORIG(MSG_ENT_TEXT),
129 129 (FLG_SG_P_TYPE | FLG_SG_P_FLAGS)),
130 130
131 131 /* psg_data */
132 132 SG_DESC_INIT(SGID_DATA, PT_LOAD, 0, MSG_ORIG(MSG_ENT_DATA),
133 133 (FLG_SG_P_TYPE | FLG_SG_P_FLAGS)),
134 134
135 135 /* psg_bss */
136 136 SG_DESC_INIT(SGID_BSS, PT_LOAD, 0, MSG_ORIG(MSG_ENT_BSS),
137 137 (FLG_SG_P_TYPE | FLG_SG_P_FLAGS | FLG_SG_DISABLED)),
138 138
139 139 #if defined(_ELF64)
140 140 /* psg_lrodata (amd64-only ) */
141 141 SG_DESC_INIT(SGID_LRODATA, PT_LOAD, PF_R, MSG_ORIG(MSG_ENT_LRODATA),
142 142 (FLG_SG_P_TYPE | FLG_SG_P_FLAGS)),
143 143
144 144 /* psg_ldata (amd64-only ) */
145 145 SG_DESC_INIT(SGID_LDATA, PT_LOAD, 0, MSG_ORIG(MSG_ENT_LDATA),
146 146 (FLG_SG_P_TYPE | FLG_SG_P_FLAGS)),
147 147 #endif
148 148 /* psg_dynamic */
149 149 SG_DESC_INIT(SGID_DYN, PT_DYNAMIC, 0, NULL,
150 150 (FLG_SG_P_TYPE | FLG_SG_P_FLAGS)),
151 151
152 152 /* psg_sunwdtrace */
153 153 SG_DESC_INIT(SGID_DTRACE, PT_SUNWDTRACE, 0, NULL,
154 154 (FLG_SG_P_TYPE | FLG_SG_P_FLAGS)),
155 155
156 156 /* psg_tls */
157 157 SG_DESC_INIT(SGID_TLS, PT_TLS, PF_R, NULL,
158 158 (FLG_SG_P_TYPE | FLG_SG_P_FLAGS)),
159 159
160 160 /* psg_unwind */
161 161 SG_DESC_INIT(SGID_UNWIND, PT_SUNW_UNWIND, PF_R, NULL,
162 162 (FLG_SG_P_TYPE | FLG_SG_P_FLAGS)),
163 163
164 164 /* psg_sunwstack */
165 165 SG_DESC_INIT(SGID_SUNWSTACK, PT_SUNWSTACK, 0, NULL,
166 166 (FLG_SG_P_TYPE | FLG_SG_P_FLAGS | FLG_SG_DISABLED)),
167 167
168 168 /* psg_note */
169 169 SG_DESC_INIT(SGID_NOTE, PT_NOTE, 0, MSG_ORIG(MSG_ENT_NOTE),
170 170 FLG_SG_P_TYPE),
171 171
172 172 /*
173 173 * psg_extra
174 174 *
175 175 * This segment is referenced by the final entrance criteria descriptor
176 176 * to catch any segment not otherwise placed. It cannot be disabled
177 177 * via a mapfile.
178 178 */
179 179 SG_DESC_INIT(SGID_EXTRA, PT_NULL, 0, MSG_ORIG(MSG_ENT_EXTRA),
180 180 (FLG_SG_P_TYPE | FLG_SG_NODISABLE))
181 181 };
182 182 #undef SG_DESC_INIT
183 183
184 184 /*
185 185 * The processing of input files by the link-editor involves matching the
186 186 * input file sections against an ordered list of entrance criteria
187 187 * descriptors. The following template defines the built in entrance criteria
188 188 * list. This list can be augmented using a mapfile. Each entrance criteria
189 189 * is associated with a segment descriptor, providing the means for mapping
190 190 * input sections to output segments.
191 191 *
192 192 * As with the segment descriptors, the EC_DESC_INIT macro is used
193 193 * to reduce boilerplate clutter.
194 194 */
195 195 #define EC_DESC_INIT(ec_is_name, ec_type, ec_attrmask, ec_attrbits, \
196 196 _seg_field, ec_flags) \
197 197 { NULL, NULL, ec_is_name, ec_type, ec_attrmask, ec_attrbits, \
198 198 &sg_desc.psg_ ## _seg_field, 0, FLG_EC_BUILTIN | ec_flags }
199 199
200 200 static const Ent_desc ent_desc[] = {
201 201 EC_DESC_INIT(NULL, SHT_NOTE, 0, 0, note, 0),
202 202
203 203 #if defined(_ELF64) /* (amd64-only) */
204 204 EC_DESC_INIT(NULL, 0, SHF_ALLOC + SHF_WRITE + SHF_AMD64_LARGE,
205 205 SHF_ALLOC + SHF_AMD64_LARGE, lrodata, 0),
206 206 #endif
207 207 EC_DESC_INIT(NULL, 0, SHF_ALLOC + SHF_WRITE, SHF_ALLOC, text, 0),
208 208
209 209 /*
210 210 * Explicitly assign the .tdata section to bss. The design of TLS
211 211 * provides for initialized data being assigned to a .tdata section,
212 212 * and uninitialized data being assigned to a .tbss section. These
213 213 * sections should be laid out adjacent to each other, with little or
214 214 * no gap between them. A PT_TLS program header is created that
215 215 * defines the address range of the two sections. This header is
216 216 * passed to libc to instantiate the appropriate thread allocation.
217 217 *
218 218 * By default a separate bss segment is disabled, however users can
219 219 * trigger the creation of a bss segment with a mapfile. By default,
220 220 * all bss sections are assigned to the data segment, and the section
221 221 * identifiers of .tdata and .tbss ensure that these two sections are
222 222 * adjacent to each other.
223 223 *
224 224 * However, if a bss segment is enabled, the adjacency of the .tdata
225 225 * and .tbss sections can only be retained by having an explicit .tdata
226 226 * entrance criteria.
227 227 */
228 228 EC_DESC_INIT(MSG_ORIG(MSG_SCN_TDATA), 0, SHF_ALLOC + SHF_WRITE,
229 229 SHF_ALLOC + SHF_WRITE, bss, 0),
230 230
231 231 EC_DESC_INIT(NULL, SHT_NOBITS, SHF_ALLOC + SHF_WRITE,
232 232 SHF_ALLOC + SHF_WRITE, bss, 0),
233 233
234 234 #if defined(_ELF64) /* (amd64-only) */
235 235 EC_DESC_INIT(NULL, SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_AMD64_LARGE,
236 236 SHF_ALLOC + SHF_WRITE + SHF_AMD64_LARGE, data, 0),
237 237
238 238 EC_DESC_INIT(NULL, 0, SHF_ALLOC + SHF_WRITE + SHF_AMD64_LARGE,
239 239 SHF_ALLOC + SHF_WRITE + SHF_AMD64_LARGE, ldata, 0),
240 240 #endif
241 241 EC_DESC_INIT(NULL, 0, SHF_ALLOC + SHF_WRITE, SHF_ALLOC + SHF_WRITE,
242 242 data, 0),
243 243
244 244 /*
245 245 * Final catchall rule sends remaining sections to "extra"
246 246 * NULL segment, which has been tagged as FLG_SG_NODISABLE,
247 247 * and which will therefore always accept them.
248 248 */
249 249 EC_DESC_INIT(NULL, 0, 0, 0, extra, FLG_EC_CATCHALL)
250 250 };
251 251 #undef EC_DESC_INIT
252 252
253 253 /*
254 254 * AVL comparison function for Sg_desc items in ofl_segs_avl.
255 255 *
256 256 * entry:
257 257 * n1, n2 - pointers to nodes to be compared
258 258 *
259 259 * exit:
260 260 * Returns -1 if (n1 < n2), 0 if they are equal, and 1 if (n1 > n2)
261 261 */
262 262 static int
263 263 ofl_segs_avl_cmp(const void *n1, const void *n2)
264 264 {
265 265 int rc;
266 266
267 267 rc = strcmp(((Sg_desc *)n1)->sg_name, ((Sg_desc *)n2)->sg_name);
268 268
269 269 if (rc > 0)
270 270 return (1);
271 271 if (rc < 0)
272 272 return (-1);
273 273 return (0);
274 274 }
275 275
276 276 /*
277 277 * AVL comparison function for Ent_desc items in ofl_ents_avl.
278 278 *
279 279 * entry:
280 280 * n1, n2 - pointers to nodes to be compared
281 281 *
282 282 * exit:
283 283 * Returns -1 if (n1 < n2), 0 if they are equal, and 1 if (n1 > n2)
284 284 */
285 285 static int
286 286 ofl_ents_avl_cmp(const void *n1, const void *n2)
287 287 {
288 288 int rc;
289 289
290 290 /*
291 291 * There are entrance criteria nodes with NULL pointer names,
292 292 * but they are never entered into the AVL tree. Hence, we can
293 293 * assume that both nodes have names.
294 294 */
295 295 rc = strcmp(((Ent_desc *)n1)->ec_name, ((Ent_desc *)n2)->ec_name);
296 296
297 297 if (rc > 0)
298 298 return (1);
299 299 if (rc < 0)
300 300 return (-1);
301 301 return (0);
302 302 }
303 303
304 304 /*
305 305 * Lookup a segment descriptor by name.
306 306 *
307 307 * entry:
308 308 * ofl - Output descriptor
309 309 * name - Name of desired segment
310 310 *
311 311 * exit:
312 312 * On success, returns pointer to descriptor. On failure, returns NULL.
313 313 */
314 314 Sg_desc *
315 315 ld_seg_lookup(Ofl_desc *ofl, const char *name, avl_index_t *where)
316 316 {
317 317 Sg_desc sg;
318 318
319 319 sg.sg_name = name;
320 320 return (avl_find(&ofl->ofl_segs_avl, &sg, where));
321 321 }
322 322
323 323
324 324 /*
325 325 * Look up an entrance criteria record by name
326 326 *
327 327 * entry:
328 328 * mf - Mapfile descriptor
329 329 * name - Name of entrance criteria to locate
330 330 *
331 331 * exit:
332 332 * On success, a pointer to the entrace criteria record is
333 333 * returned. On failure, NULL is returned.
334 334 *
335 335 * note:
336 336 * Entrance criteria are not required to have names. Only
337 337 * named entrance criteria can be looked up via this method.
338 338 */
339 339 Ent_desc *
340 340 ld_ent_lookup(Ofl_desc *ofl, const char *name, avl_index_t *where)
341 341 {
342 342 Ent_desc en;
343 343
344 344 en.ec_name = name;
345 345 return (avl_find(&ofl->ofl_ents_avl, &en, where));
346 346 }
347 347
348 348 /*
349 349 * Initialize new entrance and segment descriptors and add them as lists to
350 350 * the output file descriptor.
351 351 */
352 352 uintptr_t
353 353 ld_ent_setup(Ofl_desc *ofl, Xword segalign)
354 354 {
355 355 Ent_desc *enp;
356 356 predef_seg_t *psegs;
357 357 Sg_desc *sgp;
358 358 size_t idx;
359 359
360 360 /*
361 361 * Initialize the elf library.
362 362 */
363 363 if (elf_version(EV_CURRENT) == EV_NONE) {
364 364 ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_ELF_LIBELF),
365 365 EV_CURRENT);
366 366 return (S_ERROR);
367 367 }
368 368
369 369 /*
370 370 * Initialize internal Global Symbol Table AVL tree
371 371 */
372 372 avl_create(&ofl->ofl_symavl, &ld_sym_avl_comp, sizeof (Sym_avlnode),
373 373 SGSOFFSETOF(Sym_avlnode, sav_node));
374 374
375 375 /* Initialize segment AVL tree */
376 376 avl_create(&ofl->ofl_segs_avl, ofl_segs_avl_cmp,
377 377 sizeof (Sg_desc), SGSOFFSETOF(Sg_desc, sg_avlnode));
378 378
379 379 /* Initialize entrance criteria AVL tree */
380 380 avl_create(&ofl->ofl_ents_avl, ofl_ents_avl_cmp, sizeof (Ent_desc),
381 381 SGSOFFSETOF(Ent_desc, ec_avlnode));
382 382
383 383
384 384 /*
385 385 * Allocate and initialize writable copies of both the entrance and
386 386 * segment descriptors.
387 387 *
388 388 * Note that on non-amd64 targets, this allocates a few more
389 389 * elements than are needed. For now, we are willing to overallocate
390 390 * a small amount to simplify the code.
391 391 */
392 392 if ((psegs = libld_malloc(sizeof (sg_desc))) == NULL)
393 393 return (S_ERROR);
394 394 (void) memcpy(psegs, &sg_desc, sizeof (sg_desc));
395 395 sgp = (Sg_desc *) psegs;
396 396
397 397 /*
398 398 * The data segment and stack permissions can differ:
399 399 *
400 400 * - Architectural/ABI per-platform differences
401 401 * - Whether the object is built statically or dynamically
402 402 *
403 403 * Those segments so affected have their program header flags
404 404 * set here at runtime, rather than in the sg_desc templates above.
405 405 */
406 406 psegs->psg_data.sg_phdr.p_flags = ld_targ.t_m.m_dataseg_perm;
407 407 psegs->psg_bss.sg_phdr.p_flags = ld_targ.t_m.m_dataseg_perm;
408 408 psegs->psg_dynamic.sg_phdr.p_flags = ld_targ.t_m.m_dataseg_perm;
409 409 psegs->psg_sunwdtrace.sg_phdr.p_flags = ld_targ.t_m.m_dataseg_perm;
410 410 #if defined(_ELF64)
411 411 psegs->psg_ldata.sg_phdr.p_flags = ld_targ.t_m.m_dataseg_perm;
412 412 psegs->psg_sunwdtrace.sg_phdr.p_flags |= PF_X;
413 413 #endif
414 414 psegs->psg_sunwstack.sg_phdr.p_flags = ld_targ.t_m.m_stack_perm;
415 415 if ((ofl->ofl_flags & FLG_OF_DYNAMIC) == 0)
416 416 psegs->psg_data.sg_phdr.p_flags |= PF_X;
417 417
418 418 /*
419 419 * Traverse the new entrance descriptor list converting the segment
420 420 * pointer entries to the absolute address within the new segment
421 421 * descriptor list. Add each entrance descriptor to the output file
422 422 * list.
423 423 */
424 424 if ((enp = libld_malloc(sizeof (ent_desc))) == NULL)
425 425 return (S_ERROR);
426 426 (void) memcpy(enp, ent_desc, sizeof (ent_desc));
427 427 for (idx = 0; idx < (sizeof (ent_desc) / sizeof (ent_desc[0])); idx++,
428 428 enp++) {
429 429
430 430 #if defined(_ELF64)
431 431 /* Don't use the amd64 entry conditions for non-amd64 targets */
432 432 if ((enp->ec_attrmask & SHF_AMD64_LARGE) &&
433 433 (ld_targ.t_m.m_mach != EM_AMD64))
434 434 continue;
435 435 #endif
436 436 if (aplist_append(&ofl->ofl_ents, enp,
437 437 AL_CNT_OFL_ENTRANCE) == NULL)
438 438 return (S_ERROR);
439 439
440 440 /*
441 441 * The segment pointer is currently pointing at a template
442 442 * segment descriptor in sg_desc. Compute its array index,
443 443 * and then use that index to compute the address of the
444 444 * corresponding descriptor in the writable copy.
445 445 */
446 446 enp->ec_segment =
447 447 &sgp[(enp->ec_segment - (Sg_desc *) &sg_desc)];
448 448 }
449 449
450 450 /*
451 451 * Add each segment descriptor to the segment descriptor list. The
452 452 * ones with non-NULL sg_name are also entered into the AVL tree.
453 453 * For each loadable segment initialize a default alignment. Note
454 454 * that ld(1) and ld.so.1 initialize this differently.
455 455 */
456 456 for (idx = 0; idx < predef_seg_nelts; idx++, sgp++) {
457 457 Phdr *phdr = &(sgp->sg_phdr);
458 458
459 459 #if defined(_ELF64)
460 460 /* Ignore amd64 segment templates for non-amd64 targets */
461 461 switch (sgp->sg_id) {
462 462 case SGID_LRODATA:
463 463 case SGID_LDATA:
464 464 if ((ld_targ.t_m.m_mach != EM_AMD64))
↓ open down ↓ |
464 lines elided |
↑ open up ↑ |
465 465 continue;
466 466 }
467 467 #endif
468 468 if (phdr->p_type == PT_LOAD)
469 469 phdr->p_align = segalign;
470 470
471 471 if ((aplist_append(&ofl->ofl_segs, sgp,
472 472 AL_CNT_SEGMENTS)) == NULL)
473 473 return (S_ERROR);
474 474
475 -#ifdef NDEBUG /* assert() is enabled */
475 +#ifndef NDEBUG /* assert() is enabled */
476 476 /*
477 477 * Enforce the segment name rule: Any segment that can
478 478 * be referenced by an entrance descriptor must have
479 479 * a name. Any segment that cannot, must have a NULL
480 480 * name pointer.
481 481 */
482 482 switch (phdr->p_type) {
483 483 case PT_LOAD:
484 484 case PT_NOTE:
485 485 case PT_NULL:
486 486 assert(sgp->sg_name != NULL);
487 487 break;
488 488 default:
489 489 assert(sgp->sg_name == NULL);
490 490 break;
491 491 }
492 492 #endif
493 493
494 494 /*
495 495 * Add named segment descriptors to the AVL tree to
496 496 * provide O(logN) lookups.
497 497 */
498 498 if (sgp->sg_name != NULL)
499 499 avl_add(&ofl->ofl_segs_avl, sgp);
500 500 }
501 501
502 502 return (1);
503 503 }
↓ open down ↓ |
18 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX