blob: 5203d2a0329623ccfe6379dbc989cb3303fe379b [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.
*/
/**
* @author Ilya Berezhniuk
*/
/**
* @file jvmti_break_intf.h
* @brief JVMTI native breakpoints API
*/
#if !defined(__JVMTI_BREAK_INTF_H__)
#define __JVMTI_BREAK_INTF_H__
#include "open/types.h"
#include "jni.h"
#include "lock_manager.h"
#include "environment.h"
// Callbacks are called for interfaces according to its priority
typedef enum {
PRIORITY_NCAI_STEP_BREAKPOINT = 0,
PRIORITY_SINGLE_STEP_BREAKPOINT,
PRIORITY_NCAI_BREAKPOINT,
PRIORITY_SIMPLE_BREAKPOINT,
PRIORITY_NUMBER
} jvmti_BreakPriority;
class VMBreakInterface;
class InstructionDisassembler;
struct VMBreakPoint
{
InstructionDisassembler* disasm;
VMBreakPoint* next;
NativeCodePtr addr;
jmethodID method;
jlocation location;
jbyte saved_byte;
Registers regs;
};
// Breakpoint reference
struct VMBreakPointRef
{
VMBreakPoint* bp;
POINTER_SIZE_INT data;
VMBreakPointRef* next;
};
struct VMLocalBreak
{
VMBreakPoint *bp;
VMBreakPoint *bp_next;
VMBreakInterface *intf;
VMLocalBreak* next;
unsigned priority;
VM_thread* vmthread;
VMBreakPoint *local_bp;
};
// Pointer to interface callback function
typedef bool (*BPInterfaceCallBack)(TIEnv *env, const VMBreakPoint* bp, const POINTER_SIZE_INT data);
typedef bool (*BPInterfaceProcedure) (VMBreakPoint *bp);
class VMBreakPoints
{
public:
VMBreakPoints() : m_break(NULL), m_local(NULL)
{
for(unsigned index = 0; index < PRIORITY_NUMBER; index++ ) {
m_intf[index] = NULL;
}
}
~VMBreakPoints();
// Class lock interface
void lock() {m_lock._lock();}
void unlock() {m_lock._unlock();}
// Is used for LMAutoUnlock
Lock_Manager* get_lock() {return &m_lock;}
// Returns interface for breakpoint handling
VMBreakInterface* new_intf(TIEnv *env, BPInterfaceCallBack callback,
unsigned priority, bool is_interp);
// Destroys interface and deletes all its breakpoints
void release_intf(VMBreakInterface* intf);
// Inserts breakpoint into global list and performs instrumentation
bool insert_native_breakpoint(VMBreakPoint* bp);
bool insert_interpreter_breakpoint(VMBreakPoint* bp);
// Removes breakpoint from global list and restores instrumented area
bool remove_native_breakpoint(VMBreakPoint* bp);
bool remove_interpreter_breakpoint(VMBreakPoint* bp);
// Search breakpoints operations
VMBreakPoint* find_breakpoint(jmethodID method, jlocation location);
VMBreakPoint* find_breakpoint(NativeCodePtr addr);
VMBreakPoint* find_other_breakpoint_with_same_addr(VMBreakPoint* bp);
VMBreakPoint* find_next_breakpoint(VMBreakPoint* prev, NativeCodePtr addr);
VMBreakPoint* find_next_breakpoint(VMBreakPoint* prev, jmethodID method,
jlocation location);
// Search breakpoints for given method
VMBreakPoint* find_method_breakpoint(jmethodID method);
VMBreakPoint* find_next_method_breakpoint(VMBreakPoint* prev, jmethodID method);
// Checks if given breakpoint is set by other interfaces
VMBreakPointRef* find_other_reference(VMBreakInterface* intf,
jmethodID method, jlocation location);
VMBreakPointRef* find_other_reference(VMBreakInterface* intf,
NativeCodePtr addr);
VMBreakPointRef* find_other_reference(VMBreakInterface* intf,
VMBreakPoint* bp);
// Interfaces iterator
VMBreakInterface* get_first_intf(unsigned priority) { return m_intf[priority]; }
VMBreakInterface* get_next_intf(VMBreakInterface *intf);
// Breakpoints iterator
VMBreakPoint* get_first_breakpoint() { return m_break; }
VMBreakPoint* get_next_breakpoint(VMBreakPoint* prev);
// General callback functions
void process_native_breakpoint(Registers* regs);
jbyte process_interpreter_breakpoint(jmethodID method, jlocation location);
// Find thread-local breakpoint information
VMLocalBreak* find_thread_local_break(VM_thread* vmthread);
private:
// Checks breakpoint before inserting
inline bool check_insert_breakpoint(VMBreakPoint* bp);
void insert_breakpoint(VMBreakPoint* bp);
void remove_breakpoint(VMBreakPoint* bp);
// Set/remove thread processing breakpoints interfaces
void set_thread_local_break(VMLocalBreak *local);
void remove_thread_local_break(VMLocalBreak *local);
private:
VMBreakInterface* m_intf[PRIORITY_NUMBER];
VMBreakPoint* m_break;
VMLocalBreak* m_local;
Lock_Manager m_lock;
};
class VMBreakInterface
{
friend class VMBreakPoints;
public:
int get_priority() const { return m_priority; }
// Iteration
VMBreakPointRef* get_reference() { return m_list; }
VMBreakPointRef* get_next_reference(VMBreakPointRef* ref)
{
assert(ref);
return ref->next;
}
// Basic operations
VMBreakPointRef* add_reference(jmethodID method, jlocation location, POINTER_SIZE_INT data);
// To specify address explicitly
VMBreakPointRef* add_reference(jmethodID method, jlocation location,
NativeCodePtr addr, POINTER_SIZE_INT data);
VMBreakPointRef* add_reference(NativeCodePtr addr, POINTER_SIZE_INT data);
bool remove_reference(VMBreakPointRef* ref);
void remove_all_reference()
{
while (m_list) {
remove_reference(m_list);
}
}
VMBreakPointRef* find_reference(jmethodID method, jlocation location);
VMBreakPointRef* find_reference(NativeCodePtr addr);
VMBreakPointRef* find_reference(VMBreakPoint* bp);
protected:
VMBreakInterface(TIEnv *env,
BPInterfaceCallBack callback,
unsigned priority,
bool is_interp);
~VMBreakInterface() { remove_all_reference(); }
TIEnv* get_env() { return m_env; }
private:
inline VMBreakPointRef* add_reference_internal(VMBreakPoint *bp, POINTER_SIZE_INT data);
protected:
VMBreakInterface* m_next;
private:
BPInterfaceCallBack breakpoint_event_callback;
BPInterfaceProcedure breakpoint_insert;
BPInterfaceProcedure breakpoint_remove;
VMBreakPointRef* m_list;
TIEnv *m_env;
unsigned m_priority;
Lock_Manager m_lock;
};
// Address of this function is used for stack unwinding througn breakpoint
extern "C" void __cdecl process_native_breakpoint_event(Registers* regs);
// Callback function for native breakpoint processing
bool jvmti_jit_breakpoint_handler(Registers *regs);
// Callback function for interpreter breakpoint processing
VMEXPORT jbyte
jvmti_process_interpreter_breakpoint_event(jmethodID method, jlocation location);
// Callback for JIT method compile
void jvmti_set_pending_breakpoints(Method *method);
// debug function dump compiled method
void jvmti_dump_compiled_method(Method *method);
#endif // __JVMTI_BREAK_INTF_H__