Subversion Repositories QNX 8.QNX8 linker driver

Rev

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