-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
870 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,241 @@ | ||
/*BEGIN_LEGAL | ||
Intel Open Source License | ||
Copyright (c) 2002-2018 Intel Corporation. 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 | ||
the Intel Corporation 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 INTEL OR | ||
ITS 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. | ||
END_LEGAL */ | ||
|
||
#if !defined(CALL_STACK_H_) | ||
#define CALL_STACK_H_ | ||
|
||
#include "pin.H" | ||
#include <list> | ||
#include <map> | ||
#include <set> | ||
#include <string> | ||
#include <vector> | ||
extern "C" { | ||
#include "xed-interface.h" | ||
} | ||
|
||
namespace CALLSTACK { | ||
|
||
// struct that holds the instruction pointer address and the corresponding name | ||
// of the image | ||
typedef struct { | ||
std::string name; | ||
ADDRINT ipaddr; | ||
} ipobj_t; | ||
|
||
typedef std::vector<ipobj_t> IPVEC; | ||
|
||
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, std::vector<std::string> &out, IPVEC &ipvec); | ||
|
||
// 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(std::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 std::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; | ||
std::string _function_name; | ||
std::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 std::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 std::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; | ||
|
||
std::vector<CallStackHandlerParams> _enter_func_handlers; | ||
std::vector<CallStackHandlerParams> _exit_func_handlers; | ||
|
||
// map of ip to a vector of handlers | ||
typedef std::vector<CallStackHandlerParams *> CallStackHandlerVec; | ||
typedef std::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 | ||
std::set<ADDRINT> _marked_ip_for_exit; | ||
}; | ||
} // namespace CALLSTACK | ||
#endif |
Oops, something went wrong.