Print this page
9899 cw(1onbld) should shadow more compilation

Split Close
Expand all
Collapse all
          --- old/usr/src/tools/cw/cw.c
          +++ new/usr/src/tools/cw/cw.c
↓ open down ↓ 254 lines elided ↑ open up ↑
 255  255  
 256  256  #include <ctype.h>
 257  257  #include <err.h>
 258  258  #include <errno.h>
 259  259  #include <fcntl.h>
 260  260  #include <getopt.h>
 261  261  #include <stdio.h>
 262  262  #include <stdlib.h>
 263  263  #include <string.h>
 264  264  #include <unistd.h>
      265 +#include <dirent.h>
 265  266  
 266  267  #include <sys/param.h>
 267  268  #include <sys/stat.h>
 268  269  #include <sys/types.h>
 269  270  #include <sys/utsname.h>
 270  271  #include <sys/wait.h>
 271  272  
 272  273  #define CW_F_CXX        0x01
 273  274  #define CW_F_SHADOW     0x02
 274  275  #define CW_F_EXEC       0x04
↓ open down ↓ 29 lines elided ↑ open up ↑
 304  305  } cw_compiler_t;
 305  306  
 306  307  typedef struct cw_ictx {
 307  308          struct cw_ictx  *i_next;
 308  309          cw_compiler_t   *i_compiler;
 309  310          struct aelist   *i_ae;
 310  311          uint32_t        i_flags;
 311  312          int             i_oldargc;
 312  313          char            **i_oldargv;
 313  314          pid_t           i_pid;
 314      -        char            i_discard[MAXPATHLEN];
      315 +        char            *i_tmpdir;
 315  316          char            *i_stderr;
 316  317  } cw_ictx_t;
 317  318  
 318  319  /*
 319  320   * Status values to indicate which Studio compiler and associated
 320  321   * flags are being used.
 321  322   */
 322  323  #define M32             0x01    /* -m32 - only on Studio 12 */
 323  324  #define M64             0x02    /* -m64 - only on Studio 12 */
 324  325  #define SS11            0x100   /* Studio 11 */
