Subversion Repositories QNX 8.QNX8 linker driver

Rev

Rev 10 | Rev 12 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
8 pmbaty 1
// QNX 8.0 'gcc' linker driver drop-in replacement by Pierre-Marie Baty <pm@pmbaty.com>
2
 
3
// RATIONALE
4
// until a proper QNXToolchain class is implemented in the Clang driver, Clang relies on GNU GCC to drive the system linker 'ld'.
5
// So we *HAVE* to provide a 'gcc' executable for Clang to be able to link QNX files.
6
// GNU GCC is itself a driver which can also invoke a compiler or a linker (gcc invokes collect2 which in turn invokes ld).
7
// This means our GCC will need to either chain-call 'clang' when it is called for *compiling* and chain-call 'ld' when it is called for *linking*.
8
// When proper support is added to it, GNU GCC contains a linker specification for the system which it uses to construct the linker command line.
9
// The linker specifications for QNX 8.0 can be extracted from '<target triple>-gcc -dumpspecs' and have been reimplemented in this file.
10
// The GNU specs language is documented here: https://gcc.gnu.org/onlinedocs/gcc/Spec-Files.html
11
 
12
// environment variables:
13
//   DEBUG_LINKER_DRIVER - when defined to any value (incl. empty string), print the constructed command line to stderr before calling the linker.
14
 
15
#include <stdio.h>
16
#include <stdlib.h>
11 pmbaty 17
#include <stdint.h>
8 pmbaty 18
#include <stdarg.h>
19
#include <stdbool.h>
20
#include <string.h>
21
#include <fcntl.h>
22
#ifndef _WIN32
23
#include <unistd.h>
24
#else // _WIN32
25
#include <process.h>
26
#include <io.h>
27
#define strdup(s) _strdup ((s))
28
#define strcasecmp(a,b) _stricmp ((a), (b))
29
#define access(f,m) _access ((f), (m))
30
#define execvpe(exename,argv,envp) exit ((int) _spawnvpe (P_WAIT, (exename), (argv), (envp)))
31
int vasprintf (char **out_string, const char *fmt, va_list va_args) // vasprintf() implementation
32
{
33
   int retval; va_list ap;
34
   *out_string = (char *) malloc (16); if (*out_string == NULL) return (-1);
35
   va_copy (ap, va_args); retval = vsnprintf (*out_string, 16, fmt, ap); va_end (ap); if (retval == -1) return (-1);
36
   if (retval >= 16)
37
   {
38
      void *new_string = realloc (*out_string, (size_t) retval + 1); if (new_string == NULL) return (-1); *out_string = (char *) new_string;
39
      va_copy (ap, va_args); retval = vsnprintf (*out_string, (size_t) retval + 1, fmt, va_args); va_end (ap);
40
   }
41
   return (retval);
42
}
43
int asprintf (char **out_string, const char *fmt, ...) { int retval; va_list ap; va_start (ap, fmt); retval = vasprintf (out_string, fmt, ap); va_end (ap); return (retval); } // asprintf() implementation
44
#endif // !_WIN32
45
 
46
 
47
#define BASEVER "12.2.0"
48
#if (defined(__x86_64__) || defined(_WIN64))
49
#define IS_TARGET_INTEL 1
50
#define TARGET_TRIPLE "x86_64-pc-nto-qnx8.0.0"
51
#elif defined(__aarch64__)
52
#define IS_TARGET_INTEL 0
53
#define TARGET_TRIPLE "aarch64-unknown-nto-qnx8.0.0"
54
#else
55
#error unsupported platform (not x86_64, not aarch64le). Please implement!
56
#endif
57
#define COMPILER "clang"
58
#define LINKER TARGET_TRIPLE "-ld"
59
//#define LINKER "ld.lld"
60
 
61
 
62
#define ARGMODE_SINGLE   0
63
#define ARGMODE_HASVAL   1
64
#define ARGMODE_EQUALVAL 2
65
 
66
 
11 pmbaty 67
// handy macros that generate a version number in the format "YYYYMMDD" corresponding to the build date. Usage: printf ("version " VERSION_FMT_YYYYMMDD "\n", VERSION_ARG_YYYYMMDD);
68
#ifndef VERSION_ARG_YYYYMMDD
69
#define BUILDDATE_YEAR  (&__DATE__[7]) // compiler will optimize this into a const string, e.g. "2021"
70
#define BUILDDATE_MONTH ( \
71
   *((uint32_t *) __DATE__) == *((uint32_t *) "Jan ") ? "01" : \
72
   *((uint32_t *) __DATE__) == *((uint32_t *) "Feb ") ? "02" : \
73
   *((uint32_t *) __DATE__) == *((uint32_t *) "Mar ") ? "03" : \
74
   *((uint32_t *) __DATE__) == *((uint32_t *) "Apr ") ? "04" : \
75
   *((uint32_t *) __DATE__) == *((uint32_t *) "May ") ? "05" : \
76
   *((uint32_t *) __DATE__) == *((uint32_t *) "Jun ") ? "06" : \
77
   *((uint32_t *) __DATE__) == *((uint32_t *) "Jul ") ? "07" : \
78
   *((uint32_t *) __DATE__) == *((uint32_t *) "Aug ") ? "08" : \
79
   *((uint32_t *) __DATE__) == *((uint32_t *) "Sep ") ? "09" : \
80
   *((uint32_t *) __DATE__) == *((uint32_t *) "Oct ") ? "10" : \
81
   *((uint32_t *) __DATE__) == *((uint32_t *) "Nov ") ? "11" : \
82
   *((uint32_t *) __DATE__) == *((uint32_t *) "Dec ") ? "12" : \
83
   "XX" \
84
) // compiler will optimize this into a const string, e.g. "11"
85
#define BUILDDATE_DAY ( \
86
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) "  1 ") ? "01" : \
87
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) "  2 ") ? "02" : \
88
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) "  3 ") ? "03" : \
89
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) "  4 ") ? "04" : \
90
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) "  5 ") ? "05" : \
91
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) "  6 ") ? "06" : \
92
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) "  7 ") ? "07" : \
93
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) "  8 ") ? "08" : \
94
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) "  9 ") ? "09" : \
95
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 10 ") ? "10" : \
96
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 11 ") ? "11" : \
97
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 12 ") ? "12" : \
98
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 13 ") ? "13" : \
99
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 14 ") ? "14" : \
100
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 15 ") ? "15" : \
101
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 16 ") ? "16" : \
102
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 17 ") ? "17" : \
103
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 18 ") ? "18" : \
104
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 19 ") ? "19" : \
105
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 20 ") ? "20" : \
106
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 21 ") ? "21" : \
107
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 22 ") ? "22" : \
108
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 23 ") ? "23" : \
109
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 24 ") ? "24" : \
110
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 25 ") ? "25" : \
111
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 26 ") ? "26" : \
112
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 27 ") ? "27" : \
113
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 28 ") ? "28" : \
114
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 29 ") ? "29" : \
115
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 30 ") ? "30" : \
116
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 31 ") ? "31" : \
117
   "XX" \
118
) // compiler will optimize this into a const string, e.g. "14"
119
#define VERSION_FMT_YYYYMMDD "%s%s%s"
120
#define VERSION_ARG_YYYYMMDD BUILDDATE_YEAR, BUILDDATE_MONTH, BUILDDATE_DAY
121
#endif // !VERSION_ARG_YYYYMMDD
122
 
123
 
8 pmbaty 124
char *array_contains (int argc, char **argv, char *needle, int mode)
125
{
126
   char *arg;
127
   int arg_index;
128
   size_t needle_len = strlen (needle);
129
   for (arg_index = 1; arg_index < argc; arg_index++)
130
   {
131
      arg = argv[arg_index];
132
      if (mode == ARGMODE_SINGLE)
133
      {
134
         if (strcmp (arg, needle) == 0)
135
            return ("");
136
      }
137
      else if (mode == ARGMODE_HASVAL)
138
      {
139
         if ((arg_index + 1 < argc) && (strcmp (arg, needle) == 0))
140
            return (argv[arg_index + 1]);
141
         else if ((strncmp (arg, needle, needle_len) == 0) && (arg[needle_len] != 0))
142
            return (&arg[needle_len]);
143
      }
144
      else if (mode == ARGMODE_EQUALVAL)
145
      {
146
         if ((strncmp (arg, needle, needle_len) == 0) && (arg[needle_len] == '='))
147
            return (&arg[needle_len + 1]);
148
      }
149
   }
150
   return (NULL);
151
}
152
 
153
 
154
char *resolve_envvars (char *str)
155
{
156
   char *out_str = strdup (str), *new_str;
157
   char *varstart, *varstop, *varval;
158
   while ((varstart = strstr (out_str, "${")) != NULL)
159
   {
160
      *varstart = 0;
161
      varstart += 2;
162
      varstop = strchr (varstart, '}');
163
      *varstop = 0;
164
      varval = getenv (varstart);
165
      asprintf (&new_str, "%s%s%s", out_str, (varval != NULL ? varval : ""), varstop + 1);
166
      free (out_str);
167
      out_str = new_str;
168
   }
169
   return (out_str);
170
}
171
 
172
 
173
char *makefmtstr (const char *fmt, ...)
174
{
175
   va_list ap;
176
   char *outstr = NULL;
177
   va_start (ap, fmt);
178
   vasprintf (&outstr, fmt, ap);
179
   va_end (ap);
180
   return (outstr);
181
}
182
 
183
 
