Home | History | Annotate | Line # | Download | only in libcc1
      1 /* The library used by gdb.
      2    Copyright (C) 2014-2024 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 "marshall-cp.hh"
     32 #include "rpc.hh"
     33 #include "connection.hh"
     34 #include "names.hh"
     35 #include "callbacks.hh"
     36 #include "libiberty.h"
     37 #include "compiler-name.hh"
     38 #include "compiler.hh"
     39 #include "gdbctx.hh"
     40 
     41 // The C compiler context that we hand back to our caller.
     42 struct libcp1 : public cc1_plugin::base_gdb_plugin<gcc_cp_context>
     43 {
     44   explicit libcp1 (const gcc_cp_fe_vtable *);
     45 
     46   void add_callbacks () override;
     47 
     48   gcc_cp_oracle_function *binding_oracle = nullptr;
     49   gcc_cp_symbol_address_function *address_oracle = nullptr;
     50   gcc_cp_enter_leave_user_expr_scope_function *enter_scope = nullptr;
     51   gcc_cp_enter_leave_user_expr_scope_function *leave_scope = nullptr;
     52   void *oracle_datum = nullptr;
     53 };
     54 
     55 libcp1::libcp1 (const gcc_cp_fe_vtable *cv)
     56   : cc1_plugin::base_gdb_plugin<gcc_cp_context> ("libcp1plugin",
     57 						 CP_COMPILER_NAME,
     58 						 cv->cp_version)
     59 {
     60   cp_ops = cv;
     61 }
     62 
     63 
     64 
     66 // Enclose these functions in an anonymous namespace because they
     67 // shouldn't be exported, but they can't be static because they're
     68 // used as template arguments.
     69 namespace {
     70   // This is a wrapper function that is called by the RPC system and
     71   // that then forwards the call to the library user.  Note that the
     72   // return value is not used; the type cannot be 'void' due to
     73   // limitations in our simple RPC.
     74   int
     75   cp_call_binding_oracle (cc1_plugin::connection *conn,
     76 		       enum gcc_cp_oracle_request request,
     77 		       const char *identifier)
     78   {
     79     libcp1 *self = (libcp1 *) (((libcp1::local_connection *) conn)->back_ptr);
     80 
     81     self->binding_oracle (self->oracle_datum, self, request, identifier);
     82     return 1;
     83   }
     84 
     85   // This is a wrapper function that is called by the RPC system and
     86   // that then forwards the call to the library user.
     87   gcc_address
     88   cp_call_symbol_address (cc1_plugin::connection *conn, const char *identifier)
     89   {
     90     libcp1 *self = (libcp1 *) (((libcp1::local_connection *) conn)->back_ptr);
     91 
     92     return self->address_oracle (self->oracle_datum, self, identifier);
     93   }
     94 
     95   int
     96   cp_call_enter_scope (cc1_plugin::connection *conn)
     97   {
     98     libcp1 *self = (libcp1 *) (((libcp1::local_connection *) conn)->back_ptr);
     99 
    100     self->enter_scope (self->oracle_datum, self);
    101     return 1;
    102   }
    103 
    104   int
    105   cp_call_leave_scope (cc1_plugin::connection *conn)
    106   {
    107     libcp1 *self = (libcp1 *) (((libcp1::local_connection *) conn)->back_ptr);
    108 
    109     self->leave_scope (self->oracle_datum, self);
    110     return 1;
    111   }
    112 } /* anonymous namespace */
    113 
    114 
    115 
    117 static void
    118 set_callbacks (struct gcc_cp_context *s,
    119 	       gcc_cp_oracle_function *binding_oracle,
    120 	       gcc_cp_symbol_address_function *address_oracle,
    121 	       gcc_cp_enter_leave_user_expr_scope_function *enter_scope,
    122 	       gcc_cp_enter_leave_user_expr_scope_function *leave_scope,
    123 	       void *datum)
    124 {
    125   libcp1 *self = (libcp1 *) s;
    126 
    127   self->binding_oracle = binding_oracle;
    128   self->address_oracle = address_oracle;
    129   self->enter_scope = enter_scope;
    130   self->leave_scope = leave_scope;
    131   self->oracle_datum = datum;
    132 }
    133 
    134 static const struct gcc_cp_fe_vtable cp_vtable =
    135 {
    136   GCC_CP_FE_VERSION_0,
    137   set_callbacks,
    138 
    139 #define GCC_METHOD0(R, N) \
    140   cc1_plugin::rpc<gcc_cp_context, R, cc1_plugin::cp::N>,
    141 #define GCC_METHOD1(R, N, A) \
    142   cc1_plugin::rpc<gcc_cp_context, R, cc1_plugin::cp::N, A>,
    143 #define GCC_METHOD2(R, N, A, B) \
    144   cc1_plugin::rpc<gcc_cp_context, R, cc1_plugin::cp::N, A, B>,
    145 #define GCC_METHOD3(R, N, A, B, C) \
    146   cc1_plugin::rpc<gcc_cp_context, R, cc1_plugin::cp::N, A, B, C>,
    147 #define GCC_METHOD4(R, N, A, B, C, D) \
    148   cc1_plugin::rpc<gcc_cp_context, R, cc1_plugin::cp::N, A, B, C, D>,
    149 #define GCC_METHOD5(R, N, A, B, C, D, E) \
    150   cc1_plugin::rpc<gcc_cp_context, R, cc1_plugin::cp::N, A, B, C, D, E>,
    151 #define GCC_METHOD7(R, N, A, B, C, D, E, F, G) \
    152   cc1_plugin::rpc<gcc_cp_context, R, cc1_plugin::cp::N, A, B, C, D, E, F, G>,
    153 
    154 #include "gcc-cp-fe.def"
    155 
    156 #undef GCC_METHOD0
    157 #undef GCC_METHOD1
    158 #undef GCC_METHOD2
    159 #undef GCC_METHOD3
    160 #undef GCC_METHOD4
    161 #undef GCC_METHOD5
    162 #undef GCC_METHOD7
    163 };
    164 
    165 
    166 
    168 void
    169 libcp1::add_callbacks ()
    170 {
    171   cc1_plugin::callback_ftype *fun
    172     = cc1_plugin::invoker<int, enum gcc_cp_oracle_request,
    173 			  const char *>::invoke<cp_call_binding_oracle>;
    174   connection->add_callback ("binding_oracle", fun);
    175 
    176   fun = cc1_plugin::invoker<gcc_address,
    177 			    const char *>::invoke<cp_call_symbol_address>;
    178   connection->add_callback ("address_oracle", fun);
    179 
    180   fun = cc1_plugin::invoker<int>::invoke<cp_call_enter_scope>;
    181   connection->add_callback ("enter_scope", fun);
    182 
    183   fun = cc1_plugin::invoker<int>::invoke<cp_call_leave_scope>;
    184   connection->add_callback ("leave_scope", fun);
    185 }
    186 
    187 extern "C" gcc_cp_fe_context_function gcc_cp_fe_context;
    188 
    189 #ifdef __GNUC__
    190 #pragma GCC visibility push(default)
    191 #endif
    192 
    193 extern "C"
    194 struct gcc_cp_context *
    195 gcc_cp_fe_context (enum gcc_base_api_version base_version,
    196 		    enum gcc_cp_api_version cp_version)
    197 {
    198   if ((base_version != GCC_FE_VERSION_0 && base_version != GCC_FE_VERSION_1)
    199       || cp_version != GCC_CP_FE_VERSION_0)
    200     return NULL;
    201 
    202   return new libcp1 (&cp_vtable);
    203 }
    204