llvm.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. // SPDX-License-Identifier: GPL-2.0
  2. #include <stdio.h>
  3. #include <bpf/libbpf.h>
  4. #include <util/llvm-utils.h>
  5. #include <util/cache.h>
  6. #include "llvm.h"
  7. #include "tests.h"
  8. #include "debug.h"
  9. #include "util.h"
  10. #ifdef HAVE_LIBBPF_SUPPORT
  11. static int test__bpf_parsing(void *obj_buf, size_t obj_buf_sz)
  12. {
  13. struct bpf_object *obj;
  14. obj = bpf_object__open_buffer(obj_buf, obj_buf_sz, NULL);
  15. if (libbpf_get_error(obj))
  16. return TEST_FAIL;
  17. bpf_object__close(obj);
  18. return TEST_OK;
  19. }
  20. #else
  21. static int test__bpf_parsing(void *obj_buf __maybe_unused,
  22. size_t obj_buf_sz __maybe_unused)
  23. {
  24. pr_debug("Skip bpf parsing\n");
  25. return TEST_OK;
  26. }
  27. #endif
  28. static struct {
  29. const char *source;
  30. const char *desc;
  31. bool should_load_fail;
  32. } bpf_source_table[__LLVM_TESTCASE_MAX] = {
  33. [LLVM_TESTCASE_BASE] = {
  34. .source = test_llvm__bpf_base_prog,
  35. .desc = "Basic BPF llvm compile",
  36. },
  37. [LLVM_TESTCASE_KBUILD] = {
  38. .source = test_llvm__bpf_test_kbuild_prog,
  39. .desc = "kbuild searching",
  40. },
  41. [LLVM_TESTCASE_BPF_PROLOGUE] = {
  42. .source = test_llvm__bpf_test_prologue_prog,
  43. .desc = "Compile source for BPF prologue generation",
  44. },
  45. [LLVM_TESTCASE_BPF_RELOCATION] = {
  46. .source = test_llvm__bpf_test_relocation,
  47. .desc = "Compile source for BPF relocation",
  48. .should_load_fail = true,
  49. },
  50. };
  51. int
  52. test_llvm__fetch_bpf_obj(void **p_obj_buf,
  53. size_t *p_obj_buf_sz,
  54. enum test_llvm__testcase idx,
  55. bool force,
  56. bool *should_load_fail)
  57. {
  58. const char *source;
  59. const char *desc;
  60. const char *tmpl_old, *clang_opt_old;
  61. char *tmpl_new = NULL, *clang_opt_new = NULL;
  62. int err, old_verbose, ret = TEST_FAIL;
  63. if (idx >= __LLVM_TESTCASE_MAX)
  64. return TEST_FAIL;
  65. source = bpf_source_table[idx].source;
  66. desc = bpf_source_table[idx].desc;
  67. if (should_load_fail)
  68. *should_load_fail = bpf_source_table[idx].should_load_fail;
  69. /*
  70. * Skip this test if user's .perfconfig doesn't set [llvm] section
  71. * and clang is not found in $PATH, and this is not perf test -v
  72. */
  73. if (!force && (verbose <= 0 &&
  74. !llvm_param.user_set_param &&
  75. llvm__search_clang())) {
  76. pr_debug("No clang and no verbosive, skip this test\n");
  77. return TEST_SKIP;
  78. }
  79. /*
  80. * llvm is verbosity when error. Suppress all error output if
  81. * not 'perf test -v'.
  82. */
  83. old_verbose = verbose;
  84. if (verbose == 0)
  85. verbose = -1;
  86. *p_obj_buf = NULL;
  87. *p_obj_buf_sz = 0;
  88. if (!llvm_param.clang_bpf_cmd_template)
  89. goto out;
  90. if (!llvm_param.clang_opt)
  91. llvm_param.clang_opt = strdup("");
  92. err = asprintf(&tmpl_new, "echo '%s' | %s%s", source,
  93. llvm_param.clang_bpf_cmd_template,
  94. old_verbose ? "" : " 2>/dev/null");
  95. if (err < 0)
  96. goto out;
  97. err = asprintf(&clang_opt_new, "-xc %s", llvm_param.clang_opt);
  98. if (err < 0)
  99. goto out;
  100. tmpl_old = llvm_param.clang_bpf_cmd_template;
  101. llvm_param.clang_bpf_cmd_template = tmpl_new;
  102. clang_opt_old = llvm_param.clang_opt;
  103. llvm_param.clang_opt = clang_opt_new;
  104. err = llvm__compile_bpf("-", p_obj_buf, p_obj_buf_sz);
  105. llvm_param.clang_bpf_cmd_template = tmpl_old;
  106. llvm_param.clang_opt = clang_opt_old;
  107. verbose = old_verbose;
  108. if (err)
  109. goto out;
  110. ret = TEST_OK;
  111. out:
  112. free(tmpl_new);
  113. free(clang_opt_new);
  114. if (ret != TEST_OK)
  115. pr_debug("Failed to compile test case: '%s'\n", desc);
  116. return ret;
  117. }
  118. int test__llvm(struct test *test __maybe_unused, int subtest)
  119. {
  120. int ret;
  121. void *obj_buf = NULL;
  122. size_t obj_buf_sz = 0;
  123. bool should_load_fail = false;
  124. if ((subtest < 0) || (subtest >= __LLVM_TESTCASE_MAX))
  125. return TEST_FAIL;
  126. ret = test_llvm__fetch_bpf_obj(&obj_buf, &obj_buf_sz,
  127. subtest, false, &should_load_fail);
  128. if (ret == TEST_OK && !should_load_fail) {
  129. ret = test__bpf_parsing(obj_buf, obj_buf_sz);
  130. if (ret != TEST_OK) {
  131. pr_debug("Failed to parse test case '%s'\n",
  132. bpf_source_table[subtest].desc);
  133. }
  134. }
  135. free(obj_buf);
  136. return ret;
  137. }
  138. int test__llvm_subtest_get_nr(void)
  139. {
  140. return __LLVM_TESTCASE_MAX;
  141. }
  142. const char *test__llvm_subtest_get_desc(int subtest)
  143. {
  144. if ((subtest < 0) || (subtest >= __LLVM_TESTCASE_MAX))
  145. return NULL;
  146. return bpf_source_table[subtest].desc;
  147. }