00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #if defined(__GNUC__)
00036 #include <stdio.h>
00037 #endif
00038 #include <stdlib.h>
00039 #include <unistd.h>
00040 #include <libgen.h>
00041 #include <sys/stat.h>
00042 #include <sys/mman.h>
00043 #include <fcntl.h>
00044 #include <sys/dir.h>
00045 #include <sys/wait.h>
00046 #include <alloca.h>
00047 #include <signal.h>
00048 #include <limits.h>
00049 #include <errno.h>
00050 #include <string.h>
00051 #include <dlfcn.h>
00052
00053 #include "aout/ar.h"
00054
00055 #include "bfd.h"
00056 #include "libbfd.h"
00057 #include "elf-bfd.h"
00058
00059 #include "ipa_ld.h"
00060
00061 #define DEFAULT_TOOLROOT "/usr/bin/sgicc"
00062
00063 extern bfd_boolean is_ipa;
00064
00065 extern struct bfd_link_info link_info;
00066 extern char **environ_vars;
00067
00068 #if !defined(EF_IRIX_ABI64)
00069 #define EF_IRIX_ABI64 0x00000010
00070 #endif
00071
00072 extern void process_whirl64(void *, off_t, void *, int, const char *) __attribute__((weak));
00073 extern void process_whirl32(void *, off_t, void *, int, const char *) __attribute__((weak));
00074 extern void *ipa_open_input(char *, off_t *) __attribute__((weak));
00075
00076 void *(*p_ipa_open_input)(char *, off_t *) = NULL;
00077 void (*p_ipa_init_link_line)(int, char **) = NULL;
00078 void (*p_ipa_add_link_flag)(const char*) = NULL;
00079 void (*p_ipa_modify_link_flag)(char*, char*) = NULL;
00080 void (*p_ipa_driver)(int, char **) = NULL;
00081 #ifdef OSP_OPT
00082 void (*p_process_whirl64)(void *, off_t, void *, int, const char *, off_t, bfd_boolean) = NULL;
00083 void (*p_process_whirl32)(void *, off_t, void *, int, const char *, off_t, bfd_boolean) = NULL;
00084 #else
00085 void (*p_process_whirl64)(void *, off_t, void *, int, const char *, off_t) = NULL;
00086 void (*p_process_whirl32)(void *, off_t, void *, int, const char *, off_t) = NULL;
00087 #endif
00088 int (*p_Count_elf_external_gots)(void) = NULL;
00089 void (*p_ipa_insert_whirl_marker)(void) = NULL;
00090 void (*p_Sync_symbol_attributes)(unsigned int, unsigned int, bfd_boolean, unsigned int) = NULL;
00091 #ifdef KEY
00092 void (*p_ipa_erase_link_flag)(const char*) = NULL;
00093 void (*p_Ipalink_Set_Error_Phase)(char *) = NULL;
00094 void (*p_Ipalink_ErrMsg_EC_infile)(char *) = NULL;
00095 void (*p_Ipalink_ErrMsg_EC_outfile)(char *) = NULL;
00096 #endif
00097
00098 string toolroot = 0;
00099
00100 static int active_pid;
00101
00102 static mode_t cmask = 0;
00103
00104 static string thisfile = __FILE__;
00105
00106 static char *default_path = "/usr/ia64-sgi-linux/lib/gcc-lib/ia64-sgi-linux/sgicc-1.0";
00107 static char *env_name = "LD_LIBRARY_PATH";
00108
00109 static string *tmp_list = 0;
00110 static int tmp_list_size = 0;
00111 static int tmp_list_max = 0;
00112 string tmpdir = 0;
00113 static int tmpdir_length = 0;
00114 static bfd *p_current_bfd = NULL;
00115
00116 string outfilename = "./a.out";
00117 string WB_flags = NULL;
00118 string Y_flags = NULL;
00119
00120 LD_IPA_OPTION ld_ipa_opt[] = {
00121
00122
00123
00124 {LD_IPA_SHARABLE, F_CALL_SHARED, F_CALL_SHARED},
00125 {LD_IPA_DEMANGLE, 0, 0},
00126 {LD_IPA_SHOW, 0, 0},
00127 {LD_IPA_HIDES, 0, 0},
00128 {LD_IPA_TARGOS, TOS_IA64_64, 0},
00129 {LD_IPA_ISA, 0, 0},
00130 {LD_IPA_XXXX, 0, 0},
00131 {LD_IPA_XXXX, 0, 0}
00132 };
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143 char * always_demangle(char *name, char Demangle){return NULL;}
00144 char *__Release_ID;
00145 void read_one_section(int index, void *p_void){return;}
00146
00147 void merge_ext(void *p_sym, char *name, int num, void *p_obj)
00148 {return;}
00149
00150 void msg (int type, int msg_id, ...) {return;}
00151
00152
00153
00154
00155
00156
00157
00158
00159 char *
00160 ipa_copy_of (char *str)
00161 {
00162 register int len;
00163 register char *p;
00164
00165 len = strlen(str) + 1;
00166 p = (char *) MALLOC (len);
00167 MALLOC_ASSERT (p);
00168 BCOPY (str, p, len);
00169 return p;
00170 }
00171
00172
00173
00174
00175
00176
00177
00178
00179 string
00180 concat_names(const string name1, const string name2)
00181 {
00182 char *mangled_name = NULL;
00183 int len = strlen(name1)+strlen(name2)+1;
00184
00185 mangled_name = (char *)MALLOC(len);
00186 MALLOC_ASSERT(mangled_name);
00187
00188 strcpy(mangled_name, name1);
00189 strcat(mangled_name, name2);
00190
00191 return(mangled_name);
00192 }
00193
00194
00195
00196
00197
00198
00199
00200
00201 static void
00202 dump_argv (string *argv)
00203 {
00204 fputs (argv[0], stderr);
00205 argv++;
00206 while (*argv)
00207 fprintf (stderr, " %s", *argv++);
00208 fputc ('\n', stderr);
00209
00210 }
00211
00212
00213
00214
00215
00216
00217
00218 int
00219 do_compile (string *argv)
00220 {
00221 int pid;
00222
00223 if (toolroot) {
00224 if ((toolroot = getenv ("TOOLROOT")) == 0)
00225 toolroot = ipa_copy_of(DEFAULT_TOOLROOT);
00226 else
00227 toolroot = concat_names (toolroot, DEFAULT_TOOLROOT);
00228 }
00229
00230 argv[0] = concat_names (toolroot, basename (argv[0]));
00231
00232 if (ld_ipa_opt[LD_IPA_VERBOSE].flag || ld_ipa_opt[LD_IPA_SHOW].flag)
00233 dump_argv (argv);
00234
00235 pid = fork();
00236 pid = execve(argv[0], argv, environ_vars);
00237
00238 if (pid < 0) {
00239 perror(argv[0]);
00240 exit(1);
00241 }
00242
00243 active_pid = pid;
00244
00245 FREE (argv[0]);
00246 argv[0] = NULL;
00247
00248 if (toolroot) {
00249 FREE (toolroot);
00250 toolroot = NULL;
00251 }
00252
00253 return pid;
00254
00255 }
00256
00257
00258
00259
00260
00261
00262
00263 static void
00264 ld_kill_compilation (int sig)
00265 {
00266 if (active_pid != 0) {
00267 kill (active_pid, sig);
00268 active_pid = 0;
00269 }
00270
00271 }
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282 void
00283 add_to_tmp_file_list (string path)
00284 {
00285 if (tmp_list_max == 0) {
00286 tmp_list_max = DEFAULT_TMP_LIST_SIZE;
00287 tmp_list = (string *) MALLOC (tmp_list_max * sizeof(string));
00288 MALLOC_ASSERT (tmp_list);
00289 } else if (tmp_list_size >= tmp_list_max) {
00290 tmp_list_max *= 2;
00291 tmp_list = (string *)REALLOC (tmp_list, tmp_list_max * sizeof(string));
00292 MALLOC_ASSERT (tmp_list);
00293 }
00294
00295 tmp_list[tmp_list_size++] = path;
00296
00297 }
00298
00299
00300
00301
00302
00303
00304
00305 static void
00306 remove_from_tmp_file_list (string path)
00307 {
00308
00309 if (tmp_list_size == 0)
00310 return;
00311
00312
00313 if (tmp_list[tmp_list_size - 1] == path)
00314 tmp_list_size--;
00315
00316 }
00317
00318
00319
00320
00321
00322
00323
00324
00325 void
00326 cleanup_all_files (void)
00327 {
00328 int i;
00329
00330 if (ld_ipa_opt[LD_IPA_KEEP_TEMPS].flag)
00331 return;
00332
00333 for (i = tmp_list_size - 1; i > 0; i--)
00334 UNLINK (tmp_list[i]);
00335
00336 if (tmp_list_size >= 1)
00337 RMDIR (tmp_list[0]);
00338
00339 }
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349 string
00350 make_temp_file (string name, char suffix)
00351 {
00352 char path[PATH_MAX];
00353 int len;
00354 int count = 1;
00355
00356 len = strlen (name);
00357 if (len+4 >= PATH_MAX) {
00358 fprintf(stderr,"%s %s\n","path name too long:", name);
00359 exit(1);
00360 }
00361
00362 strcpy (path, name);
00363
00364 if (suffix && len >= 2) {
00365
00366 if (path[len-2] == '.') {
00367 len -= 2;
00368 path[len] = 0;
00369 }
00370 }
00371
00372 if (suffix) {
00373 path[len] = '.';
00374 path[len+1] = suffix;
00375 path[len+2] = 0;
00376 }
00377
00378 if (access (path, F_OK) != 0)
00379 return ipa_copy_of (path);
00380
00381 do {
00382 if (suffix)
00383 sprintf (&(path[len]), ".%d.%c", count, suffix);
00384 else
00385 sprintf (&(path[len]), "%d", count);
00386 count++;
00387 } while (access (path, F_OK) == 0);
00388
00389 return ipa_copy_of (path);
00390
00391 }
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413 int
00414 create_tmpdir ( int tracing )
00415 {
00416 int fixedname = is_ipa && ( ld_ipa_opt[LD_IPA_KEEP_TEMPS].flag );
00417
00418 if ( is_ipa ) {
00419 if ( fixedname ) {
00420 tmpdir = concat_names ( outfilename, ".ipakeep" );
00421 } else {
00422 char *tmpdir_env_var;
00423 if ((tmpdir_env_var = getenv("TMPDIR")) != NULL) {
00424 char *filename;
00425 tmpdir_env_var = concat_names ( tmpdir_env_var, "/");
00426 if ((filename = strrchr(outfilename, '/')) != NULL)
00427 filename++;
00428 else
00429 filename = outfilename;
00430
00431 tmpdir = concat_names ( tmpdir_env_var, filename);
00432 }
00433 else
00434 tmpdir = outfilename;
00435 tmpdir = concat_names ( tmpdir, ".ipaXXXXXX" );
00436 }
00437 } else {
00438 tmpdir = concat_names ( DEFAULT_TMPDIR, "XXXXXX" );
00439 }
00440 if ( ! fixedname ) {
00441 tmpdir = mktemp ( tmpdir );
00442 }
00443 tmpdir_length = strlen ( tmpdir );
00444
00445 if ( cmask == 0 ) {
00446 cmask = umask (0);
00447 (void) umask (cmask);
00448 }
00449
00450 if ( MKDIR (tmpdir, 0777 & ~cmask) != 0 ) {
00451 if ( errno == EEXIST && fixedname ) {
00452
00453 DIR *dirp;
00454 struct direct *entryp;
00455 char *prefix;
00456
00457 dirp = opendir ( tmpdir );
00458 if ( dirp != NULL ) {
00459 prefix = concat_names ( tmpdir, "/" );
00460 while ( ( entryp = readdir(dirp) ) != NULL ) {
00461
00462
00463
00464
00465 #if defined(_DIRENT_HAVE_D_NAMLEN)
00466 if ( entryp->d_namlen > 2 )
00467 #else
00468 if (_D_EXACT_NAMLEN(entryp) > 2)
00469 #endif
00470 {
00471 string fname = concat_names ( prefix, entryp->d_name);
00472 unlink (fname);
00473 FREE (fname);
00474 }
00475 }
00476 FREE (prefix);
00477 closedir ( dirp );
00478 }
00479 } else {
00480 perror("cannot create temporary directory for code generation");
00481 return -1;
00482 }
00483 }
00484
00485 add_to_tmp_file_list ( tmpdir );
00486
00487 return 0;
00488
00489 }
00490
00491
00492
00493
00494
00495
00496
00497 string
00498 create_unique_file (const string path, char suffix)
00499 {
00500 string p;
00501 string base = basename (path);
00502 string new_path;
00503 int fd;
00504
00505
00506
00507 p = (string) MALLOC (strlen(tmpdir) + strlen(base) + 2);
00508 MALLOC_ASSERT (p);
00509 strcpy (p, tmpdir);
00510 strcat (p, "/");
00511 strcat (p, base);
00512 new_path = make_temp_file (p, suffix);
00513 FREE (p);
00514
00515 if ((fd = creat (new_path, 0666 & ~cmask)) == -1) {
00516 perror(new_path);
00517 exit(1);
00518 }
00519
00520 CLOSE (fd);
00521
00522 return new_path;
00523
00524 }
00525
00526
00527
00528
00529
00530
00531
00532
00533 string *
00534 get_command_line(bfd *abfd,
00535 string in_path,
00536 string out_path,
00537 int *arg_count)
00538 {
00539 static string default_compilation_flags[] = DEFAULT_COMPILATION_FLAGS;
00540 int i;
00541 int argc = 0;
00542 string *old_argv;
00543 string *new_argv;
00544 Elf_Internal_Ehdr *ehdr = elf_elfheader (abfd);
00545 asection *p_asec;
00546
00547 for (i = 1; i < ehdr->e_shnum; i++) {
00548 Elf_Internal_Shdr *p_shdr = elf_elfsections (abfd)[i];
00549
00550 if (p_shdr->sh_info == WT_COMP_FLAGS) {
00551 char *base_addr;
00552 int j;
00553 ELF_WORD *args;
00554
00555 if (p_shdr->sh_size <= 1)
00556 continue;
00557
00558 base_addr = (char *) p_shdr->contents;
00559 argc = (int)(*((ELF_WORD *) base_addr));
00560
00561 args = (ELF_WORD *) (base_addr + sizeof(ELF_WORD));
00562 old_argv = (string *) ALLOCA (sizeof(string) * argc);
00563 MALLOC_ASSERT (old_argv);
00564
00565 for (j = 0; j < argc; j++) {
00566 OBJ_ASSERT (args[j] < p_shdr->sh_size, abfd,
00567 "invalid WT_COMP_FLAGS WHIRL section");
00568 old_argv[j] = base_addr + args[j];
00569 }
00570
00571 break;
00572 }
00573 }
00574
00575 if (argc == 0) {
00576 argc = DEFAULT_COMPILATION_ARGC;
00577 old_argv = default_compilation_flags;
00578 }
00579
00580 new_argv = (string *) MALLOC ((argc + 6) * sizeof(string));
00581 MALLOC_ASSERT (new_argv);
00582
00583 for (i = 0; i < argc; i++)
00584 new_argv[i] = old_argv[i];
00585
00586 new_argv[argc++] = "-64";
00587
00588 new_argv[argc++] = in_path;
00589 new_argv[argc++] = "-o";
00590 new_argv[argc++] = out_path;
00591 new_argv[argc++] = "-c";
00592 new_argv[argc] = 0;
00593
00594 *arg_count = argc;
00595
00596 return new_argv;
00597
00598 }
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608 static int
00609 extract_archive_member (bfd *abfd, string path)
00610 {
00611 int fd = -1;
00612 int mode = 0666;
00613 pointer addr = (pointer)-1;
00614 struct areltdata *p_areltdata = (struct areltdata *)abfd->arelt_data;
00615 struct ar_hdr *p_hdr = arch_hdr(abfd);
00616
00617 if ((fd = OPEN (path, O_RDWR|O_CREAT|O_TRUNC, mode)) != -1)
00618 addr = (pointer) MMAP ( 0,
00619 p_hdr->ar_size,
00620 PROT_READ|PROT_WRITE,
00621 MAP_SHARED,
00622 fd,
00623 0);
00624
00625 if (fd == -1 || addr == (pointer)-1 || FCHMOD (fd, mode) != 0 ) {
00626 perror("cannot create intermediate file");
00627 return -1;
00628 }
00629
00630 CLOSE (fd);
00631
00632 MEMCPY (addr, bfd_tell(abfd), p_hdr->ar_size);
00633
00634 MUNMAP (addr, p_hdr->ar_size);
00635
00636 return 0;
00637
00638 }
00639
00640
00641
00642
00643
00644
00645
00646 int
00647 make_link (const string dest, const string src)
00648 {
00649 static string working_dir = 0;
00650 int link_result;
00651
00652 #if 0
00653 LD_ASSERT (dest && src, thisfile,
00654 "NULL path name passed to symbolic_link()");
00655 #endif
00656
00657
00658
00659 if (link (dest, src) == 0)
00660 return 0;
00661
00662
00663
00664 if (dest[0] == '/')
00665 link_result = symlink (dest, src);
00666 else {
00667 string new_dest;
00668
00669 if (working_dir == 0) {
00670 string tmp;
00671 working_dir = getcwd ((char *) NULL, PATH_MAX);
00672 if (working_dir == NULL) {
00673 perror("getcwd(3)");
00674 exit(1);
00675 }
00676 tmp = working_dir;
00677 working_dir = concat_names (working_dir, "/");
00678 FREE (tmp);
00679 }
00680
00681 new_dest = concat_names (working_dir, dest);
00682 link_result = symlink (new_dest, src);
00683 FREE (new_dest);
00684 }
00685
00686 return link_result;
00687
00688 }
00689
00690
00691
00692
00693
00694
00695
00696 string
00697 ld_compile (bfd *abfd)
00698 {
00699 string input_path;
00700 string output_path;
00701 int argc;
00702 string *argv;
00703 int child_pid;
00704 int statptr;
00705 string file_name = (string)abfd->filename;
00706
00707 if (tmpdir == 0)
00708 if (create_tmpdir (FALSE) != 0) {
00709 fprintf(stderr,"create_tmpdir() failed for %s\n",abfd->filename);
00710 exit(1);
00711 }
00712
00713 if ((input_path = create_unique_file (file_name, 'B')) == 0) {
00714 fprintf(stderr,"create_unique_file() failed for %s\n",abfd->filename);
00715 exit(1);
00716 }
00717
00718 if (abfd->arelt_data) {
00719 if (extract_archive_member (abfd, input_path) != 0) {
00720 fprintf(stderr,"extract_archive_member() failed for %s\n",abfd->filename);
00721 exit(1);
00722 }
00723 } else {
00724 UNLINK (input_path);
00725 if (make_link (file_name, input_path) != 0) {
00726 fprintf(stderr,"make_link() failed for %s\n",abfd->filename);
00727 exit(1);
00728 }
00729 }
00730
00731 if ((output_path = create_unique_file (file_name, 'o')) == 0)
00732 if (create_tmpdir (FALSE) != 0) {
00733 fprintf(stderr,"create_unique_file() failed for %s\n",abfd->filename);
00734 exit(1);
00735 }
00736
00737 add_to_tmp_file_list (output_path);
00738 add_to_tmp_file_list (input_path);
00739
00740
00741 argv = get_command_line (abfd, input_path, output_path, &argc);
00742
00743
00744 if (ld_ipa_opt[LD_IPA_VERBOSE].flag || ld_ipa_opt[LD_IPA_SHOW].flag)
00745 fprintf(stderr,"Compiling %s\n",abfd->filename);
00746
00747 child_pid = do_compile (argv);
00748
00749 (void) waitpid (child_pid, &statptr, 0);
00750 if (statptr != 0 && WEXITSTATUS(statptr) != 0)
00751 {
00752 fprintf(stderr,"Compile of %s failed!\n",abfd->filename);
00753 exit(1);
00754 }
00755
00756 active_pid = 0;
00757
00758 FREE (argv);
00759
00760 UNLINK (input_path);
00761 remove_from_tmp_file_list (input_path);
00762 FREE (input_path);
00763
00764 return output_path;
00765
00766 }
00767
00768
00769
00770
00771
00772
00773 void *
00774 ld_slookup_mext(char *name, bfd_boolean is_extern)
00775 {
00776 bfd *abfd = p_current_bfd;
00777 struct elf_link_hash_entry *p_hash = NULL;
00778
00779 if (!is_extern)
00780 p_hash = elf_link_hash_lookup ( elf_hash_table (&link_info),
00781 name,
00782 bfd_false,
00783 bfd_false,
00784 bfd_false);
00785 else
00786 p_hash = ((struct elf_link_hash_entry *)
00787 bfd_wrapped_link_hash_lookup( abfd,
00788 &link_info,
00789 name,
00790 bfd_false,
00791 bfd_false,
00792 bfd_false));
00793
00794 return p_hash;
00795
00796
00797 }
00798
00799
00800
00801
00802
00803
00804
00805 void
00806 ld_set_st_idx (void *pext, int st_idx)
00807 {
00808 struct elf_link_hash_entry *p_hash = (struct elf_link_hash_entry *)pext;
00809
00810 p_hash->ipa_indx = st_idx;
00811 }
00812
00813
00814
00815
00816
00817
00818
00819 int
00820 ld_get_st_idx (void *pext)
00821 {
00822 struct elf_link_hash_entry *p_hash = (struct elf_link_hash_entry *)pext;
00823
00824 return p_hash->ipa_indx;
00825 }
00826
00827
00828
00829
00830
00831
00832
00833
00834 int
00835 ipa_set_ndx (bfd *abfd)
00836 {
00837 if (ipa_is_whirl(abfd))
00838 return WHIRL_ST_IDX_UNINITIALIZED;
00839 else
00840 return WHIRL_ST_IDX_NOT_AVAILABLE;
00841 }
00842
00843
00844
00845
00846
00847
00848 void
00849 ipa_set_def_bfd(bfd *abfd, struct bfd_link_hash_entry *p_bfd_hash)
00850 {
00851 if (is_ipa)
00852 p_bfd_hash->u.def.section = (asection *)abfd;
00853 }
00854
00855
00856
00857
00858
00859
00860 bfd_boolean
00861 ld_resolved_to_obj (void *pext, void *pobj)
00862 {
00863 struct elf_link_hash_entry *p_hash;
00864 bfd *abfd = NULL;
00865
00866 if (pext)
00867 p_hash = (struct elf_link_hash_entry *)pext;
00868 else
00869 p_hash = NULL;
00870
00871 switch(p_hash->root.type) {
00872
00873 case bfd_link_hash_common:
00874 abfd = p_hash->root.u.c.p->section->owner;
00875 break;
00876
00877 case bfd_link_hash_undefined:
00878 case bfd_link_hash_undefweak:
00879 abfd = p_hash->root.u.undef.abfd;
00880 break;
00881
00882 case bfd_link_hash_defined:
00883 case bfd_link_hash_defweak:
00884 abfd = (bfd *)p_hash->root.u.def.section;
00885 break;
00886
00887 case bfd_link_hash_new:
00888 case bfd_link_hash_indirect:
00889 case bfd_link_hash_warning:
00890 default:
00891 break;
00892
00893 }
00894
00895 return (abfd == (struct _bfd *)pobj);
00896 }
00897
00898
00899
00900
00901
00902
00903
00904
00905 char *
00906 ld_get_section_base (void *pobj, int sect_ndx)
00907 {
00908 const bfd *abfd = (bfd *) pobj;
00909 Elf_Internal_Shdr **i_shdrp = elf_elfsections (abfd);
00910 Elf_Internal_Shdr *p_shdr = i_shdrp[sect_ndx];
00911
00912 return (char *)abfd->usrdata+p_shdr->sh_offset;
00913 }
00914
00915
00916
00917
00918
00919
00920 unsigned long long
00921 ld_get_section_size(void *pobj, int sect_ndx)
00922 {
00923 const bfd *abfd = (bfd *) pobj;
00924 Elf_Internal_Shdr **i_shdrp = elf_elfsections (abfd);
00925
00926 return ((unsigned long long)i_shdrp[sect_ndx]->sh_size);
00927 }
00928
00929
00930
00931
00932
00933
00934 char *
00935 ld_get_section_name(void *pobj, int sect_ndx)
00936 {
00937 bfd *abfd = (bfd *) pobj;
00938 Elf_Internal_Shdr **i_shdrp = elf_elfsections (abfd);
00939 Elf_Internal_Shdr *p_shdr = i_shdrp[sect_ndx];
00940 char *tbl = bfd_elf_get_str_section(abfd,
00941 elf_elfheader (abfd)->e_shstrndx);
00942
00943 return &tbl[p_shdr->sh_name];
00944 }
00945
00946
00947
00948
00949
00950
00951 void *
00952 ld_get_mmap_addr(void *pobj)
00953 {
00954 const bfd *abfd = (bfd *) pobj;
00955
00956 return (void *)abfd->usrdata;
00957
00958 }
00959
00960
00961
00962
00963
00964
00965 void
00966 ld_set_section_data(void *pobj,int ndx)
00967 {
00968 bfd *abfd = (bfd *) pobj;
00969 Elf_Internal_Shdr **i_shdrp = elf_elfsections (abfd);
00970 Elf_Internal_Shdr *p_shdr = i_shdrp[ndx];
00971 size_t size = p_shdr->sh_size;
00972 char *buf;
00973
00974 if (!size)
00975 return;
00976
00977 buf = ((char *) bfd_malloc (size));
00978 if (buf == NULL) {
00979 fprintf(stderr,"bfd_malloc failed in ld_set_section_data for %s\n",abfd->filename);
00980 exit(1);
00981 }
00982
00983 if (!p_shdr->contents) {
00984 if (bfd_seek ( abfd, p_shdr->sh_offset, SEEK_SET) != 0) {
00985 fprintf(stderr,"bfd_seek failed in ld_set_section_data for %s\n",abfd->filename);
00986 exit(1);
00987 }
00988 if (bfd_read ( (PTR) buf, 1, size, abfd) != size) {
00989 fprintf(stderr,"Bfd_read failed in ld_set_section_data for %s\n",abfd->filename);
00990 exit(1);
00991 }
00992 }
00993
00994 return;
00995
00996 }
00997
00998
00999
01000
01001
01002
01003 void
01004 ld_release_section_data(void *pobj,int ndx)
01005 {
01006 const bfd *abfd = (bfd *) pobj;
01007 Elf_Internal_Shdr **i_shdrp = elf_elfsections (abfd);
01008 Elf_Internal_Shdr *p_shdr = i_shdrp[ndx];
01009
01010 if (p_shdr->contents) {
01011 free(p_shdr->contents);
01012 p_shdr->contents = NULL;
01013 }
01014 }
01015
01016
01017
01018
01019
01020
01021 int
01022 Count_elf_external_gots (void)
01023 {
01024 return(20);
01025 }
01026
01027
01028
01029
01030
01031
01032 void
01033 ld_set_cur_obj(bfd *abfd)
01034 {
01035 p_current_bfd = (bfd *)abfd;
01036 }
01037
01038
01039
01040
01041
01042
01043
01044 void *
01045 ld_get_cur_obj(void)
01046 {
01047 return p_current_bfd;
01048 }
01049
01050
01051
01052
01053
01054
01055 #define ET_SGI_IR (ET_LOPROC + 0)
01056
01057 bfd_boolean
01058 ipa_is_whirl(bfd *abfd)
01059 {
01060 Elf_Internal_Ehdr *i_ehdrp;
01061
01062 i_ehdrp = elf_elfheader (abfd);
01063
01064 if (i_ehdrp->e_type == ET_SGI_IR) {
01065 return(TRUE);
01066 }
01067
01068 return(FALSE);
01069 }
01070
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087 void
01088 ipa_process_whirl ( bfd *abfd)
01089 {
01090
01091 off_t mapped_size;
01092 abfd->usrdata = (PTR)(*p_ipa_open_input)((char *)abfd->filename, &mapped_size);
01093
01094 #if !defined(__ALWAYS_USE_64BIT_ELF__)
01095
01096
01097 if( ( elf_elfheader (abfd)->e_flags & EF_IRIX_ABI64 ) == 0 )
01098 (*p_process_whirl32) (
01099 (void *)abfd,
01100 elf_elfheader (abfd)->e_shnum,
01101 abfd->usrdata+elf_elfheader(abfd)->e_shoff,
01102 0,
01103 #ifdef OSP_OPT
01104 abfd->filename, mapped_size, FALSE);
01105 #else
01106 abfd->filename, mapped_size);
01107 #endif
01108 else
01109 #endif
01110 (*p_process_whirl64) (
01111 (void *)abfd,
01112 elf_elfheader (abfd)->e_shnum,
01113 abfd->usrdata+elf_elfheader(abfd)->e_shoff,
01114 0,
01115 #ifdef OSP_OPT
01116 abfd->filename, mapped_size, FALSE);
01117 #else
01118 abfd->filename, mapped_size);
01119 #endif
01120 }
01121
01122 #ifdef OSP_OPT
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132 char *ipa_mmap_file_in_archive ( bfd *bfd, int fd, off_t mapped_size) {
01133 off_t offset = bfd->origin % getpagesize();
01134 char *buf = (char *)mmap(0, mapped_size + offset, PROT_READ|PROT_WRITE,
01135 MAP_PRIVATE, fd, bfd->origin - offset);
01136
01137 if (buf == (char *)(-1)) {
01138 return NULL;
01139 }
01140
01141 return buf + offset;
01142 }
01143
01144 #endif
01145
01146
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156 void ipa_process_whirl_in_archive ( bfd *abfd, bfd *element)
01157 {
01158 char *buf;
01159 struct ar_hdr *p_hdr;
01160 off_t mapped_size;
01161 ld_set_cur_obj(element);
01162 p_hdr = arch_hdr(element);
01163 mapped_size = strtol (p_hdr->ar_size, NULL, 10);
01164
01165 #ifdef OSP_OPT
01166 int fd = open(abfd->filename, O_RDONLY);
01167 if ((buf = ipa_mmap_file_in_archive(element, fd, mapped_size)) == NULL) {
01168 einfo(("%F%B: ipa_mmap_file_in_archive failed for member %B\n"), abfd, element);
01169 }
01170 #else
01171 if ((buf = bfd_alloc(element, mapped_size)) == NULL) {
01172 einfo(("%F%B: bfd_alloc failed for member %B\n"), abfd, element);
01173 }
01174 if (bfd_seek(element, 0, SEEK_SET) != 0) {
01175 einfo(("%F%B: bfd_seek failed for member %B\n"), abfd, element);
01176 }
01177 if (bfd_bread(buf, mapped_size, element) != mapped_size) {
01178 einfo(("%F%B: bfd_read failed for member %B\n"), abfd, element);
01179 }
01180 #endif
01181 element->usrdata = buf;
01182
01183 #if !defined(__ALWAYS_USE_64BIT_ELF__)
01184
01185
01186 if( ( elf_elfheader (element)->e_flags & EF_IRIX_ABI64 ) == 0 )
01187 (*p_process_whirl32) (
01188 (void *)element,
01189 elf_elfheader (element)->e_shnum,
01190 element->usrdata+elf_elfheader(element)->e_shoff,
01191 0,
01192 #ifdef OSP_OPT
01193 abfd->filename, mapped_size, TRUE);
01194 #else
01195 abfd->filename, mapped_size);
01196 #endif
01197 else
01198 #endif
01199 (*p_process_whirl64) (
01200 (void *)element,
01201 elf_elfheader (element)->e_shnum,
01202 element->usrdata+elf_elfheader(element)->e_shoff,
01203 0,
01204 #ifdef OSP_OPT
01205 element->filename, mapped_size, TRUE);
01206 #else
01207 element->filename, mapped_size);
01208 #endif
01209 }
01210
01211
01212
01213
01214
01215
01216
01217
01218 void
01219 ipa_set_syms(void)
01220 {
01221
01222 void *p_handle = NULL;
01223 char *p_error = NULL;
01224
01225 p_handle = dlopen("ipa.so",RTLD_LAZY);
01226 if (!p_handle) {
01227 fputs (dlerror(), stderr);
01228 exit(1);
01229 }
01230
01231 p_ipa_open_input = dlsym(p_handle,"ipa_open_input");
01232 if ((p_error = dlerror()) != NULL) {
01233 fputs(p_error, stderr);
01234 exit(1);
01235 }
01236
01237 p_ipa_init_link_line = dlsym(p_handle,"ipa_init_link_line");
01238 if ((p_error = dlerror()) != NULL) {
01239 fputs(p_error, stderr);
01240 exit(1);
01241 }
01242
01243 p_ipa_add_link_flag = dlsym(p_handle,"ipa_add_link_flag");
01244 if ((p_error = dlerror()) != NULL) {
01245 fputs(p_error, stderr);
01246 exit(1);
01247 }
01248
01249 p_ipa_modify_link_flag = dlsym(p_handle,"ipa_modify_link_flag");
01250 if ((p_error = dlerror()) != NULL) {
01251 fputs(p_error, stderr);
01252 exit(1);
01253 }
01254 p_ipa_driver = dlsym(p_handle,"ipa_driver");
01255 if ((p_error = dlerror()) != NULL) {
01256 fputs(p_error, stderr);
01257 exit(1);
01258 }
01259
01260 p_process_whirl64 = dlsym(p_handle,"process_whirl64");
01261 if ((p_error = dlerror()) != NULL) {
01262 fputs(p_error, stderr);
01263 exit(1);
01264 }
01265
01266 p_process_whirl32 = dlsym(p_handle,"process_whirl32");
01267 if ((p_error = dlerror()) != NULL) {
01268 fputs(p_error, stderr);
01269 exit(1);
01270 }
01271
01272 p_ipa_insert_whirl_marker = dlsym(p_handle,"ipa_insert_whirl_marker");
01273 if ((p_error = dlerror()) != NULL) {
01274 fputs(p_error, stderr);
01275 exit(1);
01276 }
01277
01278 p_Sync_symbol_attributes = dlsym(p_handle,"Sync_symbol_attributes");
01279 if ((p_error = dlerror()) != NULL) {
01280 fputs(p_error, stderr);
01281 exit(1);
01282 }
01283
01284 #ifdef KEY
01285 p_ipa_erase_link_flag = dlsym(p_handle,"ipa_erase_link_flag");
01286 if ((p_error = dlerror()) != NULL) {
01287 fputs(p_error, stderr);
01288 exit(1);
01289 }
01290
01291 p_Ipalink_Set_Error_Phase = dlsym(p_handle,"Ipalink_Set_Error_Phase");
01292 if ((p_error = dlerror()) != NULL) {
01293 fputs(p_error, stderr);
01294 exit(1);
01295 }
01296
01297 p_Ipalink_ErrMsg_EC_infile = dlsym(p_handle,"Ipalink_ErrMsg_EC_infile");
01298 if ((p_error = dlerror()) != NULL) {
01299 fputs(p_error, stderr);
01300 exit(1);
01301 }
01302
01303 p_Ipalink_ErrMsg_EC_outfile = dlsym(p_handle,"Ipalink_ErrMsg_EC_outfile");
01304 if ((p_error = dlerror()) != NULL) {
01305 fputs(p_error, stderr);
01306 exit(1);
01307 }
01308 #endif
01309 }
01310
01311
01312
01313
01314
01315
01316
01317 static bfd_boolean
01318 ipa_symbol_sync(struct bfd_link_hash_entry *p_bfd_link_hash, PTR info)
01319 {
01320 const char *name;
01321 bfd_boolean is_undef = FALSE;
01322 struct elf_link_hash_entry *p_elf_link_hash ;
01323 unsigned int result = 0;
01324 bfd_boolean is_weak = FALSE;
01325
01326 name = p_bfd_link_hash->root.string;
01327
01328 if (!name)
01329 return(TRUE);
01330
01331
01332 switch (p_bfd_link_hash->type) {
01333 case bfd_link_hash_undefined:
01334 is_undef = TRUE;
01335 break;
01336 case bfd_link_hash_undefweak:
01337 is_undef = TRUE;
01338 is_weak = TRUE;
01339 break;
01340 case bfd_link_hash_defined:
01341 is_undef = FALSE;
01342 break;
01343 case bfd_link_hash_defweak:
01344 is_undef = FALSE;
01345 is_weak = TRUE;
01346 break;
01347 case bfd_link_hash_common:
01348 is_undef = FALSE;
01349 result |= OBJ_COMMON;
01350 break;
01351 default:
01352 return(TRUE);
01353 break;
01354 }
01355
01356 p_elf_link_hash = (struct elf_link_hash_entry *)ld_slookup_mext(name,is_undef);
01357
01358 if (p_elf_link_hash->def_regular) {
01359 result |= DEF_IN_OBJ;
01360 }
01361 if (p_elf_link_hash->ref_regular) {
01362 result |= USED_IN_OBJ;
01363 }
01364 if (p_elf_link_hash->ref_dynamic) {
01365 result |= USED_IN_DSO;
01366 }
01367 if (p_elf_link_hash->def_dynamic) {
01368 result |= DEF_IN_DSO;
01369 }
01370 if (p_elf_link_hash->hidden) {
01371 }
01372
01373 #if 0 // binutils 2.16.1's elf_link_hash_entry has no bitfield corresponding
01374
01375
01376 if (p_elf_link_hash->elf_link_hash_flags & ELF_LINK_HASH_ADDRESS_TAKEN) {
01377 result |= ADDR_TAKEN_IN_OBJ;
01378 }
01379 #endif
01380
01381 if (p_elf_link_hash->ipa_indx != WHIRL_ST_IDX_UNINITIALIZED &&
01382 p_elf_link_hash->ipa_indx != WHIRL_ST_IDX_NOT_AVAILABLE) {
01383
01384 (*p_Sync_symbol_attributes) (p_elf_link_hash->ipa_indx,
01385 result,
01386 is_weak,
01387 p_elf_link_hash->other);
01388
01389 }
01390
01391 return(TRUE);
01392 }
01393
01394 static void
01395 hash_dummy(struct bfd_link_hash_entry *p_bfd_link_hash, PTR info)
01396 {
01397
01398 if (p_bfd_link_hash->root.string) {
01399 printf("*** %s\n",p_bfd_link_hash->root.string);
01400 }
01401 }
01402
01403
01404
01405
01406
01407
01408
01409
01410
01411 void
01412 cleanup_symtab_for_ipa (void)
01413 {
01414
01415
01416
01417 bfd_link_hash_traverse (link_info.hash, ipa_symbol_sync, (PTR) NULL);
01418
01419 #if 0
01420
01421
01422 if (threadlocalsyms)
01423 mark_all_xlocal_not_gp_rel ();
01424
01425
01426 #endif
01427
01428 }
01429
01430
01431
01432
01433
01434
01435
01436
01437
01438
01439
01440
01441
01442
01443