Subversion Repositories QNX 8.QNX8 linker driver

Rev

Rev 2 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 pmbaty 1
// QNX 8.0 linker driver 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
#include <stdio.h>
13
#include <stdlib.h>
14
#include <stdarg.h>
15
#include <stdbool.h>
16
#include <string.h>
17
#include <fcntl.h>
18
#ifndef _WIN32
19
#include <unistd.h>
20
#else // _WIN32
21
#include <process.h>
22
#include <io.h>
23
#define strdup(s) _strdup ((s))
24
#define strcasecmp(a,b) _stricmp ((a), (b))
25
#define access(f,m) _access ((f), (m))
26
#define execvpe(exename,argv,envp) exit ((int) _spawnvpe (P_WAIT, (exename), (argv), (envp)))
27
int vasprintf (char **out_string, const char *fmt, va_list va_args) // vasprintf() implementation
28
{
29
   int retval; va_list ap;
30
   *out_string = (char *) malloc (16); if (*out_string == NULL) return (-1);
31
   va_copy (ap, va_args); retval = vsnprintf (*out_string, 16, fmt, ap); va_end (ap); if (retval == -1) return (-1);
32
   if (retval >= 16)
33
   {
34
      void *new_string = realloc (*out_string, (size_t) retval + 1); if (new_string == NULL) return (-1); *out_string = (char *) new_string;
35
      va_copy (ap, va_args); retval = vsnprintf (*out_string, (size_t) retval + 1, fmt, va_args); va_end (ap);
36
   }
37
   return (retval);
38
}
39
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
40
#endif // !_WIN32
41
 
42
 
43
#define BASEVER "12.2.0"
44
#if (defined(__x86_64__) || defined(_WIN64))
45
#define IS_TARGET_INTEL 1
46
#define TARGET_TRIPLE "x86_64-pc-nto-qnx8.0.0"
47
#elif defined(__aarch64__)
48
#define IS_TARGET_INTEL 0
49
#define TARGET_TRIPLE "aarch64-unknown-nto-qnx8.0.0"
50
#else
51
#error unsupported platform (not x86_64, not aarch64le). Please implement!
52
#endif
53
#define LINKER TARGET_TRIPLE "-ld"
54
 
55
 
56
#define ARGMODE_SINGLE   0
57
#define ARGMODE_HASVAL   1
58
#define ARGMODE_EQUALVAL 2
59
 
60
 
61
char *array_contains (int argc, char **argv, char *needle, int mode)
62
{
63
   char *arg;
64
   int arg_index;
65
   size_t needle_len = strlen (needle);
66
   for (arg_index = 1; arg_index < argc; arg_index++)
67
   {
68
      arg = argv[arg_index];
69
      if (mode == ARGMODE_SINGLE)
70
      {
71
         if (strcmp (arg, needle) == 0)
72
            return ("");
73
      }
74
      else if (mode == ARGMODE_HASVAL)
75
      {
76
         if ((arg_index + 1 < argc) && (strcmp (arg, needle) == 0))
77
            return (argv[arg_index + 1]);
78
         else if ((strncmp (arg, needle, needle_len) == 0) && (arg[needle_len] != 0))
79
            return (&arg[needle_len]);
80
      }
81
      else if (mode == ARGMODE_EQUALVAL)
82
      {
83
         if ((strncmp (arg, needle, needle_len) == 0) && (arg[needle_len] == '='))
84
            return (&arg[needle_len + 1]);
85
      }
86
   }
87
   return (NULL);
88
}
89
 
90
 
91
char *resolve_envvars (char *str)
92
{
93
   char *out_str = strdup (str), *new_str;
94
   char *varstart, *varstop, *varval;
95
   while ((varstart = strstr (out_str, "${")) != NULL)
96
   {
97
      *varstart = 0;
98
      varstart += 2;
99
      varstop = strchr (varstart, '}');
100
      *varstop = 0;
101
      varval = getenv (varstart);
102
      asprintf (&new_str, "%s%s%s", out_str, (varval != NULL ? varval : ""), varstop + 1);
103
      free (out_str);
104
      out_str = new_str;
105
   }
106
   return (out_str);
107
}
108
 
109
 
110
char *makefmtstr (const char *fmt, ...)
111
{
112
   va_list ap;
113
   char *outstr = NULL;
114
   va_start (ap, fmt);
115
   vasprintf (&outstr, fmt, ap);
116
   va_end (ap);
117
   return (outstr);
118
}
119
 
120
 
121
int main (int argc, char **argv, char **envp)
122
{
123
   #define ADD_CHAR_ARRAY(array_var,arraysize_var,val) do { \
124
      void *reallocated_ptr = realloc (array_var, (arraysize_var + 2) * sizeof (char *)); \
125
      if (reallocated_ptr == NULL) exit (1); \
126
      array_var = reallocated_ptr; \
127
      array_var[arraysize_var] = (val); \
128
      array_var[arraysize_var + 1] = NULL; \
129
      arraysize_var++; \
130
   } while (0)
131
   #define ADD_LINKER_ARG(val) ADD_CHAR_ARRAY (linker_argv, linker_argc, (val))
132
   #define ADD_L_ARG(val) ADD_CHAR_ARRAY (largs, larg_count, (val))
133
   #define ADD_O_ARG(val) ADD_CHAR_ARRAY (oargs, oarg_count, (val))
134
   #define ARGV_CONTAINS_SINGLEARG(val)       ((arg = array_contains (argc, argv, (val), ARGMODE_SINGLE))   != NULL)
135
   #define ARGV_CONTAINS_ARGWITHVAL(val)      ((arg = array_contains (argc, argv, (val), ARGMODE_HASVAL))   != NULL)
136
   #define ARGV_CONTAINS_ARGWITHEQUALVAL(val) ((arg = array_contains (argc, argv, (val), ARGMODE_EQUALVAL)) != NULL)
137
   #define ARGV_SINGLEARG(val)       array_contains (argc, argv, (val), ARGMODE_SINGLE)
138
   #define ARGV_ARGWITHVAL(val)      array_contains (argc, argv, (val), ARGMODE_HASVAL)
139
   #define ARGV_ARGWITHEQUALVAL(val) array_contains (argc, argv, (val), ARGMODE_EQUALVAL)
140
 
141
   static char filebuf[1024 * 1024];
142
   char **linker_argv = NULL;
143
   size_t linker_argc = 0;
144
   char **largs = NULL; // array of "-lxxx" arguments
145
   size_t larg_count = 0;
146
   char **oargs = NULL; // array of object files arguments
147
   size_t oarg_count = 0;
148
   size_t read_count;
149
   size_t byte_index;
150
   bool was_cpluspluslib_included = false;
151
   bool requires_libcplusplus = false;
152
   int arg_index;
153
   char *arg;
154
   FILE *fp;
155
 
156
   if (   ARGV_CONTAINS_SINGLEARG ("-fsyntax-only")
157
       || ARGV_CONTAINS_SINGLEARG ("-c")
158
       || ARGV_CONTAINS_SINGLEARG ("-M")
159
       || ARGV_CONTAINS_SINGLEARG ("-MM")
160
       || ARGV_CONTAINS_SINGLEARG ("-E")
161
       || ARGV_CONTAINS_SINGLEARG ("-S"))
162
   {
163
      argv[0] = "clang";
164
      execvpe ("clang", argv, envp);
165
   }
166
 
167
   // collect object files
168
   for (arg_index = 1; arg_index < argc; arg_index++)
