Left: | ||
Right: |
OLD | NEW |
---|---|
1 // Copyright (c) 2006, Google Inc. | 1 // Copyright (c) 2006, 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 13 matching lines...) Expand all Loading... | |
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 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. | 28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
29 | 29 |
30 #include <algorithm> | 30 #include <algorithm> |
31 #include <cstdio> | 31 #include <cstdio> |
32 | 32 |
33 #include <mach/host_info.h> | 33 #include <mach/host_info.h> |
34 #include <mach/i386/thread_status.h> | |
35 #include <mach/mach_vm.h> | 34 #include <mach/mach_vm.h> |
36 #include <mach/vm_statistics.h> | 35 #include <mach/vm_statistics.h> |
37 #include <mach-o/dyld.h> | 36 #include <mach-o/dyld.h> |
38 #include <mach-o/loader.h> | 37 #include <mach-o/loader.h> |
39 #include <sys/sysctl.h> | 38 #include <sys/sysctl.h> |
40 #include <sys/resource.h> | 39 #include <sys/resource.h> |
41 | 40 |
42 #include <CoreFoundation/CoreFoundation.h> | 41 #include <CoreFoundation/CoreFoundation.h> |
43 | 42 |
44 #include "client/mac/handler/minidump_generator.h" | 43 #include "client/mac/handler/minidump_generator.h" |
45 | 44 |
45 #ifdef HAS_ARM_SUPPORT | |
46 #include <mach/arm/thread_status.h> | |
47 #endif | |
46 #ifdef HAS_PPC_SUPPORT | 48 #ifdef HAS_PPC_SUPPORT |
47 #include <mach/ppc/thread_status.h> | 49 #include <mach/ppc/thread_status.h> |
48 #endif | 50 #endif |
51 #ifdef HAS_X86_SUPPORT | |
52 #include <mach/i386/thread_status.h> | |
53 #endif | |
49 | 54 |
50 #include "client/minidump_file_writer-inl.h" | 55 #include "client/minidump_file_writer-inl.h" |
51 #include "common/mac/file_id.h" | 56 #include "common/mac/file_id.h" |
52 #include "common/mac/string_utilities.h" | 57 #include "common/mac/string_utilities.h" |
53 | 58 |
54 using MacStringUtils::ConvertToString; | 59 using MacStringUtils::ConvertToString; |
55 using MacStringUtils::IntegerValueAtIndex; | 60 using MacStringUtils::IntegerValueAtIndex; |
56 | 61 |
57 namespace google_breakpad { | 62 namespace google_breakpad { |
58 | 63 |
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
341 | 346 |
342 stack_location->start_of_memory_range = start_addr; | 347 stack_location->start_of_memory_range = start_addr; |
343 stack_location->memory = memory.location(); | 348 stack_location->memory = memory.location(); |
344 | 349 |
345 return result; | 350 return result; |
346 } | 351 } |
347 | 352 |
348 bool MinidumpGenerator::WriteStack(breakpad_thread_state_data_t state, | 353 bool MinidumpGenerator::WriteStack(breakpad_thread_state_data_t state, |
349 MDMemoryDescriptor *stack_location) { | 354 MDMemoryDescriptor *stack_location) { |
350 switch (cpu_type_) { | 355 switch (cpu_type_) { |
356 #ifdef HAS_ARM_SUPPORT | |
357 case CPU_TYPE_ARM: | |
358 return WriteStackARM(state, stack_location); | |
359 #endif | |
351 #ifdef HAS_PPC_SUPPORT | 360 #ifdef HAS_PPC_SUPPORT |
352 case CPU_TYPE_POWERPC: | 361 case CPU_TYPE_POWERPC: |
353 return WriteStackPPC(state, stack_location); | 362 return WriteStackPPC(state, stack_location); |
354 case CPU_TYPE_POWERPC64: | 363 case CPU_TYPE_POWERPC64: |
355 return WriteStackPPC64(state, stack_location); | 364 return WriteStackPPC64(state, stack_location); |
356 #endif | 365 #endif |
366 #ifdef HAS_X86_SUPPORT | |
357 case CPU_TYPE_I386: | 367 case CPU_TYPE_I386: |
358 return WriteStackX86(state, stack_location); | 368 return WriteStackX86(state, stack_location); |
359 case CPU_TYPE_X86_64: | 369 case CPU_TYPE_X86_64: |
360 return WriteStackX86_64(state, stack_location); | 370 return WriteStackX86_64(state, stack_location); |
371 #endif | |
361 default: | 372 default: |
362 return false; | 373 return false; |
363 } | 374 } |
364 } | 375 } |
365 | 376 |
366 bool MinidumpGenerator::WriteContext(breakpad_thread_state_data_t state, | 377 bool MinidumpGenerator::WriteContext(breakpad_thread_state_data_t state, |
367 MDLocationDescriptor *register_location) { | 378 MDLocationDescriptor *register_location) { |
368 switch (cpu_type_) { | 379 switch (cpu_type_) { |
380 #ifdef HAS_ARM_SUPPORT | |
381 case CPU_TYPE_ARM: | |
382 return WriteContextARM(state, register_location); | |
383 #endif | |
369 #ifdef HAS_PPC_SUPPORT | 384 #ifdef HAS_PPC_SUPPORT |
370 case CPU_TYPE_POWERPC: | 385 case CPU_TYPE_POWERPC: |
371 return WriteContextPPC(state, register_location); | 386 return WriteContextPPC(state, register_location); |
372 case CPU_TYPE_POWERPC64: | 387 case CPU_TYPE_POWERPC64: |
373 return WriteContextPPC64(state, register_location); | 388 return WriteContextPPC64(state, register_location); |
374 #endif | 389 #endif |
390 #ifdef HAS_X86_SUPPORT | |
375 case CPU_TYPE_I386: | 391 case CPU_TYPE_I386: |
376 return WriteContextX86(state, register_location); | 392 return WriteContextX86(state, register_location); |
377 case CPU_TYPE_X86_64: | 393 case CPU_TYPE_X86_64: |
378 return WriteContextX86_64(state, register_location); | 394 return WriteContextX86_64(state, register_location); |
395 #endif | |
379 default: | 396 default: |
380 return false; | 397 return false; |
381 } | 398 } |
382 } | 399 } |
383 | 400 |
384 u_int64_t MinidumpGenerator::CurrentPCForStack( | 401 u_int64_t MinidumpGenerator::CurrentPCForStack( |
385 breakpad_thread_state_data_t state) { | 402 breakpad_thread_state_data_t state) { |
386 switch (cpu_type_) { | 403 switch (cpu_type_) { |
404 #ifdef HAS_ARM_SUPPORT | |
405 case CPU_TYPE_ARM: | |
406 return CurrentPCForStackARM(state); | |
407 #endif | |
387 #ifdef HAS_PPC_SUPPORT | 408 #ifdef HAS_PPC_SUPPORT |
388 case CPU_TYPE_POWERPC: | 409 case CPU_TYPE_POWERPC: |
389 return CurrentPCForStackPPC(state); | 410 return CurrentPCForStackPPC(state); |
390 case CPU_TYPE_POWERPC64: | 411 case CPU_TYPE_POWERPC64: |
391 return CurrentPCForStackPPC64(state); | 412 return CurrentPCForStackPPC64(state); |
392 #endif | 413 #endif |
414 #ifdef HAS_X86_SUPPORT | |
393 case CPU_TYPE_I386: | 415 case CPU_TYPE_I386: |
394 return CurrentPCForStackX86(state); | 416 return CurrentPCForStackX86(state); |
395 case CPU_TYPE_X86_64: | 417 case CPU_TYPE_X86_64: |
396 return CurrentPCForStackX86_64(state); | 418 return CurrentPCForStackX86_64(state); |
419 #endif | |
397 default: | 420 default: |
398 assert("Unknown CPU type!"); | 421 assert("Unknown CPU type!"); |
399 return 0; | 422 return 0; |
400 } | 423 } |
401 } | 424 } |
402 | 425 |
426 #ifdef HAS_ARM_SUPPORT | |
427 bool MinidumpGenerator::WriteStackARM(breakpad_thread_state_data_t state, | |
428 MDMemoryDescriptor *stack_location) { | |
429 arm_thread_state_t *machine_state = | |
430 reinterpret_cast<arm_thread_state_t *>(state); | |
431 mach_vm_address_t start_addr = REGISTER_FROM_THREADSTATE(machine_state, sp); | |
432 return WriteStackFromStartAddress(start_addr, stack_location); | |
433 } | |
434 | |
435 u_int64_t | |
436 MinidumpGenerator::CurrentPCForStackARM(breakpad_thread_state_data_t state) { | |
437 arm_thread_state_t *machine_state = | |
438 reinterpret_cast<arm_thread_state_t *>(state); | |
439 | |
440 return REGISTER_FROM_THREADSTATE(machine_state, pc); | |
441 } | |
442 | |
443 bool MinidumpGenerator::WriteContextARM(breakpad_thread_state_data_t state, | |
444 MDLocationDescriptor *register_location) | |
445 { | |
446 TypedMDRVA<MDRawContextARM> context(&writer_); | |
447 arm_thread_state_t *machine_state = | |
448 reinterpret_cast<arm_thread_state_t *>(state); | |
449 | |
450 if (!context.Allocate()) | |
451 return false; | |
452 | |
453 *register_location = context.location(); | |
454 MDRawContextARM *context_ptr = context.get(); | |
455 context_ptr->context_flags = MD_CONTEXT_ARM_FULL; | |
456 | |
457 #define AddReg(a) context_ptr->a = REGISTER_FROM_THREADSTATE(machine_state, a) | |
Ted Mielczarek
2011/10/06 14:56:09
You only use AddReg once. Doesn't seem worth the #
qsr
2011/10/06 17:48:23
Done.
| |
458 #define AddGPR(a) context_ptr->iregs[a] = REGISTER_FROM_THREADSTATE(machine_stat e, r[a]) | |
459 | |
460 context_ptr->iregs[13] = REGISTER_FROM_THREADSTATE(machine_state, sp); | |
461 context_ptr->iregs[14] = REGISTER_FROM_THREADSTATE(machine_state, lr); | |
462 context_ptr->iregs[15] = REGISTER_FROM_THREADSTATE(machine_state, pc); | |
463 AddReg(cpsr); | |
464 | |
465 AddGPR(0); | |
466 AddGPR(1); | |
467 AddGPR(2); | |
468 AddGPR(3); | |
469 AddGPR(4); | |
470 AddGPR(5); | |
471 AddGPR(6); | |
472 AddGPR(7); | |
473 AddGPR(8); | |
474 AddGPR(9); | |
475 AddGPR(10); | |
476 AddGPR(11); | |
477 AddGPR(12); | |
478 #undef AddReg | |
479 #undef AddGPR | |
480 | |
481 context_ptr->cpsr = 0; | |
Ted Mielczarek
2011/10/06 14:56:09
Why are you zeroing this out when you set it above
Mark Mentovai
2011/10/06 14:58:58
You can’t recover this from state->cpsr?
qsr
2011/10/06 17:48:23
Thanks. I let that slipped when I was trying to un
| |
482 | |
Mark Mentovai
2011/10/06 14:58:58
Wow, we never save any floating-point state for an
qsr
2011/10/06 17:48:23
No we don't. I guessed that I won't try new things
| |
483 return true; | |
484 } | |
485 #endif | |
486 | |
403 #ifdef HAS_PCC_SUPPORT | 487 #ifdef HAS_PCC_SUPPORT |
404 bool MinidumpGenerator::WriteStackPPC(breakpad_thread_state_data_t state, | 488 bool MinidumpGenerator::WriteStackPPC(breakpad_thread_state_data_t state, |
405 MDMemoryDescriptor *stack_location) { | 489 MDMemoryDescriptor *stack_location) { |
406 ppc_thread_state_t *machine_state = | 490 ppc_thread_state_t *machine_state = |
407 reinterpret_cast<ppc_thread_state_t *>(state); | 491 reinterpret_cast<ppc_thread_state_t *>(state); |
408 mach_vm_address_t start_addr = REGISTER_FROM_THREADSTATE(machine_state, r1); | 492 mach_vm_address_t start_addr = REGISTER_FROM_THREADSTATE(machine_state, r1); |
409 return WriteStackFromStartAddress(start_addr, stack_location); | 493 return WriteStackFromStartAddress(start_addr, stack_location); |
410 } | 494 } |
411 | 495 |
412 bool MinidumpGenerator::WriteStackPPC64(breakpad_thread_state_data_t state, | 496 bool MinidumpGenerator::WriteStackPPC64(breakpad_thread_state_data_t state, |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
553 AddGPR(30); | 637 AddGPR(30); |
554 AddGPR(31); | 638 AddGPR(31); |
555 #undef AddReg | 639 #undef AddReg |
556 #undef AddGPR | 640 #undef AddGPR |
557 | 641 |
558 return true; | 642 return true; |
559 } | 643 } |
560 | 644 |
561 #endif | 645 #endif |
562 | 646 |
647 #ifdef HAS_X86_SUPPORT | |
563 bool MinidumpGenerator::WriteStackX86(breakpad_thread_state_data_t state, | 648 bool MinidumpGenerator::WriteStackX86(breakpad_thread_state_data_t state, |
564 MDMemoryDescriptor *stack_location) { | 649 MDMemoryDescriptor *stack_location) { |
565 i386_thread_state_t *machine_state = | 650 i386_thread_state_t *machine_state = |
566 reinterpret_cast<i386_thread_state_t *>(state); | 651 reinterpret_cast<i386_thread_state_t *>(state); |
567 | 652 |
568 mach_vm_address_t start_addr = REGISTER_FROM_THREADSTATE(machine_state, esp); | 653 mach_vm_address_t start_addr = REGISTER_FROM_THREADSTATE(machine_state, esp); |
569 return WriteStackFromStartAddress(start_addr, stack_location); | 654 return WriteStackFromStartAddress(start_addr, stack_location); |
570 } | 655 } |
571 | 656 |
572 bool MinidumpGenerator::WriteStackX86_64(breakpad_thread_state_data_t state, | 657 bool MinidumpGenerator::WriteStackX86_64(breakpad_thread_state_data_t state, |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
671 // specifies 32 bits for the flags register, we can truncate safely | 756 // specifies 32 bits for the flags register, we can truncate safely |
672 // with no loss. | 757 // with no loss. |
673 context_ptr->eflags = static_cast<u_int32_t>(REGISTER_FROM_THREADSTATE(machine _state, rflags)); | 758 context_ptr->eflags = static_cast<u_int32_t>(REGISTER_FROM_THREADSTATE(machine _state, rflags)); |
674 AddReg(cs); | 759 AddReg(cs); |
675 AddReg(fs); | 760 AddReg(fs); |
676 AddReg(gs); | 761 AddReg(gs); |
677 #undef AddReg | 762 #undef AddReg |
678 | 763 |
679 return true; | 764 return true; |
680 } | 765 } |
766 #endif | |
681 | 767 |
682 bool MinidumpGenerator::GetThreadState(thread_act_t target_thread, | 768 bool MinidumpGenerator::GetThreadState(thread_act_t target_thread, |
683 thread_state_t state, | 769 thread_state_t state, |
684 mach_msg_type_number_t *count) { | 770 mach_msg_type_number_t *count) { |
685 thread_state_flavor_t flavor; | 771 thread_state_flavor_t flavor; |
686 switch (cpu_type_) { | 772 switch (cpu_type_) { |
773 #ifdef HAS_ARM_SUPPORT | |
774 case CPU_TYPE_ARM: | |
775 flavor = ARM_THREAD_STATE; | |
776 break; | |
777 #endif | |
687 #ifdef HAS_PPC_SUPPORT | 778 #ifdef HAS_PPC_SUPPORT |
688 case CPU_TYPE_POWERPC: | 779 case CPU_TYPE_POWERPC: |
689 flavor = PPC_THREAD_STATE; | 780 flavor = PPC_THREAD_STATE; |
690 break; | 781 break; |
691 case CPU_TYPE_POWERPC64: | 782 case CPU_TYPE_POWERPC64: |
692 flavor = PPC_THREAD_STATE64; | 783 flavor = PPC_THREAD_STATE64; |
693 break; | 784 break; |
694 #endif | 785 #endif |
786 #ifdef HAS_X86_SUPPORT | |
695 case CPU_TYPE_I386: | 787 case CPU_TYPE_I386: |
696 flavor = i386_THREAD_STATE; | 788 flavor = i386_THREAD_STATE; |
697 break; | 789 break; |
698 case CPU_TYPE_X86_64: | 790 case CPU_TYPE_X86_64: |
699 flavor = x86_THREAD_STATE64; | 791 flavor = x86_THREAD_STATE64; |
700 break; | 792 break; |
793 #endif | |
701 default: | 794 default: |
702 return false; | 795 return false; |
703 } | 796 } |
704 return thread_get_state(target_thread, flavor, | 797 return thread_get_state(target_thread, flavor, |
705 state, count) == KERN_SUCCESS; | 798 state, count) == KERN_SUCCESS; |
706 } | 799 } |
707 | 800 |
708 bool MinidumpGenerator::WriteThreadStream(mach_port_t thread_id, | 801 bool MinidumpGenerator::WriteThreadStream(mach_port_t thread_id, |
709 MDRawThread *thread) { | 802 MDRawThread *thread) { |
710 breakpad_thread_state_data_t state; | 803 breakpad_thread_state_data_t state; |
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
920 system_info_stream->stream_type = MD_SYSTEM_INFO_STREAM; | 1013 system_info_stream->stream_type = MD_SYSTEM_INFO_STREAM; |
921 system_info_stream->location = info.location(); | 1014 system_info_stream->location = info.location(); |
922 | 1015 |
923 // CPU Information | 1016 // CPU Information |
924 uint32_t number_of_processors; | 1017 uint32_t number_of_processors; |
925 size_t len = sizeof(number_of_processors); | 1018 size_t len = sizeof(number_of_processors); |
926 sysctlbyname("hw.ncpu", &number_of_processors, &len, NULL, 0); | 1019 sysctlbyname("hw.ncpu", &number_of_processors, &len, NULL, 0); |
927 MDRawSystemInfo *info_ptr = info.get(); | 1020 MDRawSystemInfo *info_ptr = info.get(); |
928 | 1021 |
929 switch (cpu_type_) { | 1022 switch (cpu_type_) { |
1023 case CPU_TYPE_ARM: | |
1024 info_ptr->processor_architecture = MD_CPU_ARCHITECTURE_ARM; | |
1025 break; | |
930 case CPU_TYPE_POWERPC: | 1026 case CPU_TYPE_POWERPC: |
931 case CPU_TYPE_POWERPC64: | 1027 case CPU_TYPE_POWERPC64: |
932 info_ptr->processor_architecture = MD_CPU_ARCHITECTURE_PPC; | 1028 info_ptr->processor_architecture = MD_CPU_ARCHITECTURE_PPC; |
933 break; | 1029 break; |
934 case CPU_TYPE_I386: | 1030 case CPU_TYPE_I386: |
935 case CPU_TYPE_X86_64: | 1031 case CPU_TYPE_X86_64: |
936 if (cpu_type_ == CPU_TYPE_I386) | 1032 if (cpu_type_ == CPU_TYPE_I386) |
937 info_ptr->processor_architecture = MD_CPU_ARCHITECTURE_X86; | 1033 info_ptr->processor_architecture = MD_CPU_ARCHITECTURE_X86; |
938 else | 1034 else |
939 info_ptr->processor_architecture = MD_CPU_ARCHITECTURE_AMD64; | 1035 info_ptr->processor_architecture = MD_CPU_ARCHITECTURE_AMD64; |
(...skipping 365 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1305 } else { | 1401 } else { |
1306 info_ptr->validity = MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID; | 1402 info_ptr->validity = MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID; |
1307 info_ptr->dump_thread_id = handler_thread_; | 1403 info_ptr->dump_thread_id = handler_thread_; |
1308 info_ptr->requesting_thread_id = 0; | 1404 info_ptr->requesting_thread_id = 0; |
1309 } | 1405 } |
1310 | 1406 |
1311 return true; | 1407 return true; |
1312 } | 1408 } |
1313 | 1409 |
1314 } // namespace google_breakpad | 1410 } // namespace google_breakpad |
OLD | NEW |