184
int main (int argc, char **argv, char **envp)
185
{
186
   #define ADD_CHAR_ARRAY(array_var,arraysize_var,val) do { \
187
      void *reallocated_ptr = realloc (array_var, (arraysize_var + 2) * sizeof (char *)); \
188
      if (reallocated_ptr == NULL) exit (1); \
189
      array_var = reallocated_ptr; \
190
      array_var[arraysize_var] = (val); \
191
      array_var[arraysize_var + 1] = NULL; \
192
      arraysize_var++; \
193
   } while (0)
194
   #define ADD_LINKER_ARG(val) ADD_CHAR_ARRAY (linker_argv, linker_argc, (val))
195
   #define ADD_L_ARG(val) ADD_CHAR_ARRAY (largs, larg_count, (val))
196
   #define ADD_O_ARG(val) ADD_CHAR_ARRAY (oargs, oarg_count, (val))
197
   #define ADD_S_ARG(val) ADD_CHAR_ARRAY (sargs, sarg_count, (val))
198
   #define ARGV_CONTAINS_SINGLEARG(val)       ((arg = array_contains (argc, argv, (val), ARGMODE_SINGLE))   != NULL)
199
   #define ARGV_CONTAINS_ARGWITHVAL(val)      ((arg = array_contains (argc, argv, (val), ARGMODE_HASVAL))   != NULL)
200
   #define ARGV_CONTAINS_ARGWITHEQUALVAL(val) ((arg = array_contains (argc, argv, (val), ARGMODE_EQUALVAL)) != NULL)
201
   #define ARGV_SINGLEARG(val)       array_contains (argc, argv, (val), ARGMODE_SINGLE)
202
   #define ARGV_ARGWITHVAL(val)      array_contains (argc, argv, (val), ARGMODE_HASVAL)
203
   #define ARGV_ARGWITHEQUALVAL(val) array_contains (argc, argv, (val), ARGMODE_EQUALVAL)
204
 
205
   static char filebuf[1024 * 1024];
206
   char **linker_argv = NULL;
207
   size_t linker_argc = 0;
208
   char **largs = NULL; // array of "-lxxx" arguments
209
   size_t larg_count = 0;
210
   char **sargs = NULL; // array of source files arguments
211
   size_t sarg_count = 0;
212
   char **oargs = NULL; // array of object files arguments
213
   size_t oarg_count = 0;
214
   size_t read_count;
215
   size_t byte_index;
216
   bool was_cpluspluslib_included = false;
217
   bool requires_libcplusplus = false;
218
   int arg_index;
219
   char *arg;
220
   FILE *fp;
221
 
11 pmbaty 222
   // special case: print the driver version and exit
223
   if ((argc == 2) && (strcmp (argv[1], "--driver-version") == 0))
224
   {
225
      printf ("clang 'gcc' linker driver for QNX 8.0 version " VERSION_FMT_YYYYMMDD " by Pierre-Marie Baty <pm@pmbaty.com>\n", VERSION_ARG_YYYYMMDD);
226
      return (0);
227
   }
228
 
8 pmbaty 229
   // if *any* of these flags are present, it means we don't want to link anything, so direct everything to the compiler
230
   if (   ARGV_CONTAINS_SINGLEARG ("-fsyntax-only")
231
       || ARGV_CONTAINS_SINGLEARG ("-c")
232
       || ARGV_CONTAINS_SINGLEARG ("-M")
233
       || ARGV_CONTAINS_SINGLEARG ("-MM")
234
       || ARGV_CONTAINS_SINGLEARG ("-E")
235
       || ARGV_CONTAINS_SINGLEARG ("-S"))
236
   {
237
      if (ARGV_CONTAINS_SINGLEARG ("-c"))
238
         for (arg_index = 1; arg_index < argc; arg_index++)
239
            if (strcmp (argv[arg_index], "-shared") == 0)
240
               argv[arg_index] = ""; // HACK for GNU autotools: when compiling, wipe out the -shared flag to avoid a warning
241
      execvpe (COMPILER, argv, envp); // by leaving argv[0] untouched, we will be invoking Clang as 'gcc', which will give it a supplemental hint about how to behave
242
   }
243
 
244
   // collect source and object files in two separate lists
245
   for (arg_index = 1; arg_index < argc; arg_index++)
246
      if ((strcmp (argv[arg_index - 1], "-o") != 0) // this arg is NOT preceded by "-o"...
247
          && (access (argv[arg_index], 0) == 0) // ... this arg is an existing file...
248
          && ((arg = strrchr (argv[arg_index], '.')) != NULL)) // this filename has an extension (FIXME: what if "-x <language>" is specified?)
249
      {
250
         if (   (strcasecmp (arg, ".s") == 0)
251
             || (strcasecmp (arg, ".c") == 0)
252
             || (strcasecmp (arg, ".cc") == 0)
253
             || (strcasecmp (arg, ".c++") == 0)
254
             || (strcasecmp (arg, ".cpp") == 0)
255
             || (strcasecmp (arg, ".cxx") == 0)
256
             || (strcasecmp (arg, ".m") == 0)
257
             || (strcasecmp (arg, ".mm") == 0)
258
             || (strcasecmp (arg, ".mxx") == 0))
259
            ADD_S_ARG (argv[arg_index]); // this file is one of the known source file extensions: add to source files list
260
         else
261
            ADD_O_ARG (argv[arg_index]); // this file is NOT one of the known file extensions: add to object files list
262
      }
263
 
264
   // if we have zero .o file, OR if we have some source files, we have to compile first
265
   if ((sarg_count > 0) || (oarg_count == 0))
266
   {
267
      if (ARGV_CONTAINS_SINGLEARG ("-c"))
268
         for (arg_index = 1; arg_index < argc; arg_index++)
269
            if (strcmp (argv[arg_index], "-shared") == 0)
270
               argv[arg_index] = ""; // HACK for GNU autotools: when compiling, wipe out the -shared flag to avoid a warning
271
      execvpe (COMPILER, argv, envp); // by leaving argv[0] untouched, we will be invoking Clang as 'gcc', which will give it a supplemental hint about how to behave
272
   }
273
 
274
   // collect -l flags
275
   for (arg_index = 1; arg_index < argc; arg_index++)
276
      if ((strncmp (argv[arg_index], "-l", 2) == 0) && ((argv[arg_index])[2] != 0))
277
         ADD_L_ARG (argv[arg_index]);
278
 
279
   //   LINKER " "
280
   ADD_LINKER_ARG (LINKER);
281
 
282
   //   "%{!fno-use-linker-plugin:"
283
   //           "%{!fno-lto:     "
284
   //                   "-plugin ${QNX_HOST}/usr/lib/gcc/" TARGET_TRIPLE "/" BASEVER "/liblto_plugin.so     "
285
   //                   "-plugin-opt=${QNX_HOST}/usr/lib/gcc/" TARGET_TRIPLE "/" BASEVER "/lto-wrapper     "
286
   //                   "-plugin-opt=-fresolution=%u.res         "
287
   //                   "%{flinker-output=*:"   "-plugin-opt=-linker-output-known"      "}     "
288
   //                   "%{!nostdlib:"
289
   //                           "%{!nodefaultlibs:"     "%:pass-through-libs(%(link_gcc_c_sequence))"   "}"
290
   //                   "}     "
291
   //           "}"
292
   //   "}"
293
   if (!ARGV_CONTAINS_SINGLEARG ("-fno-use-linker-plugin") && !ARGV_CONTAINS_SINGLEARG ("-fno-lto"))
294
   {
295
      /*ADD_LINKER_ARG ("-plugin");
296
      ADD_LINKER_ARG (resolve_envvars ("${QNX_HOST}/usr/lib/gcc/" TARGET_TRIPLE "/" BASEVER "/liblto_plugin.so"));
297
      ADD_LINKER_ARG (resolve_envvars ("-plugin-opt=${QNX_HOST}/usr/lib/gcc/" TARGET_TRIPLE "/" BASEVER "/lto-wrapper"));
298
      ADD_LINKER_ARG (makefmtstr ("-plugin-opt=-fresolution=%s.res", "TODO-UNKNOWN")); // LTO is not interoperable between clang and ld. See below.
299
      if (ARGV_CONTAINS_ARGWITHEQUALVAL ("-flinker-output"))
300
         ADD_LINKER_ARG ("-plugin-opt=-linker-output-known");
301
      if (!ARGV_CONTAINS_SINGLEARG ("-nostdlib") && !ARGV_CONTAINS_SINGLEARG ("-nodefaultlibs"))
302
         for (arg_index = 0; arg_index < larg_count; arg_index++)
303
            ADD_LINKER_ARG (makefmtstr ("-plugin-opt=-pass-through=%s", largs[arg_index]));*/
304
 
305
      // looks like LTO is a no-go. See: https://stackoverflow.com/questions/51259340/interoperability-between-clang-gcc-and-lto
306
   }
307
 
308
   //   "%{flto|flto=*:"        "%<fcompare-debug*"     "}     "
309
   if (ARGV_CONTAINS_SINGLEARG ("-flto") || ARGV_CONTAINS_ARGWITHEQUALVAL ("-flto"))
310
      for (arg_index = 1; arg_index < argc; arg_index++)
311
         if (strncmp (argv[arg_index], "-fcompare-debug", 15) == 0)
312
            argv[arg_index] = ""; // remove this arg
313
 
314
   if (ARGV_CONTAINS_SINGLEARG ("-flto"))       ADD_LINKER_ARG ("-flto");                    // "%{flto} "
315
   if (ARGV_CONTAINS_SINGLEARG ("-fno-lto"))    ADD_LINKER_ARG ("-fno-lto");                 // "%{fno-lto} "
