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