• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 * Copyright (C) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *	http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include <cstdio>
16 #include <dlfcn.h>
17 #include <execinfo.h>
18 #include <securec.h>
19 
20 #include "bt-test.h"
21 
22 #define STRING_MAX_LEN  256
23 
24 namespace testbt {
25 typedef const char* (*clibGetVer_t)();
26 typedef int (*clibMaxMin_t)(int, int);
27 
28 // close library
closeLib(void * handle)29 void closeLib(void *handle) {
30     printf("\tClosing library\n");
31     dlclose(handle);
32 }
33 
34 // open library
openLib(const char * fileName)35 void *openLib(const char *fileName) {
36     printf("\tLoading library %s\n", fileName);
37     void *handle = dlopen(fileName, RTLD_LAZY);
38     if (!handle) {
39         printf("Error loading library!\n");
40         dlerror();
41     }
42 
43     return handle;
44 }
45 
getSymbol(void * saddr)46 std::string getSymbol(void *saddr) {
47     Dl_info info = { 0 };
48     dladdr(saddr, &info);
49 
50     char *str_buffer = static_cast<char *>(malloc(STRING_MAX_LEN * sizeof(char)));
51 
52     if (info.dli_sname && info.dli_saddr && info.dli_fbase && info.dli_fname) {
53         int ret = snprintf_s(str_buffer, STRING_MAX_LEN, STRING_MAX_LEN - 1,
54             "<%s+%#lx>[%#lx] -> %s", info.dli_sname,
55             reinterpret_cast<uintptr_t>(saddr) - reinterpret_cast<uintptr_t>(info.dli_saddr),
56             reinterpret_cast<uintptr_t>(saddr) - reinterpret_cast<uintptr_t>(info.dli_fbase), info.dli_fname);
57         if (ret < 0) {
58             free(str_buffer);
59             return "Error: failed to format symbol data\n";
60         }
61 
62         std::string str(str_buffer);
63         free(str_buffer);
64         return str;
65     } else {
66         free(str_buffer);
67     }
68 
69     return "Error: could not resolve symbol data\n";
70 }
71 
72 // test if functions without parameters are loading and working properly
test()73 std::string TestVer::test() {
74     printf("Testing symbol lookup\n");
75     void *handleA = openLib(fileNameA);
76     if (!handleA) {
77         printf("Exiting!\n");
78         return "test failure\n";
79     }
80     void *handleB = openLib(fileNameB);
81     if (!handleB) {
82         printf("Exiting!\n");
83         return "test failure\n";
84     }
85 
86     printf("\tLookup symbols %s, %s\n", symbolNameA, symbolNameB);
87     clibGetVer_t getA = reinterpret_cast<clibGetVer_t>(dlsym(handleA, symbolNameA));
88     if (!getA) {
89         printf("Error lookup symbol %s!\n", symbolNameA);
90         printf("Exiting!\n");
91         return "test failure\n";
92     }
93     clibGetVer_t getB = reinterpret_cast<clibGetVer_t>(dlsym(handleB, symbolNameB));
94     if (!getB) {
95         printf("Error lookup symbol %s!\n", symbolNameB);
96         printf("Exiting!\n");
97         return "test failure\n";
98     }
99 
100     printf("\tCalling %s, %s\n", symbolNameA, symbolNameB);
101     verA = getA();
102     verB = getB();
103 
104     closeLib(handleA);
105     closeLib(handleB);
106 
107     printf("Exiting symbol lookup test\n");
108     return "test not failed";
109 }
110 
111 // test if functions without parameters symbol can be backteaced properly after
112 // loading
test()113 std::string TestVerBT::test() {
114     printf("Testing symbol backtrace\n");
115     void *handleA = openLib(fileNameA);
116     if (!handleA) {
117         printf("Exiting!\n");
118         return "test failure\n";
119     }
120     void *handleB = openLib(fileNameB);
121     if (!handleB) {
122         printf("Exiting!\n");
123         return "test failure\n";
124     }
125 
126     printf("\tLookup symbols %s, %s\n", symbolNameA, symbolNameB);
127     clibGetVer_t getA = reinterpret_cast<clibGetVer_t>(dlsym(handleA, symbolNameA));
128     if (!getA) {
129         printf("Error lookup symbol %s!\n", symbolNameA);
130         printf("Exiting!\n");
131         return "test failure\n";
132     }
133     clibGetVer_t getB = reinterpret_cast<clibGetVer_t>(dlsym(handleB, symbolNameB));
134     if (!getB) {
135         printf("Error lookup symbol %s!\n", symbolNameB);
136         printf("Exiting!\n");
137         return "test failure\n";
138     }
139 
140     btA = getSymbol(reinterpret_cast<void *>(getA));
141     btB = getSymbol(reinterpret_cast<void *>(getB));
142     printf("\tFrom dladdr for %s: %s\n", symbolNameA, btA.c_str());
143     printf("\tFrom dladdr for %s: %s\n", symbolNameB, btB.c_str());
144 
145     closeLib(handleA);
146     closeLib(handleB);
147 
148     printf("Exiting symbol backtrace test\n");
149     return "test not failed";
150 }
151 
152 // test if functions with 2 parameters are loading and working properly
test()153 std::string TestMaxMin::test() {
154     printf("Testing symbol lookup\n");
155     void *handleA = openLib(fileNameA);
156     if (!handleA) {
157         printf("Exiting!\n");
158         return "test failure\n";
159     }
160     void *handleB = openLib(fileNameB);
161     if (!handleB) {
162         printf("Exiting!\n");
163         return "test failure\n";
164     }
165 
166     printf("\tLookup symbols %s, %s\n", symbolNameA, symbolNameB);
167     clibMaxMin_t getA = reinterpret_cast<clibMaxMin_t>(dlsym(handleA, symbolNameA));
168     if (!getA) {
169         printf("Error lookup symbol %s!\n", symbolNameA);
170         printf("Exiting!\n");
171         return "test failure\n";
172     }
173     clibMaxMin_t getB = reinterpret_cast<clibMaxMin_t>(dlsym(handleB, symbolNameB));
174     if (!getB) {
175         printf("Error lookup symbol %s!\n", symbolNameB);
176         printf("Exiting!\n");
177         return "test failure\n";
178     }
179 
180     printf("\tCalling %s, %s\n", symbolNameA, symbolNameB);
181     valA = getA(aa, ab);
182     valB = getB(ba, bb);
183 
184     closeLib(handleA);
185     closeLib(handleB);
186 
187     printf("Exiting symbol lookup test\n");
188     return "test not failed";
189 }
190 
191 // test if functions with 2 parameters symbol can be backteaced properly after
192 // loading
test()193 std::string TestMaxMinBT::test() {
194     printf("Testing symbol backtrace\n");
195     void *handleA = openLib(fileNameA);
196     if (!handleA) {
197         printf("Exiting!\n");
198         return "test failure\n";
199     }
200     void *handleB = openLib(fileNameB);
201     if (!handleB) {
202         printf("Exiting!\n");
203         return "test failure\n";
204     }
205 
206     printf("\tLookup symbols %s, %s\n", symbolNameA, symbolNameB);
207     clibMaxMin_t getA = reinterpret_cast<clibMaxMin_t>(dlsym(handleA, symbolNameA));
208     if (!getA) {
209         printf("Error lookup symbol %s!\n", symbolNameA);
210         printf("Exiting!\n");
211         return "test failure\n";
212     }
213     clibMaxMin_t getB = reinterpret_cast<clibMaxMin_t>(dlsym(handleB, symbolNameB));
214     if (!getB) {
215         printf("Error lookup symbol %s!\n", symbolNameB);
216         printf("Exiting!\n");
217         return "test failure\n";
218     }
219 
220     btA = getSymbol(reinterpret_cast<void *>(getA));
221     btB = getSymbol(reinterpret_cast<void *>(getB));
222     printf("\tFrom dladdr for %s: %s\n", symbolNameA, btA.c_str());
223     printf("\tFrom dladdr for %s: %s\n", symbolNameB, btB.c_str());
224 
225     closeLib(handleA);
226     closeLib(handleB);
227 
228     printf("Exiting symbol backtrace test\n");
229     return "test not failed";
230 }
231 } // namespace testbt