Home | History | Annotate | Download | only in processor
      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 (at) google.com (Siyang Xie)
     34 
     35 #include "processor/module_comparer.h"
     36 
     37 #include <map>
     38 #include <string>
     39 
     40 #include "common/scoped_ptr.h"
     41 #include "processor/basic_code_module.h"
     42 #include "processor/logging.h"
     43 
     44 #define ASSERT_TRUE(condition) \
     45   if (!(condition)) { \
     46     BPLOG(ERROR) << "FAIL: " << #condition << " @ " \
     47                  << __FILE__ << ":" << __LINE__; \
     48     return false; \
     49   }
     50 
     51 #define ASSERT_FALSE(condition) ASSERT_TRUE(!(condition))
     52 
     53 namespace google_breakpad {
     54 
     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"));
     58 
     59   // Load symbol data into basic_module
     60   scoped_array<char> buffer(new char[symbol_data.size() + 1]);
     61   memcpy(buffer.get(), symbol_data.c_str(), symbol_data.size());
     62   buffer.get()[symbol_data.size()] = '\0';
     63   ASSERT_TRUE(basic_module->LoadMapFromMemory(buffer.get(),
     64                                               symbol_data.size() + 1));
     65   buffer.reset();
     66 
     67   // Serialize BasicSourceLineResolver::Module.
     68   unsigned int serialized_size = 0;
     69   scoped_array<char> serialized_data(
     70       serializer_.Serialize(*(basic_module.get()), &serialized_size));
     71   ASSERT_TRUE(serialized_data.get());
     72   BPLOG(INFO) << "Serialized size = " << serialized_size << " Bytes";
     73 
     74   // Load FastSourceLineResolver::Module using serialized data.
     75   ASSERT_TRUE(fast_module->LoadMapFromMemory(serialized_data.get(),
     76                                              serialized_size));
     77   ASSERT_TRUE(fast_module->IsCorrupt() == basic_module->IsCorrupt());
     78 
     79   // Compare FastSourceLineResolver::Module with
     80   // BasicSourceLineResolver::Module.
     81   ASSERT_TRUE(CompareModule(basic_module.get(), fast_module.get()));
     82 
     83   return true;
     84 }
     85 
     86 // Traversal the content of module and do comparison
     87 bool ModuleComparer::CompareModule(const BasicModule *basic_module,
     88                                   const FastModule *fast_module) const {
     89   // Compare name_.
     90   ASSERT_TRUE(basic_module->name_ == fast_module->name_);
     91 
     92   // Compare files_:
     93   {
     94     BasicModule::FileMap::const_iterator iter1 = basic_module->files_.begin();
     95     FastModule::FileMap::iterator iter2 = fast_module->files_.begin();
     96     while (iter1 != basic_module->files_.end()
     97         && iter2 != fast_module->files_.end()) {
     98       ASSERT_TRUE(iter1->first == iter2.GetKey());
     99       string tmp(iter2.GetValuePtr());
    100       ASSERT_TRUE(iter1->second == tmp);
    101       ++iter1;
    102       ++iter2;
    103     }
    104     ASSERT_TRUE(iter1 == basic_module->files_.end());
    105     ASSERT_TRUE(iter2 == fast_module->files_.end());
    106   }
    107 
    108   // Compare functions_:
    109   {
    110     RangeMap<MemAddr, linked_ptr<BasicFunc> >::MapConstIterator iter1;
    111     StaticRangeMap<MemAddr, FastFunc>::MapConstIterator iter2;
    112     iter1 = basic_module->functions_.map_.begin();
    113     iter2 = fast_module->functions_.map_.begin();
    114     while (iter1 != basic_module->functions_.map_.end()
    115         && iter2 != fast_module->functions_.map_.end()) {
    116       ASSERT_TRUE(iter1->first == iter2.GetKey());
    117       ASSERT_TRUE(iter1->second.base() == iter2.GetValuePtr()->base());
    118       ASSERT_TRUE(CompareFunction(
    119           iter1->second.entry().get(), iter2.GetValuePtr()->entryptr()));
    120       ++iter1;
    121       ++iter2;
    122     }
    123     ASSERT_TRUE(iter1 == basic_module->functions_.map_.end());
    124     ASSERT_TRUE(iter2 == fast_module->functions_.map_.end());
    125   }
    126 
    127   // Compare public_symbols_:
    128   {
    129     AddressMap<MemAddr, linked_ptr<BasicPubSymbol> >::MapConstIterator iter1;
    130     StaticAddressMap<MemAddr, FastPubSymbol>::MapConstIterator iter2;
    131     iter1 = basic_module->public_symbols_.map_.begin();
    132     iter2 = fast_module->public_symbols_.map_.begin();
    133     while (iter1 != basic_module->public_symbols_.map_.end()
    134           && iter2 != fast_module->public_symbols_.map_.end()) {
    135       ASSERT_TRUE(iter1->first == iter2.GetKey());
    136       ASSERT_TRUE(ComparePubSymbol(
    137           iter1->second.get(), iter2.GetValuePtr()));
    138       ++iter1;
    139       ++iter2;
    140     }
    141     ASSERT_TRUE(iter1 == basic_module->public_symbols_.map_.end());
    142     ASSERT_TRUE(iter2 == fast_module->public_symbols_.map_.end());
    143   }
    144 
    145   // Compare windows_frame_info_[]:
    146   for (int i = 0; i < WindowsFrameInfo::STACK_INFO_LAST; ++i) {
    147     ASSERT_TRUE(CompareCRM(&(basic_module->windows_frame_info_[i]),
    148                            &(fast_module->windows_frame_info_[i])));
    149   }
    150 
    151   // Compare cfi_initial_rules_:
    152   {
    153     RangeMap<MemAddr, string>::MapConstIterator iter1;
    154     StaticRangeMap<MemAddr, char>::MapConstIterator iter2;
    155     iter1 = basic_module->cfi_initial_rules_.map_.begin();
    156     iter2 = fast_module->cfi_initial_rules_.map_.begin();
    157     while (iter1 != basic_module->cfi_initial_rules_.map_.end()
    158         && iter2 != fast_module->cfi_initial_rules_.map_.end()) {
    159       ASSERT_TRUE(iter1->first == iter2.GetKey());
    160       ASSERT_TRUE(iter1->second.base() == iter2.GetValuePtr()->base());
    161       string tmp(iter2.GetValuePtr()->entryptr());
    162       ASSERT_TRUE(iter1->second.entry() == tmp);
    163       ++iter1;
    164       ++iter2;
    165     }
    166     ASSERT_TRUE(iter1 == basic_module->cfi_initial_rules_.map_.end());
    167     ASSERT_TRUE(iter2 == fast_module->cfi_initial_rules_.map_.end());
    168   }
    169 
    170   // Compare cfi_delta_rules_:
    171   {
    172     map<MemAddr, string>::const_iterator iter1;
    173     StaticMap<MemAddr, char>::iterator iter2;
    174     iter1 = basic_module->cfi_delta_rules_.begin();
    175     iter2 = fast_module->cfi_delta_rules_.begin();
    176     while (iter1 != basic_module->cfi_delta_rules_.end()
    177         && iter2 != fast_module->cfi_delta_rules_.end()) {
    178       ASSERT_TRUE(iter1->first == iter2.GetKey());
    179       string tmp(iter2.GetValuePtr());
    180       ASSERT_TRUE(iter1->second == tmp);
    181       ++iter1;
    182       ++iter2;
    183     }
    184     ASSERT_TRUE(iter1 == basic_module->cfi_delta_rules_.end());
    185     ASSERT_TRUE(iter2 == fast_module->cfi_delta_rules_.end());
    186   }
    187 
    188   return true;
    189 }
    190 
    191 bool ModuleComparer::CompareFunction(const BasicFunc *basic_func,
    192                                     const FastFunc *fast_func_raw) const {
    193   FastFunc* fast_func = new FastFunc();
    194   fast_func->CopyFrom(fast_func_raw);
    195   ASSERT_TRUE(basic_func->name == fast_func->name);
    196   ASSERT_TRUE(basic_func->address == fast_func->address);
    197   ASSERT_TRUE(basic_func->size == fast_func->size);
    198 
    199   // compare range map of lines:
    200   RangeMap<MemAddr, linked_ptr<BasicLine> >::MapConstIterator iter1;
    201   StaticRangeMap<MemAddr, FastLine>::MapConstIterator iter2;
    202   iter1 = basic_func->lines.map_.begin();
    203   iter2 = fast_func->lines.map_.begin();
    204   while (iter1 != basic_func->lines.map_.end()
    205       && iter2 != fast_func->lines.map_.end()) {
    206     ASSERT_TRUE(iter1->first == iter2.GetKey());
    207     ASSERT_TRUE(iter1->second.base() == iter2.GetValuePtr()->base());
    208     ASSERT_TRUE(CompareLine(iter1->second.entry().get(),
    209                             iter2.GetValuePtr()->entryptr()));
    210     ++iter1;
    211     ++iter2;
    212   }
    213   ASSERT_TRUE(iter1 == basic_func->lines.map_.end());
    214   ASSERT_TRUE(iter2 == fast_func->lines.map_.end());
    215 
    216   delete fast_func;
    217   return true;
    218 }
    219 
    220 bool ModuleComparer::CompareLine(const BasicLine *basic_line,
    221                                 const FastLine *fast_line_raw) const {
    222   FastLine *fast_line = new FastLine;
    223   fast_line->CopyFrom(fast_line_raw);
    224 
    225   ASSERT_TRUE(basic_line->address == fast_line->address);
    226   ASSERT_TRUE(basic_line->size == fast_line->size);
    227   ASSERT_TRUE(basic_line->source_file_id == fast_line->source_file_id);
    228   ASSERT_TRUE(basic_line->line == fast_line->line);
    229 
    230   delete fast_line;
    231   return true;
    232 }
    233 
    234 bool ModuleComparer::ComparePubSymbol(const BasicPubSymbol* basic_ps,
    235                                      const FastPubSymbol* fastps_raw) const {
    236   FastPubSymbol *fast_ps = new FastPubSymbol;
    237   fast_ps->CopyFrom(fastps_raw);
    238   ASSERT_TRUE(basic_ps->name == fast_ps->name);
    239   ASSERT_TRUE(basic_ps->address == fast_ps->address);
    240   ASSERT_TRUE(basic_ps->parameter_size == fast_ps->parameter_size);
    241   delete fast_ps;
    242   return true;
    243 }
    244 
    245 bool ModuleComparer::CompareWFI(const WindowsFrameInfo& wfi1,
    246                                const WindowsFrameInfo& wfi2) const {
    247   ASSERT_TRUE(wfi1.type_ == wfi2.type_);
    248   ASSERT_TRUE(wfi1.valid == wfi2.valid);
    249   ASSERT_TRUE(wfi1.prolog_size == wfi2.prolog_size);
    250   ASSERT_TRUE(wfi1.epilog_size == wfi2.epilog_size);
    251   ASSERT_TRUE(wfi1.parameter_size == wfi2.parameter_size);
    252   ASSERT_TRUE(wfi1.saved_register_size == wfi2.saved_register_size);
    253   ASSERT_TRUE(wfi1.local_size == wfi2.local_size);
    254   ASSERT_TRUE(wfi1.max_stack_size == wfi2.max_stack_size);
    255   ASSERT_TRUE(wfi1.allocates_base_pointer == wfi2.allocates_base_pointer);
    256   ASSERT_TRUE(wfi1.program_string == wfi2.program_string);
    257   return true;
    258 }
    259 
    260 // Compare ContainedRangeMap
    261 bool ModuleComparer::CompareCRM(
    262     const ContainedRangeMap<MemAddr, linked_ptr<WFI> >* basic_crm,
    263     const StaticContainedRangeMap<MemAddr, char>* fast_crm) const {
    264   ASSERT_TRUE(basic_crm->base_ == fast_crm->base_);
    265 
    266   if (!basic_crm->entry_.get() || !fast_crm->entry_ptr_) {
    267     // empty entry:
    268     ASSERT_TRUE(!basic_crm->entry_.get() && !fast_crm->entry_ptr_);
    269   } else {
    270     WFI newwfi;
    271     newwfi.CopyFrom(fast_resolver_->CopyWFI(fast_crm->entry_ptr_));
    272     ASSERT_TRUE(CompareWFI(*(basic_crm->entry_.get()), newwfi));
    273   }
    274 
    275   if ((!basic_crm->map_ || basic_crm->map_->empty())
    276       || fast_crm->map_.empty()) {
    277     ASSERT_TRUE((!basic_crm->map_ || basic_crm->map_->empty())
    278                && fast_crm->map_.empty());
    279   } else {
    280     ContainedRangeMap<MemAddr, linked_ptr<WFI> >::MapConstIterator iter1;
    281     StaticContainedRangeMap<MemAddr, char>::MapConstIterator iter2;
    282     iter1 = basic_crm->map_->begin();
    283     iter2 = fast_crm->map_.begin();
    284     while (iter1 != basic_crm->map_->end()
    285         && iter2 != fast_crm->map_.end()) {
    286       ASSERT_TRUE(iter1->first == iter2.GetKey());
    287       StaticContainedRangeMap<MemAddr, char> *child =
    288           new StaticContainedRangeMap<MemAddr, char>(
    289               reinterpret_cast<const char*>(iter2.GetValuePtr()));
    290       ASSERT_TRUE(CompareCRM(iter1->second, child));
    291       delete child;
    292       ++iter1;
    293       ++iter2;
    294     }
    295     ASSERT_TRUE(iter1 == basic_crm->map_->end());
    296     ASSERT_TRUE(iter2 == fast_crm->map_.end());
    297   }
    298 
    299   return true;
    300 }
    301 
    302 }  // namespace google_breakpad
    303