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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 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 <string.h> 34 #include <fcntl.h> 35 #include <link.h> 36 #include "debug.h" 37 #include "msg.h" 38 #include "_libld.h" 39 40 /* 41 * Part 1, Input processing. 42 */ 43 /* 44 * Get the head section number 45 */ 46 static Word 47 is_keylink_ok(Ifl_desc *ifl, Word keylink, Word limit) 48 { 49 if ((keylink != SHN_BEFORE) && (keylink != SHN_AFTER)) { 50 /* 51 * Range Check 52 */ 53 if ((keylink == 0) || (keylink >= limit)) { 54 return (DBG_ORDER_LINK_OUTRANGE); 55 } 56 57 /* 58 * The section pointed by keylink should not be an 59 * ordered section. 60 */ 61 if (ifl->ifl_isdesc[keylink]->is_shdr->sh_flags & 62 ALL_SHF_ORDER) { 63 return (DBG_ORDER_INFO_ORDER); 64 } 65 } 66 return (0); 67 } 68 69 static Word 70 get_shfordered_dest(Ifl_desc *ifl, Word ndx, Word limit) 71 { 72 Word t1_link = ndx, t2_link, ret_link; 73 Is_desc *isp, *isp1, *isp2; 74 int error = 0; 75 76 /* 77 * Check the sh_info of myself. 78 */ 79 isp = ifl->ifl_isdesc[ndx]; 80 81 isp1 = isp; 82 ret_link = t2_link = isp1->is_shdr->sh_link; 83 t1_link = ndx; 84 do { 85 /* 86 * Check the validitiy of the link 87 */ 88 if (t2_link == 0 || t2_link >= limit) { 89 error = DBG_ORDER_LINK_OUTRANGE; 90 break; 91 } 92 isp2 = ifl->ifl_isdesc[t2_link]; 93 94 /* 95 * Pointing to a bad ordered section ? 96 */ 97 if ((isp2->is_flags & FLG_IS_ORDERED) == 0) { 98 error = DBG_ORDER_LINK_ERROR; 99 break; 100 } 101 102 /* 103 * Check sh_flag 104 */ 105 if (isp1->is_shdr->sh_flags != isp2->is_shdr->sh_flags) { 106 error = DBG_ORDER_FLAGS; 107 break; 108 } 109 110 /* 111 * Check the validity of sh_info field. 112 */ 113 if ((error = is_keylink_ok(ifl, 114 isp->is_shdr->sh_info, limit)) != 0) { 115 break; 116 } 117 118 /* 119 * Can I break ? 120 */ 121 if (t1_link == t2_link) 122 break; 123 124 /* 125 * Get the next link 126 */ 127 t1_link = t2_link; 128 isp1 = ifl->ifl_isdesc[t1_link]; 129 ret_link = t2_link = isp1->is_shdr->sh_link; 130 131 /* 132 * Cyclic ? 133 */ 134 if (t2_link == ndx) { 135 error = DBG_ORDER_CYCLIC; 136 break; 137 } 138 /* CONSTANTCONDITION */ 139 } while (1); 140 141 if (error != 0) { 142 ret_link = 0; 143 DBG_CALL(Dbg_sec_order_error(ifl, ndx, error)); 144 } 145 return (ret_link); 146 } 147 148 /* 149 * Called from process_elf(). 150 * This routine does the input processing of the ordered sections. 151 */ 152 uintptr_t 153 process_ordered(Ifl_desc *ifl, Ofl_desc *ofl, Word ndx, Word limit) 154 { 155 Is_desc * isp2, * isp = ifl->ifl_isdesc[ndx]; 156 Xword shflags = isp->is_shdr->sh_flags; 157 uint_t keylink; 158 Os_desc * osp2, * osp; 159 Word dest_ndx; 160 Sort_desc * st; 161 Listnode * lnp; 162 int error = 0; 163 164 /* 165 * I might have been checked and marked error already. 166 */ 167 if ((isp->is_flags & FLG_IS_ORDERED) == 0) 168 return (0); 169 170 keylink = 0; 171 if (shflags & SHF_ORDERED) 172 keylink = isp->is_shdr->sh_info; 173 else if (shflags & SHF_LINK_ORDER) 174 keylink = isp->is_shdr->sh_link; 175 176 if ((error = is_keylink_ok(ifl, keylink, limit)) != 0) { 177 DBG_CALL(Dbg_sec_order_error(ifl, ndx, error)); 178 isp->is_flags &= ~FLG_IS_ORDERED; 179 if (isp->is_osdesc == NULL) 180 return ((uintptr_t)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 - the we search for 187 * our desitination section based off of sh_link else 188 * we follow the default rules for the desitination section. 189 */ 190 if (shflags & SHF_ORDERED) { 191 if ((dest_ndx = get_shfordered_dest(ifl, ndx, limit)) == 0) { 192 isp->is_flags &= ~FLG_IS_ORDERED; 193 if (isp->is_osdesc == NULL) 194 return ((uintptr_t)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 = place_section(ofl, isp, isp->is_ident, dest_ndx)) == 211 (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(ERR_FATAL, MSG_INTL(MSG_FIL_BADORDREF), 249 ifl->ifl_name, isp->is_name, isp->is_scnndx, 250 isp2->is_name, isp2->is_scnndx); 251 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 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 Listnode * lnp2; 281 Sec_order * scop; 282 Os_desc * osp; 283 284 for (LIST_TRAVERSE(&sgp->sg_secorder, lnp2, scop)) 285 if (!(scop->sco_flags & FLG_SGO_USED)) 286 eprintf(ERR_WARNING, MSG_INTL(MSG_MAP_SECORDER), 287 sgp->sg_name, scop->sco_secname); 288 289 if ((sgp->sg_flags & FLG_SG_KEY) == 0) 290 continue; 291 292 for (LIST_TRAVERSE(&(sgp->sg_osdescs), lnp2, osp)) { 293 Listnode * lnp3; 294 Is_desc * isp; 295 296 if ((osp->os_flags & FLG_OS_ORDER_KEY) == 0) 297 continue; 298 299 for (LIST_TRAVERSE(&(osp->os_isdescs), lnp3, isp)) { 300 if (isp->is_flags & FLG_IS_KEY) { 301 isp->is_key = key++; 302 } 303 } 304 } 305 } 306 } 307 308 static int 309 setup_sortbuf(Os_desc *osp) 310 { 311 Sort_desc *st = osp->os_sort; 312 Word num_after = 0, num_before = 0, num_order = 0; 313 Listnode *lnp1; 314 Is_desc *isp; 315 316 if ((st == NULL) || 317 ((st->st_ordercnt + st->st_beforecnt + st->st_aftercnt) == 0)) 318 return (0); 319 320 /* 321 * Get memory 322 */ 323 if (st->st_beforecnt != 0) { 324 if ((st->st_before = 325 libld_calloc(st->st_beforecnt, sizeof (Is_desc *))) == 0) 326 return (0); 327 } 328 if (st->st_ordercnt != 0) { 329 if ((st->st_order = 330 libld_calloc(st->st_ordercnt, sizeof (Is_desc *))) == 0) 331 return (0); 332 } 333 if (st->st_aftercnt != 0) { 334 if ((st->st_after = 335 libld_calloc(st->st_aftercnt, sizeof (Is_desc *))) == 0) 336 return (0); 337 } 338 339 /* 340 * Set info. 341 */ 342 for (LIST_TRAVERSE(&(osp->os_isdescs), lnp1, isp)) { 343 Word keylink = 0; 344 345 if ((isp->is_flags & FLG_IS_ORDERED) == 0) 346 continue; 347 348 if (isp->is_shdr->sh_flags & SHF_ORDERED) 349 keylink = isp->is_shdr->sh_info; 350 else if (isp->is_shdr->sh_flags & SHF_LINK_ORDER) 351 keylink = isp->is_shdr->sh_link; 352 353 if (keylink == SHN_BEFORE) 354 st->st_before[num_before++] = isp; 355 else if (keylink == SHN_AFTER) 356 st->st_after[num_after++] = isp; 357 else 358 st->st_order[num_order++] = isp; 359 } 360 return (1); 361 } 362 363 static int 364 comp(const void *ss1, const void *ss2) 365 { 366 Is_desc *s1 = *((Is_desc **)ss1); 367 Is_desc *s2 = *((Is_desc **)ss2); 368 Is_desc *i1, *i2; 369 Word ndx1, ndx2; 370 371 if (s1->is_shdr->sh_flags & SHF_ORDERED) { 372 ndx1 = s1->is_shdr->sh_info; 373 } else { 374 ndx1 = s1->is_shdr->sh_link; 375 } 376 377 if (s2->is_shdr->sh_flags & SHF_ORDERED) { 378 ndx2 = s2->is_shdr->sh_info; 379 } else { 380 ndx2 = s2->is_shdr->sh_link; 381 } 382 383 i1 = s1->is_file->ifl_isdesc[ndx1]; 384 i2 = s2->is_file->ifl_isdesc[ndx2]; 385 386 if (i1->is_key > i2->is_key) 387 return (1); 388 if (i1->is_key < i2->is_key) 389 return (-1); 390 return (0); 391 } 392 393 uintptr_t 394 sort_ordered(Ofl_desc *ofl) 395 { 396 Listnode *lnp1; 397 Os_desc *osp; 398 399 DBG_CALL(Dbg_sec_order_list(ofl, 0)); 400 401 /* 402 * Sort Sections 403 */ 404 for (LIST_TRAVERSE(&ofl->ofl_ordered, lnp1, osp)) { 405 int i; 406 List islist; 407 Listnode * lnp2; 408 Is_desc * isp; 409 Sort_desc * st = osp->os_sort; 410 411 if (setup_sortbuf(osp) == 0) 412 return (S_ERROR); 413 414 islist = osp->os_isdescs; 415 osp->os_isdescs.head = 0; 416 osp->os_isdescs.tail = 0; 417 418 /* 419 * Sorting. 420 * First Sort the ordered sections. 421 */ 422 if (st->st_ordercnt != 0) 423 qsort((char *)st->st_order, st->st_ordercnt, 424 sizeof (Is_desc *), comp); 425 426 /* 427 * Place SHN_BEFORE at head of list 428 */ 429 for (i = 0; i < st->st_beforecnt; i++) { 430 if (list_appendc(&(osp->os_isdescs), 431 st->st_before[i]) == 0) 432 return (S_ERROR); 433 } 434 435 /* 436 * Next come 'linked' ordered sections 437 */ 438 for (i = 0; i < st->st_ordercnt; i++) { 439 if (list_appendc(&(osp->os_isdescs), 440 st->st_order[i]) == 0) 441 return (S_ERROR); 442 } 443 444 /* 445 * Now we list any sections which have no sorting 446 * specifications - in the order they were input. 447 */ 448 for (LIST_TRAVERSE(&islist, lnp2, isp)) { 449 if (isp->is_flags & FLG_IS_ORDERED) 450 continue; 451 if (list_appendc(&(osp->os_isdescs), 452 isp) == 0) 453 return (S_ERROR); 454 } 455 456 /* 457 * And the end of the list are the SHN_AFTER sections. 458 */ 459 for (i = 0; i < st->st_aftercnt; i++) { 460 if (list_appendc(&(osp->os_isdescs), 461 st->st_after[i]) == 0) 462 return (S_ERROR); 463 } 464 } 465 DBG_CALL(Dbg_sec_order_list(ofl, 1)); 466 return (0); 467 } 468