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 // This code writes out minidump files:
31 //   http://msdn.microsoft.com/en-us/library/ms680378(VS.85,loband).aspx
32 //
33 // Minidumps are a Microsoft format which Breakpad uses for recording crash
34 // dumps. This code has to run in a compromised environment (the address space
35 // may have received SIGSEGV), thus the following rules apply:
36 //   * You may not enter the dynamic linker. This means that we cannot call
37 //     any symbols in a shared library (inc libc). Because of this we replace
38 //     libc functions in linux_libc_support.h.
39 //   * You may not call syscalls via the libc wrappers. This rule is a subset
40 //     of the first rule but it bears repeating. We have direct wrappers
41 //     around the system calls in linux_syscall_support.h.
42 //   * You may not malloc. There's an alternative allocator in memory.h and
43 //     a canonical instance in the LinuxDumper object. We use the placement
44 //     new form to allocate objects and we don't delete them.
45 
46 #include "linux/handler/minidump_descriptor.h"
47 #include "linux/minidump_writer/minidump_writer.h"
48 #include "minidump_file_writer-inl.h"
49 
50 #include <ctype.h>
51 #include <errno.h>
52 #include <fcntl.h>
53 #include <link.h>
54 #include <stdio.h>
55 #if defined(__ANDROID__)
56 #include <sys/system_properties.h>
57 #endif
58 #include <sys/types.h>
59 #include <sys/ucontext.h>
60 #include <sys/user.h>
61 #include <sys/utsname.h>
62 #include <time.h>
63 #include <unistd.h>
64 
65 #include <algorithm>
66 
67 #include "linux/dump_writer_common/thread_info.h"
68 #include "linux/dump_writer_common/ucontext_reader.h"
69 #include "linux/handler/exception_handler.h"
70 #include "linux/minidump_writer/cpu_set.h"
71 #include "linux/minidump_writer/line_reader.h"
72 #include "linux/minidump_writer/linux_dumper.h"
73 #include "linux/minidump_writer/linux_ptrace_dumper.h"
74 #include "linux/minidump_writer/proc_cpuinfo_reader.h"
75 #include "minidump_file_writer.h"
76 #include "common/linux/file_id.h"
77 #include "common/linux/linux_libc_support.h"
78 #include "common/minidump_type_helper.h"
79 #include "google_breakpad/common/minidump_format.h"
80 #include "third_party/lss/linux_syscall_support.h"
81 
82 namespace {
83 
84 using google_breakpad::AppMemoryList;
85 using google_breakpad::auto_wasteful_vector;
86 using google_breakpad::ExceptionHandler;
87 using google_breakpad::CpuSet;
88 using google_breakpad::kDefaultBuildIdSize;
89 using google_breakpad::LineReader;
90 using google_breakpad::LinuxDumper;
91 using google_breakpad::LinuxPtraceDumper;
92 using google_breakpad::MDTypeHelper;
93 using google_breakpad::MappingEntry;
94 using google_breakpad::MappingInfo;
95 using google_breakpad::MappingList;
96 using google_breakpad::MinidumpFileWriter;
97 using google_breakpad::PageAllocator;
98 using google_breakpad::ProcCpuInfoReader;
99 using google_breakpad::RawContextCPU;
100 using google_breakpad::ThreadInfo;
101 using google_breakpad::TypedMDRVA;
102 using google_breakpad::UContextReader;
103 using google_breakpad::UntypedMDRVA;
104 using google_breakpad::wasteful_vector;
105 
106 typedef MDTypeHelper<sizeof(void*)>::MDRawDebug MDRawDebug;
107 typedef MDTypeHelper<sizeof(void*)>::MDRawLinkMap MDRawLinkMap;
108 
109 class MinidumpWriter {
110  public:
111   // The following kLimit* constants are for when minidump_size_limit_ is set
112   // and the minidump size might exceed it.
113   //
114   // Estimate for how big each thread's stack will be (in bytes).
115   static const unsigned kLimitAverageThreadStackLength = 8 * 1024;
116   // Number of threads whose stack size we don't want to limit.  These base
117   // threads will simply be the first N threads returned by the dumper (although
118   // the crashing thread will never be limited).  Threads beyond this count are
119   // the extra threads.
120   static const unsigned kLimitBaseThreadCount = 20;
121   // Maximum stack size to dump for any extra thread (in bytes).
122   static const unsigned kLimitMaxExtraThreadStackLen = 2 * 1024;
123   // Make sure this number of additional bytes can fit in the minidump
124   // (exclude the stack data).
125   static const unsigned kLimitMinidumpFudgeFactor = 64 * 1024;
126 
MinidumpWriter(const char * minidump_path,int minidump_fd,const ExceptionHandler::CrashContext * context,const MappingList & mappings,const AppMemoryList & appmem,bool skip_stacks_if_mapping_unreferenced,uintptr_t principal_mapping_address,bool sanitize_stacks,LinuxDumper * dumper)127   MinidumpWriter(const char* minidump_path,
128                  int minidump_fd,
129                  const ExceptionHandler::CrashContext* context,
130                  const MappingList& mappings,
131                  const AppMemoryList& appmem,
132                  bool skip_stacks_if_mapping_unreferenced,
133                  uintptr_t principal_mapping_address,
134                  bool sanitize_stacks,
135                  LinuxDumper* dumper)
136       : fd_(minidump_fd),
137         path_(minidump_path),
138         ucontext_(context ? &context->context : NULL),
139 #if !defined(__ARM_EABI__) && !defined(__mips__)
140         float_state_(context ? &context->float_state : NULL),
141 #endif
142         dumper_(dumper),
143         minidump_size_limit_(-1),
144         memory_blocks_(dumper_->allocator()),
145         mapping_list_(mappings),
146         app_memory_list_(appmem),
147         skip_stacks_if_mapping_unreferenced_(
148             skip_stacks_if_mapping_unreferenced),
149         principal_mapping_address_(principal_mapping_address),
150         principal_mapping_(nullptr),
151     sanitize_stacks_(sanitize_stacks) {
152     // Assert there should be either a valid fd or a valid path, not both.
153     assert(fd_ != -1 || minidump_path);
154     assert(fd_ == -1 || !minidump_path);
155   }
156 
Init()157   bool Init() {
158     if (!dumper_->Init())
159       return false;
160 
161     if (!dumper_->ThreadsSuspend() || !dumper_->LateInit())
162       return false;
163 
164     if (skip_stacks_if_mapping_unreferenced_) {
165       principal_mapping_ =
166           dumper_->FindMappingNoBias(principal_mapping_address_);
167       if (!CrashingThreadReferencesPrincipalMapping())
168         return false;
169     }
170 
171     if (fd_ != -1)
172       minidump_writer_.SetFile(fd_);
173     else if (!minidump_writer_.Open(path_))
174       return false;
175 
176     return true;
177   }
178 
~MinidumpWriter()179   ~MinidumpWriter() {
180     // Don't close the file descriptor when it's been provided explicitly.
181     // Callers might still need to use it.
182     if (fd_ == -1)
183       minidump_writer_.Close();
184     dumper_->ThreadsResume();
185   }
186 
CrashingThreadReferencesPrincipalMapping()187   bool CrashingThreadReferencesPrincipalMapping() {
188     if (!ucontext_ || !principal_mapping_)
189       return false;
190 
191     const uintptr_t low_addr =
192         principal_mapping_->system_mapping_info.start_addr;
193     const uintptr_t high_addr =
194         principal_mapping_->system_mapping_info.end_addr;
195 
196     const uintptr_t stack_pointer = UContextReader::GetStackPointer(ucontext_);
197     const uintptr_t pc = UContextReader::GetInstructionPointer(ucontext_);
198 
199     if (pc >= low_addr && pc < high_addr)
200       return true;
201 
202     uint8_t* stack_copy;
203     const void* stack;
204     size_t stack_len;
205 
206     if (!dumper_->GetStackInfo(&stack, &stack_len, stack_pointer))
207       return false;
208 
209     stack_copy = reinterpret_cast<uint8_t*>(Alloc(stack_len));
210     dumper_->CopyFromProcess(stack_copy, GetCrashThread(), stack, stack_len);
211 
212     uintptr_t stack_pointer_offset =
213         stack_pointer - reinterpret_cast<uintptr_t>(stack);
214 
215     return dumper_->StackHasPointerToMapping(
216         stack_copy, stack_len, stack_pointer_offset, *principal_mapping_);
217   }
218 
Dump()219   bool Dump() {
220     // A minidump file contains a number of tagged streams. This is the number
221     // of stream which we write.
222     unsigned kNumWriters = 13;
223 
224     TypedMDRVA<MDRawDirectory> dir(&minidump_writer_);
225     {
226       // Ensure the header gets flushed, as that happens in the destructor.
227       // If we crash somewhere below, we should have a mostly-intact dump
228       TypedMDRVA<MDRawHeader> header(&minidump_writer_);
229       if (!header.Allocate())
230         return false;
231 
232       if (!dir.AllocateArray(kNumWriters))
233         return false;
234 
235       my_memset(header.get(), 0, sizeof(MDRawHeader));
236 
237       header.get()->signature = MD_HEADER_SIGNATURE;
238       header.get()->version = MD_HEADER_VERSION;
239       header.get()->time_date_stamp = time(NULL);
240       header.get()->stream_count = kNumWriters;
241       header.get()->stream_directory_rva = dir.position();
242     }
243 
244     unsigned dir_index = 0;
245     MDRawDirectory dirent;
246 
247     if (!WriteThreadListStream(&dirent))
248       return false;
249     dir.CopyIndex(dir_index++, &dirent);
250 
251     if (!WriteMappings(&dirent))
252       return false;
253     dir.CopyIndex(dir_index++, &dirent);
254 
255     if (!WriteAppMemory())
256       return false;
257 
258     if (!WriteMemoryListStream(&dirent))
259       return false;
260     dir.CopyIndex(dir_index++, &dirent);
261 
262     if (!WriteExceptionStream(&dirent))
263       return false;
264     dir.CopyIndex(dir_index++, &dirent);
265 
266     if (!WriteSystemInfoStream(&dirent))
267       return false;
268     dir.CopyIndex(dir_index++, &dirent);
269 
270     dirent.stream_type = MD_LINUX_CPU_INFO;
271     if (!WriteFile(&dirent.location, "/proc/cpuinfo"))
272       NullifyDirectoryEntry(&dirent);
273     dir.CopyIndex(dir_index++, &dirent);
274 
275     dirent.stream_type = MD_LINUX_PROC_STATUS;
276     if (!WriteProcFile(&dirent.location, GetCrashThread(), "status"))
277       NullifyDirectoryEntry(&dirent);
278     dir.CopyIndex(dir_index++, &dirent);
279 
280     dirent.stream_type = MD_LINUX_LSB_RELEASE;
281     if (!WriteFile(&dirent.location, "/etc/lsb-release") &&
282         !WriteFile(&dirent.location, "/etc/os-release")) {
283       NullifyDirectoryEntry(&dirent);
284     }
285     dir.CopyIndex(dir_index++, &dirent);
286 
287     dirent.stream_type = MD_LINUX_CMD_LINE;
288     if (!WriteProcFile(&dirent.location, GetCrashThread(), "cmdline"))
289       NullifyDirectoryEntry(&dirent);
290     dir.CopyIndex(dir_index++, &dirent);
291 
292     dirent.stream_type = MD_LINUX_ENVIRON;
293     if (!WriteProcFile(&dirent.location, GetCrashThread(), "environ"))
294       NullifyDirectoryEntry(&dirent);
295     dir.CopyIndex(dir_index++, &dirent);
296 
297     dirent.stream_type = MD_LINUX_AUXV;
298     if (!WriteProcFile(&dirent.location, GetCrashThread(), "auxv"))
299       NullifyDirectoryEntry(&dirent);
300     dir.CopyIndex(dir_index++, &dirent);
301 
302     dirent.stream_type = MD_LINUX_MAPS;
303     if (!WriteProcFile(&dirent.location, GetCrashThread(), "maps"))
304       NullifyDirectoryEntry(&dirent);
305     dir.CopyIndex(dir_index++, &dirent);
306 
307     dirent.stream_type = MD_LINUX_DSO_DEBUG;
308     if (!WriteDSODebugStream(&dirent))
309       NullifyDirectoryEntry(&dirent);
310     dir.CopyIndex(dir_index++, &dirent);
311 
312     // If you add more directory entries, don't forget to update kNumWriters,
313     // above.
314 
315     dumper_->ThreadsResume();
316     return true;
317   }
318 
FillThreadStack(MDRawThread * thread,uintptr_t stack_pointer,uintptr_t pc,int max_stack_len,uint8_t ** stack_copy)319   bool FillThreadStack(MDRawThread* thread, uintptr_t stack_pointer,
320                        uintptr_t pc, int max_stack_len, uint8_t** stack_copy) {
321     *stack_copy = NULL;
322     const void* stack;
323     size_t stack_len;
324 
325     thread->stack.start_of_memory_range = stack_pointer;
326     thread->stack.memory.data_size = 0;
327     thread->stack.memory.rva = minidump_writer_.position();
328 
329     if (dumper_->GetStackInfo(&stack, &stack_len, stack_pointer)) {
330       if (max_stack_len >= 0 &&
331           stack_len > static_cast<unsigned int>(max_stack_len)) {
332         stack_len = max_stack_len;
333         // Skip empty chunks of length max_stack_len.
334         uintptr_t int_stack = reinterpret_cast<uintptr_t>(stack);
335         if (max_stack_len > 0) {
336           while (int_stack + max_stack_len < stack_pointer) {
337             int_stack += max_stack_len;
338           }
339         }
340         stack = reinterpret_cast<const void*>(int_stack);
341       }
342       *stack_copy = reinterpret_cast<uint8_t*>(Alloc(stack_len));
343       dumper_->CopyFromProcess(*stack_copy, thread->thread_id, stack,
344                                stack_len);
345 
346       uintptr_t stack_pointer_offset =
347           stack_pointer - reinterpret_cast<uintptr_t>(stack);
348       if (skip_stacks_if_mapping_unreferenced_) {
349         if (!principal_mapping_) {
350           return true;
351         }
352         uintptr_t low_addr = principal_mapping_->system_mapping_info.start_addr;
353         uintptr_t high_addr = principal_mapping_->system_mapping_info.end_addr;
354         if ((pc < low_addr || pc > high_addr) &&
355             !dumper_->StackHasPointerToMapping(*stack_copy, stack_len,
356                                                stack_pointer_offset,
357                                                *principal_mapping_)) {
358           return true;
359         }
360       }
361 
362       if (sanitize_stacks_) {
363         dumper_->SanitizeStackCopy(*stack_copy, stack_len, stack_pointer,
364                                    stack_pointer_offset);
365       }
366 
367       UntypedMDRVA memory(&minidump_writer_);
368       if (!memory.Allocate(stack_len))
369         return false;
370       memory.Copy(*stack_copy, stack_len);
371       thread->stack.start_of_memory_range = reinterpret_cast<uintptr_t>(stack);
372       thread->stack.memory = memory.location();
373       memory_blocks_.push_back(thread->stack);
374     }
375     return true;
376   }
377 
378   // Write information about the threads.
WriteThreadListStream(MDRawDirectory * dirent)379   bool WriteThreadListStream(MDRawDirectory* dirent) {
380     const unsigned num_threads = dumper_->threads().size();
381 
382     TypedMDRVA<uint32_t> list(&minidump_writer_);
383     if (!list.AllocateObjectAndArray(num_threads, sizeof(MDRawThread)))
384       return false;
385 
386     dirent->stream_type = MD_THREAD_LIST_STREAM;
387     dirent->location = list.location();
388 
389     *list.get() = num_threads;
390 
391     // If there's a minidump size limit, check if it might be exceeded.  Since
392     // most of the space is filled with stack data, just check against that.
393     // If this expects to exceed the limit, set extra_thread_stack_len such
394     // that any thread beyond the first kLimitBaseThreadCount threads will
395     // have only kLimitMaxExtraThreadStackLen bytes dumped.
396     int extra_thread_stack_len = -1;  // default to no maximum
397     if (minidump_size_limit_ >= 0) {
398       const unsigned estimated_total_stack_size = num_threads *
399           kLimitAverageThreadStackLength;
400       const off_t estimated_minidump_size = minidump_writer_.position() +
401           estimated_total_stack_size + kLimitMinidumpFudgeFactor;
402       if (estimated_minidump_size > minidump_size_limit_)
403         extra_thread_stack_len = kLimitMaxExtraThreadStackLen;
404     }
405 
406     for (unsigned i = 0; i < num_threads; ++i) {
407       MDRawThread thread;
408       my_memset(&thread, 0, sizeof(thread));
409       thread.thread_id = dumper_->threads()[i];
410 
411       // We have a different source of information for the crashing thread. If
412       // we used the actual state of the thread we would find it running in the
413       // signal handler with the alternative stack, which would be deeply
414       // unhelpful.
415       if (static_cast<pid_t>(thread.thread_id) == GetCrashThread() &&
416           ucontext_ &&
417           !dumper_->IsPostMortem()) {
418         uint8_t* stack_copy;
419         const uintptr_t stack_ptr = UContextReader::GetStackPointer(ucontext_);
420         if (!FillThreadStack(&thread, stack_ptr,
421                              UContextReader::GetInstructionPointer(ucontext_),
422                              -1, &stack_copy))
423           return false;
424 
425         // Copy 256 bytes around crashing instruction pointer to minidump.
426         const size_t kIPMemorySize = 256;
427         uint64_t ip = UContextReader::GetInstructionPointer(ucontext_);
428         // Bound it to the upper and lower bounds of the memory map
429         // it's contained within. If it's not in mapped memory,
430         // don't bother trying to write it.
431         bool ip_is_mapped = false;
432         MDMemoryDescriptor ip_memory_d;
433         for (unsigned j = 0; j < dumper_->mappings().size(); ++j) {
434           const MappingInfo& mapping = *dumper_->mappings()[j];
435           if (ip >= mapping.start_addr &&
436               ip < mapping.start_addr + mapping.size) {
437             ip_is_mapped = true;
438             // Try to get 128 bytes before and after the IP, but
439             // settle for whatever's available.
440             ip_memory_d.start_of_memory_range =
441               std::max(mapping.start_addr,
442                        uintptr_t(ip - (kIPMemorySize / 2)));
443             uintptr_t end_of_range =
444               std::min(uintptr_t(ip + (kIPMemorySize / 2)),
445                        uintptr_t(mapping.start_addr + mapping.size));
446             ip_memory_d.memory.data_size =
447               end_of_range - ip_memory_d.start_of_memory_range;
448             break;
449           }
450         }
451 
452         if (ip_is_mapped) {
453           UntypedMDRVA ip_memory(&minidump_writer_);
454           if (!ip_memory.Allocate(ip_memory_d.memory.data_size))
455             return false;
456           uint8_t* memory_copy =
457               reinterpret_cast<uint8_t*>(Alloc(ip_memory_d.memory.data_size));
458           dumper_->CopyFromProcess(
459               memory_copy,
460               thread.thread_id,
461               reinterpret_cast<void*>(ip_memory_d.start_of_memory_range),
462               ip_memory_d.memory.data_size);
463           ip_memory.Copy(memory_copy, ip_memory_d.memory.data_size);
464           ip_memory_d.memory = ip_memory.location();
465           memory_blocks_.push_back(ip_memory_d);
466         }
467 
468         TypedMDRVA<RawContextCPU> cpu(&minidump_writer_);
469         if (!cpu.Allocate())
470           return false;
471         my_memset(cpu.get(), 0, sizeof(RawContextCPU));
472 #if !defined(__ARM_EABI__) && !defined(__mips__)
473         UContextReader::FillCPUContext(cpu.get(), ucontext_, float_state_);
474 #else
475         UContextReader::FillCPUContext(cpu.get(), ucontext_);
476 #endif
477         thread.thread_context = cpu.location();
478         crashing_thread_context_ = cpu.location();
479       } else {
480         ThreadInfo info;
481         if (!dumper_->GetThreadInfoByIndex(i, &info))
482           return false;
483 
484         uint8_t* stack_copy;
485         int max_stack_len = -1;  // default to no maximum for this thread
486         if (minidump_size_limit_ >= 0 && i >= kLimitBaseThreadCount)
487           max_stack_len = extra_thread_stack_len;
488         if (!FillThreadStack(&thread, info.stack_pointer,
489                              info.GetInstructionPointer(), max_stack_len,
490                              &stack_copy))
491           return false;
492 
493         TypedMDRVA<RawContextCPU> cpu(&minidump_writer_);
494         if (!cpu.Allocate())
495           return false;
496         my_memset(cpu.get(), 0, sizeof(RawContextCPU));
497         info.FillCPUContext(cpu.get());
498         thread.thread_context = cpu.location();
499         if (dumper_->threads()[i] == GetCrashThread()) {
500           crashing_thread_context_ = cpu.location();
501           if (!dumper_->IsPostMortem()) {
502             // This is the crashing thread of a live process, but
503             // no context was provided, so set the crash address
504             // while the instruction pointer is already here.
505             dumper_->set_crash_address(info.GetInstructionPointer());
506           }
507         }
508       }
509 
510       list.CopyIndexAfterObject(i, &thread, sizeof(thread));
511     }
512 
513     return true;
514   }
515 
516   // Write application-provided memory regions.
WriteAppMemory()517   bool WriteAppMemory() {
518     for (AppMemoryList::const_iterator iter = app_memory_list_.begin();
519          iter != app_memory_list_.end();
520          ++iter) {
521       uint8_t* data_copy =
522         reinterpret_cast<uint8_t*>(dumper_->allocator()->Alloc(iter->length));
523       dumper_->CopyFromProcess(data_copy, GetCrashThread(), iter->ptr,
524                                iter->length);
525 
526       UntypedMDRVA memory(&minidump_writer_);
527       if (!memory.Allocate(iter->length)) {
528         return false;
529       }
530       memory.Copy(data_copy, iter->length);
531       MDMemoryDescriptor desc;
532       desc.start_of_memory_range = reinterpret_cast<uintptr_t>(iter->ptr);
533       desc.memory = memory.location();
534       memory_blocks_.push_back(desc);
535     }
536 
537     return true;
538   }
539 
ShouldIncludeMapping(const MappingInfo & mapping)540   static bool ShouldIncludeMapping(const MappingInfo& mapping) {
541     if (mapping.name[0] == 0 ||  // only want modules with filenames.
542         // Only want to include one mapping per shared lib.
543         // Avoid filtering executable mappings.
544         (mapping.offset != 0 && !mapping.exec) ||
545         mapping.size < 4096) {  // too small to get a signature for.
546       return false;
547     }
548 
549     return true;
550   }
551 
552   // If there is caller-provided information about this mapping
553   // in the mapping_list_ list, return true. Otherwise, return false.
HaveMappingInfo(const MappingInfo & mapping)554   bool HaveMappingInfo(const MappingInfo& mapping) {
555     for (MappingList::const_iterator iter = mapping_list_.begin();
556          iter != mapping_list_.end();
557          ++iter) {
558       // Ignore any mappings that are wholly contained within
559       // mappings in the mapping_info_ list.
560       if (mapping.start_addr >= iter->first.start_addr &&
561           (mapping.start_addr + mapping.size) <=
562           (iter->first.start_addr + iter->first.size)) {
563         return true;
564       }
565     }
566     return false;
567   }
568 
569   // Write information about the mappings in effect. Because we are using the
570   // minidump format, the information about the mappings is pretty limited.
571   // Because of this, we also include the full, unparsed, /proc/$x/maps file in
572   // another stream in the file.
WriteMappings(MDRawDirectory * dirent)573   bool WriteMappings(MDRawDirectory* dirent) {
574     const unsigned num_mappings = dumper_->mappings().size();
575     unsigned num_output_mappings = mapping_list_.size();
576 
577     for (unsigned i = 0; i < dumper_->mappings().size(); ++i) {
578       const MappingInfo& mapping = *dumper_->mappings()[i];
579       if (ShouldIncludeMapping(mapping) && !HaveMappingInfo(mapping))
580         num_output_mappings++;
581     }
582 
583     TypedMDRVA<uint32_t> list(&minidump_writer_);
584     if (num_output_mappings) {
585       if (!list.AllocateObjectAndArray(num_output_mappings, MD_MODULE_SIZE))
586         return false;
587     } else {
588       // Still create the module list stream, although it will have zero
589       // modules.
590       if (!list.Allocate())
591         return false;
592     }
593 
594     dirent->stream_type = MD_MODULE_LIST_STREAM;
595     dirent->location = list.location();
596     *list.get() = num_output_mappings;
597 
598     // First write all the mappings from the dumper
599     unsigned int j = 0;
600     for (unsigned i = 0; i < num_mappings; ++i) {
601       const MappingInfo& mapping = *dumper_->mappings()[i];
602       if (!ShouldIncludeMapping(mapping) || HaveMappingInfo(mapping))
603         continue;
604 
605       MDRawModule mod;
606       if (!FillRawModule(mapping, true, i, &mod, NULL))
607         return false;
608       list.CopyIndexAfterObject(j++, &mod, MD_MODULE_SIZE);
609     }
610     // Next write all the mappings provided by the caller
611     for (MappingList::const_iterator iter = mapping_list_.begin();
612          iter != mapping_list_.end();
613          ++iter) {
614       MDRawModule mod;
615       if (!FillRawModule(iter->first, false, 0, &mod, &iter->second)) {
616         return false;
617       }
618       list.CopyIndexAfterObject(j++, &mod, MD_MODULE_SIZE);
619     }
620 
621     return true;
622   }
623 
624   // Fill the MDRawModule |mod| with information about the provided
625   // |mapping|. If |identifier| is non-NULL, use it instead of calculating
626   // a file ID from the mapping.
FillRawModule(const MappingInfo & mapping,bool member,unsigned int mapping_id,MDRawModule * mod,const std::vector<uint8_t> * identifier)627   bool FillRawModule(const MappingInfo& mapping,
628                      bool member,
629                      unsigned int mapping_id,
630                      MDRawModule* mod,
631                      const std::vector<uint8_t>* identifier) {
632     my_memset(mod, 0, MD_MODULE_SIZE);
633 
634     mod->base_of_image = mapping.start_addr;
635     mod->size_of_image = mapping.size;
636 
637     auto_wasteful_vector<uint8_t, kDefaultBuildIdSize> identifier_bytes(
638         dumper_->allocator());
639 
640     if (identifier) {
641       // GUID was provided by caller.
642       identifier_bytes.insert(identifier_bytes.end(),
643                               identifier->begin(),
644                               identifier->end());
645     } else {
646       // Note: ElfFileIdentifierForMapping() can manipulate the |mapping.name|.
647       dumper_->ElfFileIdentifierForMapping(mapping,
648                                            member,
649                                            mapping_id,
650                                            identifier_bytes);
651     }
652 
653     if (!identifier_bytes.empty()) {
654       UntypedMDRVA cv(&minidump_writer_);
655       if (!cv.Allocate(MDCVInfoELF_minsize + identifier_bytes.size()))
656         return false;
657 
658       const uint32_t cv_signature = MD_CVINFOELF_SIGNATURE;
659       cv.Copy(&cv_signature, sizeof(cv_signature));
660       cv.Copy(cv.position() + sizeof(cv_signature), &identifier_bytes[0],
661               identifier_bytes.size());
662 
663       mod->cv_record = cv.location();
664     }
665 
666     char file_name[NAME_MAX];
667     char file_path[NAME_MAX];
668     dumper_->GetMappingEffectiveNameAndPath(
669         mapping, file_path, sizeof(file_path), file_name, sizeof(file_name));
670 
671     MDLocationDescriptor ld;
672     if (!minidump_writer_.WriteString(file_path, my_strlen(file_path), &ld))
673       return false;
674     mod->module_name_rva = ld.rva;
675     return true;
676   }
677 
WriteMemoryListStream(MDRawDirectory * dirent)678   bool WriteMemoryListStream(MDRawDirectory* dirent) {
679     TypedMDRVA<uint32_t> list(&minidump_writer_);
680     if (!memory_blocks_.empty()) {
681       if (!list.AllocateObjectAndArray(memory_blocks_.size(),
682                                        sizeof(MDMemoryDescriptor)))
683         return false;
684     } else {
685       // Still create the memory list stream, although it will have zero
686       // memory blocks.
687       if (!list.Allocate())
688         return false;
689     }
690 
691     dirent->stream_type = MD_MEMORY_LIST_STREAM;
692     dirent->location = list.location();
693 
694     *list.get() = memory_blocks_.size();
695 
696     for (size_t i = 0; i < memory_blocks_.size(); ++i) {
697       list.CopyIndexAfterObject(i, &memory_blocks_[i],
698                                 sizeof(MDMemoryDescriptor));
699     }
700     return true;
701   }
702 
WriteExceptionStream(MDRawDirectory * dirent)703   bool WriteExceptionStream(MDRawDirectory* dirent) {
704     TypedMDRVA<MDRawExceptionStream> exc(&minidump_writer_);
705     if (!exc.Allocate())
706       return false;
707 
708     MDRawExceptionStream* stream = exc.get();
709     my_memset(stream, 0, sizeof(MDRawExceptionStream));
710 
711     dirent->stream_type = MD_EXCEPTION_STREAM;
712     dirent->location = exc.location();
713 
714     stream->thread_id = GetCrashThread();
715     stream->exception_record.exception_code = dumper_->crash_signal();
716     stream->exception_record.exception_flags = dumper_->crash_signal_code();
717     stream->exception_record.exception_address = dumper_->crash_address();
718     const std::vector<uint64_t> crash_exception_info =
719         dumper_->crash_exception_info();
720     stream->exception_record.number_parameters = crash_exception_info.size();
721     memcpy(stream->exception_record.exception_information,
722            crash_exception_info.data(),
723            sizeof(uint64_t) * crash_exception_info.size());
724     stream->thread_context = crashing_thread_context_;
725 
726     return true;
727   }
728 
WriteSystemInfoStream(MDRawDirectory * dirent)729   bool WriteSystemInfoStream(MDRawDirectory* dirent) {
730     TypedMDRVA<MDRawSystemInfo> si(&minidump_writer_);
731     if (!si.Allocate())
732       return false;
733     my_memset(si.get(), 0, sizeof(MDRawSystemInfo));
734 
735     dirent->stream_type = MD_SYSTEM_INFO_STREAM;
736     dirent->location = si.location();
737 
738     WriteCPUInformation(si.get());
739     WriteOSInformation(si.get());
740 
741     return true;
742   }
743 
WriteDSODebugStream(MDRawDirectory * dirent)744   bool WriteDSODebugStream(MDRawDirectory* dirent) {
745     ElfW(Phdr)* phdr = reinterpret_cast<ElfW(Phdr) *>(dumper_->auxv()[AT_PHDR]);
746     char* base;
747     int phnum = dumper_->auxv()[AT_PHNUM];
748     if (!phnum || !phdr)
749       return false;
750 
751     // Assume the program base is at the beginning of the same page as the PHDR
752     base = reinterpret_cast<char *>(reinterpret_cast<uintptr_t>(phdr) & ~0xfff);
753 
754     // Search for the program PT_DYNAMIC segment
755     ElfW(Addr) dyn_addr = 0;
756     for (; phnum >= 0; phnum--, phdr++) {
757       ElfW(Phdr) ph;
758       if (!dumper_->CopyFromProcess(&ph, GetCrashThread(), phdr, sizeof(ph)))
759         return false;
760 
761       // Adjust base address with the virtual address of the PT_LOAD segment
762       // corresponding to offset 0
763       if (ph.p_type == PT_LOAD && ph.p_offset == 0) {
764         base -= ph.p_vaddr;
765       }
766       if (ph.p_type == PT_DYNAMIC) {
767         dyn_addr = ph.p_vaddr;
768       }
769     }
770     if (!dyn_addr)
771       return false;
772 
773     ElfW(Dyn) *dynamic = reinterpret_cast<ElfW(Dyn) *>(dyn_addr + base);
774 
775     // The dynamic linker makes information available that helps gdb find all
776     // DSOs loaded into the program. If this information is indeed available,
777     // dump it to a MD_LINUX_DSO_DEBUG stream.
778     struct r_debug* r_debug = NULL;
779     uint32_t dynamic_length = 0;
780 
781     for (int i = 0; ; ++i) {
782       ElfW(Dyn) dyn;
783       dynamic_length += sizeof(dyn);
784       if (!dumper_->CopyFromProcess(&dyn, GetCrashThread(), dynamic + i,
785                                     sizeof(dyn))) {
786         return false;
787       }
788 
789 #ifdef __mips__
790       const int32_t debug_tag = DT_MIPS_RLD_MAP;
791 #else
792       const int32_t debug_tag = DT_DEBUG;
793 #endif
794       if (dyn.d_tag == debug_tag) {
795         r_debug = reinterpret_cast<struct r_debug*>(dyn.d_un.d_ptr);
796         continue;
797       } else if (dyn.d_tag == DT_NULL) {
798         break;
799       }
800     }
801 
802     // The "r_map" field of that r_debug struct contains a linked list of all
803     // loaded DSOs.
804     // Our list of DSOs potentially is different from the ones in the crashing
805     // process. So, we have to be careful to never dereference pointers
806     // directly. Instead, we use CopyFromProcess() everywhere.
807     // See <link.h> for a more detailed discussion of the how the dynamic
808     // loader communicates with debuggers.
809 
810     // Count the number of loaded DSOs
811     int dso_count = 0;
812     struct r_debug debug_entry;
813     if (!dumper_->CopyFromProcess(&debug_entry, GetCrashThread(), r_debug,
814                                   sizeof(debug_entry))) {
815       return false;
816     }
817     for (struct link_map* ptr = debug_entry.r_map; ptr; ) {
818       struct link_map map;
819       if (!dumper_->CopyFromProcess(&map, GetCrashThread(), ptr, sizeof(map)))
820         return false;
821 
822       ptr = map.l_next;
823       dso_count++;
824     }
825 
826     MDRVA linkmap_rva = MinidumpFileWriter::kInvalidMDRVA;
827     if (dso_count > 0) {
828       // If we have at least one DSO, create an array of MDRawLinkMap
829       // entries in the minidump file.
830       TypedMDRVA<MDRawLinkMap> linkmap(&minidump_writer_);
831       if (!linkmap.AllocateArray(dso_count))
832         return false;
833       linkmap_rva = linkmap.location().rva;
834       int idx = 0;
835 
836       // Iterate over DSOs and write their information to mini dump
837       for (struct link_map* ptr = debug_entry.r_map; ptr; ) {
838         struct link_map map;
839         if (!dumper_->CopyFromProcess(&map, GetCrashThread(), ptr, sizeof(map)))
840           return  false;
841 
842         ptr = map.l_next;
843         char filename[257] = { 0 };
844         if (map.l_name) {
845           dumper_->CopyFromProcess(filename, GetCrashThread(), map.l_name,
846                                    sizeof(filename) - 1);
847         }
848         MDLocationDescriptor location;
849         if (!minidump_writer_.WriteString(filename, 0, &location))
850           return false;
851         MDRawLinkMap entry;
852         entry.name = location.rva;
853         entry.addr = map.l_addr;
854         entry.ld = reinterpret_cast<uintptr_t>(map.l_ld);
855         linkmap.CopyIndex(idx++, &entry);
856       }
857     }
858 
859     // Write MD_LINUX_DSO_DEBUG record
860     TypedMDRVA<MDRawDebug> debug(&minidump_writer_);
861     if (!debug.AllocateObjectAndArray(1, dynamic_length))
862       return false;
863     my_memset(debug.get(), 0, sizeof(MDRawDebug));
864     dirent->stream_type = MD_LINUX_DSO_DEBUG;
865     dirent->location = debug.location();
866 
867     debug.get()->version = debug_entry.r_version;
868     debug.get()->map = linkmap_rva;
869     debug.get()->dso_count = dso_count;
870     debug.get()->brk = debug_entry.r_brk;
871     debug.get()->ldbase = debug_entry.r_ldbase;
872     debug.get()->dynamic = reinterpret_cast<uintptr_t>(dynamic);
873 
874     wasteful_vector<char> dso_debug_data(dumper_->allocator(), dynamic_length);
875     // The passed-in size to the constructor (above) is only a hint.
876     // Must call .resize() to do actual initialization of the elements.
877     dso_debug_data.resize(dynamic_length);
878     dumper_->CopyFromProcess(&dso_debug_data[0], GetCrashThread(), dynamic,
879                              dynamic_length);
880     debug.CopyIndexAfterObject(0, &dso_debug_data[0], dynamic_length);
881 
882     return true;
883   }
884 
set_minidump_size_limit(off_t limit)885   void set_minidump_size_limit(off_t limit) { minidump_size_limit_ = limit; }
886 
887  private:
Alloc(unsigned bytes)888   void* Alloc(unsigned bytes) {
889     return dumper_->allocator()->Alloc(bytes);
890   }
891 
GetCrashThread() const892   pid_t GetCrashThread() const {
893     return dumper_->crash_thread();
894   }
895 
NullifyDirectoryEntry(MDRawDirectory * dirent)896   void NullifyDirectoryEntry(MDRawDirectory* dirent) {
897     dirent->stream_type = 0;
898     dirent->location.data_size = 0;
899     dirent->location.rva = 0;
900   }
901 
902 #if defined(__i386__) || defined(__x86_64__) || defined(__mips__)
WriteCPUInformation(MDRawSystemInfo * sys_info)903   bool WriteCPUInformation(MDRawSystemInfo* sys_info) {
904     char vendor_id[sizeof(sys_info->cpu.x86_cpu_info.vendor_id) + 1] = {0};
905     static const char vendor_id_name[] = "vendor_id";
906 
907     struct CpuInfoEntry {
908       const char* info_name;
909       int value;
910       bool found;
911     } cpu_info_table[] = {
912       { "processor", -1, false },
913 #if defined(__i386__) || defined(__x86_64__)
914       { "model", 0, false },
915       { "stepping",  0, false },
916       { "cpu family", 0, false },
917 #endif
918     };
919 
920     // processor_architecture should always be set, do this first
921     sys_info->processor_architecture =
922 #if defined(__mips__)
923 # if _MIPS_SIM == _ABIO32
924         MD_CPU_ARCHITECTURE_MIPS;
925 # elif _MIPS_SIM == _ABI64
926         MD_CPU_ARCHITECTURE_MIPS64;
927 # else
928 #  error "This mips ABI is currently not supported (n32)"
929 #endif
930 #elif defined(__i386__)
931         MD_CPU_ARCHITECTURE_X86;
932 #else
933         MD_CPU_ARCHITECTURE_AMD64;
934 #endif
935 
936     const int fd = sys_open("/proc/cpuinfo", O_RDONLY, 0);
937     if (fd < 0)
938       return false;
939 
940     {
941       PageAllocator allocator;
942       ProcCpuInfoReader* const reader = new(allocator) ProcCpuInfoReader(fd);
943       const char* field;
944       while (reader->GetNextField(&field)) {
945         bool is_first_entry = true;
946         for (CpuInfoEntry& entry : cpu_info_table) {
947           if (!is_first_entry && entry.found) {
948             // except for the 'processor' field, ignore repeated values.
949             continue;
950           }
951           is_first_entry = false;
952           if (!my_strcmp(field, entry.info_name)) {
953             size_t value_len;
954             const char* value = reader->GetValueAndLen(&value_len);
955             if (value_len == 0)
956               continue;
957 
958             uintptr_t val;
959             if (my_read_decimal_ptr(&val, value) == value)
960               continue;
961 
962             entry.value = static_cast<int>(val);
963             entry.found = true;
964           }
965         }
966 
967         // special case for vendor_id
968         if (!my_strcmp(field, vendor_id_name)) {
969           size_t value_len;
970           const char* value = reader->GetValueAndLen(&value_len);
971           if (value_len > 0)
972             my_strlcpy(vendor_id, value, sizeof(vendor_id));
973         }
974       }
975       sys_close(fd);
976     }
977 
978     // make sure we got everything we wanted
979     for (const CpuInfoEntry& entry : cpu_info_table) {
980       if (!entry.found) {
981         return false;
982       }
983     }
984     // cpu_info_table[0] holds the last cpu id listed in /proc/cpuinfo,
985     // assuming this is the highest id, change it to the number of CPUs
986     // by adding one.
987     cpu_info_table[0].value++;
988 
989     sys_info->number_of_processors = cpu_info_table[0].value;
990 #if defined(__i386__) || defined(__x86_64__)
991     sys_info->processor_level      = cpu_info_table[3].value;
992     sys_info->processor_revision   = cpu_info_table[1].value << 8 |
993                                      cpu_info_table[2].value;
994 #endif
995 
996     if (vendor_id[0] != '\0') {
997       my_memcpy(sys_info->cpu.x86_cpu_info.vendor_id, vendor_id,
998                 sizeof(sys_info->cpu.x86_cpu_info.vendor_id));
999     }
1000     return true;
1001   }
1002 #elif defined(__arm__) || defined(__aarch64__)
WriteCPUInformation(MDRawSystemInfo * sys_info)1003   bool WriteCPUInformation(MDRawSystemInfo* sys_info) {
1004     // The CPUID value is broken up in several entries in /proc/cpuinfo.
1005     // This table is used to rebuild it from the entries.
1006     const struct CpuIdEntry {
1007       const char* field;
1008       char        format;
1009       char        bit_lshift;
1010       char        bit_length;
1011     } cpu_id_entries[] = {
1012       { "CPU implementer", 'x', 24, 8 },
1013       { "CPU variant", 'x', 20, 4 },
1014       { "CPU part", 'x', 4, 12 },
1015       { "CPU revision", 'd', 0, 4 },
1016     };
1017 
1018     // The ELF hwcaps are listed in the "Features" entry as textual tags.
1019     // This table is used to rebuild them.
1020     const struct CpuFeaturesEntry {
1021       const char* tag;
1022       uint32_t hwcaps;
1023     } cpu_features_entries[] = {
1024 #if defined(__arm__)
1025       { "swp",  MD_CPU_ARM_ELF_HWCAP_SWP },
1026       { "half", MD_CPU_ARM_ELF_HWCAP_HALF },
1027       { "thumb", MD_CPU_ARM_ELF_HWCAP_THUMB },
1028       { "26bit", MD_CPU_ARM_ELF_HWCAP_26BIT },
1029       { "fastmult", MD_CPU_ARM_ELF_HWCAP_FAST_MULT },
1030       { "fpa", MD_CPU_ARM_ELF_HWCAP_FPA },
1031       { "vfp", MD_CPU_ARM_ELF_HWCAP_VFP },
1032       { "edsp", MD_CPU_ARM_ELF_HWCAP_EDSP },
1033       { "java", MD_CPU_ARM_ELF_HWCAP_JAVA },
1034       { "iwmmxt", MD_CPU_ARM_ELF_HWCAP_IWMMXT },
1035       { "crunch", MD_CPU_ARM_ELF_HWCAP_CRUNCH },
1036       { "thumbee", MD_CPU_ARM_ELF_HWCAP_THUMBEE },
1037       { "neon", MD_CPU_ARM_ELF_HWCAP_NEON },
1038       { "vfpv3", MD_CPU_ARM_ELF_HWCAP_VFPv3 },
1039       { "vfpv3d16", MD_CPU_ARM_ELF_HWCAP_VFPv3D16 },
1040       { "tls", MD_CPU_ARM_ELF_HWCAP_TLS },
1041       { "vfpv4", MD_CPU_ARM_ELF_HWCAP_VFPv4 },
1042       { "idiva", MD_CPU_ARM_ELF_HWCAP_IDIVA },
1043       { "idivt", MD_CPU_ARM_ELF_HWCAP_IDIVT },
1044       { "idiv", MD_CPU_ARM_ELF_HWCAP_IDIVA | MD_CPU_ARM_ELF_HWCAP_IDIVT },
1045 #elif defined(__aarch64__)
1046       // No hwcaps on aarch64.
1047 #endif
1048     };
1049 
1050     // processor_architecture should always be set, do this first
1051     sys_info->processor_architecture =
1052 #if defined(__aarch64__)
1053         MD_CPU_ARCHITECTURE_ARM64_OLD;
1054 #else
1055         MD_CPU_ARCHITECTURE_ARM;
1056 #endif
1057 
1058     // /proc/cpuinfo is not readable under various sandboxed environments
1059     // (e.g. Android services with the android:isolatedProcess attribute)
1060     // prepare for this by setting default values now, which will be
1061     // returned when this happens.
1062     //
1063     // Note: Bogus values are used to distinguish between failures (to
1064     //       read /sys and /proc files) and really badly configured kernels.
1065     sys_info->number_of_processors = 0;
1066     sys_info->processor_level = 1U;  // There is no ARMv1
1067     sys_info->processor_revision = 42;
1068     sys_info->cpu.arm_cpu_info.cpuid = 0;
1069     sys_info->cpu.arm_cpu_info.elf_hwcaps = 0;
1070 
1071     // Counting the number of CPUs involves parsing two sysfs files,
1072     // because the content of /proc/cpuinfo will only mirror the number
1073     // of 'online' cores, and thus will vary with time.
1074     // See http://www.kernel.org/doc/Documentation/cputopology.txt
1075     {
1076       CpuSet cpus_present;
1077       CpuSet cpus_possible;
1078 
1079       int fd = sys_open("/sys/devices/system/cpu/present", O_RDONLY, 0);
1080       if (fd >= 0) {
1081         cpus_present.ParseSysFile(fd);
1082         sys_close(fd);
1083 
1084         fd = sys_open("/sys/devices/system/cpu/possible", O_RDONLY, 0);
1085         if (fd >= 0) {
1086           cpus_possible.ParseSysFile(fd);
1087           sys_close(fd);
1088 
1089           cpus_present.IntersectWith(cpus_possible);
1090           int cpu_count = cpus_present.GetCount();
1091           if (cpu_count > 255)
1092             cpu_count = 255;
1093           sys_info->number_of_processors = static_cast<uint8_t>(cpu_count);
1094         }
1095       }
1096     }
1097 
1098     // Parse /proc/cpuinfo to reconstruct the CPUID value, as well
1099     // as the ELF hwcaps field. For the latter, it would be easier to
1100     // read /proc/self/auxv but unfortunately, this file is not always
1101     // readable from regular Android applications on later versions
1102     // (>= 4.1) of the Android platform.
1103     const int fd = sys_open("/proc/cpuinfo", O_RDONLY, 0);
1104     if (fd < 0) {
1105       // Do not return false here to allow the minidump generation
1106       // to happen properly.
1107       return true;
1108     }
1109 
1110     {
1111       PageAllocator allocator;
1112       ProcCpuInfoReader* const reader =
1113           new(allocator) ProcCpuInfoReader(fd);
1114       const char* field;
1115       while (reader->GetNextField(&field)) {
1116         for (const CpuIdEntry& entry : cpu_id_entries) {
1117           if (my_strcmp(entry.field, field) != 0)
1118             continue;
1119           uintptr_t result = 0;
1120           const char* value = reader->GetValue();
1121           const char* p = value;
1122           if (value[0] == '0' && value[1] == 'x') {
1123             p = my_read_hex_ptr(&result, value+2);
1124           } else if (entry.format == 'x') {
1125             p = my_read_hex_ptr(&result, value);
1126           } else {
1127             p = my_read_decimal_ptr(&result, value);
1128           }
1129           if (p == value)
1130             continue;
1131 
1132           result &= (1U << entry.bit_length)-1;
1133           result <<= entry.bit_lshift;
1134           sys_info->cpu.arm_cpu_info.cpuid |=
1135               static_cast<uint32_t>(result);
1136         }
1137 #if defined(__arm__)
1138         // Get the architecture version from the "Processor" field.
1139         // Note that it is also available in the "CPU architecture" field,
1140         // however, some existing kernels are misconfigured and will report
1141         // invalid values here (e.g. 6, while the CPU is ARMv7-A based).
1142         // The "Processor" field doesn't have this issue.
1143         if (!my_strcmp(field, "Processor")) {
1144           size_t value_len;
1145           const char* value = reader->GetValueAndLen(&value_len);
1146           // Expected format: <text> (v<level><endian>)
1147           // Where <text> is some text like "ARMv7 Processor rev 2"
1148           // and <level> is a decimal corresponding to the ARM
1149           // architecture number. <endian> is either 'l' or 'b'
1150           // and corresponds to the endianess, it is ignored here.
1151           while (value_len > 0 && my_isspace(value[value_len-1]))
1152             value_len--;
1153 
1154           size_t nn = value_len;
1155           while (nn > 0 && value[nn-1] != '(')
1156             nn--;
1157           if (nn > 0 && value[nn] == 'v') {
1158             uintptr_t arch_level = 5;
1159             my_read_decimal_ptr(&arch_level, value + nn + 1);
1160             sys_info->processor_level = static_cast<uint16_t>(arch_level);
1161           }
1162         }
1163 #elif defined(__aarch64__)
1164         // The aarch64 architecture does not provide the architecture level
1165         // in the Processor field, so we instead check the "CPU architecture"
1166         // field.
1167         if (!my_strcmp(field, "CPU architecture")) {
1168           uintptr_t arch_level = 0;
1169           const char* value = reader->GetValue();
1170           const char* p = value;
1171           p = my_read_decimal_ptr(&arch_level, value);
1172           if (p == value)
1173             continue;
1174           sys_info->processor_level = static_cast<uint16_t>(arch_level);
1175         }
1176 #endif
1177         // Rebuild the ELF hwcaps from the 'Features' field.
1178         if (!my_strcmp(field, "Features")) {
1179           size_t value_len;
1180           const char* value = reader->GetValueAndLen(&value_len);
1181 
1182           // Parse each space-separated tag.
1183           while (value_len > 0) {
1184             const char* tag = value;
1185             size_t tag_len = value_len;
1186             const char* p = my_strchr(tag, ' ');
1187             if (p) {
1188               tag_len = static_cast<size_t>(p - tag);
1189               value += tag_len + 1;
1190               value_len -= tag_len + 1;
1191             } else {
1192               tag_len = strlen(tag);
1193               value_len = 0;
1194             }
1195             for (const CpuFeaturesEntry& entry : cpu_features_entries) {
1196               if (tag_len == strlen(entry.tag) &&
1197                   !memcmp(tag, entry.tag, tag_len)) {
1198                 sys_info->cpu.arm_cpu_info.elf_hwcaps |= entry.hwcaps;
1199                 break;
1200               }
1201             }
1202           }
1203         }
1204       }
1205       sys_close(fd);
1206     }
1207 
1208     return true;
1209   }
1210 #else
1211 #  error "Unsupported CPU"
1212 #endif
1213 
WriteFile(MDLocationDescriptor * result,const char * filename)1214   bool WriteFile(MDLocationDescriptor* result, const char* filename) {
1215     const int fd = sys_open(filename, O_RDONLY, 0);
1216     if (fd < 0)
1217       return false;
1218 
1219     // We can't stat the files because several of the files that we want to
1220     // read are kernel seqfiles, which always have a length of zero. So we have
1221     // to read as much as we can into a buffer.
1222     static const unsigned kBufSize = 1024 - 2*sizeof(void*);
1223     struct Buffers {
1224       Buffers* next;
1225       size_t len;
1226       uint8_t data[kBufSize];
1227     } *buffers = reinterpret_cast<Buffers*>(Alloc(sizeof(Buffers)));
1228     buffers->next = NULL;
1229     buffers->len = 0;
1230 
1231     size_t total = 0;
1232     for (Buffers* bufptr = buffers;;) {
1233       ssize_t r;
1234       do {
1235         r = sys_read(fd, &bufptr->data[bufptr->len], kBufSize - bufptr->len);
1236       } while (r == -1 && errno == EINTR);
1237 
1238       if (r < 1)
1239         break;
1240 
1241       total += r;
1242       bufptr->len += r;
1243       if (bufptr->len == kBufSize) {
1244         bufptr->next = reinterpret_cast<Buffers*>(Alloc(sizeof(Buffers)));
1245         bufptr = bufptr->next;
1246         bufptr->next = NULL;
1247         bufptr->len = 0;
1248       }
1249     }
1250     sys_close(fd);
1251 
1252     if (!total)
1253       return false;
1254 
1255     UntypedMDRVA memory(&minidump_writer_);
1256     if (!memory.Allocate(total))
1257       return false;
1258     for (MDRVA pos = memory.position(); buffers; buffers = buffers->next) {
1259       // Check for special case of a zero-length buffer.  This should only
1260       // occur if a file's size happens to be a multiple of the buffer's
1261       // size, in which case the final sys_read() will have resulted in
1262       // zero bytes being read after the final buffer was just allocated.
1263       if (buffers->len == 0) {
1264         // This can only occur with final buffer.
1265         assert(buffers->next == NULL);
1266         continue;
1267       }
1268       memory.Copy(pos, &buffers->data, buffers->len);
1269       pos += buffers->len;
1270     }
1271     *result = memory.location();
1272     return true;
1273   }
1274 
WriteOSInformation(MDRawSystemInfo * sys_info)1275   bool WriteOSInformation(MDRawSystemInfo* sys_info) {
1276 #if defined(__ANDROID__)
1277     sys_info->platform_id = MD_OS_ANDROID;
1278 #else
1279     sys_info->platform_id = MD_OS_LINUX;
1280 #endif
1281 
1282     struct utsname uts;
1283     if (uname(&uts))
1284       return false;
1285 
1286     static const size_t buf_len = 512;
1287     char buf[buf_len] = {0};
1288     size_t space_left = buf_len - 1;
1289     const char* info_table[] = {
1290       uts.sysname,
1291       uts.release,
1292       uts.version,
1293       uts.machine,
1294       NULL
1295     };
1296     bool first_item = true;
1297     for (const char** cur_info = info_table; *cur_info; cur_info++) {
1298       static const char separator[] = " ";
1299       size_t separator_len = sizeof(separator) - 1;
1300       size_t info_len = my_strlen(*cur_info);
1301       if (info_len == 0)
1302         continue;
1303 
1304       if (space_left < info_len + (first_item ? 0 : separator_len))
1305         break;
1306 
1307       if (!first_item) {
1308         my_strlcat(buf, separator, sizeof(buf));
1309         space_left -= separator_len;
1310       }
1311 
1312       first_item = false;
1313       my_strlcat(buf, *cur_info, sizeof(buf));
1314       space_left -= info_len;
1315     }
1316 
1317     MDLocationDescriptor location;
1318     if (!minidump_writer_.WriteString(buf, 0, &location))
1319       return false;
1320     sys_info->csd_version_rva = location.rva;
1321 
1322     return true;
1323   }
1324 
WriteProcFile(MDLocationDescriptor * result,pid_t pid,const char * filename)1325   bool WriteProcFile(MDLocationDescriptor* result, pid_t pid,
1326                      const char* filename) {
1327     char buf[NAME_MAX];
1328     if (!dumper_->BuildProcPath(buf, pid, filename))
1329       return false;
1330     return WriteFile(result, buf);
1331   }
1332 
1333   // Only one of the 2 member variables below should be set to a valid value.
1334   const int fd_;  // File descriptor where the minidum should be written.
1335   const char* path_;  // Path to the file where the minidum should be written.
1336 
1337   const ucontext_t* const ucontext_;  // also from the signal handler
1338 #if !defined(__ARM_EABI__) && !defined(__mips__)
1339   const google_breakpad::fpstate_t* const float_state_;  // ditto
1340 #endif
1341   LinuxDumper* dumper_;
1342   MinidumpFileWriter minidump_writer_;
1343   off_t minidump_size_limit_;
1344   MDLocationDescriptor crashing_thread_context_;
1345   // Blocks of memory written to the dump. These are all currently
1346   // written while writing the thread list stream, but saved here
1347   // so a memory list stream can be written afterwards.
1348   wasteful_vector<MDMemoryDescriptor> memory_blocks_;
1349   // Additional information about some mappings provided by the caller.
1350   const MappingList& mapping_list_;
1351   // Additional memory regions to be included in the dump,
1352   // provided by the caller.
1353   const AppMemoryList& app_memory_list_;
1354   // If set, skip recording any threads that do not reference the
1355   // mapping containing principal_mapping_address_.
1356   bool skip_stacks_if_mapping_unreferenced_;
1357   uintptr_t principal_mapping_address_;
1358   const MappingInfo* principal_mapping_;
1359   // If true, apply stack sanitization to stored stack data.
1360   bool sanitize_stacks_;
1361 };
1362 
1363 
WriteMinidumpImpl(const char * minidump_path,int minidump_fd,off_t minidump_size_limit,pid_t crashing_process,const void * blob,size_t blob_size,const MappingList & mappings,const AppMemoryList & appmem,bool skip_stacks_if_mapping_unreferenced,uintptr_t principal_mapping_address,bool sanitize_stacks)1364 bool WriteMinidumpImpl(const char* minidump_path,
1365                        int minidump_fd,
1366                        off_t minidump_size_limit,
1367                        pid_t crashing_process,
1368                        const void* blob, size_t blob_size,
1369                        const MappingList& mappings,
1370                        const AppMemoryList& appmem,
1371                        bool skip_stacks_if_mapping_unreferenced,
1372                        uintptr_t principal_mapping_address,
1373                        bool sanitize_stacks) {
1374   LinuxPtraceDumper dumper(crashing_process);
1375   const ExceptionHandler::CrashContext* context = NULL;
1376   if (blob) {
1377     if (blob_size != sizeof(ExceptionHandler::CrashContext))
1378       return false;
1379     context = reinterpret_cast<const ExceptionHandler::CrashContext*>(blob);
1380     dumper.SetCrashInfoFromSigInfo(context->siginfo);
1381     dumper.set_crash_thread(context->tid);
1382   }
1383   MinidumpWriter writer(minidump_path, minidump_fd, context, mappings,
1384                         appmem, skip_stacks_if_mapping_unreferenced,
1385                         principal_mapping_address, sanitize_stacks, &dumper);
1386   // Set desired limit for file size of minidump (-1 means no limit).
1387   writer.set_minidump_size_limit(minidump_size_limit);
1388   if (!writer.Init())
1389     return false;
1390   return writer.Dump();
1391 }
1392 
1393 }  // namespace
1394 
1395 namespace google_breakpad {
1396 
WriteMinidump(const char * minidump_path,pid_t crashing_process,const void * blob,size_t blob_size,bool skip_stacks_if_mapping_unreferenced,uintptr_t principal_mapping_address,bool sanitize_stacks)1397 bool WriteMinidump(const char* minidump_path, pid_t crashing_process,
1398                    const void* blob, size_t blob_size,
1399                    bool skip_stacks_if_mapping_unreferenced,
1400                    uintptr_t principal_mapping_address,
1401                    bool sanitize_stacks) {
1402   return WriteMinidumpImpl(minidump_path, -1, -1,
1403                            crashing_process, blob, blob_size,
1404                            MappingList(), AppMemoryList(),
1405                            skip_stacks_if_mapping_unreferenced,
1406                            principal_mapping_address,
1407                            sanitize_stacks);
1408 }
1409 
WriteMinidump(int minidump_fd,pid_t crashing_process,const void * blob,size_t blob_size,bool skip_stacks_if_mapping_unreferenced,uintptr_t principal_mapping_address,bool sanitize_stacks)1410 bool WriteMinidump(int minidump_fd, pid_t crashing_process,
1411                    const void* blob, size_t blob_size,
1412                    bool skip_stacks_if_mapping_unreferenced,
1413                    uintptr_t principal_mapping_address,
1414                    bool sanitize_stacks) {
1415   return WriteMinidumpImpl(NULL, minidump_fd, -1,
1416                            crashing_process, blob, blob_size,
1417                            MappingList(), AppMemoryList(),
1418                            skip_stacks_if_mapping_unreferenced,
1419                            principal_mapping_address,
1420                            sanitize_stacks);
1421 }
1422 
WriteMinidump(const char * minidump_path,pid_t process,pid_t process_blamed_thread)1423 bool WriteMinidump(const char* minidump_path, pid_t process,
1424                    pid_t process_blamed_thread) {
1425   LinuxPtraceDumper dumper(process);
1426   // MinidumpWriter will set crash address
1427   dumper.set_crash_signal(MD_EXCEPTION_CODE_LIN_DUMP_REQUESTED);
1428   dumper.set_crash_thread(process_blamed_thread);
1429   MappingList mapping_list;
1430   AppMemoryList app_memory_list;
1431   MinidumpWriter writer(minidump_path, -1, NULL, mapping_list,
1432                         app_memory_list, false, 0, false, &dumper);
1433   if (!writer.Init())
1434     return false;
1435   return writer.Dump();
1436 }
1437 
WriteMinidump(const char * minidump_path,pid_t crashing_process,const void * blob,size_t blob_size,const MappingList & mappings,const AppMemoryList & appmem,bool skip_stacks_if_mapping_unreferenced,uintptr_t principal_mapping_address,bool sanitize_stacks)1438 bool WriteMinidump(const char* minidump_path, pid_t crashing_process,
1439                    const void* blob, size_t blob_size,
1440                    const MappingList& mappings,
1441                    const AppMemoryList& appmem,
1442                    bool skip_stacks_if_mapping_unreferenced,
1443                    uintptr_t principal_mapping_address,
1444                    bool sanitize_stacks) {
1445   return WriteMinidumpImpl(minidump_path, -1, -1, crashing_process,
1446                            blob, blob_size,
1447                            mappings, appmem,
1448                            skip_stacks_if_mapping_unreferenced,
1449                            principal_mapping_address,
1450                            sanitize_stacks);
1451 }
1452 
WriteMinidump(int minidump_fd,pid_t crashing_process,const void * blob,size_t blob_size,const MappingList & mappings,const AppMemoryList & appmem,bool skip_stacks_if_mapping_unreferenced,uintptr_t principal_mapping_address,bool sanitize_stacks)1453 bool WriteMinidump(int minidump_fd, pid_t crashing_process,
1454                    const void* blob, size_t blob_size,
1455                    const MappingList& mappings,
1456                    const AppMemoryList& appmem,
1457                    bool skip_stacks_if_mapping_unreferenced,
1458                    uintptr_t principal_mapping_address,
1459                    bool sanitize_stacks) {
1460   return WriteMinidumpImpl(NULL, minidump_fd, -1, crashing_process,
1461                            blob, blob_size,
1462                            mappings, appmem,
1463                            skip_stacks_if_mapping_unreferenced,
1464                            principal_mapping_address,
1465                            sanitize_stacks);
1466 }
1467 
WriteMinidump(const char * minidump_path,off_t minidump_size_limit,pid_t crashing_process,const void * blob,size_t blob_size,const MappingList & mappings,const AppMemoryList & appmem,bool skip_stacks_if_mapping_unreferenced,uintptr_t principal_mapping_address,bool sanitize_stacks)1468 bool WriteMinidump(const char* minidump_path, off_t minidump_size_limit,
1469                    pid_t crashing_process,
1470                    const void* blob, size_t blob_size,
1471                    const MappingList& mappings,
1472                    const AppMemoryList& appmem,
1473                    bool skip_stacks_if_mapping_unreferenced,
1474                    uintptr_t principal_mapping_address,
1475                    bool sanitize_stacks) {
1476   return WriteMinidumpImpl(minidump_path, -1, minidump_size_limit,
1477                            crashing_process, blob, blob_size,
1478                            mappings, appmem,
1479                            skip_stacks_if_mapping_unreferenced,
1480                            principal_mapping_address,
1481                            sanitize_stacks);
1482 }
1483 
WriteMinidump(int minidump_fd,off_t minidump_size_limit,pid_t crashing_process,const void * blob,size_t blob_size,const MappingList & mappings,const AppMemoryList & appmem,bool skip_stacks_if_mapping_unreferenced,uintptr_t principal_mapping_address,bool sanitize_stacks)1484 bool WriteMinidump(int minidump_fd, off_t minidump_size_limit,
1485                    pid_t crashing_process,
1486                    const void* blob, size_t blob_size,
1487                    const MappingList& mappings,
1488                    const AppMemoryList& appmem,
1489                    bool skip_stacks_if_mapping_unreferenced,
1490                    uintptr_t principal_mapping_address,
1491                    bool sanitize_stacks) {
1492   return WriteMinidumpImpl(NULL, minidump_fd, minidump_size_limit,
1493                            crashing_process, blob, blob_size,
1494                            mappings, appmem,
1495                            skip_stacks_if_mapping_unreferenced,
1496                            principal_mapping_address,
1497                            sanitize_stacks);
1498 }
1499 
WriteMinidump(const char * filename,const MappingList & mappings,const AppMemoryList & appmem,LinuxDumper * dumper)1500 bool WriteMinidump(const char* filename,
1501                    const MappingList& mappings,
1502                    const AppMemoryList& appmem,
1503                    LinuxDumper* dumper) {
1504   MinidumpWriter writer(filename, -1, NULL, mappings, appmem,
1505                         false, 0, false, dumper);
1506   if (!writer.Init())
1507     return false;
1508   return writer.Dump();
1509 }
1510 
1511 }  // namespace google_breakpad
1512