1 /*
2  * Copyright (C) 2015 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 
19 #include <algorithm>
20 #include <map>
21 #include <memory>
22 #include <queue>
23 #include <set>
24 #include <vector>
25 
26 #include "android-base/logging.h"
27 #include "android-base/stringprintf.h"
28 
29 #include "ResourceTable.h"
30 #include "ResourceValues.h"
31 #include "ValueVisitor.h"
32 #include "text/Printer.h"
33 #include "util/Util.h"
34 
35 #include "idmap2/Policies.h"
36 
37 using ::aapt::text::Printer;
38 using ::android::StringPiece;
39 using ::android::base::StringPrintf;
40 
41 using android::idmap2::policy::kPolicyStringToFlag;
42 
43 using PolicyFlags = android::ResTable_overlayable_policy_header::PolicyFlags;
44 
45 namespace aapt {
46 
47 namespace {
48 
49 class ValueHeadlinePrinter : public ConstValueVisitor {
50  public:
51   using ConstValueVisitor::Visit;
52 
ValueHeadlinePrinter(const std::string & package,Printer * printer)53   explicit ValueHeadlinePrinter(const std::string& package, Printer* printer)
54       : package_(package), printer_(printer) {
55   }
56 
Visit(const Attribute * attr)57   void Visit(const Attribute* attr) override {
58     printer_->Print("(attr) type=");
59     printer_->Print(attr->MaskString());
60     if (!attr->symbols.empty()) {
61       printer_->Print(StringPrintf(" size=%zd", attr->symbols.size()));
62     }
63   }
64 
Visit(const Style * style)65   void Visit(const Style* style) override {
66     printer_->Print(StringPrintf("(style) size=%zd", style->entries.size()));
67     if (style->parent) {
68       printer_->Print(" parent=");
69 
70       const Reference& parent_ref = style->parent.value();
71       if (parent_ref.name) {
72         if (parent_ref.private_reference) {
73           printer_->Print("*");
74         }
75 
76         const ResourceName& parent_name = parent_ref.name.value();
77         if (package_ != parent_name.package) {
78           printer_->Print(parent_name.package);
79           printer_->Print(":");
80         }
81         printer_->Print(to_string(parent_name.type));
82         printer_->Print("/");
83         printer_->Print(parent_name.entry);
84         if (parent_ref.id) {
85           printer_->Print(" (");
86           printer_->Print(parent_ref.id.value().to_string());
87           printer_->Print(")");
88         }
89       } else if (parent_ref.id) {
90         printer_->Print(parent_ref.id.value().to_string());
91       } else {
92         printer_->Print("???");
93       }
94     }
95   }
96 
Visit(const Array * array)97   void Visit(const Array* array) override {
98     printer_->Print(StringPrintf("(array) size=%zd", array->elements.size()));
99   }
100 
Visit(const Plural * plural)101   void Visit(const Plural* plural) override {
102     size_t count = std::count_if(plural->values.begin(), plural->values.end(),
103                                  [](const std::unique_ptr<Item>& v) { return v != nullptr; });
104     printer_->Print(StringPrintf("(plurals) size=%zd", count));
105   }
106 
Visit(const Styleable * styleable)107   void Visit(const Styleable* styleable) override {
108     printer_->Println(StringPrintf("(styleable) size=%zd", styleable->entries.size()));
109   }
110 
VisitItem(const Item * item)111   void VisitItem(const Item* item) override {
112     // Pretty much guaranteed to be one line.
113     if (const Reference* ref = ValueCast<Reference>(item)) {
114       // Special case Reference so that we can print local resources without a package name.
115       ref->PrettyPrint(package_, printer_);
116     } else {
117       item->PrettyPrint(printer_);
118     }
119   }
120 
121  private:
122   std::string package_;
123   Printer* printer_;
124 };
125 
126 class ValueBodyPrinter : public ConstValueVisitor {
127  public:
128   using ConstValueVisitor::Visit;
129 
ValueBodyPrinter(const std::string & package,Printer * printer)130   explicit ValueBodyPrinter(const std::string& package, Printer* printer)
131       : package_(package), printer_(printer) {
132   }
133 
Visit(const Attribute * attr)134   void Visit(const Attribute* attr) override {
135     constexpr uint32_t kMask = android::ResTable_map::TYPE_ENUM | android::ResTable_map::TYPE_FLAGS;
136     if (attr->type_mask & kMask) {
137       for (const auto& symbol : attr->symbols) {
138         if (symbol.symbol.name) {
139           printer_->Print(symbol.symbol.name.value().entry);
140 
141           if (symbol.symbol.id) {
142             printer_->Print("(");
143             printer_->Print(symbol.symbol.id.value().to_string());
144             printer_->Print(")");
145           }
146         } else if (symbol.symbol.id) {
147           printer_->Print(symbol.symbol.id.value().to_string());
148         } else {
149           printer_->Print("???");
150         }
151 
152         printer_->Println(StringPrintf("=0x%08x", symbol.value));
153       }
154     }
155   }
156 
Visit(const Style * style)157   void Visit(const Style* style) override {
158     for (const auto& entry : style->entries) {
159       if (entry.key.name) {
160         const ResourceName& name = entry.key.name.value();
161         if (!name.package.empty() && name.package != package_) {
162           printer_->Print(name.package);
163           printer_->Print(":");
164         }
165         printer_->Print(name.entry);
166 
167         if (entry.key.id) {
168           printer_->Print("(");
169           printer_->Print(entry.key.id.value().to_string());
170           printer_->Print(")");
171         }
172       } else if (entry.key.id) {
173         printer_->Print(entry.key.id.value().to_string());
174       } else {
175         printer_->Print("???");
176       }
177 
178       printer_->Print("=");
179       PrintItem(*entry.value);
180       printer_->Println();
181     }
182   }
183 
Visit(const Array * array)184   void Visit(const Array* array) override {
185     const size_t count = array->elements.size();
186     printer_->Print("[");
187     for (size_t i = 0u; i < count; i++) {
188       if (i != 0u && i % 4u == 0u) {
189         printer_->Println();
190         printer_->Print(" ");
191       }
192       PrintItem(*array->elements[i]);
193       if (i != count - 1) {
194         printer_->Print(", ");
195       }
196     }
197     printer_->Println("]");
198   }
199 
Visit(const Plural * plural)200   void Visit(const Plural* plural) override {
201     constexpr std::array<const char*, Plural::Count> kPluralNames = {
202         {"zero", "one", "two", "few", "many", "other"}};
203 
204     for (size_t i = 0; i < Plural::Count; i++) {
205       if (plural->values[i] != nullptr) {
206         printer_->Print(StringPrintf("%s=", kPluralNames[i]));
207         PrintItem(*plural->values[i]);
208         printer_->Println();
209       }
210     }
211   }
212 
Visit(const Styleable * styleable)213   void Visit(const Styleable* styleable) override {
214     for (const auto& attr : styleable->entries) {
215       if (attr.name) {
216         const ResourceName& name = attr.name.value();
217         if (!name.package.empty() && name.package != package_) {
218           printer_->Print(name.package);
219           printer_->Print(":");
220         }
221         printer_->Print(name.entry);
222 
223         if (attr.id) {
224           printer_->Print("(");
225           printer_->Print(attr.id.value().to_string());
226           printer_->Print(")");
227         }
228       }
229 
230       if (attr.id) {
231         printer_->Print(attr.id.value().to_string());
232       }
233       printer_->Println();
234     }
235   }
236 
VisitItem(const Item * item)237   void VisitItem(const Item* item) override {
238     // Intentionally left empty, we already printed the Items.
239   }
240 
241  private:
PrintItem(const Item & item)242   void PrintItem(const Item& item) {
243     if (const Reference* ref = ValueCast<Reference>(&item)) {
244       // Special case Reference so that we can print local resources without a package name.
245       ref->PrettyPrint(package_, printer_);
246     } else {
247       item.PrettyPrint(printer_);
248     }
249   }
250 
251   std::string package_;
252   Printer* printer_;
253 };
254 
255 }  // namespace
256 
PrintTable(const ResourceTable & table,const DebugPrintTableOptions & options,Printer * printer)257 void Debug::PrintTable(const ResourceTable& table, const DebugPrintTableOptions& options,
258                        Printer* printer) {
259   const auto table_view = table.GetPartitionedView();
260   for (const auto& package : table_view.packages) {
261     ValueHeadlinePrinter headline_printer(package.name, printer);
262     ValueBodyPrinter body_printer(package.name, printer);
263 
264     printer->Print("Package name=");
265     printer->Print(package.name);
266     if (package.id) {
267       printer->Print(StringPrintf(" id=%02x", package.id.value()));
268     }
269     printer->Println();
270 
271     printer->Indent();
272     for (const auto& type : package.types) {
273       printer->Print("type ");
274       printer->Print(to_string(type.type));
275       if (type.id) {
276         printer->Print(StringPrintf(" id=%02x", type.id.value()));
277       }
278       printer->Println(StringPrintf(" entryCount=%zd", type.entries.size()));
279 
280       printer->Indent();
281       for (const ResourceTableEntryView& entry : type.entries) {
282         printer->Print("resource ");
283         printer->Print(ResourceId(package.id.value_or_default(0), type.id.value_or_default(0),
284                                   entry.id.value_or_default(0))
285                            .to_string());
286         printer->Print(" ");
287 
288         // Write the name without the package (this is obvious and too verbose).
289         printer->Print(to_string(type.type));
290         printer->Print("/");
291         printer->Print(entry.name);
292 
293         switch (entry.visibility.level) {
294           case Visibility::Level::kPublic:
295             printer->Print(" PUBLIC");
296             break;
297           case Visibility::Level::kPrivate:
298             printer->Print(" _PRIVATE_");
299             break;
300           case Visibility::Level::kUndefined:
301             // Print nothing.
302             break;
303         }
304 
305         if (entry.visibility.staged_api) {
306           printer->Print(" STAGED");
307         }
308 
309         if (entry.overlayable_item) {
310           printer->Print(" OVERLAYABLE");
311         }
312 
313         if (entry.staged_id) {
314           printer->Print(" STAGED_ID=");
315           printer->Print(entry.staged_id.value().id.to_string());
316         }
317 
318         printer->Println();
319 
320         if (options.show_values) {
321           printer->Indent();
322           for (const auto& value : entry.values) {
323             printer->Print("(");
324             printer->Print(value->config.to_string());
325             printer->Print(") ");
326             value->value->Accept(&headline_printer);
327             if (options.show_sources && !value->value->GetSource().path.empty()) {
328               printer->Print(" src=");
329               printer->Print(value->value->GetSource().to_string());
330             }
331             printer->Println();
332             printer->Indent();
333             value->value->Accept(&body_printer);
334             printer->Undent();
335           }
336           printer->Undent();
337         }
338       }
339       printer->Undent();
340     }
341     printer->Undent();
342   }
343 }
344 
GetNodeIndex(const std::vector<ResourceName> & names,const ResourceName & name)345 static size_t GetNodeIndex(const std::vector<ResourceName>& names, const ResourceName& name) {
346   auto iter = std::lower_bound(names.begin(), names.end(), name);
347   CHECK(iter != names.end());
348   CHECK(*iter == name);
349   return std::distance(names.begin(), iter);
350 }
351 
PrintStyleGraph(ResourceTable * table,const ResourceName & target_style)352 void Debug::PrintStyleGraph(ResourceTable* table, const ResourceName& target_style) {
353   std::map<ResourceName, std::set<ResourceName>> graph;
354 
355   std::queue<ResourceName> styles_to_visit;
356   styles_to_visit.push(target_style);
357   for (; !styles_to_visit.empty(); styles_to_visit.pop()) {
358     const ResourceName& style_name = styles_to_visit.front();
359     std::set<ResourceName>& parents = graph[style_name];
360     if (!parents.empty()) {
361       // We've already visited this style.
362       continue;
363     }
364 
365     Maybe<ResourceTable::SearchResult> result = table->FindResource(style_name);
366     if (result) {
367       ResourceEntry* entry = result.value().entry;
368       for (const auto& value : entry->values) {
369         if (Style* style = ValueCast<Style>(value->value.get())) {
370           if (style->parent && style->parent.value().name) {
371             parents.insert(style->parent.value().name.value());
372             styles_to_visit.push(style->parent.value().name.value());
373           }
374         }
375       }
376     }
377   }
378 
379   std::vector<ResourceName> names;
380   for (const auto& entry : graph) {
381     names.push_back(entry.first);
382   }
383 
384   std::cout << "digraph styles {\n";
385   for (const auto& name : names) {
386     std::cout << "  node_" << GetNodeIndex(names, name) << " [label=\"" << name << "\"];\n";
387   }
388 
389   for (const auto& entry : graph) {
390     const ResourceName& style_name = entry.first;
391     size_t style_node_index = GetNodeIndex(names, style_name);
392 
393     for (const auto& parent_name : entry.second) {
394       std::cout << "  node_" << style_node_index << " -> "
395                 << "node_" << GetNodeIndex(names, parent_name) << ";\n";
396     }
397   }
398 
399   std::cout << "}" << std::endl;
400 }
401 
DumpHex(const void * data,size_t len)402 void Debug::DumpHex(const void* data, size_t len) {
403   const uint8_t* d = (const uint8_t*)data;
404   for (size_t i = 0; i < len; i++) {
405     std::cerr << std::hex << std::setfill('0') << std::setw(2) << (uint32_t)d[i] << " ";
406     if (i % 8 == 7) {
407       std::cerr << "\n";
408     }
409   }
410 
411   if (len - 1 % 8 != 7) {
412     std::cerr << std::endl;
413   }
414 }
415 
DumpResStringPool(const android::ResStringPool * pool,text::Printer * printer)416 void Debug::DumpResStringPool(const android::ResStringPool* pool, text::Printer* printer) {
417   using namespace android;
418 
419   if (pool->getError() == NO_INIT) {
420     printer->Print("String pool is unitialized.\n");
421     return;
422   } else if (pool->getError() != NO_ERROR) {
423     printer->Print("String pool is corrupt/invalid.\n");
424     return;
425   }
426 
427   SortedVector<const void*> uniqueStrings;
428   const size_t N = pool->size();
429   for (size_t i=0; i<N; i++) {
430     size_t len;
431     if (pool->isUTF8()) {
432       uniqueStrings.add(UnpackOptionalString(pool->string8At(i), &len));
433     } else {
434       uniqueStrings.add(UnpackOptionalString(pool->stringAt(i), &len));
435     }
436   }
437 
438   printer->Print(StringPrintf("String pool of %zd unique %s %s strings, %zd entries and %zd styles "
439                               "using %zd bytes:\n", uniqueStrings.size(),
440                               pool->isUTF8() ? "UTF-8" : "UTF-16",
441                               pool->isSorted() ? "sorted" : "non-sorted", N, pool->styleCount(),
442                               pool->bytes()));
443 
444   const size_t NS = pool->size();
445   for (size_t s=0; s<NS; s++) {
446     auto str = pool->string8ObjectAt(s);
447     printer->Print(StringPrintf("String #%zd : %s\n", s, str.has_value() ? str->string() : ""));
448   }
449 }
450 
451 namespace {
452 
453 class XmlPrinter : public xml::ConstVisitor {
454  public:
455   using xml::ConstVisitor::Visit;
456 
XmlPrinter(Printer * printer)457   explicit XmlPrinter(Printer* printer) : printer_(printer) {
458   }
459 
Visit(const xml::Element * el)460   void Visit(const xml::Element* el) override {
461     for (const xml::NamespaceDecl& decl : el->namespace_decls) {
462       printer_->Println(StringPrintf("N: %s=%s (line=%zu)", decl.prefix.c_str(), decl.uri.c_str(),
463                                      decl.line_number));
464       printer_->Indent();
465     }
466 
467     printer_->Print("E: ");
468     if (!el->namespace_uri.empty()) {
469       printer_->Print(el->namespace_uri);
470       printer_->Print(":");
471     }
472     printer_->Println(StringPrintf("%s (line=%zu)", el->name.c_str(), el->line_number));
473     printer_->Indent();
474 
475     for (const xml::Attribute& attr : el->attributes) {
476       printer_->Print("A: ");
477       if (!attr.namespace_uri.empty()) {
478         printer_->Print(attr.namespace_uri);
479         printer_->Print(":");
480       }
481       printer_->Print(attr.name);
482 
483       if (attr.compiled_attribute) {
484         printer_->Print("(");
485         printer_->Print(
486             attr.compiled_attribute.value().id.value_or_default(ResourceId(0)).to_string());
487         printer_->Print(")");
488       }
489       printer_->Print("=");
490       if (attr.compiled_value != nullptr) {
491         attr.compiled_value->PrettyPrint(printer_);
492       } else {
493         printer_->Print("\"");
494         printer_->Print(attr.value);
495         printer_->Print("\"");
496       }
497 
498       if (!attr.value.empty()) {
499         printer_->Print(" (Raw: \"");
500         printer_->Print(attr.value);
501         printer_->Print("\")");
502       }
503       printer_->Println();
504     }
505 
506     printer_->Indent();
507     xml::ConstVisitor::Visit(el);
508     printer_->Undent();
509     printer_->Undent();
510 
511     for (size_t i = 0; i < el->namespace_decls.size(); i++) {
512       printer_->Undent();
513     }
514   }
515 
Visit(const xml::Text * text)516   void Visit(const xml::Text* text) override {
517     printer_->Println(StringPrintf("T: '%s'", text->text.c_str()));
518   }
519 
520  private:
521   Printer* printer_;
522 };
523 
524 }  // namespace
525 
DumpXml(const xml::XmlResource & doc,Printer * printer)526 void Debug::DumpXml(const xml::XmlResource& doc, Printer* printer) {
527   XmlPrinter xml_visitor(printer);
528   doc.root->Accept(&xml_visitor);
529 }
530 
531 struct DumpOverlayableEntry {
532   std::string overlayable_section;
533   std::string policy_subsection;
534   std::string resource_name;
535 };
536 
DumpOverlayable(const ResourceTable & table,text::Printer * printer)537 void Debug::DumpOverlayable(const ResourceTable& table, text::Printer* printer) {
538   std::vector<DumpOverlayableEntry> items;
539   for (const auto& package : table.packages) {
540     for (const auto& type : package->types) {
541       for (const auto& entry : type->entries) {
542         if (entry->overlayable_item) {
543           const auto& overlayable_item = entry->overlayable_item.value();
544           const auto overlayable_section = StringPrintf(R"(name="%s" actor="%s")",
545               overlayable_item.overlayable->name.c_str(),
546               overlayable_item.overlayable->actor.c_str());
547           const auto policy_subsection = StringPrintf(R"(policies="%s")",
548               android::idmap2::policy::PoliciesToDebugString(overlayable_item.policies).c_str());
549           const auto value =
550             StringPrintf("%s/%s", to_string(type->type).data(), entry->name.c_str());
551           items.push_back(DumpOverlayableEntry{overlayable_section, policy_subsection, value});
552         }
553       }
554     }
555   }
556 
557   std::sort(items.begin(), items.end(),
558       [](const DumpOverlayableEntry& a, const DumpOverlayableEntry& b) {
559         if (a.overlayable_section != b.overlayable_section) {
560           return a.overlayable_section < b.overlayable_section;
561         }
562         if (a.policy_subsection != b.policy_subsection) {
563           return a.policy_subsection < b.policy_subsection;
564         }
565         return a.resource_name < b.resource_name;
566       });
567 
568   std::string last_overlayable_section;
569   std::string last_policy_subsection;
570   for (const auto& item : items) {
571     if (last_overlayable_section != item.overlayable_section) {
572       printer->Println(item.overlayable_section);
573       last_overlayable_section = item.overlayable_section;
574     }
575     if (last_policy_subsection != item.policy_subsection) {
576       printer->Indent();
577       printer->Println(item.policy_subsection);
578       last_policy_subsection = item.policy_subsection;
579       printer->Undent();
580     }
581     printer->Indent();
582     printer->Indent();
583     printer->Println(item.resource_name);
584     printer->Undent();
585     printer->Undent();
586   }
587 }
588 
589 }  // namespace aapt
590