/ src / processor / module_serializer.cc
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