1 /*
2  * Copyright (C) 2018 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 "idmap2/RawPrintVisitor.h"
18 
19 #include <algorithm>
20 #include <cstdarg>
21 #include <string>
22 #include <utility>
23 
24 #include "android-base/macros.h"
25 #include "android-base/stringprintf.h"
26 #include "idmap2/PolicyUtils.h"
27 #include "idmap2/ResourceUtils.h"
28 #include "idmap2/Result.h"
29 
30 using android::idmap2::policy::PoliciesToDebugString;
31 
32 namespace android::idmap2 {
33 
visit(const Idmap & idmap ATTRIBUTE_UNUSED)34 void RawPrintVisitor::visit(const Idmap& idmap ATTRIBUTE_UNUSED) {
35 }
36 
visit(const IdmapHeader & header)37 void RawPrintVisitor::visit(const IdmapHeader& header) {
38   print(header.GetMagic(), "magic");
39   print(header.GetVersion(), "version");
40   print(header.GetTargetCrc(), "target crc");
41   print(header.GetOverlayCrc(), "overlay crc");
42   print(header.GetFulfilledPolicies(), "fulfilled policies: %s",
43         PoliciesToDebugString(header.GetFulfilledPolicies()).c_str());
44   print(static_cast<uint32_t>(header.GetEnforceOverlayable()), "enforce overlayable");
45   print(header.GetTargetPath(), true /* print_value */, "target path");
46   print(header.GetOverlayPath(), true /* print_value */, "overlay path");
47   print(header.GetOverlayName(), true /* print_value */, "overlay name");
48   print(header.GetDebugInfo(), false /* print_value */, "debug info");
49 
50   if (auto target = TargetResourceContainer::FromPath(header.GetTargetPath())) {
51     target_ = std::move(*target);
52   }
53   if (auto overlay = OverlayResourceContainer::FromPath(header.GetOverlayPath())) {
54     overlay_ = std::move(*overlay);
55   }
56 }
57 
visit(const IdmapData & data ATTRIBUTE_UNUSED)58 void RawPrintVisitor::visit(const IdmapData& data ATTRIBUTE_UNUSED) {
59   for (auto& target_entry : data.GetTargetEntries()) {
60     Result<std::string> target_name(Error(""));
61     if (target_ != nullptr) {
62       target_name = target_->GetResourceName(target_entry.target_id);
63     }
64     if (target_name) {
65       print(target_entry.target_id, "target id: %s", target_name->c_str());
66     } else {
67       print(target_entry.target_id, "target id");
68     }
69 
70     Result<std::string> overlay_name(Error(""));
71     if (overlay_ != nullptr) {
72       overlay_name = overlay_->GetResourceName(target_entry.overlay_id);
73     }
74     if (overlay_name) {
75       print(target_entry.overlay_id, "overlay id: %s", overlay_name->c_str());
76     } else {
77       print(target_entry.overlay_id, "overlay id");
78     }
79   }
80 
81   for (auto& target_entry : data.GetTargetInlineEntries()) {
82     Result<std::string> target_name(Error(""));
83     if (target_ != nullptr) {
84       target_name = target_->GetResourceName(target_entry.target_id);
85     }
86     if (target_name) {
87       print(target_entry.target_id, "target id: %s", target_name->c_str());
88     } else {
89       print(target_entry.target_id, "target id");
90     }
91 
92 
93     pad(sizeof(Res_value::size) + sizeof(Res_value::res0));
94 
95     for (auto& target_entry_value : target_entry.values) {
96       auto value = target_entry_value.second;
97 
98       print(target_entry_value.first.to_string(), false, "config: %s",
99           target_entry_value.first.toString().c_str());
100 
101       print(value.data_type, "type: %s",
102             utils::DataTypeToString(value.data_type).data());
103 
104       Result<std::string> overlay_name(Error(""));
105       if (overlay_ != nullptr &&
106           (value.data_value == Res_value::TYPE_REFERENCE ||
107            value.data_value == Res_value::TYPE_DYNAMIC_REFERENCE)) {
108         overlay_name = overlay_->GetResourceName(value.data_value);
109       }
110 
111       if (overlay_name) {
112         print(value.data_value, "data: %s", overlay_name->c_str());
113       } else {
114         print(value.data_value, "data");
115       }
116     }
117   }
118 
119   for (auto& overlay_entry : data.GetOverlayEntries()) {
120     Result<std::string> overlay_name(Error(""));
121     if (overlay_ != nullptr) {
122       overlay_name = overlay_->GetResourceName(overlay_entry.overlay_id);
123     }
124 
125     if (overlay_name) {
126       print(overlay_entry.overlay_id, "overlay id: %s", overlay_name->c_str());
127     } else {
128       print(overlay_entry.overlay_id, "overlay id");
129     }
130 
131     Result<std::string> target_name(Error(""));
132     if (target_ != nullptr) {
133       target_name = target_->GetResourceName(overlay_entry.target_id);
134     }
135 
136     if (target_name) {
137       print(overlay_entry.target_id, "target id: %s", target_name->c_str());
138     } else {
139       print(overlay_entry.target_id, "target id");
140     }
141   }
142 
143   print(data.GetStringPoolData(), false /* print_value */, "string pool");
144 }
145 
visit(const IdmapData::Header & header)146 void RawPrintVisitor::visit(const IdmapData::Header& header) {
147   print(header.GetTargetEntryCount(), "target entry count");
148   print(header.GetTargetInlineEntryCount(), "target inline entry count");
149   print(header.GetTargetInlineEntryValueCount(), "target inline entry value count");
150   print(header.GetConfigCount(), "config count");
151   print(header.GetOverlayEntryCount(), "overlay entry count");
152   print(header.GetStringPoolIndexOffset(), "string pool index offset");
153 }
154 
155 // NOLINTNEXTLINE(cert-dcl50-cpp)
print(uint8_t value,const char * fmt,...)156 void RawPrintVisitor::print(uint8_t value, const char* fmt, ...) {
157   va_list ap;
158   va_start(ap, fmt);
159   std::string comment;
160   base::StringAppendV(&comment, fmt, ap);
161   va_end(ap);
162 
163   stream_ << base::StringPrintf("%08zx:       %02x", offset_, value) << "  " << comment
164           << '\n';
165   offset_ += sizeof(uint8_t);
166 }
167 
168 // NOLINTNEXTLINE(cert-dcl50-cpp)
print(uint16_t value,const char * fmt,...)169 void RawPrintVisitor::print(uint16_t value, const char* fmt, ...) {
170   va_list ap;
171   va_start(ap, fmt);
172   std::string comment;
173   base::StringAppendV(&comment, fmt, ap);
174   va_end(ap);
175 
176   stream_ << base::StringPrintf("%08zx:     %04x", offset_, value) << "  " << comment << '\n';
177   offset_ += sizeof(uint16_t);
178 }
179 
180 // NOLINTNEXTLINE(cert-dcl50-cpp)
print(uint32_t value,const char * fmt,...)181 void RawPrintVisitor::print(uint32_t value, const char* fmt, ...) {
182   va_list ap;
183   va_start(ap, fmt);
184   std::string comment;
185   base::StringAppendV(&comment, fmt, ap);
186   va_end(ap);
187 
188   stream_ << base::StringPrintf("%08zx: %08x", offset_, value) << "  " << comment << '\n';
189   offset_ += sizeof(uint32_t);
190 }
191 
192 // NOLINTNEXTLINE(cert-dcl50-cpp)
print(const std::string & value,bool print_value,const char * fmt,...)193 void RawPrintVisitor::print(const std::string& value, bool print_value, const char* fmt, ...) {
194   va_list ap;
195   va_start(ap, fmt);
196   std::string comment;
197   base::StringAppendV(&comment, fmt, ap);
198   va_end(ap);
199 
200   stream_ << base::StringPrintf("%08zx: %08x", offset_, (uint32_t)value.size()) << "  " << comment
201           << " size" << '\n';
202   offset_ += sizeof(uint32_t);
203 
204   stream_ << base::StringPrintf("%08zx: ", offset_) << "........  " << comment;
205   offset_ += value.size() + CalculatePadding(value.size());
206 
207   if (print_value) {
208     stream_ << ": " << value;
209   }
210   stream_ << '\n';
211 }
212 
align()213 void RawPrintVisitor::align() {
214   offset_ += CalculatePadding(offset_);
215 }
216 
pad(size_t padding)217 void RawPrintVisitor::pad(size_t padding) {
218   offset_ += padding;
219 }
220 }  // namespace android::idmap2
221