blob: f61ec945a1c1dbcd6c233e047be95671633313c2 [file] [log] [blame]
Adam Lesinski59e04c62016-02-04 15:59:23 -08001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "Debug.h"
18#include "Diagnostics.h"
19#include "Flags.h"
Adam Lesinski64587af2016-02-18 18:33:06 -080020#include "io/ZipArchive.h"
Adam Lesinski59e04c62016-02-04 15:59:23 -080021#include "process/IResourceTableConsumer.h"
22#include "proto/ProtoSerialize.h"
Adam Lesinski5e8fa3a2016-06-27 16:21:42 -070023#include "unflatten/BinaryResourceParser.h"
Adam Lesinski59e04c62016-02-04 15:59:23 -080024#include "util/Files.h"
25#include "util/StringPiece.h"
26
27#include <vector>
28
29namespace aapt {
30
31//struct DumpOptions {
32//
33//};
34
35void dumpCompiledFile(const pb::CompiledFile& pbFile, const void* data, size_t len,
36 const Source& source, IAaptContext* context) {
37 std::unique_ptr<ResourceFile> file = deserializeCompiledFileFromPb(pbFile, source,
38 context->getDiagnostics());
39 if (!file) {
Adam Lesinski5eeaadd2016-08-25 12:26:56 -070040 context->getDiagnostics()->warn(DiagMessage() << "failed to read compiled file");
Adam Lesinski59e04c62016-02-04 15:59:23 -080041 return;
42 }
43
44 std::cout << "Resource: " << file->name << "\n"
45 << "Config: " << file->config << "\n"
46 << "Source: " << file->source << "\n";
47}
48
Adam Lesinski59e04c62016-02-04 15:59:23 -080049void tryDumpFile(IAaptContext* context, const std::string& filePath) {
Adam Lesinski5e8fa3a2016-06-27 16:21:42 -070050 std::unique_ptr<ResourceTable> table;
51
Adam Lesinski59e04c62016-02-04 15:59:23 -080052 std::string err;
Adam Lesinski64587af2016-02-18 18:33:06 -080053 std::unique_ptr<io::ZipFileCollection> zip = io::ZipFileCollection::create(filePath, &err);
54 if (zip) {
55 io::IFile* file = zip->findFile("resources.arsc.flat");
56 if (file) {
57 std::unique_ptr<io::IData> data = file->openAsData();
58 if (!data) {
59 context->getDiagnostics()->error(DiagMessage(filePath)
60 << "failed to open resources.arsc.flat");
61 return;
62 }
63
64 pb::ResourceTable pbTable;
65 if (!pbTable.ParseFromArray(data->data(), data->size())) {
66 context->getDiagnostics()->error(DiagMessage(filePath)
67 << "invalid resources.arsc.flat");
68 return;
69 }
70
Adam Lesinski5e8fa3a2016-06-27 16:21:42 -070071 table = deserializeTableFromPb(
Adam Lesinski64587af2016-02-18 18:33:06 -080072 pbTable, Source(filePath), context->getDiagnostics());
Adam Lesinski5e8fa3a2016-06-27 16:21:42 -070073 if (!table) {
74 return;
Adam Lesinski64587af2016-02-18 18:33:06 -080075 }
76 }
Adam Lesinski5e8fa3a2016-06-27 16:21:42 -070077
78 if (!table) {
79 file = zip->findFile("resources.arsc");
80 if (file) {
81 std::unique_ptr<io::IData> data = file->openAsData();
82 if (!data) {
83 context->getDiagnostics()->error(DiagMessage(filePath)
84 << "failed to open resources.arsc");
85 return;
86 }
87
88 table = util::make_unique<ResourceTable>();
89 BinaryResourceParser parser(context, table.get(), Source(filePath),
90 data->data(), data->size());
91 if (!parser.parse()) {
92 return;
93 }
94 }
95 }
Adam Lesinski64587af2016-02-18 18:33:06 -080096 }
97
Adam Lesinski5e8fa3a2016-06-27 16:21:42 -070098 if (!table) {
99 Maybe<android::FileMap> file = file::mmapPath(filePath, &err);
100 if (!file) {
101 context->getDiagnostics()->error(DiagMessage(filePath) << err);
102 return;
103 }
104
105 android::FileMap* fileMap = &file.value();
106
107 // Try as a compiled table.
108 pb::ResourceTable pbTable;
109 if (pbTable.ParseFromArray(fileMap->getDataPtr(), fileMap->getDataLength())) {
110 table = deserializeTableFromPb(pbTable, Source(filePath), context->getDiagnostics());
111 }
112
113 if (!table) {
114 // Try as a compiled file.
115 CompiledFileInputStream input(fileMap->getDataPtr(), fileMap->getDataLength());
Adam Lesinski5eeaadd2016-08-25 12:26:56 -0700116
117 uint32_t numFiles = 0;
118 if (!input.ReadLittleEndian32(&numFiles)) {
119 return;
120 }
121
122 for (uint32_t i = 0; i < numFiles; i++) {
123 pb::CompiledFile compiledFile;
124 if (!input.ReadCompiledFile(&compiledFile)) {
125 context->getDiagnostics()->warn(DiagMessage() << "failed to read compiled file");
126 return;
127 }
128
129 uint64_t offset, len;
130 if (!input.ReadDataMetaData(&offset, &len)) {
131 context->getDiagnostics()->warn(DiagMessage() << "failed to read meta data");
132 return;
133 }
134
135 const void* data = static_cast<const uint8_t*>(fileMap->getDataPtr()) + offset;
136 dumpCompiledFile(compiledFile, data, len, Source(filePath), context);
Adam Lesinski5e8fa3a2016-06-27 16:21:42 -0700137 }
138 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800139 }
140
Adam Lesinski5e8fa3a2016-06-27 16:21:42 -0700141 if (table) {
142 DebugPrintTableOptions debugPrintTableOptions;
143 debugPrintTableOptions.showSources = true;
144 Debug::printTable(table.get(), debugPrintTableOptions);
Adam Lesinski59e04c62016-02-04 15:59:23 -0800145 }
146}
147
148class DumpContext : public IAaptContext {
149public:
150 IDiagnostics* getDiagnostics() override {
151 return &mDiagnostics;
152 }
153
154 NameMangler* getNameMangler() override {
155 abort();
156 return nullptr;
157 }
158
Adam Lesinskid0f116b2016-07-08 15:00:32 -0700159 const std::string& getCompilationPackage() override {
160 static std::string empty;
Adam Lesinski64587af2016-02-18 18:33:06 -0800161 return empty;
Adam Lesinski59e04c62016-02-04 15:59:23 -0800162 }
163
164 uint8_t getPackageId() override {
165 return 0;
166 }
167
Adam Lesinski64587af2016-02-18 18:33:06 -0800168 SymbolTable* getExternalSymbols() override {
Adam Lesinski59e04c62016-02-04 15:59:23 -0800169 abort();
170 return nullptr;
171 }
172
Adam Lesinski355f2852016-02-13 20:26:45 -0800173 bool verbose() override {
174 return mVerbose;
175 }
176
177 void setVerbose(bool val) {
178 mVerbose = val;
179 }
180
Adam Lesinskifb6312f2016-06-28 14:40:32 -0700181 int getMinSdkVersion() override {
182 return 0;
183 }
184
Adam Lesinski59e04c62016-02-04 15:59:23 -0800185private:
186 StdErrDiagnostics mDiagnostics;
Adam Lesinski355f2852016-02-13 20:26:45 -0800187 bool mVerbose = false;
Adam Lesinski59e04c62016-02-04 15:59:23 -0800188};
189
190/**
191 * Entry point for dump command.
192 */
193int dump(const std::vector<StringPiece>& args) {
Adam Lesinski355f2852016-02-13 20:26:45 -0800194 bool verbose = false;
195 Flags flags = Flags()
196 .optionalSwitch("-v", "increase verbosity of output", &verbose);
Adam Lesinski59e04c62016-02-04 15:59:23 -0800197 if (!flags.parse("aapt2 dump", args, &std::cerr)) {
198 return 1;
199 }
200
201 DumpContext context;
Adam Lesinski355f2852016-02-13 20:26:45 -0800202 context.setVerbose(verbose);
Adam Lesinski59e04c62016-02-04 15:59:23 -0800203
204 for (const std::string& arg : flags.getArgs()) {
205 tryDumpFile(&context, arg);
206 }
207 return 0;
208}
209
210} // namespace aapt