1 /* 2 * CDDL HEADER START 3 * 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. 7 * 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. 12 * 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] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. 24 */ 25 26 #include <string.h> 27 #include <debug.h> 28 #include "msg.h" 29 #include "_libld.h" 30 31 /* 32 * Scan all partially initialized symbols to determine what output Move sections 33 * or partially expanded data section, must be created. 34 */ 35 static uintptr_t 36 make_mvsections(Ofl_desc *ofl) 37 { 38 Aliste idx; 39 Sym_desc *sdp; 40 Word mv_nums = 0; 41 Xword align_parexpn = 0; /* for -z nopartial .data sec */ 42 size_t size_parexpn = 0; /* size of parexpn section */ 43 44 /* 45 * Compute the size of the output move section 46 */ 47 for (APLIST_TRAVERSE(ofl->ofl_parsyms, idx, sdp)) { 48 if (sdp->sd_flags & FLG_SY_PAREXPN) { 49 Sym *sym = sdp->sd_sym; 50 Xword align_val; 51 52 if (sym->st_shndx == SHN_COMMON) 53 align_val = sym->st_value; 54 else 55 align_val = 8; 56 57 /* 58 * This global symbol is redirected to the special 59 * partial initialization .data section. 60 */ 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; 65 66 } else { 67 mv_nums += alist_nitems(sdp->sd_move); 68 } 69 } 70 71 /* 72 * Generate a new Move section. 73 */ 74 if (mv_nums && (ld_make_sunwmove(ofl, mv_nums) == S_ERROR)) 75 return (S_ERROR); 76 77 /* 78 * Add empty area for partially initialized symbols. 79 * 80 * A special .data section is created when the '-z nopartial' 81 * option is in effect in order to receive the expanded data. 82 */ 83 if (size_parexpn) { 84 /* LINTED */ 85 if (ld_make_parexpn_data(ofl, size_parexpn, 86 align_parexpn) == S_ERROR) 87 return (S_ERROR); 88 } 89 return (1); 90 } 91 92 /* 93 * Assign move descriptors with the associated target symbol. 94 */ 95 static uintptr_t 96 append_move_desc(Ofl_desc *ofl, Sym_desc *sdp, Move *mvp, Is_desc *isp) 97 { 98 int i, cnt = mvp->m_repeat; 99 100 for (i = 0; i < cnt; i++) { 101 Aliste idx; 102 Mv_desc *omdp, nmd; 103 104 /* LINTED */ 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); 108 nmd.md_move = mvp; 109 110 /* 111 * Verify that this move descriptor doesn't overlap any existing 112 * move descriptors. 113 */ 114 for (ALIST_TRAVERSE(sdp->sd_move, idx, omdp)) { 115 Mv_desc *smdp, *lmdp; 116 117 if (nmd.md_start > omdp->md_start) { 118 smdp = omdp; 119 lmdp = &nmd; 120 } else { 121 smdp = &nmd; 122 lmdp = omdp; 123 } 124 125 /* 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 130 * element. 131 */ 132 if ((nmd.md_start == omdp->md_start) && 133 ((nmd.md_len == smdp->md_len) && 134 sdp->sd_file != isp->is_file)) 135 continue; 136 137 if ((nmd.md_start != omdp->md_start) && 138 ((smdp->md_start + smdp->md_len) <= lmdp->md_start)) 139 continue; 140 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)); 146 147 /* 148 * Indicate that an error has occurred, so that 149 * processing can be terminated once all move errors 150 * are flushed out. 151 */ 152 sdp->sd_flags |= FLG_SY_OVERLAP; 153 return (1); 154 } 155 156 if (alist_append(&sdp->sd_move, &nmd, sizeof (Mv_desc), 157 AL_CNT_SDP_MOVE) == NULL) 158 return (S_ERROR); 159 } 160 return (1); 161 } 162 163 /* 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. 167 */ 168 uintptr_t 169 ld_process_move(Ofl_desc *ofl) 170 { 171 Aliste idx; 172 Is_desc *isp; 173 int errcnt = 0; 174 175 for (APLIST_TRAVERSE(ofl->ofl_ismove, idx, isp)) { 176 Ifl_desc *ifile = isp->is_file; 177 Move *mvp; 178 Xword i, num; 179 180 DBG_CALL(Dbg_move_input(ofl->ofl_lml, ifile->ifl_name)); 181 mvp = (Move *)isp->is_indata->d_buf; 182 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)); 188 return (S_ERROR); 189 } 190 num = isp->is_shdr->sh_size / isp->is_shdr->sh_entsize; 191 192 for (i = 0; i < num; i++) { 193 Xword ndx = ELF_M_SYM(mvp->m_info); 194 Sym_desc *sdp; 195 Sym *sym; 196 197 if ((ndx >= (Xword) isp->is_file->ifl_symscnt) || 198 (ndx == 0)) { 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)); 204 return (S_ERROR); 205 } 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)); 212 return (S_ERROR); 213 } 214 215 sdp = isp->is_file->ifl_oldndx[ndx]; 216 DBG_CALL(Dbg_move_entry1(ofl->ofl_lml, 1, mvp, sdp)); 217 218 /* 219 * Validate that this entry has a valid size. 220 */ 221 /* LINTED */ 222 switch (ELF_M_SIZE(mvp->m_info)) { 223 case 1: case 2: case 4: case 8: 224 break; 225 default: 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)); 231 return (S_ERROR); 232 } 233 234 /* 235 * If this is a global symbol, adjust the visibility. 236 */ 237 if (sdp->sd_aux && 238 ((sdp->sd_flags & FLG_SY_VISIBLE) == 0)) 239 ld_sym_adjust_vis(sdp, ofl); 240 241 sym = sdp->sd_sym; 242 243 if (sdp->sd_move == NULL) { 244 /* 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. 249 */ 250 if (aplist_append(&ofl->ofl_parsyms, sdp, 251 AL_CNT_OFL_PARSYMS) == NULL) 252 return (S_ERROR); 253 254 /* 255 * Even if -zredlocsym is in effect, the local 256 * symbol used for partial initialization is 257 * kept. 258 */ 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)) { 262 ofl->ofl_locscnt++; 263 if (st_insert(ofl->ofl_strtab, 264 sdp->sd_name) == -1) 265 return (S_ERROR); 266 } 267 268 /* 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. 274 * 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 280 * needed. 281 */ 282 if ((sym->st_shndx != SHN_UNDEF) && 283 (sym->st_shndx < SHN_LOPROC)) { 284 Is_desc *isc; 285 286 isc = ifile->ifl_isdesc[ sym->st_shndx]; 287 isc->is_flags |= FLG_IS_RELUPD; 288 289 if (sdp->sd_osym == NULL) { 290 if ((sdp->sd_osym = 291 libld_calloc(sizeof (Sym), 292 1)) == NULL) 293 return (S_ERROR); 294 *(sdp->sd_osym) = 295 *(sdp->sd_sym); 296 } 297 } 298 } 299 300 if (append_move_desc(ofl, sdp, mvp, isp) == S_ERROR) 301 return (S_ERROR); 302 303 if (sdp->sd_flags & FLG_SY_OVERLAP) 304 errcnt++; 305 306 /* 307 * If this symbol is marked to be expanded, go to the 308 * next move entry. 309 */ 310 if (sdp->sd_flags & FLG_SY_PAREXPN) { 311 mvp++; 312 continue; 313 } 314 315 /* 316 * Decide whether this partial symbol is to be expanded 317 * or not. 318 * 319 * The symbol will be expanded if: 320 * a) '-z nopartial' is specified 321 * b) move entries covered entire symbol 322 * 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().) 326 * 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. 332 * 333 * The following two if statements checks the 334 * if the move entry can be expanded or not. 335 */ 336 if (OFL_IS_STATIC_EXEC(ofl)) { 337 if (ELF_ST_TYPE(sym->st_info) == STT_SECTION) { 338 errcnt++; 339 ld_eprintf(ofl, ERR_FATAL, 340 MSG_INTL(MSG_PSYM_CANNOTEXPND), 341 sdp->sd_file->ifl_name, 342 EC_WORD(isp->is_scnndx), 343 isp->is_name, i, 344 MSG_INTL(MSG_PSYM_NOSTATIC)); 345 } else { 346 sdp->sd_flags |= FLG_SY_PAREXPN; 347 } 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), 354 isp->is_name, i, 355 MSG_ORIG(MSG_STR_EMPTY)); 356 } else { 357 sdp->sd_flags |= FLG_SY_PAREXPN; 358 } 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; 363 } 364 365 /* 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 370 * at runtime. 371 */ 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; 376 377 if (osp && 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; 384 } 385 mvp++; 386 } 387 } 388 389 if (errcnt != 0) 390 return (S_ERROR); 391 if (make_mvsections(ofl) == S_ERROR) 392 return (S_ERROR); 393 394 return (1); 395 } 396