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.

178 lines
4.6 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.
*/
#include <iostream>
#include <vector>
#include "pin.H"
#include "CallStack.H"
///////////////////////////////////////////////////////////////////////////////
////////// class Activation
///////////////////////////////////////////////////////////////////////////////
VOID
CallStack::CreateActivation(ADDRINT current_sp, ADDRINT target)
{
// push activation -- note this is sp at the callsite
_activations.push_back(Activation(_activations.size(), current_sp, target));
}
//
// roll back stack if we got here from a longjmp
// Note stack grows down and register stack grows up.
//
VOID
CallStack::AdjustStack(ADDRINT current_sp)
{
_stackGeneration += 1;
if( _activations.size() == 0 ) return;
// TIPP: I changed this from > to >= ...not sure it's right, but works better
while( current_sp >= _activations.back().current_sp() ) {
// debug having hit the assertion below...
if (_activations.size() == 1) {
cerr << "AdjustStack(" << current_sp << ") bottomed out" << endl;
cerr << " last activation at " << _activations.back().current_sp()
<< endl;
_activations.pop_back(); // pop activation
return;
}
_activations.pop_back(); // pop activation
ASSERTX(_activations.size() > 0);
}
}
///////////////////////////////////////////////////////////////////////////////
////////// class CallStack
///////////////////////////////////////////////////////////////////////////////
static bool
isOpaqueLib(const string& lib) {
return 0 && (lib == "/lib/tls/libc.so.6"
|| lib == "/lib/ld-linux.so.2");
}
static bool
isOpaqueRtn(const string& rtn) {
return 0 && (rtn == "malloc@@GLIBC_2.0"
|| rtn.find("GLIBC") != string::npos);
}
//
// standard call
VOID
CallStack::ProcessCall(ADDRINT current_sp, ADDRINT target)
{
// check if we got here from a longjmp.
AdjustStack(current_sp);
if( _activations.size() >= _main_entry_depth
&& (_enter_opaque_lib_entry == 0
|| _activations.size() <= _enter_opaque_lib_entry) ) {
//cout << _activations.size() << ":" << _Target2RtnName(target)
//<< "@0x" << hex << target << dec
//<< " in " << _Target2LibName(target)
// << endl;
}
if(_activations.size() >= _main_entry_depth
&& !_enter_opaque_lib_entry
&& (isOpaqueLib(_Target2LibName(target))
|| isOpaqueRtn(_Target2RtnName(target))) ) {
_enter_opaque_lib_entry = _activations.size();
}
CreateActivation(current_sp, target);
}
//
// standard call
VOID
CallStack::ProcessMainEntry(ADDRINT current_sp, ADDRINT target)
{
// check if we got here from a longjmp.
AdjustStack(current_sp);
//cout << _activations.size() << ":" << _Target2RtnName(target)
//<< " in " << _Target2LibName(target)
//<< endl;
_main_entry_depth = _activations.size();
CreateActivation(current_sp, target);
}
//
// standard return
VOID
CallStack::ProcessReturn(ADDRINT current_sp, bool prevIpDoesPush)
{
#if defined(TARGET_IA32) && defined (TARGET_WINDOWS)
if (prevIpDoesPush)
{
// on ia-32 windows to identify
// push
// ret
// and ignore it, in order to process callstack correctly
return;
}
#endif
// check if we got here from a longjmp.
AdjustStack(current_sp);
if( _enter_opaque_lib_entry == _activations.size() ) {
_enter_opaque_lib_entry = 0;
}
#if defined(TARGET_IA32) && defined (TARGET_WINDOWS)
if(_activations.size() == 0)
{
return;
}
#else
ASSERTX(_activations.size());
#endif
// pop activation
_activations.pop_back();
}
VOID
CallStack::DumpStack(ostream *o)
{
vector<Activation>::reverse_iterator i;
int level = _activations.size() - 1;
string last;
bool repeated = false;
bool first = true;
for(i = _activations.rbegin(); i != _activations.rend(); i++) {
string cur = _Target2RtnName(i->target());
if( cur != last ) {
if( !first ) {*o << endl;}
*o << level << ": " << cur;
} else {
if( !repeated ) {
*o << "(repeated)";
}
repeated = true;
}
first = false;
last = cur;
level--;
}
*o << endl;
//cout << _activations.size() << ":" << _Target2RtnName(target)
//<< "@0x" << hex << target << dec
//<< " in " << _Target2LibName(target)
// << endl;
}