// Copyright (c) 2012, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "client/ios/handler/ios_exception_minidump_generator.h"

#include <pthread.h>

#include "google_breakpad/common/minidump_cpu_arm.h"
#include "google_breakpad/common/minidump_cpu_arm64.h"
#include "google_breakpad/common/minidump_exception_mac.h"
#include "client/minidump_file_writer-inl.h"
#include "common/scoped_ptr.h"

#if defined(HAS_ARM_SUPPORT) && defined(HAS_ARM64_SUPPORT)
#error "This file should be compiled for only one architecture at a time"
#endif

namespace {

const int kExceptionType = EXC_SOFTWARE;
const int kExceptionCode = MD_EXCEPTION_CODE_MAC_NS_EXCEPTION;

#if defined(HAS_ARM_SUPPORT) || defined(HAS_ARM64_SUPPORT)
const uintptr_t kExpectedFinalFp = sizeof(uintptr_t);
const uintptr_t kExpectedFinalSp = 0;

// Append the given value to the sp position of the stack represented
// by memory.
void AppendToMemory(uint8_t *memory, uintptr_t sp, uintptr_t data) {
  memcpy(memory + sp, &data, sizeof(data));
}
#endif

}  // namespace

namespace google_breakpad {

IosExceptionMinidumpGenerator::IosExceptionMinidumpGenerator(
    NSException *exception)
    : MinidumpGenerator(mach_task_self(), 0) {
  return_addresses_ = [[exception callStackReturnAddresses] retain];
  SetExceptionInformation(kExceptionType,
                          kExceptionCode,
                          0,
                          pthread_mach_thread_np(pthread_self()));
}

IosExceptionMinidumpGenerator::~IosExceptionMinidumpGenerator() {
  [return_addresses_ release];
}

bool IosExceptionMinidumpGenerator::WriteCrashingContext(
    MDLocationDescriptor *register_location) {
#ifdef HAS_ARM_SUPPORT
  return WriteCrashingContextARM(register_location);
#elif defined(HAS_ARM64_SUPPORT)
  return WriteCrashingContextARM64(register_location);
#else
  assert(false);
  return false;
#endif
}

#ifdef HAS_ARM_SUPPORT
bool IosExceptionMinidumpGenerator::WriteCrashingContextARM(
    MDLocationDescriptor *register_location) {
  TypedMDRVA<MDRawContextARM> context(&writer_);
  if (!context.Allocate())
    return false;
  *register_location = context.location();
  MDRawContextARM *context_ptr = context.get();
  memset(context_ptr, 0, sizeof(MDRawContextARM));
  context_ptr->context_flags = MD_CONTEXT_ARM_FULL;
  context_ptr->iregs[MD_CONTEXT_ARM_REG_IOS_FP] = kExpectedFinalFp;  // FP
  context_ptr->iregs[MD_CONTEXT_ARM_REG_SP] = kExpectedFinalSp;      // SP
  context_ptr->iregs[MD_CONTEXT_ARM_REG_LR] = GetLRFromException();  // LR
  context_ptr->iregs[MD_CONTEXT_ARM_REG_PC] = GetPCFromException();  // PC
  return true;
}
#endif

#ifdef HAS_ARM64_SUPPORT
bool IosExceptionMinidumpGenerator::WriteCrashingContextARM64(
    MDLocationDescriptor *register_location) {
  TypedMDRVA<MDRawContextARM64> context(&writer_);
  if (!context.Allocate())
    return false;
  *register_location = context.location();
  MDRawContextARM64 *context_ptr = context.get();
  memset(context_ptr, 0, sizeof(*context_ptr));
  context_ptr->context_flags = MD_CONTEXT_ARM64_FULL;
  context_ptr->iregs[MD_CONTEXT_ARM64_REG_FP] = kExpectedFinalFp;      // FP
  context_ptr->iregs[MD_CONTEXT_ARM64_REG_SP] = kExpectedFinalSp;      // SP
  context_ptr->iregs[MD_CONTEXT_ARM64_REG_LR] = GetLRFromException();  // LR
  context_ptr->iregs[MD_CONTEXT_ARM64_REG_PC] = GetPCFromException();  // PC
  return true;
}
#endif

uintptr_t IosExceptionMinidumpGenerator::GetPCFromException() {
  return [[return_addresses_ objectAtIndex:0] unsignedIntegerValue];
}

uintptr_t IosExceptionMinidumpGenerator::GetLRFromException() {
  return [[return_addresses_ objectAtIndex:1] unsignedIntegerValue];
}

bool IosExceptionMinidumpGenerator::WriteExceptionStream(
    MDRawDirectory *exception_stream) {
#if defined(HAS_ARM_SUPPORT) || defined(HAS_ARM64_SUPPORT)
  TypedMDRVA<MDRawExceptionStream> exception(&writer_);

  if (!exception.Allocate())
    return false;

  exception_stream->stream_type = MD_EXCEPTION_STREAM;
  exception_stream->location = exception.location();
  MDRawExceptionStream *exception_ptr = exception.get();
  exception_ptr->thread_id = pthread_mach_thread_np(pthread_self());

  // This naming is confusing, but it is the proper translation from
  // mach naming to minidump naming.
  exception_ptr->exception_record.exception_code = kExceptionType;
  exception_ptr->exception_record.exception_flags = kExceptionCode;

  if (!WriteCrashingContext(&exception_ptr->thread_context))
    return false;

  exception_ptr->exception_record.exception_address = GetPCFromException();
  return true;
#else
  return MinidumpGenerator::WriteExceptionStream(exception_stream);
#endif
}

bool IosExceptionMinidumpGenerator::WriteThreadStream(mach_port_t thread_id,
                                                      MDRawThread *thread) {
#if defined(HAS_ARM_SUPPORT) || defined(HAS_ARM64_SUPPORT)
  if (pthread_mach_thread_np(pthread_self()) != thread_id)
    return MinidumpGenerator::WriteThreadStream(thread_id, thread);

  size_t frame_count = [return_addresses_ count];
  if (frame_count == 0)
    return false;
  UntypedMDRVA memory(&writer_);
  size_t pointer_size = sizeof(uintptr_t);
  size_t frame_record_size = 2 * pointer_size;
  size_t stack_size = frame_record_size * (frame_count - 1) + pointer_size;
  if (!memory.Allocate(stack_size))
    return false;
  scoped_array<uint8_t> stack_memory(new uint8_t[stack_size]);
  uintptr_t sp = stack_size - pointer_size;
  uintptr_t fp = 0;
  uintptr_t lr = 0;
  for (size_t current_frame = frame_count - 1;
       current_frame > 0;
       --current_frame) {
    AppendToMemory(stack_memory.get(), sp, lr);
    sp -= pointer_size;
    AppendToMemory(stack_memory.get(), sp, fp);
    fp = sp;
    sp -= pointer_size;
    lr = [[return_addresses_ objectAtIndex:current_frame] unsignedIntegerValue];
  }
  if (!memory.Copy(stack_memory.get(), stack_size))
    return false;
  assert(sp == kExpectedFinalSp);
  assert(fp == kExpectedFinalFp);
  assert(lr == GetLRFromException());
  thread->stack.start_of_memory_range = sp;
  thread->stack.memory = memory.location();
  memory_blocks_.push_back(thread->stack);

  if (!WriteCrashingContext(&thread->thread_context))
    return false;

  thread->thread_id = thread_id;
  return true;
#else
  return MinidumpGenerator::WriteThreadStream(thread_id, thread);
#endif
}

}  // namespace google_breakpad