316
   if (ARGV_CONTAINS_ARGWITHEQUALVAL ("-flto")) ADD_LINKER_ARG (makefmtstr ("-flto=%s", arg)); //       "%{flto=*} "
317
 
318
   //   "%{!static:"    "--eh-frame-hdr"                "} "
319
   if (!ARGV_CONTAINS_SINGLEARG ("-static")) ADD_LINKER_ARG ("--eh-frame-hdr");
320
 
321
#if IS_TARGET_INTEL
322
   //   "%{!m32:"       "-m elf_x86_64"                 "} "
323
   //   "%{m32:"        "-m i386nto"                    "}   "
324
   ADD_LINKER_ARG ("-m");
325
   if (ARGV_CONTAINS_SINGLEARG ("-m32"))
326
      ADD_LINKER_ARG ("i386nto");
327
   else
328
      ADD_LINKER_ARG ("elf_x86_64");
329
#endif // IS_TARGET_INTEL
330
 
331
   //   "%{h*} "
332
   for (arg_index = 1; arg_index < argc; arg_index++)
333
      if ((strcmp (argv[arg_index], "-h") == 0) && (arg_index + 1 < argc))
334
      {
335
         ADD_LINKER_ARG ("-h");
336
         ADD_LINKER_ARG (argv[++arg_index]);
337
      }
338
      else if ((strncmp (argv[arg_index], "-h", 2) == 0) && ((argv[arg_index])[2] != 0))
339
         ADD_LINKER_ARG (argv[arg_index]);
340
 
341
   //   "%{v:"  "-V"    "}   "
342
   if (ARGV_CONTAINS_SINGLEARG ("-v")) ADD_LINKER_ARG ("-V");
343
 
344
   //   "%{b}   "
345
   if (ARGV_CONTAINS_SINGLEARG ("-b")) ADD_LINKER_ARG ("-b");
346
 
347
#if !IS_TARGET_INTEL
348
   //   "%{Wl,*:"       "%*"                            "}  "
349
   for (arg_index = 1; arg_index < argc; arg_index++)
350
      if ((strcmp (argv[arg_index], "-Wl,") == 0) && (arg_index + 1 < argc))
351
         ADD_LINKER_ARG (argv[++arg_index]);
352
      else if ((strncmp (argv[arg_index], "-Wl,", 4) == 0) && ((argv[arg_index])[4] != 0))
353
         ADD_LINKER_ARG (argv[arg_index] + 4);
354
#endif // !IS_TARGET_INTEL
355
 
356
   //   "%{!r:"         "--build-id=md5"                "}   "
357
   if (!ARGV_CONTAINS_SINGLEARG ("-r")) ADD_LINKER_ARG ("--build-id=md5");
358
 
359
   //   "--warn-shared-textrel   "
360
   //   "-zrelro "
361
   //   "-znow   "
362
   ADD_LINKER_ARG ("--warn-shared-textrel");
10 pmbaty 363
   ADD_LINKER_ARG ("-zrelro"); // set relocations to be read-only
364
   ADD_LINKER_ARG ("-znow"); // do immediate binding of dylibs (the opposite would be -zlazy, which is less secure)
8 pmbaty 365
 
366
   // since clang doesn't seem to generate .note.GNU-stack sections in output ELF files we explicitly specify the linker that we don't want an executable stack
367
   // TODO: fix this in clang itself
368
   ADD_LINKER_ARG ("-znoexecstack");
369
 
370
#if IS_TARGET_INTEL
371
   //   "%{shared:"     "-G -dy -z text"                "}   "
372
   if (ARGV_CONTAINS_SINGLEARG ("-shared"))
373
   {
374
      ADD_LINKER_ARG ("-G");
375
      ADD_LINKER_ARG ("-dy");
376
      ADD_LINKER_ARG ("-z");
377
      ADD_LINKER_ARG ("text");
378
   }
379
 
380
   //   "%{symbolic:"   "-Bsymbolic -G -dy -z text"     "}   "
381
   if (ARGV_CONTAINS_SINGLEARG ("-symbolic"))
382
   {
383
      ADD_LINKER_ARG ("-Bsymbolic");
384
      ADD_LINKER_ARG ("-G");
385
      ADD_LINKER_ARG ("-dy");
386
      ADD_LINKER_ARG ("-z");
387
      ADD_LINKER_ARG ("text");
388
   }
389
 
390
   //   "%{G:"          "-G"                            "}   "
391
   if (ARGV_CONTAINS_SINGLEARG ("-G")) ADD_LINKER_ARG ("-G");
392
 
393
   //   "%{shared:"     "-shared"                       "}   "
394
   //   "%{!shared:     "
395
   //           "%{!static:       "
396
   //                   "%{rdynamic:"   "-export-dynamic"               "}       "
397
   //                   "%{m32:"
398
   //                           "%{!dynamic-linker:"    "-dynamic-linker /usr/lib/ldqnx.so.2"           "}"
399
   //                   "}       "
400
   //                   "%{!m32:"
401
   //                           "%{!dynamic-linker:"    "-dynamic-linker /usr/lib/ldqnx-64.so.2"        "}"
402
   //                   "}"
403
   //           "}     "
404
   //           "%{static:"     "-static"                                                               "}"
405
   //   "} "
406
   if (ARGV_CONTAINS_SINGLEARG ("-shared"))
407
      ADD_LINKER_ARG ("-shared");
408
   else if (ARGV_CONTAINS_SINGLEARG ("-static"))
409
      ADD_LINKER_ARG ("-static");
410
   else
411
   {
412
      if (ARGV_CONTAINS_SINGLEARG ("-rdynamic"))
413
         ADD_LINKER_ARG ("-export-dynamic");
414
      if (!ARGV_CONTAINS_SINGLEARG ("-dynamic-linker"))
415
      {
416
         ADD_LINKER_ARG ("-dynamic-linker");
417
         if (ARGV_CONTAINS_SINGLEARG ("-m32"))
418
            ADD_LINKER_ARG ("/usr/lib/ldqnx.so.2");
419
         else // not -m32
420
            ADD_LINKER_ARG ("/usr/lib/ldqnx-64.so.2");
421
      }
422
   }
423
 
424
#else // !IS_TARGET_INTEL
425
   //   "%{static:"     "-Bstatic"                      "}  "
426
   if (ARGV_CONTAINS_SINGLEARG ("-static")) ADD_LINKER_ARG ("-Bstatic");
427
 
428
   //   "%{shared}  "
429
   if (ARGV_CONTAINS_SINGLEARG ("-shared")) ADD_LINKER_ARG ("-shared");
430
 
431
   //   "%{symbolic:"   "-Bsymbolic"                    "}  "
432
   if (ARGV_CONTAINS_SINGLEARG ("-symbolic")) ADD_LINKER_ARG ("-Bsymbolic");
433
 
434
   //   "%{G:"          "-G"                            "} "
435
   if (ARGV_CONTAINS_SINGLEARG ("-G")) ADD_LINKER_ARG ("-G");
436
 
437
   //   "%{MAP:"        "-Map mapfile"                  "}  "
438
   if (ARGV_CONTAINS_SINGLEARG ("-MAP"))
439
   {
440
      ADD_LINKER_ARG ("-Map");
441
      ADD_LINKER_ARG ("mapfile");
442
   }
443
 
444
   //   "%{!shared:    "
445
   //           "%{!static:      "
446
   //                   "%{rdynamic:"   "-export-dynamic"               "}"
447
   //           "}    "
448
   //           "--dynamic-linker /usr/lib/ldqnx-64.so.2"
449
   //   "}  "
450
   if (!ARGV_CONTAINS_SINGLEARG ("-shared"))
451
   {
452
      if (!ARGV_CONTAINS_SINGLEARG ("-static") && ARGV_CONTAINS_SINGLEARG ("-rdynamic"))
453
         ADD_LINKER_ARG ("-export-dynamic");
454
      ADD_LINKER_ARG ("--dynamic-linker");
455
      ADD_LINKER_ARG ("/usr/lib/ldqnx-64.so.2");
456
   }
457
 
458
   //   "-X "
459
   ADD_LINKER_ARG ("-X");
460
 
461
   //   "%{EB:"         "-EB"                           "} "
462
   //   "%{!EB:"        "-EL"                           "} "
463
   if (ARGV_CONTAINS_SINGLEARG ("-EB"))
464
      ADD_LINKER_ARG ("-EB");
465
   else
466
      ADD_LINKER_ARG ("-EL");
467
 
468
   //   "%{EL:"         "-EL"                           "} "
469
   if (ARGV_CONTAINS_SINGLEARG ("-EL"))
470
      ADD_LINKER_ARG ("-EL");
471
#endif // IS_TARGET_INTEL
472
 
473
   //   "%{static|shared|r:;!no-pie:"   "-pie"                                                          "} "
474
   if (ARGV_CONTAINS_SINGLEARG ("-static") || !ARGV_CONTAINS_SINGLEARG ("-shared") || !ARGV_CONTAINS_SINGLEARG ("-r"))
475
      ; // nothing to do
476
   else if (!ARGV_CONTAINS_SINGLEARG ("-no-pie"))
477
      ADD_LINKER_ARG ("-pie");
478
 
479
   //   "%{fuse-ld=*:"                  "-fuse-ld=%*"                                                                   "} "
480
   for (arg_index = 1; arg_index < argc; arg_index++)
481
      if ((strncmp (argv[arg_index], "-fuse-ld=", 9) == 0) && ((argv[arg_index])[9] != 0))
482
         ADD_LINKER_ARG (argv[arg_index]);
