Convert agcj command call to the API (#3012)

This commit is contained in:
billow 2022-08-11 01:18:56 +08:00 committed by GitHub
parent ddefc0663a
commit c263d4bd1b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 54 additions and 39 deletions

2
rizin

@ -1 +1 @@
Subproject commit 215e49253d3a35e1aae340b7ae8465018254ae87 Subproject commit a9c59ce1ddc44c498b6a9a02e36989a34f184286

View File

@ -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();

View File

@ -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;