159e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski/* 259e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski * Copyright (C) 2016 The Android Open Source Project 359e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski * 459e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski * Licensed under the Apache License, Version 2.0 (the "License"); 559e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski * you may not use this file except in compliance with the License. 659e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski * You may obtain a copy of the License at 759e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski * 859e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski * http://www.apache.org/licenses/LICENSE-2.0 959e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski * 1059e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski * Unless required by applicable law or agreed to in writing, software 1159e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski * distributed under the License is distributed on an "AS IS" BASIS, 1259e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1359e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski * See the License for the specific language governing permissions and 1459e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski * limitations under the License. 1559e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski */ 1659e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski 17ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski#include <vector> 18ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski 19d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski#include "androidfw/StringPiece.h" 20d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski 2159e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski#include "Debug.h" 2259e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski#include "Diagnostics.h" 2359e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski#include "Flags.h" 2464587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski#include "io/ZipArchive.h" 2559e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski#include "process/IResourceTableConsumer.h" 2659e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski#include "proto/ProtoSerialize.h" 275e8fa3a24835a1ad39f758f630a61c83133eabf8Adam Lesinski#include "unflatten/BinaryResourceParser.h" 2859e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski#include "util/Files.h" 29d5083f6f6b9bc76bbe64052bcec639eee752a321Adam Lesinski 30b791721cd1a6154e5582d824f5d20b2c8b8d5ac5Adam Lesinskiusing ::android::StringPiece; 3159e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski 3259e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinskinamespace aapt { 3359e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski 34b791721cd1a6154e5582d824f5d20b2c8b8d5ac5Adam Lesinskibool DumpCompiledFile(const pb::internal::CompiledFile& pb_file, const void* data, size_t len, 35d0f492db038c6210c1138865d816bfb134376538Adam Lesinski const Source& source, IAaptContext* context) { 36cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::unique_ptr<ResourceFile> file = 37ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski DeserializeCompiledFileFromPb(pb_file, source, context->GetDiagnostics()); 38cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!file) { 39d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context->GetDiagnostics()->Warn(DiagMessage() << "failed to read compiled file"); 40aadf27e1b59fce0e364bb61c4add7e0b0692dba6Pierre Lecesne return false; 41cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 42cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 43cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::cout << "Resource: " << file->name << "\n" 44cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski << "Config: " << file->config << "\n" 45cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski << "Source: " << file->source << "\n"; 46aadf27e1b59fce0e364bb61c4add7e0b0692dba6Pierre Lecesne return true; 4759e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski} 4859e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski 49aadf27e1b59fce0e364bb61c4add7e0b0692dba6Pierre Lecesnebool TryDumpFile(IAaptContext* context, const std::string& file_path) { 50cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::unique_ptr<ResourceTable> table; 51cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 52cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski std::string err; 53d0f492db038c6210c1138865d816bfb134376538Adam Lesinski std::unique_ptr<io::ZipFileCollection> zip = io::ZipFileCollection::Create(file_path, &err); 54cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (zip) { 55ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski io::IFile* file = zip->FindFile("resources.arsc.flat"); 56cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (file) { 57ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<io::IData> data = file->OpenAsData(); 58cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!data) { 59d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context->GetDiagnostics()->Error(DiagMessage(file_path) 60d0f492db038c6210c1138865d816bfb134376538Adam Lesinski << "failed to open resources.arsc.flat"); 61aadf27e1b59fce0e364bb61c4add7e0b0692dba6Pierre Lecesne return false; 62cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 6364587af8179affd38ee26543b748f2d63b7f67bbAdam Lesinski 64ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski pb::ResourceTable pb_table; 65ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!pb_table.ParseFromArray(data->data(), data->size())) { 66d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context->GetDiagnostics()->Error(DiagMessage(file_path) << "invalid resources.arsc.flat"); 67aadf27e1b59fce0e364bb61c4add7e0b0692dba6Pierre Lecesne return false; 68cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 69cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 70d0f492db038c6210c1138865d816bfb134376538Adam Lesinski table = DeserializeTableFromPb(pb_table, Source(file_path), context->GetDiagnostics()); 71cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!table) { 72aadf27e1b59fce0e364bb61c4add7e0b0692dba6Pierre Lecesne return false; 73cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 7459e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski } 7559e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski 765e8fa3a24835a1ad39f758f630a61c83133eabf8Adam Lesinski if (!table) { 77ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski file = zip->FindFile("resources.arsc"); 78cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (file) { 79ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski std::unique_ptr<io::IData> data = file->OpenAsData(); 80cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!data) { 81ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context->GetDiagnostics()->Error(DiagMessage(file_path) 82cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski << "failed to open resources.arsc"); 83aadf27e1b59fce0e364bb61c4add7e0b0692dba6Pierre Lecesne return false; 845e8fa3a24835a1ad39f758f630a61c83133eabf8Adam Lesinski } 8559e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski 86cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski table = util::make_unique<ResourceTable>(); 87d0f492db038c6210c1138865d816bfb134376538Adam Lesinski BinaryResourceParser parser(context, table.get(), Source(file_path), data->data(), 88d0f492db038c6210c1138865d816bfb134376538Adam Lesinski data->size()); 89ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!parser.Parse()) { 90aadf27e1b59fce0e364bb61c4add7e0b0692dba6Pierre Lecesne return false; 91cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 92cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 93cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 94cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 95cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 96cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!table) { 97ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Maybe<android::FileMap> file = file::MmapPath(file_path, &err); 98cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!file) { 99ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context->GetDiagnostics()->Error(DiagMessage(file_path) << err); 100aadf27e1b59fce0e364bb61c4add7e0b0692dba6Pierre Lecesne return false; 101cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 102cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 103ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski android::FileMap* file_map = &file.value(); 104cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 105cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Try as a compiled table. 106ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski pb::ResourceTable pb_table; 107d0f492db038c6210c1138865d816bfb134376538Adam Lesinski if (pb_table.ParseFromArray(file_map->getDataPtr(), file_map->getDataLength())) { 108d0f492db038c6210c1138865d816bfb134376538Adam Lesinski table = DeserializeTableFromPb(pb_table, Source(file_path), context->GetDiagnostics()); 109cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 1105e8fa3a24835a1ad39f758f630a61c83133eabf8Adam Lesinski 111cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!table) { 112cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski // Try as a compiled file. 113d0f492db038c6210c1138865d816bfb134376538Adam Lesinski CompiledFileInputStream input(file_map->getDataPtr(), file_map->getDataLength()); 114cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 115ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski uint32_t num_files = 0; 116ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!input.ReadLittleEndian32(&num_files)) { 117aadf27e1b59fce0e364bb61c4add7e0b0692dba6Pierre Lecesne return false; 118cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 119cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 120ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (uint32_t i = 0; i < num_files; i++) { 121b791721cd1a6154e5582d824f5d20b2c8b8d5ac5Adam Lesinski pb::internal::CompiledFile compiled_file; 122ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!input.ReadCompiledFile(&compiled_file)) { 123d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context->GetDiagnostics()->Warn(DiagMessage() << "failed to read compiled file"); 124aadf27e1b59fce0e364bb61c4add7e0b0692dba6Pierre Lecesne return false; 1255e8fa3a24835a1ad39f758f630a61c83133eabf8Adam Lesinski } 1265e8fa3a24835a1ad39f758f630a61c83133eabf8Adam Lesinski 127cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski uint64_t offset, len; 128cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (!input.ReadDataMetaData(&offset, &len)) { 129d0f492db038c6210c1138865d816bfb134376538Adam Lesinski context->GetDiagnostics()->Warn(DiagMessage() << "failed to read meta data"); 130aadf27e1b59fce0e364bb61c4add7e0b0692dba6Pierre Lecesne return false; 1315e8fa3a24835a1ad39f758f630a61c83133eabf8Adam Lesinski } 13259e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski 133d0f492db038c6210c1138865d816bfb134376538Adam Lesinski const void* data = static_cast<const uint8_t*>(file_map->getDataPtr()) + offset; 134aadf27e1b59fce0e364bb61c4add7e0b0692dba6Pierre Lecesne if (!DumpCompiledFile(compiled_file, data, len, Source(file_path), context)) { 135aadf27e1b59fce0e364bb61c4add7e0b0692dba6Pierre Lecesne return false; 136aadf27e1b59fce0e364bb61c4add7e0b0692dba6Pierre Lecesne } 137cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 13859e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski } 139cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 140cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 141cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski if (table) { 142ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski DebugPrintTableOptions options; 143ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski options.show_sources = true; 144ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski Debug::PrintTable(table.get(), options); 145cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 146aadf27e1b59fce0e364bb61c4add7e0b0692dba6Pierre Lecesne 147aadf27e1b59fce0e364bb61c4add7e0b0692dba6Pierre Lecesne return true; 14859e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski} 14959e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski 15059e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinskiclass DumpContext : public IAaptContext { 151cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski public: 152b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski PackageType GetPackageType() override { 153b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski // Doesn't matter. 154b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski return PackageType::kApp; 155b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski } 156b522f04bc2a581e2877bef4a44ac00b827f879edAdam Lesinski 157d0f492db038c6210c1138865d816bfb134376538Adam Lesinski IDiagnostics* GetDiagnostics() override { 158d0f492db038c6210c1138865d816bfb134376538Adam Lesinski return &diagnostics_; 159d0f492db038c6210c1138865d816bfb134376538Adam Lesinski } 16059e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski 161ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski NameMangler* GetNameMangler() override { 162cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski abort(); 163cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return nullptr; 164cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 16559e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski 166ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski const std::string& GetCompilationPackage() override { 167cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski static std::string empty; 168cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return empty; 169cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 17059e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski 171d0f492db038c6210c1138865d816bfb134376538Adam Lesinski uint8_t GetPackageId() override { 172d0f492db038c6210c1138865d816bfb134376538Adam Lesinski return 0; 173d0f492db038c6210c1138865d816bfb134376538Adam Lesinski } 17459e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski 175ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski SymbolTable* GetExternalSymbols() override { 176cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski abort(); 177cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return nullptr; 178cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 17959e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski 180d0f492db038c6210c1138865d816bfb134376538Adam Lesinski bool IsVerbose() override { 181d0f492db038c6210c1138865d816bfb134376538Adam Lesinski return verbose_; 182d0f492db038c6210c1138865d816bfb134376538Adam Lesinski } 183355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 184d0f492db038c6210c1138865d816bfb134376538Adam Lesinski void SetVerbose(bool val) { 185d0f492db038c6210c1138865d816bfb134376538Adam Lesinski verbose_ = val; 186d0f492db038c6210c1138865d816bfb134376538Adam Lesinski } 187355f285ffd000f6cfe76680eb22d010546d124bbAdam Lesinski 188d0f492db038c6210c1138865d816bfb134376538Adam Lesinski int GetMinSdkVersion() override { 189d0f492db038c6210c1138865d816bfb134376538Adam Lesinski return 0; 190d0f492db038c6210c1138865d816bfb134376538Adam Lesinski } 191fb6312fe93a8544e6a95d1c619c8cea3940cbe1aAdam Lesinski 192cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski private: 193ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski StdErrDiagnostics diagnostics_; 194ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski bool verbose_ = false; 19559e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski}; 19659e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski 19759e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski/** 19859e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski * Entry point for dump command. 19959e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski */ 200ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinskiint Dump(const std::vector<StringPiece>& args) { 201cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski bool verbose = false; 202d0f492db038c6210c1138865d816bfb134376538Adam Lesinski Flags flags = Flags().OptionalSwitch("-v", "increase verbosity of output", &verbose); 203ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski if (!flags.Parse("aapt2 dump", args, &std::cerr)) { 204cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 1; 205cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 206cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 207cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski DumpContext context; 208ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski context.SetVerbose(verbose); 209cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski 210ce5e56e243d262a9b65459c3bd0bb9eaadd40628Adam Lesinski for (const std::string& arg : flags.GetArgs()) { 211aadf27e1b59fce0e364bb61c4add7e0b0692dba6Pierre Lecesne if (!TryDumpFile(&context, arg)) { 212aadf27e1b59fce0e364bb61c4add7e0b0692dba6Pierre Lecesne return 1; 213aadf27e1b59fce0e364bb61c4add7e0b0692dba6Pierre Lecesne } 214cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski } 215aadf27e1b59fce0e364bb61c4add7e0b0692dba6Pierre Lecesne 216cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski return 0; 21759e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski} 21859e04c6f92da584b322c87072f18e6cab4de4c60Adam Lesinski 219cacb28f2d60858106e2819cc7d95a65e8bda890bAdam Lesinski} // namespace aapt 220