483
 
484
   //   "%{gz|gz=zlib:"         "--compress-debug-sections=zlib"                        "} "
485
   //   "%{gz=none:"                    "--compress-debug-sections=none"                        "} "
486
   //   "%{gz=zlib-gnu:"                "--compress-debug-sections=zlib-gnu"    "} "
487
   if (ARGV_CONTAINS_SINGLEARG ("-gz") || ARGV_CONTAINS_SINGLEARG ("-gz=zlib"))
488
      ADD_LINKER_ARG ("--compress-debug-sections=zlib");
489
   if (ARGV_CONTAINS_SINGLEARG ("-gz=none"))
490
      ADD_LINKER_ARG ("--compress-debug-sections=none");
491
   if (ARGV_CONTAINS_SINGLEARG ("-gz=zlib-gnu"))
492
      ADD_LINKER_ARG ("--compress-debug-sections=zlib-gnu");
493
 
494
   //   "%X "
495
   // nothing to do (nothing was accumulated by %x previously)
496
 
497
   //   "%{o*} "
498
   for (arg_index = 1; arg_index < argc; arg_index++)
499
      if ((strcmp (argv[arg_index], "-o") == 0) && (arg_index + 1 < argc))
500
      {
501
         ADD_LINKER_ARG ("-o");
502
         ADD_LINKER_ARG (argv[++arg_index]);
503
      }
504
      else if ((strncmp (argv[arg_index], "-o", 2) == 0) && ((argv[arg_index])[2] != 0))
505
         ADD_LINKER_ARG (argv[arg_index]);
506
 
507
   //   "%{e*} "
508
   for (arg_index = 1; arg_index < argc; arg_index++)
509
      if ((strcmp (argv[arg_index], "-e") == 0) && (arg_index + 1 < argc))
510
      {
511
         ADD_LINKER_ARG ("-e");
512
         ADD_LINKER_ARG (argv[++arg_index]);
513
      }
514
      else if ((strncmp (argv[arg_index], "-e", 2) == 0) && ((argv[arg_index])[2] != 0))
515
         ADD_LINKER_ARG (argv[arg_index]);
516
 
517
   //   "%{N} "
518
   //   "%{n} "
519
   //   "%{r}    "
520
   //   "%{s} "
521
   //   "%{t} "
522
   if (ARGV_CONTAINS_SINGLEARG ("-N")) ADD_LINKER_ARG ("-N");
523
   if (ARGV_CONTAINS_SINGLEARG ("-n")) ADD_LINKER_ARG ("-n");
524
   if (ARGV_CONTAINS_SINGLEARG ("-r")) ADD_LINKER_ARG ("-r");
525
   if (ARGV_CONTAINS_SINGLEARG ("-s")) ADD_LINKER_ARG ("-s");
526
   if (ARGV_CONTAINS_SINGLEARG ("-t")) ADD_LINKER_ARG ("-t");
527
 
528
   //   "%{u*} "
529
   for (arg_index = 1; arg_index < argc; arg_index++)
530
      if ((strcmp (argv[arg_index], "-u") == 0) && (arg_index + 1 < argc))
531
      {
532
         ADD_LINKER_ARG ("-u");
533
         ADD_LINKER_ARG (argv[++arg_index]);
534
      }
535
      else if ((strncmp (argv[arg_index], "-u", 2) == 0) && ((argv[arg_index])[2] != 0))
536
         ADD_LINKER_ARG (argv[arg_index]);
537
 
538
   //   "%{z} "
539
   //   "%{Z} "
540
   if (ARGV_CONTAINS_SINGLEARG ("-z")) ADD_LINKER_ARG ("-z");
541
   if (ARGV_CONTAINS_SINGLEARG ("-Z")) ADD_LINKER_ARG ("-Z");
542
 
543
   //   "%{!nostdlib:"
544
   //           "%{!r:"
545
   //                   "%{!nostartfiles:"      "%S"    "}"
546
   //           "}"
547
   //   "}     "
548
   if (!ARGV_CONTAINS_SINGLEARG ("-nostdlib") && !ARGV_CONTAINS_SINGLEARG ("-r") && !ARGV_CONTAINS_SINGLEARG ("-nostartfiles"))
549
   {
550
#if IS_TARGET_INTEL // Intel variant
551
      //        "%{!shared:   "
552
      //                "%{!symbolic:     "
553
      //                        "%{pg:       "
554
      //                                "%{m32:"        " %${QNX_TARGET}/x86/lib/mcrt1.o%s"     "}       "
555
      //                                "%{!m32:"       " %${QNX_TARGET}/x86_64/lib/mcrt1.o%s"  "}"
556
      //                        "}     "
557
      //                        "%{!pg:       "
558
      //                                "%{p:        "
559
      //                                        "%{m32:"        " %${QNX_TARGET}/x86/lib/mcrt1.o%s"     "}        "
560
      //                                        "%{!m32:"       " %${QNX_TARGET}/x86_64/lib/mcrt1.o%s"  "}"
561
      //                                "}"
562
      //                        "}     "
563
      //                        "%{!p: "
564
      //                                "%{!pg:        "
565
      //                                        "%{m32:"        " %${QNX_TARGET}/x86/lib/crt1%{!no-pie:S}.o%s"  "}        "
566
      //                                        "%{!m32:"       " %${QNX_TARGET}/x86_64/lib/crt1.o%s"   "}"
567
      //                                "}"
568
      //                        "}     "
569
      //                "}"
570
      //        "}     "
571
      if (!ARGV_CONTAINS_SINGLEARG ("-shared") && !ARGV_CONTAINS_SINGLEARG ("-symbolic"))
572
      {
573
         if (ARGV_CONTAINS_SINGLEARG ("-pg") || ARGV_CONTAINS_SINGLEARG ("-p"))
574
         {
575
            if (ARGV_CONTAINS_SINGLEARG ("-m32"))
576
               ADD_LINKER_ARG (resolve_envvars ("${QNX_TARGET}/x86/lib/mcrt1.o"));
577
            else
578
               ADD_LINKER_ARG (resolve_envvars ("${QNX_TARGET}/x86_64/lib/mcrt1.o"));
579
         }
580
         else // neither "-pg" nor "-p"
581
         {
582
            if (ARGV_CONTAINS_SINGLEARG ("-m32"))
583
               ADD_LINKER_ARG (resolve_envvars (makefmtstr ("${QNX_TARGET}/x86/lib/crt1%s.o", ARGV_CONTAINS_SINGLEARG ("-no-pie") ? "" : "S")));
584
            else
585
               ADD_LINKER_ARG (resolve_envvars ("${QNX_TARGET}/x86_64/lib/crt1.o"));
586
         }
587
      }
588
 
589
      //        "%{m32:"        " %${QNX_TARGET}/x86/lib/crti.o%s"      "}     "
590
      //        "%{!m32:"       " %${QNX_TARGET}/x86_64/lib/crti.o%s"   "}     "
591
      if (ARGV_CONTAINS_SINGLEARG ("-m32"))
592
         ADD_LINKER_ARG (resolve_envvars ("${QNX_TARGET}/x86/lib/crti.o"));
593
      else
594
         ADD_LINKER_ARG (resolve_envvars ("${QNX_TARGET}/x86_64/lib/crti.o"));
595
#else // !IS_TARGET_INTEL
596
      //        "%{!shared: %${QNX_TARGET}/aarch64%{EB:be}%{!EB:le}/lib/%{pg:m}%{p:m}crt1.o } "
597
      if (ARGV_CONTAINS_SINGLEARG ("-shared"))
598
         if (ARGV_CONTAINS_SINGLEARG ("-EB"))
599
            ADD_LINKER_ARG (resolve_envvars (makefmtstr ("${QNX_TARGET}/aarch64be/lib/%scrt1.o", ARGV_CONTAINS_SINGLEARG ("-pg") || ARGV_CONTAINS_SINGLEARG ("-p") ? "m" : "")));
600
         else
601
            ADD_LINKER_ARG (resolve_envvars (makefmtstr ("${QNX_TARGET}/aarch64le/lib/%scrt1.o", ARGV_CONTAINS_SINGLEARG ("-pg") || ARGV_CONTAINS_SINGLEARG ("-p") ? "m" : "")));
602
 
603
      //        "%${QNX_TARGET}/aarch64%{EB:be}%{!EB:le}/lib/crti.o "
604
      if (ARGV_CONTAINS_SINGLEARG ("-EB"))
605
         ADD_LINKER_ARG (resolve_envvars ("${QNX_TARGET}/aarch64be/lib/crti.o"));
606
      else
607
         ADD_LINKER_ARG (resolve_envvars ("${QNX_TARGET}/aarch64le/lib/crti.o"));
608
#endif // IS_TARGET_INTEL
609
      //        "crtbegin.o%s "
610
      ADD_LINKER_ARG (resolve_envvars ("${QNX_HOST}/usr/bin/../lib/gcc/" TARGET_TRIPLE "/" BASEVER "/crtbegin.o"));
611
   }
612
 
613
   //   "%{static|no-pie|static-pie:"                                   "} "
614
   // nothing to do
615
 
616
   //   "%@{L*} "
617
   for (arg_index = 1; arg_index < argc; arg_index++)
618
      if ((strcmp (argv[arg_index], "-L") == 0) && (arg_index + 1 < argc))
619
      {
620
         ADD_LINKER_ARG ("-L");
621
         ADD_LINKER_ARG (argv[++arg_index]);
622
      }
623
      else if ((strncmp (argv[arg_index], "-L", 2) == 0) && ((argv[arg_index])[2] != 0))
