]> git.ipfire.org Git - thirdparty/gcc.git/blob - libcc1/libcc1.cc
libcc1: use "override"
[thirdparty/gcc.git] / libcc1 / libcc1.cc
1 /* The library used by gdb.
2 Copyright (C) 2014-2021 Free Software Foundation, Inc.
3
4 This file is part of GCC.
5
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 3, or (at your option) any later
9 version.
10
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3. If not see
18 <http://www.gnu.org/licenses/>. */
19
20 #include <cc1plugin-config.h>
21 #include <vector>
22 #include <string>
23 #include <sys/socket.h>
24 #include <sys/types.h>
25 #include <unistd.h>
26 #include <sys/wait.h>
27 #include <stdio.h>
28 #include <errno.h>
29 #include <sys/stat.h>
30 #include <stdlib.h>
31 #include <sstream>
32 #include "marshall.hh"
33 #include "rpc.hh"
34 #include "connection.hh"
35 #include "names.hh"
36 #include "callbacks.hh"
37 #include "libiberty.h"
38 #include "xregex.h"
39 #include "findcomp.hh"
40 #include "compiler-name.hh"
41 #include "intl.h"
42 #include "gcc-c-interface.h"
43
44 struct libcc1;
45
46 class libcc1_connection;
47
48 // The C compiler context that we hand back to our caller.
49 struct libcc1 : public gcc_c_context
50 {
51 libcc1 (const gcc_base_vtable *, const gcc_c_fe_vtable *);
52 ~libcc1 ();
53
54 // A convenience function to print something.
55 void print (const char *str)
56 {
57 this->print_function (this->print_datum, str);
58 }
59
60 libcc1_connection *connection;
61
62 gcc_c_oracle_function *binding_oracle;
63 gcc_c_symbol_address_function *address_oracle;
64 void *oracle_datum;
65
66 void (*print_function) (void *datum, const char *message);
67 void *print_datum;
68
69 std::vector<std::string> args;
70 std::string source_file;
71
72 /* Non-zero as an equivalent to gcc driver option "-v". */
73 bool verbose;
74
75 /* Compiler to set by set_triplet_regexp or set_driver_filename. */
76 class compiler
77 {
78 protected:
79 libcc1 *self_;
80 public:
81 compiler (libcc1 *self) : self_ (self)
82 {
83 }
84 virtual char *find (std::string &compiler) const;
85 virtual ~compiler ()
86 {
87 }
88 } *compilerp;
89
90 /* Compiler to set by set_triplet_regexp. */
91 class compiler_triplet_regexp : public compiler
92 {
93 private:
94 std::string triplet_regexp_;
95 public:
96 char *find (std::string &compiler) const override;
97 compiler_triplet_regexp (libcc1 *self, std::string triplet_regexp)
98 : compiler (self), triplet_regexp_ (triplet_regexp)
99 {
100 }
101 virtual ~compiler_triplet_regexp ()
102 {
103 }
104 };
105
106 /* Compiler to set by set_driver_filename. */
107 class compiler_driver_filename : public compiler
108 {
109 private:
110 std::string driver_filename_;
111 public:
112 char *find (std::string &compiler) const override;
113 compiler_driver_filename (libcc1 *self, std::string driver_filename)
114 : compiler (self), driver_filename_ (driver_filename)
115 {
116 }
117 virtual ~compiler_driver_filename ()
118 {
119 }
120 };
121 };
122
123 // A local subclass of connection that holds a back-pointer to the
124 // gcc_c_context object that we provide to our caller.
125 class libcc1_connection : public cc1_plugin::connection
126 {
127 public:
128
129 libcc1_connection (int fd, int aux_fd, libcc1 *b)
130 : connection (fd, aux_fd),
131 back_ptr (b)
132 {
133 }
134
135 void print (const char *buf) override
136 {
137 back_ptr->print (buf);
138 }
139
140 libcc1 *back_ptr;
141 };
142
143 libcc1::libcc1 (const gcc_base_vtable *v,
144 const gcc_c_fe_vtable *cv)
145 : connection (NULL),
146 binding_oracle (NULL),
147 address_oracle (NULL),
148 oracle_datum (NULL),
149 print_function (NULL),
150 print_datum (NULL),
151 args (),
152 source_file (),
153 verbose (false),
154 compilerp (new libcc1::compiler (this))
155 {
156 base.ops = v;
157 c_ops = cv;
158 }
159
160 libcc1::~libcc1 ()
161 {
162 delete connection;
163 delete compilerp;
164 }
165
166 \f
167
168 // Enclose these functions in an anonymous namespace because they
169 // shouldn't be exported, but they can't be static because they're
170 // used as template arguments.
171 namespace {
172 // This is a wrapper function that is called by the RPC system and
173 // that then forwards the call to the library user. Note that the
174 // return value is not used; the type cannot be 'void' due to
175 // limitations in our simple RPC.
176 int
177 c_call_binding_oracle (cc1_plugin::connection *conn,
178 enum gcc_c_oracle_request request,
179 const char *identifier)
180 {
181 libcc1 *self = ((libcc1_connection *) conn)->back_ptr;
182
183 self->binding_oracle (self->oracle_datum, self, request, identifier);
184 return 1;
185 }
186
187 // This is a wrapper function that is called by the RPC system and
188 // that then forwards the call to the library user.
189 gcc_address
190 c_call_symbol_address (cc1_plugin::connection *conn, const char *identifier)
191 {
192 libcc1 *self = ((libcc1_connection *) conn)->back_ptr;
193
194 return self->address_oracle (self->oracle_datum, self, identifier);
195 }
196 } /* anonymous namespace */
197
198 \f
199
200 static void
201 set_callbacks (struct gcc_c_context *s,
202 gcc_c_oracle_function *binding_oracle,
203 gcc_c_symbol_address_function *address_oracle,
204 void *datum)
205 {
206 libcc1 *self = (libcc1 *) s;
207
208 self->binding_oracle = binding_oracle;
209 self->address_oracle = address_oracle;
210 self->oracle_datum = datum;
211 }
212
213 // Instances of these rpc<> template functions are installed into the
214 // "c_vtable". These functions are parameterized by type and method
215 // name and forward the call via the connection.
216
217 template<typename R, const char *&NAME>
218 R rpc (struct gcc_c_context *s)
219 {
220 libcc1 *self = (libcc1 *) s;
221 R result;
222
223 if (!cc1_plugin::call (self->connection, NAME, &result))
224 return 0;
225 return result;
226 }
227
228 template<typename R, const char *&NAME, typename A>
229 R rpc (struct gcc_c_context *s, A arg)
230 {
231 libcc1 *self = (libcc1 *) s;
232 R result;
233
234 if (!cc1_plugin::call (self->connection, NAME, &result, arg))
235 return 0;
236 return result;
237 }
238
239 template<typename R, const char *&NAME, typename A1, typename A2>
240 R rpc (struct gcc_c_context *s, A1 arg1, A2 arg2)
241 {
242 libcc1 *self = (libcc1 *) s;
243 R result;
244
245 if (!cc1_plugin::call (self->connection, NAME, &result, arg1, arg2))
246 return 0;
247 return result;
248 }
249
250 template<typename R, const char *&NAME, typename A1, typename A2, typename A3>
251 R rpc (struct gcc_c_context *s, A1 arg1, A2 arg2, A3 arg3)
252 {
253 libcc1 *self = (libcc1 *) s;
254 R result;
255
256 if (!cc1_plugin::call (self->connection, NAME, &result, arg1, arg2, arg3))
257 return 0;
258 return result;
259 }
260
261 template<typename R, const char *&NAME, typename A1, typename A2, typename A3,
262 typename A4>
263 R rpc (struct gcc_c_context *s, A1 arg1, A2 arg2, A3 arg3, A4 arg4)
264 {
265 libcc1 *self = (libcc1 *) s;
266 R result;
267
268 if (!cc1_plugin::call (self->connection, NAME, &result, arg1, arg2, arg3,
269 arg4))
270 return 0;
271 return result;
272 }
273
274 template<typename R, const char *&NAME, typename A1, typename A2, typename A3,
275 typename A4, typename A5>
276 R rpc (struct gcc_c_context *s, A1 arg1, A2 arg2, A3 arg3, A4 arg4, A5 arg5)
277 {
278 libcc1 *self = (libcc1 *) s;
279 R result;
280
281 if (!cc1_plugin::call (self->connection, NAME, &result, arg1, arg2, arg3,
282 arg4, arg5))
283 return 0;
284 return result;
285 }
286
287 template<typename R, const char *&NAME, typename A1, typename A2, typename A3,
288 typename A4, typename A5, typename A6, typename A7>
289 R rpc (struct gcc_c_context *s, A1 arg1, A2 arg2, A3 arg3, A4 arg4, A5 arg5,
290 A6 arg6, A7 arg7)
291 {
292 libcc1 *self = (libcc1 *) s;
293 R result;
294
295 if (!cc1_plugin::call (self->connection, NAME, &result, arg1, arg2, arg3,
296 arg4, arg5, arg6, arg7))
297 return 0;
298 return result;
299 }
300
301 static const struct gcc_c_fe_vtable c_vtable =
302 {
303 GCC_C_FE_VERSION_0,
304 set_callbacks,
305
306 #define GCC_METHOD0(R, N) \
307 rpc<R, cc1_plugin::c::N>,
308 #define GCC_METHOD1(R, N, A) \
309 rpc<R, cc1_plugin::c::N, A>,
310 #define GCC_METHOD2(R, N, A, B) \
311 rpc<R, cc1_plugin::c::N, A, B>,
312 #define GCC_METHOD3(R, N, A, B, C) \
313 rpc<R, cc1_plugin::c::N, A, B, C>,
314 #define GCC_METHOD4(R, N, A, B, C, D) \
315 rpc<R, cc1_plugin::c::N, A, B, C, D>,
316 #define GCC_METHOD5(R, N, A, B, C, D, E) \
317 rpc<R, cc1_plugin::c::N, A, B, C, D, E>,
318 #define GCC_METHOD7(R, N, A, B, C, D, E, F, G) \
319 rpc<R, cc1_plugin::c::N, A, B, C, D, E, F, G>,
320
321 #include "gcc-c-fe.def"
322
323 #undef GCC_METHOD0
324 #undef GCC_METHOD1
325 #undef GCC_METHOD2
326 #undef GCC_METHOD3
327 #undef GCC_METHOD4
328 #undef GCC_METHOD5
329 #undef GCC_METHOD7
330 };
331
332 \f
333
334 // Construct an appropriate regexp to match the compiler name.
335 static std::string
336 make_regexp (const char *triplet_regexp, const char *compiler)
337 {
338 std::stringstream buf;
339
340 buf << "^" << triplet_regexp << "-";
341
342 // Quote the compiler name in case it has something funny in it.
343 for (const char *p = compiler; *p; ++p)
344 {
345 switch (*p)
346 {
347 case '.':
348 case '^':
349 case '$':
350 case '*':
351 case '+':
352 case '?':
353 case '(':
354 case ')':
355 case '[':
356 case '{':
357 case '\\':
358 case '|':
359 buf << '\\';
360 break;
361 }
362 buf << *p;
363 }
364 buf << "$";
365
366 return buf.str ();
367 }
368
369 static void
370 libcc1_set_verbose (struct gcc_base_context *s, int /* bool */ verbose)
371 {
372 libcc1 *self = (libcc1 *) s;
373
374 self->verbose = verbose != 0;
375 }
376
377 char *
378 libcc1::compiler::find (std::string &compiler ATTRIBUTE_UNUSED) const
379 {
380 return xstrdup (_("Compiler has not been specified"));
381 }
382
383 char *
384 libcc1::compiler_triplet_regexp::find (std::string &compiler) const
385 {
386 std::string rx = make_regexp (triplet_regexp_.c_str (), C_COMPILER_NAME);
387 if (self_->verbose)
388 fprintf (stderr, _("searching for compiler matching regex %s\n"),
389 rx.c_str());
390 regex_t triplet;
391 int code = regcomp (&triplet, rx.c_str (), REG_EXTENDED | REG_NOSUB);
392 if (code != 0)
393 {
394 size_t len = regerror (code, &triplet, NULL, 0);
395 char err[len];
396
397 regerror (code, &triplet, err, len);
398
399 return concat ("Could not compile regexp \"",
400 rx.c_str (),
401 "\": ",
402 err,
403 (char *) NULL);
404 }
405
406 if (!find_compiler (triplet, &compiler))
407 {
408 regfree (&triplet);
409 return concat ("Could not find a compiler matching \"",
410 rx.c_str (),
411 "\"",
412 (char *) NULL);
413 }
414 regfree (&triplet);
415 if (self_->verbose)
416 fprintf (stderr, _("found compiler %s\n"), compiler.c_str());
417 return NULL;
418 }
419
420 char *
421 libcc1::compiler_driver_filename::find (std::string &compiler) const
422 {
423 // Simulate fnotice by fprintf.
424 if (self_->verbose)
425 fprintf (stderr, _("using explicit compiler filename %s\n"),
426 driver_filename_.c_str());
427 compiler = driver_filename_;
428 return NULL;
429 }
430
431 static char *
432 libcc1_set_arguments (struct gcc_base_context *s,
433 int argc, char **argv)
434 {
435 libcc1 *self = (libcc1 *) s;
436
437 std::string compiler;
438 char *errmsg = self->compilerp->find (compiler);
439 if (errmsg != NULL)
440 return errmsg;
441
442 self->args.push_back (compiler);
443
444 for (int i = 0; i < argc; ++i)
445 self->args.push_back (argv[i]);
446
447 return NULL;
448 }
449
450 static char *
451 libcc1_set_triplet_regexp (struct gcc_base_context *s,
452 const char *triplet_regexp)
453 {
454 libcc1 *self = (libcc1 *) s;
455
456 delete self->compilerp;
457 self->compilerp = new libcc1::compiler_triplet_regexp (self, triplet_regexp);
458 return NULL;
459 }
460
461 static char *
462 libcc1_set_driver_filename (struct gcc_base_context *s,
463 const char *driver_filename)
464 {
465 libcc1 *self = (libcc1 *) s;
466
467 delete self->compilerp;
468 self->compilerp = new libcc1::compiler_driver_filename (self,
469 driver_filename);
470 return NULL;
471 }
472
473 static char *
474 libcc1_set_arguments_v0 (struct gcc_base_context *s,
475 const char *triplet_regexp,
476 int argc, char **argv)
477 {
478 char *errmsg = libcc1_set_triplet_regexp (s, triplet_regexp);
479 if (errmsg != NULL)
480 return errmsg;
481
482 return libcc1_set_arguments (s, argc, argv);
483 }
484
485 static void
486 libcc1_set_source_file (struct gcc_base_context *s,
487 const char *file)
488 {
489 libcc1 *self = (libcc1 *) s;
490
491 self->source_file = file;
492 }
493
494 static void
495 libcc1_set_print_callback (struct gcc_base_context *s,
496 void (*print_function) (void *datum,
497 const char *message),
498 void *datum)
499 {
500 libcc1 *self = (libcc1 *) s;
501
502 self->print_function = print_function;
503 self->print_datum = datum;
504 }
505
506 static int
507 fork_exec (libcc1 *self, char **argv, int spair_fds[2], int stderr_fds[2])
508 {
509 pid_t child_pid = fork ();
510
511 if (child_pid == -1)
512 {
513 close (spair_fds[0]);
514 close (spair_fds[1]);
515 close (stderr_fds[0]);
516 close (stderr_fds[1]);
517 return 0;
518 }
519
520 if (child_pid == 0)
521 {
522 // Child.
523 dup2 (stderr_fds[1], 1);
524 dup2 (stderr_fds[1], 2);
525 close (stderr_fds[0]);
526 close (stderr_fds[1]);
527 close (spair_fds[0]);
528
529 execvp (argv[0], argv);
530 _exit (127);
531 }
532 else
533 {
534 // Parent.
535 close (spair_fds[1]);
536 close (stderr_fds[1]);
537
538 cc1_plugin::status result = cc1_plugin::FAIL;
539 if (self->connection->send ('H')
540 && ::cc1_plugin::marshall (self->connection, GCC_C_FE_VERSION_1))
541 result = self->connection->wait_for_query ();
542
543 close (spair_fds[0]);
544 close (stderr_fds[0]);
545
546 while (true)
547 {
548 int status;
549
550 if (waitpid (child_pid, &status, 0) == -1)
551 {
552 if (errno != EINTR)
553 return 0;
554 }
555
556 if (!WIFEXITED (status) || WEXITSTATUS (status) != 0)
557 return 0;
558 break;
559 }
560
561 if (!result)
562 return 0;
563 return 1;
564 }
565 }
566
567 static int
568 libcc1_compile (struct gcc_base_context *s,
569 const char *filename)
570 {
571 libcc1 *self = (libcc1 *) s;
572
573 int fds[2];
574 if (socketpair (AF_UNIX, SOCK_STREAM, 0, fds) != 0)
575 {
576 self->print ("could not create socketpair\n");
577 return 0;
578 }
579
580 int stderr_fds[2];
581 if (pipe (stderr_fds) != 0)
582 {
583 self->print ("could not create pipe\n");
584 close (fds[0]);
585 close (fds[1]);
586 return 0;
587 }
588
589 self->args.push_back ("-fplugin=libcc1plugin");
590 char buf[100];
591 if (snprintf (buf, sizeof (buf), "-fplugin-arg-libcc1plugin-fd=%d", fds[1])
592 >= (long) sizeof (buf))
593 abort ();
594 self->args.push_back (buf);
595
596 self->args.push_back (self->source_file);
597 self->args.push_back ("-c");
598 self->args.push_back ("-o");
599 self->args.push_back (filename);
600 if (self->verbose)
601 self->args.push_back ("-v");
602
603 self->connection = new libcc1_connection (fds[0], stderr_fds[0], self);
604
605 cc1_plugin::callback_ftype *fun
606 = cc1_plugin::callback<int,
607 enum gcc_c_oracle_request,
608 const char *,
609 c_call_binding_oracle>;
610 self->connection->add_callback ("binding_oracle", fun);
611
612 fun = cc1_plugin::callback<gcc_address,
613 const char *,
614 c_call_symbol_address>;
615 self->connection->add_callback ("address_oracle", fun);
616
617 char **argv = new (std::nothrow) char *[self->args.size () + 1];
618 if (argv == NULL)
619 return 0;
620
621 for (unsigned int i = 0; i < self->args.size (); ++i)
622 argv[i] = const_cast<char *> (self->args[i].c_str ());
623 argv[self->args.size ()] = NULL;
624
625 return fork_exec (self, argv, fds, stderr_fds);
626 }
627
628 static int
629 libcc1_compile_v0 (struct gcc_base_context *s, const char *filename,
630 int verbose)
631 {
632 libcc1_set_verbose (s, verbose);
633 return libcc1_compile (s, filename);
634 }
635
636 static void
637 libcc1_destroy (struct gcc_base_context *s)
638 {
639 libcc1 *self = (libcc1 *) s;
640
641 delete self;
642 }
643
644 static const struct gcc_base_vtable vtable =
645 {
646 GCC_FE_VERSION_1,
647 libcc1_set_arguments_v0,
648 libcc1_set_source_file,
649 libcc1_set_print_callback,
650 libcc1_compile_v0,
651 libcc1_destroy,
652 libcc1_set_verbose,
653 libcc1_compile,
654 libcc1_set_arguments,
655 libcc1_set_triplet_regexp,
656 libcc1_set_driver_filename,
657 };
658
659 extern "C" gcc_c_fe_context_function gcc_c_fe_context;
660
661 #ifdef __GNUC__
662 #pragma GCC visibility push(default)
663 #endif
664
665 extern "C"
666 struct gcc_c_context *
667 gcc_c_fe_context (enum gcc_base_api_version base_version,
668 enum gcc_c_api_version c_version)
669 {
670 if ((base_version != GCC_FE_VERSION_0 && base_version != GCC_FE_VERSION_1)
671 || (c_version != GCC_C_FE_VERSION_0 && c_version != GCC_C_FE_VERSION_1))
672 return NULL;
673
674 return new libcc1 (&vtable, &c_vtable);
675 }