1 /*
   2  * This file and its contents are supplied under the terms of the
   3  * Common Development and Distribution License ("CDDL"), version 1.0.
   4  * You may only use this file in accordance with the terms of version
   5  * 1.0 of the CDDL.
   6  *
   7  * A full copy of the text of the CDDL should have accompanied this
   8  * source.  A copy of the CDDL is also available via the Internet at
   9  * http://www.illumos.org/license/CDDL.
  10  */
  11 
  12 /*
  13  * Copyright (c) 2019, Joyent, Inc.
  14  */
  15 
  16 /*
  17  * This tests that a forward declared in one object file that is defined in
  18  * another doesn't end up in the final one.
  19  */
  20 
  21 #include "check-common.h"
  22 
  23 static check_symbol_t check_syms[] = {
  24         { "list", "foo_list_t" },
  25         { NULL }
  26 };
  27 
  28 static check_member_t check_member_foo_list[] = {
  29         { "count", "int", 0 },
  30 #ifdef  TARGET_LP64
  31         { "head", "struct foo *", 8 * NBBY },
  32         { "tail", "struct foo *", 16 * NBBY },
  33 #else
  34         { "head", "struct foo *", 4 * NBBY },
  35         { "tail", "struct foo *", 8 * NBBY },
  36 #endif
  37         { NULL }
  38 };
  39 
  40 static check_member_t check_member_foo[] = {
  41         { "next", "struct foo *", 0 * NBBY },
  42 #ifdef  TARGET_LP64
  43         { "left", "int", 8 * NBBY },
  44         { "right", "int", 12 * NBBY },
  45         { "count", "int", 16 * NBBY },
  46 #else
  47         { "left", "int", 4 * NBBY },
  48         { "right", "int", 8 * NBBY },
  49         { "count", "int", 12 * NBBY },
  50 #endif
  51         { NULL }
  52 };
  53 
  54 static check_member_test_t members[] = {
  55 #ifdef  TARGET_LP64
  56         { "struct foo_list", CTF_K_STRUCT, 24, check_member_foo_list },
  57         { "struct foo", CTF_K_STRUCT, 24, check_member_foo },
  58 #else
  59         { "struct foo_list", CTF_K_STRUCT, 12, check_member_foo_list },
  60         { "struct foo", CTF_K_STRUCT, 16, check_member_foo },
  61 #endif
  62         { NULL }
  63 };
  64 
  65 static int
  66 ctf_merge_forward_cb(ctf_id_t id, boolean_t root, void *arg)
  67 {
  68         ctf_file_t *fp = arg;
  69         char buf[2048];
  70 
  71         if (ctf_type_kind(fp, id) != CTF_K_FORWARD)
  72                 return (0);
  73 
  74         if (ctf_type_name(fp, id, buf, sizeof (buf)) == NULL) {
  75                 warnx("failed to lookup the name of type %ld: %s", id,
  76                     ctf_errmsg(ctf_errno(fp)));
  77                 return (1);
  78         }
  79 
  80         /*
  81          * If a forward shows up, that's OK. It's only bad if it's the name of
  82          * the one we created.
  83          */
  84         if (strcmp("struct foo", buf) == 0) {
  85                 warnx("encountered forward type for struct foo that "
  86                     "shouldn't exist");
  87                 return (1);
  88         }
  89 
  90         return (0);
  91 }
  92 
  93 int
  94 main(int argc, char *argv[])
  95 {
  96         int i, ret = 0;
  97 
  98         if (argc < 2) {
  99                 errx(EXIT_FAILURE, "missing test files");
 100         }
 101 
 102         for (i = 1; i < argc; i++) {
 103                 ctf_file_t *fp;
 104                 uint_t j;
 105 
 106                 if ((fp = ctf_open(argv[i], &ret)) == NULL) {
 107                         warnx("failed to open %s: %s", argv[i],
 108                             ctf_errmsg(ret));
 109                         ret = EXIT_FAILURE;
 110                         continue;
 111                 }
 112 
 113                 if (!ctftest_check_symbols(fp, check_syms))
 114                         ret = EXIT_FAILURE;
 115 
 116                 for (j = 0; members[j].cmt_type != NULL; j++) {
 117                         if (!ctftest_check_members(members[j].cmt_type, fp,
 118                             members[j].cmt_kind, members[j].cmt_size,
 119                             members[j].cmt_members)) {
 120                                 ret = EXIT_FAILURE;
 121                         }
 122                 }
 123 
 124                 if (ctf_type_iter(fp, B_TRUE, ctf_merge_forward_cb, fp) != 0) {
 125                         ret = EXIT_FAILURE;
 126                 }
 127 
 128                 ctf_close(fp);
 129         }
 130 
 131         return (ret);
 132 }