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