Print this page
10063 basic support for smatch
10153 checkpaths shouldn't check packaging exceptions


   9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  10  * or http://www.opensolaris.org/os/licensing.
  11  * See the License for the specific language governing permissions
  12  * and limitations under the License.
  13  *
  14  * When distributing Covered Code, include this CDDL HEADER in each
  15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16  * If applicable, add the following below this CDDL HEADER, with the
  17  * fields enclosed by brackets "[]" replaced with your own identifying
  18  * information: Portions Copyright [yyyy] [name of copyright owner]
  19  *
  20  * CDDL HEADER END
  21  */
  22 
  23 /*
  24  * Copyright 2018, Richard Lowe.
  25  */
  26 /*
  27  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  28  * Use is subject to license terms.


  29  */
  30 
  31 /*
  32  * Wrapper for the GNU C compiler to make it accept the Sun C compiler
  33  * arguments where possible.
  34  *
  35  * Since the translation is inexact, this is something of a work-in-progress.
  36  *
  37  */
  38 
  39 /* If you modify this file, you must increment CW_VERSION */
  40 #define CW_VERSION      "3.0"
  41 
  42 /*
  43  * -#           Verbose mode
  44  * -###         Show compiler commands built by driver, no compilation
  45  * -A<name[(tokens)]>     Preprocessor predicate assertion
  46  * -B<[static|dynamic]>   Specify dynamic or static binding
  47  * -C           Prevent preprocessor from removing comments
  48  * -c           Compile only - produce .o files, suppress linking


 274 #define CW_F_XLATE      0x10
 275 #define CW_F_PROG       0x20
 276 
 277 typedef enum cw_op {
 278         CW_O_NONE = 0,
 279         CW_O_PREPROCESS,
 280         CW_O_COMPILE,
 281         CW_O_LINK
 282 } cw_op_t;
 283 
 284 struct aelist {
 285         struct ae {
 286                 struct ae *ae_next;
 287                 char *ae_arg;
 288         } *ael_head, *ael_tail;
 289         int ael_argc;
 290 };
 291 
 292 typedef enum {
 293         GNU,
 294         SUN

 295 } compiler_style_t;
 296 
 297 typedef struct {
 298         char *c_name;
 299         char *c_path;
 300         compiler_style_t c_style;
 301 } cw_compiler_t;
 302 
 303 typedef struct cw_ictx {
 304         struct cw_ictx  *i_next;
 305         cw_compiler_t   *i_compiler;
 306         struct aelist   *i_ae;
 307         uint32_t        i_flags;
 308         int             i_oldargc;
 309         char            **i_oldargv;
 310         pid_t           i_pid;
 311         char            i_discard[MAXPATHLEN];
 312         char            *i_stderr;
 313 } cw_ictx_t;
 314 


1254                 (void) fprintf(stderr,
1255                     "Incompatible -xarch= and/or -m32/-m64 options used.\n");
1256                 exit(2);
1257         }
1258 
1259         if ((op == CW_O_LINK || op == CW_O_PREPROCESS) &&
1260             (ctx->i_flags & CW_F_SHADOW))
1261                 exit(0);
1262 
1263         if (model != NULL)
1264                 newae(ctx->i_ae, model);
1265         if (!nolibc)
1266                 newae(ctx->i_ae, "-lc");
1267         if (!seen_o && (ctx->i_flags & CW_F_SHADOW)) {
1268                 newae(ctx->i_ae, "-o");
1269                 newae(ctx->i_ae, ctx->i_discard);
1270         }
1271 }
1272 
1273 static void


























1274 do_cc(cw_ictx_t *ctx)
1275 {
1276         int in_output = 0, seen_o = 0;
1277         cw_op_t op = CW_O_LINK;
1278         char *nameflag;
1279 
1280         if (ctx->i_flags & CW_F_PROG) {
1281                 newae(ctx->i_ae, "-V");
1282                 return;
1283         }
1284 
1285         if (asprintf(&nameflag, "-_%s=", ctx->i_compiler->c_name) == -1)
1286                 nomem();
1287 
1288         while (--ctx->i_oldargc > 0) {
1289                 char *arg = *++ctx->i_oldargv;
1290 
1291                 if (strncmp(arg, "-_CC=", 5) == 0) {
1292                         newae(ctx->i_ae, strchr(arg, '=') + 1);
1293                         continue;


1359 prepctx(cw_ictx_t *ctx)
1360 {
1361         newae(ctx->i_ae, ctx->i_compiler->c_path);
1362 
1363         if (ctx->i_flags & CW_F_PROG) {
1364                 (void) printf("%s: %s\n", (ctx->i_flags & CW_F_SHADOW) ?
1365                     "shadow" : "primary", ctx->i_compiler->c_path);
1366                 (void) fflush(stdout);
1367         }
1368 
1369         if (!(ctx->i_flags & CW_F_XLATE))
1370                 return;
1371 
1372         switch (ctx->i_compiler->c_style) {
1373         case SUN:
1374                 do_cc(ctx);
1375                 break;
1376         case GNU:
1377                 do_gcc(ctx);
1378                 break;



1379         }
1380 }
1381 
1382 static int
1383 invoke(cw_ictx_t *ctx)
1384 {
1385         char **newargv;
1386         int ac;
1387         struct ae *a;
1388 
1389         if ((newargv = calloc(sizeof (*newargv), ctx->i_ae->ael_argc + 1)) ==
1390             NULL)
1391                 nomem();
1392 
1393         if (ctx->i_flags & CW_F_ECHO)
1394                 (void) fprintf(stderr, "+ ");
1395 
1396         for (ac = 0, a = ctx->i_ae->ael_head; a; a = a->ae_next, ac++) {
1397                 newargv[ac] = a->ae_arg;
1398                 if (ctx->i_flags & CW_F_ECHO)


1543 static void
1544 parse_compiler(const char *spec, cw_compiler_t *compiler)
1545 {
1546         char *tspec, *token;
1547 
1548         if ((tspec = strdup(spec)) == NULL)
1549                 nomem();
1550 
1551         if ((token = strsep(&tspec, ",")) == NULL)
1552                 errx(1, "Compiler is missing a name: %s", spec);
1553         compiler->c_name = token;
1554 
1555         if ((token = strsep(&tspec, ",")) == NULL)
1556                 errx(1, "Compiler is missing a path: %s", spec);
1557         compiler->c_path = token;
1558 
1559         if ((token = strsep(&tspec, ",")) == NULL)
1560                 errx(1, "Compiler is missing a style: %s", spec);
1561 
1562         if ((strcasecmp(token, "gnu") == 0) ||
1563             (strcasecmp(token, "gcc") == 0))
1564                 compiler->c_style = GNU;
1565         else if ((strcasecmp(token, "sun") == 0) ||
1566             (strcasecmp(token, "cc") == 0))
1567                 compiler->c_style = SUN;
1568         else


1569                 errx(1, "unknown compiler style: %s", token);

1570 
1571         if (tspec != NULL)
1572                 errx(1, "Excess tokens in compiler: %s", spec);
1573 }
1574 
1575 int
1576 main(int argc, char **argv)
1577 {
1578         int ch;
1579         cw_compiler_t primary = { NULL, NULL, 0 };
1580         cw_compiler_t shadows[10];
1581         int nshadows = 0;
1582         int ret = 0;
1583         boolean_t do_serial = B_FALSE;
1584         boolean_t do_exec = B_FALSE;
1585         boolean_t vflg = B_FALSE;
1586         boolean_t Cflg = B_FALSE;
1587         boolean_t cflg = B_FALSE;
1588         boolean_t nflg = B_FALSE;
1589 




   9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  10  * or http://www.opensolaris.org/os/licensing.
  11  * See the License for the specific language governing permissions
  12  * and limitations under the License.
  13  *
  14  * When distributing Covered Code, include this CDDL HEADER in each
  15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16  * If applicable, add the following below this CDDL HEADER, with the
  17  * fields enclosed by brackets "[]" replaced with your own identifying
  18  * information: Portions Copyright [yyyy] [name of copyright owner]
  19  *
  20  * CDDL HEADER END
  21  */
  22 
  23 /*
  24  * Copyright 2018, Richard Lowe.
  25  */
  26 /*
  27  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  28  * Use is subject to license terms.
  29  *
  30  * Copyright 2018 Joyent, Inc.
  31  */
  32 
  33 /*
  34  * Wrapper for the GNU C compiler to make it accept the Sun C compiler
  35  * arguments where possible.
  36  *
  37  * Since the translation is inexact, this is something of a work-in-progress.
  38  *
  39  */
  40 
  41 /* If you modify this file, you must increment CW_VERSION */
  42 #define CW_VERSION      "3.0"
  43 
  44 /*
  45  * -#           Verbose mode
  46  * -###         Show compiler commands built by driver, no compilation
  47  * -A<name[(tokens)]>     Preprocessor predicate assertion
  48  * -B<[static|dynamic]>   Specify dynamic or static binding
  49  * -C           Prevent preprocessor from removing comments
  50  * -c           Compile only - produce .o files, suppress linking


 276 #define CW_F_XLATE      0x10
 277 #define CW_F_PROG       0x20
 278 
 279 typedef enum cw_op {
 280         CW_O_NONE = 0,
 281         CW_O_PREPROCESS,
 282         CW_O_COMPILE,
 283         CW_O_LINK
 284 } cw_op_t;
 285 
 286 struct aelist {
 287         struct ae {
 288                 struct ae *ae_next;
 289                 char *ae_arg;
 290         } *ael_head, *ael_tail;
 291         int ael_argc;
 292 };
 293 
 294 typedef enum {
 295         GNU,
 296         SUN,
 297         SMATCH
 298 } compiler_style_t;
 299 
 300 typedef struct {
 301         char *c_name;
 302         char *c_path;
 303         compiler_style_t c_style;
 304 } cw_compiler_t;
 305 
 306 typedef struct cw_ictx {
 307         struct cw_ictx  *i_next;
 308         cw_compiler_t   *i_compiler;
 309         struct aelist   *i_ae;
 310         uint32_t        i_flags;
 311         int             i_oldargc;
 312         char            **i_oldargv;
 313         pid_t           i_pid;
 314         char            i_discard[MAXPATHLEN];
 315         char            *i_stderr;
 316 } cw_ictx_t;
 317 


1257                 (void) fprintf(stderr,
1258                     "Incompatible -xarch= and/or -m32/-m64 options used.\n");
1259                 exit(2);
1260         }
1261 
1262         if ((op == CW_O_LINK || op == CW_O_PREPROCESS) &&
1263             (ctx->i_flags & CW_F_SHADOW))
1264                 exit(0);
1265 
1266         if (model != NULL)
1267                 newae(ctx->i_ae, model);
1268         if (!nolibc)
1269                 newae(ctx->i_ae, "-lc");
1270         if (!seen_o && (ctx->i_flags & CW_F_SHADOW)) {
1271                 newae(ctx->i_ae, "-o");
1272                 newae(ctx->i_ae, ctx->i_discard);
1273         }
1274 }
1275 
1276 static void
1277 do_smatch(cw_ictx_t *ctx)
1278 {
1279         if (ctx->i_flags & CW_F_PROG) {
1280                 newae(ctx->i_ae, "--version");
1281                 return;
1282         }
1283 
1284         /*
1285          * Some sources shouldn't run smatch at all.
1286          */
1287         for (int i = 0; i < ctx->i_oldargc; i++) {
1288                 char *arg = ctx->i_oldargv[i];
1289 
1290                 if (strcmp(arg, "-_smatch=off") == 0) {
1291                         ctx->i_flags &= ~ (CW_F_EXEC | CW_F_ECHO);
1292                         return;
1293                 }
1294         }
1295 
1296         /*
1297          * smatch can handle gcc's options.
1298          */
1299         do_gcc(ctx);
1300 }
1301 
1302 static void
1303 do_cc(cw_ictx_t *ctx)
1304 {
1305         int in_output = 0, seen_o = 0;
1306         cw_op_t op = CW_O_LINK;
1307         char *nameflag;
1308 
1309         if (ctx->i_flags & CW_F_PROG) {
1310                 newae(ctx->i_ae, "-V");
1311                 return;
1312         }
1313 
1314         if (asprintf(&nameflag, "-_%s=", ctx->i_compiler->c_name) == -1)
1315                 nomem();
1316 
1317         while (--ctx->i_oldargc > 0) {
1318                 char *arg = *++ctx->i_oldargv;
1319 
1320                 if (strncmp(arg, "-_CC=", 5) == 0) {
1321                         newae(ctx->i_ae, strchr(arg, '=') + 1);
1322                         continue;


1388 prepctx(cw_ictx_t *ctx)
1389 {
1390         newae(ctx->i_ae, ctx->i_compiler->c_path);
1391 
1392         if (ctx->i_flags & CW_F_PROG) {
1393                 (void) printf("%s: %s\n", (ctx->i_flags & CW_F_SHADOW) ?
1394                     "shadow" : "primary", ctx->i_compiler->c_path);
1395                 (void) fflush(stdout);
1396         }
1397 
1398         if (!(ctx->i_flags & CW_F_XLATE))
1399                 return;
1400 
1401         switch (ctx->i_compiler->c_style) {
1402         case SUN:
1403                 do_cc(ctx);
1404                 break;
1405         case GNU:
1406                 do_gcc(ctx);
1407                 break;
1408         case SMATCH:
1409                 do_smatch(ctx);
1410                 break;
1411         }
1412 }
1413 
1414 static int
1415 invoke(cw_ictx_t *ctx)
1416 {
1417         char **newargv;
1418         int ac;
1419         struct ae *a;
1420 
1421         if ((newargv = calloc(sizeof (*newargv), ctx->i_ae->ael_argc + 1)) ==
1422             NULL)
1423                 nomem();
1424 
1425         if (ctx->i_flags & CW_F_ECHO)
1426                 (void) fprintf(stderr, "+ ");
1427 
1428         for (ac = 0, a = ctx->i_ae->ael_head; a; a = a->ae_next, ac++) {
1429                 newargv[ac] = a->ae_arg;
1430                 if (ctx->i_flags & CW_F_ECHO)


1575 static void
1576 parse_compiler(const char *spec, cw_compiler_t *compiler)
1577 {
1578         char *tspec, *token;
1579 
1580         if ((tspec = strdup(spec)) == NULL)
1581                 nomem();
1582 
1583         if ((token = strsep(&tspec, ",")) == NULL)
1584                 errx(1, "Compiler is missing a name: %s", spec);
1585         compiler->c_name = token;
1586 
1587         if ((token = strsep(&tspec, ",")) == NULL)
1588                 errx(1, "Compiler is missing a path: %s", spec);
1589         compiler->c_path = token;
1590 
1591         if ((token = strsep(&tspec, ",")) == NULL)
1592                 errx(1, "Compiler is missing a style: %s", spec);
1593 
1594         if ((strcasecmp(token, "gnu") == 0) ||
1595             (strcasecmp(token, "gcc") == 0)) {
1596                 compiler->c_style = GNU;
1597         } else if ((strcasecmp(token, "sun") == 0) ||
1598             (strcasecmp(token, "cc") == 0)) {
1599                 compiler->c_style = SUN;
1600         } else if ((strcasecmp(token, "smatch") == 0)) {
1601                 compiler->c_style = SMATCH;
1602         } else {
1603                 errx(1, "unknown compiler style: %s", token);
1604         }
1605 
1606         if (tspec != NULL)
1607                 errx(1, "Excess tokens in compiler: %s", spec);
1608 }
1609 
1610 int
1611 main(int argc, char **argv)
1612 {
1613         int ch;
1614         cw_compiler_t primary = { NULL, NULL, 0 };
1615         cw_compiler_t shadows[10];
1616         int nshadows = 0;
1617         int ret = 0;
1618         boolean_t do_serial = B_FALSE;
1619         boolean_t do_exec = B_FALSE;
1620         boolean_t vflg = B_FALSE;
1621         boolean_t Cflg = B_FALSE;
1622         boolean_t cflg = B_FALSE;
1623         boolean_t nflg = B_FALSE;
1624