Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  fault_handler.h

  Sprache: C
 

/*
 * 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 <signal.h>
#include <stdint.h>

#include <atomic>
#include <vector>

#include "base/locks.h"  // For annotalysis.
#include "base/macros.h"
#include "base/mutex.h"
#include "runtime_globals.h"  // For CanDoImplicitNullCheckOn.

namespace art HIDDEN {

class ArtMethod;
class FaultHandler;

namespace gc {
namespace collector {
class MarkCompact;
}  // namespace collector
}  // namespace gc

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

  // Use libsigchain if use_sig_chain is true. Otherwise, setup SIGBUS directly
  // using sigaction().
  void Init(bool use_sig_chain);

  // Unclaim signals.
  void Release();

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

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

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

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

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

  void AddGeneratedCodeRange(const void* start, size_t size);
  void RemoveGeneratedCodeRange(const void* start, size_t size)
      REQUIRES_SHARED(Locks::mutator_lock_);

  // Retrieves fault PC from architecture-dependent `context`, returns 0 on failure.
  // Called in the context of a signal handler.
  static uintptr_t GetFaultPc(siginfo_t* siginfo, void* context);

  // Retrieves SP from architecture-dependent `context`.
  // Called in the context of a signal handler.
  static uintptr_t GetFaultSp(void* context);

  // Checks if the fault happened while running generated code.
  // Called in the context of a signal handler.
  bool IsInGeneratedCode(siginfo_t* siginfo, void *context) NO_THREAD_SAFETY_ANALYSIS;

#ifdef __aarch64__
  // Update context to cause pending thread suspension request to be recognized
  // more quickly upon return from signal handler, if that is possible.
  void SuspendFaster(siginfo_t* info, void* context);
#else
  void SuspendFaster(siginfo_t*, void*) {}
#endif

 private:
  struct GeneratedCodeRange {
    std::atomic<GeneratedCodeRange*> next;
    const void* start;
    size_t size;
  };

  GeneratedCodeRange* CreateGeneratedCodeRange(const void* start, size_t size)
      REQUIRES(generated_code_ranges_lock_);
  void FreeGeneratedCodeRange(GeneratedCodeRange* range) REQUIRES(!generated_code_ranges_lock_);

  // 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;

  // Check if this is an implicit suspend check that was somehow not recognized as being
  // in the compiled code. If that's the case, collect debugging data for the abort message
  // and crash. Focus on suspend checks in the boot image. Bug: 294339122
  // NO_THREAD_SAFETY_ANALYSIS: Same as `IsInGeneratedCode()`.
  void CheckForUnrecognizedImplicitSuspendCheckInBootImage(siginfo_t* siginfo, void* context)
      NO_THREAD_SAFETY_ANALYSIS;

  // Note: The lock guards modifications of the ranges but the function `IsInGeneratedCode()`
  // walks the list in the context of a signal handler without holding the lock.
  Mutex generated_code_ranges_lock_;
  std::atomic<GeneratedCodeRange*> generated_code_ranges_ GUARDED_BY(generated_code_ranges_lock_);

  std::vector<FaultHandler*> generated_code_handlers_;
  std::vector<FaultHandler*> other_handlers_;
  gc::collector::MarkCompact* mark_compact_;
  bool initialized_;

  // We keep a certain number of generated code ranges locally to avoid too many
  // cache misses while traversing the singly-linked list `generated_code_ranges_`.
  // 16 should be enough for the boot image (assuming `--multi-image`; there is
  // only one entry for `--single-image`), nterp, JIT code cache and a few other
  // entries for the app or system server.
  static constexpr size_t kNumLocalGeneratedCodeRanges = 16;
  GeneratedCodeRange generated_code_ranges_storage_[kNumLocalGeneratedCodeRanges];
  GeneratedCodeRange* free_generated_code_ranges_
       GUARDED_BY(generated_code_ranges_lock_);

  DISALLOW_COPY_AND_ASSIGN(FaultManager);
};

class FaultHandler {
 public:
  EXPORT FaultHandler() {}
  virtual ~FaultHandler() {}

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

 private:
  DISALLOW_COPY_AND_ASSIGN(FaultHandler);
};

//
// Null pointer fault handler
//
class NullPointerHandler final : public FaultHandler {
 public:
  NullPointerHandler() {}

  // NO_THREAD_SAFETY_ANALYSIS: Called after the fault manager determined that
  // the thread is `Runnable` and holds the mutator lock (shared) but without
  // telling annotalysis that we actually hold the lock.
  bool Action(int sig, siginfo_t* siginfo, void* context) override
      NO_THREAD_SAFETY_ANALYSIS;
  constexpr static bool IsGeneratedCodeHandler() { return true; }

  // Helper functions for checking whether the signal can be interpreted
  // as implicit NPE check. Note that the runtime will do more exhaustive
  // checks (that we cannot reasonably do in signal processing code) based
  // on the dex instruction faulting.

  static bool IsValidFaultAddress(uintptr_t fault_address) {
    // Our implicit NPE checks always limit the range to a page.
    return CanDoImplicitNullCheckOn(fault_address);
  }

  static bool IsValidMethod(ArtMethod* method)
      REQUIRES_SHARED(Locks::mutator_lock_);

  static bool IsValidReturnPc(ArtMethod** sp, uintptr_t return_pc)
      REQUIRES_SHARED(Locks::mutator_lock_);

 private:
  DISALLOW_COPY_AND_ASSIGN(NullPointerHandler);
};

//
// Suspension fault handler
//
class SuspensionHandler final : public FaultHandler {
 public:
  SuspensionHandler() {}
  bool Action(int sig, siginfo_t* siginfo, void* context) override;
  constexpr static bool IsGeneratedCodeHandler() { return true; }

 private:
  DISALLOW_COPY_AND_ASSIGN(SuspensionHandler);
};

//
// Stack overflow fault handler
//
class StackOverflowHandler final : public FaultHandler {
 public:
  StackOverflowHandler() {}
  bool Action(int sig, siginfo_t* siginfo, void* context) override;
  constexpr static bool IsGeneratedCodeHandler() { return true; }

 private:
  DISALLOW_COPY_AND_ASSIGN(StackOverflowHandler);
};

//
// Stack trace handler, used to help get a stack trace from SIGSEGV inside of compiled code.
//
class JavaStackTraceHandler final : public FaultHandler {
 public:
  explicit JavaStackTraceHandler(FaultManager* manager) : manager_(manager) {}

  bool Action(int sig, siginfo_t* siginfo, void* context) override NO_THREAD_SAFETY_ANALYSIS;
  constexpr static bool IsGeneratedCodeHandler() { return false; }

 private:
  FaultManager* manager_;

  DISALLOW_COPY_AND_ASSIGN(JavaStackTraceHandler);
};

#ifdef ART_USE_SIMULATOR
// Simulated implicit checks will need to be handled specially because they do not originate from
// native compiled code and will need to modify the simulated context before specially returning
// execution to the simulator, such that it can continue simulating the quick entrypoint code
// required for that specific fault.

class NullPointerHandlerSimulator final : public FaultHandler {
 public:
  NullPointerHandlerSimulator() {}

  bool Action(int sig, siginfo_t* siginfo, void* context) override;
  constexpr static bool IsGeneratedCodeHandler() { return true; }

 private:
  DISALLOW_COPY_AND_ASSIGN(NullPointerHandlerSimulator);
};
#endif  // ART_USE_SIMULATOR

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

}  // namespace art
#endif  // ART_RUNTIME_FAULT_HANDLER_H_


Messung V0.5 in Prozent
C=90 H=95 G=92

¤ Dauer der Verarbeitung: 0.11 Sekunden  (vorverarbeitet am  2026-06-29) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik