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