Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions pybind/AE.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ using namespace SVF;

void bind_abstract_state(py::module& m) {

// Virtual-memory address constants from AddressValue.h, exposed so Python
// code can build the null / black-hole address without hard-coding literals.
m.attr("NullMemAddr") = (uint32_t)(NullMemAddr);
m.attr("BlackHoleObjAddr") = (uint32_t)(BlackHoleObjAddr);

py::class_<BoundedInt>(m, "BoundedInt")
.def(py::init([](int64_t val) {
return new BoundedInt(val);
Expand Down
15 changes: 14 additions & 1 deletion pybind/Graphs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ void bind_icfg_node(py::module& m) {
.def("addActualParms", &CallICFGNode::addActualParms, "Add an actual parameter to the call")
.def("isVarArg", &CallICFGNode::isVarArg, "Check if the call is a vararg call")
.def("isVirtualCall", &CallICFGNode::isVirtualCall, "Check if the call is a virtual call")
.def("arg_size", &CallICFGNode::arg_size, "Get the number of actual arguments at the call site")
.def("getRetICFGNode", &CallICFGNode::getRetICFGNode, py::return_value_policy::reference, "Get the return node");

// === RetICFGNode ===
Expand Down Expand Up @@ -220,6 +221,12 @@ void bind_icfg_graph(py::module& m) {
return nodes;
}, py::return_value_policy::reference)

// getICFGEdge(src, dst, kind): 0=IntraCF, 1=CallCF, 2=RetCF. Returns None if absent.
.def("getICFGEdge", [](ICFG& icfg, const ICFGNode* src, const ICFGNode* dst, int kind) -> ICFGEdge* {
return icfg.getICFGEdge(src, dst, static_cast<ICFGEdge::ICFGEdgeK>(kind));
}, py::arg("src"), py::arg("dst"), py::arg("kind") = 0, py::return_value_policy::reference,
"Get the ICFG edge between src and dst of the given kind (0=IntraCF,1=CallCF,2=RetCF); None if absent")

// getGNode(id)
.def("getGNode", [](ICFG& icfg, NodeID id) -> ICFGNode* {
ICFGNode* node = icfg.getGNode(id);
Expand Down Expand Up @@ -404,7 +411,13 @@ void bind_callgraph(py::module& m) {
}, py::arg("id"), py::return_value_policy::reference, "Check if a node is in a cycle")
.def("repNode", [](Andersen::CallGraphSCC& cg, NodeID id) {
return cg.repNode(id);
}, py::arg("id"), "Get the representative node ID of the SCC containing the given node");
}, py::arg("id"), "Get the representative node ID of the SCC containing the given node")
.def("subNodes", [](Andersen::CallGraphSCC& cg, NodeID rep) {
std::vector<NodeID> out;
for (NodeID n : cg.subNodes(rep))
out.push_back(n);
return out;
}, py::arg("rep"), "Get the call-graph node IDs in the SCC represented by 'rep'");
}

void bind_thread_call_graph(py::module &m) {
Expand Down
2 changes: 2 additions & 0 deletions pysvf/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,8 @@ def main():
AbstractValue,
BoundedInt,
Options,
NullMemAddr,
BlackHoleObjAddr,
MTA,
MHP,
LockAnalysis,
Expand Down
13 changes: 13 additions & 0 deletions pysvf/pysvf.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ LLVM_DIR: str
EXTAPI_BC_PATH: str
Z3_DIR: str

# Virtual-memory address constants (from AddressValue.h).
NullMemAddr: int
BlackHoleObjAddr: int

def run_tool(tool_name: str, args: List[str]) -> None: ...

SVFFunction = Any
Expand Down Expand Up @@ -197,6 +201,9 @@ class CallGraphSCC:
def repNode(self, id: int) -> int: ...
"""Get the representative node ID of the SCC containing the given node"""

def subNodes(self, rep: int) -> List[int]: ...
"""Get the call-graph node IDs in the SCC represented by 'rep'"""

class FunEntryICFGNode(ICFGNode):
def __init__(self, *args, **kwargs) -> None: ...
"""Not intended for direct instantiation."""
Expand Down Expand Up @@ -236,6 +243,9 @@ class CallICFGNode(ICFGNode):
def getArgument(self, idx: int) -> "SVFVar": ...
"""Get the argument at the given index"""

def arg_size(self) -> int: ...
"""Get the number of actual arguments at the call site"""

def isVarArg(self) -> bool: ...
"""Check if the call is a vararg call"""

Expand Down Expand Up @@ -645,6 +655,9 @@ class ICFG:
def getNodes(self) -> List[ICFGNode]: ...
"""Get the nodes of the ICFG"""

def getICFGEdge(self, src: ICFGNode, dst: ICFGNode, kind: int = ...) -> Optional["ICFGEdge"]: ...
"""Get the ICFG edge between src and dst of the given kind (0=IntraCF,1=CallCF,2=RetCF); None if absent"""

def getGNode(self, id: int) -> ICFGNode: ...
"""Get the ICFG node with the given ID"""

Expand Down
Loading