624
         ADD_LINKER_ARG (argv[arg_index]);
625
 
626
   //   "%(mfwrap) "
627
   // nothing to do (looks like the libmudflap wrap spec has been officially removed from this version of GCC, except for uCLinux)
628
 
629
   //   "-L${QNX_HOST}/usr/bin/../lib/gcc/" TARGET_TRIPLE "/" BASEVER
630
   //   "-L${QNX_HOST}/usr/bin/../lib/gcc"
631
   ADD_LINKER_ARG (resolve_envvars ("-L${QNX_HOST}/usr/bin/../lib/gcc/" TARGET_TRIPLE "/" BASEVER));
632
   ADD_LINKER_ARG (resolve_envvars ("-L${QNX_HOST}/usr/bin/../lib/gcc"));
633
 
634
#if IS_TARGET_INTEL
635
   //   "%{m32:   " \
636
   //           "-L %${QNX_TARGET}/x86/lib/gcc/" BASEVER "   "
637
   //           "-L %${QNX_TARGET}/x86/lib   "
638
   //           "-L %${QNX_TARGET}/x86/usr/lib   "
639
   //           "-L %${QNX_TARGET}/x86/opt/lib   "
640
   //           "-rpath-link %${QNX_TARGET}/x86/lib/gcc/" BASEVER ":%${QNX_TARGET}/x86/lib:%${QNX_TARGET}/x86/usr/lib:%${QNX_TARGET}/x86/opt/lib"
641
   //   "}  "
642
   //   "%{!m32:   "
643
   //           "-L %${QNX_TARGET}/x86_64/lib/gcc/" BASEVER "   "
644
   //           "-L %${QNX_TARGET}/x86_64/lib   "
645
   //           "-L %${QNX_TARGET}/x86_64/usr/lib   "
646
   //           "-L %${QNX_TARGET}/x86_64/opt/lib   "
647
   //           "-rpath-link %${QNX_TARGET}/x86_64/lib/gcc/" BASEVER ":%${QNX_TARGET}/x86_64/lib:%${QNX_TARGET}/x86_64/usr/lib:%${QNX_TARGET}/x86_64/opt/lib"
648
   //   "} "
649
   if (ARGV_CONTAINS_SINGLEARG ("-m32"))
650
   {
651
      ADD_LINKER_ARG (resolve_envvars ("-L${QNX_TARGET}/x86/lib/gcc/" BASEVER));
652
      ADD_LINKER_ARG (resolve_envvars ("-L${QNX_TARGET}/x86/lib"));
653
      ADD_LINKER_ARG (resolve_envvars ("-L${QNX_TARGET}/x86/usr/lib"));
654
      ADD_LINKER_ARG (resolve_envvars ("-L${QNX_TARGET}/x86/opt/lib"));
655
      ADD_LINKER_ARG ("-rpath-link");
656
      ADD_LINKER_ARG (resolve_envvars ("${QNX_TARGET}/x86/lib/gcc/" BASEVER ":${QNX_TARGET}/x86/lib" ":${QNX_TARGET}/x86/usr/lib" ":${QNX_TARGET}/x86/opt/lib"));
657
   }
658
   else
659
   {
660
      ADD_LINKER_ARG (resolve_envvars ("-L${QNX_TARGET}/x86_64/lib/gcc/" BASEVER));
661
      ADD_LINKER_ARG (resolve_envvars ("-L${QNX_TARGET}/x86_64/lib"));
662
      ADD_LINKER_ARG (resolve_envvars ("-L${QNX_TARGET}/x86_64/usr/lib"));
663
      ADD_LINKER_ARG (resolve_envvars ("-L${QNX_TARGET}/x86_64/opt/lib"));
664
      ADD_LINKER_ARG ("-rpath-link");
665
      ADD_LINKER_ARG (resolve_envvars ("${QNX_TARGET}/x86_64/lib/gcc/" BASEVER ":${QNX_TARGET}/x86_64/lib:${QNX_TARGET}/x86_64/usr/lib:${QNX_TARGET}/x86_64/opt/lib"));
666
   }
667
#else // !IS_TARGET_INTEL
668
   //   "-L %${QNX_TARGET}/aarch64%{EB:be}%{!EB:le}/lib/gcc/" BASEVER "  "
669
   //   "-L %${QNX_TARGET}/aarch64%{EB:be}%{!EB:le}/lib  "
670
   //   "-L %${QNX_TARGET}/aarch64%{EB:be}%{!EB:le}/usr/lib  "
671
   //   "-L %${QNX_TARGET}/aarch64%{EB:be}%{!EB:le}/opt/lib  "
672
   if (ARGV_CONTAINS_SINGLEARG ("-EB"))
673
   {
674
      ADD_LINKER_ARG (resolve_envvars ("-L${QNX_TARGET}/aarch64be/lib/gcc/" BASEVER));
675
      ADD_LINKER_ARG (resolve_envvars ("-L${QNX_TARGET}/aarch64be/lib"));
676
      ADD_LINKER_ARG (resolve_envvars ("-L${QNX_TARGET}/aarch64be/usr/lib"));
677
      ADD_LINKER_ARG (resolve_envvars ("-L${QNX_TARGET}/aarch64be/opt/lib"));
678
      ADD_LINKER_ARG ("-rpath-link");
679
      ADD_LINKER_ARG (resolve_envvars ("${QNX_TARGET}/aarch64be/lib/gcc/" BASEVER ":${QNX_TARGET}/aarch64be/lib" ":${QNX_TARGET}/aarch64be/usr/lib" ":${QNX_TARGET}/aarch64be/opt/lib"));
680
   }
681
   else
682
   {
683
      ADD_LINKER_ARG (resolve_envvars ("-L${QNX_TARGET}/aarch64le/lib/gcc/" BASEVER));
684
      ADD_LINKER_ARG (resolve_envvars ("-L${QNX_TARGET}/aarch64le/lib"));
685
      ADD_LINKER_ARG (resolve_envvars ("-L${QNX_TARGET}/aarch64le/usr/lib"));
686
      ADD_LINKER_ARG (resolve_envvars ("-L${QNX_TARGET}/aarch64le/opt/lib"));
687
      ADD_LINKER_ARG ("-rpath-link");
688
      ADD_LINKER_ARG (resolve_envvars ("${QNX_TARGET}/aarch64le/lib/gcc/" BASEVER ":${QNX_TARGET}/aarch64le/lib" ":${QNX_TARGET}/aarch64le/usr/lib" ":${QNX_TARGET}/aarch64le/opt/lib"));
689
   }
690
#endif // IS_TARGET_INTEL
691
 
692
   //   "%{!nostdlib:"
693
   //           "%{!r:"
694
   //                   "%{fvtable-verify=std:"         " -lvtv -u_vtable_map_vars_start -u_vtable_map_vars_end"        "}    "
695
   //                   "%{fvtable-verify=preinit:"     " -lvtv -u_vtable_map_vars_start -u_vtable_map_vars_end"        "}"
696
   //           "}"
697
   //   "} "
698
   if (!ARGV_CONTAINS_SINGLEARG ("-nostdlib") && !ARGV_CONTAINS_SINGLEARG ("-r"))
699
   {
700
      if (ARGV_CONTAINS_SINGLEARG ("-fvtable-verify=std") || ARGV_CONTAINS_SINGLEARG ("-fvtable-verify=preinit"))
701
      {
702
         ADD_LINKER_ARG ("-lvtv");
703
         ADD_LINKER_ARG ("-u_vtable_map_vars_start");
704
         ADD_LINKER_ARG ("-u_vtable_map_vars_end");
705
      }
706
 
707
      //        "%{!nodefaultlibs:"
708
      if (!ARGV_CONTAINS_SINGLEARG ("-nodefaultlibs"))
709
      {
710
#if IS_TARGET_INTEL
711
      //                "%{%:sanitize(address):"        "}     "
712
      //                "%{%:sanitize(hwaddress):"      "}     "
713
      //                "%{%:sanitize(thread):"         "}     "
714
      //                "%{%:sanitize(leak):"           "}"
715
      /* TODO */
716
#else // !IS_TARGET_INTEL
717
      //                "%{%:sanitize(address):"
718
      //                        "%{!shared:"            "libasan_preinit%O%s"                                                                           "} "
719
      //                        "%{static-libasan:"     "%{!shared:"    "-Bstatic --whole-archive -lasan --no-whole-archive -Bdynamic"          "}"     "}"
720
      //                        "%{!static-libasan:"    "-lasan"                                                                                        "}"
721
      //                "}     "
722
      //                "%{%:sanitize(hwaddress):"
723
      //                        "%{static-libhwasan:"   "%{!shared:"    "-Bstatic --whole-archive -lhwasan --no-whole-archive -Bdynamic"        "}"     "}"
724
      //                        "%{!static-libhwasan:"  "-lhwasan"                                                                                      "}"
725
      //                "}     "
726
      //                "%{%:sanitize(thread):"
727
      //                        "%{!shared:"            "libtsan_preinit%O%s"                                                                           "} "
728
      //                        "%{static-libtsan:"     "%{!shared:"    "-Bstatic --whole-archive -ltsan --no-whole-archive -Bdynamic"          "}"     "}"
729
      //                        "%{!static-libtsan:"    "-ltsan"                                                                                        "}"
730
      //                "}     "
731
      //                "%{%:sanitize(leak):"
732
      //                        "%{!shared:"            "liblsan_preinit%O%s"                                                                           "} "
733
      //                        "%{static-liblsan:"     "%{!shared:"    "-Bstatic --whole-archive -llsan --no-whole-archive -Bdynamic"          "}"     "}"
734
      //                        "%{!static-liblsan:"    "-llsan"                                                                                        "}"
735
      //                "}"
736
      /* TODO */
737
#endif // IS_TARGET_INTEL
738
      }
739
   }
