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 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * This file contains all functions relating to stab processing. The 31 * stab table is compressed by eliminating duplicate include file entries. 32 */ 33 #include <stdio.h> 34 #include <string.h> 35 #include <stab.h> 36 #include <unistd.h> 37 #include <stdlib.h> 38 #include <signal.h> 39 #include <sys/param.h> 40 #include <errno.h> 41 #include <libintl.h> 42 #include "libld.h" 43 #include "msg.h" 44 45 46 /* 47 * With the 5.x compiler, stab.h changed struct nlist into 48 * struct stab and got rid of it's embeded unions. 49 */ 50 #if __SUNPRO_C >= 0x500 || defined(__GNUC__) 51 #define nlist stab 52 #else 53 #define n_strx n_un.n_strx 54 #endif 55 56 57 /* 58 * Data structure that holds persistent data that sbfocus_symbol & sbfocus_close 59 * needs. Passing in a pointer to this struct makes them re-entrant. 60 */ 61 typedef struct sbld_tag { 62 FILE *fd; 63 int failed; 64 } *Sbld, Sbld_rec; 65 66 67 extern Sbld_rec sb_data; 68 extern const char *out_fname, *in_fname; 69 extern Half out_e_type; 70 extern void sbfocus_symbol(Sbld, const char *, const char *, 71 const char *); 72 73 #if !defined(_ELF64) 74 75 /* 76 * holds information needed by sbfocus_symbol and sbfocus_close. 77 */ 78 Sbld_rec sb_data = { NULL, 0 }; 79 80 /* 81 * holds information out the output file being created. 82 */ 83 const char *out_fname = NULL; 84 const char *in_fname = NULL; /* current input file */ 85 Half out_e_type = ET_NONE; 86 87 /* 88 * Signal handler is called when a SIGPIPE is encountered. This would 89 * happen in case `sbfocus' did not exist and `ld' is writing down a 90 * pipe with no reader. Trap signal and set failed field so that no 91 * more subsequent writes occur. 92 */ 93 static void 94 sigpipe_handler() 95 { 96 sb_data.failed = 1; 97 } 98 99 /* 100 * sbfocus_symbol() will write one symbol to a pipe that has the program 101 * "sbfocus" at the receiving end. If the program has not been started yet, 102 * it is started, and the pipe established. "sbfocus" is started with the 103 * function arguments "type" and "name" as its arguments, in that order. 104 * 105 * sbfocus_symbol() should be called with four arguments: 106 * data Pointer to a Sbld struct that the caller has allocated in 107 * permanent storage. It must be the same struct for all related 108 * calls to sbfocus_symbol(). 109 * name This is the string name of the library/executable being built. 110 * type A string, should be one of: 111 * "-x": Building an executable or shared object 112 * "-r": Concatenating object files 113 * symbol The string that should be written to "sbfocus". If this 114 * argument is NULL "sbfocus" is started, but no symbol is 115 * written to it. 116 */ 117 void 118 sbfocus_symbol(Sbld data, const char *name, const char *type, 119 const char *symbol) 120 { 121 int fd[2], err; 122 123 if (data->failed) { 124 return; 125 } 126 127 (void) signal(SIGPIPE, (void (*)(int)) sigpipe_handler); 128 129 if (data->fd == NULL) { 130 data->failed = 0; 131 (void) pipe(fd); 132 133 switch (fork()) { 134 case -1: 135 err = errno; 136 (void) fprintf(stderr, MSG_INTL(MSG_SYS_FORK), 137 in_fname, strerror(err), 138 MSG_INTL(MSG_STAB_NOSBROW)); 139 data->failed = 1; 140 (void) close(fd[0]); 141 (void) close(fd[1]); 142 return; 143 144 /* 145 * Child process 146 */ 147 case 0: 148 (void) close(fd[1]); 149 (void) dup2(fd[0], fileno(stdin)); 150 (void) close(fd[0]); 151 (void) execlp(MSG_ORIG(MSG_STR_SBFOCUS), 152 MSG_ORIG(MSG_STR_SBFOCUS), type, name, 0); 153 154 err = errno; 155 (void) fprintf(stderr, MSG_INTL(MSG_SYS_EXEC), 156 in_fname, MSG_ORIG(MSG_STR_SBFOCUS), 157 strerror(err), MSG_INTL(MSG_STAB_NOSBROW)); 158 exit(-1); 159 160 /* 161 * Parent process 162 */ 163 default: 164 (void) close(fd[0]); 165 data->fd = fdopen(fd[1], MSG_ORIG(MSG_STR_W)); 166 break; 167 } 168 } 169 if (symbol != NULL) { 170 (void) fputs(symbol, data->fd); 171 (void) putc('\n', data->fd); 172 } 173 } 174 #endif /* !defined(_ELF64) */ 175 176 177 static Xword 178 pass1_stabindex(const Elf_Data *s_data, const Elf_Data *str_data, 179 const size_t cwd_len, const size_t name_len) 180 { 181 struct nlist *elem; 182 struct nlist *last = NULL; 183 size_t i; 184 size_t str_offset = 0; 185 size_t new_size = 0; 186 size_t first_object = 1; 187 size_t any_obj = 0; 188 size_t num_elem; 189 /* 190 * The processing of the stab table happens in two passes. 191 * 192 * first pass: calculate if any change is needed and if so, how much 193 * the string table needs to be expanded by. 194 */ 195 num_elem = s_data->d_size / sizeof (struct nlist); 196 for (i = 0; i < num_elem; i++) { 197 char *str; 198 199 elem = (struct nlist *)s_data->d_buf + i; 200 switch (elem->n_type) { 201 case 0: 202 if (last) 203 str_offset += last->n_value; 204 last = elem; 205 break; 206 case N_OBJ: 207 str = (char *)str_data->d_buf + str_offset + 208 elem->n_strx; 209 210 if ((*str == '\0') && first_object) { 211 /* 212 * This is a 'CWD' N_OBJ 213 * 214 * we only record the 'cwd' once in each 215 * stringtable. so - we only need to add 216 * it's length once to the new_size 217 */ 218 if (any_obj == 0) { 219 any_obj++; 220 new_size += cwd_len + 1; 221 } /* if */ 222 first_object = 0; 223 } /* if */ 224 else if (*str == '\0') { 225 /* 226 * This is a 'object_name' N_OBJ 227 */ 228 new_size += name_len + 1; 229 first_object = 1; 230 } /* else if */ 231 break; 232 default: 233 /* no-op */ 234 break; 235 } /* switch */ 236 } /* for */ 237 /*LINTED*/ 238 return ((Xword) new_size); 239 } /* pass1_stabindex */ 240 241 242 static int 243 pass2_stabindex(Elf_Data *s_data, Elf_Data *str_data, const char *name, 244 size_t name_len, size_t cwd_pos, size_t free_pos) 245 { 246 struct nlist *elem; 247 struct nlist *last = NULL; 248 size_t i; 249 size_t str_offset = 0; 250 size_t first_object = 1; 251 size_t num_elem; 252 /* 253 * The processing of the stab table happens in two passes. 254 * 255 * first pass: calculate if any change is needed and if so, how much 256 * the string table needs to be expanded by. 257 */ 258 num_elem = s_data->d_size / sizeof (struct nlist); 259 for (i = 0; i < num_elem; i++) { 260 char *str; 261 262 elem = (struct nlist *)s_data->d_buf + i; 263 switch (elem->n_type) { 264 case 0: 265 if (last) 266 str_offset += last->n_value; 267 last = elem; 268 break; 269 case N_OBJ: 270 str = (char *)str_data->d_buf + str_offset + 271 elem->n_strx; 272 273 if ((*str == '\0') && first_object) { 274 /* 275 * This is a 'CWD' N_OBJ 276 * 277 * We point it at the CWD entry that we've 278 * already placed in the new string_table. 279 */ 280 /*LINTED*/ 281 elem->n_strx = (unsigned)(cwd_pos - str_offset); 282 first_object = 0; 283 } /* if */ 284 else if (*str == '\0') { 285 /* 286 * This is a 'object_name' N_OBJ. 287 * 288 * Append the object name to the string table 289 * and set the elem->n_un.n_strx to point 290 * to it. 291 */ 292 (void) strcpy((char *)str_data->d_buf + 293 free_pos, name); 294 /*LINTED*/ 295 elem->n_strx = (unsigned)(free_pos - 296 str_offset); 297 free_pos += name_len + 1; 298 first_object = 1; 299 } /* if */ 300 break; 301 default: 302 break; 303 } /* switch */ 304 } /* for */ 305 306 /*LINTED*/ 307 last->n_value = (unsigned)(str_data->d_size - str_offset); 308 309 return (1); 310 } /* pass2_stabindex() */ 311 312 313 /* 314 * find_scn() 315 * 316 * Find a section in elf that matches the supplied section name, 317 * type, and flags. 318 * 319 * Returns: 320 * section number if found 321 * 0 - if no matching section found 322 * -1 - if error 323 * 324 * If shdr is a non-null pointer it will be set to the section header 325 * that was found. 326 */ 327 static size_t 328 find_scn(Elf *elf, const char *elf_strtab, const char *name, 329 const Word sh_type, const Xword sh_flags, Elf_Scn **ret_scn) 330 { 331 Elf_Scn *scn = NULL; 332 Shdr *scn_shdr; 333 334 while ((scn = elf_nextscn(elf, scn)) != 0) { 335 if ((scn_shdr = elf_getshdr(scn)) == NULL) 336 return ((size_t)-1); 337 if ((scn_shdr->sh_type == sh_type) && 338 (scn_shdr->sh_flags == sh_flags) && 339 (strcmp(elf_strtab + scn_shdr->sh_name, name) == 0)) { 340 size_t scn_ndx; 341 /* 342 * we've got a match 343 */ 344 if ((scn_ndx = elf_ndxscn(scn)) == SHN_UNDEF) 345 return ((size_t)-1); 346 if (ret_scn) 347 *ret_scn = scn; 348 return (scn_ndx); 349 } /* if */ 350 } /* while */ 351 352 /* 353 * no match found 354 */ 355 return (0); 356 } /* find_scn() */ 357 358 359 static Elf_Data * 360 get_str_data(Elf *elf, const char *strtab, const char *name, Shdr *shdr) 361 { 362 Elf_Scn *str_scn; 363 Elf_Data *str_data; 364 365 /* 366 * The stab's string table can be found through the 367 * shdr->sh_link value. 368 */ 369 if (shdr->sh_link == 0) { 370 /* 371 * Normally the sh_link field should point to the 372 * required strtab. But if it's not filled in (which 373 * means something goofed somewhere) we will try to look 374 * it up from the elf file itself. 375 */ 376 size_t strscn_ndx; 377 378 strscn_ndx = find_scn(elf, strtab, name, SHT_STRTAB, 379 shdr->sh_flags, &str_scn); 380 if (strscn_ndx == 0) { 381 (void) fprintf(stderr, MSG_INTL(MSG_STAB_MISTBL), 382 in_fname); 383 return ((Elf_Data *)S_ERROR); 384 } else if (strscn_ndx == (size_t)-1) { 385 (void) fprintf(stderr, MSG_INTL(MSG_STAB_BADTBL), 386 in_fname); 387 return ((Elf_Data *)S_ERROR); 388 } 389 } else { 390 if ((str_scn = elf_getscn(elf, shdr->sh_link)) == NULL) { 391 (void) fprintf(stderr, MSG_INTL(MSG_ELF_GETSCN), 392 in_fname, elf_errmsg(0)); 393 return ((Elf_Data *)S_ERROR); 394 } 395 } 396 397 if ((str_data = elf_getdata(str_scn, NULL)) == NULL) { 398 (void) fprintf(stderr, MSG_INTL(MSG_ELF_GETDATA), in_fname, 399 elf_errmsg(0)); 400 return ((Elf_Data *)S_ERROR); 401 } 402 403 return (str_data); 404 } 405 406 407 408 409 /* 410 * We examine all the stab's looking for pairs of N_OBJ's who's 411 * string pointers (elem->n_un.n_strx) points to a null string. 412 * When we find a pair we set the first string pointing to the 413 * CWD and we set the second string to the file object name (*name). 414 * 415 * The stab's string table will have to be expanded to hold 416 * these new enties. 417 */ 418 static void 419 process_stabindex(Elf *elf, const char *elf_strtab, const char *strtab_name, 420 Shdr *shdr, Elf_Data *s_data) 421 { 422 Elf_Data *str_data; 423 static char *cwd = NULL; 424 static size_t cwd_len; 425 size_t new_size; 426 size_t cwd_pos; 427 size_t name_len; 428 Elf_Void *data; 429 430 if ((str_data = get_str_data(elf, elf_strtab, strtab_name, 431 shdr)) == (Elf_Data *)S_ERROR) 432 return; 433 434 if (cwd == NULL) { 435 if ((cwd = getcwd(NULL, MAXPATHLEN)) == NULL) { 436 (void) fprintf(stderr, MSG_INTL(MSG_SYS_GETCWD), 437 in_fname, strerror(errno)); 438 return; 439 } 440 cwd_len = strlen(cwd); 441 } 442 name_len = strlen(in_fname); 443 444 new_size = pass1_stabindex(s_data, str_data, cwd_len, name_len); 445 446 if (new_size == 0) 447 /* no changes are needed */ 448 return; 449 /* 450 * The .stab.index data buffer must be updated so a new copy is 451 * allocated. The original is read-only. 452 */ 453 if ((data = malloc(s_data->d_size)) == 0) 454 return; 455 (void) memcpy(data, s_data->d_buf, s_data->d_size); 456 s_data->d_buf = data; 457 458 /* 459 * Allocate a new .stab.indexstr that is big enough to hold the new 460 * entries that we will need to place into it. 461 * 462 * Then append the 'cwd' onto the end of the current data. 463 */ 464 if ((data = malloc(str_data->d_size + new_size)) == 0) 465 return; 466 (void) memcpy(data, str_data->d_buf, str_data->d_size); 467 cwd_pos = str_data->d_size; 468 (void) strcpy((char *)data + cwd_pos, cwd); 469 str_data->d_buf = data; 470 str_data->d_size = str_data->d_size + new_size; 471 472 (void) pass2_stabindex(s_data, str_data, in_fname, name_len, cwd_pos, 473 cwd_pos + cwd_len + 1); 474 } 475 476 477 static void 478 process_stabsbfocus(Elf *elf, const char *elf_strtab, 479 const char *strtab_name, Shdr *shdr, Elf_Data *s_data, 480 const char *out_name, Half etype) 481 { 482 Elf_Data *str_data; 483 struct nlist *elem, *last = NULL; 484 size_t i, str_offset = 0, num_elem; 485 486 if ((str_data = get_str_data(elf, elf_strtab, strtab_name, 487 shdr)) == (Elf_Data *)S_ERROR) 488 return; 489 490 num_elem = s_data->d_size / sizeof (struct nlist); 491 for (i = 0; i < num_elem; i++) { 492 const char *type, *str; 493 494 elem = (struct nlist *)s_data->d_buf + i; 495 switch (elem->n_type) { 496 case 0: 497 if (last) 498 str_offset += last->n_value; 499 last = elem; 500 break; 501 case N_BROWS: 502 str = (char *)str_data->d_buf + elem->n_strx + 503 str_offset; 504 if (etype == ET_REL) 505 type = MSG_ORIG(MSG_STR_DASHR); 506 else 507 type = MSG_ORIG(MSG_STR_DASHX); 508 sbfocus_symbol(&sb_data, out_name, type, str); 509 break; 510 default: 511 /* no-op */ 512 break; 513 } 514 } 515 } 516 517 518 /* ARGSUSED2 */ 519 void 520 #if defined(_ELF64) 521 ld_start64(const char *out_name, const Half etype, const char *caller) 522 #else 523 ld_start(const char *out_name, const Half etype, const char *caller) 524 #endif 525 { 526 out_fname = out_name; 527 out_e_type = etype; 528 } 529 530 531 /* ARGSUSED1 */ 532 void 533 #if defined(_ELF64) 534 ld_file64(const char *name, const Elf_Kind kind, int flags, Elf *elf) 535 #else 536 ld_file(const char *name, const Elf_Kind kind, int flags, Elf *elf) 537 #endif 538 { 539 in_fname = name; 540 } 541 542 543 /* 544 * ld_section() 545 * 546 * Args: 547 * name - pointer to name of current section being processed. 548 * shdr - pointer to Section Header of current in-file being 549 * processed. 550 * s_data - pointer to Section Data structure of current in-file 551 * being processed. 552 * elf - pointer to elf structure for current in-file being 553 * processed 554 */ 555 /* ARGSUSED2 */ 556 void 557 #if defined(_ELF64) 558 ld_section64(const char *scn_name, Shdr *shdr, Word scnndx, 559 #else 560 ld_section(const char *scn_name, Shdr *shdr, Word scnndx, 561 #endif 562 Elf_Data *s_data, Elf *elf) 563 { 564 Ehdr *ehdr; 565 Elf_Data *str_data; 566 Elf_Scn *str_scn; 567 char *strtab; 568 569 ehdr = elf_getehdr(elf); 570 if ((ehdr->e_type != ET_DYN) && (shdr->sh_type == SHT_PROGBITS)) { 571 /* 572 * this is a minor optimization for speed. If it's not a 573 * stab string we aren't going to strcmp() it. 574 */ 575 if ((scn_name[1] == 's') && 576 (scn_name[2] == 't') && 577 (scn_name[3] == 'a') && 578 (scn_name[4] == 'b')) { 579 Word shstrndx; 580 581 /* 582 * If 'extended sections' are in use, then 583 * e_shstrndx == Shdr[0].sh_link 584 */ 585 if (ehdr->e_shstrndx == SHN_XINDEX) { 586 Elf_Scn *scn0; 587 Shdr *shdr0; 588 scn0 = elf_getscn(elf, 0); 589 shdr0 = elf_getshdr(scn0); 590 shstrndx = shdr0->sh_link; 591 } else 592 shstrndx = ehdr->e_shstrndx; 593 594 str_scn = elf_getscn(elf, shstrndx); 595 str_data = elf_getdata(str_scn, NULL); 596 strtab = str_data->d_buf; 597 598 if (strcmp(scn_name, MSG_ORIG(MSG_SCN_STAB)) == 0) { 599 /* 600 * Process .stab 601 */ 602 process_stabsbfocus(elf, strtab, 603 MSG_ORIG(MSG_SCN_STABSTR), shdr, 604 s_data, out_fname, out_e_type); 605 } else if (strcmp(scn_name, 606 MSG_ORIG(MSG_SCN_STABINDEX)) == 0) { 607 /* 608 * Process .stab.index 609 */ 610 process_stabindex(elf, strtab, 611 MSG_ORIG(MSG_SCN_STABINDEXSTR), shdr, 612 s_data); 613 } else if (strcmp(scn_name, 614 MSG_ORIG(MSG_SCN_STABSBFOCUS)) == 0) { 615 /* 616 * Process .stab.sbfocus 617 */ 618 process_stabsbfocus(elf, strtab, 619 MSG_ORIG(MSG_SCN_STABSBFOCUSTR), shdr, 620 s_data, out_fname, out_e_type); 621 } 622 } 623 } 624 } 625 626 /* 627 * Null atexit() routine, causes dlsym() to pass and thus no dlerror() message 628 * generation. 629 */ 630 /* ARGSUSED */ 631 void 632 #if defined(_ELF64) 633 ld_atexit64(int status) 634 #else 635 ld_atexit(int status) 636 #endif 637 { 638 } 639 640 #if !defined(_ELF64) 641 /* 642 * Messaging support - funnel everything through dgettext(). 643 */ 644 645 const char * 646 _libldstab_msg(Msg mid) 647 { 648 return (dgettext(MSG_ORIG(MSG_SUNW_OST_SGS), MSG_ORIG(mid))); 649 } 650 #endif 651