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 <ostream>
35#include <sys/stat.h>
36
37using namespace SVF;
38
39ExtAPI* ExtAPI::extOp = nullptr;
40std::string ExtAPI::extBcPath = "";
41
43{
44 if (extOp == nullptr)
45 {
46 extOp = new ExtAPI;
47 }
48 return extOp;
49}
50
52{
53 if (extOp != nullptr)
54 {
55 delete extOp;
56 extOp = nullptr;
57 }
58}
59
60// Set extapi.bc file path
61bool ExtAPI::setExtBcPath(const std::string& path)
62{
63 struct stat statbuf;
64 if (!path.empty() && !stat(path.c_str(), &statbuf))
65 {
67 return true;
68 }
69 return false;
70}
71
72// Get environment variables $SVF_DIR and "npm root" through popen() method
73static std::string GetStdoutFromCommand(const std::string& command)
74{
75 char buffer[128];
76 std::string result = "";
77 // Open pipe to file
78 FILE* pipe = popen(command.c_str(), "r");
79 if (!pipe)
80 {
81 return "popen failed!";
82 }
83 // read till end of process:
84 while (!feof(pipe))
85 {
86 // use buffer to read and add to result
87 if (fgets(buffer, 128, pipe) != NULL)
88 result += buffer;
89 }
90 pclose(pipe);
91 // remove "\n"
92 result.erase(remove(result.begin(), result.end(), '\n'), result.end());
93 return result;
94}
95
96// Get extapi.bc file path in npm
97static std::string getFilePath(const std::string& path)
98{
99 std::string bcFilePath = "";
100 if (path.compare("SVF_DIR") == 0)
101 {
102 char const* svfdir = getenv("SVF_DIR");
103 if (svfdir)
105 }
106 else if (path.compare("npm root") == 0)
107 {
109 bcFilePath.append("/SVF");
110 }
111
112 if (!bcFilePath.empty() && bcFilePath.back() != '/')
113 bcFilePath.push_back('/');
114 bcFilePath.append(SVF_BUILD_TYPE "-build").append("/lib/extapi.bc");
115 return bcFilePath;
116}
117
118// Get extapi.bc path
120{
121 // Default ways of retrieving extapi.bc (in order of precedence):
122 // 1. Set `path/to/extapi.bc` through `setExtBcPath()`
123 // 2. Set `path/to/extapi.bc` through the command line argument `-extapi=path/to/extapi.bc`
124 // 3. Get location generated by CMakeLists.txt from `config.h` header file (if SVF was installed)
125 // 4. Get location in build tree based from `config.h` header file (if SVF was only built)
126 // 5. Get location based on environment variable $ENV{SVF_DIR}
127 // 6. Search for `extapi.bc` from root directory for npm installation (iff SVF installed through npm)
128
129 // 1. Set `path/to/extapi.bc` through `setExtBcPath()`
130 if (!extBcPath.empty())
131 return extBcPath;
132
133 // 2. Set `path/to/extapi.bc` through the command line argument `-extapi=path/to/extapi.bc`
135 return extBcPath;
136
137 // 3. Get location generated by CMakeLists.txt from `config.h` header file (if SVF was installed)
138 if (setExtBcPath(SVF_EXTAPI_BC)) // Full path is available (for custom file names)
139 return extBcPath;
140 if (setExtBcPath(SVF_EXTAPI_DIR "/extapi.bc")) // Based on directory & default filename
141 return extBcPath;
142
143 // 4. Get location in build tree based from `config.h` header file (if SVF was only built)
144 if (setExtBcPath(SVF_BUILD_DIR "/lib/extapi.bc"))
145 return extBcPath;
146
147 // 5. Get location based on environment variable $ENV{SVF_DIR}
148 if (setExtBcPath(getFilePath("SVF_DIR")))
149 return extBcPath;
150
151 // 6. Search for `extapi.bc` from root directory for npm installation (iff SVF installed through npm)
152 if (setExtBcPath(getFilePath("npm root")))
153 return extBcPath;
154
155 SVFUtil::errs() << "ERROR: Failed to find \"extapi.bc\" LLVM bitcode file in " << extBcPath << std::endl
156 << "To override the default locations for \"extapi.bc\", you can:" << std::endl
157 << "\t1. Use the command line argument \"-extapi=path/to/extapi.bc\"" << std::endl
158 << "\t2. Use the \"setExtBcPath()\" function *BEFORE* calling \"buildSVFModule()\"" << std::endl
159 << "\t3. Override the paths in \"svf/Util/config.h\" (WARNING: will be overwritten when "
160 << "rebuilding SVF (generated by CMakeLists.txt))" << std::endl;
161 abort();
162}
163
164void ExtAPI::setExtFuncAnnotations(const SVFFunction* fun, const std::vector<std::string>& funcAnnotations)
165{
166 assert(fun && "Null SVFFunction* pointer");
168}
169
170bool ExtAPI::hasExtFuncAnnotation(const SVFFunction* fun, const std::string& funcAnnotation)
171{
172 assert(fun && "Null SVFFunction* pointer");
173 auto it = func2Annotations.find(fun);
174 if (it != func2Annotations.end())
175 {
176 for (const std::string& annotation : it->second)
177 if (annotation.find(funcAnnotation) != std::string::npos)
178 return true;
179 }
180 return false;
181}
182
183std::string ExtAPI::getExtFuncAnnotation(const SVFFunction* fun, const std::string& funcAnnotation)
184{
185 assert(fun && "Null SVFFunction* pointer");
186 auto it = func2Annotations.find(fun);
187 if (it != func2Annotations.end())
188 {
189 for (const std::string& annotation : it->second)
190 if (annotation.find(funcAnnotation) != std::string::npos)
191 return annotation;
192 }
193 return "";
194}
195
196const std::vector<std::string>& ExtAPI::getExtFuncAnnotations(const SVFFunction* fun)
197{
198 assert(fun && "Null SVFFunction* pointer");
199 auto it = func2Annotations.find(fun);
200 if (it != func2Annotations.end())
201 return it->second;
202 return func2Annotations[fun];
203}
204
206{
207 return F &&
208 (hasExtFuncAnnotation(F, "MEMCPY") || hasExtFuncAnnotation(F, "STRCPY")
209 || hasExtFuncAnnotation(F, "STRCAT"));
210}
211
213{
214 return F && hasExtFuncAnnotation(F, "MEMSET");
215}
216
218{
219 return F && hasExtFuncAnnotation(F, "ALLOC_HEAP_RET");
220}
221
222// Does (F) allocate a new object and assign it to one of its arguments?
224{
225 return F && hasExtFuncAnnotation(F, "ALLOC_HEAP_ARG");
226}
227
229{
230 return F && hasExtFuncAnnotation(F, "ALLOC_STACK_RET");
231}
232
233// Get the position of argument which holds the new object
235{
236 std::string allocArg = getExtFuncAnnotation(F, "ALLOC_HEAP_ARG");
237 assert(!allocArg.empty() && "Not an alloc call via argument or incorrect extern function annotation!");
238
239 std::string number;
240 for (char c : allocArg)
241 {
242 if (isdigit(c))
243 number.push_back(c);
244 }
245 assert(!number.empty() && "Incorrect naming convention for svf external functions(ALLOC_HEAP_ARG + number)?");
246 return std::stoi(number);
247}
248
249// Does (F) reallocate a new object?
251{
252 return F && hasExtFuncAnnotation(F, "REALLOC_HEAP_RET");
253}
254
255
256// Should (F) be considered "external" (either not defined in the program
257// or a user-defined version of a known alloc or no-op)?
259{
260 assert(F && "Null SVFFunction* pointer");
261 if (F->isDeclaration() || F->isIntrinsic())
262 return true;
263 else if (hasExtFuncAnnotation(F, "OVERWRITE") && getExtFuncAnnotations(F).size() == 1)
264 return false;
265 else
266 return !getExtFuncAnnotations(F).empty();
267}
static std::string GetStdoutFromCommand(const std::string &command)
Definition ExtAPI.cpp:73
static std::string getFilePath(const std::string &path)
Definition ExtAPI.cpp:97
#define F(f)
char * buffer
Definition cJSON.h:163
const char *const const double number
Definition cJSON.h:268
bool is_alloc(const SVFFunction *F)
Definition ExtAPI.cpp:217
bool is_arg_alloc(const SVFFunction *F)
Definition ExtAPI.cpp:223
bool hasExtFuncAnnotation(const SVFFunction *fun, const std::string &funcAnnotation)
Definition ExtAPI.cpp:170
bool is_ext(const SVFFunction *F)
Definition ExtAPI.cpp:258
std::string getExtBcPath()
Definition ExtAPI.cpp:119
const std::vector< std::string > & getExtFuncAnnotations(const SVFFunction *fun)
Definition ExtAPI.cpp:196
static std::string extBcPath
Definition ExtAPI.h:55
static ExtAPI * extOp
Definition ExtAPI.h:49
static ExtAPI * getExtAPI()
Definition ExtAPI.cpp:42
bool is_alloc_stack_ret(const SVFFunction *F)
Definition ExtAPI.cpp:228
std::string getExtFuncAnnotation(const SVFFunction *fun, const std::string &funcAnnotation)
Definition ExtAPI.cpp:183
s32_t get_alloc_arg_pos(const SVFFunction *F)
Definition ExtAPI.cpp:234
Map< const SVFFunction *, std::vector< std::string > > func2Annotations
Definition ExtAPI.h:52
bool is_memset(const SVFFunction *F)
Definition ExtAPI.cpp:212
bool is_memcpy(const SVFFunction *F)
Definition ExtAPI.cpp:205
ExtAPI()=default
static void destory()
Definition ExtAPI.cpp:51
static bool setExtBcPath(const std::string &path)
Definition ExtAPI.cpp:61
bool is_realloc(const SVFFunction *F)
Definition ExtAPI.cpp:250
void setExtFuncAnnotations(const SVFFunction *fun, const std::vector< std::string > &funcAnnotations)
Definition ExtAPI.cpp:164
static const Option< std::string > ExtAPIPath
Definition Options.h:220
#define NULL
Definition extapi.c:2
char * fgets(char *str, int n, void *stream)
Definition extapi.c:746
int isdigit(int c)
Definition extapi.c:851
std::ostream & errs()
Overwrite llvm::errs()
Definition SVFUtil.h:56
for isBitcode
Definition BasicTypes.h:68
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:74
signed s32_t
Definition GeneralType.h:47