1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2017 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 <openssl/sha.h>
18*795d594fSAndroid Build Coastguard Worker
19*795d594fSAndroid Build Coastguard Worker #include <fstream>
20*795d594fSAndroid Build Coastguard Worker #include <iostream>
21*795d594fSAndroid Build Coastguard Worker #include <iterator>
22*795d594fSAndroid Build Coastguard Worker #include <map>
23*795d594fSAndroid Build Coastguard Worker #include <set>
24*795d594fSAndroid Build Coastguard Worker #include <string>
25*795d594fSAndroid Build Coastguard Worker #include <string_view>
26*795d594fSAndroid Build Coastguard Worker #include <vector>
27*795d594fSAndroid Build Coastguard Worker
28*795d594fSAndroid Build Coastguard Worker #include "android-base/stringprintf.h"
29*795d594fSAndroid Build Coastguard Worker #include "android-base/strings.h"
30*795d594fSAndroid Build Coastguard Worker #include "base/bit_utils.h"
31*795d594fSAndroid Build Coastguard Worker #include "base/hiddenapi_flags.h"
32*795d594fSAndroid Build Coastguard Worker #include "base/mem_map.h"
33*795d594fSAndroid Build Coastguard Worker #include "base/os.h"
34*795d594fSAndroid Build Coastguard Worker #include "base/stl_util.h"
35*795d594fSAndroid Build Coastguard Worker #include "base/unix_file/fd_file.h"
36*795d594fSAndroid Build Coastguard Worker #include "dex/art_dex_file_loader.h"
37*795d594fSAndroid Build Coastguard Worker #include "dex/class_accessor-inl.h"
38*795d594fSAndroid Build Coastguard Worker #include "dex/dex_file-inl.h"
39*795d594fSAndroid Build Coastguard Worker #include "dex/dex_file_structs.h"
40*795d594fSAndroid Build Coastguard Worker
41*795d594fSAndroid Build Coastguard Worker namespace art {
42*795d594fSAndroid Build Coastguard Worker namespace hiddenapi {
43*795d594fSAndroid Build Coastguard Worker
44*795d594fSAndroid Build Coastguard Worker const char kErrorHelp[] = "\nSee go/hiddenapi-error for help.";
45*795d594fSAndroid Build Coastguard Worker
46*795d594fSAndroid Build Coastguard Worker static int original_argc;
47*795d594fSAndroid Build Coastguard Worker static char** original_argv;
48*795d594fSAndroid Build Coastguard Worker
CommandLine()49*795d594fSAndroid Build Coastguard Worker static std::string CommandLine() {
50*795d594fSAndroid Build Coastguard Worker std::vector<std::string> command;
51*795d594fSAndroid Build Coastguard Worker command.reserve(original_argc);
52*795d594fSAndroid Build Coastguard Worker for (int i = 0; i < original_argc; ++i) {
53*795d594fSAndroid Build Coastguard Worker command.push_back(original_argv[i]);
54*795d594fSAndroid Build Coastguard Worker }
55*795d594fSAndroid Build Coastguard Worker return android::base::Join(command, ' ');
56*795d594fSAndroid Build Coastguard Worker }
57*795d594fSAndroid Build Coastguard Worker
UsageErrorV(const char * fmt,va_list ap)58*795d594fSAndroid Build Coastguard Worker static void UsageErrorV(const char* fmt, va_list ap) {
59*795d594fSAndroid Build Coastguard Worker std::string error;
60*795d594fSAndroid Build Coastguard Worker android::base::StringAppendV(&error, fmt, ap);
61*795d594fSAndroid Build Coastguard Worker LOG(ERROR) << error;
62*795d594fSAndroid Build Coastguard Worker }
63*795d594fSAndroid Build Coastguard Worker
UsageError(const char * fmt,...)64*795d594fSAndroid Build Coastguard Worker static void UsageError(const char* fmt, ...) {
65*795d594fSAndroid Build Coastguard Worker va_list ap;
66*795d594fSAndroid Build Coastguard Worker va_start(ap, fmt);
67*795d594fSAndroid Build Coastguard Worker UsageErrorV(fmt, ap);
68*795d594fSAndroid Build Coastguard Worker va_end(ap);
69*795d594fSAndroid Build Coastguard Worker }
70*795d594fSAndroid Build Coastguard Worker
Usage(const char * fmt,...)71*795d594fSAndroid Build Coastguard Worker NO_RETURN static void Usage(const char* fmt, ...) {
72*795d594fSAndroid Build Coastguard Worker va_list ap;
73*795d594fSAndroid Build Coastguard Worker va_start(ap, fmt);
74*795d594fSAndroid Build Coastguard Worker UsageErrorV(fmt, ap);
75*795d594fSAndroid Build Coastguard Worker va_end(ap);
76*795d594fSAndroid Build Coastguard Worker
77*795d594fSAndroid Build Coastguard Worker UsageError("Command: %s", CommandLine().c_str());
78*795d594fSAndroid Build Coastguard Worker UsageError("Usage: hiddenapi [command_name] [options]...");
79*795d594fSAndroid Build Coastguard Worker UsageError("");
80*795d594fSAndroid Build Coastguard Worker UsageError(" Command \"encode\": encode API list membership in boot dex files");
81*795d594fSAndroid Build Coastguard Worker UsageError(" --input-dex=<filename>: dex file which belongs to boot class path");
82*795d594fSAndroid Build Coastguard Worker UsageError(" --output-dex=<filename>: file to write encoded dex into");
83*795d594fSAndroid Build Coastguard Worker UsageError(" input and output dex files are paired in order of appearance");
84*795d594fSAndroid Build Coastguard Worker UsageError("");
85*795d594fSAndroid Build Coastguard Worker UsageError(" --api-flags=<filename>:");
86*795d594fSAndroid Build Coastguard Worker UsageError(" CSV file with signatures of methods/fields and their respective flags");
87*795d594fSAndroid Build Coastguard Worker UsageError("");
88*795d594fSAndroid Build Coastguard Worker UsageError(" --max-hiddenapi-level=<max-target-*>:");
89*795d594fSAndroid Build Coastguard Worker UsageError(" the maximum hidden api level for APIs. If an API was originally restricted");
90*795d594fSAndroid Build Coastguard Worker UsageError(" to a newer sdk, turn it into a regular unsupported API instead.");
91*795d594fSAndroid Build Coastguard Worker UsageError(" instead. The full list of valid values is in hiddenapi_flags.h");
92*795d594fSAndroid Build Coastguard Worker UsageError("");
93*795d594fSAndroid Build Coastguard Worker UsageError(" --no-force-assign-all:");
94*795d594fSAndroid Build Coastguard Worker UsageError(" Disable check that all dex entries have been assigned a flag");
95*795d594fSAndroid Build Coastguard Worker UsageError("");
96*795d594fSAndroid Build Coastguard Worker UsageError(" Command \"list\": dump lists of public and private API");
97*795d594fSAndroid Build Coastguard Worker UsageError(" --dependency-stub-dex=<filename>: dex file containing API stubs provided");
98*795d594fSAndroid Build Coastguard Worker UsageError(" by other parts of the bootclasspath. These are used to resolve");
99*795d594fSAndroid Build Coastguard Worker UsageError(" dependencies in dex files specified in --boot-dex but do not appear in");
100*795d594fSAndroid Build Coastguard Worker UsageError(" the output");
101*795d594fSAndroid Build Coastguard Worker UsageError(" --boot-dex=<filename>: dex file which belongs to boot class path");
102*795d594fSAndroid Build Coastguard Worker UsageError(" --public-stub-classpath=<filenames>:");
103*795d594fSAndroid Build Coastguard Worker UsageError(" --system-stub-classpath=<filenames>:");
104*795d594fSAndroid Build Coastguard Worker UsageError(" --test-stub-classpath=<filenames>:");
105*795d594fSAndroid Build Coastguard Worker UsageError(" --core-platform-stub-classpath=<filenames>:");
106*795d594fSAndroid Build Coastguard Worker UsageError(" colon-separated list of dex/apk files which form API stubs of boot");
107*795d594fSAndroid Build Coastguard Worker UsageError(" classpath. Multiple classpaths can be specified");
108*795d594fSAndroid Build Coastguard Worker UsageError("");
109*795d594fSAndroid Build Coastguard Worker UsageError(" --out-api-flags=<filename>: output file for a CSV file with API flags");
110*795d594fSAndroid Build Coastguard Worker UsageError(" --fragment: the input is only a fragment of the whole bootclasspath and may");
111*795d594fSAndroid Build Coastguard Worker UsageError(" not include a complete set of classes. That requires the tool to ignore");
112*795d594fSAndroid Build Coastguard Worker UsageError(" missing classes and members. Specify --verbose to see the warnings.");
113*795d594fSAndroid Build Coastguard Worker UsageError(" --verbose: output all warnings, even when --fragment is specified.");
114*795d594fSAndroid Build Coastguard Worker UsageError("");
115*795d594fSAndroid Build Coastguard Worker
116*795d594fSAndroid Build Coastguard Worker exit(EXIT_FAILURE);
117*795d594fSAndroid Build Coastguard Worker }
118*795d594fSAndroid Build Coastguard Worker
119*795d594fSAndroid Build Coastguard Worker template<typename E>
Contains(const std::vector<E> & vec,const E & elem)120*795d594fSAndroid Build Coastguard Worker static bool Contains(const std::vector<E>& vec, const E& elem) {
121*795d594fSAndroid Build Coastguard Worker return std::find(vec.begin(), vec.end(), elem) != vec.end();
122*795d594fSAndroid Build Coastguard Worker }
123*795d594fSAndroid Build Coastguard Worker
124*795d594fSAndroid Build Coastguard Worker class DexClass : public ClassAccessor {
125*795d594fSAndroid Build Coastguard Worker public:
DexClass(const ClassAccessor & accessor)126*795d594fSAndroid Build Coastguard Worker explicit DexClass(const ClassAccessor& accessor) : ClassAccessor(accessor) {}
127*795d594fSAndroid Build Coastguard Worker
GetData() const128*795d594fSAndroid Build Coastguard Worker const uint8_t* GetData() const { return dex_file_.GetClassData(GetClassDef()); }
129*795d594fSAndroid Build Coastguard Worker
GetSuperclassIndex() const130*795d594fSAndroid Build Coastguard Worker const dex::TypeIndex GetSuperclassIndex() const { return GetClassDef().superclass_idx_; }
131*795d594fSAndroid Build Coastguard Worker
HasSuperclass() const132*795d594fSAndroid Build Coastguard Worker bool HasSuperclass() const { return dex_file_.IsTypeIndexValid(GetSuperclassIndex()); }
133*795d594fSAndroid Build Coastguard Worker
GetSuperclassDescriptor() const134*795d594fSAndroid Build Coastguard Worker std::string_view GetSuperclassDescriptor() const {
135*795d594fSAndroid Build Coastguard Worker return HasSuperclass() ? dex_file_.GetTypeDescriptorView(GetSuperclassIndex()) : "";
136*795d594fSAndroid Build Coastguard Worker }
137*795d594fSAndroid Build Coastguard Worker
GetInterfaceDescriptors() const138*795d594fSAndroid Build Coastguard Worker std::set<std::string_view> GetInterfaceDescriptors() const {
139*795d594fSAndroid Build Coastguard Worker std::set<std::string_view> list;
140*795d594fSAndroid Build Coastguard Worker const dex::TypeList* ifaces = dex_file_.GetInterfacesList(GetClassDef());
141*795d594fSAndroid Build Coastguard Worker for (uint32_t i = 0; ifaces != nullptr && i < ifaces->Size(); ++i) {
142*795d594fSAndroid Build Coastguard Worker list.insert(dex_file_.GetTypeDescriptorView(ifaces->GetTypeItem(i).type_idx_));
143*795d594fSAndroid Build Coastguard Worker }
144*795d594fSAndroid Build Coastguard Worker return list;
145*795d594fSAndroid Build Coastguard Worker }
146*795d594fSAndroid Build Coastguard Worker
IsPublic() const147*795d594fSAndroid Build Coastguard Worker inline bool IsPublic() const { return HasAccessFlags(kAccPublic); }
IsInterface() const148*795d594fSAndroid Build Coastguard Worker inline bool IsInterface() const { return HasAccessFlags(kAccInterface); }
149*795d594fSAndroid Build Coastguard Worker
Equals(const DexClass & other) const150*795d594fSAndroid Build Coastguard Worker inline bool Equals(const DexClass& other) const {
151*795d594fSAndroid Build Coastguard Worker bool equals = strcmp(GetDescriptor(), other.GetDescriptor()) == 0;
152*795d594fSAndroid Build Coastguard Worker
153*795d594fSAndroid Build Coastguard Worker if (equals) {
154*795d594fSAndroid Build Coastguard Worker LOG(FATAL) << "Class duplication: " << GetDescriptor() << " in " << dex_file_.GetLocation()
155*795d594fSAndroid Build Coastguard Worker << " and " << other.dex_file_.GetLocation();
156*795d594fSAndroid Build Coastguard Worker }
157*795d594fSAndroid Build Coastguard Worker
158*795d594fSAndroid Build Coastguard Worker return equals;
159*795d594fSAndroid Build Coastguard Worker }
160*795d594fSAndroid Build Coastguard Worker
161*795d594fSAndroid Build Coastguard Worker private:
GetAccessFlags() const162*795d594fSAndroid Build Coastguard Worker uint32_t GetAccessFlags() const { return GetClassDef().access_flags_; }
HasAccessFlags(uint32_t mask) const163*795d594fSAndroid Build Coastguard Worker bool HasAccessFlags(uint32_t mask) const { return (GetAccessFlags() & mask) == mask; }
164*795d594fSAndroid Build Coastguard Worker
JoinStringSet(const std::set<std::string_view> & s)165*795d594fSAndroid Build Coastguard Worker static std::string JoinStringSet(const std::set<std::string_view>& s) {
166*795d594fSAndroid Build Coastguard Worker return "{" + ::android::base::Join(std::vector<std::string>(s.begin(), s.end()), ",") + "}";
167*795d594fSAndroid Build Coastguard Worker }
168*795d594fSAndroid Build Coastguard Worker };
169*795d594fSAndroid Build Coastguard Worker
170*795d594fSAndroid Build Coastguard Worker class DexMember {
171*795d594fSAndroid Build Coastguard Worker public:
DexMember(const DexClass & klass,const ClassAccessor::Field & item)172*795d594fSAndroid Build Coastguard Worker DexMember(const DexClass& klass, const ClassAccessor::Field& item)
173*795d594fSAndroid Build Coastguard Worker : klass_(klass), item_(item), is_method_(false) {
174*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(GetFieldId().class_idx_, klass.GetClassIdx());
175*795d594fSAndroid Build Coastguard Worker }
176*795d594fSAndroid Build Coastguard Worker
DexMember(const DexClass & klass,const ClassAccessor::Method & item)177*795d594fSAndroid Build Coastguard Worker DexMember(const DexClass& klass, const ClassAccessor::Method& item)
178*795d594fSAndroid Build Coastguard Worker : klass_(klass), item_(item), is_method_(true) {
179*795d594fSAndroid Build Coastguard Worker DCHECK_EQ(GetMethodId().class_idx_, klass.GetClassIdx());
180*795d594fSAndroid Build Coastguard Worker }
181*795d594fSAndroid Build Coastguard Worker
GetDeclaringClass() const182*795d594fSAndroid Build Coastguard Worker inline const DexClass& GetDeclaringClass() const { return klass_; }
183*795d594fSAndroid Build Coastguard Worker
IsMethod() const184*795d594fSAndroid Build Coastguard Worker inline bool IsMethod() const { return is_method_; }
IsVirtualMethod() const185*795d594fSAndroid Build Coastguard Worker inline bool IsVirtualMethod() const { return IsMethod() && !GetMethod().IsStaticOrDirect(); }
IsConstructor() const186*795d594fSAndroid Build Coastguard Worker inline bool IsConstructor() const { return IsMethod() && HasAccessFlags(kAccConstructor); }
187*795d594fSAndroid Build Coastguard Worker
IsPublicOrProtected() const188*795d594fSAndroid Build Coastguard Worker inline bool IsPublicOrProtected() const {
189*795d594fSAndroid Build Coastguard Worker return HasAccessFlags(kAccPublic) || HasAccessFlags(kAccProtected);
190*795d594fSAndroid Build Coastguard Worker }
191*795d594fSAndroid Build Coastguard Worker
192*795d594fSAndroid Build Coastguard Worker // Constructs a string with a unique signature of this class member.
GetApiEntry() const193*795d594fSAndroid Build Coastguard Worker std::string GetApiEntry() const {
194*795d594fSAndroid Build Coastguard Worker std::stringstream ss;
195*795d594fSAndroid Build Coastguard Worker ss << klass_.GetDescriptor() << "->" << GetName() << (IsMethod() ? "" : ":")
196*795d594fSAndroid Build Coastguard Worker << GetSignature();
197*795d594fSAndroid Build Coastguard Worker return ss.str();
198*795d594fSAndroid Build Coastguard Worker }
199*795d594fSAndroid Build Coastguard Worker
operator ==(const DexMember & other) const200*795d594fSAndroid Build Coastguard Worker inline bool operator==(const DexMember& other) const {
201*795d594fSAndroid Build Coastguard Worker // These need to match if they should resolve to one another.
202*795d594fSAndroid Build Coastguard Worker bool equals = IsMethod() == other.IsMethod() &&
203*795d594fSAndroid Build Coastguard Worker GetName() == other.GetName() &&
204*795d594fSAndroid Build Coastguard Worker GetSignature() == other.GetSignature();
205*795d594fSAndroid Build Coastguard Worker
206*795d594fSAndroid Build Coastguard Worker // Soundness check that they do match.
207*795d594fSAndroid Build Coastguard Worker if (equals) {
208*795d594fSAndroid Build Coastguard Worker CHECK_EQ(IsVirtualMethod(), other.IsVirtualMethod());
209*795d594fSAndroid Build Coastguard Worker }
210*795d594fSAndroid Build Coastguard Worker
211*795d594fSAndroid Build Coastguard Worker return equals;
212*795d594fSAndroid Build Coastguard Worker }
213*795d594fSAndroid Build Coastguard Worker
214*795d594fSAndroid Build Coastguard Worker private:
GetAccessFlags() const215*795d594fSAndroid Build Coastguard Worker inline uint32_t GetAccessFlags() const { return item_.GetAccessFlags(); }
HasAccessFlags(uint32_t mask) const216*795d594fSAndroid Build Coastguard Worker inline bool HasAccessFlags(uint32_t mask) const { return (GetAccessFlags() & mask) == mask; }
217*795d594fSAndroid Build Coastguard Worker
GetName() const218*795d594fSAndroid Build Coastguard Worker inline std::string_view GetName() const {
219*795d594fSAndroid Build Coastguard Worker return IsMethod() ? item_.GetDexFile().GetMethodName(GetMethodId())
220*795d594fSAndroid Build Coastguard Worker : item_.GetDexFile().GetFieldName(GetFieldId());
221*795d594fSAndroid Build Coastguard Worker }
222*795d594fSAndroid Build Coastguard Worker
GetSignature() const223*795d594fSAndroid Build Coastguard Worker inline std::string GetSignature() const {
224*795d594fSAndroid Build Coastguard Worker return IsMethod() ? item_.GetDexFile().GetMethodSignature(GetMethodId()).ToString()
225*795d594fSAndroid Build Coastguard Worker : item_.GetDexFile().GetFieldTypeDescriptor(GetFieldId());
226*795d594fSAndroid Build Coastguard Worker }
227*795d594fSAndroid Build Coastguard Worker
GetMethod() const228*795d594fSAndroid Build Coastguard Worker inline const ClassAccessor::Method& GetMethod() const {
229*795d594fSAndroid Build Coastguard Worker DCHECK(IsMethod());
230*795d594fSAndroid Build Coastguard Worker return down_cast<const ClassAccessor::Method&>(item_);
231*795d594fSAndroid Build Coastguard Worker }
232*795d594fSAndroid Build Coastguard Worker
GetMethodId() const233*795d594fSAndroid Build Coastguard Worker inline const dex::MethodId& GetMethodId() const {
234*795d594fSAndroid Build Coastguard Worker DCHECK(IsMethod());
235*795d594fSAndroid Build Coastguard Worker return item_.GetDexFile().GetMethodId(item_.GetIndex());
236*795d594fSAndroid Build Coastguard Worker }
237*795d594fSAndroid Build Coastguard Worker
GetFieldId() const238*795d594fSAndroid Build Coastguard Worker inline const dex::FieldId& GetFieldId() const {
239*795d594fSAndroid Build Coastguard Worker DCHECK(!IsMethod());
240*795d594fSAndroid Build Coastguard Worker return item_.GetDexFile().GetFieldId(item_.GetIndex());
241*795d594fSAndroid Build Coastguard Worker }
242*795d594fSAndroid Build Coastguard Worker
243*795d594fSAndroid Build Coastguard Worker const DexClass& klass_;
244*795d594fSAndroid Build Coastguard Worker const ClassAccessor::BaseItem& item_;
245*795d594fSAndroid Build Coastguard Worker const bool is_method_;
246*795d594fSAndroid Build Coastguard Worker };
247*795d594fSAndroid Build Coastguard Worker
248*795d594fSAndroid Build Coastguard Worker class ClassPath final {
249*795d594fSAndroid Build Coastguard Worker public:
ClassPath(const std::vector<std::string> & dex_paths,bool ignore_empty)250*795d594fSAndroid Build Coastguard Worker ClassPath(const std::vector<std::string>& dex_paths, bool ignore_empty) {
251*795d594fSAndroid Build Coastguard Worker OpenDexFiles(dex_paths, ignore_empty);
252*795d594fSAndroid Build Coastguard Worker }
253*795d594fSAndroid Build Coastguard Worker
254*795d594fSAndroid Build Coastguard Worker template <typename Fn>
ForEachDexClass(const DexFile * dex_file,Fn fn)255*795d594fSAndroid Build Coastguard Worker void ForEachDexClass(const DexFile* dex_file, Fn fn) {
256*795d594fSAndroid Build Coastguard Worker for (ClassAccessor accessor : dex_file->GetClasses()) {
257*795d594fSAndroid Build Coastguard Worker fn(DexClass(accessor));
258*795d594fSAndroid Build Coastguard Worker }
259*795d594fSAndroid Build Coastguard Worker }
260*795d594fSAndroid Build Coastguard Worker
261*795d594fSAndroid Build Coastguard Worker template<typename Fn>
ForEachDexClass(Fn fn)262*795d594fSAndroid Build Coastguard Worker void ForEachDexClass(Fn fn) {
263*795d594fSAndroid Build Coastguard Worker for (auto& dex_file : dex_files_) {
264*795d594fSAndroid Build Coastguard Worker for (ClassAccessor accessor : dex_file->GetClasses()) {
265*795d594fSAndroid Build Coastguard Worker fn(DexClass(accessor));
266*795d594fSAndroid Build Coastguard Worker }
267*795d594fSAndroid Build Coastguard Worker }
268*795d594fSAndroid Build Coastguard Worker }
269*795d594fSAndroid Build Coastguard Worker
270*795d594fSAndroid Build Coastguard Worker template<typename Fn>
ForEachDexMember(Fn fn)271*795d594fSAndroid Build Coastguard Worker void ForEachDexMember(Fn fn) {
272*795d594fSAndroid Build Coastguard Worker ForEachDexClass([&fn](const DexClass& klass) {
273*795d594fSAndroid Build Coastguard Worker for (const ClassAccessor::Field& field : klass.GetFields()) {
274*795d594fSAndroid Build Coastguard Worker fn(DexMember(klass, field));
275*795d594fSAndroid Build Coastguard Worker }
276*795d594fSAndroid Build Coastguard Worker for (const ClassAccessor::Method& method : klass.GetMethods()) {
277*795d594fSAndroid Build Coastguard Worker fn(DexMember(klass, method));
278*795d594fSAndroid Build Coastguard Worker }
279*795d594fSAndroid Build Coastguard Worker });
280*795d594fSAndroid Build Coastguard Worker }
281*795d594fSAndroid Build Coastguard Worker
GetDexFiles() const282*795d594fSAndroid Build Coastguard Worker std::vector<const DexFile*> GetDexFiles() const {
283*795d594fSAndroid Build Coastguard Worker return MakeNonOwningPointerVector(dex_files_);
284*795d594fSAndroid Build Coastguard Worker }
285*795d594fSAndroid Build Coastguard Worker
UpdateDexChecksums()286*795d594fSAndroid Build Coastguard Worker void UpdateDexChecksums() {
287*795d594fSAndroid Build Coastguard Worker for (auto& dex_file : dex_files_) {
288*795d594fSAndroid Build Coastguard Worker // Obtain a writeable pointer to the dex header.
289*795d594fSAndroid Build Coastguard Worker DexFile::Header* header = const_cast<DexFile::Header*>(&dex_file->GetHeader());
290*795d594fSAndroid Build Coastguard Worker // Recalculate checksum and overwrite the value in the header.
291*795d594fSAndroid Build Coastguard Worker header->checksum_ = dex_file->CalculateChecksum();
292*795d594fSAndroid Build Coastguard Worker }
293*795d594fSAndroid Build Coastguard Worker }
294*795d594fSAndroid Build Coastguard Worker
295*795d594fSAndroid Build Coastguard Worker private:
OpenDexFiles(const std::vector<std::string> & dex_paths,bool ignore_empty)296*795d594fSAndroid Build Coastguard Worker void OpenDexFiles(const std::vector<std::string>& dex_paths, bool ignore_empty) {
297*795d594fSAndroid Build Coastguard Worker std::string error_msg;
298*795d594fSAndroid Build Coastguard Worker
299*795d594fSAndroid Build Coastguard Worker for (const std::string& filename : dex_paths) {
300*795d594fSAndroid Build Coastguard Worker DexFileLoader dex_file_loader(filename);
301*795d594fSAndroid Build Coastguard Worker DexFileLoaderErrorCode error_code;
302*795d594fSAndroid Build Coastguard Worker bool success = dex_file_loader.Open(/* verify= */ true,
303*795d594fSAndroid Build Coastguard Worker /* verify_checksum= */ true,
304*795d594fSAndroid Build Coastguard Worker /*allow_no_dex_files=*/ ignore_empty,
305*795d594fSAndroid Build Coastguard Worker &error_code,
306*795d594fSAndroid Build Coastguard Worker &error_msg,
307*795d594fSAndroid Build Coastguard Worker &dex_files_);
308*795d594fSAndroid Build Coastguard Worker CHECK(success) << "Open failed for '" << filename << "' " << error_msg;
309*795d594fSAndroid Build Coastguard Worker }
310*795d594fSAndroid Build Coastguard Worker }
311*795d594fSAndroid Build Coastguard Worker
312*795d594fSAndroid Build Coastguard Worker // Opened dex files. Note that these are opened as `const` but may be written into.
313*795d594fSAndroid Build Coastguard Worker std::vector<std::unique_ptr<const DexFile>> dex_files_;
314*795d594fSAndroid Build Coastguard Worker };
315*795d594fSAndroid Build Coastguard Worker
316*795d594fSAndroid Build Coastguard Worker class HierarchyClass final {
317*795d594fSAndroid Build Coastguard Worker public:
HierarchyClass()318*795d594fSAndroid Build Coastguard Worker HierarchyClass() {}
319*795d594fSAndroid Build Coastguard Worker
AddDexClass(const DexClass & klass)320*795d594fSAndroid Build Coastguard Worker void AddDexClass(const DexClass& klass) {
321*795d594fSAndroid Build Coastguard Worker CHECK(dex_classes_.empty() || klass.Equals(dex_classes_.front()));
322*795d594fSAndroid Build Coastguard Worker dex_classes_.push_back(klass);
323*795d594fSAndroid Build Coastguard Worker }
324*795d594fSAndroid Build Coastguard Worker
AddExtends(HierarchyClass & parent)325*795d594fSAndroid Build Coastguard Worker void AddExtends(HierarchyClass& parent) {
326*795d594fSAndroid Build Coastguard Worker CHECK(!Contains(extends_, &parent));
327*795d594fSAndroid Build Coastguard Worker CHECK(!Contains(parent.extended_by_, this));
328*795d594fSAndroid Build Coastguard Worker extends_.push_back(&parent);
329*795d594fSAndroid Build Coastguard Worker parent.extended_by_.push_back(this);
330*795d594fSAndroid Build Coastguard Worker }
331*795d594fSAndroid Build Coastguard Worker
GetOneDexClass() const332*795d594fSAndroid Build Coastguard Worker const DexClass& GetOneDexClass() const {
333*795d594fSAndroid Build Coastguard Worker CHECK(!dex_classes_.empty());
334*795d594fSAndroid Build Coastguard Worker return dex_classes_.front();
335*795d594fSAndroid Build Coastguard Worker }
336*795d594fSAndroid Build Coastguard Worker
337*795d594fSAndroid Build Coastguard Worker // See comment on Hierarchy::ForEachResolvableMember.
338*795d594fSAndroid Build Coastguard Worker template<typename Fn>
ForEachResolvableMember(const DexMember & other,Fn fn)339*795d594fSAndroid Build Coastguard Worker bool ForEachResolvableMember(const DexMember& other, Fn fn) {
340*795d594fSAndroid Build Coastguard Worker std::vector<HierarchyClass*> visited;
341*795d594fSAndroid Build Coastguard Worker return ForEachResolvableMember_Impl(other, fn, true, true, visited);
342*795d594fSAndroid Build Coastguard Worker }
343*795d594fSAndroid Build Coastguard Worker
344*795d594fSAndroid Build Coastguard Worker // Returns true if this class contains at least one member matching `other`.
HasMatchingMember(const DexMember & other)345*795d594fSAndroid Build Coastguard Worker bool HasMatchingMember(const DexMember& other) {
346*795d594fSAndroid Build Coastguard Worker return ForEachMatchingMember(other, [](const DexMember&) { return true; });
347*795d594fSAndroid Build Coastguard Worker }
348*795d594fSAndroid Build Coastguard Worker
349*795d594fSAndroid Build Coastguard Worker // Recursively iterates over all subclasses of this class and invokes `fn`
350*795d594fSAndroid Build Coastguard Worker // on each one. If `fn` returns false for a particular subclass, exploring its
351*795d594fSAndroid Build Coastguard Worker // subclasses is skipped.
352*795d594fSAndroid Build Coastguard Worker template<typename Fn>
ForEachSubClass(Fn fn)353*795d594fSAndroid Build Coastguard Worker void ForEachSubClass(Fn fn) {
354*795d594fSAndroid Build Coastguard Worker for (HierarchyClass* subclass : extended_by_) {
355*795d594fSAndroid Build Coastguard Worker if (fn(subclass)) {
356*795d594fSAndroid Build Coastguard Worker subclass->ForEachSubClass(fn);
357*795d594fSAndroid Build Coastguard Worker }
358*795d594fSAndroid Build Coastguard Worker }
359*795d594fSAndroid Build Coastguard Worker }
360*795d594fSAndroid Build Coastguard Worker
361*795d594fSAndroid Build Coastguard Worker private:
362*795d594fSAndroid Build Coastguard Worker template<typename Fn>
ForEachResolvableMember_Impl(const DexMember & other,Fn fn,bool allow_explore_up,bool allow_explore_down,std::vector<HierarchyClass * > visited)363*795d594fSAndroid Build Coastguard Worker bool ForEachResolvableMember_Impl(const DexMember& other,
364*795d594fSAndroid Build Coastguard Worker Fn fn,
365*795d594fSAndroid Build Coastguard Worker bool allow_explore_up,
366*795d594fSAndroid Build Coastguard Worker bool allow_explore_down,
367*795d594fSAndroid Build Coastguard Worker std::vector<HierarchyClass*> visited) {
368*795d594fSAndroid Build Coastguard Worker if (std::find(visited.begin(), visited.end(), this) == visited.end()) {
369*795d594fSAndroid Build Coastguard Worker visited.push_back(this);
370*795d594fSAndroid Build Coastguard Worker } else {
371*795d594fSAndroid Build Coastguard Worker return false;
372*795d594fSAndroid Build Coastguard Worker }
373*795d594fSAndroid Build Coastguard Worker
374*795d594fSAndroid Build Coastguard Worker // First try to find a member matching `other` in this class.
375*795d594fSAndroid Build Coastguard Worker bool found = ForEachMatchingMember(other, fn);
376*795d594fSAndroid Build Coastguard Worker
377*795d594fSAndroid Build Coastguard Worker // If not found, see if it is inherited from parents. Note that this will not
378*795d594fSAndroid Build Coastguard Worker // revisit parents already in `visited`.
379*795d594fSAndroid Build Coastguard Worker if (!found && allow_explore_up) {
380*795d594fSAndroid Build Coastguard Worker for (HierarchyClass* superclass : extends_) {
381*795d594fSAndroid Build Coastguard Worker found |= superclass->ForEachResolvableMember_Impl(
382*795d594fSAndroid Build Coastguard Worker other,
383*795d594fSAndroid Build Coastguard Worker fn,
384*795d594fSAndroid Build Coastguard Worker /* allow_explore_up */ true,
385*795d594fSAndroid Build Coastguard Worker /* allow_explore_down */ false,
386*795d594fSAndroid Build Coastguard Worker visited);
387*795d594fSAndroid Build Coastguard Worker }
388*795d594fSAndroid Build Coastguard Worker }
389*795d594fSAndroid Build Coastguard Worker
390*795d594fSAndroid Build Coastguard Worker // If this is a virtual method, continue exploring into subclasses so as to visit
391*795d594fSAndroid Build Coastguard Worker // all overriding methods. Allow subclasses to explore their superclasses if this
392*795d594fSAndroid Build Coastguard Worker // is an interface. This is needed to find implementations of this interface's
393*795d594fSAndroid Build Coastguard Worker // methods inherited from superclasses (b/122551864).
394*795d594fSAndroid Build Coastguard Worker if (allow_explore_down && other.IsVirtualMethod()) {
395*795d594fSAndroid Build Coastguard Worker for (HierarchyClass* subclass : extended_by_) {
396*795d594fSAndroid Build Coastguard Worker subclass->ForEachResolvableMember_Impl(
397*795d594fSAndroid Build Coastguard Worker other,
398*795d594fSAndroid Build Coastguard Worker fn,
399*795d594fSAndroid Build Coastguard Worker /* allow_explore_up */ GetOneDexClass().IsInterface(),
400*795d594fSAndroid Build Coastguard Worker /* allow_explore_down */ true,
401*795d594fSAndroid Build Coastguard Worker visited);
402*795d594fSAndroid Build Coastguard Worker }
403*795d594fSAndroid Build Coastguard Worker }
404*795d594fSAndroid Build Coastguard Worker
405*795d594fSAndroid Build Coastguard Worker return found;
406*795d594fSAndroid Build Coastguard Worker }
407*795d594fSAndroid Build Coastguard Worker
408*795d594fSAndroid Build Coastguard Worker template<typename Fn>
ForEachMatchingMember(const DexMember & other,Fn fn)409*795d594fSAndroid Build Coastguard Worker bool ForEachMatchingMember(const DexMember& other, Fn fn) {
410*795d594fSAndroid Build Coastguard Worker bool found = false;
411*795d594fSAndroid Build Coastguard Worker auto compare_member = [&](const DexMember& member) {
412*795d594fSAndroid Build Coastguard Worker // TODO(dbrazdil): Check whether class of `other` can access `member`.
413*795d594fSAndroid Build Coastguard Worker if (member == other) {
414*795d594fSAndroid Build Coastguard Worker found = true;
415*795d594fSAndroid Build Coastguard Worker fn(member);
416*795d594fSAndroid Build Coastguard Worker }
417*795d594fSAndroid Build Coastguard Worker };
418*795d594fSAndroid Build Coastguard Worker for (const DexClass& dex_class : dex_classes_) {
419*795d594fSAndroid Build Coastguard Worker for (const ClassAccessor::Field& field : dex_class.GetFields()) {
420*795d594fSAndroid Build Coastguard Worker compare_member(DexMember(dex_class, field));
421*795d594fSAndroid Build Coastguard Worker }
422*795d594fSAndroid Build Coastguard Worker for (const ClassAccessor::Method& method : dex_class.GetMethods()) {
423*795d594fSAndroid Build Coastguard Worker compare_member(DexMember(dex_class, method));
424*795d594fSAndroid Build Coastguard Worker }
425*795d594fSAndroid Build Coastguard Worker }
426*795d594fSAndroid Build Coastguard Worker return found;
427*795d594fSAndroid Build Coastguard Worker }
428*795d594fSAndroid Build Coastguard Worker
429*795d594fSAndroid Build Coastguard Worker // DexClass entries of this class found across all the provided dex files.
430*795d594fSAndroid Build Coastguard Worker std::vector<DexClass> dex_classes_;
431*795d594fSAndroid Build Coastguard Worker
432*795d594fSAndroid Build Coastguard Worker // Classes which this class inherits, or interfaces which it implements.
433*795d594fSAndroid Build Coastguard Worker std::vector<HierarchyClass*> extends_;
434*795d594fSAndroid Build Coastguard Worker
435*795d594fSAndroid Build Coastguard Worker // Classes which inherit from this class.
436*795d594fSAndroid Build Coastguard Worker std::vector<HierarchyClass*> extended_by_;
437*795d594fSAndroid Build Coastguard Worker };
438*795d594fSAndroid Build Coastguard Worker
439*795d594fSAndroid Build Coastguard Worker class Hierarchy final {
440*795d594fSAndroid Build Coastguard Worker public:
Hierarchy(ClassPath & classpath,bool fragment,bool verbose)441*795d594fSAndroid Build Coastguard Worker Hierarchy(ClassPath& classpath, bool fragment, bool verbose) : classpath_(classpath) {
442*795d594fSAndroid Build Coastguard Worker BuildClassHierarchy(fragment, verbose);
443*795d594fSAndroid Build Coastguard Worker }
444*795d594fSAndroid Build Coastguard Worker
445*795d594fSAndroid Build Coastguard Worker // Perform an operation for each member of the hierarchy which could potentially
446*795d594fSAndroid Build Coastguard Worker // be the result of method/field resolution of `other`.
447*795d594fSAndroid Build Coastguard Worker // The function `fn` should accept a DexMember reference and return true if
448*795d594fSAndroid Build Coastguard Worker // the member was changed. This drives a performance optimization which only
449*795d594fSAndroid Build Coastguard Worker // visits overriding members the first time the overridden member is visited.
450*795d594fSAndroid Build Coastguard Worker // Returns true if at least one resolvable member was found.
451*795d594fSAndroid Build Coastguard Worker template<typename Fn>
ForEachResolvableMember(const DexMember & other,Fn fn)452*795d594fSAndroid Build Coastguard Worker bool ForEachResolvableMember(const DexMember& other, Fn fn) {
453*795d594fSAndroid Build Coastguard Worker HierarchyClass* klass = FindClass(other.GetDeclaringClass().GetDescriptor());
454*795d594fSAndroid Build Coastguard Worker return (klass != nullptr) && klass->ForEachResolvableMember(other, fn);
455*795d594fSAndroid Build Coastguard Worker }
456*795d594fSAndroid Build Coastguard Worker
457*795d594fSAndroid Build Coastguard Worker // Returns true if `member`, which belongs to this classpath, is visible to
458*795d594fSAndroid Build Coastguard Worker // code in child class loaders.
IsMemberVisible(const DexMember & member)459*795d594fSAndroid Build Coastguard Worker bool IsMemberVisible(const DexMember& member) {
460*795d594fSAndroid Build Coastguard Worker if (!member.IsPublicOrProtected()) {
461*795d594fSAndroid Build Coastguard Worker // Member is private or package-private. Cannot be visible.
462*795d594fSAndroid Build Coastguard Worker return false;
463*795d594fSAndroid Build Coastguard Worker } else if (member.GetDeclaringClass().IsPublic()) {
464*795d594fSAndroid Build Coastguard Worker // Member is public or protected, and class is public. It must be visible.
465*795d594fSAndroid Build Coastguard Worker return true;
466*795d594fSAndroid Build Coastguard Worker } else if (member.IsConstructor()) {
467*795d594fSAndroid Build Coastguard Worker // Member is public or protected constructor and class is not public.
468*795d594fSAndroid Build Coastguard Worker // Must be hidden because it cannot be implicitly exposed by a subclass.
469*795d594fSAndroid Build Coastguard Worker return false;
470*795d594fSAndroid Build Coastguard Worker } else {
471*795d594fSAndroid Build Coastguard Worker // Member is public or protected method, but class is not public. Check if
472*795d594fSAndroid Build Coastguard Worker // it is exposed through a public subclass.
473*795d594fSAndroid Build Coastguard Worker // Example code (`foo` exposed by ClassB):
474*795d594fSAndroid Build Coastguard Worker // class ClassA { public void foo() { ... } }
475*795d594fSAndroid Build Coastguard Worker // public class ClassB extends ClassA {}
476*795d594fSAndroid Build Coastguard Worker HierarchyClass* klass = FindClass(member.GetDeclaringClass().GetDescriptor());
477*795d594fSAndroid Build Coastguard Worker CHECK(klass != nullptr);
478*795d594fSAndroid Build Coastguard Worker bool visible = false;
479*795d594fSAndroid Build Coastguard Worker klass->ForEachSubClass([&visible, &member](HierarchyClass* subclass) {
480*795d594fSAndroid Build Coastguard Worker if (subclass->HasMatchingMember(member)) {
481*795d594fSAndroid Build Coastguard Worker // There is a member which matches `member` in `subclass`, either
482*795d594fSAndroid Build Coastguard Worker // a virtual method overriding `member` or a field overshadowing
483*795d594fSAndroid Build Coastguard Worker // `member`. In either case, `member` remains hidden.
484*795d594fSAndroid Build Coastguard Worker CHECK(member.IsVirtualMethod() || !member.IsMethod());
485*795d594fSAndroid Build Coastguard Worker return false; // do not explore deeper
486*795d594fSAndroid Build Coastguard Worker } else if (subclass->GetOneDexClass().IsPublic()) {
487*795d594fSAndroid Build Coastguard Worker // `subclass` inherits and exposes `member`.
488*795d594fSAndroid Build Coastguard Worker visible = true;
489*795d594fSAndroid Build Coastguard Worker return false; // do not explore deeper
490*795d594fSAndroid Build Coastguard Worker } else {
491*795d594fSAndroid Build Coastguard Worker // `subclass` inherits `member` but does not expose it.
492*795d594fSAndroid Build Coastguard Worker return true; // explore deeper
493*795d594fSAndroid Build Coastguard Worker }
494*795d594fSAndroid Build Coastguard Worker });
495*795d594fSAndroid Build Coastguard Worker return visible;
496*795d594fSAndroid Build Coastguard Worker }
497*795d594fSAndroid Build Coastguard Worker }
498*795d594fSAndroid Build Coastguard Worker
499*795d594fSAndroid Build Coastguard Worker private:
FindClass(const std::string_view & descriptor)500*795d594fSAndroid Build Coastguard Worker HierarchyClass* FindClass(const std::string_view& descriptor) {
501*795d594fSAndroid Build Coastguard Worker auto it = classes_.find(descriptor);
502*795d594fSAndroid Build Coastguard Worker if (it == classes_.end()) {
503*795d594fSAndroid Build Coastguard Worker return nullptr;
504*795d594fSAndroid Build Coastguard Worker } else {
505*795d594fSAndroid Build Coastguard Worker return &it->second;
506*795d594fSAndroid Build Coastguard Worker }
507*795d594fSAndroid Build Coastguard Worker }
508*795d594fSAndroid Build Coastguard Worker
BuildClassHierarchy(bool fragment,bool verbose)509*795d594fSAndroid Build Coastguard Worker void BuildClassHierarchy(bool fragment, bool verbose) {
510*795d594fSAndroid Build Coastguard Worker // Create one HierarchyClass entry in `classes_` per class descriptor
511*795d594fSAndroid Build Coastguard Worker // and add all DexClass objects with the same descriptor to that entry.
512*795d594fSAndroid Build Coastguard Worker classpath_.ForEachDexClass([this](const DexClass& klass) {
513*795d594fSAndroid Build Coastguard Worker classes_[klass.GetDescriptor()].AddDexClass(klass);
514*795d594fSAndroid Build Coastguard Worker });
515*795d594fSAndroid Build Coastguard Worker
516*795d594fSAndroid Build Coastguard Worker // Connect each HierarchyClass to its successors and predecessors.
517*795d594fSAndroid Build Coastguard Worker for (auto& entry : classes_) {
518*795d594fSAndroid Build Coastguard Worker HierarchyClass& klass = entry.second;
519*795d594fSAndroid Build Coastguard Worker const DexClass& dex_klass = klass.GetOneDexClass();
520*795d594fSAndroid Build Coastguard Worker
521*795d594fSAndroid Build Coastguard Worker if (!dex_klass.HasSuperclass()) {
522*795d594fSAndroid Build Coastguard Worker CHECK(dex_klass.GetInterfaceDescriptors().empty())
523*795d594fSAndroid Build Coastguard Worker << "java/lang/Object should not implement any interfaces";
524*795d594fSAndroid Build Coastguard Worker continue;
525*795d594fSAndroid Build Coastguard Worker }
526*795d594fSAndroid Build Coastguard Worker
527*795d594fSAndroid Build Coastguard Worker auto add_extends = [&](const std::string_view& extends_desc) {
528*795d594fSAndroid Build Coastguard Worker HierarchyClass* extends = FindClass(extends_desc);
529*795d594fSAndroid Build Coastguard Worker if (extends != nullptr) {
530*795d594fSAndroid Build Coastguard Worker klass.AddExtends(*extends);
531*795d594fSAndroid Build Coastguard Worker } else if (!fragment || verbose) {
532*795d594fSAndroid Build Coastguard Worker auto severity = verbose ? ::android::base::WARNING : ::android::base::FATAL;
533*795d594fSAndroid Build Coastguard Worker LOG(severity)
534*795d594fSAndroid Build Coastguard Worker << "Superclass/interface " << extends_desc
535*795d594fSAndroid Build Coastguard Worker << " of class " << dex_klass.GetDescriptor() << " from dex file \""
536*795d594fSAndroid Build Coastguard Worker << dex_klass.GetDexFile().GetLocation() << "\" was not found. "
537*795d594fSAndroid Build Coastguard Worker << "Either it is missing or it appears later in the classpath spec.";
538*795d594fSAndroid Build Coastguard Worker }
539*795d594fSAndroid Build Coastguard Worker };
540*795d594fSAndroid Build Coastguard Worker
541*795d594fSAndroid Build Coastguard Worker add_extends(dex_klass.GetSuperclassDescriptor());
542*795d594fSAndroid Build Coastguard Worker for (const std::string_view& iface_desc : dex_klass.GetInterfaceDescriptors()) {
543*795d594fSAndroid Build Coastguard Worker add_extends(iface_desc);
544*795d594fSAndroid Build Coastguard Worker }
545*795d594fSAndroid Build Coastguard Worker }
546*795d594fSAndroid Build Coastguard Worker }
547*795d594fSAndroid Build Coastguard Worker
548*795d594fSAndroid Build Coastguard Worker ClassPath& classpath_;
549*795d594fSAndroid Build Coastguard Worker std::map<std::string_view, HierarchyClass> classes_;
550*795d594fSAndroid Build Coastguard Worker };
551*795d594fSAndroid Build Coastguard Worker
552*795d594fSAndroid Build Coastguard Worker // Builder of dex section containing hiddenapi flags.
553*795d594fSAndroid Build Coastguard Worker class HiddenapiClassDataBuilder final {
554*795d594fSAndroid Build Coastguard Worker public:
HiddenapiClassDataBuilder(const DexFile & dex_file)555*795d594fSAndroid Build Coastguard Worker explicit HiddenapiClassDataBuilder(const DexFile& dex_file)
556*795d594fSAndroid Build Coastguard Worker : num_classdefs_(dex_file.NumClassDefs()),
557*795d594fSAndroid Build Coastguard Worker next_class_def_idx_(0u),
558*795d594fSAndroid Build Coastguard Worker class_def_has_non_zero_flags_(false),
559*795d594fSAndroid Build Coastguard Worker dex_file_has_non_zero_flags_(false),
560*795d594fSAndroid Build Coastguard Worker data_(sizeof(uint32_t) * (num_classdefs_ + 1), 0u) {
561*795d594fSAndroid Build Coastguard Worker *GetSizeField() = GetCurrentDataSize();
562*795d594fSAndroid Build Coastguard Worker }
563*795d594fSAndroid Build Coastguard Worker
564*795d594fSAndroid Build Coastguard Worker // Notify the builder that new flags for the next class def
565*795d594fSAndroid Build Coastguard Worker // will be written now. The builder records the current offset
566*795d594fSAndroid Build Coastguard Worker // into the header.
BeginClassDef(uint32_t idx)567*795d594fSAndroid Build Coastguard Worker void BeginClassDef(uint32_t idx) {
568*795d594fSAndroid Build Coastguard Worker CHECK_EQ(next_class_def_idx_, idx);
569*795d594fSAndroid Build Coastguard Worker CHECK_LT(idx, num_classdefs_);
570*795d594fSAndroid Build Coastguard Worker GetOffsetArray()[idx] = GetCurrentDataSize();
571*795d594fSAndroid Build Coastguard Worker class_def_has_non_zero_flags_ = false;
572*795d594fSAndroid Build Coastguard Worker }
573*795d594fSAndroid Build Coastguard Worker
574*795d594fSAndroid Build Coastguard Worker // Notify the builder that all flags for this class def have been
575*795d594fSAndroid Build Coastguard Worker // written. The builder updates the total size of the data struct
576*795d594fSAndroid Build Coastguard Worker // and may set offset for class def in header to zero if no data
577*795d594fSAndroid Build Coastguard Worker // has been written.
EndClassDef(uint32_t idx)578*795d594fSAndroid Build Coastguard Worker void EndClassDef(uint32_t idx) {
579*795d594fSAndroid Build Coastguard Worker CHECK_EQ(next_class_def_idx_, idx);
580*795d594fSAndroid Build Coastguard Worker CHECK_LT(idx, num_classdefs_);
581*795d594fSAndroid Build Coastguard Worker
582*795d594fSAndroid Build Coastguard Worker ++next_class_def_idx_;
583*795d594fSAndroid Build Coastguard Worker
584*795d594fSAndroid Build Coastguard Worker if (!class_def_has_non_zero_flags_) {
585*795d594fSAndroid Build Coastguard Worker // No need to store flags for this class. Remove the written flags
586*795d594fSAndroid Build Coastguard Worker // and set offset in header to zero.
587*795d594fSAndroid Build Coastguard Worker data_.resize(GetOffsetArray()[idx]);
588*795d594fSAndroid Build Coastguard Worker GetOffsetArray()[idx] = 0u;
589*795d594fSAndroid Build Coastguard Worker }
590*795d594fSAndroid Build Coastguard Worker
591*795d594fSAndroid Build Coastguard Worker dex_file_has_non_zero_flags_ |= class_def_has_non_zero_flags_;
592*795d594fSAndroid Build Coastguard Worker
593*795d594fSAndroid Build Coastguard Worker if (idx == num_classdefs_ - 1) {
594*795d594fSAndroid Build Coastguard Worker if (dex_file_has_non_zero_flags_) {
595*795d594fSAndroid Build Coastguard Worker // This was the last class def and we have generated non-zero hiddenapi
596*795d594fSAndroid Build Coastguard Worker // flags. Update total size in the header.
597*795d594fSAndroid Build Coastguard Worker *GetSizeField() = GetCurrentDataSize();
598*795d594fSAndroid Build Coastguard Worker } else {
599*795d594fSAndroid Build Coastguard Worker // This was the last class def and we have not generated any non-zero
600*795d594fSAndroid Build Coastguard Worker // hiddenapi flags. Clear all the data.
601*795d594fSAndroid Build Coastguard Worker data_.clear();
602*795d594fSAndroid Build Coastguard Worker }
603*795d594fSAndroid Build Coastguard Worker }
604*795d594fSAndroid Build Coastguard Worker }
605*795d594fSAndroid Build Coastguard Worker
606*795d594fSAndroid Build Coastguard Worker // Append flags at the end of the data struct. This should be called
607*795d594fSAndroid Build Coastguard Worker // between BeginClassDef and EndClassDef in the order of appearance of
608*795d594fSAndroid Build Coastguard Worker // fields/methods in the class data stream.
WriteFlags(const ApiList & flags)609*795d594fSAndroid Build Coastguard Worker void WriteFlags(const ApiList& flags) {
610*795d594fSAndroid Build Coastguard Worker uint32_t dex_flags = flags.GetDexFlags();
611*795d594fSAndroid Build Coastguard Worker EncodeUnsignedLeb128(&data_, dex_flags);
612*795d594fSAndroid Build Coastguard Worker class_def_has_non_zero_flags_ |= (dex_flags != 0u);
613*795d594fSAndroid Build Coastguard Worker }
614*795d594fSAndroid Build Coastguard Worker
615*795d594fSAndroid Build Coastguard Worker // Return backing data, assuming that all flags have been written.
GetData() const616*795d594fSAndroid Build Coastguard Worker const std::vector<uint8_t>& GetData() const {
617*795d594fSAndroid Build Coastguard Worker CHECK_EQ(next_class_def_idx_, num_classdefs_) << "Incomplete data";
618*795d594fSAndroid Build Coastguard Worker return data_;
619*795d594fSAndroid Build Coastguard Worker }
620*795d594fSAndroid Build Coastguard Worker
621*795d594fSAndroid Build Coastguard Worker private:
622*795d594fSAndroid Build Coastguard Worker // Returns pointer to the size field in the header of this dex section.
GetSizeField()623*795d594fSAndroid Build Coastguard Worker uint32_t* GetSizeField() {
624*795d594fSAndroid Build Coastguard Worker // Assume malloc() aligns allocated memory to at least uint32_t.
625*795d594fSAndroid Build Coastguard Worker CHECK(IsAligned<sizeof(uint32_t)>(data_.data()));
626*795d594fSAndroid Build Coastguard Worker return reinterpret_cast<uint32_t*>(data_.data());
627*795d594fSAndroid Build Coastguard Worker }
628*795d594fSAndroid Build Coastguard Worker
629*795d594fSAndroid Build Coastguard Worker // Returns pointer to array of offsets (indexed by class def indices) in the
630*795d594fSAndroid Build Coastguard Worker // header of this dex section.
GetOffsetArray()631*795d594fSAndroid Build Coastguard Worker uint32_t* GetOffsetArray() { return &GetSizeField()[1]; }
GetCurrentDataSize() const632*795d594fSAndroid Build Coastguard Worker uint32_t GetCurrentDataSize() const { return data_.size(); }
633*795d594fSAndroid Build Coastguard Worker
634*795d594fSAndroid Build Coastguard Worker // Number of class defs in this dex file.
635*795d594fSAndroid Build Coastguard Worker const uint32_t num_classdefs_;
636*795d594fSAndroid Build Coastguard Worker
637*795d594fSAndroid Build Coastguard Worker // Next expected class def index.
638*795d594fSAndroid Build Coastguard Worker uint32_t next_class_def_idx_;
639*795d594fSAndroid Build Coastguard Worker
640*795d594fSAndroid Build Coastguard Worker // Whether non-zero flags have been encountered for this class def.
641*795d594fSAndroid Build Coastguard Worker bool class_def_has_non_zero_flags_;
642*795d594fSAndroid Build Coastguard Worker
643*795d594fSAndroid Build Coastguard Worker // Whether any non-zero flags have been encountered for this dex file.
644*795d594fSAndroid Build Coastguard Worker bool dex_file_has_non_zero_flags_;
645*795d594fSAndroid Build Coastguard Worker
646*795d594fSAndroid Build Coastguard Worker // Vector containing the data of the built data structure.
647*795d594fSAndroid Build Coastguard Worker std::vector<uint8_t> data_;
648*795d594fSAndroid Build Coastguard Worker };
649*795d594fSAndroid Build Coastguard Worker
650*795d594fSAndroid Build Coastguard Worker // Edits a dex file, inserting a new HiddenapiClassData section.
651*795d594fSAndroid Build Coastguard Worker class DexFileEditor final {
652*795d594fSAndroid Build Coastguard Worker public:
653*795d594fSAndroid Build Coastguard Worker // Add dex file to copy to output (possibly several files for multi-dex).
Add(const DexFile * dex,const std::vector<uint8_t> && hiddenapi_data)654*795d594fSAndroid Build Coastguard Worker void Add(const DexFile* dex, const std::vector<uint8_t>&& hiddenapi_data) {
655*795d594fSAndroid Build Coastguard Worker // We do not support non-standard dex encodings, e.g. compact dex.
656*795d594fSAndroid Build Coastguard Worker CHECK(dex->IsStandardDexFile());
657*795d594fSAndroid Build Coastguard Worker inputs_.emplace_back(dex, std::move(hiddenapi_data));
658*795d594fSAndroid Build Coastguard Worker }
659*795d594fSAndroid Build Coastguard Worker
660*795d594fSAndroid Build Coastguard Worker // Writes the edited dex file into a file.
WriteTo(const std::string & path)661*795d594fSAndroid Build Coastguard Worker void WriteTo(const std::string& path) {
662*795d594fSAndroid Build Coastguard Worker CHECK_GT(inputs_.size(), 0u);
663*795d594fSAndroid Build Coastguard Worker std::vector<uint8_t> output;
664*795d594fSAndroid Build Coastguard Worker
665*795d594fSAndroid Build Coastguard Worker // Copy the old dex files into the backing data vector.
666*795d594fSAndroid Build Coastguard Worker std::vector<size_t> header_offset;
667*795d594fSAndroid Build Coastguard Worker for (size_t i = 0; i < inputs_.size(); i++) {
668*795d594fSAndroid Build Coastguard Worker const DexFile* dex = inputs_[i].first;
669*795d594fSAndroid Build Coastguard Worker header_offset.push_back(output.size());
670*795d594fSAndroid Build Coastguard Worker std::copy(dex->Begin(), dex->End(), std::back_inserter(output));
671*795d594fSAndroid Build Coastguard Worker
672*795d594fSAndroid Build Coastguard Worker // Clear the old map list (make it into padding).
673*795d594fSAndroid Build Coastguard Worker const dex::MapList* map = dex->GetMapList();
674*795d594fSAndroid Build Coastguard Worker size_t map_off = dex->GetHeader().map_off_;
675*795d594fSAndroid Build Coastguard Worker size_t map_size = sizeof(map->size_) + map->size_ * sizeof(map->list_[0]);
676*795d594fSAndroid Build Coastguard Worker CHECK_LE(map_off, output.size()) << "Map list past the end of file";
677*795d594fSAndroid Build Coastguard Worker CHECK_EQ(map_size, output.size() - map_off) << "Map list expected at the end of file";
678*795d594fSAndroid Build Coastguard Worker std::fill_n(output.data() + map_off, map_size, 0);
679*795d594fSAndroid Build Coastguard Worker }
680*795d594fSAndroid Build Coastguard Worker
681*795d594fSAndroid Build Coastguard Worker // Append the hidden api data into the backing data vector.
682*795d594fSAndroid Build Coastguard Worker std::vector<size_t> hiddenapi_offset;
683*795d594fSAndroid Build Coastguard Worker for (size_t i = 0; i < inputs_.size(); i++) {
684*795d594fSAndroid Build Coastguard Worker const std::vector<uint8_t>& hiddenapi_data = inputs_[i].second;
685*795d594fSAndroid Build Coastguard Worker output.resize(RoundUp(output.size(), kHiddenapiClassDataAlignment)); // Align.
686*795d594fSAndroid Build Coastguard Worker hiddenapi_offset.push_back(output.size());
687*795d594fSAndroid Build Coastguard Worker std::copy(hiddenapi_data.begin(), hiddenapi_data.end(), std::back_inserter(output));
688*795d594fSAndroid Build Coastguard Worker }
689*795d594fSAndroid Build Coastguard Worker
690*795d594fSAndroid Build Coastguard Worker // Append modified map lists.
691*795d594fSAndroid Build Coastguard Worker std::vector<uint32_t> map_list_offset;
692*795d594fSAndroid Build Coastguard Worker for (size_t i = 0; i < inputs_.size(); i++) {
693*795d594fSAndroid Build Coastguard Worker output.resize(RoundUp(output.size(), kMapListAlignment)); // Align.
694*795d594fSAndroid Build Coastguard Worker
695*795d594fSAndroid Build Coastguard Worker const DexFile* dex = inputs_[i].first;
696*795d594fSAndroid Build Coastguard Worker const dex::MapList* map = dex->GetMapList();
697*795d594fSAndroid Build Coastguard Worker std::vector<dex::MapItem> items(map->list_, map->list_ + map->size_);
698*795d594fSAndroid Build Coastguard Worker
699*795d594fSAndroid Build Coastguard Worker // Check the header entry.
700*795d594fSAndroid Build Coastguard Worker CHECK(!items.empty());
701*795d594fSAndroid Build Coastguard Worker CHECK_EQ(items[0].type_, DexFile::kDexTypeHeaderItem);
702*795d594fSAndroid Build Coastguard Worker CHECK_EQ(items[0].offset_, header_offset[i]);
703*795d594fSAndroid Build Coastguard Worker
704*795d594fSAndroid Build Coastguard Worker // Check and remove the old map list entry (it does not have to be last).
705*795d594fSAndroid Build Coastguard Worker auto is_map_list = [](auto it) { return it.type_ == DexFile::kDexTypeMapList; };
706*795d594fSAndroid Build Coastguard Worker auto it = std::find_if(items.begin(), items.end(), is_map_list);
707*795d594fSAndroid Build Coastguard Worker CHECK(it != items.end());
708*795d594fSAndroid Build Coastguard Worker CHECK_EQ(it->offset_, dex->GetHeader().map_off_);
709*795d594fSAndroid Build Coastguard Worker items.erase(it);
710*795d594fSAndroid Build Coastguard Worker
711*795d594fSAndroid Build Coastguard Worker // Write new map list.
712*795d594fSAndroid Build Coastguard Worker if (!inputs_[i].second.empty()) {
713*795d594fSAndroid Build Coastguard Worker uint32_t payload_offset = hiddenapi_offset[i];
714*795d594fSAndroid Build Coastguard Worker items.push_back(dex::MapItem{DexFile::kDexTypeHiddenapiClassData, 0, 1u, payload_offset});
715*795d594fSAndroid Build Coastguard Worker }
716*795d594fSAndroid Build Coastguard Worker map_list_offset.push_back(output.size());
717*795d594fSAndroid Build Coastguard Worker items.push_back(dex::MapItem{DexFile::kDexTypeMapList, 0, 1u, map_list_offset.back()});
718*795d594fSAndroid Build Coastguard Worker uint32_t item_count = items.size();
719*795d594fSAndroid Build Coastguard Worker Append(&output, &item_count, 1);
720*795d594fSAndroid Build Coastguard Worker Append(&output, items.data(), items.size());
721*795d594fSAndroid Build Coastguard Worker }
722*795d594fSAndroid Build Coastguard Worker
723*795d594fSAndroid Build Coastguard Worker // Update headers.
724*795d594fSAndroid Build Coastguard Worker for (size_t i = 0; i < inputs_.size(); i++) {
725*795d594fSAndroid Build Coastguard Worker uint8_t* begin = output.data() + header_offset[i];
726*795d594fSAndroid Build Coastguard Worker auto* header = reinterpret_cast<DexFile::Header*>(begin);
727*795d594fSAndroid Build Coastguard Worker header->map_off_ = map_list_offset[i];
728*795d594fSAndroid Build Coastguard Worker if (i + 1 < inputs_.size()) {
729*795d594fSAndroid Build Coastguard Worker CHECK_EQ(header->file_size_, header_offset[i + 1] - header_offset[i]);
730*795d594fSAndroid Build Coastguard Worker } else {
731*795d594fSAndroid Build Coastguard Worker // Extend last dex file until the end of the file.
732*795d594fSAndroid Build Coastguard Worker header->data_size_ = output.size() - header->data_off_;
733*795d594fSAndroid Build Coastguard Worker header->file_size_ = output.size() - header_offset[i];
734*795d594fSAndroid Build Coastguard Worker }
735*795d594fSAndroid Build Coastguard Worker header->SetDexContainer(header_offset[i], output.size());
736*795d594fSAndroid Build Coastguard Worker size_t sha1_start = offsetof(DexFile::Header, file_size_);
737*795d594fSAndroid Build Coastguard Worker SHA1(begin + sha1_start, header->file_size_ - sha1_start, header->signature_.data());
738*795d594fSAndroid Build Coastguard Worker header->checksum_ = DexFile::CalculateChecksum(begin, header->file_size_);
739*795d594fSAndroid Build Coastguard Worker }
740*795d594fSAndroid Build Coastguard Worker
741*795d594fSAndroid Build Coastguard Worker // Write the output file.
742*795d594fSAndroid Build Coastguard Worker CHECK(!output.empty());
743*795d594fSAndroid Build Coastguard Worker std::ofstream ofs(path.c_str(), std::ofstream::out | std::ofstream::binary);
744*795d594fSAndroid Build Coastguard Worker ofs.write(reinterpret_cast<const char*>(output.data()), output.size());
745*795d594fSAndroid Build Coastguard Worker ofs.flush();
746*795d594fSAndroid Build Coastguard Worker CHECK(ofs.good());
747*795d594fSAndroid Build Coastguard Worker ofs.close();
748*795d594fSAndroid Build Coastguard Worker
749*795d594fSAndroid Build Coastguard Worker ReloadDex(path.c_str());
750*795d594fSAndroid Build Coastguard Worker }
751*795d594fSAndroid Build Coastguard Worker
752*795d594fSAndroid Build Coastguard Worker private:
753*795d594fSAndroid Build Coastguard Worker static constexpr size_t kMapListAlignment = 4u;
754*795d594fSAndroid Build Coastguard Worker static constexpr size_t kHiddenapiClassDataAlignment = 4u;
755*795d594fSAndroid Build Coastguard Worker
ReloadDex(const char * filename)756*795d594fSAndroid Build Coastguard Worker void ReloadDex(const char* filename) {
757*795d594fSAndroid Build Coastguard Worker std::string error_msg;
758*795d594fSAndroid Build Coastguard Worker ArtDexFileLoader loader(filename);
759*795d594fSAndroid Build Coastguard Worker std::vector<std::unique_ptr<const DexFile>> dex_files;
760*795d594fSAndroid Build Coastguard Worker bool ok = loader.Open(/*verify*/ true,
761*795d594fSAndroid Build Coastguard Worker /*verify_checksum*/ true,
762*795d594fSAndroid Build Coastguard Worker &error_msg,
763*795d594fSAndroid Build Coastguard Worker &dex_files);
764*795d594fSAndroid Build Coastguard Worker CHECK(ok) << "Failed to load edited dex file: " << error_msg;
765*795d594fSAndroid Build Coastguard Worker }
766*795d594fSAndroid Build Coastguard Worker
767*795d594fSAndroid Build Coastguard Worker template <typename T>
Append(std::vector<uint8_t> * output,const T * src,size_t len)768*795d594fSAndroid Build Coastguard Worker void Append(std::vector<uint8_t>* output, const T* src, size_t len) {
769*795d594fSAndroid Build Coastguard Worker const uint8_t* ptr = reinterpret_cast<const uint8_t*>(src);
770*795d594fSAndroid Build Coastguard Worker std::copy(ptr, ptr + len * sizeof(T), std::back_inserter(*output));
771*795d594fSAndroid Build Coastguard Worker }
772*795d594fSAndroid Build Coastguard Worker
773*795d594fSAndroid Build Coastguard Worker std::vector<std::pair<const DexFile*, const std::vector<uint8_t>>> inputs_;
774*795d594fSAndroid Build Coastguard Worker };
775*795d594fSAndroid Build Coastguard Worker
776*795d594fSAndroid Build Coastguard Worker class HiddenApi final {
777*795d594fSAndroid Build Coastguard Worker public:
HiddenApi()778*795d594fSAndroid Build Coastguard Worker HiddenApi() : force_assign_all_(true) {}
779*795d594fSAndroid Build Coastguard Worker
Run(int argc,char ** argv)780*795d594fSAndroid Build Coastguard Worker void Run(int argc, char** argv) {
781*795d594fSAndroid Build Coastguard Worker switch (ParseArgs(argc, argv)) {
782*795d594fSAndroid Build Coastguard Worker case Command::kEncode:
783*795d594fSAndroid Build Coastguard Worker EncodeAccessFlags();
784*795d594fSAndroid Build Coastguard Worker break;
785*795d594fSAndroid Build Coastguard Worker case Command::kList:
786*795d594fSAndroid Build Coastguard Worker ListApi();
787*795d594fSAndroid Build Coastguard Worker break;
788*795d594fSAndroid Build Coastguard Worker }
789*795d594fSAndroid Build Coastguard Worker }
790*795d594fSAndroid Build Coastguard Worker
791*795d594fSAndroid Build Coastguard Worker private:
792*795d594fSAndroid Build Coastguard Worker enum class Command {
793*795d594fSAndroid Build Coastguard Worker kEncode,
794*795d594fSAndroid Build Coastguard Worker kList,
795*795d594fSAndroid Build Coastguard Worker };
796*795d594fSAndroid Build Coastguard Worker
ParseArgs(int argc,char ** argv)797*795d594fSAndroid Build Coastguard Worker Command ParseArgs(int argc, char** argv) {
798*795d594fSAndroid Build Coastguard Worker // Skip over the binary's path.
799*795d594fSAndroid Build Coastguard Worker argv++;
800*795d594fSAndroid Build Coastguard Worker argc--;
801*795d594fSAndroid Build Coastguard Worker
802*795d594fSAndroid Build Coastguard Worker if (argc > 0) {
803*795d594fSAndroid Build Coastguard Worker const char* raw_command = argv[0];
804*795d594fSAndroid Build Coastguard Worker const std::string_view command(raw_command);
805*795d594fSAndroid Build Coastguard Worker if (command == "encode") {
806*795d594fSAndroid Build Coastguard Worker for (int i = 1; i < argc; ++i) {
807*795d594fSAndroid Build Coastguard Worker const char* raw_option = argv[i];
808*795d594fSAndroid Build Coastguard Worker const std::string_view option(raw_option);
809*795d594fSAndroid Build Coastguard Worker if (option.starts_with("--input-dex=")) {
810*795d594fSAndroid Build Coastguard Worker boot_dex_paths_.push_back(std::string(option.substr(strlen("--input-dex="))));
811*795d594fSAndroid Build Coastguard Worker } else if (option.starts_with("--output-dex=")) {
812*795d594fSAndroid Build Coastguard Worker output_dex_paths_.push_back(std::string(option.substr(strlen("--output-dex="))));
813*795d594fSAndroid Build Coastguard Worker } else if (option.starts_with("--api-flags=")) {
814*795d594fSAndroid Build Coastguard Worker api_flags_path_ = std::string(option.substr(strlen("--api-flags=")));
815*795d594fSAndroid Build Coastguard Worker } else if (option == "--no-force-assign-all") {
816*795d594fSAndroid Build Coastguard Worker force_assign_all_ = false;
817*795d594fSAndroid Build Coastguard Worker } else if (option.starts_with("--max-hiddenapi-level=")) {
818*795d594fSAndroid Build Coastguard Worker std::string value = std::string(option.substr(strlen("--max-hiddenapi-level=")));
819*795d594fSAndroid Build Coastguard Worker max_hiddenapi_level_ = ApiList::FromName(value);
820*795d594fSAndroid Build Coastguard Worker } else {
821*795d594fSAndroid Build Coastguard Worker Usage("Unknown argument '%s'", raw_option);
822*795d594fSAndroid Build Coastguard Worker }
823*795d594fSAndroid Build Coastguard Worker }
824*795d594fSAndroid Build Coastguard Worker return Command::kEncode;
825*795d594fSAndroid Build Coastguard Worker } else if (command == "list") {
826*795d594fSAndroid Build Coastguard Worker for (int i = 1; i < argc; ++i) {
827*795d594fSAndroid Build Coastguard Worker const char* raw_option = argv[i];
828*795d594fSAndroid Build Coastguard Worker const std::string_view option(raw_option);
829*795d594fSAndroid Build Coastguard Worker if (option.starts_with("--dependency-stub-dex=")) {
830*795d594fSAndroid Build Coastguard Worker const std::string path(std::string(option.substr(strlen("--dependency-stub-dex="))));
831*795d594fSAndroid Build Coastguard Worker dependency_stub_dex_paths_.push_back(path);
832*795d594fSAndroid Build Coastguard Worker // Add path to the boot dex path to resolve dependencies.
833*795d594fSAndroid Build Coastguard Worker boot_dex_paths_.push_back(path);
834*795d594fSAndroid Build Coastguard Worker } else if (option.starts_with("--boot-dex=")) {
835*795d594fSAndroid Build Coastguard Worker boot_dex_paths_.push_back(std::string(option.substr(strlen("--boot-dex="))));
836*795d594fSAndroid Build Coastguard Worker } else if (option.starts_with("--public-stub-classpath=")) {
837*795d594fSAndroid Build Coastguard Worker stub_classpaths_.push_back(std::make_pair(
838*795d594fSAndroid Build Coastguard Worker std::string(option.substr(strlen("--public-stub-classpath="))),
839*795d594fSAndroid Build Coastguard Worker ApiStubs::Kind::kPublicApi));
840*795d594fSAndroid Build Coastguard Worker } else if (option.starts_with("--system-stub-classpath=")) {
841*795d594fSAndroid Build Coastguard Worker stub_classpaths_.push_back(std::make_pair(
842*795d594fSAndroid Build Coastguard Worker std::string(option.substr(strlen("--system-stub-classpath="))),
843*795d594fSAndroid Build Coastguard Worker ApiStubs::Kind::kSystemApi));
844*795d594fSAndroid Build Coastguard Worker } else if (option.starts_with("--test-stub-classpath=")) {
845*795d594fSAndroid Build Coastguard Worker stub_classpaths_.push_back(std::make_pair(
846*795d594fSAndroid Build Coastguard Worker std::string(option.substr(strlen("--test-stub-classpath="))),
847*795d594fSAndroid Build Coastguard Worker ApiStubs::Kind::kTestApi));
848*795d594fSAndroid Build Coastguard Worker } else if (option.starts_with("--core-platform-stub-classpath=")) {
849*795d594fSAndroid Build Coastguard Worker stub_classpaths_.push_back(std::make_pair(
850*795d594fSAndroid Build Coastguard Worker std::string(option.substr(strlen("--core-platform-stub-classpath="))),
851*795d594fSAndroid Build Coastguard Worker ApiStubs::Kind::kCorePlatformApi));
852*795d594fSAndroid Build Coastguard Worker } else if (option.starts_with("--out-api-flags=")) {
853*795d594fSAndroid Build Coastguard Worker api_flags_path_ = std::string(option.substr(strlen("--out-api-flags=")));
854*795d594fSAndroid Build Coastguard Worker } else if (option == "--fragment") {
855*795d594fSAndroid Build Coastguard Worker fragment_ = true;
856*795d594fSAndroid Build Coastguard Worker } else if (option == "--verbose") {
857*795d594fSAndroid Build Coastguard Worker verbose_ = true;
858*795d594fSAndroid Build Coastguard Worker } else {
859*795d594fSAndroid Build Coastguard Worker Usage("Unknown argument '%s'", raw_option);
860*795d594fSAndroid Build Coastguard Worker }
861*795d594fSAndroid Build Coastguard Worker }
862*795d594fSAndroid Build Coastguard Worker return Command::kList;
863*795d594fSAndroid Build Coastguard Worker } else {
864*795d594fSAndroid Build Coastguard Worker Usage("Unknown command '%s'", raw_command);
865*795d594fSAndroid Build Coastguard Worker }
866*795d594fSAndroid Build Coastguard Worker } else {
867*795d594fSAndroid Build Coastguard Worker Usage("No command specified");
868*795d594fSAndroid Build Coastguard Worker }
869*795d594fSAndroid Build Coastguard Worker }
870*795d594fSAndroid Build Coastguard Worker
EncodeAccessFlags()871*795d594fSAndroid Build Coastguard Worker void EncodeAccessFlags() {
872*795d594fSAndroid Build Coastguard Worker if (boot_dex_paths_.empty()) {
873*795d594fSAndroid Build Coastguard Worker Usage("No input DEX files specified");
874*795d594fSAndroid Build Coastguard Worker } else if (output_dex_paths_.size() != boot_dex_paths_.size()) {
875*795d594fSAndroid Build Coastguard Worker Usage("Number of input DEX files does not match number of output DEX files");
876*795d594fSAndroid Build Coastguard Worker }
877*795d594fSAndroid Build Coastguard Worker
878*795d594fSAndroid Build Coastguard Worker // Load dex signatures.
879*795d594fSAndroid Build Coastguard Worker std::map<std::string, ApiList> api_list = OpenApiFile(api_flags_path_);
880*795d594fSAndroid Build Coastguard Worker
881*795d594fSAndroid Build Coastguard Worker // Iterate over input dex files and insert HiddenapiClassData sections.
882*795d594fSAndroid Build Coastguard Worker bool max_hiddenapi_level_error = false;
883*795d594fSAndroid Build Coastguard Worker for (size_t i = 0; i < boot_dex_paths_.size(); ++i) {
884*795d594fSAndroid Build Coastguard Worker const std::string& input_path = boot_dex_paths_[i];
885*795d594fSAndroid Build Coastguard Worker const std::string& output_path = output_dex_paths_[i];
886*795d594fSAndroid Build Coastguard Worker
887*795d594fSAndroid Build Coastguard Worker ClassPath boot_classpath({input_path}, /* ignore_empty= */ false);
888*795d594fSAndroid Build Coastguard Worker DexFileEditor dex_editor;
889*795d594fSAndroid Build Coastguard Worker for (const DexFile* input_dex : boot_classpath.GetDexFiles()) {
890*795d594fSAndroid Build Coastguard Worker HiddenapiClassDataBuilder builder(*input_dex);
891*795d594fSAndroid Build Coastguard Worker boot_classpath.ForEachDexClass(input_dex, [&](const DexClass& boot_class) {
892*795d594fSAndroid Build Coastguard Worker builder.BeginClassDef(boot_class.GetClassDefIndex());
893*795d594fSAndroid Build Coastguard Worker if (boot_class.GetData() != nullptr) {
894*795d594fSAndroid Build Coastguard Worker auto fn_shared = [&](const DexMember& boot_member) {
895*795d594fSAndroid Build Coastguard Worker auto signature = boot_member.GetApiEntry();
896*795d594fSAndroid Build Coastguard Worker auto it = api_list.find(signature);
897*795d594fSAndroid Build Coastguard Worker bool api_list_found = (it != api_list.end());
898*795d594fSAndroid Build Coastguard Worker CHECK(!force_assign_all_ || api_list_found)
899*795d594fSAndroid Build Coastguard Worker << "Could not find hiddenapi flags for dex entry: " << signature;
900*795d594fSAndroid Build Coastguard Worker if (api_list_found && it->second.GetIntValue() > max_hiddenapi_level_.GetIntValue()) {
901*795d594fSAndroid Build Coastguard Worker ApiList without_domain(it->second.GetIntValue());
902*795d594fSAndroid Build Coastguard Worker LOG(ERROR) << "Hidden api flag " << without_domain << " for member " << signature
903*795d594fSAndroid Build Coastguard Worker << " in " << input_path << " exceeds maximum allowable flag "
904*795d594fSAndroid Build Coastguard Worker << max_hiddenapi_level_;
905*795d594fSAndroid Build Coastguard Worker max_hiddenapi_level_error = true;
906*795d594fSAndroid Build Coastguard Worker } else {
907*795d594fSAndroid Build Coastguard Worker builder.WriteFlags(api_list_found ? it->second : ApiList::Sdk());
908*795d594fSAndroid Build Coastguard Worker }
909*795d594fSAndroid Build Coastguard Worker };
910*795d594fSAndroid Build Coastguard Worker auto fn_field = [&](const ClassAccessor::Field& boot_field) {
911*795d594fSAndroid Build Coastguard Worker fn_shared(DexMember(boot_class, boot_field));
912*795d594fSAndroid Build Coastguard Worker };
913*795d594fSAndroid Build Coastguard Worker auto fn_method = [&](const ClassAccessor::Method& boot_method) {
914*795d594fSAndroid Build Coastguard Worker fn_shared(DexMember(boot_class, boot_method));
915*795d594fSAndroid Build Coastguard Worker };
916*795d594fSAndroid Build Coastguard Worker boot_class.VisitFieldsAndMethods(fn_field, fn_field, fn_method, fn_method);
917*795d594fSAndroid Build Coastguard Worker }
918*795d594fSAndroid Build Coastguard Worker builder.EndClassDef(boot_class.GetClassDefIndex());
919*795d594fSAndroid Build Coastguard Worker });
920*795d594fSAndroid Build Coastguard Worker dex_editor.Add(input_dex, std::move(builder.GetData()));
921*795d594fSAndroid Build Coastguard Worker }
922*795d594fSAndroid Build Coastguard Worker dex_editor.WriteTo(output_path);
923*795d594fSAndroid Build Coastguard Worker }
924*795d594fSAndroid Build Coastguard Worker
925*795d594fSAndroid Build Coastguard Worker if (max_hiddenapi_level_error) {
926*795d594fSAndroid Build Coastguard Worker LOG(ERROR)
927*795d594fSAndroid Build Coastguard Worker << "Some hidden API flags could not be encoded within the dex file as"
928*795d594fSAndroid Build Coastguard Worker << " they exceed the maximum allowable level of " << max_hiddenapi_level_
929*795d594fSAndroid Build Coastguard Worker << " which is determined by the min_sdk_version of the source Java library.\n"
930*795d594fSAndroid Build Coastguard Worker << "The affected DEX members are reported in previous error messages.\n"
931*795d594fSAndroid Build Coastguard Worker << "The unsupported flags are being generated from the maxTargetSdk property"
932*795d594fSAndroid Build Coastguard Worker << " of the member's @UnsupportedAppUsage annotation.\n"
933*795d594fSAndroid Build Coastguard Worker << "See b/172453495 and/or contact art-team@ or compat-team@ for more info.\n";
934*795d594fSAndroid Build Coastguard Worker exit(EXIT_FAILURE);
935*795d594fSAndroid Build Coastguard Worker }
936*795d594fSAndroid Build Coastguard Worker }
937*795d594fSAndroid Build Coastguard Worker
OpenApiFile(const std::string & path)938*795d594fSAndroid Build Coastguard Worker std::map<std::string, ApiList> OpenApiFile(const std::string& path) {
939*795d594fSAndroid Build Coastguard Worker CHECK(!path.empty());
940*795d594fSAndroid Build Coastguard Worker std::ifstream api_file(path, std::ifstream::in);
941*795d594fSAndroid Build Coastguard Worker CHECK(!api_file.fail()) << "Unable to open file '" << path << "' " << strerror(errno);
942*795d594fSAndroid Build Coastguard Worker
943*795d594fSAndroid Build Coastguard Worker std::map<std::string, ApiList> api_flag_map;
944*795d594fSAndroid Build Coastguard Worker
945*795d594fSAndroid Build Coastguard Worker size_t line_number = 1;
946*795d594fSAndroid Build Coastguard Worker bool errors = false;
947*795d594fSAndroid Build Coastguard Worker for (std::string line; std::getline(api_file, line); line_number++) {
948*795d594fSAndroid Build Coastguard Worker // Every line contains a comma separated list with the signature as the
949*795d594fSAndroid Build Coastguard Worker // first element and the api flags as the rest
950*795d594fSAndroid Build Coastguard Worker std::vector<std::string> values = android::base::Split(line, ",");
951*795d594fSAndroid Build Coastguard Worker CHECK_GT(values.size(), 1u) << path << ":" << line_number
952*795d594fSAndroid Build Coastguard Worker << ": No flags found: " << line << kErrorHelp;
953*795d594fSAndroid Build Coastguard Worker
954*795d594fSAndroid Build Coastguard Worker const std::string& signature = values[0];
955*795d594fSAndroid Build Coastguard Worker
956*795d594fSAndroid Build Coastguard Worker CHECK(api_flag_map.find(signature) == api_flag_map.end()) << path << ":" << line_number
957*795d594fSAndroid Build Coastguard Worker << ": Duplicate entry: " << signature << kErrorHelp;
958*795d594fSAndroid Build Coastguard Worker
959*795d594fSAndroid Build Coastguard Worker ApiList membership;
960*795d594fSAndroid Build Coastguard Worker
961*795d594fSAndroid Build Coastguard Worker std::vector<std::string>::iterator apiListBegin = values.begin() + 1;
962*795d594fSAndroid Build Coastguard Worker std::vector<std::string>::iterator apiListEnd = values.end();
963*795d594fSAndroid Build Coastguard Worker bool success = ApiList::FromNames(apiListBegin, apiListEnd, &membership);
964*795d594fSAndroid Build Coastguard Worker if (!success) {
965*795d594fSAndroid Build Coastguard Worker LOG(ERROR) << path << ":" << line_number
966*795d594fSAndroid Build Coastguard Worker << ": Some flags were not recognized: " << line << kErrorHelp;
967*795d594fSAndroid Build Coastguard Worker errors = true;
968*795d594fSAndroid Build Coastguard Worker continue;
969*795d594fSAndroid Build Coastguard Worker } else if (!membership.IsValid()) {
970*795d594fSAndroid Build Coastguard Worker LOG(ERROR) << path << ":" << line_number
971*795d594fSAndroid Build Coastguard Worker << ": Invalid combination of flags: " << line << kErrorHelp;
972*795d594fSAndroid Build Coastguard Worker errors = true;
973*795d594fSAndroid Build Coastguard Worker continue;
974*795d594fSAndroid Build Coastguard Worker }
975*795d594fSAndroid Build Coastguard Worker
976*795d594fSAndroid Build Coastguard Worker api_flag_map.emplace(signature, membership);
977*795d594fSAndroid Build Coastguard Worker }
978*795d594fSAndroid Build Coastguard Worker CHECK(!errors) << "Errors encountered while parsing file " << path;
979*795d594fSAndroid Build Coastguard Worker
980*795d594fSAndroid Build Coastguard Worker api_file.close();
981*795d594fSAndroid Build Coastguard Worker return api_flag_map;
982*795d594fSAndroid Build Coastguard Worker }
983*795d594fSAndroid Build Coastguard Worker
984*795d594fSAndroid Build Coastguard Worker // A special flag added to the set of flags in boot_members to indicate that
985*795d594fSAndroid Build Coastguard Worker // it should be excluded from the output.
986*795d594fSAndroid Build Coastguard Worker static constexpr std::string_view kExcludeFromOutput{"exclude-from-output"};
987*795d594fSAndroid Build Coastguard Worker
ListApi()988*795d594fSAndroid Build Coastguard Worker void ListApi() {
989*795d594fSAndroid Build Coastguard Worker if (boot_dex_paths_.empty()) {
990*795d594fSAndroid Build Coastguard Worker Usage("No boot DEX files specified");
991*795d594fSAndroid Build Coastguard Worker } else if (stub_classpaths_.empty()) {
992*795d594fSAndroid Build Coastguard Worker Usage("No stub DEX files specified");
993*795d594fSAndroid Build Coastguard Worker } else if (api_flags_path_.empty()) {
994*795d594fSAndroid Build Coastguard Worker Usage("No output path specified");
995*795d594fSAndroid Build Coastguard Worker }
996*795d594fSAndroid Build Coastguard Worker
997*795d594fSAndroid Build Coastguard Worker // Complete list of boot class path members. The associated boolean states
998*795d594fSAndroid Build Coastguard Worker // whether it is public (true) or private (false).
999*795d594fSAndroid Build Coastguard Worker std::map<std::string, std::set<std::string_view>> boot_members;
1000*795d594fSAndroid Build Coastguard Worker
1001*795d594fSAndroid Build Coastguard Worker // Deduplicate errors before printing them.
1002*795d594fSAndroid Build Coastguard Worker std::set<std::string> unresolved;
1003*795d594fSAndroid Build Coastguard Worker
1004*795d594fSAndroid Build Coastguard Worker // Open all dex files.
1005*795d594fSAndroid Build Coastguard Worker ClassPath boot_classpath(boot_dex_paths_, /* ignore_empty= */ false);
1006*795d594fSAndroid Build Coastguard Worker Hierarchy boot_hierarchy(boot_classpath, fragment_, verbose_);
1007*795d594fSAndroid Build Coastguard Worker
1008*795d594fSAndroid Build Coastguard Worker // Mark all boot dex members private.
1009*795d594fSAndroid Build Coastguard Worker boot_classpath.ForEachDexMember([&](const DexMember& boot_member) {
1010*795d594fSAndroid Build Coastguard Worker boot_members[boot_member.GetApiEntry()] = {};
1011*795d594fSAndroid Build Coastguard Worker });
1012*795d594fSAndroid Build Coastguard Worker
1013*795d594fSAndroid Build Coastguard Worker // Open all dependency API stub dex files.
1014*795d594fSAndroid Build Coastguard Worker ClassPath dependency_classpath(dependency_stub_dex_paths_, /* ignore_empty= */ false);
1015*795d594fSAndroid Build Coastguard Worker
1016*795d594fSAndroid Build Coastguard Worker // Mark all dependency API stub dex members as coming from the dependency.
1017*795d594fSAndroid Build Coastguard Worker dependency_classpath.ForEachDexMember([&](const DexMember& boot_member) {
1018*795d594fSAndroid Build Coastguard Worker boot_members[boot_member.GetApiEntry()] = {kExcludeFromOutput};
1019*795d594fSAndroid Build Coastguard Worker });
1020*795d594fSAndroid Build Coastguard Worker
1021*795d594fSAndroid Build Coastguard Worker // Resolve each SDK dex member against the framework and mark it as SDK.
1022*795d594fSAndroid Build Coastguard Worker for (const auto& cp_entry : stub_classpaths_) {
1023*795d594fSAndroid Build Coastguard Worker // Ignore any empty stub jars as it just means that they provide no APIs
1024*795d594fSAndroid Build Coastguard Worker // for the current kind, e.g. framework-sdkextensions does not provide
1025*795d594fSAndroid Build Coastguard Worker // any public APIs.
1026*795d594fSAndroid Build Coastguard Worker ClassPath stub_classpath(android::base::Split(cp_entry.first, ":"), /*ignore_empty=*/true);
1027*795d594fSAndroid Build Coastguard Worker Hierarchy stub_hierarchy(stub_classpath, fragment_, verbose_);
1028*795d594fSAndroid Build Coastguard Worker const ApiStubs::Kind stub_api = cp_entry.second;
1029*795d594fSAndroid Build Coastguard Worker
1030*795d594fSAndroid Build Coastguard Worker stub_classpath.ForEachDexMember(
1031*795d594fSAndroid Build Coastguard Worker [&](const DexMember& stub_member) {
1032*795d594fSAndroid Build Coastguard Worker if (!stub_hierarchy.IsMemberVisible(stub_member)) {
1033*795d594fSAndroid Build Coastguard Worker // Typically fake constructors and inner-class `this` fields.
1034*795d594fSAndroid Build Coastguard Worker return;
1035*795d594fSAndroid Build Coastguard Worker }
1036*795d594fSAndroid Build Coastguard Worker bool resolved = boot_hierarchy.ForEachResolvableMember(
1037*795d594fSAndroid Build Coastguard Worker stub_member,
1038*795d594fSAndroid Build Coastguard Worker [&](const DexMember& boot_member) {
1039*795d594fSAndroid Build Coastguard Worker std::string entry = boot_member.GetApiEntry();
1040*795d594fSAndroid Build Coastguard Worker auto it = boot_members.find(entry);
1041*795d594fSAndroid Build Coastguard Worker CHECK(it != boot_members.end());
1042*795d594fSAndroid Build Coastguard Worker it->second.insert(ApiStubs::ToString(stub_api));
1043*795d594fSAndroid Build Coastguard Worker });
1044*795d594fSAndroid Build Coastguard Worker if (!resolved) {
1045*795d594fSAndroid Build Coastguard Worker unresolved.insert(stub_member.GetApiEntry());
1046*795d594fSAndroid Build Coastguard Worker }
1047*795d594fSAndroid Build Coastguard Worker });
1048*795d594fSAndroid Build Coastguard Worker }
1049*795d594fSAndroid Build Coastguard Worker
1050*795d594fSAndroid Build Coastguard Worker // Print errors.
1051*795d594fSAndroid Build Coastguard Worker if (!fragment_ || verbose_) {
1052*795d594fSAndroid Build Coastguard Worker for (const std::string& str : unresolved) {
1053*795d594fSAndroid Build Coastguard Worker LOG(WARNING) << "unresolved: " << str;
1054*795d594fSAndroid Build Coastguard Worker }
1055*795d594fSAndroid Build Coastguard Worker }
1056*795d594fSAndroid Build Coastguard Worker
1057*795d594fSAndroid Build Coastguard Worker // Write into public/private API files.
1058*795d594fSAndroid Build Coastguard Worker std::ofstream file_flags(api_flags_path_.c_str());
1059*795d594fSAndroid Build Coastguard Worker for (const auto& entry : boot_members) {
1060*795d594fSAndroid Build Coastguard Worker std::set<std::string_view> flags = entry.second;
1061*795d594fSAndroid Build Coastguard Worker if (flags.empty()) {
1062*795d594fSAndroid Build Coastguard Worker // There are no flags so it cannot be from the dependency stub API dex
1063*795d594fSAndroid Build Coastguard Worker // files so just output the signature.
1064*795d594fSAndroid Build Coastguard Worker file_flags << entry.first << std::endl;
1065*795d594fSAndroid Build Coastguard Worker } else if (flags.find(kExcludeFromOutput) == flags.end()) {
1066*795d594fSAndroid Build Coastguard Worker // The entry has flags and is not from the dependency stub API dex so
1067*795d594fSAndroid Build Coastguard Worker // output it.
1068*795d594fSAndroid Build Coastguard Worker file_flags << entry.first << ",";
1069*795d594fSAndroid Build Coastguard Worker file_flags << android::base::Join(entry.second, ",") << std::endl;
1070*795d594fSAndroid Build Coastguard Worker }
1071*795d594fSAndroid Build Coastguard Worker }
1072*795d594fSAndroid Build Coastguard Worker file_flags.close();
1073*795d594fSAndroid Build Coastguard Worker }
1074*795d594fSAndroid Build Coastguard Worker
1075*795d594fSAndroid Build Coastguard Worker // Whether to check that all dex entries have been assigned flags.
1076*795d594fSAndroid Build Coastguard Worker // Defaults to true.
1077*795d594fSAndroid Build Coastguard Worker bool force_assign_all_;
1078*795d594fSAndroid Build Coastguard Worker
1079*795d594fSAndroid Build Coastguard Worker // Paths to DEX files which should be processed.
1080*795d594fSAndroid Build Coastguard Worker std::vector<std::string> boot_dex_paths_;
1081*795d594fSAndroid Build Coastguard Worker
1082*795d594fSAndroid Build Coastguard Worker // Paths to DEX files containing API stubs provided by other parts of the
1083*795d594fSAndroid Build Coastguard Worker // boot class path which the DEX files in boot_dex_paths depend.
1084*795d594fSAndroid Build Coastguard Worker std::vector<std::string> dependency_stub_dex_paths_;
1085*795d594fSAndroid Build Coastguard Worker
1086*795d594fSAndroid Build Coastguard Worker // Output paths where modified DEX files should be written.
1087*795d594fSAndroid Build Coastguard Worker std::vector<std::string> output_dex_paths_;
1088*795d594fSAndroid Build Coastguard Worker
1089*795d594fSAndroid Build Coastguard Worker // Set of public API stub classpaths. Each classpath is formed by a list
1090*795d594fSAndroid Build Coastguard Worker // of DEX/APK files in the order they appear on the classpath.
1091*795d594fSAndroid Build Coastguard Worker std::vector<std::pair<std::string, ApiStubs::Kind>> stub_classpaths_;
1092*795d594fSAndroid Build Coastguard Worker
1093*795d594fSAndroid Build Coastguard Worker // Path to CSV file containing the list of API members and their flags.
1094*795d594fSAndroid Build Coastguard Worker // This could be both an input and output path.
1095*795d594fSAndroid Build Coastguard Worker std::string api_flags_path_;
1096*795d594fSAndroid Build Coastguard Worker
1097*795d594fSAndroid Build Coastguard Worker // Maximum allowable hidden API level that can be encoded into the dex file.
1098*795d594fSAndroid Build Coastguard Worker //
1099*795d594fSAndroid Build Coastguard Worker // By default this returns a GetIntValue() that is guaranteed to be bigger than
1100*795d594fSAndroid Build Coastguard Worker // any valid value returned by GetIntValue().
1101*795d594fSAndroid Build Coastguard Worker ApiList max_hiddenapi_level_;
1102*795d594fSAndroid Build Coastguard Worker
1103*795d594fSAndroid Build Coastguard Worker // Whether the input is only a fragment of the whole bootclasspath and may
1104*795d594fSAndroid Build Coastguard Worker // not include a complete set of classes. That requires the tool to ignore missing
1105*795d594fSAndroid Build Coastguard Worker // classes and members.
1106*795d594fSAndroid Build Coastguard Worker bool fragment_ = false;
1107*795d594fSAndroid Build Coastguard Worker
1108*795d594fSAndroid Build Coastguard Worker // Whether to output all warnings, even when `fragment_` is set.
1109*795d594fSAndroid Build Coastguard Worker bool verbose_ = false;
1110*795d594fSAndroid Build Coastguard Worker };
1111*795d594fSAndroid Build Coastguard Worker
1112*795d594fSAndroid Build Coastguard Worker } // namespace hiddenapi
1113*795d594fSAndroid Build Coastguard Worker } // namespace art
1114*795d594fSAndroid Build Coastguard Worker
main(int argc,char ** argv)1115*795d594fSAndroid Build Coastguard Worker int main(int argc, char** argv) {
1116*795d594fSAndroid Build Coastguard Worker art::hiddenapi::original_argc = argc;
1117*795d594fSAndroid Build Coastguard Worker art::hiddenapi::original_argv = argv;
1118*795d594fSAndroid Build Coastguard Worker android::base::InitLogging(argv);
1119*795d594fSAndroid Build Coastguard Worker art::MemMap::Init();
1120*795d594fSAndroid Build Coastguard Worker art::hiddenapi::HiddenApi().Run(argc, argv);
1121*795d594fSAndroid Build Coastguard Worker return EXIT_SUCCESS;
1122*795d594fSAndroid Build Coastguard Worker }
1123