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