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 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * Processing of SHF_ORDERED sections. 31 */ 32 #include <stdio.h> 33 #include <fcntl.h> 34 #include <link.h> 35 #include <debug.h> 36 #include "msg.h" 37 #include "_libld.h" 38 39 /* 40 * Part 1, Input processing. 41 */ 42 /* 43 * Get the head section number 44 */ 45 static Word 46 is_keylink_ok(Ifl_desc *ifl, Word keylink, Word limit) 47 { 48 if ((keylink != SHN_BEFORE) && (keylink != SHN_AFTER)) { 49 /* 50 * Range Check 51 */ 52 if ((keylink == 0) || (keylink >= limit)) { 53 return (DBG_ORDER_LINK_OUTRANGE); 54 } 55 56 /* 57 * The section pointed by keylink should not be an 58 * ordered section. 59 */ 60 if (ifl->ifl_isdesc[keylink]->is_shdr->sh_flags & 61 ALL_SHF_ORDER) { 62 return (DBG_ORDER_INFO_ORDER); 63 } 64 } 65 return (0); 66 } 67 68 static Word 69 get_shfordered_dest(Ofl_desc *ofl, Ifl_desc *ifl, Word ndx, Word limit) 70 { 71 Word t1_link = ndx, t2_link, ret_link; 72 Is_desc *isp, *isp1, *isp2; 73 int error = 0; 74 75 /* 76 * Check the sh_info of myself. 77 */ 78 isp = ifl->ifl_isdesc[ndx]; 79 80 isp1 = isp; 81 ret_link = t2_link = isp1->is_shdr->sh_link; 82 t1_link = ndx; 83 do { 84 /* 85 * Check the validitiy of the link 86 */ 87 if (t2_link == 0 || t2_link >= limit) { 88 error = DBG_ORDER_LINK_OUTRANGE; 89 break; 90 } 91 isp2 = ifl->ifl_isdesc[t2_link]; 92 93 /* 94 * Pointing to a bad ordered section ? 95 */ 96 if ((isp2->is_flags & FLG_IS_ORDERED) == 0) { 97 error = DBG_ORDER_LINK_ERROR; 98 break; 99 } 100 101 /* 102 * Check sh_flag 103 */ 104 if (isp1->is_shdr->sh_flags != isp2->is_shdr->sh_flags) { 105 error = DBG_ORDER_FLAGS; 106 break; 107 } 108 109 /* 110 * Check the validity of sh_info field. 111 */ 112 if ((error = is_keylink_ok(ifl, 113 isp->is_shdr->sh_info, limit)) != 0) { 114 break; 115 } 116 117 /* 118 * Can I break ? 119 */ 120 if (t1_link == t2_link) 121 break; 122 123 /* 124 * Get the next link 125 */ 126 t1_link = t2_link; 127 isp1 = ifl->ifl_isdesc[t1_link]; 128 ret_link = t2_link = isp1->is_shdr->sh_link; 129 130 /* 131 * Cyclic ? 132 */ 133 if (t2_link == ndx) { 134 error = DBG_ORDER_CYCLIC; 135 break; 136 } 137 /* CONSTANTCONDITION */ 138 } while (1); 139 140 if (error != 0) { 141 ret_link = 0; 142 DBG_CALL(Dbg_sec_order_error(ofl->ofl_lml, ifl, ndx, error)); 143 } 144 return (ret_link); 145 } 146 147 /* 148 * Called from process_elf(). 149 * This routine does the input processing of the ordered sections. 150 */ 151 uintptr_t 152 ld_process_ordered(Ifl_desc *ifl, Ofl_desc *ofl, Word ndx, Word limit) 153 { 154 Is_desc * isp2, * isp = ifl->ifl_isdesc[ndx]; 155 Xword shflags = isp->is_shdr->sh_flags; 156 uint_t keylink; 157 Os_desc * osp2, * osp; 158 Word dest_ndx; 159 Sort_desc * st; 160 Listnode * lnp; 161 int error = 0; 162 163 /* 164 * I might have been checked and marked error already. 165 */ 166 if ((isp->is_flags & FLG_IS_ORDERED) == 0) 167 return (0); 168 169 if (shflags & SHF_ORDERED) 170 keylink = isp->is_shdr->sh_info; 171 else if (shflags & SHF_LINK_ORDER) 172 keylink = isp->is_shdr->sh_link; 173 else 174 keylink = 0; 175 176 if ((error = is_keylink_ok(ifl, keylink, limit)) != 0) { 177 DBG_CALL(Dbg_sec_order_error(ofl->ofl_lml, ifl, ndx, error)); 178 isp->is_flags &= ~FLG_IS_ORDERED; 179 if (isp->is_osdesc == NULL) 180 return ((uintptr_t)ld_place_section(ofl, isp, 181 isp->is_key, 0)); 182 return ((uintptr_t)isp->is_osdesc); 183 } 184 185 /* 186 * If SHF_ORDERED is in effect, search for our destination section based 187 * off of sh_link, otherwise follow the default rules for the 188 * destination section. 189 */ 190 if (shflags & SHF_ORDERED) { 191 if ((dest_ndx = get_shfordered_dest(ofl, ifl, 192 ndx, limit)) == 0) { 193 isp->is_flags &= ~FLG_IS_ORDERED; 194 if (isp->is_osdesc == NULL) 195 return ((uintptr_t)ld_place_section(ofl, isp, 196 isp->is_key, 0)); 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_ident, 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 osp2 = isp2->is_osdesc; 258 osp2->os_flags |= FLG_OS_ORDER_KEY; 259 osp2->os_sgdesc->sg_flags |= FLG_SG_KEY; 260 isp2->is_flags |= FLG_IS_KEY; 261 } 262 263 return ((uintptr_t)osp); 264 } 265 266 /* 267 * Part 2, Sorting processing 268 */ 269 270 /* 271 * Traverse all segments looking for section ordering information that hasn't 272 * been used. If found give a warning message to the user. Also, check if 273 * there are any SHF_ORDERED key sections, and if so set up sort key values. 274 */ 275 void 276 ld_sec_validate(Ofl_desc *ofl) 277 { 278 Listnode *lnp1; 279 Sg_desc *sgp; 280 int key = 1; 281 282 for (LIST_TRAVERSE(&ofl->ofl_segs, lnp1, sgp)) { 283 Sec_order *scop; 284 Os_desc *osp; 285 Aliste idx; 286 287 for (APLIST_TRAVERSE(sgp->sg_secorder, idx, scop)) { 288 if ((scop->sco_flags & FLG_SGO_USED) == 0) { 289 eprintf(ofl->ofl_lml, ERR_WARNING, 290 MSG_INTL(MSG_MAP_SECORDER), 291 sgp->sg_name, scop->sco_secname); 292 } 293 } 294 if ((sgp->sg_flags & FLG_SG_KEY) == 0) 295 continue; 296 297 for (APLIST_TRAVERSE(sgp->sg_osdescs, idx, osp)) { 298 Listnode *lnp2; 299 Is_desc *isp; 300 301 if ((osp->os_flags & FLG_OS_ORDER_KEY) == 0) 302 continue; 303 304 for (LIST_TRAVERSE(&(osp->os_isdescs), lnp2, isp)) { 305 if (isp->is_flags & FLG_IS_KEY) 306 isp->is_key = key++; 307 } 308 } 309 } 310 } 311 312 static int 313 setup_sortbuf(Os_desc *osp) 314 { 315 Sort_desc *st = osp->os_sort; 316 Word num_after = 0, num_before = 0, num_order = 0; 317 Listnode *lnp1; 318 Is_desc *isp; 319 320 if ((st == NULL) || 321 ((st->st_ordercnt + st->st_beforecnt + st->st_aftercnt) == 0)) 322 return (0); 323 324 /* 325 * Get memory 326 */ 327 if (st->st_beforecnt != 0) { 328 if ((st->st_before = 329 libld_calloc(st->st_beforecnt, sizeof (Is_desc *))) == 0) 330 return (0); 331 } 332 if (st->st_ordercnt != 0) { 333 if ((st->st_order = 334 libld_calloc(st->st_ordercnt, sizeof (Is_desc *))) == 0) 335 return (0); 336 } 337 if (st->st_aftercnt != 0) { 338 if ((st->st_after = 339 libld_calloc(st->st_aftercnt, sizeof (Is_desc *))) == 0) 340 return (0); 341 } 342 343 /* 344 * Set info. 345 */ 346 for (LIST_TRAVERSE(&(osp->os_isdescs), lnp1, isp)) { 347 Word keylink = 0; 348 349 if ((isp->is_flags & FLG_IS_ORDERED) == 0) 350 continue; 351 352 if (isp->is_shdr->sh_flags & SHF_ORDERED) 353 keylink = isp->is_shdr->sh_info; 354 else if (isp->is_shdr->sh_flags & SHF_LINK_ORDER) 355 keylink = isp->is_shdr->sh_link; 356 357 if (keylink == SHN_BEFORE) 358 st->st_before[num_before++] = isp; 359 else if (keylink == SHN_AFTER) 360 st->st_after[num_after++] = isp; 361 else 362 st->st_order[num_order++] = isp; 363 } 364 return (1); 365 } 366 367 static int 368 comp(const void *ss1, const void *ss2) 369 { 370 Is_desc *s1 = *((Is_desc **)ss1); 371 Is_desc *s2 = *((Is_desc **)ss2); 372 Is_desc *i1, *i2; 373 Word ndx1, ndx2; 374 375 if (s1->is_shdr->sh_flags & SHF_ORDERED) { 376 ndx1 = s1->is_shdr->sh_info; 377 } else { 378 ndx1 = s1->is_shdr->sh_link; 379 } 380 381 if (s2->is_shdr->sh_flags & SHF_ORDERED) { 382 ndx2 = s2->is_shdr->sh_info; 383 } else { 384 ndx2 = s2->is_shdr->sh_link; 385 } 386 387 i1 = s1->is_file->ifl_isdesc[ndx1]; 388 i2 = s2->is_file->ifl_isdesc[ndx2]; 389 390 if (i1->is_key > i2->is_key) 391 return (1); 392 if (i1->is_key < i2->is_key) 393 return (-1); 394 return (0); 395 } 396 397 uintptr_t 398 ld_sort_ordered(Ofl_desc *ofl) 399 { 400 Listnode *lnp1; 401 Os_desc *osp; 402 403 DBG_CALL(Dbg_sec_order_list(ofl, 0)); 404 405 /* 406 * Sort Sections 407 */ 408 for (LIST_TRAVERSE(&ofl->ofl_ordered, lnp1, osp)) { 409 int i; 410 List islist; 411 Listnode * lnp2; 412 Is_desc * isp; 413 Sort_desc * st = osp->os_sort; 414 415 if (setup_sortbuf(osp) == 0) 416 return (S_ERROR); 417 418 islist = osp->os_isdescs; 419 osp->os_isdescs.head = 0; 420 osp->os_isdescs.tail = 0; 421 422 /* 423 * Sorting. 424 * First Sort the ordered sections. 425 */ 426 if (st->st_ordercnt != 0) 427 qsort((char *)st->st_order, st->st_ordercnt, 428 sizeof (Is_desc *), comp); 429 430 /* 431 * Place SHN_BEFORE at head of list 432 */ 433 for (i = 0; i < st->st_beforecnt; i++) { 434 if (ld_append_isp(ofl, osp, st->st_before[i], 0) == 0) 435 return (S_ERROR); 436 } 437 438 /* 439 * Next come 'linked' ordered sections 440 */ 441 for (i = 0; i < st->st_ordercnt; i++) { 442 if (ld_append_isp(ofl, osp, st->st_order[i], 0) == 0) 443 return (S_ERROR); 444 } 445 446 /* 447 * Now we list any sections which have no sorting 448 * specifications - in the order they were input. 449 * 450 * We use list_appendc() here instead of ld_append_isp(), 451 * because these items have already been inserted once, and 452 * we don't want any duplicate entries in osp->os_mstridescs. 453 */ 454 for (LIST_TRAVERSE(&islist, lnp2, isp)) { 455 if (isp->is_flags & FLG_IS_ORDERED) 456 continue; 457 if (list_appendc(&(osp->os_isdescs), 458 isp) == 0) 459 return (S_ERROR); 460 } 461 462 /* 463 * And the end of the list are the SHN_AFTER sections. 464 */ 465 for (i = 0; i < st->st_aftercnt; i++) { 466 if (ld_append_isp(ofl, osp, st->st_after[i], 0) == 0) 467 return (S_ERROR); 468 } 469 } 470 DBG_CALL(Dbg_sec_order_list(ofl, 1)); 471 return (0); 472 } 473