toolkit/crashreporter/google-breakpad/src/processor/module_comparer.cc

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial