diff options
author | Tom Tromey <tom@tromey.com> | 2021-05-04 15:26:58 -0600 |
---|---|---|
committer | Tom Tromey <tom@tromey.com> | 2021-05-05 00:06:18 -0600 |
commit | a8deb8323b98fbf4c4779de4b326de72ba22469b (patch) | |
tree | 6e1b3439add29c8ba76b3e5750d39e2bbcc7a8c4 /libcc1 | |
parent | b65c0bcbe13b2b56a1e84856856548f2a29ada7e (diff) | |
download | gcc-a8deb8323b98fbf4c4779de4b326de72ba22469b.tar.gz |
libcc1: share the GCC interface code
Both the C and C++ side of the GDB plugin in libcc1 share a lot of
code relating to the base GCC interface. It was all copy-and-pasted,
but is essentially identical between the two. This is by design, as
the base GCC API is intended to be shared.
This patch merges the implementations into base_gdb_plugin, which was
introduced earlier for this purpose.
libcc1
* libcp1.cc (libcp1): Change parameters. Update.
(libcp1_set_verbose, libcp1_set_arguments)
(libcp1_set_triplet_regexp, libcp1_set_driver_filename)
(libcp1_set_source_file, libcp1_set_print_callback, fork_exec)
(libcp1_compile, libcp1_destroy, vtable): Remove.
(libcp1::add_callbacks): New method, extracted from
libcp1_compile.
(gcc_c_fe_context): Update.
* libcc1.cc (libcc1): Change parameters. Update.
(libcc1_set_verbose, libcc1_set_arguments)
(libcc1_set_triplet_regexp, libcc1_set_driver_filename)
(libcc1_set_source_file, libcc1_set_print_callback, fork_exec)
(libcc1_compile, libcc1_destroy, vtable): Remove.
(libcc1::add_callbacks): New method, extracted from
libcc1_compile.
(gcc_c_fe_context): Update.
* gdbctx.hh (base_gdb_plugin): Change parameters.
(~base_gdb_plugin): New.
<add_callbacks>: New virtual method.
<plugin_name, fe_version, compiler_name, vtable>: New members.
(get_self, do_set_verbose, do_set_arguments)
(do_set_triplet_regexp, do_set_driver_filename)
(do_set_arguments_v0, do_set_source_file, do_set_print_callback)
(fork_exec, do_compile, do_compile_v0, do_destroy): New methods.
Diffstat (limited to 'libcc1')
-rw-r--r-- | libcc1/gdbctx.hh | 253 | ||||
-rw-r--r-- | libcc1/libcc1.cc | 242 | ||||
-rw-r--r-- | libcc1/libcp1.cc | 246 |
3 files changed, 277 insertions, 464 deletions
diff --git a/libcc1/gdbctx.hh b/libcc1/gdbctx.hh index 1c8d87dff02..4a48381f2b4 100644 --- a/libcc1/gdbctx.hh +++ b/libcc1/gdbctx.hh @@ -23,16 +23,38 @@ along with GCC; see the file COPYING3. If not see namespace cc1_plugin { // The compiler context that we hand back to our caller. + // Due to this, the entire implementation is in this header. template<typename T> struct base_gdb_plugin : public T { - explicit base_gdb_plugin (const gcc_base_vtable *v) + base_gdb_plugin (const char *plugin_name_, const char *base_name, + int version) : verbose (false), + plugin_name (plugin_name_), + fe_version (version), + compiler_name (base_name), compilerp (new compiler (verbose)) { - this->base.ops = v; + vtable = + { + GCC_FE_VERSION_1, + do_set_arguments_v0, + do_set_source_file, + do_set_print_callback, + do_compile_v0, + do_destroy, + do_set_verbose, + do_compile, + do_set_arguments, + do_set_triplet_regexp, + do_set_driver_filename, + }; + + this->base.ops = &vtable; } + virtual ~base_gdb_plugin () = default; + // A convenience function to print something. void print (const char *str) { @@ -53,6 +75,10 @@ namespace cc1_plugin connection.reset (new local_connection (fd, aux_fd, this)); } + // This is called just before compilation begins. It should set + // any needed callbacks on the connection. + virtual void add_callbacks () = 0; + // A local subclass of connection that holds a back-pointer to the // context object that we provide to our caller. class local_connection : public cc1_plugin::connection @@ -84,7 +110,230 @@ namespace cc1_plugin /* Non-zero as an equivalent to gcc driver option "-v". */ bool verbose; + const char *plugin_name; + int fe_version; + + const char *compiler_name; std::unique_ptr<cc1_plugin::compiler> compilerp; + + private: + + struct gcc_base_vtable vtable; + + static inline base_gdb_plugin<T> * + get_self (gcc_base_context *s) + { + T *sub = (T *) s; + return static_cast<base_gdb_plugin<T> *> (sub); + } + + static void + do_set_verbose (struct gcc_base_context *s, int /* bool */ verbose) + { + base_gdb_plugin<T> *self = get_self (s); + + self->set_verbose (verbose != 0); + } + + static char * + do_set_arguments (struct gcc_base_context *s, + int argc, char **argv) + { + base_gdb_plugin<T> *self = get_self (s); + + std::string compiler; + char *errmsg = self->compilerp->find (self->compiler_name, compiler); + if (errmsg != NULL) + return errmsg; + + self->args.push_back (compiler); + + for (int i = 0; i < argc; ++i) + self->args.push_back (argv[i]); + + return NULL; + } + + static char * + do_set_triplet_regexp (struct gcc_base_context *s, + const char *triplet_regexp) + { + base_gdb_plugin<T> *self = get_self (s); + + self->compilerp.reset + (new cc1_plugin::compiler_triplet_regexp (self->verbose, + triplet_regexp)); + return NULL; + } + + static char * + do_set_driver_filename (struct gcc_base_context *s, + const char *driver_filename) + { + base_gdb_plugin<T> *self = get_self (s); + + self->compilerp.reset + (new cc1_plugin::compiler_driver_filename (self->verbose, + driver_filename)); + return NULL; + } + + static char * + do_set_arguments_v0 (struct gcc_base_context *s, + const char *triplet_regexp, + int argc, char **argv) + { + char *errmsg = do_set_triplet_regexp (s, triplet_regexp); + if (errmsg != NULL) + return errmsg; + + return do_set_arguments (s, argc, argv); + } + + static void + do_set_source_file (struct gcc_base_context *s, + const char *file) + { + base_gdb_plugin<T> *self = get_self (s); + + self->source_file = file; + } + + static void + do_set_print_callback (struct gcc_base_context *s, + void (*print_function) (void *datum, + const char *message), + void *datum) + { + base_gdb_plugin<T> *self = get_self (s); + + self->print_function = print_function; + self->print_datum = datum; + } + + int fork_exec (char **argv, int spair_fds[2], int stderr_fds[2]) + { + pid_t child_pid = fork (); + + if (child_pid == -1) + { + close (spair_fds[0]); + close (spair_fds[1]); + close (stderr_fds[0]); + close (stderr_fds[1]); + return 0; + } + + if (child_pid == 0) + { + // Child. + dup2 (stderr_fds[1], 1); + dup2 (stderr_fds[1], 2); + close (stderr_fds[0]); + close (stderr_fds[1]); + close (spair_fds[0]); + + execvp (argv[0], argv); + _exit (127); + } + else + { + // Parent. + close (spair_fds[1]); + close (stderr_fds[1]); + + cc1_plugin::status result = cc1_plugin::FAIL; + if (connection->send ('H') + && ::cc1_plugin::marshall (connection.get (), fe_version)) + result = connection->wait_for_query (); + + close (spair_fds[0]); + close (stderr_fds[0]); + + while (true) + { + int status; + + if (waitpid (child_pid, &status, 0) == -1) + { + if (errno != EINTR) + return 0; + } + + if (!WIFEXITED (status) || WEXITSTATUS (status) != 0) + return 0; + break; + } + + if (!result) + return 0; + return 1; + } + } + + static int + do_compile (struct gcc_base_context *s, + const char *filename) + { + base_gdb_plugin<T> *self = get_self (s); + + int fds[2]; + if (socketpair (AF_UNIX, SOCK_STREAM, 0, fds) != 0) + { + self->print ("could not create socketpair\n"); + return 0; + } + + int stderr_fds[2]; + if (pipe (stderr_fds) != 0) + { + self->print ("could not create pipe\n"); + close (fds[0]); + close (fds[1]); + return 0; + } + + self->args.push_back (std::string ("-fplugin=") + self->plugin_name); + self->args.push_back (std::string ("-fplugin-arg-") + self->plugin_name + + "-fd=" + std::to_string (fds[1])); + + self->args.push_back (self->source_file); + self->args.push_back ("-c"); + self->args.push_back ("-o"); + self->args.push_back (filename); + if (self->verbose) + self->args.push_back ("-v"); + + self->set_connection (fds[0], stderr_fds[0]); + + self->add_callbacks (); + + char **argv = new (std::nothrow) char *[self->args.size () + 1]; + if (argv == NULL) + return 0; + + for (unsigned int i = 0; i < self->args.size (); ++i) + argv[i] = const_cast<char *> (self->args[i].c_str ()); + argv[self->args.size ()] = NULL; + + return self->fork_exec (argv, fds, stderr_fds); + } + + static int + do_compile_v0 (struct gcc_base_context *s, const char *filename, + int verbose) + { + do_set_verbose (s, verbose); + return do_compile (s, filename); + } + + static void + do_destroy (struct gcc_base_context *s) + { + base_gdb_plugin<T> *self = get_self (s); + + delete self; + } }; // Instances of this rpc<> template function are installed into the diff --git a/libcc1/libcc1.cc b/libcc1/libcc1.cc index b9f1eb343aa..cbc54ee0a04 100644 --- a/libcc1/libcc1.cc +++ b/libcc1/libcc1.cc @@ -42,15 +42,19 @@ along with GCC; see the file COPYING3. If not see // The C compiler context that we hand back to our caller. struct libcc1 : public cc1_plugin::base_gdb_plugin<gcc_c_context> { - libcc1 (const gcc_base_vtable *, const gcc_c_fe_vtable *); + explicit libcc1 (const gcc_c_fe_vtable *); + + void add_callbacks () override; gcc_c_oracle_function *binding_oracle = nullptr; gcc_c_symbol_address_function *address_oracle = nullptr; void *oracle_datum = nullptr; }; -libcc1::libcc1 (const gcc_base_vtable *v, const gcc_c_fe_vtable *cv) - : cc1_plugin::base_gdb_plugin<gcc_c_context> (v) +libcc1::libcc1 (const gcc_c_fe_vtable *cv) + : cc1_plugin::base_gdb_plugin<gcc_c_context> ("libcc1plugin", + C_COMPILER_NAME, + GCC_C_FE_VERSION_1) { c_ops = cv; } @@ -135,244 +139,22 @@ static const struct gcc_c_fe_vtable c_vtable = -static void -libcc1_set_verbose (struct gcc_base_context *s, int /* bool */ verbose) -{ - libcc1 *self = (libcc1 *) s; - - self->set_verbose (verbose != 0); -} - -static char * -libcc1_set_arguments (struct gcc_base_context *s, - int argc, char **argv) -{ - libcc1 *self = (libcc1 *) s; - - std::string compiler; - char *errmsg = self->compilerp->find (C_COMPILER_NAME, compiler); - if (errmsg != NULL) - return errmsg; - - self->args.push_back (compiler); - - for (int i = 0; i < argc; ++i) - self->args.push_back (argv[i]); - - return NULL; -} - -static char * -libcc1_set_triplet_regexp (struct gcc_base_context *s, - const char *triplet_regexp) -{ - libcc1 *self = (libcc1 *) s; - - self->compilerp.reset - (new cc1_plugin::compiler_triplet_regexp (self->verbose, - triplet_regexp)); - return NULL; -} - -static char * -libcc1_set_driver_filename (struct gcc_base_context *s, - const char *driver_filename) -{ - libcc1 *self = (libcc1 *) s; - - self->compilerp.reset - (new cc1_plugin::compiler_driver_filename (self->verbose, - driver_filename)); - return NULL; -} - -static char * -libcc1_set_arguments_v0 (struct gcc_base_context *s, - const char *triplet_regexp, - int argc, char **argv) +void +libcc1::add_callbacks () { - char *errmsg = libcc1_set_triplet_regexp (s, triplet_regexp); - if (errmsg != NULL) - return errmsg; - - return libcc1_set_arguments (s, argc, argv); -} - -static void -libcc1_set_source_file (struct gcc_base_context *s, - const char *file) -{ - libcc1 *self = (libcc1 *) s; - - self->source_file = file; -} - -static void -libcc1_set_print_callback (struct gcc_base_context *s, - void (*print_function) (void *datum, - const char *message), - void *datum) -{ - libcc1 *self = (libcc1 *) s; - - self->print_function = print_function; - self->print_datum = datum; -} - -static int -fork_exec (libcc1 *self, char **argv, int spair_fds[2], int stderr_fds[2]) -{ - pid_t child_pid = fork (); - - if (child_pid == -1) - { - close (spair_fds[0]); - close (spair_fds[1]); - close (stderr_fds[0]); - close (stderr_fds[1]); - return 0; - } - - if (child_pid == 0) - { - // Child. - dup2 (stderr_fds[1], 1); - dup2 (stderr_fds[1], 2); - close (stderr_fds[0]); - close (stderr_fds[1]); - close (spair_fds[0]); - - execvp (argv[0], argv); - _exit (127); - } - else - { - // Parent. - close (spair_fds[1]); - close (stderr_fds[1]); - - cc1_plugin::status result = cc1_plugin::FAIL; - if (self->connection->send ('H') - && ::cc1_plugin::marshall (self->connection.get (), - GCC_C_FE_VERSION_1)) - result = self->connection->wait_for_query (); - - close (spair_fds[0]); - close (stderr_fds[0]); - - while (true) - { - int status; - - if (waitpid (child_pid, &status, 0) == -1) - { - if (errno != EINTR) - return 0; - } - - if (!WIFEXITED (status) || WEXITSTATUS (status) != 0) - return 0; - break; - } - - if (!result) - return 0; - return 1; - } -} - -static int -libcc1_compile (struct gcc_base_context *s, - const char *filename) -{ - libcc1 *self = (libcc1 *) s; - - int fds[2]; - if (socketpair (AF_UNIX, SOCK_STREAM, 0, fds) != 0) - { - self->print ("could not create socketpair\n"); - return 0; - } - - int stderr_fds[2]; - if (pipe (stderr_fds) != 0) - { - self->print ("could not create pipe\n"); - close (fds[0]); - close (fds[1]); - return 0; - } - - self->args.push_back ("-fplugin=libcc1plugin"); - char buf[100]; - if (snprintf (buf, sizeof (buf), "-fplugin-arg-libcc1plugin-fd=%d", fds[1]) - >= (long) sizeof (buf)) - abort (); - self->args.push_back (buf); - - self->args.push_back (self->source_file); - self->args.push_back ("-c"); - self->args.push_back ("-o"); - self->args.push_back (filename); - if (self->verbose) - self->args.push_back ("-v"); - - self->set_connection (fds[0], stderr_fds[0]); - cc1_plugin::callback_ftype *fun = cc1_plugin::callback<int, enum gcc_c_oracle_request, const char *, c_call_binding_oracle>; - self->connection->add_callback ("binding_oracle", fun); + connection->add_callback ("binding_oracle", fun); fun = cc1_plugin::callback<gcc_address, const char *, c_call_symbol_address>; - self->connection->add_callback ("address_oracle", fun); - - char **argv = new (std::nothrow) char *[self->args.size () + 1]; - if (argv == NULL) - return 0; - - for (unsigned int i = 0; i < self->args.size (); ++i) - argv[i] = const_cast<char *> (self->args[i].c_str ()); - argv[self->args.size ()] = NULL; - - return fork_exec (self, argv, fds, stderr_fds); -} - -static int -libcc1_compile_v0 (struct gcc_base_context *s, const char *filename, - int verbose) -{ - libcc1_set_verbose (s, verbose); - return libcc1_compile (s, filename); + connection->add_callback ("address_oracle", fun); } -static void -libcc1_destroy (struct gcc_base_context *s) -{ - libcc1 *self = (libcc1 *) s; - - delete self; -} - -static const struct gcc_base_vtable vtable = -{ - GCC_FE_VERSION_1, - libcc1_set_arguments_v0, - libcc1_set_source_file, - libcc1_set_print_callback, - libcc1_compile_v0, - libcc1_destroy, - libcc1_set_verbose, - libcc1_compile, - libcc1_set_arguments, - libcc1_set_triplet_regexp, - libcc1_set_driver_filename, -}; - extern "C" gcc_c_fe_context_function gcc_c_fe_context; #ifdef __GNUC__ @@ -388,5 +170,5 @@ gcc_c_fe_context (enum gcc_base_api_version base_version, || (c_version != GCC_C_FE_VERSION_0 && c_version != GCC_C_FE_VERSION_1)) return NULL; - return new libcc1 (&vtable, &c_vtable); + return new libcc1 (&c_vtable); } diff --git a/libcc1/libcp1.cc b/libcc1/libcp1.cc index 65e9770205c..d22d9dc6af8 100644 --- a/libcc1/libcp1.cc +++ b/libcc1/libcp1.cc @@ -41,7 +41,9 @@ along with GCC; see the file COPYING3. If not see // The C compiler context that we hand back to our caller. struct libcp1 : public cc1_plugin::base_gdb_plugin<gcc_cp_context> { - libcp1 (const gcc_base_vtable *, const gcc_cp_fe_vtable *); + explicit libcp1 (const gcc_cp_fe_vtable *); + + void add_callbacks () override; gcc_cp_oracle_function *binding_oracle = nullptr; gcc_cp_symbol_address_function *address_oracle = nullptr; @@ -50,8 +52,10 @@ struct libcp1 : public cc1_plugin::base_gdb_plugin<gcc_cp_context> void *oracle_datum = nullptr; }; -libcp1::libcp1 (const gcc_base_vtable *v, const gcc_cp_fe_vtable *cv) - : cc1_plugin::base_gdb_plugin<gcc_cp_context> (v) +libcp1::libcp1 (const gcc_cp_fe_vtable *cv) + : cc1_plugin::base_gdb_plugin<gcc_cp_context> ("libcp1plugin", + CP_COMPILER_NAME, + GCC_CP_FE_VERSION_0) { cp_ops = cv; } @@ -158,252 +162,30 @@ static const struct gcc_cp_fe_vtable cp_vtable = -static void -libcp1_set_verbose (struct gcc_base_context *s, int /* bool */ verbose) -{ - libcp1 *self = (libcp1 *) s; - - self->set_verbose (verbose != 0); -} - -static char * -libcp1_set_arguments (struct gcc_base_context *s, - int argc, char **argv) -{ - libcp1 *self = (libcp1 *) s; - - std::string compiler; - char *errmsg = self->compilerp->find (CP_COMPILER_NAME, compiler); - if (errmsg != NULL) - return errmsg; - - self->args.push_back (compiler); - - for (int i = 0; i < argc; ++i) - self->args.push_back (argv[i]); - - return NULL; -} - -static char * -libcp1_set_triplet_regexp (struct gcc_base_context *s, - const char *triplet_regexp) -{ - libcp1 *self = (libcp1 *) s; - - self->compilerp.reset - (new cc1_plugin::compiler_triplet_regexp (self->verbose, - triplet_regexp)); - return NULL; -} - -static char * -libcp1_set_driver_filename (struct gcc_base_context *s, - const char *driver_filename) -{ - libcp1 *self = (libcp1 *) s; - - self->compilerp.reset - (new cc1_plugin::compiler_driver_filename (self->verbose, - driver_filename)); - return NULL; -} - -static char * -libcp1_set_arguments_v0 (struct gcc_base_context *s, - const char *triplet_regexp, - int argc, char **argv) -{ - char *errmsg = libcp1_set_triplet_regexp (s, triplet_regexp); - if (errmsg != NULL) - return errmsg; - - return libcp1_set_arguments (s, argc, argv); -} - -static void -libcp1_set_source_file (struct gcc_base_context *s, - const char *file) -{ - libcp1 *self = (libcp1 *) s; - - self->source_file = file; -} - -static void -libcp1_set_print_callback (struct gcc_base_context *s, - void (*print_function) (void *datum, - const char *message), - void *datum) -{ - libcp1 *self = (libcp1 *) s; - - self->print_function = print_function; - self->print_datum = datum; -} - -static int -fork_exec (libcp1 *self, char **argv, int spair_fds[2], int stderr_fds[2]) -{ - pid_t child_pid = fork (); - - if (child_pid == -1) - { - close (spair_fds[0]); - close (spair_fds[1]); - close (stderr_fds[0]); - close (stderr_fds[1]); - return 0; - } - - if (child_pid == 0) - { - // Child. - dup2 (stderr_fds[1], 1); - dup2 (stderr_fds[1], 2); - close (stderr_fds[0]); - close (stderr_fds[1]); - close (spair_fds[0]); - - execvp (argv[0], argv); - _exit (127); - } - else - { - // Parent. - close (spair_fds[1]); - close (stderr_fds[1]); - - cc1_plugin::status result = cc1_plugin::FAIL; - if (self->connection->send ('H') - && ::cc1_plugin::marshall (self->connection.get (), - GCC_CP_FE_VERSION_0)) - result = self->connection->wait_for_query (); - - close (spair_fds[0]); - close (stderr_fds[0]); - - while (true) - { - int status; - - if (waitpid (child_pid, &status, 0) == -1) - { - if (errno != EINTR) - return 0; - } - - if (!WIFEXITED (status) || WEXITSTATUS (status) != 0) - return 0; - break; - } - - if (!result) - return 0; - return 1; - } -} - -static int -libcp1_compile (struct gcc_base_context *s, - const char *filename) +void +libcp1::add_callbacks () { - libcp1 *self = (libcp1 *) s; - - int fds[2]; - if (socketpair (AF_UNIX, SOCK_STREAM, 0, fds) != 0) - { - self->print ("could not create socketpair\n"); - return 0; - } - - int stderr_fds[2]; - if (pipe (stderr_fds) != 0) - { - self->print ("could not create pipe\n"); - close (fds[0]); - close (fds[1]); - return 0; - } - - self->args.push_back ("-fplugin=libcp1plugin"); - char buf[100]; - if (snprintf (buf, sizeof (buf), "-fplugin-arg-libcp1plugin-fd=%d", fds[1]) - >= (long) sizeof (buf)) - abort (); - self->args.push_back (buf); - - self->args.push_back (self->source_file); - self->args.push_back ("-c"); - self->args.push_back ("-o"); - self->args.push_back (filename); - if (self->verbose) - self->args.push_back ("-v"); - - self->set_connection (fds[0], stderr_fds[0]); - cc1_plugin::callback_ftype *fun = cc1_plugin::callback<int, enum gcc_cp_oracle_request, const char *, cp_call_binding_oracle>; - self->connection->add_callback ("binding_oracle", fun); + connection->add_callback ("binding_oracle", fun); fun = cc1_plugin::callback<gcc_address, const char *, cp_call_symbol_address>; - self->connection->add_callback ("address_oracle", fun); + connection->add_callback ("address_oracle", fun); fun = cc1_plugin::callback<int, cp_call_enter_scope>; - self->connection->add_callback ("enter_scope", fun); + connection->add_callback ("enter_scope", fun); fun = cc1_plugin::callback<int, cp_call_leave_scope>; - self->connection->add_callback ("leave_scope", fun); - - char **argv = new (std::nothrow) char *[self->args.size () + 1]; - if (argv == NULL) - return 0; - - for (unsigned int i = 0; i < self->args.size (); ++i) - argv[i] = const_cast<char *> (self->args[i].c_str ()); - argv[self->args.size ()] = NULL; - - return fork_exec (self, argv, fds, stderr_fds); -} - -static int -libcp1_compile_v0 (struct gcc_base_context *s, const char *filename, - int verbose) -{ - libcp1_set_verbose (s, verbose); - return libcp1_compile (s, filename); + connection->add_callback ("leave_scope", fun); } -static void -libcp1_destroy (struct gcc_base_context *s) -{ - libcp1 *self = (libcp1 *) s; - - delete self; -} - -static const struct gcc_base_vtable vtable = -{ - GCC_FE_VERSION_1, - libcp1_set_arguments_v0, - libcp1_set_source_file, - libcp1_set_print_callback, - libcp1_compile_v0, - libcp1_destroy, - libcp1_set_verbose, - libcp1_compile, - libcp1_set_arguments, - libcp1_set_triplet_regexp, - libcp1_set_driver_filename, -}; - extern "C" gcc_cp_fe_context_function gcc_cp_fe_context; #ifdef __GNUC__ @@ -419,5 +201,5 @@ gcc_cp_fe_context (enum gcc_base_api_version base_version, || cp_version != GCC_CP_FE_VERSION_0) return NULL; - return new libcp1 (&vtable, &cp_vtable); + return new libcp1 (&cp_vtable); } |