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 2009 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 * Part 1, Input processing. 39 */ 40 /* 41 * Get the head section number 42 */ 43 inline static Word 44 is_keylink_ok(Ifl_desc *ifl, Word keylink, Word limit) 45 { 46 if ((keylink == SHN_BEFORE) || (keylink == SHN_AFTER)) 47 return (0); 48 49 /* 50 * Validate the key range. 51 */ 52 if ((keylink == 0) || (keylink >= limit)) 53 return (DBG_ORDER_LINK_OUTRANGE); 54 55 /* 56 * The section pointed to by keylink should not be an ordered section. 57 */ 58 if (ifl->ifl_isdesc[keylink]->is_shdr->sh_flags & ALL_SHF_ORDER) 59 return (DBG_ORDER_INFO_ORDER); 60 61 return (0); 62 } 63 64 /* 65 * Get the head section number. 66 */ 67 static Word 68 get_shfordered_dest(Ofl_desc *ofl, Ifl_desc *ifl, Word ndx, Word limit) 69 { 70 Word t1_link = ndx, t2_link, ret_link; 71 Is_desc *isp, *isp1, *isp2; 72 int error = 0; 73 74 /* 75 * Check the sh_info of myself. 76 */ 77 isp = ifl->ifl_isdesc[ndx]; 78 79 isp1 = isp; 80 ret_link = t2_link = isp1->is_shdr->sh_link; 81 t1_link = ndx; 82 do { 83 /* 84 * Check the validitiy of the link 85 */ 86 if (t2_link == 0 || t2_link >= limit) { 87 error = DBG_ORDER_LINK_OUTRANGE; 88 break; 89 } 90 isp2 = ifl->ifl_isdesc[t2_link]; 91 92 /* 93 * Pointing to a bad ordered section ? 94 */ 95 if ((isp2->is_flags & FLG_IS_ORDERED) == 0) { 96 error = DBG_ORDER_LINK_ERROR; 97 break; 98 } 99 100 /* 101 * Check sh_flag 102 */ 103 if (isp1->is_shdr->sh_flags != isp2->is_shdr->sh_flags) { 104 error = DBG_ORDER_FLAGS; 105 break; 106 } 107 108 /* 109 * Check the validity of sh_info field. 110 */ 111 if ((error = is_keylink_ok(ifl, 112 isp->is_shdr->sh_info, limit)) != 0) { 113 break; 114 } 115 116 /* 117 * Can I break ? 118 */ 119 if (t1_link == t2_link) 120 break; 121 122 /* 123 * Get the next link 124 */ 125 t1_link = t2_link; 126 isp1 = ifl->ifl_isdesc[t1_link]; 127 ret_link = t2_link = isp1->is_shdr->sh_link; 128 129 /* 130 * Cyclic ? 131 */ 132 if (t2_link == ndx) { 133 error = DBG_ORDER_CYCLIC; 134 break; 135 } 136 /* CONSTANTCONDITION */ 137 } while (1); 138 139 if (error != 0) { 140 ret_link = 0; 141 DBG_CALL(Dbg_sec_order_error(ofl->ofl_lml, ifl, ndx, error)); 142 } 143 return (ret_link); 144 } 145 146 /* 147 * Called from process_elf(). 148 * This routine does the input processing of the ordered sections. 149 */ 150 uintptr_t 151 ld_process_ordered(Ifl_desc *ifl, Ofl_desc *ofl, Word ndx) 152 { 153 Is_desc *isp2, *isp = ifl->ifl_isdesc[ndx]; 154 Xword shflags = isp->is_shdr->sh_flags; 155 Word keylink, dest_ndx, limit = ifl->ifl_shnum; 156 Os_desc *osp2, *osp; 157 Sort_desc *st; 158 Aliste idx; 159 int error = 0; 160 161 /* 162 * This section might have been checked and marked in error already. 163 */ 164 if ((isp->is_flags & FLG_IS_ORDERED) == 0) 165 return (0); 166 167 if (shflags & SHF_ORDERED) 168 keylink = isp->is_shdr->sh_info; 169 else if (shflags & SHF_LINK_ORDER) 170 keylink = isp->is_shdr->sh_link; 171 else 172 keylink = 0; 173 174 if ((error = is_keylink_ok(ifl, keylink, limit)) != 0) { 175 DBG_CALL(Dbg_sec_order_error(ofl->ofl_lml, ifl, ndx, error)); 176 isp->is_flags &= ~FLG_IS_ORDERED; 177 if (isp->is_osdesc == NULL) { 178 return ((uintptr_t)ld_place_section(ofl, isp, 179 isp->is_keyident, 0)); 180 } 181 return ((uintptr_t)isp->is_osdesc); 182 } 183 184 /* 185 * If SHF_ORDERED is in effect, search for our destination section based 186 * off of sh_link, otherwise follow the default rules for the 187 * destination section. 188 */ 189 if (shflags & SHF_ORDERED) { 190 if ((dest_ndx = get_shfordered_dest(ofl, ifl, 191 ndx, limit)) == 0) { 192 isp->is_flags &= ~FLG_IS_ORDERED; 193 if (isp->is_osdesc == NULL) { 194 return ((uintptr_t)ld_place_section(ofl, isp, 195 isp->is_keyident, 0)); 196 } 197 return ((uintptr_t)isp->is_osdesc); 198 } 199 } else { 200 /* 201 * SHF_LINK_ORDER coalesces into default sections, set dest_ndx 202 * to NULL to trigger this. 203 */ 204 dest_ndx = 0; 205 } 206 207 /* 208 * Place the section into its output section. It's possible that this 209 * section is discarded (possibly because it's defined COMDAT), in 210 * which case we're done. 211 */ 212 if ((osp = isp->is_osdesc) == NULL) { 213 if ((osp = ld_place_section(ofl, isp, isp->is_keyident, 214 dest_ndx)) == (Os_desc *)S_ERROR) 215 return ((uintptr_t)S_ERROR); 216 if (!osp) 217 return (0); 218 } 219 220 /* 221 * If the output section is not yet on the ordered list, place it on 222 * the list. 223 */ 224 osp2 = NULL; 225 for (APLIST_TRAVERSE(ofl->ofl_ordered, idx, osp2)) { 226 if (osp2 == osp) 227 break; 228 } 229 230 if ((osp != osp2) && (aplist_append(&(ofl->ofl_ordered), 231 osp, AL_CNT_OFL_ORDERED) == NULL)) 232 return ((uintptr_t)S_ERROR); 233 234 /* 235 * Output section has been found - set up it's sorting information. 236 */ 237 if ((osp->os_sort == NULL) && 238 ((osp->os_sort = libld_calloc(1, sizeof (Sort_desc))) == NULL)) 239 return (S_ERROR); 240 241 st = osp->os_sort; 242 243 if (keylink == SHN_BEFORE) { 244 st->st_beforecnt++; 245 } else if (keylink == SHN_AFTER) { 246 st->st_aftercnt++; 247 } else { 248 st->st_ordercnt++; 249 isp2 = ifl->ifl_isdesc[keylink]; 250 if (isp2->is_flags & FLG_IS_DISCARD) { 251 eprintf(ofl->ofl_lml, ERR_FATAL, 252 MSG_INTL(MSG_FIL_BADORDREF), ifl->ifl_name, 253 isp->is_name, isp->is_scnndx, isp2->is_name, 254 isp2->is_scnndx); 255 return (S_ERROR); 256 } 257 258 /* 259 * Indicate that this ordered input section will require a sort 260 * key created. Propagate the key requirement through to the 261 * associated output section, segment and file, to trigger the 262 * sort key creation. See ld_sec_validate(); 263 */ 264 isp2->is_flags |= FLG_IS_KEY; 265 266 osp2 = isp2->is_osdesc; 267 osp2->os_flags |= FLG_OS_KEY; 268 osp2->os_sgdesc->sg_flags |= FLG_SG_KEY; 269 270 ofl->ofl_flags |= FLG_OF_KEY; 271 } 272 273 return ((uintptr_t)osp); 274 } 275 276 /* 277 * Part 2, Sorting processing 278 */ 279 280 /* 281 * Traverse all segments looking for section ordering information that hasn't 282 * been used. If found give a warning message to the user. Also, check if 283 * there are any SHF_ORDERED key sections, and if so set up sort key values. 284 */ 285 void 286 ld_sec_validate(Ofl_desc *ofl) 287 { 288 Aliste idx1; 289 Sg_desc *sgp; 290 Word key = 1; 291 292 for (APLIST_TRAVERSE(ofl->ofl_segs, idx1, sgp)) { 293 Sec_order *scop; 294 Os_desc *osp; 295 Aliste idx2; 296 297 for (APLIST_TRAVERSE(sgp->sg_secorder, idx2, scop)) { 298 if ((scop->sco_flags & FLG_SGO_USED) == 0) { 299 eprintf(ofl->ofl_lml, ERR_WARNING, 300 MSG_INTL(MSG_MAP_SECORDER), 301 sgp->sg_name, scop->sco_secname); 302 } 303 } 304 if ((sgp->sg_flags & FLG_SG_KEY) == 0) 305 continue; 306 307 for (APLIST_TRAVERSE(sgp->sg_osdescs, idx2, osp)) { 308 Aliste idx3; 309 Is_desc *isp; 310 311 if ((osp->os_flags & FLG_OS_KEY) == 0) 312 continue; 313 314 for (APLIST_TRAVERSE(osp->os_isdescs, idx3, isp)) { 315 if (isp->is_flags & FLG_IS_KEY) 316 isp->is_keyident = key++; 317 } 318 } 319 } 320 } 321 322 static int 323 setup_sortbuf(Os_desc *osp) 324 { 325 Sort_desc *st = osp->os_sort; 326 Word num_after = 0, num_before = 0, num_order = 0; 327 Aliste idx; 328 Is_desc *isp; 329 330 if ((st == NULL) || 331 ((st->st_ordercnt + st->st_beforecnt + st->st_aftercnt) == 0)) 332 return (0); 333 334 /* 335 * Get memory 336 */ 337 if (st->st_beforecnt && ((st->st_before = libld_calloc(st->st_beforecnt, 338 sizeof (Is_desc *))) == NULL)) 339 return (0); 340 341 if (st->st_ordercnt && ((st->st_order = libld_calloc(st->st_ordercnt, 342 sizeof (Is_desc *))) == NULL)) 343 return (0); 344 345 if (st->st_aftercnt && ((st->st_after = libld_calloc(st->st_aftercnt, 346 sizeof (Is_desc *))) == NULL)) 347 return (0); 348 349 /* 350 * Set info. 351 */ 352 for (APLIST_TRAVERSE(osp->os_isdescs, idx, isp)) { 353 Word keylink = 0; 354 355 if ((isp->is_flags & FLG_IS_ORDERED) == 0) 356 continue; 357 358 if (isp->is_shdr->sh_flags & SHF_ORDERED) 359 keylink = isp->is_shdr->sh_info; 360 else if (isp->is_shdr->sh_flags & SHF_LINK_ORDER) 361 keylink = isp->is_shdr->sh_link; 362 363 if (keylink == SHN_BEFORE) 364 st->st_before[num_before++] = isp; 365 else if (keylink == SHN_AFTER) 366 st->st_after[num_after++] = isp; 367 else 368 st->st_order[num_order++] = isp; 369 } 370 return (1); 371 } 372 373 static int 374 comp(const void *ss1, const void *ss2) 375 { 376 Is_desc *s1 = *((Is_desc **)ss1); 377 Is_desc *s2 = *((Is_desc **)ss2); 378 Is_desc *i1, *i2; 379 Word ndx1, ndx2; 380 381 if (s1->is_shdr->sh_flags & SHF_ORDERED) 382 ndx1 = s1->is_shdr->sh_info; 383 else 384 ndx1 = s1->is_shdr->sh_link; 385 386 if (s2->is_shdr->sh_flags & SHF_ORDERED) 387 ndx2 = s2->is_shdr->sh_info; 388 else 389 ndx2 = s2->is_shdr->sh_link; 390 391 i1 = s1->is_file->ifl_isdesc[ndx1]; 392 i2 = s2->is_file->ifl_isdesc[ndx2]; 393 394 if (i1->is_keyident > i2->is_keyident) 395 return (1); 396 if (i1->is_keyident < i2->is_keyident) 397 return (-1); 398 return (0); 399 } 400 401 uintptr_t 402 ld_sort_ordered(Ofl_desc *ofl) 403 { 404 Aliste idx1; 405 Os_desc *osp; 406 407 DBG_CALL(Dbg_sec_order_list(ofl, 0)); 408 409 /* 410 * Sort Sections 411 */ 412 for (APLIST_TRAVERSE(ofl->ofl_ordered, idx1, osp)) { 413 int i; 414 APlist *islist = NULL; 415 Aliste idx2; 416 Is_desc *isp; 417 Sort_desc *st = osp->os_sort; 418 419 if (setup_sortbuf(osp) == 0) 420 return (S_ERROR); 421 422 islist = osp->os_isdescs; 423 osp->os_isdescs = NULL; 424 425 /* 426 * Sorting. 427 * First Sort the ordered sections. 428 */ 429 if (st->st_ordercnt != 0) 430 qsort((char *)st->st_order, st->st_ordercnt, 431 sizeof (Is_desc *), comp); 432 433 /* 434 * Place SHN_BEFORE at head of list 435 */ 436 for (i = 0; i < st->st_beforecnt; i++) { 437 if (ld_append_isp(ofl, osp, st->st_before[i], 0) == 0) 438 return (S_ERROR); 439 } 440 441 /* 442 * Next come 'linked' ordered sections 443 */ 444 for (i = 0; i < st->st_ordercnt; i++) { 445 if (ld_append_isp(ofl, osp, st->st_order[i], 0) == 0) 446 return (S_ERROR); 447 } 448 449 /* 450 * Now we list any sections which have no sorting 451 * specifications - in the order they were input. 452 * 453 * We use aplist_append() here instead of ld_append_isp(), 454 * because these items have already been inserted once, and 455 * we don't want any duplicate entries in osp->os_mstridescs. 456 */ 457 for (APLIST_TRAVERSE(islist, idx2, isp)) { 458 if (isp->is_flags & FLG_IS_ORDERED) 459 continue; 460 if (aplist_append(&(osp->os_isdescs), 461 isp, AL_CNT_OS_ISDESCS) == NULL) 462 return (S_ERROR); 463 } 464 465 /* 466 * And the end of the list are the SHN_AFTER sections. 467 */ 468 for (i = 0; i < st->st_aftercnt; i++) { 469 if (ld_append_isp(ofl, osp, st->st_after[i], 0) == 0) 470 return (S_ERROR); 471 } 472 473 if (islist) 474 free(islist); 475 } 476 DBG_CALL(Dbg_sec_order_list(ofl, 1)); 477 return (0); 478 } 479