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_type, ec_attrmask, ec_attrbits, _seg_field, ec_flags) \ 197 { NULL, NULL, NULL, 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(SHT_NOTE, 0, 0, note, 0), 202 203 204 #if defined(_ELF64) /* (amd64-only) */ 205 EC_DESC_INIT(0, SHF_ALLOC + SHF_WRITE + SHF_AMD64_LARGE, 206 SHF_ALLOC + SHF_AMD64_LARGE, lrodata, 0), 207 #endif 208 EC_DESC_INIT(0, SHF_ALLOC + SHF_WRITE, SHF_ALLOC, text, 0), 209 210 EC_DESC_INIT(SHT_NOBITS, SHF_ALLOC + SHF_WRITE, SHF_ALLOC + SHF_WRITE, 211 bss, 0), 212 213 #if defined(_ELF64) /* (amd64-only) */ 214 EC_DESC_INIT(SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_AMD64_LARGE, 215 SHF_ALLOC + SHF_WRITE + SHF_AMD64_LARGE, data, 0), 216 217 EC_DESC_INIT(0, SHF_ALLOC + SHF_WRITE + SHF_AMD64_LARGE, 218 SHF_ALLOC + SHF_WRITE + SHF_AMD64_LARGE, ldata, 0), 219 #endif 220 EC_DESC_INIT(0, SHF_ALLOC + SHF_WRITE, SHF_ALLOC + SHF_WRITE, data, 0), 221 222 /* 223 * Final catchall rule sends remaining sections to "extra" 224 * NULL segment, which has been tagged as FLG_SG_NODISABLE, 225 * and which will therefore always accept them. 226 */ 227 EC_DESC_INIT(0, 0, 0, extra, FLG_EC_CATCHALL) 228 }; 229 #undef EC_DESC_INIT 230 231 /* 232 * AVL comparison function for Sg_desc items in ofl_segs_avl. 233 * 234 * entry: 235 * n1, n2 - pointers to nodes to be compared 236 * 237 * exit: 238 * Returns -1 if (n1 < n2), 0 if they are equal, and 1 if (n1 > n2) 239 */ 240 static int 241 ofl_segs_avl_cmp(const void *n1, const void *n2) 242 { 243 int rc; 244 245 rc = strcmp(((Sg_desc *)n1)->sg_name, ((Sg_desc *)n2)->sg_name); 246 247 if (rc > 0) 248 return (1); 249 if (rc < 0) 250 return (-1); 251 return (0); 252 } 253 254 /* 255 * AVL comparison function for Ent_desc items in ofl_ents_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_ents_avl_cmp(const void *n1, const void *n2) 265 { 266 int rc; 267 268 /* 269 * There are entrance criteria nodes with NULL pointer names, 270 * but they are never entered into the AVL tree. Hence, we can 271 * assume that both nodes have names. 272 */ 273 rc = strcmp(((Ent_desc *)n1)->ec_name, ((Ent_desc *)n2)->ec_name); 274 275 if (rc > 0) 276 return (1); 277 if (rc < 0) 278 return (-1); 279 return (0); 280 } 281 282 /* 283 * Lookup a segment descriptor by name. 284 * 285 * entry: 286 * ofl - Output descriptor 287 * name - Name of desired segment 288 * 289 * exit: 290 * On success, returns pointer to descriptor. On failure, returns NULL. 291 */ 292 Sg_desc * 293 ld_seg_lookup(Ofl_desc *ofl, const char *name, avl_index_t *where) 294 { 295 Sg_desc sg; 296 297 sg.sg_name = name; 298 return (avl_find(&ofl->ofl_segs_avl, &sg, where)); 299 } 300 301 302 /* 303 * Look up an entrance criteria record by name 304 * 305 * entry: 306 * mf - Mapfile descriptor 307 * name - Name of entrance criteria to locate 308 * 309 * exit: 310 * On success, a pointer to the entrace criteria record is 311 * returned. On failure, NULL is returned. 312 * 313 * note: 314 * Entrance criteria are not required to have names. Only 315 * named entrance criteria can be looked up via this method. 316 */ 317 Ent_desc * 318 ld_ent_lookup(Ofl_desc *ofl, const char *name, avl_index_t *where) 319 { 320 Ent_desc en; 321 322 en.ec_name = name; 323 return (avl_find(&ofl->ofl_ents_avl, &en, where)); 324 } 325 326 /* 327 * Initialize new entrance and segment descriptors and add them as lists to 328 * the output file descriptor. 329 */ 330 uintptr_t 331 ld_ent_setup(Ofl_desc *ofl, Xword segalign) 332 { 333 Ent_desc *enp; 334 predef_seg_t *psegs; 335 Sg_desc *sgp; 336 size_t idx; 337 338 /* 339 * Initialize the elf library. 340 */ 341 if (elf_version(EV_CURRENT) == EV_NONE) { 342 eprintf(ofl->ofl_lml, ERR_FATAL, MSG_INTL(MSG_ELF_LIBELF), 343 EV_CURRENT); 344 return (S_ERROR); 345 } 346 347 /* 348 * Initialize internal Global Symbol Table AVL tree 349 */ 350 avl_create(&ofl->ofl_symavl, &ld_sym_avl_comp, sizeof (Sym_avlnode), 351 SGSOFFSETOF(Sym_avlnode, sav_node)); 352 353 /* Initialize segment AVL tree */ 354 avl_create(&ofl->ofl_segs_avl, ofl_segs_avl_cmp, 355 sizeof (Sg_desc), SGSOFFSETOF(Sg_desc, sg_avlnode)); 356 357 /* Initialize entrance criteria AVL tree */ 358 avl_create(&ofl->ofl_ents_avl, ofl_ents_avl_cmp, sizeof (Ent_desc), 359 SGSOFFSETOF(Ent_desc, ec_avlnode)); 360 361 362 /* 363 * Allocate and initialize writable copies of both the entrance and 364 * segment descriptors. 365 * 366 * Note that on non-amd64 targets, this allocates a few more 367 * elements than are needed. For now, we are willing to overallocate 368 * a small amount to simplify the code. 369 */ 370 if ((psegs = libld_malloc(sizeof (sg_desc))) == NULL) 371 return (S_ERROR); 372 (void) memcpy(psegs, &sg_desc, sizeof (sg_desc)); 373 sgp = (Sg_desc *) psegs; 374 375 /* 376 * The data segment and stack permissions can differ: 377 * 378 * - Architecural/ABI per-platform differences 379 * - Whether the object is built statically or dynamically 380 * 381 * Those segments so affected have their program header flags 382 * set here at runtime, rather than in the sg_desc templates above. 383 */ 384 psegs->psg_data.sg_phdr.p_flags = ld_targ.t_m.m_dataseg_perm; 385 psegs->psg_bss.sg_phdr.p_flags = ld_targ.t_m.m_dataseg_perm; 386 psegs->psg_dynamic.sg_phdr.p_flags = ld_targ.t_m.m_dataseg_perm; 387 psegs->psg_sunwdtrace.sg_phdr.p_flags = ld_targ.t_m.m_dataseg_perm; 388 #if defined(_ELF64) 389 psegs->psg_ldata.sg_phdr.p_flags = ld_targ.t_m.m_dataseg_perm; 390 psegs->psg_sunwdtrace.sg_phdr.p_flags |= PF_X; 391 #endif 392 psegs->psg_sunwstack.sg_phdr.p_flags = ld_targ.t_m.m_stack_perm; 393 if ((ofl->ofl_flags & FLG_OF_DYNAMIC) == 0) 394 psegs->psg_data.sg_phdr.p_flags |= PF_X; 395 396 /* 397 * Traverse the new entrance descriptor list converting the segment 398 * pointer entries to the absolute address within the new segment 399 * descriptor list. Add each entrance descriptor to the output file 400 * list. 401 */ 402 if ((enp = libld_malloc(sizeof (ent_desc))) == NULL) 403 return (S_ERROR); 404 (void) memcpy(enp, ent_desc, sizeof (ent_desc)); 405 for (idx = 0; idx < (sizeof (ent_desc) / sizeof (ent_desc[0])); idx++, 406 enp++) { 407 408 #if defined(_ELF64) 409 /* Don't use the amd64 entry conditions for non-amd64 targets */ 410 if ((enp->ec_attrmask & SHF_AMD64_LARGE) && 411 (ld_targ.t_m.m_mach != EM_AMD64)) 412 continue; 413 #endif 414 if (aplist_append(&ofl->ofl_ents, enp, 415 AL_CNT_OFL_ENTRANCE) == NULL) 416 return (S_ERROR); 417 418 /* 419 * The segment pointer is currently pointing at a template 420 * segment descriptor in sg_desc. Compute its array index, 421 * and then use that index to compute the address of the 422 * corresponding descriptor in the writable copy. 423 */ 424 enp->ec_segment = 425 &sgp[(enp->ec_segment - (Sg_desc *) &sg_desc)]; 426 } 427 428 /* 429 * Add each segment descriptor to the segment descriptor list. The 430 * ones with non-NULL sg_name are also entered into the AVL tree. 431 * For each loadable segment initialize a default alignment. Note 432 * that ld(1) and ld.so.1 initialize this differently. 433 */ 434 for (idx = 0; idx < predef_seg_nelts; idx++, sgp++) { 435 Phdr *phdr = &(sgp->sg_phdr); 436 437 #if defined(_ELF64) 438 /* Ignore amd64 segment templates for non-amd64 targets */ 439 switch (sgp->sg_id) { 440 case SGID_LRODATA: 441 case SGID_LDATA: 442 if ((ld_targ.t_m.m_mach != EM_AMD64)) 443 continue; 444 } 445 #endif 446 if (phdr->p_type == PT_LOAD) 447 phdr->p_align = segalign; 448 449 if ((aplist_append(&ofl->ofl_segs, sgp, 450 AL_CNT_SEGMENTS)) == NULL) 451 return (S_ERROR); 452 453 #ifdef NDEBUG /* assert() is enabled */ 454 /* 455 * Enforce the segment name rule: Any segment that can 456 * be referenced by an entrance descriptor must have 457 * a name. Any segment that cannot, must have a NULL 458 * name pointer. 459 */ 460 switch (phdr->p_type) { 461 case PT_LOAD: 462 case PT_NOTE: 463 case PT_NULL: 464 assert(sgp->sg_name != NULL); 465 break; 466 default: 467 assert(sgp->sg_name == NULL); 468 break; 469 } 470 #endif 471 472 /* 473 * Add named segment descriptors to the AVL tree to 474 * provide O(logN) lookups. 475 */ 476 if (sgp->sg_name != NULL) 477 avl_add(&ofl->ofl_segs_avl, sgp); 478 } 479 480 return (1); 481 } 482