blob: 4ae57690141d37a9b8c7b47555fcba84f7d8ae97 [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
19#include "dex/code_item_accessors-inl.h"
20#include "dex/dex_instruction-inl.h"
21#include "dex/dex_file.h"
22#include "dex/method_reference.h"
23#include "flow_analysis.h"
24#include "hidden_api.h"
25#include "resolver.h"
26#include "veridex.h"
27
28#include <iostream>
29
30namespace art {
31
32void PreciseHiddenApiFinder::Run(const std::vector<std::unique_ptr<VeridexResolver>>& resolvers) {
33 for (const std::unique_ptr<VeridexResolver>& resolver : resolvers) {
34 const DexFile& dex_file = resolver->GetDexFile();
35 size_t class_def_count = dex_file.NumClassDefs();
36 for (size_t class_def_index = 0; class_def_index < class_def_count; ++class_def_index) {
37 const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
38 const uint8_t* class_data = dex_file.GetClassData(class_def);
39 if (class_data == nullptr) {
40 // Empty class.
41 continue;
42 }
43 ClassDataItemIterator it(dex_file, class_data);
44 it.SkipAllFields();
45 for (; it.HasNextMethod(); it.Next()) {
46 const DexFile::CodeItem* code_item = it.GetMethodCodeItem();
47 if (code_item == nullptr) {
48 continue;
49 }
50 CodeItemDataAccessor code_item_accessor(dex_file, code_item);
51 VeriFlowAnalysis ana(resolver.get(), code_item_accessor);
52 ana.Run();
53 if (!ana.GetFieldUses().empty()) {
54 field_uses_[MethodReference(&dex_file, it.GetMemberIndex())] = ana.GetFieldUses();
55 }
56 if (!ana.GetMethodUses().empty()) {
57 method_uses_[MethodReference(&dex_file, it.GetMemberIndex())] = ana.GetMethodUses();
58 }
59 }
60 }
61 }
62}
63
64void PreciseHiddenApiFinder::Dump(std::ostream& os, HiddenApiStats* stats) {
65 static const char* kPrefix = " ";
Nicolas Geoffray909b1272018-04-23 13:43:31 +010066 std::map<std::string, std::vector<MethodReference>> uses;
Nicolas Geoffray2ebff052018-04-04 22:32:03 +010067 for (auto kinds : { field_uses_, method_uses_ }) {
68 for (auto it : kinds) {
69 MethodReference ref = it.first;
70 for (const std::pair<RegisterValue, RegisterValue>& info : it.second) {
71 if ((info.first.GetSource() == RegisterSource::kClass ||
72 info.first.GetSource() == RegisterSource::kString) &&
73 info.second.GetSource() == RegisterSource::kString) {
74 std::string cls(info.first.ToString());
75 std::string name(info.second.ToString());
76 std::string full_name = cls + "->" + name;
77 HiddenApiAccessFlags::ApiList api_list = hidden_api_.GetApiList(full_name);
Nicolas Geoffray2ebff052018-04-04 22:32:03 +010078 if (api_list != HiddenApiAccessFlags::kWhitelist) {
Nicolas Geoffray909b1272018-04-23 13:43:31 +010079 uses[full_name].push_back(ref);
Nicolas Geoffray2ebff052018-04-04 22:32:03 +010080 }
81 }
82 }
83 }
84 }
Nicolas Geoffray909b1272018-04-23 13:43:31 +010085
86 for (auto it : uses) {
87 ++stats->reflection_count;
88 const std::string& full_name = it.first;
89 HiddenApiAccessFlags::ApiList api_list = hidden_api_.GetApiList(full_name);
90 stats->api_counts[api_list]++;
91 os << "#" << ++stats->count << ": Reflection " << api_list << " " << full_name << " use(s):";
92 os << std::endl;
93 for (const MethodReference& ref : it.second) {
94 os << kPrefix << HiddenApi::GetApiMethodName(ref) << std::endl;
95 }
96 os << std::endl;
97 }
Nicolas Geoffray2ebff052018-04-04 22:32:03 +010098}
99
100} // namespace art