Subversion Repositories QNX 8.QNX8 linker driver

Rev

Rev 12 | Details | Compare with Previous | Last modification | View Log | RSS feed

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