169
      if ((strcmp (argv[arg_index - 1], "-o") != 0) // arg is NOT preceded by -o AND is an existing file that is NOT a known extension
170
          && (access (argv[arg_index], 0) == 0)
171
          && ((arg = strrchr (argv[arg_index], '.')) != NULL)
172
          && (strcasecmp (arg, ".s") != 0)
173
          && (strcasecmp (arg, ".c") != 0)
174
          && (strcasecmp (arg, ".c++") != 0)
175
          && (strcasecmp (arg, ".cpp") != 0)
176
          && (strcasecmp (arg, ".cxx") != 0)
177
          && (strcasecmp (arg, ".m") != 0)
178
          && (strcasecmp (arg, ".mm") != 0)
179
          && (strcasecmp (arg, ".mxx") != 0)
180
          )
181
         ADD_O_ARG (argv[arg_index]);
182
 
183
   if (oarg_count == 0)
184
   {
185
      argv[0] = "clang";
186
      execvpe ("clang", argv, envp);
187
   }
188
 
189
   // collect -l flags
190
   for (arg_index = 1; arg_index < argc; arg_index++)
191
      if ((strncmp (argv[arg_index], "-l", 2) == 0) && ((argv[arg_index])[2] != 0))
192
         ADD_L_ARG (argv[arg_index]);
193
 
194
   //   LINKER " "
195
   ADD_LINKER_ARG (LINKER);
196
 
197
   //   "%{!fno-use-linker-plugin:"
198
   //           "%{!fno-lto:     "
199
   //                   "-plugin ${QNX_HOST}/usr/lib/gcc/" TARGET_TRIPLE "/" BASEVER "/liblto_plugin.so     "
200
   //                   "-plugin-opt=${QNX_HOST}/usr/lib/gcc/" TARGET_TRIPLE "/" BASEVER "/lto-wrapper     "
201
   //                   "-plugin-opt=-fresolution=%u.res         "
202
   //                   "%{flinker-output=*:"   "-plugin-opt=-linker-output-known"      "}     "
203
   //                   "%{!nostdlib:"
204
   //                           "%{!nodefaultlibs:"     "%:pass-through-libs(%(link_gcc_c_sequence))"   "}"
205
   //                   "}     "
206
   //           "}"
207
   //   "}"
208
   /*if (!ARGV_CONTAINS_SINGLEARG ("-fno-use-linker-plugin") && !ARGV_CONTAINS_SINGLEARG ("-fno-lto"))
209
   {
210
      ADD_LINKER_ARG ("-plugin");
211
      ADD_LINKER_ARG (resolve_envvars ("${QNX_HOST}/usr/lib/gcc/" TARGET_TRIPLE "/" BASEVER "/liblto_plugin.so"));
212
      ADD_LINKER_ARG (resolve_envvars ("-plugin-opt=${QNX_HOST}/usr/lib/gcc/" TARGET_TRIPLE "/" BASEVER "/lto-wrapper"));
213
      ADD_LINKER_ARG (makefmtstr ("-plugin-opt=-fresolution=%s.res", "FIXME-UNKNOWN")); // FIXME: how to get the linker resolution file? Are the GCC and LLVM LTO ABI-compatible?
214
      if (ARGV_CONTAINS_ARGWITHEQUALVAL ("-flinker-output"))
215
         ADD_LINKER_ARG ("-plugin-opt=-linker-output-known");
216
      if (!ARGV_CONTAINS_SINGLEARG ("-nostdlib") && !ARGV_CONTAINS_SINGLEARG ("-nodefaultlibs"))
217
         for (arg_index = 0; arg_index < larg_count; arg_index++)
218
            ADD_LINKER_ARG (makefmtstr ("-plugin-opt=-pass-through=%s", largs[arg_index]));
219
   }*/
220
 
221
   //   "%{flto|flto=*:"        "%<fcompare-debug*"     "}     "
222
   if (ARGV_CONTAINS_SINGLEARG ("-flto") || ARGV_CONTAINS_ARGWITHEQUALVAL ("-flto"))
223
      for (arg_index = 1; arg_index < argc; arg_index++)
224
         if (strncmp (argv[arg_index], "-fcompare-debug", 15) == 0)
225
            argv[arg_index] = ""; // remove this arg
226
 
227
   if (ARGV_CONTAINS_SINGLEARG ("-flto"))       ADD_LINKER_ARG ("-flto");                    // "%{flto} "
228
   if (ARGV_CONTAINS_SINGLEARG ("-fno-lto"))    ADD_LINKER_ARG ("-fno-lto");                 // "%{fno-lto} "
229
   if (ARGV_CONTAINS_ARGWITHEQUALVAL ("-flto")) ADD_LINKER_ARG (makefmtstr ("-flto=%s", arg)); //       "%{flto=*} "
230
 
231
   //   "%{!static:"    "--eh-frame-hdr"                "} "
232
   if (!ARGV_CONTAINS_SINGLEARG ("-static")) ADD_LINKER_ARG ("--eh-frame-hdr");
233
 
234
#if IS_TARGET_INTEL
235
   //   "%{!m32:"       "-m elf_x86_64"                 "} "
236
   //   "%{m32:"        "-m i386nto"                    "}   "
237
   ADD_LINKER_ARG ("-m");
238
   if (ARGV_CONTAINS_SINGLEARG ("-m32"))
239
      ADD_LINKER_ARG ("i386nto");
240
   else
241
      ADD_LINKER_ARG ("elf_x86_64");
242
#endif // IS_TARGET_INTEL
243
 
244
   //   "%{h*} "
245
   for (arg_index = 1; arg_index < argc; arg_index++)
246
      if ((strcmp (argv[arg_index], "-h") == 0) && (arg_index + 1 < argc))
247
      {
248
         ADD_LINKER_ARG ("-h");
249
         ADD_LINKER_ARG (argv[++arg_index]);
250
      }
251
      else if ((strncmp (argv[arg_index], "-h", 2) == 0) && ((argv[arg_index])[2] != 0))
252
         ADD_LINKER_ARG (argv[arg_index]);
253
 
254
   //   "%{v:"  "-V"    "}   "
255
   if (ARGV_CONTAINS_SINGLEARG ("-v")) ADD_LINKER_ARG ("-V");
256
 
257
   //   "%{b}   "
258
   if (ARGV_CONTAINS_SINGLEARG ("-b")) ADD_LINKER_ARG ("-b");
259
 
260
#if !IS_TARGET_INTEL
261
   //   "%{Wl,*:"       "%*"                            "}  "
262
   for (arg_index = 1; arg_index < argc; arg_index++)
263
      if ((strcmp (argv[arg_index], "-Wl,") == 0) && (arg_index + 1 < argc))
264
         ADD_LINKER_ARG (argv[++arg_index]);
265
      else if ((strncmp (argv[arg_index], "-Wl,", 4) == 0) && ((argv[arg_index])[4] != 0))
266
         ADD_LINKER_ARG (argv[arg_index] + 4);
267
#endif // !IS_TARGET_INTEL
268
 
269
   //   "%{!r:"         "--build-id=md5"                "}   "
270
   if (!ARGV_CONTAINS_SINGLEARG ("-r")) ADD_LINKER_ARG ("--build-id=md5");
271
 
272
   //   "--warn-shared-textrel   "
273
   //   "-zrelro "
274
   //   "-znow   "
275
   ADD_LINKER_ARG ("--warn-shared-textrel");
