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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright (c) 1988 AT&T 24 * All Rights Reserved 25 * 26 * 27 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 28 * Use is subject to license terms. 29 */ 30 #pragma ident "%Z%%M% %I% %E% SMI" 31 32 /* 33 * Map file parsing and input section to output segment mapping. 34 */ 35 #include <stdio.h> 36 #include <string.h> 37 #include "debug.h" 38 #include "msg.h" 39 #include "_libld.h" 40 41 /* 42 * Compute LCM 43 */ 44 static void 45 set_addralign(Ofl_desc *ofl, Os_desc *osp, Is_desc *isp) 46 { 47 if ((ofl->ofl_flags1 & FLG_OF1_NOHDR) && 48 (osp->os_sgdesc->sg_phdr).p_type != PT_LOAD) 49 return; 50 51 osp->os_sgdesc->sg_addralign = lcm(osp->os_sgdesc->sg_addralign, 52 isp->is_shdr->sh_addralign); 53 } 54 55 /* 56 * Determine if section ordering is turned on. If so, return the appropriate 57 * os_txtndx. This information is derived from the Sg_desc->sg_segorder 58 * list that was built up from the Mapfile. 59 */ 60 int 61 set_os_txtndx(Is_desc *isp, Sg_desc * sgp) 62 { 63 Listnode * lnp; 64 Sec_order * scop; 65 66 for (LIST_TRAVERSE(&sgp->sg_secorder, lnp, scop)) { 67 if (strcmp(scop->sco_secname, isp->is_name) == 0) { 68 scop->sco_flags |= FLG_SGO_USED; 69 return ((int)scop->sco_index); 70 } 71 } 72 return (0); 73 } 74 75 /* 76 * Place a section into the appropriate segment. 77 */ 78 Os_desc * 79 place_section(Ofl_desc * ofl, Is_desc * isp, int ident, Word link) 80 { 81 Listnode * lnp1, * lnp2; 82 Ent_desc * enp; 83 Sg_desc * sgp; 84 Os_desc * osp; 85 int os_ndx; 86 Shdr * shdr = isp->is_shdr; 87 Xword shflagmask, shflags = shdr->sh_flags; 88 Ifl_desc * ifl = isp->is_file; 89 90 DBG_CALL(Dbg_sec_in(isp)); 91 92 if ((shflags & SHF_GROUP) || (shdr->sh_type == SHT_GROUP)) { 93 Group_desc * gdesc; 94 95 if ((gdesc = get_group(ofl, isp)) == (Group_desc *)S_ERROR) 96 return ((Os_desc *)S_ERROR); 97 98 if (gdesc) { 99 DBG_CALL(Dbg_sec_group(isp, gdesc)); 100 101 /* 102 * If this group is marked as discarded, then this 103 * section needs to be discarded. 104 */ 105 if (gdesc->gd_flags & GRP_FLG_DISCARD) { 106 isp->is_flags |= FLG_IS_DISCARD; 107 return ((Os_desc *)0); 108 } 109 } 110 111 /* 112 * SHT_GROUP sections can only be included into relocatable 113 * objects. 114 */ 115 if (shdr->sh_type == SHT_GROUP) { 116 if ((ofl->ofl_flags & FLG_OF_RELOBJ) == 0) { 117 isp->is_flags |= FLG_IS_DISCARD; 118 return ((Os_desc *)0); 119 } 120 } 121 } 122 123 /* 124 * Always assign SHF_TLS sections to the DATA segment (and then the 125 * PT_TLS embedded inside of there). 126 */ 127 if (shflags & SHF_TLS) 128 shflags |= SHF_WRITE; 129 130 /* 131 * Traverse the entrance criteria list searching for a segment that 132 * matches the input section we have. If an entrance criterion is set 133 * then there must be an exact match. If we complete the loop without 134 * finding a segment, then sgp will be NULL. 135 */ 136 sgp = NULL; 137 for (LIST_TRAVERSE(&ofl->ofl_ents, lnp1, enp)) { 138 if (enp->ec_segment && 139 (enp->ec_segment->sg_flags & FLG_SG_DISABLED)) 140 continue; 141 if (enp->ec_type && (enp->ec_type != shdr->sh_type)) 142 continue; 143 if (enp->ec_attrmask && 144 /* LINTED */ 145 (enp->ec_attrmask & enp->ec_attrbits) != 146 (enp->ec_attrmask & shflags)) 147 continue; 148 if (enp->ec_name && (strcmp(enp->ec_name, isp->is_name) != 0)) 149 continue; 150 if (enp->ec_files.head) { 151 char *file; 152 int found = 0; 153 154 if (isp->is_file == 0) 155 continue; 156 157 for (LIST_TRAVERSE(&(enp->ec_files), lnp2, file)) { 158 const char *name = isp->is_file->ifl_name; 159 160 if (file[0] == '*') { 161 const char *basename; 162 163 basename = strrchr(name, '/'); 164 if (basename == NULL) 165 basename = name; 166 else if (basename[1] != '\0') 167 basename++; 168 169 if (strcmp(&file[1], basename) == 0) { 170 found++; 171 break; 172 } 173 } else { 174 if (strcmp(file, name) == 0) { 175 found++; 176 break; 177 } 178 } 179 } 180 if (!found) 181 continue; 182 } 183 break; 184 } 185 186 if ((sgp = enp->ec_segment) == 0) 187 sgp = ((Ent_desc *)(ofl->ofl_ents.tail->data))->ec_segment; 188 189 isp->is_basename = isp->is_name; 190 191 /* 192 * Strip out the % from the section name in all cases except when '-r' 193 * is used without '-M', and '-r' is used with '-M' without 194 * the ?O flag. 195 */ 196 if (((ofl->ofl_flags & FLG_OF_RELOBJ) && 197 (sgp->sg_flags & FLG_SG_ORDER)) || 198 !(ofl->ofl_flags & FLG_OF_RELOBJ)) { 199 char *cp; 200 201 if ((cp = strchr(isp->is_name, '%')) != NULL) { 202 char *name; 203 size_t size = (size_t)(cp - isp->is_name); 204 205 if ((name = libld_malloc(size + 1)) == 0) 206 return ((Os_desc *)S_ERROR); 207 (void) strncpy(name, isp->is_name, size); 208 cp = name + size; 209 *cp = '\0'; 210 isp->is_name = name; 211 } 212 isp->is_txtndx = enp->ec_ndx; 213 } 214 215 /* 216 * Assign the is_namehash value now that we've settled 217 * on the final name for the section. 218 */ 219 isp->is_namehash = sgs_str_hash(isp->is_name); 220 221 if (sgp->sg_flags & FLG_SG_ORDER) 222 enp->ec_flags |= FLG_EC_USED; 223 224 /* 225 * If the link is not 0, then the isp is going to be appened 226 * to the output section where the input section pointed by 227 * link is placed. 228 */ 229 if (link != 0) { 230 osp = isp->is_file->ifl_isdesc[link]->is_osdesc; 231 /* 232 * If this is a COMDAT section, then see if this 233 * section is a keeper and/or if it is to 234 * be discarded. 235 */ 236 if (shdr->sh_type == SHT_SUNW_COMDAT) { 237 Listnode * clist; 238 Is_desc * cisp; 239 240 for (LIST_TRAVERSE(&(osp->os_comdats), clist, cisp)) { 241 if (strcmp(isp->is_basename, 242 cisp->is_basename) == 0) { 243 isp->is_flags |= FLG_IS_DISCARD; 244 DBG_CALL(Dbg_sec_discarded(isp, cisp)); 245 return (0); 246 } 247 } 248 249 /* 250 * This is a new COMDAT section - so keep it. 251 */ 252 if (list_appendc(&(osp->os_comdats), isp) == 0) 253 return ((Os_desc *)S_ERROR); 254 } 255 256 /* 257 * Set alignment 258 */ 259 set_addralign(ofl, osp, isp); 260 261 if (list_appendc(&(osp->os_isdescs), isp) == 0) 262 return ((Os_desc *)S_ERROR); 263 isp->is_osdesc = osp; 264 sgp = osp->os_sgdesc; 265 DBG_CALL(Dbg_sec_added(osp, sgp)); 266 return (osp); 267 } 268 269 /* 270 * call the function set_os_txtndx() to set the 271 * os_txtndx field based upon the sg_segorder list that 272 * was built from a Mapfile. If there is no match then 273 * os_txtndx will be set to 0. 274 * 275 * for now this value will be held in os_ndx. 276 */ 277 os_ndx = set_os_txtndx(isp, sgp); 278 279 /* 280 * Setup the masks to flagout when matching sections 281 */ 282 shflagmask = ALL_SHF_ORDER; 283 if ((ofl->ofl_flags & FLG_OF_RELOBJ) == 0) 284 shflagmask = ALL_SHF_IGNORE; 285 286 /* 287 * Traverse the input section list for the output section we have been 288 * assigned. If we find a matching section simply add this new section. 289 */ 290 lnp2 = NULL; 291 for (LIST_TRAVERSE(&(sgp->sg_osdescs), lnp1, osp)) { 292 Shdr * _shdr = osp->os_shdr; 293 294 if ((ident == osp->os_scnsymndx) && 295 (shdr->sh_type != SHT_SUNW_dof) && 296 ((shdr->sh_type == _shdr->sh_type) || 297 ((shdr->sh_type == SHT_SUNW_COMDAT) && 298 (_shdr->sh_type == SHT_PROGBITS))) && 299 ((shflags & ~shflagmask) == 300 (_shdr->sh_flags & ~shflagmask)) && 301 (ident != M_ID_REL) && (shdr->sh_type != SHT_GROUP) && 302 (isp->is_namehash == osp->os_namehash) && 303 (strcmp(isp->is_name, osp->os_name) == 0)) { 304 /* 305 * If this is a COMDAT section, then see if this 306 * section is a keeper and/or if it is to 307 * be discarded. 308 */ 309 if (shdr->sh_type == SHT_SUNW_COMDAT) { 310 Listnode * clist; 311 Is_desc * cisp; 312 313 for (LIST_TRAVERSE(&(osp->os_comdats), 314 clist, cisp)) { 315 if (strcmp(isp->is_basename, 316 cisp->is_basename) == 0) { 317 isp->is_flags |= FLG_IS_DISCARD; 318 DBG_CALL(Dbg_sec_discarded(isp, 319 cisp)); 320 return (0); 321 } 322 } 323 324 /* 325 * This is a new COMDAT section - so keep it. 326 */ 327 if (list_appendc(&(osp->os_comdats), isp) == 0) 328 return ((Os_desc *)S_ERROR); 329 } 330 331 /* 332 * Set alignment 333 */ 334 set_addralign(ofl, osp, isp); 335 336 /* 337 * If this section is a non-empty TLS section indicate 338 * that a PT_TLS program header is required. 339 */ 340 if ((shflags & SHF_TLS) && shdr->sh_size && 341 ((ofl->ofl_flags & FLG_OF_RELOBJ) == 0)) 342 ofl->ofl_flags |= FLG_OF_TLSPHDR; 343 344 /* 345 * If is_txtndx is 0 then this section was not 346 * seen in mapfile, so put it at the end. 347 * If is_txtndx is not 0 and ?O is turned on 348 * then check to see where this section should 349 * be inserted. 350 */ 351 if ((sgp->sg_flags & FLG_SG_ORDER) && isp->is_txtndx) { 352 Listnode * tlist; 353 354 tlist = list_where(&(osp->os_isdescs), 355 isp->is_txtndx); 356 if (tlist != NULL) { 357 if (list_insertc(&(osp->os_isdescs), 358 isp, tlist) == 0) 359 return ((Os_desc *)S_ERROR); 360 } else { 361 if (list_prependc(&(osp->os_isdescs), 362 isp) == 0) 363 return ((Os_desc *)S_ERROR); 364 } 365 } else 366 if (list_appendc(&(osp->os_isdescs), isp) == 0) 367 return ((Os_desc *)S_ERROR); 368 369 isp->is_osdesc = osp; 370 371 /* 372 * If this input section and file is associated to an 373 * artificially referenced output section, make sure 374 * they are marked as referenced also. This insures this 375 * input section and file isn't eliminated when -zignore 376 * is in effect. 377 * See -zignore comments when creating a new output 378 * section below. 379 */ 380 if (((ifl && (ifl->ifl_flags & FLG_IF_IGNORE)) || 381 dbg_mask) && 382 (osp->os_flags & FLG_OS_SECTREF)) { 383 isp->is_flags |= FLG_IS_SECTREF; 384 if (ifl) 385 ifl->ifl_flags |= FLG_IF_FILEREF; 386 } 387 388 DBG_CALL(Dbg_sec_added(osp, sgp)); 389 return (osp); 390 } 391 392 /* 393 * check to see if we need to worry about section 394 * ordering. 395 */ 396 if (os_ndx) { 397 if (osp->os_txtndx) { 398 if (os_ndx < osp->os_txtndx) 399 /* insert section here. */ 400 break; 401 else { 402 lnp2 = lnp1; 403 continue; 404 } 405 } else { 406 /* insert section here. */ 407 break; 408 } 409 } else if (osp->os_txtndx) { 410 lnp2 = lnp1; 411 continue; 412 } 413 414 /* 415 * If the new sections identifier is less than that of the 416 * present input section we need to insert the new section 417 * at this point. 418 */ 419 if (ident < osp->os_scnsymndx) 420 break; 421 lnp2 = lnp1; 422 } 423 424 /* 425 * We are adding a new output section. Update the section header 426 * count and associated string size. 427 */ 428 ofl->ofl_shdrcnt++; 429 if (st_insert(ofl->ofl_shdrsttab, isp->is_name) == -1) 430 return ((Os_desc *)S_ERROR); 431 432 /* 433 * Create a new output section descriptor. 434 */ 435 if ((osp = libld_calloc(sizeof (Os_desc), 1)) == 0) 436 return ((Os_desc *)S_ERROR); 437 if ((osp->os_shdr = libld_calloc(sizeof (Shdr), 1)) == 0) 438 return ((Os_desc *)S_ERROR); 439 440 /* 441 * We convert COMDAT sections to PROGBITS if this is the first 442 * section of a output section. 443 */ 444 if (shdr->sh_type == SHT_SUNW_COMDAT) { 445 Shdr * tshdr; 446 447 if ((tshdr = libld_malloc(sizeof (Shdr))) == 0) 448 return ((Os_desc *)S_ERROR); 449 *tshdr = *shdr; 450 isp->is_shdr = shdr = tshdr; 451 shdr->sh_type = SHT_PROGBITS; 452 if (list_appendc(&(osp->os_comdats), isp) == 0) 453 return ((Os_desc *)S_ERROR); 454 } 455 456 osp->os_shdr->sh_type = shdr->sh_type; 457 osp->os_shdr->sh_flags = shdr->sh_flags; 458 osp->os_shdr->sh_entsize = shdr->sh_entsize; 459 osp->os_name = isp->is_name; 460 osp->os_namehash = isp->is_namehash; 461 osp->os_txtndx = os_ndx; 462 osp->os_sgdesc = sgp; 463 if (ifl && (shdr->sh_type == SHT_PROGBITS)) { 464 /* 465 * Trying to preserved the possibly intended meaning of 466 * sh_link/sh_info. See the translate_link() 467 * in update.c. 468 */ 469 osp->os_shdr->sh_link = shdr->sh_link; 470 if (shdr->sh_flags & SHF_INFO_LINK) 471 osp->os_shdr->sh_info = shdr->sh_info; 472 } 473 474 /* 475 * When -zignore is in effect, sections and files that are not 476 * referenced * from other sections, will be eliminated from the 477 * object being produced. Some sections, although unreferenced, 478 * are special, and must not be eliminated. Determine if this new 479 * output section is one of those special sections, and if so mark 480 * it artificially as referenced. 481 * Any input section and file associated to this output section 482 * will also be marked as referenced, and thus won't be eliminated 483 * from the final output. 484 */ 485 if ((strcmp(osp->os_name, MSG_ORIG(MSG_SCN_INIT)) == 0) || 486 (strcmp(osp->os_name, MSG_ORIG(MSG_SCN_FINI)) == 0) || 487 (strcmp(osp->os_name, MSG_ORIG(MSG_SCN_EX_RANGES)) == 0) || 488 (strcmp(osp->os_name, MSG_ORIG(MSG_SCN_EX_SHARED)) == 0) || 489 (strcmp(osp->os_name, MSG_ORIG(MSG_SCN_CTORS)) == 0) || 490 (strcmp(osp->os_name, MSG_ORIG(MSG_SCN_DTORS)) == 0) || 491 (strcmp(osp->os_name, MSG_ORIG(MSG_SCN_EHFRAME)) == 0) || 492 (strcmp(osp->os_name, MSG_ORIG(MSG_SCN_EHFRAME_HDR)) == 0) || 493 (strcmp(osp->os_name, MSG_ORIG(MSG_SCN_JCR)) == 0)) { 494 osp->os_flags |= FLG_OS_SECTREF; 495 496 if ((ifl && (ifl->ifl_flags & FLG_IF_IGNORE)) || dbg_mask) { 497 isp->is_flags |= FLG_IS_SECTREF; 498 if (ifl) 499 ifl->ifl_flags |= FLG_IF_FILEREF; 500 } 501 } 502 503 /* 504 * Setions of SHT_GROUP are added to the ofl->ofl_osgroups 505 * list - so that they can be updated as a group later. 506 */ 507 if (shdr->sh_type == SHT_GROUP) { 508 if (list_appendc(&ofl->ofl_osgroups, osp) == 0) 509 return ((Os_desc *)S_ERROR); 510 } 511 512 /* 513 * If this section is a non-empty TLS section indicate that a PT_TLS 514 * program header is required. 515 */ 516 if ((shflags & SHF_TLS) && shdr->sh_size && 517 ((ofl->ofl_flags & FLG_OF_RELOBJ) == 0)) 518 ofl->ofl_flags |= FLG_OF_TLSPHDR; 519 520 /* 521 * If a non-allocatable section is going to be put into a loadable 522 * segment then turn on the allocate bit for this section and warn the 523 * user that we have done so. This could only happen through the use 524 * of a mapfile. 525 */ 526 if (sgp->sg_phdr.p_type == PT_LOAD) { 527 if (!(osp->os_shdr->sh_flags & SHF_ALLOC)) { 528 eprintf(ERR_WARNING, MSG_INTL(MSG_SCN_NONALLOC), 529 ofl->ofl_name, osp->os_name); 530 osp->os_shdr->sh_flags |= SHF_ALLOC; 531 } 532 } 533 534 /* 535 * Retain this sections identifier for future comparisons when placing 536 * a section (after all sections have been processed this variable will 537 * be used to hold the sections symbol index as we don't need to retain 538 * the identifier any more). 539 */ 540 osp->os_scnsymndx = ident; 541 542 /* 543 * Set alignment 544 */ 545 set_addralign(ofl, osp, isp); 546 547 if (list_appendc(&(osp->os_isdescs), isp) == 0) 548 return ((Os_desc *)S_ERROR); 549 550 DBG_CALL(Dbg_sec_created(osp, sgp)); 551 isp->is_osdesc = osp; 552 if (lnp2) { 553 if (list_insertc(&(sgp->sg_osdescs), osp, lnp2) == 0) 554 return ((Os_desc *)S_ERROR); 555 } else { 556 if (list_prependc(&(sgp->sg_osdescs), osp) == 0) 557 return ((Os_desc *)S_ERROR); 558 } 559 return (osp); 560 } 561