order.c revision 2647:e440e3da2a6f
1251881Speter/* 2251881Speter * CDDL HEADER START 3251881Speter * 4251881Speter * The contents of this file are subject to the terms of the 5251881Speter * Common Development and Distribution License (the "License"). 6251881Speter * You may not use this file except in compliance with the License. 7251881Speter * 8251881Speter * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9251881Speter * or http://www.opensolaris.org/os/licensing. 10251881Speter * See the License for the specific language governing permissions 11251881Speter * and limitations under the License. 12251881Speter * 13251881Speter * When distributing Covered Code, include this CDDL HEADER in each 14251881Speter * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15251881Speter * If applicable, add the following below this CDDL HEADER, with the 16251881Speter * fields enclosed by brackets "[]" replaced with your own identifying 17251881Speter * information: Portions Copyright [yyyy] [name of copyright owner] 18251881Speter * 19251881Speter * CDDL HEADER END 20251881Speter */ 21251881Speter 22251881Speter/* 23251881Speter * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24251881Speter * Use is subject to license terms. 25251881Speter */ 26251881Speter 27251881Speter#pragma ident "%Z%%M% %I% %E% SMI" 28251881Speter 29251881Speter/* 30251881Speter * Processing of SHF_ORDERED sections. 31251881Speter */ 32251881Speter#include <stdio.h> 33251881Speter#include <fcntl.h> 34251881Speter#include <link.h> 35251881Speter#include <debug.h> 36251881Speter#include "msg.h" 37251881Speter#include "_libld.h" 38251881Speter 39251881Speter/* 40251881Speter * Part 1, Input processing. 41251881Speter */ 42251881Speter/* 43251881Speter * Get the head section number 44251881Speter */ 45251881Speterstatic Word 46251881Speteris_keylink_ok(Ifl_desc *ifl, Word keylink, Word limit) 47251881Speter{ 48251881Speter if ((keylink != SHN_BEFORE) && (keylink != SHN_AFTER)) { 49251881Speter /* 50251881Speter * Range Check 51251881Speter */ 52251881Speter if ((keylink == 0) || (keylink >= limit)) { 53251881Speter return (DBG_ORDER_LINK_OUTRANGE); 54251881Speter } 55251881Speter 56251881Speter /* 57251881Speter * The section pointed by keylink should not be an 58251881Speter * ordered section. 59251881Speter */ 60251881Speter if (ifl->ifl_isdesc[keylink]->is_shdr->sh_flags & 61251881Speter ALL_SHF_ORDER) { 62251881Speter return (DBG_ORDER_INFO_ORDER); 63251881Speter } 64251881Speter } 65251881Speter return (0); 66251881Speter} 67251881Speter 68251881Speterstatic Word 69251881Speterget_shfordered_dest(Ofl_desc *ofl, Ifl_desc *ifl, Word ndx, Word limit) 70251881Speter{ 71251881Speter Word t1_link = ndx, t2_link, ret_link; 72251881Speter Is_desc *isp, *isp1, *isp2; 73251881Speter int error = 0; 74251881Speter 75251881Speter /* 76251881Speter * Check the sh_info of myself. 77251881Speter */ 78251881Speter isp = ifl->ifl_isdesc[ndx]; 79251881Speter 80251881Speter isp1 = isp; 81251881Speter ret_link = t2_link = isp1->is_shdr->sh_link; 82251881Speter t1_link = ndx; 83251881Speter do { 84251881Speter /* 85251881Speter * Check the validitiy of the link 86251881Speter */ 87251881Speter if (t2_link == 0 || t2_link >= limit) { 88251881Speter error = DBG_ORDER_LINK_OUTRANGE; 89251881Speter break; 90251881Speter } 91251881Speter isp2 = ifl->ifl_isdesc[t2_link]; 92251881Speter 93251881Speter /* 94251881Speter * Pointing to a bad ordered section ? 95251881Speter */ 96251881Speter if ((isp2->is_flags & FLG_IS_ORDERED) == 0) { 97251881Speter error = DBG_ORDER_LINK_ERROR; 98251881Speter break; 99251881Speter } 100251881Speter 101251881Speter /* 102251881Speter * Check sh_flag 103251881Speter */ 104251881Speter if (isp1->is_shdr->sh_flags != isp2->is_shdr->sh_flags) { 105251881Speter error = DBG_ORDER_FLAGS; 106251881Speter break; 107251881Speter } 108251881Speter 109251881Speter /* 110251881Speter * Check the validity of sh_info field. 111251881Speter */ 112251881Speter if ((error = is_keylink_ok(ifl, 113251881Speter isp->is_shdr->sh_info, limit)) != 0) { 114251881Speter break; 115251881Speter } 116251881Speter 117251881Speter /* 118251881Speter * Can I break ? 119251881Speter */ 120251881Speter if (t1_link == t2_link) 121251881Speter break; 122251881Speter 123251881Speter /* 124251881Speter * Get the next link 125251881Speter */ 126251881Speter t1_link = t2_link; 127251881Speter isp1 = ifl->ifl_isdesc[t1_link]; 128251881Speter ret_link = t2_link = isp1->is_shdr->sh_link; 129251881Speter 130251881Speter /* 131251881Speter * Cyclic ? 132251881Speter */ 133251881Speter if (t2_link == ndx) { 134251881Speter error = DBG_ORDER_CYCLIC; 135251881Speter break; 136251881Speter } 137251881Speter /* CONSTANTCONDITION */ 138251881Speter } while (1); 139251881Speter 140251881Speter if (error != 0) { 141251881Speter ret_link = 0; 142251881Speter DBG_CALL(Dbg_sec_order_error(ofl->ofl_lml, ifl, ndx, error)); 143251881Speter } 144251881Speter return (ret_link); 145251881Speter} 146251881Speter 147251881Speter/* 148251881Speter * Called from process_elf(). 149251881Speter * This routine does the input processing of the ordered sections. 150251881Speter */ 151251881Speteruintptr_t 152251881Speterld_process_ordered(Ifl_desc *ifl, Ofl_desc *ofl, Word ndx, Word limit) 153251881Speter{ 154251881Speter Is_desc * isp2, * isp = ifl->ifl_isdesc[ndx]; 155251881Speter Xword shflags = isp->is_shdr->sh_flags; 156251881Speter uint_t keylink; 157251881Speter Os_desc * osp2, * osp; 158251881Speter Word dest_ndx; 159251881Speter Sort_desc * st; 160251881Speter Listnode * lnp; 161251881Speter int error = 0; 162251881Speter 163251881Speter /* 164251881Speter * I might have been checked and marked error already. 165251881Speter */ 166251881Speter if ((isp->is_flags & FLG_IS_ORDERED) == 0) 167251881Speter return (0); 168251881Speter 169251881Speter if (shflags & SHF_ORDERED) 170251881Speter keylink = isp->is_shdr->sh_info; 171251881Speter else if (shflags & SHF_LINK_ORDER) 172251881Speter keylink = isp->is_shdr->sh_link; 173251881Speter else 174251881Speter keylink = 0; 175251881Speter 176251881Speter if ((error = is_keylink_ok(ifl, keylink, limit)) != 0) { 177251881Speter DBG_CALL(Dbg_sec_order_error(ofl->ofl_lml, ifl, ndx, error)); 178251881Speter isp->is_flags &= ~FLG_IS_ORDERED; 179251881Speter if (isp->is_osdesc == NULL) 180251881Speter return ((uintptr_t)ld_place_section(ofl, isp, 181251881Speter isp->is_key, 0)); 182251881Speter return ((uintptr_t)isp->is_osdesc); 183251881Speter } 184251881Speter 185251881Speter /* 186251881Speter * If SHF_ORDERED is in effect, search for our destination section based 187251881Speter * off of sh_link, otherwise follow the default rules for the 188251881Speter * destination section. 189251881Speter */ 190251881Speter if (shflags & SHF_ORDERED) { 191251881Speter if ((dest_ndx = get_shfordered_dest(ofl, ifl, 192251881Speter ndx, limit)) == 0) { 193251881Speter isp->is_flags &= ~FLG_IS_ORDERED; 194251881Speter if (isp->is_osdesc == NULL) 195251881Speter return ((uintptr_t)ld_place_section(ofl, isp, 196251881Speter isp->is_key, 0)); 197251881Speter return ((uintptr_t)isp->is_osdesc); 198251881Speter } 199251881Speter } else { 200251881Speter /* 201251881Speter * SHF_LINK_ORDER coalesces into default sections, set dest_ndx 202251881Speter * to NULL to trigger this. 203251881Speter */ 204251881Speter dest_ndx = 0; 205251881Speter } 206251881Speter 207251881Speter /* 208251881Speter * Place the section into it's output section. 209251881Speter */ 210251881Speter if ((osp = isp->is_osdesc) == NULL) { 211251881Speter if ((osp = ld_place_section(ofl, isp, isp->is_ident, 212251881Speter dest_ndx)) == (Os_desc *)S_ERROR) 213251881Speter return ((uintptr_t)S_ERROR); 214251881Speter if (!osp) 215251881Speter return (0); 216251881Speter } 217251881Speter 218251881Speter /* 219251881Speter * If the output section is not yet on the ordered 220251881Speter * list - place it on the list. 221251881Speter */ 222251881Speter osp2 = NULL; 223251881Speter for (LIST_TRAVERSE(&ofl->ofl_ordered, lnp, osp2)) { 224251881Speter if (osp2 == osp) 225251881Speter break; 226251881Speter } 227251881Speter 228251881Speter if (osp != osp2) { 229251881Speter if (list_appendc(&(ofl->ofl_ordered), osp) == 0) 230251881Speter return ((uintptr_t)S_ERROR); 231251881Speter } 232251881Speter 233251881Speter /* 234251881Speter * Output section has been found - set up it's 235251881Speter * sorting information. 236251881Speter */ 237251881Speter if (osp->os_sort == 0) { 238251881Speter if ((osp->os_sort = libld_calloc(1, sizeof (Sort_desc))) == 0) 239251881Speter return (S_ERROR); 240251881Speter } 241251881Speter st = osp->os_sort; 242251881Speter 243251881Speter if (keylink == SHN_BEFORE) { 244251881Speter st->st_beforecnt++; 245251881Speter } else if (keylink == SHN_AFTER) { 246251881Speter st->st_aftercnt++; 247251881Speter } else { 248251881Speter st->st_ordercnt++; 249251881Speter isp2 = ifl->ifl_isdesc[keylink]; 250251881Speter if (isp2->is_flags & FLG_IS_DISCARD) { 251251881Speter eprintf(ofl->ofl_lml, ERR_FATAL, 252251881Speter MSG_INTL(MSG_FIL_BADORDREF), ifl->ifl_name, 253251881Speter isp->is_name, isp->is_scnndx, isp2->is_name, 254251881Speter isp2->is_scnndx); 255251881Speter return (S_ERROR); 256251881Speter } 257251881Speter osp2 = isp2->is_osdesc; 258251881Speter osp2->os_flags |= FLG_OS_ORDER_KEY; 259251881Speter osp2->os_sgdesc->sg_flags |= FLG_SG_KEY; 260251881Speter isp2->is_flags |= FLG_IS_KEY; 261251881Speter } 262251881Speter 263251881Speter return ((uintptr_t)osp); 264251881Speter} 265251881Speter 266251881Speter/* 267251881Speter * Part 2, Sorting processing 268251881Speter */ 269251881Speter 270251881Speter/* 271251881Speter * Traverse all segments looking for section ordering information that hasn't 272251881Speter * been used. If found give a warning message to the user. Also, check if 273251881Speter * there are any SHF_ORDERED key sections, and if so set up sort key values. 274251881Speter */ 275251881Spetervoid 276251881Speterld_sec_validate(Ofl_desc *ofl) 277251881Speter{ 278251881Speter Listnode *lnp1; 279251881Speter Sg_desc *sgp; 280251881Speter int key = 1; 281251881Speter 282251881Speter for (LIST_TRAVERSE(&ofl->ofl_segs, lnp1, sgp)) { 283251881Speter Sec_order **scopp; 284251881Speter Os_desc **ospp; 285251881Speter Aliste off; 286251881Speter 287251881Speter for (ALIST_TRAVERSE(sgp->sg_secorder, off, scopp)) { 288251881Speter Sec_order *scop = *scopp; 289251881Speter 290251881Speter if ((scop->sco_flags & FLG_SGO_USED) == 0) { 291251881Speter eprintf(ofl->ofl_lml, ERR_WARNING, 292251881Speter MSG_INTL(MSG_MAP_SECORDER), 293251881Speter sgp->sg_name, scop->sco_secname); 294251881Speter } 295251881Speter } 296251881Speter if ((sgp->sg_flags & FLG_SG_KEY) == 0) 297251881Speter continue; 298251881Speter 299251881Speter for (ALIST_TRAVERSE(sgp->sg_osdescs, off, ospp)) { 300251881Speter Listnode *lnp2; 301251881Speter Is_desc *isp; 302251881Speter Os_desc *osp = *ospp; 303251881Speter 304251881Speter if ((osp->os_flags & FLG_OS_ORDER_KEY) == 0) 305251881Speter continue; 306251881Speter 307251881Speter for (LIST_TRAVERSE(&(osp->os_isdescs), lnp2, isp)) { 308251881Speter if (isp->is_flags & FLG_IS_KEY) 309251881Speter isp->is_key = key++; 310251881Speter } 311251881Speter } 312251881Speter } 313251881Speter} 314251881Speter 315251881Speterstatic int 316251881Spetersetup_sortbuf(Os_desc *osp) 317251881Speter{ 318251881Speter Sort_desc *st = osp->os_sort; 319251881Speter Word num_after = 0, num_before = 0, num_order = 0; 320251881Speter Listnode *lnp1; 321251881Speter Is_desc *isp; 322251881Speter 323251881Speter if ((st == NULL) || 324251881Speter ((st->st_ordercnt + st->st_beforecnt + st->st_aftercnt) == 0)) 325251881Speter return (0); 326251881Speter 327251881Speter /* 328251881Speter * Get memory 329251881Speter */ 330251881Speter if (st->st_beforecnt != 0) { 331251881Speter if ((st->st_before = 332251881Speter libld_calloc(st->st_beforecnt, sizeof (Is_desc *))) == 0) 333251881Speter return (0); 334251881Speter } 335251881Speter if (st->st_ordercnt != 0) { 336251881Speter if ((st->st_order = 337251881Speter libld_calloc(st->st_ordercnt, sizeof (Is_desc *))) == 0) 338251881Speter return (0); 339251881Speter } 340251881Speter if (st->st_aftercnt != 0) { 341251881Speter if ((st->st_after = 342251881Speter libld_calloc(st->st_aftercnt, sizeof (Is_desc *))) == 0) 343251881Speter return (0); 344251881Speter } 345251881Speter 346251881Speter /* 347251881Speter * Set info. 348251881Speter */ 349251881Speter for (LIST_TRAVERSE(&(osp->os_isdescs), lnp1, isp)) { 350251881Speter Word keylink = 0; 351251881Speter 352251881Speter if ((isp->is_flags & FLG_IS_ORDERED) == 0) 353251881Speter continue; 354251881Speter 355251881Speter if (isp->is_shdr->sh_flags & SHF_ORDERED) 356251881Speter keylink = isp->is_shdr->sh_info; 357251881Speter else if (isp->is_shdr->sh_flags & SHF_LINK_ORDER) 358251881Speter keylink = isp->is_shdr->sh_link; 359251881Speter 360251881Speter if (keylink == SHN_BEFORE) 361251881Speter st->st_before[num_before++] = isp; 362251881Speter else if (keylink == SHN_AFTER) 363251881Speter st->st_after[num_after++] = isp; 364251881Speter else 365251881Speter st->st_order[num_order++] = isp; 366251881Speter } 367251881Speter return (1); 368251881Speter} 369253734Speter 370251881Speterstatic int 371251881Spetercomp(const void *ss1, const void *ss2) 372251881Speter{ 373251881Speter Is_desc *s1 = *((Is_desc **)ss1); 374251881Speter Is_desc *s2 = *((Is_desc **)ss2); 375251881Speter 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 400uintptr_t 401ld_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