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