276
   ADD_LINKER_ARG ("-zrelro");
277
   ADD_LINKER_ARG ("-znow");
278
 
279
#if IS_TARGET_INTEL
280
   //   "%{shared:"     "-G -dy -z text"                "}   "
281
   if (ARGV_CONTAINS_SINGLEARG ("-shared"))
282
   {
283
      ADD_LINKER_ARG ("-G");
284
      ADD_LINKER_ARG ("-dy");
285
      ADD_LINKER_ARG ("-z");
286
      ADD_LINKER_ARG ("text");
287
   }
288
 
289
   //   "%{symbolic:"   "-Bsymbolic -G -dy -z text"     "}   "
290
   if (ARGV_CONTAINS_SINGLEARG ("-symbolic"))
291
   {
292
      ADD_LINKER_ARG ("-Bsymbolic");
293
      ADD_LINKER_ARG ("-G");
294
      ADD_LINKER_ARG ("-dy");
295
      ADD_LINKER_ARG ("-z");
296
      ADD_LINKER_ARG ("text");
297
   }
298
 
299
   //   "%{G:"          "-G"                            "}   "
300
   if (ARGV_CONTAINS_SINGLEARG ("-G")) ADD_LINKER_ARG ("-G");
301
 
302
   //   "%{shared:"     "-shared"                       "}   "
303
   //   "%{!shared:     "
304
   //           "%{!static:       "
305
   //                   "%{rdynamic:"   "-export-dynamic"               "}       "
306
   //                   "%{m32:"
307
   //                           "%{!dynamic-linker:"    "-dynamic-linker /usr/lib/ldqnx.so.2"           "}"
308
   //                   "}       "
309
   //                   "%{!m32:"
310
   //                           "%{!dynamic-linker:"    "-dynamic-linker /usr/lib/ldqnx-64.so.2"        "}"
311
   //                   "}"
312
   //           "}     "
313
   //           "%{static:"     "-static"                                                               "}"
314
   //   "} "
315
   if (ARGV_CONTAINS_SINGLEARG ("-shared"))
316
      ADD_LINKER_ARG ("-shared");
317
   else if (ARGV_CONTAINS_SINGLEARG ("-static"))
318
      ADD_LINKER_ARG ("-static");
319
   else
320
   {
321
      if (ARGV_CONTAINS_SINGLEARG ("-rdynamic"))
322
         ADD_LINKER_ARG ("-export-dynamic");
323
      if (!ARGV_CONTAINS_SINGLEARG ("-dynamic-linker"))
324
      {
325
         ADD_LINKER_ARG ("-dynamic-linker");
326
         if (ARGV_CONTAINS_SINGLEARG ("-m32"))
327
            ADD_LINKER_ARG ("/usr/lib/ldqnx.so.2");
328
         else // not -m32
329
            ADD_LINKER_ARG ("/usr/lib/ldqnx-64.so.2");
330
      }
331
   }
332
 
333
#else // !IS_TARGET_INTEL
334
   //   "%{static:"     "-Bstatic"                      "}  "
335
   if (ARGV_CONTAINS_SINGLEARG ("-static")) ADD_LINKER_ARG ("-Bstatic");
336
 
337
   //   "%{shared}  "
338
   if (ARGV_CONTAINS_SINGLEARG ("-shared")) ADD_LINKER_ARG ("-shared");
339
 
340
   //   "%{symbolic:"   "-Bsymbolic"                    "}  "
341
   if (ARGV_CONTAINS_SINGLEARG ("-symbolic")) ADD_LINKER_ARG ("-Bsymbolic");
342
 
343
   //   "%{G:"          "-G"                            "} "
344
   if (ARGV_CONTAINS_SINGLEARG ("-G")) ADD_LINKER_ARG ("-G");
345
 
346
   //   "%{MAP:"        "-Map mapfile"                  "}  "
347
   if (ARGV_CONTAINS_SINGLEARG ("-MAP"))
348
   {
349
      ADD_LINKER_ARG ("-Map");
350
      ADD_LINKER_ARG ("mapfile");
351
   }
352
 
353
   //   "%{!shared:    "
354
   //           "%{!static:      "
355
   //                   "%{rdynamic:"   "-export-dynamic"               "}"
356
   //           "}    "
357
   //           "--dynamic-linker /usr/lib/ldqnx-64.so.2"
358
   //   "}  "
359
   if (!ARGV_CONTAINS_SINGLEARG ("-shared"))
360
   {
361
      if (!ARGV_CONTAINS_SINGLEARG ("-static") && ARGV_CONTAINS_SINGLEARG ("-rdynamic"))
362
         ADD_LINKER_ARG ("-export-dynamic");
363
      ADD_LINKER_ARG ("--dynamic-linker");
364
      ADD_LINKER_ARG ("/usr/lib/ldqnx-64.so.2");
365
   }
366
 
367
   //   "-X "
368
   ADD_LINKER_ARG ("-X");
369
 
370
   //   "%{EB:"         "-EB"                           "} "
371
   //   "%{!EB:"        "-EL"                           "} "
372
   if (ARGV_CONTAINS_SINGLEARG ("-EB"))
373
      ADD_LINKER_ARG ("-EB");
374
   else
375
      ADD_LINKER_ARG ("-EL");
376
 
377
   //   "%{EL:"         "-EL"                           "} "
378
   if (ARGV_CONTAINS_SINGLEARG ("-EL"))
379
      ADD_LINKER_ARG ("-EL");
380
#endif // IS_TARGET_INTEL
381
 
382
   //   "%{static|shared|r:;!no-pie:"   "-pie"                                                          "} "
383
   if (ARGV_CONTAINS_SINGLEARG ("-static") || !ARGV_CONTAINS_SINGLEARG ("-shared") || !ARGV_CONTAINS_SINGLEARG ("-r"))
384
      ; // nothing to do
385
   else if (!ARGV_CONTAINS_SINGLEARG ("-no-pie"))
386
      ADD_LINKER_ARG ("-pie");
387
 
388
   //   "%{fuse-ld=*:"                  "-fuse-ld=%*"                                                                   "} "
389
   for (arg_index = 1; arg_index < argc; arg_index++)
390
      if ((strncmp (argv[arg_index], "-fuse-ld=", 9) == 0) && ((argv[arg_index])[9] != 0))
391
         ADD_LINKER_ARG (argv[arg_index]);
392
 
393
   //   "%{gz|gz=zlib:"         "--compress-debug-sections=zlib"                        "} "
394
   //   "%{gz=none:"                    "--compress-debug-sections=none"                        "} "
395
   //   "%{gz=zlib-gnu:"                "--compress-debug-sections=zlib-gnu"    "} "
396
   if (ARGV_CONTAINS_SINGLEARG ("-gz") || ARGV_CONTAINS_SINGLEARG ("-gz=zlib"))
397
      ADD_LINKER_ARG ("--compress-debug-sections=zlib");
398
   if (ARGV_CONTAINS_SINGLEARG ("-gz=none"))
399
      ADD_LINKER_ARG ("--compress-debug-sections=none");
400
   if (ARGV_CONTAINS_SINGLEARG ("-gz=zlib-gnu"))
401
      ADD_LINKER_ARG ("--compress-debug-sections=zlib-gnu");
402
 
403
   //   "%X "
404
   // nothing to do (nothing was accumulated by %x previously)
405
 
406
   //   "%{o*} "
407
   for (arg_index = 1; arg_index < argc; arg_index++)