740
 
741
   //   "%o      "
742
   for (arg_index = 0; arg_index < oarg_count; arg_index++)
743
      ADD_LINKER_ARG (oargs[arg_index]);
744
 
745
   // QUOTE FROM https://gcc.gnu.org/onlinedocs/gcc/Spec-Files.html -- BEGIN
746
   // "The following example inserts the link_gomp spec if the last -ftree-parallelize-loops= option given on the command line is greater than 1:
747
   //  %{                 %:gt(%{ftree-parallelize-loops=*:%*} 1):%:include(libgomp.spec)%(link_gomp)}"
748
   // QUOTE FROM https://gcc.gnu.org/onlinedocs/gcc/Spec-Files.html -- END
749
   //   "%{fopenacc|fopenmp|%:gt(%{ftree-parallelize-loops=*:%*} 1):%:include(libgomp.spec)%(link_gomp)}    "
750
   // nothing to do (link_gomp is an empty string in this GCC)
751
 
752
   //   "%{fgnu-tm:"    "%:include(libitm.spec)%(link_itm)"     "}    "
753
   if (ARGV_CONTAINS_SINGLEARG ("-fgnu-tm"))
754
   {
755
      ADD_LINKER_ARG ("-litm");
756
      ADD_LINKER_ARG ("-lpthread"); // FIXME: possibly wrong
757
   }
758
 
759
   //   "%(mflib)  "
760
   // nothing to do (looks like the mflib spec has been officially removed from this version of GCC)
761
 
762
   //   "%{fsplit-stack: "                              "--wrap=pthread_create"         "}    "
763
   if (ARGV_CONTAINS_SINGLEARG ("-fsplit-stack"))
764
      ADD_LINKER_ARG ("--wrap=pthread_create");
765
 
766
   //   "%{fprofile-arcs|fprofile-generate*|coverage:"  "-lgcov"                        "} "
767
   if (ARGV_CONTAINS_SINGLEARG ("-fprofile-arcs") || ARGV_CONTAINS_ARGWITHVAL ("-fprofile-generate") || ARGV_CONTAINS_SINGLEARG ("-coverage"))
768
      ADD_LINKER_ARG ("-lgcov");
769
 
770
   if (!ARGV_CONTAINS_SINGLEARG ("-nostdlib") && !ARGV_CONTAINS_SINGLEARG ("-r"))
