• 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 "testbacktrace.h"
21 
22 #define STRING_MAX_LEN  256
23 
24 namespace testbt {
25     typedef const char* (*clibGetVer_t)();
26     typedef int (*clibMax_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 * func)46     std::string getSymbol(void *func) {
47         Dl_info info = { 0 };
48         dladdr(func, &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\n", info.dli_sname,
55             reinterpret_cast<uintptr_t>(func) - reinterpret_cast<uintptr_t>(info.dli_saddr),
56             reinterpret_cast<uintptr_t>(func) - 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 clibGetVer is loading and working properly
testVer(const char * filename)73     std::string testVer(const char *filename) {
74         printf("Testing clibGetVer\n");
75         void *handle = openLib(filename);
76         if (!handle) {
77             printf("Exiting!\n");
78             return "test failure";
79         }
80 
81         printf("\tLoading symbol clibGetVer\n");
82         clibGetVer_t getVer = reinterpret_cast<clibGetVer_t>(dlsym(handle, "clibGetVer"));
83 
84         printf("\tCalling clibGetVer\n");
85         const char *ver = getVer();
86 
87         closeLib(handle);
88 
89         printf("Exiting clibGetVer test\n");
90         return ver;
91     }
92 
93     // test if clibGetVer symbol can be backteaced properly after loading
testVerBT(const char * filename)94     std::string testVerBT(const char *filename) {
95         printf("Testing clibGetVer symbol backtrace\n");
96         void *handle = openLib(filename);
97         if (!handle) {
98             printf("Exiting!\n");
99             return "test failure";
100         }
101 
102         printf("\tLoading symbol clibGetVer\n");
103         clibGetVer_t getVer = reinterpret_cast<clibGetVer_t>(dlsym(handle, "clibGetVer"));
104 
105         auto ret = getSymbol(reinterpret_cast<void *>(getVer));
106         printf("\tThis is what dladdr returned: %s\n", ret.c_str());
107 
108         closeLib(handle);
109 
110         printf("Exiting clibGetVer symbol backtrace test\n");
111         return ret;
112     }
113 
114     // test if clibmax is loading and working properly
testMax(const char * filename,int a,int b)115     int testMax(const char *filename, int a, int b) {
116         printf("Testing clibMax\n");
117         void *handle = openLib(filename);
118         if (!handle) {
119             printf("Exiting!\n");
120             return -1;
121         }
122 
123         printf("\tLoading symbol clibMax\n");
124         clibMax_t libMax = reinterpret_cast<clibMax_t>(dlsym(handle, "clibMax"));
125 
126         printf("\tCalling clibMax\n");
127         int max = libMax(a, b);
128 
129         closeLib(handle);
130 
131         printf("Exiting clibMax test\n");
132         return max;
133     }
134 
135     // test if clibGetVer symbol can be backteaced properly after loading
testMaxBT(const char * filename)136     std::string testMaxBT(const char *filename) {
137         printf("Testing clibMax symbol backtrace\n");
138         void *handle = openLib(filename);
139         if (!handle) {
140             printf("Exiting!\n");
141             return "test failure";
142         }
143 
144         printf("\tLoading symbol clibMax\n");
145         clibMax_t libMax = reinterpret_cast<clibMax_t>(dlsym(handle, "clibMax"));
146 
147         auto ret = getSymbol(reinterpret_cast<void *>(libMax));
148         printf("\tThis is what dladdr returned: %s\n", ret.c_str());
149 
150         closeLib(handle);
151 
152         printf("Exiting clibMax symbol backtrace test\n");
153         return ret;
154     }
155 } // namespace testbt
156