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