1 /* The library used by gdb. 2 Copyright (C) 2014-2019 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 <sstream> 32 #include "marshall-cp.hh" 33 #include "rpc.hh" 34 #include "connection.hh" 35 #include "names.hh" 36 #include "callbacks.hh" 37 #include "libiberty.h" 38 #include "xregex.h" 39 #include "findcomp.hh" 40 #include "compiler-name.hh" 41 #include "intl.h" 42 43 struct libcp1; 44 45 class libcp1_connection; 46 47 // The C compiler context that we hand back to our caller. 48 struct libcp1 : public gcc_cp_context 49 { 50 libcp1 (const gcc_base_vtable *, const gcc_cp_fe_vtable *); 51 ~libcp1 (); 52 53 // A convenience function to print something. 54 void print (const char *str) 55 { 56 this->print_function (this->print_datum, str); 57 } 58 59 libcp1_connection *connection; 60 61 gcc_cp_oracle_function *binding_oracle; 62 gcc_cp_symbol_address_function *address_oracle; 63 gcc_cp_enter_leave_user_expr_scope_function *enter_scope; 64 gcc_cp_enter_leave_user_expr_scope_function *leave_scope; 65 void *oracle_datum; 66 67 void (*print_function) (void *datum, const char *message); 68 void *print_datum; 69 70 std::vector<std::string> args; 71 std::string source_file; 72 73 /* Non-zero as an equivalent to gcc driver option "-v". */ 74 bool verbose; 75 76 /* Compiler to set by set_triplet_regexp or set_driver_filename. */ 77 class compiler 78 { 79 protected: 80 libcp1 *self_; 81 public: 82 compiler (libcp1 *self) : self_ (self) 83 { 84 } 85 virtual char *find (std::string &compiler) const; 86 virtual ~compiler () 87 { 88 } 89 } *compilerp; 90 91 /* Compiler to set by set_triplet_regexp. */ 92 class compiler_triplet_regexp : public compiler 93 { 94 private: 95 std::string triplet_regexp_; 96 public: 97 virtual char *find (std::string &compiler) const; 98 compiler_triplet_regexp (libcp1 *self, std::string triplet_regexp) 99 : compiler (self), triplet_regexp_ (triplet_regexp) 100 { 101 } 102 virtual ~compiler_triplet_regexp () 103 { 104 } 105 }; 106 107 /* Compiler to set by set_driver_filename. */ 108 class compiler_driver_filename : public compiler 109 { 110 private: 111 std::string driver_filename_; 112 public: 113 virtual char *find (std::string &compiler) const; 114 compiler_driver_filename (libcp1 *self, std::string driver_filename) 115 : compiler (self), driver_filename_ (driver_filename) 116 { 117 } 118 virtual ~compiler_driver_filename () 119 { 120 } 121 }; 122 }; 123 124 // A local subclass of connection that holds a back-pointer to the 125 // gcc_c_context object that we provide to our caller. 126 class libcp1_connection : public cc1_plugin::connection 127 { 128 public: 129 130 libcp1_connection (int fd, int aux_fd, libcp1 *b) 131 : connection (fd, aux_fd), 132 back_ptr (b) 133 { 134 } 135 136 virtual void print (const char *buf) 137 { 138 back_ptr->print (buf); 139 } 140 141 libcp1 *back_ptr; 142 }; 143 144 libcp1::libcp1 (const gcc_base_vtable *v, 145 const gcc_cp_fe_vtable *cv) 146 : connection (NULL), 147 binding_oracle (NULL), 148 address_oracle (NULL), 149 oracle_datum (NULL), 150 print_function (NULL), 151 print_datum (NULL), 152 args (), 153 source_file (), 154 verbose (false), 155 compilerp (new libcp1::compiler (this)) 156 { 157 base.ops = v; 158 cp_ops = cv; 159 } 160 161 libcp1::~libcp1 () 162 { 163 delete connection; 164 delete compilerp; 165 } 166 167 168 169 // Enclose these functions in an anonymous namespace because they 170 // shouldn't be exported, but they can't be static because they're 171 // used as template arguments. 172 namespace { 173 // This is a wrapper function that is called by the RPC system and 174 // that then forwards the call to the library user. Note that the 175 // return value is not used; the type cannot be 'void' due to 176 // limitations in our simple RPC. 177 int 178 cp_call_binding_oracle (cc1_plugin::connection *conn, 179 enum gcc_cp_oracle_request request, 180 const char *identifier) 181 { 182 libcp1 *self = ((libcp1_connection *) conn)->back_ptr; 183 184 self->binding_oracle (self->oracle_datum, self, request, identifier); 185 return 1; 186 } 187 188 // This is a wrapper function that is called by the RPC system and 189 // that then forwards the call to the library user. 190 gcc_address 191 cp_call_symbol_address (cc1_plugin::connection *conn, const char *identifier) 192 { 193 libcp1 *self = ((libcp1_connection *) conn)->back_ptr; 194 195 return self->address_oracle (self->oracle_datum, self, identifier); 196 } 197 198 int 199 cp_call_enter_scope (cc1_plugin::connection *conn) 200 { 201 libcp1 *self = ((libcp1_connection *) conn)->back_ptr; 202 203 self->enter_scope (self->oracle_datum, self); 204 return 1; 205 } 206 207 int 208 cp_call_leave_scope (cc1_plugin::connection *conn) 209 { 210 libcp1 *self = ((libcp1_connection *) conn)->back_ptr; 211 212 self->leave_scope (self->oracle_datum, self); 213 return 1; 214 } 215 } /* anonymous namespace */ 216 217 218 219 static void 220 set_callbacks (struct gcc_cp_context *s, 221 gcc_cp_oracle_function *binding_oracle, 222 gcc_cp_symbol_address_function *address_oracle, 223 gcc_cp_enter_leave_user_expr_scope_function *enter_scope, 224 gcc_cp_enter_leave_user_expr_scope_function *leave_scope, 225 void *datum) 226 { 227 libcp1 *self = (libcp1 *) s; 228 229 self->binding_oracle = binding_oracle; 230 self->address_oracle = address_oracle; 231 self->enter_scope = enter_scope; 232 self->leave_scope = leave_scope; 233 self->oracle_datum = datum; 234 } 235 236 // Instances of these rpc<> template functions are installed into the 237 // "cp_vtable". These functions are parameterized by type and method 238 // name and forward the call via the connection. 239 240 template<typename R, const char *&NAME> 241 R rpc (struct gcc_cp_context *s) 242 { 243 libcp1 *self = (libcp1 *) s; 244 R result; 245 246 if (!cc1_plugin::call (self->connection, NAME, &result)) 247 return 0; 248 return result; 249 } 250 251 template<typename R, const char *&NAME, typename A> 252 R rpc (struct gcc_cp_context *s, A arg) 253 { 254 libcp1 *self = (libcp1 *) s; 255 R result; 256 257 if (!cc1_plugin::call (self->connection, NAME, &result, arg)) 258 return 0; 259 return result; 260 } 261 262 template<typename R, const char *&NAME, typename A1, typename A2> 263 R rpc (struct gcc_cp_context *s, A1 arg1, A2 arg2) 264 { 265 libcp1 *self = (libcp1 *) s; 266 R result; 267 268 if (!cc1_plugin::call (self->connection, NAME, &result, arg1, arg2)) 269 return 0; 270 return result; 271 } 272 273 template<typename R, const char *&NAME, typename A1, typename A2, typename A3> 274 R rpc (struct gcc_cp_context *s, A1 arg1, A2 arg2, A3 arg3) 275 { 276 libcp1 *self = (libcp1 *) s; 277 R result; 278 279 if (!cc1_plugin::call (self->connection, NAME, &result, arg1, arg2, arg3)) 280 return 0; 281 return result; 282 } 283 284 template<typename R, const char *&NAME, typename A1, typename A2, typename A3, 285 typename A4> 286 R rpc (struct gcc_cp_context *s, A1 arg1, A2 arg2, A3 arg3, A4 arg4) 287 { 288 libcp1 *self = (libcp1 *) s; 289 R result; 290 291 if (!cc1_plugin::call (self->connection, NAME, &result, arg1, arg2, arg3, 292 arg4)) 293 return 0; 294 return result; 295 } 296 297 template<typename R, const char *&NAME, typename A1, typename A2, typename A3, 298 typename A4, typename A5> 299 R rpc (struct gcc_cp_context *s, A1 arg1, A2 arg2, A3 arg3, A4 arg4, A5 arg5) 300 { 301 libcp1 *self = (libcp1 *) s; 302 R result; 303 304 if (!cc1_plugin::call (self->connection, NAME, &result, arg1, arg2, arg3, 305 arg4, arg5)) 306 return 0; 307 return result; 308 } 309 310 template<typename R, const char *&NAME, typename A1, typename A2, typename A3, 311 typename A4, typename A5, typename A6, typename A7> 312 R rpc (struct gcc_cp_context *s, A1 arg1, A2 arg2, A3 arg3, A4 arg4, A5 arg5, 313 A6 arg6, A7 arg7) 314 { 315 libcp1 *self = (libcp1 *) s; 316 R result; 317 318 if (!cc1_plugin::call (self->connection, NAME, &result, arg1, arg2, arg3, 319 arg4, arg5, arg6, arg7)) 320 return 0; 321 return result; 322 } 323 324 static const struct gcc_cp_fe_vtable cp_vtable = 325 { 326 GCC_CP_FE_VERSION_0, 327 set_callbacks, 328 329 #define GCC_METHOD0(R, N) \ 330 rpc<R, cc1_plugin::cp::N>, 331 #define GCC_METHOD1(R, N, A) \ 332 rpc<R, cc1_plugin::cp::N, A>, 333 #define GCC_METHOD2(R, N, A, B) \ 334 rpc<R, cc1_plugin::cp::N, A, B>, 335 #define GCC_METHOD3(R, N, A, B, C) \ 336 rpc<R, cc1_plugin::cp::N, A, B, C>, 337 #define GCC_METHOD4(R, N, A, B, C, D) \ 338 rpc<R, cc1_plugin::cp::N, A, B, C, D>, 339 #define GCC_METHOD5(R, N, A, B, C, D, E) \ 340 rpc<R, cc1_plugin::cp::N, A, B, C, D, E>, 341 #define GCC_METHOD7(R, N, A, B, C, D, E, F, G) \ 342 rpc<R, cc1_plugin::cp::N, A, B, C, D, E, F, G>, 343 344 #include "gcc-cp-fe.def" 345 346 #undef GCC_METHOD0 347 #undef GCC_METHOD1 348 #undef GCC_METHOD2 349 #undef GCC_METHOD3 350 #undef GCC_METHOD4 351 #undef GCC_METHOD5 352 #undef GCC_METHOD7 353 }; 354 355 356 357 // Construct an appropriate regexp to match the compiler name. 358 static std::string 359 make_regexp (const char *triplet_regexp, const char *compiler) 360 { 361 std::stringstream buf; 362 363 buf << "^" << triplet_regexp << "-"; 364 365 // Quote the compiler name in case it has something funny in it. 366 for (const char *p = compiler; *p; ++p) 367 { 368 switch (*p) 369 { 370 case '.': 371 case '^': 372 case '$': 373 case '*': 374 case '+': 375 case '?': 376 case '(': 377 case ')': 378 case '[': 379 case '{': 380 case '\\': 381 case '|': 382 buf << '\\'; 383 break; 384 } 385 buf << *p; 386 } 387 buf << "$"; 388 389 return buf.str (); 390 } 391 392 static void 393 libcp1_set_verbose (struct gcc_base_context *s, int /* bool */ verbose) 394 { 395 libcp1 *self = (libcp1 *) s; 396 397 self->verbose = verbose != 0; 398 } 399 400 char * 401 libcp1::compiler::find (std::string &compiler ATTRIBUTE_UNUSED) const 402 { 403 return xstrdup (_("Compiler has not been specified")); 404 } 405 406 char * 407 libcp1::compiler_triplet_regexp::find (std::string &compiler) const 408 { 409 std::string rx = make_regexp (triplet_regexp_.c_str (), CP_COMPILER_NAME); 410 if (self_->verbose) 411 fprintf (stderr, _("searching for compiler matching regex %s\n"), 412 rx.c_str()); 413 regex_t triplet; 414 int code = regcomp (&triplet, rx.c_str (), REG_EXTENDED | REG_NOSUB); 415 if (code != 0) 416 { 417 size_t len = regerror (code, &triplet, NULL, 0); 418 char err[len]; 419 420 regerror (code, &triplet, err, len); 421 422 return concat ("Could not compile regexp \"", 423 rx.c_str (), 424 "\": ", 425 err, 426 (char *) NULL); 427 } 428 429 if (!find_compiler (triplet, &compiler)) 430 { 431 regfree (&triplet); 432 return concat ("Could not find a compiler matching \"", 433 rx.c_str (), 434 "\"", 435 (char *) NULL); 436 } 437 regfree (&triplet); 438 if (self_->verbose) 439 fprintf (stderr, _("found compiler %s\n"), compiler.c_str()); 440 return NULL; 441 } 442 443 char * 444 libcp1::compiler_driver_filename::find (std::string &compiler) const 445 { 446 // Simulate fnotice by fprintf. 447 if (self_->verbose) 448 fprintf (stderr, _("using explicit compiler filename %s\n"), 449 driver_filename_.c_str()); 450 compiler = driver_filename_; 451 return NULL; 452 } 453 454 static char * 455 libcp1_set_arguments (struct gcc_base_context *s, 456 int argc, char **argv) 457 { 458 libcp1 *self = (libcp1 *) s; 459 460 std::string compiler; 461 char *errmsg = self->compilerp->find (compiler); 462 if (errmsg != NULL) 463 return errmsg; 464 465 self->args.push_back (compiler); 466 467 for (int i = 0; i < argc; ++i) 468 self->args.push_back (argv[i]); 469 470 return NULL; 471 } 472 473 static char * 474 libcp1_set_triplet_regexp (struct gcc_base_context *s, 475 const char *triplet_regexp) 476 { 477 libcp1 *self = (libcp1 *) s; 478 479 delete self->compilerp; 480 self->compilerp = new libcp1::compiler_triplet_regexp (self, triplet_regexp); 481 return NULL; 482 } 483 484 static char * 485 libcp1_set_driver_filename (struct gcc_base_context *s, 486 const char *driver_filename) 487 { 488 libcp1 *self = (libcp1 *) s; 489 490 delete self->compilerp; 491 self->compilerp = new libcp1::compiler_driver_filename (self, 492 driver_filename); 493 return NULL; 494 } 495 496 static char * 497 libcp1_set_arguments_v0 (struct gcc_base_context *s, 498 const char *triplet_regexp, 499 int argc, char **argv) 500 { 501 char *errmsg = libcp1_set_triplet_regexp (s, triplet_regexp); 502 if (errmsg != NULL) 503 return errmsg; 504 505 return libcp1_set_arguments (s, argc, argv); 506 } 507 508 static void 509 libcp1_set_source_file (struct gcc_base_context *s, 510 const char *file) 511 { 512 libcp1 *self = (libcp1 *) s; 513 514 self->source_file = file; 515 } 516 517 static void 518 libcp1_set_print_callback (struct gcc_base_context *s, 519 void (*print_function) (void *datum, 520 const char *message), 521 void *datum) 522 { 523 libcp1 *self = (libcp1 *) s; 524 525 self->print_function = print_function; 526 self->print_datum = datum; 527 } 528 529 static int 530 fork_exec (libcp1 *self, char **argv, int spair_fds[2], int stderr_fds[2]) 531 { 532 pid_t child_pid = fork (); 533 534 if (child_pid == -1) 535 { 536 close (spair_fds[0]); 537 close (spair_fds[1]); 538 close (stderr_fds[0]); 539 close (stderr_fds[1]); 540 return 0; 541 } 542 543 if (child_pid == 0) 544 { 545 // Child. 546 dup2 (stderr_fds[1], 1); 547 dup2 (stderr_fds[1], 2); 548 close (stderr_fds[0]); 549 close (stderr_fds[1]); 550 close (spair_fds[0]); 551 552 execvp (argv[0], argv); 553 _exit (127); 554 } 555 else 556 { 557 // Parent. 558 close (spair_fds[1]); 559 close (stderr_fds[1]); 560 561 cc1_plugin::status result = cc1_plugin::FAIL; 562 if (self->connection->send ('H') 563 && ::cc1_plugin::marshall (self->connection, GCC_CP_FE_VERSION_0)) 564 result = self->connection->wait_for_query (); 565 566 close (spair_fds[0]); 567 close (stderr_fds[0]); 568 569 while (true) 570 { 571 int status; 572 573 if (waitpid (child_pid, &status, 0) == -1) 574 { 575 if (errno != EINTR) 576 return 0; 577 } 578 579 if (!WIFEXITED (status) || WEXITSTATUS (status) != 0) 580 return 0; 581 break; 582 } 583 584 if (!result) 585 return 0; 586 return 1; 587 } 588 } 589 590 static int 591 libcp1_compile (struct gcc_base_context *s, 592 const char *filename) 593 { 594 libcp1 *self = (libcp1 *) s; 595 596 int fds[2]; 597 if (socketpair (AF_UNIX, SOCK_STREAM, 0, fds) != 0) 598 { 599 self->print ("could not create socketpair\n"); 600 return 0; 601 } 602 603 int stderr_fds[2]; 604 if (pipe (stderr_fds) != 0) 605 { 606 self->print ("could not create pipe\n"); 607 close (fds[0]); 608 close (fds[1]); 609 return 0; 610 } 611 612 self->args.push_back ("-fplugin=libcp1plugin"); 613 char buf[100]; 614 if (snprintf (buf, sizeof (buf), "-fplugin-arg-libcp1plugin-fd=%d", fds[1]) 615 >= (long) sizeof (buf)) 616 abort (); 617 self->args.push_back (buf); 618 619 self->args.push_back (self->source_file); 620 self->args.push_back ("-c"); 621 self->args.push_back ("-o"); 622 self->args.push_back (filename); 623 if (self->verbose) 624 self->args.push_back ("-v"); 625 626 self->connection = new libcp1_connection (fds[0], stderr_fds[0], self); 627 628 cc1_plugin::callback_ftype *fun 629 = cc1_plugin::callback<int, 630 enum gcc_cp_oracle_request, 631 const char *, 632 cp_call_binding_oracle>; 633 self->connection->add_callback ("binding_oracle", fun); 634 635 fun = cc1_plugin::callback<gcc_address, 636 const char *, 637 cp_call_symbol_address>; 638 self->connection->add_callback ("address_oracle", fun); 639 640 fun = cc1_plugin::callback<int, 641 cp_call_enter_scope>; 642 self->connection->add_callback ("enter_scope", fun); 643 644 fun = cc1_plugin::callback<int, 645 cp_call_leave_scope>; 646 self->connection->add_callback ("leave_scope", fun); 647 648 char **argv = new (std::nothrow) char *[self->args.size () + 1]; 649 if (argv == NULL) 650 return 0; 651 652 for (unsigned int i = 0; i < self->args.size (); ++i) 653 argv[i] = const_cast<char *> (self->args[i].c_str ()); 654 argv[self->args.size ()] = NULL; 655 656 return fork_exec (self, argv, fds, stderr_fds); 657 } 658 659 static int 660 libcp1_compile_v0 (struct gcc_base_context *s, const char *filename, 661 int verbose) 662 { 663 libcp1_set_verbose (s, verbose); 664 return libcp1_compile (s, filename); 665 } 666 667 static void 668 libcp1_destroy (struct gcc_base_context *s) 669 { 670 libcp1 *self = (libcp1 *) s; 671 672 delete self; 673 } 674 675 static const struct gcc_base_vtable vtable = 676 { 677 GCC_FE_VERSION_0, 678 libcp1_set_arguments_v0, 679 libcp1_set_source_file, 680 libcp1_set_print_callback, 681 libcp1_compile_v0, 682 libcp1_destroy, 683 libcp1_set_verbose, 684 libcp1_compile, 685 libcp1_set_arguments, 686 libcp1_set_triplet_regexp, 687 libcp1_set_driver_filename, 688 }; 689 690 extern "C" gcc_cp_fe_context_function gcc_cp_fe_context; 691 692 #ifdef __GNUC__ 693 #pragma GCC visibility push(default) 694 #endif 695 696 extern "C" 697 struct gcc_cp_context * 698 gcc_cp_fe_context (enum gcc_base_api_version base_version, 699 enum gcc_cp_api_version cp_version) 700 { 701 if ((base_version != GCC_FE_VERSION_0 && base_version != GCC_FE_VERSION_1) 702 || cp_version != GCC_CP_FE_VERSION_0) 703 return NULL; 704 705 return new libcp1 (&vtable, &cp_vtable); 706 } 707