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