Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / breakpad / src / client / linux / minidump_writer / minidump_writer.cc
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 "client/linux/handler/minidump_descriptor.h"
47 #include "client/linux/minidump_writer/minidump_writer.h"
48 #include "client/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 <unistd.h>
63
64 #include <algorithm>
65
66 #include "client/linux/handler/exception_handler.h"
67 #include "client/linux/minidump_writer/cpu_set.h"
68 #include "client/linux/minidump_writer/line_reader.h"
69 #include "client/linux/minidump_writer/linux_dumper.h"
70 #include "client/linux/minidump_writer/linux_ptrace_dumper.h"
71 #include "client/linux/minidump_writer/proc_cpuinfo_reader.h"
72 #include "client/minidump_file_writer.h"
73 #include "common/linux/linux_libc_support.h"
74 #include "google_breakpad/common/minidump_format.h"
75 #include "third_party/lss/linux_syscall_support.h"
76
77 namespace {
78
79 using google_breakpad::AppMemoryList;
80 using google_breakpad::ExceptionHandler;
81 using google_breakpad::CpuSet;
82 using google_breakpad::LineReader;
83 using google_breakpad::LinuxDumper;
84 using google_breakpad::LinuxPtraceDumper;
85 using google_breakpad::MappingEntry;
86 using google_breakpad::MappingInfo;
87 using google_breakpad::MappingList;
88 using google_breakpad::MinidumpFileWriter;
89 using google_breakpad::PageAllocator;
90 using google_breakpad::ProcCpuInfoReader;
91 using google_breakpad::ThreadInfo;
92 using google_breakpad::TypedMDRVA;
93 using google_breakpad::UntypedMDRVA;
94 using google_breakpad::wasteful_vector;
95
96 // Minidump defines register structures which are different from the raw
97 // structures which we get from the kernel. These are platform specific
98 // functions to juggle the ucontext and user structures into minidump format.
99 #if defined(__i386__)
100 typedef MDRawContextX86 RawContextCPU;
101
102 // Write a uint16_t to memory
103 //   out: memory location to write to
104 //   v: value to write.
105 void U16(void* out, uint16_t v) {
106   my_memcpy(out, &v, sizeof(v));
107 }
108
109 // Write a uint32_t to memory
110 //   out: memory location to write to
111 //   v: value to write.
112 void U32(void* out, uint32_t v) {
113   my_memcpy(out, &v, sizeof(v));
114 }
115
116 // Juggle an x86 user_(fp|fpx|)regs_struct into minidump format
117 //   out: the minidump structure
118 //   info: the collection of register structures.
119 void CPUFillFromThreadInfo(MDRawContextX86 *out,
120                            const google_breakpad::ThreadInfo &info) {
121   out->context_flags = MD_CONTEXT_X86_ALL;
122
123   out->dr0 = info.dregs[0];
124   out->dr1 = info.dregs[1];
125   out->dr2 = info.dregs[2];
126   out->dr3 = info.dregs[3];
127   // 4 and 5 deliberatly omitted because they aren't included in the minidump
128   // format.
129   out->dr6 = info.dregs[6];
130   out->dr7 = info.dregs[7];
131
132   out->gs = info.regs.xgs;
133   out->fs = info.regs.xfs;
134   out->es = info.regs.xes;
135   out->ds = info.regs.xds;
136
137   out->edi = info.regs.edi;
138   out->esi = info.regs.esi;
139   out->ebx = info.regs.ebx;
140   out->edx = info.regs.edx;
141   out->ecx = info.regs.ecx;
142   out->eax = info.regs.eax;
143
144   out->ebp = info.regs.ebp;
145   out->eip = info.regs.eip;
146   out->cs = info.regs.xcs;
147   out->eflags = info.regs.eflags;
148   out->esp = info.regs.esp;
149   out->ss = info.regs.xss;
150
151   out->float_save.control_word = info.fpregs.cwd;
152   out->float_save.status_word = info.fpregs.swd;
153   out->float_save.tag_word = info.fpregs.twd;
154   out->float_save.error_offset = info.fpregs.fip;
155   out->float_save.error_selector = info.fpregs.fcs;
156   out->float_save.data_offset = info.fpregs.foo;
157   out->float_save.data_selector = info.fpregs.fos;
158
159   // 8 registers * 10 bytes per register.
160   my_memcpy(out->float_save.register_area, info.fpregs.st_space, 10 * 8);
161
162   // This matches the Intel fpsave format.
163   U16(out->extended_registers + 0, info.fpregs.cwd);
164   U16(out->extended_registers + 2, info.fpregs.swd);
165   U16(out->extended_registers + 4, info.fpregs.twd);
166   U16(out->extended_registers + 6, info.fpxregs.fop);
167   U32(out->extended_registers + 8, info.fpxregs.fip);
168   U16(out->extended_registers + 12, info.fpxregs.fcs);
169   U32(out->extended_registers + 16, info.fpregs.foo);
170   U16(out->extended_registers + 20, info.fpregs.fos);
171   U32(out->extended_registers + 24, info.fpxregs.mxcsr);
172
173   my_memcpy(out->extended_registers + 32, &info.fpxregs.st_space, 128);
174   my_memcpy(out->extended_registers + 160, &info.fpxregs.xmm_space, 128);
175 }
176
177 // Juggle an x86 ucontext into minidump format
178 //   out: the minidump structure
179 //   info: the collection of register structures.
180 void CPUFillFromUContext(MDRawContextX86 *out, const ucontext *uc,
181                          const struct _libc_fpstate* fp) {
182   const greg_t* regs = uc->uc_mcontext.gregs;
183
184   out->context_flags = MD_CONTEXT_X86_FULL |
185                        MD_CONTEXT_X86_FLOATING_POINT;
186
187   out->gs = regs[REG_GS];
188   out->fs = regs[REG_FS];
189   out->es = regs[REG_ES];
190   out->ds = regs[REG_DS];
191
192   out->edi = regs[REG_EDI];
193   out->esi = regs[REG_ESI];
194   out->ebx = regs[REG_EBX];
195   out->edx = regs[REG_EDX];
196   out->ecx = regs[REG_ECX];
197   out->eax = regs[REG_EAX];
198
199   out->ebp = regs[REG_EBP];
200   out->eip = regs[REG_EIP];
201   out->cs = regs[REG_CS];
202   out->eflags = regs[REG_EFL];
203   out->esp = regs[REG_UESP];
204   out->ss = regs[REG_SS];
205
206   out->float_save.control_word = fp->cw;
207   out->float_save.status_word = fp->sw;
208   out->float_save.tag_word = fp->tag;
209   out->float_save.error_offset = fp->ipoff;
210   out->float_save.error_selector = fp->cssel;
211   out->float_save.data_offset = fp->dataoff;
212   out->float_save.data_selector = fp->datasel;
213
214   // 8 registers * 10 bytes per register.
215   my_memcpy(out->float_save.register_area, fp->_st, 10 * 8);
216 }
217
218 #elif defined(__x86_64)
219 typedef MDRawContextAMD64 RawContextCPU;
220
221 void CPUFillFromThreadInfo(MDRawContextAMD64 *out,
222                            const google_breakpad::ThreadInfo &info) {
223   out->context_flags = MD_CONTEXT_AMD64_FULL |
224                        MD_CONTEXT_AMD64_SEGMENTS;
225
226   out->cs = info.regs.cs;
227
228   out->ds = info.regs.ds;
229   out->es = info.regs.es;
230   out->fs = info.regs.fs;
231   out->gs = info.regs.gs;
232
233   out->ss = info.regs.ss;
234   out->eflags = info.regs.eflags;
235
236   out->dr0 = info.dregs[0];
237   out->dr1 = info.dregs[1];
238   out->dr2 = info.dregs[2];
239   out->dr3 = info.dregs[3];
240   // 4 and 5 deliberatly omitted because they aren't included in the minidump
241   // format.
242   out->dr6 = info.dregs[6];
243   out->dr7 = info.dregs[7];
244
245   out->rax = info.regs.rax;
246   out->rcx = info.regs.rcx;
247   out->rdx = info.regs.rdx;
248   out->rbx = info.regs.rbx;
249
250   out->rsp = info.regs.rsp;
251
252   out->rbp = info.regs.rbp;
253   out->rsi = info.regs.rsi;
254   out->rdi = info.regs.rdi;
255   out->r8 = info.regs.r8;
256   out->r9 = info.regs.r9;
257   out->r10 = info.regs.r10;
258   out->r11 = info.regs.r11;
259   out->r12 = info.regs.r12;
260   out->r13 = info.regs.r13;
261   out->r14 = info.regs.r14;
262   out->r15 = info.regs.r15;
263
264   out->rip = info.regs.rip;
265
266   out->flt_save.control_word = info.fpregs.cwd;
267   out->flt_save.status_word = info.fpregs.swd;
268   out->flt_save.tag_word = info.fpregs.ftw;
269   out->flt_save.error_opcode = info.fpregs.fop;
270   out->flt_save.error_offset = info.fpregs.rip;
271   out->flt_save.error_selector = 0;  // We don't have this.
272   out->flt_save.data_offset = info.fpregs.rdp;
273   out->flt_save.data_selector = 0;   // We don't have this.
274   out->flt_save.mx_csr = info.fpregs.mxcsr;
275   out->flt_save.mx_csr_mask = info.fpregs.mxcr_mask;
276   my_memcpy(&out->flt_save.float_registers, &info.fpregs.st_space, 8 * 16);
277   my_memcpy(&out->flt_save.xmm_registers, &info.fpregs.xmm_space, 16 * 16);
278 }
279
280 void CPUFillFromUContext(MDRawContextAMD64 *out, const ucontext *uc,
281                          const struct _libc_fpstate* fpregs) {
282   const greg_t* regs = uc->uc_mcontext.gregs;
283
284   out->context_flags = MD_CONTEXT_AMD64_FULL;
285
286   out->cs = regs[REG_CSGSFS] & 0xffff;
287
288   out->fs = (regs[REG_CSGSFS] >> 32) & 0xffff;
289   out->gs = (regs[REG_CSGSFS] >> 16) & 0xffff;
290
291   out->eflags = regs[REG_EFL];
292
293   out->rax = regs[REG_RAX];
294   out->rcx = regs[REG_RCX];
295   out->rdx = regs[REG_RDX];
296   out->rbx = regs[REG_RBX];
297
298   out->rsp = regs[REG_RSP];
299   out->rbp = regs[REG_RBP];
300   out->rsi = regs[REG_RSI];
301   out->rdi = regs[REG_RDI];
302   out->r8 = regs[REG_R8];
303   out->r9 = regs[REG_R9];
304   out->r10 = regs[REG_R10];
305   out->r11 = regs[REG_R11];
306   out->r12 = regs[REG_R12];
307   out->r13 = regs[REG_R13];
308   out->r14 = regs[REG_R14];
309   out->r15 = regs[REG_R15];
310
311   out->rip = regs[REG_RIP];
312
313   out->flt_save.control_word = fpregs->cwd;
314   out->flt_save.status_word = fpregs->swd;
315   out->flt_save.tag_word = fpregs->ftw;
316   out->flt_save.error_opcode = fpregs->fop;
317   out->flt_save.error_offset = fpregs->rip;
318   out->flt_save.data_offset = fpregs->rdp;
319   out->flt_save.error_selector = 0;  // We don't have this.
320   out->flt_save.data_selector = 0;  // We don't have this.
321   out->flt_save.mx_csr = fpregs->mxcsr;
322   out->flt_save.mx_csr_mask = fpregs->mxcr_mask;
323   my_memcpy(&out->flt_save.float_registers, &fpregs->_st, 8 * 16);
324   my_memcpy(&out->flt_save.xmm_registers, &fpregs->_xmm, 16 * 16);
325 }
326
327 #elif defined(__ARMEL__)
328 typedef MDRawContextARM RawContextCPU;
329
330 void CPUFillFromThreadInfo(MDRawContextARM* out,
331                            const google_breakpad::ThreadInfo& info) {
332   out->context_flags = MD_CONTEXT_ARM_FULL;
333
334   for (int i = 0; i < MD_CONTEXT_ARM_GPR_COUNT; ++i)
335     out->iregs[i] = info.regs.uregs[i];
336   // No CPSR register in ThreadInfo(it's not accessible via ptrace)
337   out->cpsr = 0;
338 #if !defined(__ANDROID__)
339   out->float_save.fpscr = info.fpregs.fpsr |
340     (static_cast<uint64_t>(info.fpregs.fpcr) << 32);
341   // TODO: sort this out, actually collect floating point registers
342   my_memset(&out->float_save.regs, 0, sizeof(out->float_save.regs));
343   my_memset(&out->float_save.extra, 0, sizeof(out->float_save.extra));
344 #endif
345 }
346
347 void CPUFillFromUContext(MDRawContextARM* out, const ucontext* uc) {
348   out->context_flags = MD_CONTEXT_ARM_FULL;
349
350   out->iregs[0] = uc->uc_mcontext.arm_r0;
351   out->iregs[1] = uc->uc_mcontext.arm_r1;
352   out->iregs[2] = uc->uc_mcontext.arm_r2;
353   out->iregs[3] = uc->uc_mcontext.arm_r3;
354   out->iregs[4] = uc->uc_mcontext.arm_r4;
355   out->iregs[5] = uc->uc_mcontext.arm_r5;
356   out->iregs[6] = uc->uc_mcontext.arm_r6;
357   out->iregs[7] = uc->uc_mcontext.arm_r7;
358   out->iregs[8] = uc->uc_mcontext.arm_r8;
359   out->iregs[9] = uc->uc_mcontext.arm_r9;
360   out->iregs[10] = uc->uc_mcontext.arm_r10;
361
362   out->iregs[11] = uc->uc_mcontext.arm_fp;
363   out->iregs[12] = uc->uc_mcontext.arm_ip;
364   out->iregs[13] = uc->uc_mcontext.arm_sp;
365   out->iregs[14] = uc->uc_mcontext.arm_lr;
366   out->iregs[15] = uc->uc_mcontext.arm_pc;
367
368   out->cpsr = uc->uc_mcontext.arm_cpsr;
369
370   // TODO: fix this after fixing ExceptionHandler
371   out->float_save.fpscr = 0;
372   my_memset(&out->float_save.regs, 0, sizeof(out->float_save.regs));
373   my_memset(&out->float_save.extra, 0, sizeof(out->float_save.extra));
374 }
375
376 #elif defined(__aarch64__)
377 typedef MDRawContextARM64 RawContextCPU;
378
379 void CPUFillFromThreadInfo(MDRawContextARM64* out,
380                            const google_breakpad::ThreadInfo& info) {
381   out->context_flags = MD_CONTEXT_ARM64_FULL;
382
383   out->cpsr = static_cast<uint32_t>(info.regs.pstate);
384   for (int i = 0; i < MD_CONTEXT_ARM64_REG_SP; ++i)
385     out->iregs[i] = info.regs.regs[i];
386   out->iregs[MD_CONTEXT_ARM64_REG_SP] = info.regs.sp;
387   out->iregs[MD_CONTEXT_ARM64_REG_PC] = info.regs.pc;
388
389   out->float_save.fpsr = info.fpregs.fpsr;
390   out->float_save.fpcr = info.fpregs.fpcr;
391   my_memcpy(&out->float_save.regs, &info.fpregs.vregs,
392       MD_FLOATINGSAVEAREA_ARM64_FPR_COUNT * 16);
393 }
394
395 void CPUFillFromUContext(MDRawContextARM64* out, const ucontext* uc,
396                          const struct fpsimd_context* fpregs) {
397   out->context_flags = MD_CONTEXT_ARM64_FULL;
398
399   out->cpsr = static_cast<uint32_t>(uc->uc_mcontext.pstate);
400   for (int i = 0; i < MD_CONTEXT_ARM64_REG_SP; ++i)
401     out->iregs[i] = uc->uc_mcontext.regs[i];
402   out->iregs[MD_CONTEXT_ARM64_REG_SP] = uc->uc_mcontext.sp;
403   out->iregs[MD_CONTEXT_ARM64_REG_PC] = uc->uc_mcontext.pc;
404
405   out->float_save.fpsr = fpregs->fpsr;
406   out->float_save.fpcr = fpregs->fpcr;
407   my_memcpy(&out->float_save.regs, &fpregs->vregs,
408       MD_FLOATINGSAVEAREA_ARM64_FPR_COUNT * 16);
409 }
410
411 #elif defined(__mips__)
412 typedef MDRawContextMIPS RawContextCPU;
413
414 static void CPUFillFromThreadInfo(MDRawContextMIPS* out,
415                                   const google_breakpad::ThreadInfo& info) {
416   out->context_flags = MD_CONTEXT_MIPS_FULL;
417
418   for (int i = 0; i < MD_CONTEXT_MIPS_GPR_COUNT; ++i)
419     out->iregs[i] = info.regs.regs[i];
420
421   out->mdhi = info.regs.hi;
422   out->mdlo = info.regs.lo;
423
424   for (int i = 0; i < MD_CONTEXT_MIPS_DSP_COUNT; ++i) {
425     out->hi[i] = info.hi[i];
426     out->lo[i] = info.lo[i];
427   }
428   out->dsp_control = info.dsp_control;
429
430   out->epc = info.regs.epc;
431   out->badvaddr = info.regs.badvaddr;
432   out->status = info.regs.status;
433   out->cause = info.regs.cause;
434
435   for (int i = 0; i < MD_FLOATINGSAVEAREA_MIPS_FPR_COUNT; ++i)
436     out->float_save.regs[i] = info.fpregs.regs[i];
437
438   out->float_save.fpcsr = info.fpregs.fpcsr;
439   out->float_save.fir = info.fpregs.fir;
440 }
441
442 static void CPUFillFromUContext(MDRawContextMIPS* out, const ucontext* uc) {
443   out->context_flags = MD_CONTEXT_MIPS_FULL;
444
445   for (int i = 0; i < MD_CONTEXT_MIPS_GPR_COUNT; ++i)
446     out->iregs[i] = uc->uc_mcontext.gregs[i];
447
448   out->mdhi = uc->uc_mcontext.mdhi;
449   out->mdlo = uc->uc_mcontext.mdlo;
450
451   out->hi[0] = uc->uc_mcontext.hi1;
452   out->hi[1] = uc->uc_mcontext.hi2;
453   out->hi[2] = uc->uc_mcontext.hi3;
454   out->lo[0] = uc->uc_mcontext.lo1;
455   out->lo[1] = uc->uc_mcontext.lo2;
456   out->lo[2] = uc->uc_mcontext.lo3;
457   out->dsp_control = uc->uc_mcontext.dsp;
458
459   out->epc = uc->uc_mcontext.pc;
460   out->badvaddr = 0;  // Not reported in signal context.
461   out->status = 0;  // Not reported in signal context.
462   out->cause = 0;  // Not reported in signal context.
463
464   for (int i = 0; i < MD_FLOATINGSAVEAREA_MIPS_FPR_COUNT; ++i)
465 #if defined (__ANDROID__)
466     out->float_save.regs[i] = uc->uc_mcontext.fpregs[i];
467 #else
468     out->float_save.regs[i] = uc->uc_mcontext.fpregs.fp_r.fp_dregs[i];
469 #endif
470
471   out->float_save.fpcsr = uc->uc_mcontext.fpc_csr;
472   out->float_save.fir = uc->uc_mcontext.fpc_eir;  // Unused.
473 }
474
475 #else
476 #error "This code has not been ported to your platform yet."
477 #endif
478
479 class MinidumpWriter {
480  public:
481   // The following kLimit* constants are for when minidump_size_limit_ is set
482   // and the minidump size might exceed it.
483   //
484   // Estimate for how big each thread's stack will be (in bytes).
485   static const unsigned kLimitAverageThreadStackLength = 8 * 1024;
486   // Number of threads whose stack size we don't want to limit.  These base
487   // threads will simply be the first N threads returned by the dumper (although
488   // the crashing thread will never be limited).  Threads beyond this count are
489   // the extra threads.
490   static const unsigned kLimitBaseThreadCount = 20;
491   // Maximum stack size to dump for any extra thread (in bytes).
492   static const unsigned kLimitMaxExtraThreadStackLen = 2 * 1024;
493   // Make sure this number of additional bytes can fit in the minidump
494   // (exclude the stack data).
495   static const unsigned kLimitMinidumpFudgeFactor = 64 * 1024;
496
497   MinidumpWriter(const char* minidump_path,
498                  int minidump_fd,
499                  const ExceptionHandler::CrashContext* context,
500                  const MappingList& mappings,
501                  const AppMemoryList& appmem,
502                  LinuxDumper* dumper)
503       : fd_(minidump_fd),
504         path_(minidump_path),
505         ucontext_(context ? &context->context : NULL),
506 #if !defined(__ARM_EABI__) && !defined(__mips__)
507         float_state_(context ? &context->float_state : NULL),
508 #endif
509         dumper_(dumper),
510         minidump_size_limit_(-1),
511         memory_blocks_(dumper_->allocator()),
512         mapping_list_(mappings),
513         app_memory_list_(appmem) {
514     // Assert there should be either a valid fd or a valid path, not both.
515     assert(fd_ != -1 || minidump_path);
516     assert(fd_ == -1 || !minidump_path);
517   }
518
519   bool Init() {
520     if (!dumper_->Init())
521       return false;
522
523     if (fd_ != -1)
524       minidump_writer_.SetFile(fd_);
525     else if (!minidump_writer_.Open(path_))
526       return false;
527
528     return dumper_->ThreadsSuspend();
529   }
530
531   ~MinidumpWriter() {
532     // Don't close the file descriptor when it's been provided explicitly.
533     // Callers might still need to use it.
534     if (fd_ == -1)
535       minidump_writer_.Close();
536     dumper_->ThreadsResume();
537   }
538
539   bool Dump() {
540     // A minidump file contains a number of tagged streams. This is the number
541     // of stream which we write.
542     unsigned kNumWriters = 13;
543
544     TypedMDRVA<MDRawHeader> header(&minidump_writer_);
545     TypedMDRVA<MDRawDirectory> dir(&minidump_writer_);
546     if (!header.Allocate())
547       return false;
548     if (!dir.AllocateArray(kNumWriters))
549       return false;
550     my_memset(header.get(), 0, sizeof(MDRawHeader));
551
552     header.get()->signature = MD_HEADER_SIGNATURE;
553     header.get()->version = MD_HEADER_VERSION;
554     header.get()->time_date_stamp = time(NULL);
555     header.get()->stream_count = kNumWriters;
556     header.get()->stream_directory_rva = dir.position();
557
558     unsigned dir_index = 0;
559     MDRawDirectory dirent;
560
561     if (!WriteThreadListStream(&dirent))
562       return false;
563     dir.CopyIndex(dir_index++, &dirent);
564
565     if (!WriteMappings(&dirent))
566       return false;
567     dir.CopyIndex(dir_index++, &dirent);
568
569     if (!WriteAppMemory())
570       return false;
571
572     if (!WriteMemoryListStream(&dirent))
573       return false;
574     dir.CopyIndex(dir_index++, &dirent);
575
576     if (!WriteExceptionStream(&dirent))
577       return false;
578     dir.CopyIndex(dir_index++, &dirent);
579
580     if (!WriteSystemInfoStream(&dirent))
581       return false;
582     dir.CopyIndex(dir_index++, &dirent);
583
584     dirent.stream_type = MD_LINUX_CPU_INFO;
585     if (!WriteFile(&dirent.location, "/proc/cpuinfo"))
586       NullifyDirectoryEntry(&dirent);
587     dir.CopyIndex(dir_index++, &dirent);
588
589     dirent.stream_type = MD_LINUX_PROC_STATUS;
590     if (!WriteProcFile(&dirent.location, GetCrashThread(), "status"))
591       NullifyDirectoryEntry(&dirent);
592     dir.CopyIndex(dir_index++, &dirent);
593
594     dirent.stream_type = MD_LINUX_LSB_RELEASE;
595     if (!WriteFile(&dirent.location, "/etc/lsb-release"))
596       NullifyDirectoryEntry(&dirent);
597     dir.CopyIndex(dir_index++, &dirent);
598
599     dirent.stream_type = MD_LINUX_CMD_LINE;
600     if (!WriteProcFile(&dirent.location, GetCrashThread(), "cmdline"))
601       NullifyDirectoryEntry(&dirent);
602     dir.CopyIndex(dir_index++, &dirent);
603
604     dirent.stream_type = MD_LINUX_ENVIRON;
605     if (!WriteProcFile(&dirent.location, GetCrashThread(), "environ"))
606       NullifyDirectoryEntry(&dirent);
607     dir.CopyIndex(dir_index++, &dirent);
608
609     dirent.stream_type = MD_LINUX_AUXV;
610     if (!WriteProcFile(&dirent.location, GetCrashThread(), "auxv"))
611       NullifyDirectoryEntry(&dirent);
612     dir.CopyIndex(dir_index++, &dirent);
613
614     dirent.stream_type = MD_LINUX_MAPS;
615     if (!WriteProcFile(&dirent.location, GetCrashThread(), "maps"))
616       NullifyDirectoryEntry(&dirent);
617     dir.CopyIndex(dir_index++, &dirent);
618
619     dirent.stream_type = MD_LINUX_DSO_DEBUG;
620     if (!WriteDSODebugStream(&dirent))
621       NullifyDirectoryEntry(&dirent);
622     dir.CopyIndex(dir_index++, &dirent);
623
624     // If you add more directory entries, don't forget to update kNumWriters,
625     // above.
626
627     dumper_->ThreadsResume();
628     return true;
629   }
630
631   // Check if the top of the stack is part of a system call that has been
632   // redirected by the seccomp sandbox. If so, try to pop the stack frames
633   // all the way back to the point where the interception happened.
634   void PopSeccompStackFrame(RawContextCPU* cpu, const MDRawThread& thread,
635                             uint8_t* stack_copy) {
636 #if defined(__x86_64)
637     uint64_t bp = cpu->rbp;
638     uint64_t top = thread.stack.start_of_memory_range;
639     for (int i = 4; i--; ) {
640       if (bp < top ||
641           bp + sizeof(bp) > thread.stack.start_of_memory_range +
642           thread.stack.memory.data_size ||
643           bp & 1) {
644         break;
645       }
646       uint64_t old_top = top;
647       top = bp;
648       uint8_t* bp_addr = stack_copy + bp - thread.stack.start_of_memory_range;
649       my_memcpy(&bp, bp_addr, sizeof(bp));
650       if (bp == 0xDEADBEEFDEADBEEFull) {
651         struct {
652           uint64_t r15;
653           uint64_t r14;
654           uint64_t r13;
655           uint64_t r12;
656           uint64_t r11;
657           uint64_t r10;
658           uint64_t r9;
659           uint64_t r8;
660           uint64_t rdi;
661           uint64_t rsi;
662           uint64_t rdx;
663           uint64_t rcx;
664           uint64_t rbx;
665           uint64_t deadbeef;
666           uint64_t rbp;
667           uint64_t fakeret;
668           uint64_t ret;
669           /* char redzone[128]; */
670         } seccomp_stackframe;
671         if (top - offsetof(typeof(seccomp_stackframe), deadbeef) < old_top ||
672             top - offsetof(typeof(seccomp_stackframe), deadbeef) +
673             sizeof(seccomp_stackframe) >
674             thread.stack.start_of_memory_range+thread.stack.memory.data_size) {
675           break;
676         }
677         my_memcpy(&seccomp_stackframe,
678                   bp_addr - offsetof(typeof(seccomp_stackframe), deadbeef),
679                   sizeof(seccomp_stackframe));
680         cpu->rbx = seccomp_stackframe.rbx;
681         cpu->rcx = seccomp_stackframe.rcx;
682         cpu->rdx = seccomp_stackframe.rdx;
683         cpu->rsi = seccomp_stackframe.rsi;
684         cpu->rdi = seccomp_stackframe.rdi;
685         cpu->rbp = seccomp_stackframe.rbp;
686         cpu->rsp = top + 4*sizeof(uint64_t) + 128;
687         cpu->r8  = seccomp_stackframe.r8;
688         cpu->r9  = seccomp_stackframe.r9;
689         cpu->r10 = seccomp_stackframe.r10;
690         cpu->r11 = seccomp_stackframe.r11;
691         cpu->r12 = seccomp_stackframe.r12;
692         cpu->r13 = seccomp_stackframe.r13;
693         cpu->r14 = seccomp_stackframe.r14;
694         cpu->r15 = seccomp_stackframe.r15;
695         cpu->rip = seccomp_stackframe.fakeret;
696         return;
697       }
698     }
699 #elif defined(__i386__)
700     uint32_t bp = cpu->ebp;
701     uint32_t top = thread.stack.start_of_memory_range;
702     for (int i = 4; i--; ) {
703       if (bp < top ||
704           bp + sizeof(bp) > thread.stack.start_of_memory_range +
705           thread.stack.memory.data_size ||
706           bp & 1) {
707         break;
708       }
709       uint32_t old_top = top;
710       top = bp;
711       uint8_t* bp_addr = stack_copy + bp - thread.stack.start_of_memory_range;
712       my_memcpy(&bp, bp_addr, sizeof(bp));
713       if (bp == 0xDEADBEEFu) {
714         struct {
715           uint32_t edi;
716           uint32_t esi;
717           uint32_t edx;
718           uint32_t ecx;
719           uint32_t ebx;
720           uint32_t deadbeef;
721           uint32_t ebp;
722           uint32_t fakeret;
723           uint32_t ret;
724         } seccomp_stackframe;
725         if (top - offsetof(typeof(seccomp_stackframe), deadbeef) < old_top ||
726             top - offsetof(typeof(seccomp_stackframe), deadbeef) +
727             sizeof(seccomp_stackframe) >
728             thread.stack.start_of_memory_range+thread.stack.memory.data_size) {
729           break;
730         }
731         my_memcpy(&seccomp_stackframe,
732                   bp_addr - offsetof(typeof(seccomp_stackframe), deadbeef),
733                   sizeof(seccomp_stackframe));
734         cpu->ebx = seccomp_stackframe.ebx;
735         cpu->ecx = seccomp_stackframe.ecx;
736         cpu->edx = seccomp_stackframe.edx;
737         cpu->esi = seccomp_stackframe.esi;
738         cpu->edi = seccomp_stackframe.edi;
739         cpu->ebp = seccomp_stackframe.ebp;
740         cpu->esp = top + 4*sizeof(void*);
741         cpu->eip = seccomp_stackframe.fakeret;
742         return;
743       }
744     }
745 #endif
746   }
747
748   bool FillThreadStack(MDRawThread* thread, uintptr_t stack_pointer,
749                        int max_stack_len, uint8_t** stack_copy) {
750     *stack_copy = NULL;
751     const void* stack;
752     size_t stack_len;
753     if (dumper_->GetStackInfo(&stack, &stack_len, stack_pointer)) {
754       UntypedMDRVA memory(&minidump_writer_);
755       if (max_stack_len >= 0 &&
756           stack_len > static_cast<unsigned int>(max_stack_len)) {
757         stack_len = max_stack_len;
758       }
759       if (!memory.Allocate(stack_len))
760         return false;
761       *stack_copy = reinterpret_cast<uint8_t*>(Alloc(stack_len));
762       dumper_->CopyFromProcess(*stack_copy, thread->thread_id, stack,
763                                stack_len);
764       memory.Copy(*stack_copy, stack_len);
765       thread->stack.start_of_memory_range =
766           reinterpret_cast<uintptr_t>(stack);
767       thread->stack.memory = memory.location();
768       memory_blocks_.push_back(thread->stack);
769     } else {
770       thread->stack.start_of_memory_range = stack_pointer;
771       thread->stack.memory.data_size = 0;
772       thread->stack.memory.rva = minidump_writer_.position();
773     }
774     return true;
775   }
776
777   // Write information about the threads.
778   bool WriteThreadListStream(MDRawDirectory* dirent) {
779     const unsigned num_threads = dumper_->threads().size();
780
781     TypedMDRVA<uint32_t> list(&minidump_writer_);
782     if (!list.AllocateObjectAndArray(num_threads, sizeof(MDRawThread)))
783       return false;
784
785     dirent->stream_type = MD_THREAD_LIST_STREAM;
786     dirent->location = list.location();
787
788     *list.get() = num_threads;
789
790     // If there's a minidump size limit, check if it might be exceeded.  Since
791     // most of the space is filled with stack data, just check against that.
792     // If this expects to exceed the limit, set extra_thread_stack_len such
793     // that any thread beyond the first kLimitBaseThreadCount threads will
794     // have only kLimitMaxExtraThreadStackLen bytes dumped.
795     int extra_thread_stack_len = -1;  // default to no maximum
796     if (minidump_size_limit_ >= 0) {
797       const unsigned estimated_total_stack_size = num_threads *
798           kLimitAverageThreadStackLength;
799       const off_t estimated_minidump_size = minidump_writer_.position() +
800           estimated_total_stack_size + kLimitMinidumpFudgeFactor;
801       if (estimated_minidump_size > minidump_size_limit_)
802         extra_thread_stack_len = kLimitMaxExtraThreadStackLen;
803     }
804
805     for (unsigned i = 0; i < num_threads; ++i) {
806       MDRawThread thread;
807       my_memset(&thread, 0, sizeof(thread));
808       thread.thread_id = dumper_->threads()[i];
809
810       // We have a different source of information for the crashing thread. If
811       // we used the actual state of the thread we would find it running in the
812       // signal handler with the alternative stack, which would be deeply
813       // unhelpful.
814       if (static_cast<pid_t>(thread.thread_id) == GetCrashThread() &&
815           ucontext_ &&
816           !dumper_->IsPostMortem()) {
817         uint8_t* stack_copy;
818         if (!FillThreadStack(&thread, GetStackPointer(), -1, &stack_copy))
819           return false;
820
821         // Copy 256 bytes around crashing instruction pointer to minidump.
822         const size_t kIPMemorySize = 256;
823         uint64_t ip = GetInstructionPointer();
824         // Bound it to the upper and lower bounds of the memory map
825         // it's contained within. If it's not in mapped memory,
826         // don't bother trying to write it.
827         bool ip_is_mapped = false;
828         MDMemoryDescriptor ip_memory_d;
829         for (unsigned j = 0; j < dumper_->mappings().size(); ++j) {
830           const MappingInfo& mapping = *dumper_->mappings()[j];
831           if (ip >= mapping.start_addr &&
832               ip < mapping.start_addr + mapping.size) {
833             ip_is_mapped = true;
834             // Try to get 128 bytes before and after the IP, but
835             // settle for whatever's available.
836             ip_memory_d.start_of_memory_range =
837               std::max(mapping.start_addr,
838                        uintptr_t(ip - (kIPMemorySize / 2)));
839             uintptr_t end_of_range =
840               std::min(uintptr_t(ip + (kIPMemorySize / 2)),
841                        uintptr_t(mapping.start_addr + mapping.size));
842             ip_memory_d.memory.data_size =
843               end_of_range - ip_memory_d.start_of_memory_range;
844             break;
845           }
846         }
847
848         if (ip_is_mapped) {
849           UntypedMDRVA ip_memory(&minidump_writer_);
850           if (!ip_memory.Allocate(ip_memory_d.memory.data_size))
851             return false;
852           uint8_t* memory_copy =
853               reinterpret_cast<uint8_t*>(Alloc(ip_memory_d.memory.data_size));
854           dumper_->CopyFromProcess(
855               memory_copy,
856               thread.thread_id,
857               reinterpret_cast<void*>(ip_memory_d.start_of_memory_range),
858               ip_memory_d.memory.data_size);
859           ip_memory.Copy(memory_copy, ip_memory_d.memory.data_size);
860           ip_memory_d.memory = ip_memory.location();
861           memory_blocks_.push_back(ip_memory_d);
862         }
863
864         TypedMDRVA<RawContextCPU> cpu(&minidump_writer_);
865         if (!cpu.Allocate())
866           return false;
867         my_memset(cpu.get(), 0, sizeof(RawContextCPU));
868 #if !defined(__ARM_EABI__) && !defined(__mips__)
869         CPUFillFromUContext(cpu.get(), ucontext_, float_state_);
870 #else
871         CPUFillFromUContext(cpu.get(), ucontext_);
872 #endif
873         if (stack_copy)
874           PopSeccompStackFrame(cpu.get(), thread, stack_copy);
875         thread.thread_context = cpu.location();
876         crashing_thread_context_ = cpu.location();
877       } else {
878         ThreadInfo info;
879         if (!dumper_->GetThreadInfoByIndex(i, &info))
880           return false;
881
882         uint8_t* stack_copy;
883         int max_stack_len = -1;  // default to no maximum for this thread
884         if (minidump_size_limit_ >= 0 && i >= kLimitBaseThreadCount)
885           max_stack_len = extra_thread_stack_len;
886         if (!FillThreadStack(&thread, info.stack_pointer, max_stack_len,
887             &stack_copy))
888           return false;
889
890         TypedMDRVA<RawContextCPU> cpu(&minidump_writer_);
891         if (!cpu.Allocate())
892           return false;
893         my_memset(cpu.get(), 0, sizeof(RawContextCPU));
894         CPUFillFromThreadInfo(cpu.get(), info);
895         if (stack_copy)
896           PopSeccompStackFrame(cpu.get(), thread, stack_copy);
897         thread.thread_context = cpu.location();
898         if (dumper_->threads()[i] == GetCrashThread()) {
899           crashing_thread_context_ = cpu.location();
900           if (!dumper_->IsPostMortem()) {
901             // This is the crashing thread of a live process, but
902             // no context was provided, so set the crash address
903             // while the instruction pointer is already here.
904             dumper_->set_crash_address(GetInstructionPointer(info));
905           }
906         }
907       }
908
909       list.CopyIndexAfterObject(i, &thread, sizeof(thread));
910     }
911
912     return true;
913   }
914
915   // Write application-provided memory regions.
916   bool WriteAppMemory() {
917     for (AppMemoryList::const_iterator iter = app_memory_list_.begin();
918          iter != app_memory_list_.end();
919          ++iter) {
920       uint8_t* data_copy =
921         reinterpret_cast<uint8_t*>(dumper_->allocator()->Alloc(iter->length));
922       dumper_->CopyFromProcess(data_copy, GetCrashThread(), iter->ptr,
923                                iter->length);
924
925       UntypedMDRVA memory(&minidump_writer_);
926       if (!memory.Allocate(iter->length)) {
927         return false;
928       }
929       memory.Copy(data_copy, iter->length);
930       MDMemoryDescriptor desc;
931       desc.start_of_memory_range = reinterpret_cast<uintptr_t>(iter->ptr);
932       desc.memory = memory.location();
933       memory_blocks_.push_back(desc);
934     }
935
936     return true;
937   }
938
939   static bool ShouldIncludeMapping(const MappingInfo& mapping) {
940     if (mapping.name[0] == 0 ||  // only want modules with filenames.
941         // Only want to include one mapping per shared lib.
942         // Avoid filtering executable mappings.
943         (mapping.offset != 0 && !mapping.exec) ||
944         mapping.size < 4096) {  // too small to get a signature for.
945       return false;
946     }
947
948     return true;
949   }
950
951   // If there is caller-provided information about this mapping
952   // in the mapping_list_ list, return true. Otherwise, return false.
953   bool HaveMappingInfo(const MappingInfo& mapping) {
954     for (MappingList::const_iterator iter = mapping_list_.begin();
955          iter != mapping_list_.end();
956          ++iter) {
957       // Ignore any mappings that are wholly contained within
958       // mappings in the mapping_info_ list.
959       if (mapping.start_addr >= iter->first.start_addr &&
960           (mapping.start_addr + mapping.size) <=
961           (iter->first.start_addr + iter->first.size)) {
962         return true;
963       }
964     }
965     return false;
966   }
967
968   // Write information about the mappings in effect. Because we are using the
969   // minidump format, the information about the mappings is pretty limited.
970   // Because of this, we also include the full, unparsed, /proc/$x/maps file in
971   // another stream in the file.
972   bool WriteMappings(MDRawDirectory* dirent) {
973     const unsigned num_mappings = dumper_->mappings().size();
974     unsigned num_output_mappings = mapping_list_.size();
975
976     for (unsigned i = 0; i < dumper_->mappings().size(); ++i) {
977       const MappingInfo& mapping = *dumper_->mappings()[i];
978       if (ShouldIncludeMapping(mapping) && !HaveMappingInfo(mapping))
979         num_output_mappings++;
980     }
981
982     TypedMDRVA<uint32_t> list(&minidump_writer_);
983     if (num_output_mappings) {
984       if (!list.AllocateObjectAndArray(num_output_mappings, MD_MODULE_SIZE))
985         return false;
986     } else {
987       // Still create the module list stream, although it will have zero
988       // modules.
989       if (!list.Allocate())
990         return false;
991     }
992
993     dirent->stream_type = MD_MODULE_LIST_STREAM;
994     dirent->location = list.location();
995     *list.get() = num_output_mappings;
996
997     // First write all the mappings from the dumper
998     unsigned int j = 0;
999     for (unsigned i = 0; i < num_mappings; ++i) {
1000       const MappingInfo& mapping = *dumper_->mappings()[i];
1001       if (!ShouldIncludeMapping(mapping) || HaveMappingInfo(mapping))
1002         continue;
1003
1004       MDRawModule mod;
1005       if (!FillRawModule(mapping, true, i, mod, NULL))
1006         return false;
1007       list.CopyIndexAfterObject(j++, &mod, MD_MODULE_SIZE);
1008     }
1009     // Next write all the mappings provided by the caller
1010     for (MappingList::const_iterator iter = mapping_list_.begin();
1011          iter != mapping_list_.end();
1012          ++iter) {
1013       MDRawModule mod;
1014       if (!FillRawModule(iter->first, false, 0, mod, iter->second))
1015         return false;
1016       list.CopyIndexAfterObject(j++, &mod, MD_MODULE_SIZE);
1017     }
1018
1019     return true;
1020   }
1021
1022   // Fill the MDRawModule |mod| with information about the provided
1023   // |mapping|. If |identifier| is non-NULL, use it instead of calculating
1024   // a file ID from the mapping.
1025   bool FillRawModule(const MappingInfo& mapping,
1026                      bool member,
1027                      unsigned int mapping_id,
1028                      MDRawModule& mod,
1029                      const uint8_t* identifier) {
1030     my_memset(&mod, 0, MD_MODULE_SIZE);
1031
1032     mod.base_of_image = mapping.start_addr;
1033     mod.size_of_image = mapping.size;
1034     const char* filepath_ptr = mapping.name;
1035     size_t filepath_len = my_strlen(mapping.name);
1036
1037     // Figure out file name from path
1038     const char* filename_ptr = mapping.name + filepath_len - 1;
1039     while (filename_ptr >= mapping.name) {
1040       if (*filename_ptr == '/')
1041         break;
1042       filename_ptr--;
1043     }
1044     filename_ptr++;
1045
1046     size_t filename_len = mapping.name + filepath_len - filename_ptr;
1047
1048     // If an executable is mapped from a non-zero offset, this is likely
1049     // because the executable was loaded directly from inside an archive
1050     // file. We try to find the name of the shared object (SONAME) by
1051     // looking in the file for ELF sections.
1052
1053     char soname[NAME_MAX];
1054     char pathname[NAME_MAX];
1055     if (mapping.exec && mapping.offset != 0 &&
1056         LinuxDumper::ElfFileSoName(mapping, soname, sizeof(soname))) {
1057       filename_ptr = soname;
1058       filename_len = my_strlen(soname);
1059
1060       if (filepath_len + filename_len + 1 < NAME_MAX) {
1061         // It doesn't have a real pathname, but tools such as stackwalk
1062         // extract the basename, so simulating a pathname is helpful.
1063         my_memcpy(pathname, filepath_ptr, filepath_len);
1064         pathname[filepath_len] = '/';
1065         my_memcpy(pathname + filepath_len + 1, filename_ptr, filename_len);
1066         pathname[filepath_len + filename_len + 1] = '\0';
1067         filepath_ptr = pathname;
1068         filepath_len = filepath_len + filename_len + 1;
1069       }
1070     }
1071
1072     uint8_t cv_buf[MDCVInfoPDB70_minsize + NAME_MAX];
1073     uint8_t* cv_ptr = cv_buf;
1074     UntypedMDRVA cv(&minidump_writer_);
1075     if (!cv.Allocate(MDCVInfoPDB70_minsize + filename_len + 1))
1076       return false;
1077
1078     const uint32_t cv_signature = MD_CVINFOPDB70_SIGNATURE;
1079     my_memcpy(cv_ptr, &cv_signature, sizeof(cv_signature));
1080     cv_ptr += sizeof(cv_signature);
1081     uint8_t* signature = cv_ptr;
1082     cv_ptr += sizeof(MDGUID);
1083     if (identifier) {
1084       // GUID was provided by caller.
1085       my_memcpy(signature, identifier, sizeof(MDGUID));
1086     } else {
1087       dumper_->ElfFileIdentifierForMapping(mapping, member,
1088                                            mapping_id, signature);
1089     }
1090     my_memset(cv_ptr, 0, sizeof(uint32_t));  // Set age to 0 on Linux.
1091     cv_ptr += sizeof(uint32_t);
1092
1093     // Write pdb_file_name
1094     my_memcpy(cv_ptr, filename_ptr, filename_len + 1);
1095     cv.Copy(cv_buf, MDCVInfoPDB70_minsize + filename_len + 1);
1096
1097     mod.cv_record = cv.location();
1098
1099     MDLocationDescriptor ld;
1100     if (!minidump_writer_.WriteString(filepath_ptr, filepath_len, &ld))
1101       return false;
1102     mod.module_name_rva = ld.rva;
1103     return true;
1104   }
1105
1106   bool WriteMemoryListStream(MDRawDirectory* dirent) {
1107     TypedMDRVA<uint32_t> list(&minidump_writer_);
1108     if (memory_blocks_.size()) {
1109       if (!list.AllocateObjectAndArray(memory_blocks_.size(),
1110                                        sizeof(MDMemoryDescriptor)))
1111         return false;
1112     } else {
1113       // Still create the memory list stream, although it will have zero
1114       // memory blocks.
1115       if (!list.Allocate())
1116         return false;
1117     }
1118
1119     dirent->stream_type = MD_MEMORY_LIST_STREAM;
1120     dirent->location = list.location();
1121
1122     *list.get() = memory_blocks_.size();
1123
1124     for (size_t i = 0; i < memory_blocks_.size(); ++i) {
1125       list.CopyIndexAfterObject(i, &memory_blocks_[i],
1126                                 sizeof(MDMemoryDescriptor));
1127     }
1128     return true;
1129   }
1130
1131   bool WriteExceptionStream(MDRawDirectory* dirent) {
1132     TypedMDRVA<MDRawExceptionStream> exc(&minidump_writer_);
1133     if (!exc.Allocate())
1134       return false;
1135     my_memset(exc.get(), 0, sizeof(MDRawExceptionStream));
1136
1137     dirent->stream_type = MD_EXCEPTION_STREAM;
1138     dirent->location = exc.location();
1139
1140     exc.get()->thread_id = GetCrashThread();
1141     exc.get()->exception_record.exception_code = dumper_->crash_signal();
1142     exc.get()->exception_record.exception_address = dumper_->crash_address();
1143     exc.get()->thread_context = crashing_thread_context_;
1144
1145     return true;
1146   }
1147
1148   bool WriteSystemInfoStream(MDRawDirectory* dirent) {
1149     TypedMDRVA<MDRawSystemInfo> si(&minidump_writer_);
1150     if (!si.Allocate())
1151       return false;
1152     my_memset(si.get(), 0, sizeof(MDRawSystemInfo));
1153
1154     dirent->stream_type = MD_SYSTEM_INFO_STREAM;
1155     dirent->location = si.location();
1156
1157     WriteCPUInformation(si.get());
1158     WriteOSInformation(si.get());
1159
1160     return true;
1161   }
1162
1163   bool WriteDSODebugStream(MDRawDirectory* dirent) {
1164     ElfW(Phdr)* phdr = reinterpret_cast<ElfW(Phdr) *>(dumper_->auxv()[AT_PHDR]);
1165     char* base;
1166     int phnum = dumper_->auxv()[AT_PHNUM];
1167     if (!phnum || !phdr)
1168       return false;
1169
1170     // Assume the program base is at the beginning of the same page as the PHDR
1171     base = reinterpret_cast<char *>(reinterpret_cast<uintptr_t>(phdr) & ~0xfff);
1172
1173     // Search for the program PT_DYNAMIC segment
1174     ElfW(Addr) dyn_addr = 0;
1175     for (; phnum >= 0; phnum--, phdr++) {
1176       ElfW(Phdr) ph;
1177       dumper_->CopyFromProcess(&ph, GetCrashThread(), phdr, sizeof(ph));
1178       // Adjust base address with the virtual address of the PT_LOAD segment
1179       // corresponding to offset 0
1180       if (ph.p_type == PT_LOAD && ph.p_offset == 0) {
1181         base -= ph.p_vaddr;
1182       }
1183       if (ph.p_type == PT_DYNAMIC) {
1184         dyn_addr = ph.p_vaddr;
1185       }
1186     }
1187     if (!dyn_addr)
1188       return false;
1189
1190     ElfW(Dyn) *dynamic = reinterpret_cast<ElfW(Dyn) *>(dyn_addr + base);
1191
1192     // The dynamic linker makes information available that helps gdb find all
1193     // DSOs loaded into the program. If this information is indeed available,
1194     // dump it to a MD_LINUX_DSO_DEBUG stream.
1195     struct r_debug* r_debug = NULL;
1196     uint32_t dynamic_length = 0;
1197
1198     for (int i = 0;;) {
1199       ElfW(Dyn) dyn;
1200       dynamic_length += sizeof(dyn);
1201       dumper_->CopyFromProcess(&dyn, GetCrashThread(), dynamic+i++,
1202                                sizeof(dyn));
1203       if (dyn.d_tag == DT_DEBUG) {
1204         r_debug = reinterpret_cast<struct r_debug*>(dyn.d_un.d_ptr);
1205         continue;
1206       } else if (dyn.d_tag == DT_NULL) {
1207         break;
1208       }
1209     }
1210
1211     // The "r_map" field of that r_debug struct contains a linked list of all
1212     // loaded DSOs.
1213     // Our list of DSOs potentially is different from the ones in the crashing
1214     // process. So, we have to be careful to never dereference pointers
1215     // directly. Instead, we use CopyFromProcess() everywhere.
1216     // See <link.h> for a more detailed discussion of the how the dynamic
1217     // loader communicates with debuggers.
1218
1219     // Count the number of loaded DSOs
1220     int dso_count = 0;
1221     struct r_debug debug_entry;
1222     dumper_->CopyFromProcess(&debug_entry, GetCrashThread(), r_debug,
1223                              sizeof(debug_entry));
1224     for (struct link_map* ptr = debug_entry.r_map; ptr; ) {
1225       struct link_map map;
1226       dumper_->CopyFromProcess(&map, GetCrashThread(), ptr, sizeof(map));
1227       ptr = map.l_next;
1228       dso_count++;
1229     }
1230
1231     MDRVA linkmap_rva = minidump_writer_.kInvalidMDRVA;
1232     if (dso_count > 0) {
1233       // If we have at least one DSO, create an array of MDRawLinkMap
1234       // entries in the minidump file.
1235       TypedMDRVA<MDRawLinkMap> linkmap(&minidump_writer_);
1236       if (!linkmap.AllocateArray(dso_count))
1237         return false;
1238       linkmap_rva = linkmap.location().rva;
1239       int idx = 0;
1240
1241       // Iterate over DSOs and write their information to mini dump
1242       for (struct link_map* ptr = debug_entry.r_map; ptr; ) {
1243         struct link_map map;
1244         dumper_->CopyFromProcess(&map, GetCrashThread(), ptr, sizeof(map));
1245         ptr = map.l_next;
1246         char filename[257] = { 0 };
1247         if (map.l_name) {
1248           dumper_->CopyFromProcess(filename, GetCrashThread(), map.l_name,
1249                                    sizeof(filename) - 1);
1250         }
1251         MDLocationDescriptor location;
1252         if (!minidump_writer_.WriteString(filename, 0, &location))
1253           return false;
1254         MDRawLinkMap entry;
1255         entry.name = location.rva;
1256         entry.addr = reinterpret_cast<void*>(map.l_addr);
1257         entry.ld = reinterpret_cast<void*>(map.l_ld);
1258         linkmap.CopyIndex(idx++, &entry);
1259       }
1260     }
1261
1262     // Write MD_LINUX_DSO_DEBUG record
1263     TypedMDRVA<MDRawDebug> debug(&minidump_writer_);
1264     if (!debug.AllocateObjectAndArray(1, dynamic_length))
1265       return false;
1266     my_memset(debug.get(), 0, sizeof(MDRawDebug));
1267     dirent->stream_type = MD_LINUX_DSO_DEBUG;
1268     dirent->location = debug.location();
1269
1270     debug.get()->version = debug_entry.r_version;
1271     debug.get()->map = linkmap_rva;
1272     debug.get()->dso_count = dso_count;
1273     debug.get()->brk = reinterpret_cast<void*>(debug_entry.r_brk);
1274     debug.get()->ldbase = reinterpret_cast<void*>(debug_entry.r_ldbase);
1275     debug.get()->dynamic = dynamic;
1276
1277     wasteful_vector<char> dso_debug_data(dumper_->allocator(), dynamic_length);
1278     // The passed-in size to the constructor (above) is only a hint.
1279     // Must call .resize() to do actual initialization of the elements.
1280     dso_debug_data.resize(dynamic_length);
1281     dumper_->CopyFromProcess(&dso_debug_data[0], GetCrashThread(), dynamic,
1282                              dynamic_length);
1283     debug.CopyIndexAfterObject(0, &dso_debug_data[0], dynamic_length);
1284
1285     return true;
1286   }
1287
1288   void set_minidump_size_limit(off_t limit) { minidump_size_limit_ = limit; }
1289
1290  private:
1291   void* Alloc(unsigned bytes) {
1292     return dumper_->allocator()->Alloc(bytes);
1293   }
1294
1295   pid_t GetCrashThread() const {
1296     return dumper_->crash_thread();
1297   }
1298
1299 #if defined(__i386__)
1300   uintptr_t GetStackPointer() {
1301     return ucontext_->uc_mcontext.gregs[REG_ESP];
1302   }
1303
1304   uintptr_t GetInstructionPointer() {
1305     return ucontext_->uc_mcontext.gregs[REG_EIP];
1306   }
1307
1308   uintptr_t GetInstructionPointer(const ThreadInfo& info) {
1309     return info.regs.eip;
1310   }
1311 #elif defined(__x86_64)
1312   uintptr_t GetStackPointer() {
1313     return ucontext_->uc_mcontext.gregs[REG_RSP];
1314   }
1315
1316   uintptr_t GetInstructionPointer() {
1317     return ucontext_->uc_mcontext.gregs[REG_RIP];
1318   }
1319
1320   uintptr_t GetInstructionPointer(const ThreadInfo& info) {
1321     return info.regs.rip;
1322   }
1323 #elif defined(__ARM_EABI__)
1324   uintptr_t GetStackPointer() {
1325     return ucontext_->uc_mcontext.arm_sp;
1326   }
1327
1328   uintptr_t GetInstructionPointer() {
1329     return ucontext_->uc_mcontext.arm_pc;
1330   }
1331
1332   uintptr_t GetInstructionPointer(const ThreadInfo& info) {
1333     return info.regs.uregs[15];
1334   }
1335 #elif defined(__aarch64__)
1336   uintptr_t GetStackPointer() {
1337     return ucontext_->uc_mcontext.sp;
1338   }
1339
1340   uintptr_t GetInstructionPointer() {
1341     return ucontext_->uc_mcontext.pc;
1342   }
1343
1344   uintptr_t GetInstructionPointer(const ThreadInfo& info) {
1345     return info.regs.pc;
1346   }
1347 #elif defined(__mips__)
1348   uintptr_t GetStackPointer() {
1349     return ucontext_->uc_mcontext.gregs[MD_CONTEXT_MIPS_REG_SP];
1350   }
1351
1352   uintptr_t GetInstructionPointer() {
1353     return ucontext_->uc_mcontext.pc;
1354   }
1355
1356   uintptr_t GetInstructionPointer(const ThreadInfo& info) {
1357     return info.regs.epc;
1358   }
1359 #else
1360 #error "This code has not been ported to your platform yet."
1361 #endif
1362
1363   void NullifyDirectoryEntry(MDRawDirectory* dirent) {
1364     dirent->stream_type = 0;
1365     dirent->location.data_size = 0;
1366     dirent->location.rva = 0;
1367   }
1368
1369 #if defined(__i386__) || defined(__x86_64__) || defined(__mips__)
1370   bool WriteCPUInformation(MDRawSystemInfo* sys_info) {
1371     char vendor_id[sizeof(sys_info->cpu.x86_cpu_info.vendor_id) + 1] = {0};
1372     static const char vendor_id_name[] = "vendor_id";
1373
1374     struct CpuInfoEntry {
1375       const char* info_name;
1376       int value;
1377       bool found;
1378     } cpu_info_table[] = {
1379       { "processor", -1, false },
1380 #if defined(__i386__) || defined(__x86_64__)
1381       { "model", 0, false },
1382       { "stepping",  0, false },
1383       { "cpu family", 0, false },
1384 #endif
1385     };
1386
1387     // processor_architecture should always be set, do this first
1388     sys_info->processor_architecture =
1389 #if defined(__mips__)
1390         MD_CPU_ARCHITECTURE_MIPS;
1391 #elif defined(__i386__)
1392         MD_CPU_ARCHITECTURE_X86;
1393 #else
1394         MD_CPU_ARCHITECTURE_AMD64;
1395 #endif
1396
1397     const int fd = sys_open("/proc/cpuinfo", O_RDONLY, 0);
1398     if (fd < 0)
1399       return false;
1400
1401     {
1402       PageAllocator allocator;
1403       ProcCpuInfoReader* const reader = new(allocator) ProcCpuInfoReader(fd);
1404       const char* field;
1405       while (reader->GetNextField(&field)) {
1406         for (size_t i = 0;
1407              i < sizeof(cpu_info_table) / sizeof(cpu_info_table[0]);
1408              i++) {
1409           CpuInfoEntry* entry = &cpu_info_table[i];
1410           if (i > 0 && entry->found) {
1411             // except for the 'processor' field, ignore repeated values.
1412             continue;
1413           }
1414           if (!my_strcmp(field, entry->info_name)) {
1415             size_t value_len;
1416             const char* value = reader->GetValueAndLen(&value_len);
1417             if (value_len == 0)
1418               continue;
1419
1420             uintptr_t val;
1421             if (my_read_decimal_ptr(&val, value) == value)
1422               continue;
1423
1424             entry->value = static_cast<int>(val);
1425             entry->found = true;
1426           }
1427         }
1428
1429         // special case for vendor_id
1430         if (!my_strcmp(field, vendor_id_name)) {
1431           size_t value_len;
1432           const char* value = reader->GetValueAndLen(&value_len);
1433           if (value_len > 0)
1434             my_strlcpy(vendor_id, value, sizeof(vendor_id));
1435         }
1436       }
1437       sys_close(fd);
1438     }
1439
1440     // make sure we got everything we wanted
1441     for (size_t i = 0;
1442          i < sizeof(cpu_info_table) / sizeof(cpu_info_table[0]);
1443          i++) {
1444       if (!cpu_info_table[i].found) {
1445         return false;
1446       }
1447     }
1448     // cpu_info_table[0] holds the last cpu id listed in /proc/cpuinfo,
1449     // assuming this is the highest id, change it to the number of CPUs
1450     // by adding one.
1451     cpu_info_table[0].value++;
1452
1453     sys_info->number_of_processors = cpu_info_table[0].value;
1454 #if defined(__i386__) || defined(__x86_64__)
1455     sys_info->processor_level      = cpu_info_table[3].value;
1456     sys_info->processor_revision   = cpu_info_table[1].value << 8 |
1457                                      cpu_info_table[2].value;
1458 #endif
1459
1460     if (vendor_id[0] != '\0') {
1461       my_memcpy(sys_info->cpu.x86_cpu_info.vendor_id, vendor_id,
1462                 sizeof(sys_info->cpu.x86_cpu_info.vendor_id));
1463     }
1464     return true;
1465   }
1466 #elif defined(__arm__) || defined(__aarch64__)
1467   bool WriteCPUInformation(MDRawSystemInfo* sys_info) {
1468     // The CPUID value is broken up in several entries in /proc/cpuinfo.
1469     // This table is used to rebuild it from the entries.
1470     const struct CpuIdEntry {
1471       const char* field;
1472       char        format;
1473       char        bit_lshift;
1474       char        bit_length;
1475     } cpu_id_entries[] = {
1476       { "CPU implementer", 'x', 24, 8 },
1477       { "CPU variant", 'x', 20, 4 },
1478       { "CPU part", 'x', 4, 12 },
1479       { "CPU revision", 'd', 0, 4 },
1480     };
1481
1482     // The ELF hwcaps are listed in the "Features" entry as textual tags.
1483     // This table is used to rebuild them.
1484     const struct CpuFeaturesEntry {
1485       const char* tag;
1486       uint32_t hwcaps;
1487     } cpu_features_entries[] = {
1488 #if defined(__arm__)
1489       { "swp",  MD_CPU_ARM_ELF_HWCAP_SWP },
1490       { "half", MD_CPU_ARM_ELF_HWCAP_HALF },
1491       { "thumb", MD_CPU_ARM_ELF_HWCAP_THUMB },
1492       { "26bit", MD_CPU_ARM_ELF_HWCAP_26BIT },
1493       { "fastmult", MD_CPU_ARM_ELF_HWCAP_FAST_MULT },
1494       { "fpa", MD_CPU_ARM_ELF_HWCAP_FPA },
1495       { "vfp", MD_CPU_ARM_ELF_HWCAP_VFP },
1496       { "edsp", MD_CPU_ARM_ELF_HWCAP_EDSP },
1497       { "java", MD_CPU_ARM_ELF_HWCAP_JAVA },
1498       { "iwmmxt", MD_CPU_ARM_ELF_HWCAP_IWMMXT },
1499       { "crunch", MD_CPU_ARM_ELF_HWCAP_CRUNCH },
1500       { "thumbee", MD_CPU_ARM_ELF_HWCAP_THUMBEE },
1501       { "neon", MD_CPU_ARM_ELF_HWCAP_NEON },
1502       { "vfpv3", MD_CPU_ARM_ELF_HWCAP_VFPv3 },
1503       { "vfpv3d16", MD_CPU_ARM_ELF_HWCAP_VFPv3D16 },
1504       { "tls", MD_CPU_ARM_ELF_HWCAP_TLS },
1505       { "vfpv4", MD_CPU_ARM_ELF_HWCAP_VFPv4 },
1506       { "idiva", MD_CPU_ARM_ELF_HWCAP_IDIVA },
1507       { "idivt", MD_CPU_ARM_ELF_HWCAP_IDIVT },
1508       { "idiv", MD_CPU_ARM_ELF_HWCAP_IDIVA | MD_CPU_ARM_ELF_HWCAP_IDIVT },
1509 #elif defined(__aarch64__)
1510       // No hwcaps on aarch64.
1511 #endif
1512     };
1513
1514     // processor_architecture should always be set, do this first
1515     sys_info->processor_architecture =
1516 #if defined(__aarch64__)
1517         MD_CPU_ARCHITECTURE_ARM64;
1518 #else
1519         MD_CPU_ARCHITECTURE_ARM;
1520 #endif
1521
1522     // /proc/cpuinfo is not readable under various sandboxed environments
1523     // (e.g. Android services with the android:isolatedProcess attribute)
1524     // prepare for this by setting default values now, which will be
1525     // returned when this happens.
1526     //
1527     // Note: Bogus values are used to distinguish between failures (to
1528     //       read /sys and /proc files) and really badly configured kernels.
1529     sys_info->number_of_processors = 0;
1530     sys_info->processor_level = 1U;  // There is no ARMv1
1531     sys_info->processor_revision = 42;
1532     sys_info->cpu.arm_cpu_info.cpuid = 0;
1533     sys_info->cpu.arm_cpu_info.elf_hwcaps = 0;
1534
1535     // Counting the number of CPUs involves parsing two sysfs files,
1536     // because the content of /proc/cpuinfo will only mirror the number
1537     // of 'online' cores, and thus will vary with time.
1538     // See http://www.kernel.org/doc/Documentation/cputopology.txt
1539     {
1540       CpuSet cpus_present;
1541       CpuSet cpus_possible;
1542
1543       int fd = sys_open("/sys/devices/system/cpu/present", O_RDONLY, 0);
1544       if (fd >= 0) {
1545         cpus_present.ParseSysFile(fd);
1546         sys_close(fd);
1547
1548         fd = sys_open("/sys/devices/system/cpu/possible", O_RDONLY, 0);
1549         if (fd >= 0) {
1550           cpus_possible.ParseSysFile(fd);
1551           sys_close(fd);
1552
1553           cpus_present.IntersectWith(cpus_possible);
1554           int cpu_count = cpus_present.GetCount();
1555           if (cpu_count > 255)
1556             cpu_count = 255;
1557           sys_info->number_of_processors = static_cast<uint8_t>(cpu_count);
1558         }
1559       }
1560     }
1561
1562     // Parse /proc/cpuinfo to reconstruct the CPUID value, as well
1563     // as the ELF hwcaps field. For the latter, it would be easier to
1564     // read /proc/self/auxv but unfortunately, this file is not always
1565     // readable from regular Android applications on later versions
1566     // (>= 4.1) of the Android platform.
1567     const int fd = sys_open("/proc/cpuinfo", O_RDONLY, 0);
1568     if (fd < 0) {
1569       // Do not return false here to allow the minidump generation
1570       // to happen properly.
1571       return true;
1572     }
1573
1574     {
1575       PageAllocator allocator;
1576       ProcCpuInfoReader* const reader =
1577           new(allocator) ProcCpuInfoReader(fd);
1578       const char* field;
1579       while (reader->GetNextField(&field)) {
1580         for (size_t i = 0;
1581              i < sizeof(cpu_id_entries)/sizeof(cpu_id_entries[0]);
1582              ++i) {
1583           const CpuIdEntry* entry = &cpu_id_entries[i];
1584           if (my_strcmp(entry->field, field) != 0)
1585             continue;
1586           uintptr_t result = 0;
1587           const char* value = reader->GetValue();
1588           const char* p = value;
1589           if (value[0] == '0' && value[1] == 'x') {
1590             p = my_read_hex_ptr(&result, value+2);
1591           } else if (entry->format == 'x') {
1592             p = my_read_hex_ptr(&result, value);
1593           } else {
1594             p = my_read_decimal_ptr(&result, value);
1595           }
1596           if (p == value)
1597             continue;
1598
1599           result &= (1U << entry->bit_length)-1;
1600           result <<= entry->bit_lshift;
1601           sys_info->cpu.arm_cpu_info.cpuid |=
1602               static_cast<uint32_t>(result);
1603         }
1604 #if defined(__arm__)
1605         // Get the architecture version from the "Processor" field.
1606         // Note that it is also available in the "CPU architecture" field,
1607         // however, some existing kernels are misconfigured and will report
1608         // invalid values here (e.g. 6, while the CPU is ARMv7-A based).
1609         // The "Processor" field doesn't have this issue.
1610         if (!my_strcmp(field, "Processor")) {
1611           size_t value_len;
1612           const char* value = reader->GetValueAndLen(&value_len);
1613           // Expected format: <text> (v<level><endian>)
1614           // Where <text> is some text like "ARMv7 Processor rev 2"
1615           // and <level> is a decimal corresponding to the ARM
1616           // architecture number. <endian> is either 'l' or 'b'
1617           // and corresponds to the endianess, it is ignored here.
1618           while (value_len > 0 && my_isspace(value[value_len-1]))
1619             value_len--;
1620
1621           size_t nn = value_len;
1622           while (nn > 0 && value[nn-1] != '(')
1623             nn--;
1624           if (nn > 0 && value[nn] == 'v') {
1625             uintptr_t arch_level = 5;
1626             my_read_decimal_ptr(&arch_level, value + nn + 1);
1627             sys_info->processor_level = static_cast<uint16_t>(arch_level);
1628           }
1629         }
1630 #elif defined(__aarch64__)
1631         // The aarch64 architecture does not provide the architecture level
1632         // in the Processor field, so we instead check the "CPU architecture"
1633         // field.
1634         if (!my_strcmp(field, "CPU architecture")) {
1635           uintptr_t arch_level = 0;
1636           const char* value = reader->GetValue();
1637           const char* p = value;
1638           p = my_read_decimal_ptr(&arch_level, value);
1639           if (p == value)
1640             continue;
1641           sys_info->processor_level = static_cast<uint16_t>(arch_level);
1642         }
1643 #endif
1644         // Rebuild the ELF hwcaps from the 'Features' field.
1645         if (!my_strcmp(field, "Features")) {
1646           size_t value_len;
1647           const char* value = reader->GetValueAndLen(&value_len);
1648
1649           // Parse each space-separated tag.
1650           while (value_len > 0) {
1651             const char* tag = value;
1652             size_t tag_len = value_len;
1653             const char* p = my_strchr(tag, ' ');
1654             if (p != NULL) {
1655               tag_len = static_cast<size_t>(p - tag);
1656               value += tag_len + 1;
1657               value_len -= tag_len + 1;
1658             } else {
1659               tag_len = strlen(tag);
1660               value_len = 0;
1661             }
1662             for (size_t i = 0;
1663                 i < sizeof(cpu_features_entries)/
1664                     sizeof(cpu_features_entries[0]);
1665                 ++i) {
1666               const CpuFeaturesEntry* entry = &cpu_features_entries[i];
1667               if (tag_len == strlen(entry->tag) &&
1668                   !memcmp(tag, entry->tag, tag_len)) {
1669                 sys_info->cpu.arm_cpu_info.elf_hwcaps |= entry->hwcaps;
1670                 break;
1671               }
1672             }
1673           }
1674         }
1675       }
1676       sys_close(fd);
1677     }
1678
1679     return true;
1680   }
1681 #else
1682 #  error "Unsupported CPU"
1683 #endif
1684
1685   bool WriteFile(MDLocationDescriptor* result, const char* filename) {
1686     const int fd = sys_open(filename, O_RDONLY, 0);
1687     if (fd < 0)
1688       return false;
1689
1690     // We can't stat the files because several of the files that we want to
1691     // read are kernel seqfiles, which always have a length of zero. So we have
1692     // to read as much as we can into a buffer.
1693     static const unsigned kBufSize = 1024 - 2*sizeof(void*);
1694     struct Buffers {
1695       Buffers* next;
1696       size_t len;
1697       uint8_t data[kBufSize];
1698     } *buffers = reinterpret_cast<Buffers*>(Alloc(sizeof(Buffers)));
1699     buffers->next = NULL;
1700     buffers->len = 0;
1701
1702     size_t total = 0;
1703     for (Buffers* bufptr = buffers;;) {
1704       ssize_t r;
1705       do {
1706         r = sys_read(fd, &bufptr->data[bufptr->len], kBufSize - bufptr->len);
1707       } while (r == -1 && errno == EINTR);
1708
1709       if (r < 1)
1710         break;
1711
1712       total += r;
1713       bufptr->len += r;
1714       if (bufptr->len == kBufSize) {
1715         bufptr->next = reinterpret_cast<Buffers*>(Alloc(sizeof(Buffers)));
1716         bufptr = bufptr->next;
1717         bufptr->next = NULL;
1718         bufptr->len = 0;
1719       }
1720     }
1721     sys_close(fd);
1722
1723     if (!total)
1724       return false;
1725
1726     UntypedMDRVA memory(&minidump_writer_);
1727     if (!memory.Allocate(total))
1728       return false;
1729     for (MDRVA pos = memory.position(); buffers; buffers = buffers->next) {
1730       // Check for special case of a zero-length buffer.  This should only
1731       // occur if a file's size happens to be a multiple of the buffer's
1732       // size, in which case the final sys_read() will have resulted in
1733       // zero bytes being read after the final buffer was just allocated.
1734       if (buffers->len == 0) {
1735         // This can only occur with final buffer.
1736         assert(buffers->next == NULL);
1737         continue;
1738       }
1739       memory.Copy(pos, &buffers->data, buffers->len);
1740       pos += buffers->len;
1741     }
1742     *result = memory.location();
1743     return true;
1744   }
1745
1746   bool WriteOSInformation(MDRawSystemInfo* sys_info) {
1747 #if defined(__ANDROID__)
1748     sys_info->platform_id = MD_OS_ANDROID;
1749 #else
1750     sys_info->platform_id = MD_OS_LINUX;
1751 #endif
1752
1753     struct utsname uts;
1754     if (uname(&uts))
1755       return false;
1756
1757     static const size_t buf_len = 512;
1758     char buf[buf_len] = {0};
1759     size_t space_left = buf_len - 1;
1760     const char* info_table[] = {
1761       uts.sysname,
1762       uts.release,
1763       uts.version,
1764       uts.machine,
1765       NULL
1766     };
1767     bool first_item = true;
1768     for (const char** cur_info = info_table; *cur_info; cur_info++) {
1769       static const char separator[] = " ";
1770       size_t separator_len = sizeof(separator) - 1;
1771       size_t info_len = my_strlen(*cur_info);
1772       if (info_len == 0)
1773         continue;
1774
1775       if (space_left < info_len + (first_item ? 0 : separator_len))
1776         break;
1777
1778       if (!first_item) {
1779         my_strlcat(buf, separator, sizeof(buf));
1780         space_left -= separator_len;
1781       }
1782
1783       first_item = false;
1784       my_strlcat(buf, *cur_info, sizeof(buf));
1785       space_left -= info_len;
1786     }
1787
1788     MDLocationDescriptor location;
1789     if (!minidump_writer_.WriteString(buf, 0, &location))
1790       return false;
1791     sys_info->csd_version_rva = location.rva;
1792
1793     return true;
1794   }
1795
1796   bool WriteProcFile(MDLocationDescriptor* result, pid_t pid,
1797                      const char* filename) {
1798     char buf[NAME_MAX];
1799     if (!dumper_->BuildProcPath(buf, pid, filename))
1800       return false;
1801     return WriteFile(result, buf);
1802   }
1803
1804   // Only one of the 2 member variables below should be set to a valid value.
1805   const int fd_;  // File descriptor where the minidum should be written.
1806   const char* path_;  // Path to the file where the minidum should be written.
1807
1808   const struct ucontext* const ucontext_;  // also from the signal handler
1809 #if !defined(__ARM_EABI__) && !defined(__mips__)
1810   const google_breakpad::fpstate_t* const float_state_;  // ditto
1811 #endif
1812   LinuxDumper* dumper_;
1813   MinidumpFileWriter minidump_writer_;
1814   off_t minidump_size_limit_;
1815   MDLocationDescriptor crashing_thread_context_;
1816   // Blocks of memory written to the dump. These are all currently
1817   // written while writing the thread list stream, but saved here
1818   // so a memory list stream can be written afterwards.
1819   wasteful_vector<MDMemoryDescriptor> memory_blocks_;
1820   // Additional information about some mappings provided by the caller.
1821   const MappingList& mapping_list_;
1822   // Additional memory regions to be included in the dump,
1823   // provided by the caller.
1824   const AppMemoryList& app_memory_list_;
1825 };
1826
1827
1828 bool WriteMinidumpImpl(const char* minidump_path,
1829                        int minidump_fd,
1830                        off_t minidump_size_limit,
1831                        pid_t crashing_process,
1832                        const void* blob, size_t blob_size,
1833                        const MappingList& mappings,
1834                        const AppMemoryList& appmem) {
1835   LinuxPtraceDumper dumper(crashing_process);
1836   const ExceptionHandler::CrashContext* context = NULL;
1837   if (blob) {
1838     if (blob_size != sizeof(ExceptionHandler::CrashContext))
1839       return false;
1840     context = reinterpret_cast<const ExceptionHandler::CrashContext*>(blob);
1841     dumper.set_crash_address(
1842         reinterpret_cast<uintptr_t>(context->siginfo.si_addr));
1843     dumper.set_crash_signal(context->siginfo.si_signo);
1844     dumper.set_crash_thread(context->tid);
1845   }
1846   MinidumpWriter writer(minidump_path, minidump_fd, context, mappings,
1847                         appmem, &dumper);
1848   // Set desired limit for file size of minidump (-1 means no limit).
1849   writer.set_minidump_size_limit(minidump_size_limit);
1850   if (!writer.Init())
1851     return false;
1852   return writer.Dump();
1853 }
1854
1855 }  // namespace
1856
1857 namespace google_breakpad {
1858
1859 bool WriteMinidump(const char* minidump_path, pid_t crashing_process,
1860                    const void* blob, size_t blob_size) {
1861   return WriteMinidumpImpl(minidump_path, -1, -1,
1862                            crashing_process, blob, blob_size,
1863                            MappingList(), AppMemoryList());
1864 }
1865
1866 bool WriteMinidump(int minidump_fd, pid_t crashing_process,
1867                    const void* blob, size_t blob_size) {
1868   return WriteMinidumpImpl(NULL, minidump_fd, -1,
1869                            crashing_process, blob, blob_size,
1870                            MappingList(), AppMemoryList());
1871 }
1872
1873 bool WriteMinidump(const char* minidump_path, pid_t process,
1874                    pid_t process_blamed_thread) {
1875   LinuxPtraceDumper dumper(process);
1876   // MinidumpWriter will set crash address
1877   dumper.set_crash_signal(MD_EXCEPTION_CODE_LIN_DUMP_REQUESTED);
1878   dumper.set_crash_thread(process_blamed_thread);
1879   MinidumpWriter writer(minidump_path, -1, NULL, MappingList(),
1880                         AppMemoryList(), &dumper);
1881   if (!writer.Init())
1882     return false;
1883   return writer.Dump();
1884 }
1885
1886 bool WriteMinidump(const char* minidump_path, pid_t crashing_process,
1887                    const void* blob, size_t blob_size,
1888                    const MappingList& mappings,
1889                    const AppMemoryList& appmem) {
1890   return WriteMinidumpImpl(minidump_path, -1, -1, crashing_process,
1891                            blob, blob_size,
1892                            mappings, appmem);
1893 }
1894
1895 bool WriteMinidump(int minidump_fd, pid_t crashing_process,
1896                    const void* blob, size_t blob_size,
1897                    const MappingList& mappings,
1898                    const AppMemoryList& appmem) {
1899   return WriteMinidumpImpl(NULL, minidump_fd, -1, crashing_process,
1900                            blob, blob_size,
1901                            mappings, appmem);
1902 }
1903
1904 bool WriteMinidump(const char* minidump_path, off_t minidump_size_limit,
1905                    pid_t crashing_process,
1906                    const void* blob, size_t blob_size,
1907                    const MappingList& mappings,
1908                    const AppMemoryList& appmem) {
1909   return WriteMinidumpImpl(minidump_path, -1, minidump_size_limit,
1910                            crashing_process, blob, blob_size,
1911                            mappings, appmem);
1912 }
1913
1914 bool WriteMinidump(int minidump_fd, off_t minidump_size_limit,
1915                    pid_t crashing_process,
1916                    const void* blob, size_t blob_size,
1917                    const MappingList& mappings,
1918                    const AppMemoryList& appmem) {
1919   return WriteMinidumpImpl(NULL, minidump_fd, minidump_size_limit,
1920                            crashing_process, blob, blob_size,
1921                            mappings, appmem);
1922 }
1923
1924 bool WriteMinidump(const char* filename,
1925                    const MappingList& mappings,
1926                    const AppMemoryList& appmem,
1927                    LinuxDumper* dumper) {
1928   MinidumpWriter writer(filename, -1, NULL, mappings, appmem, dumper);
1929   if (!writer.Init())
1930     return false;
1931   return writer.Dump();
1932 }
1933
1934 }  // namespace google_breakpad