408
      if ((strcmp (argv[arg_index], "-o") == 0) && (arg_index + 1 < argc))
409
      {
410
         ADD_LINKER_ARG ("-o");
411
         ADD_LINKER_ARG (argv[++arg_index]);
412
      }
413
      else if ((strncmp (argv[arg_index], "-o", 2) == 0) && ((argv[arg_index])[2] != 0))
414
         ADD_LINKER_ARG (argv[arg_index]);
415
 
416
   //   "%{e*} "
417
   for (arg_index = 1; arg_index < argc; arg_index++)
418
      if ((strcmp (argv[arg_index], "-e") == 0) && (arg_index + 1 < argc))
419
      {
420
         ADD_LINKER_ARG ("-e");
421
         ADD_LINKER_ARG (argv[++arg_index]);
422
      }
423
      else if ((strncmp (argv[arg_index], "-e", 2) == 0) && ((argv[arg_index])[2] != 0))
424
         ADD_LINKER_ARG (argv[arg_index]);
425
 
426
   //   "%{N} "
427
   //   "%{n} "
428
   //   "%{r}    "
429
   //   "%{s} "
430
   //   "%{t} "
431
   if (ARGV_CONTAINS_SINGLEARG ("-N")) ADD_LINKER_ARG ("-N");
432
   if (ARGV_CONTAINS_SINGLEARG ("-n")) ADD_LINKER_ARG ("-n");
433
   if (ARGV_CONTAINS_SINGLEARG ("-r")) ADD_LINKER_ARG ("-r");
434
   if (ARGV_CONTAINS_SINGLEARG ("-s")) ADD_LINKER_ARG ("-s");
435
   if (ARGV_CONTAINS_SINGLEARG ("-t")) ADD_LINKER_ARG ("-t");
436
 
437
   //   "%{u*} "
438
   for (arg_index = 1; arg_index < argc; arg_index++)
439
      if ((strcmp (argv[arg_index], "-u") == 0) && (arg_index + 1 < argc))
440
      {
441
         ADD_LINKER_ARG ("-u");
442
         ADD_LINKER_ARG (argv[++arg_index]);
443
      }
444
      else if ((strncmp (argv[arg_index], "-u", 2) == 0) && ((argv[arg_index])[2] != 0))
445
         ADD_LINKER_ARG (argv[arg_index]);
446
 
447
   //   "%{z} "
448
   //   "%{Z} "
449
   if (ARGV_CONTAINS_SINGLEARG ("-z")) ADD_LINKER_ARG ("-z");
450
   if (ARGV_CONTAINS_SINGLEARG ("-Z")) ADD_LINKER_ARG ("-Z");
451
 
452
   //   "%{!nostdlib:"
453
   //           "%{!r:"
454
   //                   "%{!nostartfiles:"      "%S"    "}"
455
   //           "}"
456
   //   "}     "
457
   if (!ARGV_CONTAINS_SINGLEARG ("-nostdlib") && !ARGV_CONTAINS_SINGLEARG ("-r") && !ARGV_CONTAINS_SINGLEARG ("-nostartfiles"))
458
   {
459
#if IS_TARGET_INTEL // Intel variant
460
      //        "%{!shared:   "
461
      //                "%{!symbolic:     "
462
      //                        "%{pg:       "
463
      //                                "%{m32:"        " %${QNX_TARGET}/x86/lib/mcrt1.o%s"     "}       "
464
      //                                "%{!m32:"       " %${QNX_TARGET}/x86_64/lib/mcrt1.o%s"  "}"
465
      //                        "}     "
466
      //                        "%{!pg:       "
467
      //                                "%{p:        "
468
      //                                        "%{m32:"        " %${QNX_TARGET}/x86/lib/mcrt1.o%s"     "}        "
469
      //                                        "%{!m32:"       " %${QNX_TARGET}/x86_64/lib/mcrt1.o%s"  "}"
470
      //                                "}"
471
      //                        "}     "
472
      //                        "%{!p: "
473
      //                                "%{!pg:        "
474
      //                                        "%{m32:"        " %${QNX_TARGET}/x86/lib/crt1%{!no-pie:S}.o%s"  "}        "
475
      //                                        "%{!m32:"       " %${QNX_TARGET}/x86_64/lib/crt1.o%s"   "}"
476
      //                                "}"
477
      //                        "}     "
478
      //                "}"
479
      //        "}     "
480
      if (!ARGV_CONTAINS_SINGLEARG ("-shared") && !ARGV_CONTAINS_SINGLEARG ("-symbolic"))
481
      {
482
         if (ARGV_CONTAINS_SINGLEARG ("-pg") || ARGV_CONTAINS_SINGLEARG ("-p"))
483
         {
484
            if (ARGV_CONTAINS_SINGLEARG ("-m32"))
485
               ADD_LINKER_ARG (resolve_envvars ("${QNX_TARGET}/x86/lib/mcrt1.o"));
486
            else
487
               ADD_LINKER_ARG (resolve_envvars ("${QNX_TARGET}/x86_64/lib/mcrt1.o"));
488
         }
489
         else // neither "-pg" nor "-p"
490
         {
491
            if (ARGV_CONTAINS_SINGLEARG ("-m32"))
492
               ADD_LINKER_ARG (resolve_envvars (makefmtstr ("${QNX_TARGET}/x86/lib/crt1%s.o", ARGV_CONTAINS_SINGLEARG ("-no-pie") ? "" : "S")));
493
            else
494
               ADD_LINKER_ARG (resolve_envvars ("${QNX_TARGET}/x86_64/lib/crt1.o"));
495
         }
496
      }
497
 
498
      //        "%{m32:"        " %${QNX_TARGET}/x86/lib/crti.o%s"      "}     "
499
      //        "%{!m32:"       " %${QNX_TARGET}/x86_64/lib/crti.o%s"   "}     "
500
      if (ARGV_CONTAINS_SINGLEARG ("-m32"))
501
         ADD_LINKER_ARG (resolve_envvars ("${QNX_TARGET}/x86/lib/crti.o"));
502
      else
503
         ADD_LINKER_ARG (resolve_envvars ("${QNX_TARGET}/x86_64/lib/crti.o"));
504
#else // !IS_TARGET_INTEL
505
      //        "%{!shared: %${QNX_TARGET}/aarch64%{EB:be}%{!EB:le}/lib/%{pg:m}%{p:m}crt1.o } "
506
      if (ARGV_CONTAINS_SINGLEARG ("-shared"))
507
         if (ARGV_CONTAINS_SINGLEARG ("-EB"))
508
            ADD_LINKER_ARG (resolve_envvars (makefmtstr ("${QNX_TARGET}/aarch64be/lib/%scrt1.o", ARGV_CONTAINS_SINGLEARG ("-pg") || ARGV_CONTAINS_SINGLEARG ("-p") ? "m" : "")));
509
         else
510
            ADD_LINKER_ARG (resolve_envvars (makefmtstr ("${QNX_TARGET}/aarch64le/lib/%scrt1.o", ARGV_CONTAINS_SINGLEARG ("-pg") || ARGV_CONTAINS_SINGLEARG ("-p") ? "m" : "")));
511
 
512
      //        "%${QNX_TARGET}/aarch64%{EB:be}%{!EB:le}/lib/crti.o "
513
      if (ARGV_CONTAINS_SINGLEARG ("-EB"))
514
         ADD_LINKER_ARG (resolve_envvars ("${QNX_TARGET}/aarch64be/lib/crti.o"));
515
      else
516
         ADD_LINKER_ARG (resolve_envvars ("${QNX_TARGET}/aarch64le/lib/crti.o"));
517
#endif // IS_TARGET_INTEL
518
      //        "crtbegin.o%s "
519
      ADD_LINKER_ARG (resolve_envvars ("${QNX_HOST}/usr/bin/../lib/gcc/" TARGET_TRIPLE "/" BASEVER "/crtbegin.o"));
520
   }
