blob: 6f66a3368cc63d1f3a66ac594b7c01df4bc96c0d [file] [log] [blame]
Nicolas Geoffray2ebff052018-04-04 22:32:03 +01001/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "precise_hidden_api_finder.h"
18
David Brazdild76e1232019-05-07 19:23:41 +010019#include "class_filter.h"
Mathieu Chartier8f75f7b2018-08-06 23:38:48 -070020#include "dex/class_accessor-inl.h"
Nicolas Geoffray2ebff052018-04-04 22:32:03 +010021#include "dex/code_item_accessors-inl.h"
22#include "dex/dex_instruction-inl.h"
23#include "dex/dex_file.h"
24#include "dex/method_reference.h"
25#include "flow_analysis.h"
26#include "hidden_api.h"
27#include "resolver.h"
28#include "veridex.h"
29
30#include <iostream>
31
32namespace art {
33
Nicolas Geoffraye2b41952018-04-25 09:09:28 +010034void PreciseHiddenApiFinder::RunInternal(
35 const std::vector<std::unique_ptr<VeridexResolver>>& resolvers,
David Brazdild76e1232019-05-07 19:23:41 +010036 const ClassFilter& class_filter,
Mathieu Chartier8f75f7b2018-08-06 23:38:48 -070037 const std::function<void(VeridexResolver*, const ClassAccessor::Method&)>& action) {
Nicolas Geoffray2ebff052018-04-04 22:32:03 +010038 for (const std::unique_ptr<VeridexResolver>& resolver : resolvers) {
Mathieu Chartier8f75f7b2018-08-06 23:38:48 -070039 for (ClassAccessor accessor : resolver->GetDexFile().GetClasses()) {
David Brazdild76e1232019-05-07 19:23:41 +010040 if (class_filter.Matches(accessor.GetDescriptor())) {
41 for (const ClassAccessor::Method& method : accessor.GetMethods()) {
42 if (method.GetCodeItem() != nullptr) {
43 action(resolver.get(), method);
44 }
Nicolas Geoffray2ebff052018-04-04 22:32:03 +010045 }
Nicolas Geoffray2ebff052018-04-04 22:32:03 +010046 }
47 }
48 }
49}
50
Nicolas Geoffraye2b41952018-04-25 09:09:28 +010051void PreciseHiddenApiFinder::AddUsesAt(const std::vector<ReflectAccessInfo>& accesses,
52 MethodReference ref) {
53 for (const ReflectAccessInfo& info : accesses) {
54 if (info.IsConcrete()) {
55 concrete_uses_[ref].push_back(info);
56 } else {
57 abstract_uses_[ref].push_back(info);
58 }
59 }
60}
61
David Brazdild76e1232019-05-07 19:23:41 +010062void PreciseHiddenApiFinder::Run(const std::vector<std::unique_ptr<VeridexResolver>>& resolvers,
63 const ClassFilter& class_filter) {
Nicolas Geoffraye2b41952018-04-25 09:09:28 +010064 // Collect reflection uses.
David Brazdild76e1232019-05-07 19:23:41 +010065 RunInternal(resolvers,
66 class_filter,
67 [this] (VeridexResolver* resolver, const ClassAccessor::Method& method) {
Mathieu Chartier8f75f7b2018-08-06 23:38:48 -070068 FlowAnalysisCollector collector(resolver, method);
Nicolas Geoffraye2b41952018-04-25 09:09:28 +010069 collector.Run();
Mathieu Chartier8f75f7b2018-08-06 23:38:48 -070070 AddUsesAt(collector.GetUses(), method.GetReference());
Nicolas Geoffraye2b41952018-04-25 09:09:28 +010071 });
72
73 // For non-final reflection uses, do a limited fixed point calculation over the code to try
74 // substituting them with final reflection uses.
75 // We limit the number of times we iterate over the code as one run can be long.
76 static const int kMaximumIterations = 10;
77 uint32_t i = 0;
78 while (!abstract_uses_.empty() && (i++ < kMaximumIterations)) {
79 // Fetch and clear the worklist.
80 std::map<MethodReference, std::vector<ReflectAccessInfo>> current_uses
81 = std::move(abstract_uses_);
82 RunInternal(resolvers,
David Brazdild76e1232019-05-07 19:23:41 +010083 class_filter,
Mathieu Chartier8f75f7b2018-08-06 23:38:48 -070084 [this, current_uses] (VeridexResolver* resolver,
85 const ClassAccessor::Method& method) {
86 FlowAnalysisSubstitutor substitutor(resolver, method, current_uses);
Nicolas Geoffraye2b41952018-04-25 09:09:28 +010087 substitutor.Run();
Mathieu Chartier8f75f7b2018-08-06 23:38:48 -070088 AddUsesAt(substitutor.GetUses(), method.GetReference());
Nicolas Geoffraye2b41952018-04-25 09:09:28 +010089 });
90 }
91}
92
Nicolas Geoffray2ebff052018-04-04 22:32:03 +010093void PreciseHiddenApiFinder::Dump(std::ostream& os, HiddenApiStats* stats) {
94 static const char* kPrefix = " ";
Nicolas Geoffraye2b41952018-04-25 09:09:28 +010095 std::map<std::string, std::vector<MethodReference>> named_uses;
Andreas Gampe370f0412018-10-02 12:11:11 -070096 for (auto& it : concrete_uses_) {
Nicolas Geoffraye2b41952018-04-25 09:09:28 +010097 MethodReference ref = it.first;
98 for (const ReflectAccessInfo& info : it.second) {
99 std::string cls(info.cls.ToString());
100 std::string name(info.name.ToString());
101 std::string full_name = cls + "->" + name;
Artur Satayev39c399a2019-09-13 16:09:09 +0100102 named_uses[full_name].push_back(ref);
Nicolas Geoffray2ebff052018-04-04 22:32:03 +0100103 }
104 }
Nicolas Geoffray909b1272018-04-23 13:43:31 +0100105
Andreas Gampe370f0412018-10-02 12:11:11 -0700106 for (auto& it : named_uses) {
Nicolas Geoffray909b1272018-04-23 13:43:31 +0100107 const std::string& full_name = it.first;
Artur Satayev39c399a2019-09-13 16:09:09 +0100108 if (hidden_api_.GetSignatureSource(full_name) != SignatureSource::APP &&
109 hidden_api_.ShouldReport(full_name)) {
110 stats->reflection_count++;
111 hiddenapi::ApiList api_list = hidden_api_.GetApiList(full_name);
112 stats->api_counts[api_list.GetIntValue()]++;
113 os << "#" << ++stats->count << ": Reflection " << api_list << " " << full_name << " use(s):";
114 os << std::endl;
115 for (const MethodReference& ref : it.second) {
116 os << kPrefix << HiddenApi::GetApiMethodName(ref) << std::endl;
117 }
118 os << std::endl;
Nicolas Geoffray909b1272018-04-23 13:43:31 +0100119 }
Nicolas Geoffray909b1272018-04-23 13:43:31 +0100120 }
Nicolas Geoffray2ebff052018-04-04 22:32:03 +0100121}
122
123} // namespace art