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 */
21fb1354edSrie
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate * Copyright (c) 1988 AT&T
247c478bd9Sstevel@tonic-gate * All Rights Reserved
257c478bd9Sstevel@tonic-gate *
26bf994817SAli Bahrami * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
277c478bd9Sstevel@tonic-gate */
287c478bd9Sstevel@tonic-gate
297c478bd9Sstevel@tonic-gate /*
307c478bd9Sstevel@tonic-gate * Module sections. Initialize special sections
317c478bd9Sstevel@tonic-gate */
32ba2be530Sab196087
33ba2be530Sab196087 #define ELF_TARGET_AMD64
34ba2be530Sab196087
357c478bd9Sstevel@tonic-gate #include <string.h>
367c478bd9Sstevel@tonic-gate #include <strings.h>
377c478bd9Sstevel@tonic-gate #include <stdio.h>
387c478bd9Sstevel@tonic-gate #include <link.h>
395aefb655Srie #include <debug.h>
407c478bd9Sstevel@tonic-gate #include "msg.h"
417c478bd9Sstevel@tonic-gate #include "_libld.h"
427c478bd9Sstevel@tonic-gate
43a194faf8Srie inline static void
remove_local(Ofl_desc * ofl,Sym_desc * sdp,int allow_ldynsym)4460758829Srie remove_local(Ofl_desc *ofl, Sym_desc *sdp, int allow_ldynsym)
4560758829Srie {
4660758829Srie Sym *sym = sdp->sd_sym;
4760758829Srie uchar_t type = ELF_ST_TYPE(sym->st_info);
4860758829Srie /* LINTED - only used for assert() */
4960758829Srie int err;
5060758829Srie
5144bac77bSrie if ((ofl->ofl_flags & FLG_OF_REDLSYM) == 0) {
5260758829Srie ofl->ofl_locscnt--;
53a194faf8Srie
5460758829Srie err = st_delstring(ofl->ofl_strtab, sdp->sd_name);
5560758829Srie assert(err != -1);
5660758829Srie
5760758829Srie if (allow_ldynsym && ldynsym_symtype[type]) {
5860758829Srie ofl->ofl_dynlocscnt--;
59a194faf8Srie
6060758829Srie err = st_delstring(ofl->ofl_dynstrtab, sdp->sd_name);
6160758829Srie assert(err != -1);
6260758829Srie /* Remove from sort section? */
6360758829Srie DYNSORT_COUNT(sdp, sym, type, --);
6460758829Srie }
6560758829Srie }
6660758829Srie sdp->sd_flags |= FLG_SY_ISDISC;
6760758829Srie }
6860758829Srie
69a194faf8Srie inline static void
remove_scoped(Ofl_desc * ofl,Sym_desc * sdp,int allow_ldynsym)7060758829Srie remove_scoped(Ofl_desc *ofl, Sym_desc *sdp, int allow_ldynsym)
7160758829Srie {
7260758829Srie Sym *sym = sdp->sd_sym;
7360758829Srie uchar_t type = ELF_ST_TYPE(sym->st_info);
7460758829Srie /* LINTED - only used for assert() */
7560758829Srie int err;
7660758829Srie
7760758829Srie ofl->ofl_scopecnt--;
7860758829Srie ofl->ofl_elimcnt++;
7960758829Srie
8060758829Srie err = st_delstring(ofl->ofl_strtab, sdp->sd_name);
8160758829Srie assert(err != -1);
8260758829Srie
8360758829Srie if (allow_ldynsym && ldynsym_symtype[type]) {
8460758829Srie ofl->ofl_dynscopecnt--;
85a194faf8Srie
8660758829Srie err = st_delstring(ofl->ofl_dynstrtab, sdp->sd_name);
8760758829Srie assert(err != -1);
8860758829Srie /* Remove from sort section? */
8960758829Srie DYNSORT_COUNT(sdp, sym, type, --);
9060758829Srie }
91635216b6SRod Evans sdp->sd_flags |= FLG_SY_ELIM;
9260758829Srie }
9360758829Srie
94a194faf8Srie inline static void
ignore_sym(Ofl_desc * ofl,Ifl_desc * ifl,Sym_desc * sdp,int allow_ldynsym)95a194faf8Srie ignore_sym(Ofl_desc *ofl, Ifl_desc *ifl, Sym_desc *sdp, int allow_ldynsym)
96a194faf8Srie {
97a194faf8Srie Os_desc *osp;
98a194faf8Srie Is_desc *isp = sdp->sd_isc;
99a194faf8Srie uchar_t bind = ELF_ST_BIND(sdp->sd_sym->st_info);
100a194faf8Srie
101a194faf8Srie if (bind == STB_LOCAL) {
102a194faf8Srie uchar_t type = ELF_ST_TYPE(sdp->sd_sym->st_info);
1037c478bd9Sstevel@tonic-gate
1047c478bd9Sstevel@tonic-gate /*
105a194faf8Srie * Skip section symbols, these were never collected in the
106a194faf8Srie * first place.
107a194faf8Srie */
108a194faf8Srie if (type == STT_SECTION)
109a194faf8Srie return;
110a194faf8Srie
111a194faf8Srie /*
112a194faf8Srie * Determine if the whole file is being removed. Remove any
113a194faf8Srie * file symbol, and any symbol that is not associated with a
114a194faf8Srie * section, provided the symbol has not been identified as
115a194faf8Srie * (update) required.
116a194faf8Srie */
117a194faf8Srie if (((ifl->ifl_flags & FLG_IF_FILEREF) == 0) &&
118a194faf8Srie ((type == STT_FILE) || ((isp == NULL) &&
119a194faf8Srie ((sdp->sd_flags & FLG_SY_UPREQD) == 0)))) {
120a194faf8Srie DBG_CALL(Dbg_syms_discarded(ofl->ofl_lml, sdp));
121a194faf8Srie if (ifl->ifl_flags & FLG_IF_IGNORE)
122a194faf8Srie remove_local(ofl, sdp, allow_ldynsym);
123a194faf8Srie return;
124a194faf8Srie }
125a194faf8Srie
126a194faf8Srie } else {
127a194faf8Srie /*
128a194faf8Srie * Global symbols can only be eliminated when the interfaces of
129a194faf8Srie * an object have been defined via versioning/scoping.
130a194faf8Srie */
13108278a5eSRod Evans if (!SYM_IS_HIDDEN(sdp))
132a194faf8Srie return;
133a194faf8Srie
134a194faf8Srie /*
135a194faf8Srie * Remove any unreferenced symbols that are not associated with
136a194faf8Srie * a section.
137a194faf8Srie */
138a194faf8Srie if ((isp == NULL) && ((sdp->sd_flags & FLG_SY_UPREQD) == 0)) {
139a194faf8Srie DBG_CALL(Dbg_syms_discarded(ofl->ofl_lml, sdp));
140a194faf8Srie if (ifl->ifl_flags & FLG_IF_IGNORE)
141a194faf8Srie remove_scoped(ofl, sdp, allow_ldynsym);
142a194faf8Srie return;
143a194faf8Srie }
144a194faf8Srie }
145a194faf8Srie
146a194faf8Srie /*
147a194faf8Srie * Do not discard any symbols that are associated with non-allocable
148a194faf8Srie * segments.
149a194faf8Srie */
150a194faf8Srie if (isp && ((isp->is_flags & FLG_IS_SECTREF) == 0) &&
151a194faf8Srie ((osp = isp->is_osdesc) != 0) &&
152a194faf8Srie (osp->os_sgdesc->sg_phdr.p_type == PT_LOAD)) {
153a194faf8Srie DBG_CALL(Dbg_syms_discarded(ofl->ofl_lml, sdp));
154a194faf8Srie if (ifl->ifl_flags & FLG_IF_IGNORE) {
155a194faf8Srie if (bind == STB_LOCAL)
156a194faf8Srie remove_local(ofl, sdp, allow_ldynsym);
157a194faf8Srie else
158a194faf8Srie remove_scoped(ofl, sdp, allow_ldynsym);
159a194faf8Srie }
160a194faf8Srie }
161a194faf8Srie }
162a194faf8Srie
163*d9c5840bSRichard Lowe static Boolean
isdesc_discarded(Is_desc * isp)164*d9c5840bSRichard Lowe isdesc_discarded(Is_desc *isp)
165*d9c5840bSRichard Lowe {
166*d9c5840bSRichard Lowe Ifl_desc *ifl = isp->is_file;
167*d9c5840bSRichard Lowe Os_desc *osp = isp->is_osdesc;
168*d9c5840bSRichard Lowe Word ptype = osp->os_sgdesc->sg_phdr.p_type;
169*d9c5840bSRichard Lowe
170*d9c5840bSRichard Lowe if (isp->is_flags & FLG_IS_DISCARD)
171*d9c5840bSRichard Lowe return (TRUE);
172*d9c5840bSRichard Lowe
173*d9c5840bSRichard Lowe /*
174*d9c5840bSRichard Lowe * If the file is discarded, it will take
175*d9c5840bSRichard Lowe * the section with it.
176*d9c5840bSRichard Lowe */
177*d9c5840bSRichard Lowe if (ifl &&
178*d9c5840bSRichard Lowe (((ifl->ifl_flags & FLG_IF_FILEREF) == 0) ||
179*d9c5840bSRichard Lowe ((ptype == PT_LOAD) &&
180*d9c5840bSRichard Lowe ((isp->is_flags & FLG_IS_SECTREF) == 0) &&
181*d9c5840bSRichard Lowe (isp->is_shdr->sh_size > 0))) &&
182*d9c5840bSRichard Lowe (ifl->ifl_flags & FLG_IF_IGNORE))
183*d9c5840bSRichard Lowe return (TRUE);
184*d9c5840bSRichard Lowe
185*d9c5840bSRichard Lowe return (FALSE);
186*d9c5840bSRichard Lowe }
187*d9c5840bSRichard Lowe
188a194faf8Srie /*
189e64d0ff9SAli Bahrami * There are situations where we may count output sections (ofl_shdrcnt)
190e64d0ff9SAli Bahrami * that are subsequently eliminated from the output object. Whether or
191e64d0ff9SAli Bahrami * not this happens cannot be known until all input has been seen and
192e64d0ff9SAli Bahrami * section elimination code has run. However, the situations where this
193e64d0ff9SAli Bahrami * outcome is possible are known, and are flagged by setting FLG_OF_ADJOSCNT.
194e64d0ff9SAli Bahrami *
195e64d0ff9SAli Bahrami * If FLG_OF_ADJOSCNT is set, this routine makes a pass over the output
196e64d0ff9SAli Bahrami * sections. If an unused output section is encountered, we decrement
197e64d0ff9SAli Bahrami * ofl->ofl_shdrcnt and remove the section name from the .shstrtab string
198e64d0ff9SAli Bahrami * table (ofl->ofl_shdrsttab).
199e64d0ff9SAli Bahrami *
200e64d0ff9SAli Bahrami * This code must be kept in sync with the similar code
201e64d0ff9SAli Bahrami * found in outfile.c:ld_create_outfile().
202e64d0ff9SAli Bahrami */
203e64d0ff9SAli Bahrami static void
adjust_os_count(Ofl_desc * ofl)204e64d0ff9SAli Bahrami adjust_os_count(Ofl_desc *ofl)
205e64d0ff9SAli Bahrami {
206e64d0ff9SAli Bahrami Sg_desc *sgp;
207e64d0ff9SAli Bahrami Is_desc *isp;
208e64d0ff9SAli Bahrami Os_desc *osp;
209e64d0ff9SAli Bahrami Aliste idx1;
210e64d0ff9SAli Bahrami
211e64d0ff9SAli Bahrami if ((ofl->ofl_flags & FLG_OF_ADJOSCNT) == 0)
212e64d0ff9SAli Bahrami return;
213e64d0ff9SAli Bahrami
214e64d0ff9SAli Bahrami /*
215e64d0ff9SAli Bahrami * For each output section, look at the input sections to find at least
216e64d0ff9SAli Bahrami * one input section that has not been eliminated. If none are found,
217e64d0ff9SAli Bahrami * the -z ignore processing above has eliminated that output section.
218e64d0ff9SAli Bahrami */
219e64d0ff9SAli Bahrami for (APLIST_TRAVERSE(ofl->ofl_segs, idx1, sgp)) {
220e64d0ff9SAli Bahrami Aliste idx2;
221e64d0ff9SAli Bahrami
222e64d0ff9SAli Bahrami for (APLIST_TRAVERSE(sgp->sg_osdescs, idx2, osp)) {
223e64d0ff9SAli Bahrami Aliste idx3;
224e64d0ff9SAli Bahrami int keep = 0, os_isdescs_idx;
225e64d0ff9SAli Bahrami
226e64d0ff9SAli Bahrami OS_ISDESCS_TRAVERSE(os_isdescs_idx, osp, idx3, isp) {
227e64d0ff9SAli Bahrami /*
228e64d0ff9SAli Bahrami * We have found a kept input section,
229e64d0ff9SAli Bahrami * so the output section will be created.
230e64d0ff9SAli Bahrami */
231*d9c5840bSRichard Lowe if (!isdesc_discarded(isp)) {
232e64d0ff9SAli Bahrami keep = 1;
233e64d0ff9SAli Bahrami break;
234e64d0ff9SAli Bahrami }
235*d9c5840bSRichard Lowe }
236e64d0ff9SAli Bahrami /*
237e64d0ff9SAli Bahrami * If no section of this name was kept, decrement
238e64d0ff9SAli Bahrami * the count and remove the name from .shstrtab.
239e64d0ff9SAli Bahrami */
240e64d0ff9SAli Bahrami if (keep == 0) {
241e64d0ff9SAli Bahrami /* LINTED - only used for assert() */
242e64d0ff9SAli Bahrami int err;
243e64d0ff9SAli Bahrami
244e64d0ff9SAli Bahrami ofl->ofl_shdrcnt--;
245e64d0ff9SAli Bahrami err = st_delstring(ofl->ofl_shdrsttab,
246e64d0ff9SAli Bahrami osp->os_name);
247e64d0ff9SAli Bahrami assert(err != -1);
248e64d0ff9SAli Bahrami }
249e64d0ff9SAli Bahrami }
250e64d0ff9SAli Bahrami }
251e64d0ff9SAli Bahrami }
252e64d0ff9SAli Bahrami
253e64d0ff9SAli Bahrami /*
254a194faf8Srie * If -zignore has been in effect, scan all input files to determine if the
255a194faf8Srie * file, or sections from the file, have been referenced. If not, the file or
2561da7e599SAli Bahrami * some of the files sections can be discarded. If sections are to be
2571da7e599SAli Bahrami * discarded, rescan the output relocations and the symbol table and remove
2581da7e599SAli Bahrami * the relocations and symbol entries that are no longer required.
2597c478bd9Sstevel@tonic-gate *
2607c478bd9Sstevel@tonic-gate * Note: It's possible that a section which is being discarded has contributed
2617c478bd9Sstevel@tonic-gate * to the GOT table or the PLT table. However, we can't at this point
2627c478bd9Sstevel@tonic-gate * eliminate the corresponding entries. This is because there could well
2637c478bd9Sstevel@tonic-gate * be other sections referencing those same entries, but we don't have
2647c478bd9Sstevel@tonic-gate * the infrastructure to determine this. So, keep the PLT and GOT
2657c478bd9Sstevel@tonic-gate * entries in the table in case someone wants them.
2667c478bd9Sstevel@tonic-gate * Note: The section to be affected needs to be allocatable.
2677c478bd9Sstevel@tonic-gate * So even if -zignore is in effect, if the section is not allocatable,
2687c478bd9Sstevel@tonic-gate * we do not eliminate it.
2697c478bd9Sstevel@tonic-gate */
2705aefb655Srie static uintptr_t
ignore_section_processing(Ofl_desc * ofl)2717c478bd9Sstevel@tonic-gate ignore_section_processing(Ofl_desc *ofl)
2727c478bd9Sstevel@tonic-gate {
2731da7e599SAli Bahrami Sg_desc *sgp;
2741da7e599SAli Bahrami Is_desc *isp;
2751da7e599SAli Bahrami Os_desc *osp;
2767c478bd9Sstevel@tonic-gate Ifl_desc *ifl;
277bf994817SAli Bahrami Rel_cachebuf *rcbp;
278bf994817SAli Bahrami Rel_desc *rsp;
279a194faf8Srie int allow_ldynsym = OFL_ALLOW_LDYNSYM(ofl);
28057ef7aa9SRod Evans Aliste idx1;
2817c478bd9Sstevel@tonic-gate
28257ef7aa9SRod Evans for (APLIST_TRAVERSE(ofl->ofl_objs, idx1, ifl)) {
2837c478bd9Sstevel@tonic-gate uint_t num, discard;
2847c478bd9Sstevel@tonic-gate
2857c478bd9Sstevel@tonic-gate /*
2867c478bd9Sstevel@tonic-gate * Diagnose (-D unused) a completely unreferenced file.
2877c478bd9Sstevel@tonic-gate */
2887c478bd9Sstevel@tonic-gate if ((ifl->ifl_flags & FLG_IF_FILEREF) == 0)
2895aefb655Srie DBG_CALL(Dbg_unused_file(ofl->ofl_lml,
2905aefb655Srie ifl->ifl_name, 0, 0));
291fb1354edSrie if (((ofl->ofl_flags1 & FLG_OF1_IGNPRC) == 0) ||
292fb1354edSrie ((ifl->ifl_flags & FLG_IF_IGNORE) == 0))
2937c478bd9Sstevel@tonic-gate continue;
2947c478bd9Sstevel@tonic-gate
2957c478bd9Sstevel@tonic-gate /*
296fb1354edSrie * Before scanning the whole symbol table to determine if
297fb1354edSrie * symbols should be discard - quickly (relatively) scan the
298fb1354edSrie * sections to determine if any are to be discarded.
2997c478bd9Sstevel@tonic-gate */
300fb1354edSrie discard = 0;
301fb1354edSrie if (ifl->ifl_flags & FLG_IF_FILEREF) {
302fb1354edSrie for (num = 1; num < ifl->ifl_shnum; num++) {
3031da7e599SAli Bahrami if (((isp = ifl->ifl_isdesc[num]) != NULL) &&
3047c478bd9Sstevel@tonic-gate ((isp->is_flags & FLG_IS_SECTREF) == 0) &&
3051da7e599SAli Bahrami ((osp = isp->is_osdesc) != NULL) &&
3061da7e599SAli Bahrami ((sgp = osp->os_sgdesc) != NULL) &&
307fb1354edSrie (sgp->sg_phdr.p_type == PT_LOAD)) {
3087c478bd9Sstevel@tonic-gate discard++;
3097c478bd9Sstevel@tonic-gate break;
3107c478bd9Sstevel@tonic-gate }
3117c478bd9Sstevel@tonic-gate }
312fb1354edSrie }
313fb1354edSrie
3147c478bd9Sstevel@tonic-gate /*
3157c478bd9Sstevel@tonic-gate * No sections are to be 'ignored'
3167c478bd9Sstevel@tonic-gate */
317fb1354edSrie if ((discard == 0) && (ifl->ifl_flags & FLG_IF_FILEREF))
3187c478bd9Sstevel@tonic-gate continue;
3197c478bd9Sstevel@tonic-gate
3207c478bd9Sstevel@tonic-gate /*
321fb1354edSrie * We know that we have discarded sections. Scan the symbol
322fb1354edSrie * table for this file to determine if symbols need to be
323fb1354edSrie * discarded that are associated with the 'ignored' sections.
3247c478bd9Sstevel@tonic-gate */
3257c478bd9Sstevel@tonic-gate for (num = 1; num < ifl->ifl_symscnt; num++) {
3267c478bd9Sstevel@tonic-gate Sym_desc *sdp;
3277c478bd9Sstevel@tonic-gate
328a194faf8Srie /*
329a194faf8Srie * If the symbol definition has been resolved to another
330a194faf8Srie * file, or the symbol has already been discarded or
331a194faf8Srie * eliminated, skip it.
332a194faf8Srie */
3337c478bd9Sstevel@tonic-gate sdp = ifl->ifl_oldndx[num];
334a194faf8Srie if ((sdp->sd_file != ifl) ||
335635216b6SRod Evans (sdp->sd_flags &
336635216b6SRod Evans (FLG_SY_ISDISC | FLG_SY_INVALID | FLG_SY_ELIM)))
3377c478bd9Sstevel@tonic-gate continue;
3387c478bd9Sstevel@tonic-gate
3397c478bd9Sstevel@tonic-gate /*
340a194faf8Srie * Complete the investigation of the symbol.
3417c478bd9Sstevel@tonic-gate */
342a194faf8Srie ignore_sym(ofl, ifl, sdp, allow_ldynsym);
343a194faf8Srie }
3447c478bd9Sstevel@tonic-gate }
3457c478bd9Sstevel@tonic-gate
346fb1354edSrie /*
347a194faf8Srie * If we were only here to solicit debugging diagnostics, we're done.
348fb1354edSrie */
349fb1354edSrie if ((ofl->ofl_flags1 & FLG_OF1_IGNPRC) == 0)
350fb1354edSrie return (1);
351fb1354edSrie
3527c478bd9Sstevel@tonic-gate /*
353fb1354edSrie * Scan all output relocations searching for those against discarded or
354fb1354edSrie * ignored sections. If one is found, decrement the total outrel count.
3557c478bd9Sstevel@tonic-gate */
356bf994817SAli Bahrami REL_CACHE_TRAVERSE(&ofl->ofl_outrels, idx1, rcbp, rsp) {
357a194faf8Srie Is_desc *isc = rsp->rel_isdesc;
3587c478bd9Sstevel@tonic-gate uint_t flags, entsize;
3597c478bd9Sstevel@tonic-gate Shdr *shdr;
3607c478bd9Sstevel@tonic-gate
361bf994817SAli Bahrami if ((isc == NULL) || ((isc->is_flags & (FLG_IS_SECTREF))) ||
36257ef7aa9SRod Evans ((ifl = isc->is_file) == NULL) ||
3637c478bd9Sstevel@tonic-gate ((ifl->ifl_flags & FLG_IF_IGNORE) == 0) ||
36457ef7aa9SRod Evans ((shdr = isc->is_shdr) == NULL) ||
3657c478bd9Sstevel@tonic-gate ((shdr->sh_flags & SHF_ALLOC) == 0))
3667c478bd9Sstevel@tonic-gate continue;
3677c478bd9Sstevel@tonic-gate
368a194faf8Srie flags = rsp->rel_flags;
3697c478bd9Sstevel@tonic-gate
3707c478bd9Sstevel@tonic-gate if (flags & (FLG_REL_GOT | FLG_REL_BSS |
3717c478bd9Sstevel@tonic-gate FLG_REL_NOINFO | FLG_REL_PLT))
3727c478bd9Sstevel@tonic-gate continue;
3737c478bd9Sstevel@tonic-gate
374bf994817SAli Bahrami osp = RELAUX_GET_OSDESC(rsp);
3757c478bd9Sstevel@tonic-gate
376a194faf8Srie if (rsp->rel_flags & FLG_REL_RELA)
3777c478bd9Sstevel@tonic-gate entsize = sizeof (Rela);
3787c478bd9Sstevel@tonic-gate else
3797c478bd9Sstevel@tonic-gate entsize = sizeof (Rel);
3807c478bd9Sstevel@tonic-gate
381a194faf8Srie assert(osp->os_szoutrels > 0);
382a194faf8Srie osp->os_szoutrels -= entsize;
3837c478bd9Sstevel@tonic-gate
3847c478bd9Sstevel@tonic-gate if (!(flags & FLG_REL_PLT))
3857c478bd9Sstevel@tonic-gate ofl->ofl_reloccntsub++;
3867c478bd9Sstevel@tonic-gate
387ba2be530Sab196087 if (rsp->rel_rtype == ld_targ.t_m.m_r_relative)
3887c478bd9Sstevel@tonic-gate ofl->ofl_relocrelcnt--;
3897c478bd9Sstevel@tonic-gate }
3901da7e599SAli Bahrami
3911da7e599SAli Bahrami /*
392e64d0ff9SAli Bahrami * As a result of our work here, the number of output sections may
393e64d0ff9SAli Bahrami * have decreased. Trigger a call to adjust_os_count().
3941da7e599SAli Bahrami */
395e64d0ff9SAli Bahrami ofl->ofl_flags |= FLG_OF_ADJOSCNT;
3961da7e599SAli Bahrami
3977c478bd9Sstevel@tonic-gate return (1);
3987c478bd9Sstevel@tonic-gate }
3997c478bd9Sstevel@tonic-gate
4007c478bd9Sstevel@tonic-gate /*
4019039eeafSab196087 * Allocate Elf_Data, Shdr, and Is_desc structures for a new
4029039eeafSab196087 * section.
4039039eeafSab196087 *
4049039eeafSab196087 * entry:
4059039eeafSab196087 * ofl - Output file descriptor
4069039eeafSab196087 * shtype - SHT_ type code for section.
4079039eeafSab196087 * shname - String giving the name for the new section.
4089039eeafSab196087 * entcnt - # of items contained in the data part of the new section.
4099039eeafSab196087 * This value is multiplied against the known element size
4109039eeafSab196087 * for the section type to determine the size of the data
4119039eeafSab196087 * area for the section. It is only meaningful in cases where
4129039eeafSab196087 * the section type has a non-zero element size. In other cases,
4139039eeafSab196087 * the caller must set the size fields in the *ret_data and
4149039eeafSab196087 * *ret_shdr structs manually.
4159039eeafSab196087 * ret_isec, ret_shdr, ret_data - Address of pointers to
4169039eeafSab196087 * receive address of newly allocated structs.
4179039eeafSab196087 *
4189039eeafSab196087 * exit:
4199039eeafSab196087 * On error, returns S_ERROR. On success, returns (1), and the
4209039eeafSab196087 * ret_ pointers have been updated to point at the new structures,
421cce0e03bSab196087 * which have been filled in. To finish the task, the caller must
4229039eeafSab196087 * update any fields within the supplied descriptors that differ
4239039eeafSab196087 * from its needs, and then call ld_place_section().
4249039eeafSab196087 */
4259039eeafSab196087 static uintptr_t
new_section(Ofl_desc * ofl,Word shtype,const char * shname,Xword entcnt,Is_desc ** ret_isec,Shdr ** ret_shdr,Elf_Data ** ret_data)4269039eeafSab196087 new_section(Ofl_desc *ofl, Word shtype, const char *shname, Xword entcnt,
4279039eeafSab196087 Is_desc **ret_isec, Shdr **ret_shdr, Elf_Data **ret_data)
4289039eeafSab196087 {
4299039eeafSab196087 typedef struct sec_info {
4309039eeafSab196087 Word d_type;
4319039eeafSab196087 Word align; /* Used in both data and section header */
4329039eeafSab196087 Word sh_flags;
4339039eeafSab196087 Word sh_entsize;
4349039eeafSab196087 } SEC_INFO_T;
4359039eeafSab196087
4369039eeafSab196087 const SEC_INFO_T *sec_info;
4379039eeafSab196087
4389039eeafSab196087 Shdr *shdr;
4399039eeafSab196087 Elf_Data *data;
4409039eeafSab196087 Is_desc *isec;
4419039eeafSab196087 size_t size;
4429039eeafSab196087
4439039eeafSab196087 /*
4449039eeafSab196087 * For each type of section, we have a distinct set of
4459039eeafSab196087 * SEC_INFO_T values. This macro defines a static structure
4469039eeafSab196087 * containing those values and generates code to set the sec_info
4479039eeafSab196087 * pointer to refer to it. The pointer in sec_info remains valid
4489039eeafSab196087 * outside of the declaration scope because the info_s struct is static.
449ba2be530Sab196087 *
450ba2be530Sab196087 * We can't determine the value of M_WORD_ALIGN at compile time, so
451ba2be530Sab196087 * a different variant is used for those cases.
4529039eeafSab196087 */
4539039eeafSab196087 #define SET_SEC_INFO(d_type, d_align, sh_flags, sh_entsize) \
4549039eeafSab196087 { \
4559039eeafSab196087 static const SEC_INFO_T info_s = { d_type, d_align, sh_flags, \
4569039eeafSab196087 sh_entsize}; \
4579039eeafSab196087 sec_info = &info_s; \
4589039eeafSab196087 }
459ba2be530Sab196087 #define SET_SEC_INFO_WORD_ALIGN(d_type, sh_flags, sh_entsize) \
460ba2be530Sab196087 { \
461ba2be530Sab196087 static SEC_INFO_T info_s = { d_type, 0, sh_flags, \
462ba2be530Sab196087 sh_entsize}; \
463ba2be530Sab196087 info_s.align = ld_targ.t_m.m_word_align; \
464ba2be530Sab196087 sec_info = &info_s; \
465ba2be530Sab196087 }
4669039eeafSab196087
4679039eeafSab196087 switch (shtype) {
4689039eeafSab196087 case SHT_PROGBITS:
4699039eeafSab196087 /*
4709039eeafSab196087 * SHT_PROGBITS sections contain are used for many
4719039eeafSab196087 * different sections. Alignments and flags differ.
4729039eeafSab196087 * Some have a standard entsize, and others don't.
4739039eeafSab196087 * We set some defaults here, but there is no expectation
4749039eeafSab196087 * that they are correct or complete for any specific
4759039eeafSab196087 * purpose. The caller must provide the correct values.
4769039eeafSab196087 */
477ba2be530Sab196087 SET_SEC_INFO_WORD_ALIGN(ELF_T_BYTE, SHF_ALLOC, 0)
4789039eeafSab196087 break;
4799039eeafSab196087
4809039eeafSab196087 case SHT_SYMTAB:
481ba2be530Sab196087 SET_SEC_INFO_WORD_ALIGN(ELF_T_SYM, 0, sizeof (Sym))
4829039eeafSab196087 break;
4839039eeafSab196087
4849039eeafSab196087 case SHT_DYNSYM:
4854f680cc6SAli Bahrami SET_SEC_INFO_WORD_ALIGN(ELF_T_SYM, SHF_ALLOC, sizeof (Sym))
4864f680cc6SAli Bahrami break;
4874f680cc6SAli Bahrami
4889039eeafSab196087 case SHT_SUNW_LDYNSYM:
4894f680cc6SAli Bahrami ofl->ofl_flags |= FLG_OF_OSABI;
490ba2be530Sab196087 SET_SEC_INFO_WORD_ALIGN(ELF_T_SYM, SHF_ALLOC, sizeof (Sym))
4919039eeafSab196087 break;
4929039eeafSab196087
4939039eeafSab196087 case SHT_STRTAB:
4949039eeafSab196087 /*
4959039eeafSab196087 * A string table may or may not be allocable, depending
4969039eeafSab196087 * on context, so we leave that flag unset and leave it to
4979039eeafSab196087 * the caller to add it if necessary.
4989039eeafSab196087 *
4999039eeafSab196087 * String tables do not have a standard entsize, so
5009039eeafSab196087 * we set it to 0.
5019039eeafSab196087 */
5029039eeafSab196087 SET_SEC_INFO(ELF_T_BYTE, 1, SHF_STRINGS, 0)
5039039eeafSab196087 break;
5049039eeafSab196087
5059039eeafSab196087 case SHT_RELA:
5069039eeafSab196087 /*
5079039eeafSab196087 * Relocations with an addend (Everything except 32-bit X86).
5089039eeafSab196087 * The caller is expected to set all section header flags.
5099039eeafSab196087 */
510ba2be530Sab196087 SET_SEC_INFO_WORD_ALIGN(ELF_T_RELA, 0, sizeof (Rela))
5119039eeafSab196087 break;
5129039eeafSab196087
5139039eeafSab196087 case SHT_REL:
5149039eeafSab196087 /*
5159039eeafSab196087 * Relocations without an addend (32-bit X86 only).
5169039eeafSab196087 * The caller is expected to set all section header flags.
5179039eeafSab196087 */
518ba2be530Sab196087 SET_SEC_INFO_WORD_ALIGN(ELF_T_REL, 0, sizeof (Rel))
5199039eeafSab196087 break;
5209039eeafSab196087
5219039eeafSab196087 case SHT_HASH:
5224f680cc6SAli Bahrami SET_SEC_INFO_WORD_ALIGN(ELF_T_WORD, SHF_ALLOC, sizeof (Word))
5234f680cc6SAli Bahrami break;
5244f680cc6SAli Bahrami
525d579eb63Sab196087 case SHT_SUNW_symsort:
526d579eb63Sab196087 case SHT_SUNW_tlssort:
5274f680cc6SAli Bahrami ofl->ofl_flags |= FLG_OF_OSABI;
528ba2be530Sab196087 SET_SEC_INFO_WORD_ALIGN(ELF_T_WORD, SHF_ALLOC, sizeof (Word))
5299039eeafSab196087 break;
5309039eeafSab196087
5319039eeafSab196087 case SHT_DYNAMIC:
5329039eeafSab196087 /*
53394c044f4SRod Evans * A dynamic section may or may not be allocable, and may or
53494c044f4SRod Evans * may not be writable, depending on context, so we leave the
53594c044f4SRod Evans * flags unset and leave it to the caller to add them if
53694c044f4SRod Evans * necessary.
5379039eeafSab196087 */
53894c044f4SRod Evans SET_SEC_INFO_WORD_ALIGN(ELF_T_DYN, 0, sizeof (Dyn))
5399039eeafSab196087 break;
5409039eeafSab196087
5419039eeafSab196087 case SHT_NOBITS:
5429039eeafSab196087 /*
5439039eeafSab196087 * SHT_NOBITS is used for BSS-type sections. The size and
5449039eeafSab196087 * alignment depend on the specific use and must be adjusted
5459039eeafSab196087 * by the caller.
5469039eeafSab196087 */
5479039eeafSab196087 SET_SEC_INFO(ELF_T_BYTE, 0, SHF_ALLOC | SHF_WRITE, 0)
5489039eeafSab196087 break;
5499039eeafSab196087
5509039eeafSab196087 case SHT_INIT_ARRAY:
5519039eeafSab196087 case SHT_FINI_ARRAY:
5529039eeafSab196087 case SHT_PREINIT_ARRAY:
5539039eeafSab196087 SET_SEC_INFO(ELF_T_ADDR, sizeof (Addr), SHF_ALLOC | SHF_WRITE,
5549039eeafSab196087 sizeof (Addr))
5559039eeafSab196087 break;
5569039eeafSab196087
5579039eeafSab196087 case SHT_SYMTAB_SHNDX:
5589039eeafSab196087 /*
5599039eeafSab196087 * Note that these sections are created to be associated
5609039eeafSab196087 * with both symtab and dynsym symbol tables. However, they
5619039eeafSab196087 * are non-allocable in all cases, because the runtime
5629039eeafSab196087 * linker has no need for this information. It is purely
5639039eeafSab196087 * informational, used by elfdump(1), debuggers, etc.
5649039eeafSab196087 */
565ba2be530Sab196087 SET_SEC_INFO_WORD_ALIGN(ELF_T_WORD, 0, sizeof (Word));
5669039eeafSab196087 break;
5679039eeafSab196087
5689039eeafSab196087 case SHT_SUNW_cap:
5694f680cc6SAli Bahrami ofl->ofl_flags |= FLG_OF_OSABI;
570ba2be530Sab196087 SET_SEC_INFO_WORD_ALIGN(ELF_T_CAP, SHF_ALLOC, sizeof (Cap));
5719039eeafSab196087 break;
5729039eeafSab196087
57308278a5eSRod Evans case SHT_SUNW_capchain:
57408278a5eSRod Evans ofl->ofl_flags |= FLG_OF_OSABI;
57508278a5eSRod Evans SET_SEC_INFO_WORD_ALIGN(ELF_T_WORD, SHF_ALLOC,
57608278a5eSRod Evans sizeof (Capchain));
57708278a5eSRod Evans break;
57808278a5eSRod Evans
57908278a5eSRod Evans case SHT_SUNW_capinfo:
58008278a5eSRod Evans ofl->ofl_flags |= FLG_OF_OSABI;
58108278a5eSRod Evans #if _ELF64
58208278a5eSRod Evans SET_SEC_INFO(ELF_T_XWORD, sizeof (Xword), SHF_ALLOC,
58308278a5eSRod Evans sizeof (Capinfo));
58408278a5eSRod Evans #else
58508278a5eSRod Evans SET_SEC_INFO(ELF_T_WORD, sizeof (Word), SHF_ALLOC,
58608278a5eSRod Evans sizeof (Capinfo));
58708278a5eSRod Evans #endif
58808278a5eSRod Evans break;
58908278a5eSRod Evans
5909039eeafSab196087 case SHT_SUNW_move:
5914f680cc6SAli Bahrami ofl->ofl_flags |= FLG_OF_OSABI;
5929039eeafSab196087 SET_SEC_INFO(ELF_T_BYTE, sizeof (Lword),
5939039eeafSab196087 SHF_ALLOC | SHF_WRITE, sizeof (Move));
5949039eeafSab196087 break;
5959039eeafSab196087
5969039eeafSab196087 case SHT_SUNW_syminfo:
5974f680cc6SAli Bahrami ofl->ofl_flags |= FLG_OF_OSABI;
5989039eeafSab196087 /*
5999039eeafSab196087 * The sh_info field of the SHT_*_syminfo section points
6009039eeafSab196087 * to the header index of the associated .dynamic section,
6019039eeafSab196087 * so we also set SHF_INFO_LINK.
6029039eeafSab196087 */
603ba2be530Sab196087 SET_SEC_INFO_WORD_ALIGN(ELF_T_BYTE,
6049039eeafSab196087 SHF_ALLOC | SHF_INFO_LINK, sizeof (Syminfo));
6059039eeafSab196087 break;
6069039eeafSab196087
6079039eeafSab196087 case SHT_SUNW_verneed:
6089039eeafSab196087 case SHT_SUNW_verdef:
6094f680cc6SAli Bahrami ofl->ofl_flags |= FLG_OF_OSABI;
6109039eeafSab196087 /*
6119039eeafSab196087 * The info for verneed and versym happen to be the same.
6129039eeafSab196087 * The entries in these sections are not of uniform size,
6139039eeafSab196087 * so we set the entsize to 0.
6149039eeafSab196087 */
615ba2be530Sab196087 SET_SEC_INFO_WORD_ALIGN(ELF_T_BYTE, SHF_ALLOC, 0);
6169039eeafSab196087 break;
6179039eeafSab196087
6189039eeafSab196087 case SHT_SUNW_versym:
6194f680cc6SAli Bahrami ofl->ofl_flags |= FLG_OF_OSABI;
620ba2be530Sab196087 SET_SEC_INFO_WORD_ALIGN(ELF_T_BYTE, SHF_ALLOC,
6219039eeafSab196087 sizeof (Versym));
6229039eeafSab196087 break;
6239039eeafSab196087
6249039eeafSab196087 default:
6259039eeafSab196087 /* Should not happen: fcn called with unknown section type */
6269039eeafSab196087 assert(0);
6279039eeafSab196087 return (S_ERROR);
6289039eeafSab196087 }
6299039eeafSab196087 #undef SET_SEC_INFO
630ba2be530Sab196087 #undef SET_SEC_INFO_WORD_ALIGN
6319039eeafSab196087
6329039eeafSab196087 size = entcnt * sec_info->sh_entsize;
6339039eeafSab196087
6349039eeafSab196087 /*
6359039eeafSab196087 * Allocate and initialize the Elf_Data structure.
6369039eeafSab196087 */
63757ef7aa9SRod Evans if ((data = libld_calloc(sizeof (Elf_Data), 1)) == NULL)
6389039eeafSab196087 return (S_ERROR);
6399039eeafSab196087 data->d_type = sec_info->d_type;
6409039eeafSab196087 data->d_size = size;
6419039eeafSab196087 data->d_align = sec_info->align;
6429039eeafSab196087 data->d_version = ofl->ofl_dehdr->e_version;
6439039eeafSab196087
6449039eeafSab196087 /*
6459039eeafSab196087 * Allocate and initialize the Shdr structure.
6469039eeafSab196087 */
64757ef7aa9SRod Evans if ((shdr = libld_calloc(sizeof (Shdr), 1)) == NULL)
6489039eeafSab196087 return (S_ERROR);
6499039eeafSab196087 shdr->sh_type = shtype;
6509039eeafSab196087 shdr->sh_size = size;
6519039eeafSab196087 shdr->sh_flags = sec_info->sh_flags;
6529039eeafSab196087 shdr->sh_addralign = sec_info->align;
6539039eeafSab196087 shdr->sh_entsize = sec_info->sh_entsize;
6549039eeafSab196087
6559039eeafSab196087 /*
6569039eeafSab196087 * Allocate and initialize the Is_desc structure.
6579039eeafSab196087 */
65857ef7aa9SRod Evans if ((isec = libld_calloc(1, sizeof (Is_desc))) == NULL)
6599039eeafSab196087 return (S_ERROR);
6609039eeafSab196087 isec->is_name = shname;
6619039eeafSab196087 isec->is_shdr = shdr;
6629039eeafSab196087 isec->is_indata = data;
6639039eeafSab196087
6649039eeafSab196087
6659039eeafSab196087 *ret_isec = isec;
6669039eeafSab196087 *ret_shdr = shdr;
6679039eeafSab196087 *ret_data = data;
6689039eeafSab196087 return (1);
6699039eeafSab196087 }
6709039eeafSab196087
6719039eeafSab196087 /*
672cce0e03bSab196087 * Use an existing input section as a template to create a new
673cce0e03bSab196087 * input section with the same values as the original, other than
674cce0e03bSab196087 * the size of the data area which is supplied by the caller.
675cce0e03bSab196087 *
676cce0e03bSab196087 * entry:
677cce0e03bSab196087 * ofl - Output file descriptor
678cce0e03bSab196087 * ifl - Input file section to use as a template
679cce0e03bSab196087 * size - Size of data area for new section
680cce0e03bSab196087 * ret_isec, ret_shdr, ret_data - Address of pointers to
681cce0e03bSab196087 * receive address of newly allocated structs.
682cce0e03bSab196087 *
683cce0e03bSab196087 * exit:
684cce0e03bSab196087 * On error, returns S_ERROR. On success, returns (1), and the
685cce0e03bSab196087 * ret_ pointers have been updated to point at the new structures,
686cce0e03bSab196087 * which have been filled in. To finish the task, the caller must
687cce0e03bSab196087 * update any fields within the supplied descriptors that differ
688cce0e03bSab196087 * from its needs, and then call ld_place_section().
689cce0e03bSab196087 */
690cce0e03bSab196087 static uintptr_t
new_section_from_template(Ofl_desc * ofl,Is_desc * tmpl_isp,size_t size,Is_desc ** ret_isec,Shdr ** ret_shdr,Elf_Data ** ret_data)691cce0e03bSab196087 new_section_from_template(Ofl_desc *ofl, Is_desc *tmpl_isp, size_t size,
692cce0e03bSab196087 Is_desc **ret_isec, Shdr **ret_shdr, Elf_Data **ret_data)
693cce0e03bSab196087 {
694cce0e03bSab196087 Shdr *shdr;
695cce0e03bSab196087 Elf_Data *data;
696cce0e03bSab196087 Is_desc *isec;
697cce0e03bSab196087
698cce0e03bSab196087 /*
699cce0e03bSab196087 * Allocate and initialize the Elf_Data structure.
700cce0e03bSab196087 */
70157ef7aa9SRod Evans if ((data = libld_calloc(sizeof (Elf_Data), 1)) == NULL)
702cce0e03bSab196087 return (S_ERROR);
703cce0e03bSab196087 data->d_type = tmpl_isp->is_indata->d_type;
704cce0e03bSab196087 data->d_size = size;
705cce0e03bSab196087 data->d_align = tmpl_isp->is_shdr->sh_addralign;
706cce0e03bSab196087 data->d_version = ofl->ofl_dehdr->e_version;
707cce0e03bSab196087
708cce0e03bSab196087 /*
709cce0e03bSab196087 * Allocate and initialize the Shdr structure.
710cce0e03bSab196087 */
71157ef7aa9SRod Evans if ((shdr = libld_malloc(sizeof (Shdr))) == NULL)
712cce0e03bSab196087 return (S_ERROR);
713cce0e03bSab196087 *shdr = *tmpl_isp->is_shdr;
714cce0e03bSab196087 shdr->sh_addr = 0;
715cce0e03bSab196087 shdr->sh_offset = 0;
716cce0e03bSab196087 shdr->sh_size = size;
717cce0e03bSab196087
718cce0e03bSab196087 /*
719cce0e03bSab196087 * Allocate and initialize the Is_desc structure.
720cce0e03bSab196087 */
72157ef7aa9SRod Evans if ((isec = libld_calloc(1, sizeof (Is_desc))) == NULL)
722cce0e03bSab196087 return (S_ERROR);
723cce0e03bSab196087 isec->is_name = tmpl_isp->is_name;
724cce0e03bSab196087 isec->is_shdr = shdr;
725cce0e03bSab196087 isec->is_indata = data;
726cce0e03bSab196087
727cce0e03bSab196087
728cce0e03bSab196087 *ret_isec = isec;
729cce0e03bSab196087 *ret_shdr = shdr;
730cce0e03bSab196087 *ret_data = data;
731cce0e03bSab196087 return (1);
732cce0e03bSab196087 }
733cce0e03bSab196087
734cce0e03bSab196087 /*
7357c478bd9Sstevel@tonic-gate * Build a .bss section for allocation of tentative definitions. Any `static'
7367c478bd9Sstevel@tonic-gate * .bss definitions would have been associated to their own .bss sections and
7377c478bd9Sstevel@tonic-gate * thus collected from the input files. `global' .bss definitions are tagged
7387c478bd9Sstevel@tonic-gate * as COMMON and do not cause any associated .bss section elements to be
7397c478bd9Sstevel@tonic-gate * generated. Here we add up all these COMMON symbols and generate the .bss
7407c478bd9Sstevel@tonic-gate * section required to represent them.
7417c478bd9Sstevel@tonic-gate */
7427c478bd9Sstevel@tonic-gate uintptr_t
ld_make_bss(Ofl_desc * ofl,Xword size,Xword align,uint_t ident)74357ef7aa9SRod Evans ld_make_bss(Ofl_desc *ofl, Xword size, Xword align, uint_t ident)
7447c478bd9Sstevel@tonic-gate {
7457c478bd9Sstevel@tonic-gate Shdr *shdr;
7467c478bd9Sstevel@tonic-gate Elf_Data *data;
7477c478bd9Sstevel@tonic-gate Is_desc *isec;
7487c478bd9Sstevel@tonic-gate Os_desc *osp;
7497c478bd9Sstevel@tonic-gate Xword rsize = (Xword)ofl->ofl_relocbsssz;
7507c478bd9Sstevel@tonic-gate
7517c478bd9Sstevel@tonic-gate /*
7529039eeafSab196087 * Allocate header structs. We will set the name ourselves below,
7539039eeafSab196087 * and there is no entcnt for a BSS. So, the shname and entcnt
7549039eeafSab196087 * arguments are 0.
7557c478bd9Sstevel@tonic-gate */
7569039eeafSab196087 if (new_section(ofl, SHT_NOBITS, NULL, 0,
7579039eeafSab196087 &isec, &shdr, &data) == S_ERROR)
7587c478bd9Sstevel@tonic-gate return (S_ERROR);
7599039eeafSab196087
7607c478bd9Sstevel@tonic-gate data->d_size = (size_t)size;
7617c478bd9Sstevel@tonic-gate data->d_align = (size_t)align;
7627c478bd9Sstevel@tonic-gate
7637c478bd9Sstevel@tonic-gate shdr->sh_size = size;
7647c478bd9Sstevel@tonic-gate shdr->sh_addralign = align;
7657c478bd9Sstevel@tonic-gate
76657ef7aa9SRod Evans if (ident == ld_targ.t_id.id_tlsbss) {
7677c478bd9Sstevel@tonic-gate isec->is_name = MSG_ORIG(MSG_SCN_TBSS);
7687c478bd9Sstevel@tonic-gate ofl->ofl_istlsbss = isec;
76954d82594Sseizo shdr->sh_flags |= SHF_TLS;
7700bc07c75Srie
77157ef7aa9SRod Evans } else if (ident == ld_targ.t_id.id_bss) {
7727c478bd9Sstevel@tonic-gate isec->is_name = MSG_ORIG(MSG_SCN_BSS);
7737c478bd9Sstevel@tonic-gate ofl->ofl_isbss = isec;
77454d82594Sseizo
775ba2be530Sab196087 #if defined(_ELF64)
77657ef7aa9SRod Evans } else if ((ld_targ.t_m.m_mach == EM_AMD64) &&
77757ef7aa9SRod Evans (ident == ld_targ.t_id.id_lbss)) {
77854d82594Sseizo isec->is_name = MSG_ORIG(MSG_SCN_LBSS);
77954d82594Sseizo ofl->ofl_islbss = isec;
78054d82594Sseizo shdr->sh_flags |= SHF_AMD64_LARGE;
78154d82594Sseizo #endif
7827c478bd9Sstevel@tonic-gate }
78354d82594Sseizo
7847c478bd9Sstevel@tonic-gate /*
78557ef7aa9SRod Evans * Retain this .*bss input section as this will be where global symbol
78657ef7aa9SRod Evans * references are added.
7877c478bd9Sstevel@tonic-gate */
78869112eddSAli Bahrami if ((osp = ld_place_section(ofl, isec, NULL, ident, NULL)) ==
7891dd9d86fSAli Bahrami (Os_desc *)S_ERROR)
7907c478bd9Sstevel@tonic-gate return (S_ERROR);
7917c478bd9Sstevel@tonic-gate
7927c478bd9Sstevel@tonic-gate /*
79357ef7aa9SRod Evans * If relocations exist against a .*bss section, a section symbol must
79457ef7aa9SRod Evans * be created for the section in the .dynsym symbol table.
7957c478bd9Sstevel@tonic-gate */
7967c478bd9Sstevel@tonic-gate if (!(osp->os_flags & FLG_OS_OUTREL)) {
7971d9df23bSab196087 ofl_flag_t flagtotest;
79857ef7aa9SRod Evans
79957ef7aa9SRod Evans if (ident == ld_targ.t_id.id_tlsbss)
8007c478bd9Sstevel@tonic-gate flagtotest = FLG_OF1_TLSOREL;
8017c478bd9Sstevel@tonic-gate else
8027c478bd9Sstevel@tonic-gate flagtotest = FLG_OF1_BSSOREL;
8037c478bd9Sstevel@tonic-gate
8047c478bd9Sstevel@tonic-gate if (ofl->ofl_flags1 & flagtotest) {
8057c478bd9Sstevel@tonic-gate ofl->ofl_dynshdrcnt++;
8067c478bd9Sstevel@tonic-gate osp->os_flags |= FLG_OS_OUTREL;
8077c478bd9Sstevel@tonic-gate }
8087c478bd9Sstevel@tonic-gate }
8097c478bd9Sstevel@tonic-gate
8107c478bd9Sstevel@tonic-gate osp->os_szoutrels = rsize;
8117c478bd9Sstevel@tonic-gate return (1);
8127c478bd9Sstevel@tonic-gate }
8137c478bd9Sstevel@tonic-gate
8147c478bd9Sstevel@tonic-gate /*
8157c478bd9Sstevel@tonic-gate * Build a SHT_{INIT|FINI|PREINIT}ARRAY section (specified via
81657ef7aa9SRod Evans * ld -z *array=name).
8177c478bd9Sstevel@tonic-gate */
8185aefb655Srie static uintptr_t
make_array(Ofl_desc * ofl,Word shtype,const char * sectname,APlist * alp)81957ef7aa9SRod Evans make_array(Ofl_desc *ofl, Word shtype, const char *sectname, APlist *alp)
8207c478bd9Sstevel@tonic-gate {
8217c478bd9Sstevel@tonic-gate uint_t entcount;
82257ef7aa9SRod Evans Aliste idx;
8237c478bd9Sstevel@tonic-gate Elf_Data *data;
8247c478bd9Sstevel@tonic-gate Is_desc *isec;
8257c478bd9Sstevel@tonic-gate Shdr *shdr;
8267c478bd9Sstevel@tonic-gate Sym_desc *sdp;
8277c478bd9Sstevel@tonic-gate Rel_desc reld;
8287c478bd9Sstevel@tonic-gate Rela reloc;
8297c478bd9Sstevel@tonic-gate Os_desc *osp;
83002ca3e02Srie uintptr_t ret = 1;
8317c478bd9Sstevel@tonic-gate
83257ef7aa9SRod Evans if (alp == NULL)
8337c478bd9Sstevel@tonic-gate return (1);
8347c478bd9Sstevel@tonic-gate
8357c478bd9Sstevel@tonic-gate entcount = 0;
83657ef7aa9SRod Evans for (APLIST_TRAVERSE(alp, idx, sdp))
8377c478bd9Sstevel@tonic-gate entcount++;
8387c478bd9Sstevel@tonic-gate
8399039eeafSab196087 if (new_section(ofl, shtype, sectname, entcount, &isec, &shdr, &data) ==
8409039eeafSab196087 S_ERROR)
8417c478bd9Sstevel@tonic-gate return (S_ERROR);
8427c478bd9Sstevel@tonic-gate
84357ef7aa9SRod Evans if ((data->d_buf = libld_calloc(sizeof (Addr), entcount)) == NULL)
8447c478bd9Sstevel@tonic-gate return (S_ERROR);
8457c478bd9Sstevel@tonic-gate
84669112eddSAli Bahrami if (ld_place_section(ofl, isec, NULL, ld_targ.t_id.id_array, NULL) ==
847ba2be530Sab196087 (Os_desc *)S_ERROR)
8487c478bd9Sstevel@tonic-gate return (S_ERROR);
8497c478bd9Sstevel@tonic-gate
8507c478bd9Sstevel@tonic-gate osp = isec->is_osdesc;
8517c478bd9Sstevel@tonic-gate
8520e233487SRod Evans if ((ofl->ofl_osinitarray == NULL) && (shtype == SHT_INIT_ARRAY))
8537c478bd9Sstevel@tonic-gate ofl->ofl_osinitarray = osp;
8540e233487SRod Evans if ((ofl->ofl_ospreinitarray == NULL) && (shtype == SHT_PREINIT_ARRAY))
8557c478bd9Sstevel@tonic-gate ofl->ofl_ospreinitarray = osp;
8560e233487SRod Evans else if ((ofl->ofl_osfiniarray == NULL) && (shtype == SHT_FINI_ARRAY))
8577c478bd9Sstevel@tonic-gate ofl->ofl_osfiniarray = osp;
8587c478bd9Sstevel@tonic-gate
8597c478bd9Sstevel@tonic-gate /*
8607c478bd9Sstevel@tonic-gate * Create relocations against this section to initialize it to the
8617c478bd9Sstevel@tonic-gate * function addresses.
8627c478bd9Sstevel@tonic-gate */
8637c478bd9Sstevel@tonic-gate reld.rel_isdesc = isec;
864bf994817SAli Bahrami reld.rel_aux = NULL;
8657c478bd9Sstevel@tonic-gate reld.rel_flags = FLG_REL_LOAD;
8667c478bd9Sstevel@tonic-gate
8677c478bd9Sstevel@tonic-gate /*
8687c478bd9Sstevel@tonic-gate * Fabricate the relocation information (as if a relocation record had
8697c478bd9Sstevel@tonic-gate * been input - see init_rel()).
8707c478bd9Sstevel@tonic-gate */
871ba2be530Sab196087 reld.rel_rtype = ld_targ.t_m.m_r_arrayaddr;
8727c478bd9Sstevel@tonic-gate reld.rel_roffset = 0;
8737c478bd9Sstevel@tonic-gate reld.rel_raddend = 0;
8747c478bd9Sstevel@tonic-gate
8757c478bd9Sstevel@tonic-gate /*
8767c478bd9Sstevel@tonic-gate * Create a minimal relocation record to satisfy process_sym_reloc()
8777c478bd9Sstevel@tonic-gate * debugging requirements.
8787c478bd9Sstevel@tonic-gate */
8797c478bd9Sstevel@tonic-gate reloc.r_offset = 0;
880ba2be530Sab196087 reloc.r_info = ELF_R_INFO(0, ld_targ.t_m.m_r_arrayaddr);
8817c478bd9Sstevel@tonic-gate reloc.r_addend = 0;
8827c478bd9Sstevel@tonic-gate
883ba2be530Sab196087 DBG_CALL(Dbg_reloc_generate(ofl->ofl_lml, osp,
884ba2be530Sab196087 ld_targ.t_m.m_rel_sht_type));
88557ef7aa9SRod Evans for (APLIST_TRAVERSE(alp, idx, sdp)) {
8867c478bd9Sstevel@tonic-gate reld.rel_sym = sdp;
8877c478bd9Sstevel@tonic-gate
8885aefb655Srie if (ld_process_sym_reloc(ofl, &reld, (Rel *)&reloc, isec,
889e23c41c9SAli Bahrami MSG_INTL(MSG_STR_COMMAND), 0) == S_ERROR) {
89002ca3e02Srie ret = S_ERROR;
89102ca3e02Srie continue;
89202ca3e02Srie }
8937c478bd9Sstevel@tonic-gate
8947c478bd9Sstevel@tonic-gate reld.rel_roffset += (Xword)sizeof (Addr);
8957c478bd9Sstevel@tonic-gate reloc.r_offset = reld.rel_roffset;
8967c478bd9Sstevel@tonic-gate }
8977c478bd9Sstevel@tonic-gate
89802ca3e02Srie return (ret);
8997c478bd9Sstevel@tonic-gate }
9007c478bd9Sstevel@tonic-gate
9017c478bd9Sstevel@tonic-gate /*
9027c478bd9Sstevel@tonic-gate * Build a comment section (-Qy option).
9037c478bd9Sstevel@tonic-gate */
9045aefb655Srie static uintptr_t
make_comment(Ofl_desc * ofl)9057c478bd9Sstevel@tonic-gate make_comment(Ofl_desc *ofl)
9067c478bd9Sstevel@tonic-gate {
9077c478bd9Sstevel@tonic-gate Shdr *shdr;
9087c478bd9Sstevel@tonic-gate Elf_Data *data;
9097c478bd9Sstevel@tonic-gate Is_desc *isec;
9107c478bd9Sstevel@tonic-gate
9119039eeafSab196087 if (new_section(ofl, SHT_PROGBITS, MSG_ORIG(MSG_SCN_COMMENT), 0,
9129039eeafSab196087 &isec, &shdr, &data) == S_ERROR)
9137c478bd9Sstevel@tonic-gate return (S_ERROR);
9149039eeafSab196087
9157c478bd9Sstevel@tonic-gate data->d_buf = (void *)ofl->ofl_sgsid;
9167c478bd9Sstevel@tonic-gate data->d_size = strlen(ofl->ofl_sgsid) + 1;
9177c478bd9Sstevel@tonic-gate data->d_align = 1;
9187c478bd9Sstevel@tonic-gate
9197c478bd9Sstevel@tonic-gate shdr->sh_size = (Xword)data->d_size;
9209039eeafSab196087 shdr->sh_flags = 0;
9217c478bd9Sstevel@tonic-gate shdr->sh_addralign = 1;
9227c478bd9Sstevel@tonic-gate
92369112eddSAli Bahrami return ((uintptr_t)ld_place_section(ofl, isec, NULL,
9241dd9d86fSAli Bahrami ld_targ.t_id.id_note, NULL));
9257c478bd9Sstevel@tonic-gate }
9267c478bd9Sstevel@tonic-gate
9277c478bd9Sstevel@tonic-gate /*
9287c478bd9Sstevel@tonic-gate * Make the dynamic section. Calculate the size of any strings referenced
9297c478bd9Sstevel@tonic-gate * within this structure, they will be added to the global string table
9307c478bd9Sstevel@tonic-gate * (.dynstr). This routine should be called before make_dynstr().
9311d9df23bSab196087 *
9321d9df23bSab196087 * This routine must be maintained in parallel with update_odynamic()
9331d9df23bSab196087 * in update.c
9347c478bd9Sstevel@tonic-gate */
9355aefb655Srie static uintptr_t
make_dynamic(Ofl_desc * ofl)9367c478bd9Sstevel@tonic-gate make_dynamic(Ofl_desc *ofl)
9377c478bd9Sstevel@tonic-gate {
9387c478bd9Sstevel@tonic-gate Shdr *shdr;
9397c478bd9Sstevel@tonic-gate Os_desc *osp;
9407c478bd9Sstevel@tonic-gate Elf_Data *data;
9417c478bd9Sstevel@tonic-gate Is_desc *isec;
9427c478bd9Sstevel@tonic-gate size_t cnt = 0;
94357ef7aa9SRod Evans Aliste idx;
9447c478bd9Sstevel@tonic-gate Ifl_desc *ifl;
9457c478bd9Sstevel@tonic-gate Sym_desc *sdp;
9467c478bd9Sstevel@tonic-gate size_t size;
947635216b6SRod Evans Str_tbl *strtbl;
9481d9df23bSab196087 ofl_flag_t flags = ofl->ofl_flags;
9491d9df23bSab196087 int not_relobj = !(flags & FLG_OF_RELOBJ);
9507c478bd9Sstevel@tonic-gate int unused = 0;
9517c478bd9Sstevel@tonic-gate
9521d9df23bSab196087 /*
953635216b6SRod Evans * Select the required string table.
954635216b6SRod Evans */
955635216b6SRod Evans if (OFL_IS_STATIC_OBJ(ofl))
956635216b6SRod Evans strtbl = ofl->ofl_strtab;
957635216b6SRod Evans else
958635216b6SRod Evans strtbl = ofl->ofl_dynstrtab;
959635216b6SRod Evans
960635216b6SRod Evans /*
9611d9df23bSab196087 * Only a limited subset of DT_ entries apply to relocatable
9621d9df23bSab196087 * objects. See the comment at the head of update_odynamic() in
9631d9df23bSab196087 * update.c for details.
9641d9df23bSab196087 */
9659039eeafSab196087 if (new_section(ofl, SHT_DYNAMIC, MSG_ORIG(MSG_SCN_DYNAMIC), 0,
9669039eeafSab196087 &isec, &shdr, &data) == S_ERROR)
9677c478bd9Sstevel@tonic-gate return (S_ERROR);
9689039eeafSab196087
96994c044f4SRod Evans /*
97094c044f4SRod Evans * new_section() does not set SHF_ALLOC. If we're building anything
97194c044f4SRod Evans * besides a relocatable object, then the .dynamic section should
97294c044f4SRod Evans * reside in allocatable memory.
97394c044f4SRod Evans */
9741d9df23bSab196087 if (not_relobj)
9757c478bd9Sstevel@tonic-gate shdr->sh_flags |= SHF_ALLOC;
9767c478bd9Sstevel@tonic-gate
97794c044f4SRod Evans /*
97894c044f4SRod Evans * new_section() does not set SHF_WRITE. If we're building an object
97994c044f4SRod Evans * that specifies an interpretor, then a DT_DEBUG entry is created,
98094c044f4SRod Evans * which is initialized to the applications link-map list at runtime.
98194c044f4SRod Evans */
98294c044f4SRod Evans if (ofl->ofl_osinterp)
98394c044f4SRod Evans shdr->sh_flags |= SHF_WRITE;
98494c044f4SRod Evans
985ba2be530Sab196087 osp = ofl->ofl_osdynamic =
98669112eddSAli Bahrami ld_place_section(ofl, isec, NULL, ld_targ.t_id.id_dynamic, NULL);
9877c478bd9Sstevel@tonic-gate
9887c478bd9Sstevel@tonic-gate /*
9897c478bd9Sstevel@tonic-gate * Reserve entries for any needed dependencies.
9907c478bd9Sstevel@tonic-gate */
99157ef7aa9SRod Evans for (APLIST_TRAVERSE(ofl->ofl_sos, idx, ifl)) {
9927c478bd9Sstevel@tonic-gate if (!(ifl->ifl_flags & (FLG_IF_NEEDED | FLG_IF_NEEDSTR)))
9937c478bd9Sstevel@tonic-gate continue;
9947c478bd9Sstevel@tonic-gate
9957c478bd9Sstevel@tonic-gate /*
996fb1354edSrie * If this dependency didn't satisfy any symbol references,
9977c478bd9Sstevel@tonic-gate * generate a debugging diagnostic (ld(1) -Dunused can be used
9987c478bd9Sstevel@tonic-gate * to display these). If this is a standard needed dependency,
9997c478bd9Sstevel@tonic-gate * and -z ignore is in effect, drop the dependency. Explicitly
10007c478bd9Sstevel@tonic-gate * defined dependencies (i.e., -N dep) don't get dropped, and
10017c478bd9Sstevel@tonic-gate * are flagged as being required to simplify update_odynamic()
10027c478bd9Sstevel@tonic-gate * processing.
10037c478bd9Sstevel@tonic-gate */
1004fb1354edSrie if ((ifl->ifl_flags & FLG_IF_NEEDSTR) ||
1005fb1354edSrie ((ifl->ifl_flags & FLG_IF_DEPREQD) == 0)) {
10067c478bd9Sstevel@tonic-gate if (unused++ == 0)
10075aefb655Srie DBG_CALL(Dbg_util_nl(ofl->ofl_lml, DBG_NL_STD));
10085aefb655Srie DBG_CALL(Dbg_unused_file(ofl->ofl_lml, ifl->ifl_soname,
1009fb1354edSrie (ifl->ifl_flags & FLG_IF_NEEDSTR), 0));
10107c478bd9Sstevel@tonic-gate
10111007fd6fSAli Bahrami /*
10121007fd6fSAli Bahrami * Guidance: Remove unused dependency.
10131007fd6fSAli Bahrami *
10141007fd6fSAli Bahrami * If -z ignore is in effect, this warning is not
10151007fd6fSAli Bahrami * needed because we will quietly remove the unused
10161007fd6fSAli Bahrami * dependency.
10171007fd6fSAli Bahrami */
10181007fd6fSAli Bahrami if (OFL_GUIDANCE(ofl, FLG_OFG_NO_UNUSED) &&
10191007fd6fSAli Bahrami ((ifl->ifl_flags & FLG_IF_IGNORE) == 0))
10201007fd6fSAli Bahrami ld_eprintf(ofl, ERR_GUIDANCE,
10211007fd6fSAli Bahrami MSG_INTL(MSG_GUIDE_UNUSED),
10221007fd6fSAli Bahrami ifl->ifl_soname);
10231007fd6fSAli Bahrami
10247c478bd9Sstevel@tonic-gate if (ifl->ifl_flags & FLG_IF_NEEDSTR)
10257c478bd9Sstevel@tonic-gate ifl->ifl_flags |= FLG_IF_DEPREQD;
10267c478bd9Sstevel@tonic-gate else if (ifl->ifl_flags & FLG_IF_IGNORE)
10277c478bd9Sstevel@tonic-gate continue;
10287c478bd9Sstevel@tonic-gate }
10297c478bd9Sstevel@tonic-gate
10307c478bd9Sstevel@tonic-gate /*
1031f441771bSRod Evans * If this object requires a DT_POSFLAG_1 entry, reserve it.
10327c478bd9Sstevel@tonic-gate */
1033f441771bSRod Evans if ((ifl->ifl_flags & MSK_IF_POSFLAG1) && not_relobj)
10347c478bd9Sstevel@tonic-gate cnt++;
10357c478bd9Sstevel@tonic-gate
1036635216b6SRod Evans if (st_insert(strtbl, ifl->ifl_soname) == -1)
10377c478bd9Sstevel@tonic-gate return (S_ERROR);
10387c478bd9Sstevel@tonic-gate cnt++;
10397c478bd9Sstevel@tonic-gate
10407c478bd9Sstevel@tonic-gate /*
10417c478bd9Sstevel@tonic-gate * If the needed entry contains the $ORIGIN token make sure
10427c478bd9Sstevel@tonic-gate * the associated DT_1_FLAGS entry is created.
10437c478bd9Sstevel@tonic-gate */
10447c478bd9Sstevel@tonic-gate if (strstr(ifl->ifl_soname, MSG_ORIG(MSG_STR_ORIGIN))) {
10457c478bd9Sstevel@tonic-gate ofl->ofl_dtflags_1 |= DF_1_ORIGIN;
10467c478bd9Sstevel@tonic-gate ofl->ofl_dtflags |= DF_ORIGIN;
10477c478bd9Sstevel@tonic-gate }
10487c478bd9Sstevel@tonic-gate }
10497c478bd9Sstevel@tonic-gate
10507c478bd9Sstevel@tonic-gate if (unused)
10515aefb655Srie DBG_CALL(Dbg_util_nl(ofl->ofl_lml, DBG_NL_STD));
10527c478bd9Sstevel@tonic-gate
10531d9df23bSab196087 if (not_relobj) {
10547c478bd9Sstevel@tonic-gate /*
10557c478bd9Sstevel@tonic-gate * Reserve entries for any per-symbol auxiliary/filter strings.
10567c478bd9Sstevel@tonic-gate */
1057cce0e03bSab196087 cnt += alist_nitems(ofl->ofl_dtsfltrs);
10587c478bd9Sstevel@tonic-gate
10597c478bd9Sstevel@tonic-gate /*
10601d9df23bSab196087 * Reserve entries for _init() and _fini() section addresses.
10617c478bd9Sstevel@tonic-gate */
10625aefb655Srie if (((sdp = ld_sym_find(MSG_ORIG(MSG_SYM_INIT_U),
1063635216b6SRod Evans SYM_NOHASH, NULL, ofl)) != NULL) &&
10641d9df23bSab196087 (sdp->sd_ref == REF_REL_NEED) &&
10655b59e4caSab196087 (sdp->sd_sym->st_shndx != SHN_UNDEF)) {
10667c478bd9Sstevel@tonic-gate sdp->sd_flags |= FLG_SY_UPREQD;
10677c478bd9Sstevel@tonic-gate cnt++;
10687c478bd9Sstevel@tonic-gate }
10695aefb655Srie if (((sdp = ld_sym_find(MSG_ORIG(MSG_SYM_FINI_U),
1070635216b6SRod Evans SYM_NOHASH, NULL, ofl)) != NULL) &&
10711d9df23bSab196087 (sdp->sd_ref == REF_REL_NEED) &&
10725b59e4caSab196087 (sdp->sd_sym->st_shndx != SHN_UNDEF)) {
10737c478bd9Sstevel@tonic-gate sdp->sd_flags |= FLG_SY_UPREQD;
10747c478bd9Sstevel@tonic-gate cnt++;
10757c478bd9Sstevel@tonic-gate }
10767c478bd9Sstevel@tonic-gate
10777c478bd9Sstevel@tonic-gate /*
10781d9df23bSab196087 * Reserve entries for any soname, filter name (shared libs
10791d9df23bSab196087 * only), run-path pointers, cache names and audit requirements.
10807c478bd9Sstevel@tonic-gate */
10817c478bd9Sstevel@tonic-gate if (ofl->ofl_soname) {
10827c478bd9Sstevel@tonic-gate cnt++;
1083635216b6SRod Evans if (st_insert(strtbl, ofl->ofl_soname) == -1)
10847c478bd9Sstevel@tonic-gate return (S_ERROR);
10857c478bd9Sstevel@tonic-gate }
10867c478bd9Sstevel@tonic-gate if (ofl->ofl_filtees) {
10877c478bd9Sstevel@tonic-gate cnt++;
1088635216b6SRod Evans if (st_insert(strtbl, ofl->ofl_filtees) == -1)
10897c478bd9Sstevel@tonic-gate return (S_ERROR);
10907c478bd9Sstevel@tonic-gate
10917c478bd9Sstevel@tonic-gate /*
10921d9df23bSab196087 * If the filtees entry contains the $ORIGIN token
10931d9df23bSab196087 * make sure the associated DT_1_FLAGS entry is created.
10947c478bd9Sstevel@tonic-gate */
10951d9df23bSab196087 if (strstr(ofl->ofl_filtees,
10961d9df23bSab196087 MSG_ORIG(MSG_STR_ORIGIN))) {
10977c478bd9Sstevel@tonic-gate ofl->ofl_dtflags_1 |= DF_1_ORIGIN;
10987c478bd9Sstevel@tonic-gate ofl->ofl_dtflags |= DF_ORIGIN;
10997c478bd9Sstevel@tonic-gate }
11007c478bd9Sstevel@tonic-gate }
11011d9df23bSab196087 }
11021d9df23bSab196087
11037c478bd9Sstevel@tonic-gate if (ofl->ofl_rpath) {
11047c478bd9Sstevel@tonic-gate cnt += 2; /* DT_RPATH & DT_RUNPATH */
1105635216b6SRod Evans if (st_insert(strtbl, ofl->ofl_rpath) == -1)
11067c478bd9Sstevel@tonic-gate return (S_ERROR);
11077c478bd9Sstevel@tonic-gate
11087c478bd9Sstevel@tonic-gate /*
11097c478bd9Sstevel@tonic-gate * If the rpath entry contains the $ORIGIN token make sure
11107c478bd9Sstevel@tonic-gate * the associated DT_1_FLAGS entry is created.
11117c478bd9Sstevel@tonic-gate */
11127c478bd9Sstevel@tonic-gate if (strstr(ofl->ofl_rpath, MSG_ORIG(MSG_STR_ORIGIN))) {
11137c478bd9Sstevel@tonic-gate ofl->ofl_dtflags_1 |= DF_1_ORIGIN;
11147c478bd9Sstevel@tonic-gate ofl->ofl_dtflags |= DF_ORIGIN;
11157c478bd9Sstevel@tonic-gate }
11167c478bd9Sstevel@tonic-gate }
11171d9df23bSab196087
11181d9df23bSab196087 if (not_relobj) {
111957ef7aa9SRod Evans Aliste idx;
112094c044f4SRod Evans Sg_desc *sgp;
112157ef7aa9SRod Evans
11227c478bd9Sstevel@tonic-gate if (ofl->ofl_config) {
11237c478bd9Sstevel@tonic-gate cnt++;
1124635216b6SRod Evans if (st_insert(strtbl, ofl->ofl_config) == -1)
11257c478bd9Sstevel@tonic-gate return (S_ERROR);
11267c478bd9Sstevel@tonic-gate
11277c478bd9Sstevel@tonic-gate /*
11281d9df23bSab196087 * If the config entry contains the $ORIGIN token
11291d9df23bSab196087 * make sure the associated DT_1_FLAGS entry is created.
11307c478bd9Sstevel@tonic-gate */
11317c478bd9Sstevel@tonic-gate if (strstr(ofl->ofl_config, MSG_ORIG(MSG_STR_ORIGIN))) {
11327c478bd9Sstevel@tonic-gate ofl->ofl_dtflags_1 |= DF_1_ORIGIN;
11337c478bd9Sstevel@tonic-gate ofl->ofl_dtflags |= DF_ORIGIN;
11347c478bd9Sstevel@tonic-gate }
11357c478bd9Sstevel@tonic-gate }
11367c478bd9Sstevel@tonic-gate if (ofl->ofl_depaudit) {
11377c478bd9Sstevel@tonic-gate cnt++;
1138635216b6SRod Evans if (st_insert(strtbl, ofl->ofl_depaudit) == -1)
11397c478bd9Sstevel@tonic-gate return (S_ERROR);
11407c478bd9Sstevel@tonic-gate }
11417c478bd9Sstevel@tonic-gate if (ofl->ofl_audit) {
11427c478bd9Sstevel@tonic-gate cnt++;
1143635216b6SRod Evans if (st_insert(strtbl, ofl->ofl_audit) == -1)
11447c478bd9Sstevel@tonic-gate return (S_ERROR);
11457c478bd9Sstevel@tonic-gate }
11467c478bd9Sstevel@tonic-gate
11477c478bd9Sstevel@tonic-gate /*
114894c044f4SRod Evans * Reserve entries for the DT_HASH, DT_STRTAB, DT_STRSZ,
114994c044f4SRod Evans * DT_SYMTAB, DT_SYMENT, and DT_CHECKSUM.
11507c478bd9Sstevel@tonic-gate */
11517c478bd9Sstevel@tonic-gate cnt += 6;
11527c478bd9Sstevel@tonic-gate
11539039eeafSab196087 /*
11549039eeafSab196087 * If we are including local functions at the head of
11559039eeafSab196087 * the dynsym, then also reserve entries for DT_SUNW_SYMTAB
11569039eeafSab196087 * and DT_SUNW_SYMSZ.
11579039eeafSab196087 */
1158d579eb63Sab196087 if (OFL_ALLOW_LDYNSYM(ofl))
11599039eeafSab196087 cnt += 2;
11609039eeafSab196087
1161d579eb63Sab196087 if ((ofl->ofl_dynsymsortcnt > 0) ||
1162d579eb63Sab196087 (ofl->ofl_dyntlssortcnt > 0))
1163d579eb63Sab196087 cnt++; /* DT_SUNW_SORTENT */
1164d579eb63Sab196087
1165d579eb63Sab196087 if (ofl->ofl_dynsymsortcnt > 0)
1166d579eb63Sab196087 cnt += 2; /* DT_SUNW_[SYMSORT|SYMSORTSZ] */
1167d579eb63Sab196087
1168d579eb63Sab196087 if (ofl->ofl_dyntlssortcnt > 0)
1169d579eb63Sab196087 cnt += 2; /* DT_SUNW_[TLSSORT|TLSSORTSZ] */
1170d579eb63Sab196087
11717c478bd9Sstevel@tonic-gate if ((flags & (FLG_OF_VERDEF | FLG_OF_NOVERSEC)) ==
11727c478bd9Sstevel@tonic-gate FLG_OF_VERDEF)
11737c478bd9Sstevel@tonic-gate cnt += 2; /* DT_VERDEF & DT_VERDEFNUM */
11747c478bd9Sstevel@tonic-gate
11757c478bd9Sstevel@tonic-gate if ((flags & (FLG_OF_VERNEED | FLG_OF_NOVERSEC)) ==
11767c478bd9Sstevel@tonic-gate FLG_OF_VERNEED)
11777c478bd9Sstevel@tonic-gate cnt += 2; /* DT_VERNEED & DT_VERNEEDNUM */
11787c478bd9Sstevel@tonic-gate
11791d9df23bSab196087 if ((flags & FLG_OF_COMREL) && ofl->ofl_relocrelcnt)
118094c044f4SRod Evans cnt++; /* DT_RELACOUNT */
11817c478bd9Sstevel@tonic-gate
118294c044f4SRod Evans if (flags & FLG_OF_TEXTREL) /* DT_TEXTREL */
11837c478bd9Sstevel@tonic-gate cnt++;
11847c478bd9Sstevel@tonic-gate
118594c044f4SRod Evans if (ofl->ofl_osfiniarray) /* DT_FINI_ARRAY */
118694c044f4SRod Evans cnt += 2; /* DT_FINI_ARRAYSZ */
11877c478bd9Sstevel@tonic-gate
118894c044f4SRod Evans if (ofl->ofl_osinitarray) /* DT_INIT_ARRAY */
118994c044f4SRod Evans cnt += 2; /* DT_INIT_ARRAYSZ */
11907c478bd9Sstevel@tonic-gate
119194c044f4SRod Evans if (ofl->ofl_ospreinitarray) /* DT_PREINIT_ARRAY & */
119294c044f4SRod Evans cnt += 2; /* DT_PREINIT_ARRAYSZ */
11937c478bd9Sstevel@tonic-gate
11947c478bd9Sstevel@tonic-gate /*
119594c044f4SRod Evans * If we have plt's reserve a DT_PLTRELSZ, DT_PLTREL and
119694c044f4SRod Evans * DT_JMPREL.
11977c478bd9Sstevel@tonic-gate */
11987c478bd9Sstevel@tonic-gate if (ofl->ofl_pltcnt)
11997c478bd9Sstevel@tonic-gate cnt += 3;
12007c478bd9Sstevel@tonic-gate
12017c478bd9Sstevel@tonic-gate /*
120294c044f4SRod Evans * If plt padding is needed (Sparcv9).
12037c478bd9Sstevel@tonic-gate */
12047c478bd9Sstevel@tonic-gate if (ofl->ofl_pltpad)
12057c478bd9Sstevel@tonic-gate cnt += 2; /* DT_PLTPAD & DT_PLTPADSZ */
12067c478bd9Sstevel@tonic-gate
12077c478bd9Sstevel@tonic-gate /*
120894c044f4SRod Evans * If we have any relocations reserve a DT_REL, DT_RELSZ and
120994c044f4SRod Evans * DT_RELENT entry.
12107c478bd9Sstevel@tonic-gate */
12117c478bd9Sstevel@tonic-gate if (ofl->ofl_relocsz)
12127c478bd9Sstevel@tonic-gate cnt += 3;
12137c478bd9Sstevel@tonic-gate
12147c478bd9Sstevel@tonic-gate /*
121594c044f4SRod Evans * If a syminfo section is required create DT_SYMINFO,
121694c044f4SRod Evans * DT_SYMINSZ, and DT_SYMINENT entries.
12177c478bd9Sstevel@tonic-gate */
12181d9df23bSab196087 if (flags & FLG_OF_SYMINFO)
12197c478bd9Sstevel@tonic-gate cnt += 3;
12207c478bd9Sstevel@tonic-gate
12217c478bd9Sstevel@tonic-gate /*
12227c478bd9Sstevel@tonic-gate * If there are any partially initialized sections allocate
122394c044f4SRod Evans * DT_MOVETAB, DT_MOVESZ and DT_MOVEENT.
12247c478bd9Sstevel@tonic-gate */
12257c478bd9Sstevel@tonic-gate if (ofl->ofl_osmove)
12267c478bd9Sstevel@tonic-gate cnt += 3;
12277c478bd9Sstevel@tonic-gate
12287c478bd9Sstevel@tonic-gate /*
12299039eeafSab196087 * Allocate one DT_REGISTER entry for every register symbol.
12307c478bd9Sstevel@tonic-gate */
12317c478bd9Sstevel@tonic-gate cnt += ofl->ofl_regsymcnt;
12327c478bd9Sstevel@tonic-gate
12337c478bd9Sstevel@tonic-gate /*
12347c478bd9Sstevel@tonic-gate * Reserve a entry for each '-zrtldinfo=...' specified
12357c478bd9Sstevel@tonic-gate * on the command line.
12367c478bd9Sstevel@tonic-gate */
123757ef7aa9SRod Evans for (APLIST_TRAVERSE(ofl->ofl_rtldinfo, idx, sdp))
12387c478bd9Sstevel@tonic-gate cnt++;
12397c478bd9Sstevel@tonic-gate
12407c478bd9Sstevel@tonic-gate /*
124194c044f4SRod Evans * The following entry should only be placed in a segment that
124294c044f4SRod Evans * is writable.
12437c478bd9Sstevel@tonic-gate */
124494c044f4SRod Evans if (((sgp = osp->os_sgdesc) != NULL) &&
124594c044f4SRod Evans (sgp->sg_phdr.p_flags & PF_W) && ofl->ofl_osinterp)
124694c044f4SRod Evans cnt++; /* DT_DEBUG */
12477c478bd9Sstevel@tonic-gate
12487c478bd9Sstevel@tonic-gate /*
124908278a5eSRod Evans * Capabilities require a .dynamic entry for the .SUNW_cap
125008278a5eSRod Evans * section.
12517c478bd9Sstevel@tonic-gate */
12527c478bd9Sstevel@tonic-gate if (ofl->ofl_oscap)
125394c044f4SRod Evans cnt++; /* DT_SUNW_CAP */
12547c478bd9Sstevel@tonic-gate
125508278a5eSRod Evans /*
125608278a5eSRod Evans * Symbol capabilities require a .dynamic entry for the
125708278a5eSRod Evans * .SUNW_capinfo section.
125808278a5eSRod Evans */
125908278a5eSRod Evans if (ofl->ofl_oscapinfo)
126094c044f4SRod Evans cnt++; /* DT_SUNW_CAPINFO */
126108278a5eSRod Evans
126208278a5eSRod Evans /*
126308278a5eSRod Evans * Capabilities chain information requires a .SUNW_capchain
126494c044f4SRod Evans * entry (DT_SUNW_CAPCHAIN), entry size (DT_SUNW_CAPCHAINENT),
126594c044f4SRod Evans * and total size (DT_SUNW_CAPCHAINSZ).
126608278a5eSRod Evans */
126708278a5eSRod Evans if (ofl->ofl_oscapchain)
126894c044f4SRod Evans cnt += 3;
126908278a5eSRod Evans
12707c478bd9Sstevel@tonic-gate if (flags & FLG_OF_SYMBOLIC)
127194c044f4SRod Evans cnt++; /* DT_SYMBOLIC */
12721d9df23bSab196087 }
12737c478bd9Sstevel@tonic-gate
12747c478bd9Sstevel@tonic-gate /*
12755aefb655Srie * Account for Architecture dependent .dynamic entries, and defaults.
12767c478bd9Sstevel@tonic-gate */
1277ba2be530Sab196087 (*ld_targ.t_mr.mr_mach_make_dynamic)(ofl, &cnt);
12787c478bd9Sstevel@tonic-gate
12793244bcaaSab196087 /*
12803244bcaaSab196087 * DT_FLAGS, DT_FLAGS_1, DT_SUNW_STRPAD, and DT_NULL. Also,
12813244bcaaSab196087 * allow room for the unused extra DT_NULLs. These are included
12823244bcaaSab196087 * to allow an ELF editor room to add items later.
12833244bcaaSab196087 */
12843244bcaaSab196087 cnt += 4 + DYNAMIC_EXTRA_ELTS;
12857c478bd9Sstevel@tonic-gate
12867c478bd9Sstevel@tonic-gate /*
1287ba2be530Sab196087 * DT_SUNW_LDMACH. Used to hold the ELF machine code of the
1288ba2be530Sab196087 * linker that produced the output object. This information
1289ba2be530Sab196087 * allows us to determine whether a given object was linked
1290ba2be530Sab196087 * natively, or by a linker running on a different type of
1291ba2be530Sab196087 * system. This information can be valuable if one suspects
1292ba2be530Sab196087 * that a problem might be due to alignment or byte order issues.
1293ba2be530Sab196087 */
1294ba2be530Sab196087 cnt++;
1295ba2be530Sab196087
1296ba2be530Sab196087 /*
12977c478bd9Sstevel@tonic-gate * Determine the size of the section from the number of entries.
12987c478bd9Sstevel@tonic-gate */
12997c478bd9Sstevel@tonic-gate size = cnt * (size_t)shdr->sh_entsize;
13007c478bd9Sstevel@tonic-gate
13017c478bd9Sstevel@tonic-gate shdr->sh_size = (Xword)size;
13027c478bd9Sstevel@tonic-gate data->d_size = size;
13037c478bd9Sstevel@tonic-gate
13044f680cc6SAli Bahrami /*
13054f680cc6SAli Bahrami * There are several tags that are specific to the Solaris osabi
13064f680cc6SAli Bahrami * range which we unconditionally put into any dynamic section
13074f680cc6SAli Bahrami * we create (e.g. DT_SUNW_STRPAD or DT_SUNW_LDMACH). As such,
13084f680cc6SAli Bahrami * any Solaris object with a dynamic section should be tagged as
13094f680cc6SAli Bahrami * ELFOSABI_SOLARIS.
13104f680cc6SAli Bahrami */
13114f680cc6SAli Bahrami ofl->ofl_flags |= FLG_OF_OSABI;
13124f680cc6SAli Bahrami
13137c478bd9Sstevel@tonic-gate return ((uintptr_t)ofl->ofl_osdynamic);
13147c478bd9Sstevel@tonic-gate }
13157c478bd9Sstevel@tonic-gate
13167c478bd9Sstevel@tonic-gate /*
13177c478bd9Sstevel@tonic-gate * Build the GOT section and its associated relocation entries.
13187c478bd9Sstevel@tonic-gate */
13197c478bd9Sstevel@tonic-gate uintptr_t
ld_make_got(Ofl_desc * ofl)13205aefb655Srie ld_make_got(Ofl_desc *ofl)
13217c478bd9Sstevel@tonic-gate {
13227c478bd9Sstevel@tonic-gate Elf_Data *data;
1323ba2be530Sab196087 Shdr *shdr;
13247c478bd9Sstevel@tonic-gate Is_desc *isec;
1325ba2be530Sab196087 size_t size = (size_t)ofl->ofl_gotcnt * ld_targ.t_m.m_got_entsize;
13267c478bd9Sstevel@tonic-gate size_t rsize = (size_t)ofl->ofl_relocgotsz;
13277c478bd9Sstevel@tonic-gate
13289039eeafSab196087 if (new_section(ofl, SHT_PROGBITS, MSG_ORIG(MSG_SCN_GOT), 0,
13299039eeafSab196087 &isec, &shdr, &data) == S_ERROR)
13307c478bd9Sstevel@tonic-gate return (S_ERROR);
13319039eeafSab196087
13327c478bd9Sstevel@tonic-gate data->d_size = size;
13337c478bd9Sstevel@tonic-gate
13349039eeafSab196087 shdr->sh_flags |= SHF_WRITE;
13357c478bd9Sstevel@tonic-gate shdr->sh_size = (Xword)size;
1336ba2be530Sab196087 shdr->sh_entsize = ld_targ.t_m.m_got_entsize;
13377c478bd9Sstevel@tonic-gate
133869112eddSAli Bahrami ofl->ofl_osgot = ld_place_section(ofl, isec, NULL,
133969112eddSAli Bahrami ld_targ.t_id.id_got, NULL);
1340ba2be530Sab196087 if (ofl->ofl_osgot == (Os_desc *)S_ERROR)
13417c478bd9Sstevel@tonic-gate return (S_ERROR);
13427c478bd9Sstevel@tonic-gate
13437c478bd9Sstevel@tonic-gate ofl->ofl_osgot->os_szoutrels = (Xword)rsize;
13447c478bd9Sstevel@tonic-gate
13457c478bd9Sstevel@tonic-gate return (1);
13467c478bd9Sstevel@tonic-gate }
13477c478bd9Sstevel@tonic-gate
13487c478bd9Sstevel@tonic-gate /*
134970d3e49eSrie * Build an interpreter section.
13507c478bd9Sstevel@tonic-gate */
13515aefb655Srie static uintptr_t
make_interp(Ofl_desc * ofl)13527c478bd9Sstevel@tonic-gate make_interp(Ofl_desc *ofl)
13537c478bd9Sstevel@tonic-gate {
13547c478bd9Sstevel@tonic-gate Shdr *shdr;
13557c478bd9Sstevel@tonic-gate Elf_Data *data;
13567c478bd9Sstevel@tonic-gate Is_desc *isec;
13577c478bd9Sstevel@tonic-gate const char *iname = ofl->ofl_interp;
13587c478bd9Sstevel@tonic-gate size_t size;
13597c478bd9Sstevel@tonic-gate
13607c478bd9Sstevel@tonic-gate /*
136170d3e49eSrie * If -z nointerp is in effect, don't create an interpreter section.
136270d3e49eSrie */
136370d3e49eSrie if (ofl->ofl_flags1 & FLG_OF1_NOINTRP)
136470d3e49eSrie return (1);
136570d3e49eSrie
136670d3e49eSrie /*
136794c044f4SRod Evans * An .interp section is always created for a dynamic executable.
136894c044f4SRod Evans * A user can define the interpreter to use. This definition overrides
136994c044f4SRod Evans * the default that would be recorded in an executable, and triggers
137094c044f4SRod Evans * the creation of an .interp section in any other object. Presumably
137194c044f4SRod Evans * the user knows what they are doing. Refer to the generic ELF ABI
137294c044f4SRod Evans * section 5-4, and the ld(1) -I option.
13737c478bd9Sstevel@tonic-gate */
13747c478bd9Sstevel@tonic-gate if (((ofl->ofl_flags & (FLG_OF_DYNAMIC | FLG_OF_EXEC |
13757c478bd9Sstevel@tonic-gate FLG_OF_RELOBJ)) != (FLG_OF_DYNAMIC | FLG_OF_EXEC)) && !iname)
13767c478bd9Sstevel@tonic-gate return (1);
13777c478bd9Sstevel@tonic-gate
13787c478bd9Sstevel@tonic-gate /*
137994c044f4SRod Evans * In the case of a dynamic executable, supply a default interpreter
138094c044f4SRod Evans * if the user has not specified their own.
13817c478bd9Sstevel@tonic-gate */
1382ba2be530Sab196087 if (iname == NULL)
1383ba2be530Sab196087 iname = ofl->ofl_interp = ld_targ.t_m.m_def_interp;
13847c478bd9Sstevel@tonic-gate
13857c478bd9Sstevel@tonic-gate size = strlen(iname) + 1;
13867c478bd9Sstevel@tonic-gate
13879039eeafSab196087 if (new_section(ofl, SHT_PROGBITS, MSG_ORIG(MSG_SCN_INTERP), 0,
13889039eeafSab196087 &isec, &shdr, &data) == S_ERROR)
13897c478bd9Sstevel@tonic-gate return (S_ERROR);
13909039eeafSab196087
13917c478bd9Sstevel@tonic-gate data->d_size = size;
13927c478bd9Sstevel@tonic-gate shdr->sh_size = (Xword)size;
13939039eeafSab196087 data->d_align = shdr->sh_addralign = 1;
13947c478bd9Sstevel@tonic-gate
1395ba2be530Sab196087 ofl->ofl_osinterp =
139669112eddSAli Bahrami ld_place_section(ofl, isec, NULL, ld_targ.t_id.id_interp, NULL);
13977c478bd9Sstevel@tonic-gate return ((uintptr_t)ofl->ofl_osinterp);
13987c478bd9Sstevel@tonic-gate }
13997c478bd9Sstevel@tonic-gate
14007c478bd9Sstevel@tonic-gate /*
140108278a5eSRod Evans * Common function used to build the SHT_SUNW_versym section, SHT_SUNW_syminfo
140208278a5eSRod Evans * section, and SHT_SUNW_capinfo section. Each of these sections provide
140308278a5eSRod Evans * additional symbol information, and their size parallels the associated
140408278a5eSRod Evans * symbol table.
140569112eddSAli Bahrami */
140608278a5eSRod Evans static Os_desc *
make_sym_sec(Ofl_desc * ofl,const char * sectname,Word stype,int ident)140708278a5eSRod Evans make_sym_sec(Ofl_desc *ofl, const char *sectname, Word stype, int ident)
14087c478bd9Sstevel@tonic-gate {
14097c478bd9Sstevel@tonic-gate Shdr *shdr;
14107c478bd9Sstevel@tonic-gate Elf_Data *data;
14117c478bd9Sstevel@tonic-gate Is_desc *isec;
14127c478bd9Sstevel@tonic-gate
14137c478bd9Sstevel@tonic-gate /*
141408278a5eSRod Evans * We don't know the size of this section yet, so set it to 0. The
141508278a5eSRod Evans * size gets filled in after the associated symbol table is sized.
14167c478bd9Sstevel@tonic-gate */
141708278a5eSRod Evans if (new_section(ofl, stype, sectname, 0, &isec, &shdr, &data) ==
141808278a5eSRod Evans S_ERROR)
141908278a5eSRod Evans return ((Os_desc *)S_ERROR);
14207c478bd9Sstevel@tonic-gate
142108278a5eSRod Evans return (ld_place_section(ofl, isec, NULL, ident, NULL));
142269112eddSAli Bahrami }
142369112eddSAli Bahrami
142408278a5eSRod Evans /*
142508278a5eSRod Evans * Determine whether a symbol capability is redundant because the object
142608278a5eSRod Evans * capabilities are more restrictive.
142708278a5eSRod Evans */
142808278a5eSRod Evans inline static int
is_cap_redundant(Objcapset * ocapset,Objcapset * scapset)142908278a5eSRod Evans is_cap_redundant(Objcapset *ocapset, Objcapset *scapset)
143008278a5eSRod Evans {
143108278a5eSRod Evans Alist *oalp, *salp;
143208278a5eSRod Evans elfcap_mask_t omsk, smsk;
143369112eddSAli Bahrami
143408278a5eSRod Evans /*
143508278a5eSRod Evans * Inspect any platform capabilities. If the object defines platform
143608278a5eSRod Evans * capabilities, then the object will only be loaded for those
143708278a5eSRod Evans * platforms. A symbol capability set that doesn't define the same
143808278a5eSRod Evans * platforms is redundant, and a symbol capability that does not provide
143908278a5eSRod Evans * at least one platform name that matches a platform name in the object
144008278a5eSRod Evans * capabilities will never execute (as the object wouldn't have been
144108278a5eSRod Evans * loaded).
144208278a5eSRod Evans */
144308278a5eSRod Evans oalp = ocapset->oc_plat.cl_val;
144408278a5eSRod Evans salp = scapset->oc_plat.cl_val;
144508278a5eSRod Evans if (oalp && ((salp == NULL) || cap_names_match(oalp, salp)))
144608278a5eSRod Evans return (1);
144708278a5eSRod Evans
144808278a5eSRod Evans /*
144908278a5eSRod Evans * If the symbol capability set defines platforms, and the object
145008278a5eSRod Evans * doesn't, then the symbol set is more restrictive.
145108278a5eSRod Evans */
145208278a5eSRod Evans if (salp && (oalp == NULL))
145308278a5eSRod Evans return (0);
145408278a5eSRod Evans
145508278a5eSRod Evans /*
145608278a5eSRod Evans * Next, inspect any machine name capabilities. If the object defines
145708278a5eSRod Evans * machine name capabilities, then the object will only be loaded for
145808278a5eSRod Evans * those machines. A symbol capability set that doesn't define the same
145908278a5eSRod Evans * machine names is redundant, and a symbol capability that does not
146008278a5eSRod Evans * provide at least one machine name that matches a machine name in the
146108278a5eSRod Evans * object capabilities will never execute (as the object wouldn't have
146208278a5eSRod Evans * been loaded).
146308278a5eSRod Evans */
146408278a5eSRod Evans oalp = ocapset->oc_plat.cl_val;
146508278a5eSRod Evans salp = scapset->oc_plat.cl_val;
146608278a5eSRod Evans if (oalp && ((salp == NULL) || cap_names_match(oalp, salp)))
146708278a5eSRod Evans return (1);
146808278a5eSRod Evans
146908278a5eSRod Evans /*
147008278a5eSRod Evans * If the symbol capability set defines machine names, and the object
147108278a5eSRod Evans * doesn't, then the symbol set is more restrictive.
147208278a5eSRod Evans */
147308278a5eSRod Evans if (salp && (oalp == NULL))
147408278a5eSRod Evans return (0);
147508278a5eSRod Evans
147608278a5eSRod Evans /*
147708278a5eSRod Evans * Next, inspect any hardware capabilities. If the objects hardware
147808278a5eSRod Evans * capabilities are greater than or equal to that of the symbols
147908278a5eSRod Evans * capabilities, then the symbol capability set is redundant. If the
148008278a5eSRod Evans * symbols hardware capabilities are greater that the objects, then the
148108278a5eSRod Evans * symbol set is more restrictive.
148208278a5eSRod Evans *
148308278a5eSRod Evans * Note that this is a somewhat arbitrary definition, as each capability
148408278a5eSRod Evans * bit is independent of the others, and some of the higher order bits
148508278a5eSRod Evans * could be considered to be less important than lower ones. However,
148608278a5eSRod Evans * this is the only reasonable non-subjective definition.
148708278a5eSRod Evans */
148808278a5eSRod Evans omsk = ocapset->oc_hw_2.cm_val;
148908278a5eSRod Evans smsk = scapset->oc_hw_2.cm_val;
149008278a5eSRod Evans if ((omsk > smsk) || (omsk && (omsk == smsk)))
149108278a5eSRod Evans return (1);
149208278a5eSRod Evans if (omsk < smsk)
149308278a5eSRod Evans return (0);
149408278a5eSRod Evans
149508278a5eSRod Evans /*
149608278a5eSRod Evans * Finally, inspect the remaining hardware capabilities.
149708278a5eSRod Evans */
149808278a5eSRod Evans omsk = ocapset->oc_hw_1.cm_val;
149908278a5eSRod Evans smsk = scapset->oc_hw_1.cm_val;
150008278a5eSRod Evans if ((omsk > smsk) || (omsk && (omsk == smsk)))
150108278a5eSRod Evans return (1);
150208278a5eSRod Evans
150308278a5eSRod Evans return (0);
150408278a5eSRod Evans }
150508278a5eSRod Evans
150608278a5eSRod Evans /*
150708278a5eSRod Evans * Capabilities values might have been assigned excluded values. These
150808278a5eSRod Evans * excluded values should be removed before calculating any capabilities
150908278a5eSRod Evans * sections size.
151008278a5eSRod Evans */
151108278a5eSRod Evans static void
capmask_value(Lm_list * lml,Word type,Capmask * capmask,int * title)151208278a5eSRod Evans capmask_value(Lm_list *lml, Word type, Capmask *capmask, int *title)
151308278a5eSRod Evans {
151408278a5eSRod Evans /*
151508278a5eSRod Evans * First determine whether any bits should be excluded.
151608278a5eSRod Evans */
151708278a5eSRod Evans if ((capmask->cm_val & capmask->cm_exc) == 0)
151808278a5eSRod Evans return;
151908278a5eSRod Evans
152008278a5eSRod Evans DBG_CALL(Dbg_cap_post_title(lml, title));
152108278a5eSRod Evans
152208278a5eSRod Evans DBG_CALL(Dbg_cap_val_entry(lml, DBG_STATE_CURRENT, type,
152308278a5eSRod Evans capmask->cm_val, ld_targ.t_m.m_mach));
152408278a5eSRod Evans DBG_CALL(Dbg_cap_val_entry(lml, DBG_STATE_EXCLUDE, type,
152508278a5eSRod Evans capmask->cm_exc, ld_targ.t_m.m_mach));
152608278a5eSRod Evans
152708278a5eSRod Evans capmask->cm_val &= ~capmask->cm_exc;
152808278a5eSRod Evans
152908278a5eSRod Evans DBG_CALL(Dbg_cap_val_entry(lml, DBG_STATE_RESOLVED, type,
153008278a5eSRod Evans capmask->cm_val, ld_targ.t_m.m_mach));
153108278a5eSRod Evans }
153208278a5eSRod Evans
153308278a5eSRod Evans static void
capstr_value(Lm_list * lml,Word type,Caplist * caplist,int * title)153408278a5eSRod Evans capstr_value(Lm_list *lml, Word type, Caplist *caplist, int *title)
153508278a5eSRod Evans {
153608278a5eSRod Evans Aliste idx1, idx2;
153708278a5eSRod Evans char *estr;
153808278a5eSRod Evans Capstr *capstr;
153908278a5eSRod Evans Boolean found = FALSE;
154008278a5eSRod Evans
154108278a5eSRod Evans /*
154208278a5eSRod Evans * First determine whether any strings should be excluded.
154308278a5eSRod Evans */
154408278a5eSRod Evans for (APLIST_TRAVERSE(caplist->cl_exc, idx1, estr)) {
154508278a5eSRod Evans for (ALIST_TRAVERSE(caplist->cl_val, idx2, capstr)) {
154608278a5eSRod Evans if (strcmp(estr, capstr->cs_str) == 0) {
154708278a5eSRod Evans found = TRUE;
154808278a5eSRod Evans break;
154908278a5eSRod Evans }
155008278a5eSRod Evans }
155108278a5eSRod Evans }
155208278a5eSRod Evans
155308278a5eSRod Evans if (found == FALSE)
155408278a5eSRod Evans return;
155508278a5eSRod Evans
155608278a5eSRod Evans /*
155708278a5eSRod Evans * Traverse the current strings, then delete the excluded strings,
155808278a5eSRod Evans * and finally display the resolved strings.
155908278a5eSRod Evans */
156008278a5eSRod Evans if (DBG_ENABLED) {
156108278a5eSRod Evans Dbg_cap_post_title(lml, title);
156208278a5eSRod Evans for (ALIST_TRAVERSE(caplist->cl_val, idx2, capstr)) {
156308278a5eSRod Evans Dbg_cap_ptr_entry(lml, DBG_STATE_CURRENT, type,
156408278a5eSRod Evans capstr->cs_str);
156508278a5eSRod Evans }
156608278a5eSRod Evans }
156708278a5eSRod Evans for (APLIST_TRAVERSE(caplist->cl_exc, idx1, estr)) {
156808278a5eSRod Evans for (ALIST_TRAVERSE(caplist->cl_val, idx2, capstr)) {
156908278a5eSRod Evans if (strcmp(estr, capstr->cs_str) == 0) {
157008278a5eSRod Evans DBG_CALL(Dbg_cap_ptr_entry(lml,
157108278a5eSRod Evans DBG_STATE_EXCLUDE, type, capstr->cs_str));
157208278a5eSRod Evans alist_delete(caplist->cl_val, &idx2);
157308278a5eSRod Evans break;
157408278a5eSRod Evans }
157508278a5eSRod Evans }
157608278a5eSRod Evans }
157708278a5eSRod Evans if (DBG_ENABLED) {
157808278a5eSRod Evans for (ALIST_TRAVERSE(caplist->cl_val, idx2, capstr)) {
157908278a5eSRod Evans Dbg_cap_ptr_entry(lml, DBG_STATE_RESOLVED, type,
158008278a5eSRod Evans capstr->cs_str);
158108278a5eSRod Evans }
158208278a5eSRod Evans }
158308278a5eSRod Evans }
158408278a5eSRod Evans
158508278a5eSRod Evans /*
158608278a5eSRod Evans * Build a capabilities section.
158708278a5eSRod Evans */
158808278a5eSRod Evans #define CAP_UPDATE(cap, capndx, tag, val) \
158908278a5eSRod Evans cap->c_tag = tag; \
159008278a5eSRod Evans cap->c_un.c_val = val; \
159108278a5eSRod Evans cap++, capndx++;
159208278a5eSRod Evans
159308278a5eSRod Evans static uintptr_t
make_cap(Ofl_desc * ofl,Word shtype,const char * shname,int ident)159408278a5eSRod Evans make_cap(Ofl_desc *ofl, Word shtype, const char *shname, int ident)
159508278a5eSRod Evans {
159608278a5eSRod Evans Shdr *shdr;
159708278a5eSRod Evans Elf_Data *data;
159808278a5eSRod Evans Is_desc *isec;
159908278a5eSRod Evans Cap *cap;
160008278a5eSRod Evans size_t size = 0;
160108278a5eSRod Evans Word capndx = 0;
160208278a5eSRod Evans Str_tbl *strtbl;
160308278a5eSRod Evans Objcapset *ocapset = &ofl->ofl_ocapset;
160408278a5eSRod Evans Aliste idx1;
160508278a5eSRod Evans Capstr *capstr;
160608278a5eSRod Evans int title = 0;
160708278a5eSRod Evans
160808278a5eSRod Evans /*
160908278a5eSRod Evans * Determine which string table to use for any CA_SUNW_MACH,
161008278a5eSRod Evans * CA_SUNW_PLAT, or CA_SUNW_ID strings.
161108278a5eSRod Evans */
161208278a5eSRod Evans if (OFL_IS_STATIC_OBJ(ofl))
161308278a5eSRod Evans strtbl = ofl->ofl_strtab;
161408278a5eSRod Evans else
161508278a5eSRod Evans strtbl = ofl->ofl_dynstrtab;
161608278a5eSRod Evans
161708278a5eSRod Evans /*
1618d47ecb8cSRod Evans * If symbol capabilities have been requested, but none have been
1619d47ecb8cSRod Evans * created, warn the user. This scenario can occur if none of the
1620d47ecb8cSRod Evans * input relocatable objects defined any object capabilities.
1621d47ecb8cSRod Evans */
16221007fd6fSAli Bahrami if ((ofl->ofl_flags & FLG_OF_OTOSCAP) && (ofl->ofl_capsymcnt == 0))
16231007fd6fSAli Bahrami ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_CAP_NOSYMSFOUND));
1624d47ecb8cSRod Evans
1625d47ecb8cSRod Evans /*
162608278a5eSRod Evans * If symbol capabilities have been collected, but no symbols are left
162708278a5eSRod Evans * referencing these capabilities, promote the capability groups back
162808278a5eSRod Evans * to an object capability definition.
162908278a5eSRod Evans */
163008278a5eSRod Evans if ((ofl->ofl_flags & FLG_OF_OTOSCAP) && ofl->ofl_capsymcnt &&
163108278a5eSRod Evans (ofl->ofl_capfamilies == NULL)) {
16321007fd6fSAli Bahrami ld_eprintf(ofl, ERR_WARNING, MSG_INTL(MSG_CAP_NOSYMSFOUND));
163308278a5eSRod Evans ld_cap_move_symtoobj(ofl);
163408278a5eSRod Evans ofl->ofl_capsymcnt = 0;
163508278a5eSRod Evans ofl->ofl_capgroups = NULL;
1636f441771bSRod Evans ofl->ofl_flags &= ~FLG_OF_OTOSCAP;
163708278a5eSRod Evans }
163808278a5eSRod Evans
163908278a5eSRod Evans /*
164008278a5eSRod Evans * Remove any excluded capabilities.
164108278a5eSRod Evans */
164208278a5eSRod Evans capstr_value(ofl->ofl_lml, CA_SUNW_PLAT, &ocapset->oc_plat, &title);
164308278a5eSRod Evans capstr_value(ofl->ofl_lml, CA_SUNW_MACH, &ocapset->oc_mach, &title);
164408278a5eSRod Evans capmask_value(ofl->ofl_lml, CA_SUNW_HW_2, &ocapset->oc_hw_2, &title);
164508278a5eSRod Evans capmask_value(ofl->ofl_lml, CA_SUNW_HW_1, &ocapset->oc_hw_1, &title);
164608278a5eSRod Evans capmask_value(ofl->ofl_lml, CA_SUNW_SF_1, &ocapset->oc_sf_1, &title);
164708278a5eSRod Evans
164808278a5eSRod Evans /*
164908278a5eSRod Evans * Determine how many entries are required for any object capabilities.
165008278a5eSRod Evans */
165108278a5eSRod Evans size += alist_nitems(ocapset->oc_plat.cl_val);
165208278a5eSRod Evans size += alist_nitems(ocapset->oc_mach.cl_val);
165308278a5eSRod Evans if (ocapset->oc_hw_2.cm_val)
165408278a5eSRod Evans size++;
165508278a5eSRod Evans if (ocapset->oc_hw_1.cm_val)
165608278a5eSRod Evans size++;
165708278a5eSRod Evans if (ocapset->oc_sf_1.cm_val)
165808278a5eSRod Evans size++;
165908278a5eSRod Evans
166008278a5eSRod Evans /*
166108278a5eSRod Evans * Only identify a capabilities group if the group has content. If a
166208278a5eSRod Evans * capabilities identifier exists, and no other capabilities have been
166308278a5eSRod Evans * supplied, remove the identifier. This scenario could exist if a
166408278a5eSRod Evans * user mistakenly defined a lone identifier, or if an identified group
166508278a5eSRod Evans * was overridden so as to clear the existing capabilities and the
166608278a5eSRod Evans * identifier was not also cleared.
166708278a5eSRod Evans */
166808278a5eSRod Evans if (ocapset->oc_id.cs_str) {
166908278a5eSRod Evans if (size)
167008278a5eSRod Evans size++;
167108278a5eSRod Evans else
167208278a5eSRod Evans ocapset->oc_id.cs_str = NULL;
167308278a5eSRod Evans }
167408278a5eSRod Evans if (size)
167508278a5eSRod Evans size++; /* Add CA_SUNW_NULL */
167608278a5eSRod Evans
167708278a5eSRod Evans /*
167808278a5eSRod Evans * Determine how many entries are required for any symbol capabilities.
167908278a5eSRod Evans */
168008278a5eSRod Evans if (ofl->ofl_capsymcnt) {
168108278a5eSRod Evans /*
168208278a5eSRod Evans * If there are no object capabilities, a CA_SUNW_NULL entry
168308278a5eSRod Evans * is required before any symbol capabilities.
168408278a5eSRod Evans */
168508278a5eSRod Evans if (size == 0)
168608278a5eSRod Evans size++;
168708278a5eSRod Evans size += ofl->ofl_capsymcnt;
168808278a5eSRod Evans }
168908278a5eSRod Evans
169008278a5eSRod Evans if (size == 0)
169108278a5eSRod Evans return (NULL);
169208278a5eSRod Evans
169308278a5eSRod Evans if (new_section(ofl, shtype, shname, size, &isec,
169408278a5eSRod Evans &shdr, &data) == S_ERROR)
16957c478bd9Sstevel@tonic-gate return (S_ERROR);
16967c478bd9Sstevel@tonic-gate
169757ef7aa9SRod Evans if ((data->d_buf = libld_malloc(shdr->sh_size)) == NULL)
16987c478bd9Sstevel@tonic-gate return (S_ERROR);
16997c478bd9Sstevel@tonic-gate
17007c478bd9Sstevel@tonic-gate cap = (Cap *)data->d_buf;
17017c478bd9Sstevel@tonic-gate
17027c478bd9Sstevel@tonic-gate /*
170308278a5eSRod Evans * Fill in any object capabilities. If there is an identifier, then the
170408278a5eSRod Evans * identifier comes first. The remaining items follow in precedence
170508278a5eSRod Evans * order, although the order isn't important for runtime verification.
17067c478bd9Sstevel@tonic-gate */
170708278a5eSRod Evans if (ocapset->oc_id.cs_str) {
170808278a5eSRod Evans ofl->ofl_flags |= FLG_OF_CAPSTRS;
170908278a5eSRod Evans if (st_insert(strtbl, ocapset->oc_id.cs_str) == -1)
171008278a5eSRod Evans return (S_ERROR);
171108278a5eSRod Evans ocapset->oc_id.cs_ndx = capndx;
171208278a5eSRod Evans CAP_UPDATE(cap, capndx, CA_SUNW_ID, 0);
17137c478bd9Sstevel@tonic-gate }
171408278a5eSRod Evans if (ocapset->oc_plat.cl_val) {
171508278a5eSRod Evans ofl->ofl_flags |= (FLG_OF_PTCAP | FLG_OF_CAPSTRS);
171608278a5eSRod Evans
171708278a5eSRod Evans /*
171808278a5eSRod Evans * Insert any platform name strings in the appropriate string
171908278a5eSRod Evans * table. The capability value can't be filled in yet, as the
172008278a5eSRod Evans * final offset of the strings isn't known until later.
172108278a5eSRod Evans */
172208278a5eSRod Evans for (ALIST_TRAVERSE(ocapset->oc_plat.cl_val, idx1, capstr)) {
172308278a5eSRod Evans if (st_insert(strtbl, capstr->cs_str) == -1)
172408278a5eSRod Evans return (S_ERROR);
172508278a5eSRod Evans capstr->cs_ndx = capndx;
172608278a5eSRod Evans CAP_UPDATE(cap, capndx, CA_SUNW_PLAT, 0);
172708278a5eSRod Evans }
172808278a5eSRod Evans }
172908278a5eSRod Evans if (ocapset->oc_mach.cl_val) {
173008278a5eSRod Evans ofl->ofl_flags |= (FLG_OF_PTCAP | FLG_OF_CAPSTRS);
173108278a5eSRod Evans
173208278a5eSRod Evans /*
173308278a5eSRod Evans * Insert the machine name strings in the appropriate string
173408278a5eSRod Evans * table. The capability value can't be filled in yet, as the
173508278a5eSRod Evans * final offset of the strings isn't known until later.
173608278a5eSRod Evans */
173708278a5eSRod Evans for (ALIST_TRAVERSE(ocapset->oc_mach.cl_val, idx1, capstr)) {
173808278a5eSRod Evans if (st_insert(strtbl, capstr->cs_str) == -1)
173908278a5eSRod Evans return (S_ERROR);
174008278a5eSRod Evans capstr->cs_ndx = capndx;
174108278a5eSRod Evans CAP_UPDATE(cap, capndx, CA_SUNW_MACH, 0);
174208278a5eSRod Evans }
174308278a5eSRod Evans }
174408278a5eSRod Evans if (ocapset->oc_hw_2.cm_val) {
174508278a5eSRod Evans ofl->ofl_flags |= FLG_OF_PTCAP;
174608278a5eSRod Evans CAP_UPDATE(cap, capndx, CA_SUNW_HW_2, ocapset->oc_hw_2.cm_val);
174708278a5eSRod Evans }
174808278a5eSRod Evans if (ocapset->oc_hw_1.cm_val) {
174908278a5eSRod Evans ofl->ofl_flags |= FLG_OF_PTCAP;
175008278a5eSRod Evans CAP_UPDATE(cap, capndx, CA_SUNW_HW_1, ocapset->oc_hw_1.cm_val);
175108278a5eSRod Evans }
175208278a5eSRod Evans if (ocapset->oc_sf_1.cm_val) {
175308278a5eSRod Evans ofl->ofl_flags |= FLG_OF_PTCAP;
175408278a5eSRod Evans CAP_UPDATE(cap, capndx, CA_SUNW_SF_1, ocapset->oc_sf_1.cm_val);
175508278a5eSRod Evans }
175608278a5eSRod Evans CAP_UPDATE(cap, capndx, CA_SUNW_NULL, 0);
175708278a5eSRod Evans
175808278a5eSRod Evans /*
175908278a5eSRod Evans * Fill in any symbol capabilities.
176008278a5eSRod Evans */
176108278a5eSRod Evans if (ofl->ofl_capgroups) {
176208278a5eSRod Evans Cap_group *cgp;
176308278a5eSRod Evans
176408278a5eSRod Evans for (APLIST_TRAVERSE(ofl->ofl_capgroups, idx1, cgp)) {
176508278a5eSRod Evans Objcapset *scapset = &cgp->cg_set;
176608278a5eSRod Evans Aliste idx2;
176708278a5eSRod Evans Is_desc *isp;
176808278a5eSRod Evans
176908278a5eSRod Evans cgp->cg_ndx = capndx;
177008278a5eSRod Evans
177108278a5eSRod Evans if (scapset->oc_id.cs_str) {
177208278a5eSRod Evans ofl->ofl_flags |= FLG_OF_CAPSTRS;
177308278a5eSRod Evans /*
177408278a5eSRod Evans * Insert the identifier string in the
177508278a5eSRod Evans * appropriate string table. The capability
177608278a5eSRod Evans * value can't be filled in yet, as the final
177708278a5eSRod Evans * offset of the string isn't known until later.
177808278a5eSRod Evans */
177908278a5eSRod Evans if (st_insert(strtbl,
178008278a5eSRod Evans scapset->oc_id.cs_str) == -1)
178108278a5eSRod Evans return (S_ERROR);
178208278a5eSRod Evans scapset->oc_id.cs_ndx = capndx;
178308278a5eSRod Evans CAP_UPDATE(cap, capndx, CA_SUNW_ID, 0);
178408278a5eSRod Evans }
178508278a5eSRod Evans
178608278a5eSRod Evans if (scapset->oc_plat.cl_val) {
178708278a5eSRod Evans ofl->ofl_flags |= FLG_OF_CAPSTRS;
178808278a5eSRod Evans
178908278a5eSRod Evans /*
179008278a5eSRod Evans * Insert the platform name string in the
179108278a5eSRod Evans * appropriate string table. The capability
179208278a5eSRod Evans * value can't be filled in yet, as the final
179308278a5eSRod Evans * offset of the string isn't known until later.
179408278a5eSRod Evans */
179508278a5eSRod Evans for (ALIST_TRAVERSE(scapset->oc_plat.cl_val,
179608278a5eSRod Evans idx2, capstr)) {
179708278a5eSRod Evans if (st_insert(strtbl,
179808278a5eSRod Evans capstr->cs_str) == -1)
179908278a5eSRod Evans return (S_ERROR);
180008278a5eSRod Evans capstr->cs_ndx = capndx;
180108278a5eSRod Evans CAP_UPDATE(cap, capndx,
180208278a5eSRod Evans CA_SUNW_PLAT, 0);
180308278a5eSRod Evans }
180408278a5eSRod Evans }
180508278a5eSRod Evans if (scapset->oc_mach.cl_val) {
180608278a5eSRod Evans ofl->ofl_flags |= FLG_OF_CAPSTRS;
180708278a5eSRod Evans
180808278a5eSRod Evans /*
180908278a5eSRod Evans * Insert the machine name string in the
181008278a5eSRod Evans * appropriate string table. The capability
181108278a5eSRod Evans * value can't be filled in yet, as the final
181208278a5eSRod Evans * offset of the string isn't known until later.
181308278a5eSRod Evans */
181408278a5eSRod Evans for (ALIST_TRAVERSE(scapset->oc_mach.cl_val,
181508278a5eSRod Evans idx2, capstr)) {
181608278a5eSRod Evans if (st_insert(strtbl,
181708278a5eSRod Evans capstr->cs_str) == -1)
181808278a5eSRod Evans return (S_ERROR);
181908278a5eSRod Evans capstr->cs_ndx = capndx;
182008278a5eSRod Evans CAP_UPDATE(cap, capndx,
182108278a5eSRod Evans CA_SUNW_MACH, 0);
182208278a5eSRod Evans }
182308278a5eSRod Evans }
182408278a5eSRod Evans if (scapset->oc_hw_2.cm_val) {
182508278a5eSRod Evans CAP_UPDATE(cap, capndx, CA_SUNW_HW_2,
182608278a5eSRod Evans scapset->oc_hw_2.cm_val);
182708278a5eSRod Evans }
182808278a5eSRod Evans if (scapset->oc_hw_1.cm_val) {
182908278a5eSRod Evans CAP_UPDATE(cap, capndx, CA_SUNW_HW_1,
183008278a5eSRod Evans scapset->oc_hw_1.cm_val);
183108278a5eSRod Evans }
183208278a5eSRod Evans if (scapset->oc_sf_1.cm_val) {
183308278a5eSRod Evans CAP_UPDATE(cap, capndx, CA_SUNW_SF_1,
183408278a5eSRod Evans scapset->oc_sf_1.cm_val);
183508278a5eSRod Evans }
183608278a5eSRod Evans CAP_UPDATE(cap, capndx, CA_SUNW_NULL, 0);
183708278a5eSRod Evans
183808278a5eSRod Evans /*
183908278a5eSRod Evans * If any object capabilities are available, determine
184008278a5eSRod Evans * whether these symbol capabilities are less
184108278a5eSRod Evans * restrictive, and hence redundant.
184208278a5eSRod Evans */
184308278a5eSRod Evans if (((ofl->ofl_flags & FLG_OF_PTCAP) == 0) ||
184408278a5eSRod Evans (is_cap_redundant(ocapset, scapset) == 0))
184508278a5eSRod Evans continue;
184608278a5eSRod Evans
184708278a5eSRod Evans /*
184808278a5eSRod Evans * Indicate any files that provide redundant symbol
184908278a5eSRod Evans * capabilities.
185008278a5eSRod Evans */
185108278a5eSRod Evans for (APLIST_TRAVERSE(cgp->cg_secs, idx2, isp)) {
18521007fd6fSAli Bahrami ld_eprintf(ofl, ERR_WARNING,
185308278a5eSRod Evans MSG_INTL(MSG_CAP_REDUNDANT),
185408278a5eSRod Evans isp->is_file->ifl_name,
185508278a5eSRod Evans EC_WORD(isp->is_scnndx), isp->is_name);
185608278a5eSRod Evans }
185708278a5eSRod Evans }
185808278a5eSRod Evans }
185908278a5eSRod Evans
186008278a5eSRod Evans /*
186108278a5eSRod Evans * If capabilities strings are required, the sh_info field of the
186208278a5eSRod Evans * section header will be set to the associated string table.
186308278a5eSRod Evans */
186408278a5eSRod Evans if (ofl->ofl_flags & FLG_OF_CAPSTRS)
186508278a5eSRod Evans shdr->sh_flags |= SHF_INFO_LINK;
186608278a5eSRod Evans
186708278a5eSRod Evans /*
186808278a5eSRod Evans * Place these capabilities in the output file.
186908278a5eSRod Evans */
187008278a5eSRod Evans if ((ofl->ofl_oscap = ld_place_section(ofl, isec,
187108278a5eSRod Evans NULL, ident, NULL)) == (Os_desc *)S_ERROR)
187208278a5eSRod Evans return (S_ERROR);
187308278a5eSRod Evans
187408278a5eSRod Evans /*
187508278a5eSRod Evans * If symbol capabilities are required, then a .SUNW_capinfo section is
187608278a5eSRod Evans * also created. This table will eventually be sized to match the
187708278a5eSRod Evans * associated symbol table.
187808278a5eSRod Evans */
187908278a5eSRod Evans if (ofl->ofl_capfamilies) {
188008278a5eSRod Evans if ((ofl->ofl_oscapinfo = make_sym_sec(ofl,
188108278a5eSRod Evans MSG_ORIG(MSG_SCN_SUNWCAPINFO), SHT_SUNW_capinfo,
188208278a5eSRod Evans ld_targ.t_id.id_capinfo)) == (Os_desc *)S_ERROR)
188308278a5eSRod Evans return (S_ERROR);
188408278a5eSRod Evans
188508278a5eSRod Evans /*
188608278a5eSRod Evans * If we're generating a dynamic object, capabilities family
188708278a5eSRod Evans * members are maintained in a .SUNW_capchain section.
188808278a5eSRod Evans */
188908278a5eSRod Evans if (ofl->ofl_capchaincnt &&
189008278a5eSRod Evans ((ofl->ofl_flags & FLG_OF_RELOBJ) == 0)) {
189108278a5eSRod Evans if (new_section(ofl, SHT_SUNW_capchain,
189208278a5eSRod Evans MSG_ORIG(MSG_SCN_SUNWCAPCHAIN),
189308278a5eSRod Evans ofl->ofl_capchaincnt, &isec, &shdr,
189408278a5eSRod Evans &data) == S_ERROR)
189508278a5eSRod Evans return (S_ERROR);
189608278a5eSRod Evans
189708278a5eSRod Evans ofl->ofl_oscapchain = ld_place_section(ofl, isec,
189808278a5eSRod Evans NULL, ld_targ.t_id.id_capchain, NULL);
189908278a5eSRod Evans if (ofl->ofl_oscapchain == (Os_desc *)S_ERROR)
190008278a5eSRod Evans return (S_ERROR);
190108278a5eSRod Evans
190208278a5eSRod Evans }
190308278a5eSRod Evans }
190408278a5eSRod Evans return (1);
190508278a5eSRod Evans }
190608278a5eSRod Evans #undef CAP_UPDATE
19077c478bd9Sstevel@tonic-gate
19087c478bd9Sstevel@tonic-gate /*
19097c478bd9Sstevel@tonic-gate * Build the PLT section and its associated relocation entries.
19107c478bd9Sstevel@tonic-gate */
19115aefb655Srie static uintptr_t
make_plt(Ofl_desc * ofl)19127c478bd9Sstevel@tonic-gate make_plt(Ofl_desc *ofl)
19137c478bd9Sstevel@tonic-gate {
19147c478bd9Sstevel@tonic-gate Shdr *shdr;
19157c478bd9Sstevel@tonic-gate Elf_Data *data;
19167c478bd9Sstevel@tonic-gate Is_desc *isec;
1917ba2be530Sab196087 size_t size = ld_targ.t_m.m_plt_reservsz +
191860758829Srie (((size_t)ofl->ofl_pltcnt + (size_t)ofl->ofl_pltpad) *
1919ba2be530Sab196087 ld_targ.t_m.m_plt_entsize);
19207c478bd9Sstevel@tonic-gate size_t rsize = (size_t)ofl->ofl_relocpltsz;
19217c478bd9Sstevel@tonic-gate
19227c478bd9Sstevel@tonic-gate /*
1923ba2be530Sab196087 * On sparc, account for the NOP at the end of the plt.
19247c478bd9Sstevel@tonic-gate */
1925ba2be530Sab196087 if (ld_targ.t_m.m_mach == LD_TARG_BYCLASS(EM_SPARC, EM_SPARCV9))
19267c478bd9Sstevel@tonic-gate size += sizeof (Word);
19277c478bd9Sstevel@tonic-gate
19289039eeafSab196087 if (new_section(ofl, SHT_PROGBITS, MSG_ORIG(MSG_SCN_PLT), 0,
19299039eeafSab196087 &isec, &shdr, &data) == S_ERROR)
19307c478bd9Sstevel@tonic-gate return (S_ERROR);
19319039eeafSab196087
19327c478bd9Sstevel@tonic-gate data->d_size = size;
1933ba2be530Sab196087 data->d_align = ld_targ.t_m.m_plt_align;
19347c478bd9Sstevel@tonic-gate
1935ba2be530Sab196087 shdr->sh_flags = ld_targ.t_m.m_plt_shf_flags;
19367c478bd9Sstevel@tonic-gate shdr->sh_size = (Xword)size;
1937ba2be530Sab196087 shdr->sh_addralign = ld_targ.t_m.m_plt_align;
1938ba2be530Sab196087 shdr->sh_entsize = ld_targ.t_m.m_plt_entsize;
19397c478bd9Sstevel@tonic-gate
194069112eddSAli Bahrami ofl->ofl_osplt = ld_place_section(ofl, isec, NULL,
194169112eddSAli Bahrami ld_targ.t_id.id_plt, NULL);
1942ba2be530Sab196087 if (ofl->ofl_osplt == (Os_desc *)S_ERROR)
19437c478bd9Sstevel@tonic-gate return (S_ERROR);
19447c478bd9Sstevel@tonic-gate
19457c478bd9Sstevel@tonic-gate ofl->ofl_osplt->os_szoutrels = (Xword)rsize;
19467c478bd9Sstevel@tonic-gate
19477c478bd9Sstevel@tonic-gate return (1);
19487c478bd9Sstevel@tonic-gate }
19497c478bd9Sstevel@tonic-gate
19507c478bd9Sstevel@tonic-gate /*
19517c478bd9Sstevel@tonic-gate * Make the hash table. Only built for dynamic executables and shared
19527c478bd9Sstevel@tonic-gate * libraries, and provides hashed lookup into the global symbol table
19537c478bd9Sstevel@tonic-gate * (.dynsym) for the run-time linker to resolve symbol lookups.
19547c478bd9Sstevel@tonic-gate */
19555aefb655Srie static uintptr_t
make_hash(Ofl_desc * ofl)19567c478bd9Sstevel@tonic-gate make_hash(Ofl_desc *ofl)
19577c478bd9Sstevel@tonic-gate {
19587c478bd9Sstevel@tonic-gate Shdr *shdr;
19597c478bd9Sstevel@tonic-gate Elf_Data *data;
19607c478bd9Sstevel@tonic-gate Is_desc *isec;
19617c478bd9Sstevel@tonic-gate size_t size;
19627c478bd9Sstevel@tonic-gate Word nsyms = ofl->ofl_globcnt;
19637c478bd9Sstevel@tonic-gate size_t cnt;
19647c478bd9Sstevel@tonic-gate
19657c478bd9Sstevel@tonic-gate /*
19669039eeafSab196087 * Allocate section header structures. We set entcnt to 0
19679039eeafSab196087 * because it's going to change after we place this section.
19687c478bd9Sstevel@tonic-gate */
19699039eeafSab196087 if (new_section(ofl, SHT_HASH, MSG_ORIG(MSG_SCN_HASH), 0,
19709039eeafSab196087 &isec, &shdr, &data) == S_ERROR)
19717c478bd9Sstevel@tonic-gate return (S_ERROR);
19727c478bd9Sstevel@tonic-gate
19737c478bd9Sstevel@tonic-gate /*
19747c478bd9Sstevel@tonic-gate * Place the section first since it will affect the local symbol
19757c478bd9Sstevel@tonic-gate * count.
19767c478bd9Sstevel@tonic-gate */
19771dd9d86fSAli Bahrami ofl->ofl_oshash =
197869112eddSAli Bahrami ld_place_section(ofl, isec, NULL, ld_targ.t_id.id_hash, NULL);
1979ba2be530Sab196087 if (ofl->ofl_oshash == (Os_desc *)S_ERROR)
19807c478bd9Sstevel@tonic-gate return (S_ERROR);
19817c478bd9Sstevel@tonic-gate
19827c478bd9Sstevel@tonic-gate /*
19837c478bd9Sstevel@tonic-gate * Calculate the number of output hash buckets.
19847c478bd9Sstevel@tonic-gate */
19857c478bd9Sstevel@tonic-gate ofl->ofl_hashbkts = findprime(nsyms);
19867c478bd9Sstevel@tonic-gate
19877c478bd9Sstevel@tonic-gate /*
19887c478bd9Sstevel@tonic-gate * The size of the hash table is determined by
19897c478bd9Sstevel@tonic-gate *
19907c478bd9Sstevel@tonic-gate * i. the initial nbucket and nchain entries (2)
19917c478bd9Sstevel@tonic-gate * ii. the number of buckets (calculated above)
19927c478bd9Sstevel@tonic-gate * iii. the number of chains (this is based on the number of
1993635216b6SRod Evans * symbols in the .dynsym array).
19947c478bd9Sstevel@tonic-gate */
1995635216b6SRod Evans cnt = 2 + ofl->ofl_hashbkts + DYNSYM_ALL_CNT(ofl);
19967c478bd9Sstevel@tonic-gate size = cnt * shdr->sh_entsize;
19977c478bd9Sstevel@tonic-gate
19987c478bd9Sstevel@tonic-gate /*
19997c478bd9Sstevel@tonic-gate * Finalize the section header and data buffer initialization.
20007c478bd9Sstevel@tonic-gate */
200157ef7aa9SRod Evans if ((data->d_buf = libld_calloc(size, 1)) == NULL)
20027c478bd9Sstevel@tonic-gate return (S_ERROR);
20037c478bd9Sstevel@tonic-gate data->d_size = size;
20047c478bd9Sstevel@tonic-gate shdr->sh_size = (Xword)size;
20057c478bd9Sstevel@tonic-gate
20067c478bd9Sstevel@tonic-gate return (1);
20077c478bd9Sstevel@tonic-gate }
20087c478bd9Sstevel@tonic-gate
20097c478bd9Sstevel@tonic-gate /*
20107c478bd9Sstevel@tonic-gate * Generate the standard symbol table. Contains all locals and globals,
20117c478bd9Sstevel@tonic-gate * and resides in a non-allocatable section (ie. it can be stripped).
20127c478bd9Sstevel@tonic-gate */
20135aefb655Srie static uintptr_t
make_symtab(Ofl_desc * ofl)20147c478bd9Sstevel@tonic-gate make_symtab(Ofl_desc *ofl)
20157c478bd9Sstevel@tonic-gate {
20167c478bd9Sstevel@tonic-gate Shdr *shdr;
20177c478bd9Sstevel@tonic-gate Elf_Data *data;
20187c478bd9Sstevel@tonic-gate Is_desc *isec;
20197c478bd9Sstevel@tonic-gate Is_desc *xisec = 0;
20207c478bd9Sstevel@tonic-gate size_t size;
20217c478bd9Sstevel@tonic-gate Word symcnt;
20227c478bd9Sstevel@tonic-gate
20237c478bd9Sstevel@tonic-gate /*
20249039eeafSab196087 * Create the section headers. Note that we supply an ent_cnt
20259039eeafSab196087 * of 0. We won't know the count until the section has been placed.
20267c478bd9Sstevel@tonic-gate */
20279039eeafSab196087 if (new_section(ofl, SHT_SYMTAB, MSG_ORIG(MSG_SCN_SYMTAB), 0,
20289039eeafSab196087 &isec, &shdr, &data) == S_ERROR)
20297c478bd9Sstevel@tonic-gate return (S_ERROR);
20307c478bd9Sstevel@tonic-gate
20317c478bd9Sstevel@tonic-gate /*
20327c478bd9Sstevel@tonic-gate * Place the section first since it will affect the local symbol
20337c478bd9Sstevel@tonic-gate * count.
20347c478bd9Sstevel@tonic-gate */
203569112eddSAli Bahrami if ((ofl->ofl_ossymtab = ld_place_section(ofl, isec, NULL,
2036635216b6SRod Evans ld_targ.t_id.id_symtab, NULL)) == (Os_desc *)S_ERROR)
20377c478bd9Sstevel@tonic-gate return (S_ERROR);
20387c478bd9Sstevel@tonic-gate
20397c478bd9Sstevel@tonic-gate /*
20407c478bd9Sstevel@tonic-gate * At this point we've created all but the 'shstrtab' section.
20417c478bd9Sstevel@tonic-gate * Determine if we have to use 'Extended Sections'. If so - then
20427c478bd9Sstevel@tonic-gate * also create a SHT_SYMTAB_SHNDX section.
20437c478bd9Sstevel@tonic-gate */
20447c478bd9Sstevel@tonic-gate if ((ofl->ofl_shdrcnt + 1) >= SHN_LORESERVE) {
20457c478bd9Sstevel@tonic-gate Shdr *xshdr;
20467c478bd9Sstevel@tonic-gate Elf_Data *xdata;
20477c478bd9Sstevel@tonic-gate
20489039eeafSab196087 if (new_section(ofl, SHT_SYMTAB_SHNDX,
20499039eeafSab196087 MSG_ORIG(MSG_SCN_SYMTAB_SHNDX), 0, &xisec,
20509039eeafSab196087 &xshdr, &xdata) == S_ERROR)
20517c478bd9Sstevel@tonic-gate return (S_ERROR);
20529039eeafSab196087
205369112eddSAli Bahrami if ((ofl->ofl_ossymshndx = ld_place_section(ofl, xisec, NULL,
20541dd9d86fSAli Bahrami ld_targ.t_id.id_symtab_ndx, NULL)) == (Os_desc *)S_ERROR)
20557c478bd9Sstevel@tonic-gate return (S_ERROR);
20567c478bd9Sstevel@tonic-gate }
20570e233487SRod Evans
20587c478bd9Sstevel@tonic-gate /*
20597c478bd9Sstevel@tonic-gate * Calculated number of symbols, which need to be augmented by
2060635216b6SRod Evans * the (yet to be created) .shstrtab entry.
20617c478bd9Sstevel@tonic-gate */
2062635216b6SRod Evans symcnt = (size_t)(1 + SYMTAB_ALL_CNT(ofl));
20637c478bd9Sstevel@tonic-gate size = symcnt * shdr->sh_entsize;
20647c478bd9Sstevel@tonic-gate
20657c478bd9Sstevel@tonic-gate /*
20667c478bd9Sstevel@tonic-gate * Finalize the section header and data buffer initialization.
20677c478bd9Sstevel@tonic-gate */
20687c478bd9Sstevel@tonic-gate data->d_size = size;
20697c478bd9Sstevel@tonic-gate shdr->sh_size = (Xword)size;
20707c478bd9Sstevel@tonic-gate
20717c478bd9Sstevel@tonic-gate /*
20727c478bd9Sstevel@tonic-gate * If we created a SHT_SYMTAB_SHNDX - then set it's sizes too.
20737c478bd9Sstevel@tonic-gate */
20747c478bd9Sstevel@tonic-gate if (xisec) {
20757c478bd9Sstevel@tonic-gate size_t xsize = symcnt * sizeof (Word);
20767c478bd9Sstevel@tonic-gate
20777c478bd9Sstevel@tonic-gate xisec->is_indata->d_size = xsize;
20787c478bd9Sstevel@tonic-gate xisec->is_shdr->sh_size = (Xword)xsize;
20797c478bd9Sstevel@tonic-gate }
20807c478bd9Sstevel@tonic-gate
20817c478bd9Sstevel@tonic-gate return (1);
20827c478bd9Sstevel@tonic-gate }
20837c478bd9Sstevel@tonic-gate
20847c478bd9Sstevel@tonic-gate /*
2085d579eb63Sab196087 * Build a dynamic symbol table. These tables reside in the text
2086d579eb63Sab196087 * segment of a dynamic executable or shared library.
2087d579eb63Sab196087 *
2088d579eb63Sab196087 * .SUNW_ldynsym contains local function symbols
2089d579eb63Sab196087 * .dynsym contains only globals symbols
2090d579eb63Sab196087 *
2091d579eb63Sab196087 * The two tables are created adjacent to each other, with .SUNW_ldynsym
2092d579eb63Sab196087 * coming first.
20937c478bd9Sstevel@tonic-gate */
20945aefb655Srie static uintptr_t
make_dynsym(Ofl_desc * ofl)20957c478bd9Sstevel@tonic-gate make_dynsym(Ofl_desc *ofl)
20967c478bd9Sstevel@tonic-gate {
20979039eeafSab196087 Shdr *shdr, *lshdr;
20989039eeafSab196087 Elf_Data *data, *ldata;
20999039eeafSab196087 Is_desc *isec, *lisec;
21007c478bd9Sstevel@tonic-gate size_t size;
21017c478bd9Sstevel@tonic-gate Xword cnt;
2102d579eb63Sab196087 int allow_ldynsym;
21039039eeafSab196087
2104d579eb63Sab196087 /*
2105d579eb63Sab196087 * Unless explicitly disabled, always produce a .SUNW_ldynsym section
2106d579eb63Sab196087 * when it is allowed by the file type, even if the resulting
2107d579eb63Sab196087 * table only ends up with a single STT_FILE in it. There are
2108d579eb63Sab196087 * two reasons: (1) It causes the generation of the DT_SUNW_SYMTAB
2109d579eb63Sab196087 * entry in the .dynamic section, which is something we would
2110d579eb63Sab196087 * like to encourage, and (2) Without it, we cannot generate
2111d579eb63Sab196087 * the associated .SUNW_dyn[sym|tls]sort sections, which are of
2112d579eb63Sab196087 * value to DTrace.
2113d579eb63Sab196087 *
2114d579eb63Sab196087 * In practice, it is extremely rare for an object not to have
2115d579eb63Sab196087 * local symbols for .SUNW_ldynsym, so 99% of the time, we'd be
2116d579eb63Sab196087 * doing it anyway.
2117d579eb63Sab196087 */
2118d579eb63Sab196087 allow_ldynsym = OFL_ALLOW_LDYNSYM(ofl);
21197c478bd9Sstevel@tonic-gate
21207c478bd9Sstevel@tonic-gate /*
21219039eeafSab196087 * Create the section headers. Note that we supply an ent_cnt
21229039eeafSab196087 * of 0. We won't know the count until the section has been placed.
21237c478bd9Sstevel@tonic-gate */
2124d579eb63Sab196087 if (allow_ldynsym && new_section(ofl, SHT_SUNW_LDYNSYM,
21259039eeafSab196087 MSG_ORIG(MSG_SCN_LDYNSYM), 0, &lisec, &lshdr, &ldata) == S_ERROR)
21267c478bd9Sstevel@tonic-gate return (S_ERROR);
21279039eeafSab196087
21289039eeafSab196087 if (new_section(ofl, SHT_DYNSYM, MSG_ORIG(MSG_SCN_DYNSYM), 0,
21299039eeafSab196087 &isec, &shdr, &data) == S_ERROR)
21309039eeafSab196087 return (S_ERROR);
21317c478bd9Sstevel@tonic-gate
21327c478bd9Sstevel@tonic-gate /*
21339039eeafSab196087 * Place the section(s) first since it will affect the local symbol
21347c478bd9Sstevel@tonic-gate * count.
21357c478bd9Sstevel@tonic-gate */
2136d579eb63Sab196087 if (allow_ldynsym &&
213769112eddSAli Bahrami ((ofl->ofl_osldynsym = ld_place_section(ofl, lisec, NULL,
21381dd9d86fSAli Bahrami ld_targ.t_id.id_ldynsym, NULL)) == (Os_desc *)S_ERROR))
21399039eeafSab196087 return (S_ERROR);
2140ba2be530Sab196087 ofl->ofl_osdynsym =
214169112eddSAli Bahrami ld_place_section(ofl, isec, NULL, ld_targ.t_id.id_dynsym, NULL);
2142ba2be530Sab196087 if (ofl->ofl_osdynsym == (Os_desc *)S_ERROR)
21437c478bd9Sstevel@tonic-gate return (S_ERROR);
21447c478bd9Sstevel@tonic-gate
2145635216b6SRod Evans cnt = DYNSYM_ALL_CNT(ofl);
21467c478bd9Sstevel@tonic-gate size = (size_t)cnt * shdr->sh_entsize;
21477c478bd9Sstevel@tonic-gate
21487c478bd9Sstevel@tonic-gate /*
21497c478bd9Sstevel@tonic-gate * Finalize the section header and data buffer initialization.
21507c478bd9Sstevel@tonic-gate */
21517c478bd9Sstevel@tonic-gate data->d_size = size;
21527c478bd9Sstevel@tonic-gate shdr->sh_size = (Xword)size;
21537c478bd9Sstevel@tonic-gate
21549039eeafSab196087 /*
21559039eeafSab196087 * An ldynsym contains local function symbols. It is not
21569039eeafSab196087 * used for linking, but if present, serves to allow better
21579039eeafSab196087 * stack traces to be generated in contexts where the symtab
21589039eeafSab196087 * is not available. (dladdr(), or stripped executable/library files).
21599039eeafSab196087 */
2160d579eb63Sab196087 if (allow_ldynsym) {
21619039eeafSab196087 cnt = 1 + ofl->ofl_dynlocscnt + ofl->ofl_dynscopecnt;
21629039eeafSab196087 size = (size_t)cnt * shdr->sh_entsize;
21639039eeafSab196087
21649039eeafSab196087 ldata->d_size = size;
21659039eeafSab196087 lshdr->sh_size = (Xword)size;
21669039eeafSab196087 }
21679039eeafSab196087
21687c478bd9Sstevel@tonic-gate return (1);
21697c478bd9Sstevel@tonic-gate }
21707c478bd9Sstevel@tonic-gate
21717c478bd9Sstevel@tonic-gate /*
2172d579eb63Sab196087 * Build .SUNW_dynsymsort and/or .SUNW_dyntlssort sections. These are
2173d579eb63Sab196087 * index sections for the .SUNW_ldynsym/.dynsym pair that present data
2174d579eb63Sab196087 * and function symbols sorted by address.
2175d579eb63Sab196087 */
2176d579eb63Sab196087 static uintptr_t
make_dynsort(Ofl_desc * ofl)2177d579eb63Sab196087 make_dynsort(Ofl_desc *ofl)
2178d579eb63Sab196087 {
2179d579eb63Sab196087 Shdr *shdr;
2180d579eb63Sab196087 Elf_Data *data;
2181d579eb63Sab196087 Is_desc *isec;
2182d579eb63Sab196087
2183d579eb63Sab196087 /* Only do it if the .SUNW_ldynsym section is present */
2184d579eb63Sab196087 if (!OFL_ALLOW_LDYNSYM(ofl))
2185d579eb63Sab196087 return (1);
2186d579eb63Sab196087
2187d579eb63Sab196087 /* .SUNW_dynsymsort */
2188d579eb63Sab196087 if (ofl->ofl_dynsymsortcnt > 0) {
2189d579eb63Sab196087 if (new_section(ofl, SHT_SUNW_symsort,
2190d579eb63Sab196087 MSG_ORIG(MSG_SCN_DYNSYMSORT), ofl->ofl_dynsymsortcnt,
2191d579eb63Sab196087 &isec, &shdr, &data) == S_ERROR)
2192d579eb63Sab196087 return (S_ERROR);
2193d579eb63Sab196087
219469112eddSAli Bahrami if ((ofl->ofl_osdynsymsort = ld_place_section(ofl, isec, NULL,
21951dd9d86fSAli Bahrami ld_targ.t_id.id_dynsort, NULL)) == (Os_desc *)S_ERROR)
2196d579eb63Sab196087 return (S_ERROR);
2197d579eb63Sab196087 }
2198d579eb63Sab196087
2199d579eb63Sab196087 /* .SUNW_dyntlssort */
2200d579eb63Sab196087 if (ofl->ofl_dyntlssortcnt > 0) {
2201d579eb63Sab196087 if (new_section(ofl, SHT_SUNW_tlssort,
2202d579eb63Sab196087 MSG_ORIG(MSG_SCN_DYNTLSSORT),
2203d579eb63Sab196087 ofl->ofl_dyntlssortcnt, &isec, &shdr, &data) == S_ERROR)
2204d579eb63Sab196087 return (S_ERROR);
2205d579eb63Sab196087
220669112eddSAli Bahrami if ((ofl->ofl_osdyntlssort = ld_place_section(ofl, isec, NULL,
22071dd9d86fSAli Bahrami ld_targ.t_id.id_dynsort, NULL)) == (Os_desc *)S_ERROR)
2208d579eb63Sab196087 return (S_ERROR);
2209d579eb63Sab196087 }
2210d579eb63Sab196087
2211d579eb63Sab196087 return (1);
2212d579eb63Sab196087 }
2213d579eb63Sab196087
2214d579eb63Sab196087 /*
22159039eeafSab196087 * Helper routine for make_dynsym_shndx. Builds a
2216d579eb63Sab196087 * a SHT_SYMTAB_SHNDX for .dynsym or .SUNW_ldynsym, without knowing
22179039eeafSab196087 * which one it is.
22187c478bd9Sstevel@tonic-gate */
22195aefb655Srie static uintptr_t
make_dyn_shndx(Ofl_desc * ofl,const char * shname,Os_desc * symtab,Os_desc ** ret_os)22209039eeafSab196087 make_dyn_shndx(Ofl_desc *ofl, const char *shname, Os_desc *symtab,
22219039eeafSab196087 Os_desc **ret_os)
22227c478bd9Sstevel@tonic-gate {
22237c478bd9Sstevel@tonic-gate Is_desc *isec;
22247c478bd9Sstevel@tonic-gate Is_desc *dynsymisp;
22257c478bd9Sstevel@tonic-gate Shdr *shdr, *dynshdr;
22267c478bd9Sstevel@tonic-gate Elf_Data *data;
22277c478bd9Sstevel@tonic-gate
22281dd9d86fSAli Bahrami dynsymisp = ld_os_first_isdesc(symtab);
22299039eeafSab196087 dynshdr = dynsymisp->is_shdr;
22307c478bd9Sstevel@tonic-gate
22319039eeafSab196087 if (new_section(ofl, SHT_SYMTAB_SHNDX, shname,
22329039eeafSab196087 (dynshdr->sh_size / dynshdr->sh_entsize),
22339039eeafSab196087 &isec, &shdr, &data) == S_ERROR)
22347c478bd9Sstevel@tonic-gate return (S_ERROR);
22357c478bd9Sstevel@tonic-gate
223669112eddSAli Bahrami if ((*ret_os = ld_place_section(ofl, isec, NULL,
22371dd9d86fSAli Bahrami ld_targ.t_id.id_dynsym_ndx, NULL)) == (Os_desc *)S_ERROR)
22387c478bd9Sstevel@tonic-gate return (S_ERROR);
22397c478bd9Sstevel@tonic-gate
22409039eeafSab196087 assert(*ret_os);
22419039eeafSab196087
22429039eeafSab196087 return (1);
22439039eeafSab196087 }
22449039eeafSab196087
22459039eeafSab196087 /*
22469039eeafSab196087 * Build a SHT_SYMTAB_SHNDX for the .dynsym, and .SUNW_ldynsym
22479039eeafSab196087 */
22489039eeafSab196087 static uintptr_t
make_dynsym_shndx(Ofl_desc * ofl)22499039eeafSab196087 make_dynsym_shndx(Ofl_desc *ofl)
22509039eeafSab196087 {
22519039eeafSab196087 /*
2252d579eb63Sab196087 * If there is a .SUNW_ldynsym, generate a section for its extended
22539039eeafSab196087 * index section as well.
22549039eeafSab196087 */
2255d579eb63Sab196087 if (OFL_ALLOW_LDYNSYM(ofl)) {
22569039eeafSab196087 if (make_dyn_shndx(ofl, MSG_ORIG(MSG_SCN_LDYNSYM_SHNDX),
22579039eeafSab196087 ofl->ofl_osldynsym, &ofl->ofl_osldynshndx) == S_ERROR)
22589039eeafSab196087 return (S_ERROR);
22599039eeafSab196087 }
22609039eeafSab196087
22619039eeafSab196087 /* The Generate a section for the dynsym */
22629039eeafSab196087 if (make_dyn_shndx(ofl, MSG_ORIG(MSG_SCN_DYNSYM_SHNDX),
22639039eeafSab196087 ofl->ofl_osdynsym, &ofl->ofl_osdynshndx) == S_ERROR)
22649039eeafSab196087 return (S_ERROR);
22657c478bd9Sstevel@tonic-gate
22667c478bd9Sstevel@tonic-gate return (1);
22677c478bd9Sstevel@tonic-gate }
22687c478bd9Sstevel@tonic-gate
22697c478bd9Sstevel@tonic-gate
22707c478bd9Sstevel@tonic-gate /*
22717c478bd9Sstevel@tonic-gate * Build a string table for the section headers.
22727c478bd9Sstevel@tonic-gate */
22735aefb655Srie static uintptr_t
make_shstrtab(Ofl_desc * ofl)22747c478bd9Sstevel@tonic-gate make_shstrtab(Ofl_desc *ofl)
22757c478bd9Sstevel@tonic-gate {
22767c478bd9Sstevel@tonic-gate Shdr *shdr;
22777c478bd9Sstevel@tonic-gate Elf_Data *data;
22787c478bd9Sstevel@tonic-gate Is_desc *isec;
22797c478bd9Sstevel@tonic-gate size_t size;
22807c478bd9Sstevel@tonic-gate
22819039eeafSab196087 if (new_section(ofl, SHT_STRTAB, MSG_ORIG(MSG_SCN_SHSTRTAB),
22829039eeafSab196087 0, &isec, &shdr, &data) == S_ERROR)
22837c478bd9Sstevel@tonic-gate return (S_ERROR);
22847c478bd9Sstevel@tonic-gate
22857c478bd9Sstevel@tonic-gate /*
22867c478bd9Sstevel@tonic-gate * Place the section first, as it may effect the number of section
22877c478bd9Sstevel@tonic-gate * headers to account for.
22887c478bd9Sstevel@tonic-gate */
2289ba2be530Sab196087 ofl->ofl_osshstrtab =
229069112eddSAli Bahrami ld_place_section(ofl, isec, NULL, ld_targ.t_id.id_note, NULL);
2291ba2be530Sab196087 if (ofl->ofl_osshstrtab == (Os_desc *)S_ERROR)
22927c478bd9Sstevel@tonic-gate return (S_ERROR);
22937c478bd9Sstevel@tonic-gate
22947c478bd9Sstevel@tonic-gate size = st_getstrtab_sz(ofl->ofl_shdrsttab);
22957c478bd9Sstevel@tonic-gate assert(size > 0);
22967c478bd9Sstevel@tonic-gate
22977c478bd9Sstevel@tonic-gate data->d_size = size;
22987c478bd9Sstevel@tonic-gate shdr->sh_size = (Xword)size;
22997c478bd9Sstevel@tonic-gate
23007c478bd9Sstevel@tonic-gate return (1);
23017c478bd9Sstevel@tonic-gate }
23027c478bd9Sstevel@tonic-gate
23037c478bd9Sstevel@tonic-gate /*
23047c478bd9Sstevel@tonic-gate * Build a string section for the standard symbol table.
23057c478bd9Sstevel@tonic-gate */
23065aefb655Srie static uintptr_t
make_strtab(Ofl_desc * ofl)23077c478bd9Sstevel@tonic-gate make_strtab(Ofl_desc *ofl)
23087c478bd9Sstevel@tonic-gate {
23097c478bd9Sstevel@tonic-gate Shdr *shdr;
23107c478bd9Sstevel@tonic-gate Elf_Data *data;
23117c478bd9Sstevel@tonic-gate Is_desc *isec;
23127c478bd9Sstevel@tonic-gate size_t size;
23137c478bd9Sstevel@tonic-gate
23147c478bd9Sstevel@tonic-gate /*
23157c478bd9Sstevel@tonic-gate * This string table consists of all the global and local symbols.
23167c478bd9Sstevel@tonic-gate * Account for null bytes at end of the file name and the beginning
23177c478bd9Sstevel@tonic-gate * of section.
23187c478bd9Sstevel@tonic-gate */
23197c478bd9Sstevel@tonic-gate if (st_insert(ofl->ofl_strtab, ofl->ofl_name) == -1)
23207c478bd9Sstevel@tonic-gate return (S_ERROR);
23217c478bd9Sstevel@tonic-gate
23227c478bd9Sstevel@tonic-gate size = st_getstrtab_sz(ofl->ofl_strtab);
23237c478bd9Sstevel@tonic-gate assert(size > 0);
23247c478bd9Sstevel@tonic-gate
23259039eeafSab196087 if (new_section(ofl, SHT_STRTAB, MSG_ORIG(MSG_SCN_STRTAB),
23269039eeafSab196087 0, &isec, &shdr, &data) == S_ERROR)
23277c478bd9Sstevel@tonic-gate return (S_ERROR);
23289039eeafSab196087
23299039eeafSab196087 /* Set the size of the data area */
23307c478bd9Sstevel@tonic-gate data->d_size = size;
23317c478bd9Sstevel@tonic-gate shdr->sh_size = (Xword)size;
23327c478bd9Sstevel@tonic-gate
2333ba2be530Sab196087 ofl->ofl_osstrtab =
233469112eddSAli Bahrami ld_place_section(ofl, isec, NULL, ld_targ.t_id.id_strtab, NULL);
23357c478bd9Sstevel@tonic-gate return ((uintptr_t)ofl->ofl_osstrtab);
23367c478bd9Sstevel@tonic-gate }
23377c478bd9Sstevel@tonic-gate
23387c478bd9Sstevel@tonic-gate /*
23397c478bd9Sstevel@tonic-gate * Build a string table for the dynamic symbol table.
23407c478bd9Sstevel@tonic-gate */
23415aefb655Srie static uintptr_t
make_dynstr(Ofl_desc * ofl)23427c478bd9Sstevel@tonic-gate make_dynstr(Ofl_desc *ofl)
23437c478bd9Sstevel@tonic-gate {
23447c478bd9Sstevel@tonic-gate Shdr *shdr;
23457c478bd9Sstevel@tonic-gate Elf_Data *data;
23467c478bd9Sstevel@tonic-gate Is_desc *isec;
23477c478bd9Sstevel@tonic-gate size_t size;
23487c478bd9Sstevel@tonic-gate
23497c478bd9Sstevel@tonic-gate /*
2350d579eb63Sab196087 * If producing a .SUNW_ldynsym, account for the initial STT_FILE
2351d579eb63Sab196087 * symbol that precedes the scope reduced global symbols.
23529039eeafSab196087 */
2353d579eb63Sab196087 if (OFL_ALLOW_LDYNSYM(ofl)) {
23549039eeafSab196087 if (st_insert(ofl->ofl_dynstrtab, ofl->ofl_name) == -1)
23559039eeafSab196087 return (S_ERROR);
23569039eeafSab196087 ofl->ofl_dynscopecnt++;
23579039eeafSab196087 }
23589039eeafSab196087
23599039eeafSab196087 /*
23607c478bd9Sstevel@tonic-gate * Account for any local, named register symbols. These locals are
23617c478bd9Sstevel@tonic-gate * required for reference from DT_REGISTER .dynamic entries.
23627c478bd9Sstevel@tonic-gate */
23637c478bd9Sstevel@tonic-gate if (ofl->ofl_regsyms) {
23647c478bd9Sstevel@tonic-gate int ndx;
23657c478bd9Sstevel@tonic-gate
23667c478bd9Sstevel@tonic-gate for (ndx = 0; ndx < ofl->ofl_regsymsno; ndx++) {
23677c478bd9Sstevel@tonic-gate Sym_desc *sdp;
23687c478bd9Sstevel@tonic-gate
236957ef7aa9SRod Evans if ((sdp = ofl->ofl_regsyms[ndx]) == NULL)
23707c478bd9Sstevel@tonic-gate continue;
23717c478bd9Sstevel@tonic-gate
237208278a5eSRod Evans if (!SYM_IS_HIDDEN(sdp) &&
23737c478bd9Sstevel@tonic-gate (ELF_ST_BIND(sdp->sd_sym->st_info) != STB_LOCAL))
23747c478bd9Sstevel@tonic-gate continue;
23757c478bd9Sstevel@tonic-gate
237657ef7aa9SRod Evans if (sdp->sd_sym->st_name == NULL)
23777c478bd9Sstevel@tonic-gate continue;
23787c478bd9Sstevel@tonic-gate
23797c478bd9Sstevel@tonic-gate if (st_insert(ofl->ofl_dynstrtab, sdp->sd_name) == -1)
23807c478bd9Sstevel@tonic-gate return (S_ERROR);
23817c478bd9Sstevel@tonic-gate }
23827c478bd9Sstevel@tonic-gate }
23837c478bd9Sstevel@tonic-gate
23847c478bd9Sstevel@tonic-gate /*
23857c478bd9Sstevel@tonic-gate * Reserve entries for any per-symbol auxiliary/filter strings.
23867c478bd9Sstevel@tonic-gate */
2387cce0e03bSab196087 if (ofl->ofl_dtsfltrs != NULL) {
23887c478bd9Sstevel@tonic-gate Dfltr_desc *dftp;
2389cce0e03bSab196087 Aliste idx;
23907c478bd9Sstevel@tonic-gate
2391cce0e03bSab196087 for (ALIST_TRAVERSE(ofl->ofl_dtsfltrs, idx, dftp))
23927c478bd9Sstevel@tonic-gate if (st_insert(ofl->ofl_dynstrtab, dftp->dft_str) == -1)
23937c478bd9Sstevel@tonic-gate return (S_ERROR);
23947c478bd9Sstevel@tonic-gate }
23957c478bd9Sstevel@tonic-gate
23967c478bd9Sstevel@tonic-gate size = st_getstrtab_sz(ofl->ofl_dynstrtab);
23977c478bd9Sstevel@tonic-gate assert(size > 0);
23987c478bd9Sstevel@tonic-gate
23999039eeafSab196087 if (new_section(ofl, SHT_STRTAB, MSG_ORIG(MSG_SCN_DYNSTR),
24009039eeafSab196087 0, &isec, &shdr, &data) == S_ERROR)
24017c478bd9Sstevel@tonic-gate return (S_ERROR);
24027c478bd9Sstevel@tonic-gate
24039039eeafSab196087 /* Make it allocable if necessary */
24047c478bd9Sstevel@tonic-gate if (!(ofl->ofl_flags & FLG_OF_RELOBJ))
24059039eeafSab196087 shdr->sh_flags |= SHF_ALLOC;
24067c478bd9Sstevel@tonic-gate
24079039eeafSab196087 /* Set the size of the data area */
24083244bcaaSab196087 data->d_size = size + DYNSTR_EXTRA_PAD;
24093244bcaaSab196087
24107c478bd9Sstevel@tonic-gate shdr->sh_size = (Xword)size;
24117c478bd9Sstevel@tonic-gate
2412ba2be530Sab196087 ofl->ofl_osdynstr =
241369112eddSAli Bahrami ld_place_section(ofl, isec, NULL, ld_targ.t_id.id_dynstr, NULL);
24147c478bd9Sstevel@tonic-gate return ((uintptr_t)ofl->ofl_osdynstr);
24157c478bd9Sstevel@tonic-gate }
24167c478bd9Sstevel@tonic-gate
24177c478bd9Sstevel@tonic-gate /*
24187c478bd9Sstevel@tonic-gate * Generate an output relocation section which will contain the relocation
24197c478bd9Sstevel@tonic-gate * information to be applied to the `osp' section.
24207c478bd9Sstevel@tonic-gate *
24217c478bd9Sstevel@tonic-gate * If (osp == NULL) then we are creating the coalesced relocation section
24227c478bd9Sstevel@tonic-gate * for an executable and/or a shared object.
24237c478bd9Sstevel@tonic-gate */
24245aefb655Srie static uintptr_t
make_reloc(Ofl_desc * ofl,Os_desc * osp)24257c478bd9Sstevel@tonic-gate make_reloc(Ofl_desc *ofl, Os_desc *osp)
24267c478bd9Sstevel@tonic-gate {
24277c478bd9Sstevel@tonic-gate Shdr *shdr;
24287c478bd9Sstevel@tonic-gate Elf_Data *data;
24297c478bd9Sstevel@tonic-gate Is_desc *isec;
24307c478bd9Sstevel@tonic-gate size_t size;
24317c478bd9Sstevel@tonic-gate Xword sh_flags;
24327c478bd9Sstevel@tonic-gate char *sectname;
24337c478bd9Sstevel@tonic-gate Os_desc *rosp;
24347c478bd9Sstevel@tonic-gate Word relsize;
24357c478bd9Sstevel@tonic-gate const char *rel_prefix;
24367c478bd9Sstevel@tonic-gate
24377c478bd9Sstevel@tonic-gate /* LINTED */
2438ba2be530Sab196087 if (ld_targ.t_m.m_rel_sht_type == SHT_REL) {
24397c478bd9Sstevel@tonic-gate /* REL */
24407c478bd9Sstevel@tonic-gate relsize = sizeof (Rel);
24417c478bd9Sstevel@tonic-gate rel_prefix = MSG_ORIG(MSG_SCN_REL);
24427c478bd9Sstevel@tonic-gate } else {
24437c478bd9Sstevel@tonic-gate /* RELA */
24447c478bd9Sstevel@tonic-gate relsize = sizeof (Rela);
24457c478bd9Sstevel@tonic-gate rel_prefix = MSG_ORIG(MSG_SCN_RELA);
24467c478bd9Sstevel@tonic-gate }
24477c478bd9Sstevel@tonic-gate
24487c478bd9Sstevel@tonic-gate if (osp) {
24497c478bd9Sstevel@tonic-gate size = osp->os_szoutrels;
24507c478bd9Sstevel@tonic-gate sh_flags = osp->os_shdr->sh_flags;
24517c478bd9Sstevel@tonic-gate if ((sectname = libld_malloc(strlen(rel_prefix) +
24527c478bd9Sstevel@tonic-gate strlen(osp->os_name) + 1)) == 0)
24537c478bd9Sstevel@tonic-gate return (S_ERROR);
24547c478bd9Sstevel@tonic-gate (void) strcpy(sectname, rel_prefix);
24557c478bd9Sstevel@tonic-gate (void) strcat(sectname, osp->os_name);
2456e38a713aSrie } else if (ofl->ofl_flags & FLG_OF_COMREL) {
24577c478bd9Sstevel@tonic-gate size = (ofl->ofl_reloccnt - ofl->ofl_reloccntsub) * relsize;
24587c478bd9Sstevel@tonic-gate sh_flags = SHF_ALLOC;
24597c478bd9Sstevel@tonic-gate sectname = (char *)MSG_ORIG(MSG_SCN_SUNWRELOC);
24607c478bd9Sstevel@tonic-gate } else {
24617c478bd9Sstevel@tonic-gate size = ofl->ofl_relocrelsz;
24627c478bd9Sstevel@tonic-gate sh_flags = SHF_ALLOC;
24637c478bd9Sstevel@tonic-gate sectname = (char *)rel_prefix;
24647c478bd9Sstevel@tonic-gate }
24657c478bd9Sstevel@tonic-gate
24667c478bd9Sstevel@tonic-gate /*
24677c478bd9Sstevel@tonic-gate * Keep track of total size of 'output relocations' (to be stored
24687c478bd9Sstevel@tonic-gate * in .dynamic)
24697c478bd9Sstevel@tonic-gate */
24707c478bd9Sstevel@tonic-gate /* LINTED */
24717c478bd9Sstevel@tonic-gate ofl->ofl_relocsz += (Xword)size;
24727c478bd9Sstevel@tonic-gate
2473ba2be530Sab196087 if (new_section(ofl, ld_targ.t_m.m_rel_sht_type, sectname, 0, &isec,
2474ba2be530Sab196087 &shdr, &data) == S_ERROR)
24757c478bd9Sstevel@tonic-gate return (S_ERROR);
24769039eeafSab196087
24777c478bd9Sstevel@tonic-gate data->d_size = size;
24787c478bd9Sstevel@tonic-gate
24797c478bd9Sstevel@tonic-gate shdr->sh_size = (Xword)size;
24809039eeafSab196087 if (OFL_ALLOW_DYNSYM(ofl) && (sh_flags & SHF_ALLOC))
24817c478bd9Sstevel@tonic-gate shdr->sh_flags = SHF_ALLOC;
24827c478bd9Sstevel@tonic-gate
24837c478bd9Sstevel@tonic-gate if (osp) {
24847c478bd9Sstevel@tonic-gate /*
24857c478bd9Sstevel@tonic-gate * The sh_info field of the SHT_REL* sections points to the
24867c478bd9Sstevel@tonic-gate * section the relocations are to be applied to.
24877c478bd9Sstevel@tonic-gate */
24887c478bd9Sstevel@tonic-gate shdr->sh_flags |= SHF_INFO_LINK;
24897c478bd9Sstevel@tonic-gate }
24907c478bd9Sstevel@tonic-gate
249169112eddSAli Bahrami rosp = ld_place_section(ofl, isec, NULL, ld_targ.t_id.id_rel, NULL);
2492ba2be530Sab196087 if (rosp == (Os_desc *)S_ERROR)
24937c478bd9Sstevel@tonic-gate return (S_ERROR);
24947c478bd9Sstevel@tonic-gate
24956b3ba5bdSAli Bahrami /*
24966b3ba5bdSAli Bahrami * Associate this relocation section to the section its going to
24976b3ba5bdSAli Bahrami * relocate.
24986b3ba5bdSAli Bahrami */
24997c478bd9Sstevel@tonic-gate if (osp) {
25006b3ba5bdSAli Bahrami Aliste idx;
25017c478bd9Sstevel@tonic-gate Is_desc *risp;
25020bc07c75Srie
25037c478bd9Sstevel@tonic-gate /*
25047c478bd9Sstevel@tonic-gate * This is used primarily so that we can update
25057c478bd9Sstevel@tonic-gate * SHT_GROUP[sect_no] entries to point to the
25067c478bd9Sstevel@tonic-gate * created output relocation sections.
25077c478bd9Sstevel@tonic-gate */
25086b3ba5bdSAli Bahrami for (APLIST_TRAVERSE(osp->os_relisdescs, idx, risp)) {
25097c478bd9Sstevel@tonic-gate risp->is_osdesc = rosp;
25100bc07c75Srie
25117c478bd9Sstevel@tonic-gate /*
25120bc07c75Srie * If the input relocation section had the SHF_GROUP
25137010c12aSrie * flag set - propagate it to the output relocation
25140bc07c75Srie * section.
25157c478bd9Sstevel@tonic-gate */
25167c478bd9Sstevel@tonic-gate if (risp->is_shdr->sh_flags & SHF_GROUP) {
25177c478bd9Sstevel@tonic-gate rosp->os_shdr->sh_flags |= SHF_GROUP;
25187c478bd9Sstevel@tonic-gate break;
25197c478bd9Sstevel@tonic-gate }
25207c478bd9Sstevel@tonic-gate }
25217c478bd9Sstevel@tonic-gate osp->os_relosdesc = rosp;
25227c478bd9Sstevel@tonic-gate } else
25237c478bd9Sstevel@tonic-gate ofl->ofl_osrel = rosp;
25247c478bd9Sstevel@tonic-gate
25257c478bd9Sstevel@tonic-gate /*
25267c478bd9Sstevel@tonic-gate * If this is the first relocation section we've encountered save it
25277c478bd9Sstevel@tonic-gate * so that the .dynamic entry can be initialized accordingly.
25287c478bd9Sstevel@tonic-gate */
25297c478bd9Sstevel@tonic-gate if (ofl->ofl_osrelhead == (Os_desc *)0)
25307c478bd9Sstevel@tonic-gate ofl->ofl_osrelhead = rosp;
25317c478bd9Sstevel@tonic-gate
25327c478bd9Sstevel@tonic-gate return (1);
25337c478bd9Sstevel@tonic-gate }
25347c478bd9Sstevel@tonic-gate
25357c478bd9Sstevel@tonic-gate /*
25367c478bd9Sstevel@tonic-gate * Generate version needed section.
25377c478bd9Sstevel@tonic-gate */
25385aefb655Srie static uintptr_t
make_verneed(Ofl_desc * ofl)25397c478bd9Sstevel@tonic-gate make_verneed(Ofl_desc *ofl)
25407c478bd9Sstevel@tonic-gate {
25417c478bd9Sstevel@tonic-gate Shdr *shdr;
25427c478bd9Sstevel@tonic-gate Elf_Data *data;
25437c478bd9Sstevel@tonic-gate Is_desc *isec;
25447c478bd9Sstevel@tonic-gate
25457c478bd9Sstevel@tonic-gate /*
25469039eeafSab196087 * verneed sections do not have a constant element size, so the
25479039eeafSab196087 * value of ent_cnt specified here (0) is meaningless.
25487c478bd9Sstevel@tonic-gate */
25499039eeafSab196087 if (new_section(ofl, SHT_SUNW_verneed, MSG_ORIG(MSG_SCN_SUNWVERSION),
25509039eeafSab196087 0, &isec, &shdr, &data) == S_ERROR)
25517c478bd9Sstevel@tonic-gate return (S_ERROR);
25527c478bd9Sstevel@tonic-gate
25539039eeafSab196087 /* During version processing we calculated the total size. */
25549039eeafSab196087 data->d_size = ofl->ofl_verneedsz;
25559039eeafSab196087 shdr->sh_size = (Xword)ofl->ofl_verneedsz;
25567c478bd9Sstevel@tonic-gate
2557ba2be530Sab196087 ofl->ofl_osverneed =
255869112eddSAli Bahrami ld_place_section(ofl, isec, NULL, ld_targ.t_id.id_version, NULL);
25597c478bd9Sstevel@tonic-gate return ((uintptr_t)ofl->ofl_osverneed);
25607c478bd9Sstevel@tonic-gate }
25617c478bd9Sstevel@tonic-gate
25627c478bd9Sstevel@tonic-gate /*
25637c478bd9Sstevel@tonic-gate * Generate a version definition section.
25647c478bd9Sstevel@tonic-gate *
25657c478bd9Sstevel@tonic-gate * o the SHT_SUNW_verdef section defines the versions that exist within this
25667c478bd9Sstevel@tonic-gate * image.
25677c478bd9Sstevel@tonic-gate */
25685aefb655Srie static uintptr_t
make_verdef(Ofl_desc * ofl)25697c478bd9Sstevel@tonic-gate make_verdef(Ofl_desc *ofl)
25707c478bd9Sstevel@tonic-gate {
25717c478bd9Sstevel@tonic-gate Shdr *shdr;
25727c478bd9Sstevel@tonic-gate Elf_Data *data;
25737c478bd9Sstevel@tonic-gate Is_desc *isec;
25747c478bd9Sstevel@tonic-gate Ver_desc *vdp;
2575635216b6SRod Evans Str_tbl *strtab;
25767c478bd9Sstevel@tonic-gate
25777c478bd9Sstevel@tonic-gate /*
25787c478bd9Sstevel@tonic-gate * Reserve a string table entry for the base version dependency (other
25797c478bd9Sstevel@tonic-gate * dependencies have symbol representations, which will already be
25807c478bd9Sstevel@tonic-gate * accounted for during symbol processing).
25817c478bd9Sstevel@tonic-gate */
258257ef7aa9SRod Evans vdp = (Ver_desc *)ofl->ofl_verdesc->apl_data[0];
25837c478bd9Sstevel@tonic-gate
2584635216b6SRod Evans if (OFL_IS_STATIC_OBJ(ofl))
2585635216b6SRod Evans strtab = ofl->ofl_strtab;
2586635216b6SRod Evans else
2587635216b6SRod Evans strtab = ofl->ofl_dynstrtab;
2588635216b6SRod Evans
2589635216b6SRod Evans if (st_insert(strtab, vdp->vd_name) == -1)
25907c478bd9Sstevel@tonic-gate return (S_ERROR);
25917c478bd9Sstevel@tonic-gate
25927c478bd9Sstevel@tonic-gate /*
25939039eeafSab196087 * verdef sections do not have a constant element size, so the
25949039eeafSab196087 * value of ent_cnt specified here (0) is meaningless.
25957c478bd9Sstevel@tonic-gate */
25969039eeafSab196087 if (new_section(ofl, SHT_SUNW_verdef, MSG_ORIG(MSG_SCN_SUNWVERSION),
25979039eeafSab196087 0, &isec, &shdr, &data) == S_ERROR)
25987c478bd9Sstevel@tonic-gate return (S_ERROR);
25997c478bd9Sstevel@tonic-gate
26009039eeafSab196087 /* During version processing we calculated the total size. */
26019039eeafSab196087 data->d_size = ofl->ofl_verdefsz;
26029039eeafSab196087 shdr->sh_size = (Xword)ofl->ofl_verdefsz;
26037c478bd9Sstevel@tonic-gate
2604ba2be530Sab196087 ofl->ofl_osverdef =
260569112eddSAli Bahrami ld_place_section(ofl, isec, NULL, ld_targ.t_id.id_version, NULL);
26067c478bd9Sstevel@tonic-gate return ((uintptr_t)ofl->ofl_osverdef);
26077c478bd9Sstevel@tonic-gate }
26087c478bd9Sstevel@tonic-gate
26097c478bd9Sstevel@tonic-gate /*
26107c478bd9Sstevel@tonic-gate * This routine is called when -z nopartial is in effect.
26117c478bd9Sstevel@tonic-gate */
26127c478bd9Sstevel@tonic-gate uintptr_t
ld_make_parexpn_data(Ofl_desc * ofl,size_t size,Xword align)261335450702SAli Bahrami ld_make_parexpn_data(Ofl_desc *ofl, size_t size, Xword align)
26147c478bd9Sstevel@tonic-gate {
26157c478bd9Sstevel@tonic-gate Shdr *shdr;
26167c478bd9Sstevel@tonic-gate Elf_Data *data;
26177c478bd9Sstevel@tonic-gate Is_desc *isec;
26187c478bd9Sstevel@tonic-gate Os_desc *osp;
26197c478bd9Sstevel@tonic-gate
262035450702SAli Bahrami if (new_section(ofl, SHT_PROGBITS, MSG_ORIG(MSG_SCN_DATA), 0,
26219039eeafSab196087 &isec, &shdr, &data) == S_ERROR)
26227c478bd9Sstevel@tonic-gate return (S_ERROR);
26239039eeafSab196087
26249039eeafSab196087 shdr->sh_flags |= SHF_WRITE;
26257c478bd9Sstevel@tonic-gate data->d_size = size;
26269039eeafSab196087 shdr->sh_size = (Xword)size;
26279039eeafSab196087 if (align != 0) {
26289039eeafSab196087 data->d_align = align;
26299039eeafSab196087 shdr->sh_addralign = align;
26309039eeafSab196087 }
26319039eeafSab196087
263257ef7aa9SRod Evans if ((data->d_buf = libld_calloc(size, 1)) == NULL)
26337c478bd9Sstevel@tonic-gate return (S_ERROR);
26347c478bd9Sstevel@tonic-gate
26357c478bd9Sstevel@tonic-gate /*
263635450702SAli Bahrami * Retain handle to this .data input section. Variables using move
263735450702SAli Bahrami * sections (partial initialization) will be redirected here when
263835450702SAli Bahrami * such global references are added and '-z nopartial' is in effect.
26397c478bd9Sstevel@tonic-gate */
264035450702SAli Bahrami ofl->ofl_isparexpn = isec;
264169112eddSAli Bahrami osp = ld_place_section(ofl, isec, NULL, ld_targ.t_id.id_data, NULL);
2642ba2be530Sab196087 if (osp == (Os_desc *)S_ERROR)
26437c478bd9Sstevel@tonic-gate return (S_ERROR);
26447c478bd9Sstevel@tonic-gate
26457c478bd9Sstevel@tonic-gate if (!(osp->os_flags & FLG_OS_OUTREL)) {
26467c478bd9Sstevel@tonic-gate ofl->ofl_dynshdrcnt++;
26477c478bd9Sstevel@tonic-gate osp->os_flags |= FLG_OS_OUTREL;
26487c478bd9Sstevel@tonic-gate }
26497c478bd9Sstevel@tonic-gate return (1);
26507c478bd9Sstevel@tonic-gate }
26517c478bd9Sstevel@tonic-gate
26527c478bd9Sstevel@tonic-gate /*
26537c478bd9Sstevel@tonic-gate * Make .sunwmove section
26547c478bd9Sstevel@tonic-gate */
26557c478bd9Sstevel@tonic-gate uintptr_t
ld_make_sunwmove(Ofl_desc * ofl,int mv_nums)26565aefb655Srie ld_make_sunwmove(Ofl_desc *ofl, int mv_nums)
26577c478bd9Sstevel@tonic-gate {
26587c478bd9Sstevel@tonic-gate Shdr *shdr;
26597c478bd9Sstevel@tonic-gate Elf_Data *data;
26607c478bd9Sstevel@tonic-gate Is_desc *isec;
266157ef7aa9SRod Evans Aliste idx;
266257ef7aa9SRod Evans Sym_desc *sdp;
26637c478bd9Sstevel@tonic-gate int cnt = 1;
26647c478bd9Sstevel@tonic-gate
26657c478bd9Sstevel@tonic-gate
26669039eeafSab196087 if (new_section(ofl, SHT_SUNW_move, MSG_ORIG(MSG_SCN_SUNWMOVE),
26679039eeafSab196087 mv_nums, &isec, &shdr, &data) == S_ERROR)
26687c478bd9Sstevel@tonic-gate return (S_ERROR);
26697c478bd9Sstevel@tonic-gate
267057ef7aa9SRod Evans if ((data->d_buf = libld_calloc(data->d_size, 1)) == NULL)
26717c478bd9Sstevel@tonic-gate return (S_ERROR);
26727c478bd9Sstevel@tonic-gate
26737c478bd9Sstevel@tonic-gate /*
26747c478bd9Sstevel@tonic-gate * Copy move entries
26757c478bd9Sstevel@tonic-gate */
267657ef7aa9SRod Evans for (APLIST_TRAVERSE(ofl->ofl_parsyms, idx, sdp)) {
267757ef7aa9SRod Evans Aliste idx2;
267857ef7aa9SRod Evans Mv_desc *mdp;
26797c478bd9Sstevel@tonic-gate
268057ef7aa9SRod Evans if (sdp->sd_flags & FLG_SY_PAREXPN)
26817c478bd9Sstevel@tonic-gate continue;
268257ef7aa9SRod Evans
268357ef7aa9SRod Evans for (ALIST_TRAVERSE(sdp->sd_move, idx2, mdp))
268457ef7aa9SRod Evans mdp->md_oidx = cnt++;
26857c478bd9Sstevel@tonic-gate }
268657ef7aa9SRod Evans
268769112eddSAli Bahrami if ((ofl->ofl_osmove = ld_place_section(ofl, isec, NULL, 0, NULL)) ==
26887c478bd9Sstevel@tonic-gate (Os_desc *)S_ERROR)
26897c478bd9Sstevel@tonic-gate return (S_ERROR);
26907c478bd9Sstevel@tonic-gate
26917c478bd9Sstevel@tonic-gate return (1);
26927c478bd9Sstevel@tonic-gate }
26937c478bd9Sstevel@tonic-gate
26947c478bd9Sstevel@tonic-gate /*
2695cce0e03bSab196087 * Given a relocation descriptor that references a string table
2696cce0e03bSab196087 * input section, locate the string referenced and return a pointer
2697cce0e03bSab196087 * to it.
2698cce0e03bSab196087 */
2699cce0e03bSab196087 static const char *
strmerge_get_reloc_str(Ofl_desc * ofl,Rel_desc * rsp)2700cce0e03bSab196087 strmerge_get_reloc_str(Ofl_desc *ofl, Rel_desc *rsp)
2701cce0e03bSab196087 {
2702cce0e03bSab196087 Sym_desc *sdp = rsp->rel_sym;
2703cce0e03bSab196087 Xword str_off;
2704cce0e03bSab196087
2705cce0e03bSab196087 /*
2706cce0e03bSab196087 * In the case of an STT_SECTION symbol, the addend of the
2707cce0e03bSab196087 * relocation gives the offset into the string section. For
2708cce0e03bSab196087 * other symbol types, the symbol value is the offset.
2709cce0e03bSab196087 */
2710cce0e03bSab196087
2711cce0e03bSab196087 if (ELF_ST_TYPE(sdp->sd_sym->st_info) != STT_SECTION) {
2712cce0e03bSab196087 str_off = sdp->sd_sym->st_value;
2713cce0e03bSab196087 } else if ((rsp->rel_flags & FLG_REL_RELA) == FLG_REL_RELA) {
2714cce0e03bSab196087 /*
2715cce0e03bSab196087 * For SHT_RELA, the addend value is found in the
2716cce0e03bSab196087 * rel_raddend field of the relocation.
2717cce0e03bSab196087 */
2718cce0e03bSab196087 str_off = rsp->rel_raddend;
2719cce0e03bSab196087 } else { /* REL and STT_SECTION */
2720cce0e03bSab196087 /*
2721cce0e03bSab196087 * For SHT_REL, the "addend" is not part of the relocation
2722cce0e03bSab196087 * record. Instead, it is found at the relocation target
2723cce0e03bSab196087 * address.
2724cce0e03bSab196087 */
2725cce0e03bSab196087 uchar_t *addr = (uchar_t *)((uintptr_t)rsp->rel_roffset +
2726cce0e03bSab196087 (uintptr_t)rsp->rel_isdesc->is_indata->d_buf);
2727cce0e03bSab196087
2728cce0e03bSab196087 if (ld_reloc_targval_get(ofl, rsp, addr, &str_off) == 0)
2729cce0e03bSab196087 return (0);
2730cce0e03bSab196087 }
2731cce0e03bSab196087
2732cce0e03bSab196087 return (str_off + (char *)sdp->sd_isc->is_indata->d_buf);
2733cce0e03bSab196087 }
2734cce0e03bSab196087
2735cce0e03bSab196087 /*
2736cce0e03bSab196087 * First pass over the relocation records for string table merging.
2737cce0e03bSab196087 * Build lists of relocations and symbols that will need modification,
2738cce0e03bSab196087 * and insert the strings they reference into the mstrtab string table.
2739cce0e03bSab196087 *
2740cce0e03bSab196087 * entry:
2741cce0e03bSab196087 * ofl, osp - As passed to ld_make_strmerge().
2742cce0e03bSab196087 * mstrtab - String table to receive input strings. This table
2743cce0e03bSab196087 * must be in its first (initialization) pass and not
2744cce0e03bSab196087 * yet cooked (st_getstrtab_sz() not yet called).
274557ef7aa9SRod Evans * rel_alpp - APlist to receive pointer to any relocation
2746cce0e03bSab196087 * descriptors with STT_SECTION symbols that reference
2747cce0e03bSab196087 * one of the input sections being merged.
274857ef7aa9SRod Evans * sym_alpp - APlist to receive pointer to any symbols that reference
2749cce0e03bSab196087 * one of the input sections being merged.
2750bf994817SAli Bahrami * rcp - Pointer to cache of relocation descriptors to examine.
2751bf994817SAli Bahrami * Either &ofl->ofl_actrels (active relocations)
2752cce0e03bSab196087 * or &ofl->ofl_outrels (output relocations).
2753cce0e03bSab196087 *
2754cce0e03bSab196087 * exit:
275557ef7aa9SRod Evans * On success, rel_alpp and sym_alpp are updated, and
275608278a5eSRod Evans * any strings in the mergeable input sections referenced by
2757cce0e03bSab196087 * a relocation has been entered into mstrtab. True (1) is returned.
2758cce0e03bSab196087 *
2759cce0e03bSab196087 * On failure, False (0) is returned.
2760cce0e03bSab196087 */
2761cce0e03bSab196087 static int
strmerge_pass1(Ofl_desc * ofl,Os_desc * osp,Str_tbl * mstrtab,APlist ** rel_alpp,APlist ** sym_alpp,Rel_cache * rcp)2762cce0e03bSab196087 strmerge_pass1(Ofl_desc *ofl, Os_desc *osp, Str_tbl *mstrtab,
2763bf994817SAli Bahrami APlist **rel_alpp, APlist **sym_alpp, Rel_cache *rcp)
2764cce0e03bSab196087 {
276557ef7aa9SRod Evans Aliste idx;
2766bf994817SAli Bahrami Rel_cachebuf *rcbp;
2767cce0e03bSab196087 Sym_desc *sdp;
2768cce0e03bSab196087 Sym_desc *last_sdp = NULL;
2769cce0e03bSab196087 Rel_desc *rsp;
2770cce0e03bSab196087 const char *name;
2771cce0e03bSab196087
2772bf994817SAli Bahrami REL_CACHE_TRAVERSE(rcp, idx, rcbp, rsp) {
2773cce0e03bSab196087 sdp = rsp->rel_sym;
2774bf994817SAli Bahrami if ((sdp->sd_isc == NULL) || ((sdp->sd_isc->is_flags &
2775bf994817SAli Bahrami (FLG_IS_DISCARD | FLG_IS_INSTRMRG)) != FLG_IS_INSTRMRG) ||
2776cce0e03bSab196087 (sdp->sd_isc->is_osdesc != osp))
2777cce0e03bSab196087 continue;
2778cce0e03bSab196087
2779cce0e03bSab196087 /*
2780bf994817SAli Bahrami * Remember symbol for use in the third pass. There is no
2781bf994817SAli Bahrami * reason to save a given symbol more than once, so we take
2782bf994817SAli Bahrami * advantage of the fact that relocations to a given symbol
2783bf994817SAli Bahrami * tend to cluster in the list. If this is the same symbol
2784bf994817SAli Bahrami * we saved last time, don't bother.
2785cce0e03bSab196087 */
2786cce0e03bSab196087 if (last_sdp != sdp) {
2787bf994817SAli Bahrami if (aplist_append(sym_alpp, sdp, AL_CNT_STRMRGSYM) ==
2788bf994817SAli Bahrami NULL)
2789cce0e03bSab196087 return (0);
2790cce0e03bSab196087 last_sdp = sdp;
2791cce0e03bSab196087 }
2792cce0e03bSab196087
2793cce0e03bSab196087 /* Enter the string into our new string table */
2794cce0e03bSab196087 name = strmerge_get_reloc_str(ofl, rsp);
2795cce0e03bSab196087 if (st_insert(mstrtab, name) == -1)
2796cce0e03bSab196087 return (0);
2797cce0e03bSab196087
2798cce0e03bSab196087 /*
2799bf994817SAli Bahrami * If this is an STT_SECTION symbol, then the second pass
2800bf994817SAli Bahrami * will need to modify this relocation, so hang on to it.
2801cce0e03bSab196087 */
2802bf994817SAli Bahrami if ((ELF_ST_TYPE(sdp->sd_sym->st_info) == STT_SECTION) &&
2803bf994817SAli Bahrami (aplist_append(rel_alpp, rsp, AL_CNT_STRMRGREL) == NULL))
2804cce0e03bSab196087 return (0);
2805cce0e03bSab196087 }
2806cce0e03bSab196087
2807cce0e03bSab196087 return (1);
2808cce0e03bSab196087 }
2809cce0e03bSab196087
2810cce0e03bSab196087 /*
2811cce0e03bSab196087 * If the output section has any SHF_MERGE|SHF_STRINGS input sections,
2812cce0e03bSab196087 * replace them with a single merged/compressed input section.
2813cce0e03bSab196087 *
2814cce0e03bSab196087 * entry:
2815cce0e03bSab196087 * ofl - Output file descriptor
2816cce0e03bSab196087 * osp - Output section descriptor
281757ef7aa9SRod Evans * rel_alpp, sym_alpp, - Address of 2 APlists, to be used
2818cce0e03bSab196087 * for internal processing. On the initial call to
2819cce0e03bSab196087 * ld_make_strmerge, these list pointers must be NULL.
2820cce0e03bSab196087 * The caller is encouraged to pass the same lists back for
2821cce0e03bSab196087 * successive calls to this function without freeing
2822cce0e03bSab196087 * them in between calls. This causes a single pair of
2823cce0e03bSab196087 * memory allocations to be reused multiple times.
2824cce0e03bSab196087 *
2825cce0e03bSab196087 * exit:
2826cce0e03bSab196087 * If section merging is possible, it is done. If no errors are
2827cce0e03bSab196087 * encountered, True (1) is returned. On error, S_ERROR.
2828cce0e03bSab196087 *
282957ef7aa9SRod Evans * The contents of rel_alpp and sym_alpp on exit are
2830cce0e03bSab196087 * undefined. The caller can free them, or pass them back to a subsequent
2831cce0e03bSab196087 * call to this routine, but should not examine their contents.
2832cce0e03bSab196087 */
2833cce0e03bSab196087 static uintptr_t
ld_make_strmerge(Ofl_desc * ofl,Os_desc * osp,APlist ** rel_alpp,APlist ** sym_alpp)283457ef7aa9SRod Evans ld_make_strmerge(Ofl_desc *ofl, Os_desc *osp, APlist **rel_alpp,
283557ef7aa9SRod Evans APlist **sym_alpp)
2836cce0e03bSab196087 {
2837cce0e03bSab196087 Str_tbl *mstrtab; /* string table for string merge secs */
2838cce0e03bSab196087 Is_desc *mstrsec; /* Generated string merge section */
2839cce0e03bSab196087 Is_desc *isp;
2840cce0e03bSab196087 Shdr *mstr_shdr;
2841cce0e03bSab196087 Elf_Data *mstr_data;
2842cce0e03bSab196087 Sym_desc *sdp;
2843cce0e03bSab196087 Rel_desc *rsp;
2844cce0e03bSab196087 Aliste idx;
2845cce0e03bSab196087 size_t data_size;
2846cce0e03bSab196087 int st_setstring_status;
2847cce0e03bSab196087 size_t stoff;
2848cce0e03bSab196087
2849cce0e03bSab196087 /* If string table compression is disabled, there's nothing to do */
2850cce0e03bSab196087 if ((ofl->ofl_flags1 & FLG_OF1_NCSTTAB) != 0)
2851cce0e03bSab196087 return (1);
2852cce0e03bSab196087
2853cce0e03bSab196087 /*
2854cce0e03bSab196087 * Pass over the mergeable input sections, and if they haven't
2855cce0e03bSab196087 * all been discarded, create a string table.
2856cce0e03bSab196087 */
2857cce0e03bSab196087 mstrtab = NULL;
2858cce0e03bSab196087 for (APLIST_TRAVERSE(osp->os_mstrisdescs, idx, isp)) {
2859*d9c5840bSRichard Lowe if (isdesc_discarded(isp))
2860*d9c5840bSRichard Lowe continue;
2861*d9c5840bSRichard Lowe
2862*d9c5840bSRichard Lowe /*
2863*d9c5840bSRichard Lowe * Input sections of 0 size are dubiously valid since they do
2864*d9c5840bSRichard Lowe * not even contain the NUL string. Ignore them.
2865*d9c5840bSRichard Lowe */
2866*d9c5840bSRichard Lowe if (isp->is_shdr->sh_size == 0)
2867cce0e03bSab196087 continue;
2868cce0e03bSab196087
2869cce0e03bSab196087 /*
2870cce0e03bSab196087 * We have at least one non-discarded section.
2871cce0e03bSab196087 * Create a string table descriptor.
2872cce0e03bSab196087 */
2873cce0e03bSab196087 if ((mstrtab = st_new(FLG_STNEW_COMPRESS)) == NULL)
2874cce0e03bSab196087 return (S_ERROR);
2875cce0e03bSab196087 break;
2876cce0e03bSab196087 }
2877cce0e03bSab196087
2878cce0e03bSab196087 /* If no string table was created, we have no mergeable sections */
2879cce0e03bSab196087 if (mstrtab == NULL)
2880cce0e03bSab196087 return (1);
2881cce0e03bSab196087
2882cce0e03bSab196087 /*
2883cce0e03bSab196087 * This routine has to make 3 passes:
2884cce0e03bSab196087 *
2885cce0e03bSab196087 * 1) Examine all relocations, insert strings from relocations
288608278a5eSRod Evans * to the mergeable input sections into the string table.
2887cce0e03bSab196087 * 2) Modify the relocation values to be correct for the
2888cce0e03bSab196087 * new merged section.
2889cce0e03bSab196087 * 3) Modify the symbols used by the relocations to reference
2890cce0e03bSab196087 * the new section.
2891cce0e03bSab196087 *
2892cce0e03bSab196087 * These passes cannot be combined:
2893cce0e03bSab196087 * - The string table code works in two passes, and all
2894cce0e03bSab196087 * strings have to be loaded in pass one before the
2895cce0e03bSab196087 * offset of any strings can be determined.
2896cce0e03bSab196087 * - Multiple relocations reference a single symbol, so the
2897cce0e03bSab196087 * symbol cannot be modified until all relocations are
2898cce0e03bSab196087 * fixed.
2899cce0e03bSab196087 *
2900cce0e03bSab196087 * The number of relocations related to section merging is usually
2901cce0e03bSab196087 * a mere fraction of the overall active and output relocation lists,
2902cce0e03bSab196087 * and the number of symbols is usually a fraction of the number
2903cce0e03bSab196087 * of related relocations. We therefore build APlists for the
2904cce0e03bSab196087 * relocations and symbols in the first pass, and then use those
2905cce0e03bSab196087 * lists to accelerate the operation of pass 2 and 3.
2906cce0e03bSab196087 *
2907cce0e03bSab196087 * Reinitialize the lists to a completely empty state.
2908cce0e03bSab196087 */
290957ef7aa9SRod Evans aplist_reset(*rel_alpp);
291057ef7aa9SRod Evans aplist_reset(*sym_alpp);
2911cce0e03bSab196087
2912cce0e03bSab196087 /*
2913cce0e03bSab196087 * Pass 1:
2914cce0e03bSab196087 *
2915cce0e03bSab196087 * Every relocation related to this output section (and the input
2916cce0e03bSab196087 * sections that make it up) is found in either the active, or the
2917cce0e03bSab196087 * output relocation list, depending on whether the relocation is to
2918cce0e03bSab196087 * be processed by this invocation of the linker, or inserted into the
2919cce0e03bSab196087 * output object.
2920cce0e03bSab196087 *
2921cce0e03bSab196087 * Build lists of relocations and symbols that will need modification,
2922cce0e03bSab196087 * and insert the strings they reference into the mstrtab string table.
2923cce0e03bSab196087 */
292457ef7aa9SRod Evans if (strmerge_pass1(ofl, osp, mstrtab, rel_alpp, sym_alpp,
2925bf994817SAli Bahrami &ofl->ofl_actrels) == 0)
2926cce0e03bSab196087 goto return_s_error;
292757ef7aa9SRod Evans if (strmerge_pass1(ofl, osp, mstrtab, rel_alpp, sym_alpp,
2928bf994817SAli Bahrami &ofl->ofl_outrels) == 0)
2929cce0e03bSab196087 goto return_s_error;
2930cce0e03bSab196087
2931cce0e03bSab196087 /*
2932cce0e03bSab196087 * Get the size of the new input section. Requesting the
2933cce0e03bSab196087 * string table size "cooks" the table, and finalizes its contents.
2934cce0e03bSab196087 */
2935cce0e03bSab196087 data_size = st_getstrtab_sz(mstrtab);
2936cce0e03bSab196087
2937cce0e03bSab196087 /* Create a new input section to hold the merged strings */
2938cce0e03bSab196087 if (new_section_from_template(ofl, isp, data_size,
2939cce0e03bSab196087 &mstrsec, &mstr_shdr, &mstr_data) == S_ERROR)
2940cce0e03bSab196087 goto return_s_error;
2941cce0e03bSab196087 mstrsec->is_flags |= FLG_IS_GNSTRMRG;
2942cce0e03bSab196087
2943cce0e03bSab196087 /*
2944cce0e03bSab196087 * Allocate a data buffer for the new input section.
2945cce0e03bSab196087 * Then, associate the buffer with the string table descriptor.
2946cce0e03bSab196087 */
294757ef7aa9SRod Evans if ((mstr_data->d_buf = libld_malloc(data_size)) == NULL)
2948cce0e03bSab196087 goto return_s_error;
2949cce0e03bSab196087 if (st_setstrbuf(mstrtab, mstr_data->d_buf, data_size) == -1)
2950cce0e03bSab196087 goto return_s_error;
2951cce0e03bSab196087
2952cce0e03bSab196087 /* Add the new section to the output image */
295369112eddSAli Bahrami if (ld_place_section(ofl, mstrsec, NULL, osp->os_identndx, NULL) ==
2954cce0e03bSab196087 (Os_desc *)S_ERROR)
2955cce0e03bSab196087 goto return_s_error;
2956cce0e03bSab196087
2957cce0e03bSab196087 /*
2958cce0e03bSab196087 * Pass 2:
2959cce0e03bSab196087 *
2960cce0e03bSab196087 * Revisit the relocation descriptors with STT_SECTION symbols
2961cce0e03bSab196087 * that were saved by the first pass. Update each relocation
2962cce0e03bSab196087 * record so that the offset it contains is for the new section
2963cce0e03bSab196087 * instead of the original.
2964cce0e03bSab196087 */
296557ef7aa9SRod Evans for (APLIST_TRAVERSE(*rel_alpp, idx, rsp)) {
2966cce0e03bSab196087 const char *name;
2967cce0e03bSab196087
2968cce0e03bSab196087 /* Put the string into the merged string table */
2969cce0e03bSab196087 name = strmerge_get_reloc_str(ofl, rsp);
2970cce0e03bSab196087 st_setstring_status = st_setstring(mstrtab, name, &stoff);
2971cce0e03bSab196087 if (st_setstring_status == -1) {
2972cce0e03bSab196087 /*
2973cce0e03bSab196087 * A failure to insert at this point means that
2974cce0e03bSab196087 * something is corrupt. This isn't a resource issue.
2975cce0e03bSab196087 */
2976cce0e03bSab196087 assert(st_setstring_status != -1);
2977cce0e03bSab196087 goto return_s_error;
2978cce0e03bSab196087 }
2979cce0e03bSab196087
2980cce0e03bSab196087 /*
2981cce0e03bSab196087 * Alter the relocation to access the string at the
2982cce0e03bSab196087 * new offset in our new string table.
2983cce0e03bSab196087 *
2984cce0e03bSab196087 * For SHT_RELA platforms, it suffices to simply
2985cce0e03bSab196087 * update the rel_raddend field of the relocation.
2986cce0e03bSab196087 *
2987cce0e03bSab196087 * For SHT_REL platforms, the new "addend" value
2988cce0e03bSab196087 * needs to be written at the address being relocated.
2989cce0e03bSab196087 * However, we can't alter the input sections which
2990cce0e03bSab196087 * are mapped readonly, and the output image has not
2991cce0e03bSab196087 * been created yet. So, we defer this operation,
2992cce0e03bSab196087 * using the rel_raddend field of the relocation
2993cce0e03bSab196087 * which is normally 0 on a REL platform, to pass the
2994cce0e03bSab196087 * new "addend" value to ld_perform_outreloc() or
2995cce0e03bSab196087 * ld_do_activerelocs(). The FLG_REL_NADDEND flag
2996cce0e03bSab196087 * tells them that this is the case.
2997cce0e03bSab196087 */
2998cce0e03bSab196087 if ((rsp->rel_flags & FLG_REL_RELA) == 0) /* REL */
2999cce0e03bSab196087 rsp->rel_flags |= FLG_REL_NADDEND;
3000cce0e03bSab196087 rsp->rel_raddend = (Sxword)stoff;
3001cce0e03bSab196087
3002cce0e03bSab196087 /*
3003bf994817SAli Bahrami * Generate a symbol name string for STT_SECTION symbols
3004bf994817SAli Bahrami * that might reference our merged section. This shows up
3005bf994817SAli Bahrami * in debug output and helps show how the relocation has
3006bf994817SAli Bahrami * changed from its original input section to our merged one.
3007cce0e03bSab196087 */
3008bf994817SAli Bahrami if (ld_stt_section_sym_name(mstrsec) == NULL)
3009cce0e03bSab196087 goto return_s_error;
3010cce0e03bSab196087 }
3011cce0e03bSab196087
3012cce0e03bSab196087 /*
3013cce0e03bSab196087 * Pass 3:
3014cce0e03bSab196087 *
3015cce0e03bSab196087 * Modify the symbols referenced by the relocation descriptors
3016cce0e03bSab196087 * so that they reference the new input section containing the
3017cce0e03bSab196087 * merged strings instead of the original input sections.
3018cce0e03bSab196087 */
301957ef7aa9SRod Evans for (APLIST_TRAVERSE(*sym_alpp, idx, sdp)) {
3020cce0e03bSab196087 /*
3021cce0e03bSab196087 * If we've already processed this symbol, don't do it
3022cce0e03bSab196087 * twice. strmerge_pass1() uses a heuristic (relocations to
3023cce0e03bSab196087 * the same symbol clump together) to avoid inserting a
3024cce0e03bSab196087 * given symbol more than once, but repeat symbols in
3025cce0e03bSab196087 * the list can occur.
3026cce0e03bSab196087 */
3027cce0e03bSab196087 if ((sdp->sd_isc->is_flags & FLG_IS_INSTRMRG) == 0)
3028cce0e03bSab196087 continue;
3029cce0e03bSab196087
3030cce0e03bSab196087 if (ELF_ST_TYPE(sdp->sd_sym->st_info) != STT_SECTION) {
3031cce0e03bSab196087 /*
3032cce0e03bSab196087 * This is not an STT_SECTION symbol, so its
3033cce0e03bSab196087 * value is the offset of the string within the
3034cce0e03bSab196087 * input section. Update the address to reflect
3035cce0e03bSab196087 * the address in our new merged section.
3036cce0e03bSab196087 */
3037cce0e03bSab196087 const char *name = sdp->sd_sym->st_value +
3038cce0e03bSab196087 (char *)sdp->sd_isc->is_indata->d_buf;
3039cce0e03bSab196087
3040cce0e03bSab196087 st_setstring_status =
3041cce0e03bSab196087 st_setstring(mstrtab, name, &stoff);
3042cce0e03bSab196087 if (st_setstring_status == -1) {
3043cce0e03bSab196087 /*
3044cce0e03bSab196087 * A failure to insert at this point means
3045cce0e03bSab196087 * something is corrupt. This isn't a
3046cce0e03bSab196087 * resource issue.
3047cce0e03bSab196087 */
3048cce0e03bSab196087 assert(st_setstring_status != -1);
3049cce0e03bSab196087 goto return_s_error;
3050cce0e03bSab196087 }
3051cce0e03bSab196087
3052cce0e03bSab196087 if (ld_sym_copy(sdp) == S_ERROR)
3053cce0e03bSab196087 goto return_s_error;
3054cce0e03bSab196087 sdp->sd_sym->st_value = (Word)stoff;
3055cce0e03bSab196087 }
3056cce0e03bSab196087
3057cce0e03bSab196087 /* Redirect the symbol to our new merged section */
3058cce0e03bSab196087 sdp->sd_isc = mstrsec;
3059cce0e03bSab196087 }
3060cce0e03bSab196087
3061cce0e03bSab196087 /*
3062cce0e03bSab196087 * There are no references left to the original input string sections.
3063cce0e03bSab196087 * Mark them as discarded so they don't go into the output image.
3064cce0e03bSab196087 * At the same time, add up the sizes of the replaced sections.
3065cce0e03bSab196087 */
3066cce0e03bSab196087 data_size = 0;
3067cce0e03bSab196087 for (APLIST_TRAVERSE(osp->os_mstrisdescs, idx, isp)) {
3068cce0e03bSab196087 if (isp->is_flags & (FLG_IS_DISCARD | FLG_IS_GNSTRMRG))
3069cce0e03bSab196087 continue;
3070cce0e03bSab196087
3071cce0e03bSab196087 data_size += isp->is_indata->d_size;
3072cce0e03bSab196087
3073cce0e03bSab196087 isp->is_flags |= FLG_IS_DISCARD;
3074cce0e03bSab196087 DBG_CALL(Dbg_sec_discarded(ofl->ofl_lml, isp, mstrsec));
3075cce0e03bSab196087 }
3076cce0e03bSab196087
3077cce0e03bSab196087 /* Report how much space we saved in the output section */
307869112eddSAli Bahrami DBG_CALL(Dbg_sec_genstr_compress(ofl->ofl_lml, osp->os_name, data_size,
307969112eddSAli Bahrami mstr_data->d_size));
3080cce0e03bSab196087
3081cce0e03bSab196087 st_destroy(mstrtab);
3082cce0e03bSab196087 return (1);
3083cce0e03bSab196087
3084cce0e03bSab196087 return_s_error:
3085cce0e03bSab196087 st_destroy(mstrtab);
3086cce0e03bSab196087 return (S_ERROR);
3087cce0e03bSab196087 }
3088cce0e03bSab196087
3089635216b6SRod Evans /*
3090635216b6SRod Evans * Update a data buffers size. A number of sections have to be created, and
3091635216b6SRod Evans * the sections header contributes to the size of the eventual section. Thus,
3092635216b6SRod Evans * a section may be created, and once all associated sections have been created,
3093635216b6SRod Evans * we return to establish the required section size.
3094635216b6SRod Evans */
3095635216b6SRod Evans inline static void
update_data_size(Os_desc * osp,ulong_t cnt)3096635216b6SRod Evans update_data_size(Os_desc *osp, ulong_t cnt)
3097635216b6SRod Evans {
3098635216b6SRod Evans Is_desc *isec = ld_os_first_isdesc(osp);
3099635216b6SRod Evans Elf_Data *data = isec->is_indata;
3100635216b6SRod Evans Shdr *shdr = osp->os_shdr;
3101635216b6SRod Evans size_t size = cnt * shdr->sh_entsize;
3102635216b6SRod Evans
3103635216b6SRod Evans shdr->sh_size = (Xword)size;
3104635216b6SRod Evans data->d_size = size;
3105635216b6SRod Evans }
3106cce0e03bSab196087
3107cce0e03bSab196087 /*
31087c478bd9Sstevel@tonic-gate * The following sections are built after all input file processing and symbol
31097c478bd9Sstevel@tonic-gate * validation has been carried out. The order is important (because the
31107c478bd9Sstevel@tonic-gate * addition of a section adds a new symbol there is a chicken and egg problem
31117c478bd9Sstevel@tonic-gate * of maintaining the appropriate counts). By maintaining a known order the
31127c478bd9Sstevel@tonic-gate * individual routines can compensate for later, known, additions.
31137c478bd9Sstevel@tonic-gate */
31147c478bd9Sstevel@tonic-gate uintptr_t
ld_make_sections(Ofl_desc * ofl)31155aefb655Srie ld_make_sections(Ofl_desc *ofl)
31167c478bd9Sstevel@tonic-gate {
31171d9df23bSab196087 ofl_flag_t flags = ofl->ofl_flags;
31187c478bd9Sstevel@tonic-gate Sg_desc *sgp;
31197c478bd9Sstevel@tonic-gate
31207c478bd9Sstevel@tonic-gate /*
31217c478bd9Sstevel@tonic-gate * Generate any special sections.
31227c478bd9Sstevel@tonic-gate */
31237c478bd9Sstevel@tonic-gate if (flags & FLG_OF_ADDVERS)
31247c478bd9Sstevel@tonic-gate if (make_comment(ofl) == S_ERROR)
31257c478bd9Sstevel@tonic-gate return (S_ERROR);
31267c478bd9Sstevel@tonic-gate
31277c478bd9Sstevel@tonic-gate if (make_interp(ofl) == S_ERROR)
31287c478bd9Sstevel@tonic-gate return (S_ERROR);
31297c478bd9Sstevel@tonic-gate
313008278a5eSRod Evans /*
313108278a5eSRod Evans * Create a capabilities section if required.
313208278a5eSRod Evans */
313308278a5eSRod Evans if (make_cap(ofl, SHT_SUNW_cap, MSG_ORIG(MSG_SCN_SUNWCAP),
313408278a5eSRod Evans ld_targ.t_id.id_cap) == S_ERROR)
31357c478bd9Sstevel@tonic-gate return (S_ERROR);
31367c478bd9Sstevel@tonic-gate
313708278a5eSRod Evans /*
313808278a5eSRod Evans * Create any init/fini array sections.
313908278a5eSRod Evans */
31407c478bd9Sstevel@tonic-gate if (make_array(ofl, SHT_INIT_ARRAY, MSG_ORIG(MSG_SCN_INITARRAY),
314157ef7aa9SRod Evans ofl->ofl_initarray) == S_ERROR)
31427c478bd9Sstevel@tonic-gate return (S_ERROR);
31437c478bd9Sstevel@tonic-gate
31447c478bd9Sstevel@tonic-gate if (make_array(ofl, SHT_FINI_ARRAY, MSG_ORIG(MSG_SCN_FINIARRAY),
314557ef7aa9SRod Evans ofl->ofl_finiarray) == S_ERROR)
31467c478bd9Sstevel@tonic-gate return (S_ERROR);
31477c478bd9Sstevel@tonic-gate
31487c478bd9Sstevel@tonic-gate if (make_array(ofl, SHT_PREINIT_ARRAY, MSG_ORIG(MSG_SCN_PREINITARRAY),
314957ef7aa9SRod Evans ofl->ofl_preiarray) == S_ERROR)
31507c478bd9Sstevel@tonic-gate return (S_ERROR);
31517c478bd9Sstevel@tonic-gate
31527c478bd9Sstevel@tonic-gate /*
31537c478bd9Sstevel@tonic-gate * Make the .plt section. This occurs after any other relocation
31547c478bd9Sstevel@tonic-gate * sections are generated (see reloc_init()) to ensure that the
31557c478bd9Sstevel@tonic-gate * associated relocation section is after all the other relocation
31567c478bd9Sstevel@tonic-gate * sections.
31577c478bd9Sstevel@tonic-gate */
31587c478bd9Sstevel@tonic-gate if ((ofl->ofl_pltcnt) || (ofl->ofl_pltpad))
31597c478bd9Sstevel@tonic-gate if (make_plt(ofl) == S_ERROR)
31607c478bd9Sstevel@tonic-gate return (S_ERROR);
31617c478bd9Sstevel@tonic-gate
3162fb1354edSrie /*
3163fb1354edSrie * Determine whether any sections or files are not referenced. Under
3164fb1354edSrie * -Dunused a diagnostic for any unused components is generated, under
3165fb1354edSrie * -zignore the component is removed from the final output.
3166fb1354edSrie */
31675aefb655Srie if (DBG_ENABLED || (ofl->ofl_flags1 & FLG_OF1_IGNPRC)) {
31687c478bd9Sstevel@tonic-gate if (ignore_section_processing(ofl) == S_ERROR)
31697c478bd9Sstevel@tonic-gate return (S_ERROR);
31707c478bd9Sstevel@tonic-gate }
31717c478bd9Sstevel@tonic-gate
31727c478bd9Sstevel@tonic-gate /*
3173e64d0ff9SAli Bahrami * If we have detected a situation in which previously placed
3174e64d0ff9SAli Bahrami * output sections may have been discarded, perform the necessary
3175e64d0ff9SAli Bahrami * readjustment.
3176e64d0ff9SAli Bahrami */
3177e64d0ff9SAli Bahrami if (ofl->ofl_flags & FLG_OF_ADJOSCNT)
3178e64d0ff9SAli Bahrami adjust_os_count(ofl);
3179e64d0ff9SAli Bahrami
3180e64d0ff9SAli Bahrami /*
3181cce0e03bSab196087 * Do any of the output sections contain input sections that
3182cce0e03bSab196087 * are candidates for string table merging? For each such case,
3183cce0e03bSab196087 * we create a replacement section, insert it, and discard the
3184cce0e03bSab196087 * originals.
3185cce0e03bSab196087 *
318657ef7aa9SRod Evans * rel_alpp and sym_alpp are used by ld_make_strmerge()
3187cce0e03bSab196087 * for its internal processing. We are responsible for the
3188cce0e03bSab196087 * initialization and cleanup, and ld_make_strmerge() handles the rest.
318957ef7aa9SRod Evans * This allows us to reuse a single pair of memory buffers, allocated
319057ef7aa9SRod Evans * for this processing, for all the output sections.
3191cce0e03bSab196087 */
3192cce0e03bSab196087 if ((ofl->ofl_flags1 & FLG_OF1_NCSTTAB) == 0) {
3193cce0e03bSab196087 int error_seen = 0;
319457ef7aa9SRod Evans APlist *rel_alpp = NULL;
319557ef7aa9SRod Evans APlist *sym_alpp = NULL;
319657ef7aa9SRod Evans Aliste idx1;
3197cce0e03bSab196087
319857ef7aa9SRod Evans for (APLIST_TRAVERSE(ofl->ofl_segs, idx1, sgp)) {
3199cce0e03bSab196087 Os_desc *osp;
320057ef7aa9SRod Evans Aliste idx2;
3201cce0e03bSab196087
320257ef7aa9SRod Evans for (APLIST_TRAVERSE(sgp->sg_osdescs, idx2, osp))
3203cce0e03bSab196087 if ((osp->os_mstrisdescs != NULL) &&
3204cce0e03bSab196087 (ld_make_strmerge(ofl, osp,
320557ef7aa9SRod Evans &rel_alpp, &sym_alpp) ==
3206cce0e03bSab196087 S_ERROR)) {
3207cce0e03bSab196087 error_seen = 1;
3208cce0e03bSab196087 break;
3209cce0e03bSab196087 }
3210cce0e03bSab196087 }
321157ef7aa9SRod Evans if (rel_alpp != NULL)
321269112eddSAli Bahrami libld_free(rel_alpp);
321357ef7aa9SRod Evans if (sym_alpp != NULL)
321469112eddSAli Bahrami libld_free(sym_alpp);
3215cce0e03bSab196087 if (error_seen != 0)
3216cce0e03bSab196087 return (S_ERROR);
3217cce0e03bSab196087 }
3218cce0e03bSab196087
3219cce0e03bSab196087 /*
32207c478bd9Sstevel@tonic-gate * Add any necessary versioning information.
32217c478bd9Sstevel@tonic-gate */
3222090a8d9eSAli Bahrami if (!(flags & FLG_OF_NOVERSEC)) {
3223090a8d9eSAli Bahrami if ((flags & FLG_OF_VERNEED) &&
3224090a8d9eSAli Bahrami (make_verneed(ofl) == S_ERROR))
32257c478bd9Sstevel@tonic-gate return (S_ERROR);
3226090a8d9eSAli Bahrami if ((flags & FLG_OF_VERDEF) &&
3227090a8d9eSAli Bahrami (make_verdef(ofl) == S_ERROR))
32287c478bd9Sstevel@tonic-gate return (S_ERROR);
3229090a8d9eSAli Bahrami if ((flags & (FLG_OF_VERNEED | FLG_OF_VERDEF)) &&
3230090a8d9eSAli Bahrami ((ofl->ofl_osversym = make_sym_sec(ofl,
32319039eeafSab196087 MSG_ORIG(MSG_SCN_SUNWVERSYM), SHT_SUNW_versym,
3232090a8d9eSAli Bahrami ld_targ.t_id.id_version)) == (Os_desc*)S_ERROR))
32337c478bd9Sstevel@tonic-gate return (S_ERROR);
32347c478bd9Sstevel@tonic-gate }
32357c478bd9Sstevel@tonic-gate
32367c478bd9Sstevel@tonic-gate /*
32379039eeafSab196087 * Create a syminfo section if necessary.
32387c478bd9Sstevel@tonic-gate */
32391d9df23bSab196087 if (flags & FLG_OF_SYMINFO) {
32407c478bd9Sstevel@tonic-gate if ((ofl->ofl_ossyminfo = make_sym_sec(ofl,
32419039eeafSab196087 MSG_ORIG(MSG_SCN_SUNWSYMINFO), SHT_SUNW_syminfo,
3242ba2be530Sab196087 ld_targ.t_id.id_syminfo)) == (Os_desc *)S_ERROR)
32437c478bd9Sstevel@tonic-gate return (S_ERROR);
32447c478bd9Sstevel@tonic-gate }
32457c478bd9Sstevel@tonic-gate
32461d9df23bSab196087 if (flags & FLG_OF_COMREL) {
32477c478bd9Sstevel@tonic-gate /*
32487c478bd9Sstevel@tonic-gate * If -zcombreloc is enabled then all relocations (except for
32497c478bd9Sstevel@tonic-gate * the PLT's) are coalesced into a single relocation section.
32507c478bd9Sstevel@tonic-gate */
32517c478bd9Sstevel@tonic-gate if (ofl->ofl_reloccnt) {
32527c478bd9Sstevel@tonic-gate if (make_reloc(ofl, NULL) == S_ERROR)
32537c478bd9Sstevel@tonic-gate return (S_ERROR);
32547c478bd9Sstevel@tonic-gate }
32557c478bd9Sstevel@tonic-gate } else {
325657ef7aa9SRod Evans Aliste idx1;
325757ef7aa9SRod Evans
32587c478bd9Sstevel@tonic-gate /*
32590bc07c75Srie * Create the required output relocation sections. Note, new
32600bc07c75Srie * sections may be added to the section list that is being
32610bc07c75Srie * traversed. These insertions can move the elements of the
32620bc07c75Srie * Alist such that a section descriptor is re-read. Recursion
32630bc07c75Srie * is prevented by maintaining a previous section pointer and
32640bc07c75Srie * insuring that this pointer isn't re-examined.
32657c478bd9Sstevel@tonic-gate */
326657ef7aa9SRod Evans for (APLIST_TRAVERSE(ofl->ofl_segs, idx1, sgp)) {
3267cce0e03bSab196087 Os_desc *osp, *posp = 0;
326857ef7aa9SRod Evans Aliste idx2;
32697c478bd9Sstevel@tonic-gate
327057ef7aa9SRod Evans for (APLIST_TRAVERSE(sgp->sg_osdescs, idx2, osp)) {
32710bc07c75Srie if ((osp != posp) && osp->os_szoutrels &&
32727c478bd9Sstevel@tonic-gate (osp != ofl->ofl_osplt)) {
32737c478bd9Sstevel@tonic-gate if (make_reloc(ofl, osp) == S_ERROR)
32747c478bd9Sstevel@tonic-gate return (S_ERROR);
32757c478bd9Sstevel@tonic-gate }
32760bc07c75Srie posp = osp;
32777c478bd9Sstevel@tonic-gate }
32787c478bd9Sstevel@tonic-gate }
32797c478bd9Sstevel@tonic-gate
32807c478bd9Sstevel@tonic-gate /*
32817c478bd9Sstevel@tonic-gate * If we're not building a combined relocation section, then
32827c478bd9Sstevel@tonic-gate * build a .rel[a] section as required.
32837c478bd9Sstevel@tonic-gate */
32847c478bd9Sstevel@tonic-gate if (ofl->ofl_relocrelsz) {
32857c478bd9Sstevel@tonic-gate if (make_reloc(ofl, NULL) == S_ERROR)
32867c478bd9Sstevel@tonic-gate return (S_ERROR);
32877c478bd9Sstevel@tonic-gate }
32887c478bd9Sstevel@tonic-gate }
32897c478bd9Sstevel@tonic-gate
32907c478bd9Sstevel@tonic-gate /*
32917c478bd9Sstevel@tonic-gate * The PLT relocations are always in their own section, and we try to
32927c478bd9Sstevel@tonic-gate * keep them at the end of the PLT table. We do this to keep the hot
32937c478bd9Sstevel@tonic-gate * "data" PLT's at the head of the table nearer the .dynsym & .hash.
32947c478bd9Sstevel@tonic-gate */
32957c478bd9Sstevel@tonic-gate if (ofl->ofl_osplt && ofl->ofl_relocpltsz) {
32967c478bd9Sstevel@tonic-gate if (make_reloc(ofl, ofl->ofl_osplt) == S_ERROR)
32977c478bd9Sstevel@tonic-gate return (S_ERROR);
32987c478bd9Sstevel@tonic-gate }
32997c478bd9Sstevel@tonic-gate
33007c478bd9Sstevel@tonic-gate /*
33017c478bd9Sstevel@tonic-gate * Finally build the symbol and section header sections.
33027c478bd9Sstevel@tonic-gate */
33037c478bd9Sstevel@tonic-gate if (flags & FLG_OF_DYNAMIC) {
33047c478bd9Sstevel@tonic-gate if (make_dynamic(ofl) == S_ERROR)
33057c478bd9Sstevel@tonic-gate return (S_ERROR);
3306635216b6SRod Evans
33077c478bd9Sstevel@tonic-gate /*
3308635216b6SRod Evans * A number of sections aren't necessary within a relocatable
3309635216b6SRod Evans * object, even if -dy has been used.
33107c478bd9Sstevel@tonic-gate */
33117c478bd9Sstevel@tonic-gate if (!(flags & FLG_OF_RELOBJ)) {
33127c478bd9Sstevel@tonic-gate if (make_hash(ofl) == S_ERROR)
33137c478bd9Sstevel@tonic-gate return (S_ERROR);
3314635216b6SRod Evans if (make_dynstr(ofl) == S_ERROR)
3315635216b6SRod Evans return (S_ERROR);
33167c478bd9Sstevel@tonic-gate if (make_dynsym(ofl) == S_ERROR)
33177c478bd9Sstevel@tonic-gate return (S_ERROR);
33187e16fca0SAli Bahrami if (ld_unwind_make_hdr(ofl) == S_ERROR)
33197c478bd9Sstevel@tonic-gate return (S_ERROR);
3320d579eb63Sab196087 if (make_dynsort(ofl) == S_ERROR)
3321d579eb63Sab196087 return (S_ERROR);
33227c478bd9Sstevel@tonic-gate }
33237c478bd9Sstevel@tonic-gate }
33247c478bd9Sstevel@tonic-gate
33257c478bd9Sstevel@tonic-gate if (!(flags & FLG_OF_STRIP) || (flags & FLG_OF_RELOBJ) ||
33267c478bd9Sstevel@tonic-gate ((flags & FLG_OF_STATIC) && ofl->ofl_osversym)) {
33277c478bd9Sstevel@tonic-gate /*
33287c478bd9Sstevel@tonic-gate * Do we need to make a SHT_SYMTAB_SHNDX section
33297c478bd9Sstevel@tonic-gate * for the dynsym. If so - do it now.
33307c478bd9Sstevel@tonic-gate */
33317c478bd9Sstevel@tonic-gate if (ofl->ofl_osdynsym &&
33327c478bd9Sstevel@tonic-gate ((ofl->ofl_shdrcnt + 3) >= SHN_LORESERVE)) {
33337c478bd9Sstevel@tonic-gate if (make_dynsym_shndx(ofl) == S_ERROR)
33347c478bd9Sstevel@tonic-gate return (S_ERROR);
33357c478bd9Sstevel@tonic-gate }
33367c478bd9Sstevel@tonic-gate
33377c478bd9Sstevel@tonic-gate if (make_strtab(ofl) == S_ERROR)
33387c478bd9Sstevel@tonic-gate return (S_ERROR);
33397c478bd9Sstevel@tonic-gate if (make_symtab(ofl) == S_ERROR)
33407c478bd9Sstevel@tonic-gate return (S_ERROR);
33417c478bd9Sstevel@tonic-gate } else {
33427c478bd9Sstevel@tonic-gate /*
33437c478bd9Sstevel@tonic-gate * Do we need to make a SHT_SYMTAB_SHNDX section
33447c478bd9Sstevel@tonic-gate * for the dynsym. If so - do it now.
33457c478bd9Sstevel@tonic-gate */
33467c478bd9Sstevel@tonic-gate if (ofl->ofl_osdynsym &&
33477c478bd9Sstevel@tonic-gate ((ofl->ofl_shdrcnt + 1) >= SHN_LORESERVE)) {
33487c478bd9Sstevel@tonic-gate if (make_dynsym_shndx(ofl) == S_ERROR)
33497c478bd9Sstevel@tonic-gate return (S_ERROR);
33507c478bd9Sstevel@tonic-gate }
33517c478bd9Sstevel@tonic-gate }
33527c478bd9Sstevel@tonic-gate
33537c478bd9Sstevel@tonic-gate if (make_shstrtab(ofl) == S_ERROR)
33547c478bd9Sstevel@tonic-gate return (S_ERROR);
33557c478bd9Sstevel@tonic-gate
33567c478bd9Sstevel@tonic-gate /*
3357635216b6SRod Evans * Now that we've created all output sections, adjust the size of the
3358635216b6SRod Evans * SHT_SUNW_versym and SHT_SUNW_syminfo section, which are dependent on
3359635216b6SRod Evans * the associated symbol table sizes.
33607c478bd9Sstevel@tonic-gate */
33617c478bd9Sstevel@tonic-gate if (ofl->ofl_osversym || ofl->ofl_ossyminfo) {
33627c478bd9Sstevel@tonic-gate ulong_t cnt;
3363635216b6SRod Evans Is_desc *isp;
336460758829Srie Os_desc *osp;
33657c478bd9Sstevel@tonic-gate
3366635216b6SRod Evans if (OFL_IS_STATIC_OBJ(ofl))
336760758829Srie osp = ofl->ofl_ossymtab;
3368635216b6SRod Evans else
336960758829Srie osp = ofl->ofl_osdynsym;
33707c478bd9Sstevel@tonic-gate
3371635216b6SRod Evans isp = ld_os_first_isdesc(osp);
3372635216b6SRod Evans cnt = (isp->is_shdr->sh_size / isp->is_shdr->sh_entsize);
3373635216b6SRod Evans
3374635216b6SRod Evans if (ofl->ofl_osversym)
3375635216b6SRod Evans update_data_size(ofl->ofl_osversym, cnt);
3376635216b6SRod Evans
3377635216b6SRod Evans if (ofl->ofl_ossyminfo)
3378635216b6SRod Evans update_data_size(ofl->ofl_ossyminfo, cnt);
33797c478bd9Sstevel@tonic-gate }
33807c478bd9Sstevel@tonic-gate
338108278a5eSRod Evans /*
338208278a5eSRod Evans * Now that we've created all output sections, adjust the size of the
338308278a5eSRod Evans * SHT_SUNW_capinfo, which is dependent on the associated symbol table
338408278a5eSRod Evans * size.
338508278a5eSRod Evans */
338608278a5eSRod Evans if (ofl->ofl_oscapinfo) {
338708278a5eSRod Evans ulong_t cnt;
338808278a5eSRod Evans
338908278a5eSRod Evans /*
339008278a5eSRod Evans * Symbol capabilities symbols are placed directly after the
339108278a5eSRod Evans * STT_FILE symbol, section symbols, and any register symbols.
339208278a5eSRod Evans * Effectively these are the first of any series of demoted
339308278a5eSRod Evans * (scoped) symbols.
339408278a5eSRod Evans */
339508278a5eSRod Evans if (OFL_IS_STATIC_OBJ(ofl))
339608278a5eSRod Evans cnt = SYMTAB_ALL_CNT(ofl);
339708278a5eSRod Evans else
339808278a5eSRod Evans cnt = DYNSYM_ALL_CNT(ofl);
339908278a5eSRod Evans
340008278a5eSRod Evans update_data_size(ofl->ofl_oscapinfo, cnt);
340108278a5eSRod Evans }
34027c478bd9Sstevel@tonic-gate return (1);
34037c478bd9Sstevel@tonic-gate }
3404c1c6f601Srie
3405c1c6f601Srie /*
3406c1c6f601Srie * Build an additional data section - used to back OBJT symbol definitions
3407c1c6f601Srie * added with a mapfile.
3408c1c6f601Srie */
3409c1c6f601Srie Is_desc *
ld_make_data(Ofl_desc * ofl,size_t size)3410c1c6f601Srie ld_make_data(Ofl_desc *ofl, size_t size)
3411c1c6f601Srie {
3412c1c6f601Srie Shdr *shdr;
3413c1c6f601Srie Elf_Data *data;
3414c1c6f601Srie Is_desc *isec;
3415c1c6f601Srie
34169039eeafSab196087 if (new_section(ofl, SHT_PROGBITS, MSG_ORIG(MSG_SCN_DATA), 0,
34179039eeafSab196087 &isec, &shdr, &data) == S_ERROR)
3418c1c6f601Srie return ((Is_desc *)S_ERROR);
34199039eeafSab196087
3420c1c6f601Srie data->d_size = size;
3421c1c6f601Srie shdr->sh_size = (Xword)size;
34229039eeafSab196087 shdr->sh_flags |= SHF_WRITE;
3423c1c6f601Srie
342457ef7aa9SRod Evans if (aplist_append(&ofl->ofl_mapdata, isec, AL_CNT_OFL_MAPSECS) == NULL)
3425c1c6f601Srie return ((Is_desc *)S_ERROR);
3426c1c6f601Srie
3427c1c6f601Srie return (isec);
3428c1c6f601Srie }
3429c1c6f601Srie
3430c1c6f601Srie /*
3431c1c6f601Srie * Build an additional text section - used to back FUNC symbol definitions
3432c1c6f601Srie * added with a mapfile.
3433c1c6f601Srie */
3434c1c6f601Srie Is_desc *
ld_make_text(Ofl_desc * ofl,size_t size)3435c1c6f601Srie ld_make_text(Ofl_desc *ofl, size_t size)
3436c1c6f601Srie {
3437c1c6f601Srie Shdr *shdr;
3438c1c6f601Srie Elf_Data *data;
3439c1c6f601Srie Is_desc *isec;
3440c1c6f601Srie
3441c1c6f601Srie /*
3442c1c6f601Srie * Insure the size is sufficient to contain the minimum return
3443c1c6f601Srie * instruction.
3444c1c6f601Srie */
3445ba2be530Sab196087 if (size < ld_targ.t_nf.nf_size)
3446ba2be530Sab196087 size = ld_targ.t_nf.nf_size;
3447c1c6f601Srie
34489039eeafSab196087 if (new_section(ofl, SHT_PROGBITS, MSG_ORIG(MSG_SCN_TEXT), 0,
34499039eeafSab196087 &isec, &shdr, &data) == S_ERROR)
3450c1c6f601Srie return ((Is_desc *)S_ERROR);
34519039eeafSab196087
3452c1c6f601Srie data->d_size = size;
3453c1c6f601Srie shdr->sh_size = (Xword)size;
34549039eeafSab196087 shdr->sh_flags |= SHF_EXECINSTR;
3455c1c6f601Srie
3456ba2be530Sab196087 /*
3457ba2be530Sab196087 * Fill the buffer with the appropriate return instruction.
3458ba2be530Sab196087 * Note that there is no need to swap bytes on a non-native,
3459ba2be530Sab196087 * link, as the data being copied is given in bytes.
3460ba2be530Sab196087 */
346157ef7aa9SRod Evans if ((data->d_buf = libld_calloc(size, 1)) == NULL)
3462c1c6f601Srie return ((Is_desc *)S_ERROR);
3463ba2be530Sab196087 (void) memcpy(data->d_buf, ld_targ.t_nf.nf_template,
3464ba2be530Sab196087 ld_targ.t_nf.nf_size);
3465c1c6f601Srie
34663c573fccSAli Bahrami /*
34673c573fccSAli Bahrami * If size was larger than required, and the target supplies
34683c573fccSAli Bahrami * a fill function, use it to fill the balance. If there is no
34693c573fccSAli Bahrami * fill function, we accept the 0-fill supplied by libld_calloc().
34703c573fccSAli Bahrami */
34713c573fccSAli Bahrami if ((ld_targ.t_ff.ff_execfill != NULL) && (size > ld_targ.t_nf.nf_size))
34723c573fccSAli Bahrami ld_targ.t_ff.ff_execfill(data->d_buf, ld_targ.t_nf.nf_size,
34733c573fccSAli Bahrami size - ld_targ.t_nf.nf_size);
34743c573fccSAli Bahrami
347557ef7aa9SRod Evans if (aplist_append(&ofl->ofl_maptext, isec, AL_CNT_OFL_MAPSECS) == NULL)
3476c1c6f601Srie return ((Is_desc *)S_ERROR);
3477c1c6f601Srie
3478c1c6f601Srie return (isec);
3479c1c6f601Srie }
3480ef16f6b5SRichard Lowe
3481ef16f6b5SRichard Lowe void
ld_comdat_validate(Ofl_desc * ofl,Ifl_desc * ifl)3482ef16f6b5SRichard Lowe ld_comdat_validate(Ofl_desc *ofl, Ifl_desc *ifl)
3483ef16f6b5SRichard Lowe {
3484ef16f6b5SRichard Lowe int i;
3485ef16f6b5SRichard Lowe
3486ef16f6b5SRichard Lowe for (i = 0; i < ifl->ifl_shnum; i++) {
3487ef16f6b5SRichard Lowe Is_desc *isp = ifl->ifl_isdesc[i];
3488ef16f6b5SRichard Lowe int types = 0;
3489ef16f6b5SRichard Lowe char buf[1024] = "";
3490ef16f6b5SRichard Lowe Group_desc *gr = NULL;
3491ef16f6b5SRichard Lowe
3492ef16f6b5SRichard Lowe if ((isp == NULL) || (isp->is_flags & FLG_IS_COMDAT) == 0)
3493ef16f6b5SRichard Lowe continue;
3494ef16f6b5SRichard Lowe
3495ef16f6b5SRichard Lowe if (isp->is_shdr->sh_type == SHT_SUNW_COMDAT) {
3496ef16f6b5SRichard Lowe types++;
3497ef16f6b5SRichard Lowe (void) strlcpy(buf, MSG_ORIG(MSG_STR_SUNW_COMDAT),
3498ef16f6b5SRichard Lowe sizeof (buf));
3499ef16f6b5SRichard Lowe }
3500ef16f6b5SRichard Lowe
3501ef16f6b5SRichard Lowe if (strncmp(MSG_ORIG(MSG_SCN_GNU_LINKONCE), isp->is_name,
3502ef16f6b5SRichard Lowe MSG_SCN_GNU_LINKONCE_SIZE) == 0) {
3503ef16f6b5SRichard Lowe types++;
3504ef16f6b5SRichard Lowe if (types > 1)
3505ef16f6b5SRichard Lowe (void) strlcat(buf, ", ", sizeof (buf));
3506ef16f6b5SRichard Lowe (void) strlcat(buf, MSG_ORIG(MSG_SCN_GNU_LINKONCE),
3507ef16f6b5SRichard Lowe sizeof (buf));
3508ef16f6b5SRichard Lowe }
3509ef16f6b5SRichard Lowe
3510ef16f6b5SRichard Lowe if ((isp->is_shdr->sh_flags & SHF_GROUP) &&
3511ef16f6b5SRichard Lowe ((gr = ld_get_group(ofl, isp)) != NULL) &&
3512ef16f6b5SRichard Lowe (gr->gd_data[0] & GRP_COMDAT)) {
3513ef16f6b5SRichard Lowe types++;
3514ef16f6b5SRichard Lowe if (types > 1)
3515ef16f6b5SRichard Lowe (void) strlcat(buf, ", ", sizeof (buf));
3516ef16f6b5SRichard Lowe (void) strlcat(buf, MSG_ORIG(MSG_STR_GROUP),
3517ef16f6b5SRichard Lowe sizeof (buf));
3518ef16f6b5SRichard Lowe }
3519ef16f6b5SRichard Lowe
3520ef16f6b5SRichard Lowe if (types > 1)
3521ef16f6b5SRichard Lowe ld_eprintf(ofl, ERR_FATAL,
3522ef16f6b5SRichard Lowe MSG_INTL(MSG_SCN_MULTICOMDAT), ifl->ifl_name,
3523ef16f6b5SRichard Lowe EC_WORD(isp->is_scnndx), isp->is_name, buf);
3524ef16f6b5SRichard Lowe }
3525ef16f6b5SRichard Lowe }
3526