1 // Copyright (c) 2010, Google Inc.
2 // All rights reserved.
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
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
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.
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.
30 // This code writes out minidump files:
31 // http://msdn.microsoft.com/en-us/library/ms680378(VS.85,loband).aspx
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.
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"
55 #if defined(__ANDROID__)
56 #include <sys/system_properties.h>
58 #include <sys/types.h>
59 #include <sys/ucontext.h>
61 #include <sys/utsname.h>
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"
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;
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.
100 typedef MDRawContextX86 RawContextCPU;
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));
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));
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;
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
129 out->dr6 = info.dregs[6];
130 out->dr7 = info.dregs[7];
132 out->gs = info.regs.xgs;
133 out->fs = info.regs.xfs;
134 out->es = info.regs.xes;
135 out->ds = info.regs.xds;
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;
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;
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;
159 // 8 registers * 10 bytes per register.
160 my_memcpy(out->float_save.register_area, info.fpregs.st_space, 10 * 8);
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);
173 my_memcpy(out->extended_registers + 32, &info.fpxregs.st_space, 128);
174 my_memcpy(out->extended_registers + 160, &info.fpxregs.xmm_space, 128);
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;
184 out->context_flags = MD_CONTEXT_X86_FULL |
185 MD_CONTEXT_X86_FLOATING_POINT;
187 out->gs = regs[REG_GS];
188 out->fs = regs[REG_FS];
189 out->es = regs[REG_ES];
190 out->ds = regs[REG_DS];
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];
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];
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;
214 // 8 registers * 10 bytes per register.
215 my_memcpy(out->float_save.register_area, fp->_st, 10 * 8);
218 #elif defined(__x86_64)
219 typedef MDRawContextAMD64 RawContextCPU;
221 void CPUFillFromThreadInfo(MDRawContextAMD64 *out,
222 const google_breakpad::ThreadInfo &info) {
223 out->context_flags = MD_CONTEXT_AMD64_FULL |
224 MD_CONTEXT_AMD64_SEGMENTS;
226 out->cs = info.regs.cs;
228 out->ds = info.regs.ds;
229 out->es = info.regs.es;
230 out->fs = info.regs.fs;
231 out->gs = info.regs.gs;
233 out->ss = info.regs.ss;
234 out->eflags = info.regs.eflags;
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
242 out->dr6 = info.dregs[6];
243 out->dr7 = info.dregs[7];
245 out->rax = info.regs.rax;
246 out->rcx = info.regs.rcx;
247 out->rdx = info.regs.rdx;
248 out->rbx = info.regs.rbx;
250 out->rsp = info.regs.rsp;
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;
264 out->rip = info.regs.rip;
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);
280 void CPUFillFromUContext(MDRawContextAMD64 *out, const ucontext *uc,
281 const struct _libc_fpstate* fpregs) {
282 const greg_t* regs = uc->uc_mcontext.gregs;
284 out->context_flags = MD_CONTEXT_AMD64_FULL;
286 out->cs = regs[REG_CSGSFS] & 0xffff;
288 out->fs = (regs[REG_CSGSFS] >> 32) & 0xffff;
289 out->gs = (regs[REG_CSGSFS] >> 16) & 0xffff;
291 out->eflags = regs[REG_EFL];
293 out->rax = regs[REG_RAX];
294 out->rcx = regs[REG_RCX];
295 out->rdx = regs[REG_RDX];
296 out->rbx = regs[REG_RBX];
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];
311 out->rip = regs[REG_RIP];
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);
327 #elif defined(__ARMEL__)
328 typedef MDRawContextARM RawContextCPU;
330 void CPUFillFromThreadInfo(MDRawContextARM* out,
331 const google_breakpad::ThreadInfo& info) {
332 out->context_flags = MD_CONTEXT_ARM_FULL;
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)
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));
347 void CPUFillFromUContext(MDRawContextARM* out, const ucontext* uc) {
348 out->context_flags = MD_CONTEXT_ARM_FULL;
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;
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;
368 out->cpsr = uc->uc_mcontext.arm_cpsr;
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));
376 #elif defined(__aarch64__)
377 typedef MDRawContextARM64 RawContextCPU;
379 void CPUFillFromThreadInfo(MDRawContextARM64* out,
380 const google_breakpad::ThreadInfo& info) {
381 out->context_flags = MD_CONTEXT_ARM64_FULL;
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;
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);
395 void CPUFillFromUContext(MDRawContextARM64* out, const ucontext* uc,
396 const struct fpsimd_context* fpregs) {
397 out->context_flags = MD_CONTEXT_ARM64_FULL;
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;
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);
411 #elif defined(__mips__)
412 typedef MDRawContextMIPS RawContextCPU;
414 static void CPUFillFromThreadInfo(MDRawContextMIPS* out,
415 const google_breakpad::ThreadInfo& info) {
416 out->context_flags = MD_CONTEXT_MIPS_FULL;
418 for (int i = 0; i < MD_CONTEXT_MIPS_GPR_COUNT; ++i)
419 out->iregs[i] = info.regs.regs[i];
421 out->mdhi = info.regs.hi;
422 out->mdlo = info.regs.lo;
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];
428 out->dsp_control = info.dsp_control;
430 out->epc = info.regs.epc;
431 out->badvaddr = info.regs.badvaddr;
432 out->status = info.regs.status;
433 out->cause = info.regs.cause;
435 for (int i = 0; i < MD_FLOATINGSAVEAREA_MIPS_FPR_COUNT; ++i)
436 out->float_save.regs[i] = info.fpregs.regs[i];
438 out->float_save.fpcsr = info.fpregs.fpcsr;
439 out->float_save.fir = info.fpregs.fir;
442 static void CPUFillFromUContext(MDRawContextMIPS* out, const ucontext* uc) {
443 out->context_flags = MD_CONTEXT_MIPS_FULL;
445 for (int i = 0; i < MD_CONTEXT_MIPS_GPR_COUNT; ++i)
446 out->iregs[i] = uc->uc_mcontext.gregs[i];
448 out->mdhi = uc->uc_mcontext.mdhi;
449 out->mdlo = uc->uc_mcontext.mdlo;
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;
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.
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];
468 out->float_save.regs[i] = uc->uc_mcontext.fpregs.fp_r.fp_dregs[i];
471 out->float_save.fpcsr = uc->uc_mcontext.fpc_csr;
472 out->float_save.fir = uc->uc_mcontext.fpc_eir; // Unused.
476 #error "This code has not been ported to your platform yet."
479 class MinidumpWriter {
481 // The following kLimit* constants are for when minidump_size_limit_ is set
482 // and the minidump size might exceed it.
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;
497 MinidumpWriter(const char* minidump_path,
499 const ExceptionHandler::CrashContext* context,
500 const MappingList& mappings,
501 const AppMemoryList& appmem,
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),
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);
520 if (!dumper_->Init())
524 minidump_writer_.SetFile(fd_);
525 else if (!minidump_writer_.Open(path_))
528 return dumper_->ThreadsSuspend();
532 // Don't close the file descriptor when it's been provided explicitly.
533 // Callers might still need to use it.
535 minidump_writer_.Close();
536 dumper_->ThreadsResume();
540 // A minidump file contains a number of tagged streams. This is the number
541 // of stream which we write.
542 unsigned kNumWriters = 13;
544 TypedMDRVA<MDRawHeader> header(&minidump_writer_);
545 TypedMDRVA<MDRawDirectory> dir(&minidump_writer_);
546 if (!header.Allocate())
548 if (!dir.AllocateArray(kNumWriters))
550 my_memset(header.get(), 0, sizeof(MDRawHeader));
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();
558 unsigned dir_index = 0;
559 MDRawDirectory dirent;
561 if (!WriteThreadListStream(&dirent))
563 dir.CopyIndex(dir_index++, &dirent);
565 if (!WriteMappings(&dirent))
567 dir.CopyIndex(dir_index++, &dirent);
569 if (!WriteAppMemory())
572 if (!WriteMemoryListStream(&dirent))
574 dir.CopyIndex(dir_index++, &dirent);
576 if (!WriteExceptionStream(&dirent))
578 dir.CopyIndex(dir_index++, &dirent);
580 if (!WriteSystemInfoStream(&dirent))
582 dir.CopyIndex(dir_index++, &dirent);
584 dirent.stream_type = MD_LINUX_CPU_INFO;
585 if (!WriteFile(&dirent.location, "/proc/cpuinfo"))
586 NullifyDirectoryEntry(&dirent);
587 dir.CopyIndex(dir_index++, &dirent);
589 dirent.stream_type = MD_LINUX_PROC_STATUS;
590 if (!WriteProcFile(&dirent.location, GetCrashThread(), "status"))
591 NullifyDirectoryEntry(&dirent);
592 dir.CopyIndex(dir_index++, &dirent);
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);
599 dirent.stream_type = MD_LINUX_CMD_LINE;
600 if (!WriteProcFile(&dirent.location, GetCrashThread(), "cmdline"))
601 NullifyDirectoryEntry(&dirent);
602 dir.CopyIndex(dir_index++, &dirent);
604 dirent.stream_type = MD_LINUX_ENVIRON;
605 if (!WriteProcFile(&dirent.location, GetCrashThread(), "environ"))
606 NullifyDirectoryEntry(&dirent);
607 dir.CopyIndex(dir_index++, &dirent);
609 dirent.stream_type = MD_LINUX_AUXV;
610 if (!WriteProcFile(&dirent.location, GetCrashThread(), "auxv"))
611 NullifyDirectoryEntry(&dirent);
612 dir.CopyIndex(dir_index++, &dirent);
614 dirent.stream_type = MD_LINUX_MAPS;
615 if (!WriteProcFile(&dirent.location, GetCrashThread(), "maps"))
616 NullifyDirectoryEntry(&dirent);
617 dir.CopyIndex(dir_index++, &dirent);
619 dirent.stream_type = MD_LINUX_DSO_DEBUG;
620 if (!WriteDSODebugStream(&dirent))
621 NullifyDirectoryEntry(&dirent);
622 dir.CopyIndex(dir_index++, &dirent);
624 // If you add more directory entries, don't forget to update kNumWriters,
627 dumper_->ThreadsResume();
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--; ) {
641 bp + sizeof(bp) > thread.stack.start_of_memory_range +
642 thread.stack.memory.data_size ||
646 uint64_t old_top = top;
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) {
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) {
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;
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--; ) {
704 bp + sizeof(bp) > thread.stack.start_of_memory_range +
705 thread.stack.memory.data_size ||
709 uint32_t old_top = top;
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) {
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) {
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;
748 bool FillThreadStack(MDRawThread* thread, uintptr_t stack_pointer,
749 int max_stack_len, uint8_t** stack_copy) {
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;
759 if (!memory.Allocate(stack_len))
761 *stack_copy = reinterpret_cast<uint8_t*>(Alloc(stack_len));
762 dumper_->CopyFromProcess(*stack_copy, thread->thread_id, stack,
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);
770 thread->stack.start_of_memory_range = stack_pointer;
771 thread->stack.memory.data_size = 0;
772 thread->stack.memory.rva = minidump_writer_.position();
777 // Write information about the threads.
778 bool WriteThreadListStream(MDRawDirectory* dirent) {
779 const unsigned num_threads = dumper_->threads().size();
781 TypedMDRVA<uint32_t> list(&minidump_writer_);
782 if (!list.AllocateObjectAndArray(num_threads, sizeof(MDRawThread)))
785 dirent->stream_type = MD_THREAD_LIST_STREAM;
786 dirent->location = list.location();
788 *list.get() = num_threads;
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;
805 for (unsigned i = 0; i < num_threads; ++i) {
807 my_memset(&thread, 0, sizeof(thread));
808 thread.thread_id = dumper_->threads()[i];
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
814 if (static_cast<pid_t>(thread.thread_id) == GetCrashThread() &&
816 !dumper_->IsPostMortem()) {
818 if (!FillThreadStack(&thread, GetStackPointer(), -1, &stack_copy))
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) {
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;
849 UntypedMDRVA ip_memory(&minidump_writer_);
850 if (!ip_memory.Allocate(ip_memory_d.memory.data_size))
852 uint8_t* memory_copy =
853 reinterpret_cast<uint8_t*>(Alloc(ip_memory_d.memory.data_size));
854 dumper_->CopyFromProcess(
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);
864 TypedMDRVA<RawContextCPU> cpu(&minidump_writer_);
867 my_memset(cpu.get(), 0, sizeof(RawContextCPU));
868 #if !defined(__ARM_EABI__) && !defined(__mips__)
869 CPUFillFromUContext(cpu.get(), ucontext_, float_state_);
871 CPUFillFromUContext(cpu.get(), ucontext_);
874 PopSeccompStackFrame(cpu.get(), thread, stack_copy);
875 thread.thread_context = cpu.location();
876 crashing_thread_context_ = cpu.location();
879 if (!dumper_->GetThreadInfoByIndex(i, &info))
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,
890 TypedMDRVA<RawContextCPU> cpu(&minidump_writer_);
893 my_memset(cpu.get(), 0, sizeof(RawContextCPU));
894 CPUFillFromThreadInfo(cpu.get(), info);
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));
909 list.CopyIndexAfterObject(i, &thread, sizeof(thread));
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();
921 reinterpret_cast<uint8_t*>(dumper_->allocator()->Alloc(iter->length));
922 dumper_->CopyFromProcess(data_copy, GetCrashThread(), iter->ptr,
925 UntypedMDRVA memory(&minidump_writer_);
926 if (!memory.Allocate(iter->length)) {
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);
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.
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();
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)) {
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();
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++;
982 TypedMDRVA<uint32_t> list(&minidump_writer_);
983 if (num_output_mappings) {
984 if (!list.AllocateObjectAndArray(num_output_mappings, MD_MODULE_SIZE))
987 // Still create the module list stream, although it will have zero
989 if (!list.Allocate())
993 dirent->stream_type = MD_MODULE_LIST_STREAM;
994 dirent->location = list.location();
995 *list.get() = num_output_mappings;
997 // First write all the mappings from the dumper
999 for (unsigned i = 0; i < num_mappings; ++i) {
1000 const MappingInfo& mapping = *dumper_->mappings()[i];
1001 if (!ShouldIncludeMapping(mapping) || HaveMappingInfo(mapping))
1005 if (!FillRawModule(mapping, true, i, mod, NULL))
1007 list.CopyIndexAfterObject(j++, &mod, MD_MODULE_SIZE);
1009 // Next write all the mappings provided by the caller
1010 for (MappingList::const_iterator iter = mapping_list_.begin();
1011 iter != mapping_list_.end();
1014 if (!FillRawModule(iter->first, false, 0, mod, iter->second))
1016 list.CopyIndexAfterObject(j++, &mod, MD_MODULE_SIZE);
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,
1027 unsigned int mapping_id,
1029 const uint8_t* identifier) {
1030 my_memset(&mod, 0, MD_MODULE_SIZE);
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);
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 == '/')
1046 size_t filename_len = mapping.name + filepath_len - filename_ptr;
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.
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);
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;
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))
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);
1084 // GUID was provided by caller.
1085 my_memcpy(signature, identifier, sizeof(MDGUID));
1087 dumper_->ElfFileIdentifierForMapping(mapping, member,
1088 mapping_id, signature);
1090 my_memset(cv_ptr, 0, sizeof(uint32_t)); // Set age to 0 on Linux.
1091 cv_ptr += sizeof(uint32_t);
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);
1097 mod.cv_record = cv.location();
1099 MDLocationDescriptor ld;
1100 if (!minidump_writer_.WriteString(filepath_ptr, filepath_len, &ld))
1102 mod.module_name_rva = ld.rva;
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)))
1113 // Still create the memory list stream, although it will have zero
1115 if (!list.Allocate())
1119 dirent->stream_type = MD_MEMORY_LIST_STREAM;
1120 dirent->location = list.location();
1122 *list.get() = memory_blocks_.size();
1124 for (size_t i = 0; i < memory_blocks_.size(); ++i) {
1125 list.CopyIndexAfterObject(i, &memory_blocks_[i],
1126 sizeof(MDMemoryDescriptor));
1131 bool WriteExceptionStream(MDRawDirectory* dirent) {
1132 TypedMDRVA<MDRawExceptionStream> exc(&minidump_writer_);
1133 if (!exc.Allocate())
1135 my_memset(exc.get(), 0, sizeof(MDRawExceptionStream));
1137 dirent->stream_type = MD_EXCEPTION_STREAM;
1138 dirent->location = exc.location();
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_;
1148 bool WriteSystemInfoStream(MDRawDirectory* dirent) {
1149 TypedMDRVA<MDRawSystemInfo> si(&minidump_writer_);
1152 my_memset(si.get(), 0, sizeof(MDRawSystemInfo));
1154 dirent->stream_type = MD_SYSTEM_INFO_STREAM;
1155 dirent->location = si.location();
1157 WriteCPUInformation(si.get());
1158 WriteOSInformation(si.get());
1163 bool WriteDSODebugStream(MDRawDirectory* dirent) {
1164 ElfW(Phdr)* phdr = reinterpret_cast<ElfW(Phdr) *>(dumper_->auxv()[AT_PHDR]);
1166 int phnum = dumper_->auxv()[AT_PHNUM];
1167 if (!phnum || !phdr)
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);
1173 // Search for the program PT_DYNAMIC segment
1174 ElfW(Addr) dyn_addr = 0;
1175 for (; phnum >= 0; phnum--, phdr++) {
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) {
1183 if (ph.p_type == PT_DYNAMIC) {
1184 dyn_addr = ph.p_vaddr;
1190 ElfW(Dyn) *dynamic = reinterpret_cast<ElfW(Dyn) *>(dyn_addr + base);
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;
1200 dynamic_length += sizeof(dyn);
1201 dumper_->CopyFromProcess(&dyn, GetCrashThread(), dynamic+i++,
1203 if (dyn.d_tag == DT_DEBUG) {
1204 r_debug = reinterpret_cast<struct r_debug*>(dyn.d_un.d_ptr);
1206 } else if (dyn.d_tag == DT_NULL) {
1211 // The "r_map" field of that r_debug struct contains a linked list of all
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.
1219 // Count the number of loaded DSOs
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));
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))
1238 linkmap_rva = linkmap.location().rva;
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));
1246 char filename[257] = { 0 };
1248 dumper_->CopyFromProcess(filename, GetCrashThread(), map.l_name,
1249 sizeof(filename) - 1);
1251 MDLocationDescriptor location;
1252 if (!minidump_writer_.WriteString(filename, 0, &location))
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);
1262 // Write MD_LINUX_DSO_DEBUG record
1263 TypedMDRVA<MDRawDebug> debug(&minidump_writer_);
1264 if (!debug.AllocateObjectAndArray(1, dynamic_length))
1266 my_memset(debug.get(), 0, sizeof(MDRawDebug));
1267 dirent->stream_type = MD_LINUX_DSO_DEBUG;
1268 dirent->location = debug.location();
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;
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,
1283 debug.CopyIndexAfterObject(0, &dso_debug_data[0], dynamic_length);
1288 void set_minidump_size_limit(off_t limit) { minidump_size_limit_ = limit; }
1291 void* Alloc(unsigned bytes) {
1292 return dumper_->allocator()->Alloc(bytes);
1295 pid_t GetCrashThread() const {
1296 return dumper_->crash_thread();
1299 #if defined(__i386__)
1300 uintptr_t GetStackPointer() {
1301 return ucontext_->uc_mcontext.gregs[REG_ESP];
1304 uintptr_t GetInstructionPointer() {
1305 return ucontext_->uc_mcontext.gregs[REG_EIP];
1308 uintptr_t GetInstructionPointer(const ThreadInfo& info) {
1309 return info.regs.eip;
1311 #elif defined(__x86_64)
1312 uintptr_t GetStackPointer() {
1313 return ucontext_->uc_mcontext.gregs[REG_RSP];
1316 uintptr_t GetInstructionPointer() {
1317 return ucontext_->uc_mcontext.gregs[REG_RIP];
1320 uintptr_t GetInstructionPointer(const ThreadInfo& info) {
1321 return info.regs.rip;
1323 #elif defined(__ARM_EABI__)
1324 uintptr_t GetStackPointer() {
1325 return ucontext_->uc_mcontext.arm_sp;
1328 uintptr_t GetInstructionPointer() {
1329 return ucontext_->uc_mcontext.arm_pc;
1332 uintptr_t GetInstructionPointer(const ThreadInfo& info) {
1333 return info.regs.uregs[15];
1335 #elif defined(__aarch64__)
1336 uintptr_t GetStackPointer() {
1337 return ucontext_->uc_mcontext.sp;
1340 uintptr_t GetInstructionPointer() {
1341 return ucontext_->uc_mcontext.pc;
1344 uintptr_t GetInstructionPointer(const ThreadInfo& info) {
1345 return info.regs.pc;
1347 #elif defined(__mips__)
1348 uintptr_t GetStackPointer() {
1349 return ucontext_->uc_mcontext.gregs[MD_CONTEXT_MIPS_REG_SP];
1352 uintptr_t GetInstructionPointer() {
1353 return ucontext_->uc_mcontext.pc;
1356 uintptr_t GetInstructionPointer(const ThreadInfo& info) {
1357 return info.regs.epc;
1360 #error "This code has not been ported to your platform yet."
1363 void NullifyDirectoryEntry(MDRawDirectory* dirent) {
1364 dirent->stream_type = 0;
1365 dirent->location.data_size = 0;
1366 dirent->location.rva = 0;
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";
1374 struct CpuInfoEntry {
1375 const char* info_name;
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 },
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;
1394 MD_CPU_ARCHITECTURE_AMD64;
1397 const int fd = sys_open("/proc/cpuinfo", O_RDONLY, 0);
1402 PageAllocator allocator;
1403 ProcCpuInfoReader* const reader = new(allocator) ProcCpuInfoReader(fd);
1405 while (reader->GetNextField(&field)) {
1407 i < sizeof(cpu_info_table) / sizeof(cpu_info_table[0]);
1409 CpuInfoEntry* entry = &cpu_info_table[i];
1410 if (i > 0 && entry->found) {
1411 // except for the 'processor' field, ignore repeated values.
1414 if (!my_strcmp(field, entry->info_name)) {
1416 const char* value = reader->GetValueAndLen(&value_len);
1421 if (my_read_decimal_ptr(&val, value) == value)
1424 entry->value = static_cast<int>(val);
1425 entry->found = true;
1429 // special case for vendor_id
1430 if (!my_strcmp(field, vendor_id_name)) {
1432 const char* value = reader->GetValueAndLen(&value_len);
1434 my_strlcpy(vendor_id, value, sizeof(vendor_id));
1440 // make sure we got everything we wanted
1442 i < sizeof(cpu_info_table) / sizeof(cpu_info_table[0]);
1444 if (!cpu_info_table[i].found) {
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
1451 cpu_info_table[0].value++;
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;
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));
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 {
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 },
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 {
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.
1514 // processor_architecture should always be set, do this first
1515 sys_info->processor_architecture =
1516 #if defined(__aarch64__)
1517 MD_CPU_ARCHITECTURE_ARM64;
1519 MD_CPU_ARCHITECTURE_ARM;
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.
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;
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
1540 CpuSet cpus_present;
1541 CpuSet cpus_possible;
1543 int fd = sys_open("/sys/devices/system/cpu/present", O_RDONLY, 0);
1545 cpus_present.ParseSysFile(fd);
1548 fd = sys_open("/sys/devices/system/cpu/possible", O_RDONLY, 0);
1550 cpus_possible.ParseSysFile(fd);
1553 cpus_present.IntersectWith(cpus_possible);
1554 int cpu_count = cpus_present.GetCount();
1555 if (cpu_count > 255)
1557 sys_info->number_of_processors = static_cast<uint8_t>(cpu_count);
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);
1569 // Do not return false here to allow the minidump generation
1570 // to happen properly.
1575 PageAllocator allocator;
1576 ProcCpuInfoReader* const reader =
1577 new(allocator) ProcCpuInfoReader(fd);
1579 while (reader->GetNextField(&field)) {
1581 i < sizeof(cpu_id_entries)/sizeof(cpu_id_entries[0]);
1583 const CpuIdEntry* entry = &cpu_id_entries[i];
1584 if (my_strcmp(entry->field, field) != 0)
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);
1594 p = my_read_decimal_ptr(&result, value);
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);
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")) {
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]))
1621 size_t nn = value_len;
1622 while (nn > 0 && value[nn-1] != '(')
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);
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"
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);
1641 sys_info->processor_level = static_cast<uint16_t>(arch_level);
1644 // Rebuild the ELF hwcaps from the 'Features' field.
1645 if (!my_strcmp(field, "Features")) {
1647 const char* value = reader->GetValueAndLen(&value_len);
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, ' ');
1655 tag_len = static_cast<size_t>(p - tag);
1656 value += tag_len + 1;
1657 value_len -= tag_len + 1;
1659 tag_len = strlen(tag);
1663 i < sizeof(cpu_features_entries)/
1664 sizeof(cpu_features_entries[0]);
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;
1682 # error "Unsupported CPU"
1685 bool WriteFile(MDLocationDescriptor* result, const char* filename) {
1686 const int fd = sys_open(filename, O_RDONLY, 0);
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*);
1697 uint8_t data[kBufSize];
1698 } *buffers = reinterpret_cast<Buffers*>(Alloc(sizeof(Buffers)));
1699 buffers->next = NULL;
1703 for (Buffers* bufptr = buffers;;) {
1706 r = sys_read(fd, &bufptr->data[bufptr->len], kBufSize - bufptr->len);
1707 } while (r == -1 && errno == EINTR);
1714 if (bufptr->len == kBufSize) {
1715 bufptr->next = reinterpret_cast<Buffers*>(Alloc(sizeof(Buffers)));
1716 bufptr = bufptr->next;
1717 bufptr->next = NULL;
1726 UntypedMDRVA memory(&minidump_writer_);
1727 if (!memory.Allocate(total))
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);
1739 memory.Copy(pos, &buffers->data, buffers->len);
1740 pos += buffers->len;
1742 *result = memory.location();
1746 bool WriteOSInformation(MDRawSystemInfo* sys_info) {
1747 #if defined(__ANDROID__)
1748 sys_info->platform_id = MD_OS_ANDROID;
1750 sys_info->platform_id = MD_OS_LINUX;
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[] = {
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);
1775 if (space_left < info_len + (first_item ? 0 : separator_len))
1779 my_strlcat(buf, separator, sizeof(buf));
1780 space_left -= separator_len;
1784 my_strlcat(buf, *cur_info, sizeof(buf));
1785 space_left -= info_len;
1788 MDLocationDescriptor location;
1789 if (!minidump_writer_.WriteString(buf, 0, &location))
1791 sys_info->csd_version_rva = location.rva;
1796 bool WriteProcFile(MDLocationDescriptor* result, pid_t pid,
1797 const char* filename) {
1799 if (!dumper_->BuildProcPath(buf, pid, filename))
1801 return WriteFile(result, buf);
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.
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
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_;
1828 bool WriteMinidumpImpl(const char* minidump_path,
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;
1838 if (blob_size != sizeof(ExceptionHandler::CrashContext))
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);
1846 MinidumpWriter writer(minidump_path, minidump_fd, context, mappings,
1848 // Set desired limit for file size of minidump (-1 means no limit).
1849 writer.set_minidump_size_limit(minidump_size_limit);
1852 return writer.Dump();
1857 namespace google_breakpad {
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());
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());
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);
1883 return writer.Dump();
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,
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,
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,
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,
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);
1931 return writer.Dump();
1934 } // namespace google_breakpad