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