| OLD | NEW |
| 1 // Copyright (c) 2009, Google Inc. | 1 // Copyright (c) 2009, Google Inc. |
| 2 // All rights reserved. | 2 // All rights reserved. |
| 3 // | 3 // |
| 4 // Redistribution and use in source and binary forms, with or without | 4 // Redistribution and use in source and binary forms, with or without |
| 5 // modification, are permitted provided that the following conditions are | 5 // modification, are permitted provided that the following conditions are |
| 6 // met: | 6 // met: |
| 7 // | 7 // |
| 8 // * Redistributions of source code must retain the above copyright | 8 // * Redistributions of source code must retain the above copyright |
| 9 // notice, this list of conditions and the following disclaimer. | 9 // notice, this list of conditions and the following disclaimer. |
| 10 // * Redistributions in binary form must reproduce the above | 10 // * Redistributions in binary form must reproduce the above |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 140 U16(out->extended_registers + 20, info.fpregs.fos); | 140 U16(out->extended_registers + 20, info.fpregs.fos); |
| 141 U32(out->extended_registers + 24, info.fpxregs.mxcsr); | 141 U32(out->extended_registers + 24, info.fpxregs.mxcsr); |
| 142 | 142 |
| 143 memcpy(out->extended_registers + 32, &info.fpxregs.st_space, 128); | 143 memcpy(out->extended_registers + 32, &info.fpxregs.st_space, 128); |
| 144 memcpy(out->extended_registers + 160, &info.fpxregs.xmm_space, 128); | 144 memcpy(out->extended_registers + 160, &info.fpxregs.xmm_space, 128); |
| 145 } | 145 } |
| 146 | 146 |
| 147 // Juggle an x86 ucontext into minidump format | 147 // Juggle an x86 ucontext into minidump format |
| 148 // out: the minidump structure | 148 // out: the minidump structure |
| 149 // info: the collection of register structures. | 149 // info: the collection of register structures. |
| 150 static void CPUFillFromUContext(MDRawContextX86 *out, const ucontext *uc) { | 150 static void CPUFillFromUContext(MDRawContextX86 *out, const ucontext *uc, |
| 151 const struct _libc_fpstate* fp) { |
| 151 const greg_t* regs = uc->uc_mcontext.gregs; | 152 const greg_t* regs = uc->uc_mcontext.gregs; |
| 152 const fpregset_t fp = uc->uc_mcontext.fpregs; | |
| 153 | 153 |
| 154 out->context_flags = MD_CONTEXT_X86_FULL | | 154 out->context_flags = MD_CONTEXT_X86_FULL | |
| 155 MD_CONTEXT_X86_FLOATING_POINT; | 155 MD_CONTEXT_X86_FLOATING_POINT; |
| 156 | 156 |
| 157 out->gs = regs[REG_GS]; | 157 out->gs = regs[REG_GS]; |
| 158 out->fs = regs[REG_FS]; | 158 out->fs = regs[REG_FS]; |
| 159 out->es = regs[REG_ES]; | 159 out->es = regs[REG_ES]; |
| 160 out->ds = regs[REG_DS]; | 160 out->ds = regs[REG_DS]; |
| 161 | 161 |
| 162 out->edi = regs[REG_EDI]; | 162 out->edi = regs[REG_EDI]; |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 240 out->flt_save.error_offset = info.fpregs.rip; | 240 out->flt_save.error_offset = info.fpregs.rip; |
| 241 out->flt_save.error_selector = 0; // We don't have this. | 241 out->flt_save.error_selector = 0; // We don't have this. |
| 242 out->flt_save.data_offset = info.fpregs.rdp; | 242 out->flt_save.data_offset = info.fpregs.rdp; |
| 243 out->flt_save.data_selector = 0; // We don't have this. | 243 out->flt_save.data_selector = 0; // We don't have this. |
| 244 out->flt_save.mx_csr = info.fpregs.mxcsr; | 244 out->flt_save.mx_csr = info.fpregs.mxcsr; |
| 245 out->flt_save.mx_csr_mask = info.fpregs.mxcsr_mask; | 245 out->flt_save.mx_csr_mask = info.fpregs.mxcsr_mask; |
| 246 memcpy(&out->flt_save.float_registers, &info.fpregs.st_space, 8 * 16); | 246 memcpy(&out->flt_save.float_registers, &info.fpregs.st_space, 8 * 16); |
| 247 memcpy(&out->flt_save.xmm_registers, &info.fpregs.xmm_space, 16 * 16); | 247 memcpy(&out->flt_save.xmm_registers, &info.fpregs.xmm_space, 16 * 16); |
| 248 } | 248 } |
| 249 | 249 |
| 250 static void CPUFillFromUContext(MDRawContextAMD64 *out, const ucontext *uc) { | 250 static void CPUFillFromUContext(MDRawContextAMD64 *out, const ucontext *uc, |
| 251 const struct _libc_fpstate* fpregs) { |
| 251 const greg_t* regs = uc->gregs; | 252 const greg_t* regs = uc->gregs; |
| 252 const fpregset_t fpregs = uc->fpregs; | |
| 253 | 253 |
| 254 out->context_flags = MD_CONTEXT_AMD64_FULL; | 254 out->context_flags = MD_CONTEXT_AMD64_FULL; |
| 255 | 255 |
| 256 out->cs = regs[REG_CSGSFS] & 0xffff; | 256 out->cs = regs[REG_CSGSFS] & 0xffff; |
| 257 | 257 |
| 258 out->fs = (regs[REG_CSGSFS] >> 32) & 0xffff; | 258 out->fs = (regs[REG_CSGSFS] >> 32) & 0xffff; |
| 259 out->gs = (regs[REG_CSGSFS] >> 16) & 0xffff; | 259 out->gs = (regs[REG_CSGSFS] >> 16) & 0xffff; |
| 260 | 260 |
| 261 out->eflags = regs[REG_EFL]; | 261 out->eflags = regs[REG_EFL]; |
| 262 | 262 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 301 namespace google_breakpad { | 301 namespace google_breakpad { |
| 302 | 302 |
| 303 class MinidumpWriter { | 303 class MinidumpWriter { |
| 304 public: | 304 public: |
| 305 MinidumpWriter(const char* filename, | 305 MinidumpWriter(const char* filename, |
| 306 pid_t crashing_pid, | 306 pid_t crashing_pid, |
| 307 const ExceptionHandler::CrashContext* context) | 307 const ExceptionHandler::CrashContext* context) |
| 308 : filename_(filename), | 308 : filename_(filename), |
| 309 siginfo_(&context->siginfo), | 309 siginfo_(&context->siginfo), |
| 310 ucontext_(&context->context), | 310 ucontext_(&context->context), |
| 311 float_state_(&context->float_state), |
| 311 crashing_tid_(context->tid), | 312 crashing_tid_(context->tid), |
| 312 dumper_(crashing_pid) { | 313 dumper_(crashing_pid) { |
| 313 } | 314 } |
| 314 | 315 |
| 315 bool Init() { | 316 bool Init() { |
| 316 return dumper_.Init() && minidump_writer_.Open(filename_) && | 317 return dumper_.Init() && minidump_writer_.Open(filename_) && |
| 317 dumper_.ThreadsSuspend(); | 318 dumper_.ThreadsSuspend(); |
| 318 } | 319 } |
| 319 | 320 |
| 320 ~MinidumpWriter() { | 321 ~MinidumpWriter() { |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 433 return false; | 434 return false; |
| 434 uint8_t* stack_copy = (uint8_t*) dumper_.allocator()->Alloc(stack_len); | 435 uint8_t* stack_copy = (uint8_t*) dumper_.allocator()->Alloc(stack_len); |
| 435 dumper_.CopyFromProcess(stack_copy, thread.thread_id, stack, stack_len); | 436 dumper_.CopyFromProcess(stack_copy, thread.thread_id, stack, stack_len); |
| 436 memory.Copy(stack_copy, stack_len); | 437 memory.Copy(stack_copy, stack_len); |
| 437 thread.stack.start_of_memory_range = (uintptr_t) (stack); | 438 thread.stack.start_of_memory_range = (uintptr_t) (stack); |
| 438 thread.stack.memory = memory.location(); | 439 thread.stack.memory = memory.location(); |
| 439 TypedMDRVA<RawContextCPU> cpu(&minidump_writer_); | 440 TypedMDRVA<RawContextCPU> cpu(&minidump_writer_); |
| 440 if (!cpu.Allocate()) | 441 if (!cpu.Allocate()) |
| 441 return false; | 442 return false; |
| 442 my_memset(cpu.get(), 0, sizeof(RawContextCPU)); | 443 my_memset(cpu.get(), 0, sizeof(RawContextCPU)); |
| 443 CPUFillFromUContext(cpu.get(), ucontext_); | 444 CPUFillFromUContext(cpu.get(), ucontext_, float_state_); |
| 444 thread.thread_context = cpu.location(); | 445 thread.thread_context = cpu.location(); |
| 445 crashing_thread_context_ = cpu.location(); | 446 crashing_thread_context_ = cpu.location(); |
| 446 } else { | 447 } else { |
| 447 ThreadInfo info; | 448 ThreadInfo info; |
| 448 if (!dumper_.ThreadInfoGet(dumper_.threads()[i], &info)) | 449 if (!dumper_.ThreadInfoGet(dumper_.threads()[i], &info)) |
| 449 return false; | 450 return false; |
| 450 UntypedMDRVA memory(&minidump_writer_); | 451 UntypedMDRVA memory(&minidump_writer_); |
| 451 if (!memory.Allocate(info.stack_len)) | 452 if (!memory.Allocate(info.stack_len)) |
| 452 return false; | 453 return false; |
| 453 uint8_t* stack_copy = | 454 uint8_t* stack_copy = |
| (...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 668 const unsigned pid_len = my_int_len(pid); | 669 const unsigned pid_len = my_int_len(pid); |
| 669 my_itos(buf + 6, pid, pid_len); | 670 my_itos(buf + 6, pid, pid_len); |
| 670 buf[6 + pid_len] = '/'; | 671 buf[6 + pid_len] = '/'; |
| 671 memcpy(buf + 6 + pid_len + 1, filename, my_strlen(filename) + 1); | 672 memcpy(buf + 6 + pid_len + 1, filename, my_strlen(filename) + 1); |
| 672 return WriteFile(result, buf); | 673 return WriteFile(result, buf); |
| 673 } | 674 } |
| 674 | 675 |
| 675 const char* const filename_; // output filename | 676 const char* const filename_; // output filename |
| 676 const siginfo_t* const siginfo_; // from the signal handler (see sigaction) | 677 const siginfo_t* const siginfo_; // from the signal handler (see sigaction) |
| 677 const struct ucontext* const ucontext_; // also from the signal handler | 678 const struct ucontext* const ucontext_; // also from the signal handler |
| 679 const struct _libc_fpstate* const float_state_; // ditto |
| 678 const pid_t crashing_tid_; // the process which actually crashed | 680 const pid_t crashing_tid_; // the process which actually crashed |
| 679 LinuxDumper dumper_; | 681 LinuxDumper dumper_; |
| 680 MinidumpFileWriter minidump_writer_; | 682 MinidumpFileWriter minidump_writer_; |
| 681 MDLocationDescriptor crashing_thread_context_; | 683 MDLocationDescriptor crashing_thread_context_; |
| 682 }; | 684 }; |
| 683 | 685 |
| 684 bool WriteMinidump(const char* filename, pid_t crashing_process, | 686 bool WriteMinidump(const char* filename, pid_t crashing_process, |
| 685 const void* blob, size_t blob_size) { | 687 const void* blob, size_t blob_size) { |
| 686 if (blob_size != sizeof(ExceptionHandler::CrashContext)) | 688 if (blob_size != sizeof(ExceptionHandler::CrashContext)) |
| 687 return false; | 689 return false; |
| 688 const ExceptionHandler::CrashContext* context = | 690 const ExceptionHandler::CrashContext* context = |
| 689 reinterpret_cast<const ExceptionHandler::CrashContext*>(blob); | 691 reinterpret_cast<const ExceptionHandler::CrashContext*>(blob); |
| 690 MinidumpWriter writer(filename, crashing_process, context); | 692 MinidumpWriter writer(filename, crashing_process, context); |
| 691 if (!writer.Init()) | 693 if (!writer.Init()) |
| 692 return false; | 694 return false; |
| 693 return writer.Dump(); | 695 return writer.Dump(); |
| 694 } | 696 } |
| 695 | 697 |
| 696 } // namespace google_breakpad | 698 } // namespace google_breakpad |
| OLD | NEW |