linux/tools/perf/tests/llvm.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2#include <stdio.h>
   3#include <stdlib.h>
   4#include <string.h>
   5#include "tests.h"
   6#include "debug.h"
   7
   8#ifdef HAVE_LIBBPF_SUPPORT
   9#include <bpf/libbpf.h>
  10#include <util/llvm-utils.h>
  11#include "llvm.h"
  12static int test__bpf_parsing(void *obj_buf, size_t obj_buf_sz)
  13{
  14        struct bpf_object *obj;
  15
  16        obj = bpf_object__open_mem(obj_buf, obj_buf_sz, NULL);
  17        if (libbpf_get_error(obj))
  18                return TEST_FAIL;
  19        bpf_object__close(obj);
  20        return TEST_OK;
  21}
  22
  23static struct {
  24        const char *source;
  25        const char *desc;
  26        bool should_load_fail;
  27} bpf_source_table[__LLVM_TESTCASE_MAX] = {
  28        [LLVM_TESTCASE_BASE] = {
  29                .source = test_llvm__bpf_base_prog,
  30                .desc = "Basic BPF llvm compile",
  31        },
  32        [LLVM_TESTCASE_KBUILD] = {
  33                .source = test_llvm__bpf_test_kbuild_prog,
  34                .desc = "kbuild searching",
  35        },
  36        [LLVM_TESTCASE_BPF_PROLOGUE] = {
  37                .source = test_llvm__bpf_test_prologue_prog,
  38                .desc = "Compile source for BPF prologue generation",
  39        },
  40        [LLVM_TESTCASE_BPF_RELOCATION] = {
  41                .source = test_llvm__bpf_test_relocation,
  42                .desc = "Compile source for BPF relocation",
  43                .should_load_fail = true,
  44        },
  45};
  46
  47int
  48test_llvm__fetch_bpf_obj(void **p_obj_buf,
  49                         size_t *p_obj_buf_sz,
  50                         enum test_llvm__testcase idx,
  51                         bool force,
  52                         bool *should_load_fail)
  53{
  54        const char *source;
  55        const char *desc;
  56        const char *tmpl_old, *clang_opt_old;
  57        char *tmpl_new = NULL, *clang_opt_new = NULL;
  58        int err, old_verbose, ret = TEST_FAIL;
  59
  60        if (idx >= __LLVM_TESTCASE_MAX)
  61                return TEST_FAIL;
  62
  63        source = bpf_source_table[idx].source;
  64        desc = bpf_source_table[idx].desc;
  65        if (should_load_fail)
  66                *should_load_fail = bpf_source_table[idx].should_load_fail;
  67
  68        /*
  69         * Skip this test if user's .perfconfig doesn't set [llvm] section
  70         * and clang is not found in $PATH
  71         */
  72        if (!force && (!llvm_param.user_set_param &&
  73                       llvm__search_clang())) {
  74                pr_debug("No clang, skip this test\n");
  75                return TEST_SKIP;
  76        }
  77
  78        /*
  79         * llvm is verbosity when error. Suppress all error output if
  80         * not 'perf test -v'.
  81         */
  82        old_verbose = verbose;
  83        if (verbose == 0)
  84                verbose = -1;
  85
  86        *p_obj_buf = NULL;
  87        *p_obj_buf_sz = 0;
  88
  89        if (!llvm_param.clang_bpf_cmd_template)
  90                goto out;
  91
  92        if (!llvm_param.clang_opt)
  93                llvm_param.clang_opt = strdup("");
  94
  95        err = asprintf(&tmpl_new, "echo '%s' | %s%s", source,
  96                       llvm_param.clang_bpf_cmd_template,
  97                       old_verbose ? "" : " 2>/dev/null");
  98        if (err < 0)
  99                goto out;
 100        err = asprintf(&clang_opt_new, "-xc %s", llvm_param.clang_opt);
 101        if (err < 0)
 102                goto out;
 103
 104        tmpl_old = llvm_param.clang_bpf_cmd_template;
 105        llvm_param.clang_bpf_cmd_template = tmpl_new;
 106        clang_opt_old = llvm_param.clang_opt;
 107        llvm_param.clang_opt = clang_opt_new;
 108
 109        err = llvm__compile_bpf("-", p_obj_buf, p_obj_buf_sz);
 110
 111        llvm_param.clang_bpf_cmd_template = tmpl_old;
 112        llvm_param.clang_opt = clang_opt_old;
 113
 114        verbose = old_verbose;
 115        if (err)
 116                goto out;
 117
 118        ret = TEST_OK;
 119out:
 120        free(tmpl_new);
 121        free(clang_opt_new);
 122        if (ret != TEST_OK)
 123                pr_debug("Failed to compile test case: '%s'\n", desc);
 124        return ret;
 125}
 126
 127static int test__llvm(int subtest)
 128{
 129        int ret;
 130        void *obj_buf = NULL;
 131        size_t obj_buf_sz = 0;
 132        bool should_load_fail = false;
 133
 134        if ((subtest < 0) || (subtest >= __LLVM_TESTCASE_MAX))
 135                return TEST_FAIL;
 136
 137        ret = test_llvm__fetch_bpf_obj(&obj_buf, &obj_buf_sz,
 138                                       subtest, false, &should_load_fail);
 139
 140        if (ret == TEST_OK && !should_load_fail) {
 141                ret = test__bpf_parsing(obj_buf, obj_buf_sz);
 142                if (ret != TEST_OK) {
 143                        pr_debug("Failed to parse test case '%s'\n",
 144                                 bpf_source_table[subtest].desc);
 145                }
 146        }
 147        free(obj_buf);
 148
 149        return ret;
 150}
 151#endif //HAVE_LIBBPF_SUPPORT
 152
 153static int test__llvm__bpf_base_prog(struct test_suite *test __maybe_unused,
 154                                     int subtest __maybe_unused)
 155{
 156#ifdef HAVE_LIBBPF_SUPPORT
 157        return test__llvm(LLVM_TESTCASE_BASE);
 158#else
 159        pr_debug("Skip LLVM test because BPF support is not compiled\n");
 160        return TEST_SKIP;
 161#endif
 162}
 163
 164static int test__llvm__bpf_test_kbuild_prog(struct test_suite *test __maybe_unused,
 165                                            int subtest __maybe_unused)
 166{
 167#ifdef HAVE_LIBBPF_SUPPORT
 168        return test__llvm(LLVM_TESTCASE_KBUILD);
 169#else
 170        pr_debug("Skip LLVM test because BPF support is not compiled\n");
 171        return TEST_SKIP;
 172#endif
 173}
 174
 175static int test__llvm__bpf_test_prologue_prog(struct test_suite *test __maybe_unused,
 176                                              int subtest __maybe_unused)
 177{
 178#ifdef HAVE_LIBBPF_SUPPORT
 179        return test__llvm(LLVM_TESTCASE_BPF_PROLOGUE);
 180#else
 181        pr_debug("Skip LLVM test because BPF support is not compiled\n");
 182        return TEST_SKIP;
 183#endif
 184}
 185
 186static int test__llvm__bpf_test_relocation(struct test_suite *test __maybe_unused,
 187                                           int subtest __maybe_unused)
 188{
 189#ifdef HAVE_LIBBPF_SUPPORT
 190        return test__llvm(LLVM_TESTCASE_BPF_RELOCATION);
 191#else
 192        pr_debug("Skip LLVM test because BPF support is not compiled\n");
 193        return TEST_SKIP;
 194#endif
 195}
 196
 197
 198static struct test_case llvm_tests[] = {
 199#ifdef HAVE_LIBBPF_SUPPORT
 200        TEST_CASE("Basic BPF llvm compile", llvm__bpf_base_prog),
 201        TEST_CASE("kbuild searching", llvm__bpf_test_kbuild_prog),
 202        TEST_CASE("Compile source for BPF prologue generation",
 203                  llvm__bpf_test_prologue_prog),
 204        TEST_CASE("Compile source for BPF relocation", llvm__bpf_test_relocation),
 205#else
 206        TEST_CASE_REASON("Basic BPF llvm compile", llvm__bpf_base_prog, "not compiled in"),
 207        TEST_CASE_REASON("kbuild searching", llvm__bpf_test_kbuild_prog, "not compiled in"),
 208        TEST_CASE_REASON("Compile source for BPF prologue generation",
 209                        llvm__bpf_test_prologue_prog, "not compiled in"),
 210        TEST_CASE_REASON("Compile source for BPF relocation",
 211                        llvm__bpf_test_relocation, "not compiled in"),
 212#endif
 213        { .name = NULL, }
 214};
 215
 216struct test_suite suite__llvm = {
 217        .desc = "LLVM search and compile",
 218        .test_cases = llvm_tests,
 219};
 220