1313
1414namespace klee {
1515
16- MockBuilder::MockBuilder (const llvm::Module *initModule,
17- std::string mockEntrypoint, std::string userEntrypoint,
18- std::map<std::string, llvm::Type *> externals,
19- const std::string &annotationsFile)
20- : userModule(initModule), externals(std::move(externals)),
21- mockEntrypoint (std::move(mockEntrypoint)),
22- userEntrypoint(std::move(userEntrypoint)) {
23- annotations = parseAnnotations (annotationsFile, userModule);
16+ template <typename T>
17+ void inline removeAliases (const llvm::Module *userModule,
18+ std::map<std::string, T *> &externals) {
19+ for (const auto &alias : userModule->aliases ()) {
20+ auto it = externals.find (alias.getName ().str ());
21+ if (it != externals.end ()) {
22+ externals.erase (it);
23+ }
24+ }
25+ }
26+
27+ std::map<std::string, llvm::FunctionType *>
28+ MockBuilder::getExternalFunctions () {
29+ std::map<std::string, llvm::FunctionType *> externals;
30+ for (const auto &f : userModule->functions ()) {
31+ if (f.isDeclaration () && !f.use_empty () &&
32+ !ignoredExternals.count (f.getName ().str ())) {
33+ // NOTE: here we detect all the externals, even linked.
34+ externals.insert (std::make_pair (f.getName (), f.getFunctionType ()));
35+ }
36+ }
37+ removeAliases (userModule, externals);
38+
39+ for (const auto &e : externals) {
40+ klee_message (" Mocking external function %s" , e.first .c_str ());
41+ }
42+
43+ return externals;
44+ }
45+
46+ std::map<std::string, llvm::Type *> MockBuilder::getExternalGlobals () {
47+ std::map<std::string, llvm::Type *> externals;
48+ for (const auto &global : userModule->globals ()) {
49+ if (global.isDeclaration () &&
50+ !ignoredExternals.count (global.getName ().str ())) {
51+ externals.insert (std::make_pair (global.getName (), global.getValueType ()));
52+ }
53+ }
54+ removeAliases (userModule, externals);
55+
56+ for (const auto &e : externals) {
57+ klee_message (" Mocking external variable %s" , e.first .c_str ());
58+ }
59+
60+ return externals;
61+ }
62+
63+ MockBuilder::MockBuilder (
64+ const llvm::Module *initModule, const Interpreter::ModuleOptions &opts,
65+ const std::set<std::string> &ignoredExternals,
66+ std::vector<std::pair<std::string, std::string>> &redefinitions,
67+ InterpreterHandler *interpreterHandler)
68+ : userModule(initModule), opts(opts), ignoredExternals(ignoredExternals),
69+ redefinitions (redefinitions), interpreterHandler(interpreterHandler) {
70+ annotations = parseAnnotations (opts.AnnotationsFile , userModule);
2471}
2572
2673std::unique_ptr<llvm::Module> MockBuilder::build () {
2774 initMockModule ();
2875 buildMockMain ();
2976 buildExternalFunctionsDefinitions ();
77+
78+ if (!mockModule) {
79+ klee_error (" Unable to generate mocks" );
80+ }
81+
82+ {
83+ std::unique_ptr<llvm::raw_fd_ostream> of (
84+ interpreterHandler->openOutputFile (" redefinitions.txt" ));
85+ for (const auto &i : redefinitions) {
86+ *of << i.first << " " << i.second << " \n " ;
87+ }
88+ }
89+
90+ {
91+ auto mainFn = mockModule->getFunction (opts.MainCurrentName );
92+ mainFn->setName (opts.EntryPoint );
93+ std::unique_ptr<llvm::raw_fd_ostream> of (
94+ interpreterHandler->openOutputFile (" externals.ll" ));
95+ *of << *mockModule;
96+ mainFn->setName (opts.MainCurrentName );
97+ }
98+
3099 return std::move (mockModule);
31100}
32101
@@ -42,17 +111,18 @@ void MockBuilder::initMockModule() {
42111// Set up entrypoint in new module. Here we'll define external globals and then
43112// call user's entrypoint.
44113void MockBuilder::buildMockMain () {
45- llvm::Function *userMainFn = userModule->getFunction (userEntrypoint );
114+ llvm::Function *userMainFn = userModule->getFunction (opts. MainNameAfterMock );
46115 if (!userMainFn) {
47116 klee_error (" Mock: Entry function '%s' not found in module" ,
48- userEntrypoint .c_str ());
117+ opts. MainNameAfterMock .c_str ());
49118 }
50- mockModule->getOrInsertFunction (mockEntrypoint, userMainFn->getFunctionType (),
119+ mockModule->getOrInsertFunction (opts.MainCurrentName ,
120+ userMainFn->getFunctionType (),
51121 userMainFn->getAttributes ());
52- llvm::Function *mockMainFn = mockModule->getFunction (mockEntrypoint );
122+ llvm::Function *mockMainFn = mockModule->getFunction (opts. MainCurrentName );
53123 if (!mockMainFn) {
54124 klee_error (" Mock: Entry function '%s' not found in module" ,
55- mockEntrypoint .c_str ());
125+ opts. MainCurrentName .c_str ());
56126 }
57127 auto globalsInitBlock =
58128 llvm::BasicBlock::Create (mockModule->getContext (), " entry" , mockMainFn);
@@ -61,7 +131,7 @@ void MockBuilder::buildMockMain() {
61131 buildExternalGlobalsDefinitions ();
62132
63133 auto userMainCallee = mockModule->getOrInsertFunction (
64- userEntrypoint , userMainFn->getFunctionType ());
134+ opts. MainNameAfterMock , userMainFn->getFunctionType ());
65135 std::vector<llvm::Value *> args;
66136 args.reserve (userMainFn->arg_size ());
67137 for (auto it = mockMainFn->arg_begin (); it != mockMainFn->arg_end (); it++) {
@@ -72,12 +142,8 @@ void MockBuilder::buildMockMain() {
72142}
73143
74144void MockBuilder::buildExternalGlobalsDefinitions () {
75- for (const auto &it : externals) {
76- if (it.second ->isFunctionTy ()) {
77- continue ;
78- }
79- const std::string &extName = it.first ;
80- llvm::Type *type = it.second ;
145+ auto externalGlobals = getExternalGlobals ();
146+ for (const auto &[extName, type] : externalGlobals) {
81147 mockModule->getOrInsertGlobal (extName, type);
82148 auto *global = mockModule->getGlobalVariable (extName);
83149 if (!global) {
@@ -89,7 +155,7 @@ void MockBuilder::buildExternalGlobalsDefinitions() {
89155 continue ;
90156 }
91157
92- auto *zeroInitializer = llvm::Constant::getNullValue (it. second );
158+ auto *zeroInitializer = llvm::Constant::getNullValue (type );
93159 if (!zeroInitializer) {
94160 klee_error (" Mock: Unable to get zero initializer for '%s'" ,
95161 extName.c_str ());
@@ -101,24 +167,19 @@ void MockBuilder::buildExternalGlobalsDefinitions() {
101167}
102168
103169void MockBuilder::buildExternalFunctionsDefinitions () {
104- bool mockAllAnnotation = true ;
170+ auto externalFunctions = getExternalFunctions () ;
105171
106- if (mockAllAnnotation ) {
172+ if (!opts. AnnotateOnlyExternal ) {
107173 for (const auto &i : annotations) {
108174 llvm::Function *func = userModule->getFunction (i.first );
109- auto ext = externals .find (i.first );
110- if (ext == externals .end ()) {
111- externals [i.first ] = func->getType ();
175+ auto ext = externalFunctions .find (i.first );
176+ if (ext == externalFunctions .end ()) {
177+ externalFunctions [i.first ] = func->getFunctionType ();
112178 }
113179 }
114180 }
115181
116- for (const auto &it : externals) {
117- if (!it.second ->isFunctionTy ()) {
118- continue ;
119- }
120- std::string extName = it.first ;
121- auto *type = llvm::cast<llvm::FunctionType>(it.second );
182+ for (const auto &[extName, type] : externalFunctions) {
122183 mockModule->getOrInsertFunction (extName, type);
123184 llvm::Function *func = mockModule->getFunction (extName);
124185 if (!func) {
0 commit comments