diff options
| author | Mason Reed <mason@vector35.com> | 2026-03-03 07:57:33 -0800 |
|---|---|---|
| committer | Mason Reed <35282038+emesare@users.noreply.github.com> | 2026-03-24 18:46:48 -0700 |
| commit | 2c358e705bbde855b12780be86ef19501a62dfed (patch) | |
| tree | 4f3012bdf36c9a0f7de4218790e6e1aa389621ba /plugins/warp/ui | |
| parent | 7877f7caa3535a7c477c911ddeafdf5bb14ebc14 (diff) | |
[WARP] Server-side constraint matching
Reduce networked functions by constraining on the returned set of functions on the server
Diffstat (limited to 'plugins/warp/ui')
| -rw-r--r-- | plugins/warp/ui/shared/fetchdialog.cpp | 34 | ||||
| -rw-r--r-- | plugins/warp/ui/shared/fetchdialog.h | 3 | ||||
| -rw-r--r-- | plugins/warp/ui/shared/fetcher.cpp | 28 | ||||
| -rw-r--r-- | plugins/warp/ui/shared/misc.h | 4 |
4 files changed, 35 insertions, 34 deletions
diff --git a/plugins/warp/ui/shared/fetchdialog.cpp b/plugins/warp/ui/shared/fetchdialog.cpp index 328f00c2..44d7c237 100644 --- a/plugins/warp/ui/shared/fetchdialog.cpp +++ b/plugins/warp/ui/shared/fetchdialog.cpp @@ -67,12 +67,6 @@ WarpFetchDialog::WarpFetchDialog(BinaryViewRef bv, std::shared_ptr<WarpFetcher> for (const auto& t : GetAllowedTagsFromView(m_bv)) AddListItem(m_tagsList, QString::fromStdString(t)); - // Batch size and matcher checkbox - m_batchSize = new QSpinBox(this); - m_batchSize->setRange(10, 1000); - m_batchSize->setValue(GetBatchSizeFromView(m_bv)); - m_batchSize->setToolTip("Number of functions to fetch in each batch"); - m_rerunMatcher = new QCheckBox("Re-run matcher after fetch", this); m_rerunMatcher->setChecked(true); @@ -83,7 +77,6 @@ WarpFetchDialog::WarpFetchDialog(BinaryViewRef bv, std::shared_ptr<WarpFetcher> form->addRow(new QLabel("Container: "), m_containerCombo); form->addRow(new QLabel("Allowed Tags: "), tagWrapper); - form->addRow(new QLabel("Batch Size: "), m_batchSize); form->addRow(m_rerunMatcher); form->addRow(m_clearProcessed); @@ -144,7 +137,6 @@ void WarpFetchDialog::onAccept() if (idx > 0) // 0 == All Containers containerIndex = static_cast<size_t>(idx - 1); - const auto batch = static_cast<size_t>(m_batchSize->value()); const bool rerun = m_rerunMatcher->isChecked(); const auto tags = collectTags(); @@ -155,7 +147,7 @@ void WarpFetchDialog::onAccept() m_fetchProcessor->ClearProcessed(); // Execute the network fetch in batches - runBatchedFetch(containerIndex, tags, batch, rerun); + runBatchedFetch(containerIndex, tags, rerun); accept(); } @@ -169,7 +161,7 @@ void WarpFetchDialog::onReject() } void WarpFetchDialog::runBatchedFetch(const std::optional<size_t>& containerIndex, - const std::vector<Warp::SourceTag>& allowedTags, size_t batchSize, bool rerunMatcher) + const std::vector<Warp::SourceTag>& allowedTags, bool rerunMatcher) { if (!m_bv) return; @@ -177,42 +169,34 @@ void WarpFetchDialog::runBatchedFetch(const std::optional<size_t>& containerInde std::vector<Ref<Function>> funcs = m_bv->GetAnalysisFunctionList(); if (funcs.empty()) return; - const size_t totalFuncs = funcs.size(); - const size_t totalBatches = (totalFuncs + batchSize - 1) / batchSize; // Create a background task to show progress in the UI Ref<BackgroundTask> task = - new BackgroundTask("Fetching WARP functions (0 / " + std::to_string(totalBatches) + ")", false); + new BackgroundTask("Fetching WARP functions (0 / " + std::to_string(funcs.size()) + ")", true); auto fetcher = m_fetchProcessor; auto bv = m_bv; // TODO: Too many captures in this thing lol. WorkerInteractiveEnqueue( - [fetcher, bv, funcs = std::move(funcs), batchSize, rerunMatcher, task, allowedTags]() mutable { + [fetcher, bv, funcs = std::move(funcs), rerunMatcher, task, allowedTags]() mutable { + const auto batchSize = GetBatchSizeFromView(bv); size_t processed = 0; - size_t batchIndex = 0; - while (processed < funcs.size()) { + if (task->IsCancelled()) + break; const size_t remaining = funcs.size() - processed; const size_t thisBatchCount = std::min(batchSize, remaining); - for (size_t i = 0; i < thisBatchCount; ++i) fetcher->AddPendingFunction(funcs[processed + i]); - fetcher->FetchPendingFunctions(allowedTags); - - ++batchIndex; processed += thisBatchCount; - - task->SetProgressText("Fetching WARP functions (" + std::to_string(batchIndex) + " / " - + std::to_string((funcs.size() + batchSize - 1) / batchSize) + ")"); + task->SetProgressText("Fetching WARP functions (" + std::to_string(processed) + " / " + std::to_string(funcs.size()) + ")"); } task->Finish(); - // TODO: Print how long it took? - Logger("WARP Fetcher").LogInfo("Finished fetching WARP functions..."); + Logger("WARP Fetcher").LogInfo("Finished fetching WARP functions in %d seconds...", task->GetRuntimeSeconds()); if (rerunMatcher && bv) Warp::RunMatcher(*bv); diff --git a/plugins/warp/ui/shared/fetchdialog.h b/plugins/warp/ui/shared/fetchdialog.h index c642d31e..72b8c57e 100644 --- a/plugins/warp/ui/shared/fetchdialog.h +++ b/plugins/warp/ui/shared/fetchdialog.h @@ -22,7 +22,6 @@ class WarpFetchDialog : public QDialog QPushButton* m_removeTagBtn; QPushButton* m_resetTagBtn; - QSpinBox* m_batchSize; QCheckBox* m_rerunMatcher; QCheckBox* m_clearProcessed; @@ -51,7 +50,7 @@ private: std::vector<Warp::SourceTag> collectTags() const; void runBatchedFetch(const std::optional<size_t>& containerIndex, const std::vector<Warp::SourceTag>& allowedTags, - size_t batchSize, bool rerunMatcher); + bool rerunMatcher); }; void RegisterWarpFetchFunctionsCommand(); diff --git a/plugins/warp/ui/shared/fetcher.cpp b/plugins/warp/ui/shared/fetcher.cpp index 51ab018c..2eab910a 100644 --- a/plugins/warp/ui/shared/fetcher.cpp +++ b/plugins/warp/ui/shared/fetcher.cpp @@ -63,22 +63,40 @@ void WarpFetcher::FetchPendingFunctions(const std::vector<Warp::SourceTag>& allo // Because we must fetch for a single target we map the function guids to the associated platform to perform fetches // for each. - std::map<PlatformRef, std::vector<Warp::FunctionGUID>> platformMappedGuids; + std::map<PlatformRef, std::unordered_set<Warp::FunctionGUID>> platformMappedGuidSet; + std::map<PlatformRef, std::unordered_set<Warp::ConstraintGUID>> platformMappedConstraintSet; for (const auto& func : requests) { - const auto guid = Warp::GetAnalysisFunctionGUID(*func); - if (!guid.has_value()) + const auto warpFunc = Warp::Function::Get(*func); + if (!warpFunc) continue; auto platform = func->GetPlatform(); - platformMappedGuids[platform].push_back(guid.value()); + platformMappedGuidSet[platform].insert(warpFunc->GetGUID()); + + // We want to keep track of the guids so we can constrain the server response to only return functions with any of them. + const auto constraints = warpFunc->GetConstraints(); + std::vector<Warp::ConstraintGUID> constraintGuids; + constraintGuids.reserve(constraints.size()); + for (const auto& constraint : constraints) + constraintGuids.push_back(constraint.guid); + platformMappedConstraintSet[platform].insert(constraintGuids.begin(), constraintGuids.end()); } + std::map<PlatformRef, std::vector<Warp::FunctionGUID>> platformMappedGuids; + for (const auto& [platform, guids] : platformMappedGuidSet) + platformMappedGuids[platform] = std::vector(guids.begin(), guids.end()); + + // We keep them in the set above so we don't duplicate a bunch for functions with the same set of constraint guids. + std::map<PlatformRef, std::vector<Warp::ConstraintGUID>> platformMappedConstraints; + for (const auto& [platform, guids] : platformMappedConstraintSet) + platformMappedConstraints[platform] = std::vector(guids.begin(), guids.end()); + for (const auto& [platform, guids] : platformMappedGuids) { m_logger->LogDebugF("Fetching {} functions for platform {}", guids.size(), platform->GetName()); auto target = Warp::Target::FromPlatform(*platform); for (const auto& container : Warp::Container::All()) - container->FetchFunctions(*target, guids, allowedTags); + container->FetchFunctions(*target, guids, allowedTags, platformMappedConstraints[platform]); std::lock_guard<std::mutex> lock(m_requestMutex); for (const auto& guid : guids) diff --git a/plugins/warp/ui/shared/misc.h b/plugins/warp/ui/shared/misc.h index 97adcab0..92e27fd8 100644 --- a/plugins/warp/ui/shared/misc.h +++ b/plugins/warp/ui/shared/misc.h @@ -138,10 +138,10 @@ inline void SetTagsToView(const BinaryViewRef& view, const std::vector<Warp::Sou settings->Set(ALLOWED_TAGS_SETTING, tags, view); } -inline int GetBatchSizeFromView(const BinaryViewRef& view) +inline size_t GetBatchSizeFromView(const BinaryViewRef& view) { auto settings = BinaryNinja::Settings::Instance(); if (!settings->Contains(BATCH_SIZE_SETTING)) - return 100; + return 10000; return settings->Get<uint64_t>(BATCH_SIZE_SETTING, view); }
\ No newline at end of file |