521
 
522
   //   "%{static|no-pie|static-pie:"                                   "} "
523
   // nothing to do
524
 
525
   //   "%@{L*} "
526
   for (arg_index = 1; arg_index < argc; arg_index++)
527
      if ((strcmp (argv[arg_index], "-L") == 0) && (arg_index + 1 < argc))
528
      {
529
         ADD_LINKER_ARG ("-L");
530
         ADD_LINKER_ARG (argv[++arg_index]);
531
      }
532
      else if ((strncmp (argv[arg_index], "-L", 2) == 0) && ((argv[arg_index])[2] != 0))
533
         ADD_LINKER_ARG (argv[arg_index]);
534
 
535
   //   "%(mfwrap) "
536
   // nothing to do (looks like the libmudflap wrap spec has been officially removed from this version of GCC, except for uCLinux)
537
 
538
   //   "-L${QNX_HOST}/usr/bin/../lib/gcc/" TARGET_TRIPLE "/" BASEVER
539
   //   "-L${QNX_HOST}/usr/bin/../lib/gcc"
540
   ADD_LINKER_ARG (resolve_envvars ("-L${QNX_HOST}/usr/bin/../lib/gcc/" TARGET_TRIPLE "/" BASEVER));
541
   ADD_LINKER_ARG (resolve_envvars ("-L${QNX_HOST}/usr/bin/../lib/gcc"));
542
 
543
#if IS_TARGET_INTEL
544
   //   "%{m32:   " \
545
   //           "-L %${QNX_TARGET}/x86/lib/gcc/" BASEVER "   "
546
   //           "-L %${QNX_TARGET}/x86/lib   "
547
   //           "-L %${QNX_TARGET}/x86/usr/lib   "
548
   //           "-L %${QNX_TARGET}/x86/opt/lib   "
549
   //           "-rpath-link %${QNX_TARGET}/x86/lib/gcc/" BASEVER ":%${QNX_TARGET}/x86/lib:%${QNX_TARGET}/x86/usr/lib:%${QNX_TARGET}/x86/opt/lib"
550
   //   "}  "
551
   //   "%{!m32:   "
552
   //           "-L %${QNX_TARGET}/x86_64/lib/gcc/" BASEVER "   "
553
   //           "-L %${QNX_TARGET}/x86_64/lib   "
554
   //           "-L %${QNX_TARGET}/x86_64/usr/lib   "
555
   //           "-L %${QNX_TARGET}/x86_64/opt/lib   "
556
   //           "-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"
557
   //   "} "
558
   if (ARGV_CONTAINS_SINGLEARG ("-m32"))
559
   {
560
      ADD_LINKER_ARG (resolve_envvars ("-L${QNX_TARGET}/x86/lib/gcc/" BASEVER));
561
      ADD_LINKER_ARG (resolve_envvars ("-L${QNX_TARGET}/x86/lib"));
562
      ADD_LINKER_ARG (resolve_envvars ("-L${QNX_TARGET}/x86/usr/lib"));
563
      ADD_LINKER_ARG (resolve_envvars ("-L${QNX_TARGET}/x86/opt/lib"));
564
      ADD_LINKER_ARG ("-rpath-link");
565
      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"));
566
   }
567
   else
568
   {
569
      ADD_LINKER_ARG (resolve_envvars ("-L${QNX_TARGET}/x86_64/lib/gcc/" BASEVER));
570
      ADD_LINKER_ARG (resolve_envvars ("-L${QNX_TARGET}/x86_64/lib"));
571
      ADD_LINKER_ARG (resolve_envvars ("-L${QNX_TARGET}/x86_64/usr/lib"));
572
      ADD_LINKER_ARG (resolve_envvars ("-L${QNX_TARGET}/x86_64/opt/lib"));
573
      ADD_LINKER_ARG ("-rpath-link");
574
      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"));
575
   }
576
#else // !IS_TARGET_INTEL
577
   //   "-L %${QNX_TARGET}/aarch64%{EB:be}%{!EB:le}/lib/gcc/" BASEVER "  "
578
   //   "-L %${QNX_TARGET}/aarch64%{EB:be}%{!EB:le}/lib  "
579
   //   "-L %${QNX_TARGET}/aarch64%{EB:be}%{!EB:le}/usr/lib  "
580
   //   "-L %${QNX_TARGET}/aarch64%{EB:be}%{!EB:le}/opt/lib  "
581
   if (ARGV_CONTAINS_SINGLEARG ("-EB"))
582
   {
583
      ADD_LINKER_ARG (resolve_envvars ("-L${QNX_TARGET}/aarch64be/lib/gcc/" BASEVER));
584
      ADD_LINKER_ARG (resolve_envvars ("-L${QNX_TARGET}/aarch64be/lib"));
585
      ADD_LINKER_ARG (resolve_envvars ("-L${QNX_TARGET}/aarch64be/usr/lib"));
586
      ADD_LINKER_ARG (resolve_envvars ("-L${QNX_TARGET}/aarch64be/opt/lib"));
587
      ADD_LINKER_ARG ("-rpath-link");
588
      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"));
589
   }
590
   else
591
   {
592
      ADD_LINKER_ARG (resolve_envvars ("-L${QNX_TARGET}/aarch64le/lib/gcc/" BASEVER));
593
      ADD_LINKER_ARG (resolve_envvars ("-L${QNX_TARGET}/aarch64le/lib"));
594
      ADD_LINKER_ARG (resolve_envvars ("-L${QNX_TARGET}/aarch64le/usr/lib"));
595
      ADD_LINKER_ARG (resolve_envvars ("-L${QNX_TARGET}/aarch64le/opt/lib"));
596
      ADD_LINKER_ARG ("-rpath-link");
597
      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"));
598
   }
599
#endif // IS_TARGET_INTEL
600
 
601
   //   "%{!nostdlib:"
602
   //           "%{!r:"
603
   //                   "%{fvtable-verify=std:"         " -lvtv -u_vtable_map_vars_start -u_vtable_map_vars_end"        "}    "
604
   //                   "%{fvtable-verify=preinit:"     " -lvtv -u_vtable_map_vars_start -u_vtable_map_vars_end"        "}"
605
   //           "}"
606
   //   "} "
607
   if (!ARGV_CONTAINS_SINGLEARG ("-nostdlib") && !ARGV_CONTAINS_SINGLEARG ("-r"))
