Subversion Repositories QNX 8.QNX8 linker driver

Rev

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

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