4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
32 * Scan all partially initialized symbols to determine what output Move sections
33 * or partially expanded data section, must be created.
36 make_mvsections(Ofl_desc
*ofl
)
41 Xword align_parexpn
= 0; /* for -z nopartial .data sec */
42 size_t size_parexpn
= 0; /* size of parexpn section */
45 * Compute the size of the output move section
47 for (APLIST_TRAVERSE(ofl
->ofl_parsyms
, idx
, sdp
)) {
48 if (sdp
->sd_flags
& FLG_SY_PAREXPN
) {
49 Sym
*sym
= sdp
->sd_sym
;
52 if (sym
->st_shndx
== SHN_COMMON
)
53 align_val
= sym
->st_value
;
58 * This global symbol is redirected to the special
59 * partial initialization .data section.
61 size_parexpn
= (size_t)S_ROUND(size_parexpn
,
62 sym
->st_value
) + sym
->st_size
;
63 if (align_val
> align_parexpn
)
64 align_parexpn
= align_val
;
67 mv_nums
+= alist_nitems(sdp
->sd_move
);
72 * Generate a new Move section.
74 if (mv_nums
&& (ld_make_sunwmove(ofl
, mv_nums
) == S_ERROR
))
78 * Add empty area for partially initialized symbols.
80 * A special .data section is created when the '-z nopartial'
81 * option is in effect in order to receive the expanded data.
85 if (ld_make_parexpn_data(ofl
, size_parexpn
,
86 align_parexpn
) == S_ERROR
)
93 * Assign move descriptors with the associated target symbol.
96 append_move_desc(Ofl_desc
*ofl
, Sym_desc
*sdp
, Move
*mvp
, Is_desc
*isp
)
98 int i
, cnt
= mvp
->m_repeat
;
100 for (i
= 0; i
< cnt
; i
++) {
105 nmd
.md_len
= ELF_M_SIZE(mvp
->m_info
);
106 nmd
.md_start
= mvp
->m_poffset
+ i
*
107 ((mvp
->m_stride
+ 1) * nmd
.md_len
);
111 * Verify that this move descriptor doesn't overlap any existing
114 for (ALIST_TRAVERSE(sdp
->sd_move
, idx
, omdp
)) {
115 Mv_desc
*smdp
, *lmdp
;
117 if (nmd
.md_start
> omdp
->md_start
) {
126 * If this move entry is exactly the same as that of
127 * a symbol that has overridden this symbol (for example
128 * should two identical COMMON definitions be associated
129 * with the same move data), simply ignore this move
132 if ((nmd
.md_start
== omdp
->md_start
) &&
133 ((nmd
.md_len
== smdp
->md_len
) &&
134 sdp
->sd_file
!= isp
->is_file
))
137 if ((nmd
.md_start
!= omdp
->md_start
) &&
138 ((smdp
->md_start
+ smdp
->md_len
) <= lmdp
->md_start
))
141 ld_eprintf(ofl
, ERR_FATAL
, MSG_INTL(MSG_MOVE_OVERLAP
),
142 sdp
->sd_file
->ifl_name
, EC_WORD(isp
->is_scnndx
),
143 isp
->is_name
, demangle(sdp
->sd_name
),
144 EC_XWORD(nmd
.md_start
), EC_XWORD(nmd
.md_len
),
145 EC_XWORD(omdp
->md_start
), EC_XWORD(omdp
->md_len
));
148 * Indicate that an error has occurred, so that
149 * processing can be terminated once all move errors
152 sdp
->sd_flags
|= FLG_SY_OVERLAP
;
156 if (alist_append(&sdp
->sd_move
, &nmd
, sizeof (Mv_desc
),
157 AL_CNT_SDP_MOVE
) == NULL
)
164 * Validate a SHT_SUNW_move section. These are only processed from input
165 * relocatable objects. The move section entries are validated and any data
166 * structures required for later processing are created.
169 ld_process_move(Ofl_desc
*ofl
)
175 for (APLIST_TRAVERSE(ofl
->ofl_ismove
, idx
, isp
)) {
176 Ifl_desc
*ifile
= isp
->is_file
;
180 DBG_CALL(Dbg_move_input(ofl
->ofl_lml
, ifile
->ifl_name
));
181 mvp
= (Move
*)isp
->is_indata
->d_buf
;
183 if (isp
->is_shdr
->sh_entsize
== 0) {
184 ld_eprintf(ofl
, ERR_FATAL
,
185 MSG_INTL(MSG_FIL_INVSHENTSIZE
),
186 isp
->is_file
->ifl_name
, EC_WORD(isp
->is_scnndx
),
187 isp
->is_name
, EC_XWORD(0));
190 num
= isp
->is_shdr
->sh_size
/ isp
->is_shdr
->sh_entsize
;
192 for (i
= 0; i
< num
; i
++) {
193 Xword ndx
= ELF_M_SYM(mvp
->m_info
);
197 if ((ndx
>= (Xword
) isp
->is_file
->ifl_symscnt
) ||
199 ld_eprintf(ofl
, ERR_FATAL
,
200 MSG_INTL(MSG_PSYM_INVMINFO1
),
201 isp
->is_file
->ifl_name
,
202 EC_WORD(isp
->is_scnndx
), isp
->is_name
, i
,
203 EC_XWORD(mvp
->m_info
));
206 if (mvp
->m_repeat
== 0) {
207 ld_eprintf(ofl
, ERR_FATAL
,
208 MSG_INTL(MSG_PSYM_INVMREPEAT
),
209 isp
->is_file
->ifl_name
,
210 EC_WORD(isp
->is_scnndx
), isp
->is_name
, i
,
211 EC_XWORD(mvp
->m_repeat
));
215 sdp
= isp
->is_file
->ifl_oldndx
[ndx
];
216 DBG_CALL(Dbg_move_entry1(ofl
->ofl_lml
, 1, mvp
, sdp
));
219 * Validate that this entry has a valid size.
222 switch (ELF_M_SIZE(mvp
->m_info
)) {
223 case 1: case 2: case 4: case 8:
226 ld_eprintf(ofl
, ERR_FATAL
,
227 MSG_INTL(MSG_PSYM_INVMINFO2
),
228 isp
->is_file
->ifl_name
,
229 EC_WORD(isp
->is_scnndx
), isp
->is_name
, i
,
230 EC_XWORD(mvp
->m_info
));
235 * If this is a global symbol, adjust the visibility.
238 ((sdp
->sd_flags
& FLG_SY_VISIBLE
) == 0))
239 ld_sym_adjust_vis(sdp
, ofl
);
243 if (sdp
->sd_move
== NULL
) {
245 * If this is the first move entry associated
246 * with this symbol, save the symbol on the
247 * partial symbol list, and initialize various
248 * state regarding this symbol.
250 if (aplist_append(&ofl
->ofl_parsyms
, sdp
,
251 AL_CNT_OFL_PARSYMS
) == NULL
)
255 * Even if -zredlocsym is in effect, the local
256 * symbol used for partial initialization is
259 if ((ofl
->ofl_flags
& FLG_OF_REDLSYM
) &&
260 (ELF_ST_BIND(sym
->st_info
) == STB_LOCAL
) &&
261 (ELF_ST_TYPE(sym
->st_info
) == STT_OBJECT
)) {
263 if (st_insert(ofl
->ofl_strtab
,
269 * Mark the input section associated with this
270 * partially initialized symbol.
271 * This is needed when the symbol
272 * the relocation entry uses symbol information
273 * not from the symbol entry.
275 * For executable, the following is
276 * needed only for expanded symbol. However,
277 * for shared object any partially non
278 * expanded symbols are moved from
279 * .bss/COMMON to .sunwbss. So the following are
282 if ((sym
->st_shndx
!= SHN_UNDEF
) &&
283 (sym
->st_shndx
< SHN_LOPROC
)) {
286 isc
= ifile
->ifl_isdesc
[ sym
->st_shndx
];
287 isc
->is_flags
|= FLG_IS_RELUPD
;
289 if (sdp
->sd_osym
== NULL
) {
291 libld_calloc(sizeof (Sym
),
300 if (append_move_desc(ofl
, sdp
, mvp
, isp
) == S_ERROR
)
303 if (sdp
->sd_flags
& FLG_SY_OVERLAP
)
307 * If this symbol is marked to be expanded, go to the
310 if (sdp
->sd_flags
& FLG_SY_PAREXPN
) {
316 * Decide whether this partial symbol is to be expanded
319 * The symbol will be expanded if:
320 * a) '-z nopartial' is specified
321 * b) move entries covered entire symbol
323 * To expand an move entry, size of the symbol to be
324 * expanded need to be known to generate a file space.
325 * (see make_movesections().)
327 * Therefore the move entry can not be expanded
328 * if the partial symbol is a section symbol.
329 * (The size of the symbol may be unknown.)
330 * This may happen, for example, when a local symbol is
331 * reduced by the -zredlocsym.
333 * The following two if statements checks the
334 * if the move entry can be expanded or not.
336 if (OFL_IS_STATIC_EXEC(ofl
)) {
337 if (ELF_ST_TYPE(sym
->st_info
) == STT_SECTION
) {
339 ld_eprintf(ofl
, ERR_FATAL
,
340 MSG_INTL(MSG_PSYM_CANNOTEXPND
),
341 sdp
->sd_file
->ifl_name
,
342 EC_WORD(isp
->is_scnndx
),
344 MSG_INTL(MSG_PSYM_NOSTATIC
));
346 sdp
->sd_flags
|= FLG_SY_PAREXPN
;
348 } else if ((ofl
->ofl_flags1
& FLG_OF1_NOPARTI
) != 0) {
349 if (ELF_ST_TYPE(sym
->st_info
) == STT_SECTION
) {
350 ld_eprintf(ofl
, ERR_WARNING
,
351 MSG_INTL(MSG_PSYM_CANNOTEXPND
),
352 sdp
->sd_file
->ifl_name
,
353 EC_WORD(isp
->is_scnndx
),
355 MSG_ORIG(MSG_STR_EMPTY
));
357 sdp
->sd_flags
|= FLG_SY_PAREXPN
;
359 } else if (((Xword
)((sizeof (Move
)) *
360 alist_nitems(sdp
->sd_move
)) > sym
->st_size
) &&
361 (ELF_ST_TYPE(sym
->st_info
) == STT_OBJECT
)) {
362 sdp
->sd_flags
|= FLG_SY_PAREXPN
;
366 * If a move entry exists that references a local
367 * symbol, and this symbol reference will eventually
368 * be assigned to the associated section, make sure the
369 * section symbol is available for relocating against
372 if ((ELF_ST_BIND(sym
->st_info
) == STB_LOCAL
) &&
373 (((ofl
->ofl_flags
& FLG_OF_RELOBJ
) == 0) ||
374 (ofl
->ofl_flags
& FLG_OF_REDLSYM
))) {
375 Os_desc
*osp
= sdp
->sd_isc
->is_osdesc
;
378 ((osp
->os_flags
& FLG_OS_OUTREL
) == 0)) {
379 ofl
->ofl_dynshdrcnt
++;
380 osp
->os_flags
|= FLG_OS_OUTREL
;
381 } else if ((sdp
->sd_flags
&
382 FLG_SY_PAREXPN
) == 0)
383 ofl
->ofl_flags1
|= FLG_OF1_BSSOREL
;
391 if (make_mvsections(ofl
) == S_ERROR
)