3535#include " WPA/Andersen.h"
3636#include < cmath>
3737#include < deque>
38+ #include < sstream>
3839
3940using namespace SVF ;
4041using namespace SVFUtil ;
@@ -163,13 +164,47 @@ void AbstractInterpretation::initWTO()
163164 }
164165}
165166
166- // / Collect all entry point functions (functions without callers)
167+ // / Parse comma-separated function names from the -ae-entry-funcs option
168+ static Set<std::string> parseEntryFuncNames ()
169+ {
170+ Set<std::string> funcNames;
171+ const std::string& entryFuncsStr = Options::AEEntryFuncs ();
172+
173+ if (entryFuncsStr.empty ())
174+ return funcNames;
175+
176+ std::stringstream ss (entryFuncsStr);
177+ std::string funcName;
178+ while (std::getline (ss, funcName, ' ,' ))
179+ {
180+ // Trim whitespace from function name
181+ size_t start = funcName.find_first_not_of (" \t " );
182+ size_t end = funcName.find_last_not_of (" \t " );
183+ if (start != std::string::npos && end != std::string::npos)
184+ {
185+ funcNames.insert (funcName.substr (start, end - start + 1 ));
186+ }
187+ else if (!funcName.empty ())
188+ {
189+ funcNames.insert (funcName);
190+ }
191+ }
192+ return funcNames;
193+ }
194+
195+ // / Collect entry point functions for analysis.
196+ // / If -ae-entry-funcs is specified, only those functions are used.
197+ // / Otherwise, all functions without callers are collected as entry points.
167198// / Uses a deque to allow efficient insertion at front for prioritizing main()
168199std::deque<const FunObjVar*> AbstractInterpretation::collectProgEntryFuns ()
169200{
170201 std::deque<const FunObjVar*> entryFunctions;
171202 const CallGraph* callGraph = svfir->getCallGraph ();
172203
204+ // Check if user specified explicit entry functions
205+ Set<std::string> specifiedFuncs = parseEntryFuncNames ();
206+ bool hasSpecifiedFuncs = !specifiedFuncs.empty ();
207+
173208 for (auto it = callGraph->begin (); it != callGraph->end (); ++it)
174209 {
175210 const CallGraphNode* cgNode = it->second ;
@@ -179,8 +214,20 @@ std::deque<const FunObjVar*> AbstractInterpretation::collectProgEntryFuns()
179214 if (fun->isDeclaration ())
180215 continue ;
181216
182- // Check if function has no callers (entry point)
183- if (cgNode->getInEdges ().empty ())
217+ bool shouldInclude = false ;
218+
219+ if (hasSpecifiedFuncs)
220+ {
221+ // Use only functions specified by -ae-entry-funcs
222+ shouldInclude = specifiedFuncs.count (fun->getName ()) > 0 ;
223+ }
224+ else
225+ {
226+ // Default: use functions without callers (entry points)
227+ shouldInclude = cgNode->getInEdges ().empty ();
228+ }
229+
230+ if (shouldInclude)
184231 {
185232 // If main exists, put it first for priority using deque's push_front
186233 if (fun->getName () == " main" )
@@ -194,6 +241,23 @@ std::deque<const FunObjVar*> AbstractInterpretation::collectProgEntryFuns()
194241 }
195242 }
196243
244+ // Warn if specified functions were not found
245+ if (hasSpecifiedFuncs)
246+ {
247+ Set<std::string> foundFuncs;
248+ for (const FunObjVar* fun : entryFunctions)
249+ {
250+ foundFuncs.insert (fun->getName ());
251+ }
252+ for (const std::string& name : specifiedFuncs)
253+ {
254+ if (foundFuncs.count (name) == 0 )
255+ {
256+ SVFUtil::errs () << " Warning: Specified entry function '" << name << " ' not found\n " ;
257+ }
258+ }
259+ }
260+
197261 return entryFunctions;
198262}
199263
@@ -203,34 +267,15 @@ void AbstractInterpretation::clearAbstractTrace()
203267 abstractTrace.clear ();
204268}
205269
206- // / Program entry - analyze from main if exists, otherwise analyze from all entry points
270+ // / Program entry - analyze from all entry points (multi-entry analysis is the default)
207271void AbstractInterpretation::analyse ()
208272{
209273 initWTO ();
210274 // handle Global ICFGNode of SVFModule
211275 handleGlobalNode ();
212276
213- // If -ae-multientry is set, always use multi-entry analysis
214- if (Options::AEMultiEntry ())
215- {
216- SVFUtil::outs () << " Multi-entry analysis enabled, analyzing from all entry points...\n " ;
217- analyzeFromAllProgEntries ();
218- return ;
219- }
220-
221- // Default behavior: start from main if exists
222- if (const CallGraphNode* cgn = svfir->getCallGraph ()->getCallGraphNode (" main" ))
223- {
224- // Use worklist-based function handling instead of recursive WTO component handling
225- const ICFGNode* mainEntry = icfg->getFunEntryICFGNode (cgn->getFunction ());
226- handleFunction (mainEntry);
227- }
228- else
229- {
230- // No main function found, analyze from all entry points (library code)
231- SVFUtil::outs () << " No main function found, analyzing from all entry points...\n " ;
232- analyzeFromAllProgEntries ();
233- }
277+ // Always use multi-entry analysis from all entry points
278+ analyzeFromAllProgEntries ();
234279}
235280
236281// / Analyze all entry points (functions without callers) - for whole-program analysis without main
0 commit comments