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 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include <string.h> 28 #include <debug.h> 29 #include "msg.h" 30 #include "_libld.h" 31 32 /* 33 * Scan all partially initialized symbols to determine what output Move sections 34 * or partially expanded data section, must be created. 35 */ 36 static uintptr_t 37 make_mvsections(Ofl_desc *ofl) 38 { 39 Aliste idx; 40 Sym_desc *sdp; 41 Word mv_nums = 0; 42 Xword align_parexpn = 0; /* for -z nopartial .data sec */ 43 size_t size_parexpn = 0; /* size of parexpn section */ 44 45 /* 46 * Compute the size of the output move section 47 */ 48 for (APLIST_TRAVERSE(ofl->ofl_parsyms, idx, sdp)) { 49 if (sdp->sd_flags & FLG_SY_PAREXPN) { 50 Sym *sym = sdp->sd_sym; 51 Xword align_val; 52 53 if (sym->st_shndx == SHN_COMMON) 54 align_val = sym->st_value; 55 else 56 align_val = 8; 57 58 /* 59 * This global symbol is redirected to the special 60 * partial initialization .data section. 61 */ 62 size_parexpn = (size_t)S_ROUND(size_parexpn, 63 sym->st_value) + sym->st_size; 64 if (align_val > align_parexpn) 65 align_parexpn = align_val; 66 67 } else { 68 mv_nums += alist_nitems(sdp->sd_move); 69 } 70 } 71 72 /* 73 * Generate a new Move section. 74 */ 75 if (mv_nums && (ld_make_sunwmove(ofl, mv_nums) == S_ERROR)) 76 return (S_ERROR); 77 78 /* 79 * Add empty area for partially initialized symbols. 80 * 81 * A special .data section is created when the '-z nopartial' 82 * option is in effect in order to receive the expanded data. 83 */ 84 if (size_parexpn) { 85 /* LINTED */ 86 if (ld_make_parexpn_data(ofl, size_parexpn, 87 align_parexpn) == S_ERROR) 88 return (S_ERROR); 89 } 90 return (1); 91 } 92 93 /* 94 * Assign move descriptors with the associated target symbol. 95 */ 96 static uintptr_t 97 append_move_desc(Ofl_desc *ofl, Sym_desc *sdp, Move *mvp, Is_desc *isp) 98 { 99 int i, cnt = mvp->m_repeat; 100 101 for (i = 0; i < cnt; i++) { 102 Aliste idx; 103 Mv_desc *omdp, nmd; 104 105 /* LINTED */ 106 nmd.md_len = ELF_M_SIZE(mvp->m_info); 107 nmd.md_start = mvp->m_poffset + i * 108 ((mvp->m_stride + 1) * nmd.md_len); 109 nmd.md_move = mvp; 110 111 /* 112 * Verify that this move descriptor doesn't overlap any existing 113 * move descriptors. 114 */ 115 for (ALIST_TRAVERSE(sdp->sd_move, idx, omdp)) { 116 Mv_desc *smdp, *lmdp; 117 118 if (nmd.md_start > omdp->md_start) { 119 smdp = omdp; 120 lmdp = &nmd; 121 } else { 122 smdp = &nmd; 123 lmdp = omdp; 124 } 125 126 /* 127 * If this move entry is exactly the same as that of 128 * a symbol that has overridden this symbol (for example 129 * should two identical COMMON definitions be associated 130 * with the same move data), simply ignore this move 131 * element. 132 */ 133 if ((nmd.md_start == omdp->md_start) && 134 ((nmd.md_len == smdp->md_len) && 135 sdp->sd_file != isp->is_file)) 136 continue; 137 138 if ((nmd.md_start != omdp->md_start) && 139 ((smdp->md_start + smdp->md_len) <= lmdp->md_start)) 140 continue; 141 142 eprintf(ofl->ofl_lml, ERR_FATAL, 143 MSG_INTL(MSG_MOVE_OVERLAP), sdp->sd_file->ifl_name, 144 EC_WORD(isp->is_scnndx), 145 isp->is_name, demangle(sdp->sd_name), 146 EC_XWORD(nmd.md_start), EC_XWORD(nmd.md_len), 147 EC_XWORD(omdp->md_start), EC_XWORD(omdp->md_len)); 148 149 /* 150 * Indicate that an error has occurred, so that 151 * processing can be terminated once all move errors 152 * are flushed out. 153 */ 154 sdp->sd_flags1 |= FLG_SY1_OVERLAP; 155 return (1); 156 } 157 158 if (alist_append(&sdp->sd_move, &nmd, sizeof (Mv_desc), 159 AL_CNT_SDP_MOVE) == NULL) 160 return (S_ERROR); 161 } 162 return (1); 163 } 164 165 /* 166 * Validate a SHT_SUNW_move section. These are only processed from input 167 * relocatable objects. The move section entries are validated and any data 168 * structures required for later processing are created. 169 */ 170 uintptr_t 171 ld_process_move(Ofl_desc *ofl) 172 { 173 Aliste idx; 174 Is_desc *isp; 175 int errcnt = 0; 176 177 for (APLIST_TRAVERSE(ofl->ofl_ismove, idx, isp)) { 178 Ifl_desc *ifile = isp->is_file; 179 Move *mvp; 180 Xword i, num; 181 182 DBG_CALL(Dbg_move_input(ofl->ofl_lml, ifile->ifl_name)); 183 mvp = (Move *)isp->is_indata->d_buf; 184 185 if (isp->is_shdr->sh_entsize == 0) { 186 eprintf(ofl->ofl_lml, ERR_FATAL, 187 MSG_INTL(MSG_FIL_INVSHENTSIZE), 188 isp->is_file->ifl_name, EC_WORD(isp->is_scnndx), 189 isp->is_name, EC_XWORD(0)); 190 return (S_ERROR); 191 } 192 num = isp->is_shdr->sh_size / isp->is_shdr->sh_entsize; 193 194 for (i = 0; i < num; i++) { 195 Xword ndx = ELF_M_SYM(mvp->m_info); 196 Sym_desc *sdp; 197 Sym *sym; 198 199 if ((ndx >= (Xword) isp->is_file->ifl_symscnt) || 200 (ndx == 0)) { 201 eprintf(ofl->ofl_lml, ERR_FATAL, 202 MSG_INTL(MSG_PSYM_INVMINFO1), 203 isp->is_file->ifl_name, 204 EC_WORD(isp->is_scnndx), isp->is_name, i, 205 EC_XWORD(mvp->m_info)); 206 return (S_ERROR); 207 } 208 if (mvp->m_repeat == 0) { 209 eprintf(ofl->ofl_lml, ERR_FATAL, 210 MSG_INTL(MSG_PSYM_INVMREPEAT), 211 isp->is_file->ifl_name, 212 EC_WORD(isp->is_scnndx), isp->is_name, i, 213 EC_XWORD(mvp->m_repeat)); 214 return (S_ERROR); 215 } 216 217 sdp = isp->is_file->ifl_oldndx[ndx]; 218 DBG_CALL(Dbg_move_entry1(ofl->ofl_lml, 1, mvp, sdp)); 219 220 /* 221 * Validate that this entry has a valid size. 222 */ 223 /* LINTED */ 224 switch (ELF_M_SIZE(mvp->m_info)) { 225 case 1: case 2: case 4: case 8: 226 break; 227 default: 228 eprintf(ofl->ofl_lml, ERR_FATAL, 229 MSG_INTL(MSG_PSYM_INVMINFO2), 230 isp->is_file->ifl_name, 231 EC_WORD(isp->is_scnndx), isp->is_name, i, 232 EC_XWORD(mvp->m_info)); 233 return (S_ERROR); 234 } 235 236 /* 237 * If this is a global symbol, adjust the visibility. 238 */ 239 if (sdp->sd_aux && 240 ((sdp->sd_flags & FLG_SY_VISIBLE) == 0)) 241 ld_sym_adjust_vis(sdp, ofl); 242 243 sym = sdp->sd_sym; 244 245 if (sdp->sd_move == NULL) { 246 /* 247 * If this is the first move entry associated 248 * with this symbol, save the symbol on the 249 * partial symbol list, and initialize various 250 * state regarding this symbol. 251 */ 252 if (aplist_append(&ofl->ofl_parsyms, sdp, 253 AL_CNT_OFL_PARSYMS) == NULL) 254 return (S_ERROR); 255 256 /* 257 * Even if -zredlocsym is in effect, the local 258 * symbol used for partial initialization is 259 * kept. 260 */ 261 if ((ofl->ofl_flags & FLG_OF_REDLSYM) && 262 (ELF_ST_BIND(sym->st_info) == STB_LOCAL) && 263 (ELF_ST_TYPE(sym->st_info) == STT_OBJECT)) { 264 ofl->ofl_locscnt++; 265 if (st_insert(ofl->ofl_strtab, 266 sdp->sd_name) == -1) 267 return (S_ERROR); 268 } 269 270 /* 271 * Mark the input section associated with this 272 * partially initialized symbol. 273 * This is needed when the symbol 274 * the relocation entry uses symbol information 275 * not from the symbol entry. 276 * 277 * For executable, the following is 278 * needed only for expanded symbol. However, 279 * for shared object any partially non 280 * expanded symbols are moved from 281 * .bss/COMMON to .sunwbss. So the following are 282 * needed. 283 */ 284 if ((sym->st_shndx != SHN_UNDEF) && 285 (sym->st_shndx < SHN_LOPROC)) { 286 Is_desc *isc; 287 288 isc = ifile->ifl_isdesc[ sym->st_shndx]; 289 isc->is_flags |= FLG_IS_RELUPD; 290 291 if (sdp->sd_osym == NULL) { 292 if ((sdp->sd_osym = 293 libld_calloc(sizeof (Sym), 294 1)) == NULL) 295 return (S_ERROR); 296 *(sdp->sd_osym) = 297 *(sdp->sd_sym); 298 } 299 } 300 } 301 302 if (append_move_desc(ofl, sdp, mvp, isp) == S_ERROR) 303 return (S_ERROR); 304 305 if (sdp->sd_flags1 & FLG_SY1_OVERLAP) 306 errcnt++; 307 308 /* 309 * If this symbol is marked to be expanded, go to the 310 * next move entry. 311 */ 312 if (sdp->sd_flags & FLG_SY_PAREXPN) { 313 mvp++; 314 continue; 315 } 316 317 /* 318 * Decide whether this partial symbol is to be expanded 319 * or not. 320 * 321 * The symbol will be expanded if: 322 * a) '-z nopartial' is specified 323 * b) move entries covered entire symbol 324 * 325 * To expand an move entry, size of the symbol to be 326 * expanded need to be known to generate a file space. 327 * (see make_movesections().) 328 * 329 * Therefore the move entry can not be expanded 330 * if the partial symbol is a section symbol. 331 * (The size of the symbol may be unknown.) 332 * This may happen, for example, when a local symbol is 333 * reduced by the -zredlocsym. 334 * 335 * The following two if statements checks the 336 * if the move entry can be expanded or not. 337 */ 338 if (((ofl->ofl_flags & FLG_OF_STATIC) != 0) && 339 ((ofl->ofl_flags & FLG_OF_EXEC) != 0)) { 340 if (ELF_ST_TYPE(sym->st_info) == STT_SECTION) { 341 errcnt++; 342 eprintf(ofl->ofl_lml, ERR_FATAL, 343 MSG_INTL(MSG_PSYM_CANNOTEXPND), 344 sdp->sd_file->ifl_name, 345 EC_WORD(isp->is_scnndx), 346 isp->is_name, i, 347 MSG_INTL(MSG_PSYM_NOSTATIC)); 348 } else { 349 sdp->sd_flags |= FLG_SY_PAREXPN; 350 } 351 } else if ((ofl->ofl_flags1 & FLG_OF1_NOPARTI) != 0) { 352 if (ELF_ST_TYPE(sym->st_info) == STT_SECTION) { 353 eprintf(ofl->ofl_lml, ERR_WARNING, 354 MSG_INTL(MSG_PSYM_CANNOTEXPND), 355 sdp->sd_file->ifl_name, 356 EC_WORD(isp->is_scnndx), 357 isp->is_name, i, 358 MSG_ORIG(MSG_STR_EMPTY)); 359 } else { 360 sdp->sd_flags |= FLG_SY_PAREXPN; 361 } 362 } else if (((Xword)((sizeof (Move)) * 363 alist_nitems(sdp->sd_move)) > sym->st_size) && 364 (ELF_ST_TYPE(sym->st_info) == STT_OBJECT)) { 365 sdp->sd_flags |= FLG_SY_PAREXPN; 366 } 367 368 /* 369 * If a move entry exists that references a local 370 * symbol, and this symbol reference will eventually 371 * be assigned to the associated section, make sure the 372 * section symbol is available for relocating against 373 * at runtime. 374 */ 375 if ((ELF_ST_BIND(sym->st_info) == STB_LOCAL) && 376 (((ofl->ofl_flags & FLG_OF_RELOBJ) == 0) || 377 (ofl->ofl_flags & FLG_OF_REDLSYM))) { 378 Os_desc *osp = sdp->sd_isc->is_osdesc; 379 380 if (osp && 381 ((osp->os_flags & FLG_OS_OUTREL) == 0)) { 382 ofl->ofl_dynshdrcnt++; 383 osp->os_flags |= FLG_OS_OUTREL; 384 } else if ((sdp->sd_flags & 385 FLG_SY_PAREXPN) == 0) 386 ofl->ofl_flags1 |= FLG_OF1_BSSOREL; 387 } 388 mvp++; 389 } 390 } 391 392 if (errcnt != 0) 393 return (S_ERROR); 394 if (make_mvsections(ofl) == S_ERROR) 395 return (S_ERROR); 396 397 return (1); 398 } 399