↓ open down ↓ 224 lines elided ↑ open up ↑
 549  550                  error(xarg);
 550  551  
 551  552          table++;
 552  553  
 553  554          while (*table != NULL) {
 554  555                  newae(h, *table);
 555  556                  table++;
 556  557          }
 557  558  }
 558  559  
      560 +/*
      561 + * The compiler wants the output file to end in appropriate extension.  If
      562 + * we're generating a name from whole cloth (path == NULL), we assume that
      563 + * extension to be .o, otherwise we match the extension of the caller.
      564 + */
      565 +static char *
      566 +discard_file_name(cw_ictx_t *ctx, const char *path)
      567 +{
      568 +        char *ret, *ext;
      569 +        char tmpl[] = "cwXXXXXX";
      570 +
      571 +        if (path == NULL) {
      572 +                ext = ".o";
      573 +        } else {
      574 +                ext = strrchr(path, '.');
      575 +        }
      576 +
      577 +        /*
      578 +         * We need absolute control over where the temporary file goes, since
      579 +         * we rely on it for cleanup so tempnam(3C) and tmpnam(3C) are
      580 +         * inappropriate (they use TMPDIR, preferentially).
      581 +         *
      582 +         * mkstemp(3C) doesn't actually help us, since the temporary file
      583 +         * isn't used by us, only its name.
      584 +         */
      585 +        if (mktemp(tmpl) == NULL)
      586 +                nomem();
      587 +
      588 +        (void) asprintf(&ret, "%s/%s%s", ctx->i_tmpdir, tmpl,
      589 +            (ext != NULL) ? ext : "");
      590 +
      591 +        if (ret == NULL)
      592 +                nomem();
      593 +
      594 +        return (ret);
      595 +}
      596 +
 559  597  static void
 560  598  do_gcc(cw_ictx_t *ctx)
 561  599  {
 562  600          int c;
 563  601          int nolibc = 0;
 564  602          int in_output = 0, seen_o = 0, c_files = 0;
 565  603          cw_op_t op = CW_O_LINK;
 566  604          char *model = NULL;
 567  605          char *nameflag;
 568      -        int     mflag = 0;
      606 +        int mflag = 0;
 569  607  
 570  608          if (ctx->i_flags & CW_F_PROG) {
 571  609                  newae(ctx->i_ae, "--version");
 572  610                  return;
 573  611          }
 574  612  
 575  613          newae(ctx->i_ae, "-fident");
 576  614          newae(ctx->i_ae, "-finline");
 577  615          newae(ctx->i_ae, "-fno-inline-functions");
 578  616          newae(ctx->i_ae, "-fno-builtin");
↓ open down ↓ 47 lines elided ↑ open up ↑
 626  664                              (arg[arglen - 1] == 'S' || arg[arglen - 1] == 's' ||
 627  665                              arg[arglen - 1] == 'c' || arg[arglen - 1] == 'i'))
 628  666                                  c_files++;
 629  667  
 630  668                          /*
 631  669                           * Otherwise, filenames and partial arguments
 632  670                           * are passed through for gcc to chew on.  However,
 633  671                           * output is always discarded for the secondary
 634  672                           * compiler.
 635  673                           */
 636      -                        if ((ctx->i_flags & CW_F_SHADOW) && in_output)
 637      -                                newae(ctx->i_ae, ctx->i_discard);
 638      -                        else
      674 +                        if ((ctx->i_flags & CW_F_SHADOW) && in_output) {
      675 +                                newae(ctx->i_ae, discard_file_name(ctx, arg));
      676 +                        } else {
 639  677                                  newae(ctx->i_ae, arg);
      678 +                        }
 640  679                          in_output = 0;
 641  680                          continue;
 642  681                  }
 643  682  
 644  683                  if (ctx->i_flags & CW_F_CXX) {
 645  684                          if (strncmp(arg, "-_g++=", 6) == 0) {
 646  685                                  newae(ctx->i_ae, strchr(arg, '=') + 1);
 647  686                                  continue;
 648  687                          }
 649  688                          if (strncmp(arg, "-compat=", 8) == 0) {
↓ open down ↓ 95 lines elided ↑ open up ↑
 745  784                  case 'w':
 746  785                          newae(ctx->i_ae, arg);
 747  786                          break;
 748  787                  case 'o':
 749  788                          seen_o = 1;
 750  789                          if (arglen == 1) {
 751  790                                  in_output = 1;
 752  791                                  newae(ctx->i_ae, arg);
 753  792                          } else if (ctx->i_flags & CW_F_SHADOW) {
 754  793                                  newae(ctx->i_ae, "-o");
 755      -                                newae(ctx->i_ae, ctx->i_discard);
      794 +                                newae(ctx->i_ae, discard_file_name(ctx, arg));
 756  795                          } else {
 757  796                                  newae(ctx->i_ae, arg);
 758  797                          }
 759  798                          break;
 760  799                  case 'D':
 761  800                          newae(ctx->i_ae, arg);
 762  801                          /*
 763  802                           * XXX  Clearly a hack ... do we need _KADB too?
 764  803                           */
 765  804                          if (strcmp(arg, "-D_KERNEL") == 0 ||
↓ open down ↓ 417 lines elided ↑ open up ↑
1183 1222                           * We could map -Qy into -Wl,-Qy etc.
1184 1223                           */
1185 1224                  default:
1186 1225                          error(arg);
1187 1226                          break;
1188 1227                  }
1189 1228          }
1190 1229  
1191 1230          free(nameflag);
1192 1231  
1193      -        if (c_files > 1 && (ctx->i_flags & CW_F_SHADOW) &&
1194      -            op != CW_O_PREPROCESS) {
     1232 +        /*
     1233 +         * When compiling multiple source files in a single invocation some
     1234 +         * compilers output objects into the current directory with
     1235 +         * predictable and conventional names.
     1236 +         *
     1237 +         * We prevent any attempt to compile multiple files at once so that
     1238 +         * any such objects created by a shadow can't escape into a later
     1239 +         * link-edit.
     1240 +         */
     1241 +        if (c_files > 1 && op != CW_O_PREPROCESS) {
1195 1242                  errx(2, "multiple source files are "
1196 1243                      "allowed only with -E or -P");
1197 1244          }
1198 1245  
1199 1246          /*
1200 1247           * Make sure that we do not have any unintended interactions between
1201 1248           * the xarch options passed in and the version of the Studio compiler
1202 1249           * used.
1203 1250           */
1204 1251          if ((mflag & (SS11|SS12)) == (SS11|SS12)) {
↓ open down ↓ 47 lines elided ↑ open up ↑
1252 1299  #endif
1253 1300                  break;
1254 1301          case (SS12|M64):
1255 1302                  break;
1256 1303          default:
1257 1304                  (void) fprintf(stderr,
1258 1305                      "Incompatible -xarch= and/or -m32/-m64 options used.\n");
1259 1306                  exit(2);
1260 1307          }
1261 1308  
1262      -        if ((op == CW_O_LINK || op == CW_O_PREPROCESS) &&
1263      -            (ctx->i_flags & CW_F_SHADOW))
1264      -                exit(0);
     1309 +        if (ctx->i_flags & CW_F_SHADOW) {
     1310 +                if (op == CW_O_PREPROCESS)
     1311 +                        exit(0);
     1312 +                else if (op == CW_O_LINK && c_files == 0)
     1313 +                        exit(0);
     1314 +        }
1265 1315  
1266 1316          if (model != NULL)
1267 1317                  newae(ctx->i_ae, model);
1268 1318          if (!nolibc)
1269 1319                  newae(ctx->i_ae, "-lc");
1270 1320          if (!seen_o && (ctx->i_flags & CW_F_SHADOW)) {
1271 1321                  newae(ctx->i_ae, "-o");
1272      -                newae(ctx->i_ae, ctx->i_discard);
     1322 +                newae(ctx->i_ae, discard_file_name(ctx, NULL));
1273 1323          }
1274 1324  }
1275 1325  
1276 1326  static void
1277 1327  do_smatch(cw_ictx_t *ctx)
1278 1328  {
1279 1329          if (ctx->i_flags & CW_F_PROG) {
1280 1330                  newae(ctx->i_ae, "--version");
1281 1331                  return;
1282 1332          }
↓ open down ↓ 12 lines elided ↑ open up ↑
1295 1345  
1296 1346          /*
1297 1347           * smatch can handle gcc's options.
1298 1348           */
1299 1349          do_gcc(ctx);
1300 1350  }
1301 1351  
1302 1352  static void
1303 1353  do_cc(cw_ictx_t *ctx)
1304 1354  {
1305      -        int in_output = 0, seen_o = 0;
     1355 +        int in_output = 0, seen_o = 0, c_files = 0;
1306 1356          cw_op_t op = CW_O_LINK;
1307 1357          char *nameflag;
1308 1358  
1309 1359          if (ctx->i_flags & CW_F_PROG) {
1310 1360                  newae(ctx->i_ae, "-V");
1311 1361                  return;
1312 1362          }
1313 1363  
1314 1364          if (asprintf(&nameflag, "-_%s=", ctx->i_compiler->c_name) == -1)
1315 1365                  nomem();
1316 1366  
1317 1367          while (--ctx->i_oldargc > 0) {
1318 1368                  char *arg = *++ctx->i_oldargv;
     1369 +                size_t arglen = strlen(arg);
1319 1370  
1320 1371                  if (strncmp(arg, "-_CC=", 5) == 0) {
1321 1372                          newae(ctx->i_ae, strchr(arg, '=') + 1);
1322 1373                          continue;
1323 1374                  }
1324 1375  
1325 1376                  if (*arg != '-') {
     1377 +                        if (!in_output && arglen > 2 &&
     1378 +                            arg[arglen - 2] == '.' &&
     1379 +                            (arg[arglen - 1] == 'S' || arg[arglen - 1] == 's' ||
     1380 +                            arg[arglen - 1] == 'c' || arg[arglen - 1] == 'i'))
     1381 +                                c_files++;
     1382 +
1326 1383                          if (in_output == 0 || !(ctx->i_flags & CW_F_SHADOW)) {
1327 1384                                  newae(ctx->i_ae, arg);
1328 1385                          } else {
1329 1386                                  in_output = 0;
1330      -                                newae(ctx->i_ae, ctx->i_discard);
     1387 +                                newae(ctx->i_ae, discard_file_name(ctx, arg));
1331 1388                          }
1332 1389                          continue;
1333 1390                  }
1334 1391                  switch (*(arg + 1)) {
1335 1392                  case '_':
1336 1393                          if ((strncmp(arg, nameflag, strlen(nameflag)) == 0) ||
1337 1394                              (strncmp(arg, "-_cc=", 5) == 0) ||
1338 1395                              (strncmp(arg, "-_sun=", 6) == 0)) {
1339 1396                                  newae(ctx->i_ae, strchr(arg, '=') + 1);
1340 1397                          }
↓ open down ↓ 3 lines elided ↑ open up ↑
1344 1401                          ctx->i_flags &= ~CW_F_ECHO;
1345 1402                          newae(ctx->i_ae, arg);
1346 1403                          break;
1347 1404                  case 'o':
1348 1405                          seen_o = 1;
1349 1406                          if (strlen(arg) == 2) {
1350 1407                                  in_output = 1;
1351 1408                                  newae(ctx->i_ae, arg);
1352 1409                          } else if (ctx->i_flags & CW_F_SHADOW) {
1353 1410                                  newae(ctx->i_ae, "-o");
1354      -                                newae(ctx->i_ae, ctx->i_discard);
     1411 +                                newae(ctx->i_ae, discard_file_name(ctx, arg));
1355 1412                          } else {
1356 1413                                  newae(ctx->i_ae, arg);
1357 1414                          }
1358 1415                          break;
1359 1416                  case 'c':
1360 1417                  case 'S':
1361 1418                          if (strlen(arg) == 2)
1362 1419                                  op = CW_O_COMPILE;
1363 1420                          newae(ctx->i_ae, arg);
1364 1421                          break;
↓ open down ↓ 2 lines elided ↑ open up ↑
1367 1424                          if (strlen(arg) == 2)
1368 1425                                  op = CW_O_PREPROCESS;
1369 1426                  /*FALLTHROUGH*/
1370 1427                  default:
1371 1428                          newae(ctx->i_ae, arg);
1372 1429                  }
1373 1430          }
1374 1431  
1375 1432          free(nameflag);
1376 1433  
1377      -        if ((op == CW_O_LINK || op == CW_O_PREPROCESS) &&
1378      -            (ctx->i_flags & CW_F_SHADOW))
1379      -                exit(0);
     1434 +        /* See the comment on this same code in do_gcc() */
     1435 +        if (c_files > 1 && op != CW_O_PREPROCESS) {
     1436 +                errx(2, "multiple source files are "
     1437 +                    "allowed only with -E or -P");
     1438 +        }
     1439 +
     1440 +        if (ctx->i_flags & CW_F_SHADOW) {
     1441 +                if (op == CW_O_PREPROCESS)
     1442 +                        exit(0);
     1443 +                else if (op == CW_O_LINK && c_files == 0)
     1444 +                        exit(0);
     1445 +        }
1380 1446  
1381 1447          if (!seen_o && (ctx->i_flags & CW_F_SHADOW)) {
1382 1448                  newae(ctx->i_ae, "-o");
1383      -                newae(ctx->i_ae, ctx->i_discard);
     1449 +                newae(ctx->i_ae, discard_file_name(ctx, NULL));
1384 1450          }
1385 1451  }
1386 1452  
1387 1453  static void
1388 1454  prepctx(cw_ictx_t *ctx)
1389 1455  {
1390 1456          newae(ctx->i_ae, ctx->i_compiler->c_path);
1391 1457  
1392 1458          if (ctx->i_flags & CW_F_PROG) {
1393 1459                  (void) printf("%s: %s\n", (ctx->i_flags & CW_F_SHADOW) ?
↓ open down ↓ 90 lines elided ↑ open up ↑
1484 1550                          if (WIFSIGNALED(status)) {
1485 1551                                  ret = -WTERMSIG(status);
1486 1552                                  break;
1487 1553                          } else if (WIFEXITED(status)) {
1488 1554                                  ret = WEXITSTATUS(status);
1489 1555                                  break;
1490 1556                          }
1491 1557                  }
1492 1558          } while (!WIFEXITED(status) && !WIFSIGNALED(status));
1493 1559  
1494      -        (void) unlink(ctx->i_discard);
1495      -
1496 1560          if (stat(ctx->i_stderr, &s) < 0) {
1497 1561                  warn("stat failed on child cleanup");
1498 1562                  return (-1);
1499 1563          }
1500 1564          if (s.st_size != 0) {
1501 1565                  FILE *f;
1502 1566  
1503 1567                  if ((f = fopen(ctx->i_stderr, "r")) != NULL) {
1504 1568                          while (fgets(buf, sizeof (buf), f))
1505 1569                                  (void) fprintf(stderr, "%s", buf);
↓ open down ↓ 9 lines elided ↑ open up ↑
1515 1579           */
1516 1580          if (ctx->i_flags & CW_F_PROG)
1517 1581                  return (0);
1518 1582  
1519 1583          return (ret);
1520 1584  }
1521 1585  
1522 1586  static int
1523 1587  exec_ctx(cw_ictx_t *ctx, int block)
1524 1588  {
1525      -        char *file;
1526      -
1527      -        /*
1528      -         * To avoid offending cc's sensibilities, the name of its output
1529      -         * file must end in '.o'.
1530      -         */
1531      -        if ((file = tempnam(NULL, ".cw")) == NULL) {
1532      -                nomem();
1533      -                return (-1);
1534      -        }
1535      -        (void) strlcpy(ctx->i_discard, file, MAXPATHLEN);
1536      -        (void) strlcat(ctx->i_discard, ".o", MAXPATHLEN);
1537      -        free(file);
1538      -
1539      -        if ((ctx->i_stderr = tempnam(NULL, ".cw")) == NULL) {
     1589 +        if ((ctx->i_stderr = tempnam(ctx->i_tmpdir, "cw")) == NULL) {
1540 1590                  nomem();
1541 1591                  return (-1);
1542 1592          }
1543 1593  
1544 1594          if ((ctx->i_pid = fork()) == 0) {
1545 1595                  int fd;
1546 1596  
1547 1597                  (void) fclose(stderr);
1548 1598                  if ((fd = open(ctx->i_stderr, O_WRONLY | O_CREAT | O_EXCL,
1549 1599                      0666)) < 0) {
↓ open down ↓ 50 lines elided ↑ open up ↑
1600 1650          } else if ((strcasecmp(token, "smatch") == 0)) {
1601 1651                  compiler->c_style = SMATCH;
1602 1652          } else {
1603 1653                  errx(1, "unknown compiler style: %s", token);
1604 1654          }
1605 1655  
1606 1656          if (tspec != NULL)
1607 1657                  errx(1, "Excess tokens in compiler: %s", spec);
1608 1658  }
1609 1659  
     1660 +static void
     1661 +cleanup(cw_ictx_t *ctx)
     1662 +{
     1663 +        DIR *dirp;
     1664 +        struct dirent *dp;
     1665 +        char buf[MAXPATHLEN];
     1666 +
     1667 +        if ((dirp = opendir(ctx->i_tmpdir)) == NULL) {
     1668 +                if (errno != ENOENT) {
     1669 +                        err(1, "couldn't open temp directory: %s",
     1670 +                            ctx->i_tmpdir);
     1671 +                } else {
     1672 +                        return;
     1673 +                }
     1674 +        }
     1675 +
     1676 +        errno = 0;
     1677 +        while ((dp = readdir(dirp)) != NULL) {
     1678 +                (void) snprintf(buf, MAXPATHLEN, "%s/%s", ctx->i_tmpdir,
     1679 +                    dp->d_name);
     1680 +
     1681 +                if (strncmp(dp->d_name, ".", strlen(dp->d_name)) == 0 ||
     1682 +                    strncmp(dp->d_name, "..", strlen(dp->d_name)) == 0)
     1683 +                        continue;
     1684 +
     1685 +                if (unlink(buf) == -1)
     1686 +                        err(1, "failed to unlink temp file: %s", dp->d_name);
     1687 +                errno = 0;
     1688 +        }
     1689 +
     1690 +        if (errno != 0) {
     1691 +                err(1, "failed to read temporary directory: %s",
     1692 +                    ctx->i_tmpdir);
     1693 +        }
     1694 +
     1695 +        (void) closedir(dirp);
     1696 +        if (rmdir(ctx->i_tmpdir) != 0) {
     1697 +                err(1, "failed to unlink temporary directory: %s",
     1698 +                    ctx->i_tmpdir);
     1699 +        }
     1700 +}
     1701 +
1610 1702  int
1611 1703  main(int argc, char **argv)
1612 1704  {
1613 1705          int ch;
1614 1706          cw_compiler_t primary = { NULL, NULL, 0 };
1615 1707          cw_compiler_t shadows[10];
1616 1708          int nshadows = 0;
1617 1709          int ret = 0;
1618 1710          boolean_t do_serial = B_FALSE;
1619 1711          boolean_t do_exec = B_FALSE;
1620 1712          boolean_t vflg = B_FALSE;
1621 1713          boolean_t Cflg = B_FALSE;
1622 1714          boolean_t cflg = B_FALSE;
1623 1715          boolean_t nflg = B_FALSE;
     1716 +        char *tmpdir;
1624 1717  
1625 1718          cw_ictx_t *main_ctx;
1626 1719  
1627 1720          static struct option longopts[] = {
1628 1721                  { "compiler", no_argument, NULL, 'c' },
1629 1722                  { "noecho", no_argument, NULL, 'n' },
1630 1723                  { "primary", required_argument, NULL, 'p' },
1631 1724                  { "shadow", required_argument, NULL, 's' },
1632 1725                  { "versions", no_argument, NULL, 'v' },
1633 1726                  { NULL, 0, NULL, 0 },
↓ open down ↓ 67 lines elided ↑ open up ↑
1701 1794          }
1702 1795  
1703 1796          if (vflg) {
1704 1797                  (void) printf("cw version %s\n", CW_VERSION);
1705 1798                  (void) fflush(stdout);
1706 1799                  main_ctx->i_flags &= ~CW_F_ECHO;
1707 1800                  main_ctx->i_flags |= CW_F_PROG | CW_F_EXEC;
1708 1801                  do_serial = 1;
1709 1802          }
1710 1803  
     1804 +        tmpdir = getenv("TMPDIR");
     1805 +        if (tmpdir == NULL)
     1806 +                tmpdir = "/tmp";
     1807 +
     1808 +        if (asprintf(&main_ctx->i_tmpdir, "%s/cw.XXXXXX", tmpdir) == -1)
     1809 +                nomem();
     1810 +
     1811 +        if ((main_ctx->i_tmpdir = mkdtemp(main_ctx->i_tmpdir)) == NULL)
     1812 +                errx(1, "failed to create temporary directory");
     1813 +
1711 1814          ret |= exec_ctx(main_ctx, do_serial);
1712 1815  
1713 1816          for (int i = 0; i < nshadows; i++) {
1714 1817                  int r;
1715 1818                  cw_ictx_t *shadow_ctx;
1716 1819  
1717 1820                  if ((shadow_ctx = newictx()) == NULL)
1718 1821                          nomem();
1719 1822  
1720      -                memcpy(shadow_ctx, main_ctx, sizeof (cw_ictx_t));
     1823 +                (void) memcpy(shadow_ctx, main_ctx, sizeof (cw_ictx_t));
1721 1824  
1722 1825                  shadow_ctx->i_flags |= CW_F_SHADOW;
1723 1826                  shadow_ctx->i_compiler = &shadows[i];
1724 1827  
1725 1828                  r = exec_ctx(shadow_ctx, do_serial);
1726 1829                  if (r == 0) {
1727 1830                          shadow_ctx->i_next = main_ctx->i_next;
1728 1831                          main_ctx->i_next = shadow_ctx;
1729 1832                  }
1730 1833                  ret |= r;
↓ open down ↓ 1 lines elided ↑ open up ↑
1732 1835  
1733 1836          if (!do_serial) {
1734 1837                  cw_ictx_t *next = main_ctx;
1735 1838                  while (next != NULL) {
1736 1839                          cw_ictx_t *toreap = next;
1737 1840                          next = next->i_next;
1738 1841                          ret |= reap(toreap);
1739 1842                  }
1740 1843          }
1741 1844  
     1845 +        cleanup(main_ctx);
1742 1846          return (ret);
1743 1847  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX