mirror of
https://github.com/rizinorg/cutter.git
synced 2025-01-19 02:48:49 +00:00
Convert agcj
command call to the API (#3012)
This commit is contained in:
parent
ddefc0663a
commit
c263d4bd1b
2
rizin
2
rizin
@ -1 +1 @@
|
|||||||
Subproject commit 215e49253d3a35e1aae340b7ae8465018254ae87
|
Subproject commit a9c59ce1ddc44c498b6a9a02e36989a34f184286
|
@ -53,11 +53,8 @@ void CallGraphView::showExportDialog()
|
|||||||
void CallGraphView::showAddress(RVA address)
|
void CallGraphView::showAddress(RVA address)
|
||||||
{
|
{
|
||||||
if (global) {
|
if (global) {
|
||||||
auto addressMappingIt = addressMapping.find(address);
|
selectBlockWithId(address);
|
||||||
if (addressMappingIt != addressMapping.end()) {
|
showBlock(blocks[address]);
|
||||||
selectBlockWithId(addressMappingIt->second);
|
|
||||||
showBlock(blocks[addressMappingIt->second]);
|
|
||||||
}
|
|
||||||
} else if (address != this->address) {
|
} else if (address != this->address) {
|
||||||
this->address = address;
|
this->address = address;
|
||||||
refreshView();
|
refreshView();
|
||||||
@ -72,53 +69,72 @@ void CallGraphView::refreshView()
|
|||||||
SimpleTextGraphView::refreshView();
|
SimpleTextGraphView::refreshView();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool isBetween(ut64 a, ut64 x, ut64 b)
|
||||||
|
{
|
||||||
|
return (a == UT64_MAX || a <= x) && (b == UT64_MAX || x <= b);
|
||||||
|
}
|
||||||
|
|
||||||
|
using PRzList = std::unique_ptr<RzList, decltype(rz_list_free) *>;
|
||||||
|
|
||||||
void CallGraphView::loadCurrentGraph()
|
void CallGraphView::loadCurrentGraph()
|
||||||
{
|
{
|
||||||
blockContent.clear();
|
blockContent.clear();
|
||||||
blocks.clear();
|
blocks.clear();
|
||||||
|
|
||||||
CutterJson nodes = Core()->cmdj(global ? "agCj" : QString("agcj @ %1").arg(address));
|
const ut64 from = Core()->getConfigi("graph.from");
|
||||||
|
const ut64 to = Core()->getConfigi("graph.to");
|
||||||
|
const bool usenames = Core()->getConfigb("graph.json.usenames");
|
||||||
|
|
||||||
QHash<QString, uint64_t> idMapping;
|
auto edges = std::unordered_set<ut64> {};
|
||||||
|
auto addFunction = [&](RzAnalysisFunction *fcn) {
|
||||||
|
GraphLayout::GraphBlock block;
|
||||||
|
block.entry = fcn->addr;
|
||||||
|
|
||||||
auto getId = [&](const QString &name) -> uint64_t {
|
auto xrefs = PRzList { rz_analysis_function_get_xrefs_from(fcn), rz_list_free };
|
||||||
auto nextId = idMapping.size();
|
auto calls = std::unordered_set<ut64>();
|
||||||
auto &itemId = idMapping[name];
|
for (const auto &xref : CutterRzList<RzAnalysisXRef>(xrefs.get())) {
|
||||||
if (idMapping.size() != nextId) {
|
const auto x = xref->to;
|
||||||
itemId = nextId;
|
if (!(xref->type == RZ_ANALYSIS_XREF_TYPE_CALL && calls.find(x) == calls.end())) {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
return itemId;
|
calls.insert(x);
|
||||||
|
block.edges.emplace_back(x);
|
||||||
|
edges.insert(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString name = usenames ? fcn->name : RzAddressString(fcn->addr);
|
||||||
|
addBlock(std::move(block), name, fcn->addr);
|
||||||
};
|
};
|
||||||
|
|
||||||
for (CutterJson block : nodes) {
|
if (global) {
|
||||||
QString name = block["name"].toString();
|
for (const auto &fcn : CutterRzList<RzAnalysisFunction>(Core()->core()->analysis->fcns)) {
|
||||||
|
if (!isBetween(from, fcn->addr, to)) {
|
||||||
auto edges = block["imports"];
|
continue;
|
||||||
GraphLayout::GraphBlock layoutBlock;
|
}
|
||||||
layoutBlock.entry = getId(name);
|
addFunction(fcn);
|
||||||
for (auto edge : edges) {
|
}
|
||||||
auto targetName = edge.toString();
|
} else {
|
||||||
auto targetId = getId(targetName);
|
const auto &fcn = Core()->functionIn(address);
|
||||||
layoutBlock.edges.emplace_back(targetId);
|
if (fcn) {
|
||||||
|
addFunction(fcn);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// it would be good if address came directly from json instead of having to lookup by name
|
for (const auto &x : edges) {
|
||||||
addBlock(std::move(layoutBlock), name, Core()->num(name));
|
if (blockContent.find(x) != blockContent.end()) {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
for (auto it = idMapping.begin(), end = idMapping.end(); it != end; ++it) {
|
|
||||||
if (blocks.find(it.value()) == blocks.end()) {
|
|
||||||
GraphLayout::GraphBlock block;
|
GraphLayout::GraphBlock block;
|
||||||
block.entry = it.value();
|
block.entry = x;
|
||||||
addBlock(std::move(block), it.key(), Core()->num(it.key()));
|
QString flagName = Core()->flagAt(x);
|
||||||
}
|
QString name = usenames
|
||||||
|
? (!flagName.isEmpty() ? flagName : QString("unk.%0").arg(RzAddressString(x)))
|
||||||
|
: RzAddressString(x);
|
||||||
|
addBlock(std::move(block), name, x);
|
||||||
}
|
}
|
||||||
if (blockContent.empty() && !global) {
|
if (blockContent.empty() && !global) {
|
||||||
addBlock({}, RzAddressString(address), address);
|
const auto name = RzAddressString(address);
|
||||||
}
|
addBlock({}, name, address);
|
||||||
|
|
||||||
addressMapping.clear();
|
|
||||||
for (auto &it : blockContent) {
|
|
||||||
addressMapping[it.second.address] = it.first;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
computeGraphPlacement();
|
computeGraphPlacement();
|
||||||
|
@ -22,7 +22,6 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
bool global; ///< is this a global or function callgraph
|
bool global; ///< is this a global or function callgraph
|
||||||
RVA address = RVA_INVALID; ///< function address if this is not a global callgraph
|
RVA address = RVA_INVALID; ///< function address if this is not a global callgraph
|
||||||
std::unordered_map<RVA, ut64> addressMapping; ///< mapping from addresses to block id
|
|
||||||
void loadCurrentGraph() override;
|
void loadCurrentGraph() override;
|
||||||
void restoreCurrentBlock() override;
|
void restoreCurrentBlock() override;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user