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 2010 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * Processing of SHF_ORDERED sections. 29 */ 30 #include <stdio.h> 31 #include <fcntl.h> 32 #include <link.h> 33 #include <debug.h> 34 #include "msg.h" 35 #include "_libld.h" 36 37 /* 38 * Section Ordering History/Background: 39 * 40 * There are two forms of section ordering, SHF_ORDERED, and SHF_LINK_ORDER. 41 * 42 * SHF_ORDERED was invented at Sun in order to support the PowerPC port 43 * of Solaris 2.6, which used it for sorting tag words which describe 44 * the state of callee saves registers for given PC ranges. It was defined 45 * in the OS specific ELF section flag range. Some other values were defined 46 * at the same time: 47 * SHF_EXCLUDE - Section is to be excluded from executables or shared 48 * objects, and only kept in relocatable object output. 49 * SHN_BEFORE/SHN_AFTER - Sections are placed before/after all other 50 * sections, in the order they are encountered by the linker. 51 * Although initially conceived to support the PowerPC, the functionality 52 * was implemented for all platforms, and was later used to manage C++ 53 * exceptions and stack unwinding. The PowerPC port was discontinued after 54 * one release, but SHF_ORDERED lives on. 55 * 56 * SHF_LINK_ORDER was invented later by the wider ELF community, and is 57 * therefore assigned a value in the generic ELF section flag range. It is 58 * essentially a simpler version of SHF_ORDERED, dispensing with some 59 * unnecessary features. The Solaris implementation of SHF_LINK_ORDER uses 60 * SHF_EXCLUDE, and SHF_BEFORE/SHN_AFTER as well, but it appears that these 61 * are still Solaris-only extensions not used by other implementations. 62 * SHF_LINK_ORDER has superseded SHF_ORDERED. The older mechanism is 63 * supported for the benefit of old pre-existing objects. 64 * 65 * ----- 66 * 67 * SHF_ORDERED offers two distinct and separate abilities: 68 * 69 * (1) To specify the output section 70 * (2) To optionally be sorted relative to other sorted sections, 71 * using a non-sorted section as a sort key. 72 * 73 * To do this, it uses both the sh_link, and sh_info fields: 74 * 75 * sh_link 76 * Specifies the output section to receive this input section. 77 * The sh_link field of an SHF_ORDERED section forms a linked list of 78 * sections, all of which must have identical section header flags 79 * (including SHF_ORDERED). The list is terminated by a final section 80 * with a sh_link that points at itself. All input sections in this list 81 * are assigned to the output section of the final section in the list. 82 * Hence, if a section points at itself, the effect is that it gets 83 * assigned to an output section in the usual default manner (i.e. an 84 * output section with the same name as the input). However, it can 85 * point at any arbitrary other section. This is a way to put a section 86 * with one name into an output section with a different name. It should 87 * be noted that this is of little value overall, because the link-editor 88 * already supports a more general feature for directing input sections 89 * to output sections: An input section named .text%foo will be sent to 90 * an output section named ".text", and this works for all sections, 91 * not just ordered ones. 92 * 93 * sh_info 94 * If sh_info is in the range (1 <= value < shnum), then this input section 95 * is added to the group of sorted sections. The section referenced by 96 * sh_info must be unsorted, and is used as the sort key. 97 * 98 * If sh_info is SHN_BEFORE or SHN_AFTER, it is put in the pre/post group, 99 * in the order it arrives (the before/after classes are not sorted). 100 * 101 * If sh_info is "invalid" (typically 0), then this section is added to 102 * the group of non-sorted sections, and goes into the output file in the 103 * order it arrives. This is not a valuable feature, as the same effect 104 * can be achieved more simply by not setting SHF_ORDERED at all. 105 * 106 * SHF_LINK_ORDER is a simplification of SHF_ORDERED. It uses sh_link to specify 107 * the section to use as a sort key and sh_info is set to 0. The standard 108 * ".text%foo" mechanism is used to direct input sections to output sections, 109 * and unordered sections indicate that by not setting SHF_LINK_ORDER. 110 */ 111 112 113 /* 114 * A "keyshndx" is the section index for the unordered section that should 115 * be used as a sort key for a ordered section. Verify that the given 116 * keyshndx is valid. 117 * 118 * exit: 119 * Returns 0 if the keyshndx is valid. A non-zero DBG_ORDER_ code is 120 * returned if the keyshndx is not valid to describe the problem. 121 */ 122 inline static Word 123 is_keyshndx_ok(Ifl_desc *ifl, Word keyshndx) 124 { 125 if ((keyshndx == SHN_BEFORE) || (keyshndx == SHN_AFTER)) 126 return (0); 127 128 /* 129 * Validate the key range. 130 */ 131 if ((keyshndx == 0) || (keyshndx >= ifl->ifl_shnum)) 132 return (DBG_ORDER_LINK_OUTRANGE); 133 134 /* 135 * The section pointed to by keyshndx should not be an ordered section. 136 * Strictly speaking, we could test for SHF_ORDERED here instead of 137 * ALL_SHF_ORDER as the two ordering flags are not supposed to be 138 * mixed. Using ALL_SHF_ORDER costs the same and ensures that such 139 * mixing doesn't go undetected. 140 */ 141 if (ifl->ifl_isdesc[keyshndx]->is_shdr->sh_flags & ALL_SHF_ORDER) 142 return (DBG_ORDER_INFO_ORDER); 143 144 return (0); 145 } 146 147 /* 148 * The sh_link field of an SHF_ORDERED section forms a linked list of 149 * sections. The list is terminated by a final section with a sh_link 150 * that points at itself. Given the index of an SHF_ORDERED section, find 151 * the index of the final section in the list. 152 * 153 * entry: 154 * ofl - Output file descriptor 155 * ifl - Input file descriptor 156 * ndx - Section index of SHF_ORDERED section 157 * alt_os_name - Address of pointer to string. If the final section 158 * name is different than the section given by ndx, *alt_os_name 159 * will be updated with the name of the final section. The caller 160 * should initialize *alt_os_name to NULL before calling 161 * this routine. 162 * 163 * exit: 164 * On success: If the final section is different than the section 165 * given by ndx, then *alt_os_name is set to its name. TRUE is returned. 166 * 167 * On failure, FALSE is returned. 168 */ 169 static Boolean 170 validate_shf_ordered_dest(Ofl_desc *ofl, Ifl_desc *ifl, Word ndx, 171 const char **alt_os_name) 172 { 173 Word shnum = ifl->ifl_shnum; 174 Word isp1_ndx, isp2_ndx; 175 Is_desc *isp1, *isp2; 176 int error = 0; 177 size_t iter = 0; 178 179 /* 180 * Traverse the list until we find the termination, or encounter 181 * an invalid condition in the object that prevents ordering. 182 */ 183 isp1_ndx = ndx; 184 isp1 = ifl->ifl_isdesc[ndx]; 185 do { 186 /* 187 * Obtain index of next section in list. Ensure it is in range. 188 */ 189 isp2_ndx = isp1->is_shdr->sh_link; 190 if ((isp2_ndx == 0) || (isp2_ndx >= shnum)) { 191 error = DBG_ORDER_LINK_OUTRANGE; 192 break; 193 } 194 isp2 = ifl->ifl_isdesc[isp2_ndx]; 195 196 /* The section flags must match exactly */ 197 if (isp1->is_shdr->sh_flags != isp2->is_shdr->sh_flags) { 198 /* 199 * The case where the next section in the list does 200 * not have the same ordered flag set as the original 201 * ordered section gets a unique error code. This 202 * provides more accurate/useful debugging diagnostics. 203 */ 204 error = ((isp2->is_flags & FLG_IS_ORDERED) == 0) ? 205 DBG_ORDER_LINK_ERROR : DBG_ORDER_FLAGS; 206 break; 207 } 208 209 /* 210 * The sh_info field specifies the section index of an 211 * unorderd section which will be used as a sort key. 212 * Ensure it is in range. If not, we terminate the list 213 * at the current node instead of continuing on. 214 */ 215 if ((error = is_keyshndx_ok(ifl, isp2->is_shdr->sh_info)) != 0) 216 break; 217 218 /* If the section points at itself, it terminates the list */ 219 if (isp1_ndx == isp2_ndx) 220 break; 221 222 /* 223 * Advance to next section in list 224 */ 225 isp1_ndx = isp2_ndx; 226 isp1 = isp2; 227 228 /* 229 * If we loop more times than the input file has sections, 230 * we have encountered a malformed object in which the list 231 * of SHF_ORDERED sections has a cycle. This can only happen 232 * if the compiler generating the object has a bad bug. 233 */ 234 if (++iter >= shnum) { 235 error = DBG_ORDER_CYCLIC; 236 break; 237 } 238 /* CONSTANTCONDITION */ 239 } while (1); 240 241 /* 242 * If we have found a problem, issue a debug diagnostic and map 243 * the output section to 0. This indicates that the section should 244 * remove the ordering flag and treat it as a standard section. 245 */ 246 if (error != 0) { 247 isp2_ndx = 0; 248 DBG_CALL(Dbg_sec_order_error(ofl->ofl_lml, ifl, ndx, error)); 249 } 250 251 /* Report success */ 252 if (isp2_ndx != 0) { 253 /* 254 * If the destination section is different than the input 255 * section, then set *alt_os_name to the destination name. 256 */ 257 if (isp2_ndx != ndx) 258 *alt_os_name = ifl->ifl_isdesc[isp2_ndx]->is_name; 259 return (TRUE); 260 } 261 262 /* If we get here, there is no valid destination */ 263 return (FALSE); 264 } 265 266 /* 267 * Called when an ordered section has a problem that prevents ordering. 268 * The order flag is removed, and then the section is placed as an 269 * unsorted section. 270 */ 271 static uintptr_t 272 place_unordered(Ofl_desc *ofl, Is_desc *isp, Place_path_info *path_info) 273 { 274 isp->is_flags &= ~FLG_IS_ORDERED; 275 if (isp->is_osdesc == NULL) 276 return ((uintptr_t)ld_place_section(ofl, isp, path_info, 277 isp->is_keyident, NULL)); 278 return ((uintptr_t)isp->is_osdesc); 279 } 280 281 /* 282 * Process ordered input section. Called from process_elf() after 283 * all the non-ordered sections have been placed. 284 * 285 * entry: 286 * ofl - Output file descriptor 287 * ifl - Input file descriptor 288 * ndx - Section index of SHF_ORDERED section 289 * 290 * exit: 291 */ 292 uintptr_t 293 ld_process_ordered(Ofl_desc *ofl, Ifl_desc *ifl, Place_path_info *path_info, 294 Word ndx) 295 { 296 Is_desc *isp2, *isp = ifl->ifl_isdesc[ndx]; 297 Xword shflags = isp->is_shdr->sh_flags; 298 const char *alt_os_name = NULL; 299 Word keyshndx; 300 Os_desc *osp; 301 int error = 0; 302 303 /* 304 * Obtain the sort key section index for this ordered section. 305 * SHF_ORDERED uses sh_info, while SHF_LINK_ORDER uses sh_link. 306 * In order for this function to be called, one of SHF_ORDERED 307 * or SHF_LINK_ORDER must be set. Testing for one implies the 308 * state of the other. 309 */ 310 keyshndx = (shflags & SHF_ORDERED) ? 311 isp->is_shdr->sh_info : isp->is_shdr->sh_link; 312 313 /* 314 * Validate the sort key section index. If something is wrong, 315 * fall back to treating it as a non-ordered section. 316 */ 317 if ((error = is_keyshndx_ok(ifl, keyshndx)) != 0) { 318 DBG_CALL(Dbg_sec_order_error(ofl->ofl_lml, ifl, ndx, error)); 319 return (place_unordered(ofl, isp, path_info)); 320 } 321 322 /* 323 * If SHF_ORDERED is in effect, validate the destination section 324 * name given by sh_link, and set alt_os_name to the name of the 325 * destination if it differs from the section being processed. 326 */ 327 if ((shflags & SHF_ORDERED) && 328 (validate_shf_ordered_dest(ofl, ifl, ndx, &alt_os_name) == FALSE)) 329 return (place_unordered(ofl, isp, path_info)); 330 331 /* 332 * Place the section into its output section. It's possible that this 333 * section is discarded (possibly because it's defined COMDAT), in 334 * which case we're done. 335 */ 336 if ((osp = isp->is_osdesc) == NULL) { 337 osp = ld_place_section(ofl, isp, path_info, isp->is_keyident, 338 alt_os_name); 339 if ((osp == (Os_desc *)S_ERROR) || (osp == NULL)) 340 return ((uintptr_t)osp); 341 } 342 343 /* 344 * If the output section is not yet on the ordered list, place it on 345 * the list. 346 */ 347 if (aplist_test(&ofl->ofl_ordered, osp, AL_CNT_OFL_ORDERED) == 348 ALE_ALLOCFAIL) 349 return ((uintptr_t)S_ERROR); 350 351 /* 352 * Output section has been found - set up its sorting information. 353 */ 354 if ((keyshndx != SHN_BEFORE) && (keyshndx != SHN_AFTER)) { 355 Os_desc *osp2; 356 357 isp2 = ifl->ifl_isdesc[keyshndx]; 358 if (isp2->is_flags & FLG_IS_DISCARD) { 359 eprintf(ofl->ofl_lml, ERR_FATAL, 360 MSG_INTL(MSG_FIL_BADORDREF), ifl->ifl_name, 361 EC_WORD(isp->is_scnndx), isp->is_name, 362 EC_WORD(isp2->is_scnndx), isp2->is_name); 363 return (S_ERROR); 364 } 365 366 /* 367 * Indicate that this ordered input section will require a 368 * sort key. Propagate the key requirement through to the 369 * associated output section, segment and file, to trigger 370 * the sort key creation. See ld_sec_validate(); 371 */ 372 isp2->is_flags |= FLG_IS_KEY; 373 374 osp2 = isp2->is_osdesc; 375 osp2->os_flags |= FLG_OS_KEY; 376 osp2->os_sgdesc->sg_flags |= FLG_SG_KEY; 377 378 ofl->ofl_flags |= FLG_OF_KEY; 379 } 380 381 return ((uintptr_t)osp); 382 } 383 384 /* 385 * Traverse all segments looking for section ordering information that hasn't 386 * been used. If found give a warning message to the user. Also, check if 387 * there are any ordered key sections, and if so set up sort key values. 388 */ 389 void 390 ld_sec_validate(Ofl_desc *ofl) 391 { 392 Aliste idx1; 393 Sg_desc *sgp; 394 Word key = 1; 395 396 for (APLIST_TRAVERSE(ofl->ofl_segs, idx1, sgp)) { 397 Sec_order *scop; 398 Os_desc *osp; 399 Aliste idx2; 400 401 for (ALIST_TRAVERSE(sgp->sg_os_order, idx2, scop)) { 402 if ((scop->sco_flags & FLG_SGO_USED) == 0) { 403 eprintf(ofl->ofl_lml, ERR_WARNING, 404 MSG_INTL(MSG_MAP_SECORDER), 405 sgp->sg_name, scop->sco_secname); 406 } 407 } 408 if ((sgp->sg_flags & FLG_SG_KEY) == 0) 409 continue; 410 411 for (APLIST_TRAVERSE(sgp->sg_osdescs, idx2, osp)) { 412 Aliste idx3; 413 Is_desc *isp; 414 415 if ((osp->os_flags & FLG_OS_KEY) == 0) 416 continue; 417 418 /* 419 * The input sections used as sort keys are required 420 * to be unordered, so we only have to look at the 421 * DEFAULT list of input sections. 422 */ 423 for (APLIST_TRAVERSE(osp->os_isdescs[OS_ISD_DEFAULT], 424 idx3, isp)) { 425 if (isp->is_flags & FLG_IS_KEY) 426 isp->is_keyident = key++; 427 } 428 } 429 } 430 } 431 432 static int 433 comp(const void *ss1, const void *ss2) 434 { 435 Is_desc *s1 = *((Is_desc **)ss1); 436 Is_desc *s2 = *((Is_desc **)ss2); 437 Is_desc *i1, *i2; 438 Word ndx1, ndx2; 439 440 if (s1->is_shdr->sh_flags & SHF_ORDERED) 441 ndx1 = s1->is_shdr->sh_info; 442 else 443 ndx1 = s1->is_shdr->sh_link; 444 445 if (s2->is_shdr->sh_flags & SHF_ORDERED) 446 ndx2 = s2->is_shdr->sh_info; 447 else 448 ndx2 = s2->is_shdr->sh_link; 449 450 i1 = s1->is_file->ifl_isdesc[ndx1]; 451 i2 = s2->is_file->ifl_isdesc[ndx2]; 452 453 if (i1->is_keyident > i2->is_keyident) 454 return (1); 455 if (i1->is_keyident < i2->is_keyident) 456 return (-1); 457 return (0); 458 } 459 460 /* 461 * Sort ordered input sections 462 */ 463 uintptr_t 464 ld_sort_ordered(Ofl_desc *ofl) 465 { 466 Aliste idx1; 467 Os_desc *osp; 468 469 DBG_CALL(Dbg_sec_order_list(ofl, 0)); 470 471 for (APLIST_TRAVERSE(ofl->ofl_ordered, idx1, osp)) { 472 APlist *ap_list = osp->os_isdescs[OS_ISD_ORDERED]; 473 Aliste apl_nitems = aplist_nitems(ap_list); 474 475 /* 476 * If this output section has a non-empty list of ordered 477 * input sections, sort their APlist in place into their 478 * final order. 479 */ 480 if (apl_nitems != 0) 481 qsort((char *)ap_list->apl_data, apl_nitems, 482 sizeof (Is_desc *), comp); 483 } 484 DBG_CALL(Dbg_sec_order_list(ofl, 1)); 485 return (0); 486 } 487