You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
215 lines
6.7 KiB
215 lines
6.7 KiB
/*
|
|
* Copyright 2002-2019 Intel Corporation.
|
|
*
|
|
* This software is provided to you as Sample Source Code as defined in the accompanying
|
|
* End User License Agreement for the Intel(R) Software Development Products ("Agreement")
|
|
* section 1.L.
|
|
*
|
|
* This software and the related documents are provided as is, with no express or implied
|
|
* warranties, other than those that are expressly stated in the License.
|
|
*/
|
|
|
|
|
|
#if !defined(_EMX_CALL_STACK_H_)
|
|
#define _EMX_CALL_STACK_H_
|
|
|
|
#include <string>
|
|
#include <vector>
|
|
#include <map>
|
|
#include <set>
|
|
#include <list>
|
|
#include "pin.H"
|
|
using std::vector;
|
|
using std::list;
|
|
using std::string;
|
|
using std::map;
|
|
using std::set;
|
|
|
|
|
|
extern "C"{
|
|
#include "xed-interface.h"
|
|
}
|
|
|
|
namespace CALLSTACK{
|
|
class CallEntry {
|
|
private:
|
|
ADDRINT _current_sp;
|
|
ADDRINT _target;
|
|
|
|
public:
|
|
CallEntry(): _current_sp(0),_target(0) { }
|
|
CallEntry(ADDRINT current_sp, ADDRINT target):
|
|
_current_sp(current_sp),
|
|
_target(target)
|
|
{ }
|
|
|
|
bool operator==( const CallEntry& a) const {
|
|
return(_current_sp == a._current_sp);
|
|
}
|
|
ADDRINT sp() const {return _current_sp;}
|
|
ADDRINT target() const {return _target;}
|
|
};
|
|
|
|
|
|
class CallStack {
|
|
public:
|
|
// print the call stack, emit only 'depth' entries
|
|
void emit_stack(UINT32 depth, vector<string>& out);
|
|
|
|
// return the depth of the call stack
|
|
UINT32 depth();
|
|
|
|
// add the current_sp and the target to the top of the call stack
|
|
void push_head(ADDRINT current_sp, ADDRINT target);
|
|
|
|
// return the ip target of the latest call
|
|
ADDRINT top_target();
|
|
|
|
// return the ip target of call per depth
|
|
ADDRINT depth_target(UINT32 depth);
|
|
|
|
// capture the info for each ip in the call stack
|
|
// see CallStackInfo
|
|
void save_all_ips_info();
|
|
|
|
void process_call(ADDRINT current_sp, ADDRINT target);
|
|
void process_return(ADDRINT current_sp, ADDRINT ip);
|
|
|
|
// print the call stack, emit only 'depth' entries
|
|
void get_targets(list<ADDRINT>& out);
|
|
|
|
private:
|
|
typedef std::vector<CallEntry> CallVec;
|
|
CallVec _call_vec;
|
|
|
|
void create_entry(ADDRINT current_sp, ADDRINT target);
|
|
void adjust_stack( ADDRINT current_sp);
|
|
};
|
|
|
|
typedef void (*CALL_STACK_HANDLER)(CONTEXT* ctxt, ADDRINT ip, THREADID tid, VOID *v);
|
|
class CallStackHandlerParams{
|
|
public:
|
|
CallStackHandlerParams(CALL_STACK_HANDLER h, const string& func_name, void* v,
|
|
ADDRINT func_ip = 0, BOOL name_handler = TRUE){
|
|
_handler = h;
|
|
_function_name = func_name;
|
|
_name_handler = name_handler;
|
|
_args = v;
|
|
_first_ip = 0;
|
|
}
|
|
|
|
CALL_STACK_HANDLER _handler;
|
|
string _function_name;
|
|
string _function_ip;
|
|
BOOL _name_handler;
|
|
void* _args;
|
|
ADDRINT _first_ip; //the first ip of the function, used for recursive function call
|
|
};
|
|
|
|
|
|
// this struct holds the informations need for emitting the call stack
|
|
// we hold a map of ip->CallStackInfo so we will no
|
|
// generate info for the same ip more than once
|
|
typedef struct CallStackInfoStruct {
|
|
char * func_name;
|
|
char * image_name;
|
|
char * file_name;
|
|
UINT32 rtn_id;
|
|
INT32 line;
|
|
INT32 column;
|
|
CallStackInfoStruct() : func_name(0), image_name(0), file_name(0), rtn_id(0), line(0), column(0) {}
|
|
} CallStackInfo;
|
|
|
|
|
|
// a singleton class
|
|
class CallStackManager{
|
|
public:
|
|
// return a pointer to an instance of the class
|
|
static CallStackManager* get_instance();
|
|
|
|
// return a copied CallStack of thread tid
|
|
CallStack get_stack(THREADID tid);
|
|
|
|
// activate the CallStackManager
|
|
void activate();
|
|
|
|
// fill in info with the information about the ip, see CallStackInfo
|
|
// if the the info does not exists we generated it first
|
|
void get_ip_info(ADDRINT ip, CallStackInfo& info);
|
|
|
|
//register a callback the will be called when entering to function: func_name
|
|
void on_function_enter(CALL_STACK_HANDLER handler, const string& func_name, void* v, BOOL use_ctxt);
|
|
|
|
//register a callback the will be called when returning from function: func_name
|
|
void on_function_exit(CALL_STACK_HANDLER handler, const string& func_name, void* v, BOOL use_ctxt);
|
|
|
|
// Register a callback that will be called when entering function: function_ip
|
|
// The parameters are: function handler
|
|
// function ip address
|
|
// parameter to the function
|
|
// flag if the function uses PIN context
|
|
void on_function_ip_enter(CALL_STACK_HANDLER handler, ADDRINT func_ip, void* v, BOOL use_ctxt);
|
|
|
|
// Register a callback that will be called when exiting function: function_ip
|
|
// The parameters are: function handler
|
|
// function ip address
|
|
// parameter to the function
|
|
// flag if the function uses PIN context
|
|
void on_function_ip_exit(CALL_STACK_HANDLER handler, ADDRINT func_ip, void* v, BOOL use_ctxt);
|
|
|
|
//// internal use ////
|
|
void on_call(THREADID tid, CONTEXT* ctxt, ADDRINT ip);
|
|
void on_ret_fire(THREADID tid, CONTEXT* ctxt, ADDRINT ip);
|
|
BOOL on_ret_should_fire(THREADID tid);
|
|
BOOL NeedContext();
|
|
BOOL TargetInteresting(ADDRINT ip);
|
|
|
|
private:
|
|
CallStackManager(): _activated(false),_use_ctxt(false),
|
|
_depth_func_handlers_tid_vec(PIN_MAX_THREADS){
|
|
PIN_InitLock(&_lock);
|
|
}
|
|
static void thread_begin(THREADID tid, CONTEXT* ctxt,
|
|
INT32 flags, void* v);
|
|
void add_stack(THREADID tid, CallStack* call_stack);
|
|
static void Img(IMG img, void* v);
|
|
|
|
static CallStackManager* _instance;
|
|
bool _activated;
|
|
//a map to threadid -> CallStack*
|
|
typedef std::map<THREADID, CallStack*> CallStackMap;
|
|
CallStackMap _call_stack_map;
|
|
PIN_LOCK _map_lock;
|
|
|
|
//map of ip to its info(file, func, line, ...)
|
|
//used to prevent collecting info about the same ip multiple times
|
|
typedef std::map<ADDRINT, CallStackInfo> CallStackInfoMap;
|
|
CallStackInfoMap _call_stack_info;
|
|
PIN_LOCK _lock;
|
|
BOOL _use_ctxt;
|
|
|
|
vector<CallStackHandlerParams> _enter_func_handlers;
|
|
vector<CallStackHandlerParams> _exit_func_handlers;
|
|
|
|
//map of ip to a vector of handlers
|
|
typedef vector<CallStackHandlerParams*> CallStackHandlerVec;
|
|
typedef map<ADDRINT, CallStackHandlerVec> IpFuncHnadlersMap;
|
|
IpFuncHnadlersMap _enter_func_handlers_map;
|
|
|
|
//map of ip to a vector of handlers
|
|
IpFuncHnadlersMap _exit_func_handlers_map;
|
|
|
|
//map of stack depth to a vector of handlers
|
|
typedef std::map<UINT32, CallStackHandlerVec> DepthFuncHandlersMap;
|
|
typedef std::vector<DepthFuncHandlersMap> DepthFuncHandlersTidVec;
|
|
//a vector with entry per thread
|
|
DepthFuncHandlersTidVec _depth_func_handlers_tid_vec;
|
|
|
|
//holds the ips that we have marked for exit, needed for recursive calls
|
|
set<ADDRINT> _marked_ip_for_exit;
|
|
|
|
|
|
};
|
|
} //namespace
|
|
#endif
|