blob: aec1d0c1b7a9d24690fc52b135306c59d4c310aa [file] [log] [blame]
Jeff Haoec7f1a92017-03-13 16:24:24 -07001/*
2 * Copyright (C) 2017 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 * Implementation file of dex ir verifier.
17 *
18 * Compares two dex files at the IR level, allowing differences in layout, but not in data.
19 */
20
21#include "dex_verify.h"
22
23#include "android-base/stringprintf.h"
24
25namespace art {
26
27using android::base::StringPrintf;
28
29bool VerifyOutputDexFile(dex_ir::Header* orig_header,
30 dex_ir::Header* output_header,
31 std::string* error_msg) {
32 dex_ir::Collections& orig = orig_header->GetCollections();
33 dex_ir::Collections& output = output_header->GetCollections();
34
35 // Compare all id sections.
36 if (!VerifyIds(orig.StringIds(), output.StringIds(), "string ids", error_msg) ||
37 !VerifyIds(orig.TypeIds(), output.TypeIds(), "type ids", error_msg) ||
38 !VerifyIds(orig.ProtoIds(), output.ProtoIds(), "proto ids", error_msg) ||
39 !VerifyIds(orig.FieldIds(), output.FieldIds(), "field ids", error_msg) ||
40 !VerifyIds(orig.MethodIds(), output.MethodIds(), "method ids", error_msg)) {
41 return false;
42 }
43 return true;
44}
45
46template<class T> bool VerifyIds(std::vector<std::unique_ptr<T>>& orig,
47 std::vector<std::unique_ptr<T>>& output,
48 const char* section_name,
49 std::string* error_msg) {
50 if (orig.size() != output.size()) {
51 *error_msg = StringPrintf(
52 "Mismatched size for %s section, %zu vs %zu.", section_name, orig.size(), output.size());
53 return false;
54 }
55 for (size_t i = 0; i < orig.size(); ++i) {
56 if (!VerifyId(orig[i].get(), output[i].get(), error_msg)) {
57 return false;
58 }
59 }
60 return true;
61}
62
63bool VerifyId(dex_ir::StringId* orig, dex_ir::StringId* output, std::string* error_msg) {
64 if (strcmp(orig->Data(), output->Data()) != 0) {
65 *error_msg = StringPrintf("Mismatched string data for string id %u @ orig offset %x, %s vs %s.",
66 orig->GetIndex(),
67 orig->GetOffset(),
68 orig->Data(),
69 output->Data());
70 return false;
71 }
72 return true;
73}
74
75bool VerifyId(dex_ir::TypeId* orig, dex_ir::TypeId* output, std::string* error_msg) {
76 if (orig->GetStringId()->GetIndex() != output->GetStringId()->GetIndex()) {
77 *error_msg = StringPrintf("Mismatched string index for type id %u @ orig offset %x, %u vs %u.",
78 orig->GetIndex(),
79 orig->GetOffset(),
80 orig->GetStringId()->GetIndex(),
81 output->GetStringId()->GetIndex());
82 return false;
83 }
84 return true;
85}
86
87bool VerifyId(dex_ir::ProtoId* orig, dex_ir::ProtoId* output, std::string* error_msg) {
88 if (orig->Shorty()->GetIndex() != output->Shorty()->GetIndex()) {
89 *error_msg = StringPrintf("Mismatched string index for proto id %u @ orig offset %x, %u vs %u.",
90 orig->GetIndex(),
91 orig->GetOffset(),
92 orig->Shorty()->GetIndex(),
93 output->Shorty()->GetIndex());
94 return false;
95 }
96 if (orig->ReturnType()->GetIndex() != output->ReturnType()->GetIndex()) {
97 *error_msg = StringPrintf("Mismatched type index for proto id %u @ orig offset %x, %u vs %u.",
98 orig->GetIndex(),
99 orig->GetOffset(),
100 orig->ReturnType()->GetIndex(),
101 output->ReturnType()->GetIndex());
102 return false;
103 }
104 if (!VerifyTypeList(orig->Parameters(), output->Parameters())) {
105 *error_msg = StringPrintf("Mismatched type list for proto id %u @ orig offset %x.",
106 orig->GetIndex(),
107 orig->GetOffset());
108 }
109 return true;
110}
111
112bool VerifyId(dex_ir::FieldId* orig, dex_ir::FieldId* output, std::string* error_msg) {
113 if (orig->Class()->GetIndex() != output->Class()->GetIndex()) {
114 *error_msg =
115 StringPrintf("Mismatched class type index for field id %u @ orig offset %x, %u vs %u.",
116 orig->GetIndex(),
117 orig->GetOffset(),
118 orig->Class()->GetIndex(),
119 output->Class()->GetIndex());
120 return false;
121 }
122 if (orig->Type()->GetIndex() != output->Type()->GetIndex()) {
123 *error_msg = StringPrintf("Mismatched type index for field id %u @ orig offset %x, %u vs %u.",
124 orig->GetIndex(),
125 orig->GetOffset(),
126 orig->Class()->GetIndex(),
127 output->Class()->GetIndex());
128 return false;
129 }
130 if (orig->Name()->GetIndex() != output->Name()->GetIndex()) {
131 *error_msg = StringPrintf("Mismatched string index for field id %u @ orig offset %x, %u vs %u.",
132 orig->GetIndex(),
133 orig->GetOffset(),
134 orig->Name()->GetIndex(),
135 output->Name()->GetIndex());
136 return false;
137 }
138 return true;
139}
140
141bool VerifyId(dex_ir::MethodId* orig, dex_ir::MethodId* output, std::string* error_msg) {
142 if (orig->Class()->GetIndex() != output->Class()->GetIndex()) {
143 *error_msg = StringPrintf("Mismatched type index for method id %u @ orig offset %x, %u vs %u.",
144 orig->GetIndex(),
145 orig->GetOffset(),
146 orig->Class()->GetIndex(),
147 output->Class()->GetIndex());
148 return false;
149 }
150 if (orig->Proto()->GetIndex() != output->Proto()->GetIndex()) {
151 *error_msg = StringPrintf("Mismatched proto index for method id %u @ orig offset %x, %u vs %u.",
152 orig->GetIndex(),
153 orig->GetOffset(),
154 orig->Class()->GetIndex(),
155 output->Class()->GetIndex());
156 return false;
157 }
158 if (orig->Name()->GetIndex() != output->Name()->GetIndex()) {
159 *error_msg =
160 StringPrintf("Mismatched string index for method id %u @ orig offset %x, %u vs %u.",
161 orig->GetIndex(),
162 orig->GetOffset(),
163 orig->Name()->GetIndex(),
164 output->Name()->GetIndex());
165 return false;
166 }
167 return true;
168}
169
170bool VerifyTypeList(const dex_ir::TypeList* orig, const dex_ir::TypeList* output) {
171 if (orig == nullptr || output == nullptr) {
172 return orig == output;
173 }
174 const dex_ir::TypeIdVector* orig_list = orig->GetTypeList();
175 const dex_ir::TypeIdVector* output_list = output->GetTypeList();
176 if (orig_list->size() != output_list->size()) {
177 return false;
178 }
179 for (size_t i = 0; i < orig_list->size(); ++i) {
180 if ((*orig_list)[i]->GetIndex() != (*output_list)[i]->GetIndex()) {
181 return false;
182 }
183 }
184 return true;
185}
186
187} // namespace art