xref: /aosp_15_r20/external/google-breakpad/src/processor/module_serializer.cc (revision 9712c20fc9bbfbac4935993a2ca0b3958c5adad2)
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 ([email protected])
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 
SizeOf(const BasicSourceLineResolver::Module & module)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 
Write(const BasicSourceLineResolver::Module & module,char * dest)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 
Serialize(const BasicSourceLineResolver::Module & module,size_t * size)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 
SerializeModuleAndLoadIntoFastResolver(const BasicSourceLineResolver::ModuleMap::const_iterator & iter,FastSourceLineResolver * fast_resolver)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 
ConvertAllModules(const BasicSourceLineResolver * basic_resolver,FastSourceLineResolver * fast_resolver)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 
ConvertOneModule(const string & moduleid,const BasicSourceLineResolver * basic_resolver,FastSourceLineResolver * fast_resolver)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 
SerializeSymbolFileData(const string & symbol_data,size_t * size)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
220