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