608
   {
609
      if (ARGV_CONTAINS_SINGLEARG ("-fvtable-verify=std") || ARGV_CONTAINS_SINGLEARG ("-fvtable-verify=preinit"))
610
      {
611
         ADD_LINKER_ARG ("-lvtv");
612
         ADD_LINKER_ARG ("-u_vtable_map_vars_start");
613
         ADD_LINKER_ARG ("-u_vtable_map_vars_end");
614
      }
615
 
616
      //        "%{!nodefaultlibs:"
617
      if (!ARGV_CONTAINS_SINGLEARG ("-nodefaultlibs"))
618
      {
619
#if IS_TARGET_INTEL
620
      //                "%{%:sanitize(address):"        "}     "
621
      //                "%{%:sanitize(hwaddress):"      "}     "
622
      //                "%{%:sanitize(thread):"         "}     "
623
      //                "%{%:sanitize(leak):"           "}"
624
      /* TODO */
625
#else // !IS_TARGET_INTEL
626
      //                "%{%:sanitize(address):"
627
      //                        "%{!shared:"            "libasan_preinit%O%s"                                                                           "} "
628
      //                        "%{static-libasan:"     "%{!shared:"    "-Bstatic --whole-archive -lasan --no-whole-archive -Bdynamic"          "}"     "}"
629
      //                        "%{!static-libasan:"    "-lasan"                                                                                        "}"
630
      //                "}     "
631
      //                "%{%:sanitize(hwaddress):"
632
      //                        "%{static-libhwasan:"   "%{!shared:"    "-Bstatic --whole-archive -lhwasan --no-whole-archive -Bdynamic"        "}"     "}"
633
      //                        "%{!static-libhwasan:"  "-lhwasan"                                                                                      "}"
634
      //                "}     "
635
      //                "%{%:sanitize(thread):"
636
      //                        "%{!shared:"            "libtsan_preinit%O%s"                                                                           "} "
637
      //                        "%{static-libtsan:"     "%{!shared:"    "-Bstatic --whole-archive -ltsan --no-whole-archive -Bdynamic"          "}"     "}"
638
      //                        "%{!static-libtsan:"    "-ltsan"                                                                                        "}"
639
      //                "}     "
640
      //                "%{%:sanitize(leak):"
641
      //                        "%{!shared:"            "liblsan_preinit%O%s"                                                                           "} "
642
      //                        "%{static-liblsan:"     "%{!shared:"    "-Bstatic --whole-archive -llsan --no-whole-archive -Bdynamic"          "}"     "}"
643
      //                        "%{!static-liblsan:"    "-llsan"                                                                                        "}"
644
      //                "}"
645
      /* TODO */
646
#endif // IS_TARGET_INTEL
647
      }
648
   }
649
 
650
   //   "%o      "
651
   for (arg_index = 0; arg_index < oarg_count; arg_index++)
652
      ADD_LINKER_ARG (oargs[arg_index]);
653
 
654
   //   "%{fopenacc|fopenmp|%:"
655
   //           "gt("
656
   //                   "%{ftree-parallelize-loops=*:"  "%*"    "}"
657
   //           " 1):   %:include(libgomp.spec)%(link_gomp)"
658
   //   "}    "
659
   /* FIXME: TODO */
660
 
661
   //   "%{fgnu-tm:"    "%:include(libitm.spec)%(link_itm)"     "}    "
662
   if (ARGV_CONTAINS_SINGLEARG ("-fgnu-tm"))
663
   {
664
      ADD_LINKER_ARG ("-litm");
665
      ADD_LINKER_ARG ("-lpthread"); // FIXME: possibly wrong
666
   }
667
 
668
   //   "%(mflib)  "
669
   // nothing to do (looks like the mflib spec has been officially removed from this version of GCC)
670
 
671
   //   "%{fsplit-stack: "                              "--wrap=pthread_create"         "}    "
672
   if (ARGV_CONTAINS_SINGLEARG ("-fsplit-stack"))
673
      ADD_LINKER_ARG ("--wrap=pthread_create");
674
 
675
   //   "%{fprofile-arcs|fprofile-generate*|coverage:"  "-lgcov"                        "} "
676
   if (ARGV_CONTAINS_SINGLEARG ("-fprofile-arcs") || ARGV_CONTAINS_ARGWITHVAL ("-fprofile-generate") || ARGV_CONTAINS_SINGLEARG ("-coverage"))
677
      ADD_LINKER_ARG ("-lgcov");
678
 
679
   if (!ARGV_CONTAINS_SINGLEARG ("-nostdlib") && !ARGV_CONTAINS_SINGLEARG ("-r"))
