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 2006 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 **scopp; 284 Os_desc **ospp; 285 Aliste off; 286 287 for (ALIST_TRAVERSE(sgp->sg_secorder, off, scopp)) { 288 Sec_order *scop = *scopp; 289 290 if ((scop->sco_flags & FLG_SGO_USED) == 0) { 291 eprintf(ofl->ofl_lml, ERR_WARNING, 292 MSG_INTL(MSG_MAP_SECORDER), 293 sgp->sg_name, scop->sco_secname); 294 } 295 } 296 if ((sgp->sg_flags & FLG_SG_KEY) == 0) 297 continue; 298 299 for (ALIST_TRAVERSE(sgp->sg_osdescs, off, ospp)) { 300 Listnode *lnp2; 301 Is_desc *isp; 302 Os_desc *osp = *ospp; 303 304 if ((osp->os_flags & FLG_OS_ORDER_KEY) == 0) 305 continue; 306 307 for (LIST_TRAVERSE(&(osp->os_isdescs), lnp2, isp)) { 308 if (isp->is_flags & FLG_IS_KEY) 309 isp->is_key = key++; 310 } 311 } 312 } 313 } 314 315 static int 316 setup_sortbuf(Os_desc *osp) 317 { 318 Sort_desc *st = osp->os_sort; 319 Word num_after = 0, num_before = 0, num_order = 0; 320 Listnode *lnp1; 321 Is_desc *isp; 322 323 if ((st == NULL) || 324 ((st->st_ordercnt + st->st_beforecnt + st->st_aftercnt) == 0)) 325 return (0); 326 327 /* 328 * Get memory 329 */ 330 if (st->st_beforecnt != 0) { 331 if ((st->st_before = 332 libld_calloc(st->st_beforecnt, sizeof (Is_desc *))) == 0) 333 return (0); 334 } 335 if (st->st_ordercnt != 0) { 336 if ((st->st_order = 337 libld_calloc(st->st_ordercnt, sizeof (Is_desc *))) == 0) 338 return (0); 339 } 340 if (st->st_aftercnt != 0) { 341 if ((st->st_after = 342 libld_calloc(st->st_aftercnt, sizeof (Is_desc *))) == 0) 343 return (0); 344 } 345 346 /* 347 * Set info. 348 */ 349 for (LIST_TRAVERSE(&(osp->os_isdescs), lnp1, isp)) { 350 Word keylink = 0; 351 352 if ((isp->is_flags & FLG_IS_ORDERED) == 0) 353 continue; 354 355 if (isp->is_shdr->sh_flags & SHF_ORDERED) 356 keylink = isp->is_shdr->sh_info; 357 else if (isp->is_shdr->sh_flags & SHF_LINK_ORDER) 358 keylink = isp->is_shdr->sh_link; 359 360 if (keylink == SHN_BEFORE) 361 st->st_before[num_before++] = isp; 362 else if (keylink == SHN_AFTER) 363 st->st_after[num_after++] = isp; 364 else 365 st->st_order[num_order++] = isp; 366 } 367 return (1); 368 } 369 370 static int 371 comp(const void *ss1, const void *ss2) 372 { 373 Is_desc *s1 = *((Is_desc **)ss1); 374 Is_desc *s2 = *((Is_desc **)ss2); 375 Is_desc *i1, *i2; 376 Word ndx1, ndx2; 377 378 if (s1->is_shdr->sh_flags & SHF_ORDERED) { 379 ndx1 = s1->is_shdr->sh_info; 380 } else { 381 ndx1 = s1->is_shdr->sh_link; 382 } 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 390 i1 = s1->is_file->ifl_isdesc[ndx1]; 391 i2 = s2->is_file->ifl_isdesc[ndx2]; 392 393 if (i1->is_key > i2->is_key) 394 return (1); 395 if (i1->is_key < i2->is_key) 396 return (-1); 397 return (0); 398 } 399 400 uintptr_t 401 ld_sort_ordered(Ofl_desc *ofl) 402 { 403 Listnode *lnp1; 404 Os_desc *osp; 405 406 DBG_CALL(Dbg_sec_order_list(ofl, 0)); 407 408 /* 409 * Sort Sections 410 */ 411 for (LIST_TRAVERSE(&ofl->ofl_ordered, lnp1, osp)) { 412 int i; 413 List islist; 414 Listnode * lnp2; 415 Is_desc * isp; 416 Sort_desc * st = osp->os_sort; 417 418 if (setup_sortbuf(osp) == 0) 419 return (S_ERROR); 420 421 islist = osp->os_isdescs; 422 osp->os_isdescs.head = 0; 423 osp->os_isdescs.tail = 0; 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 (list_appendc(&(osp->os_isdescs), 438 st->st_before[i]) == 0) 439 return (S_ERROR); 440 } 441 442 /* 443 * Next come 'linked' ordered sections 444 */ 445 for (i = 0; i < st->st_ordercnt; i++) { 446 if (list_appendc(&(osp->os_isdescs), 447 st->st_order[i]) == 0) 448 return (S_ERROR); 449 } 450 451 /* 452 * Now we list any sections which have no sorting 453 * specifications - in the order they were input. 454 */ 455 for (LIST_TRAVERSE(&islist, lnp2, isp)) { 456 if (isp->is_flags & FLG_IS_ORDERED) 457 continue; 458 if (list_appendc(&(osp->os_isdescs), 459 isp) == 0) 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 (list_appendc(&(osp->os_isdescs), 468 st->st_after[i]) == 0) 469 return (S_ERROR); 470 } 471 } 472 DBG_CALL(Dbg_sec_order_list(ofl, 1)); 473 return (0); 474 } 475