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