in libredex/DexAssessments.cpp [283:453]
DexAssessment DexScopeAssessor::run() {
// This struct combines all individual assessment implementations.
struct Assessment {
dex_position::Assessment dex_position_assessment;
Assessment& operator+=(const Assessment& other) {
dex_position_assessment += other.dex_position_assessment;
return *this;
}
bool has_problems() { return dex_position_assessment.has_problems(); }
DexAssessment to_dex_assessment() {
return dex_position_assessment.to_dex_assessment();
}
};
struct ClassStats {
std::atomic<size_t> classes_without_deobfuscated_name{0};
std::atomic<size_t> with_annotations{0};
std::atomic<size_t> sum_annotations{0};
};
ClassStats class_stats{};
walk::parallel::classes(m_scope, [&class_stats](DexClass* c) {
if (c->get_deobfuscated_name_or_null() == nullptr) {
class_stats.classes_without_deobfuscated_name.fetch_add(1);
}
auto* aset = c->get_anno_set();
if (aset != nullptr && aset->size() > 0) {
class_stats.with_annotations.fetch_add(1, std::memory_order_relaxed);
class_stats.sum_annotations.fetch_add(aset->size(),
std::memory_order_relaxed);
}
});
struct FieldStats {
std::atomic<size_t> fields_without_deobfuscated_name{0};
std::atomic<size_t> num_fields{0};
std::atomic<size_t> with_annotations{0};
std::atomic<size_t> sum_annotations{0};
};
FieldStats field_stats{};
walk::parallel::fields(m_scope, [&field_stats](DexField* f) {
field_stats.num_fields.fetch_add(1, std::memory_order_relaxed);
auto* aset = f->get_anno_set();
if (aset != nullptr && aset->size() > 0) {
field_stats.with_annotations.fetch_add(1, std::memory_order_relaxed);
field_stats.sum_annotations.fetch_add(aset->size(),
std::memory_order_relaxed);
}
if (f->get_deobfuscated_name().empty()) {
field_stats.fields_without_deobfuscated_name.fetch_add(1);
}
});
struct MethodStats {
std::atomic<size_t> methods_without_deobfuscated_name{0};
std::atomic<size_t> num_methods{0};
std::atomic<size_t> methods_with_code{0};
std::atomic<size_t> num_instructions{0};
std::atomic<size_t> sum_opcodes{0};
std::atomic<size_t> with_annotations{0};
std::atomic<size_t> sum_annotations{0};
std::atomic<size_t> with_param_annotations{0};
std::atomic<size_t> sum_param_annotations{0};
};
MethodStats method_stats{};
walk::parallel::methods(m_scope, [&method_stats](auto* m) {
method_stats.num_methods.fetch_add(1, std::memory_order_relaxed);
{
auto* aset = m->get_anno_set();
if (aset != nullptr && aset->size() > 0) {
method_stats.with_annotations.fetch_add(1, std::memory_order_relaxed);
method_stats.sum_annotations.fetch_add(aset->size(),
std::memory_order_relaxed);
}
}
{
auto* panno = m->get_param_anno();
if (panno != nullptr && !panno->empty()) {
method_stats.with_param_annotations.fetch_add(
1, std::memory_order_relaxed);
method_stats.sum_param_annotations.fetch_add(panno->size(),
std::memory_order_relaxed);
}
}
if (m->get_deobfuscated_name_or_null() == nullptr) {
method_stats.methods_without_deobfuscated_name.fetch_add(1);
}
auto code = m->get_code();
if (code == nullptr) {
return;
}
method_stats.methods_with_code.fetch_add(1, std::memory_order_relaxed);
method_stats.num_instructions.fetch_add(code->count_opcodes(),
std::memory_order_relaxed);
method_stats.sum_opcodes.fetch_add(code->sum_opcode_sizes(),
std::memory_order_relaxed);
});
dex_position::Assessor dex_position_assessor;
auto combined_assessment = walk::parallel::methods<Assessment>(
m_scope, [&dex_position_assessor](DexMethod* method) {
Assessment assessment;
auto code = method->get_code();
if (!code) {
return assessment;
}
always_assert(!code->editable_cfg_built());
if (!code->cfg_built()) {
code->build_cfg(/*editable*/ false);
}
assessment.dex_position_assessment =
dex_position_assessor.analyze_method(method, code->cfg());
if (traceEnabled(ASSESSOR, 2) && assessment.has_problems()) {
if (traceEnabled(ASSESSOR, 3)) {
TRACE(ASSESSOR,
3,
"[scope assessor] %s: %s\n%s",
SHOW(method),
to_string(assessment.to_dex_assessment()).c_str(),
SHOW(code->cfg()));
} else {
TRACE(ASSESSOR,
2,
"[scope assessor] %s: %s",
SHOW(method),
to_string(assessment.to_dex_assessment()).c_str());
}
}
return assessment;
});
auto res = combined_assessment.to_dex_assessment();
res["without_deobfuscated_names.methods"] =
method_stats.methods_without_deobfuscated_name.load();
res["without_deobfuscated_names.fields"] =
field_stats.fields_without_deobfuscated_name.load();
res["without_deobfuscated_names.classes"] =
class_stats.classes_without_deobfuscated_name.load();
res["num_classes"] = m_scope.size();
res["num_methods"] = method_stats.num_methods.load();
res["num_fields"] = field_stats.num_fields.load();
res["methods~with~code"] = method_stats.methods_with_code.load();
res["num_instructions"] = method_stats.num_instructions.load();
res["sum_opcodes"] = method_stats.sum_opcodes.load();
res["methods.with_annotations"] = method_stats.with_annotations.load();
res["methods.sum_annotations"] = method_stats.sum_annotations.load();
res["methods.with_param_annotations"] =
method_stats.with_param_annotations.load();
res["methods.sum_param_annotations"] =
method_stats.sum_param_annotations.load();
res["fields.with_annotations"] = field_stats.with_annotations.load();
res["fields.sum_annotations"] = field_stats.sum_annotations.load();
res["classes.with_annotations"] = class_stats.with_annotations.load();
res["classes.sum_annotations"] = class_stats.sum_annotations.load();
if (combined_assessment.has_problems()) {
TRACE(ASSESSOR, 1, "[scope assessor] %s", to_string(res).c_str());
}
return res;
}