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 ofl->ofl_flags1 |= FLG_OF1_GRPSECT; 121 } 122 } 123 124 /* 125 * Always assign SHF_TLS sections to the DATA segment (and then the 126 * PT_TLS embedded inside of there). 127 */ 128 if (shflags & SHF_TLS) 129 shflags |= SHF_WRITE; 130 131 /* 132 * Traverse the entrance criteria list searching for a segment that 133 * matches the input section we have. If an entrance criterion is set 134 * then there must be an exact match. If we complete the loop without 135 * finding a segment, then sgp will be NULL. 136 */ 137 sgp = NULL; 138 for (LIST_TRAVERSE(&ofl->ofl_ents, lnp1, enp)) { 139 if (enp->ec_segment && 140 (enp->ec_segment->sg_flags & FLG_SG_DISABLED)) 141 continue; 142 if (enp->ec_type && (enp->ec_type != shdr->sh_type)) 143 continue; 144 if (enp->ec_attrmask && 145 /* LINTED */ 146 (enp->ec_attrmask & enp->ec_attrbits) != 147 (enp->ec_attrmask & shflags)) 148 continue; 149 if (enp->ec_name && (strcmp(enp->ec_name, isp->is_name) != 0)) 150 continue; 151 if (enp->ec_files.head) { 152 char *file; 153 int found = 0; 154 155 if (isp->is_file == 0) 156 continue; 157 158 for (LIST_TRAVERSE(&(enp->ec_files), lnp2, file)) { 159 const char *name = isp->is_file->ifl_name; 160 161 if (file[0] == '*') { 162 const char *basename; 163 164 basename = strrchr(name, '/'); 165 if (basename == NULL) 166 basename = name; 167 else if (basename[1] != '\0') 168 basename++; 169 170 if (strcmp(&file[1], basename) == 0) { 171 found++; 172 break; 173 } 174 } else { 175 if (strcmp(file, name) == 0) { 176 found++; 177 break; 178 } 179 } 180 } 181 if (!found) 182 continue; 183 } 184 break; 185 } 186 187 if ((sgp = enp->ec_segment) == 0) 188 sgp = ((Ent_desc *)(ofl->ofl_ents.tail->data))->ec_segment; 189 190 isp->is_basename = isp->is_name; 191 192 /* 193 * Strip out the % from the section name in all cases except when '-r' 194 * is used without '-M', and '-r' is used with '-M' without 195 * the ?O flag. 196 */ 197 if (((ofl->ofl_flags & FLG_OF_RELOBJ) && 198 (sgp->sg_flags & FLG_SG_ORDER)) || 199 !(ofl->ofl_flags & FLG_OF_RELOBJ)) { 200 char *cp; 201 202 if ((cp = strchr(isp->is_name, '%')) != NULL) { 203 char *name; 204 size_t size = (size_t)(cp - isp->is_name); 205 206 if ((name = libld_malloc(size + 1)) == 0) 207 return ((Os_desc *)S_ERROR); 208 (void) strncpy(name, isp->is_name, size); 209 cp = name + size; 210 *cp = '\0'; 211 isp->is_name = name; 212 } 213 isp->is_txtndx = enp->ec_ndx; 214 } 215 216 /* 217 * Assign the is_namehash value now that we've settled 218 * on the final name for the section. 219 */ 220 isp->is_namehash = sgs_str_hash(isp->is_name); 221 222 if (sgp->sg_flags & FLG_SG_ORDER) 223 enp->ec_flags |= FLG_EC_USED; 224 225 /* 226 * If the link is not 0, then the isp is going to be appened 227 * to the output section where the input section pointed by 228 * link is placed. 229 */ 230 if (link != 0) { 231 osp = isp->is_file->ifl_isdesc[link]->is_osdesc; 232 /* 233 * If this is a COMDAT section, then see if this 234 * section is a keeper and/or if it is to 235 * be discarded. 236 */ 237 if (shdr->sh_type == SHT_SUNW_COMDAT) { 238 Listnode * clist; 239 Is_desc * cisp; 240 241 for (LIST_TRAVERSE(&(osp->os_comdats), clist, cisp)) { 242 if (strcmp(isp->is_basename, 243 cisp->is_basename) == 0) { 244 isp->is_flags |= FLG_IS_DISCARD; 245 DBG_CALL(Dbg_sec_discarded(isp, cisp)); 246 return (0); 247 } 248 } 249 250 /* 251 * This is a new COMDAT section - so keep it. 252 */ 253 if (list_appendc(&(osp->os_comdats), isp) == 0) 254 return ((Os_desc *)S_ERROR); 255 } 256 257 /* 258 * Set alignment 259 */ 260 set_addralign(ofl, osp, isp); 261 262 if (list_appendc(&(osp->os_isdescs), isp) == 0) 263 return ((Os_desc *)S_ERROR); 264 isp->is_osdesc = osp; 265 sgp = osp->os_sgdesc; 266 DBG_CALL(Dbg_sec_added(osp, sgp)); 267 return (osp); 268 } 269 270 /* 271 * call the function set_os_txtndx() to set the 272 * os_txtndx field based upon the sg_segorder list that 273 * was built from a Mapfile. If there is no match then 274 * os_txtndx will be set to 0. 275 * 276 * for now this value will be held in os_ndx. 277 */ 278 os_ndx = set_os_txtndx(isp, sgp); 279 280 /* 281 * Setup the masks to flagout when matching sections 282 */ 283 shflagmask = ALL_SHF_ORDER; 284 if ((ofl->ofl_flags & FLG_OF_RELOBJ) == 0) 285 shflagmask = ALL_SHF_IGNORE; 286 287 /* 288 * Traverse the input section list for the output section we have been 289 * assigned. If we find a matching section simply add this new section. 290 */ 291 lnp2 = NULL; 292 for (LIST_TRAVERSE(&(sgp->sg_osdescs), lnp1, osp)) { 293 Shdr * _shdr = osp->os_shdr; 294 295 if ((ident == osp->os_scnsymndx) && 296 (shdr->sh_type != SHT_SUNW_dof) && 297 ((shdr->sh_type == _shdr->sh_type) || 298 ((shdr->sh_type == SHT_SUNW_COMDAT) && 299 (_shdr->sh_type == SHT_PROGBITS))) && 300 ((shflags & ~shflagmask) == 301 (_shdr->sh_flags & ~shflagmask)) && 302 (ident != M_ID_REL) && (shdr->sh_type != SHT_GROUP) && 303 (isp->is_namehash == osp->os_namehash) && 304 (strcmp(isp->is_name, osp->os_name) == 0)) { 305 /* 306 * If this is a COMDAT section, then see if this 307 * section is a keeper and/or if it is to 308 * be discarded. 309 */ 310 if (shdr->sh_type == SHT_SUNW_COMDAT) { 311 Listnode * clist; 312 Is_desc * cisp; 313 314 for (LIST_TRAVERSE(&(osp->os_comdats), 315 clist, cisp)) { 316 if (strcmp(isp->is_basename, 317 cisp->is_basename) == 0) { 318 isp->is_flags |= FLG_IS_DISCARD; 319 DBG_CALL(Dbg_sec_discarded(isp, 320 cisp)); 321 return (0); 322 } 323 } 324 325 /* 326 * This is a new COMDAT section - so keep it. 327 */ 328 if (list_appendc(&(osp->os_comdats), isp) == 0) 329 return ((Os_desc *)S_ERROR); 330 } 331 332 /* 333 * Set alignment 334 */ 335 set_addralign(ofl, osp, isp); 336 337 /* 338 * If this section is a non-empty TLS section and 339 * if the osp is not yet recorded in ofl_osttlsseg, 340 * record it. 341 */ 342 if ((shflags & SHF_TLS) && (shdr->sh_size != 0) && 343 ((osp->os_flags & FLG_OS_TLSNONEMPTY) == 0)) { 344 osp->os_flags |= FLG_OS_TLSNONEMPTY; 345 if (list_appendc(&ofl->ofl_ostlsseg, osp) == 0) 346 return ((Os_desc *)S_ERROR); 347 } 348 349 /* 350 * If is_txtndx is 0 then this section was not 351 * seen in mapfile, so put it at the end. 352 * If is_txtndx is not 0 and ?O is turned on 353 * then check to see where this section should 354 * be inserted. 355 */ 356 if ((sgp->sg_flags & FLG_SG_ORDER) && isp->is_txtndx) { 357 Listnode * tlist; 358 359 tlist = list_where(&(osp->os_isdescs), 360 isp->is_txtndx); 361 if (tlist != NULL) { 362 if (list_insertc(&(osp->os_isdescs), 363 isp, tlist) == 0) 364 return ((Os_desc *)S_ERROR); 365 } else { 366 if (list_prependc(&(osp->os_isdescs), 367 isp) == 0) 368 return ((Os_desc *)S_ERROR); 369 } 370 } else 371 if (list_appendc(&(osp->os_isdescs), isp) == 0) 372 return ((Os_desc *)S_ERROR); 373 374 isp->is_osdesc = osp; 375 376 /* 377 * If this input section and file is associated to an 378 * artificially referenced output section, make sure 379 * they are marked as referenced also. This insures this 380 * input section and file isn't eliminated when -zignore 381 * is in effect. 382 * See -zignore comments when creating a new output 383 * section below. 384 */ 385 if (((ifl && (ifl->ifl_flags & FLG_IF_IGNORE)) || 386 dbg_mask) && 387 (osp->os_flags & FLG_OS_SECTREF)) { 388 isp->is_flags |= FLG_IS_SECTREF; 389 if (ifl) 390 ifl->ifl_flags |= FLG_IF_FILEREF; 391 } 392 393 DBG_CALL(Dbg_sec_added(osp, sgp)); 394 return (osp); 395 } 396 397 /* 398 * check to see if we need to worry about section 399 * ordering. 400 */ 401 if (os_ndx) { 402 if (osp->os_txtndx) { 403 if (os_ndx < osp->os_txtndx) 404 /* insert section here. */ 405 break; 406 else { 407 lnp2 = lnp1; 408 continue; 409 } 410 } else { 411 /* insert section here. */ 412 break; 413 } 414 } else if (osp->os_txtndx) { 415 lnp2 = lnp1; 416 continue; 417 } 418 419 /* 420 * If the new sections identifier is less than that of the 421 * present input section we need to insert the new section 422 * at this point. 423 */ 424 if (ident < osp->os_scnsymndx) 425 break; 426 lnp2 = lnp1; 427 } 428 429 /* 430 * We are adding a new output section. Update the section header 431 * count and associated string size. 432 */ 433 ofl->ofl_shdrcnt++; 434 if (st_insert(ofl->ofl_shdrsttab, isp->is_name) == -1) 435 return ((Os_desc *)S_ERROR); 436 437 /* 438 * Create a new output section descriptor. 439 */ 440 if ((osp = libld_calloc(sizeof (Os_desc), 1)) == 0) 441 return ((Os_desc *)S_ERROR); 442 if ((osp->os_shdr = libld_calloc(sizeof (Shdr), 1)) == 0) 443 return ((Os_desc *)S_ERROR); 444 445 /* 446 * We convert COMDAT sections to PROGBITS if this is the first 447 * section of a output section. 448 */ 449 if (shdr->sh_type == SHT_SUNW_COMDAT) { 450 Shdr * tshdr; 451 452 if ((tshdr = libld_malloc(sizeof (Shdr))) == 0) 453 return ((Os_desc *)S_ERROR); 454 *tshdr = *shdr; 455 isp->is_shdr = shdr = tshdr; 456 shdr->sh_type = SHT_PROGBITS; 457 if (list_appendc(&(osp->os_comdats), isp) == 0) 458 return ((Os_desc *)S_ERROR); 459 } 460 461 osp->os_shdr->sh_type = shdr->sh_type; 462 osp->os_shdr->sh_flags = shdr->sh_flags; 463 osp->os_shdr->sh_entsize = shdr->sh_entsize; 464 osp->os_name = isp->is_name; 465 osp->os_namehash = isp->is_namehash; 466 osp->os_txtndx = os_ndx; 467 osp->os_sgdesc = sgp; 468 if (ifl && (shdr->sh_type == SHT_PROGBITS)) { 469 /* 470 * Trying to preserved the possibly intended meaning of 471 * sh_link/sh_info. See the translate_link() 472 * in update.c. 473 */ 474 osp->os_shdr->sh_link = shdr->sh_link; 475 if (shdr->sh_flags & SHF_INFO_LINK) 476 osp->os_shdr->sh_info = shdr->sh_info; 477 } 478 479 /* 480 * When -zignore is in effect, sections and files that are not 481 * referenced * from other sections, will be eliminated from the 482 * object being produced. Some sections, although unreferenced, 483 * are special, and must not be eliminated. Determine if this new 484 * output section is one of those special sections, and if so mark 485 * it artificially as referenced. 486 * Any input section and file associated to this output section 487 * will also be marked as referenced, and thus won't be eliminated 488 * from the final output. 489 */ 490 if ((strcmp(osp->os_name, MSG_ORIG(MSG_SCN_INIT)) == 0) || 491 (strcmp(osp->os_name, MSG_ORIG(MSG_SCN_FINI)) == 0) || 492 (strcmp(osp->os_name, MSG_ORIG(MSG_SCN_EX_RANGES)) == 0) || 493 (strcmp(osp->os_name, MSG_ORIG(MSG_SCN_EX_SHARED)) == 0) || 494 (strcmp(osp->os_name, MSG_ORIG(MSG_SCN_CTORS)) == 0) || 495 (strcmp(osp->os_name, MSG_ORIG(MSG_SCN_DTORS)) == 0) || 496 (strcmp(osp->os_name, MSG_ORIG(MSG_SCN_EHFRAME)) == 0) || 497 (strcmp(osp->os_name, MSG_ORIG(MSG_SCN_EHFRAME_HDR)) == 0) || 498 (strcmp(osp->os_name, MSG_ORIG(MSG_SCN_JCR)) == 0)) { 499 osp->os_flags |= FLG_OS_SECTREF; 500 501 if ((ifl && (ifl->ifl_flags & FLG_IF_IGNORE)) || dbg_mask) { 502 isp->is_flags |= FLG_IS_SECTREF; 503 if (ifl) 504 ifl->ifl_flags |= FLG_IF_FILEREF; 505 } 506 } 507 508 /* 509 * Setions of SHT_GROUP are added to the ofl->ofl_osgroups 510 * list - so that they can be updated as a group later. 511 */ 512 if (shdr->sh_type == SHT_GROUP) { 513 if (list_appendc(&ofl->ofl_osgroups, osp) == 0) 514 return ((Os_desc *)S_ERROR); 515 } 516 517 /* 518 * If this section is a TLS section - keep track of it 519 * for the latter building of the PT_TLS segment. 520 */ 521 if ((shflags & SHF_TLS) && (shdr->sh_size != 0)) { 522 osp->os_flags |= FLG_OS_TLSNONEMPTY; 523 if (list_appendc(&ofl->ofl_ostlsseg, osp) == 0) 524 return ((Os_desc *)S_ERROR); 525 } 526 527 /* 528 * If a non-allocatable section is going to be put into a loadable 529 * segment then turn on the allocate bit for this section and warn the 530 * user that we have done so. This could only happen through the use 531 * of a mapfile. 532 */ 533 if (sgp->sg_phdr.p_type == PT_LOAD) { 534 if (!(osp->os_shdr->sh_flags & SHF_ALLOC)) { 535 eprintf(ERR_WARNING, MSG_INTL(MSG_SCN_NONALLOC), 536 ofl->ofl_name, osp->os_name); 537 osp->os_shdr->sh_flags |= SHF_ALLOC; 538 } 539 } 540 541 /* 542 * Retain this sections identifier for future comparisons when placing 543 * a section (after all sections have been processed this variable will 544 * be used to hold the sections symbol index as we don't need to retain 545 * the identifier any more). 546 */ 547 osp->os_scnsymndx = ident; 548 549 /* 550 * Set alignment 551 */ 552 set_addralign(ofl, osp, isp); 553 554 if (list_appendc(&(osp->os_isdescs), isp) == 0) 555 return ((Os_desc *)S_ERROR); 556 557 DBG_CALL(Dbg_sec_created(osp, sgp)); 558 isp->is_osdesc = osp; 559 if (lnp2) { 560 if (list_insertc(&(sgp->sg_osdescs), osp, lnp2) == 0) 561 return ((Os_desc *)S_ERROR); 562 } else { 563 if (list_prependc(&(sgp->sg_osdescs), osp) == 0) 564 return ((Os_desc *)S_ERROR); 565 } 566 return (osp); 567 } 568