Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
1 // Copyright (c) 2010, Google Inc.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
13 // distribution.
14 // * Neither the name of Google Inc. nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 //
30 // module_comparer.cc: ModuleComparer implementation.
31 // See module_comparer.h for documentation.
32 //
33 // Author: lambxsy@google.com (Siyang Xie)
35 #include "processor/module_comparer.h"
37 #include <map>
38 #include <string>
40 #include "common/scoped_ptr.h"
41 #include "processor/basic_code_module.h"
42 #include "processor/logging.h"
44 #define ASSERT_TRUE(condition) \
45 if (!(condition)) { \
46 BPLOG(ERROR) << "FAIL: " << #condition << " @ " \
47 << __FILE__ << ":" << __LINE__; \
48 return false; \
49 }
51 #define ASSERT_FALSE(condition) ASSERT_TRUE(!(condition))
53 namespace google_breakpad {
55 bool ModuleComparer::Compare(const string &symbol_data) {
56 scoped_ptr<BasicModule> basic_module(new BasicModule("test_module"));
57 scoped_ptr<FastModule> fast_module(new FastModule("test_module"));
59 // Load symbol data into basic_module
60 scoped_array<char> buffer(new char[symbol_data.size() + 1]);
61 strcpy(buffer.get(), symbol_data.c_str());
62 ASSERT_TRUE(basic_module->LoadMapFromMemory(buffer.get()));
63 buffer.reset();
65 // Serialize BasicSourceLineResolver::Module.
66 unsigned int serialized_size = 0;
67 scoped_array<char> serialized_data(
68 serializer_.Serialize(*(basic_module.get()), &serialized_size));
69 ASSERT_TRUE(serialized_data.get());
70 BPLOG(INFO) << "Serialized size = " << serialized_size << " Bytes";
72 // Load FastSourceLineResolver::Module using serialized data.
73 ASSERT_TRUE(fast_module->LoadMapFromMemory(serialized_data.get()));
75 // Compare FastSourceLineResolver::Module with
76 // BasicSourceLineResolver::Module.
77 ASSERT_TRUE(CompareModule(basic_module.get(), fast_module.get()));
79 return true;
80 }
82 // Traversal the content of module and do comparison
83 bool ModuleComparer::CompareModule(const BasicModule *basic_module,
84 const FastModule *fast_module) const {
85 // Compare name_.
86 ASSERT_TRUE(basic_module->name_ == fast_module->name_);
88 // Compare files_:
89 {
90 BasicModule::FileMap::const_iterator iter1 = basic_module->files_.begin();
91 FastModule::FileMap::iterator iter2 = fast_module->files_.begin();
92 while (iter1 != basic_module->files_.end()
93 && iter2 != fast_module->files_.end()) {
94 ASSERT_TRUE(iter1->first == iter2.GetKey());
95 string tmp(iter2.GetValuePtr());
96 ASSERT_TRUE(iter1->second == tmp);
97 ++iter1;
98 ++iter2;
99 }
100 ASSERT_TRUE(iter1 == basic_module->files_.end());
101 ASSERT_TRUE(iter2 == fast_module->files_.end());
102 }
104 // Compare functions_:
105 {
106 RangeMap<MemAddr, linked_ptr<BasicFunc> >::MapConstIterator iter1;
107 StaticRangeMap<MemAddr, FastFunc>::MapConstIterator iter2;
108 iter1 = basic_module->functions_.map_.begin();
109 iter2 = fast_module->functions_.map_.begin();
110 while (iter1 != basic_module->functions_.map_.end()
111 && iter2 != fast_module->functions_.map_.end()) {
112 ASSERT_TRUE(iter1->first == iter2.GetKey());
113 ASSERT_TRUE(iter1->second.base() == iter2.GetValuePtr()->base());
114 ASSERT_TRUE(CompareFunction(
115 iter1->second.entry().get(), iter2.GetValuePtr()->entryptr()));
116 ++iter1;
117 ++iter2;
118 }
119 ASSERT_TRUE(iter1 == basic_module->functions_.map_.end());
120 ASSERT_TRUE(iter2 == fast_module->functions_.map_.end());
121 }
123 // Compare public_symbols_:
124 {
125 AddressMap<MemAddr, linked_ptr<BasicPubSymbol> >::MapConstIterator iter1;
126 StaticAddressMap<MemAddr, FastPubSymbol>::MapConstIterator iter2;
127 iter1 = basic_module->public_symbols_.map_.begin();
128 iter2 = fast_module->public_symbols_.map_.begin();
129 while (iter1 != basic_module->public_symbols_.map_.end()
130 && iter2 != fast_module->public_symbols_.map_.end()) {
131 ASSERT_TRUE(iter1->first == iter2.GetKey());
132 ASSERT_TRUE(ComparePubSymbol(
133 iter1->second.get(), iter2.GetValuePtr()));
134 ++iter1;
135 ++iter2;
136 }
137 ASSERT_TRUE(iter1 == basic_module->public_symbols_.map_.end());
138 ASSERT_TRUE(iter2 == fast_module->public_symbols_.map_.end());
139 }
141 // Compare windows_frame_info_[]:
142 for (int i = 0; i < WindowsFrameInfo::STACK_INFO_LAST; ++i) {
143 ASSERT_TRUE(CompareCRM(&(basic_module->windows_frame_info_[i]),
144 &(fast_module->windows_frame_info_[i])));
145 }
147 // Compare cfi_initial_rules_:
148 {
149 RangeMap<MemAddr, string>::MapConstIterator iter1;
150 StaticRangeMap<MemAddr, char>::MapConstIterator iter2;
151 iter1 = basic_module->cfi_initial_rules_.map_.begin();
152 iter2 = fast_module->cfi_initial_rules_.map_.begin();
153 while (iter1 != basic_module->cfi_initial_rules_.map_.end()
154 && iter2 != fast_module->cfi_initial_rules_.map_.end()) {
155 ASSERT_TRUE(iter1->first == iter2.GetKey());
156 ASSERT_TRUE(iter1->second.base() == iter2.GetValuePtr()->base());
157 string tmp(iter2.GetValuePtr()->entryptr());
158 ASSERT_TRUE(iter1->second.entry() == tmp);
159 ++iter1;
160 ++iter2;
161 }
162 ASSERT_TRUE(iter1 == basic_module->cfi_initial_rules_.map_.end());
163 ASSERT_TRUE(iter2 == fast_module->cfi_initial_rules_.map_.end());
164 }
166 // Compare cfi_delta_rules_:
167 {
168 map<MemAddr, string>::const_iterator iter1;
169 StaticMap<MemAddr, char>::iterator iter2;
170 iter1 = basic_module->cfi_delta_rules_.begin();
171 iter2 = fast_module->cfi_delta_rules_.begin();
172 while (iter1 != basic_module->cfi_delta_rules_.end()
173 && iter2 != fast_module->cfi_delta_rules_.end()) {
174 ASSERT_TRUE(iter1->first == iter2.GetKey());
175 string tmp(iter2.GetValuePtr());
176 ASSERT_TRUE(iter1->second == tmp);
177 ++iter1;
178 ++iter2;
179 }
180 ASSERT_TRUE(iter1 == basic_module->cfi_delta_rules_.end());
181 ASSERT_TRUE(iter2 == fast_module->cfi_delta_rules_.end());
182 }
184 return true;
185 }
187 bool ModuleComparer::CompareFunction(const BasicFunc *basic_func,
188 const FastFunc *fast_func_raw) const {
189 FastFunc* fast_func = new FastFunc();
190 fast_func->CopyFrom(fast_func_raw);
191 ASSERT_TRUE(basic_func->name == fast_func->name);
192 ASSERT_TRUE(basic_func->address == fast_func->address);
193 ASSERT_TRUE(basic_func->size == fast_func->size);
195 // compare range map of lines:
196 RangeMap<MemAddr, linked_ptr<BasicLine> >::MapConstIterator iter1;
197 StaticRangeMap<MemAddr, FastLine>::MapConstIterator iter2;
198 iter1 = basic_func->lines.map_.begin();
199 iter2 = fast_func->lines.map_.begin();
200 while (iter1 != basic_func->lines.map_.end()
201 && iter2 != fast_func->lines.map_.end()) {
202 ASSERT_TRUE(iter1->first == iter2.GetKey());
203 ASSERT_TRUE(iter1->second.base() == iter2.GetValuePtr()->base());
204 ASSERT_TRUE(CompareLine(iter1->second.entry().get(),
205 iter2.GetValuePtr()->entryptr()));
206 ++iter1;
207 ++iter2;
208 }
209 ASSERT_TRUE(iter1 == basic_func->lines.map_.end());
210 ASSERT_TRUE(iter2 == fast_func->lines.map_.end());
212 delete fast_func;
213 return true;
214 }
216 bool ModuleComparer::CompareLine(const BasicLine *basic_line,
217 const FastLine *fast_line_raw) const {
218 FastLine *fast_line = new FastLine;
219 fast_line->CopyFrom(fast_line_raw);
221 ASSERT_TRUE(basic_line->address == fast_line->address);
222 ASSERT_TRUE(basic_line->size == fast_line->size);
223 ASSERT_TRUE(basic_line->source_file_id == fast_line->source_file_id);
224 ASSERT_TRUE(basic_line->line == fast_line->line);
226 delete fast_line;
227 return true;
228 }
230 bool ModuleComparer::ComparePubSymbol(const BasicPubSymbol* basic_ps,
231 const FastPubSymbol* fastps_raw) const {
232 FastPubSymbol *fast_ps = new FastPubSymbol;
233 fast_ps->CopyFrom(fastps_raw);
234 ASSERT_TRUE(basic_ps->name == fast_ps->name);
235 ASSERT_TRUE(basic_ps->address == fast_ps->address);
236 ASSERT_TRUE(basic_ps->parameter_size == fast_ps->parameter_size);
237 delete fast_ps;
238 return true;
239 }
241 bool ModuleComparer::CompareWFI(const WindowsFrameInfo& wfi1,
242 const WindowsFrameInfo& wfi2) const {
243 ASSERT_TRUE(wfi1.type_ == wfi2.type_);
244 ASSERT_TRUE(wfi1.valid == wfi2.valid);
245 ASSERT_TRUE(wfi1.prolog_size == wfi2.prolog_size);
246 ASSERT_TRUE(wfi1.epilog_size == wfi2.epilog_size);
247 ASSERT_TRUE(wfi1.parameter_size == wfi2.parameter_size);
248 ASSERT_TRUE(wfi1.saved_register_size == wfi2.saved_register_size);
249 ASSERT_TRUE(wfi1.local_size == wfi2.local_size);
250 ASSERT_TRUE(wfi1.max_stack_size == wfi2.max_stack_size);
251 ASSERT_TRUE(wfi1.allocates_base_pointer == wfi2.allocates_base_pointer);
252 ASSERT_TRUE(wfi1.program_string == wfi2.program_string);
253 return true;
254 }
256 // Compare ContainedRangeMap
257 bool ModuleComparer::CompareCRM(
258 const ContainedRangeMap<MemAddr, linked_ptr<WFI> >* basic_crm,
259 const StaticContainedRangeMap<MemAddr, char>* fast_crm) const {
260 ASSERT_TRUE(basic_crm->base_ == fast_crm->base_);
262 if (!basic_crm->entry_.get() || !fast_crm->entry_ptr_) {
263 // empty entry:
264 ASSERT_TRUE(!basic_crm->entry_.get() && !fast_crm->entry_ptr_);
265 } else {
266 WFI newwfi;
267 newwfi.CopyFrom(fast_resolver_->CopyWFI(fast_crm->entry_ptr_));
268 ASSERT_TRUE(CompareWFI(*(basic_crm->entry_.get()), newwfi));
269 }
271 if ((!basic_crm->map_ || basic_crm->map_->empty())
272 || fast_crm->map_.empty()) {
273 ASSERT_TRUE((!basic_crm->map_ || basic_crm->map_->empty())
274 && fast_crm->map_.empty());
275 } else {
276 ContainedRangeMap<MemAddr, linked_ptr<WFI> >::MapConstIterator iter1;
277 StaticContainedRangeMap<MemAddr, char>::MapConstIterator iter2;
278 iter1 = basic_crm->map_->begin();
279 iter2 = fast_crm->map_.begin();
280 while (iter1 != basic_crm->map_->end()
281 && iter2 != fast_crm->map_.end()) {
282 ASSERT_TRUE(iter1->first == iter2.GetKey());
283 StaticContainedRangeMap<MemAddr, char> *child =
284 new StaticContainedRangeMap<MemAddr, char>(
285 reinterpret_cast<const char*>(iter2.GetValuePtr()));
286 ASSERT_TRUE(CompareCRM(iter1->second, child));
287 delete child;
288 ++iter1;
289 ++iter2;
290 }
291 ASSERT_TRUE(iter1 == basic_crm->map_->end());
292 ASSERT_TRUE(iter2 == fast_crm->map_.end());
293 }
295 return true;
296 }
298 } // namespace google_breakpad