xref: /aosp_15_r20/external/google-breakpad/src/processor/microdump.cc (revision 9712c20fc9bbfbac4935993a2ca0b3958c5adad2)
1*9712c20fSFrederick Mayle // Copyright 2014 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 // microdump.cc: A microdump reader.
30*9712c20fSFrederick Mayle //
31*9712c20fSFrederick Mayle // See microdump.h for documentation.
32*9712c20fSFrederick Mayle 
33*9712c20fSFrederick Mayle #ifdef HAVE_CONFIG_H
34*9712c20fSFrederick Mayle #include <config.h>  // Must come first
35*9712c20fSFrederick Mayle #endif
36*9712c20fSFrederick Mayle 
37*9712c20fSFrederick Mayle #include "google_breakpad/processor/microdump.h"
38*9712c20fSFrederick Mayle 
39*9712c20fSFrederick Mayle #include <stdio.h>
40*9712c20fSFrederick Mayle #include <string.h>
41*9712c20fSFrederick Mayle 
42*9712c20fSFrederick Mayle #include <memory>
43*9712c20fSFrederick Mayle #include <sstream>
44*9712c20fSFrederick Mayle #include <string>
45*9712c20fSFrederick Mayle #include <vector>
46*9712c20fSFrederick Mayle 
47*9712c20fSFrederick Mayle #include "google_breakpad/common/minidump_cpu_arm.h"
48*9712c20fSFrederick Mayle #include "google_breakpad/processor/code_module.h"
49*9712c20fSFrederick Mayle #include "processor/basic_code_module.h"
50*9712c20fSFrederick Mayle #include "processor/convert_old_arm64_context.h"
51*9712c20fSFrederick Mayle #include "processor/linked_ptr.h"
52*9712c20fSFrederick Mayle #include "processor/logging.h"
53*9712c20fSFrederick Mayle #include "processor/range_map-inl.h"
54*9712c20fSFrederick Mayle 
55*9712c20fSFrederick Mayle namespace {
56*9712c20fSFrederick Mayle static const char kGoogleBreakpadKey[] = "google-breakpad";
57*9712c20fSFrederick Mayle static const char kMicrodumpBegin[] = "-----BEGIN BREAKPAD MICRODUMP-----";
58*9712c20fSFrederick Mayle static const char kMicrodumpEnd[] = "-----END BREAKPAD MICRODUMP-----";
59*9712c20fSFrederick Mayle static const char kOsKey[] = ": O ";
60*9712c20fSFrederick Mayle static const char kCpuKey[] = ": C ";
61*9712c20fSFrederick Mayle static const char kCrashReasonKey[] = ": R ";
62*9712c20fSFrederick Mayle static const char kGpuKey[] = ": G ";
63*9712c20fSFrederick Mayle static const char kMmapKey[] = ": M ";
64*9712c20fSFrederick Mayle static const char kStackKey[] = ": S ";
65*9712c20fSFrederick Mayle static const char kStackFirstLineKey[] = ": S 0 ";
66*9712c20fSFrederick Mayle static const char kArmArchitecture[] = "arm";
67*9712c20fSFrederick Mayle static const char kArm64Architecture[] = "arm64";
68*9712c20fSFrederick Mayle static const char kX86Architecture[] = "x86";
69*9712c20fSFrederick Mayle static const char kMipsArchitecture[] = "mips";
70*9712c20fSFrederick Mayle static const char kMips64Architecture[] = "mips64";
71*9712c20fSFrederick Mayle static const char kGpuUnknown[] = "UNKNOWN";
72*9712c20fSFrederick Mayle 
73*9712c20fSFrederick Mayle template<typename T>
HexStrToL(const string & str)74*9712c20fSFrederick Mayle T HexStrToL(const string& str) {
75*9712c20fSFrederick Mayle   uint64_t res = 0;
76*9712c20fSFrederick Mayle   std::istringstream ss(str);
77*9712c20fSFrederick Mayle   ss >> std::hex >> res;
78*9712c20fSFrederick Mayle   return static_cast<T>(res);
79*9712c20fSFrederick Mayle }
80*9712c20fSFrederick Mayle 
ParseHexBuf(const string & str)81*9712c20fSFrederick Mayle std::vector<uint8_t> ParseHexBuf(const string& str) {
82*9712c20fSFrederick Mayle   std::vector<uint8_t> buf;
83*9712c20fSFrederick Mayle   for (size_t i = 0; i < str.length(); i += 2) {
84*9712c20fSFrederick Mayle     buf.push_back(HexStrToL<uint8_t>(str.substr(i, 2)));
85*9712c20fSFrederick Mayle   }
86*9712c20fSFrederick Mayle   return buf;
87*9712c20fSFrederick Mayle }
88*9712c20fSFrederick Mayle 
GetLine(std::istringstream * istream,string * str)89*9712c20fSFrederick Mayle bool GetLine(std::istringstream* istream, string* str) {
90*9712c20fSFrederick Mayle   if (std::getline(*istream, *str)) {
91*9712c20fSFrederick Mayle     // Trim any trailing newline from the end of the line. Allows us
92*9712c20fSFrederick Mayle     // to seamlessly handle both Windows/DOS and Unix formatted input. The
93*9712c20fSFrederick Mayle     // adb tool generally writes logcat dumps in Windows/DOS format.
94*9712c20fSFrederick Mayle     if (!str->empty() && str->at(str->size() - 1) == '\r') {
95*9712c20fSFrederick Mayle       str->erase(str->size() - 1);
96*9712c20fSFrederick Mayle     }
97*9712c20fSFrederick Mayle     return true;
98*9712c20fSFrederick Mayle   }
99*9712c20fSFrederick Mayle   return false;
100*9712c20fSFrederick Mayle }
101*9712c20fSFrederick Mayle 
102*9712c20fSFrederick Mayle }  // namespace
103*9712c20fSFrederick Mayle 
104*9712c20fSFrederick Mayle namespace google_breakpad {
105*9712c20fSFrederick Mayle 
106*9712c20fSFrederick Mayle //
107*9712c20fSFrederick Mayle // MicrodumpModules
108*9712c20fSFrederick Mayle //
109*9712c20fSFrederick Mayle 
Add(const CodeModule * module)110*9712c20fSFrederick Mayle void MicrodumpModules::Add(const CodeModule* module) {
111*9712c20fSFrederick Mayle   linked_ptr<const CodeModule> module_ptr(module);
112*9712c20fSFrederick Mayle   if (!map_.StoreRange(module->base_address(), module->size(), module_ptr)) {
113*9712c20fSFrederick Mayle     BPLOG(ERROR) << "Module " << module->code_file() <<
114*9712c20fSFrederick Mayle                     " could not be stored";
115*9712c20fSFrederick Mayle   }
116*9712c20fSFrederick Mayle }
117*9712c20fSFrederick Mayle 
SetEnableModuleShrink(bool is_enabled)118*9712c20fSFrederick Mayle void MicrodumpModules::SetEnableModuleShrink(bool is_enabled) {
119*9712c20fSFrederick Mayle   map_.SetMergeStrategy(is_enabled ? MergeRangeStrategy::kTruncateUpper
120*9712c20fSFrederick Mayle                                    : MergeRangeStrategy::kExclusiveRanges);
121*9712c20fSFrederick Mayle }
122*9712c20fSFrederick Mayle 
123*9712c20fSFrederick Mayle //
124*9712c20fSFrederick Mayle // MicrodumpContext
125*9712c20fSFrederick Mayle //
126*9712c20fSFrederick Mayle 
SetContextARM(MDRawContextARM * arm)127*9712c20fSFrederick Mayle void MicrodumpContext::SetContextARM(MDRawContextARM* arm) {
128*9712c20fSFrederick Mayle   DumpContext::SetContextFlags(MD_CONTEXT_ARM);
129*9712c20fSFrederick Mayle   DumpContext::SetContextARM(arm);
130*9712c20fSFrederick Mayle   valid_ = true;
131*9712c20fSFrederick Mayle }
132*9712c20fSFrederick Mayle 
SetContextARM64(MDRawContextARM64 * arm64)133*9712c20fSFrederick Mayle void MicrodumpContext::SetContextARM64(MDRawContextARM64* arm64) {
134*9712c20fSFrederick Mayle   DumpContext::SetContextFlags(MD_CONTEXT_ARM64);
135*9712c20fSFrederick Mayle   DumpContext::SetContextARM64(arm64);
136*9712c20fSFrederick Mayle   valid_ = true;
137*9712c20fSFrederick Mayle }
138*9712c20fSFrederick Mayle 
SetContextX86(MDRawContextX86 * x86)139*9712c20fSFrederick Mayle void MicrodumpContext::SetContextX86(MDRawContextX86* x86) {
140*9712c20fSFrederick Mayle   DumpContext::SetContextFlags(MD_CONTEXT_X86);
141*9712c20fSFrederick Mayle   DumpContext::SetContextX86(x86);
142*9712c20fSFrederick Mayle   valid_ = true;
143*9712c20fSFrederick Mayle }
144*9712c20fSFrederick Mayle 
SetContextMIPS(MDRawContextMIPS * mips32)145*9712c20fSFrederick Mayle void MicrodumpContext::SetContextMIPS(MDRawContextMIPS* mips32) {
146*9712c20fSFrederick Mayle   DumpContext::SetContextFlags(MD_CONTEXT_MIPS);
147*9712c20fSFrederick Mayle   DumpContext::SetContextMIPS(mips32);
148*9712c20fSFrederick Mayle   valid_ = true;
149*9712c20fSFrederick Mayle }
150*9712c20fSFrederick Mayle 
SetContextMIPS64(MDRawContextMIPS * mips64)151*9712c20fSFrederick Mayle void MicrodumpContext::SetContextMIPS64(MDRawContextMIPS* mips64) {
152*9712c20fSFrederick Mayle   DumpContext::SetContextFlags(MD_CONTEXT_MIPS64);
153*9712c20fSFrederick Mayle   DumpContext::SetContextMIPS(mips64);
154*9712c20fSFrederick Mayle   valid_ = true;
155*9712c20fSFrederick Mayle }
156*9712c20fSFrederick Mayle 
157*9712c20fSFrederick Mayle 
158*9712c20fSFrederick Mayle //
159*9712c20fSFrederick Mayle // MicrodumpMemoryRegion
160*9712c20fSFrederick Mayle //
161*9712c20fSFrederick Mayle 
MicrodumpMemoryRegion()162*9712c20fSFrederick Mayle MicrodumpMemoryRegion::MicrodumpMemoryRegion() : base_address_(0) { }
163*9712c20fSFrederick Mayle 
Init(uint64_t base_address,const std::vector<uint8_t> & contents)164*9712c20fSFrederick Mayle void MicrodumpMemoryRegion::Init(uint64_t base_address,
165*9712c20fSFrederick Mayle                                  const std::vector<uint8_t>& contents) {
166*9712c20fSFrederick Mayle   base_address_ = base_address;
167*9712c20fSFrederick Mayle   contents_ = contents;
168*9712c20fSFrederick Mayle }
169*9712c20fSFrederick Mayle 
GetBase() const170*9712c20fSFrederick Mayle uint64_t MicrodumpMemoryRegion::GetBase() const { return base_address_; }
171*9712c20fSFrederick Mayle 
GetSize() const172*9712c20fSFrederick Mayle uint32_t MicrodumpMemoryRegion::GetSize() const { return contents_.size(); }
173*9712c20fSFrederick Mayle 
GetMemoryAtAddress(uint64_t address,uint8_t * value) const174*9712c20fSFrederick Mayle bool MicrodumpMemoryRegion::GetMemoryAtAddress(uint64_t address,
175*9712c20fSFrederick Mayle                                                uint8_t* value) const {
176*9712c20fSFrederick Mayle   return GetMemoryLittleEndian(address, value);
177*9712c20fSFrederick Mayle }
178*9712c20fSFrederick Mayle 
GetMemoryAtAddress(uint64_t address,uint16_t * value) const179*9712c20fSFrederick Mayle bool MicrodumpMemoryRegion::GetMemoryAtAddress(uint64_t address,
180*9712c20fSFrederick Mayle                                                uint16_t* value) const {
181*9712c20fSFrederick Mayle   return GetMemoryLittleEndian(address, value);
182*9712c20fSFrederick Mayle }
183*9712c20fSFrederick Mayle 
GetMemoryAtAddress(uint64_t address,uint32_t * value) const184*9712c20fSFrederick Mayle bool MicrodumpMemoryRegion::GetMemoryAtAddress(uint64_t address,
185*9712c20fSFrederick Mayle                                                uint32_t* value) const {
186*9712c20fSFrederick Mayle   return GetMemoryLittleEndian(address, value);
187*9712c20fSFrederick Mayle }
188*9712c20fSFrederick Mayle 
GetMemoryAtAddress(uint64_t address,uint64_t * value) const189*9712c20fSFrederick Mayle bool MicrodumpMemoryRegion::GetMemoryAtAddress(uint64_t address,
190*9712c20fSFrederick Mayle                                                uint64_t* value) const {
191*9712c20fSFrederick Mayle   return GetMemoryLittleEndian(address, value);
192*9712c20fSFrederick Mayle }
193*9712c20fSFrederick Mayle 
194*9712c20fSFrederick Mayle template<typename ValueType>
GetMemoryLittleEndian(uint64_t address,ValueType * value) const195*9712c20fSFrederick Mayle bool MicrodumpMemoryRegion::GetMemoryLittleEndian(uint64_t address,
196*9712c20fSFrederick Mayle                                                   ValueType* value) const {
197*9712c20fSFrederick Mayle   if (address < base_address_ ||
198*9712c20fSFrederick Mayle       address - base_address_ + sizeof(ValueType) > contents_.size())
199*9712c20fSFrederick Mayle     return false;
200*9712c20fSFrederick Mayle   ValueType v = 0;
201*9712c20fSFrederick Mayle   uint64_t start = address - base_address_;
202*9712c20fSFrederick Mayle   // The loop condition is odd, but it's correct for size_t.
203*9712c20fSFrederick Mayle   for (size_t i = sizeof(ValueType) - 1; i < sizeof(ValueType); i--)
204*9712c20fSFrederick Mayle     v = (v << 8) | static_cast<uint8_t>(contents_[start + i]);
205*9712c20fSFrederick Mayle   *value = v;
206*9712c20fSFrederick Mayle   return true;
207*9712c20fSFrederick Mayle }
208*9712c20fSFrederick Mayle 
Print() const209*9712c20fSFrederick Mayle void MicrodumpMemoryRegion::Print() const {
210*9712c20fSFrederick Mayle   // Not reached, just needed to honor the base class contract.
211*9712c20fSFrederick Mayle   assert(false);
212*9712c20fSFrederick Mayle }
213*9712c20fSFrederick Mayle 
214*9712c20fSFrederick Mayle //
215*9712c20fSFrederick Mayle // Microdump
216*9712c20fSFrederick Mayle //
Microdump(const string & contents)217*9712c20fSFrederick Mayle Microdump::Microdump(const string& contents)
218*9712c20fSFrederick Mayle   : context_(new MicrodumpContext()),
219*9712c20fSFrederick Mayle     stack_region_(new MicrodumpMemoryRegion()),
220*9712c20fSFrederick Mayle     modules_(new MicrodumpModules()),
221*9712c20fSFrederick Mayle     system_info_(new SystemInfo()),
222*9712c20fSFrederick Mayle     crash_reason_(),
223*9712c20fSFrederick Mayle     crash_address_(0u) {
224*9712c20fSFrederick Mayle   assert(!contents.empty());
225*9712c20fSFrederick Mayle 
226*9712c20fSFrederick Mayle   bool in_microdump = false;
227*9712c20fSFrederick Mayle   string line;
228*9712c20fSFrederick Mayle   uint64_t stack_start = 0;
229*9712c20fSFrederick Mayle   std::vector<uint8_t> stack_content;
230*9712c20fSFrederick Mayle   string arch;
231*9712c20fSFrederick Mayle 
232*9712c20fSFrederick Mayle   std::istringstream stream(contents);
233*9712c20fSFrederick Mayle   while (GetLine(&stream, &line)) {
234*9712c20fSFrederick Mayle     if (line.find(kGoogleBreakpadKey) == string::npos) {
235*9712c20fSFrederick Mayle       continue;
236*9712c20fSFrederick Mayle     }
237*9712c20fSFrederick Mayle     if (line.find(kMicrodumpBegin) != string::npos) {
238*9712c20fSFrederick Mayle       in_microdump = true;
239*9712c20fSFrederick Mayle       continue;
240*9712c20fSFrederick Mayle     }
241*9712c20fSFrederick Mayle     if (!in_microdump) {
242*9712c20fSFrederick Mayle       continue;
243*9712c20fSFrederick Mayle     }
244*9712c20fSFrederick Mayle     if (line.find(kMicrodumpEnd) != string::npos) {
245*9712c20fSFrederick Mayle       break;
246*9712c20fSFrederick Mayle     }
247*9712c20fSFrederick Mayle 
248*9712c20fSFrederick Mayle     size_t pos;
249*9712c20fSFrederick Mayle     if ((pos = line.find(kOsKey)) != string::npos) {
250*9712c20fSFrederick Mayle       string os_str(line, pos + strlen(kOsKey));
251*9712c20fSFrederick Mayle       std::istringstream os_tokens(os_str);
252*9712c20fSFrederick Mayle       string os_id;
253*9712c20fSFrederick Mayle       string num_cpus;
254*9712c20fSFrederick Mayle       string os_version;
255*9712c20fSFrederick Mayle       // This reflect the actual HW arch and might not match the arch emulated
256*9712c20fSFrederick Mayle       // for the execution (e.g., running a 32-bit binary on a 64-bit cpu).
257*9712c20fSFrederick Mayle       string hw_arch;
258*9712c20fSFrederick Mayle 
259*9712c20fSFrederick Mayle       os_tokens >> os_id;
260*9712c20fSFrederick Mayle       os_tokens >> arch;
261*9712c20fSFrederick Mayle       os_tokens >> num_cpus;
262*9712c20fSFrederick Mayle       os_tokens >> hw_arch;
263*9712c20fSFrederick Mayle       GetLine(&os_tokens, &os_version);
264*9712c20fSFrederick Mayle       os_version.erase(0, 1);  // remove leading space.
265*9712c20fSFrederick Mayle 
266*9712c20fSFrederick Mayle       system_info_->cpu = arch;
267*9712c20fSFrederick Mayle       system_info_->cpu_count = HexStrToL<uint8_t>(num_cpus);
268*9712c20fSFrederick Mayle       system_info_->os_version = os_version;
269*9712c20fSFrederick Mayle 
270*9712c20fSFrederick Mayle       if (os_id == "L") {
271*9712c20fSFrederick Mayle         system_info_->os = "Linux";
272*9712c20fSFrederick Mayle         system_info_->os_short = "linux";
273*9712c20fSFrederick Mayle       } else if (os_id == "A") {
274*9712c20fSFrederick Mayle         system_info_->os = "Android";
275*9712c20fSFrederick Mayle         system_info_->os_short = "android";
276*9712c20fSFrederick Mayle         modules_->SetEnableModuleShrink(true);
277*9712c20fSFrederick Mayle       }
278*9712c20fSFrederick Mayle 
279*9712c20fSFrederick Mayle       // OS line also contains release and version for future use.
280*9712c20fSFrederick Mayle     } else if ((pos = line.find(kStackKey)) != string::npos) {
281*9712c20fSFrederick Mayle       if (line.find(kStackFirstLineKey) != string::npos) {
282*9712c20fSFrederick Mayle         // The first line of the stack (S 0 stack header) provides the value of
283*9712c20fSFrederick Mayle         // the stack pointer, the start address of the stack being dumped and
284*9712c20fSFrederick Mayle         // the length of the stack. We could use it in future to double check
285*9712c20fSFrederick Mayle         // that we received all the stack as expected.
286*9712c20fSFrederick Mayle         continue;
287*9712c20fSFrederick Mayle       }
288*9712c20fSFrederick Mayle       string stack_str(line, pos + strlen(kStackKey));
289*9712c20fSFrederick Mayle       std::istringstream stack_tokens(stack_str);
290*9712c20fSFrederick Mayle       string start_addr_str;
291*9712c20fSFrederick Mayle       string raw_content;
292*9712c20fSFrederick Mayle       stack_tokens >> start_addr_str;
293*9712c20fSFrederick Mayle       stack_tokens >> raw_content;
294*9712c20fSFrederick Mayle       uint64_t start_addr = HexStrToL<uint64_t>(start_addr_str);
295*9712c20fSFrederick Mayle 
296*9712c20fSFrederick Mayle       if (stack_start != 0) {
297*9712c20fSFrederick Mayle         // Verify that the stack chunks in the microdump are contiguous.
298*9712c20fSFrederick Mayle         assert(start_addr == stack_start + stack_content.size());
299*9712c20fSFrederick Mayle       } else {
300*9712c20fSFrederick Mayle         stack_start = start_addr;
301*9712c20fSFrederick Mayle       }
302*9712c20fSFrederick Mayle       std::vector<uint8_t> chunk = ParseHexBuf(raw_content);
303*9712c20fSFrederick Mayle       stack_content.insert(stack_content.end(), chunk.begin(), chunk.end());
304*9712c20fSFrederick Mayle 
305*9712c20fSFrederick Mayle     } else if ((pos = line.find(kCpuKey)) != string::npos) {
306*9712c20fSFrederick Mayle       string cpu_state_str(line, pos + strlen(kCpuKey));
307*9712c20fSFrederick Mayle       std::vector<uint8_t> cpu_state_raw = ParseHexBuf(cpu_state_str);
308*9712c20fSFrederick Mayle       if (strcmp(arch.c_str(), kArmArchitecture) == 0) {
309*9712c20fSFrederick Mayle         if (cpu_state_raw.size() != sizeof(MDRawContextARM)) {
310*9712c20fSFrederick Mayle           std::cerr << "Malformed CPU context. Got " << cpu_state_raw.size()
311*9712c20fSFrederick Mayle                     << " bytes instead of " << sizeof(MDRawContextARM)
312*9712c20fSFrederick Mayle                     << std::endl;
313*9712c20fSFrederick Mayle           continue;
314*9712c20fSFrederick Mayle         }
315*9712c20fSFrederick Mayle         MDRawContextARM* arm = new MDRawContextARM();
316*9712c20fSFrederick Mayle         memcpy(arm, &cpu_state_raw[0], cpu_state_raw.size());
317*9712c20fSFrederick Mayle         context_->SetContextARM(arm);
318*9712c20fSFrederick Mayle       } else if (strcmp(arch.c_str(), kArm64Architecture) == 0) {
319*9712c20fSFrederick Mayle         if (cpu_state_raw.size() == sizeof(MDRawContextARM64)) {
320*9712c20fSFrederick Mayle           MDRawContextARM64* arm = new MDRawContextARM64();
321*9712c20fSFrederick Mayle           memcpy(arm, &cpu_state_raw[0], cpu_state_raw.size());
322*9712c20fSFrederick Mayle           context_->SetContextARM64(arm);
323*9712c20fSFrederick Mayle         } else if (cpu_state_raw.size() == sizeof(MDRawContextARM64_Old)) {
324*9712c20fSFrederick Mayle           MDRawContextARM64_Old old_arm;
325*9712c20fSFrederick Mayle           memcpy(&old_arm, &cpu_state_raw[0], cpu_state_raw.size());
326*9712c20fSFrederick Mayle           MDRawContextARM64* new_arm = new MDRawContextARM64();
327*9712c20fSFrederick Mayle           ConvertOldARM64Context(old_arm, new_arm);
328*9712c20fSFrederick Mayle           context_->SetContextARM64(new_arm);
329*9712c20fSFrederick Mayle         } else {
330*9712c20fSFrederick Mayle           std::cerr << "Malformed CPU context. Got " << cpu_state_raw.size()
331*9712c20fSFrederick Mayle                     << " bytes instead of " << sizeof(MDRawContextARM64)
332*9712c20fSFrederick Mayle                     << std::endl;
333*9712c20fSFrederick Mayle           continue;
334*9712c20fSFrederick Mayle         }
335*9712c20fSFrederick Mayle       } else if (strcmp(arch.c_str(), kX86Architecture) == 0) {
336*9712c20fSFrederick Mayle         if (cpu_state_raw.size() != sizeof(MDRawContextX86)) {
337*9712c20fSFrederick Mayle           std::cerr << "Malformed CPU context. Got " << cpu_state_raw.size()
338*9712c20fSFrederick Mayle                     << " bytes instead of " << sizeof(MDRawContextX86)
339*9712c20fSFrederick Mayle                     << std::endl;
340*9712c20fSFrederick Mayle           continue;
341*9712c20fSFrederick Mayle         }
342*9712c20fSFrederick Mayle         MDRawContextX86* x86 = new MDRawContextX86();
343*9712c20fSFrederick Mayle         memcpy(x86, &cpu_state_raw[0], cpu_state_raw.size());
344*9712c20fSFrederick Mayle         context_->SetContextX86(x86);
345*9712c20fSFrederick Mayle       } else if (strcmp(arch.c_str(), kMipsArchitecture) == 0) {
346*9712c20fSFrederick Mayle         if (cpu_state_raw.size() != sizeof(MDRawContextMIPS)) {
347*9712c20fSFrederick Mayle           std::cerr << "Malformed CPU context. Got " << cpu_state_raw.size()
348*9712c20fSFrederick Mayle                     << " bytes instead of " << sizeof(MDRawContextMIPS)
349*9712c20fSFrederick Mayle                     << std::endl;
350*9712c20fSFrederick Mayle           continue;
351*9712c20fSFrederick Mayle         }
352*9712c20fSFrederick Mayle         MDRawContextMIPS* mips32 = new MDRawContextMIPS();
353*9712c20fSFrederick Mayle         memcpy(mips32, &cpu_state_raw[0], cpu_state_raw.size());
354*9712c20fSFrederick Mayle         context_->SetContextMIPS(mips32);
355*9712c20fSFrederick Mayle       } else if (strcmp(arch.c_str(), kMips64Architecture) == 0) {
356*9712c20fSFrederick Mayle         if (cpu_state_raw.size() != sizeof(MDRawContextMIPS)) {
357*9712c20fSFrederick Mayle           std::cerr << "Malformed CPU context. Got " << cpu_state_raw.size()
358*9712c20fSFrederick Mayle                     << " bytes instead of " << sizeof(MDRawContextMIPS)
359*9712c20fSFrederick Mayle                     << std::endl;
360*9712c20fSFrederick Mayle           continue;
361*9712c20fSFrederick Mayle         }
362*9712c20fSFrederick Mayle         MDRawContextMIPS* mips64 = new MDRawContextMIPS();
363*9712c20fSFrederick Mayle         memcpy(mips64, &cpu_state_raw[0], cpu_state_raw.size());
364*9712c20fSFrederick Mayle         context_->SetContextMIPS64(mips64);
365*9712c20fSFrederick Mayle       } else {
366*9712c20fSFrederick Mayle         std::cerr << "Unsupported architecture: " << arch << std::endl;
367*9712c20fSFrederick Mayle       }
368*9712c20fSFrederick Mayle     } else if ((pos = line.find(kCrashReasonKey)) != string::npos) {
369*9712c20fSFrederick Mayle       string crash_reason_str(line, pos + strlen(kCrashReasonKey));
370*9712c20fSFrederick Mayle       std::istringstream crash_reason_tokens(crash_reason_str);
371*9712c20fSFrederick Mayle       string signal;
372*9712c20fSFrederick Mayle       string address;
373*9712c20fSFrederick Mayle       crash_reason_tokens >> signal;
374*9712c20fSFrederick Mayle       crash_reason_tokens >> crash_reason_;
375*9712c20fSFrederick Mayle       crash_reason_tokens >> address;
376*9712c20fSFrederick Mayle       crash_address_ = HexStrToL<uint64_t>(address);
377*9712c20fSFrederick Mayle     } else if ((pos = line.find(kGpuKey)) != string::npos) {
378*9712c20fSFrederick Mayle       string gpu_str(line, pos + strlen(kGpuKey));
379*9712c20fSFrederick Mayle       if (strcmp(gpu_str.c_str(), kGpuUnknown) != 0) {
380*9712c20fSFrederick Mayle         std::istringstream gpu_tokens(gpu_str);
381*9712c20fSFrederick Mayle         std::getline(gpu_tokens, system_info_->gl_version, '|');
382*9712c20fSFrederick Mayle         std::getline(gpu_tokens, system_info_->gl_vendor, '|');
383*9712c20fSFrederick Mayle         std::getline(gpu_tokens, system_info_->gl_renderer, '|');
384*9712c20fSFrederick Mayle       }
385*9712c20fSFrederick Mayle     } else if ((pos = line.find(kMmapKey)) != string::npos) {
386*9712c20fSFrederick Mayle       string mmap_line(line, pos + strlen(kMmapKey));
387*9712c20fSFrederick Mayle       std::istringstream mmap_tokens(mmap_line);
388*9712c20fSFrederick Mayle       string addr, offset, size, identifier, filename;
389*9712c20fSFrederick Mayle       mmap_tokens >> addr;
390*9712c20fSFrederick Mayle       mmap_tokens >> offset;
391*9712c20fSFrederick Mayle       mmap_tokens >> size;
392*9712c20fSFrederick Mayle       mmap_tokens >> identifier;
393*9712c20fSFrederick Mayle       mmap_tokens >> filename;
394*9712c20fSFrederick Mayle 
395*9712c20fSFrederick Mayle       modules_->Add(new BasicCodeModule(
396*9712c20fSFrederick Mayle           HexStrToL<uint64_t>(addr),  // base_address
397*9712c20fSFrederick Mayle           HexStrToL<uint64_t>(size),  // size
398*9712c20fSFrederick Mayle           filename,                   // code_file
399*9712c20fSFrederick Mayle           identifier,                 // code_identifier
400*9712c20fSFrederick Mayle           filename,                   // debug_file
401*9712c20fSFrederick Mayle           identifier,                 // debug_identifier
402*9712c20fSFrederick Mayle           ""));                       // version
403*9712c20fSFrederick Mayle     }
404*9712c20fSFrederick Mayle   }
405*9712c20fSFrederick Mayle   stack_region_->Init(stack_start, stack_content);
406*9712c20fSFrederick Mayle }
407*9712c20fSFrederick Mayle 
408*9712c20fSFrederick Mayle }  // namespace google_breakpad
409