1 /* Check ISA level on dlopened shared object.
2 Copyright (C) 2020-2022 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
18
19 #include <stdlib.h>
20 #include <stdbool.h>
21 #include <string.h>
22 #include <elf.h>
23 #include <get-isa-level.h>
24 #include <support/xdlfcn.h>
25 #include <support/check.h>
26 #include <support/test-driver.h>
27
28 static void
do_test_1(const char * modname,bool fail)29 do_test_1 (const char *modname, bool fail)
30 {
31 int (*fp) (void);
32 void *h;
33
34 h = dlopen (modname, RTLD_LAZY);
35 if (h == NULL)
36 {
37 const char *err = dlerror ();
38 if (fail)
39 {
40 if (strstr (err, "CPU ISA level is lower than required") == NULL)
41 FAIL_EXIT1 ("incorrect dlopen '%s' error: %s\n", modname, err);
42
43 return;
44 }
45
46 FAIL_EXIT1 ("cannot open '%s': %s\n", modname, err);
47 }
48
49 if (fail)
50 FAIL_EXIT1 ("dlopen '%s' should have failed\n", modname);
51
52 fp = xdlsym (h, "test");
53
54 if (fp () != 0)
55 FAIL_EXIT1 ("test () != 0\n");
56
57 dlclose (h);
58 }
59
60 static int
do_test(void)61 do_test (void)
62 {
63 const struct cpu_features *cpu_features = __get_cpu_features ();
64 unsigned int isa_level = get_isa_level (cpu_features);
65 bool has_isa_baseline = ((isa_level & GNU_PROPERTY_X86_ISA_1_BASELINE)
66 == GNU_PROPERTY_X86_ISA_1_BASELINE);
67 bool has_isa_v2 = ((isa_level & GNU_PROPERTY_X86_ISA_1_V2)
68 == GNU_PROPERTY_X86_ISA_1_V2);
69 bool has_isa_v3 = ((isa_level & GNU_PROPERTY_X86_ISA_1_V3)
70 == GNU_PROPERTY_X86_ISA_1_V3);
71 bool has_isa_v4 = ((isa_level & GNU_PROPERTY_X86_ISA_1_V4)
72 == GNU_PROPERTY_X86_ISA_1_V4);
73
74 if (!has_isa_baseline)
75 {
76 do_test_1 ("tst-isa-level-mod-1-baseline.so", true);
77 return EXIT_SUCCESS;
78 }
79
80 do_test_1 ("tst-isa-level-mod-1-baseline.so", false);
81
82 /* Skip on x86-64-v4 platforms since dlopen v4 module always works. */
83 if (has_isa_v4)
84 return EXIT_SUCCESS;
85
86 do_test_1 ("tst-isa-level-mod-1-v4.so", true);
87
88 /* Skip on x86-64-v3 platforms since dlopen v3 module always works. */
89 if (has_isa_v3)
90 return EXIT_SUCCESS;
91
92 do_test_1 ("tst-isa-level-mod-1-v3.so", true);
93
94 /* Skip on x86-64-v2 platforms since dlopen v2 module always works. */
95 if (has_isa_v2)
96 return EXIT_SUCCESS;
97
98 do_test_1 ("tst-isa-level-mod-1-v2.so", true);
99
100 return EXIT_SUCCESS;
101 }
102
103 #include <support/test-driver.c>
104