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 keylink = 0; 170 if (shflags & SHF_ORDERED) 171 keylink = isp->is_shdr->sh_info; 172 else if (shflags & SHF_LINK_ORDER) 173 keylink = isp->is_shdr->sh_link; 174 175 if ((error = is_keylink_ok(ifl, keylink, limit)) != 0) { 176 DBG_CALL(Dbg_sec_order_error(ofl->ofl_lml, ifl, ndx, error)); 177 isp->is_flags &= ~FLG_IS_ORDERED; 178 if (isp->is_osdesc == NULL) 179 return ((uintptr_t)ld_place_section(ofl, isp, 180 isp->is_key, 0)); 181 return ((uintptr_t)isp->is_osdesc); 182 } 183 184 /* 185 * If SHF_ORDERED is in effect - the we search for 186 * our desitination section based off of sh_link else 187 * we follow the default rules for the desitination 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_key, 0)); 196 return ((uintptr_t)isp->is_osdesc); 197 } 198 } else { 199 /* 200 * SHF_LINK_ORDER coelsces into default sections - so 201 * we set dest_ndx to NULL to trigger this. 202 */ 203 dest_ndx = 0; 204 } 205 206 /* 207 * Place the section into it's output section. 208 */ 209 if ((osp = isp->is_osdesc) == NULL) { 210 if ((osp = ld_place_section(ofl, isp, isp->is_ident, 211 dest_ndx)) == (Os_desc *)S_ERROR) 212 return ((uintptr_t)S_ERROR); 213 if (!osp) 214 return (0); 215 } 216 217 /* 218 * If the output section is not yet on the ordered 219 * list - place it on the list. 220 */ 221 osp2 = NULL; 222 for (LIST_TRAVERSE(&ofl->ofl_ordered, lnp, osp2)) 223 if (osp2 == osp) 224 break; 225 226 if (osp != osp2) 227 if (list_appendc(&(ofl->ofl_ordered), osp) == 0) 228 return ((uintptr_t)S_ERROR); 229 230 /* 231 * Output section has been found - set up it's 232 * sorting information. 233 */ 234 if (osp->os_sort == 0) { 235 if ((osp->os_sort = libld_calloc(1, sizeof (Sort_desc))) == 0) 236 return (S_ERROR); 237 } 238 st = osp->os_sort; 239 240 if (keylink == SHN_BEFORE) { 241 st->st_beforecnt++; 242 } else if (keylink == SHN_AFTER) { 243 st->st_aftercnt++; 244 } else { 245 st->st_ordercnt++; 246 isp2 = ifl->ifl_isdesc[keylink]; 247 if (isp2->is_flags & FLG_IS_DISCARD) { 248 eprintf(ofl->ofl_lml, ERR_FATAL, 249 MSG_INTL(MSG_FIL_BADORDREF), ifl->ifl_name, 250 isp->is_name, isp->is_scnndx, isp2->is_name, 251 isp2->is_scnndx); 252 return (S_ERROR); 253 } 254 osp2 = isp2->is_osdesc; 255 osp2->os_flags |= FLG_OS_ORDER_KEY; 256 osp2->os_sgdesc->sg_flags |= FLG_SG_KEY; 257 isp2->is_flags |= FLG_IS_KEY; 258 } 259 260 return ((uintptr_t)osp); 261 } 262 263 /* 264 * Part 2, Sorting processing 265 */ 266 267 /* 268 * Traverse all segments looking for section ordering information that hasn't 269 * been used. If found give a warning message to the user. Also, check if 270 * there are any SHF_ORDERED key sections, and if so set up sort key values. 271 */ 272 void 273 ld_sec_validate(Ofl_desc *ofl) 274 { 275 Listnode *lnp1; 276 Sg_desc *sgp; 277 int key = 1; 278 279 for (LIST_TRAVERSE(&ofl->ofl_segs, lnp1, sgp)) { 280 Sec_order **scopp; 281 Os_desc **ospp; 282 Aliste off; 283 284 for (ALIST_TRAVERSE(sgp->sg_secorder, off, scopp)) { 285 Sec_order *scop = *scopp; 286 287 if ((scop->sco_flags & FLG_SGO_USED) == 0) { 288 eprintf(ofl->ofl_lml, ERR_WARNING, 289 MSG_INTL(MSG_MAP_SECORDER), 290 sgp->sg_name, scop->sco_secname); 291 } 292 } 293 if ((sgp->sg_flags & FLG_SG_KEY) == 0) 294 continue; 295 296 for (ALIST_TRAVERSE(sgp->sg_osdescs, off, ospp)) { 297 Listnode *lnp2; 298 Is_desc *isp; 299 Os_desc *osp = *ospp; 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 (list_appendc(&(osp->os_isdescs), 435 st->st_before[i]) == 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 (list_appendc(&(osp->os_isdescs), 444 st->st_order[i]) == 0) 445 return (S_ERROR); 446 } 447 448 /* 449 * Now we list any sections which have no sorting 450 * specifications - in the order they were input. 451 */ 452 for (LIST_TRAVERSE(&islist, lnp2, isp)) { 453 if (isp->is_flags & FLG_IS_ORDERED) 454 continue; 455 if (list_appendc(&(osp->os_isdescs), 456 isp) == 0) 457 return (S_ERROR); 458 } 459 460 /* 461 * And the end of the list are the SHN_AFTER sections. 462 */ 463 for (i = 0; i < st->st_aftercnt; i++) { 464 if (list_appendc(&(osp->os_isdescs), 465 st->st_after[i]) == 0) 466 return (S_ERROR); 467 } 468 } 469 DBG_CALL(Dbg_sec_order_list(ofl, 1)); 470 return (0); 471 } 472