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