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