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 2008 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 Listnode * lnp; 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 220 * list - place it on the list. 221 */ 222 osp2 = NULL; 223 for (LIST_TRAVERSE(&ofl->ofl_ordered, lnp, osp2)) { 224 if (osp2 == osp) 225 break; 226 } 227 228 if (osp != osp2) { 229 if (list_appendc(&(ofl->ofl_ordered), osp) == 0) 230 return ((uintptr_t)S_ERROR); 231 } 232 233 /* 234 * Output section has been found - set up it's 235 * sorting information. 236 */ 237 if (osp->os_sort == 0) { 238 if ((osp->os_sort = libld_calloc(1, sizeof (Sort_desc))) == 0) 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 Listnode *lnp1; 289 Sg_desc *sgp; 290 Word key = 1; 291 292 for (LIST_TRAVERSE(&ofl->ofl_segs, lnp1, sgp)) { 293 Sec_order *scop; 294 Os_desc *osp; 295 Aliste idx; 296 297 for (APLIST_TRAVERSE(sgp->sg_secorder, idx, 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, idx, osp)) { 308 Listnode *lnp2; 309 Is_desc *isp; 310 311 if ((osp->os_flags & FLG_OS_KEY) == 0) 312 continue; 313 314 for (LIST_TRAVERSE(&(osp->os_isdescs), lnp2, 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 Listnode *lnp1; 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 != 0) { 338 if ((st->st_before = 339 libld_calloc(st->st_beforecnt, sizeof (Is_desc *))) == 0) 340 return (0); 341 } 342 if (st->st_ordercnt != 0) { 343 if ((st->st_order = 344 libld_calloc(st->st_ordercnt, sizeof (Is_desc *))) == 0) 345 return (0); 346 } 347 if (st->st_aftercnt != 0) { 348 if ((st->st_after = 349 libld_calloc(st->st_aftercnt, sizeof (Is_desc *))) == 0) 350 return (0); 351 } 352 353 /* 354 * Set info. 355 */ 356 for (LIST_TRAVERSE(&(osp->os_isdescs), lnp1, isp)) { 357 Word keylink = 0; 358 359 if ((isp->is_flags & FLG_IS_ORDERED) == 0) 360 continue; 361 362 if (isp->is_shdr->sh_flags & SHF_ORDERED) 363 keylink = isp->is_shdr->sh_info; 364 else if (isp->is_shdr->sh_flags & SHF_LINK_ORDER) 365 keylink = isp->is_shdr->sh_link; 366 367 if (keylink == SHN_BEFORE) 368 st->st_before[num_before++] = isp; 369 else if (keylink == SHN_AFTER) 370 st->st_after[num_after++] = isp; 371 else 372 st->st_order[num_order++] = isp; 373 } 374 return (1); 375 } 376 377 static int 378 comp(const void *ss1, const void *ss2) 379 { 380 Is_desc *s1 = *((Is_desc **)ss1); 381 Is_desc *s2 = *((Is_desc **)ss2); 382 Is_desc *i1, *i2; 383 Word ndx1, ndx2; 384 385 if (s1->is_shdr->sh_flags & SHF_ORDERED) 386 ndx1 = s1->is_shdr->sh_info; 387 else 388 ndx1 = s1->is_shdr->sh_link; 389 390 if (s2->is_shdr->sh_flags & SHF_ORDERED) 391 ndx2 = s2->is_shdr->sh_info; 392 else 393 ndx2 = s2->is_shdr->sh_link; 394 395 i1 = s1->is_file->ifl_isdesc[ndx1]; 396 i2 = s2->is_file->ifl_isdesc[ndx2]; 397 398 if (i1->is_keyident > i2->is_keyident) 399 return (1); 400 if (i1->is_keyident < i2->is_keyident) 401 return (-1); 402 return (0); 403 } 404 405 uintptr_t 406 ld_sort_ordered(Ofl_desc *ofl) 407 { 408 Listnode *lnp1; 409 Os_desc *osp; 410 411 DBG_CALL(Dbg_sec_order_list(ofl, 0)); 412 413 /* 414 * Sort Sections 415 */ 416 for (LIST_TRAVERSE(&ofl->ofl_ordered, lnp1, osp)) { 417 int i; 418 List islist; 419 Listnode * lnp2; 420 Is_desc * isp; 421 Sort_desc * st = osp->os_sort; 422 423 if (setup_sortbuf(osp) == 0) 424 return (S_ERROR); 425 426 islist = osp->os_isdescs; 427 osp->os_isdescs.head = 0; 428 osp->os_isdescs.tail = 0; 429 430 /* 431 * Sorting. 432 * First Sort the ordered sections. 433 */ 434 if (st->st_ordercnt != 0) 435 qsort((char *)st->st_order, st->st_ordercnt, 436 sizeof (Is_desc *), comp); 437 438 /* 439 * Place SHN_BEFORE at head of list 440 */ 441 for (i = 0; i < st->st_beforecnt; i++) { 442 if (ld_append_isp(ofl, osp, st->st_before[i], 0) == 0) 443 return (S_ERROR); 444 } 445 446 /* 447 * Next come 'linked' ordered sections 448 */ 449 for (i = 0; i < st->st_ordercnt; i++) { 450 if (ld_append_isp(ofl, osp, st->st_order[i], 0) == 0) 451 return (S_ERROR); 452 } 453 454 /* 455 * Now we list any sections which have no sorting 456 * specifications - in the order they were input. 457 * 458 * We use list_appendc() here instead of ld_append_isp(), 459 * because these items have already been inserted once, and 460 * we don't want any duplicate entries in osp->os_mstridescs. 461 */ 462 for (LIST_TRAVERSE(&islist, lnp2, isp)) { 463 if (isp->is_flags & FLG_IS_ORDERED) 464 continue; 465 if (list_appendc(&(osp->os_isdescs), 466 isp) == 0) 467 return (S_ERROR); 468 } 469 470 /* 471 * And the end of the list are the SHN_AFTER sections. 472 */ 473 for (i = 0; i < st->st_aftercnt; i++) { 474 if (ld_append_isp(ofl, osp, st->st_after[i], 0) == 0) 475 return (S_ERROR); 476 } 477 } 478 DBG_CALL(Dbg_sec_order_list(ofl, 1)); 479 return (0); 480 } 481