680
   {
681
      if (!ARGV_CONTAINS_SINGLEARG ("-nodefaultlibs"))
682
      {
683
#if IS_TARGET_INTEL
684
         //     "%{%:sanitize(address):"
685
         //             "%{static-libasan:"             "-Bstatic"                                              "} "
686
         //             "-lasan "
687
         //             "%{static-libasan:"             "-Bdynamic"                                             "} "
688
         //             "%{static-libasan|static:"      "%:include(libsanitizer.spec)%(link_libasan)"           "}    "
689
         //             "%{static:"                     "%ecannot specify -static with -fsanitize=address"      "}"
690
         //     "}    "
691
         //     "%{%:sanitize(hwaddress):"
692
         //             "%{static-libhwasan:"           "-Bstatic"                                              "} "
693
         //             "-lhwasan "
694
         //             "%{static-libhwasan:"           "-Bdynamic"                                             "} "
695
         //             "%{static-libhwasan|static:"    "%:include(libsanitizer.spec)%(link_libhwasan)"         "}      "
696
         //             "%{static:"                     "%ecannot specify -static with -fsanitize=hwaddress"    "}"
697
         //     "}    "
698
         //     "%{%:sanitize(thread):"
699
         //             "%{static-libtsan:"             "-Bstatic"                                              "} "
700
         //             "-ltsan "
701
         //             "%{static-libtsan:"             "-Bdynamic"                                             "} "
702
         //             "%{static-libtsan|static:"      "%:include(libsanitizer.spec)%(link_libtsan)"           "}    "
703
         //             "%{static:"                     "%ecannot specify -static with -fsanitize=thread"       "}"
704
         //     "}    "
705
         //     "%{%:sanitize(undefined):"
706
         //             "%{static-libubsan:"            "-Bstatic"                                              "} "
707
         //             "-lubsan "
708
         //             "%{static-libubsan:"            "-Bdynamic"                                             "} "
709
         //             "%{static-libubsan|static:"     "%:include(libsanitizer.spec)%(link_libubsan)"          "}"
710
         //     "}    "
711
         //     "%{%:sanitize(leak):"
712
         //             "%{static-liblsan:"             "-Bstatic"                                              "} "
713
         //             "-llsan "
714
         //             "%{static-liblsan:"             "-Bdynamic"                                             "} "
715
         //             "%{static-liblsan|static:"      "%:include(libsanitizer.spec)%(link_liblsan)"           "}"
716
         //     "}"
717
         /* FIXME: TODO */
718
#else // !IS_TARGET_INTEL
719
         //     "%{%:sanitize(address): "
720
         //             "%{static-libasan|static:"      "%:include(libsanitizer.spec)%(link_libasan)"           "}    "
721
         //             "%{static:"                     "%ecannot specify -static with -fsanitize=address"      "}"
722
         //     "}    "
723
         //     "%{%:sanitize(hwaddress): "
724
         //             "%{static-libhwasan|static:"    "%:include(libsanitizer.spec)%(link_libhwasan)"         "}      "
725
         //             "%{static:"                     "%ecannot specify -static with -fsanitize=hwaddress"    "}"
726
         //     "}    "
727
         //     "%{%:sanitize(thread): "
728
         //             "%{static-libtsan|static:"      "%:include(libsanitizer.spec)%(link_libtsan)"           "}    "
729
         //             "%{static:"                     "%ecannot specify -static with -fsanitize=thread"       "}"
730
         //     "}    "
731
         //     "%{%:sanitize(undefined):"
732
         //             "%{static-libubsan:"            "-Bstatic"                                              "} "
733
         //             "-lubsan "
734
         //             "%{static-libubsan:"            "-Bdynamic"                                             "} "
735
         //             "%{static-libubsan|static:"     "%:include(libsanitizer.spec)%(link_libubsan)"          "}"
736
         //     "}    "
737
         //     "%{%:sanitize(leak): "
738
         //             "%{static-liblsan|static:"      "%:include(libsanitizer.spec)%(link_liblsan)"           "}"
739
         //     "}"
740
         /* FIXME: TODO */
741
#endif // IS_TARGET_INTEL
742
 
743
         // "%{fstack-protector|fstack-protector-all|fstack-protector-strong|fstack-protector-explicit:}"
744
         // nothing to do
745
 
746
         // "%(link_gcc_c_sequence)"
747
#if IS_TARGET_INTEL
748
         //     "%{static|static-libgcc:"                       "-lgcc -lgcc_eh"        "}"
749
         if (ARGV_CONTAINS_SINGLEARG ("-static") || ARGV_CONTAINS_SINGLEARG ("-static-libgcc"))
750
         {
751
            ADD_LINKER_ARG ("-lgcc");
752
            ADD_LINKER_ARG ("-lgcc_eh");
753
         }
754
 
755
         //     "%{!static:"
756
         //             "%{!static-libgcc:"
757
         //                     "%{!shared:"
758
         //                             "%{!shared-libgcc:"     "-lgcc -lgcc_eh"        "}"
759
         //                             "%{shared-libgcc:"      "-lgcc_s -lgcc"         "}"
760
         //                     "}"
761
         //                     "%{shared:"
762
         //                             "%{shared-libgcc:"      "-lgcc_s"               "}"
763
         //                             "%{!shared-libgcc:"     "-lgcc"                 "}"
764
         //                     "}"
765
         //             "}"
766
         //     "}"
767
         if (!ARGV_CONTAINS_SINGLEARG ("-static") && !ARGV_CONTAINS_SINGLEARG ("-static-libgcc"))
768
         {
769
            if (!ARGV_CONTAINS_SINGLEARG ("-shared"))
770
            {
771
               if (ARGV_CONTAINS_SINGLEARG ("-shared-libgcc"))
772
               {
773
                  ADD_LINKER_ARG ("-lgcc_s");
774
                  ADD_LINKER_ARG ("-lgcc");
775
               }
776
               else
777
               {
778
                  ADD_LINKER_ARG ("-lgcc");
779
                  ADD_LINKER_ARG ("-lgcc_eh");
780
               }
781
            }
782
            else if (ARGV_CONTAINS_SINGLEARG ("-shared-libgcc"))
783
               ADD_LINKER_ARG ("-lgcc_s");
784
            else
785
               ADD_LINKER_ARG ("-lgcc");
786
         }
787
 
788
         //     "%{!nolibc:"
789
         if (!ARGV_CONTAINS_SINGLEARG ("-nolibc"))
790
         {
791
            //  "%{!symbolic:"
792
            //          " -lc"
793
            //          " %{shared:"    "-lcS"  "}"
794
            //          " %{!no-pie:"   "-lcS"  "}"
795
            //          " %{no-pie:"    "-lc"   "}"
796
            //  "} "
797
            if (!ARGV_CONTAINS_SINGLEARG ("-symbolic"))
798
            {
799
               ADD_LINKER_ARG ("-lc");
800
               if (ARGV_CONTAINS_SINGLEARG ("-shared") || !ARGV_CONTAINS_SINGLEARG ("-no-pie"))
801
                  ADD_LINKER_ARG ("-lcS");
802
            }
803
 
804
            //  "%{static|static-libgcc:"                       "-lgcc -lgcc_eh"        "}"
805
            if (ARGV_CONTAINS_SINGLEARG ("-static") || ARGV_CONTAINS_SINGLEARG ("-static-libgcc"))
806
            {
807
               ADD_LINKER_ARG ("-lgcc");
808
               ADD_LINKER_ARG ("-lgcc_eh");
809
            }
810
 
811
            //  "%{!static:"
812
            //          "%{!static-libgcc:"
813
            //                  "%{!shared:"
814
            //                          "%{!shared-libgcc:"     "-lgcc -lgcc_eh"        "}"
815
            //                          "%{shared-libgcc:"      "-lgcc_s -lgcc"         "}"
816
            //                  "}"
817
            //                  "%{shared:"
818
            //                          "%{shared-libgcc:"      "-lgcc_s"               "}"
819
            //                          "%{!shared-libgcc:"     "-lgcc"                 "}"
820
            //                  "}"
821
            //          "}"
822
            //  "
823
            if (!ARGV_CONTAINS_SINGLEARG ("-static") && !ARGV_CONTAINS_SINGLEARG ("-static-libgcc"))
824
            {
825
               if (!ARGV_CONTAINS_SINGLEARG ("-shared"))
826
               {
827
                  if (ARGV_CONTAINS_SINGLEARG ("-shared-libgcc"))
828
                  {
829
                     ADD_LINKER_ARG ("-lgcc_s");
830
                     ADD_LINKER_ARG ("-lgcc");
831
                  }
832
                  else
833
                  {
834
                     ADD_LINKER_ARG ("-lgcc");
835
                     ADD_LINKER_ARG ("-lgcc_eh");
836
                  }
837
               }
838
               else if (ARGV_CONTAINS_SINGLEARG ("-shared-libgcc"))
839
                  ADD_LINKER_ARG ("-lgcc_s");
840
               else
841
                  ADD_LINKER_ARG ("-lgcc");
842
            }
843
         }
844
#else // !IS_TARGET_INTEL
845
         //     "%{static|static-pie:"  "--start-group" "} "
846
         if (ARGV_CONTAINS_SINGLEARG ("-static") || ARGV_CONTAINS_SINGLEARG ("-static-pie"))
847
            ADD_LINKER_ARG ("--start-group");
848
 
849
         //     "%{static|static-libgcc|static-pie:"            "-lgcc -lgcc_eh"        "}"
850
         if (ARGV_CONTAINS_SINGLEARG ("-static") || ARGV_CONTAINS_SINGLEARG ("-static-libgcc") || ARGV_CONTAINS_SINGLEARG ("-static-pie"))
851
         {
852
            ADD_LINKER_ARG ("-lgcc");
853
            ADD_LINKER_ARG ("-lgcc_eh");
854
         }
855
 
856
         //     "%{!static:"
857
         //             "%{!static-libgcc:"
858
         //                     "%{!static-pie:"
859
         //                             "%{!shared-libgcc:"     "-lgcc --push-state --as-needed -lgcc_s --pop-state"    "}"
860
         //                             "%{shared-libgcc:"      "-lgcc_s%{!shared: -lgcc}"                              "}"
861
         //                     "}"
862
         //             "}"
863
         //     "}"
864
         if (!ARGV_CONTAINS_SINGLEARG ("-static") && !ARGV_CONTAINS_SINGLEARG ("-static-libgcc") && !ARGV_CONTAINS_SINGLEARG ("-static-pie"))
865
         {
866
            if (!ARGV_CONTAINS_SINGLEARG ("-shared-libgcc"))
867
            {
868
               ADD_LINKER_ARG ("-lgcc");
869
               ADD_LINKER_ARG ("--push-state");
870
               ADD_LINKER_ARG ("--as-needed");
871
               ADD_LINKER_ARG ("-lgcc_s");
872
               ADD_LINKER_ARG ("--pop-state");
873
            }
874
            else
875
            {
876
               ADD_LINKER_ARG ("-lgcc_s");
877
               if (!ARGV_CONTAINS_SINGLEARG ("-shared"))
878
                  ADD_LINKER_ARG ("-lgcc");
879
            }
880
         }
881
 
882
         //     "%{!nolibc:"
883
         //             "%{!symbolic:"
884
         //                     " -lc"
885
         //                     " %{shared:"    "-lcS"  "}"
886
         //                     " %{!no-pie:"   "-lcS"  "}"
887
         //                     " %{no-pie:"    "-lc"   "}"
888
         //             "} "
889
         // "}    "
890
         if (!ARGV_CONTAINS_SINGLEARG ("-nolibc") && !ARGV_CONTAINS_SINGLEARG ("-symbolic"))
891
         {
892
            ADD_LINKER_ARG ("-lc");
893
            if (ARGV_CONTAINS_SINGLEARG ("-shared") || !ARGV_CONTAINS_SINGLEARG ("-no-pie"))
894
               ADD_LINKER_ARG ("-lcS");
895
         }
896
 
897
         //     "%{static|static-pie:"  "--end-group"   "}"
898
         if (ARGV_CONTAINS_SINGLEARG ("-static") || ARGV_CONTAINS_SINGLEARG ("-static-pie"))
899
            ADD_LINKER_ARG ("--end-group");
900
         //     "%{!static:"
901
         //             "%{!static-pie:"
902
         else
903
         {
904
            //  "%{static|static-libgcc|static-pie:"            "-lgcc -lgcc_eh"        "}"
905
            if (ARGV_CONTAINS_SINGLEARG ("-static-libgcc"))
906
            {
907
               ADD_LINKER_ARG ("-lgcc");
908
               ADD_LINKER_ARG ("-lgcc_eh");
909
            }
910
 
911
            //  "%{!static:"
912
            //          "%{!static-libgcc:"
913
            //                  "%{!static-pie:"
914
            //                          "%{!shared-libgcc:"     "-lgcc --push-state --as-needed -lgcc_s --pop-state"    "}"
915
            //                          "%{shared-libgcc:"      "-lgcc_s%{!shared: -lgcc}"                              "}"
916
            //                  "}"
917
            //          "}"
918
            //  "}"
919
            if (!ARGV_CONTAINS_SINGLEARG ("-static") && !ARGV_CONTAINS_SINGLEARG ("-static-libgcc") && !ARGV_CONTAINS_SINGLEARG ("-static-pie"))
920
            {
921
               if (!ARGV_CONTAINS_SINGLEARG ("-shared-libgcc"))
922
               {
923
                  ADD_LINKER_ARG ("-lgcc");
924
                  ADD_LINKER_ARG ("--push-state");
925
                  ADD_LINKER_ARG ("--as-needed");
926
                  ADD_LINKER_ARG ("-lgcc_s");
927
                  ADD_LINKER_ARG ("--pop-state");
928
               }
929
               else
930
               {
931
                  ADD_LINKER_ARG ("-lgcc_s");
932
                  if (!ARGV_CONTAINS_SINGLEARG ("-shared"))
933
                     ADD_LINKER_ARG ("-lgcc");
934
               }
935
            }
936
         }
937
#endif // IS_TARGET_INTEL
938
 
939
         was_cpluspluslib_included = false;
940
         for (arg_index = 0; arg_index < larg_count; arg_index++)
941
         {
942
            ADD_LINKER_ARG (largs[arg_index]);
943
            if (strstr (largs[arg_index], "c++") != NULL)
944
               was_cpluspluslib_included = true;
945
         }
946
         if (!was_cpluspluslib_included)
947
         {
948
            if (strstr (argv[0], "g++") != NULL)
949
               ADD_LINKER_ARG ("-lc++"); // if we were invoked as g++ to link stuff it probably means we need a C++ library
950
            else
951
            {
952
               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
953
               for (arg_index = 0; !requires_libcplusplus && (arg_index < oarg_count); arg_index++)
954
               {
955
                  fp = fopen (oargs[arg_index], "rb");
956
                  if (fp == NULL) continue; // unopenable object file, should error out perhaps?
957
                  while (!requires_libcplusplus && ((read_count = fread (filebuf, 1, sizeof (filebuf), fp)) > 0))
958
                     for (byte_index = 0; !requires_libcplusplus && (byte_index < read_count - 8); byte_index++)
959
                        if (memcmp (&filebuf[byte_index], ".text._Z", 8) == 0)
960
                           requires_libcplusplus = true;
961
                  fclose (fp);
962
               }
963
               if (requires_libcplusplus)
964
                  ADD_LINKER_ARG ("-lc++"); // we did it the hard way
965
            }
966
         }
967
      }
968
 
969
      //        "%{!nostartfiles:"      "%E"                                    "}"
970
      if (!ARGV_CONTAINS_SINGLEARG ("-nostartfiles"))
971
      {
972
         ADD_LINKER_ARG (resolve_envvars ("${QNX_HOST}/usr/bin/../lib/gcc/" TARGET_TRIPLE "/" BASEVER "/crtend.o"));
973
#if IS_TARGET_INTEL
974
         if (ARGV_CONTAINS_SINGLEARG ("-m32"))
975
            ADD_LINKER_ARG (resolve_envvars ("${QNX_TARGET}/x86/lib/crtn.o"));
976
         else
977
            ADD_LINKER_ARG (resolve_envvars ("${QNX_TARGET}/x86_64/lib/crtn.o"));
978
#else // !IS_TARGET_INTEL
979
         if (ARGV_CONTAINS_SINGLEARG ("-EB"))
980
            ADD_LINKER_ARG (resolve_envvars ("${QNX_TARGET}/aarch64be/lib/crtn.o"));
981
         else
982
            ADD_LINKER_ARG (resolve_envvars ("${QNX_TARGET}/aarch64le/lib/crtn.o"));
983
#endif // IS_TARGET_INTEL
984
      }
985
   }
