Subversion Repositories QNX 8.QNX8 linker driver

Rev

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