xref: /aosp_15_r20/art/tools/veridex/veridex.cc (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2018 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker #include "veridex.h"
18*795d594fSAndroid Build Coastguard Worker 
19*795d594fSAndroid Build Coastguard Worker #include <android-base/file.h>
20*795d594fSAndroid Build Coastguard Worker #include <android-base/strings.h>
21*795d594fSAndroid Build Coastguard Worker 
22*795d594fSAndroid Build Coastguard Worker #include <cstdlib>
23*795d594fSAndroid Build Coastguard Worker #include <sstream>
24*795d594fSAndroid Build Coastguard Worker #include <string_view>
25*795d594fSAndroid Build Coastguard Worker 
26*795d594fSAndroid Build Coastguard Worker #include "base/mem_map.h"
27*795d594fSAndroid Build Coastguard Worker #include "dex/dex_file.h"
28*795d594fSAndroid Build Coastguard Worker #include "dex/dex_file_loader.h"
29*795d594fSAndroid Build Coastguard Worker #include "hidden_api.h"
30*795d594fSAndroid Build Coastguard Worker #include "hidden_api_finder.h"
31*795d594fSAndroid Build Coastguard Worker #include "precise_hidden_api_finder.h"
32*795d594fSAndroid Build Coastguard Worker #include "resolver.h"
33*795d594fSAndroid Build Coastguard Worker 
34*795d594fSAndroid Build Coastguard Worker namespace art {
35*795d594fSAndroid Build Coastguard Worker 
36*795d594fSAndroid Build Coastguard Worker static VeriClass z_(Primitive::Type::kPrimBoolean, 0, nullptr);
37*795d594fSAndroid Build Coastguard Worker static VeriClass b_(Primitive::Type::kPrimByte, 0, nullptr);
38*795d594fSAndroid Build Coastguard Worker static VeriClass c_(Primitive::Type::kPrimChar, 0, nullptr);
39*795d594fSAndroid Build Coastguard Worker static VeriClass s_(Primitive::Type::kPrimShort, 0, nullptr);
40*795d594fSAndroid Build Coastguard Worker static VeriClass i_(Primitive::Type::kPrimInt, 0, nullptr);
41*795d594fSAndroid Build Coastguard Worker static VeriClass f_(Primitive::Type::kPrimFloat, 0, nullptr);
42*795d594fSAndroid Build Coastguard Worker static VeriClass d_(Primitive::Type::kPrimDouble, 0, nullptr);
43*795d594fSAndroid Build Coastguard Worker static VeriClass j_(Primitive::Type::kPrimLong, 0, nullptr);
44*795d594fSAndroid Build Coastguard Worker static VeriClass v_(Primitive::Type::kPrimVoid, 0, nullptr);
45*795d594fSAndroid Build Coastguard Worker 
46*795d594fSAndroid Build Coastguard Worker VeriClass* VeriClass::boolean_ = &z_;
47*795d594fSAndroid Build Coastguard Worker VeriClass* VeriClass::byte_ = &b_;
48*795d594fSAndroid Build Coastguard Worker VeriClass* VeriClass::char_ = &c_;
49*795d594fSAndroid Build Coastguard Worker VeriClass* VeriClass::short_ = &s_;
50*795d594fSAndroid Build Coastguard Worker VeriClass* VeriClass::integer_ = &i_;
51*795d594fSAndroid Build Coastguard Worker VeriClass* VeriClass::float_ = &f_;
52*795d594fSAndroid Build Coastguard Worker VeriClass* VeriClass::double_ = &d_;
53*795d594fSAndroid Build Coastguard Worker VeriClass* VeriClass::long_ = &j_;
54*795d594fSAndroid Build Coastguard Worker VeriClass* VeriClass::void_ = &v_;
55*795d594fSAndroid Build Coastguard Worker 
56*795d594fSAndroid Build Coastguard Worker // Will be set after boot classpath has been resolved.
57*795d594fSAndroid Build Coastguard Worker VeriClass* VeriClass::object_ = nullptr;
58*795d594fSAndroid Build Coastguard Worker VeriClass* VeriClass::class_ = nullptr;
59*795d594fSAndroid Build Coastguard Worker VeriClass* VeriClass::class_loader_ = nullptr;
60*795d594fSAndroid Build Coastguard Worker VeriClass* VeriClass::string_ = nullptr;
61*795d594fSAndroid Build Coastguard Worker VeriClass* VeriClass::throwable_ = nullptr;
62*795d594fSAndroid Build Coastguard Worker VeriMethod VeriClass::forName_ = nullptr;
63*795d594fSAndroid Build Coastguard Worker VeriMethod VeriClass::getField_ = nullptr;
64*795d594fSAndroid Build Coastguard Worker VeriMethod VeriClass::getDeclaredField_ = nullptr;
65*795d594fSAndroid Build Coastguard Worker VeriMethod VeriClass::getMethod_ = nullptr;
66*795d594fSAndroid Build Coastguard Worker VeriMethod VeriClass::getDeclaredMethod_ = nullptr;
67*795d594fSAndroid Build Coastguard Worker VeriMethod VeriClass::getClass_ = nullptr;
68*795d594fSAndroid Build Coastguard Worker VeriMethod VeriClass::loadClass_ = nullptr;
69*795d594fSAndroid Build Coastguard Worker VeriField VeriClass::sdkInt_ = nullptr;
70*795d594fSAndroid Build Coastguard Worker 
71*795d594fSAndroid Build Coastguard Worker static const char* kDexFileOption = "--dex-file=";
72*795d594fSAndroid Build Coastguard Worker static const char* kStubsOption = "--core-stubs=";
73*795d594fSAndroid Build Coastguard Worker static const char* kFlagsOption = "--api-flags=";
74*795d594fSAndroid Build Coastguard Worker static const char* kImprecise = "--imprecise";
75*795d594fSAndroid Build Coastguard Worker static const char* kTargetSdkVersion = "--target-sdk-version=";
76*795d594fSAndroid Build Coastguard Worker static const char* kAppClassFilter = "--app-class-filter=";
77*795d594fSAndroid Build Coastguard Worker static const char* kExcludeApiListsOption = "--exclude-api-lists=";
78*795d594fSAndroid Build Coastguard Worker 
79*795d594fSAndroid Build Coastguard Worker struct VeridexOptions {
80*795d594fSAndroid Build Coastguard Worker   const char* dex_file = nullptr;
81*795d594fSAndroid Build Coastguard Worker   const char* core_stubs = nullptr;
82*795d594fSAndroid Build Coastguard Worker   const char* flags_file = nullptr;
83*795d594fSAndroid Build Coastguard Worker   bool precise = true;
84*795d594fSAndroid Build Coastguard Worker   int target_sdk_version = 29; /* Q */
85*795d594fSAndroid Build Coastguard Worker   std::vector<std::string> app_class_name_filter;
86*795d594fSAndroid Build Coastguard Worker   std::vector<std::string> exclude_api_lists;
87*795d594fSAndroid Build Coastguard Worker };
88*795d594fSAndroid Build Coastguard Worker 
Substr(const char * str,int index)89*795d594fSAndroid Build Coastguard Worker static const char* Substr(const char* str, int index) {
90*795d594fSAndroid Build Coastguard Worker   return str + index;
91*795d594fSAndroid Build Coastguard Worker }
92*795d594fSAndroid Build Coastguard Worker 
ParseArgs(VeridexOptions * options,int argc,char ** argv)93*795d594fSAndroid Build Coastguard Worker static void ParseArgs(VeridexOptions* options, int argc, char** argv) {
94*795d594fSAndroid Build Coastguard Worker   // Skip over the command name.
95*795d594fSAndroid Build Coastguard Worker   argv++;
96*795d594fSAndroid Build Coastguard Worker   argc--;
97*795d594fSAndroid Build Coastguard Worker 
98*795d594fSAndroid Build Coastguard Worker   for (int i = 0; i < argc; ++i) {
99*795d594fSAndroid Build Coastguard Worker     std::string_view arg(argv[i]);
100*795d594fSAndroid Build Coastguard Worker     if (arg.starts_with(kDexFileOption)) {
101*795d594fSAndroid Build Coastguard Worker       options->dex_file = Substr(argv[i], strlen(kDexFileOption));
102*795d594fSAndroid Build Coastguard Worker     } else if (arg.starts_with(kStubsOption)) {
103*795d594fSAndroid Build Coastguard Worker       options->core_stubs = Substr(argv[i], strlen(kStubsOption));
104*795d594fSAndroid Build Coastguard Worker     } else if (arg.starts_with(kFlagsOption)) {
105*795d594fSAndroid Build Coastguard Worker       options->flags_file = Substr(argv[i], strlen(kFlagsOption));
106*795d594fSAndroid Build Coastguard Worker     } else if (strcmp(argv[i], kImprecise) == 0) {
107*795d594fSAndroid Build Coastguard Worker       options->precise = false;
108*795d594fSAndroid Build Coastguard Worker     } else if (arg.starts_with(kTargetSdkVersion)) {
109*795d594fSAndroid Build Coastguard Worker       options->target_sdk_version = atoi(Substr(argv[i], strlen(kTargetSdkVersion)));
110*795d594fSAndroid Build Coastguard Worker     } else if (arg.starts_with(kAppClassFilter)) {
111*795d594fSAndroid Build Coastguard Worker       options->app_class_name_filter = android::base::Split(
112*795d594fSAndroid Build Coastguard Worker           Substr(argv[i], strlen(kAppClassFilter)), ",");
113*795d594fSAndroid Build Coastguard Worker     } else if (arg.starts_with(kExcludeApiListsOption)) {
114*795d594fSAndroid Build Coastguard Worker       options->exclude_api_lists = android::base::Split(
115*795d594fSAndroid Build Coastguard Worker           Substr(argv[i], strlen(kExcludeApiListsOption)), ",");
116*795d594fSAndroid Build Coastguard Worker     } else {
117*795d594fSAndroid Build Coastguard Worker       LOG(ERROR) << "Unknown command line argument: " << argv[i];
118*795d594fSAndroid Build Coastguard Worker     }
119*795d594fSAndroid Build Coastguard Worker   }
120*795d594fSAndroid Build Coastguard Worker }
121*795d594fSAndroid Build Coastguard Worker 
Split(const std::string & str,char sep)122*795d594fSAndroid Build Coastguard Worker static std::vector<std::string> Split(const std::string& str, char sep) {
123*795d594fSAndroid Build Coastguard Worker   std::vector<std::string> tokens;
124*795d594fSAndroid Build Coastguard Worker   std::string tmp;
125*795d594fSAndroid Build Coastguard Worker   std::istringstream iss(str);
126*795d594fSAndroid Build Coastguard Worker   while (std::getline(iss, tmp, sep)) {
127*795d594fSAndroid Build Coastguard Worker     tokens.push_back(tmp);
128*795d594fSAndroid Build Coastguard Worker   }
129*795d594fSAndroid Build Coastguard Worker   return tokens;
130*795d594fSAndroid Build Coastguard Worker }
131*795d594fSAndroid Build Coastguard Worker 
132*795d594fSAndroid Build Coastguard Worker class Veridex {
133*795d594fSAndroid Build Coastguard Worker  public:
Run(int argc,char ** argv)134*795d594fSAndroid Build Coastguard Worker   static int Run(int argc, char** argv) {
135*795d594fSAndroid Build Coastguard Worker     VeridexOptions options;
136*795d594fSAndroid Build Coastguard Worker     ParseArgs(&options, argc, argv);
137*795d594fSAndroid Build Coastguard Worker     android::base::InitLogging(argv);
138*795d594fSAndroid Build Coastguard Worker 
139*795d594fSAndroid Build Coastguard Worker     if (!options.dex_file) {
140*795d594fSAndroid Build Coastguard Worker       LOG(ERROR) << "Required argument '" << kDexFileOption << "' not provided.";
141*795d594fSAndroid Build Coastguard Worker       return 1;
142*795d594fSAndroid Build Coastguard Worker     }
143*795d594fSAndroid Build Coastguard Worker 
144*795d594fSAndroid Build Coastguard Worker     gTargetSdkVersion = options.target_sdk_version;
145*795d594fSAndroid Build Coastguard Worker 
146*795d594fSAndroid Build Coastguard Worker     std::vector<std::string> boot_content;
147*795d594fSAndroid Build Coastguard Worker     std::vector<std::string> app_content;
148*795d594fSAndroid Build Coastguard Worker     std::vector<std::unique_ptr<const DexFile>> boot_dex_files;
149*795d594fSAndroid Build Coastguard Worker     std::vector<std::unique_ptr<const DexFile>> app_dex_files;
150*795d594fSAndroid Build Coastguard Worker     std::string error_msg;
151*795d594fSAndroid Build Coastguard Worker 
152*795d594fSAndroid Build Coastguard Worker     // Read the boot classpath.
153*795d594fSAndroid Build Coastguard Worker     std::vector<std::string> boot_classpath = Split(options.core_stubs, ':');
154*795d594fSAndroid Build Coastguard Worker     boot_content.resize(boot_classpath.size());
155*795d594fSAndroid Build Coastguard Worker     uint32_t i = 0;
156*795d594fSAndroid Build Coastguard Worker     for (const std::string& str : boot_classpath) {
157*795d594fSAndroid Build Coastguard Worker       if (!Load(str, boot_content[i++], &boot_dex_files, &error_msg)) {
158*795d594fSAndroid Build Coastguard Worker         LOG(ERROR) << error_msg;
159*795d594fSAndroid Build Coastguard Worker         return 1;
160*795d594fSAndroid Build Coastguard Worker       }
161*795d594fSAndroid Build Coastguard Worker     }
162*795d594fSAndroid Build Coastguard Worker 
163*795d594fSAndroid Build Coastguard Worker     // Read the apps dex files.
164*795d594fSAndroid Build Coastguard Worker     std::vector<std::string> app_files = Split(options.dex_file, ':');
165*795d594fSAndroid Build Coastguard Worker     app_content.resize(app_files.size());
166*795d594fSAndroid Build Coastguard Worker     i = 0;
167*795d594fSAndroid Build Coastguard Worker     for (const std::string& str : app_files) {
168*795d594fSAndroid Build Coastguard Worker       if (!Load(str, app_content[i++], &app_dex_files, &error_msg)) {
169*795d594fSAndroid Build Coastguard Worker         LOG(ERROR) << error_msg;
170*795d594fSAndroid Build Coastguard Worker         return 1;
171*795d594fSAndroid Build Coastguard Worker       }
172*795d594fSAndroid Build Coastguard Worker     }
173*795d594fSAndroid Build Coastguard Worker 
174*795d594fSAndroid Build Coastguard Worker     // Resolve classes/methods/fields defined in each dex file.
175*795d594fSAndroid Build Coastguard Worker 
176*795d594fSAndroid Build Coastguard Worker     ApiListFilter api_list_filter(options.exclude_api_lists);
177*795d594fSAndroid Build Coastguard Worker     HiddenApi hidden_api(options.flags_file, api_list_filter);
178*795d594fSAndroid Build Coastguard Worker 
179*795d594fSAndroid Build Coastguard Worker     // Cache of types we've seen, for quick class name lookups.
180*795d594fSAndroid Build Coastguard Worker     TypeMap type_map;
181*795d594fSAndroid Build Coastguard Worker     // Add internally defined primitives.
182*795d594fSAndroid Build Coastguard Worker     type_map["Z"] = VeriClass::boolean_;
183*795d594fSAndroid Build Coastguard Worker     type_map["B"] = VeriClass::byte_;
184*795d594fSAndroid Build Coastguard Worker     type_map["S"] = VeriClass::short_;
185*795d594fSAndroid Build Coastguard Worker     type_map["C"] = VeriClass::char_;
186*795d594fSAndroid Build Coastguard Worker     type_map["I"] = VeriClass::integer_;
187*795d594fSAndroid Build Coastguard Worker     type_map["F"] = VeriClass::float_;
188*795d594fSAndroid Build Coastguard Worker     type_map["D"] = VeriClass::double_;
189*795d594fSAndroid Build Coastguard Worker     type_map["J"] = VeriClass::long_;
190*795d594fSAndroid Build Coastguard Worker     type_map["V"] = VeriClass::void_;
191*795d594fSAndroid Build Coastguard Worker 
192*795d594fSAndroid Build Coastguard Worker     // Cache of resolvers, to easily query address in memory to VeridexResolver.
193*795d594fSAndroid Build Coastguard Worker     DexResolverMap resolver_map;
194*795d594fSAndroid Build Coastguard Worker 
195*795d594fSAndroid Build Coastguard Worker     std::vector<std::unique_ptr<VeridexResolver>> boot_resolvers;
196*795d594fSAndroid Build Coastguard Worker     Resolve(boot_dex_files, resolver_map, type_map, &boot_resolvers);
197*795d594fSAndroid Build Coastguard Worker     for (const auto &it : type_map) {
198*795d594fSAndroid Build Coastguard Worker         hidden_api.AddSignatureSource(it.first, SignatureSource::BOOT);
199*795d594fSAndroid Build Coastguard Worker     }
200*795d594fSAndroid Build Coastguard Worker 
201*795d594fSAndroid Build Coastguard Worker     if (options.precise) {
202*795d594fSAndroid Build Coastguard Worker       // For precise mode we expect core-stubs to contain java.lang classes.
203*795d594fSAndroid Build Coastguard Worker       VeriClass::object_ = type_map["Ljava/lang/Object;"];
204*795d594fSAndroid Build Coastguard Worker       VeriClass::class_ = type_map["Ljava/lang/Class;"];
205*795d594fSAndroid Build Coastguard Worker       VeriClass::class_loader_ = type_map["Ljava/lang/ClassLoader;"];
206*795d594fSAndroid Build Coastguard Worker       VeriClass::string_ = type_map["Ljava/lang/String;"];
207*795d594fSAndroid Build Coastguard Worker       VeriClass::throwable_ = type_map["Ljava/lang/Throwable;"];
208*795d594fSAndroid Build Coastguard Worker       VeriClass::forName_ = boot_resolvers[0]->LookupDeclaredMethodIn(
209*795d594fSAndroid Build Coastguard Worker           *VeriClass::class_, "forName", "(Ljava/lang/String;)Ljava/lang/Class;");
210*795d594fSAndroid Build Coastguard Worker       VeriClass::getField_ = boot_resolvers[0]->LookupDeclaredMethodIn(
211*795d594fSAndroid Build Coastguard Worker           *VeriClass::class_, "getField", "(Ljava/lang/String;)Ljava/lang/reflect/Field;");
212*795d594fSAndroid Build Coastguard Worker       VeriClass::getDeclaredField_ = boot_resolvers[0]->LookupDeclaredMethodIn(
213*795d594fSAndroid Build Coastguard Worker           *VeriClass::class_, "getDeclaredField", "(Ljava/lang/String;)Ljava/lang/reflect/Field;");
214*795d594fSAndroid Build Coastguard Worker       VeriClass::getMethod_ = boot_resolvers[0]->LookupDeclaredMethodIn(
215*795d594fSAndroid Build Coastguard Worker           *VeriClass::class_,
216*795d594fSAndroid Build Coastguard Worker           "getMethod",
217*795d594fSAndroid Build Coastguard Worker           "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;");
218*795d594fSAndroid Build Coastguard Worker       VeriClass::getDeclaredMethod_ = boot_resolvers[0]->LookupDeclaredMethodIn(
219*795d594fSAndroid Build Coastguard Worker           *VeriClass::class_,
220*795d594fSAndroid Build Coastguard Worker           "getDeclaredMethod",
221*795d594fSAndroid Build Coastguard Worker           "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;");
222*795d594fSAndroid Build Coastguard Worker       VeriClass::getClass_ = boot_resolvers[0]->LookupDeclaredMethodIn(
223*795d594fSAndroid Build Coastguard Worker           *VeriClass::object_, "getClass", "()Ljava/lang/Class;");
224*795d594fSAndroid Build Coastguard Worker       VeriClass::loadClass_ = boot_resolvers[0]->LookupDeclaredMethodIn(
225*795d594fSAndroid Build Coastguard Worker           *VeriClass::class_loader_, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;");
226*795d594fSAndroid Build Coastguard Worker 
227*795d594fSAndroid Build Coastguard Worker       VeriClass* version = type_map["Landroid/os/Build$VERSION;"];
228*795d594fSAndroid Build Coastguard Worker       if (version != nullptr) {
229*795d594fSAndroid Build Coastguard Worker         VeriClass::sdkInt_ = boot_resolvers[0]->LookupFieldIn(*version, "SDK_INT", "I");
230*795d594fSAndroid Build Coastguard Worker       }
231*795d594fSAndroid Build Coastguard Worker     }
232*795d594fSAndroid Build Coastguard Worker 
233*795d594fSAndroid Build Coastguard Worker     std::vector<std::unique_ptr<VeridexResolver>> app_resolvers;
234*795d594fSAndroid Build Coastguard Worker     Resolve(app_dex_files, resolver_map, type_map, &app_resolvers);
235*795d594fSAndroid Build Coastguard Worker     for (const auto &it : type_map) {
236*795d594fSAndroid Build Coastguard Worker       if (!hidden_api.IsInBoot(it.first)) {
237*795d594fSAndroid Build Coastguard Worker         hidden_api.AddSignatureSource(it.first, SignatureSource::APP);
238*795d594fSAndroid Build Coastguard Worker       }
239*795d594fSAndroid Build Coastguard Worker     }
240*795d594fSAndroid Build Coastguard Worker 
241*795d594fSAndroid Build Coastguard Worker     ClassFilter app_class_filter(options.app_class_name_filter);
242*795d594fSAndroid Build Coastguard Worker 
243*795d594fSAndroid Build Coastguard Worker     // Find and log uses of hidden APIs.
244*795d594fSAndroid Build Coastguard Worker     HiddenApiStats stats;
245*795d594fSAndroid Build Coastguard Worker 
246*795d594fSAndroid Build Coastguard Worker     HiddenApiFinder api_finder(hidden_api);
247*795d594fSAndroid Build Coastguard Worker     api_finder.Run(app_resolvers, app_class_filter);
248*795d594fSAndroid Build Coastguard Worker     api_finder.Dump(std::cout, &stats, !options.precise);
249*795d594fSAndroid Build Coastguard Worker 
250*795d594fSAndroid Build Coastguard Worker     if (options.precise) {
251*795d594fSAndroid Build Coastguard Worker       PreciseHiddenApiFinder precise_api_finder(hidden_api);
252*795d594fSAndroid Build Coastguard Worker       precise_api_finder.Run(app_resolvers, app_class_filter);
253*795d594fSAndroid Build Coastguard Worker       precise_api_finder.Dump(std::cout, &stats);
254*795d594fSAndroid Build Coastguard Worker     }
255*795d594fSAndroid Build Coastguard Worker 
256*795d594fSAndroid Build Coastguard Worker     DumpSummaryStats(std::cout, stats, api_list_filter);
257*795d594fSAndroid Build Coastguard Worker 
258*795d594fSAndroid Build Coastguard Worker     if (options.precise) {
259*795d594fSAndroid Build Coastguard Worker       std::cout << "To run an analysis that can give more reflection accesses, " << std::endl
260*795d594fSAndroid Build Coastguard Worker                 << "but could include false positives, pass the --imprecise flag. " << std::endl;
261*795d594fSAndroid Build Coastguard Worker     }
262*795d594fSAndroid Build Coastguard Worker 
263*795d594fSAndroid Build Coastguard Worker     return 0;
264*795d594fSAndroid Build Coastguard Worker   }
265*795d594fSAndroid Build Coastguard Worker 
266*795d594fSAndroid Build Coastguard Worker  private:
DumpSummaryStats(std::ostream & os,const HiddenApiStats & stats,const ApiListFilter & api_list_filter)267*795d594fSAndroid Build Coastguard Worker   static void DumpSummaryStats(std::ostream& os,
268*795d594fSAndroid Build Coastguard Worker                                const HiddenApiStats& stats,
269*795d594fSAndroid Build Coastguard Worker                                const ApiListFilter& api_list_filter) {
270*795d594fSAndroid Build Coastguard Worker     os << stats.count << " hidden API(s) used: "
271*795d594fSAndroid Build Coastguard Worker        << stats.linking_count << " linked against, "
272*795d594fSAndroid Build Coastguard Worker        << stats.reflection_count << " through reflection" << std::endl;
273*795d594fSAndroid Build Coastguard Worker     DumpApiListStats(os, stats, hiddenapi::ApiList(), api_list_filter);
274*795d594fSAndroid Build Coastguard Worker     for (size_t i = 0; i < hiddenapi::ApiList::kValueCount; ++i) {
275*795d594fSAndroid Build Coastguard Worker       DumpApiListStats(os, stats, hiddenapi::ApiList(i), api_list_filter);
276*795d594fSAndroid Build Coastguard Worker     }
277*795d594fSAndroid Build Coastguard Worker   }
278*795d594fSAndroid Build Coastguard Worker 
DumpApiListStats(std::ostream & os,const HiddenApiStats & stats,const hiddenapi::ApiList & api_list,const ApiListFilter & api_list_filter)279*795d594fSAndroid Build Coastguard Worker   static void DumpApiListStats(std::ostream& os,
280*795d594fSAndroid Build Coastguard Worker                                const HiddenApiStats& stats,
281*795d594fSAndroid Build Coastguard Worker                                const hiddenapi::ApiList& api_list,
282*795d594fSAndroid Build Coastguard Worker                                const ApiListFilter& api_list_filter) {
283*795d594fSAndroid Build Coastguard Worker     if (api_list_filter.Matches(api_list)) {
284*795d594fSAndroid Build Coastguard Worker       os << "\t" << stats.api_counts[api_list.GetIntValue()] << " in " << api_list << std::endl;
285*795d594fSAndroid Build Coastguard Worker     }
286*795d594fSAndroid Build Coastguard Worker   }
287*795d594fSAndroid Build Coastguard Worker 
Load(const std::string & filename,std::string & content,std::vector<std::unique_ptr<const DexFile>> * dex_files,std::string * error_msg)288*795d594fSAndroid Build Coastguard Worker   static bool Load(const std::string& filename,
289*795d594fSAndroid Build Coastguard Worker                    std::string& content,
290*795d594fSAndroid Build Coastguard Worker                    std::vector<std::unique_ptr<const DexFile>>* dex_files,
291*795d594fSAndroid Build Coastguard Worker                    std::string* error_msg) {
292*795d594fSAndroid Build Coastguard Worker     if (filename.empty()) {
293*795d594fSAndroid Build Coastguard Worker       *error_msg = "Missing file name";
294*795d594fSAndroid Build Coastguard Worker       return false;
295*795d594fSAndroid Build Coastguard Worker     }
296*795d594fSAndroid Build Coastguard Worker 
297*795d594fSAndroid Build Coastguard Worker     // TODO: once added, use an api to android::base to read a std::vector<uint8_t>.
298*795d594fSAndroid Build Coastguard Worker     if (!android::base::ReadFileToString(filename, &content)) {
299*795d594fSAndroid Build Coastguard Worker       *error_msg = "ReadFileToString failed for " + filename;
300*795d594fSAndroid Build Coastguard Worker       return false;
301*795d594fSAndroid Build Coastguard Worker     }
302*795d594fSAndroid Build Coastguard Worker 
303*795d594fSAndroid Build Coastguard Worker     DexFileLoaderErrorCode error_code;
304*795d594fSAndroid Build Coastguard Worker     static constexpr bool kVerifyChecksum = true;
305*795d594fSAndroid Build Coastguard Worker     static constexpr bool kRunDexFileVerifier = true;
306*795d594fSAndroid Build Coastguard Worker     DexFileLoader dex_file_loader(
307*795d594fSAndroid Build Coastguard Worker         reinterpret_cast<const uint8_t*>(content.data()), content.size(), filename);
308*795d594fSAndroid Build Coastguard Worker     if (!dex_file_loader.Open(
309*795d594fSAndroid Build Coastguard Worker             kRunDexFileVerifier, kVerifyChecksum, &error_code, error_msg, dex_files)) {
310*795d594fSAndroid Build Coastguard Worker       if (error_code == DexFileLoaderErrorCode::kEntryNotFound) {
311*795d594fSAndroid Build Coastguard Worker         LOG(INFO) << "No .dex found, skipping analysis.";
312*795d594fSAndroid Build Coastguard Worker         return true;
313*795d594fSAndroid Build Coastguard Worker       }
314*795d594fSAndroid Build Coastguard Worker       return false;
315*795d594fSAndroid Build Coastguard Worker     }
316*795d594fSAndroid Build Coastguard Worker 
317*795d594fSAndroid Build Coastguard Worker     return true;
318*795d594fSAndroid Build Coastguard Worker   }
319*795d594fSAndroid Build Coastguard Worker 
Resolve(const std::vector<std::unique_ptr<const DexFile>> & dex_files,DexResolverMap & resolver_map,TypeMap & type_map,std::vector<std::unique_ptr<VeridexResolver>> * resolvers)320*795d594fSAndroid Build Coastguard Worker   static void Resolve(const std::vector<std::unique_ptr<const DexFile>>& dex_files,
321*795d594fSAndroid Build Coastguard Worker                       DexResolverMap& resolver_map,
322*795d594fSAndroid Build Coastguard Worker                       TypeMap& type_map,
323*795d594fSAndroid Build Coastguard Worker                       std::vector<std::unique_ptr<VeridexResolver>>* resolvers) {
324*795d594fSAndroid Build Coastguard Worker     for (const std::unique_ptr<const DexFile>& dex_file : dex_files) {
325*795d594fSAndroid Build Coastguard Worker       VeridexResolver* resolver =
326*795d594fSAndroid Build Coastguard Worker           new VeridexResolver(*dex_file.get(), resolver_map, type_map);
327*795d594fSAndroid Build Coastguard Worker       resolvers->emplace_back(resolver);
328*795d594fSAndroid Build Coastguard Worker       resolver_map[reinterpret_cast<uintptr_t>(dex_file->Begin())] = resolver;
329*795d594fSAndroid Build Coastguard Worker     }
330*795d594fSAndroid Build Coastguard Worker 
331*795d594fSAndroid Build Coastguard Worker     for (const std::unique_ptr<VeridexResolver>& resolver : *resolvers) {
332*795d594fSAndroid Build Coastguard Worker       resolver->Run();
333*795d594fSAndroid Build Coastguard Worker     }
334*795d594fSAndroid Build Coastguard Worker   }
335*795d594fSAndroid Build Coastguard Worker };
336*795d594fSAndroid Build Coastguard Worker 
337*795d594fSAndroid Build Coastguard Worker }  // namespace art
338*795d594fSAndroid Build Coastguard Worker 
main(int argc,char ** argv)339*795d594fSAndroid Build Coastguard Worker int main(int argc, char** argv) {
340*795d594fSAndroid Build Coastguard Worker   art::MemMap::Init();
341*795d594fSAndroid Build Coastguard Worker   return art::Veridex::Run(argc, argv);
342*795d594fSAndroid Build Coastguard Worker }
343