2 Copyright (C) 2011, 2012 Free Software Foundation, Inc.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
12 GCC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
21 /* This program is a wrapper around the VMS linker.
22 It translates Unix style command line options into corresponding
23 VMS style qualifiers and then spawns the VMS linker.
25 It is possible to build this program on UNIX but only for the purpose of
26 checking for errors. */
33 #include "libiberty.h"
34 #include <safe-ctype.h>
37 /* Macro for logicals. */
39 #define LNM_C_NAMLENGTH 255
43 /* Local variable declarations. */
44 static int ld_nocall_debug
= 0;
45 static int ld_mkthreads
= 0;
46 static int ld_upcalls
= 0;
48 /* verbose = 1 if -v passed. */
49 static int verbose
= 0;
51 /* save_temps = 1 if -save-temps passed. */
52 static int save_temps
= 0;
54 /* By default don't generate executable file if there are errors
55 in the link. Override with --noinhibit-exec. */
56 static int inhibit_exec
= 1;
58 /* debug = 1 if -g passed. */
61 /* By default prefer to link with static libraries. */
62 static int staticp
= 1;
64 /* By default generate an executable, not a shareable image library.
65 Override with -shared. */
68 /* Linker command line. */
69 static int link_cmd_maxlen
= 0;
70 static char *link_cmd
= 0;
71 static int link_cmd_len
= 0;
73 /* Keep track of filenames. */
74 static char *sharebasename
;
75 static const char *exefullfilename
;
76 static const char *exefilename
;
78 /* Search dir list passed on command line (with -L). */
79 static const char **search_dirs
;
80 static int search_dirs_len
;
82 /* Local function declarations. */
83 static void addarg (const char *);
84 static int is_regular_file (char *);
85 static char *to_host_file_spec (char *);
86 static char *locate_lib (char *);
87 static const char *expand_lib (char *);
88 static void preprocess_args (int, char **);
89 static void process_args (int, char **);
90 static void maybe_set_link_compat (void);
91 static int set_exe (const char *);
93 static int translate_unix (char *, int);
97 /* Append STR to the command line to invoke the linker.
98 Expand the line as necessary to accommodate. */
101 addarg (const char *str
)
103 int l
= strlen (str
);
105 /* Extend the line. */
106 if (link_cmd_len
+ l
>= link_cmd_maxlen
)
108 link_cmd_maxlen
= link_cmd_len
+ l
+ 1024;
109 link_cmd
= XRESIZEVEC (char, link_cmd
, link_cmd_maxlen
);
112 memcpy (link_cmd
+ link_cmd_len
, str
, l
);
116 /* Check to see if NAME is a regular file, i.e. not a directory. */
119 is_regular_file (char *name
)
124 ret
= stat (name
, &statbuf
);
125 return !ret
&& S_ISREG (statbuf
.st_mode
);
129 static char new_host_filespec
[255];
130 static char filename_buff
[256];
132 /* Action routine called by decc$to_vms. NAME is a file name or
133 directory name. TYPE is unused. */
136 translate_unix (char *name
, int type ATTRIBUTE_UNUSED
)
138 strcpy (filename_buff
, name
);
143 /* Translate a Unix syntax file specification FILESPEC into VMS syntax.
144 If indicators of VMS syntax found, return input string.
145 Return a pointer to a static buffer. */
148 to_host_file_spec (char *filespec
)
151 if (strchr (filespec
, ']') || strchr (filespec
, ':'))
153 /* Looks like a VMS path. */
159 strcpy (filename_buff
, filespec
);
160 decc$
to_vms (filespec
, translate_unix
, 1, 1);
161 strcpy (new_host_filespec
, filename_buff
);
162 return new_host_filespec
;
169 /* Locate library LIB_NAME on the library path. */
172 locate_lib (char *lib_name
)
174 int lib_len
= strlen (lib_name
);
180 /* For static links, look for shareable image libraries last. */
192 for (i
= 0; i
< search_dirs_len
; i
++)
198 l
= strlen (search_dirs
[i
]);
199 buf
= (char *)alloca (l
+ 4 + lib_len
+ 4 + 1);
200 /* Put PATH/libLIB. */
201 memcpy (buf
, search_dirs
[i
], l
);
202 memcpy (buf
+ l
, "/lib", 4);
204 memcpy (buf
+ l
, lib_name
, lib_len
);
207 /* Look for files with the extensions. */
208 for (j
= 0; j
< 3; j
++)
210 strcpy (buf
+ l
, exts
[j
]);
211 if (is_regular_file (buf
))
212 return xstrdup (to_host_file_spec (buf
));
219 /* Given a library name NAME, i.e. foo, Look for libfoo.lib and then
220 libfoo.a in the set of directories we are allowed to search in.
221 May return NULL if the library can be discarded. */
224 expand_lib (char *name
)
229 if (strcmp (name
, "c") == 0)
232 /* Discard libm. No separate library for math functions. */
233 if (strcmp (name
, "m") == 0)
236 /* Search on path. */
237 lib_path
= locate_lib (name
);
242 "Couldn't locate library: lib%s.exe, lib%s.a or lib%s.olb\n",
248 /* Preprocess the number of args P_ARGC in ARGV.
249 Look for special flags, etc. that must be handled first. */
252 preprocess_args (int argc
, char **argv
)
256 /* Scan for -shared. */
257 for (i
= 1; i
< argc
; i
++)
258 if (strcmp (argv
[i
], "-shared") == 0)
264 for (i
= 1; i
< argc
; i
++)
265 if (strcmp (argv
[i
], "-o") == 0)
270 exefilename
= lbasename (argv
[i
]);
271 exefullfilename
= xstrdup (to_host_file_spec (argv
[i
]));
277 addarg (exefullfilename
);
283 /* Extract the basename. */
284 ptr
= strchr (argv
[i
], ']');
286 ptr
= strchr (argv
[i
], ':');
288 ptr
= strchr (argv
[i
], '/');
290 sharebasename
= xstrdup (argv
[i
]);
292 sharebasename
= xstrdup (ptr
+ 1);
294 len
= strlen (sharebasename
);
295 if (strncasecmp (&sharebasename
[len
-4], ".exe", 4) == 0)
296 sharebasename
[len
- 4] = 0;
298 /* Convert to uppercase. */
299 for (ptr
= sharebasename
; *ptr
; ptr
++)
300 *ptr
= TOUPPER (*ptr
);
304 if (exefullfilename
== NULL
&& !share
)
306 exefilename
= "a_out.exe";
307 exefullfilename
= "a_out.exe";
308 addarg (xstrdup (" /exe=a_out.exe"));
312 /* Preprocess the number of args ARGC in ARGV. Look for
313 special flags, etc. that must be handled for the VMS linker. */
316 process_args (int argc
, char **argv
)
320 for (i
= 1; i
< argc
; i
++)
322 if (strncmp (argv
[i
], "-L", 2) == 0)
324 search_dirs
= XRESIZEVEC(const char *, search_dirs
,
325 search_dirs_len
+ 1);
326 search_dirs
[search_dirs_len
++] = &argv
[i
][2];
329 /* -v turns on verbose option here and is passed on to gcc. */
330 else if (strcmp (argv
[i
], "-v") == 0)
332 else if (strcmp (argv
[i
], "--version") == 0)
334 fprintf (stdout
, "VMS Linker\n");
337 else if (strcmp (argv
[i
], "--help") == 0)
339 fprintf (stdout
, "VMS Linker\n");
342 else if (strcmp (argv
[i
], "-g0") == 0)
343 addarg ("/notraceback");
344 else if (strncmp (argv
[i
], "-g", 2) == 0)
349 else if (strcmp (argv
[i
], "-static") == 0)
351 else if (strcmp (argv
[i
], "-map") == 0)
355 buff
= (char *) xstrdup (exefullfilename
);
356 ptr
= strrchr (buff
, '.');
360 strcat (buff
, ".map");
368 else if (strcmp (argv
[i
], "-save-temps") == 0)
370 else if (strcmp (argv
[i
], "--noinhibit-exec") == 0)
378 unsigned short len
, mbz
;
384 unsigned short buflen
, item_code
;
391 struct lst items
[1];
392 unsigned int terminator
;
397 struct lst items
[2];
398 unsigned int terminator
;
401 /* Checks if logical names are defined for setting system library path and
402 linker program to enable compatibility with earlier VMS versions. */
405 maybe_set_link_compat (void)
407 char lnm_buff
[LNM_C_NAMLENGTH
];
408 unsigned int lnm_buff_len
;
410 Descriptor tabledsc
, linkdsc
;
412 tabledsc
.adr
= "LNM$JOB";
413 tabledsc
.len
= strlen (tabledsc
.adr
);
416 linkdsc
.adr
= "GCC_LD_SYS$LIBRARY";
417 linkdsc
.len
= strlen (linkdsc
.adr
);
420 item_lst1
.items
[0].buflen
= LNM_C_NAMLENGTH
;
421 item_lst1
.items
[0].item_code
= LNM__STRING
;
422 item_lst1
.items
[0].bufaddr
= lnm_buff
;
423 item_lst1
.items
[0].retlenaddr
= &lnm_buff_len
;
424 item_lst1
.terminator
= 0;
428 &tabledsc
, /* tabnam */
429 &linkdsc
, /* lognam */
433 /* If GCC_LD_SYS$LIBRARY is defined, redefine SYS$LIBRARY to search
434 the equivalence name first for system libraries, then the default
435 system library directory */
437 if ((status
& 1) == 1)
439 unsigned char acmode
= PSL_C_USER
; /* Don't retain after image exit */
440 const char *syslib
= "SYS$SYSROOT:[SYSLIB]"; /* Default SYS$LIBRARY */
442 /* Only visible to current and child processes */
443 tabledsc
.adr
= "LNM$PROCESS";
444 tabledsc
.len
= strlen (tabledsc
.adr
);
447 linkdsc
.adr
= "SYS$LIBRARY";
448 linkdsc
.len
= strlen (linkdsc
.adr
);
451 item_lst2
.items
[0].buflen
= lnm_buff_len
;
452 item_lst2
.items
[0].item_code
= LNM__STRING
;
453 item_lst2
.items
[0].bufaddr
= lnm_buff
;
454 item_lst2
.items
[0].retlenaddr
= 0;
456 item_lst2
.items
[1].buflen
= strlen (syslib
);
457 item_lst2
.items
[1].item_code
= LNM__STRING
;
458 item_lst2
.items
[1].bufaddr
= syslib
;
459 item_lst2
.items
[1].retlenaddr
= 0;
460 item_lst2
.terminator
= 0;
464 &tabledsc
, /* tabnam */
465 &linkdsc
, /* lognam */
466 &acmode
, /* acmode */
471 tabledsc
.adr
= "LNM$JOB";
472 tabledsc
.len
= strlen (tabledsc
.adr
);
475 linkdsc
.adr
= "GCC_LD_LINK";
476 linkdsc
.len
= strlen (linkdsc
.adr
);
479 item_lst1
.items
[0].buflen
= LNM_C_NAMLENGTH
;
480 item_lst1
.items
[0].item_code
= LNM__STRING
;
481 item_lst1
.items
[0].bufaddr
= lnm_buff
;
482 item_lst1
.items
[0].retlenaddr
= &lnm_buff_len
;
483 item_lst1
.terminator
= 0;
487 &tabledsc
, /* tabnam */
488 &linkdsc
, /* lognam */
492 /* If GCC_LD_LINK is defined, redefine LINK to use the equivalence name
493 (sometimes the LINK program version is used by VMS to determine
496 if ((status
& 1) == 1)
498 unsigned char acmode
= PSL_C_USER
; /* Don't retain after image exit. */
500 /* Only visible to current and child processes. */
501 tabledsc
.adr
= "LNM$PROCESS";
502 tabledsc
.len
= strlen (tabledsc
.adr
);
505 linkdsc
.adr
= "LINK";
506 linkdsc
.len
= strlen (linkdsc
.adr
);
509 item_lst1
.items
[0].buflen
= lnm_buff_len
;
510 item_lst1
.items
[0].item_code
= LNM__STRING
;
511 item_lst1
.items
[0].bufaddr
= lnm_buff
;
512 item_lst1
.items
[0].retlenaddr
= 0;
513 item_lst1
.terminator
= 0;
517 &tabledsc
, /* tabnam */
518 &linkdsc
, /* lognam */
519 &acmode
, /* acmode */
525 maybe_set_link_compat (void)
530 /* Set environment defined executable attributes. */
533 set_exe (const char *arg
)
538 snprintf (allargs
, sizeof (allargs
),
539 "$@gnu:[bin]set_exe %s %s", exefullfilename
, arg
);
541 printf ("%s\n", allargs
);
543 res
= system (allargs
);
545 printf ("$!status = %d\n", res
);
549 fprintf (stderr
, "ld error: popen set_exe\n");
555 /* The main program. Spawn the VMS linker after fixing up the Unix-like flags
556 and args to be what the VMS linker wants. */
559 main (int argc
, char **argv
)
561 /* File specification for vms-dwarf2.o. */
562 char *vmsdwarf2spec
= 0;
564 /* File specification for vms-dwarf2eh.o. */
565 char *vmsdwarf2ehspec
= 0;
568 char cwdev
[128], *devptr
;
575 /* Some linker options can be set with logicals. */
576 if (getenv ("GNAT$LD_NOCALL_DEBUG"))
578 if (getenv ("GNAT$LD_MKTHREADS"))
580 if (getenv ("GNAT$LD_UPCALLS"))
582 if (getenv ("GNAT$LD_SHARED_LIBS"))
585 /* Get current dir. */
587 cwd
= getcwd (0, 1024, 1);
589 cwd
= getcwd (0, 1024);
593 /* Extract device part of the path. */
594 devptr
= strchr (cwd
, ':');
596 cwdevlen
= (devptr
- cwd
) + 1;
599 memcpy (cwdev
, cwd
, cwdevlen
);
600 cwdev
[cwdevlen
] = '\0';
602 maybe_set_link_compat ();
604 /* Linker command starts with the command name. */
607 /* Pass to find args that have to be append first. */
608 preprocess_args (argc
, argv
);
610 /* Pass to find the rest of the args. */
611 process_args (argc
, argv
);
614 addarg ("/noinform");
616 /* Create a temp file to hold args, otherwise we can easily exceed the VMS
617 command line length limits. */
618 optfilename
= (char *) xmalloc (strlen (exefilename
) + 13);
619 strcpy (optfilename
, exefilename
);
620 ptr
= strrchr (optfilename
, '.');
623 strcat (optfilename
, ".opt_tmpfile");
624 optfile
= fopen (optfilename
, "w");
626 /* Write out the IDENTIFICATION argument first so that it can be overridden
627 by an options file. */
628 for (i
= 1; i
< argc
; i
++)
630 int arg_len
= strlen (argv
[i
]);
632 if (arg_len
> 6 && strncasecmp (argv
[i
], "IDENT=", 6) == 0)
634 /* Comes from command line. If present will always appear before
635 --identification=... and will override. */
638 else if (arg_len
> 17
639 && strncasecmp (argv
[i
], "--identification=", 17) == 0)
641 /* Comes from pragma Ident (). */
642 fprintf (optfile
, "case_sensitive=yes\n");
643 fprintf (optfile
, "IDENTIFICATION=\"%-.15s\"\n", &argv
[i
][17]);
644 fprintf (optfile
, "case_sensitive=NO\n");
648 for (i
= 1; i
< argc
; i
++)
650 int arg_len
= strlen (argv
[i
]);
652 if (strcmp (argv
[i
], "-o") == 0)
654 /* Already handled. */
657 else if (arg_len
> 2 && strncmp (argv
[i
], "-l", 2) == 0)
661 libname
= expand_lib (&argv
[i
][2]);
664 int len
= strlen (libname
);
667 if (len
> 4 && strcasecmp (&libname
[len
-4], ".exe") == 0)
672 if (libname
[0] == '[')
673 fprintf (optfile
, "%s%s%s\n", cwdev
, libname
, ext
);
675 fprintf (optfile
, "%s%s\n", libname
, ext
);
678 else if (strcmp (argv
[i
], "-v" ) == 0
679 || strncmp (argv
[i
], "-g", 2 ) == 0
680 || strcmp (argv
[i
], "-static" ) == 0
681 || strcmp (argv
[i
], "-map" ) == 0
682 || strcmp (argv
[i
], "-save-temps") == 0
683 || strcmp (argv
[i
], "--noinhibit-exec") == 0
684 || (arg_len
> 2 && strncmp (argv
[i
], "-L", 2) == 0)
685 || (arg_len
>= 6 && strncmp (argv
[i
], "-share", 6) == 0))
687 /* Already handled. */
689 else if (strncmp (argv
[i
], "--opt=", 6) == 0)
690 fprintf (optfile
, "%s\n", argv
[i
] + 6);
691 else if (arg_len
> 1 && argv
[i
][0] == '@')
693 /* Read response file (in fact a single line of filenames). */
700 if (stat (&argv
[i
][1], &statbuf
))
702 fprintf (stderr
, "Couldn't open linker response file: %s\n",
708 buff
= (char *) xmalloc (statbuf
.st_size
+ 1);
709 atfile
= fopen (&argv
[i
][1], "r");
710 fgets (buff
, statbuf
.st_size
+ 1, atfile
);
713 /* Remove trailing \n. */
715 if (buff
[len
- 1] == '\n')
721 /* Put the filenames to the opt file. */
725 ptr1
= strchr (ptr
, ' ');
729 /* Add device name if a path is present. */
730 ptr
= to_host_file_spec (ptr
);
732 fprintf (optfile
, "%s%s\n", cwdev
, ptr
);
734 fprintf (optfile
, "%s\n", ptr
);
740 else if ((argv
[i
][0] == '/') && (strchr (&argv
[i
][1], '/') == 0))
742 /* Unix style file specs and VMS style switches look alike,
743 so assume an arg consisting of one and only one slash,
744 and that being first, is really a switch. */
748 && strncasecmp (&argv
[i
][arg_len
-4], ".opt", 4) == 0)
750 /* Read option file. */
754 /* Disable __UNIX_FOPEN redefinition in case user supplied .opt
755 file is not stream oriented. */
757 optfile1
= (fopen
) (argv
[i
], "r");
762 goto cleanup_and_exit
;
765 while (fgets (buff
, sizeof (buff
), optfile1
))
766 fputs (buff
, optfile
);
770 else if (arg_len
> 7 && strncasecmp (argv
[i
], "GSMATCH", 7) == 0)
771 fprintf (optfile
, "%s\n", argv
[i
]);
772 else if (arg_len
> 6 && strncasecmp (argv
[i
], "IDENT=", 6) == 0)
774 /* Comes from command line and will override pragma. */
775 fprintf (optfile
, "case_sensitive=yes\n");
776 fprintf (optfile
, "IDENT=\"%15.15s\"\n", &argv
[i
][6]);
777 fprintf (optfile
, "case_sensitive=NO\n");
779 else if (arg_len
> 17
780 && strncasecmp (argv
[i
], "--identification=", 17) == 0)
782 /* Already handled. */
786 /* Assume filename arg. */
788 const char *addswitch
= NULL
;
793 file
= to_host_file_spec (argv
[i
]);
794 arg_len
= strlen (file
);
796 /* Handle shareable image libraries. */
797 if (arg_len
> 4 && strcasecmp (&file
[arg_len
- 4], ".exe") == 0)
798 addswitch
= "/shareable";
799 else if (arg_len
> 4 && strcasecmp (&file
[arg_len
- 4], ".cld") == 0)
801 addswitch
= "/shareable";
805 /* Handle object libraries. */
806 else if (arg_len
> 2 && strcasecmp (&file
[arg_len
- 2], ".a") == 0)
808 else if (arg_len
> 4 && strcasecmp (&file
[arg_len
- 4], ".olb") == 0)
811 /* Absolutize file location. */
814 buff
= (char *) xmalloc (cwdevlen
+ arg_len
+ 1);
815 sprintf (buff
, "%s%s", cwdev
, file
);
817 else if (strchr (file
, ':'))
819 buff
= xstrdup (file
);
823 buff
= (char *) xmalloc (strlen (cwd
) + arg_len
+ 1);
824 sprintf (buff
, "%s%s", cwd
, file
);
827 buff_len
= strlen (buff
);
830 && strcasecmp (&buff
[buff_len
- 14], "vms-dwarf2eh.o") == 0)
833 vmsdwarf2ehspec
= xstrdup (buff
);
835 else if (buff_len
>= 13
836 && strcasecmp (&buff
[buff_len
- 12], "vms-dwarf2.o") == 0)
839 vmsdwarf2spec
= xstrdup (buff
);
843 /* Command line definition file. */
850 fprintf (optfile
, "%s%s\n",
851 buff
, addswitch
!= NULL
? addswitch
: "");
859 /* Sequentialize exception handling info. */
861 fprintf (optfile
, "case_sensitive=yes\n");
862 fprintf (optfile
, "cluster=DWARF2eh,,,%s\n", vmsdwarf2ehspec
);
863 fprintf (optfile
, "collect=DWARF2eh,eh_frame\n");
864 fprintf (optfile
, "case_sensitive=NO\n");
867 if (debug
&& vmsdwarf2spec
)
869 /* Sequentialize the debug info. */
871 fprintf (optfile
, "case_sensitive=yes\n");
872 fprintf (optfile
, "cluster=DWARF2debug,,,%s\n", vmsdwarf2spec
);
873 fprintf (optfile
, "collect=DWARF2debug,debug_abbrev,debug_aranges,-\n");
874 fprintf (optfile
, " debug_frame,debug_info,debug_line,debug_loc,-\n");
875 fprintf (optfile
, " debug_macinfo,debug_pubnames,debug_str,-\n");
876 fprintf (optfile
, " debug_zzzzzz\n");
877 fprintf (optfile
, "case_sensitive=NO\n");
880 if (debug
&& share
&& vmsdwarf2spec
)
882 /* Sequentialize the shared library debug info. */
884 fprintf (optfile
, "case_sensitive=yes\n");
885 fprintf (optfile
, "symbol_vector=(-\n");
887 "%s$DWARF2.DEBUG_ABBREV/$dwarf2.debug_abbrev=DATA,-\n",
890 "%s$DWARF2.DEBUG_ARANGES/$dwarf2.debug_aranges=DATA,-\n",
892 fprintf (optfile
, "%s$DWARF2.DEBUG_FRAME/$dwarf2.debug_frame=DATA,-\n",
894 fprintf (optfile
, "%s$DWARF2.DEBUG_INFO/$dwarf2.debug_info=DATA,-\n",
896 fprintf (optfile
, "%s$DWARF2.DEBUG_LINE/$dwarf2.debug_line=DATA,-\n",
898 fprintf (optfile
, "%s$DWARF2.DEBUG_LOC/$dwarf2.debug_loc=DATA,-\n",
901 "%s$DWARF2.DEBUG_MACINFO/$dwarf2.debug_macinfo=DATA,-\n",
904 "%s$DWARF2.DEBUG_PUBNAMES/$dwarf2.debug_pubnames=DATA,-\n",
906 fprintf (optfile
, "%s$DWARF2.DEBUG_STR/$dwarf2.debug_str=DATA,-\n",
908 fprintf (optfile
, "%s$DWARF2.DEBUG_ZZZZZZ/$dwarf2.debug_zzzzzz=DATA)\n",
910 fprintf (optfile
, "case_sensitive=NO\n");
913 fprintf (optfile
, "PSECT_ATTR=LIB$INITIALIZE,GBL\n");
916 /* Append opt file. */
918 addarg (optfilename
);
922 printf ("%s\n", link_cmd
);
924 status
= system (link_cmd
);
926 printf ("$!status = %d\n", status
);
928 if ((status
& 1) != 1)
931 goto cleanup_and_exit
;
934 if (debug
&& !share
&& ld_nocall_debug
)
936 status
= set_exe ("/flags=nocall_debug");
938 goto cleanup_and_exit
;
941 if (!share
&& ld_mkthreads
)
943 status
= set_exe ("/flags=mkthreads");
945 goto cleanup_and_exit
;
948 if (!share
&& ld_upcalls
)
950 status
= set_exe ("/flags=upcalls");
952 goto cleanup_and_exit
;
959 remove (optfilename
);
964 if (exefullfilename
&& inhibit_exec
== 1)
965 remove (exefullfilename
);