Static Value-Flow Analysis
Loading...
Searching...
No Matches
LLVMModule.cpp
Go to the documentation of this file.
1//===----- SVFModule.cpp Base class of pointer analyses ---------------------//
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 * LLVMModule.cpp
25 *
26 * Created on: Aug 4, 2017
27 * Author: Yulei Sui
28 * Refactored on: Jan 25, 2024
29 * Author: Xiao Cheng, Yulei Sui
30 */
31
32#include <queue>
33#include <algorithm>
34#include "Util/SVFUtil.h"
35#include "SVF-LLVM/BasicTypes.h"
36#include "SVF-LLVM/LLVMUtil.h"
37#include "SVF-LLVM/CppUtil.h"
40#include "MSSA/SVFGBuilder.h"
41#include "llvm/Support/FileSystem.h"
43#include "llvm/Transforms/Utils/Cloning.h"
45#include "Graphs/CallGraph.h"
47
48#include <llvm/Passes/PassBuilder.h>
49
50using namespace std;
51using namespace SVF;
52
53/*
54 svf.main() is used to model the real entry point of a C++ program, which
55 initializes all global C++ objects and then call main().
56 LLVM may generate two global arrays @llvm.global_ctors and @llvm.global_dtors
57 that contain constructor and destructor functions for global variables. They
58 are not called explicitly, so we have to add them in the svf.main function.
59 The order to call these constructor and destructor functions are also
60 specified in the global arrays.
61 Related part in LLVM language reference:
62 https://llvm.org/docs/LangRef.html#the-llvm-global-ctors-global-variable
63 For example, given a "int main(int argc, char * argv[])", the corresponding
64 svf.main will be generated as follows:
65 define void @svf.main(i32, i8**, i8**) {
66 entry:
67 call void @ctor1()
68 call void @ctor2()
69 %3 = call i32 @main(i32 %0, i8** %1)
70 call void @dtor1()
71 call void @dtor2()
72 ret void
73 }
74*/
75
76#define SVF_MAIN_FUNC_NAME "svf.main"
77#define SVF_GLOBAL_CTORS "llvm.global_ctors"
78#define SVF_GLOBAL_DTORS "llvm.global_dtors"
79
82
87
89{
90
91 delete typeInference;
92 typeInference = nullptr;
93
94}
95
100
102{
103 auto it = FunToDominatorTree.find(fun);
104 if(it != FunToDominatorTree.end()) return it->second;
106 dt.recalculate(const_cast<Function&>(*fun));
107 return dt;
108}
109
111{
113
114 double startSVFModuleTime = SVFStat::getClk(true);
115 PAG::getPAG()->setModuleIdentifier(mod.getModuleIdentifier());
116 mset->modules.emplace_back(mod); // Populates `modules`; can get context via `this->getContext()`
117 mset->loadExtAPIModules(); // Uses context from module through `this->getContext()`
118 mset->build();
119 double endSVFModuleTime = SVFStat::getClk(true);
120 SVFStat::timeOfBuildingLLVMModule = (endSVFModuleTime - startSVFModuleTime)/TIMEINTERVAL;
121
122 mset->buildSymbolTable();
123}
124
125void LLVMModuleSet::buildSVFModule(const std::vector<std::string> &moduleNameVec)
126{
127 double startSVFModuleTime = SVFStat::getClk(true);
128
130
131 mset->loadModules(moduleNameVec); // Populates `modules`; can get context via `this->getContext()`
132 mset->loadExtAPIModules(); // Uses context from first module through `this->getContext()`
133
134 if (!moduleNameVec.empty())
135 {
136 PAG::getPAG()->setModuleIdentifier(moduleNameVec.front());
137 }
138
139 mset->build();
140
141 double endSVFModuleTime = SVFStat::getClk(true);
143 (endSVFModuleTime - startSVFModuleTime) / TIMEINTERVAL;
144
145 mset->buildSymbolTable();
146}
147
149{
150 double startSymInfoTime = SVFStat::getClk(true);
152 {
154 DBOUT(DGENERAL, SVFUtil::outs() << SVFUtil::pasMsg("Building Symbol table ...\n"));
155 SymbolTableBuilder builder(svfir);
156 builder.buildMemModel();
157 }
158 double endSymInfoTime = SVFStat::getClk(true);
160 (endSymInfoTime - startSymInfoTime) / TIMEINTERVAL;
161}
162
164{
165 if (!empty())
166 {
169 }
170
171 if(preProcessed==false)
173
176
177 if (Options::SVFMain())
178 addSVFMain();
179
181
182}
183
185{
188 // Functions need to be retrieved in the order of insertion
189 // candidateDefs is the vector for all used defined functions
190 // candidateDecls is the vector for all used declared functions
191 std::vector<const Function*> candidateDefs, candidateDecls;
192
193 for (Module& mod : modules)
194 {
196 for (Function& func : mod.functions())
197 {
198 if (func.isDeclaration())
199 {
200 candidateDecls.push_back(&func);
201 }
202 else
203 {
204 candidateDefs.push_back(&func);
205 }
206 }
207 }
208
209 for (const Function* func: candidateDefs)
210 {
211 addFunctionSet(func);
212 }
213 for (const Function* func: candidateDecls)
214 {
215 addFunctionSet(func);
216 }
217
218 // set function exit block
219 for (const auto& func: funSet)
220 {
221 for (Function::const_iterator bit = func->begin(), ebit = func->end(); bit != ebit; ++bit)
222 {
223 const BasicBlock* bb = &*bit;
225 if (succ_size(bb) == 0)
226 {
228 {
229 assert((LLVMUtil::functionDoesNotRet(func) ||
230 SVFUtil::isa<ReturnInst>(bb->back())) &&
231 "last inst must be return inst");
232 setFunExitBB(func, bb);
233 }
234 }
235 }
236 // For no return functions, we set the last block as exit BB
237 // This ensures that each function that has definition must have an exit BB
238 if (func->size() != 0 && !getFunExitBB(func))
239 {
240 assert((LLVMUtil::functionDoesNotRet(func) ||
241 SVFUtil::isa<ReturnInst>(&func->back().back())) &&
242 "last inst must be return inst");
243 setFunExitBB(func, &func->back());
244 }
245 }
246
247 // Store annotations of functions in extapi.bc
248 for (const auto& pair : ExtFun2Annotations)
249 {
250 const Function* fun = getFunction(pair.first);
251 setExtFuncAnnotations(fun, pair.second);
252 }
253
254}
255
260{
262 std::unique_ptr<BreakConstantGEPs> p1 = std::make_unique<BreakConstantGEPs>();
263 for (Module &M : getLLVMModules())
264 {
265 p1->runOnModule(M);
266 }
267
269 std::unique_ptr<UnifyFunctionExitNodes> p2 =
270 std::make_unique<UnifyFunctionExitNodes>();
271 for (Module &M : getLLVMModules())
272 {
273 for (auto F = M.begin(), E = M.end(); F != E; ++F)
274 {
275 Function &fun = *F;
276 if (fun.isDeclaration())
277 continue;
278 llvm::PassBuilder PB;
279 llvm::LoopAnalysisManager LAM;
280 llvm::FunctionAnalysisManager FAM;
281 llvm::CGSCCAnalysisManager CGAM;
282 llvm::ModuleAnalysisManager MAM;
283 PB.registerModuleAnalyses(MAM);
284 PB.registerCGSCCAnalyses(CGAM);
285 PB.registerFunctionAnalyses(FAM);
286 PB.registerLoopAnalyses(LAM);
287 PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
288 llvm::FunctionPassManager FPM;
289 FPM.addPass(llvm::UnifyFunctionExitNodesPass());
290 FPM.run(fun, FAM);
291 }
292 }
293}
294
295void LLVMModuleSet::preProcessBCs(std::vector<std::string> &moduleNameVec)
296{
298 mset->loadModules(moduleNameVec);
299 mset->loadExtAPIModules();
300 mset->prePassSchedule();
301
302 std::string preProcessSuffix = ".pre.bc";
303 // Get the existing module names, remove old extension, add preProcessSuffix
304 for (u32_t i = 0; i < moduleNameVec.size(); i++)
305 {
306 u32_t lastIndex = moduleNameVec[i].find_last_of(".");
307 std::string rawName = moduleNameVec[i].substr(0, lastIndex);
308 moduleNameVec[i] = (rawName + preProcessSuffix);
309 }
310
311 mset->dumpModulesToFile(preProcessSuffix);
312 preProcessed = true;
314}
315
316void LLVMModuleSet::loadModules(const std::vector<std::string> &moduleNameVec)
317{
318
319 // We read SVFIR from LLVM IR
321 {
322 if(moduleNameVec.empty())
323 {
324 SVFUtil::outs() << "no LLVM bc file is found!\n";
325 exit(0);
326 }
327 //assert(!moduleNameVec.empty() && "no LLVM bc file is found!");
328 }
329 // We read SVFIR from a user-defined txt instead of parsing SVFIR from LLVM IR
330 else
331 {
333 }
334 //
335 // LLVMContext objects separate global LLVM settings (from which e.g. types are
336 // derived); multiple LLVMContext objects can coexist and each context can "own"
337 // multiple modules (modules can only have one context). Mixing contexts can lead
338 // to unintended inequalities, such as the following:
339 //
340 // ------------------------------------------------------------------
341 // LLVMContext ctxa,ctxb;
342 // IntegerType * t1 = IntegerType::get(ctxa,32);
343 // IntegerType * t2 = IntegerType::get(ctxa,32);
344 // assert(t1 == t2);
345 // IntegerType * t3 = IntegerType::get(ctxb,32);
346 // IntegerType * t4 = IntegerType::get(ctxb,32);
347 // assert(t3 == t4);
348 // assert(t1 != t3);
349 // ------------------------------------------------------------------
350 //
351 // When loading bytecode files, SVF will use the same LLVMContext object for all
352 // modules (i.e. the context owns all loaded modules). This applies to ExtAPI as
353 // well, which *must* be loaded using the same LLVMContext object. Hence, when
354 // loading modules from bitcode files, a new LLVMContext is created (using a
355 // `std::unique_ptr<LLVMContext>` type to ensure automatic garbage collection).
356 //
357 // This garbage collection should be avoided when building an SVF module from an LLVM
358 // module instance; see the comment(s) in `buildSVFModule` and `loadExtAPIModules()`
359
360 owned_ctx = std::make_unique<LLVMContext>();
361 for (const std::string& moduleName : moduleNameVec)
362 {
363 if (!LLVMUtil::isIRFile(moduleName))
364 {
365 SVFUtil::errs() << "not an IR file: " << moduleName << std::endl;
366 abort();
367 }
368
369 SMDiagnostic Err;
370 std::unique_ptr<Module> mod = parseIRFile(moduleName, Err, *owned_ctx);
371 if (mod == nullptr)
372 {
373 SVFUtil::errs() << "load module: " << moduleName << "failed!!\n\n";
374 Err.print("SVFModuleLoader", llvm::errs());
375 abort();
376 }
377 modules.emplace_back(*mod);
378 owned_modules.emplace_back(std::move(mod));
379 }
380}
381
383{
384 // This function loads the ExtAPI bitcode file as an LLVM module. Note that it is important that
385 // the same LLVMContext object is used to load this bitcode file as is used by the other modules
386 // being analysed.
387 // When the modules are loaded from bitcode files (i.e. passing filenames to files containing
388 // LLVM IR to `buildSVFModule({file1.bc, file2.bc, ...})) the context is created while loading
389 // the modules in `loadModules()`, which populates this->modules and this->owned_modules.
390 // If, however, an LLVM Module object is passed to `buildSVFModule` (e.g. from an LLVM pass),
391 // the context should be retrieved from the module itself (note that the garbage collection from
392 // `std::unique_ptr<LLVMContext> LLVMModuleSet::owned_ctx` should be avoided in this case). This
393 // function populates only this->modules.
394 // In both cases, fetching the context from the main LLVM module (through `getContext`) works
395 assert(!empty() && "LLVMModuleSet contains no modules; cannot load ExtAPI module without LLVMContext!");
396
397 // Load external API module (extapi.bc)
398 if (!ExtAPI::getExtAPI()->getExtBcPath().empty())
399 {
400 std::string extModuleName = ExtAPI::getExtAPI()->getExtBcPath();
401 if (!LLVMUtil::isIRFile(extModuleName))
402 {
403 SVFUtil::errs() << "not an external IR file: " << extModuleName << std::endl;
404 abort();
405 }
406 SMDiagnostic Err;
407 std::unique_ptr<Module> mod = parseIRFile(extModuleName, Err, getContext());
408 if (mod == nullptr)
409 {
410 SVFUtil::errs() << "load external module: " << extModuleName << "failed!!\n\n";
411 Err.print("SVFModuleLoader", llvm::errs());
412 abort();
413 }
414 // The module of extapi.bc needs to be inserted before applications modules, like std::vector<std::reference_wrapper<Module>> modules{extapi_module, app_module}.
415 // Otherwise, when overwriting the app function with SVF extern function, the corresponding SVFFunction of the extern function will not be found.
416 modules.insert(modules.begin(), *mod);
417 owned_modules.insert(owned_modules.begin(),std::move(mod));
418 }
419}
420
421std::vector<const Function* > LLVMModuleSet::getLLVMGlobalFunctions(const GlobalVariable *global)
422{
423 // This function is used to extract constructor and destructor functions
424 // sorted by their priority from @llvm.global_ctors or @llvm.global_dtors.
425 // For example, given following @llvm.global_ctors, the returning sorted
426 // function list should be [ctor3, ctor1, ctor2].
427 // ------------------------------------------------------------------
428 // ; Each struct in the array is {priority, function, associated data}
429 //
430 // @llvm.global_ctors = appending global [2 x { i32, void ()*, i8* }]
431 // [{ i32, void ()*, i8* } { i32 1234, void ()* @ctor1.cpp, i8* null },
432 // { i32, void ()*, i8* } { i32 2345, void ()* @ctor2.cpp, i8* null },
433 // { i32, void ()*, i8* } { i32 345, void ()* @ctor3.cpp, i8* null }]
434 // ------------------------------------------------------------------
435 // TODO: According to LLVM language reference, if the third field is
436 // non-null, and points to a global variable or function, the initializer
437 // function will only run if the associated data from the current module is
438 // not discarded. However the associated data is currently ignored.
439
440
441 // This class is used for the priority queue that sorts the functions by
442 // their priority. Each object of this class stands for an item in the
443 // function array.
444 class LLVMGlobalFunction
445 {
446 public:
447 u32_t priority;
448 const Function* func;
449 LLVMGlobalFunction() {};
450 LLVMGlobalFunction(u32_t _priority, const Function* _func)
451 : priority(_priority), func(_func) {};
452 bool operator>(const LLVMGlobalFunction &other) const
453 {
454 if (priority != other.priority)
455 {
456 return priority > other.priority;
457 }
458 else
459 {
460 return func > other.func;
461 }
462 }
463 };
464
465 std::priority_queue<LLVMGlobalFunction, std::vector<LLVMGlobalFunction>,
466 greater<LLVMGlobalFunction>>
467 queue;
468 std::vector<const Function* > result;
469
470 // The @llvm.global_ctors/dtors global variable is an array of struct. Each
471 // struct has three fields: {i32 priority, void ()* @ctor/dtor, i8* @data}.
472 // First get the array here.
473 if(const ConstantArray *globalFuncArray =
474 SVFUtil::dyn_cast<ConstantArray>(global->getInitializer()))
475 {
476 // Get each struct in the array.
477 for (unsigned int i = 0; i < globalFuncArray->getNumOperands(); ++i)
478 {
479 if (
480 const ConstantStruct *globalFuncItem =
482 globalFuncArray->getOperand(i)))
483 {
484
485 // Extract priority and function from the struct
487 globalFuncItem->getOperand(0));
489 globalFuncItem->getOperand(1));
490
491 if (priority && func)
492 {
493 queue.push(LLVMGlobalFunction(LLVMUtil::getIntegerValue(priority).second,
494 func));
495 }
496 }
497 }
498 }
499
500 // Generate a sorted vector of functions from the priority queue.
501 while (!queue.empty())
502 {
503 result.push_back(queue.top().func);
504 queue.pop();
505 }
506 return result;
507}
508
510{
511 std::vector<const Function*> ctor_funcs;
512 std::vector<const Function*> dtor_funcs;
513 Function* orgMain = 0;
514 Module* mainMod = nullptr;
515
516 for (Module &mod : modules)
517 {
518 // Collect ctor and dtor functions
519 for (const GlobalVariable& global : mod.globals())
520 {
521 if (global.getName() == SVF_GLOBAL_CTORS && global.hasInitializer())
522 {
523 ctor_funcs = getLLVMGlobalFunctions(&global);
524 }
525 else if (global.getName() == SVF_GLOBAL_DTORS && global.hasInitializer())
526 {
527 dtor_funcs = getLLVMGlobalFunctions(&global);
528 }
529 }
530
531 // Find main function
532 for (auto &func : mod)
533 {
534 auto funName = func.getName();
535
536 assert(!(funName == SVF_MAIN_FUNC_NAME) && SVF_MAIN_FUNC_NAME " already defined");
537
538 if (funName == "main")
539 {
540 orgMain = &func;
541 mainMod = &mod;
542 }
543 }
544 }
545
546 // Only create svf.main when the original main function is found, and also
547 // there are global constructor or destructor functions.
548 if (orgMain && getModuleNum() > 0 &&
549 (ctor_funcs.size() > 0 || dtor_funcs.size() > 0))
550 {
551 assert(mainMod && "Module with main function not found.");
552 Module& M = *mainMod;
553 // char **
554 Type* ptr = PointerType::getUnqual(M.getContext());
555 Type* i32 = IntegerType::getInt32Ty(M.getContext());
556 // define void @svf.main(i32, i8**, i8**)
557 FunctionCallee svfmainFn = M.getOrInsertFunction(
559 Type::getVoidTy(M.getContext()),
560 i32,ptr,ptr
561 );
562 Function* svfmain = SVFUtil::dyn_cast<Function>(svfmainFn.getCallee());
563 svfmain->setCallingConv(llvm::CallingConv::C);
564 BasicBlock* block = BasicBlock::Create(M.getContext(), "entry", svfmain);
565 IRBuilder Builder(block);
566 // emit "call void @ctor()". ctor_funcs is sorted so the functions are
567 // emitted in the order of priority
568 for (auto& ctor : ctor_funcs)
569 {
570 auto target = M.getOrInsertFunction(
571 ctor->getName(),
572 Type::getVoidTy(M.getContext())
573 );
574 Builder.CreateCall(target);
575 }
576 // main() should be called after all ctor functions and before dtor
577 // functions.
578 Function::arg_iterator arg_it = svfmain->arg_begin();
579 Value* args[] = {arg_it, arg_it + 1, arg_it + 2};
580 size_t cnt = orgMain->arg_size();
581 assert(cnt <= 3 && "Too many arguments for main()");
582 Builder.CreateCall(orgMain, llvm::ArrayRef<Value*>(args, args + cnt));
583 // emit "call void @dtor()". dtor_funcs is sorted so the functions are
584 // emitted in the order of priority
585 for (auto& dtor : dtor_funcs)
586 {
587 auto target = M.getOrInsertFunction(dtor->getName(), Type::getVoidTy(M.getContext()));
588 Builder.CreateCall(target);
589 }
590 // return;
591 Builder.CreateRetVoid();
592 }
593 else
594 {
595 // use SVF::Options to record whether svf.main is added or not
596 Options::SVFMain.setValue(false);
597 }
598}
599
601{
602 GlobalVariable *glob = mod->getGlobalVariable("llvm.global.annotations");
603 if (glob == nullptr || !glob->hasInitializer())
604 return;
605
606 ConstantArray *ca = SVFUtil::dyn_cast<ConstantArray>(glob->getInitializer());
607 if (ca == nullptr)
608 return;
609
610 for (unsigned i = 0; i < ca->getNumOperands(); ++i)
611 {
612 ConstantStruct *structAn = SVFUtil::dyn_cast<ConstantStruct>(ca->getOperand(i));
613 if (structAn == nullptr || structAn->getNumOperands() == 0)
614 continue;
615
616 // Check if the annotation is for a function
617 Function* fun = nullptr;
618 GlobalVariable *annotateStr = nullptr;
620 if (ConstantExpr *expr = SVFUtil::dyn_cast<ConstantExpr>(structAn->getOperand(0)))
621 {
622 if (expr->getOpcode() == Instruction::BitCast && SVFUtil::isa<Function>(expr->getOperand(0)))
623 fun = SVFUtil::cast<Function>(expr->getOperand(0));
624
625 ConstantExpr *note = SVFUtil::cast<ConstantExpr>(structAn->getOperand(1));
626 if (note->getOpcode() != Instruction::GetElementPtr)
627 continue;
628
629 annotateStr = SVFUtil::dyn_cast<GlobalVariable>(note->getOperand(0));
630 }
632 else
633 {
634 fun = SVFUtil::dyn_cast<Function>(structAn->getOperand(0));
635 annotateStr = SVFUtil::dyn_cast<GlobalVariable>(structAn->getOperand(1));
636 }
637
638 if (!fun || annotateStr == nullptr || !annotateStr->hasInitializer())
639 continue;;
640
641 ConstantDataSequential *data = SVFUtil::dyn_cast<ConstantDataSequential>(annotateStr->getInitializer());
642 if (data && data->isString())
643 {
644 std::string annotation = data->getAsString().str();
645 if (!annotation.empty())
646 ExtFun2Annotations[fun->getName().str()].push_back(annotation);
647 }
648 }
649}
650
651/*
652 There are three types of functions(definitions) in extapi.c:
653 1. (Fun_Overwrite): Functions with "OVERWRITE" annotion:
654 These functions are used to replace the corresponding function definitions in the application.
655 2. (Fun_Annotation): Functions with annotation(s) but without "OVERWRITE" annotation:
656 These functions are used to tell SVF to do special processing, like malloc().
657 3. (Fun_Noraml): Functions without any annotation:
658 These functions are used to replace the corresponding function declarations in the application.
659
660
661 We will iterate over declarations (appFunDecl) and definitons (appFunDef) of functions in the application and extapi.c to do the following clone or replace operations:
662 1. appFuncDecl --> Fun_Normal: Clone the Fun_Overwrite and replace the appFuncDecl in application.
663 2. appFuncDecl --> Fun_Annotation: Move the annotions on Fun_Annotation to appFuncDecl in application.
664
665 3. appFunDef --> Fun_Overwrite: Clone the Fun_Overwrite and overwrite the appFunDef in application.
666 4. appFunDef --> Fun_Annotation: Replace the appFunDef with appFunDecl and move the annotions to appFunDecl in application
667*/
669{
670 Set<const Function*> appFunDecls, appFunDefs, extFuncs, clonedFuncs;
671 OrderedSet<string> appFuncDeclNames, appFuncDefNames, extFunDefNames, intersectNames;
672 Map<const Function*, const Function*> extFuncs2ClonedFuncs;
673 Module* appModule = nullptr;
674 Module* extModule = nullptr;
675
676 for (Module& mod : modules)
677 {
678 // extapi.bc functions
679 if (mod.getName().str() == ExtAPI::getExtAPI()->getExtBcPath())
680 {
682 extModule = &mod;
683 for (const Function& fun : mod.functions())
684 {
685 // there is main declaration in ext bc, it should be mapped to
686 // main definition in app bc.
687 if (fun.getName().str() == "main")
688 {
689 appFunDecls.insert(&fun);
690 appFuncDeclNames.insert(fun.getName().str());
691 }
693 else if (fun.getName().str() == "svf__main")
694 {
695 ExtFuncsVec.push_back(&fun);
696 }
697 else
698 {
699 extFuncs.insert(&fun);
700 extFunDefNames.insert(fun.getName().str());
701 }
702 }
703 }
704 else
705 {
706 appModule = &mod;
708 for (const Function& fun : mod.functions())
709 {
710 if (fun.isDeclaration())
711 {
712 appFunDecls.insert(&fun);
713 appFuncDeclNames.insert(fun.getName().str());
714 }
715 else
716 {
717 appFunDefs.insert(&fun);
718 appFuncDefNames.insert(fun.getName().str());
719 }
720 }
721 }
722 }
723
724 // Find the intersectNames between appFuncDefNames and externalFunDefNames
725 std::set_intersection(
726 appFuncDefNames.begin(), appFuncDefNames.end(), extFunDefNames.begin(), extFunDefNames.end(),
727 std::inserter(intersectNames, intersectNames.end()));
728
729 auto cloneAndReplaceFunction = [&](const Function* extFunToClone, Function* appFunToReplace, Module* appModule, bool cloneBody) -> Function*
730 {
731 assert(!(appFunToReplace == NULL && appModule == NULL) && "appFunToReplace and appModule cannot both be NULL");
732
733 if (appFunToReplace)
734 {
735 appModule = appFunToReplace->getParent();
736 }
737 Function* clonedFunction = Function::Create(extFunToClone->getFunctionType(),
738 Function::ExternalLinkage,
739 extFunToClone->getName());
740 // Map the arguments of the new function to the arguments of extFunToClone
741 llvm::ValueToValueMapTy valueMap;
742 Function::arg_iterator destArg = clonedFunction->arg_begin();
743 for (Function::const_arg_iterator srcArg = extFunToClone->arg_begin(); srcArg != extFunToClone->arg_end(); ++srcArg)
744 {
745 destArg->setName(srcArg->getName()); // Copy the name of the original argument
746 valueMap[&*srcArg] = &*destArg++; // Add a mapping from the old arg to the new arg
747 }
748 if (cloneBody)
749 {
750 // Collect global variables referenced by extFunToClone
751 // This step identifies all global variables used within the function to be cloned
752 std::set<GlobalVariable*> referencedGlobals;
753 for (const BasicBlock& BB : *extFunToClone)
754 {
755 for (const Instruction& I : BB)
756 {
757 for (const Value* operand : I.operands())
758 {
759 // Check if the operand is a global variable
760 if (const GlobalVariable* GV = SVFUtil::dyn_cast<GlobalVariable>(operand))
761 {
762 referencedGlobals.insert(const_cast<GlobalVariable*>(GV));
763 }
764 }
765 }
766 }
767
768 // Copy global variables to target module and update valueMap
769 // When cloning a function, we need to ensure all global variables it references are available in the target module
770 for (GlobalVariable* GV : referencedGlobals)
771 {
772 // Check if the global variable already exists in the target module
773 GlobalVariable* existingGV = appModule->getGlobalVariable(GV->getName());
774 if (existingGV)
775 {
776 // If the global variable already exists, ensure type consistency
777 assert(existingGV->getType() == GV->getType() && "Global variable type mismatch in client module!");
778 // Map the original global to the existing one in the target module
779 valueMap[GV] = existingGV; // Map to existing global variable
780 }
781 else
782 {
783 // If the global variable doesn't exist in the target module, create a new one with the same properties
784 GlobalVariable* newGV = new GlobalVariable(
785 *appModule, // Target module
786 GV->getValueType(), // Type of the global variable
787 GV->isConstant(), // Whether it's constant
788 GV->getLinkage(), // Linkage type
789 nullptr, // No initializer yet
790 GV->getName(), // Same name
791 nullptr, // No insert before instruction
792 GV->getThreadLocalMode(), // Thread local mode
793 GV->getAddressSpace() // Address space
794 );
795
796 // Copy initializer if present to maintain the global's value
797 if (GV->hasInitializer())
798 {
799 Constant* init = GV->getInitializer();
800 newGV->setInitializer(init); // Simple case: direct copy
801 }
802
803 // Copy other attributes like alignment to ensure identical behavior
804 newGV->copyAttributesFrom(GV);
805
806 // Add mapping from original global to the new one for use during function cloning
807 valueMap[GV] = newGV;
808 }
809 }
810
811 // Clone function body with updated valueMap
812 llvm::SmallVector<ReturnInst*, 8> ignoredReturns;
813 CloneFunctionInto(clonedFunction, extFunToClone, valueMap, llvm::CloneFunctionChangeType::LocalChangesOnly, ignoredReturns, "", nullptr);
814 }
815 if (appFunToReplace)
816 {
817 // Replace all uses of appFunToReplace with clonedFunction
818 appFunToReplace->replaceAllUsesWith(clonedFunction);
819 std::string oldFunctionName = appFunToReplace->getName().str();
820 // Delete the old function
821 appFunToReplace->eraseFromParent();
822 appModule->getFunctionList().push_back(clonedFunction);
823 clonedFunction->setName(oldFunctionName);
824 }
825 else
826 {
827 appModule->getFunctionList().push_back(clonedFunction);
828 }
829 return clonedFunction;
830 };
831
833 for (const Function* appFunDecl : appFunDecls)
834 {
835 std::string appFunDeclName = LLVMUtil::restoreFuncName(appFunDecl->getName().str());
836 for (const Function* extFun : extFuncs)
837 {
838 if (extFun->getName().str().compare(appFunDeclName) == 0)
839 {
840 auto it = ExtFun2Annotations.find(extFun->getName().str());
841 // Without annotations, this function is normal function with useful function body
842 if (it == ExtFun2Annotations.end())
843 {
844 Function* clonedFunction = cloneAndReplaceFunction(const_cast<Function*>(extFun), const_cast<Function*>(appFunDecl), nullptr, true);
845 extFuncs2ClonedFuncs[extFun] = clonedFunction;
846 clonedFuncs.insert(clonedFunction);
847 }
848 else
849 {
850 ExtFuncsVec.push_back(appFunDecl);
851 }
852 break;
853 }
854 }
855 }
856
859 for (string sameFuncDef: intersectNames)
860 {
861 Function* appFuncDef = appModule->getFunction(sameFuncDef);
862 Function* extFuncDef = extModule->getFunction(sameFuncDef);
863 if (appFuncDef == nullptr || extFuncDef == nullptr)
864 continue;
865
866 FunctionType *appFuncDefType = appFuncDef->getFunctionType();
867 FunctionType *extFuncDefType = extFuncDef->getFunctionType();
868 if (appFuncDefType != extFuncDefType)
869 continue;
870
871 auto it = ExtFun2Annotations.find(sameFuncDef);
872 if (it != ExtFun2Annotations.end())
873 {
874 std::vector<std::string> annotations = it->second;
875 if (annotations.size() == 1 && annotations[0].find("OVERWRITE") != std::string::npos)
876 {
877 Function* clonedFunction = cloneAndReplaceFunction(const_cast<Function*>(extFuncDef), const_cast<Function*>(appFuncDef), nullptr, true);
878 extFuncs2ClonedFuncs[extFuncDef] = clonedFunction;
879 clonedFuncs.insert(clonedFunction);
880 }
881 else
882 {
883 if (annotations.size() >= 2)
884 {
885 for (const auto& annotation : annotations)
886 {
887 if(annotation.find("OVERWRITE") != std::string::npos)
888 {
889 assert(false && "overwrite and other annotations cannot co-exist");
890 }
891 }
892 }
893 }
894 }
895 }
896
897 auto linkFunctions = [&](Function* caller, Function* callee)
898 {
899 for (inst_iterator I = inst_begin(caller), E = inst_end(caller); I != E; ++I)
900 {
901 Instruction *inst = &*I;
902
903 if (CallInst *callInst = SVFUtil::dyn_cast<CallInst>(inst))
904 {
905 Function *calledFunc = callInst->getCalledFunction();
906
907 if (calledFunc && calledFunc->getName() == callee->getName())
908 {
909 callInst->setCalledFunction(callee);
910 }
911 }
912 }
913 };
914
915 std::function<void(const Function*, Function*)> cloneAndLinkFunction;
916 cloneAndLinkFunction = [&](const Function* extFunToClone, Function* appClonedFun)
917 {
918 if (clonedFuncs.find(extFunToClone) != clonedFuncs.end())
919 return;
920
921 Module* appModule = appClonedFun->getParent();
922 // Check if the function already exists in the parent module
923 if (appModule->getFunction(extFunToClone->getName()))
924 {
925 // The function already exists, no need to clone, but need to link it with the caller
926 Function* func = appModule->getFunction(extFunToClone->getName());
927 linkFunctions(appClonedFun, func);
928 return;
929 }
930 // Decide whether to clone the function body based on ExtFun2Annotations
931 bool cloneBody = true;
932 auto it = ExtFun2Annotations.find(extFunToClone->getName().str());
933 if (it != ExtFun2Annotations.end())
934 {
935 std::vector<std::string> annotations = it->second;
936 if (!(annotations.size() == 1 && annotations[0].find("OVERWRITE") != std::string::npos))
937 {
938 cloneBody = false;
939 }
940 }
941
942 Function* clonedFunction = cloneAndReplaceFunction(extFunToClone, nullptr, appModule, cloneBody);
943
944 clonedFuncs.insert(clonedFunction);
945 // Add the cloned function to ExtFuncsVec for further processing
946 ExtFuncsVec.push_back(clonedFunction);
947
948 linkFunctions(appClonedFun, clonedFunction);
949
950 std::vector<const Function*> calledFunctions = LLVMUtil::getCalledFunctions(extFunToClone);
951
952 for (const auto& calledFunction : calledFunctions)
953 {
954 cloneAndLinkFunction(calledFunction, clonedFunction);
955 }
956 };
957
958 // Recursive clone called functions
959 for (const auto& pair : extFuncs2ClonedFuncs)
960 {
961 Function* extFun = const_cast<Function*>(pair.first);
962 Function* clonedExtFun = const_cast<Function*>(pair.second);
963 std::vector<const Function*> extCalledFuns = LLVMUtil::getCalledFunctions(extFun);
964
965 for (const auto& extCalledFun : extCalledFuns)
966 {
967 cloneAndLinkFunction(extCalledFun, clonedExtFun);
968 }
969 }
970
971 // Remove unused annotations in ExtFun2Annotations according to the functions in ExtFuncsVec
972 Fun2AnnoMap newFun2AnnoMap;
973 for (const Function* extFun : ExtFuncsVec)
974 {
975 std::string name = LLVMUtil::restoreFuncName(extFun->getName().str());
976 auto it = ExtFun2Annotations.find(name);
977 if (it != ExtFun2Annotations.end())
978 {
979 std::string newKey = name;
980 if (name != extFun->getName().str())
981 {
982 newKey = extFun->getName().str();
983 }
984 newFun2AnnoMap.insert({newKey, it->second});
985 }
986 }
987 ExtFun2Annotations.swap(newFun2AnnoMap);
988
989 // Remove ExtAPI module from modules
990 auto it = std::find_if(modules.begin(), modules.end(),
991 [&extModule](const std::reference_wrapper<llvm::Module>& moduleRef)
992 {
993 return &moduleRef.get() == extModule;
994 });
995
996 if (it != modules.end())
997 {
998 size_t index = std::distance(modules.begin(), it);
999 modules.erase(it);
1000 owned_modules.erase(owned_modules.begin() + index);
1001 }
1002}
1003
1005{
1006 typedef Map<string, Set<GlobalVariable*>> NameToGlobalsMapTy;
1007 NameToGlobalsMapTy nameToGlobalsMap;
1008 for (Module &mod : modules)
1009 {
1010 // Collect ctor and dtor functions
1011 for (GlobalVariable& global : mod.globals())
1012 {
1013 if (global.hasPrivateLinkage())
1014 continue;
1015 string name = global.getName().str();
1016 if (name.empty())
1017 continue;
1018 nameToGlobalsMap[std::move(name)].insert(&global);
1019 }
1020 }
1021
1022 for (const auto& pair : nameToGlobalsMap)
1023 {
1024 const Set<GlobalVariable*> &globals = pair.second;
1025
1026 const auto repIt =
1027 std::find_if(globals.begin(), globals.end(),
1028 [](GlobalVariable* g)
1029 {
1030 return g->hasInitializer();
1031 });
1032 GlobalVariable* rep =
1033 repIt != globals.end()
1034 ? *repIt
1035 // When there is no initializer, just pick the first one.
1036 : (assert(!globals.empty() && "Empty global set"),
1037 *globals.begin());
1038
1039 for (const GlobalVariable* cur : globals)
1040 {
1041 GlobalDefToRepMap[cur] = rep;
1042 }
1043 }
1044}
1045
1046// Dump modules to files
1047void LLVMModuleSet::dumpModulesToFile(const std::string& suffix)
1048{
1049 for (Module& mod : modules)
1050 {
1051 std::string moduleName = mod.getName().str();
1052 std::string OutputFilename;
1053 std::size_t pos = moduleName.rfind('.');
1054 if (pos != std::string::npos)
1055 OutputFilename = moduleName.substr(0, pos) + suffix;
1056 else
1057 OutputFilename = moduleName + suffix;
1058
1059 std::error_code EC;
1060 raw_fd_ostream OS(OutputFilename.c_str(), EC, llvm::sys::fs::OF_None);
1061 WriteBitcodeToFile(mod, OS);
1062 OS.flush();
1063 }
1064}
1065
1067{
1068 if (SVFUtil::isa<ConstantPointerNull>(llvm_value))
1069 return svfir->nullPtrSymID();
1070 else if (SVFUtil::isa<UndefValue>(llvm_value))
1071 {
1072 // For phi ptr [ @x, ... ], [ undef, ... ], keep @x without adding
1073 // a black-hole target. Integer and aggregate undef keep their model.
1074 if (Options::UndefAsNull() && llvm_value->getType()->isPointerTy())
1075 return svfir->nullPtrSymID();
1076 return svfir->blkPtrSymID();
1077 }
1078 else
1079 {
1080 ValueToIDMapTy::const_iterator iter = valSymMap.find(llvm_value);
1081 assert(iter!=valSymMap.end() &&"value sym not found");
1082 return iter->second;
1083 }
1084}
1086{
1088 return true;
1089 else
1090 return (valSymMap.find(val) != valSymMap.end());
1091}
1092
1094{
1095 if (const GlobalVariable* glob = SVFUtil::dyn_cast<GlobalVariable>(llvm_value))
1096 llvm_value = LLVMUtil::getGlobalRep(glob);
1097 ValueToIDMapTy::const_iterator iter = objSymMap.find(llvm_value);
1098 assert(iter!=objSymMap.end() && "obj sym not found");
1099 return iter->second;
1100}
1101
1102
1104{
1106 for (ValueToIDMapTy::iterator iter = valSymMap.begin(); iter != valSymMap.end();
1107 ++iter)
1108 {
1109 const NodeID i = iter->second;
1110 idmap[i] = iter->first;
1111 }
1112 for (ValueToIDMapTy::iterator iter = objSymMap.begin(); iter != objSymMap.end();
1113 ++iter)
1114 {
1115 const NodeID i = iter->second;
1116 idmap[i] = iter->first;
1117 }
1118 for (FunToIDMapTy::iterator iter = retSyms().begin(); iter != retSyms().end();
1119 ++iter)
1120 {
1121 const NodeID i = iter->second;
1122 idmap[i] = iter->first;
1123 }
1124 for (FunToIDMapTy::iterator iter = varargSyms().begin(); iter != varargSyms().end();
1125 ++iter)
1126 {
1127 const NodeID i = iter->second;
1128 idmap[i] = iter->first;
1129 }
1130 SVFUtil::outs() << "{SymbolTableInfo \n";
1131
1132
1133
1134
1135 for (auto iter : idmap)
1136 {
1137 std::string str;
1138 llvm::raw_string_ostream rawstr(str);
1139 auto llvmVal = iter.second;
1140 if (llvmVal)
1141 rawstr << " " << *llvmVal << " ";
1142 else
1143 rawstr << " No llvmVal found";
1144 rawstr << LLVMUtil::getSourceLoc(llvmVal);
1145 SVFUtil::outs() << iter.first << " " << rawstr.str() << "\n";
1146 }
1147 SVFUtil::outs() << "}\n";
1148}
1149
1151 SVFValue* svfBaseNode)
1152{
1153 SVFBaseNode2LLVMValue[svfBaseNode] = val;
1154 svfBaseNode->setSourceLoc(LLVMUtil::getSourceLoc(val));
1155 svfBaseNode->setName(val->getName().str());
1156}
1157
1159{
1160 Function* fun = nullptr;
1161
1162 for (u32_t i = 0; i < llvmModuleSet->getModuleNum(); ++i)
1163 {
1164 Module* mod = llvmModuleSet->getModule(i);
1165 fun = mod->getFunction(name);
1166 if (fun)
1167 {
1168 return llvmModuleSet->getFunObjVar(fun);
1169 }
1170 }
1171 return nullptr;
1172}
1173
1174
1176{
1177 for(LLVMType2SVFTypeMap::const_iterator it = LLVMType2SVFType.begin(), eit = LLVMType2SVFType.end(); it!=eit; ++it)
1178 {
1179 if (it->second == T)
1180 return it->first;
1181 }
1182 assert(false && "can't find the corresponding LLVM Type");
1183 abort();
1184}
1185
1190{
1191 assert(T && "SVFType should not be null");
1192 LLVMType2SVFTypeMap::const_iterator it = LLVMType2SVFType.find(T);
1193 if (it != LLVMType2SVFType.end())
1194 return it->second;
1195
1196 SVFType* svfType = addSVFTypeInfo(T);
1197 StInfo* stinfo = collectTypeInfo(T);
1198 svfType->setTypeInfo(stinfo);
1199 return svfType;
1200}
1201
1202
1205{
1206 ICFGNode* node;
1208 node = getCallICFGNode(inst);
1209 else if(LLVMUtil::isIntrinsicInst(inst))
1210 node = getIntraICFGNode(inst);
1211 else
1212 node = getIntraICFGNode(inst);
1213
1214 assert (node!=nullptr && "no ICFGNode for this instruction?");
1215 return node;
1216}
1217
1219{
1220 ICFGNode* node;
1222 node = getCallBlock(inst);
1223 else if(LLVMUtil::isIntrinsicInst(inst))
1224 node = getIntraBlock(inst);
1225 else
1226 node = getIntraBlock(inst);
1227
1228 return node != nullptr;
1229}
1230
1232{
1233 assert(LLVMUtil::isCallSite(inst) && "not a call instruction?");
1234 assert(LLVMUtil::isNonInstricCallSite(inst) && "associating an intrinsic debug instruction with an ICFGNode!");
1235 CallICFGNode* node = getCallBlock(inst);
1236 assert (node!=nullptr && "no CallICFGNode for this instruction?");
1237 return node;
1238}
1239
1241{
1242 assert(LLVMUtil::isCallSite(inst) && "not a call instruction?");
1243 assert(LLVMUtil::isNonInstricCallSite(inst) && "associating an intrinsic debug instruction with an ICFGNode!");
1244 RetICFGNode* node = getRetBlock(inst);
1245 assert (node!=nullptr && "no RetICFGNode for this instruction?");
1246 return node;
1247}
1248
1250{
1251 IntraICFGNode* node = getIntraBlock(inst);
1252 assert (node!=nullptr && "no IntraICFGNode for this instruction?");
1253 return node;
1254}
1255
1257{
1258 Type2TypeInfoMap::iterator tit = Type2TypeInfo.find(T);
1259 if (tit != Type2TypeInfo.end())
1260 {
1261 return tit->second;
1262 }
1263 // No such StInfo for T, create it now.
1264 StInfo* stInfo;
1265 if (const ArrayType* aty = SVFUtil::dyn_cast<ArrayType>(T))
1266 {
1267 stInfo = collectArrayInfo(aty);
1268 }
1269 else if (const StructType* sty = SVFUtil::dyn_cast<StructType>(T))
1270 {
1271 u32_t nf;
1272 stInfo = collectStructInfo(sty, nf);
1273 if (nf > svfir->maxStSize)
1274 {
1275 svfir->maxStruct = getSVFType(sty);
1276 svfir->maxStSize = nf;
1277 }
1278 }
1279 else
1280 {
1281 stInfo = collectSimpleTypeInfo(T);
1282 }
1283 Type2TypeInfo.emplace(T, stInfo);
1284 svfir->addStInfo(stInfo);
1285 return stInfo;
1286}
1287
1289{
1290 assert(LLVMType2SVFType.find(T) == LLVMType2SVFType.end() &&
1291 "SVFType has been added before");
1292
1293 // add SVFType's LLVM byte size iff T isSized(), otherwise byteSize is 1 (default value)
1294 u32_t byteSize = 1;
1295 if (T->isSized())
1296 {
1297 const llvm::DataLayout &DL = LLVMModuleSet::getLLVMModuleSet()->
1298 getMainLLVMModule()->getDataLayout();
1299 Type *mut_T = const_cast<Type *>(T);
1300 byteSize = DL.getTypeAllocSize(mut_T);
1301 }
1302
1303 SVFType* svftype;
1304
1307 {
1308 svftype = new SVFPointerType(id, byteSize);
1309 }
1310 else if (const IntegerType* intT = SVFUtil::dyn_cast<IntegerType>(T))
1311 {
1312 auto svfIntT = new SVFIntegerType(id, byteSize);
1313 unsigned signWidth = intT->getBitWidth();
1314 assert(signWidth < INT16_MAX && "Integer width too big");
1315 svfIntT->setSignAndWidth(intT->getSignBit() ? -signWidth : signWidth);
1316 svftype = svfIntT;
1317 }
1318 else if (const FunctionType* ft = SVFUtil::dyn_cast<FunctionType>(T))
1319 {
1320 std::vector<const SVFType*> paramTypes;
1321 for (const auto& t: ft->params())
1322 {
1323 paramTypes.push_back(getSVFType(t));
1324 }
1325 svftype = new SVFFunctionType(id, getSVFType(ft->getReturnType()), paramTypes, ft->isVarArg());
1326 }
1327 else if (const StructType* st = SVFUtil::dyn_cast<StructType>(T))
1328 {
1329 std::vector<const SVFType*> fieldTypes;
1330
1331 for (const auto& t: st->elements())
1332 {
1333 fieldTypes.push_back(getSVFType(t));
1334 }
1335 auto svfst = new SVFStructType(id, fieldTypes, byteSize);
1336 if (st->hasName())
1337 svfst->setName(st->getName().str());
1338 svftype = svfst;
1339 }
1340 else if (const auto at = SVFUtil::dyn_cast<ArrayType>(T))
1341 {
1342 auto svfat = new SVFArrayType(id, byteSize);
1343 svfat->setNumOfElement(at->getNumElements());
1344 svfat->setTypeOfElement(getSVFType(at->getElementType()));
1345 svftype = svfat;
1346 }
1347 else
1348 {
1349 std::string buffer;
1350 auto ot = new SVFOtherType(id, T->isSingleValueType(), byteSize);
1351 llvm::raw_string_ostream(buffer) << *T;
1352 ot->setRepr(std::move(buffer));
1353 svftype = ot;
1354 }
1355
1356 svfir->addTypeInfo(svftype);
1357 LLVMType2SVFType[T] = svftype;
1358
1359 return svftype;
1360}
1361
1366{
1367 u64_t totalElemNum = ty->getNumElements();
1368 const Type* elemTy = ty->getElementType();
1369 while (const ArrayType* aty = SVFUtil::dyn_cast<ArrayType>(elemTy))
1370 {
1371 totalElemNum *= aty->getNumElements();
1372 elemTy = aty->getElementType();
1373 }
1374
1375 StInfo* stInfo = new StInfo(totalElemNum);
1376 const SVFType* elemSvfType = getSVFType(elemTy);
1377
1379 if (totalElemNum == 0)
1380 {
1381 stInfo->addFldWithType(0, elemSvfType, 0);
1382 stInfo->setNumOfFieldsAndElems(1, 1);
1383 stInfo->getFlattenFieldTypes().push_back(elemSvfType);
1384 stInfo->getFlattenElementTypes().push_back(elemSvfType);
1385 return stInfo;
1386 }
1387
1390 StInfo* elemStInfo = collectTypeInfo(elemTy);
1391 u32_t nfF = elemStInfo->getNumOfFlattenFields();
1392 u32_t nfE = elemStInfo->getNumOfFlattenElements();
1393 for (u32_t j = 0; j < nfF; j++)
1394 {
1395 const SVFType* fieldTy = elemStInfo->getFlattenFieldTypes()[j];
1396 stInfo->getFlattenFieldTypes().push_back(fieldTy);
1397 }
1398
1401 u32_t outArrayElemNum = ty->getNumElements();
1402 for (u32_t i = 0; i < outArrayElemNum; ++i)
1403 {
1404 auto idx = (i * nfE * totalElemNum) / outArrayElemNum;
1405 stInfo->addFldWithType(0, elemSvfType, idx);
1406 }
1407
1408 for (u32_t i = 0; i < totalElemNum; ++i)
1409 {
1410 for (u32_t j = 0; j < nfE; ++j)
1411 {
1412 const SVFType* et = elemStInfo->getFlattenElementTypes()[j];
1413 stInfo->getFlattenElementTypes().push_back(et);
1414 }
1415 }
1416
1417 assert(stInfo->getFlattenElementTypes().size() == nfE * totalElemNum &&
1418 "typeForArray size incorrect!!!");
1419 stInfo->setNumOfFieldsAndElems(nfF, nfE * totalElemNum);
1420
1421 return stInfo;
1422}
1423
1429 u32_t& numFields)
1430{
1432 StInfo* stInfo = new StInfo(1);
1433
1434 // Number of fields after flattening the struct
1435 numFields = 0;
1436 // The offset when considering array stride info
1437 u32_t strideOffset = 0;
1438 for (const Type* elemTy : structTy->elements())
1439 {
1440 const SVFType* elemSvfTy = getSVFType(elemTy);
1441 // offset with int_32 (s32_t) is large enough and won't overflow
1442 stInfo->addFldWithType(numFields, elemSvfTy, strideOffset);
1443
1445 {
1446 StInfo* subStInfo = collectTypeInfo(elemTy);
1447 u32_t nfF = subStInfo->getNumOfFlattenFields();
1448 u32_t nfE = subStInfo->getNumOfFlattenElements();
1449 // Copy ST's info, whose element 0 is the size of ST itself.
1450 for (u32_t j = 0; j < nfF; ++j)
1451 {
1452 const SVFType* elemTy = subStInfo->getFlattenFieldTypes()[j];
1453 stInfo->getFlattenFieldTypes().push_back(elemTy);
1454 }
1455 numFields += nfF;
1456 strideOffset += nfE;
1457 for (u32_t tpj = 0; tpj < nfE; ++tpj)
1458 {
1459 const SVFType* ty = subStInfo->getFlattenElementTypes()[tpj];
1460 stInfo->getFlattenElementTypes().push_back(ty);
1461 }
1462
1463 }
1464 else
1465 {
1466 // Simple type
1467 numFields += 1;
1468 strideOffset += 1;
1469 stInfo->getFlattenFieldTypes().push_back(elemSvfTy);
1470 stInfo->getFlattenElementTypes().push_back(elemSvfTy);
1471 }
1472 }
1473
1474 assert(stInfo->getFlattenElementTypes().size() == strideOffset &&
1475 "typeForStruct size incorrect!");
1476 stInfo->setNumOfFieldsAndElems(numFields,strideOffset);
1477
1478 return stInfo;
1479}
1480
1481
1486{
1488 StInfo* stInfo = new StInfo(1);
1489 SVFType* svfType = getSVFType(ty);
1490 stInfo->addFldWithType(0, svfType, 0);
1491
1492 stInfo->getFlattenFieldTypes().push_back(svfType);
1493 stInfo->getFlattenElementTypes().push_back(svfType);
1494 stInfo->setNumOfFieldsAndElems(1,1);
1495
1496 return stInfo;
1497}
1498
1499void LLVMModuleSet::setExtFuncAnnotations(const Function* fun, const std::vector<std::string>& funcAnnotations)
1500{
1501 assert(fun && "Null SVFFunction* pointer");
1502 func2Annotations[fun] = funcAnnotations;
1503}
1504
1505bool LLVMModuleSet::hasExtFuncAnnotation(const Function* fun, const std::string& funcAnnotation)
1506{
1507 assert(fun && "Null SVFFunction* pointer");
1508 auto it = func2Annotations.find(fun);
1509 if (it != func2Annotations.end())
1510 {
1511 for (const std::string& annotation : it->second)
1512 if (annotation.find(funcAnnotation) != std::string::npos)
1513 return true;
1514 }
1515 return false;
1516}
1517
1518std::string LLVMModuleSet::getExtFuncAnnotation(const Function* fun, const std::string& funcAnnotation)
1519{
1520 assert(fun && "Null Function* pointer");
1521 auto it = func2Annotations.find(fun);
1522 if (it != func2Annotations.end())
1523 {
1524 for (const std::string& annotation : it->second)
1525 if (annotation.find(funcAnnotation) != std::string::npos)
1526 return annotation;
1527 }
1528 return "";
1529}
1530
1531const std::vector<std::string>& LLVMModuleSet::getExtFuncAnnotations(const Function* fun)
1532{
1533 assert(fun && "Null Function* pointer");
1534 auto it = func2Annotations.find(fun);
1535 if (it != func2Annotations.end())
1536 return it->second;
1537 return func2Annotations[fun];
1538}
1539
1541{
1542 return F &&
1543 (hasExtFuncAnnotation(F, "MEMCPY") || hasExtFuncAnnotation(F, "STRCPY")
1544 || hasExtFuncAnnotation(F, "STRCAT"));
1545}
1546
1548{
1549 return F && hasExtFuncAnnotation(F, "MEMSET");
1550}
1551
1553{
1554 return F && hasExtFuncAnnotation(F, "ALLOC_HEAP_RET");
1555}
1556
1557// Does (F) allocate a new object and assign it to one of its arguments?
1559{
1560 return F && hasExtFuncAnnotation(F, "ALLOC_HEAP_ARG");
1561}
1562
1564{
1565 return F && hasExtFuncAnnotation(F, "ALLOC_STACK_RET");
1566}
1567
1568// Get the position of argument which holds the new object
1570{
1571 std::string allocArg = getExtFuncAnnotation(F, "ALLOC_HEAP_ARG");
1572 assert(!allocArg.empty() && "Not an alloc call via argument or incorrect extern function annotation!");
1573
1574 std::string number;
1575 for (char c : allocArg)
1576 {
1577 if (isdigit(c))
1578 number.push_back(c);
1579 }
1580 assert(!number.empty() && "Incorrect naming convention for svf external functions(ALLOC_HEAP_ARG + number)?");
1581 return std::stoi(number);
1582}
1583
1584// Does (F) reallocate a new object?
1586{
1587 return F && hasExtFuncAnnotation(F, "REALLOC_HEAP_RET");
1588}
1589
1590
1591// Should (F) be considered "external" (either not defined in the program
1592// or a user-defined version of a known alloc or no-op)?
1594{
1595 assert(F && "Null SVFFunction* pointer");
1596 if (F->isDeclaration() || F->isIntrinsic())
1597 return true;
1598 else if (hasExtFuncAnnotation(F, "OVERWRITE") && getExtFuncAnnotations(F).size() == 1)
1599 return false;
1600 else
1601 return !getExtFuncAnnotations(F).empty();
1602}
#define SVF_MAIN_FUNC_NAME
#define SVF_GLOBAL_DTORS
#define SVF_GLOBAL_CTORS
#define DBOUT(TYPE, X)
LLVM debug macros, define type of your DBUG model of each pass.
Definition SVFType.h:576
#define TIMEINTERVAL
Definition SVFType.h:604
#define DGENERAL
Definition SVFType.h:582
const char *const name
Definition cJSON.h:264
char * buffer
Definition cJSON.h:163
const char *const const double number
Definition cJSON.h:268
int index
Definition cJSON.h:170
std::string getExtBcPath()
Definition ExtAPI.cpp:111
static ExtAPI * getExtAPI()
Definition ExtAPI.cpp:43
bool hasValueNode(const Value *V)
TargetABI targetABI
C++ ABI of the module being analyzed.
Definition LLVMModule.h:92
NodeID getValueNode(const Value *V)
IntraICFGNode * getIntraBlock(const Instruction *inst)
Definition LLVMModule.h:512
LLVMType2SVFTypeMap LLVMType2SVFType
Definition LLVMModule.h:107
bool is_alloc_stack_ret(const Function *F)
std::vector< const Function * > getLLVMGlobalFunctions(const GlobalVariable *global)
FunToIDMapTy & retSyms()
Definition LLVMModule.h:281
void buildSymbolTable() const
Module * getMainLLVMModule() const
Definition LLVMModule.h:373
const FunObjVar * getFunObjVar(const Function *fun) const
Definition LLVMModule.h:274
ValueToIDMapTy valSymMap
map a value to its sym id
Definition LLVMModule.h:120
StInfo * collectTypeInfo(const Type *ty)
Collect a type info.
static LLVMModuleSet * getLLVMModuleSet()
Definition LLVMModule.h:137
void loadModules(const std::vector< std::string > &moduleNameVec)
ObjTypeInference * typeInference
Definition LLVMModule.h:109
static void releaseLLVMModuleSet()
Definition LLVMModule.h:144
static void preProcessBCs(std::vector< std::string > &moduleNameVec)
static bool preProcessed
Definition LLVMModule.h:85
DominatorTree & getDomTree(const Function *fun)
void addToSVFVar2LLVMValueMap(const Value *val, SVFValue *svfBaseNode)
RetICFGNode * getRetBlock(const Instruction *cs)
Get/Add a return node.
Definition LLVMModule.h:504
std::unique_ptr< LLVMContext > owned_ctx
Definition LLVMModule.h:87
void createSVFDataStructure()
StInfo * collectSimpleTypeInfo(const Type *T)
Collect simple type (non-aggregate) info.
bool is_alloc(const Function *F)
const std::vector< std::string > & getExtFuncAnnotations(const Function *fun)
SVFType * getSVFType(const Type *T)
Get or create SVFType and typeinfo.
void setFunExitBB(const Function *fun, const BasicBlock *bb)
Definition LLVMModule.h:457
const Type * getLLVMType(const SVFType *T) const
Get LLVM Type.
void setExtFuncAnnotations(const Function *fun, const std::vector< std::string > &funcAnnotations)
bool hasICFGNode(const Instruction *inst)
CallICFGNode * getCallBlock(const Instruction *cs)
Get/Add a call node.
Definition LLVMModule.h:495
ValueToIDMapTy objSymMap
map a obj reference to its sym id
Definition LLVMModule.h:121
ICFGNode * getICFGNode(const Instruction *inst)
Get a basic block ICFGNode.
const Function * getFunction(const std::string &name)
Get the corresponding Function based on its name.
Definition LLVMModule.h:313
CallICFGNode * getCallICFGNode(const Instruction *cs)
get a call node
Fun2AnnoMap ExtFun2Annotations
Record annotations of function in extapi.bc.
Definition LLVMModule.h:97
bool is_arg_alloc(const Function *F)
Map< const Function *, std::vector< std::string > > func2Annotations
Definition LLVMModule.h:100
const BasicBlock * getFunExitBB(const Function *fun) const
Definition LLVMModule.h:185
NodeID getObjectNode(const Value *V)
RetICFGNode * getRetICFGNode(const Instruction *cs)
get a return node
void prePassSchedule()
Invoke llvm passes to modify module.
StInfo * collectStructInfo(const StructType *structTy, u32_t &numFields)
Collect the struct info and set the number of fields after flattening.
s32_t get_alloc_arg_pos(const Function *F)
void addFunctionSet(const Function *svfFunc)
Definition LLVMModule.h:452
const std::vector< std::reference_wrapper< Module > > & getLLVMModules() const
Definition LLVMModule.h:164
LLVMContext & getContext() const
Definition LLVMModule.h:393
friend class SymbolTableBuilder
Definition LLVMModule.h:51
bool is_ext(const Function *F)
Map< const Function *, DominatorTree > FunToDominatorTree
Definition LLVMModule.h:118
static void buildSVFModule(Module &mod)
SVFBaseNode2LLVMValueMap SVFBaseNode2LLVMValue
Definition LLVMModule.h:111
StInfo * collectArrayInfo(const ArrayType *T)
Collect the array info.
LLVMModuleSet()
Constructor.
SVFType * addSVFTypeInfo(const Type *t)
Create SVFTypes.
FunctionSet funSet
Definition LLVMModule.h:125
FunctionSetType ExtFuncsVec
Record some "sse_" function declarations used in other ext function definition, e....
Definition LLVMModule.h:95
bool hasExtFuncAnnotation(const Function *fun, const std::string &funcAnnotation)
static LLVMModuleSet * llvmModuleSet
Definition LLVMModule.h:84
IntraICFGNode * getIntraICFGNode(const Instruction *inst)
get a intra node
std::vector< std::reference_wrapper< Module > > modules
Definition LLVMModule.h:89
std::string getExtFuncAnnotation(const Function *fun, const std::string &funcAnnotation)
bool empty() const
Definition LLVMModule.h:399
Map< std::string, std::vector< std::string > > Fun2AnnoMap
Definition LLVMModule.h:65
u32_t getModuleNum() const
Definition LLVMModule.h:159
GlobalDefToRepMapTy GlobalDefToRepMap
Global definition to a rep definition map.
Definition LLVMModule.h:103
std::vector< std::unique_ptr< Module > > owned_modules
Definition LLVMModule.h:88
bool is_memset(const Function *F)
FunToIDMapTy & varargSyms()
Definition LLVMModule.h:286
Type2TypeInfoMap Type2TypeInfo
Definition LLVMModule.h:108
void dumpModulesToFile(const std::string &suffix)
void collectExtFunAnnotations(const Module *mod)
bool is_memcpy(const Function *F)
ObjTypeInference * getTypeInference()
bool is_realloc(const Function *F)
static NodeIDAllocator * get(void)
Return (singleton) allocator.
NodeID allocateTypeId(void)
Allocate an type ID as determined by the strategy.
static const Option< bool > UndefAsNull
Definition Options.h:99
static const Option< std::string > Graphtxt
Definition Options.h:174
static Option< bool > SVFMain
Definition Options.h:175
static bool pagReadFromTXT()
Definition SVFIR.h:281
void setModuleIdentifier(const std::string &moduleIdentifier)
Definition SVFIR.h:291
static SVFIR * getPAG(bool buildFromFile=false)
Singleton design here to make sure we only have one instance during any analysis.
Definition SVFIR.h:121
static void setPagFromTXT(const std::string &txt)
Definition SVFIR.h:286
static double timeOfBuildingLLVMModule
Definition SVFStat.h:96
static double getClk(bool mark=false)
Definition SVFStat.cpp:52
static double timeOfBuildingSymbolTable
Definition SVFStat.h:97
static SVFType * svfPtrTy
ptr type
Definition SVFType.h:230
static SVFType * svfI8Ty
8-bit int type
Definition SVFType.h:231
void setTypeInfo(StInfo *ti)
Definition SVFType.h:268
virtual void setSourceLoc(const std::string &sourceCodeInfo)
Definition SVFValue.h:189
virtual void setName(const std::string &nameInfo)
Definition SVFValue.h:174
std::vector< const SVFType * > & getFlattenElementTypes()
Definition SVFType.h:127
void setNumOfFieldsAndElems(u32_t nf, u32_t ne)
Set number of fields and elements of an aggregate.
Definition SVFType.h:157
u32_t getNumOfFlattenElements() const
Return number of elements after flattening (including array elements).
Definition SVFType.h:164
std::vector< const SVFType * > & getFlattenFieldTypes()
Definition SVFType.h:131
void addFldWithType(u32_t fldIdx, const SVFType *type, u32_t elemIdx)
Add field index and element index and their corresponding type.
Definition SVFValue.cpp:58
u32_t getNumOfFlattenFields() const
Return the number of fields after flattening (ignoring array elements).
Definition SVFType.h:170
void buildMemModel()
Start building memory model.
#define NULL
Definition extapi.c:5
int isdigit(int c)
Definition extapi.c:1031
bool isIntrinsicInst(const Instruction *inst)
Return true if it is an intrinsic instruction.
Definition LLVMUtil.cpp:204
std::vector< const Function * > getCalledFunctions(const Function *F)
Get all called funcions in a parent function.
Definition LLVMUtil.cpp:365
bool isCallSite(const Instruction *inst)
Whether an instruction is a call or invoke instruction.
Definition LLVMUtil.h:57
bool functionDoesNotRet(const Function *fun)
Definition LLVMUtil.cpp:124
std::pair< s64_t, u64_t > getIntegerValue(const ConstantInt *intValue)
Definition LLVMUtil.h:95
static TargetABI detectTargetABI(const llvm::Triple &triple)
Definition LLVMUtil.h:337
const std::string getSourceLoc(const Value *val)
Definition LLVMUtil.cpp:454
const Value * getGlobalRep(const Value *val)
find the unique defined global across multiple modules
Definition LLVMUtil.cpp:441
bool basicBlockHasRetInst(const BasicBlock *bb)
Return true if the function has a return instruction.
Definition LLVMUtil.cpp:110
static llvm::Triple getTargetTriple(const Module *mod)
Definition LLVMUtil.h:327
bool isIRFile(const std::string &filename)
Check whether a file is an LLVM IR file.
Definition LLVMUtil.cpp:316
std::string restoreFuncName(std::string funcName)
Definition LLVMUtil.cpp:408
bool isNonInstricCallSite(const Instruction *inst)
Whether an instruction is a callsite in the application code, excluding llvm intrinsic calls.
Definition LLVMUtil.cpp:732
std::string pasMsg(const std::string &msg)
Print each pass/phase message by converting a string into blue string output.
Definition SVFUtil.cpp:121
std::enable_if_t<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type > cast(const Y &Val)
Definition Casting.h:360
LLVM_NODISCARD bool isa(const Y &Val)
Definition Casting.h:241
std::ostream & errs()
Overwrite llvm::errs().
Definition SVFUtil.h:64
std::ostream & outs()
Overwrite llvm::outs().
Definition SVFUtil.h:58
LLVM_NODISCARD std::enable_if_t<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type > dyn_cast(const Y &Val)
Definition Casting.h:405
for isBitcode
Definition BasicTypes.h:70
std::map< Key, Value, Compare, Allocator > OrderedMap
Definition GeneralType.h:64
llvm::GlobalVariable GlobalVariable
Definition BasicTypes.h:131
llvm::ArrayType ArrayType
Definition BasicTypes.h:93
llvm::raw_fd_ostream raw_fd_ostream
LLVM outputs.
Definition BasicTypes.h:267
llvm::Type Type
Definition BasicTypes.h:81
llvm::BasicBlock BasicBlock
Definition BasicTypes.h:84
llvm::inst_iterator inst_iterator
Definition BasicTypes.h:252
llvm::ConstantStruct ConstantStruct
Definition BasicTypes.h:104
llvm::StructType StructType
LLVM types.
Definition BasicTypes.h:92
unsigned long long u64_t
Definition GeneralType.h:69
llvm::IntegerType IntegerType
Definition BasicTypes.h:95
u32_t NodeID
Definition GeneralType.h:76
std::set< Key, Compare, Allocator > OrderedSet
Definition GeneralType.h:60
std::unordered_set< Key, Hash, KeyEqual, Allocator > Set
Definition GeneralType.h:51
llvm::ConstantArray ConstantArray
Definition BasicTypes.h:121
llvm::Function Function
Definition BasicTypes.h:83
llvm::FunctionType FunctionType
Definition BasicTypes.h:96
llvm::Instruction Instruction
Definition BasicTypes.h:85
llvm::Constant Constant
Definition BasicTypes.h:122
llvm::SMDiagnostic SMDiagnostic
Definition BasicTypes.h:88
llvm::ConstantDataSequential ConstantDataSequential
Definition BasicTypes.h:117
llvm::Value Value
LLVM Basic classes.
Definition BasicTypes.h:80
llvm::ConstantExpr ConstantExpr
Definition BasicTypes.h:118
llvm::IRBuilder IRBuilder
Definition BasicTypes.h:76
std::unordered_map< Key, Value, Hash, KeyEqual, Allocator > Map
Definition GeneralType.h:56
signed s32_t
Definition GeneralType.h:68
llvm::Module Module
Definition BasicTypes.h:82
SVFIR PAG
Definition SVFIR.h:937
unsigned u32_t
Definition GeneralType.h:67
llvm::CallInst CallInst
Definition BasicTypes.h:148
llvm::FunctionCallee FunctionCallee
Definition BasicTypes.h:271
llvm::ConstantInt ConstantInt
Definition BasicTypes.h:123
llvm::DominatorTree DominatorTree
LLVM Dominators.
Definition BasicTypes.h:134
IntervalValue operator>(const IntervalValue &lhs, const IntervalValue &rhs)