Skip to content

Commit 7554611

Browse files
authored
Model Extern Callback Calls in LLVM Call Graphs (#849)
* Model Extern Callback Calls * Improve Extern Callback Model Validation * Validate Extern Callback Callee Types * Refine Extern Callback Model IR * Address extern callback review comments * Format call graph builder overload
1 parent 305624f commit 7554611

22 files changed

Lines changed: 1192 additions & 26 deletions
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/******************************************************************************
2+
* Copyright (c) 2026 Fabian Schiebel.
3+
* All rights reserved. This program and the accompanying materials are made
4+
* available under the terms of LICENSE.txt.
5+
*
6+
* Contributors:
7+
* Fabian Schiebel and others
8+
*****************************************************************************/
9+
10+
#ifndef PHASAR_PHASARLLVM_CONTROLFLOW_EXTERNCALLBACKMODEL_H
11+
#define PHASAR_PHASARLLVM_CONTROLFLOW_EXTERNCALLBACKMODEL_H
12+
13+
#include "llvm/ADT/StringRef.h"
14+
#include "llvm/IR/Function.h"
15+
16+
namespace psr {
17+
class LLVMProjectIRDB;
18+
19+
/// \brief Provides utilities to model calls through known external callback
20+
/// brokers.
21+
///
22+
/// The inserted model keeps the original broker call and adds a regular call to
23+
/// the callback argument, so later analyses still see an ordinary call-site.
24+
class ExternCallbackModel {
25+
public:
26+
static constexpr llvm::StringLiteral ModelPrefix = "__psrExternCallbackModel";
27+
28+
/// Rewrites all supported external callback call-sites in \p IRDB.
29+
///
30+
/// \returns the number of rewritten call-sites.
31+
static size_t rewriteCalls(LLVMProjectIRDB &IRDB);
32+
33+
/// Returns true, if a function was generated by the ExternCallbackModel.
34+
[[nodiscard]] static bool isPhasarGenerated(const llvm::Function &F) noexcept;
35+
};
36+
} // namespace psr
37+
38+
#endif // PHASAR_PHASARLLVM_CONTROLFLOW_EXTERNCALLBACKMODEL_H

include/phasar/PhasarLLVM/ControlFlow/LLVMBasedCallGraphBuilder.h

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ class Resolver;
2424
/// Constructs a call-graph using the given CGResolver to resolve indirect
2525
/// calls.
2626
///
27+
/// This overload does not mutate the IRDB. Use
28+
/// buildLLVMBasedCallGraphWithExternCallbackModels() if PhASAR should insert
29+
/// its model functions first.
30+
///
2731
/// Uses a fixpoint iteration, if
2832
/// `CGResolver.mutatesHelperAnalysisInformation()` returns true and the
2933
/// soundness S is not Soundness::Unsound.
@@ -40,9 +44,24 @@ buildLLVMBasedCallGraph(const LLVMProjectIRDB &IRDB, Resolver &CGResolver,
4044
llvm::ArrayRef<const llvm::Function *> EntryPoints,
4145
Soundness S = Soundness::Soundy);
4246

47+
/// May insert model functions for known external callback brokers before the
48+
/// call-graph is built.
49+
/// If CGResolver owns helper-analysis state that should include generated model
50+
/// functions, rewrite the IRDB before constructing that state or use a CGType
51+
/// overload.
52+
[[nodiscard]] LLVMBasedCallGraph
53+
buildLLVMBasedCallGraphWithExternCallbackModels(
54+
LLVMProjectIRDB &IRDB, Resolver &CGResolver,
55+
llvm::ArrayRef<const llvm::Function *> EntryPoints,
56+
Soundness S = Soundness::Soundy);
57+
4358
/// Constructs a call-graph using the given CGResolver to resolve indirect
4459
/// calls.
4560
///
61+
/// This overload does not mutate the IRDB. Use
62+
/// buildLLVMBasedCallGraphWithExternCallbackModels() if PhASAR should insert
63+
/// its model functions first.
64+
///
4665
/// Uses a fixpoint iteration, if
4766
/// `CGResolver.mutatesHelperAnalysisInformation()` returns true and the
4867
/// soundness S is not Soundness::Unsound.
@@ -59,6 +78,27 @@ buildLLVMBasedCallGraph(const LLVMProjectIRDB &IRDB, Resolver &CGResolver,
5978
llvm::ArrayRef<std::string> EntryPoints,
6079
Soundness S = Soundness::Soundy);
6180

81+
/// May insert model functions for known external callback brokers before the
82+
/// call-graph is built.
83+
/// If CGResolver owns helper-analysis state that should include generated model
84+
/// functions, rewrite the IRDB before constructing that state or use a CGType
85+
/// overload.
86+
[[nodiscard]] LLVMBasedCallGraph
87+
buildLLVMBasedCallGraphWithExternCallbackModels(
88+
LLVMProjectIRDB &IRDB, Resolver &CGResolver,
89+
llvm::ArrayRef<std::string> EntryPoints, Soundness S = Soundness::Soundy);
90+
91+
/// Kept for compatibility with LLVMBasedICFG. See the constructor of
92+
/// LLVMBasedICFG::LLVMBasedICFG(LLVMProjectIRDB *, CallGraphAnalysisType,
93+
/// llvm::ArrayRef<std::string>, DIBasedTypeHierarchy *, LLVMAliasInfoRef,
94+
/// Soundness, bool) for more information.
95+
[[nodiscard]] LLVMBasedCallGraph
96+
buildLLVMBasedCallGraph(LLVMProjectIRDB &IRDB, CallGraphAnalysisType CGType,
97+
llvm::ArrayRef<const llvm::Function *> EntryPoints,
98+
DIBasedTypeHierarchy *TH, LLVMVFTableProvider &VTP,
99+
LLVMAliasInfoRef PT = nullptr,
100+
Soundness S = Soundness::Soundy);
101+
62102
/// Kept for compatibility with LLVMBasedICFG. See the constructor of
63103
/// LLVMBasedICFG::LLVMBasedICFG(LLVMProjectIRDB *, CallGraphAnalysisType,
64104
/// llvm::ArrayRef<std::string>, DIBasedTypeHierarchy *, LLVMAliasInfoRef,
@@ -70,6 +110,17 @@ buildLLVMBasedCallGraph(LLVMProjectIRDB &IRDB, CallGraphAnalysisType CGType,
70110
LLVMAliasInfoRef PT = nullptr,
71111
Soundness S = Soundness::Soundy);
72112

113+
/// Kept for compatibility with LLVMBasedICFG. See the constructor of
114+
/// LLVMBasedICFG::LLVMBasedICFG(LLVMProjectIRDB *, CallGraphAnalysisType,
115+
/// llvm::ArrayRef<std::string>, DIBasedTypeHierarchy *, LLVMAliasInfoRef,
116+
/// Soundness, bool) for more information.
117+
[[nodiscard]] LLVMBasedCallGraph
118+
buildLLVMBasedCallGraph(LLVMProjectIRDB &IRDB, CallGraphAnalysisType CGType,
119+
llvm::ArrayRef<std::string> EntryPoints,
120+
DIBasedTypeHierarchy *TH, LLVMVFTableProvider &VTP,
121+
LLVMAliasInfoRef PT = nullptr,
122+
Soundness S = Soundness::Soundy);
123+
73124
/// Kept for compatibility with LLVMBasedICFG. See the constructor of
74125
/// LLVMBasedICFG::LLVMBasedICFG(LLVMProjectIRDB *, CallGraphAnalysisType,
75126
/// llvm::ArrayRef<std::string>, DIBasedTypeHierarchy *, LLVMAliasInfoRef,

include/phasar/PhasarLLVM/ControlFlow/LLVMBasedICFG.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "phasar/ControlFlow/CallGraph.h"
2121
#include "phasar/ControlFlow/CallGraphAnalysisType.h"
2222
#include "phasar/ControlFlow/ICFGBase.h"
23+
#include "phasar/PhasarLLVM/ControlFlow/ExternCallbackModel.h"
2324
#include "phasar/PhasarLLVM/ControlFlow/GlobalCtorsDtorsModel.h"
2425
#include "phasar/PhasarLLVM/ControlFlow/LLVMBasedCFG.h"
2526
#include "phasar/PhasarLLVM/ControlFlow/LLVMBasedCallGraph.h"
@@ -74,6 +75,9 @@ class LLVMBasedICFG : public LLVMBasedCFG, public ICFGBase<LLVMBasedICFG> {
7475
/// \param IncludeGlobals Properly include global constructors/destructors
7576
/// into the ICFG, if true. Requires to generate artificial functions into the
7677
/// IRDB. True by default
78+
///
79+
/// Note that LLVMBasedICFG may also insert model functions for known external
80+
/// callback brokers, independent of IncludeGlobals.
7781
explicit LLVMBasedICFG(LLVMProjectIRDB *IRDB, CallGraphAnalysisType CGType,
7882
llvm::ArrayRef<std::string> EntryPoints = {},
7983
DIBasedTypeHierarchy *TH = nullptr,
@@ -132,7 +136,8 @@ class LLVMBasedICFG : public LLVMBasedCFG, public ICFGBase<LLVMBasedICFG> {
132136
/// Returns true, if a function was generated by phasar.
133137
[[nodiscard]] static bool
134138
isPhasarGenerated(const llvm::Function &F) noexcept {
135-
return GlobalCtorsDtorsModel::isPhasarGenerated(F);
139+
return GlobalCtorsDtorsModel::isPhasarGenerated(F) ||
140+
ExternCallbackModel::isPhasarGenerated(F);
136141
}
137142

138143
using CFGBase::print;

0 commit comments

Comments
 (0)