1 /* The library used by gdb.
2 Copyright (C) 2014 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>
33 #include "connection.hh"
35 #include "callbacks.hh"
36 #include "gcc-interface.h"
37 #include "libiberty.h"
39 #include "findcomp.hh"
40 #include "compiler-name.h"
44 class libcc1_connection
;
46 // The C compiler context that we hand back to our caller.
47 struct libcc1
: public gcc_c_context
49 libcc1 (const gcc_base_vtable
*, const gcc_c_fe_vtable
*);
52 // A convenience function to print something.
53 void print (const char *str
)
55 this->print_function (this->print_datum
, str
);
58 libcc1_connection
*connection
;
60 gcc_c_oracle_function
*binding_oracle
;
61 gcc_c_symbol_address_function
*address_oracle
;
64 void (*print_function
) (void *datum
, const char *message
);
67 std::vector
<std::string
> args
;
68 std::string source_file
;
71 // A local subclass of connection that holds a back-pointer to the
72 // gcc_c_context object that we provide to our caller.
73 class libcc1_connection
: public cc1_plugin::connection
77 libcc1_connection (int fd
, int aux_fd
, libcc1
*b
)
78 : connection (fd
, aux_fd
),
83 virtual void print (const char *buf
)
85 back_ptr
->print (buf
);
91 libcc1::libcc1 (const gcc_base_vtable
*v
,
92 const gcc_c_fe_vtable
*cv
)
94 binding_oracle (NULL
),
95 address_oracle (NULL
),
97 print_function (NULL
),
113 // This is a wrapper function that is called by the RPC system and
114 // that then forwards the call to the library user. Note that the
115 // return value is not used; the type cannot be 'void' due to
116 // limitations in our simple RPC.
118 call_binding_oracle (cc1_plugin::connection
*conn
,
119 enum gcc_c_oracle_request request
,
120 const char *identifier
)
122 libcc1
*self
= ((libcc1_connection
*) conn
)->back_ptr
;
124 self
->binding_oracle (self
->oracle_datum
, self
, request
, identifier
);
128 // This is a wrapper function that is called by the RPC system and
129 // that then forwards the call to the library user.
131 call_symbol_address (cc1_plugin::connection
*conn
, const char *identifier
)
133 libcc1
*self
= ((libcc1_connection
*) conn
)->back_ptr
;
135 return self
->address_oracle (self
->oracle_datum
, self
, identifier
);
141 set_callbacks (struct gcc_c_context
*s
,
142 gcc_c_oracle_function
*binding_oracle
,
143 gcc_c_symbol_address_function
*address_oracle
,
146 libcc1
*self
= (libcc1
*) s
;
148 self
->binding_oracle
= binding_oracle
;
149 self
->address_oracle
= address_oracle
;
150 self
->oracle_datum
= datum
;
153 // Instances of these rpc<> template functions are installed into the
154 // "c_vtable". These functions are parameterized by type and method
155 // name and forward the call via the connection.
157 template<typename R
, const char *&NAME
>
158 R
rpc (struct gcc_c_context
*s
)
160 libcc1
*self
= (libcc1
*) s
;
163 if (!cc1_plugin::call (self
->connection
, NAME
, &result
))
168 template<typename R
, const char *&NAME
, typename A
>
169 R
rpc (struct gcc_c_context
*s
, A arg
)
171 libcc1
*self
= (libcc1
*) s
;
174 if (!cc1_plugin::call (self
->connection
, NAME
, &result
, arg
))
179 template<typename R
, const char *&NAME
, typename A1
, typename A2
>
180 R
rpc (struct gcc_c_context
*s
, A1 arg1
, A2 arg2
)
182 libcc1
*self
= (libcc1
*) s
;
185 if (!cc1_plugin::call (self
->connection
, NAME
, &result
, arg1
, arg2
))
190 template<typename R
, const char *&NAME
, typename A1
, typename A2
, typename A3
>
191 R
rpc (struct gcc_c_context
*s
, A1 arg1
, A2 arg2
, A3 arg3
)
193 libcc1
*self
= (libcc1
*) s
;
196 if (!cc1_plugin::call (self
->connection
, NAME
, &result
, arg1
, arg2
, arg3
))
201 template<typename R
, const char *&NAME
, typename A1
, typename A2
, typename A3
,
203 R
rpc (struct gcc_c_context
*s
, A1 arg1
, A2 arg2
, A3 arg3
, A4 arg4
)
205 libcc1
*self
= (libcc1
*) s
;
208 if (!cc1_plugin::call (self
->connection
, NAME
, &result
, arg1
, arg2
, arg3
,
214 template<typename R
, const char *&NAME
, typename A1
, typename A2
, typename A3
,
215 typename A4
, typename A5
>
216 R
rpc (struct gcc_c_context
*s
, A1 arg1
, A2 arg2
, A3 arg3
, A4 arg4
, A5 arg5
)
218 libcc1
*self
= (libcc1
*) s
;
221 if (!cc1_plugin::call (self
->connection
, NAME
, &result
, arg1
, arg2
, arg3
,
227 template<typename R
, const char *&NAME
, typename A1
, typename A2
, typename A3
,
228 typename A4
, typename A5
, typename A6
, typename A7
>
229 R
rpc (struct gcc_c_context
*s
, A1 arg1
, A2 arg2
, A3 arg3
, A4 arg4
, A5 arg5
,
232 libcc1
*self
= (libcc1
*) s
;
235 if (!cc1_plugin::call (self
->connection
, NAME
, &result
, arg1
, arg2
, arg3
,
236 arg4
, arg5
, arg6
, arg7
))
241 static const struct gcc_c_fe_vtable c_vtable
=
246 #define GCC_METHOD0(R, N) \
247 rpc<R, cc1_plugin::N>,
248 #define GCC_METHOD1(R, N, A) \
249 rpc<R, cc1_plugin::N, A>,
250 #define GCC_METHOD2(R, N, A, B) \
251 rpc<R, cc1_plugin::N, A, B>,
252 #define GCC_METHOD3(R, N, A, B, C) \
253 rpc<R, cc1_plugin::N, A, B, C>,
254 #define GCC_METHOD4(R, N, A, B, C, D) \
255 rpc<R, cc1_plugin::N, A, B, C, D>,
256 #define GCC_METHOD5(R, N, A, B, C, D, E) \
257 rpc<R, cc1_plugin::N, A, B, C, D, E>,
258 #define GCC_METHOD7(R, N, A, B, C, D, E, F, G) \
259 rpc<R, cc1_plugin::N, A, B, C, D, E, F, G>,
261 #include "gcc-c-fe.def"
274 // Construct an appropriate regexp to match the compiler name.
276 make_regexp (const char *triplet_regexp
, const char *compiler
)
278 std::stringstream buf
;
280 buf
<< "^" << triplet_regexp
<< "-";
282 // Quote the compiler name in case it has something funny in it.
283 for (const char *p
= compiler
; *p
; ++p
)
310 libcc1_set_arguments (struct gcc_base_context
*s
,
311 const char *triplet_regexp
,
312 int argc
, char **argv
)
314 libcc1
*self
= (libcc1
*) s
;
318 std::string rx
= make_regexp (triplet_regexp
, COMPILER_NAME
);
319 code
= regcomp (&triplet
, rx
.c_str (), REG_EXTENDED
| REG_NOSUB
);
322 size_t len
= regerror (code
, &triplet
, NULL
, 0);
325 regerror (code
, &triplet
, err
, len
);
327 return concat ("Could not compile regexp \"",
334 std::string compiler
;
335 if (!find_compiler (triplet
, &compiler
))
338 return concat ("Could not find a compiler matching \"",
345 self
->args
.push_back (compiler
);
347 for (int i
= 0; i
< argc
; ++i
)
348 self
->args
.push_back (argv
[i
]);
354 libcc1_set_source_file (struct gcc_base_context
*s
,
357 libcc1
*self
= (libcc1
*) s
;
359 self
->source_file
= file
;
363 libcc1_set_print_callback (struct gcc_base_context
*s
,
364 void (*print_function
) (void *datum
,
365 const char *message
),
368 libcc1
*self
= (libcc1
*) s
;
370 self
->print_function
= print_function
;
371 self
->print_datum
= datum
;
375 fork_exec (libcc1
*self
, char **argv
, int spair_fds
[2], int stderr_fds
[2])
377 pid_t child_pid
= fork ();
381 close (spair_fds
[0]);
382 close (spair_fds
[1]);
383 close (stderr_fds
[0]);
384 close (stderr_fds
[1]);
391 dup2 (stderr_fds
[1], 1);
392 dup2 (stderr_fds
[1], 2);
393 close (stderr_fds
[0]);
394 close (stderr_fds
[1]);
395 close (spair_fds
[0]);
397 execvp (argv
[0], argv
);
403 close (spair_fds
[1]);
404 close (stderr_fds
[1]);
406 cc1_plugin::status result
= cc1_plugin::FAIL
;
407 if (self
->connection
->send ('H')
408 && ::cc1_plugin::marshall (self
->connection
, GCC_C_FE_VERSION_0
))
409 result
= self
->connection
->wait_for_query ();
411 close (spair_fds
[0]);
412 close (stderr_fds
[0]);
418 if (waitpid (child_pid
, &status
, 0) == -1)
424 if (!WIFEXITED (status
) || WEXITSTATUS (status
) != 0)
436 libcc1_compile (struct gcc_base_context
*s
,
437 const char *filename
,
440 libcc1
*self
= (libcc1
*) s
;
443 if (socketpair (AF_UNIX
, SOCK_STREAM
, 0, fds
) != 0)
445 self
->print ("could not create socketpair\n");
450 if (pipe (stderr_fds
) != 0)
452 self
->print ("could not create pipe\n");
458 self
->args
.push_back ("-fplugin=libcc1plugin");
460 if (snprintf (buf
, sizeof (buf
), "-fplugin-arg-libcc1plugin-fd=%d", fds
[1])
461 >= (long) sizeof (buf
))
463 self
->args
.push_back (buf
);
465 self
->args
.push_back (self
->source_file
);
466 self
->args
.push_back ("-c");
467 self
->args
.push_back ("-o");
468 self
->args
.push_back (filename
);
470 self
->args
.push_back ("-v");
472 self
->connection
= new libcc1_connection (fds
[0], stderr_fds
[0], self
);
474 cc1_plugin::callback_ftype
*fun
475 = cc1_plugin::callback
<int,
476 enum gcc_c_oracle_request
,
478 call_binding_oracle
>;
479 self
->connection
->add_callback ("binding_oracle", fun
);
481 fun
= cc1_plugin::callback
<gcc_address
,
483 call_symbol_address
>;
484 self
->connection
->add_callback ("address_oracle", fun
);
486 char **argv
= new (std::nothrow
) char *[self
->args
.size () + 1];
490 for (unsigned int i
= 0; i
< self
->args
.size (); ++i
)
491 argv
[i
] = const_cast<char *> (self
->args
[i
].c_str ());
492 argv
[self
->args
.size ()] = NULL
;
494 return fork_exec (self
, argv
, fds
, stderr_fds
);
498 libcc1_destroy (struct gcc_base_context
*s
)
500 libcc1
*self
= (libcc1
*) s
;
505 static const struct gcc_base_vtable vtable
=
508 libcc1_set_arguments
,
509 libcc1_set_source_file
,
510 libcc1_set_print_callback
,
515 extern "C" gcc_c_fe_context_function gcc_c_fe_context
;
518 #pragma GCC visibility push(default)
522 struct gcc_c_context
*
523 gcc_c_fe_context (enum gcc_base_api_version base_version
,
524 enum gcc_c_api_version c_version
)
526 if (base_version
!= GCC_FE_VERSION_0
|| c_version
!= GCC_C_FE_VERSION_0
)
529 return new libcc1 (&vtable
, &c_vtable
);