771
   {
772
      if (!ARGV_CONTAINS_SINGLEARG ("-nodefaultlibs"))
773
      {
774
#if IS_TARGET_INTEL
775
         //     "%{%:sanitize(address):"
776
         //             "%{static-libasan:"             "-Bstatic"                                              "} "
777
         //             "-lasan "
778
         //             "%{static-libasan:"             "-Bdynamic"                                             "} "
779
         //             "%{static-libasan|static:"      "%:include(libsanitizer.spec)%(link_libasan)"           "}    "
780
         //             "%{static:"                     "%ecannot specify -static with -fsanitize=address"      "}"
781
         //     "}    "
782
         if (ARGV_CONTAINS_SINGLEARG ("-fsanitize=address"))
783
         {
784
            if (ARGV_CONTAINS_SINGLEARG ("-static-libasan")) ADD_LINKER_ARG ("-Bstatic");
785
            ADD_LINKER_ARG ("-lasan");
786
            if (ARGV_CONTAINS_SINGLEARG ("-static-libasan")) ADD_LINKER_ARG ("-Bdynamic");
787
            if (ARGV_CONTAINS_SINGLEARG ("-static-libasan") || ARGV_CONTAINS_SINGLEARG ("-static"))
788
               ADD_LINKER_ARG ("-lm"); // only known dependency to libasan on QNX
789
            if (ARGV_CONTAINS_SINGLEARG ("-static"))
790
            {
791
               fprintf (stderr, "%s: error: cannot specify -static with -fsanitize=address\n", argv[0]);
792
               exit (1);
793
            }
794
         }
795
 
796
         //     "%{%:sanitize(hwaddress):"
797
         //             "%{static-libhwasan:"           "-Bstatic"                                              "} "
798
         //             "-lhwasan "
799
         //             "%{static-libhwasan:"           "-Bdynamic"                                             "} "
800
         //             "%{static-libhwasan|static:"    "%:include(libsanitizer.spec)%(link_libhwasan)"         "}      "
801
         //             "%{static:"                     "%ecannot specify -static with -fsanitize=hwaddress"    "}"
802
         //     "}    "
803
         if (ARGV_CONTAINS_SINGLEARG ("-fsanitize=hwaddress"))
804
         {
805
            if (ARGV_CONTAINS_SINGLEARG ("-static-libhwasan")) ADD_LINKER_ARG ("-Bstatic");
806
            ADD_LINKER_ARG ("-lhwasan");
807
            if (ARGV_CONTAINS_SINGLEARG ("-static-libhwasan")) ADD_LINKER_ARG ("-Bdynamic");
808
            if (ARGV_CONTAINS_SINGLEARG ("-static-libhwasan") || ARGV_CONTAINS_SINGLEARG ("-static"))
809
               ADD_LINKER_ARG ("-lm"); // only known dependency to libhwasan on QNX
810
            if (ARGV_CONTAINS_SINGLEARG ("-static"))
811
            {
812
               fprintf (stderr, "%s: error: cannot specify -static with -fsanitize=hwaddress\n", argv[0]);
813
               exit (1);
814
            }
815
         }
816
 
817
         //     "%{%:sanitize(thread):"
818
         //             "%{static-libtsan:"             "-Bstatic"                                              "} "
819
         //             "-ltsan "
820
         //             "%{static-libtsan:"             "-Bdynamic"                                             "} "
821
         //             "%{static-libtsan|static:"      "%:include(libsanitizer.spec)%(link_libtsan)"           "}    "
822
         //             "%{static:"                     "%ecannot specify -static with -fsanitize=thread"       "}"
823
         //     "}    "
824
         if (ARGV_CONTAINS_SINGLEARG ("-fsanitize=thread"))
825
         {
826
            if (ARGV_CONTAINS_SINGLEARG ("-static-libtsan")) ADD_LINKER_ARG ("-Bstatic");
827
            ADD_LINKER_ARG ("-ltsan");
828
            if (ARGV_CONTAINS_SINGLEARG ("-static-libtsan")) ADD_LINKER_ARG ("-Bdynamic");
829
            if (ARGV_CONTAINS_SINGLEARG ("-static-libtsan") || ARGV_CONTAINS_SINGLEARG ("-static"))
830
               ADD_LINKER_ARG ("-lm"); // only known dependency to libtsan on QNX
831
            if (ARGV_CONTAINS_SINGLEARG ("-static"))
832
            {
833
               fprintf (stderr, "%s: error: cannot specify -static with -fsanitize=thread\n", argv[0]);
834
               exit (1);
835
            }
836
         }
837
 
838
         //     "%{%:sanitize(undefined):"
839
         //             "%{static-libubsan:"            "-Bstatic"                                              "} "
840
         //             "-lubsan "
841
         //             "%{static-libubsan:"            "-Bdynamic"                                             "} "
842
         //             "%{static-libubsan|static:"     "%:include(libsanitizer.spec)%(link_libubsan)"          "}"
843
         //     "}    "
844
         if (ARGV_CONTAINS_SINGLEARG ("-fsanitize=undefined"))
845
         {
846
            if (ARGV_CONTAINS_SINGLEARG ("-static-libubsan")) ADD_LINKER_ARG ("-Bstatic");
847
            ADD_LINKER_ARG ("-lubsan");
848
            if (ARGV_CONTAINS_SINGLEARG ("-static-libubsan")) ADD_LINKER_ARG ("-Bdynamic");
849
            if (ARGV_CONTAINS_SINGLEARG ("-static-libubsan") || ARGV_CONTAINS_SINGLEARG ("-static"))
850
               ADD_LINKER_ARG ("-lm"); // only known dependency to libubsan on QNX
851
         }
852
 
853
         //     "%{%:sanitize(leak):"
854
         //             "%{static-liblsan:"             "-Bstatic"                                              "} "
855
         //             "-llsan "
856
         //             "%{static-liblsan:"             "-Bdynamic"                                             "} "
857
         //             "%{static-liblsan|static:"      "%:include(libsanitizer.spec)%(link_liblsan)"           "}"
858
         //     "}"
859
         if (ARGV_CONTAINS_SINGLEARG ("-fsanitize=leak"))
860
         {
861
            if (ARGV_CONTAINS_SINGLEARG ("-static-liblsan")) ADD_LINKER_ARG ("-Bstatic");
862
            ADD_LINKER_ARG ("-llsan");
863
            if (ARGV_CONTAINS_SINGLEARG ("-static-liblsan")) ADD_LINKER_ARG ("-Bdynamic");
864
            if (ARGV_CONTAINS_SINGLEARG ("-static-liblsan") || ARGV_CONTAINS_SINGLEARG ("-static"))
865
               ADD_LINKER_ARG ("-lm"); // only known dependency to liblsan on QNX
866
         }
867
#else // !IS_TARGET_INTEL
868
         //     "%{%:sanitize(address): "
869
         //             "%{static-libasan|static:"      "%:include(libsanitizer.spec)%(link_libasan)"           "}    "
870
         //             "%{static:"                     "%ecannot specify -static with -fsanitize=address"      "}"
871
         //     "}    "
872
         if (ARGV_CONTAINS_SINGLEARG ("-fsanitize=address"))
873
         {
874
            if (ARGV_CONTAINS_SINGLEARG ("-static-libasan") || ARGV_CONTAINS_SINGLEARG ("-static"))
875
               ADD_LINKER_ARG ("-lm"); // only known dependency to libasan on QNX
876
            if (ARGV_CONTAINS_SINGLEARG ("-static"))
877
            {
878
               fprintf (stderr, "%s: error: cannot specify -static with -fsanitize=address\n", argv[0]);
879
               exit (1);
880
            }
881
         }
882
 
883
         //     "%{%:sanitize(hwaddress): "
884
         //             "%{static-libhwasan|static:"    "%:include(libsanitizer.spec)%(link_libhwasan)"         "}      "
885
         //             "%{static:"                     "%ecannot specify -static with -fsanitize=hwaddress"    "}"
886
         //     "}    "
887
         if (ARGV_CONTAINS_SINGLEARG ("-fsanitize=hwaddress"))
888
         {
889
            if (ARGV_CONTAINS_SINGLEARG ("-static-libhwasan") || ARGV_CONTAINS_SINGLEARG ("-static"))
890
               ADD_LINKER_ARG ("-lm"); // only known dependency to libhwasan on QNX
891
            if (ARGV_CONTAINS_SINGLEARG ("-static"))
892
            {
893
               fprintf (stderr, "%s: error: cannot specify -static with -fsanitize=hwaddress\n", argv[0]);
894
               exit (1);
895
            }
896
         }
897
 
898
         //     "%{%:sanitize(thread): "
899
         //             "%{static-libtsan|static:"      "%:include(libsanitizer.spec)%(link_libtsan)"           "}    "
900
         //             "%{static:"                     "%ecannot specify -static with -fsanitize=thread"       "}"
901
         //     "}    "
902
         if (ARGV_CONTAINS_SINGLEARG ("-fsanitize=thread"))
903
         {
904
            if (ARGV_CONTAINS_SINGLEARG ("-static-libtsan") || ARGV_CONTAINS_SINGLEARG ("-static"))
905
               ADD_LINKER_ARG ("-lm"); // only known dependency to libtsan on QNX
906
            if (ARGV_CONTAINS_SINGLEARG ("-static"))
907
            {
908
               fprintf (stderr, "%s: error: cannot specify -static with -fsanitize=thread\n", argv[0]);
909
               exit (1);
910
            }
911
         }
912
 
913
         //     "%{%:sanitize(undefined):"
914
         //             "%{static-libubsan:"            "-Bstatic"                                              "} "
915
         //             "-lubsan "
916
         //             "%{static-libubsan:"            "-Bdynamic"                                             "} "
917
         //             "%{static-libubsan|static:"     "%:include(libsanitizer.spec)%(link_libubsan)"          "}"
918
         //     "}    "
919
         if (ARGV_CONTAINS_SINGLEARG ("-fsanitize=undefined"))
920
         {
921
            if (ARGV_CONTAINS_SINGLEARG ("-static-libubsan")) ADD_LINKER_ARG ("-Bstatic");
922
            ADD_LINKER_ARG ("-lubsan");
923
            if (ARGV_CONTAINS_SINGLEARG ("-static-libubsan")) ADD_LINKER_ARG ("-Bdynamic");
924
            if (ARGV_CONTAINS_SINGLEARG ("-static-libubsan") || ARGV_CONTAINS_SINGLEARG ("-static"))
925
               ADD_LINKER_ARG ("-lm"); // only known dependency to libubsan on QNX
926
         }
927
 
928
         //     "%{%:sanitize(leak): "
929
         //             "%{static-liblsan|static:"      "%:include(libsanitizer.spec)%(link_liblsan)"           "}"
930
         //     "}"
931
         if (ARGV_CONTAINS_SINGLEARG ("-fsanitize=leak"))
932
         {
933
            if (ARGV_CONTAINS_SINGLEARG ("-static-liblsan") || ARGV_CONTAINS_SINGLEARG ("-static"))
934
               ADD_LINKER_ARG ("-lm"); // only known dependency to liblsan on QNX
935
         }
936
#endif // IS_TARGET_INTEL
937
 
938
         // "%{fstack-protector|fstack-protector-all|fstack-protector-strong|fstack-protector-explicit:}"
939
         // nothing to do
940
 
941
         // "%(link_gcc_c_sequence)"
942
#if IS_TARGET_INTEL
943
         //     "%{static|static-libgcc:"                       "-lgcc -lgcc_eh"        "}"
944
         if (ARGV_CONTAINS_SINGLEARG ("-static") || ARGV_CONTAINS_SINGLEARG ("-static-libgcc"))
945
         {
946
            ADD_LINKER_ARG ("-lgcc");
947
            ADD_LINKER_ARG ("-lgcc_eh");
948
         }
949
 
950
         //     "%{!static:"
951
         //             "%{!static-libgcc:"
952
         //                     "%{!shared:"
953
         //                             "%{!shared-libgcc:"     "-lgcc -lgcc_eh"        "}"
954
         //                             "%{shared-libgcc:"      "-lgcc_s -lgcc"         "}"
955
         //                     "}"
956
         //                     "%{shared:"
957
         //                             "%{shared-libgcc:"      "-lgcc_s"               "}"
958
         //                             "%{!shared-libgcc:"     "-lgcc"                 "}"
959
         //                     "}"
960
         //             "}"
961
         //     "}"
962
         if (!ARGV_CONTAINS_SINGLEARG ("-static") && !ARGV_CONTAINS_SINGLEARG ("-static-libgcc"))
963
         {
964
            if (!ARGV_CONTAINS_SINGLEARG ("-shared"))
965
            {
966
               if (ARGV_CONTAINS_SINGLEARG ("-shared-libgcc"))
967
               {
968
                  ADD_LINKER_ARG ("-lgcc_s");
969
                  ADD_LINKER_ARG ("-lgcc");
970
               }
971
               else
972
               {
973
                  ADD_LINKER_ARG ("-lgcc");
974
                  ADD_LINKER_ARG ("-lgcc_eh");
975
               }
976
            }
977
            else if (ARGV_CONTAINS_SINGLEARG ("-shared-libgcc"))
978
               ADD_LINKER_ARG ("-lgcc_s");
979
            else
980
               ADD_LINKER_ARG ("-lgcc");
981
         }
982
 
983
         //     "%{!nolibc:"
984
         if (!ARGV_CONTAINS_SINGLEARG ("-nolibc"))
985
         {
986
            //  "%{!symbolic:"
987
            //          " -lc"
988
            //          " %{shared:"    "-lcS"  "}"
989
            //          " %{!no-pie:"   "-lcS"  "}"
990
            //          " %{no-pie:"    "-lc"   "}"
991
            //  "} "
992
            if (!ARGV_CONTAINS_SINGLEARG ("-symbolic"))
993
            {
994
               ADD_LINKER_ARG ("-lc");
995
               if (ARGV_CONTAINS_SINGLEARG ("-shared") || !ARGV_CONTAINS_SINGLEARG ("-no-pie"))
996
                  ADD_LINKER_ARG ("-lcS");
997
            }
998
 
999
            //  "%{static|static-libgcc:"                       "-lgcc -lgcc_eh"        "}"
1000
            if (ARGV_CONTAINS_SINGLEARG ("-static") || ARGV_CONTAINS_SINGLEARG ("-static-libgcc"))
1001
            {
1002
               ADD_LINKER_ARG ("-lgcc");
1003
               ADD_LINKER_ARG ("-lgcc_eh");
1004
            }
1005
 
1006
            //  "%{!static:"
1007
            //          "%{!static-libgcc:"
1008
            //                  "%{!shared:"
1009
            //                          "%{!shared-libgcc:"     "-lgcc -lgcc_eh"        "}"
1010
            //                          "%{shared-libgcc:"      "-lgcc_s -lgcc"         "}"
1011
            //                  "}"
1012
            //                  "%{shared:"
1013
            //                          "%{shared-libgcc:"      "-lgcc_s"               "}"
1014
            //                          "%{!shared-libgcc:"     "-lgcc"                 "}"
1015
            //                  "}"
1016
            //          "}"
1017
            //  "
1018
            if (!ARGV_CONTAINS_SINGLEARG ("-static") && !ARGV_CONTAINS_SINGLEARG ("-static-libgcc"))
1019
            {
1020
               if (!ARGV_CONTAINS_SINGLEARG ("-shared"))
1021
               {
1022
                  if (ARGV_CONTAINS_SINGLEARG ("-shared-libgcc"))
1023
                  {
1024
                     ADD_LINKER_ARG ("-lgcc_s");
1025
                     ADD_LINKER_ARG ("-lgcc");
1026
                  }
1027
                  else
1028
                  {
1029
                     ADD_LINKER_ARG ("-lgcc");
1030
                     ADD_LINKER_ARG ("-lgcc_eh");
1031
                  }
1032
               }
1033
               else if (ARGV_CONTAINS_SINGLEARG ("-shared-libgcc"))
1034
                  ADD_LINKER_ARG ("-lgcc_s");
1035
               else
1036
                  ADD_LINKER_ARG ("-lgcc");
1037
            }
1038
         }
1039
#else // !IS_TARGET_INTEL
1040
         //     "%{static|static-pie:"  "--start-group" "} "
1041
         if (ARGV_CONTAINS_SINGLEARG ("-static") || ARGV_CONTAINS_SINGLEARG ("-static-pie"))
1042
            ADD_LINKER_ARG ("--start-group");
1043
 
1044
         //     "%{static|static-libgcc|static-pie:"            "-lgcc -lgcc_eh"        "}"
1045
         if (ARGV_CONTAINS_SINGLEARG ("-static") || ARGV_CONTAINS_SINGLEARG ("-static-libgcc") || ARGV_CONTAINS_SINGLEARG ("-static-pie"))
1046
         {
1047
            ADD_LINKER_ARG ("-lgcc");
1048
            ADD_LINKER_ARG ("-lgcc_eh");
1049
         }
1050
 
1051
         //     "%{!static:"
1052
         //             "%{!static-libgcc:"
1053
         //                     "%{!static-pie:"
1054
         //                             "%{!shared-libgcc:"     "-lgcc --push-state --as-needed -lgcc_s --pop-state"    "}"
1055
         //                             "%{shared-libgcc:"      "-lgcc_s%{!shared: -lgcc}"                              "}"
1056
         //                     "}"
1057
         //             "}"
1058
         //     "}"
1059
         if (!ARGV_CONTAINS_SINGLEARG ("-static") && !ARGV_CONTAINS_SINGLEARG ("-static-libgcc") && !ARGV_CONTAINS_SINGLEARG ("-static-pie"))
1060
         {
1061
            if (!ARGV_CONTAINS_SINGLEARG ("-shared-libgcc"))
1062
            {
1063
               ADD_LINKER_ARG ("-lgcc");
1064
               ADD_LINKER_ARG ("--push-state");
1065
               ADD_LINKER_ARG ("--as-needed");
1066
               ADD_LINKER_ARG ("-lgcc_s");
1067
               ADD_LINKER_ARG ("--pop-state");
1068
            }
1069
            else
1070
            {
1071
               ADD_LINKER_ARG ("-lgcc_s");
1072
               if (!ARGV_CONTAINS_SINGLEARG ("-shared"))
1073
                  ADD_LINKER_ARG ("-lgcc");
1074
            }
1075
         }
1076
 
1077
         //     "%{!nolibc:"
1078
         //             "%{!symbolic:"
1079
         //                     " -lc"
1080
         //                     " %{shared:"    "-lcS"  "}"
1081
         //                     " %{!no-pie:"   "-lcS"  "}"
1082
         //                     " %{no-pie:"    "-lc"   "}"
1083
         //             "} "
1084
         // "}    "
1085
         if (!ARGV_CONTAINS_SINGLEARG ("-nolibc") && !ARGV_CONTAINS_SINGLEARG ("-symbolic"))
1086
         {
1087
            ADD_LINKER_ARG ("-lc");
1088
            if (ARGV_CONTAINS_SINGLEARG ("-shared") || !ARGV_CONTAINS_SINGLEARG ("-no-pie"))
1089
               ADD_LINKER_ARG ("-lcS");
1090
         }
1091
 
1092
         //     "%{static|static-pie:"  "--end-group"   "}"
1093
         if (ARGV_CONTAINS_SINGLEARG ("-static") || ARGV_CONTAINS_SINGLEARG ("-static-pie"))
1094
            ADD_LINKER_ARG ("--end-group");
1095
         //     "%{!static:"
1096
         //             "%{!static-pie:"
1097
         else
1098
         {
1099
            //  "%{static|static-libgcc|static-pie:"            "-lgcc -lgcc_eh"        "}"
1100
            if (ARGV_CONTAINS_SINGLEARG ("-static-libgcc"))
1101
            {
1102
               ADD_LINKER_ARG ("-lgcc");
1103
               ADD_LINKER_ARG ("-lgcc_eh");
1104
            }
1105
 
1106
            //  "%{!static:"
1107
            //          "%{!static-libgcc:"
1108
            //                  "%{!static-pie:"
1109
            //                          "%{!shared-libgcc:"     "-lgcc --push-state --as-needed -lgcc_s --pop-state"    "}"
1110
            //                          "%{shared-libgcc:"      "-lgcc_s%{!shared: -lgcc}"                              "}"
1111
            //                  "}"
1112
            //          "}"
1113
            //  "}"
1114
            if (!ARGV_CONTAINS_SINGLEARG ("-static") && !ARGV_CONTAINS_SINGLEARG ("-static-libgcc") && !ARGV_CONTAINS_SINGLEARG ("-static-pie"))
1115
            {
1116
               if (!ARGV_CONTAINS_SINGLEARG ("-shared-libgcc"))
1117
               {
1118
                  ADD_LINKER_ARG ("-lgcc");
1119
                  ADD_LINKER_ARG ("--push-state");
1120
                  ADD_LINKER_ARG ("--as-needed");
1121
                  ADD_LINKER_ARG ("-lgcc_s");
1122
                  ADD_LINKER_ARG ("--pop-state");
1123
               }
1124
               else
1125
               {
1126
                  ADD_LINKER_ARG ("-lgcc_s");
1127
                  if (!ARGV_CONTAINS_SINGLEARG ("-shared"))
1128
                     ADD_LINKER_ARG ("-lgcc");
1129
               }
1130
            }
1131
         }
1132
#endif // IS_TARGET_INTEL
1133
 
1134
         was_cpluspluslib_included = false;
1135
         for (arg_index = 0; arg_index < larg_count; arg_index++)
1136
         {
1137
            ADD_LINKER_ARG (largs[arg_index]);
1138
            if (((arg = strstr (largs[arg_index], "c++")) != NULL) && (arg[3] == 0))
1139
               was_cpluspluslib_included = true; // catches -lstdc++ and -lc++
1140
         }
1141
         if (!was_cpluspluslib_included)
1142
         {
1143
            if (strstr (argv[0], "g++") != NULL)
1144
               ADD_LINKER_ARG ("-lc++"); // if clang invoked us as g++ to link stuff it probably means we need a C++ library
1145
            else
1146
            {
1147
               requires_libcplusplus = false; // figure it out the hard way: if we see a C++ mangled symbol name in one of the object files, it means we need a C++ library
1148
               for (arg_index = 0; !requires_libcplusplus && (arg_index < oarg_count); arg_index++)
1149
               {
1150
                  fp = fopen (oargs[arg_index], "rb");
1151
                  if (fp == NULL) continue; // unopenable object file, should error out perhaps?
1152
                  while (!requires_libcplusplus && ((read_count = fread (filebuf, 1, sizeof (filebuf), fp)) > 0))
1153
                     for (byte_index = 0; !requires_libcplusplus && (byte_index < read_count - 8); byte_index++)
1154
                        if (memcmp (&filebuf[byte_index], ".text._Z", 8) == 0)
1155
                           requires_libcplusplus = true;
1156
                  fclose (fp);
1157
               }
1158
               if (requires_libcplusplus)
1159
                  ADD_LINKER_ARG ("-lc++"); // we did it the hard way
1160
            }
1161
         }
1162
      }
1163
 
1164
      //        "%{!nostartfiles:"      "%E"                                    "}"
1165
      if (!ARGV_CONTAINS_SINGLEARG ("-nostartfiles"))
1166
      {
1167
         ADD_LINKER_ARG (resolve_envvars ("${QNX_HOST}/usr/bin/../lib/gcc/" TARGET_TRIPLE "/" BASEVER "/crtend.o"));
1168
#if IS_TARGET_INTEL
1169
         if (ARGV_CONTAINS_SINGLEARG ("-m32"))
1170
            ADD_LINKER_ARG (resolve_envvars ("${QNX_TARGET}/x86/lib/crtn.o"));
1171
         else
1172
            ADD_LINKER_ARG (resolve_envvars ("${QNX_TARGET}/x86_64/lib/crtn.o"));
1173
#else // !IS_TARGET_INTEL
1174
         if (ARGV_CONTAINS_SINGLEARG ("-EB"))
1175
            ADD_LINKER_ARG (resolve_envvars ("${QNX_TARGET}/aarch64be/lib/crtn.o"));
1176
         else
1177
            ADD_LINKER_ARG (resolve_envvars ("${QNX_TARGET}/aarch64le/lib/crtn.o"));
1178
#endif // IS_TARGET_INTEL
1179
      }
1180
   }
