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 /* 23*1007fd6fSAli Bahrami * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate /* 277c478bd9Sstevel@tonic-gate * Processing of SHF_ORDERED sections. 287c478bd9Sstevel@tonic-gate */ 297c478bd9Sstevel@tonic-gate #include <stdio.h> 307c478bd9Sstevel@tonic-gate #include <fcntl.h> 317c478bd9Sstevel@tonic-gate #include <link.h> 325aefb655Srie #include <debug.h> 337c478bd9Sstevel@tonic-gate #include "msg.h" 347c478bd9Sstevel@tonic-gate #include "_libld.h" 357c478bd9Sstevel@tonic-gate 367c478bd9Sstevel@tonic-gate /* 371dd9d86fSAli Bahrami * Section Ordering History/Background: 381dd9d86fSAli Bahrami * 391dd9d86fSAli Bahrami * There are two forms of section ordering, SHF_ORDERED, and SHF_LINK_ORDER. 401dd9d86fSAli Bahrami * 411dd9d86fSAli Bahrami * SHF_ORDERED was invented at Sun in order to support the PowerPC port 421dd9d86fSAli Bahrami * of Solaris 2.6, which used it for sorting tag words which describe 431dd9d86fSAli Bahrami * the state of callee saves registers for given PC ranges. It was defined 441dd9d86fSAli Bahrami * in the OS specific ELF section flag range. Some other values were defined 451dd9d86fSAli Bahrami * at the same time: 461dd9d86fSAli Bahrami * SHF_EXCLUDE - Section is to be excluded from executables or shared 471dd9d86fSAli Bahrami * objects, and only kept in relocatable object output. 481dd9d86fSAli Bahrami * SHN_BEFORE/SHN_AFTER - Sections are placed before/after all other 491dd9d86fSAli Bahrami * sections, in the order they are encountered by the linker. 501dd9d86fSAli Bahrami * Although initially conceived to support the PowerPC, the functionality 511dd9d86fSAli Bahrami * was implemented for all platforms, and was later used to manage C++ 521dd9d86fSAli Bahrami * exceptions and stack unwinding. The PowerPC port was discontinued after 531dd9d86fSAli Bahrami * one release, but SHF_ORDERED lives on. 541dd9d86fSAli Bahrami * 551dd9d86fSAli Bahrami * SHF_LINK_ORDER was invented later by the wider ELF community, and is 561dd9d86fSAli Bahrami * therefore assigned a value in the generic ELF section flag range. It is 571dd9d86fSAli Bahrami * essentially a simpler version of SHF_ORDERED, dispensing with some 581dd9d86fSAli Bahrami * unnecessary features. The Solaris implementation of SHF_LINK_ORDER uses 591dd9d86fSAli Bahrami * SHF_EXCLUDE, and SHF_BEFORE/SHN_AFTER as well, but it appears that these 601dd9d86fSAli Bahrami * are still Solaris-only extensions not used by other implementations. 611dd9d86fSAli Bahrami * SHF_LINK_ORDER has superseded SHF_ORDERED. The older mechanism is 621dd9d86fSAli Bahrami * supported for the benefit of old pre-existing objects. 631dd9d86fSAli Bahrami * 641dd9d86fSAli Bahrami * ----- 651dd9d86fSAli Bahrami * 661dd9d86fSAli Bahrami * SHF_ORDERED offers two distinct and separate abilities: 671dd9d86fSAli Bahrami * 681dd9d86fSAli Bahrami * (1) To specify the output section 691dd9d86fSAli Bahrami * (2) To optionally be sorted relative to other sorted sections, 701dd9d86fSAli Bahrami * using a non-sorted section as a sort key. 711dd9d86fSAli Bahrami * 721dd9d86fSAli Bahrami * To do this, it uses both the sh_link, and sh_info fields: 731dd9d86fSAli Bahrami * 741dd9d86fSAli Bahrami * sh_link 751dd9d86fSAli Bahrami * Specifies the output section to receive this input section. 761dd9d86fSAli Bahrami * The sh_link field of an SHF_ORDERED section forms a linked list of 771dd9d86fSAli Bahrami * sections, all of which must have identical section header flags 781dd9d86fSAli Bahrami * (including SHF_ORDERED). The list is terminated by a final section 791dd9d86fSAli Bahrami * with a sh_link that points at itself. All input sections in this list 801dd9d86fSAli Bahrami * are assigned to the output section of the final section in the list. 811dd9d86fSAli Bahrami * Hence, if a section points at itself, the effect is that it gets 821dd9d86fSAli Bahrami * assigned to an output section in the usual default manner (i.e. an 831dd9d86fSAli Bahrami * output section with the same name as the input). However, it can 841dd9d86fSAli Bahrami * point at any arbitrary other section. This is a way to put a section 851dd9d86fSAli Bahrami * with one name into an output section with a different name. It should 861dd9d86fSAli Bahrami * be noted that this is of little value overall, because the link-editor 871dd9d86fSAli Bahrami * already supports a more general feature for directing input sections 881dd9d86fSAli Bahrami * to output sections: An input section named .text%foo will be sent to 891dd9d86fSAli Bahrami * an output section named ".text", and this works for all sections, 901dd9d86fSAli Bahrami * not just ordered ones. 911dd9d86fSAli Bahrami * 921dd9d86fSAli Bahrami * sh_info 931dd9d86fSAli Bahrami * If sh_info is in the range (1 <= value < shnum), then this input section 941dd9d86fSAli Bahrami * is added to the group of sorted sections. The section referenced by 951dd9d86fSAli Bahrami * sh_info must be unsorted, and is used as the sort key. 961dd9d86fSAli Bahrami * 971dd9d86fSAli Bahrami * If sh_info is SHN_BEFORE or SHN_AFTER, it is put in the pre/post group, 981dd9d86fSAli Bahrami * in the order it arrives (the before/after classes are not sorted). 991dd9d86fSAli Bahrami * 1001dd9d86fSAli Bahrami * If sh_info is "invalid" (typically 0), then this section is added to 1011dd9d86fSAli Bahrami * the group of non-sorted sections, and goes into the output file in the 1021dd9d86fSAli Bahrami * order it arrives. This is not a valuable feature, as the same effect 1031dd9d86fSAli Bahrami * can be achieved more simply by not setting SHF_ORDERED at all. 1041dd9d86fSAli Bahrami * 1051dd9d86fSAli Bahrami * SHF_LINK_ORDER is a simplification of SHF_ORDERED. It uses sh_link to specify 1061dd9d86fSAli Bahrami * the section to use as a sort key and sh_info is set to 0. The standard 1071dd9d86fSAli Bahrami * ".text%foo" mechanism is used to direct input sections to output sections, 1081dd9d86fSAli Bahrami * and unordered sections indicate that by not setting SHF_LINK_ORDER. 1097c478bd9Sstevel@tonic-gate */ 1101dd9d86fSAli Bahrami 1111dd9d86fSAli Bahrami 1127c478bd9Sstevel@tonic-gate /* 1131dd9d86fSAli Bahrami * A "keyshndx" is the section index for the unordered section that should 1141dd9d86fSAli Bahrami * be used as a sort key for a ordered section. Verify that the given 1151dd9d86fSAli Bahrami * keyshndx is valid. 1161dd9d86fSAli Bahrami * 1171dd9d86fSAli Bahrami * exit: 1181dd9d86fSAli Bahrami * Returns 0 if the keyshndx is valid. A non-zero DBG_ORDER_ code is 1191dd9d86fSAli Bahrami * returned if the keyshndx is not valid to describe the problem. 1207c478bd9Sstevel@tonic-gate */ 121e23c41c9SAli Bahrami inline static Word 1221dd9d86fSAli Bahrami is_keyshndx_ok(Ifl_desc *ifl, Word keyshndx) 1237c478bd9Sstevel@tonic-gate { 1241dd9d86fSAli Bahrami if ((keyshndx == SHN_BEFORE) || (keyshndx == SHN_AFTER)) 125e23c41c9SAli Bahrami return (0); 1267c478bd9Sstevel@tonic-gate 1277c478bd9Sstevel@tonic-gate /* 128e23c41c9SAli Bahrami * Validate the key range. 1297c478bd9Sstevel@tonic-gate */ 1301dd9d86fSAli Bahrami if ((keyshndx == 0) || (keyshndx >= ifl->ifl_shnum)) 131e23c41c9SAli Bahrami return (DBG_ORDER_LINK_OUTRANGE); 132e23c41c9SAli Bahrami 133e23c41c9SAli Bahrami /* 1341dd9d86fSAli Bahrami * The section pointed to by keyshndx should not be an ordered section. 1351dd9d86fSAli Bahrami * Strictly speaking, we could test for SHF_ORDERED here instead of 1361dd9d86fSAli Bahrami * ALL_SHF_ORDER as the two ordering flags are not supposed to be 1371dd9d86fSAli Bahrami * mixed. Using ALL_SHF_ORDER costs the same and ensures that such 1381dd9d86fSAli Bahrami * mixing doesn't go undetected. 139e23c41c9SAli Bahrami */ 1401dd9d86fSAli Bahrami if (ifl->ifl_isdesc[keyshndx]->is_shdr->sh_flags & ALL_SHF_ORDER) 1417c478bd9Sstevel@tonic-gate return (DBG_ORDER_INFO_ORDER); 142e23c41c9SAli Bahrami 1437c478bd9Sstevel@tonic-gate return (0); 1447c478bd9Sstevel@tonic-gate } 1457c478bd9Sstevel@tonic-gate 146e23c41c9SAli Bahrami /* 1471dd9d86fSAli Bahrami * The sh_link field of an SHF_ORDERED section forms a linked list of 1481dd9d86fSAli Bahrami * sections. The list is terminated by a final section with a sh_link 1491dd9d86fSAli Bahrami * that points at itself. Given the index of an SHF_ORDERED section, find 1501dd9d86fSAli Bahrami * the index of the final section in the list. 1511dd9d86fSAli Bahrami * 1521dd9d86fSAli Bahrami * entry: 1531dd9d86fSAli Bahrami * ofl - Output file descriptor 1541dd9d86fSAli Bahrami * ifl - Input file descriptor 1551dd9d86fSAli Bahrami * ndx - Section index of SHF_ORDERED section 1561dd9d86fSAli Bahrami * alt_os_name - Address of pointer to string. If the final section 1571dd9d86fSAli Bahrami * name is different than the section given by ndx, *alt_os_name 1581dd9d86fSAli Bahrami * will be updated with the name of the final section. The caller 1591dd9d86fSAli Bahrami * should initialize *alt_os_name to NULL before calling 1601dd9d86fSAli Bahrami * this routine. 1611dd9d86fSAli Bahrami * 1621dd9d86fSAli Bahrami * exit: 1631dd9d86fSAli Bahrami * On success: If the final section is different than the section 1641dd9d86fSAli Bahrami * given by ndx, then *alt_os_name is set to its name. TRUE is returned. 1651dd9d86fSAli Bahrami * 1661dd9d86fSAli Bahrami * On failure, FALSE is returned. 167e23c41c9SAli Bahrami */ 1681dd9d86fSAli Bahrami static Boolean 1691dd9d86fSAli Bahrami validate_shf_ordered_dest(Ofl_desc *ofl, Ifl_desc *ifl, Word ndx, 1701dd9d86fSAli Bahrami const char **alt_os_name) 1717c478bd9Sstevel@tonic-gate { 1721dd9d86fSAli Bahrami Word shnum = ifl->ifl_shnum; 1731dd9d86fSAli Bahrami Word isp1_ndx, isp2_ndx; 1741dd9d86fSAli Bahrami Is_desc *isp1, *isp2; 1757c478bd9Sstevel@tonic-gate int error = 0; 1761dd9d86fSAli Bahrami size_t iter = 0; 1777c478bd9Sstevel@tonic-gate 1787c478bd9Sstevel@tonic-gate /* 1791dd9d86fSAli Bahrami * Traverse the list until we find the termination, or encounter 1801dd9d86fSAli Bahrami * an invalid condition in the object that prevents ordering. 1817c478bd9Sstevel@tonic-gate */ 1821dd9d86fSAli Bahrami isp1_ndx = ndx; 1831dd9d86fSAli Bahrami isp1 = ifl->ifl_isdesc[ndx]; 1847c478bd9Sstevel@tonic-gate do { 1857c478bd9Sstevel@tonic-gate /* 1861dd9d86fSAli Bahrami * Obtain index of next section in list. Ensure it is in range. 1877c478bd9Sstevel@tonic-gate */ 1881dd9d86fSAli Bahrami isp2_ndx = isp1->is_shdr->sh_link; 1891dd9d86fSAli Bahrami if ((isp2_ndx == 0) || (isp2_ndx >= shnum)) { 1907c478bd9Sstevel@tonic-gate error = DBG_ORDER_LINK_OUTRANGE; 1917c478bd9Sstevel@tonic-gate break; 1927c478bd9Sstevel@tonic-gate } 1931dd9d86fSAli Bahrami isp2 = ifl->ifl_isdesc[isp2_ndx]; 1947c478bd9Sstevel@tonic-gate 1951dd9d86fSAli Bahrami /* The section flags must match exactly */ 1967c478bd9Sstevel@tonic-gate if (isp1->is_shdr->sh_flags != isp2->is_shdr->sh_flags) { 1971dd9d86fSAli Bahrami /* 1981dd9d86fSAli Bahrami * The case where the next section in the list does 1991dd9d86fSAli Bahrami * not have the same ordered flag set as the original 2001dd9d86fSAli Bahrami * ordered section gets a unique error code. This 2011dd9d86fSAli Bahrami * provides more accurate/useful debugging diagnostics. 2021dd9d86fSAli Bahrami */ 2031dd9d86fSAli Bahrami error = ((isp2->is_flags & FLG_IS_ORDERED) == 0) ? 2041dd9d86fSAli Bahrami DBG_ORDER_LINK_ERROR : DBG_ORDER_FLAGS; 2057c478bd9Sstevel@tonic-gate break; 2067c478bd9Sstevel@tonic-gate } 2077c478bd9Sstevel@tonic-gate 2087c478bd9Sstevel@tonic-gate /* 2091dd9d86fSAli Bahrami * The sh_info field specifies the section index of an 2101dd9d86fSAli Bahrami * unorderd section which will be used as a sort key. 2111dd9d86fSAli Bahrami * Ensure it is in range. If not, we terminate the list 2121dd9d86fSAli Bahrami * at the current node instead of continuing on. 2137c478bd9Sstevel@tonic-gate */ 2141dd9d86fSAli Bahrami if ((error = is_keyshndx_ok(ifl, isp2->is_shdr->sh_info)) != 0) 2157c478bd9Sstevel@tonic-gate break; 2167c478bd9Sstevel@tonic-gate 2171dd9d86fSAli Bahrami /* If the section points at itself, it terminates the list */ 2181dd9d86fSAli Bahrami if (isp1_ndx == isp2_ndx) 2197c478bd9Sstevel@tonic-gate break; 2207c478bd9Sstevel@tonic-gate 2217c478bd9Sstevel@tonic-gate /* 2221dd9d86fSAli Bahrami * Advance to next section in list 2237c478bd9Sstevel@tonic-gate */ 2241dd9d86fSAli Bahrami isp1_ndx = isp2_ndx; 2251dd9d86fSAli Bahrami isp1 = isp2; 2267c478bd9Sstevel@tonic-gate 2277c478bd9Sstevel@tonic-gate /* 2281dd9d86fSAli Bahrami * If we loop more times than the input file has sections, 2291dd9d86fSAli Bahrami * we have encountered a malformed object in which the list 2301dd9d86fSAli Bahrami * of SHF_ORDERED sections has a cycle. This can only happen 2311dd9d86fSAli Bahrami * if the compiler generating the object has a bad bug. 2327c478bd9Sstevel@tonic-gate */ 2331dd9d86fSAli Bahrami if (++iter >= shnum) { 2347c478bd9Sstevel@tonic-gate error = DBG_ORDER_CYCLIC; 2357c478bd9Sstevel@tonic-gate break; 2367c478bd9Sstevel@tonic-gate } 2377c478bd9Sstevel@tonic-gate /* CONSTANTCONDITION */ 2387c478bd9Sstevel@tonic-gate } while (1); 2397c478bd9Sstevel@tonic-gate 2401dd9d86fSAli Bahrami /* 2411dd9d86fSAli Bahrami * If we have found a problem, issue a debug diagnostic and map 2421dd9d86fSAli Bahrami * the output section to 0. This indicates that the section should 2431dd9d86fSAli Bahrami * remove the ordering flag and treat it as a standard section. 2441dd9d86fSAli Bahrami */ 2457c478bd9Sstevel@tonic-gate if (error != 0) { 2461dd9d86fSAli Bahrami isp2_ndx = 0; 2475aefb655Srie DBG_CALL(Dbg_sec_order_error(ofl->ofl_lml, ifl, ndx, error)); 2487c478bd9Sstevel@tonic-gate } 2491dd9d86fSAli Bahrami 2501dd9d86fSAli Bahrami /* Report success */ 2511dd9d86fSAli Bahrami if (isp2_ndx != 0) { 2521dd9d86fSAli Bahrami /* 2531dd9d86fSAli Bahrami * If the destination section is different than the input 2541dd9d86fSAli Bahrami * section, then set *alt_os_name to the destination name. 2551dd9d86fSAli Bahrami */ 2561dd9d86fSAli Bahrami if (isp2_ndx != ndx) 2571dd9d86fSAli Bahrami *alt_os_name = ifl->ifl_isdesc[isp2_ndx]->is_name; 2581dd9d86fSAli Bahrami return (TRUE); 2591dd9d86fSAli Bahrami } 2601dd9d86fSAli Bahrami 2611dd9d86fSAli Bahrami /* If we get here, there is no valid destination */ 2621dd9d86fSAli Bahrami return (FALSE); 2637c478bd9Sstevel@tonic-gate } 2647c478bd9Sstevel@tonic-gate 2657c478bd9Sstevel@tonic-gate /* 2661dd9d86fSAli Bahrami * Called when an ordered section has a problem that prevents ordering. 2671dd9d86fSAli Bahrami * The order flag is removed, and then the section is placed as an 2681dd9d86fSAli Bahrami * unsorted section. 2691dd9d86fSAli Bahrami */ 2701dd9d86fSAli Bahrami static uintptr_t 27169112eddSAli Bahrami place_unordered(Ofl_desc *ofl, Is_desc *isp, Place_path_info *path_info) 2721dd9d86fSAli Bahrami { 2731dd9d86fSAli Bahrami isp->is_flags &= ~FLG_IS_ORDERED; 2741dd9d86fSAli Bahrami if (isp->is_osdesc == NULL) 27569112eddSAli Bahrami return ((uintptr_t)ld_place_section(ofl, isp, path_info, 2761dd9d86fSAli Bahrami isp->is_keyident, NULL)); 2771dd9d86fSAli Bahrami return ((uintptr_t)isp->is_osdesc); 2781dd9d86fSAli Bahrami } 2791dd9d86fSAli Bahrami 2801dd9d86fSAli Bahrami /* 2811dd9d86fSAli Bahrami * Process ordered input section. Called from process_elf() after 2821dd9d86fSAli Bahrami * all the non-ordered sections have been placed. 2831dd9d86fSAli Bahrami * 2841dd9d86fSAli Bahrami * entry: 2851dd9d86fSAli Bahrami * ofl - Output file descriptor 2861dd9d86fSAli Bahrami * ifl - Input file descriptor 2871dd9d86fSAli Bahrami * ndx - Section index of SHF_ORDERED section 2881dd9d86fSAli Bahrami * 2891dd9d86fSAli Bahrami * exit: 2907c478bd9Sstevel@tonic-gate */ 2917c478bd9Sstevel@tonic-gate uintptr_t 29269112eddSAli Bahrami ld_process_ordered(Ofl_desc *ofl, Ifl_desc *ifl, Place_path_info *path_info, 29369112eddSAli Bahrami Word ndx) 2947c478bd9Sstevel@tonic-gate { 2957c478bd9Sstevel@tonic-gate Is_desc *isp2, *isp = ifl->ifl_isdesc[ndx]; 2967c478bd9Sstevel@tonic-gate Xword shflags = isp->is_shdr->sh_flags; 2971dd9d86fSAli Bahrami const char *alt_os_name = NULL; 2981dd9d86fSAli Bahrami Word keyshndx; 2991dd9d86fSAli Bahrami Os_desc *osp; 3007c478bd9Sstevel@tonic-gate int error = 0; 3017c478bd9Sstevel@tonic-gate 3027c478bd9Sstevel@tonic-gate /* 3031dd9d86fSAli Bahrami * Obtain the sort key section index for this ordered section. 3041dd9d86fSAli Bahrami * SHF_ORDERED uses sh_info, while SHF_LINK_ORDER uses sh_link. 3051dd9d86fSAli Bahrami * In order for this function to be called, one of SHF_ORDERED 3061dd9d86fSAli Bahrami * or SHF_LINK_ORDER must be set. Testing for one implies the 3071dd9d86fSAli Bahrami * state of the other. 3087c478bd9Sstevel@tonic-gate */ 3091dd9d86fSAli Bahrami keyshndx = (shflags & SHF_ORDERED) ? 3101dd9d86fSAli Bahrami isp->is_shdr->sh_info : isp->is_shdr->sh_link; 3117c478bd9Sstevel@tonic-gate 3121dd9d86fSAli Bahrami /* 3131dd9d86fSAli Bahrami * Validate the sort key section index. If something is wrong, 3141dd9d86fSAli Bahrami * fall back to treating it as a non-ordered section. 3151dd9d86fSAli Bahrami */ 3161dd9d86fSAli Bahrami if ((error = is_keyshndx_ok(ifl, keyshndx)) != 0) { 3175aefb655Srie DBG_CALL(Dbg_sec_order_error(ofl->ofl_lml, ifl, ndx, error)); 31869112eddSAli Bahrami return (place_unordered(ofl, isp, path_info)); 3197c478bd9Sstevel@tonic-gate } 3207c478bd9Sstevel@tonic-gate 3217c478bd9Sstevel@tonic-gate /* 3221dd9d86fSAli Bahrami * If SHF_ORDERED is in effect, validate the destination section 3231dd9d86fSAli Bahrami * name given by sh_link, and set alt_os_name to the name of the 3241dd9d86fSAli Bahrami * destination if it differs from the section being processed. 3257c478bd9Sstevel@tonic-gate */ 3261dd9d86fSAli Bahrami if ((shflags & SHF_ORDERED) && 3271dd9d86fSAli Bahrami (validate_shf_ordered_dest(ofl, ifl, ndx, &alt_os_name) == FALSE)) 32869112eddSAli Bahrami return (place_unordered(ofl, isp, path_info)); 3297c478bd9Sstevel@tonic-gate 3307c478bd9Sstevel@tonic-gate /* 331e23c41c9SAli Bahrami * Place the section into its output section. It's possible that this 332e23c41c9SAli Bahrami * section is discarded (possibly because it's defined COMDAT), in 333e23c41c9SAli Bahrami * which case we're done. 3347c478bd9Sstevel@tonic-gate */ 3357c478bd9Sstevel@tonic-gate if ((osp = isp->is_osdesc) == NULL) { 33669112eddSAli Bahrami osp = ld_place_section(ofl, isp, path_info, isp->is_keyident, 33769112eddSAli Bahrami alt_os_name); 3381dd9d86fSAli Bahrami if ((osp == (Os_desc *)S_ERROR) || (osp == NULL)) 3391dd9d86fSAli Bahrami return ((uintptr_t)osp); 3407c478bd9Sstevel@tonic-gate } 3417c478bd9Sstevel@tonic-gate 3427c478bd9Sstevel@tonic-gate /* 34357ef7aa9SRod Evans * If the output section is not yet on the ordered list, place it on 34457ef7aa9SRod Evans * the list. 3457c478bd9Sstevel@tonic-gate */ 3461dd9d86fSAli Bahrami if (aplist_test(&ofl->ofl_ordered, osp, AL_CNT_OFL_ORDERED) == 3471dd9d86fSAli Bahrami ALE_ALLOCFAIL) 3487c478bd9Sstevel@tonic-gate return ((uintptr_t)S_ERROR); 3497c478bd9Sstevel@tonic-gate 3507c478bd9Sstevel@tonic-gate /* 3511dd9d86fSAli Bahrami * Output section has been found - set up its sorting information. 3527c478bd9Sstevel@tonic-gate */ 3531dd9d86fSAli Bahrami if ((keyshndx != SHN_BEFORE) && (keyshndx != SHN_AFTER)) { 3541dd9d86fSAli Bahrami Os_desc *osp2; 35557ef7aa9SRod Evans 3561dd9d86fSAli Bahrami isp2 = ifl->ifl_isdesc[keyshndx]; 3577c478bd9Sstevel@tonic-gate if (isp2->is_flags & FLG_IS_DISCARD) { 358*1007fd6fSAli Bahrami ld_eprintf(ofl, ERR_FATAL, MSG_INTL(MSG_FIL_BADORDREF), 359*1007fd6fSAli Bahrami ifl->ifl_name, EC_WORD(isp->is_scnndx), 360*1007fd6fSAli Bahrami isp->is_name, EC_WORD(isp2->is_scnndx), 361*1007fd6fSAli Bahrami isp2->is_name); 3627c478bd9Sstevel@tonic-gate return (S_ERROR); 3637c478bd9Sstevel@tonic-gate } 3640e233487SRod Evans 3650e233487SRod Evans /* 3661dd9d86fSAli Bahrami * Indicate that this ordered input section will require a 3671dd9d86fSAli Bahrami * sort key. Propagate the key requirement through to the 3681dd9d86fSAli Bahrami * associated output section, segment and file, to trigger 3691dd9d86fSAli Bahrami * the sort key creation. See ld_sec_validate(); 3700e233487SRod Evans */ 3717c478bd9Sstevel@tonic-gate isp2->is_flags |= FLG_IS_KEY; 3720e233487SRod Evans 3730e233487SRod Evans osp2 = isp2->is_osdesc; 3740e233487SRod Evans osp2->os_flags |= FLG_OS_KEY; 3750e233487SRod Evans osp2->os_sgdesc->sg_flags |= FLG_SG_KEY; 3760e233487SRod Evans 3770e233487SRod Evans ofl->ofl_flags |= FLG_OF_KEY; 3787c478bd9Sstevel@tonic-gate } 3797c478bd9Sstevel@tonic-gate 3807c478bd9Sstevel@tonic-gate return ((uintptr_t)osp); 3817c478bd9Sstevel@tonic-gate } 3827c478bd9Sstevel@tonic-gate 3837c478bd9Sstevel@tonic-gate /* 3847c478bd9Sstevel@tonic-gate * Traverse all segments looking for section ordering information that hasn't 3857c478bd9Sstevel@tonic-gate * been used. If found give a warning message to the user. Also, check if 3861dd9d86fSAli Bahrami * there are any ordered key sections, and if so set up sort key values. 3877c478bd9Sstevel@tonic-gate */ 3887c478bd9Sstevel@tonic-gate void 3895aefb655Srie ld_sec_validate(Ofl_desc *ofl) 3907c478bd9Sstevel@tonic-gate { 39157ef7aa9SRod Evans Aliste idx1; 3927c478bd9Sstevel@tonic-gate Sg_desc *sgp; 3930e233487SRod Evans Word key = 1; 3947c478bd9Sstevel@tonic-gate 39557ef7aa9SRod Evans for (APLIST_TRAVERSE(ofl->ofl_segs, idx1, sgp)) { 396cce0e03bSab196087 Sec_order *scop; 397cce0e03bSab196087 Os_desc *osp; 39857ef7aa9SRod Evans Aliste idx2; 3997c478bd9Sstevel@tonic-gate 40069112eddSAli Bahrami for (ALIST_TRAVERSE(sgp->sg_os_order, idx2, scop)) { 4010bc07c75Srie if ((scop->sco_flags & FLG_SGO_USED) == 0) { 402*1007fd6fSAli Bahrami ld_eprintf(ofl, ERR_WARNING, 4035aefb655Srie MSG_INTL(MSG_MAP_SECORDER), 4047c478bd9Sstevel@tonic-gate sgp->sg_name, scop->sco_secname); 4050bc07c75Srie } 4060bc07c75Srie } 4077c478bd9Sstevel@tonic-gate if ((sgp->sg_flags & FLG_SG_KEY) == 0) 4087c478bd9Sstevel@tonic-gate continue; 4097c478bd9Sstevel@tonic-gate 41057ef7aa9SRod Evans for (APLIST_TRAVERSE(sgp->sg_osdescs, idx2, osp)) { 41157ef7aa9SRod Evans Aliste idx3; 4127c478bd9Sstevel@tonic-gate Is_desc *isp; 4137c478bd9Sstevel@tonic-gate 4140e233487SRod Evans if ((osp->os_flags & FLG_OS_KEY) == 0) 4157c478bd9Sstevel@tonic-gate continue; 4167c478bd9Sstevel@tonic-gate 4171dd9d86fSAli Bahrami /* 4181dd9d86fSAli Bahrami * The input sections used as sort keys are required 4191dd9d86fSAli Bahrami * to be unordered, so we only have to look at the 4201dd9d86fSAli Bahrami * DEFAULT list of input sections. 4211dd9d86fSAli Bahrami */ 4221dd9d86fSAli Bahrami for (APLIST_TRAVERSE(osp->os_isdescs[OS_ISD_DEFAULT], 4231dd9d86fSAli Bahrami idx3, isp)) { 4240bc07c75Srie if (isp->is_flags & FLG_IS_KEY) 4250e233487SRod Evans isp->is_keyident = key++; 4267c478bd9Sstevel@tonic-gate } 4277c478bd9Sstevel@tonic-gate } 4287c478bd9Sstevel@tonic-gate } 4297c478bd9Sstevel@tonic-gate } 4307c478bd9Sstevel@tonic-gate 4317c478bd9Sstevel@tonic-gate static int 4327c478bd9Sstevel@tonic-gate comp(const void *ss1, const void *ss2) 4337c478bd9Sstevel@tonic-gate { 4347c478bd9Sstevel@tonic-gate Is_desc *s1 = *((Is_desc **)ss1); 4357c478bd9Sstevel@tonic-gate Is_desc *s2 = *((Is_desc **)ss2); 4367c478bd9Sstevel@tonic-gate Is_desc *i1, *i2; 4377c478bd9Sstevel@tonic-gate Word ndx1, ndx2; 4387c478bd9Sstevel@tonic-gate 4390e233487SRod Evans if (s1->is_shdr->sh_flags & SHF_ORDERED) 4407c478bd9Sstevel@tonic-gate ndx1 = s1->is_shdr->sh_info; 4410e233487SRod Evans else 4427c478bd9Sstevel@tonic-gate ndx1 = s1->is_shdr->sh_link; 4437c478bd9Sstevel@tonic-gate 4440e233487SRod Evans if (s2->is_shdr->sh_flags & SHF_ORDERED) 4457c478bd9Sstevel@tonic-gate ndx2 = s2->is_shdr->sh_info; 4460e233487SRod Evans else 4477c478bd9Sstevel@tonic-gate ndx2 = s2->is_shdr->sh_link; 4487c478bd9Sstevel@tonic-gate 4497c478bd9Sstevel@tonic-gate i1 = s1->is_file->ifl_isdesc[ndx1]; 4507c478bd9Sstevel@tonic-gate i2 = s2->is_file->ifl_isdesc[ndx2]; 4517c478bd9Sstevel@tonic-gate 4520e233487SRod Evans if (i1->is_keyident > i2->is_keyident) 4537c478bd9Sstevel@tonic-gate return (1); 4540e233487SRod Evans if (i1->is_keyident < i2->is_keyident) 4557c478bd9Sstevel@tonic-gate return (-1); 4567c478bd9Sstevel@tonic-gate return (0); 4577c478bd9Sstevel@tonic-gate } 4587c478bd9Sstevel@tonic-gate 4591dd9d86fSAli Bahrami /* 4601dd9d86fSAli Bahrami * Sort ordered input sections 4611dd9d86fSAli Bahrami */ 4627c478bd9Sstevel@tonic-gate uintptr_t 4635aefb655Srie ld_sort_ordered(Ofl_desc *ofl) 4647c478bd9Sstevel@tonic-gate { 46557ef7aa9SRod Evans Aliste idx1; 4667c478bd9Sstevel@tonic-gate Os_desc *osp; 4677c478bd9Sstevel@tonic-gate 4687c478bd9Sstevel@tonic-gate DBG_CALL(Dbg_sec_order_list(ofl, 0)); 4697c478bd9Sstevel@tonic-gate 47057ef7aa9SRod Evans for (APLIST_TRAVERSE(ofl->ofl_ordered, idx1, osp)) { 4711dd9d86fSAli Bahrami APlist *ap_list = osp->os_isdescs[OS_ISD_ORDERED]; 4721dd9d86fSAli Bahrami Aliste apl_nitems = aplist_nitems(ap_list); 4737c478bd9Sstevel@tonic-gate 4747c478bd9Sstevel@tonic-gate /* 4751dd9d86fSAli Bahrami * If this output section has a non-empty list of ordered 4761dd9d86fSAli Bahrami * input sections, sort their APlist in place into their 4771dd9d86fSAli Bahrami * final order. 4787c478bd9Sstevel@tonic-gate */ 4791dd9d86fSAli Bahrami if (apl_nitems != 0) 4801dd9d86fSAli Bahrami qsort((char *)ap_list->apl_data, apl_nitems, 4817c478bd9Sstevel@tonic-gate sizeof (Is_desc *), comp); 4827c478bd9Sstevel@tonic-gate } 4837c478bd9Sstevel@tonic-gate DBG_CALL(Dbg_sec_order_list(ofl, 1)); 4847c478bd9Sstevel@tonic-gate return (0); 4857c478bd9Sstevel@tonic-gate } 486