1+
2+
3+ #include " clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
4+ #include " clang/StaticAnalyzer/Core/BugReporter/BugType.h"
5+ #include " clang/StaticAnalyzer/Core/Checker.h"
6+ #include " clang/StaticAnalyzer/Core/CheckerManager.h"
7+ #include " clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
8+ #include " clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
9+
10+ #include " clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h"
11+
12+ using namespace clang ;
13+ using namespace ento ;
14+
15+ #pragma clang optimize off
16+
17+ namespace {
18+
19+ // Since we are looking to extract the arguments, go with pre call for now
20+ class ThreadModeling : public Checker <check::PreCall> {
21+
22+ const CallDescriptionSet ThreadCreateCalls {
23+ { CDM::CLibrary, {" pthread_create" }, 4 },
24+ };
25+
26+ const FunctionDecl *GetFunctionDecl (SVal V, CheckerContext &C) const ;
27+ public:
28+ void checkPreCall (const CallEvent &Call, CheckerContext &C) const ;
29+ };
30+
31+ } // end anonymous namespace
32+
33+
34+ void ThreadModeling::checkPreCall (const CallEvent &Call, CheckerContext &C) const {
35+ if (!ThreadCreateCalls.contains (Call)) {
36+ return ;
37+ }
38+
39+ // 1. Get the `start_routine` argument
40+ ProgramStateRef State = C.getState ();
41+ const FunctionDecl *CreateCall = reinterpret_cast <const FunctionDecl*>(Call.getDecl ());
42+
43+ // 2. Extract the start_routine parameter
44+ /* int pthread_create(pthread_t *restrict thread,
45+ const pthread_attr_t *restrict attr,
46+ void *(*start_routine)(void *),
47+ void *restrict arg);
48+ */
49+ assert (Call.getNumArgs () == 4 && " pthread_create(3) should have 4 arguments" );
50+ Expr const *StartRoutineExpr = Call.getArgExpr (2 );
51+ assert (StartRoutineExpr && " start_routine should exist" ); // XXX: might fail if in diff TU?
52+
53+ // 3. Get the function pointer for `start_routine`
54+ SVal const SRV = C.getSVal (StartRoutineExpr);
55+ MemRegion const *SRR = SRV.getAsRegion ();
56+ assert (SRR && " start_routine should be a pointer" );
57+
58+ // 4. Resolve FunctionDecl from pointer
59+ FunctionDecl const *StartRoutine = nullptr ;
60+
61+ if (auto const *FR = dyn_cast<FunctionCodeRegion>(SRR)) {
62+ StartRoutine = dyn_cast<FunctionDecl>(FR->getDecl ());
63+ } // XXX: Can the function pointer be a different region type? (e.g. SymbolicRegion)
64+ assert (StartRoutine && " start_routine be a valid function pointer" );
65+
66+ // 5. Get AST (single TU for now)
67+ // 6. Resolve AST to Call
68+ // 7. Inline Call
69+
70+
71+ }
72+
73+ const FunctionDecl *ThreadModeling::GetFunctionDecl (SVal V, CheckerContext &C) const {
74+ if (const FunctionDecl *FD = V.getAsFunctionDecl ())
75+ return FD;
76+ return nullptr ;
77+ }
78+
79+ void clang::ento::registerThreadModeling (CheckerManager &Mgr) {
80+ Mgr.registerChecker <ThreadModeling>();
81+ }
82+
83+ bool clang::ento::shouldRegisterThreadModeling (const CheckerManager &) {
84+ return true ;
85+ }
0 commit comments