1181
 
1182
   //   "%{T*}"
1183
   for (arg_index = 1; arg_index < argc; arg_index++)
1184
      if ((strcmp (argv[arg_index], "-T") == 0) && (arg_index + 1 < argc))
1185
      {
1186
         ADD_LINKER_ARG ("-T");
1187
         ADD_LINKER_ARG (argv[++arg_index]);
1188
      }
1189
      else if ((strncmp (argv[arg_index], "-T", 2) == 0) && ((argv[arg_index])[2] != 0))
1190
         ADD_LINKER_ARG (argv[arg_index]);
1191
 
1192
   if (ARGV_CONTAINS_SINGLEARG ("-v") || (getenv ("DEBUG_LINKER_DRIVER") != NULL))
1193
   {
1194
      fputs ("LINKER DRIVER: CONSTRUCTED COMMAND LINE BEGIN\n", stderr);
1195
      for (arg_index = 0; arg_index < linker_argc; arg_index++)
1196
         fprintf (stderr, "%s%s%s\n", (arg_index > 0 ? "\t" : ""), linker_argv[arg_index], ((size_t) arg_index + 1 < linker_argc ? " \\" : ""));
1197
      fputs ("LINKER DRIVER: CONSTRUCTED COMMAND LINE END\n", stderr);
1198
   }
1199
 
1200
   execvpe (LINKER, linker_argv, envp);
1201
   return (1); // unreachable code
1202
}