1 /* The library used by gdb.
2 Copyright (C) 2014-2021 Free Software Foundation, Inc.
4 This file is part of GCC.
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
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
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/>. */
20 #include <cc1plugin-config.h>
23 #include <sys/socket.h>
24 #include <sys/types.h>
32 #include "marshall.hh"
34 #include "connection.hh"
36 #include "callbacks.hh"
37 #include "libiberty.h"
39 #include "findcomp.hh"
40 #include "compiler-name.hh"
42 #include "gcc-c-interface.h"
46 class libcc1_connection
;
48 // The C compiler context that we hand back to our caller.
49 struct libcc1
: public gcc_c_context
51 libcc1 (const gcc_base_vtable
*, const gcc_c_fe_vtable
*);
54 // A convenience function to print something.
55 void print (const char *str
)
57 this->print_function (this->print_datum
, str
);
60 libcc1_connection
*connection
;
62 gcc_c_oracle_function
*binding_oracle
;
63 gcc_c_symbol_address_function
*address_oracle
;
66 void (*print_function
) (void *datum
, const char *message
);
69 std::vector
<std::string
> args
;
70 std::string source_file
;
72 /* Non-zero as an equivalent to gcc driver option "-v". */
75 /* Compiler to set by set_triplet_regexp or set_driver_filename. */
81 compiler (libcc1
*self
) : self_ (self
)
84 virtual char *find (std::string
&compiler
) const;
90 /* Compiler to set by set_triplet_regexp. */
91 class compiler_triplet_regexp
: public compiler
94 std::string triplet_regexp_
;
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
)
101 virtual ~compiler_triplet_regexp ()
106 /* Compiler to set by set_driver_filename. */
107 class compiler_driver_filename
: public compiler
110 std::string driver_filename_
;
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
)
117 virtual ~compiler_driver_filename ()
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
129 libcc1_connection (int fd
, int aux_fd
, libcc1
*b
)
130 : connection (fd
, aux_fd
),
135 void print (const char *buf
) override
137 back_ptr
->print (buf
);
143 libcc1::libcc1 (const gcc_base_vtable
*v
,
144 const gcc_c_fe_vtable
*cv
)
146 binding_oracle (NULL
),
147 address_oracle (NULL
),
149 print_function (NULL
),
154 compilerp (new libcc1::compiler (this))
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.
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.
177 c_call_binding_oracle (cc1_plugin::connection
*conn
,
178 enum gcc_c_oracle_request request
,
179 const char *identifier
)
181 libcc1
*self
= ((libcc1_connection
*) conn
)->back_ptr
;
183 self
->binding_oracle (self
->oracle_datum
, self
, request
, identifier
);
187 // This is a wrapper function that is called by the RPC system and
188 // that then forwards the call to the library user.
190 c_call_symbol_address (cc1_plugin::connection
*conn
, const char *identifier
)
192 libcc1
*self
= ((libcc1_connection
*) conn
)->back_ptr
;
194 return self
->address_oracle (self
->oracle_datum
, self
, identifier
);
196 } /* anonymous namespace */
201 set_callbacks (struct gcc_c_context
*s
,
202 gcc_c_oracle_function
*binding_oracle
,
203 gcc_c_symbol_address_function
*address_oracle
,
206 libcc1
*self
= (libcc1
*) s
;
208 self
->binding_oracle
= binding_oracle
;
209 self
->address_oracle
= address_oracle
;
210 self
->oracle_datum
= datum
;
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.
217 template<typename R
, const char *&NAME
>
218 R
rpc (struct gcc_c_context
*s
)
220 libcc1
*self
= (libcc1
*) s
;
223 if (!cc1_plugin::call (self
->connection
, NAME
, &result
))
228 template<typename R
, const char *&NAME
, typename A
>
229 R
rpc (struct gcc_c_context
*s
, A arg
)
231 libcc1
*self
= (libcc1
*) s
;
234 if (!cc1_plugin::call (self
->connection
, NAME
, &result
, arg
))
239 template<typename R
, const char *&NAME
, typename A1
, typename A2
>
240 R
rpc (struct gcc_c_context
*s
, A1 arg1
, A2 arg2
)
242 libcc1
*self
= (libcc1
*) s
;
245 if (!cc1_plugin::call (self
->connection
, NAME
, &result
, arg1
, arg2
))
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
)
253 libcc1
*self
= (libcc1
*) s
;
256 if (!cc1_plugin::call (self
->connection
, NAME
, &result
, arg1
, arg2
, arg3
))
261 template<typename R
, const char *&NAME
, typename A1
, typename A2
, typename A3
,
263 R
rpc (struct gcc_c_context
*s
, A1 arg1
, A2 arg2
, A3 arg3
, A4 arg4
)
265 libcc1
*self
= (libcc1
*) s
;
268 if (!cc1_plugin::call (self
->connection
, NAME
, &result
, arg1
, arg2
, arg3
,
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
)
278 libcc1
*self
= (libcc1
*) s
;
281 if (!cc1_plugin::call (self
->connection
, NAME
, &result
, arg1
, arg2
, arg3
,
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
,
292 libcc1
*self
= (libcc1
*) s
;
295 if (!cc1_plugin::call (self
->connection
, NAME
, &result
, arg1
, arg2
, arg3
,
296 arg4
, arg5
, arg6
, arg7
))
301 static const struct gcc_c_fe_vtable c_vtable
=
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>,
321 #include "gcc-c-fe.def"
334 // Construct an appropriate regexp to match the compiler name.
336 make_regexp (const char *triplet_regexp
, const char *compiler
)
338 std::stringstream buf
;
340 buf
<< "^" << triplet_regexp
<< "-";
342 // Quote the compiler name in case it has something funny in it.
343 for (const char *p
= compiler
; *p
; ++p
)
370 libcc1_set_verbose (struct gcc_base_context
*s
, int /* bool */ verbose
)
372 libcc1
*self
= (libcc1
*) s
;
374 self
->verbose
= verbose
!= 0;
378 libcc1::compiler::find (std::string
&compiler ATTRIBUTE_UNUSED
) const
380 return xstrdup (_("Compiler has not been specified"));
384 libcc1::compiler_triplet_regexp::find (std::string
&compiler
) const
386 std::string rx
= make_regexp (triplet_regexp_
.c_str (), C_COMPILER_NAME
);
388 fprintf (stderr
, _("searching for compiler matching regex %s\n"),
391 int code
= regcomp (&triplet
, rx
.c_str (), REG_EXTENDED
| REG_NOSUB
);
394 size_t len
= regerror (code
, &triplet
, NULL
, 0);
397 regerror (code
, &triplet
, err
, len
);
399 return concat ("Could not compile regexp \"",
406 if (!find_compiler (triplet
, &compiler
))
409 return concat ("Could not find a compiler matching \"",
416 fprintf (stderr
, _("found compiler %s\n"), compiler
.c_str());
421 libcc1::compiler_driver_filename::find (std::string
&compiler
) const
423 // Simulate fnotice by fprintf.
425 fprintf (stderr
, _("using explicit compiler filename %s\n"),
426 driver_filename_
.c_str());
427 compiler
= driver_filename_
;
432 libcc1_set_arguments (struct gcc_base_context
*s
,
433 int argc
, char **argv
)
435 libcc1
*self
= (libcc1
*) s
;
437 std::string compiler
;
438 char *errmsg
= self
->compilerp
->find (compiler
);
442 self
->args
.push_back (compiler
);
444 for (int i
= 0; i
< argc
; ++i
)
445 self
->args
.push_back (argv
[i
]);
451 libcc1_set_triplet_regexp (struct gcc_base_context
*s
,
452 const char *triplet_regexp
)
454 libcc1
*self
= (libcc1
*) s
;
456 delete self
->compilerp
;
457 self
->compilerp
= new libcc1::compiler_triplet_regexp (self
, triplet_regexp
);
462 libcc1_set_driver_filename (struct gcc_base_context
*s
,
463 const char *driver_filename
)
465 libcc1
*self
= (libcc1
*) s
;
467 delete self
->compilerp
;
468 self
->compilerp
= new libcc1::compiler_driver_filename (self
,
474 libcc1_set_arguments_v0 (struct gcc_base_context
*s
,
475 const char *triplet_regexp
,
476 int argc
, char **argv
)
478 char *errmsg
= libcc1_set_triplet_regexp (s
, triplet_regexp
);
482 return libcc1_set_arguments (s
, argc
, argv
);
486 libcc1_set_source_file (struct gcc_base_context
*s
,
489 libcc1
*self
= (libcc1
*) s
;
491 self
->source_file
= file
;
495 libcc1_set_print_callback (struct gcc_base_context
*s
,
496 void (*print_function
) (void *datum
,
497 const char *message
),
500 libcc1
*self
= (libcc1
*) s
;
502 self
->print_function
= print_function
;
503 self
->print_datum
= datum
;
507 fork_exec (libcc1
*self
, char **argv
, int spair_fds
[2], int stderr_fds
[2])
509 pid_t child_pid
= fork ();
513 close (spair_fds
[0]);
514 close (spair_fds
[1]);
515 close (stderr_fds
[0]);
516 close (stderr_fds
[1]);
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]);
529 execvp (argv
[0], argv
);
535 close (spair_fds
[1]);
536 close (stderr_fds
[1]);
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 ();
543 close (spair_fds
[0]);
544 close (stderr_fds
[0]);
550 if (waitpid (child_pid
, &status
, 0) == -1)
556 if (!WIFEXITED (status
) || WEXITSTATUS (status
) != 0)
568 libcc1_compile (struct gcc_base_context
*s
,
569 const char *filename
)
571 libcc1
*self
= (libcc1
*) s
;
574 if (socketpair (AF_UNIX
, SOCK_STREAM
, 0, fds
) != 0)
576 self
->print ("could not create socketpair\n");
581 if (pipe (stderr_fds
) != 0)
583 self
->print ("could not create pipe\n");
589 self
->args
.push_back ("-fplugin=libcc1plugin");
591 if (snprintf (buf
, sizeof (buf
), "-fplugin-arg-libcc1plugin-fd=%d", fds
[1])
592 >= (long) sizeof (buf
))
594 self
->args
.push_back (buf
);
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
);
601 self
->args
.push_back ("-v");
603 self
->connection
= new libcc1_connection (fds
[0], stderr_fds
[0], self
);
605 cc1_plugin::callback_ftype
*fun
606 = cc1_plugin::callback
<int,
607 enum gcc_c_oracle_request
,
609 c_call_binding_oracle
>;
610 self
->connection
->add_callback ("binding_oracle", fun
);
612 fun
= cc1_plugin::callback
<gcc_address
,
614 c_call_symbol_address
>;
615 self
->connection
->add_callback ("address_oracle", fun
);
617 char **argv
= new (std::nothrow
) char *[self
->args
.size () + 1];
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
;
625 return fork_exec (self
, argv
, fds
, stderr_fds
);
629 libcc1_compile_v0 (struct gcc_base_context
*s
, const char *filename
,
632 libcc1_set_verbose (s
, verbose
);
633 return libcc1_compile (s
, filename
);
637 libcc1_destroy (struct gcc_base_context
*s
)
639 libcc1
*self
= (libcc1
*) s
;
644 static const struct gcc_base_vtable vtable
=
647 libcc1_set_arguments_v0
,
648 libcc1_set_source_file
,
649 libcc1_set_print_callback
,
654 libcc1_set_arguments
,
655 libcc1_set_triplet_regexp
,
656 libcc1_set_driver_filename
,
659 extern "C" gcc_c_fe_context_function gcc_c_fe_context
;
662 #pragma GCC visibility push(default)
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
)
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
))
674 return new libcc1 (&vtable
, &c_vtable
);