17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 55aefb655Srie * Common Development and Distribution License (the "License"). 65aefb655Srie * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 215aefb655Srie 227c478bd9Sstevel@tonic-gate /* 23cce0e03bSab196087 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate /* 287c478bd9Sstevel@tonic-gate * Processing of SHF_ORDERED sections. 297c478bd9Sstevel@tonic-gate */ 307c478bd9Sstevel@tonic-gate #include <stdio.h> 317c478bd9Sstevel@tonic-gate #include <fcntl.h> 327c478bd9Sstevel@tonic-gate #include <link.h> 335aefb655Srie #include <debug.h> 347c478bd9Sstevel@tonic-gate #include "msg.h" 357c478bd9Sstevel@tonic-gate #include "_libld.h" 367c478bd9Sstevel@tonic-gate 377c478bd9Sstevel@tonic-gate /* 387c478bd9Sstevel@tonic-gate * Part 1, Input processing. 397c478bd9Sstevel@tonic-gate */ 407c478bd9Sstevel@tonic-gate /* 417c478bd9Sstevel@tonic-gate * Get the head section number 427c478bd9Sstevel@tonic-gate */ 437c478bd9Sstevel@tonic-gate static Word 447c478bd9Sstevel@tonic-gate is_keylink_ok(Ifl_desc *ifl, Word keylink, Word limit) 457c478bd9Sstevel@tonic-gate { 467c478bd9Sstevel@tonic-gate if ((keylink != SHN_BEFORE) && (keylink != SHN_AFTER)) { 477c478bd9Sstevel@tonic-gate /* 487c478bd9Sstevel@tonic-gate * Range Check 497c478bd9Sstevel@tonic-gate */ 507c478bd9Sstevel@tonic-gate if ((keylink == 0) || (keylink >= limit)) { 517c478bd9Sstevel@tonic-gate return (DBG_ORDER_LINK_OUTRANGE); 527c478bd9Sstevel@tonic-gate } 537c478bd9Sstevel@tonic-gate 547c478bd9Sstevel@tonic-gate /* 557c478bd9Sstevel@tonic-gate * The section pointed by keylink should not be an 567c478bd9Sstevel@tonic-gate * ordered section. 577c478bd9Sstevel@tonic-gate */ 587c478bd9Sstevel@tonic-gate if (ifl->ifl_isdesc[keylink]->is_shdr->sh_flags & 597c478bd9Sstevel@tonic-gate ALL_SHF_ORDER) { 607c478bd9Sstevel@tonic-gate return (DBG_ORDER_INFO_ORDER); 617c478bd9Sstevel@tonic-gate } 627c478bd9Sstevel@tonic-gate } 637c478bd9Sstevel@tonic-gate return (0); 647c478bd9Sstevel@tonic-gate } 657c478bd9Sstevel@tonic-gate 667c478bd9Sstevel@tonic-gate static Word 675aefb655Srie get_shfordered_dest(Ofl_desc *ofl, Ifl_desc *ifl, Word ndx, Word limit) 687c478bd9Sstevel@tonic-gate { 697c478bd9Sstevel@tonic-gate Word t1_link = ndx, t2_link, ret_link; 707c478bd9Sstevel@tonic-gate Is_desc *isp, *isp1, *isp2; 717c478bd9Sstevel@tonic-gate int error = 0; 727c478bd9Sstevel@tonic-gate 737c478bd9Sstevel@tonic-gate /* 747c478bd9Sstevel@tonic-gate * Check the sh_info of myself. 757c478bd9Sstevel@tonic-gate */ 767c478bd9Sstevel@tonic-gate isp = ifl->ifl_isdesc[ndx]; 777c478bd9Sstevel@tonic-gate 787c478bd9Sstevel@tonic-gate isp1 = isp; 797c478bd9Sstevel@tonic-gate ret_link = t2_link = isp1->is_shdr->sh_link; 807c478bd9Sstevel@tonic-gate t1_link = ndx; 817c478bd9Sstevel@tonic-gate do { 827c478bd9Sstevel@tonic-gate /* 837c478bd9Sstevel@tonic-gate * Check the validitiy of the link 847c478bd9Sstevel@tonic-gate */ 857c478bd9Sstevel@tonic-gate if (t2_link == 0 || t2_link >= limit) { 867c478bd9Sstevel@tonic-gate error = DBG_ORDER_LINK_OUTRANGE; 877c478bd9Sstevel@tonic-gate break; 887c478bd9Sstevel@tonic-gate } 897c478bd9Sstevel@tonic-gate isp2 = ifl->ifl_isdesc[t2_link]; 907c478bd9Sstevel@tonic-gate 917c478bd9Sstevel@tonic-gate /* 927c478bd9Sstevel@tonic-gate * Pointing to a bad ordered section ? 937c478bd9Sstevel@tonic-gate */ 947c478bd9Sstevel@tonic-gate if ((isp2->is_flags & FLG_IS_ORDERED) == 0) { 957c478bd9Sstevel@tonic-gate error = DBG_ORDER_LINK_ERROR; 967c478bd9Sstevel@tonic-gate break; 977c478bd9Sstevel@tonic-gate } 987c478bd9Sstevel@tonic-gate 997c478bd9Sstevel@tonic-gate /* 1007c478bd9Sstevel@tonic-gate * Check sh_flag 1017c478bd9Sstevel@tonic-gate */ 1027c478bd9Sstevel@tonic-gate if (isp1->is_shdr->sh_flags != isp2->is_shdr->sh_flags) { 1037c478bd9Sstevel@tonic-gate error = DBG_ORDER_FLAGS; 1047c478bd9Sstevel@tonic-gate break; 1057c478bd9Sstevel@tonic-gate } 1067c478bd9Sstevel@tonic-gate 1077c478bd9Sstevel@tonic-gate /* 1087c478bd9Sstevel@tonic-gate * Check the validity of sh_info field. 1097c478bd9Sstevel@tonic-gate */ 1107c478bd9Sstevel@tonic-gate if ((error = is_keylink_ok(ifl, 1117c478bd9Sstevel@tonic-gate isp->is_shdr->sh_info, limit)) != 0) { 1127c478bd9Sstevel@tonic-gate break; 1137c478bd9Sstevel@tonic-gate } 1147c478bd9Sstevel@tonic-gate 1157c478bd9Sstevel@tonic-gate /* 1167c478bd9Sstevel@tonic-gate * Can I break ? 1177c478bd9Sstevel@tonic-gate */ 1187c478bd9Sstevel@tonic-gate if (t1_link == t2_link) 1197c478bd9Sstevel@tonic-gate break; 1207c478bd9Sstevel@tonic-gate 1217c478bd9Sstevel@tonic-gate /* 1227c478bd9Sstevel@tonic-gate * Get the next link 1237c478bd9Sstevel@tonic-gate */ 1247c478bd9Sstevel@tonic-gate t1_link = t2_link; 1257c478bd9Sstevel@tonic-gate isp1 = ifl->ifl_isdesc[t1_link]; 1267c478bd9Sstevel@tonic-gate ret_link = t2_link = isp1->is_shdr->sh_link; 1277c478bd9Sstevel@tonic-gate 1287c478bd9Sstevel@tonic-gate /* 1297c478bd9Sstevel@tonic-gate * Cyclic ? 1307c478bd9Sstevel@tonic-gate */ 1317c478bd9Sstevel@tonic-gate if (t2_link == ndx) { 1327c478bd9Sstevel@tonic-gate error = DBG_ORDER_CYCLIC; 1337c478bd9Sstevel@tonic-gate break; 1347c478bd9Sstevel@tonic-gate } 1357c478bd9Sstevel@tonic-gate /* CONSTANTCONDITION */ 1367c478bd9Sstevel@tonic-gate } while (1); 1377c478bd9Sstevel@tonic-gate 1387c478bd9Sstevel@tonic-gate if (error != 0) { 1397c478bd9Sstevel@tonic-gate ret_link = 0; 1405aefb655Srie DBG_CALL(Dbg_sec_order_error(ofl->ofl_lml, ifl, ndx, error)); 1417c478bd9Sstevel@tonic-gate } 1427c478bd9Sstevel@tonic-gate return (ret_link); 1437c478bd9Sstevel@tonic-gate } 1447c478bd9Sstevel@tonic-gate 1457c478bd9Sstevel@tonic-gate /* 1467c478bd9Sstevel@tonic-gate * Called from process_elf(). 1477c478bd9Sstevel@tonic-gate * This routine does the input processing of the ordered sections. 1487c478bd9Sstevel@tonic-gate */ 1497c478bd9Sstevel@tonic-gate uintptr_t 1505aefb655Srie ld_process_ordered(Ifl_desc *ifl, Ofl_desc *ofl, Word ndx, Word limit) 1517c478bd9Sstevel@tonic-gate { 1527c478bd9Sstevel@tonic-gate Is_desc * isp2, * isp = ifl->ifl_isdesc[ndx]; 1537c478bd9Sstevel@tonic-gate Xword shflags = isp->is_shdr->sh_flags; 1547c478bd9Sstevel@tonic-gate uint_t keylink; 1557c478bd9Sstevel@tonic-gate Os_desc * osp2, * osp; 1567c478bd9Sstevel@tonic-gate Word dest_ndx; 1577c478bd9Sstevel@tonic-gate Sort_desc * st; 1587c478bd9Sstevel@tonic-gate Listnode * lnp; 1597c478bd9Sstevel@tonic-gate int error = 0; 1607c478bd9Sstevel@tonic-gate 1617c478bd9Sstevel@tonic-gate /* 1627c478bd9Sstevel@tonic-gate * I might have been checked and marked error already. 1637c478bd9Sstevel@tonic-gate */ 1647c478bd9Sstevel@tonic-gate if ((isp->is_flags & FLG_IS_ORDERED) == 0) 1657c478bd9Sstevel@tonic-gate return (0); 1667c478bd9Sstevel@tonic-gate 1677c478bd9Sstevel@tonic-gate if (shflags & SHF_ORDERED) 1687c478bd9Sstevel@tonic-gate keylink = isp->is_shdr->sh_info; 1697c478bd9Sstevel@tonic-gate else if (shflags & SHF_LINK_ORDER) 1707c478bd9Sstevel@tonic-gate keylink = isp->is_shdr->sh_link; 1717010c12aSrie else 1727010c12aSrie keylink = 0; 1737c478bd9Sstevel@tonic-gate 1747c478bd9Sstevel@tonic-gate if ((error = is_keylink_ok(ifl, keylink, limit)) != 0) { 1755aefb655Srie DBG_CALL(Dbg_sec_order_error(ofl->ofl_lml, ifl, ndx, error)); 1767c478bd9Sstevel@tonic-gate isp->is_flags &= ~FLG_IS_ORDERED; 177*0e233487SRod Evans if (isp->is_osdesc == NULL) { 1785aefb655Srie return ((uintptr_t)ld_place_section(ofl, isp, 179*0e233487SRod Evans isp->is_keyident, 0)); 180*0e233487SRod Evans } 1817c478bd9Sstevel@tonic-gate return ((uintptr_t)isp->is_osdesc); 1827c478bd9Sstevel@tonic-gate } 1837c478bd9Sstevel@tonic-gate 1847c478bd9Sstevel@tonic-gate /* 1857010c12aSrie * If SHF_ORDERED is in effect, search for our destination section based 1867010c12aSrie * off of sh_link, otherwise follow the default rules for the 1877010c12aSrie * destination section. 1887c478bd9Sstevel@tonic-gate */ 1897c478bd9Sstevel@tonic-gate if (shflags & SHF_ORDERED) { 1905aefb655Srie if ((dest_ndx = get_shfordered_dest(ofl, ifl, 1915aefb655Srie ndx, limit)) == 0) { 1927c478bd9Sstevel@tonic-gate isp->is_flags &= ~FLG_IS_ORDERED; 193*0e233487SRod Evans if (isp->is_osdesc == NULL) { 1945aefb655Srie return ((uintptr_t)ld_place_section(ofl, isp, 195*0e233487SRod Evans isp->is_keyident, 0)); 196*0e233487SRod Evans } 1977c478bd9Sstevel@tonic-gate return ((uintptr_t)isp->is_osdesc); 1987c478bd9Sstevel@tonic-gate } 1997c478bd9Sstevel@tonic-gate } else { 2007c478bd9Sstevel@tonic-gate /* 2017010c12aSrie * SHF_LINK_ORDER coalesces into default sections, set dest_ndx 2027010c12aSrie * to NULL to trigger this. 2037c478bd9Sstevel@tonic-gate */ 2047c478bd9Sstevel@tonic-gate dest_ndx = 0; 2057c478bd9Sstevel@tonic-gate } 2067c478bd9Sstevel@tonic-gate 2077c478bd9Sstevel@tonic-gate /* 2087c478bd9Sstevel@tonic-gate * Place the section into it's output section. 2097c478bd9Sstevel@tonic-gate */ 2107c478bd9Sstevel@tonic-gate if ((osp = isp->is_osdesc) == NULL) { 211*0e233487SRod Evans if ((osp = ld_place_section(ofl, isp, isp->is_keyident, 2125aefb655Srie dest_ndx)) == (Os_desc *)S_ERROR) 2137c478bd9Sstevel@tonic-gate return ((uintptr_t)S_ERROR); 2147c478bd9Sstevel@tonic-gate if (!osp) 2157c478bd9Sstevel@tonic-gate return (0); 2167c478bd9Sstevel@tonic-gate } 2177c478bd9Sstevel@tonic-gate 2187c478bd9Sstevel@tonic-gate /* 2197c478bd9Sstevel@tonic-gate * If the output section is not yet on the ordered 2207c478bd9Sstevel@tonic-gate * list - place it on the list. 2217c478bd9Sstevel@tonic-gate */ 2227c478bd9Sstevel@tonic-gate osp2 = NULL; 2237010c12aSrie for (LIST_TRAVERSE(&ofl->ofl_ordered, lnp, osp2)) { 2247c478bd9Sstevel@tonic-gate if (osp2 == osp) 2257c478bd9Sstevel@tonic-gate break; 2267010c12aSrie } 2277c478bd9Sstevel@tonic-gate 2287010c12aSrie if (osp != osp2) { 2297c478bd9Sstevel@tonic-gate if (list_appendc(&(ofl->ofl_ordered), osp) == 0) 2307c478bd9Sstevel@tonic-gate return ((uintptr_t)S_ERROR); 2317010c12aSrie } 2327c478bd9Sstevel@tonic-gate 2337c478bd9Sstevel@tonic-gate /* 2347c478bd9Sstevel@tonic-gate * Output section has been found - set up it's 2357c478bd9Sstevel@tonic-gate * sorting information. 2367c478bd9Sstevel@tonic-gate */ 2377c478bd9Sstevel@tonic-gate if (osp->os_sort == 0) { 2387c478bd9Sstevel@tonic-gate if ((osp->os_sort = libld_calloc(1, sizeof (Sort_desc))) == 0) 2397c478bd9Sstevel@tonic-gate return (S_ERROR); 2407c478bd9Sstevel@tonic-gate } 2417c478bd9Sstevel@tonic-gate st = osp->os_sort; 2427c478bd9Sstevel@tonic-gate 2437c478bd9Sstevel@tonic-gate if (keylink == SHN_BEFORE) { 2447c478bd9Sstevel@tonic-gate st->st_beforecnt++; 2457c478bd9Sstevel@tonic-gate } else if (keylink == SHN_AFTER) { 2467c478bd9Sstevel@tonic-gate st->st_aftercnt++; 2477c478bd9Sstevel@tonic-gate } else { 2487c478bd9Sstevel@tonic-gate st->st_ordercnt++; 2497c478bd9Sstevel@tonic-gate isp2 = ifl->ifl_isdesc[keylink]; 2507c478bd9Sstevel@tonic-gate if (isp2->is_flags & FLG_IS_DISCARD) { 2515aefb655Srie eprintf(ofl->ofl_lml, ERR_FATAL, 2525aefb655Srie MSG_INTL(MSG_FIL_BADORDREF), ifl->ifl_name, 2535aefb655Srie isp->is_name, isp->is_scnndx, isp2->is_name, 2545aefb655Srie isp2->is_scnndx); 2557c478bd9Sstevel@tonic-gate return (S_ERROR); 2567c478bd9Sstevel@tonic-gate } 257*0e233487SRod Evans 258*0e233487SRod Evans /* 259*0e233487SRod Evans * Indicate that this ordered input section will require a sort 260*0e233487SRod Evans * key created. Propagate the key requirement through to the 261*0e233487SRod Evans * associated output section, segment and file, to trigger the 262*0e233487SRod Evans * sort key creation. See ld_sec_validate(); 263*0e233487SRod Evans */ 2647c478bd9Sstevel@tonic-gate isp2->is_flags |= FLG_IS_KEY; 265*0e233487SRod Evans 266*0e233487SRod Evans osp2 = isp2->is_osdesc; 267*0e233487SRod Evans osp2->os_flags |= FLG_OS_KEY; 268*0e233487SRod Evans osp2->os_sgdesc->sg_flags |= FLG_SG_KEY; 269*0e233487SRod Evans 270*0e233487SRod Evans ofl->ofl_flags |= FLG_OF_KEY; 2717c478bd9Sstevel@tonic-gate } 2727c478bd9Sstevel@tonic-gate 2737c478bd9Sstevel@tonic-gate return ((uintptr_t)osp); 2747c478bd9Sstevel@tonic-gate } 2757c478bd9Sstevel@tonic-gate 2767c478bd9Sstevel@tonic-gate /* 2777c478bd9Sstevel@tonic-gate * Part 2, Sorting processing 2787c478bd9Sstevel@tonic-gate */ 2797c478bd9Sstevel@tonic-gate 2807c478bd9Sstevel@tonic-gate /* 2817c478bd9Sstevel@tonic-gate * Traverse all segments looking for section ordering information that hasn't 2827c478bd9Sstevel@tonic-gate * been used. If found give a warning message to the user. Also, check if 2837c478bd9Sstevel@tonic-gate * there are any SHF_ORDERED key sections, and if so set up sort key values. 2847c478bd9Sstevel@tonic-gate */ 2857c478bd9Sstevel@tonic-gate void 2865aefb655Srie ld_sec_validate(Ofl_desc *ofl) 2877c478bd9Sstevel@tonic-gate { 2887c478bd9Sstevel@tonic-gate Listnode *lnp1; 2897c478bd9Sstevel@tonic-gate Sg_desc *sgp; 290*0e233487SRod Evans Word key = 1; 2917c478bd9Sstevel@tonic-gate 2927c478bd9Sstevel@tonic-gate for (LIST_TRAVERSE(&ofl->ofl_segs, lnp1, sgp)) { 293cce0e03bSab196087 Sec_order *scop; 294cce0e03bSab196087 Os_desc *osp; 295cce0e03bSab196087 Aliste idx; 2967c478bd9Sstevel@tonic-gate 297cce0e03bSab196087 for (APLIST_TRAVERSE(sgp->sg_secorder, idx, scop)) { 2980bc07c75Srie if ((scop->sco_flags & FLG_SGO_USED) == 0) { 2995aefb655Srie eprintf(ofl->ofl_lml, ERR_WARNING, 3005aefb655Srie MSG_INTL(MSG_MAP_SECORDER), 3017c478bd9Sstevel@tonic-gate sgp->sg_name, scop->sco_secname); 3020bc07c75Srie } 3030bc07c75Srie } 3047c478bd9Sstevel@tonic-gate if ((sgp->sg_flags & FLG_SG_KEY) == 0) 3057c478bd9Sstevel@tonic-gate continue; 3067c478bd9Sstevel@tonic-gate 307cce0e03bSab196087 for (APLIST_TRAVERSE(sgp->sg_osdescs, idx, osp)) { 3080bc07c75Srie Listnode *lnp2; 3097c478bd9Sstevel@tonic-gate Is_desc *isp; 3107c478bd9Sstevel@tonic-gate 311*0e233487SRod Evans if ((osp->os_flags & FLG_OS_KEY) == 0) 3127c478bd9Sstevel@tonic-gate continue; 3137c478bd9Sstevel@tonic-gate 3140bc07c75Srie for (LIST_TRAVERSE(&(osp->os_isdescs), lnp2, isp)) { 3150bc07c75Srie if (isp->is_flags & FLG_IS_KEY) 316*0e233487SRod Evans isp->is_keyident = key++; 3177c478bd9Sstevel@tonic-gate } 3187c478bd9Sstevel@tonic-gate } 3197c478bd9Sstevel@tonic-gate } 3207c478bd9Sstevel@tonic-gate } 3217c478bd9Sstevel@tonic-gate 3227c478bd9Sstevel@tonic-gate static int 3237c478bd9Sstevel@tonic-gate setup_sortbuf(Os_desc *osp) 3247c478bd9Sstevel@tonic-gate { 3257c478bd9Sstevel@tonic-gate Sort_desc *st = osp->os_sort; 3267c478bd9Sstevel@tonic-gate Word num_after = 0, num_before = 0, num_order = 0; 3277c478bd9Sstevel@tonic-gate Listnode *lnp1; 3287c478bd9Sstevel@tonic-gate Is_desc *isp; 3297c478bd9Sstevel@tonic-gate 3307c478bd9Sstevel@tonic-gate if ((st == NULL) || 3317c478bd9Sstevel@tonic-gate ((st->st_ordercnt + st->st_beforecnt + st->st_aftercnt) == 0)) 3327c478bd9Sstevel@tonic-gate return (0); 3337c478bd9Sstevel@tonic-gate 3347c478bd9Sstevel@tonic-gate /* 3357c478bd9Sstevel@tonic-gate * Get memory 3367c478bd9Sstevel@tonic-gate */ 3377c478bd9Sstevel@tonic-gate if (st->st_beforecnt != 0) { 3387c478bd9Sstevel@tonic-gate if ((st->st_before = 3397c478bd9Sstevel@tonic-gate libld_calloc(st->st_beforecnt, sizeof (Is_desc *))) == 0) 3407c478bd9Sstevel@tonic-gate return (0); 3417c478bd9Sstevel@tonic-gate } 3427c478bd9Sstevel@tonic-gate if (st->st_ordercnt != 0) { 3437c478bd9Sstevel@tonic-gate if ((st->st_order = 3447c478bd9Sstevel@tonic-gate libld_calloc(st->st_ordercnt, sizeof (Is_desc *))) == 0) 3457c478bd9Sstevel@tonic-gate return (0); 3467c478bd9Sstevel@tonic-gate } 3477c478bd9Sstevel@tonic-gate if (st->st_aftercnt != 0) { 3487c478bd9Sstevel@tonic-gate if ((st->st_after = 3497c478bd9Sstevel@tonic-gate libld_calloc(st->st_aftercnt, sizeof (Is_desc *))) == 0) 3507c478bd9Sstevel@tonic-gate return (0); 3517c478bd9Sstevel@tonic-gate } 3527c478bd9Sstevel@tonic-gate 3537c478bd9Sstevel@tonic-gate /* 3547c478bd9Sstevel@tonic-gate * Set info. 3557c478bd9Sstevel@tonic-gate */ 3567c478bd9Sstevel@tonic-gate for (LIST_TRAVERSE(&(osp->os_isdescs), lnp1, isp)) { 3577c478bd9Sstevel@tonic-gate Word keylink = 0; 3587c478bd9Sstevel@tonic-gate 3597c478bd9Sstevel@tonic-gate if ((isp->is_flags & FLG_IS_ORDERED) == 0) 3607c478bd9Sstevel@tonic-gate continue; 3617c478bd9Sstevel@tonic-gate 3627c478bd9Sstevel@tonic-gate if (isp->is_shdr->sh_flags & SHF_ORDERED) 3637c478bd9Sstevel@tonic-gate keylink = isp->is_shdr->sh_info; 3647c478bd9Sstevel@tonic-gate else if (isp->is_shdr->sh_flags & SHF_LINK_ORDER) 3657c478bd9Sstevel@tonic-gate keylink = isp->is_shdr->sh_link; 3667c478bd9Sstevel@tonic-gate 3677c478bd9Sstevel@tonic-gate if (keylink == SHN_BEFORE) 3687c478bd9Sstevel@tonic-gate st->st_before[num_before++] = isp; 3697c478bd9Sstevel@tonic-gate else if (keylink == SHN_AFTER) 3707c478bd9Sstevel@tonic-gate st->st_after[num_after++] = isp; 3717c478bd9Sstevel@tonic-gate else 3727c478bd9Sstevel@tonic-gate st->st_order[num_order++] = isp; 3737c478bd9Sstevel@tonic-gate } 3747c478bd9Sstevel@tonic-gate return (1); 3757c478bd9Sstevel@tonic-gate } 3767c478bd9Sstevel@tonic-gate 3777c478bd9Sstevel@tonic-gate static int 3787c478bd9Sstevel@tonic-gate comp(const void *ss1, const void *ss2) 3797c478bd9Sstevel@tonic-gate { 3807c478bd9Sstevel@tonic-gate Is_desc *s1 = *((Is_desc **)ss1); 3817c478bd9Sstevel@tonic-gate Is_desc *s2 = *((Is_desc **)ss2); 3827c478bd9Sstevel@tonic-gate Is_desc *i1, *i2; 3837c478bd9Sstevel@tonic-gate Word ndx1, ndx2; 3847c478bd9Sstevel@tonic-gate 385*0e233487SRod Evans if (s1->is_shdr->sh_flags & SHF_ORDERED) 3867c478bd9Sstevel@tonic-gate ndx1 = s1->is_shdr->sh_info; 387*0e233487SRod Evans else 3887c478bd9Sstevel@tonic-gate ndx1 = s1->is_shdr->sh_link; 3897c478bd9Sstevel@tonic-gate 390*0e233487SRod Evans if (s2->is_shdr->sh_flags & SHF_ORDERED) 3917c478bd9Sstevel@tonic-gate ndx2 = s2->is_shdr->sh_info; 392*0e233487SRod Evans else 3937c478bd9Sstevel@tonic-gate ndx2 = s2->is_shdr->sh_link; 3947c478bd9Sstevel@tonic-gate 3957c478bd9Sstevel@tonic-gate i1 = s1->is_file->ifl_isdesc[ndx1]; 3967c478bd9Sstevel@tonic-gate i2 = s2->is_file->ifl_isdesc[ndx2]; 3977c478bd9Sstevel@tonic-gate 398*0e233487SRod Evans if (i1->is_keyident > i2->is_keyident) 3997c478bd9Sstevel@tonic-gate return (1); 400*0e233487SRod Evans if (i1->is_keyident < i2->is_keyident) 4017c478bd9Sstevel@tonic-gate return (-1); 4027c478bd9Sstevel@tonic-gate return (0); 4037c478bd9Sstevel@tonic-gate } 4047c478bd9Sstevel@tonic-gate 4057c478bd9Sstevel@tonic-gate uintptr_t 4065aefb655Srie ld_sort_ordered(Ofl_desc *ofl) 4077c478bd9Sstevel@tonic-gate { 4087c478bd9Sstevel@tonic-gate Listnode *lnp1; 4097c478bd9Sstevel@tonic-gate Os_desc *osp; 4107c478bd9Sstevel@tonic-gate 4117c478bd9Sstevel@tonic-gate DBG_CALL(Dbg_sec_order_list(ofl, 0)); 4127c478bd9Sstevel@tonic-gate 4137c478bd9Sstevel@tonic-gate /* 4147c478bd9Sstevel@tonic-gate * Sort Sections 4157c478bd9Sstevel@tonic-gate */ 4167c478bd9Sstevel@tonic-gate for (LIST_TRAVERSE(&ofl->ofl_ordered, lnp1, osp)) { 4177c478bd9Sstevel@tonic-gate int i; 4187c478bd9Sstevel@tonic-gate List islist; 4197c478bd9Sstevel@tonic-gate Listnode * lnp2; 4207c478bd9Sstevel@tonic-gate Is_desc * isp; 4217c478bd9Sstevel@tonic-gate Sort_desc * st = osp->os_sort; 4227c478bd9Sstevel@tonic-gate 4237c478bd9Sstevel@tonic-gate if (setup_sortbuf(osp) == 0) 4247c478bd9Sstevel@tonic-gate return (S_ERROR); 4257c478bd9Sstevel@tonic-gate 4267c478bd9Sstevel@tonic-gate islist = osp->os_isdescs; 4277c478bd9Sstevel@tonic-gate osp->os_isdescs.head = 0; 4287c478bd9Sstevel@tonic-gate osp->os_isdescs.tail = 0; 4297c478bd9Sstevel@tonic-gate 4307c478bd9Sstevel@tonic-gate /* 4317c478bd9Sstevel@tonic-gate * Sorting. 4327c478bd9Sstevel@tonic-gate * First Sort the ordered sections. 4337c478bd9Sstevel@tonic-gate */ 4347c478bd9Sstevel@tonic-gate if (st->st_ordercnt != 0) 4357c478bd9Sstevel@tonic-gate qsort((char *)st->st_order, st->st_ordercnt, 4367c478bd9Sstevel@tonic-gate sizeof (Is_desc *), comp); 4377c478bd9Sstevel@tonic-gate 4387c478bd9Sstevel@tonic-gate /* 4397c478bd9Sstevel@tonic-gate * Place SHN_BEFORE at head of list 4407c478bd9Sstevel@tonic-gate */ 4417c478bd9Sstevel@tonic-gate for (i = 0; i < st->st_beforecnt; i++) { 442cce0e03bSab196087 if (ld_append_isp(ofl, osp, st->st_before[i], 0) == 0) 4437c478bd9Sstevel@tonic-gate return (S_ERROR); 4447c478bd9Sstevel@tonic-gate } 4457c478bd9Sstevel@tonic-gate 4467c478bd9Sstevel@tonic-gate /* 4477c478bd9Sstevel@tonic-gate * Next come 'linked' ordered sections 4487c478bd9Sstevel@tonic-gate */ 4497c478bd9Sstevel@tonic-gate for (i = 0; i < st->st_ordercnt; i++) { 450cce0e03bSab196087 if (ld_append_isp(ofl, osp, st->st_order[i], 0) == 0) 4517c478bd9Sstevel@tonic-gate return (S_ERROR); 4527c478bd9Sstevel@tonic-gate } 4537c478bd9Sstevel@tonic-gate 4547c478bd9Sstevel@tonic-gate /* 4557c478bd9Sstevel@tonic-gate * Now we list any sections which have no sorting 4567c478bd9Sstevel@tonic-gate * specifications - in the order they were input. 457cce0e03bSab196087 * 458cce0e03bSab196087 * We use list_appendc() here instead of ld_append_isp(), 459cce0e03bSab196087 * because these items have already been inserted once, and 460cce0e03bSab196087 * we don't want any duplicate entries in osp->os_mstridescs. 4617c478bd9Sstevel@tonic-gate */ 4627c478bd9Sstevel@tonic-gate for (LIST_TRAVERSE(&islist, lnp2, isp)) { 4637c478bd9Sstevel@tonic-gate if (isp->is_flags & FLG_IS_ORDERED) 4647c478bd9Sstevel@tonic-gate continue; 4657c478bd9Sstevel@tonic-gate if (list_appendc(&(osp->os_isdescs), 4667c478bd9Sstevel@tonic-gate isp) == 0) 4677c478bd9Sstevel@tonic-gate return (S_ERROR); 4687c478bd9Sstevel@tonic-gate } 4697c478bd9Sstevel@tonic-gate 4707c478bd9Sstevel@tonic-gate /* 4717c478bd9Sstevel@tonic-gate * And the end of the list are the SHN_AFTER sections. 4727c478bd9Sstevel@tonic-gate */ 4737c478bd9Sstevel@tonic-gate for (i = 0; i < st->st_aftercnt; i++) { 474cce0e03bSab196087 if (ld_append_isp(ofl, osp, st->st_after[i], 0) == 0) 4757c478bd9Sstevel@tonic-gate return (S_ERROR); 4767c478bd9Sstevel@tonic-gate } 4777c478bd9Sstevel@tonic-gate } 4787c478bd9Sstevel@tonic-gate DBG_CALL(Dbg_sec_order_list(ofl, 1)); 4797c478bd9Sstevel@tonic-gate return (0); 4807c478bd9Sstevel@tonic-gate } 481