986
 
987
   //   "%{T*}"
988
   for (arg_index = 1; arg_index < argc; arg_index++)
989
      if ((strcmp (argv[arg_index], "-T") == 0) && (arg_index + 1 < argc))
990
      {
991
         ADD_LINKER_ARG ("-T");
992
         ADD_LINKER_ARG (argv[++arg_index]);
993
      }
994
      else if ((strncmp (argv[arg_index], "-T", 2) == 0) && ((argv[arg_index])[2] != 0))
995
         ADD_LINKER_ARG (argv[arg_index]);
996
 
997
   // 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
998
   ADD_LINKER_ARG ("-z");
999
   ADD_LINKER_ARG ("noexecstack");
1000
 
1001
   if (ARGV_CONTAINS_SINGLEARG ("-v"))
1002
   {
1003
      fputs ("LINKER DRIVER: CONSTRUCTED COMMAND LINE BEGIN\n", stderr);
1004
      for (arg_index = 0; arg_index < linker_argc; arg_index++)
1005
         fprintf (stderr, "%s%s%s\n", (arg_index > 0 ? "\t" : ""), linker_argv[arg_index], ((size_t) arg_index + 1 < linker_argc ? " \\" : ""));
1006
      fputs ("LINKER DRIVER: CONSTRUCTED COMMAND LINE END\n", stderr);
1007
   }
1008
 
1009
   execvpe (LINKER, linker_argv, envp);
1010
   return (1); // unreahable code
1011
}