symbols_test.c revision fc2512cfb727d49529d8ed99164db871f4829b73
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore * This file and its contents are supplied under the terms of the
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore * Common Development and Distribution License ("CDDL"), version 1.0.
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore * You may only use this file in accordance with the terms of version
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore * 1.0 of the CDDL.
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore * A full copy of the text of the CDDL should have accompanied this
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore * source. A copy of the CDDL is also available via the Internet at
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore * Copyright 2015 Garrett D'Amore <garrett@damore.org>
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi * Copyright 2016 Joyent, Inc.
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi * This program tests symbol visibility in different compilation environments.
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amorestatic char *compilation = "compilation.cfg";
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amoreconst char *compilers[] = {
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore#define MAXENV 64 /* maximum number of environments (bitmask width) */
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore#define MAXHDR 10 /* maximum # headers to require to access symbol */
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore#define MAXARG 20 /* maximum # of arguments */
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amorestatic int next_env = 0;
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amorestatic struct compile_env compile_env[MAXENV];
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchitypedef enum {
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amorefind_env_mask(const char *name, uint64_t *mask)
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore for (int i = 0; i < MAXENV; i++) {
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore strcmp(compile_env[i].ce_name, name) == 0) {
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore for (struct env_group *eg = env_groups; eg != NULL; eg = eg->eg_next) {
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amoreexpand_env(char *list, uint64_t *mask, char **erritem)
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore for (item = strtok(list, WS); item != NULL; item = strtok(NULL, WS)) {
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amoreexpand_env_list(char *list, uint64_t *test, uint64_t *need, char **erritem)
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore for (item = strtok(list, WS); item != NULL; item = strtok(NULL, WS)) {
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore switch (item[0]) {
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amoredo_env(char **fields, int nfields, char **err)
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore myasprintf(err, "number of fields (%d) != 3", nfields);
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore compile_env[next_env].ce_name = mystrdup(name);
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore compile_env[next_env].ce_lang = mystrdup(lang);
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore compile_env[next_env].ce_defs = mystrdup(defs);
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amoredo_env_group(char **fields, int nfields, char **err)
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore myasprintf(err, "number of fields (%d) != 2", nfields);
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore myasprintf(err, "reference to undefined env %s", item);
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi if (custr_append_vprintf(st_custr, fmt, va) == -1) {
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore for (int i = 0; i < MAXHDR && st->st_hdrs[i] != NULL; i++) {
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore addprogfmt("#include <%s>\n", st->st_hdrs[i]);
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi if (*s == '(') {
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore /* for function pointers, s is closing suffix, otherwise empty */
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore addprogfmt("test_value%s;\n", s); /* s usually empty */
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore addprogfmt("\ttest_value = %s;\n}", st->st_name);
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi addprogfmt("#if !defined(%s)", st->st_name);
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi addprogfmt("|| %s != %s", st->st_name, st->st_defval);
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi addprogfmt("\n#error %s is not defined or has the wrong value",
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore for (int i = 0; st->st_atypes[i] != NULL && i < MAXARG; i++) {
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore if (strcmp(st->st_atypes[i], "void") == 0) {
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore /* print the argument list */
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore * Close argument list, and closing ")" for func ptrs.
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore * Note that for non-function pointers, s will be empty
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore * below, otherwise it points to the trailing argument
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore /* add the function call */
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore for (int i = 0; st->st_atypes[i] != NULL && i < MAXARG; i++) {
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amoreadd_envs(struct sym_test *st, char *envs, char **err)
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore if (expand_env_list(envs, &st->st_test_mask, &st->st_need_mask,
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amoreadd_headers(struct sym_test *st, char *hdrs, char **err)
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore for (char *h = strsep(&hdrs, ";"); h != NULL; h = strsep(&hdrs, ";")) {
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amoreadd_arg_types(struct sym_test *st, char *atype, char **err)
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore for (a = strsep(&atype, ";"); a != NULL; a = strsep(&atype, ";")) {
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amoredo_type(char **fields, int nfields, char **err)
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore myasprintf(err, "number of fields (%d) != 3", nfields);
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amoredo_value(char **fields, int nfields, char **err)
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore myasprintf(err, "number of fields (%d) != 4", nfields);
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchido_define(char **fields, int nfields, char **err)
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi myasprintf(err, "number of fields (%d) != 4", nfields);
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi * A value to compare against is optional. trim will leave it as a null
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi * pointer if there's nothing there.
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amoredo_func(char **fields, int nfields, char **err)
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore myasprintf(err, "number of fields (%d) != 5", nfields);
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore return (st == NULL ? sym_tests : st->st_next);
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore * Iterate through tests. Pass in NULL for cenv to begin the iteration. For
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore * subsequent iterations, use the return value from the previous iteration.
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore * Returns NULL when there are no more environments.
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amoresym_test_env(struct sym_test *st, struct compile_env *cenv, int *need)
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore while ((i < MAXENV) && (b != 0)) {
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore test_debugf(t, "fopen(%s): %s", path, strerror(errno));
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore test_debugf(t, "----->> begin (%s) <<------", path);
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore test_debugf(t, "----->> end (%s) <<------", path);
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore (void) strlcpy(b, "/tmp/symbols_testXXXXXX", sizeof (b));
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore myasprintf(&lfile, "%s/compile_test.log", d);
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore myasprintf(&efile, "%s/compile_test.exe", d);
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore test_failed(t, "Unable to open %s for write: %s", cfile,
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore (void) fprintf(cf, "int main(int argc, char **argv) {\n");
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore (void) fprintf(cf, "#if defined(__SUNPRO_C)\n");
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore (void) fprintf(cf, "#elif defined(__GNUC__)\n");
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore "%s %s %s -o %s >/dev/null 2>&1",
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore if ((rv < 0) || !WIFEXITED(rv) || WEXITSTATUS(rv) != 0)
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore c89flags = "-Xc -errwarn=%all -v -xc99=%none " MFLAG;
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore c99flags = "-Xc -errwarn=%all -v -xc99=%all " MFLAG;
b599bd937c305a895426e8c412ca920ce7824850Robert Mustacchi c89flags = "-Wall -Werror -std=c89 -nostdinc "
b599bd937c305a895426e8c412ca920ce7824850Robert Mustacchi c99flags = "-Wall -Werror -std=c99 -nostdinc "
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi c11flags = "-Wall -Werror -std=c11 -nostdinc "
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore test_debugf(t, "Found unknown (unsupported) compiler");
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amoredo_compile(test_t t, struct sym_test *st, struct compile_env *cenv, int need)
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore test_failed(t, "fopen(%s): %s", cfile, strerror(errno));
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore if (fwrite(prog, 1, strlen(prog), dotc) < strlen(prog)) {
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore test_failed(t, "fwrite: %s", strerror(errno));
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore test_failed(t, "fclose: %s", strerror(errno));
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi } else if (strcmp(env_lang(cenv), "c11") == 0) {
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi test_failed(t, "compiler %s does not support %s", compiler,
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore myasprintf(&cmd, "%s %s %s -c %s -o %s >>%s 2>&1",
fc2512cfb727d49529d8ed99164db871f4829b73Robert Mustacchi compiler, cflags, env_defs(cenv), cfile, ofile, lfile);
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore test_failed(t, "fopen: %s", strerror(errno));
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore (void) fprintf(logf, "===================\n");
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore (void) fprintf(logf, "PROGRAM:\n%s\n", sym_test_prog(st));
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore (void) fprintf(logf, "EXPECT: %s\n", need ? "OK" : "FAIL");
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore test_failed(t, "error compiling in %s: %s", env_name(cenv),
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore test_failed(t, "symbol visible in %s", env_name(cenv));
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore test_failed(t, "error compiling in %s", env_name(cenv));
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore for (st = next_sym_test(NULL); st; st = next_sym_test(st)) {
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore if ((sym != NULL) && strcmp(sym, sym_test_name(st))) {
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore /* XXX: we really want a sym_test_desc() */
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore t = test_start("%s : %c%s", sym_test_name(st),
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore while ((optc = getopt(argc, argv, "DdfCs:c:")) != EOF) {
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore (void) fprintf(stderr, "Usage: %s [-df]\n", argv[0]);
de572d98af8238405c5d1292a788b1a85b0c68ebGarrett D'Amore "env", do_env, "env_group", do_env_group, NULL) < 0) {