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_serializer.cc: ModuleSerializer implementation. 31 // 32 // See module_serializer.h for documentation. 33 // 34 // Author: Siyang Xie (lambxsy (at) google.com) 35 36 #include "processor/module_serializer.h" 37 38 #include <map> 39 #include <string> 40 41 #include "processor/basic_code_module.h" 42 #include "processor/logging.h" 43 44 namespace google_breakpad { 45 46 // Definition of static member variable in SimplerSerializer<Funcion>, which 47 // is declared in file "simple_serializer-inl.h" 48 RangeMapSerializer< MemAddr, linked_ptr<BasicSourceLineResolver::Line> > 49 SimpleSerializer<BasicSourceLineResolver::Function>::range_map_serializer_; 50 51 size_t ModuleSerializer::SizeOf(const BasicSourceLineResolver::Module &module) { 52 size_t total_size_alloc_ = 0; 53 54 // Size of the "is_corrupt" flag. 55 total_size_alloc_ += SimpleSerializer<bool>::SizeOf(module.is_corrupt_); 56 57 // Compute memory size for each map component in Module class. 58 int map_index = 0; 59 map_sizes_[map_index++] = files_serializer_.SizeOf(module.files_); 60 map_sizes_[map_index++] = functions_serializer_.SizeOf(module.functions_); 61 map_sizes_[map_index++] = pubsym_serializer_.SizeOf(module.public_symbols_); 62 for (int i = 0; i < WindowsFrameInfo::STACK_INFO_LAST; ++i) 63 map_sizes_[map_index++] = 64 wfi_serializer_.SizeOf(&(module.windows_frame_info_[i])); 65 map_sizes_[map_index++] = cfi_init_rules_serializer_.SizeOf( 66 module.cfi_initial_rules_); 67 map_sizes_[map_index++] = cfi_delta_rules_serializer_.SizeOf( 68 module.cfi_delta_rules_); 69 70 // Header size. 71 total_size_alloc_ += kNumberMaps_ * sizeof(uint32_t); 72 73 for (int i = 0; i < kNumberMaps_; ++i) { 74 total_size_alloc_ += map_sizes_[i]; 75 } 76 77 // Extra one byte for null terminator for C-string copy safety. 78 total_size_alloc_ += SimpleSerializer<char>::SizeOf(0); 79 80 return total_size_alloc_; 81 } 82 83 char *ModuleSerializer::Write(const BasicSourceLineResolver::Module &module, 84 char *dest) { 85 // Write the is_corrupt flag. 86 dest = SimpleSerializer<bool>::Write(module.is_corrupt_, dest); 87 // Write header. 88 memcpy(dest, map_sizes_, kNumberMaps_ * sizeof(uint32_t)); 89 dest += kNumberMaps_ * sizeof(uint32_t); 90 // Write each map. 91 dest = files_serializer_.Write(module.files_, dest); 92 dest = functions_serializer_.Write(module.functions_, dest); 93 dest = pubsym_serializer_.Write(module.public_symbols_, dest); 94 for (int i = 0; i < WindowsFrameInfo::STACK_INFO_LAST; ++i) 95 dest = wfi_serializer_.Write(&(module.windows_frame_info_[i]), dest); 96 dest = cfi_init_rules_serializer_.Write(module.cfi_initial_rules_, dest); 97 dest = cfi_delta_rules_serializer_.Write(module.cfi_delta_rules_, dest); 98 // Write a null terminator. 99 dest = SimpleSerializer<char>::Write(0, dest); 100 return dest; 101 } 102 103 char* ModuleSerializer::Serialize( 104 const BasicSourceLineResolver::Module &module, unsigned int *size) { 105 // Compute size of memory to allocate. 106 unsigned int size_to_alloc = SizeOf(module); 107 108 // Allocate memory for serialized data. 109 char *serialized_data = new char[size_to_alloc]; 110 if (!serialized_data) { 111 BPLOG(ERROR) << "ModuleSerializer: memory allocation failed, " 112 << "size to alloc: " << size_to_alloc; 113 if (size) *size = 0; 114 return NULL; 115 } 116 117 // Write serialized data to allocated memory chunk. 118 char *end_address = Write(module, serialized_data); 119 // Verify the allocated memory size is equal to the size of data been written. 120 unsigned int size_written = 121 static_cast<unsigned int>(end_address - serialized_data); 122 if (size_to_alloc != size_written) { 123 BPLOG(ERROR) << "size_to_alloc differs from size_written: " 124 << size_to_alloc << " vs " << size_written; 125 } 126 127 // Set size and return the start address of memory chunk. 128 if (size) 129 *size = size_to_alloc; 130 return serialized_data; 131 } 132 133 bool ModuleSerializer::SerializeModuleAndLoadIntoFastResolver( 134 const BasicSourceLineResolver::ModuleMap::const_iterator &iter, 135 FastSourceLineResolver *fast_resolver) { 136 BPLOG(INFO) << "Converting symbol " << iter->first.c_str(); 137 138 // Cast SourceLineResolverBase::Module* to BasicSourceLineResolver::Module*. 139 BasicSourceLineResolver::Module* basic_module = 140 dynamic_cast<BasicSourceLineResolver::Module*>(iter->second); 141 142 unsigned int size = 0; 143 scoped_array<char> symbol_data(Serialize(*basic_module, &size)); 144 if (!symbol_data.get()) { 145 BPLOG(ERROR) << "Serialization failed for module: " << basic_module->name_; 146 return false; 147 } 148 BPLOG(INFO) << "Serialized Symbol Size " << size; 149 150 // Copy the data into string. 151 // Must pass string to LoadModuleUsingMapBuffer(), instead of passing char* to 152 // LoadModuleUsingMemoryBuffer(), becaused of data ownership/lifetime issue. 153 string symbol_data_string(symbol_data.get(), size); 154 symbol_data.reset(); 155 156 scoped_ptr<CodeModule> code_module( 157 new BasicCodeModule(0, 0, iter->first, "", "", "", "")); 158 159 return fast_resolver->LoadModuleUsingMapBuffer(code_module.get(), 160 symbol_data_string); 161 } 162 163 void ModuleSerializer::ConvertAllModules( 164 const BasicSourceLineResolver *basic_resolver, 165 FastSourceLineResolver *fast_resolver) { 166 // Check for NULL pointer. 167 if (!basic_resolver || !fast_resolver) 168 return; 169 170 // Traverse module list in basic resolver. 171 BasicSourceLineResolver::ModuleMap::const_iterator iter; 172 iter = basic_resolver->modules_->begin(); 173 for (; iter != basic_resolver->modules_->end(); ++iter) 174 SerializeModuleAndLoadIntoFastResolver(iter, fast_resolver); 175 } 176 177 bool ModuleSerializer::ConvertOneModule( 178 const string &moduleid, 179 const BasicSourceLineResolver *basic_resolver, 180 FastSourceLineResolver *fast_resolver) { 181 // Check for NULL pointer. 182 if (!basic_resolver || !fast_resolver) 183 return false; 184 185 BasicSourceLineResolver::ModuleMap::const_iterator iter; 186 iter = basic_resolver->modules_->find(moduleid); 187 if (iter == basic_resolver->modules_->end()) 188 return false; 189 190 return SerializeModuleAndLoadIntoFastResolver(iter, fast_resolver); 191 } 192 193 char* ModuleSerializer::SerializeSymbolFileData( 194 const string &symbol_data, unsigned int *size) { 195 scoped_ptr<BasicSourceLineResolver::Module> module( 196 new BasicSourceLineResolver::Module("no name")); 197 scoped_array<char> buffer(new char[symbol_data.size() + 1]); 198 memcpy(buffer.get(), symbol_data.c_str(), symbol_data.size()); 199 buffer.get()[symbol_data.size()] = '\0'; 200 if (!module->LoadMapFromMemory(buffer.get(), symbol_data.size() + 1)) { 201 return NULL; 202 } 203 buffer.reset(NULL); 204 return Serialize(*(module.get()), size); 205 } 206 207 } // namespace google_breakpad 208