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
is_keyshndx_ok(Ifl_desc * ifl,Word keyshndx)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
validate_shf_ordered_dest(Ofl_desc * ofl,Ifl_desc * ifl,Word ndx,const char ** alt_os_name)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
place_unordered(Ofl_desc * ofl,Is_desc * isp,Place_path_info * path_info)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
ld_process_ordered(Ofl_desc * ofl,Ifl_desc * ifl,Place_path_info * path_info,Word ndx)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
ld_sec_validate(Ofl_desc * ofl)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
comp(const void * ss1,const void * ss2)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
ld_sort_ordered(Ofl_desc * ofl)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