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 /* 28 * Copyright (c) 1988 AT&T 29 * All Rights Reserved 30 */ 31 32 /* 33 * Utility functions 34 */ 35 #include <unistd.h> 36 #include <stdio.h> 37 #include <stdarg.h> 38 #include <string.h> 39 #include <fcntl.h> 40 #include <sys/types.h> 41 #include <sys/mman.h> 42 #include <errno.h> 43 #include <sgs.h> 44 #include <libintl.h> 45 #include <debug.h> 46 #include "msg.h" 47 #include "_libld.h" 48 49 /* 50 * libld_malloc() and dz_map() are used for both performance and for ease of 51 * programming: 52 * 53 * Performance: 54 * The link-edit is a short lived process which doesn't really free much 55 * of the dynamic memory that it requests. Because of this, it is more 56 * important to optimize for quick memory allocations than the 57 * re-usability of the memory. 58 * 59 * By also mmaping blocks of pages in from /dev/zero we don't need to 60 * waste the overhead of zeroing out these pages for calloc() requests. 61 * 62 * Memory Management: 63 * By doing all libld memory management through the ld_malloc routine 64 * it's much easier to free up all memory at the end by simply unmaping 65 * all of the blocks that were mapped in through dz_map(). This is much 66 * simpler then trying to track all of the libld structures that were 67 * dynamically allocate and are actually pointers into the ELF files. 68 * 69 * It's important that we can free up all of our dynamic memory because 70 * libld is used by ld.so.1 when it performs dlopen()'s of relocatable 71 * objects. 72 * 73 * Format: 74 * The memory blocks for each allocation store the size of the allocation 75 * in the first 8 bytes of the block. The pointer that is returned by 76 * libld_malloc() is actually the address of (block + 8): 77 * 78 * (addr - 8) block_size 79 * (addr) <allocated block> 80 * 81 * The size is retained in order to implement realloc(), and to perform 82 * the required memcpy(). 8 bytes are uses, as the memory area returned 83 * by libld_malloc() must be 8 byte-aligned. Even in a 32-bit environment, 84 * u_longlog_t pointers are employed. 85 * 86 * Map anonymous memory via MAP_ANON (added in Solaris 8). 87 */ 88 static void * 89 dz_map(size_t size) 90 { 91 void *addr; 92 93 if ((addr = mmap(0, size, (PROT_READ | PROT_WRITE | PROT_EXEC), 94 (MAP_PRIVATE | MAP_ANON), -1, 0)) == MAP_FAILED) { 95 int err = errno; 96 eprintf(0, ERR_FATAL, MSG_INTL(MSG_SYS_MMAPANON), 97 strerror(err)); 98 return (MAP_FAILED); 99 } 100 return (addr); 101 } 102 103 void * 104 libld_malloc(size_t size) 105 { 106 Ld_heap *chp = ld_heap; 107 void *vptr; 108 size_t asize = size + HEAPALIGN; 109 110 /* 111 * If this is the first allocation, or the allocation request is greater 112 * than the current free space available, allocate a new heap. 113 */ 114 if ((chp == NULL) || 115 (((size_t)chp->lh_end - (size_t)chp->lh_free) <= asize)) { 116 Ld_heap *nhp; 117 size_t hsize = (size_t)S_ROUND(sizeof (Ld_heap), HEAPALIGN); 118 size_t tsize = (size_t)S_ROUND((asize + hsize), HEAPALIGN); 119 120 /* 121 * Allocate a block that is at minimum 'HEAPBLOCK' size 122 */ 123 if (tsize < HEAPBLOCK) 124 tsize = HEAPBLOCK; 125 126 if ((nhp = dz_map(tsize)) == MAP_FAILED) 127 return (NULL); 128 129 nhp->lh_next = chp; 130 nhp->lh_free = (void *)((size_t)nhp + hsize); 131 nhp->lh_end = (void *)((size_t)nhp + tsize); 132 133 ld_heap = chp = nhp; 134 } 135 vptr = chp->lh_free; 136 137 /* 138 * Assign size to head of allocated block (used by realloc), and 139 * memory arena as then next 8-byte aligned offset. 140 */ 141 *((size_t *)vptr) = size; 142 vptr = (void *)((size_t)vptr + HEAPALIGN); 143 144 /* 145 * Increment free to point to next available block 146 */ 147 chp->lh_free = (void *)S_ROUND((size_t)chp->lh_free + asize, 148 HEAPALIGN); 149 150 return (vptr); 151 } 152 153 void * 154 libld_realloc(void *ptr, size_t size) 155 { 156 size_t psize; 157 void *vptr; 158 159 if (ptr == NULL) 160 return (libld_malloc(size)); 161 162 /* 163 * Size of the allocated blocks is stored *just* before the blocks 164 * address. 165 */ 166 psize = *((size_t *)((size_t)ptr - HEAPALIGN)); 167 168 /* 169 * If the block actually fits then just return. 170 */ 171 if (size <= psize) 172 return (ptr); 173 174 if ((vptr = libld_malloc(size)) != NULL) 175 (void) memcpy(vptr, ptr, psize); 176 177 return (vptr); 178 } 179 180 void 181 /* ARGSUSED 0 */ 182 libld_free(void *ptr) 183 { 184 } 185 186 /* 187 * Determine if a shared object definition structure already exists and if 188 * not create one. These definitions provide for recording information 189 * regarding shared objects that are still to be processed. Once processed 190 * shared objects are maintained on the ofl_sos list. The information 191 * recorded in this structure includes: 192 * 193 * o DT_USED requirements. In these cases definitions are added during 194 * mapfile processing of `-' entries (see map_dash()). 195 * 196 * o implicit NEEDED entries. As shared objects are processed from the 197 * command line so any of their dependencies are recorded in these 198 * structures for later processing (see process_dynamic()). 199 * 200 * o version requirements. Any explicit shared objects that have version 201 * dependencies on other objects have their version requirements recorded. 202 * In these cases definitions are added during mapfile processing of `-' 203 * entries (see map_dash()). Also, shared objects may have versioning 204 * requirements on their NEEDED entries. These cases are added during 205 * their version processing (see vers_need_process()). 206 * 207 * Note: Both process_dynamic() and vers_need_process() may generate the 208 * initial version definition structure because you can't rely on what 209 * section (.dynamic or .SUNW_version) may be processed first from any 210 * input file. 211 */ 212 Sdf_desc * 213 sdf_find(const char *name, APlist *alp) 214 { 215 Aliste idx; 216 Sdf_desc *sdf; 217 218 for (APLIST_TRAVERSE(alp, idx, sdf)) 219 if (strcmp(name, sdf->sdf_name) == 0) 220 return (sdf); 221 222 return (NULL); 223 } 224 225 Sdf_desc * 226 sdf_add(const char *name, APlist **alpp) 227 { 228 Sdf_desc *sdf; 229 230 if ((sdf = libld_calloc(sizeof (Sdf_desc), 1)) == NULL) 231 return ((Sdf_desc *)S_ERROR); 232 233 sdf->sdf_name = name; 234 235 if (aplist_append(alpp, sdf, AL_CNT_OFL_LIBS) == NULL) 236 return ((Sdf_desc *)S_ERROR); 237 238 return (sdf); 239 } 240 241 /* 242 * Add a string, separated by a colon, to an existing string. Typically used 243 * to maintain filter, rpath and audit names, of which there is normally only 244 * one string supplied anyway. 245 */ 246 char * 247 add_string(char *old, char *str) 248 { 249 char *new; 250 251 if (old) { 252 char *_str; 253 size_t len; 254 255 /* 256 * If an original string exists, make sure this new string 257 * doesn't get duplicated. 258 */ 259 if ((_str = strstr(old, str)) != NULL) { 260 if (((_str == old) || 261 (*(_str - 1) == *(MSG_ORIG(MSG_STR_COLON)))) && 262 (_str += strlen(str)) && 263 ((*_str == '\0') || 264 (*_str == *(MSG_ORIG(MSG_STR_COLON))))) 265 return (old); 266 } 267 268 len = strlen(old) + strlen(str) + 2; 269 if ((new = libld_calloc(1, len)) == NULL) 270 return ((char *)S_ERROR); 271 (void) snprintf(new, len, MSG_ORIG(MSG_FMT_COLPATH), old, str); 272 } else { 273 if ((new = libld_malloc(strlen(str) + 1)) == NULL) 274 return ((char *)S_ERROR); 275 (void) strcpy(new, str); 276 } 277 278 return (new); 279 } 280 281 /* 282 * Determine whether this string, possibly with an associated option, should be 283 * translated to an option character. If so, update the optind and optarg 284 * as described for short options in getopt(3c). 285 */ 286 static int 287 str2chr(Lm_list *lml, int ndx, int argc, char **argv, char *arg, int c, 288 const char *opt, size_t optsz) 289 { 290 if (optsz == 0) { 291 /* 292 * Compare a single option (ie. there's no associated option 293 * argument). 294 */ 295 if (strcmp(arg, opt) == 0) { 296 DBG_CALL(Dbg_args_str2chr(lml, ndx, opt, c)); 297 optind += 1; 298 return (c); 299 } 300 301 } else if (strncmp(arg, opt, optsz) == 0) { 302 /* 303 * Otherwise, compare the option name, which may be 304 * concatenated with the option argument. 305 */ 306 DBG_CALL(Dbg_args_str2chr(lml, ndx, opt, c)); 307 308 if (arg[optsz] == '\0') { 309 /* 310 * Optarg is the next argument (white space separated). 311 * Make sure an optarg is available, and if not return 312 * a failure to prevent any fall-through to the generic 313 * getopt() processing. 314 */ 315 if ((++optind + 1) > argc) { 316 return ('?'); 317 } 318 optarg = argv[optind]; 319 optind++; 320 } else { 321 /* 322 * Optarg concatenated to option (no white space). 323 * GNU option/option argument pairs can be represented 324 * with a "=" separator. If this is the case, remove 325 * the separator. 326 */ 327 optarg = &arg[optsz]; 328 optind++; 329 if (*optarg == '=') { 330 if (*(++optarg) == '\0') 331 return ('?'); 332 } 333 } 334 return (c); 335 } 336 return (0); 337 } 338 339 /* 340 * Parse an individual option. The intent of this function is to determine if 341 * any known, non-Solaris options have been passed to ld(1). This condition 342 * can occur as a result of build configuration tools, because of users 343 * familiarity with other systems, or simply the users preferences. If a known 344 * non-Solaris option can be determined, translate that option into the Solaris 345 * counterpart. 346 * 347 * This function will probably never be a complete solution, as new, non-Solaris 348 * options are discovered, their translation will have to be added. Other 349 * non-Solaris options are incompatible with the Solaris link-editor, and will 350 * never be recognized. We support what we can. 351 */ 352 int 353 ld_getopt(Lm_list *lml, int ndx, int argc, char **argv) 354 { 355 int c; 356 357 if ((optind < argc) && argv[optind] && (argv[optind][0] == '-')) { 358 char *arg = &argv[optind][1]; 359 360 switch (*arg) { 361 case 'r': 362 /* Translate -rpath <optarg> to -R <optarg> */ 363 if ((c = str2chr(lml, ndx, argc, argv, arg, 'R', 364 MSG_ORIG(MSG_ARG_T_RPATH), 365 MSG_ARG_T_RPATH_SIZE)) != 0) { 366 return (c); 367 } 368 break; 369 case 's': 370 /* Translate -shared to -G */ 371 if ((c = str2chr(lml, ndx, argc, argv, arg, 'G', 372 MSG_ORIG(MSG_ARG_T_SHARED), 0)) != 0) { 373 return (c); 374 375 /* Translate -soname <optarg> to -h <optarg> */ 376 } else if ((c = str2chr(lml, ndx, argc, argv, arg, 'h', 377 MSG_ORIG(MSG_ARG_T_SONAME), 378 MSG_ARG_T_SONAME_SIZE)) != 0) { 379 return (c); 380 } 381 break; 382 case '(': 383 /* 384 * Translate -( to -z rescan-start 385 */ 386 if ((c = str2chr(lml, ndx, argc, argv, 387 arg, 'z', MSG_ORIG(MSG_ARG_T_OPAR), 0)) != 0) { 388 optarg = (char *)MSG_ORIG(MSG_ARG_RESCAN_START); 389 return (c); 390 } 391 break; 392 case ')': 393 /* 394 * Translate -) to -z rescan-end 395 */ 396 if ((c = str2chr(lml, ndx, argc, argv, 397 arg, 'z', MSG_ORIG(MSG_ARG_T_CPAR), 0)) != 0) { 398 optarg = (char *)MSG_ORIG(MSG_ARG_RESCAN_END); 399 return (c); 400 } 401 break; 402 case '-': 403 switch (*(arg + 1)) { 404 case 'a': 405 /* 406 * Translate --allow-multiple-definition to 407 * -zmuldefs 408 */ 409 if ((c = str2chr(lml, ndx, argc, argv, arg, 'z', 410 MSG_ORIG(MSG_ARG_T_MULDEFS), 0)) != 0) { 411 optarg = 412 (char *)MSG_ORIG(MSG_ARG_MULDEFS); 413 return (c); 414 415 /* 416 * Translate --auxiliary <optarg> to 417 * -f <optarg> 418 */ 419 } else if ((c = str2chr(lml, argc, ndx, argv, 420 arg, 'f', MSG_ORIG(MSG_ARG_T_AUXFLTR), 421 MSG_ARG_T_AUXFLTR_SIZE)) != 0) { 422 return (c); 423 } 424 break; 425 case 'd': 426 /* 427 * Translate --dynamic-linker <optarg> to 428 * -I <optarg> 429 */ 430 if ((c = str2chr(lml, ndx, argc, argv, arg, 'I', 431 MSG_ORIG(MSG_ARG_T_INTERP), 432 MSG_ARG_T_INTERP_SIZE)) != 0) { 433 return (c); 434 } 435 break; 436 case 'e': 437 /* Translate --entry <optarg> to -e <optarg> */ 438 if ((c = str2chr(lml, ndx, argc, argv, arg, 'e', 439 MSG_ORIG(MSG_ARG_T_ENTRY), 440 MSG_ARG_T_ENTRY_SIZE)) != 0) { 441 return (c); 442 } 443 /* 444 * Translate --end-group to -z rescan-end 445 */ 446 if ((c = str2chr(lml, ndx, argc, argv, 447 arg, 'z', 448 MSG_ORIG(MSG_ARG_T_ENDGROUP), 0)) != 0) { 449 optarg = (char *) 450 MSG_ORIG(MSG_ARG_RESCAN_END); 451 return (c); 452 } 453 break; 454 case 'f': 455 /* Translate --filter <optarg> to -F <optarg> */ 456 if ((c = str2chr(lml, ndx, argc, argv, arg, 'F', 457 MSG_ORIG(MSG_ARG_T_STDFLTR), 458 MSG_ARG_T_STDFLTR_SIZE)) != 0) { 459 return (c); 460 } 461 break; 462 case 'h': 463 /* Translate --help to -zhelp */ 464 if ((c = str2chr(lml, ndx, argc, argv, arg, 'z', 465 MSG_ORIG(MSG_ARG_T_HELP), 0)) != 0) { 466 optarg = (char *)MSG_ORIG(MSG_ARG_HELP); 467 return (c); 468 } 469 break; 470 case 'l': 471 /* 472 * Translate --library <optarg> to -l <optarg> 473 */ 474 if ((c = str2chr(lml, ndx, argc, argv, arg, 'l', 475 MSG_ORIG(MSG_ARG_T_LIBRARY), 476 MSG_ARG_T_LIBRARY_SIZE)) != 0) { 477 return (c); 478 479 /* 480 * Translate --library-path <optarg> to 481 * -L <optarg> 482 */ 483 } else if ((c = str2chr(lml, ndx, argc, argv, 484 arg, 'L', MSG_ORIG(MSG_ARG_T_LIBPATH), 485 MSG_ARG_T_LIBPATH_SIZE)) != 0) { 486 return (c); 487 } 488 break; 489 case 'n': 490 /* Translate --no-undefined to -zdefs */ 491 if ((c = str2chr(lml, ndx, argc, argv, arg, 'z', 492 MSG_ORIG(MSG_ARG_T_NOUNDEF), 0)) != 0) { 493 optarg = (char *)MSG_ORIG(MSG_ARG_DEFS); 494 return (c); 495 496 /* 497 * Translate --no-whole-archive to 498 * -z defaultextract 499 */ 500 } else if ((c = str2chr(lml, ndx, argc, argv, 501 arg, 'z', 502 MSG_ORIG(MSG_ARG_T_NOWHOLEARC), 0)) != 0) { 503 optarg = 504 (char *)MSG_ORIG(MSG_ARG_DFLEXTRT); 505 return (c); 506 } 507 break; 508 case 'o': 509 /* Translate --output <optarg> to -o <optarg> */ 510 if ((c = str2chr(lml, ndx, argc, argv, arg, 'o', 511 MSG_ORIG(MSG_ARG_T_OUTPUT), 512 MSG_ARG_T_OUTPUT_SIZE)) != 0) { 513 return (c); 514 } 515 break; 516 case 'r': 517 /* Translate --relocatable to -r */ 518 if ((c = str2chr(lml, ndx, argc, argv, arg, 'r', 519 MSG_ORIG(MSG_ARG_T_RELOCATABLE), 0)) != 0) { 520 return (c); 521 } 522 break; 523 case 's': 524 /* Translate --strip-all to -s */ 525 if ((c = str2chr(lml, ndx, argc, argv, arg, 's', 526 MSG_ORIG(MSG_ARG_T_STRIP), 0)) != 0) { 527 return (c); 528 } 529 /* 530 * Translate --start-group to -z rescan-start 531 */ 532 if ((c = str2chr(lml, ndx, argc, argv, 533 arg, 'z', 534 MSG_ORIG(MSG_ARG_T_STARTGROUP), 0)) != 0) { 535 optarg = (char *) 536 MSG_ORIG(MSG_ARG_RESCAN_START); 537 return (c); 538 } 539 break; 540 case 'u': 541 /* 542 * Translate --undefined <optarg> to 543 * -u <optarg> 544 */ 545 if ((c = str2chr(lml, ndx, argc, argv, arg, 'u', 546 MSG_ORIG(MSG_ARG_T_UNDEF), 547 MSG_ARG_T_UNDEF_SIZE)) != 0) { 548 return (c); 549 } 550 break; 551 case 'v': 552 /* Translate --version to -V */ 553 if ((c = str2chr(lml, ndx, argc, argv, arg, 'V', 554 MSG_ORIG(MSG_ARG_T_VERSION), 0)) != 0) { 555 return (c); 556 } 557 break; 558 case 'w': 559 /* 560 * Translate --whole-archive to -z alltextract 561 */ 562 if ((c = str2chr(lml, ndx, argc, argv, 563 arg, 'z', 564 MSG_ORIG(MSG_ARG_T_WHOLEARC), 0)) != 0) { 565 optarg = 566 (char *)MSG_ORIG(MSG_ARG_ALLEXTRT); 567 return (c); 568 } 569 break; 570 } 571 break; 572 } 573 } 574 if ((c = getopt(argc, argv, MSG_ORIG(MSG_STR_OPTIONS))) != -1) { 575 /* 576 * It is possible that a "-Wl," argument has been used to 577 * specify an option. This isn't advertized ld(1) syntax, but 578 * compiler drivers and configuration tools, have been known to 579 * pass this compiler option to ld(1). Strip off the "-Wl," 580 * prefix and pass the option through. 581 */ 582 if ((c == 'W') && (strncmp(optarg, 583 MSG_ORIG(MSG_ARG_T_WL), MSG_ARG_T_WL_SIZE) == 0)) { 584 DBG_CALL(Dbg_args_Wldel(lml, ndx, optarg)); 585 c = optarg[MSG_ARG_T_WL_SIZE]; 586 optarg += MSG_ARG_T_WL_SIZE + 1; 587 } 588 } 589 590 return (c); 591 } 592 593 /* 594 * A compare routine for Isd_node AVLT trees. 595 */ 596 int 597 isdavl_compare(const void *n1, const void *n2) 598 { 599 uint_t hash1, hash2; 600 const char *st1, *st2; 601 int rc; 602 603 hash1 = ((Isd_node *)n1)->isd_hash; 604 hash2 = ((Isd_node *)n2)->isd_hash; 605 606 if (hash1 > hash2) 607 return (1); 608 if (hash1 < hash2) 609 return (-1); 610 611 st1 = ((Isd_node *)n1)->isd_isp->is_name; 612 st2 = ((Isd_node *)n2)->isd_isp->is_name; 613 614 rc = strcmp(st1, st2); 615 if (rc > 0) 616 return (1); 617 if (rc < 0) 618 return (-1); 619 return (0); 620 } 621 622 /* 623 * Messaging support - funnel everything through dgettext(). 624 */ 625 const char * 626 _libld_msg(Msg mid) 627 { 628 return (dgettext(MSG_ORIG(MSG_SUNW_OST_SGS), MSG_ORIG(mid))); 629 } 630 631 /* 632 * Determine whether a symbol name should be demangled. 633 */ 634 const char * 635 demangle(const char *name) 636 { 637 if (demangle_flag) 638 return (Elf_demangle_name(name)); 639 else 640 return (name); 641 } 642