module_serializer.cc
1 // Copyright 2010 Google LLC 2 // 3 // Redistribution and use in source and binary forms, with or without 4 // modification, are permitted provided that the following conditions are 5 // met: 6 // 7 // * Redistributions of source code must retain the above copyright 8 // notice, this list of conditions and the following disclaimer. 9 // * Redistributions in binary form must reproduce the above 10 // copyright notice, this list of conditions and the following disclaimer 11 // in the documentation and/or other materials provided with the 12 // distribution. 13 // * Neither the name of Google LLC nor the names of its 14 // contributors may be used to endorse or promote products derived from 15 // this software without specific prior written permission. 16 // 17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 // 29 // module_serializer.cc: ModuleSerializer implementation. 30 // 31 // See module_serializer.h for documentation. 32 // 33 // Author: Siyang Xie (lambxsy@google.com) 34 35 #ifdef HAVE_CONFIG_H 36 #include <config.h> // Must come first 37 #endif 38 39 #include "processor/module_serializer.h" 40 41 #include <map> 42 #include <string> 43 44 #include "processor/basic_code_module.h" 45 #include "processor/logging.h" 46 47 namespace google_breakpad { 48 49 // Definition of static member variables in SimplerSerializer<Funcion> and 50 // SimplerSerializer<Inline>, which are declared in file 51 // "simple_serializer-inl.h" 52 RangeMapSerializer<MemAddr, linked_ptr<BasicSourceLineResolver::Line>> 53 SimpleSerializer<BasicSourceLineResolver::Function>::range_map_serializer_; 54 ContainedRangeMapSerializer<MemAddr, 55 linked_ptr<BasicSourceLineResolver::Inline>> 56 SimpleSerializer< 57 BasicSourceLineResolver::Function>::inline_range_map_serializer_; 58 59 size_t ModuleSerializer::SizeOf(const BasicSourceLineResolver::Module& module) { 60 size_t total_size_alloc_ = 0; 61 62 // Size of the "is_corrupt" flag. 63 total_size_alloc_ += SimpleSerializer<bool>::SizeOf(module.is_corrupt_); 64 65 // Compute memory size for each map component in Module class. 66 int map_index = 0; 67 map_sizes_[map_index++] = files_serializer_.SizeOf(module.files_); 68 map_sizes_[map_index++] = functions_serializer_.SizeOf(module.functions_); 69 map_sizes_[map_index++] = pubsym_serializer_.SizeOf(module.public_symbols_); 70 for (int i = 0; i < WindowsFrameInfo::STACK_INFO_LAST; ++i) 71 map_sizes_[map_index++] = 72 wfi_serializer_.SizeOf(&(module.windows_frame_info_[i])); 73 map_sizes_[map_index++] = cfi_init_rules_serializer_.SizeOf( 74 module.cfi_initial_rules_); 75 map_sizes_[map_index++] = cfi_delta_rules_serializer_.SizeOf( 76 module.cfi_delta_rules_); 77 map_sizes_[map_index++] = 78 inline_origin_serializer_.SizeOf(module.inline_origins_); 79 80 // Header size. 81 total_size_alloc_ += kNumberMaps_ * sizeof(uint32_t); 82 83 for (int i = 0; i < kNumberMaps_; ++i) { 84 total_size_alloc_ += map_sizes_[i]; 85 } 86 87 // Extra one byte for null terminator for C-string copy safety. 88 total_size_alloc_ += SimpleSerializer<char>::SizeOf(0); 89 90 return total_size_alloc_; 91 } 92 93 char* ModuleSerializer::Write(const BasicSourceLineResolver::Module& module, 94 char* dest) { 95 // Write the is_corrupt flag. 96 dest = SimpleSerializer<bool>::Write(module.is_corrupt_, dest); 97 // Write header. 98 memcpy(dest, map_sizes_, kNumberMaps_ * sizeof(uint32_t)); 99 dest += kNumberMaps_ * sizeof(uint32_t); 100 // Write each map. 101 dest = files_serializer_.Write(module.files_, dest); 102 dest = functions_serializer_.Write(module.functions_, dest); 103 dest = pubsym_serializer_.Write(module.public_symbols_, dest); 104 for (int i = 0; i < WindowsFrameInfo::STACK_INFO_LAST; ++i) 105 dest = wfi_serializer_.Write(&(module.windows_frame_info_[i]), dest); 106 dest = cfi_init_rules_serializer_.Write(module.cfi_initial_rules_, dest); 107 dest = cfi_delta_rules_serializer_.Write(module.cfi_delta_rules_, dest); 108 dest = inline_origin_serializer_.Write(module.inline_origins_, dest); 109 // Write a null terminator. 110 dest = SimpleSerializer<char>::Write(0, dest); 111 return dest; 112 } 113 114 char* ModuleSerializer::Serialize(const BasicSourceLineResolver::Module& module, 115 size_t* size) { 116 // Compute size of memory to allocate. 117 const size_t size_to_alloc = SizeOf(module); 118 119 // Allocate memory for serialized data. 120 char* serialized_data = new char[size_to_alloc]; 121 if (!serialized_data) { 122 BPLOG(ERROR) << "ModuleSerializer: memory allocation failed, " 123 << "size to alloc: " << size_to_alloc; 124 if (size) *size = 0; 125 return NULL; 126 } 127 128 // Write serialized data to allocated memory chunk. 129 char* end_address = Write(module, serialized_data); 130 // Verify the allocated memory size is equal to the size of data been written. 131 const size_t size_written = 132 static_cast<size_t>(end_address - serialized_data); 133 if (size_to_alloc != size_written) { 134 BPLOG(ERROR) << "size_to_alloc differs from size_written: " 135 << size_to_alloc << " vs " << size_written; 136 } 137 138 // Set size and return the start address of memory chunk. 139 if (size) 140 *size = size_to_alloc; 141 142 return serialized_data; 143 } 144 145 bool ModuleSerializer::SerializeModuleAndLoadIntoFastResolver( 146 const BasicSourceLineResolver::ModuleMap::const_iterator& iter, 147 FastSourceLineResolver* fast_resolver) { 148 BPLOG(INFO) << "Converting symbol " << iter->first.c_str(); 149 150 // Cast SourceLineResolverBase::Module* to BasicSourceLineResolver::Module*. 151 BasicSourceLineResolver::Module* basic_module = 152 dynamic_cast<BasicSourceLineResolver::Module*>(iter->second); 153 154 size_t size = 0; 155 scoped_array<char> symbol_data(Serialize(*basic_module, &size)); 156 if (!symbol_data.get()) { 157 BPLOG(ERROR) << "Serialization failed for module: " << basic_module->name_; 158 return false; 159 } 160 BPLOG(INFO) << "Serialized Symbol Size " << size; 161 162 // Copy the data into string. 163 // Must pass string to LoadModuleUsingMapBuffer(), instead of passing char* to 164 // LoadModuleUsingMemoryBuffer(), becaused of data ownership/lifetime issue. 165 string symbol_data_string(symbol_data.get(), size); 166 symbol_data.reset(); 167 168 scoped_ptr<CodeModule> code_module( 169 new BasicCodeModule(0, 0, iter->first, "", "", "", "")); 170 171 return fast_resolver->LoadModuleUsingMapBuffer(code_module.get(), 172 symbol_data_string); 173 } 174 175 void ModuleSerializer::ConvertAllModules( 176 const BasicSourceLineResolver* basic_resolver, 177 FastSourceLineResolver* fast_resolver) { 178 // Check for NULL pointer. 179 if (!basic_resolver || !fast_resolver) 180 return; 181 182 // Traverse module list in basic resolver. 183 BasicSourceLineResolver::ModuleMap::const_iterator iter; 184 iter = basic_resolver->modules_->begin(); 185 for (; iter != basic_resolver->modules_->end(); ++iter) 186 SerializeModuleAndLoadIntoFastResolver(iter, fast_resolver); 187 } 188 189 bool ModuleSerializer::ConvertOneModule( 190 const string& moduleid, 191 const BasicSourceLineResolver* basic_resolver, 192 FastSourceLineResolver* fast_resolver) { 193 // Check for NULL pointer. 194 if (!basic_resolver || !fast_resolver) 195 return false; 196 197 BasicSourceLineResolver::ModuleMap::const_iterator iter; 198 iter = basic_resolver->modules_->find(moduleid); 199 if (iter == basic_resolver->modules_->end()) 200 return false; 201 202 return SerializeModuleAndLoadIntoFastResolver(iter, fast_resolver); 203 } 204 205 char* ModuleSerializer::SerializeSymbolFileData(const string& symbol_data, 206 size_t* size) { 207 scoped_ptr<BasicSourceLineResolver::Module> module( 208 new BasicSourceLineResolver::Module("no name")); 209 scoped_array<char> buffer(new char[symbol_data.size() + 1]); 210 memcpy(buffer.get(), symbol_data.c_str(), symbol_data.size()); 211 buffer.get()[symbol_data.size()] = '\0'; 212 if (!module->LoadMapFromMemory(buffer.get(), symbol_data.size() + 1)) { 213 return NULL; 214 } 215 buffer.reset(NULL); 216 return Serialize(*(module.get()), size); 217 } 218 219 } // namespace google_breakpad