svf-tools 1.0.313 → 1.0.314
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/SVF-doxygen/html/html/Andersen_8cpp_source.html +4 -4
- package/SVF-doxygen/html/html/CHG_8cpp_source.html +1 -1
- package/SVF-doxygen/html/html/FlowSensitive_8cpp_source.html +4 -4
- package/SVF-doxygen/html/html/MemModelBuilder_8cpp.html +90 -0
- package/SVF-doxygen/html/html/MemModelBuilder_8cpp_source.html +205 -0
- package/SVF-doxygen/html/html/MemModelBuilder_8h.html +97 -0
- package/SVF-doxygen/html/html/MemModelBuilder_8h_source.html +105 -0
- package/SVF-doxygen/html/html/MemModel_8cpp_source.html +1 -1
- package/SVF-doxygen/html/html/MemRegion_8cpp_source.html +1 -1
- package/SVF-doxygen/html/html/NodeIDAllocator_8cpp_source.html +12 -12
- package/SVF-doxygen/html/html/NodeIDAllocator_8h_source.html +12 -12
- package/SVF-doxygen/html/html/PAGBuilder_8cpp_source.html +11 -11
- package/SVF-doxygen/html/html/PAGNode_8h_source.html +2 -2
- package/SVF-doxygen/html/html/PAG_8cpp_source.html +3 -3
- package/SVF-doxygen/html/html/PAG_8h_source.html +21 -21
- package/SVF-doxygen/html/html/PTAStat_8cpp_source.html +2 -2
- package/SVF-doxygen/html/html/PointerAnalysis_8cpp_source.html +2 -2
- package/SVF-doxygen/html/html/SVFModule_8cpp.html +1 -1
- package/SVF-doxygen/html/html/SVFModule_8cpp_source.html +5 -4
- package/SVF-doxygen/html/html/SymbolTableInfo_8cpp_source.html +2 -59
- package/SVF-doxygen/html/html/SymbolTableInfo_8h_source.html +86 -97
- package/SVF-doxygen/html/html/VersionedFlowSensitive_8cpp_source.html +2 -2
- package/SVF-doxygen/html/html/annotated.html +135 -134
- package/SVF-doxygen/html/html/classSVF_1_1Andersen.html +4 -4
- package/SVF-doxygen/html/html/classSVF_1_1CHGraph.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1FlowSensitive.html +4 -4
- package/SVF-doxygen/html/html/classSVF_1_1GepObjPN.html +2 -2
- package/SVF-doxygen/html/html/classSVF_1_1MRGenerator.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1MemModelBuilder-members.html +95 -0
- package/SVF-doxygen/html/html/classSVF_1_1MemModelBuilder.html +711 -0
- package/SVF-doxygen/html/html/classSVF_1_1MemObj.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1NodeIDAllocator-members.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1NodeIDAllocator.html +7 -7
- package/SVF-doxygen/html/html/classSVF_1_1NodeIDAllocator_1_1Clusterer.html +34 -34
- package/SVF-doxygen/html/html/classSVF_1_1ObjTypeInfo.html +2 -2
- package/SVF-doxygen/html/html/classSVF_1_1PAG.html +27 -27
- package/SVF-doxygen/html/html/classSVF_1_1PAGBuilder.html +21 -21
- package/SVF-doxygen/html/html/classSVF_1_1PTAStat.html +3 -3
- package/SVF-doxygen/html/html/classSVF_1_1PointerAnalysis.html +2 -2
- package/SVF-doxygen/html/html/classSVF_1_1SVFModule.html +3 -3
- package/SVF-doxygen/html/html/classSVF_1_1SymbolTableInfo-members.html +45 -56
- package/SVF-doxygen/html/html/classSVF_1_1SymbolTableInfo.html +266 -778
- package/SVF-doxygen/html/html/classSVF_1_1VersionedFlowSensitive.html +2 -2
- package/SVF-doxygen/html/html/classes.html +89 -89
- package/SVF-doxygen/html/html/dir_5840dc76920ee0f379cd88b55fa041fd.html +1 -1
- package/SVF-doxygen/html/html/dir_770a542efe75a1b68c109cb4e4290224.html +1 -1
- package/SVF-doxygen/html/html/files.html +2 -2
- package/SVF-doxygen/html/html/functions_a.html +1 -1
- package/SVF-doxygen/html/html/functions_b.html +1 -1
- package/SVF-doxygen/html/html/functions_c.html +10 -11
- package/SVF-doxygen/html/html/functions_e.html +1 -1
- package/SVF-doxygen/html/html/functions_f.html +3 -3
- package/SVF-doxygen/html/html/functions_func.html +1 -1
- package/SVF-doxygen/html/html/functions_func_b.html +1 -1
- package/SVF-doxygen/html/html/functions_func_c.html +8 -7
- package/SVF-doxygen/html/html/functions_func_e.html +1 -1
- package/SVF-doxygen/html/html/functions_func_g.html +1 -1
- package/SVF-doxygen/html/html/functions_func_h.html +3 -3
- package/SVF-doxygen/html/html/functions_func_i.html +1 -1
- package/SVF-doxygen/html/html/functions_func_m.html +3 -0
- package/SVF-doxygen/html/html/functions_func_p.html +1 -1
- package/SVF-doxygen/html/html/functions_func_s.html +8 -5
- package/SVF-doxygen/html/html/functions_g.html +1 -1
- package/SVF-doxygen/html/html/functions_h.html +3 -3
- package/SVF-doxygen/html/html/functions_i.html +4 -4
- package/SVF-doxygen/html/html/functions_l.html +5 -5
- package/SVF-doxygen/html/html/functions_m.html +4 -0
- package/SVF-doxygen/html/html/functions_n.html +4 -4
- package/SVF-doxygen/html/html/functions_p.html +10 -6
- package/SVF-doxygen/html/html/functions_r.html +2 -2
- package/SVF-doxygen/html/html/functions_rela.html +3 -0
- package/SVF-doxygen/html/html/functions_s.html +20 -16
- package/SVF-doxygen/html/html/functions_t.html +3 -3
- package/SVF-doxygen/html/html/functions_u.html +3 -3
- package/SVF-doxygen/html/html/functions_v.html +3 -3
- package/SVF-doxygen/html/html/functions_vars_s.html +2 -1
- package/SVF-doxygen/html/html/functions_w.html +3 -1
- package/SVF-doxygen/html/html/hierarchy.html +127 -126
- package/SVF-doxygen/html/html/namespaceSVF.html +2 -0
- package/SVF-doxygen/html/html/search/all_1.js +1 -1
- package/SVF-doxygen/html/html/search/all_10.js +6 -6
- package/SVF-doxygen/html/html/search/all_12.js +1 -1
- package/SVF-doxygen/html/html/search/all_13.js +5 -4
- package/SVF-doxygen/html/html/search/all_14.js +5 -5
- package/SVF-doxygen/html/html/search/all_15.js +2 -2
- package/SVF-doxygen/html/html/search/all_16.js +1 -1
- package/SVF-doxygen/html/html/search/all_17.js +1 -1
- package/SVF-doxygen/html/html/search/all_2.js +1 -1
- package/SVF-doxygen/html/html/search/all_3.js +7 -7
- package/SVF-doxygen/html/html/search/all_5.js +1 -1
- package/SVF-doxygen/html/html/search/all_6.js +1 -1
- package/SVF-doxygen/html/html/search/all_7.js +1 -1
- package/SVF-doxygen/html/html/search/all_8.js +3 -3
- package/SVF-doxygen/html/html/search/all_9.js +2 -2
- package/SVF-doxygen/html/html/search/all_c.js +2 -4
- package/SVF-doxygen/html/html/search/all_d.js +4 -1
- package/SVF-doxygen/html/html/search/all_e.js +3 -3
- package/SVF-doxygen/html/html/search/classes_a.js +1 -0
- package/SVF-doxygen/html/html/search/files_8.js +1 -3
- package/SVF-doxygen/html/html/search/files_9.js +2 -0
- package/SVF-doxygen/html/html/search/functions_0.js +1 -1
- package/SVF-doxygen/html/html/search/functions_1.js +1 -1
- package/SVF-doxygen/html/html/search/functions_10.js +1 -0
- package/SVF-doxygen/html/html/search/functions_2.js +6 -6
- package/SVF-doxygen/html/html/search/functions_4.js +1 -1
- package/SVF-doxygen/html/html/search/functions_6.js +1 -1
- package/SVF-doxygen/html/html/search/functions_7.js +3 -3
- package/SVF-doxygen/html/html/search/functions_8.js +1 -1
- package/SVF-doxygen/html/html/search/functions_b.js +1 -0
- package/SVF-doxygen/html/html/search/functions_e.js +1 -1
- package/SVF-doxygen/html/html/search/related_3.js +1 -0
- package/SVF-doxygen/html/html/search/variables_13.js +1 -1
- package/SVF-doxygen/html/html/search/variables_14.js +3 -3
- package/SVF-doxygen/html/html/search/variables_15.js +1 -1
- package/SVF-doxygen/html/html/search/variables_d.js +1 -1
- package/SVF-doxygen/html/html/search/variables_e.js +2 -2
- package/include/SVF-FE/MemModelBuilder.h +102 -0
- package/include/SVF-FE/SymbolTableInfo.h +7 -32
- package/include/Util/NodeIDAllocator.h +1 -1
- package/lib/SVF-FE/MemModelBuilder.cpp +616 -0
- package/lib/SVF-FE/SymbolTableInfo.cpp +0 -570
- package/lib/Util/NodeIDAllocator.cpp +2 -1
- package/lib/Util/SVFModule.cpp +3 -2
- package/package.json +1 -1
- package/include/SVF-FE/LocMemModel.h +0 -35
- package/lib/SVF-FE/LocMemModel.cpp +0 -31
|
@@ -48,156 +48,6 @@ DataLayout* SymbolTableInfo::dl = nullptr;
|
|
|
48
48
|
SymbolTableInfo* SymbolTableInfo::symInfo = nullptr;
|
|
49
49
|
|
|
50
50
|
|
|
51
|
-
/*!
|
|
52
|
-
* Analyse types of all flattened fields of this object
|
|
53
|
-
*/
|
|
54
|
-
void SymbolTableInfo::analyzeGlobalStackObjType(ObjTypeInfo* typeinfo, const Value* val)
|
|
55
|
-
{
|
|
56
|
-
|
|
57
|
-
const PointerType * refty = SVFUtil::dyn_cast<PointerType>(val->getType());
|
|
58
|
-
assert(SVFUtil::isa<PointerType>(refty) && "this value should be a pointer type!");
|
|
59
|
-
Type* elemTy = refty->getElementType();
|
|
60
|
-
bool isPtrObj = false;
|
|
61
|
-
// Find the inter nested array element
|
|
62
|
-
while (const ArrayType *AT= SVFUtil::dyn_cast<ArrayType>(elemTy))
|
|
63
|
-
{
|
|
64
|
-
elemTy = AT->getElementType();
|
|
65
|
-
if(elemTy->isPointerTy())
|
|
66
|
-
isPtrObj = true;
|
|
67
|
-
if(SVFUtil::isa<GlobalVariable>(val) && SVFUtil::cast<GlobalVariable>(val)->hasInitializer()
|
|
68
|
-
&& SVFUtil::isa<ConstantArray>(SVFUtil::cast<GlobalVariable>(val)->getInitializer()))
|
|
69
|
-
{
|
|
70
|
-
typeinfo->setFlag(ObjTypeInfo::CONST_ARRAY_OBJ);
|
|
71
|
-
}
|
|
72
|
-
else
|
|
73
|
-
typeinfo->setFlag(ObjTypeInfo::VAR_ARRAY_OBJ);
|
|
74
|
-
}
|
|
75
|
-
if (const StructType *ST= SVFUtil::dyn_cast<StructType>(elemTy))
|
|
76
|
-
{
|
|
77
|
-
const std::vector<FieldInfo>& flattenFields = SymbolTableInfo::SymbolInfo()->getFlattenFieldInfoVec(ST);
|
|
78
|
-
for(std::vector<FieldInfo>::const_iterator it = flattenFields.begin(), eit = flattenFields.end();
|
|
79
|
-
it!=eit; ++it)
|
|
80
|
-
{
|
|
81
|
-
if((*it).getFlattenElemTy()->isPointerTy())
|
|
82
|
-
isPtrObj = true;
|
|
83
|
-
}
|
|
84
|
-
if(SVFUtil::isa<GlobalVariable>(val) && SVFUtil::cast<GlobalVariable>(val)->hasInitializer()
|
|
85
|
-
&& SVFUtil::isa<ConstantStruct>(SVFUtil::cast<GlobalVariable>(val)->getInitializer()))
|
|
86
|
-
typeinfo->setFlag(ObjTypeInfo::CONST_STRUCT_OBJ);
|
|
87
|
-
else
|
|
88
|
-
typeinfo->setFlag(ObjTypeInfo::VAR_STRUCT_OBJ);
|
|
89
|
-
}
|
|
90
|
-
else if (elemTy->isPointerTy())
|
|
91
|
-
{
|
|
92
|
-
isPtrObj = true;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
if(isPtrObj)
|
|
96
|
-
typeinfo->setFlag(ObjTypeInfo::HASPTR_OBJ);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/*!
|
|
100
|
-
* Initialize the type info of an object
|
|
101
|
-
*/
|
|
102
|
-
void SymbolTableInfo::initTypeInfo(ObjTypeInfo* typeinfo, const Value* val){
|
|
103
|
-
|
|
104
|
-
Size_t objSize = 1;
|
|
105
|
-
// Global variable
|
|
106
|
-
if (SVFUtil::isa<Function>(val))
|
|
107
|
-
{
|
|
108
|
-
typeinfo->setFlag(ObjTypeInfo::FUNCTION_OBJ);
|
|
109
|
-
analyzeGlobalStackObjType(typeinfo,val);
|
|
110
|
-
objSize = getObjSize(val);
|
|
111
|
-
}
|
|
112
|
-
else if(SVFUtil::isa<AllocaInst>(val))
|
|
113
|
-
{
|
|
114
|
-
typeinfo->setFlag(ObjTypeInfo::STACK_OBJ);
|
|
115
|
-
analyzeGlobalStackObjType(typeinfo,val);
|
|
116
|
-
objSize = getObjSize(val);
|
|
117
|
-
}
|
|
118
|
-
else if(SVFUtil::isa<GlobalVariable>(val))
|
|
119
|
-
{
|
|
120
|
-
typeinfo->setFlag(ObjTypeInfo::GLOBVAR_OBJ);
|
|
121
|
-
if(SymbolTableInfo::SymbolInfo()->isConstantObjSym(val))
|
|
122
|
-
typeinfo->setFlag(ObjTypeInfo::CONST_OBJ);
|
|
123
|
-
analyzeGlobalStackObjType(typeinfo,val);
|
|
124
|
-
objSize = getObjSize(val);
|
|
125
|
-
}
|
|
126
|
-
else if (SVFUtil::isa<Instruction>(val) && isHeapAllocExtCall(SVFUtil::cast<Instruction>(val)))
|
|
127
|
-
{
|
|
128
|
-
typeinfo->analyzeHeapObjType(val->getType());
|
|
129
|
-
// Heap object, label its field as infinite here
|
|
130
|
-
objSize = -1;
|
|
131
|
-
}
|
|
132
|
-
else if (SVFUtil::isa<Instruction>(val) && isStaticExtCall(SVFUtil::cast<Instruction>(val)))
|
|
133
|
-
{
|
|
134
|
-
typeinfo->analyzeStaticObjType(val->getType());
|
|
135
|
-
// static object allocated before main, label its field as infinite here
|
|
136
|
-
objSize = -1;
|
|
137
|
-
}
|
|
138
|
-
else if(ArgInProgEntryFunction(val))
|
|
139
|
-
{
|
|
140
|
-
typeinfo->analyzeStaticObjType(val->getType());
|
|
141
|
-
// user input data, label its field as infinite here
|
|
142
|
-
objSize = -1;
|
|
143
|
-
}
|
|
144
|
-
else
|
|
145
|
-
assert("what other object do we have??");
|
|
146
|
-
|
|
147
|
-
// Reset maxOffsetLimit if it is over the total fieldNum of this object
|
|
148
|
-
if(objSize > 0 && typeinfo->getMaxFieldOffsetLimit() > objSize)
|
|
149
|
-
typeinfo->setMaxFieldOffsetLimit(objSize);
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
/*!
|
|
153
|
-
* Return size of this Object
|
|
154
|
-
*/
|
|
155
|
-
u32_t SymbolTableInfo::getObjSize(const Value* val)
|
|
156
|
-
{
|
|
157
|
-
|
|
158
|
-
Type* ety = SVFUtil::cast<PointerType>(val->getType())->getElementType();
|
|
159
|
-
u32_t numOfFields = 1;
|
|
160
|
-
if (SVFUtil::isa<StructType>(ety) || SVFUtil::isa<ArrayType>(ety))
|
|
161
|
-
{
|
|
162
|
-
numOfFields = SymbolTableInfo::SymbolInfo()->getFlattenFieldInfoVec(ety).size();
|
|
163
|
-
}
|
|
164
|
-
return numOfFields;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
/*
|
|
168
|
-
* Initial the memory object here
|
|
169
|
-
*/
|
|
170
|
-
ObjTypeInfo* SymbolTableInfo::createObjTypeInfo(const Value *val)
|
|
171
|
-
{
|
|
172
|
-
const PointerType *refTy = nullptr;
|
|
173
|
-
|
|
174
|
-
const Instruction *I = SVFUtil::dyn_cast<Instruction>(val);
|
|
175
|
-
|
|
176
|
-
// We consider two types of objects:
|
|
177
|
-
// (1) A heap/static object from a callsite
|
|
178
|
-
if (I && isNonInstricCallSite(I))
|
|
179
|
-
refTy = getRefTypeOfHeapAllocOrStatic(I);
|
|
180
|
-
// (2) Other objects (e.g., alloca, global, etc.)
|
|
181
|
-
else
|
|
182
|
-
refTy = SVFUtil::dyn_cast<PointerType>(val->getType());
|
|
183
|
-
|
|
184
|
-
if (refTy)
|
|
185
|
-
{
|
|
186
|
-
Type *objTy = refTy->getElementType();
|
|
187
|
-
ObjTypeInfo* typeInfo = new ObjTypeInfo(val, objTy, Options::MaxFieldLimit);
|
|
188
|
-
initTypeInfo(typeInfo,val);
|
|
189
|
-
return typeInfo;
|
|
190
|
-
}
|
|
191
|
-
else
|
|
192
|
-
{
|
|
193
|
-
writeWrnMsg("try to create an object with a non-pointer type.");
|
|
194
|
-
writeWrnMsg(val->getName().str());
|
|
195
|
-
writeWrnMsg("(" + getSourceLoc(val) + ")");
|
|
196
|
-
assert(false && "Memory object must be held by a pointer-typed ref value.");
|
|
197
|
-
abort();
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
|
|
201
51
|
/*
|
|
202
52
|
* Initial the memory object here (for a dummy object)
|
|
203
53
|
*/
|
|
@@ -528,161 +378,6 @@ LocationSet SymbolTableInfo::getModulusOffset(const MemObj* obj, const LocationS
|
|
|
528
378
|
}
|
|
529
379
|
|
|
530
380
|
|
|
531
|
-
/*!
|
|
532
|
-
* This method identify which is value sym and which is object sym
|
|
533
|
-
*/
|
|
534
|
-
void SymbolTableInfo::buildMemModel(SVFModule* svfModule)
|
|
535
|
-
{
|
|
536
|
-
SVFUtil::increaseStackSize();
|
|
537
|
-
|
|
538
|
-
mod = svfModule;
|
|
539
|
-
|
|
540
|
-
StInfo::setMaxFieldLimit(Options::MaxFieldLimit);
|
|
541
|
-
|
|
542
|
-
// Object #0 is black hole the object that may point to any object
|
|
543
|
-
assert(totalSymNum == BlackHole && "Something changed!");
|
|
544
|
-
symTyMap.insert(std::make_pair(totalSymNum++, BlackHole));
|
|
545
|
-
createBlkOrConstantObj(BlackHole);
|
|
546
|
-
|
|
547
|
-
// Object #1 always represents the constant
|
|
548
|
-
assert(totalSymNum == ConstantObj && "Something changed!");
|
|
549
|
-
symTyMap.insert(std::make_pair(totalSymNum++, ConstantObj));
|
|
550
|
-
createBlkOrConstantObj(ConstantObj);
|
|
551
|
-
|
|
552
|
-
// Pointer #2 always represents the pointer points-to black hole.
|
|
553
|
-
assert(totalSymNum == BlkPtr && "Something changed!");
|
|
554
|
-
symTyMap.insert(std::make_pair(totalSymNum++, BlkPtr));
|
|
555
|
-
|
|
556
|
-
// Pointer #3 always represents the null pointer.
|
|
557
|
-
assert(totalSymNum == NullPtr && "Something changed!");
|
|
558
|
-
symTyMap.insert(std::make_pair(totalSymNum, NullPtr));
|
|
559
|
-
|
|
560
|
-
// Add symbols for all the globals .
|
|
561
|
-
for (SVFModule::global_iterator I = svfModule->global_begin(), E =
|
|
562
|
-
svfModule->global_end(); I != E; ++I)
|
|
563
|
-
{
|
|
564
|
-
collectSym(*I);
|
|
565
|
-
}
|
|
566
|
-
|
|
567
|
-
// Add symbols for all the global aliases
|
|
568
|
-
for (SVFModule::alias_iterator I = svfModule->alias_begin(), E =
|
|
569
|
-
svfModule->alias_end(); I != E; I++)
|
|
570
|
-
{
|
|
571
|
-
collectSym(*I);
|
|
572
|
-
collectSym((*I)->getAliasee());
|
|
573
|
-
}
|
|
574
|
-
|
|
575
|
-
// Add symbols for all of the functions and the instructions in them.
|
|
576
|
-
for (SVFModule::llvm_iterator F = svfModule->llvmFunBegin(), E = svfModule->llvmFunEnd(); F != E; ++F)
|
|
577
|
-
{
|
|
578
|
-
Function *fun = *F;
|
|
579
|
-
collectSym(fun);
|
|
580
|
-
collectRet(fun);
|
|
581
|
-
if (fun->getFunctionType()->isVarArg())
|
|
582
|
-
collectVararg(fun);
|
|
583
|
-
|
|
584
|
-
// Add symbols for all formal parameters.
|
|
585
|
-
for (Function::arg_iterator I = fun->arg_begin(), E = fun->arg_end();
|
|
586
|
-
I != E; ++I)
|
|
587
|
-
{
|
|
588
|
-
collectSym(&*I);
|
|
589
|
-
}
|
|
590
|
-
|
|
591
|
-
// collect and create symbols inside the function body
|
|
592
|
-
for (inst_iterator II = inst_begin(*fun), E = inst_end(*fun); II != E; ++II)
|
|
593
|
-
{
|
|
594
|
-
const Instruction *inst = &*II;
|
|
595
|
-
collectSym(inst);
|
|
596
|
-
|
|
597
|
-
// initialization for some special instructions
|
|
598
|
-
//{@
|
|
599
|
-
if (const StoreInst *st = SVFUtil::dyn_cast<StoreInst>(inst))
|
|
600
|
-
{
|
|
601
|
-
collectSym(st->getPointerOperand());
|
|
602
|
-
collectSym(st->getValueOperand());
|
|
603
|
-
}
|
|
604
|
-
else if (const LoadInst *ld = SVFUtil::dyn_cast<LoadInst>(inst))
|
|
605
|
-
{
|
|
606
|
-
collectSym(ld->getPointerOperand());
|
|
607
|
-
}
|
|
608
|
-
else if (const PHINode *phi = SVFUtil::dyn_cast<PHINode>(inst))
|
|
609
|
-
{
|
|
610
|
-
for (u32_t i = 0; i < phi->getNumIncomingValues(); ++i)
|
|
611
|
-
{
|
|
612
|
-
collectSym(phi->getIncomingValue(i));
|
|
613
|
-
}
|
|
614
|
-
}
|
|
615
|
-
else if (const GetElementPtrInst *gep = SVFUtil::dyn_cast<GetElementPtrInst>(
|
|
616
|
-
inst))
|
|
617
|
-
{
|
|
618
|
-
collectSym(gep->getPointerOperand());
|
|
619
|
-
}
|
|
620
|
-
else if (const SelectInst *sel = SVFUtil::dyn_cast<SelectInst>(inst))
|
|
621
|
-
{
|
|
622
|
-
collectSym(sel->getTrueValue());
|
|
623
|
-
collectSym(sel->getFalseValue());
|
|
624
|
-
}
|
|
625
|
-
else if (const BinaryOperator *binary = SVFUtil::dyn_cast<BinaryOperator>(inst))
|
|
626
|
-
{
|
|
627
|
-
for (u32_t i = 0; i < binary->getNumOperands(); i++)
|
|
628
|
-
collectSym(binary->getOperand(i));
|
|
629
|
-
}
|
|
630
|
-
else if (const UnaryOperator *unary = SVFUtil::dyn_cast<UnaryOperator>(inst))
|
|
631
|
-
{
|
|
632
|
-
for (u32_t i = 0; i < unary->getNumOperands(); i++)
|
|
633
|
-
collectSym(unary->getOperand(i));
|
|
634
|
-
}
|
|
635
|
-
else if (const CmpInst *cmp = SVFUtil::dyn_cast<CmpInst>(inst))
|
|
636
|
-
{
|
|
637
|
-
for (u32_t i = 0; i < cmp->getNumOperands(); i++)
|
|
638
|
-
collectSym(cmp->getOperand(i));
|
|
639
|
-
}
|
|
640
|
-
else if (const CastInst *cast = SVFUtil::dyn_cast<CastInst>(inst))
|
|
641
|
-
{
|
|
642
|
-
collectSym(cast->getOperand(0));
|
|
643
|
-
}
|
|
644
|
-
else if (const ReturnInst *ret = SVFUtil::dyn_cast<ReturnInst>(inst))
|
|
645
|
-
{
|
|
646
|
-
if(ret->getReturnValue())
|
|
647
|
-
collectSym(ret->getReturnValue());
|
|
648
|
-
}
|
|
649
|
-
else if (const BranchInst *br = SVFUtil::dyn_cast<BranchInst>(inst))
|
|
650
|
-
{
|
|
651
|
-
Value* opnd = br->isConditional() ? br->getCondition() : br->getOperand(0);
|
|
652
|
-
collectSym(opnd);
|
|
653
|
-
}
|
|
654
|
-
else if (const SwitchInst *sw = SVFUtil::dyn_cast<SwitchInst>(inst))
|
|
655
|
-
{
|
|
656
|
-
collectSym(sw->getCondition());
|
|
657
|
-
}
|
|
658
|
-
else if (isNonInstricCallSite(inst))
|
|
659
|
-
{
|
|
660
|
-
|
|
661
|
-
CallSite cs = SVFUtil::getLLVMCallSite(inst);
|
|
662
|
-
callSiteSet.insert(cs);
|
|
663
|
-
for (CallSite::arg_iterator it = cs.arg_begin();
|
|
664
|
-
it != cs.arg_end(); ++it)
|
|
665
|
-
{
|
|
666
|
-
collectSym(*it);
|
|
667
|
-
}
|
|
668
|
-
// Calls to inline asm need to be added as well because the callee isn't
|
|
669
|
-
// referenced anywhere else.
|
|
670
|
-
const Value *Callee = cs.getCalledValue();
|
|
671
|
-
collectSym(Callee);
|
|
672
|
-
|
|
673
|
-
//TODO handle inlineAsm
|
|
674
|
-
///if (SVFUtil::isa<InlineAsm>(Callee))
|
|
675
|
-
|
|
676
|
-
}
|
|
677
|
-
//@}
|
|
678
|
-
}
|
|
679
|
-
}
|
|
680
|
-
|
|
681
|
-
NodeIDAllocator::get()->endSymbolAllocation();
|
|
682
|
-
if (Options::SymTabPrint) {
|
|
683
|
-
SymbolTableInfo::SymbolInfo()->dump();
|
|
684
|
-
}
|
|
685
|
-
}
|
|
686
381
|
|
|
687
382
|
/*!
|
|
688
383
|
* Destroy the memory for this symbol table after use
|
|
@@ -707,121 +402,6 @@ void SymbolTableInfo::destroy()
|
|
|
707
402
|
dl = nullptr;
|
|
708
403
|
}
|
|
709
404
|
|
|
710
|
-
/*!
|
|
711
|
-
* Collect symbols, including value and object syms
|
|
712
|
-
*/
|
|
713
|
-
void SymbolTableInfo::collectSym(const Value *val)
|
|
714
|
-
{
|
|
715
|
-
|
|
716
|
-
//TODO: filter the non-pointer type // if (!SVFUtil::isa<PointerType>(val->getType())) return;
|
|
717
|
-
|
|
718
|
-
DBOUT(DMemModel, outs() << "collect sym from ##" << *val << " \n");
|
|
719
|
-
|
|
720
|
-
// special sym here
|
|
721
|
-
if (isNullPtrSym(val) || isBlackholeSym(val))
|
|
722
|
-
return;
|
|
723
|
-
|
|
724
|
-
//TODO handle constant expression value here??
|
|
725
|
-
handleCE(val);
|
|
726
|
-
|
|
727
|
-
// create a value sym
|
|
728
|
-
collectVal(val);
|
|
729
|
-
|
|
730
|
-
// create an object If it is a heap, stack, global, function.
|
|
731
|
-
if (isObject(val))
|
|
732
|
-
{
|
|
733
|
-
collectObj(val);
|
|
734
|
-
}
|
|
735
|
-
}
|
|
736
|
-
|
|
737
|
-
/*!
|
|
738
|
-
* Get value sym, if not available create a new one
|
|
739
|
-
*/
|
|
740
|
-
void SymbolTableInfo::collectVal(const Value *val)
|
|
741
|
-
{
|
|
742
|
-
ValueToIDMapTy::iterator iter = valSymMap.find(val);
|
|
743
|
-
if (iter == valSymMap.end())
|
|
744
|
-
{
|
|
745
|
-
// create val sym and sym type
|
|
746
|
-
SymID id = NodeIDAllocator::get()->allocateValueId();
|
|
747
|
-
valSymMap.insert(std::make_pair(val, id));
|
|
748
|
-
symTyMap.insert(std::make_pair(id, ValSym));
|
|
749
|
-
DBOUT(DMemModel,
|
|
750
|
-
outs() << "create a new value sym " << id << "\n");
|
|
751
|
-
/// handle global constant expression here
|
|
752
|
-
if (const GlobalVariable* globalVar = SVFUtil::dyn_cast<GlobalVariable>(val))
|
|
753
|
-
handleGlobalCE(globalVar);
|
|
754
|
-
}
|
|
755
|
-
|
|
756
|
-
if (isConstantObjSym(val))
|
|
757
|
-
collectObj(val);
|
|
758
|
-
}
|
|
759
|
-
|
|
760
|
-
/*!
|
|
761
|
-
* Get memory object sym, if not available create a new one
|
|
762
|
-
*/
|
|
763
|
-
void SymbolTableInfo::collectObj(const Value *val)
|
|
764
|
-
{
|
|
765
|
-
val = getGlobalRep(val);
|
|
766
|
-
ValueToIDMapTy::iterator iter = objSymMap.find(val);
|
|
767
|
-
if (iter == objSymMap.end())
|
|
768
|
-
{
|
|
769
|
-
// if the object pointed by the pointer is a constant data (e.g., i32 0) or a global constant object (e.g. string)
|
|
770
|
-
// then we treat them as one ConstantObj
|
|
771
|
-
if(isConstantData(val) || (isConstantObjSym(val) && !getModelConstants()))
|
|
772
|
-
{
|
|
773
|
-
objSymMap.insert(std::make_pair(val, constantSymID()));
|
|
774
|
-
}
|
|
775
|
-
// otherwise, we will create an object for each abstract memory location
|
|
776
|
-
else
|
|
777
|
-
{
|
|
778
|
-
// create obj sym and sym type
|
|
779
|
-
SymID id = NodeIDAllocator::get()->allocateObjectId();
|
|
780
|
-
objSymMap.insert(std::make_pair(val, id));
|
|
781
|
-
symTyMap.insert(std::make_pair(id, ObjSym));
|
|
782
|
-
DBOUT(DMemModel,
|
|
783
|
-
outs() << "create a new obj sym " << id << "\n");
|
|
784
|
-
|
|
785
|
-
// create a memory object
|
|
786
|
-
MemObj* mem = new MemObj(id, createObjTypeInfo(val), val);
|
|
787
|
-
assert(objMap.find(id) == objMap.end());
|
|
788
|
-
objMap[id] = mem;
|
|
789
|
-
}
|
|
790
|
-
}
|
|
791
|
-
}
|
|
792
|
-
|
|
793
|
-
/*!
|
|
794
|
-
* Create unique return sym, if not available create a new one
|
|
795
|
-
*/
|
|
796
|
-
void SymbolTableInfo::collectRet(const Function *val)
|
|
797
|
-
{
|
|
798
|
-
FunToIDMapTy::iterator iter = returnSymMap.find(val);
|
|
799
|
-
if (iter == returnSymMap.end())
|
|
800
|
-
{
|
|
801
|
-
SymID id = NodeIDAllocator::get()->allocateValueId();
|
|
802
|
-
returnSymMap.insert(std::make_pair(val, id));
|
|
803
|
-
symTyMap.insert(std::make_pair(id, RetSym));
|
|
804
|
-
DBOUT(DMemModel,
|
|
805
|
-
outs() << "create a return sym " << id << "\n");
|
|
806
|
-
}
|
|
807
|
-
}
|
|
808
|
-
|
|
809
|
-
/*!
|
|
810
|
-
* Create vararg sym, if not available create a new one
|
|
811
|
-
*/
|
|
812
|
-
void SymbolTableInfo::collectVararg(const Function *val)
|
|
813
|
-
{
|
|
814
|
-
FunToIDMapTy::iterator iter = varargSymMap.find(val);
|
|
815
|
-
if (iter == varargSymMap.end())
|
|
816
|
-
{
|
|
817
|
-
SymID id = NodeIDAllocator::get()->allocateValueId();
|
|
818
|
-
varargSymMap.insert(std::make_pair(val, id));
|
|
819
|
-
symTyMap.insert(std::make_pair(id, VarargSym));
|
|
820
|
-
DBOUT(DMemModel,
|
|
821
|
-
outs() << "create a vararg sym " << id << "\n");
|
|
822
|
-
}
|
|
823
|
-
}
|
|
824
|
-
|
|
825
405
|
/*!
|
|
826
406
|
* Check whether this value is null pointer
|
|
827
407
|
*/
|
|
@@ -877,156 +457,6 @@ bool SymbolTableInfo::isConstantObjSym(const Value *val)
|
|
|
877
457
|
}
|
|
878
458
|
|
|
879
459
|
|
|
880
|
-
/*!
|
|
881
|
-
* Handle constant expression
|
|
882
|
-
*/
|
|
883
|
-
void SymbolTableInfo::handleCE(const Value *val)
|
|
884
|
-
{
|
|
885
|
-
if (const Constant* ref = SVFUtil::dyn_cast<Constant>(val))
|
|
886
|
-
{
|
|
887
|
-
if (const ConstantExpr* ce = isGepConstantExpr(ref))
|
|
888
|
-
{
|
|
889
|
-
DBOUT(DMemModelCE,
|
|
890
|
-
outs() << "handle constant expression " << *ref << "\n");
|
|
891
|
-
collectVal(ce);
|
|
892
|
-
collectVal(ce->getOperand(0));
|
|
893
|
-
// handle the recursive constant express case
|
|
894
|
-
// like (gep (bitcast (gep X 1)) 1); the inner gep is ce->getOperand(0)
|
|
895
|
-
handleCE(ce->getOperand(0));
|
|
896
|
-
}
|
|
897
|
-
else if (const ConstantExpr* ce = isCastConstantExpr(ref))
|
|
898
|
-
{
|
|
899
|
-
DBOUT(DMemModelCE,
|
|
900
|
-
outs() << "handle constant expression " << *ref << "\n");
|
|
901
|
-
collectVal(ce);
|
|
902
|
-
collectVal(ce->getOperand(0));
|
|
903
|
-
// handle the recursive constant express case
|
|
904
|
-
// like (gep (bitcast (gep X 1)) 1); the inner gep is ce->getOperand(0)
|
|
905
|
-
handleCE(ce->getOperand(0));
|
|
906
|
-
}
|
|
907
|
-
else if (const ConstantExpr* ce = isSelectConstantExpr(ref))
|
|
908
|
-
{
|
|
909
|
-
DBOUT(DMemModelCE,
|
|
910
|
-
outs() << "handle constant expression " << *ref << "\n");
|
|
911
|
-
collectVal(ce);
|
|
912
|
-
collectVal(ce->getOperand(0));
|
|
913
|
-
collectVal(ce->getOperand(1));
|
|
914
|
-
collectVal(ce->getOperand(2));
|
|
915
|
-
// handle the recursive constant express case
|
|
916
|
-
// like (gep (bitcast (gep X 1)) 1); the inner gep is ce->getOperand(0)
|
|
917
|
-
handleCE(ce->getOperand(0));
|
|
918
|
-
handleCE(ce->getOperand(1));
|
|
919
|
-
handleCE(ce->getOperand(2));
|
|
920
|
-
}
|
|
921
|
-
// if we meet a int2ptr, then it points-to black hole
|
|
922
|
-
else if (const ConstantExpr *int2Ptrce = isInt2PtrConstantExpr(ref)) {
|
|
923
|
-
collectVal(int2Ptrce);
|
|
924
|
-
} else if (const ConstantExpr *ptr2Intce = isPtr2IntConstantExpr(ref)) {
|
|
925
|
-
collectVal(ptr2Intce);
|
|
926
|
-
const Constant *opnd = ptr2Intce->getOperand(0);
|
|
927
|
-
handleCE(opnd);
|
|
928
|
-
} else if (isTruncConstantExpr(ref) || isCmpConstantExpr(ref)) {
|
|
929
|
-
collectVal(ref);
|
|
930
|
-
} else if (isBinaryConstantExpr(ref)) {
|
|
931
|
-
collectVal(ref);
|
|
932
|
-
} else if (isUnaryConstantExpr(ref)) {
|
|
933
|
-
// we don't handle unary constant expression like fneg(x) now
|
|
934
|
-
collectVal(ref);
|
|
935
|
-
} else if (SVFUtil::isa<ConstantAggregate>(ref)) {
|
|
936
|
-
// we don't handle constant agrgregate like constant vectors
|
|
937
|
-
collectVal(ref);
|
|
938
|
-
} else {
|
|
939
|
-
if (SVFUtil::isa<ConstantExpr>(val))
|
|
940
|
-
assert(false && "we don't handle all other constant expression for now!");
|
|
941
|
-
collectVal(ref);
|
|
942
|
-
}
|
|
943
|
-
}
|
|
944
|
-
}
|
|
945
|
-
|
|
946
|
-
/*!
|
|
947
|
-
* Handle global constant expression
|
|
948
|
-
*/
|
|
949
|
-
void SymbolTableInfo::handleGlobalCE(const GlobalVariable *G)
|
|
950
|
-
{
|
|
951
|
-
assert(G);
|
|
952
|
-
|
|
953
|
-
//The type this global points to
|
|
954
|
-
const Type *T = G->getType()->getContainedType(0);
|
|
955
|
-
bool is_array = 0;
|
|
956
|
-
//An array is considered a single variable of its type.
|
|
957
|
-
while (const ArrayType *AT = SVFUtil::dyn_cast<ArrayType>(T))
|
|
958
|
-
{
|
|
959
|
-
T = AT->getElementType();
|
|
960
|
-
is_array = 1;
|
|
961
|
-
}
|
|
962
|
-
|
|
963
|
-
if (SVFUtil::isa<StructType>(T))
|
|
964
|
-
{
|
|
965
|
-
//A struct may be used in constant GEP expr.
|
|
966
|
-
for (Value::const_user_iterator it = G->user_begin(), ie = G->user_end();
|
|
967
|
-
it != ie; ++it)
|
|
968
|
-
{
|
|
969
|
-
handleCE(*it);
|
|
970
|
-
}
|
|
971
|
-
}
|
|
972
|
-
else
|
|
973
|
-
{
|
|
974
|
-
if (is_array)
|
|
975
|
-
{
|
|
976
|
-
for (Value::const_user_iterator it = G->user_begin(), ie =
|
|
977
|
-
G->user_end(); it != ie; ++it)
|
|
978
|
-
{
|
|
979
|
-
handleCE(*it);
|
|
980
|
-
}
|
|
981
|
-
}
|
|
982
|
-
}
|
|
983
|
-
|
|
984
|
-
if (G->hasInitializer())
|
|
985
|
-
{
|
|
986
|
-
handleGlobalInitializerCE(G->getInitializer(), 0);
|
|
987
|
-
}
|
|
988
|
-
}
|
|
989
|
-
|
|
990
|
-
/*!
|
|
991
|
-
* Handle global variable initialization
|
|
992
|
-
*/
|
|
993
|
-
void SymbolTableInfo::handleGlobalInitializerCE(const Constant *C,
|
|
994
|
-
u32_t offset)
|
|
995
|
-
{
|
|
996
|
-
|
|
997
|
-
if (C->getType()->isSingleValueType())
|
|
998
|
-
{
|
|
999
|
-
if (const ConstantExpr *E = SVFUtil::dyn_cast<ConstantExpr>(C))
|
|
1000
|
-
{
|
|
1001
|
-
handleCE(E);
|
|
1002
|
-
}
|
|
1003
|
-
else
|
|
1004
|
-
{
|
|
1005
|
-
collectVal(C);
|
|
1006
|
-
}
|
|
1007
|
-
}
|
|
1008
|
-
else if (SVFUtil::isa<ConstantArray>(C))
|
|
1009
|
-
{
|
|
1010
|
-
for (u32_t i = 0, e = C->getNumOperands(); i != e; i++)
|
|
1011
|
-
{
|
|
1012
|
-
handleGlobalInitializerCE(SVFUtil::cast<Constant>(C->getOperand(i)), offset);
|
|
1013
|
-
}
|
|
1014
|
-
}
|
|
1015
|
-
else if (SVFUtil::isa<ConstantStruct>(C))
|
|
1016
|
-
{
|
|
1017
|
-
const StructType *sty = SVFUtil::cast<StructType>(C->getType());
|
|
1018
|
-
const std::vector<u32_t>& offsetvect =
|
|
1019
|
-
SymbolTableInfo::SymbolInfo()->getFattenFieldIdxVec(sty);
|
|
1020
|
-
for (u32_t i = 0, e = C->getNumOperands(); i != e; i++)
|
|
1021
|
-
{
|
|
1022
|
-
u32_t off = offsetvect[i];
|
|
1023
|
-
handleGlobalInitializerCE(SVFUtil::cast<Constant>(C->getOperand(i)),
|
|
1024
|
-
offset + off);
|
|
1025
|
-
}
|
|
1026
|
-
}
|
|
1027
|
-
}
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
460
|
/*
|
|
1031
461
|
* Print out the composite type information
|
|
1032
462
|
*/
|
|
@@ -148,9 +148,10 @@ namespace SVF
|
|
|
148
148
|
return id;
|
|
149
149
|
}
|
|
150
150
|
|
|
151
|
-
|
|
151
|
+
NodeID NodeIDAllocator::endSymbolAllocation(void)
|
|
152
152
|
{
|
|
153
153
|
numSymbols = numNodes;
|
|
154
|
+
return numSymbols;
|
|
154
155
|
}
|
|
155
156
|
|
|
156
157
|
const std::string NodeIDAllocator::Clusterer::NumObjects = "NumObjects";
|
package/lib/Util/SVFModule.cpp
CHANGED
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
#include "Util/SVFModule.h"
|
|
25
|
-
#include "SVF-FE/
|
|
25
|
+
#include "SVF-FE/MemModelBuilder.h"
|
|
26
26
|
#include "Util/SVFUtil.h"
|
|
27
27
|
|
|
28
28
|
using namespace SVF;
|
|
@@ -34,6 +34,7 @@ void SVFModule::buildSymbolTableInfo()
|
|
|
34
34
|
/// building symbol table
|
|
35
35
|
DBOUT(DGENERAL, SVFUtil::outs() << SVFUtil::pasMsg("Building Symbol table ...\n"));
|
|
36
36
|
SymbolTableInfo *symInfo = SymbolTableInfo::SymbolInfo();
|
|
37
|
-
symInfo
|
|
37
|
+
MemModelBuilder builder(symInfo);
|
|
38
|
+
builder.buildMemModel(this);
|
|
38
39
|
}
|
|
39
40
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "svf-tools",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.314",
|
|
4
4
|
"description": "* <b>[TypeClone](https://github.com/SVF-tools/SVF/wiki/TypeClone) published in our [ECOOP paper](https://yuleisui.github.io/publications/ecoop20.pdf) is now available in SVF </b> * <b>SVF now uses a single script for its build. Just type [`source ./build.sh`](https://github.com/SVF-tools/SVF/blob/master/build.sh) in your terminal, that's it!</b> * <b>SVF now supports LLVM-10.0.0! </b> * <b>We thank [bsauce](https://github.com/bsauce) for writing a user manual of SVF ([link1](https://www.jianshu.com/p/068a08ec749c) and [link2](https://www.jianshu.com/p/777c30d4240e)) in Chinese </b> * <b>SVF now supports LLVM-9.0.0 (Thank [Byoungyoung Lee](https://github.com/SVF-tools/SVF/issues/142) for his help!). </b> * <b>SVF now supports a set of [field-sensitive pointer analyses](https://yuleisui.github.io/publications/sas2019a.pdf). </b> * <b>[Use SVF as an external lib](https://github.com/SVF-tools/SVF/wiki/Using-SVF-as-a-lib-in-your-own-tool) for your own project (Contributed by [Hongxu Chen](https://github.com/HongxuChen)). </b> * <b>SVF now supports LLVM-7.0.0. </b> * <b>SVF now supports Docker. [Try SVF in Docker](https://github.com/SVF-tools/SVF/wiki/Try-SVF-in-Docker)! </b> * <b>SVF now supports [LLVM-6.0.0](https://github.com/svf-tools/SVF/pull/38) (Contributed by [Jack Anthony](https://github.com/jackanth)). </b> * <b>SVF now supports [LLVM-4.0.0](https://github.com/svf-tools/SVF/pull/23) (Contributed by Jared Carlson. Thank [Jared](https://github.com/jcarlson23) and [Will](https://github.com/dtzWill) for their in-depth [discussions](https://github.com/svf-tools/SVF/pull/18) about updating SVF!) </b> * <b>SVF now supports analysis for C++ programs.</b> <br />",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
//===- LocMemModel.h -- Location set based memory model-----------------------//
|
|
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 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 General Public License for more details.
|
|
17
|
-
|
|
18
|
-
// You should have received a copy of the GNU General Public License
|
|
19
|
-
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
20
|
-
//
|
|
21
|
-
//===----------------------------------------------------------------------===//
|
|
22
|
-
|
|
23
|
-
/*
|
|
24
|
-
* LocMemModel.h
|
|
25
|
-
*
|
|
26
|
-
* Created on: Apr 28, 2014
|
|
27
|
-
* Author: Yulei
|
|
28
|
-
*/
|
|
29
|
-
|
|
30
|
-
#ifndef LOCMEMMODEL_H_
|
|
31
|
-
#define LOCMEMMODEL_H_
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
#endif /* LOCMEMMODEL_H_ */
|