/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


#ifndef ART_RUNTIME_FAULT_HANDLER_H_
#define ART_RUNTIME_FAULT_HANDLER_H_

#include <setjmp.h>
#include <signal.h>
#include <stdint.h>

#include <vector>

#include "base/mutex.h"  // For annotalysis.

namespace art {

class ArtMethod;
class FaultHandler;

class FaultManager {
 public:
  FaultManager();
  ~FaultManager();

  void Init();

  // Unclaim signals.
  void Release();

  // Unclaim signals and delete registered handlers.
  void Shutdown();

  // Try to handle a fault, returns true if successful.
  bool HandleFault(int sig, siginfo_t* info, void* context);

  // Added handlers are owned by the fault handler and will be freed on Shutdown().
  void AddHandler(FaultHandler* handler, bool generated_code);
  void RemoveHandler(FaultHandler* handler);

  // Note that the following two functions are called in the context of a signal handler.
  // The IsInGeneratedCode() function checks that the mutator lock is held before it
  // calls GetMethodAndReturnPCAndSP().
  // TODO: think about adding lock assertions and fake lock and unlock functions.
  void GetMethodAndReturnPcAndSp(siginfo_t* siginfo, void* context, ArtMethod** out_method,
                                 uintptr_t* out_return_pc, uintptr_t* out_sp)
                                 NO_THREAD_SAFETY_ANALYSIS;
  bool IsInGeneratedCode(siginfo_t* siginfo, void *context, bool check_dex_pc)
                         NO_THREAD_SAFETY_ANALYSIS;

 private:
  // The HandleFaultByOtherHandlers function is only called by HandleFault function for generated code.
  bool HandleFaultByOtherHandlers(int sig, siginfo_t* info, void* context)
                                  NO_THREAD_SAFETY_ANALYSIS;

  std::vector<FaultHandler*> generated_code_handlers_;
  std::vector<FaultHandler*> other_handlers_;
  struct sigaction oldaction_;
  bool initialized_;
  DISALLOW_COPY_AND_ASSIGN(FaultManager);
};

class FaultHandler {
 public:
  explicit FaultHandler(FaultManager* manager);
  virtual ~FaultHandler() {}
  FaultManager* GetFaultManager() {
    return manager_;
  }

  virtual bool Action(int sig, siginfo_t* siginfo, void* context) = 0;

 protected:
  FaultManager* const manager_;

 private:
  DISALLOW_COPY_AND_ASSIGN(FaultHandler);
};

class NullPointerHandler FINAL : public FaultHandler {
 public:
  explicit NullPointerHandler(FaultManager* manager);

  bool Action(int sig, siginfo_t* siginfo, void* context) OVERRIDE;

  static bool IsValidImplicitCheck(siginfo_t* siginfo) {
    // Our implicit NPE checks always limit the range to a page.
    // Note that the runtime will do more exhaustive checks (that we cannot
    // reasonably do in signal processing code) based on the dex instruction
    // faulting.
    return CanDoImplicitNullCheckOn(reinterpret_cast<uintptr_t>(siginfo->si_addr));
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(NullPointerHandler);
};

class SuspensionHandler FINAL : public FaultHandler {
 public:
  explicit SuspensionHandler(FaultManager* manager);

  bool Action(int sig, siginfo_t* siginfo, void* context) OVERRIDE;

 private:
  DISALLOW_COPY_AND_ASSIGN(SuspensionHandler);
};

class StackOverflowHandler FINAL : public FaultHandler {
 public:
  explicit StackOverflowHandler(FaultManager* manager);

  bool Action(int sig, siginfo_t* siginfo, void* context) OVERRIDE;

 private:
  DISALLOW_COPY_AND_ASSIGN(StackOverflowHandler);
};

class JavaStackTraceHandler FINAL : public FaultHandler {
 public:
  explicit JavaStackTraceHandler(FaultManager* manager);

  bool Action(int sig, siginfo_t* siginfo, void* context) OVERRIDE NO_THREAD_SAFETY_ANALYSIS;

 private:
  DISALLOW_COPY_AND_ASSIGN(JavaStackTraceHandler);
};

// Statically allocated so the the signal handler can Get access to it.
extern FaultManager fault_manager;

}       // namespace art
#endif  // ART_RUNTIME_FAULT_HANDLER_H_

