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