Static Value-Flow Analysis
Loading...
Searching...
No Matches
ExtAPI.cpp
Go to the documentation of this file.
1//===- ExtAPI.cpp -- External functions -----------------------------------------//
2//
3// SVF: Static Value-Flow Analysis
4//
5// Copyright (C) <2013-2017> <Yulei Sui>
6//
7
8// This program is free software: you can redistribute it and/or modify
9// it under the terms of the GNU Affero General Public License as published by
10// the Free Software Foundation, either version 3 of the License, or
11// (at your option) any later version.
12
13// This program is distributed in the hope that it will be useful,
14// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16// GNU Affero General Public License for more details.
17
18// You should have received a copy of the GNU Affero General Public License
19// along with this program. If not, see <http://www.gnu.org/licenses/>.
20//
21//===----------------------------------------------------------------------===//
22
23/*
24 * ExtAPI.cpp
25 *
26 * Created on: July 1, 2022
27 * Author: Shuangxiang Kan
28 */
29
30#include "Util/ExtAPI.h"
31#include "Util/SVFUtil.h"
32#include "Util/Options.h"
33#include "Util/config.h"
34#include "SVFIR/SVFVariables.h"
35#include <algorithm>
36#include <ostream>
37
38using namespace SVF;
39
40ExtAPI* ExtAPI::extOp = nullptr;
41std::string ExtAPI::extBcPath = "";
42
44{
45 if (extOp == nullptr)
46 {
47 extOp = new ExtAPI;
48 }
49 return extOp;
50}
51
53{
54 if (extOp != nullptr)
55 {
56 delete extOp;
57 extOp = nullptr;
58 }
59}
60
61// Set extapi.bc file path
62bool ExtAPI::setExtBcPath(const std::string& path)
63{
64 if (!path.empty() && SVFUtil::fileExists(path))
65 {
67 return true;
68 }
69 return false;
70}
71
72// Get extapi.bc file path from SVF_DIR or npm installation
73static std::string getFilePath(const std::string& path)
74{
75 std::string bcFilePath;
76
77 if (path == "SVF_DIR")
78 {
79 const char* svfdir = getenv("SVF_DIR");
80 if (!svfdir)
81 return "";
82
84
85 if (!bcFilePath.empty() && bcFilePath.back() != '/')
86 bcFilePath.push_back('/');
87
88 bcFilePath.append(SVF_BUILD_TYPE "-build/lib/extapi.bc");
89 }
90 else if (path == "npm root")
91 {
92 // Check npm exists before calling `npm root`.
93 // If npm is missing, this command returns empty.
95 "command -v npm >/dev/null 2>&1 && npm root"
96 );
97
98 if (bcFilePath.empty())
99 return "";
100
101 if (!bcFilePath.empty() && bcFilePath.back() != '/')
102 bcFilePath.push_back('/');
103
104 bcFilePath.append("SVF/lib/extapi.bc");
105 }
106
107 return bcFilePath;
108}
109
110// Get extapi.bc path
112{
113 // Try to locate extapi.bc in the following order:
114 // 1. If setExtBcPath() has been called, use that path.
115 // 2. If the command line argument -extapi=path/to/extapi.bc is provided, use that path.
116 // 3. If SVF is being developed and used directly from a build directory, try the build dir (SVF_BUILD_DIR).
117 // 4. If the SVF_DIR environment variable is set, try $SVF_DIR with the standard relative path.
118 // 5. If installed via npm, use `npm root` and append the standard relative path.
119 // 6. As a last resort, use the directory of the loaded libSVFCore.so (or .dylib) and append extapi.bc.
120
121 std::vector<std::string> candidatePaths;
122
123 // 1. Use path set by setExtBcPath()
124 if (!extBcPath.empty())
125 return extBcPath;
126
127 // 2. Use command line argument -extapi=...
129 {
130 return extBcPath;
131 }
132 else
133 {
135 }
136
137 // 3. SVF developer: try build directory (SVF_BUILD_DIR)
138 if (setExtBcPath(SVF_BUILD_DIR "/lib/extapi.bc"))
139 {
140 return extBcPath;
141 }
142 else
143 {
144 candidatePaths.push_back(SVF_BUILD_DIR "/lib/extapi.bc");
145 }
146
147 // 4. Use $SVF_DIR environment variable + standard relative path
148 if (setExtBcPath(getFilePath("SVF_DIR")))
149 {
150 return extBcPath;
151 }
152 else
153 {
154 candidatePaths.push_back(getFilePath("SVF_DIR"));
155 }
156
157 // 5. Use npm root + standard relative path (for npm installations)
158 std::string npmPath = getFilePath("npm root");
160 {
161 return extBcPath;
162 }
163 else
164 {
165 candidatePaths.push_back(npmPath.empty() ? "npm root unavailable" : npmPath);
166 }
167
168 // 6. Use the directory of the loaded libSVFCore.so/.dylib + extapi.bc
169 std::string soPath = SVFUtil::getCurrentSOPath();
170 if (!soPath.empty())
171 {
172 std::string dir = soPath.substr(0, soPath.find_last_of('/'));
173 std::string candidate = dir + "/extapi.bc";
175 {
176 return extBcPath;
177 }
178 else
179 {
180 candidatePaths.push_back(candidate);
181 }
182 }
183
184 // If all candidate paths failed, print error and suggestions
185 SVFUtil::errs() << "ERROR: Failed to locate \"extapi.bc\". Tried the following candidate paths:" << std::endl;
186 for (const auto& path : candidatePaths)
187 {
188 SVFUtil::errs() << " " << path << std::endl;
189 }
190 SVFUtil::errs() << "To override the default locations for \"extapi.bc\", you can:" << std::endl
191 << "\t1. Use the command line argument \"-extapi=path/to/extapi.bc\"" << std::endl
192 << "\t2. Use the \"setExtBcPath()\" function *BEFORE* calling \"buildSVFModule()\"" << std::endl
193 << "\t3. Override the paths in \"include/SVF/Util/config.h\" (WARNING: will be overwritten "
194 << "when rebuilding SVF (generated by CMakeLists.txt))" << std::endl;
195 abort();
196}
197
198
199void ExtAPI::setExtFuncAnnotations(const FunObjVar* fun, const std::vector<std::string>& funcAnnotations)
200{
201 assert(fun && "Null FunObjVar* pointer");
203}
204
205bool ExtAPI::hasExtFuncAnnotation(const FunObjVar *fun, const std::string &funcAnnotation)
206{
207 assert(fun && "Null FunObjVar* pointer");
208 auto it = funObjVar2Annotations.find(fun);
209 if (it != funObjVar2Annotations.end())
210 {
211 for (const std::string& annotation : it->second)
212 if (annotation.find(funcAnnotation) != std::string::npos)
213 return true;
214 }
215 return false;
216}
217
218
219std::string ExtAPI::getExtFuncAnnotation(const FunObjVar* fun, const std::string& funcAnnotation)
220{
221 assert(fun && "Null FunObjVar* pointer");
222 auto it = funObjVar2Annotations.find(fun);
223 if (it != funObjVar2Annotations.end())
224 {
225 for (const std::string& annotation : it->second)
226 if (annotation.find(funcAnnotation) != std::string::npos)
227 return annotation;
228 }
229 return "";
230}
231
232const std::vector<std::string>& ExtAPI::getExtFuncAnnotations(const FunObjVar* fun)
233{
234 assert(fun && "Null FunObjVar* pointer");
235 auto it = funObjVar2Annotations.find(fun);
236 if (it != funObjVar2Annotations.end())
237 return it->second;
238 return funObjVar2Annotations[fun];
239}
240
242{
243 return F &&
244 (hasExtFuncAnnotation(F, "MEMCPY") || hasExtFuncAnnotation(F, "STRCPY")
245 || hasExtFuncAnnotation(F, "STRCAT"));
246}
247
249{
250 return F && hasExtFuncAnnotation(F, "MEMSET");
251}
252
254{
255 return F && hasExtFuncAnnotation(F, "ALLOC_HEAP_RET");
256}
257
258// Does (F) allocate a new object and assign it to one of its arguments?
260{
261 return F && hasExtFuncAnnotation(F, "ALLOC_HEAP_ARG");
262}
263
265{
266 return F && hasExtFuncAnnotation(F, "ALLOC_STACK_RET");
267}
268
269// Get the position of argument which holds the new object
271{
272 std::string allocArg = getExtFuncAnnotation(F, "ALLOC_HEAP_ARG");
273 assert(!allocArg.empty() && "Not an alloc call via argument or incorrect extern function annotation!");
274
275 std::string number;
276 for (char c : allocArg)
277 {
278 if (isdigit(c))
279 number.push_back(c);
280 }
281 assert(!number.empty() && "Incorrect naming convention for svf external functions(ALLOC_HEAP_ARG + number)?");
282 return std::stoi(number);
283}
284
285// Does (F) reallocate a new object?
287{
288 return F && hasExtFuncAnnotation(F, "REALLOC_HEAP_RET");
289}
291{
292 assert(F && "Null FunObjVar* pointer");
293 if (F->isDeclaration() || F->isIntrinsic())
294 return true;
295 else if (hasExtFuncAnnotation(F, "OVERWRITE") && getExtFuncAnnotations(F).size() == 1)
296 return false;
297 else
298 return !getExtFuncAnnotations(F).empty();
299}
static std::string getFilePath(const std::string &path)
Definition ExtAPI.cpp:73
const char *const const double number
Definition cJSON.h:268
bool is_alloc_stack_ret(const FunObjVar *F)
Definition ExtAPI.cpp:264
bool is_arg_alloc(const FunObjVar *F)
Definition ExtAPI.cpp:259
bool is_memcpy(const FunObjVar *F)
Definition ExtAPI.cpp:241
std::string getExtBcPath()
Definition ExtAPI.cpp:111
static std::string extBcPath
Definition ExtAPI.h:59
static ExtAPI * extOp
Definition ExtAPI.h:53
s32_t get_alloc_arg_pos(const FunObjVar *F)
Definition ExtAPI.cpp:270
static ExtAPI * getExtAPI()
Definition ExtAPI.cpp:43
bool is_ext(const FunObjVar *funObjVar)
Definition ExtAPI.cpp:290
std::string getExtFuncAnnotation(const FunObjVar *fun, const std::string &funcAnnotation)
Definition ExtAPI.cpp:219
bool is_realloc(const FunObjVar *F)
Definition ExtAPI.cpp:286
Map< const FunObjVar *, std::vector< std::string > > funObjVar2Annotations
Definition ExtAPI.h:56
void setExtFuncAnnotations(const FunObjVar *fun, const std::vector< std::string > &funcAnnotations)
Definition ExtAPI.cpp:199
ExtAPI()=default
static void destory()
Definition ExtAPI.cpp:52
static bool setExtBcPath(const std::string &path)
Definition ExtAPI.cpp:62
bool hasExtFuncAnnotation(const FunObjVar *fun, const std::string &funcAnnotation)
Definition ExtAPI.cpp:205
bool is_alloc(const FunObjVar *F)
Definition ExtAPI.cpp:253
const std::vector< std::string > & getExtFuncAnnotations(const FunObjVar *fun)
Definition ExtAPI.cpp:232
bool is_memset(const FunObjVar *F)
Definition ExtAPI.cpp:248
bool isIntrinsic() const
bool isDeclaration() const
static const Option< std::string > ExtAPIPath
Definition Options.h:210
int isdigit(int c)
Definition extapi.c:1016
char * getenv(const char *name)
Definition extapi.c:1214
std::ostream & errs()
Overwrite llvm::errs()
Definition SVFUtil.h:64
bool fileExists(const std::string &path)
Check whether a file exists at the given path.
Definition SVFUtil.cpp:271
std::string getCurrentSOPath()
Return the absolute path of the current module/executable.
Definition SVFUtil.cpp:302
std::string getStdoutFromCommand(const std::string &command)
Execute a shell command and capture its stdout output.
Definition SVFUtil.cpp:277
for isBitcode
Definition BasicTypes.h:70
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:76
signed s32_t
Definition GeneralType.h:68