1/* The library used by gdb.
2   Copyright (C) 2014 Free Software Foundation, Inc.
3
4This file is part of GCC.
5
6GCC is free software; you can redistribute it and/or modify it under
7the terms of the GNU General Public License as published by the Free
8Software Foundation; either version 3, or (at your option) any later
9version.
10
11GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12WARRANTY; without even the implied warranty of MERCHANTABILITY or
13FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14for more details.
15
16You should have received a copy of the GNU General Public License
17along 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 "rpc.hh"
33#include "connection.hh"
34#include "names.hh"
35#include "callbacks.hh"
36#include "gcc-interface.h"
37#include "libiberty.h"
38#include "xregex.h"
39#include "findcomp.hh"
40#include "compiler-name.h"
41
42struct libcc1;
43
44class libcc1_connection;
45
46// The C compiler context that we hand back to our caller.
47struct libcc1 : public gcc_c_context
48{
49  libcc1 (const gcc_base_vtable *, const gcc_c_fe_vtable *);
50  ~libcc1 ();
51
52  // A convenience function to print something.
53  void print (const char *str)
54  {
55    this->print_function (this->print_datum, str);
56  }
57
58  libcc1_connection *connection;
59
60  gcc_c_oracle_function *binding_oracle;
61  gcc_c_symbol_address_function *address_oracle;
62  void *oracle_datum;
63
64  void (*print_function) (void *datum, const char *message);
65  void *print_datum;
66
67  std::vector<std::string> args;
68  std::string source_file;
69};
70
71// A local subclass of connection that holds a back-pointer to the
72// gcc_c_context object that we provide to our caller.
73class libcc1_connection : public cc1_plugin::connection
74{
75public:
76
77  libcc1_connection (int fd, int aux_fd, libcc1 *b)
78    : connection (fd, aux_fd),
79      back_ptr (b)
80  {
81  }
82
83  virtual void print (const char *buf)
84  {
85    back_ptr->print (buf);
86  }
87
88  libcc1 *back_ptr;
89};
90
91libcc1::libcc1 (const gcc_base_vtable *v,
92		const gcc_c_fe_vtable *cv)
93  : connection (NULL),
94    binding_oracle (NULL),
95    address_oracle (NULL),
96    oracle_datum (NULL),
97    print_function (NULL),
98    print_datum (NULL),
99    args (),
100    source_file ()
101{
102  base.ops = v;
103  c_ops = cv;
104}
105
106libcc1::~libcc1 ()
107{
108  delete connection;
109}
110
111
112
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.
117int
118call_binding_oracle (cc1_plugin::connection *conn,
119		     enum gcc_c_oracle_request request,
120		     const char *identifier)
121{
122  libcc1 *self = ((libcc1_connection *) conn)->back_ptr;
123
124  self->binding_oracle (self->oracle_datum, self, request, identifier);
125  return 1;
126}
127
128// This is a wrapper function that is called by the RPC system and
129// that then forwards the call to the library user.
130gcc_address
131call_symbol_address (cc1_plugin::connection *conn, const char *identifier)
132{
133  libcc1 *self = ((libcc1_connection *) conn)->back_ptr;
134
135  return self->address_oracle (self->oracle_datum, self, identifier);
136}
137
138
139
140static void
141set_callbacks (struct gcc_c_context *s,
142	       gcc_c_oracle_function *binding_oracle,
143	       gcc_c_symbol_address_function *address_oracle,
144	       void *datum)
145{
146  libcc1 *self = (libcc1 *) s;
147
148  self->binding_oracle = binding_oracle;
149  self->address_oracle = address_oracle;
150  self->oracle_datum = datum;
151}
152
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.
156
157template<typename R, const char *&NAME>
158R rpc (struct gcc_c_context *s)
159{
160  libcc1 *self = (libcc1 *) s;
161  R result;
162
163  if (!cc1_plugin::call (self->connection, NAME, &result))
164    return 0;
165  return result;
166}
167
168template<typename R, const char *&NAME, typename A>
169R rpc (struct gcc_c_context *s, A arg)
170{
171  libcc1 *self = (libcc1 *) s;
172  R result;
173
174  if (!cc1_plugin::call (self->connection, NAME, &result, arg))
175    return 0;
176  return result;
177}
178
179template<typename R, const char *&NAME, typename A1, typename A2>
180R rpc (struct gcc_c_context *s, A1 arg1, A2 arg2)
181{
182  libcc1 *self = (libcc1 *) s;
183  R result;
184
185  if (!cc1_plugin::call (self->connection, NAME, &result, arg1, arg2))
186    return 0;
187  return result;
188}
189
190template<typename R, const char *&NAME, typename A1, typename A2, typename A3>
191R rpc (struct gcc_c_context *s, A1 arg1, A2 arg2, A3 arg3)
192{
193  libcc1 *self = (libcc1 *) s;
194  R result;
195
196  if (!cc1_plugin::call (self->connection, NAME, &result, arg1, arg2, arg3))
197    return 0;
198  return result;
199}
200
201template<typename R, const char *&NAME, typename A1, typename A2, typename A3,
202	 typename A4>
203R rpc (struct gcc_c_context *s, A1 arg1, A2 arg2, A3 arg3, A4 arg4)
204{
205  libcc1 *self = (libcc1 *) s;
206  R result;
207
208  if (!cc1_plugin::call (self->connection, NAME, &result, arg1, arg2, arg3,
209			 arg4))
210    return 0;
211  return result;
212}
213
214template<typename R, const char *&NAME, typename A1, typename A2, typename A3,
215	 typename A4, typename A5>
216R rpc (struct gcc_c_context *s, A1 arg1, A2 arg2, A3 arg3, A4 arg4, A5 arg5)
217{
218  libcc1 *self = (libcc1 *) s;
219  R result;
220
221  if (!cc1_plugin::call (self->connection, NAME, &result, arg1, arg2, arg3,
222			 arg4, arg5))
223    return 0;
224  return result;
225}
226
227template<typename R, const char *&NAME, typename A1, typename A2, typename A3,
228	 typename A4, typename A5, typename A6, typename A7>
229R rpc (struct gcc_c_context *s, A1 arg1, A2 arg2, A3 arg3, A4 arg4, A5 arg5,
230       A6 arg6, A7 arg7)
231{
232  libcc1 *self = (libcc1 *) s;
233  R result;
234
235  if (!cc1_plugin::call (self->connection, NAME, &result, arg1, arg2, arg3,
236			 arg4, arg5, arg6, arg7))
237    return 0;
238  return result;
239}
240
241static const struct gcc_c_fe_vtable c_vtable =
242{
243  GCC_C_FE_VERSION_0,
244  set_callbacks,
245
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>,
260
261#include "gcc-c-fe.def"
262
263#undef GCC_METHOD0
264#undef GCC_METHOD1
265#undef GCC_METHOD2
266#undef GCC_METHOD3
267#undef GCC_METHOD4
268#undef GCC_METHOD5
269#undef GCC_METHOD7
270};
271
272
273
274// Construct an appropriate regexp to match the compiler name.
275static std::string
276make_regexp (const char *triplet_regexp, const char *compiler)
277{
278  std::stringstream buf;
279
280  buf << "^" << triplet_regexp << "-";
281
282  // Quote the compiler name in case it has something funny in it.
283  for (const char *p = compiler; *p; ++p)
284    {
285      switch (*p)
286	{
287	case '.':
288	case '^':
289	case '$':
290	case '*':
291	case '+':
292	case '?':
293	case '(':
294	case ')':
295	case '[':
296	case '{':
297	case '\\':
298	case '|':
299	  buf << '\\';
300	  break;
301	}
302      buf << *p;
303    }
304  buf << "$";
305
306  return buf.str ();
307}
308
309static char *
310libcc1_set_arguments (struct gcc_base_context *s,
311		      const char *triplet_regexp,
312		      int argc, char **argv)
313{
314  libcc1 *self = (libcc1 *) s;
315  regex_t triplet;
316  int code;
317
318  std::string rx = make_regexp (triplet_regexp, COMPILER_NAME);
319  code = regcomp (&triplet, rx.c_str (), REG_EXTENDED | REG_NOSUB);
320  if (code != 0)
321    {
322      size_t len = regerror (code, &triplet, NULL, 0);
323      char err[len];
324
325      regerror (code, &triplet, err, len);
326
327      return concat ("Could not compile regexp \"",
328		     rx.c_str (),
329		     "\": ",
330		     err,
331		     (char *) NULL);
332    }
333
334  std::string compiler;
335  if (!find_compiler (triplet, &compiler))
336    {
337      regfree (&triplet);
338      return concat ("Could not find a compiler matching \"",
339		     rx.c_str (),
340		     "\"",
341		     (char *) NULL);
342    }
343  regfree (&triplet);
344
345  self->args.push_back (compiler);
346
347  for (int i = 0; i < argc; ++i)
348    self->args.push_back (argv[i]);
349
350  return NULL;
351}
352
353static void
354libcc1_set_source_file (struct gcc_base_context *s,
355			const char *file)
356{
357  libcc1 *self = (libcc1 *) s;
358
359  self->source_file = file;
360}
361
362static void
363libcc1_set_print_callback (struct gcc_base_context *s,
364			   void (*print_function) (void *datum,
365						   const char *message),
366			   void *datum)
367{
368  libcc1 *self = (libcc1 *) s;
369
370  self->print_function = print_function;
371  self->print_datum = datum;
372}
373
374static int
375fork_exec (libcc1 *self, char **argv, int spair_fds[2], int stderr_fds[2])
376{
377  pid_t child_pid = fork ();
378
379  if (child_pid == -1)
380    {
381      close (spair_fds[0]);
382      close (spair_fds[1]);
383      close (stderr_fds[0]);
384      close (stderr_fds[1]);
385      return 0;
386    }
387
388  if (child_pid == 0)
389    {
390      // Child.
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]);
396
397      execvp (argv[0], argv);
398      _exit (127);
399    }
400  else
401    {
402      // Parent.
403      close (spair_fds[1]);
404      close (stderr_fds[1]);
405
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 ();
410
411      close (spair_fds[0]);
412      close (stderr_fds[0]);
413
414      while (true)
415	{
416	  int status;
417
418	  if (waitpid (child_pid, &status, 0) == -1)
419	    {
420	      if (errno != EINTR)
421		return 0;
422	    }
423
424	  if (!WIFEXITED (status) || WEXITSTATUS (status) != 0)
425	    return 0;
426	  break;
427	}
428
429      if (!result)
430	return 0;
431      return 1;
432    }
433}
434
435static int
436libcc1_compile (struct gcc_base_context *s,
437		const char *filename,
438		int verbose)
439{
440  libcc1 *self = (libcc1 *) s;
441
442  int fds[2];
443  if (socketpair (AF_UNIX, SOCK_STREAM, 0, fds) != 0)
444    {
445      self->print ("could not create socketpair\n");
446      return 0;
447    }
448
449  int stderr_fds[2];
450  if (pipe (stderr_fds) != 0)
451    {
452      self->print ("could not create pipe\n");
453      close (fds[0]);
454      close (fds[1]);
455      return 0;
456    }
457
458  self->args.push_back ("-fplugin=libcc1plugin");
459  char buf[100];
460  if (snprintf (buf, sizeof (buf), "-fplugin-arg-libcc1plugin-fd=%d", fds[1])
461      >= (long) sizeof (buf))
462    abort ();
463  self->args.push_back (buf);
464
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);
469  if (verbose)
470    self->args.push_back ("-v");
471
472  self->connection = new libcc1_connection (fds[0], stderr_fds[0], self);
473
474  cc1_plugin::callback_ftype *fun
475    = cc1_plugin::callback<int,
476			   enum gcc_c_oracle_request,
477			   const char *,
478			   call_binding_oracle>;
479  self->connection->add_callback ("binding_oracle", fun);
480
481  fun = cc1_plugin::callback<gcc_address,
482			     const char *,
483			     call_symbol_address>;
484  self->connection->add_callback ("address_oracle", fun);
485
486  char **argv = new (std::nothrow) char *[self->args.size () + 1];
487  if (argv == NULL)
488    return 0;
489
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;
493
494  return fork_exec (self, argv, fds, stderr_fds);
495}
496
497static void
498libcc1_destroy (struct gcc_base_context *s)
499{
500  libcc1 *self = (libcc1 *) s;
501
502  delete self;
503}
504
505static const struct gcc_base_vtable vtable =
506{
507  GCC_FE_VERSION_0,
508  libcc1_set_arguments,
509  libcc1_set_source_file,
510  libcc1_set_print_callback,
511  libcc1_compile,
512  libcc1_destroy
513};
514
515extern "C" gcc_c_fe_context_function gcc_c_fe_context;
516
517#ifdef __GNUC__
518#pragma GCC visibility push(default)
519#endif
520
521extern "C"
522struct gcc_c_context *
523gcc_c_fe_context (enum gcc_base_api_version base_version,
524		  enum gcc_c_api_version c_version)
525{
526  if (base_version != GCC_FE_VERSION_0 || c_version != GCC_C_FE_VERSION_0)
527    return NULL;
528
529  return new libcc1 (&vtable, &c_vtable);
530}
531