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   for (const auto& package : table.packages) {
260     ValueHeadlinePrinter headline_printer(package->name, printer);
261     ValueBodyPrinter body_printer(package->name, printer);
262 
263     printer->Print("Package name=");
264     printer->Print(package->name);
265     if (package->id) {
266       printer->Print(StringPrintf(" id=%02x", package->id.value()));
267     }
268     printer->Println();
269 
270     printer->Indent();
271     for (const auto& type : package->types) {
272       printer->Print("type ");
273       printer->Print(to_string(type->type));
274       if (type->id) {
275         printer->Print(StringPrintf(" id=%02x", type->id.value()));
276       }
277       printer->Println(StringPrintf(" entryCount=%zd", type->entries.size()));
278 
279       std::vector<const ResourceEntry*> sorted_entries;
280       for (const auto& entry : type->entries) {
281         auto iter = std::lower_bound(
282             sorted_entries.begin(), sorted_entries.end(), entry.get(),
283             [](const ResourceEntry* a, const ResourceEntry* b) -> bool {
284               if (a->id && b->id) {
285                 return a->id.value() < b->id.value();
286               } else if (a->id) {
287                 return true;
288               } else {
289                 return false;
290               }
291             });
292         sorted_entries.insert(iter, entry.get());
293       }
294 
295       printer->Indent();
296       for (const ResourceEntry* entry : sorted_entries) {
297         const ResourceId id(package->id.value_or_default(0), type->id.value_or_default(0),
298                             entry->id.value_or_default(0));
299 
300         printer->Print("resource ");
301         printer->Print(id.to_string());
302         printer->Print(" ");
303 
304         // Write the name without the package (this is obvious and too verbose).
305         printer->Print(to_string(type->type));
306         printer->Print("/");
307         printer->Print(entry->name);
308 
309         switch (entry->visibility.level) {
310           case Visibility::Level::kPublic:
311             printer->Print(" PUBLIC");
312             break;
313           case Visibility::Level::kPrivate:
314             printer->Print(" _PRIVATE_");
315             break;
316           case Visibility::Level::kUndefined:
317             // Print nothing.
318             break;
319         }
320 
321         if (entry->overlayable_item) {
322           printer->Print(" OVERLAYABLE");
323         }
324 
325         printer->Println();
326 
327         if (options.show_values) {
328           printer->Indent();
329           for (const auto& value : entry->values) {
330             printer->Print("(");
331             printer->Print(value->config.to_string());
332             printer->Print(") ");
333             value->value->Accept(&headline_printer);
334             if (options.show_sources && !value->value->GetSource().path.empty()) {
335               printer->Print(" src=");
336               printer->Print(value->value->GetSource().to_string());
337             }
338             printer->Println();
339             printer->Indent();
340             value->value->Accept(&body_printer);
341             printer->Undent();
342           }
343           printer->Undent();
344         }
345       }
346       printer->Undent();
347     }
348     printer->Undent();
349   }
350 }
351 
GetNodeIndex(const std::vector<ResourceName> & names,const ResourceName & name)352 static size_t GetNodeIndex(const std::vector<ResourceName>& names, const ResourceName& name) {
353   auto iter = std::lower_bound(names.begin(), names.end(), name);
354   CHECK(iter != names.end());
355   CHECK(*iter == name);
356   return std::distance(names.begin(), iter);
357 }
358 
PrintStyleGraph(ResourceTable * table,const ResourceName & target_style)359 void Debug::PrintStyleGraph(ResourceTable* table, const ResourceName& target_style) {
360   std::map<ResourceName, std::set<ResourceName>> graph;
361 
362   std::queue<ResourceName> styles_to_visit;
363   styles_to_visit.push(target_style);
364   for (; !styles_to_visit.empty(); styles_to_visit.pop()) {
365     const ResourceName& style_name = styles_to_visit.front();
366     std::set<ResourceName>& parents = graph[style_name];
367     if (!parents.empty()) {
368       // We've already visited this style.
369       continue;
370     }
371 
372     Maybe<ResourceTable::SearchResult> result = table->FindResource(style_name);
373     if (result) {
374       ResourceEntry* entry = result.value().entry;
375       for (const auto& value : entry->values) {
376         if (Style* style = ValueCast<Style>(value->value.get())) {
377           if (style->parent && style->parent.value().name) {
378             parents.insert(style->parent.value().name.value());
379             styles_to_visit.push(style->parent.value().name.value());
380           }
381         }
382       }
383     }
384   }
385 
386   std::vector<ResourceName> names;
387   for (const auto& entry : graph) {
388     names.push_back(entry.first);
389   }
390 
391   std::cout << "digraph styles {\n";
392   for (const auto& name : names) {
393     std::cout << "  node_" << GetNodeIndex(names, name) << " [label=\"" << name << "\"];\n";
394   }
395 
396   for (const auto& entry : graph) {
397     const ResourceName& style_name = entry.first;
398     size_t style_node_index = GetNodeIndex(names, style_name);
399 
400     for (const auto& parent_name : entry.second) {
401       std::cout << "  node_" << style_node_index << " -> "
402                 << "node_" << GetNodeIndex(names, parent_name) << ";\n";
403     }
404   }
405 
406   std::cout << "}" << std::endl;
407 }
408 
DumpHex(const void * data,size_t len)409 void Debug::DumpHex(const void* data, size_t len) {
410   const uint8_t* d = (const uint8_t*)data;
411   for (size_t i = 0; i < len; i++) {
412     std::cerr << std::hex << std::setfill('0') << std::setw(2) << (uint32_t)d[i] << " ";
413     if (i % 8 == 7) {
414       std::cerr << "\n";
415     }
416   }
417 
418   if (len - 1 % 8 != 7) {
419     std::cerr << std::endl;
420   }
421 }
422 
DumpResStringPool(const android::ResStringPool * pool,text::Printer * printer)423 void Debug::DumpResStringPool(const android::ResStringPool* pool, text::Printer* printer) {
424   using namespace android;
425 
426   if (pool->getError() == NO_INIT) {
427     printer->Print("String pool is unitialized.\n");
428     return;
429   } else if (pool->getError() != NO_ERROR) {
430     printer->Print("String pool is corrupt/invalid.\n");
431     return;
432   }
433 
434   SortedVector<const void*> uniqueStrings;
435   const size_t N = pool->size();
436   for (size_t i=0; i<N; i++) {
437     size_t len;
438     if (pool->isUTF8()) {
439       uniqueStrings.add(pool->string8At(i, &len));
440     } else {
441       uniqueStrings.add(pool->stringAt(i, &len));
442     }
443   }
444 
445   printer->Print(StringPrintf("String pool of %zd unique %s %s strings, %zd entries and %zd styles "
446                               "using %zd bytes:\n", uniqueStrings.size(),
447                               pool->isUTF8() ? "UTF-8" : "UTF-16",
448                               pool->isSorted() ? "sorted" : "non-sorted", N, pool->styleCount(),
449                               pool->bytes()));
450 
451   const size_t NS = pool->size();
452   for (size_t s=0; s<NS; s++) {
453     String8 str = pool->string8ObjectAt(s);
454     printer->Print(StringPrintf("String #%zd : %s\n", s, str.string()));
455   }
456 }
457 
458 namespace {
459 
460 class XmlPrinter : public xml::ConstVisitor {
461  public:
462   using xml::ConstVisitor::Visit;
463 
XmlPrinter(Printer * printer)464   explicit XmlPrinter(Printer* printer) : printer_(printer) {
465   }
466 
Visit(const xml::Element * el)467   void Visit(const xml::Element* el) override {
468     for (const xml::NamespaceDecl& decl : el->namespace_decls) {
469       printer_->Println(StringPrintf("N: %s=%s (line=%zu)", decl.prefix.c_str(), decl.uri.c_str(),
470                                      decl.line_number));
471       printer_->Indent();
472     }
473 
474     printer_->Print("E: ");
475     if (!el->namespace_uri.empty()) {
476       printer_->Print(el->namespace_uri);
477       printer_->Print(":");
478     }
479     printer_->Println(StringPrintf("%s (line=%zu)", el->name.c_str(), el->line_number));
480     printer_->Indent();
481 
482     for (const xml::Attribute& attr : el->attributes) {
483       printer_->Print("A: ");
484       if (!attr.namespace_uri.empty()) {
485         printer_->Print(attr.namespace_uri);
486         printer_->Print(":");
487       }
488       printer_->Print(attr.name);
489 
490       if (attr.compiled_attribute) {
491         printer_->Print("(");
492         printer_->Print(
493             attr.compiled_attribute.value().id.value_or_default(ResourceId(0)).to_string());
494         printer_->Print(")");
495       }
496       printer_->Print("=");
497       if (attr.compiled_value != nullptr) {
498         attr.compiled_value->PrettyPrint(printer_);
499       } else {
500         printer_->Print("\"");
501         printer_->Print(attr.value);
502         printer_->Print("\"");
503       }
504 
505       if (!attr.value.empty()) {
506         printer_->Print(" (Raw: \"");
507         printer_->Print(attr.value);
508         printer_->Print("\")");
509       }
510       printer_->Println();
511     }
512 
513     printer_->Indent();
514     xml::ConstVisitor::Visit(el);
515     printer_->Undent();
516     printer_->Undent();
517 
518     for (size_t i = 0; i < el->namespace_decls.size(); i++) {
519       printer_->Undent();
520     }
521   }
522 
Visit(const xml::Text * text)523   void Visit(const xml::Text* text) override {
524     printer_->Println(StringPrintf("T: '%s'", text->text.c_str()));
525   }
526 
527  private:
528   Printer* printer_;
529 };
530 
531 }  // namespace
532 
DumpXml(const xml::XmlResource & doc,Printer * printer)533 void Debug::DumpXml(const xml::XmlResource& doc, Printer* printer) {
534   XmlPrinter xml_visitor(printer);
535   doc.root->Accept(&xml_visitor);
536 }
537 
538 struct DumpOverlayableEntry {
539   std::string overlayable_section;
540   std::string policy_subsection;
541   std::string resource_name;
542 };
543 
DumpOverlayable(const ResourceTable & table,text::Printer * printer)544 void Debug::DumpOverlayable(const ResourceTable& table, text::Printer* printer) {
545   std::vector<DumpOverlayableEntry> items;
546   for (const auto& package : table.packages) {
547     for (const auto& type : package->types) {
548       for (const auto& entry : type->entries) {
549         if (entry->overlayable_item) {
550           const auto& overlayable_item = entry->overlayable_item.value();
551           const auto overlayable_section = StringPrintf(R"(name="%s" actor="%s")",
552               overlayable_item.overlayable->name.c_str(),
553               overlayable_item.overlayable->actor.c_str());
554           const auto policy_subsection = StringPrintf(R"(policies="%s")",
555               android::idmap2::policy::PoliciesToDebugString(overlayable_item.policies).c_str());
556           const auto value =
557             StringPrintf("%s/%s", to_string(type->type).data(), entry->name.c_str());
558           items.push_back(DumpOverlayableEntry{overlayable_section, policy_subsection, value});
559         }
560       }
561     }
562   }
563 
564   std::sort(items.begin(), items.end(),
565       [](const DumpOverlayableEntry& a, const DumpOverlayableEntry& b) {
566         if (a.overlayable_section != b.overlayable_section) {
567           return a.overlayable_section < b.overlayable_section;
568         }
569         if (a.policy_subsection != b.policy_subsection) {
570           return a.policy_subsection < b.policy_subsection;
571         }
572         return a.resource_name < b.resource_name;
573       });
574 
575   std::string last_overlayable_section;
576   std::string last_policy_subsection;
577   for (const auto& item : items) {
578     if (last_overlayable_section != item.overlayable_section) {
579       printer->Println(item.overlayable_section);
580       last_overlayable_section = item.overlayable_section;
581     }
582     if (last_policy_subsection != item.policy_subsection) {
583       printer->Indent();
584       printer->Println(item.policy_subsection);
585       last_policy_subsection = item.policy_subsection;
586       printer->Undent();
587     }
588     printer->Indent();
589     printer->Indent();
590     printer->Println(item.resource_name);
591     printer->Undent();
592     printer->Undent();
593   }
594 }
595 
596 }  // namespace aapt
597