minidump_generator.cc revision 0344a368deac6abaa280a298bcea9bb00a90df3f
1// Copyright (c) 2006, 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#include <algorithm> 31#include <cstdio> 32 33#include <mach/host_info.h> 34#include <mach/i386/thread_status.h> 35#include <mach/mach_vm.h> 36#include <mach/ppc/thread_status.h> 37#include <mach/vm_statistics.h> 38#include <mach-o/dyld.h> 39#include <mach-o/loader.h> 40#include <sys/sysctl.h> 41#include <sys/resource.h> 42 43#include <CoreFoundation/CoreFoundation.h> 44 45#include "client/mac/handler/minidump_generator.h" 46#include "client/minidump_file_writer-inl.h" 47#include "common/mac/file_id.h" 48#include "common/mac/string_utilities.h" 49 50using MacStringUtils::ConvertToString; 51using MacStringUtils::IntegerValueAtIndex; 52 53namespace google_breakpad { 54 55#if __LP64__ 56#define LC_SEGMENT_ARCH LC_SEGMENT_64 57#else 58#define LC_SEGMENT_ARCH LC_SEGMENT 59#endif 60 61// constructor when generating from within the crashed process 62MinidumpGenerator::MinidumpGenerator() 63 : writer_(), 64 exception_type_(0), 65 exception_code_(0), 66 exception_subcode_(0), 67 exception_thread_(0), 68 crashing_task_(mach_task_self()), 69 handler_thread_(mach_thread_self()), 70 cpu_type_(DynamicImages::GetNativeCPUType()), 71 dynamic_images_(NULL), 72 memory_blocks_(&allocator_) { 73 GatherSystemInformation(); 74} 75 76// constructor when generating from a different process than the 77// crashed process 78MinidumpGenerator::MinidumpGenerator(mach_port_t crashing_task, 79 mach_port_t handler_thread) 80 : writer_(), 81 exception_type_(0), 82 exception_code_(0), 83 exception_subcode_(0), 84 exception_thread_(0), 85 crashing_task_(crashing_task), 86 handler_thread_(handler_thread), 87 cpu_type_(DynamicImages::GetNativeCPUType()), 88 dynamic_images_(NULL), 89 memory_blocks_(&allocator_) { 90 if (crashing_task != mach_task_self()) { 91 dynamic_images_ = new DynamicImages(crashing_task_); 92 cpu_type_ = dynamic_images_->GetCPUType(); 93 } else { 94 dynamic_images_ = NULL; 95 cpu_type_ = DynamicImages::GetNativeCPUType(); 96 } 97 98 GatherSystemInformation(); 99} 100 101MinidumpGenerator::~MinidumpGenerator() { 102 delete dynamic_images_; 103} 104 105char MinidumpGenerator::build_string_[16]; 106int MinidumpGenerator::os_major_version_ = 0; 107int MinidumpGenerator::os_minor_version_ = 0; 108int MinidumpGenerator::os_build_number_ = 0; 109 110// static 111void MinidumpGenerator::GatherSystemInformation() { 112 // If this is non-zero, then we've already gathered the information 113 if (os_major_version_) 114 return; 115 116 // This code extracts the version and build information from the OS 117 CFStringRef vers_path = 118 CFSTR("/System/Library/CoreServices/SystemVersion.plist"); 119 CFURLRef sys_vers = 120 CFURLCreateWithFileSystemPath(NULL, 121 vers_path, 122 kCFURLPOSIXPathStyle, 123 false); 124 CFDataRef data; 125 SInt32 error; 126 CFURLCreateDataAndPropertiesFromResource(NULL, sys_vers, &data, NULL, NULL, 127 &error); 128 129 if (!data) 130 return; 131 132 CFDictionaryRef list = static_cast<CFDictionaryRef> 133 (CFPropertyListCreateFromXMLData(NULL, data, kCFPropertyListImmutable, 134 NULL)); 135 if (!list) 136 return; 137 138 CFStringRef build_version = static_cast<CFStringRef> 139 (CFDictionaryGetValue(list, CFSTR("ProductBuildVersion"))); 140 CFStringRef product_version = static_cast<CFStringRef> 141 (CFDictionaryGetValue(list, CFSTR("ProductVersion"))); 142 string build_str = ConvertToString(build_version); 143 string product_str = ConvertToString(product_version); 144 145 CFRelease(list); 146 CFRelease(sys_vers); 147 CFRelease(data); 148 149 strlcpy(build_string_, build_str.c_str(), sizeof(build_string_)); 150 151 // Parse the string that looks like "10.4.8" 152 os_major_version_ = IntegerValueAtIndex(product_str, 0); 153 os_minor_version_ = IntegerValueAtIndex(product_str, 1); 154 os_build_number_ = IntegerValueAtIndex(product_str, 2); 155} 156 157string MinidumpGenerator::UniqueNameInDirectory(const string &dir, 158 string *unique_name) { 159 CFUUIDRef uuid = CFUUIDCreate(NULL); 160 CFStringRef uuid_cfstr = CFUUIDCreateString(NULL, uuid); 161 CFRelease(uuid); 162 string file_name(ConvertToString(uuid_cfstr)); 163 CFRelease(uuid_cfstr); 164 string path(dir); 165 166 // Ensure that the directory (if non-empty) has a trailing slash so that 167 // we can append the file name and have a valid pathname. 168 if (!dir.empty()) { 169 if (dir.at(dir.size() - 1) != '/') 170 path.append(1, '/'); 171 } 172 173 path.append(file_name); 174 path.append(".dmp"); 175 176 if (unique_name) 177 *unique_name = file_name; 178 179 return path; 180} 181 182bool MinidumpGenerator::Write(const char *path) { 183 WriteStreamFN writers[] = { 184 &MinidumpGenerator::WriteThreadListStream, 185 &MinidumpGenerator::WriteMemoryListStream, 186 &MinidumpGenerator::WriteSystemInfoStream, 187 &MinidumpGenerator::WriteModuleListStream, 188 &MinidumpGenerator::WriteMiscInfoStream, 189 &MinidumpGenerator::WriteBreakpadInfoStream, 190 // Exception stream needs to be the last entry in this array as it may 191 // be omitted in the case where the minidump is written without an 192 // exception. 193 &MinidumpGenerator::WriteExceptionStream, 194 }; 195 bool result = false; 196 197 // If opening was successful, create the header, directory, and call each 198 // writer. The destructor for the TypedMDRVAs will cause the data to be 199 // flushed. The destructor for the MinidumpFileWriter will close the file. 200 if (writer_.Open(path)) { 201 TypedMDRVA<MDRawHeader> header(&writer_); 202 TypedMDRVA<MDRawDirectory> dir(&writer_); 203 204 if (!header.Allocate()) 205 return false; 206 207 int writer_count = static_cast<int>(sizeof(writers) / sizeof(writers[0])); 208 209 // If we don't have exception information, don't write out the 210 // exception stream 211 if (!exception_thread_ && !exception_type_) 212 --writer_count; 213 214 // Add space for all writers 215 if (!dir.AllocateArray(writer_count)) 216 return false; 217 218 MDRawHeader *header_ptr = header.get(); 219 header_ptr->signature = MD_HEADER_SIGNATURE; 220 header_ptr->version = MD_HEADER_VERSION; 221 time(reinterpret_cast<time_t *>(&(header_ptr->time_date_stamp))); 222 header_ptr->stream_count = writer_count; 223 header_ptr->stream_directory_rva = dir.position(); 224 225 MDRawDirectory local_dir; 226 result = true; 227 for (int i = 0; (result) && (i < writer_count); ++i) { 228 result = (this->*writers[i])(&local_dir); 229 230 if (result) 231 dir.CopyIndex(i, &local_dir); 232 } 233 } 234 return result; 235} 236 237size_t MinidumpGenerator::CalculateStackSize(mach_vm_address_t start_addr) { 238 mach_vm_address_t stack_region_base = start_addr; 239 mach_vm_size_t stack_region_size; 240 natural_t nesting_level = 0; 241 vm_region_submap_info_64 submap_info; 242 mach_msg_type_number_t info_count = VM_REGION_SUBMAP_INFO_COUNT_64; 243 244 vm_region_recurse_info_t region_info; 245 region_info = reinterpret_cast<vm_region_recurse_info_t>(&submap_info); 246 247 if (start_addr == 0) { 248 return 0; 249 } 250 251 kern_return_t result = 252 mach_vm_region_recurse(crashing_task_, &stack_region_base, 253 &stack_region_size, &nesting_level, 254 region_info, 255 &info_count); 256 257 if (start_addr < stack_region_base) { 258 // probably stack corruption, since mach_vm_region had to go 259 // higher in the process address space to find a valid region. 260 return 0; 261 } 262 263 if (((cpu_type_ & CPU_ARCH_ABI64) && 264 (stack_region_base + stack_region_size) == TOP_OF_THREAD0_STACK_64BIT) || 265 (!(cpu_type_ & CPU_ARCH_ABI64) && 266 (stack_region_base + stack_region_size) == TOP_OF_THREAD0_STACK_32BIT)) { 267 // The stack for thread 0 needs to extend all the way to 268 // 0xc0000000 on 32 bit and 00007fff5fc00000 on 64bit. HOWEVER, 269 // for many processes, the stack is first created in one page 270 // below this, and is then later extended to a much larger size by 271 // creating a new VM region immediately below the initial page. 272 273 // You can see this for yourself by running vmmap on a "hello, 274 // world" program 275 276 // Because of the above, we'll add 4k to include the original 277 // stack frame page. 278 // This method of finding the stack region needs to be done in 279 // a better way; the breakpad issue 247 is tracking this. 280 stack_region_size += 0x1000; 281 } 282 283 return result == KERN_SUCCESS ? 284 stack_region_base + stack_region_size - start_addr : 0; 285} 286 287bool MinidumpGenerator::WriteStackFromStartAddress( 288 mach_vm_address_t start_addr, 289 MDMemoryDescriptor *stack_location) { 290 UntypedMDRVA memory(&writer_); 291 292 bool result = false; 293 size_t size = CalculateStackSize(start_addr); 294 295 if (size == 0) { 296 // In some situations the stack address for the thread can come back 0. 297 // In these cases we skip over the threads in question and stuff the 298 // stack with a clearly borked value. 299 start_addr = 0xDEADBEEF; 300 size = 16; 301 if (!memory.Allocate(size)) 302 return false; 303 304 unsigned long long dummy_stack[2]; // Fill dummy stack with 16 bytes of 305 // junk. 306 dummy_stack[0] = 0xDEADBEEF; 307 dummy_stack[1] = 0xDEADBEEF; 308 309 result = memory.Copy(dummy_stack, size); 310 } else { 311 312 if (!memory.Allocate(size)) 313 return false; 314 315 if (dynamic_images_) { 316 vector<uint8_t> stack_memory; 317 if (ReadTaskMemory(crashing_task_, 318 start_addr, 319 size, 320 stack_memory) != KERN_SUCCESS) { 321 return false; 322 } 323 324 result = memory.Copy(&stack_memory[0], size); 325 } else { 326 result = memory.Copy(reinterpret_cast<const void *>(start_addr), size); 327 } 328 } 329 330 stack_location->start_of_memory_range = start_addr; 331 stack_location->memory = memory.location(); 332 333 return result; 334} 335 336bool MinidumpGenerator::WriteStack(breakpad_thread_state_data_t state, 337 MDMemoryDescriptor *stack_location) { 338 switch (cpu_type_) { 339 case CPU_TYPE_POWERPC: 340 return WriteStackPPC(state, stack_location); 341 case CPU_TYPE_POWERPC64: 342 return WriteStackPPC64(state, stack_location); 343 case CPU_TYPE_I386: 344 return WriteStackX86(state, stack_location); 345 case CPU_TYPE_X86_64: 346 return WriteStackX86_64(state, stack_location); 347 default: 348 return false; 349 } 350} 351 352bool MinidumpGenerator::WriteContext(breakpad_thread_state_data_t state, 353 MDLocationDescriptor *register_location) { 354 switch (cpu_type_) { 355 case CPU_TYPE_POWERPC: 356 return WriteContextPPC(state, register_location); 357 case CPU_TYPE_POWERPC64: 358 return WriteContextPPC64(state, register_location); 359 case CPU_TYPE_I386: 360 return WriteContextX86(state, register_location); 361 case CPU_TYPE_X86_64: 362 return WriteContextX86_64(state, register_location); 363 default: 364 return false; 365 } 366} 367 368u_int64_t MinidumpGenerator::CurrentPCForStack( 369 breakpad_thread_state_data_t state) { 370 switch (cpu_type_) { 371 case CPU_TYPE_POWERPC: 372 return CurrentPCForStackPPC(state); 373 case CPU_TYPE_POWERPC64: 374 return CurrentPCForStackPPC64(state); 375 case CPU_TYPE_I386: 376 return CurrentPCForStackX86(state); 377 case CPU_TYPE_X86_64: 378 return CurrentPCForStackX86_64(state); 379 default: 380 assert("Unknown CPU type!"); 381 return 0; 382 } 383} 384 385bool MinidumpGenerator::WriteStackPPC(breakpad_thread_state_data_t state, 386 MDMemoryDescriptor *stack_location) { 387 ppc_thread_state_t *machine_state = 388 reinterpret_cast<ppc_thread_state_t *>(state); 389 mach_vm_address_t start_addr = REGISTER_FROM_THREADSTATE(machine_state, r1); 390 return WriteStackFromStartAddress(start_addr, stack_location); 391} 392 393bool MinidumpGenerator::WriteStackPPC64(breakpad_thread_state_data_t state, 394 MDMemoryDescriptor *stack_location) { 395 ppc_thread_state64_t *machine_state = 396 reinterpret_cast<ppc_thread_state64_t *>(state); 397 mach_vm_address_t start_addr = REGISTER_FROM_THREADSTATE(machine_state, r1); 398 return WriteStackFromStartAddress(start_addr, stack_location); 399} 400 401u_int64_t 402MinidumpGenerator::CurrentPCForStackPPC(breakpad_thread_state_data_t state) { 403 ppc_thread_state_t *machine_state = 404 reinterpret_cast<ppc_thread_state_t *>(state); 405 406 return REGISTER_FROM_THREADSTATE(machine_state, srr0); 407} 408 409u_int64_t 410MinidumpGenerator::CurrentPCForStackPPC64(breakpad_thread_state_data_t state) { 411 ppc_thread_state64_t *machine_state = 412 reinterpret_cast<ppc_thread_state64_t *>(state); 413 414 return REGISTER_FROM_THREADSTATE(machine_state, srr0); 415} 416 417bool MinidumpGenerator::WriteContextPPC(breakpad_thread_state_data_t state, 418 MDLocationDescriptor *register_location) 419{ 420 TypedMDRVA<MDRawContextPPC> context(&writer_); 421 ppc_thread_state_t *machine_state = 422 reinterpret_cast<ppc_thread_state_t *>(state); 423 424 if (!context.Allocate()) 425 return false; 426 427 *register_location = context.location(); 428 MDRawContextPPC *context_ptr = context.get(); 429 context_ptr->context_flags = MD_CONTEXT_PPC_BASE; 430 431#define AddReg(a) context_ptr->a = REGISTER_FROM_THREADSTATE(machine_state, a) 432#define AddGPR(a) context_ptr->gpr[a] = REGISTER_FROM_THREADSTATE(machine_state, r ## a) 433 434 AddReg(srr0); 435 AddReg(cr); 436 AddReg(xer); 437 AddReg(ctr); 438 AddReg(lr); 439 AddReg(vrsave); 440 441 AddGPR(0); 442 AddGPR(1); 443 AddGPR(2); 444 AddGPR(3); 445 AddGPR(4); 446 AddGPR(5); 447 AddGPR(6); 448 AddGPR(7); 449 AddGPR(8); 450 AddGPR(9); 451 AddGPR(10); 452 AddGPR(11); 453 AddGPR(12); 454 AddGPR(13); 455 AddGPR(14); 456 AddGPR(15); 457 AddGPR(16); 458 AddGPR(17); 459 AddGPR(18); 460 AddGPR(19); 461 AddGPR(20); 462 AddGPR(21); 463 AddGPR(22); 464 AddGPR(23); 465 AddGPR(24); 466 AddGPR(25); 467 AddGPR(26); 468 AddGPR(27); 469 AddGPR(28); 470 AddGPR(29); 471 AddGPR(30); 472 AddGPR(31); 473 AddReg(mq); 474#undef AddReg 475#undef AddGPR 476 477 return true; 478} 479 480bool MinidumpGenerator::WriteContextPPC64( 481 breakpad_thread_state_data_t state, 482 MDLocationDescriptor *register_location) { 483 TypedMDRVA<MDRawContextPPC64> context(&writer_); 484 ppc_thread_state64_t *machine_state = 485 reinterpret_cast<ppc_thread_state64_t *>(state); 486 487 if (!context.Allocate()) 488 return false; 489 490 *register_location = context.location(); 491 MDRawContextPPC64 *context_ptr = context.get(); 492 context_ptr->context_flags = MD_CONTEXT_PPC_BASE; 493 494#define AddReg(a) context_ptr->a = REGISTER_FROM_THREADSTATE(machine_state, a) 495#define AddGPR(a) context_ptr->gpr[a] = REGISTER_FROM_THREADSTATE(machine_state, r ## a) 496 497 AddReg(srr0); 498 AddReg(cr); 499 AddReg(xer); 500 AddReg(ctr); 501 AddReg(lr); 502 AddReg(vrsave); 503 504 AddGPR(0); 505 AddGPR(1); 506 AddGPR(2); 507 AddGPR(3); 508 AddGPR(4); 509 AddGPR(5); 510 AddGPR(6); 511 AddGPR(7); 512 AddGPR(8); 513 AddGPR(9); 514 AddGPR(10); 515 AddGPR(11); 516 AddGPR(12); 517 AddGPR(13); 518 AddGPR(14); 519 AddGPR(15); 520 AddGPR(16); 521 AddGPR(17); 522 AddGPR(18); 523 AddGPR(19); 524 AddGPR(20); 525 AddGPR(21); 526 AddGPR(22); 527 AddGPR(23); 528 AddGPR(24); 529 AddGPR(25); 530 AddGPR(26); 531 AddGPR(27); 532 AddGPR(28); 533 AddGPR(29); 534 AddGPR(30); 535 AddGPR(31); 536#undef AddReg 537#undef AddGPR 538 539 return true; 540} 541 542bool MinidumpGenerator::WriteStackX86(breakpad_thread_state_data_t state, 543 MDMemoryDescriptor *stack_location) { 544 i386_thread_state_t *machine_state = 545 reinterpret_cast<i386_thread_state_t *>(state); 546 547 mach_vm_address_t start_addr = REGISTER_FROM_THREADSTATE(machine_state, esp); 548 return WriteStackFromStartAddress(start_addr, stack_location); 549} 550 551bool MinidumpGenerator::WriteStackX86_64(breakpad_thread_state_data_t state, 552 MDMemoryDescriptor *stack_location) { 553 x86_thread_state64_t *machine_state = 554 reinterpret_cast<x86_thread_state64_t *>(state); 555 556 mach_vm_address_t start_addr = REGISTER_FROM_THREADSTATE(machine_state, rsp); 557 return WriteStackFromStartAddress(start_addr, stack_location); 558} 559 560u_int64_t 561MinidumpGenerator::CurrentPCForStackX86(breakpad_thread_state_data_t state) { 562 i386_thread_state_t *machine_state = 563 reinterpret_cast<i386_thread_state_t *>(state); 564 565 return REGISTER_FROM_THREADSTATE(machine_state, eip); 566} 567 568u_int64_t 569MinidumpGenerator::CurrentPCForStackX86_64(breakpad_thread_state_data_t state) { 570 x86_thread_state64_t *machine_state = 571 reinterpret_cast<x86_thread_state64_t *>(state); 572 573 return REGISTER_FROM_THREADSTATE(machine_state, rip); 574} 575 576bool MinidumpGenerator::WriteContextX86(breakpad_thread_state_data_t state, 577 MDLocationDescriptor *register_location) 578{ 579 TypedMDRVA<MDRawContextX86> context(&writer_); 580 i386_thread_state_t *machine_state = 581 reinterpret_cast<i386_thread_state_t *>(state); 582 583 if (!context.Allocate()) 584 return false; 585 586 *register_location = context.location(); 587 MDRawContextX86 *context_ptr = context.get(); 588 589#define AddReg(a) context_ptr->a = REGISTER_FROM_THREADSTATE(machine_state, a) 590 591 context_ptr->context_flags = MD_CONTEXT_X86; 592 AddReg(eax); 593 AddReg(ebx); 594 AddReg(ecx); 595 AddReg(edx); 596 AddReg(esi); 597 AddReg(edi); 598 AddReg(ebp); 599 AddReg(esp); 600 601 AddReg(cs); 602 AddReg(ds); 603 AddReg(ss); 604 AddReg(es); 605 AddReg(fs); 606 AddReg(gs); 607 AddReg(eflags); 608 609 AddReg(eip); 610#undef AddReg(a) 611 612 return true; 613} 614 615bool MinidumpGenerator::WriteContextX86_64( 616 breakpad_thread_state_data_t state, 617 MDLocationDescriptor *register_location) { 618 TypedMDRVA<MDRawContextAMD64> context(&writer_); 619 x86_thread_state64_t *machine_state = 620 reinterpret_cast<x86_thread_state64_t *>(state); 621 622 if (!context.Allocate()) 623 return false; 624 625 *register_location = context.location(); 626 MDRawContextAMD64 *context_ptr = context.get(); 627 628#define AddReg(a) context_ptr->a = REGISTER_FROM_THREADSTATE(machine_state, a) 629 630 context_ptr->context_flags = MD_CONTEXT_AMD64; 631 AddReg(rax); 632 AddReg(rbx); 633 AddReg(rcx); 634 AddReg(rdx); 635 AddReg(rdi); 636 AddReg(rsi); 637 AddReg(rbp); 638 AddReg(rsp); 639 AddReg(r8); 640 AddReg(r9); 641 AddReg(r10); 642 AddReg(r11); 643 AddReg(r12); 644 AddReg(r13); 645 AddReg(r14); 646 AddReg(r15); 647 AddReg(rip); 648 // according to AMD's software developer guide, bits above 18 are 649 // not used in the flags register. Since the minidump format 650 // specifies 32 bits for the flags register, we can truncate safely 651 // with no loss. 652 context_ptr->eflags = static_cast<u_int32_t>(REGISTER_FROM_THREADSTATE(machine_state, rflags)); 653 AddReg(cs); 654 AddReg(fs); 655 AddReg(gs); 656#undef AddReg(a) 657 658 return true; 659} 660 661bool MinidumpGenerator::GetThreadState(thread_act_t target_thread, 662 thread_state_t state, 663 mach_msg_type_number_t *count) { 664 thread_state_flavor_t flavor; 665 switch (cpu_type_) { 666 case CPU_TYPE_POWERPC: 667 flavor = PPC_THREAD_STATE; 668 break; 669 case CPU_TYPE_POWERPC64: 670 flavor = PPC_THREAD_STATE64; 671 break; 672 case CPU_TYPE_I386: 673 flavor = i386_THREAD_STATE; 674 break; 675 case CPU_TYPE_X86_64: 676 flavor = x86_THREAD_STATE64; 677 break; 678 default: 679 return false; 680 } 681 return thread_get_state(target_thread, flavor, 682 state, count) == KERN_SUCCESS; 683} 684 685bool MinidumpGenerator::WriteThreadStream(mach_port_t thread_id, 686 MDRawThread *thread) { 687 breakpad_thread_state_data_t state; 688 mach_msg_type_number_t state_count 689 = static_cast<mach_msg_type_number_t>(sizeof(state)); 690 691 if (GetThreadState(thread_id, state, &state_count)) { 692 if (!WriteStack(state, &thread->stack)) 693 return false; 694 695 memory_blocks_.push_back(thread->stack); 696 697 if (!WriteContext(state, &thread->thread_context)) 698 return false; 699 700 thread->thread_id = thread_id; 701 } else { 702 return false; 703 } 704 705 return true; 706} 707 708bool MinidumpGenerator::WriteThreadListStream( 709 MDRawDirectory *thread_list_stream) { 710 TypedMDRVA<MDRawThreadList> list(&writer_); 711 thread_act_port_array_t threads_for_task; 712 mach_msg_type_number_t thread_count; 713 int non_generator_thread_count; 714 715 if (task_threads(crashing_task_, &threads_for_task, &thread_count)) 716 return false; 717 718 // Don't include the generator thread 719 if (handler_thread_ != MACH_PORT_NULL) 720 non_generator_thread_count = thread_count - 1; 721 else 722 non_generator_thread_count = thread_count; 723 if (!list.AllocateObjectAndArray(non_generator_thread_count, 724 sizeof(MDRawThread))) 725 return false; 726 727 thread_list_stream->stream_type = MD_THREAD_LIST_STREAM; 728 thread_list_stream->location = list.location(); 729 730 list.get()->number_of_threads = non_generator_thread_count; 731 732 MDRawThread thread; 733 int thread_idx = 0; 734 735 for (unsigned int i = 0; i < thread_count; ++i) { 736 memset(&thread, 0, sizeof(MDRawThread)); 737 738 if (threads_for_task[i] != handler_thread_) { 739 if (!WriteThreadStream(threads_for_task[i], &thread)) 740 return false; 741 742 list.CopyIndexAfterObject(thread_idx++, &thread, sizeof(MDRawThread)); 743 } 744 } 745 746 return true; 747} 748 749bool MinidumpGenerator::WriteMemoryListStream( 750 MDRawDirectory *memory_list_stream) { 751 TypedMDRVA<MDRawMemoryList> list(&writer_); 752 753 // If the dump has an exception, include some memory around the 754 // instruction pointer. 755 const size_t kIPMemorySize = 256; // bytes 756 bool have_ip_memory = false; 757 MDMemoryDescriptor ip_memory_d; 758 if (exception_thread_ && exception_type_) { 759 breakpad_thread_state_data_t state; 760 mach_msg_type_number_t stateCount 761 = static_cast<mach_msg_type_number_t>(sizeof(state)); 762 763 if (thread_get_state(exception_thread_, 764 BREAKPAD_MACHINE_THREAD_STATE, 765 state, 766 &stateCount) == KERN_SUCCESS) { 767 u_int64_t ip = CurrentPCForStack(state); 768 // Bound it to the upper and lower bounds of the region 769 // it's contained within. If it's not in a known memory region, 770 // don't bother trying to write it. 771 mach_vm_address_t addr = ip; 772 mach_vm_size_t size; 773 natural_t nesting_level = 0; 774 vm_region_submap_info_64 info; 775 mach_msg_type_number_t info_count = VM_REGION_SUBMAP_INFO_COUNT_64; 776 777 kern_return_t ret = 778 mach_vm_region_recurse(crashing_task_, 779 &addr, 780 &size, 781 &nesting_level, 782 (vm_region_recurse_info_t)&info, 783 &info_count); 784 if (ret == KERN_SUCCESS && ip >= addr && ip < (addr + size)) { 785 // Try to get 128 bytes before and after the IP, but 786 // settle for whatever's available. 787 ip_memory_d.start_of_memory_range = 788 std::max(uintptr_t(addr), 789 uintptr_t(ip - (kIPMemorySize / 2))); 790 uintptr_t end_of_range = 791 std::min(uintptr_t(ip + (kIPMemorySize / 2)), 792 uintptr_t(addr + size)); 793 ip_memory_d.memory.data_size = 794 end_of_range - ip_memory_d.start_of_memory_range; 795 have_ip_memory = true; 796 // This needs to get appended to the list even though 797 // the memory bytes aren't filled in yet so the entire 798 // list can be written first. The memory bytes will get filled 799 // in after the memory list is written. 800 memory_blocks_.push_back(ip_memory_d); 801 } 802 } 803 } 804 805 // Now fill in the memory list and write it. 806 unsigned memory_count = memory_blocks_.size(); 807 if (!list.AllocateObjectAndArray(memory_count, 808 sizeof(MDMemoryDescriptor))) 809 return false; 810 811 memory_list_stream->stream_type = MD_MEMORY_LIST_STREAM; 812 memory_list_stream->location = list.location(); 813 814 list.get()->number_of_memory_ranges = memory_count; 815 816 unsigned int i; 817 for (i = 0; i < memory_count; ++i) { 818 list.CopyIndexAfterObject(i, &memory_blocks_[i], 819 sizeof(MDMemoryDescriptor)); 820 } 821 822 if (have_ip_memory) { 823 // Now read the memory around the instruction pointer. 824 UntypedMDRVA ip_memory(&writer_); 825 if (!ip_memory.Allocate(ip_memory_d.memory.data_size)) 826 return false; 827 828 if (dynamic_images_) { 829 // Out-of-process. 830 vector<uint8_t> memory; 831 if (ReadTaskMemory(crashing_task_, 832 ip_memory_d.start_of_memory_range, 833 ip_memory_d.memory.data_size, 834 memory) != KERN_SUCCESS) { 835 return false; 836 } 837 838 ip_memory.Copy(&memory[0], ip_memory_d.memory.data_size); 839 } else { 840 // In-process, just copy from local memory. 841 ip_memory.Copy( 842 reinterpret_cast<const void *>(ip_memory_d.start_of_memory_range), 843 ip_memory_d.memory.data_size); 844 } 845 846 ip_memory_d.memory = ip_memory.location(); 847 // Write this again now that the data location is filled in. 848 list.CopyIndexAfterObject(i - 1, &ip_memory_d, 849 sizeof(MDMemoryDescriptor)); 850 } 851 852 return true; 853} 854 855bool 856MinidumpGenerator::WriteExceptionStream(MDRawDirectory *exception_stream) { 857 TypedMDRVA<MDRawExceptionStream> exception(&writer_); 858 859 if (!exception.Allocate()) 860 return false; 861 862 exception_stream->stream_type = MD_EXCEPTION_STREAM; 863 exception_stream->location = exception.location(); 864 MDRawExceptionStream *exception_ptr = exception.get(); 865 exception_ptr->thread_id = exception_thread_; 866 867 // This naming is confusing, but it is the proper translation from 868 // mach naming to minidump naming. 869 exception_ptr->exception_record.exception_code = exception_type_; 870 exception_ptr->exception_record.exception_flags = exception_code_; 871 872 breakpad_thread_state_data_t state; 873 mach_msg_type_number_t stateCount 874 = static_cast<mach_msg_type_number_t>(sizeof(state)); 875 876 if (thread_get_state(exception_thread_, 877 BREAKPAD_MACHINE_THREAD_STATE, 878 state, 879 &stateCount) != KERN_SUCCESS) 880 return false; 881 882 if (!WriteContext(state, &exception_ptr->thread_context)) 883 return false; 884 885 if (exception_type_ == EXC_BAD_ACCESS) 886 exception_ptr->exception_record.exception_address = exception_subcode_; 887 else 888 exception_ptr->exception_record.exception_address = CurrentPCForStack(state); 889 890 return true; 891} 892 893bool MinidumpGenerator::WriteSystemInfoStream( 894 MDRawDirectory *system_info_stream) { 895 TypedMDRVA<MDRawSystemInfo> info(&writer_); 896 897 if (!info.Allocate()) 898 return false; 899 900 system_info_stream->stream_type = MD_SYSTEM_INFO_STREAM; 901 system_info_stream->location = info.location(); 902 903 // CPU Information 904 uint32_t number_of_processors; 905 size_t len = sizeof(number_of_processors); 906 sysctlbyname("hw.ncpu", &number_of_processors, &len, NULL, 0); 907 MDRawSystemInfo *info_ptr = info.get(); 908 909 switch (cpu_type_) { 910 case CPU_TYPE_POWERPC: 911 case CPU_TYPE_POWERPC64: 912 info_ptr->processor_architecture = MD_CPU_ARCHITECTURE_PPC; 913 break; 914 case CPU_TYPE_I386: 915 case CPU_TYPE_X86_64: 916 if (cpu_type_ == CPU_TYPE_I386) 917 info_ptr->processor_architecture = MD_CPU_ARCHITECTURE_X86; 918 else 919 info_ptr->processor_architecture = MD_CPU_ARCHITECTURE_AMD64; 920#ifdef __i386__ 921 // ebx is used for PIC code, so we need 922 // to preserve it. 923#define cpuid(op,eax,ebx,ecx,edx) \ 924 asm ("pushl %%ebx \n\t" \ 925 "cpuid \n\t" \ 926 "movl %%ebx,%1 \n\t" \ 927 "popl %%ebx" \ 928 : "=a" (eax), \ 929 "=g" (ebx), \ 930 "=c" (ecx), \ 931 "=d" (edx) \ 932 : "0" (op)) 933#elif defined(__x86_64__) 934 935#define cpuid(op,eax,ebx,ecx,edx) \ 936 asm ("cpuid \n\t" \ 937 : "=a" (eax), \ 938 "=b" (ebx), \ 939 "=c" (ecx), \ 940 "=d" (edx) \ 941 : "0" (op)) 942#endif 943 944#if defined(__i386__) || defined(__x86_64__) 945 int unused, unused2; 946 // get vendor id 947 cpuid(0, unused, info_ptr->cpu.x86_cpu_info.vendor_id[0], 948 info_ptr->cpu.x86_cpu_info.vendor_id[2], 949 info_ptr->cpu.x86_cpu_info.vendor_id[1]); 950 // get version and feature info 951 cpuid(1, info_ptr->cpu.x86_cpu_info.version_information, unused, unused2, 952 info_ptr->cpu.x86_cpu_info.feature_information); 953 954 // family 955 info_ptr->processor_level = 956 (info_ptr->cpu.x86_cpu_info.version_information & 0xF00) >> 8; 957 // 0xMMSS (Model, Stepping) 958 info_ptr->processor_revision = 959 (info_ptr->cpu.x86_cpu_info.version_information & 0xF) | 960 ((info_ptr->cpu.x86_cpu_info.version_information & 0xF0) << 4); 961 962 // decode extended model info 963 if (info_ptr->processor_level == 0xF || 964 info_ptr->processor_level == 0x6) { 965 info_ptr->processor_revision |= 966 ((info_ptr->cpu.x86_cpu_info.version_information & 0xF0000) >> 4); 967 } 968 969 // decode extended family info 970 if (info_ptr->processor_level == 0xF) { 971 info_ptr->processor_level += 972 ((info_ptr->cpu.x86_cpu_info.version_information & 0xFF00000) >> 20); 973 } 974 975#endif // __i386__ || __x86_64_ 976 break; 977 default: 978 info_ptr->processor_architecture = MD_CPU_ARCHITECTURE_UNKNOWN; 979 break; 980 } 981 982 info_ptr->number_of_processors = number_of_processors; 983 info_ptr->platform_id = MD_OS_MAC_OS_X; 984 985 MDLocationDescriptor build_string_loc; 986 987 if (!writer_.WriteString(build_string_, 0, 988 &build_string_loc)) 989 return false; 990 991 info_ptr->csd_version_rva = build_string_loc.rva; 992 info_ptr->major_version = os_major_version_; 993 info_ptr->minor_version = os_minor_version_; 994 info_ptr->build_number = os_build_number_; 995 996 return true; 997} 998 999bool MinidumpGenerator::WriteModuleStream(unsigned int index, 1000 MDRawModule *module) { 1001 if (dynamic_images_) { 1002 // we're in a different process than the crashed process 1003 DynamicImage *image = dynamic_images_->GetImage(index); 1004 1005 if (!image) 1006 return false; 1007 1008 memset(module, 0, sizeof(MDRawModule)); 1009 1010 MDLocationDescriptor string_location; 1011 1012 string name = image->GetFilePath(); 1013 if (!writer_.WriteString(name.c_str(), 0, &string_location)) 1014 return false; 1015 1016 module->base_of_image = image->GetVMAddr() + image->GetVMAddrSlide(); 1017 module->size_of_image = static_cast<u_int32_t>(image->GetVMSize()); 1018 module->module_name_rva = string_location.rva; 1019 1020 // We'll skip the executable module, because they don't have 1021 // LC_ID_DYLIB load commands, and the crash processing server gets 1022 // version information from the Plist file, anyway. 1023 if (index != (uint32_t)FindExecutableModule()) { 1024 module->version_info.signature = MD_VSFIXEDFILEINFO_SIGNATURE; 1025 module->version_info.struct_version |= MD_VSFIXEDFILEINFO_VERSION; 1026 // Convert MAC dylib version format, which is a 32 bit number, to the 1027 // format used by minidump. The mac format is <16 bits>.<8 bits>.<8 bits> 1028 // so it fits nicely into the windows version with some massaging 1029 // The mapping is: 1030 // 1) upper 16 bits of MAC version go to lower 16 bits of product HI 1031 // 2) Next most significant 8 bits go to upper 16 bits of product LO 1032 // 3) Least significant 8 bits go to lower 16 bits of product LO 1033 uint32_t modVersion = image->GetVersion(); 1034 module->version_info.file_version_hi = 0; 1035 module->version_info.file_version_hi = modVersion >> 16; 1036 module->version_info.file_version_lo |= (modVersion & 0xff00) << 8; 1037 module->version_info.file_version_lo |= (modVersion & 0xff); 1038 } 1039 1040 if (!WriteCVRecord(module, image->GetCPUType(), name.c_str())) { 1041 return false; 1042 } 1043 } else { 1044 // Getting module info in the crashed process 1045 const breakpad_mach_header *header; 1046 header = (breakpad_mach_header*)_dyld_get_image_header(index); 1047 if (!header) 1048 return false; 1049 1050#ifdef __LP64__ 1051 assert(header->magic == MH_MAGIC_64); 1052 1053 if(header->magic != MH_MAGIC_64) 1054 return false; 1055#else 1056 assert(header->magic == MH_MAGIC); 1057 1058 if(header->magic != MH_MAGIC) 1059 return false; 1060#endif 1061 1062 int cpu_type = header->cputype; 1063 unsigned long slide = _dyld_get_image_vmaddr_slide(index); 1064 const char* name = _dyld_get_image_name(index); 1065 const struct load_command *cmd = 1066 reinterpret_cast<const struct load_command *>(header + 1); 1067 1068 memset(module, 0, sizeof(MDRawModule)); 1069 1070 for (unsigned int i = 0; cmd && (i < header->ncmds); i++) { 1071 if (cmd->cmd == LC_SEGMENT_ARCH) { 1072 1073 const breakpad_mach_segment_command *seg = 1074 reinterpret_cast<const breakpad_mach_segment_command *>(cmd); 1075 1076 if (!strcmp(seg->segname, "__TEXT")) { 1077 MDLocationDescriptor string_location; 1078 1079 if (!writer_.WriteString(name, 0, &string_location)) 1080 return false; 1081 1082 module->base_of_image = seg->vmaddr + slide; 1083 module->size_of_image = static_cast<u_int32_t>(seg->vmsize); 1084 module->module_name_rva = string_location.rva; 1085 1086 if (!WriteCVRecord(module, cpu_type, name)) 1087 return false; 1088 1089 return true; 1090 } 1091 } 1092 1093 cmd = reinterpret_cast<struct load_command*>((char *)cmd + cmd->cmdsize); 1094 } 1095 } 1096 1097 return true; 1098} 1099 1100int MinidumpGenerator::FindExecutableModule() { 1101 if (dynamic_images_) { 1102 int index = dynamic_images_->GetExecutableImageIndex(); 1103 1104 if (index >= 0) { 1105 return index; 1106 } 1107 } else { 1108 int image_count = _dyld_image_count(); 1109 const struct mach_header *header; 1110 1111 for (int index = 0; index < image_count; ++index) { 1112 header = _dyld_get_image_header(index); 1113 1114 if (header->filetype == MH_EXECUTE) 1115 return index; 1116 } 1117 } 1118 1119 // failed - just use the first image 1120 return 0; 1121} 1122 1123bool MinidumpGenerator::WriteCVRecord(MDRawModule *module, int cpu_type, 1124 const char *module_path) { 1125 TypedMDRVA<MDCVInfoPDB70> cv(&writer_); 1126 1127 // Only return the last path component of the full module path 1128 const char *module_name = strrchr(module_path, '/'); 1129 1130 // Increment past the slash 1131 if (module_name) 1132 ++module_name; 1133 else 1134 module_name = "<Unknown>"; 1135 1136 size_t module_name_length = strlen(module_name); 1137 1138 if (!cv.AllocateObjectAndArray(module_name_length + 1, sizeof(u_int8_t))) 1139 return false; 1140 1141 if (!cv.CopyIndexAfterObject(0, module_name, module_name_length)) 1142 return false; 1143 1144 module->cv_record = cv.location(); 1145 MDCVInfoPDB70 *cv_ptr = cv.get(); 1146 cv_ptr->cv_signature = MD_CVINFOPDB70_SIGNATURE; 1147 cv_ptr->age = 0; 1148 1149 // Get the module identifier 1150 FileID file_id(module_path); 1151 unsigned char identifier[16]; 1152 1153 if (file_id.MachoIdentifier(cpu_type, identifier)) { 1154 cv_ptr->signature.data1 = (uint32_t)identifier[0] << 24 | 1155 (uint32_t)identifier[1] << 16 | (uint32_t)identifier[2] << 8 | 1156 (uint32_t)identifier[3]; 1157 cv_ptr->signature.data2 = (uint32_t)identifier[4] << 8 | identifier[5]; 1158 cv_ptr->signature.data3 = (uint32_t)identifier[6] << 8 | identifier[7]; 1159 cv_ptr->signature.data4[0] = identifier[8]; 1160 cv_ptr->signature.data4[1] = identifier[9]; 1161 cv_ptr->signature.data4[2] = identifier[10]; 1162 cv_ptr->signature.data4[3] = identifier[11]; 1163 cv_ptr->signature.data4[4] = identifier[12]; 1164 cv_ptr->signature.data4[5] = identifier[13]; 1165 cv_ptr->signature.data4[6] = identifier[14]; 1166 cv_ptr->signature.data4[7] = identifier[15]; 1167 } 1168 1169 return true; 1170} 1171 1172bool MinidumpGenerator::WriteModuleListStream( 1173 MDRawDirectory *module_list_stream) { 1174 TypedMDRVA<MDRawModuleList> list(&writer_); 1175 1176 int image_count = dynamic_images_ ? 1177 dynamic_images_->GetImageCount() : _dyld_image_count(); 1178 1179 if (!list.AllocateObjectAndArray(image_count, MD_MODULE_SIZE)) 1180 return false; 1181 1182 module_list_stream->stream_type = MD_MODULE_LIST_STREAM; 1183 module_list_stream->location = list.location(); 1184 list.get()->number_of_modules = image_count; 1185 1186 // Write out the executable module as the first one 1187 MDRawModule module; 1188 int executableIndex = FindExecutableModule(); 1189 1190 if (!WriteModuleStream(executableIndex, &module)) { 1191 return false; 1192 } 1193 1194 list.CopyIndexAfterObject(0, &module, MD_MODULE_SIZE); 1195 int destinationIndex = 1; // Write all other modules after this one 1196 1197 for (int i = 0; i < image_count; ++i) { 1198 if (i != executableIndex) { 1199 if (!WriteModuleStream(i, &module)) { 1200 return false; 1201 } 1202 1203 list.CopyIndexAfterObject(destinationIndex++, &module, MD_MODULE_SIZE); 1204 } 1205 } 1206 1207 return true; 1208} 1209 1210bool MinidumpGenerator::WriteMiscInfoStream(MDRawDirectory *misc_info_stream) { 1211 TypedMDRVA<MDRawMiscInfo> info(&writer_); 1212 1213 if (!info.Allocate()) 1214 return false; 1215 1216 misc_info_stream->stream_type = MD_MISC_INFO_STREAM; 1217 misc_info_stream->location = info.location(); 1218 1219 MDRawMiscInfo *info_ptr = info.get(); 1220 info_ptr->size_of_info = static_cast<u_int32_t>(sizeof(MDRawMiscInfo)); 1221 info_ptr->flags1 = MD_MISCINFO_FLAGS1_PROCESS_ID | 1222 MD_MISCINFO_FLAGS1_PROCESS_TIMES | 1223 MD_MISCINFO_FLAGS1_PROCESSOR_POWER_INFO; 1224 1225 // Process ID 1226 info_ptr->process_id = getpid(); 1227 1228 // Times 1229 struct rusage usage; 1230 if (getrusage(RUSAGE_SELF, &usage) != -1) { 1231 // Omit the fractional time since the MDRawMiscInfo only wants seconds 1232 info_ptr->process_user_time = 1233 static_cast<u_int32_t>(usage.ru_utime.tv_sec); 1234 info_ptr->process_kernel_time = 1235 static_cast<u_int32_t>(usage.ru_stime.tv_sec); 1236 } 1237 int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, info_ptr->process_id }; 1238 u_int mibsize = static_cast<u_int>(sizeof(mib) / sizeof(mib[0])); 1239 size_t size; 1240 if (!sysctl(mib, mibsize, NULL, &size, NULL, 0)) { 1241 mach_vm_address_t addr; 1242 if (mach_vm_allocate(mach_task_self(), 1243 &addr, 1244 size, 1245 true) == KERN_SUCCESS) { 1246 struct kinfo_proc *proc = (struct kinfo_proc *)addr; 1247 if (!sysctl(mib, mibsize, proc, &size, NULL, 0)) 1248 info_ptr->process_create_time = 1249 static_cast<u_int32_t>(proc->kp_proc.p_starttime.tv_sec); 1250 mach_vm_deallocate(mach_task_self(), addr, size); 1251 } 1252 } 1253 1254 // Speed 1255 uint64_t speed; 1256 const uint64_t kOneMillion = 1000 * 1000; 1257 size = sizeof(speed); 1258 sysctlbyname("hw.cpufrequency_max", &speed, &size, NULL, 0); 1259 info_ptr->processor_max_mhz = static_cast<u_int32_t>(speed / kOneMillion); 1260 info_ptr->processor_mhz_limit = static_cast<u_int32_t>(speed / kOneMillion); 1261 size = sizeof(speed); 1262 sysctlbyname("hw.cpufrequency", &speed, &size, NULL, 0); 1263 info_ptr->processor_current_mhz = static_cast<u_int32_t>(speed / kOneMillion); 1264 1265 return true; 1266} 1267 1268bool MinidumpGenerator::WriteBreakpadInfoStream( 1269 MDRawDirectory *breakpad_info_stream) { 1270 TypedMDRVA<MDRawBreakpadInfo> info(&writer_); 1271 1272 if (!info.Allocate()) 1273 return false; 1274 1275 breakpad_info_stream->stream_type = MD_BREAKPAD_INFO_STREAM; 1276 breakpad_info_stream->location = info.location(); 1277 MDRawBreakpadInfo *info_ptr = info.get(); 1278 1279 if (exception_thread_ && exception_type_) { 1280 info_ptr->validity = MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID | 1281 MD_BREAKPAD_INFO_VALID_REQUESTING_THREAD_ID; 1282 info_ptr->dump_thread_id = handler_thread_; 1283 info_ptr->requesting_thread_id = exception_thread_; 1284 } else { 1285 info_ptr->validity = MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID; 1286 info_ptr->dump_thread_id = handler_thread_; 1287 info_ptr->requesting_thread_id = 0; 1288 } 1289 1290 return true; 1291} 1292 1293} // namespace google_breakpad 1294