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.
279 lines
11 KiB
279 lines
11 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.
|
|
*/
|
|
|
|
#ifndef DEBUGGER_SHELL_H
|
|
#define DEBUGGER_SHELL_H
|
|
|
|
#include <string>
|
|
#include "pin.H"
|
|
|
|
|
|
/*! @defgroup DEBUGGER_SHELL
|
|
* Pin tools that run with the "-appdebug" switch can use this class to implement
|
|
* some common custom debugger commands. Once enabled, a user can type these
|
|
* commands interactively at the debugger prompt. In GDB, type "monitor help" to
|
|
* see a list of the available commands.
|
|
*
|
|
* Typical usage in the tool is as follows:
|
|
*
|
|
* @code
|
|
* #include "debugger-shell.H"
|
|
*
|
|
* int main(int argc, char **argv)
|
|
* {
|
|
* if (PIN_Init(argc,argv))
|
|
* return 1;
|
|
*
|
|
* DEBUGGER_SHELL::ISHELL *shell = DEBUGGER_SHELL::CreateShell();
|
|
* DEBUGGER_SHELL::STARTUP_ARGUMENTS args;
|
|
* if (!shell->Enable(args))
|
|
* return 1;
|
|
*
|
|
* PIN_StartProgram();
|
|
* }
|
|
* @endcode
|
|
*
|
|
* The tool must also compile and link with "debugger-shell.cpp".
|
|
*/
|
|
namespace DEBUGGER_SHELL
|
|
{
|
|
|
|
|
|
struct STARTUP_ARGUMENTS;
|
|
class ICUSTOM_INSTRUMENTOR;
|
|
|
|
|
|
/*! @ingroup DEBUGGER_SHELL
|
|
* The public interface to the debugger shell.
|
|
*/
|
|
class ISHELL
|
|
{
|
|
public:
|
|
/*!
|
|
* This method must be called once, typically from the tool's main() function.
|
|
* It enables the Pin instrumentation which implements the debugger extensions.
|
|
*
|
|
* @param[in] args Arguments that customize the debugger shell.
|
|
*
|
|
* @return TRUE on success. If there is an error, a diagnostic is printed
|
|
* and this method returns FALSE.
|
|
*/
|
|
virtual BOOL Enable(const STARTUP_ARGUMENTS &args) = 0;
|
|
|
|
/*!
|
|
* Tools that use the debugger shell may still implement their own extended debugger
|
|
* commands by using PIN_AddDebugInterpreter(). The debugger shell provides a way
|
|
* for such tools to include a help message for these extended commands in the help
|
|
* message that the debugger shell prints. Tools can use AddExtendedHelpCategory()
|
|
* to define their own category of help messages.
|
|
*
|
|
* @param[in] name The name of the category.
|
|
* @param[in] description Describes this category of extended commands.
|
|
* @param[out] alreadyExists If not NULL, receives TRUE if a tool already added
|
|
* a custom category for \a name. In this case, the
|
|
* debugger shell uses the previous description.
|
|
*
|
|
* @return The ID for this custom category. If a tool already added a category
|
|
* named \a name, that previous category ID is returned.
|
|
*/
|
|
virtual unsigned AddExtendedHelpCategory(const std::string &name,
|
|
const std::string &description, BOOL *alreadyExists) = 0;
|
|
|
|
/*!
|
|
* Adds a help message for an extended command that is implemented by the layered tool.
|
|
* See also AddExtendedHelpCategory() for more information on adding extended debugger
|
|
* commands.
|
|
*
|
|
* @param[in] category The category for this extended command. This can either be
|
|
* one of the predefined HELP_CATEGORY constants or a value
|
|
* returned by AddExtendedHelpCategory().
|
|
* @param[in] cmd The name of a tool's extended command.
|
|
* @param[in] description Describes what the command does.
|
|
*/
|
|
virtual void AddExtendedHelpMessage(unsigned category, const std::string &cmd,
|
|
const std::string &description) = 0;
|
|
|
|
/*!
|
|
* Tools that override the default instrumentation with ICUSTOM_INSTRUMENTOR
|
|
* may need a virtual register to hold the "skip one" flag. This method provides the
|
|
* register number to use for this.
|
|
*
|
|
* @return The Pin virtual register to use for the "skip one" flag. This is one
|
|
* of the REG_INST_Gn registers.
|
|
*/
|
|
virtual REG GetSkipOneRegister() = 0;
|
|
|
|
virtual inline ~ISHELL() = 0; ///< Destroys the debugger shell object.
|
|
};
|
|
|
|
ISHELL::~ISHELL() {}
|
|
|
|
/*! @ingroup DEBUGGER_SHELL
|
|
* Create a debugger shell object.
|
|
*
|
|
* @return A new debugger shell object on success. If there is an error, a diagnostic
|
|
* is printed and this method returns NULL.
|
|
*/
|
|
ISHELL *CreateShell();
|
|
|
|
|
|
/*! @ingroup DEBUGGER_SHELL
|
|
* Arguments that customize the debugger shell.
|
|
*/
|
|
struct STARTUP_ARGUMENTS
|
|
{
|
|
STARTUP_ARGUMENTS() :
|
|
_callOrderBefore(CALL_ORDER_DEFAULT),
|
|
_callOrderAfter(CALL_ORDER_DEFAULT),
|
|
_enableIcountBreakpoints(FALSE),
|
|
_countPrefetchAsMemOp(FALSE),
|
|
_countZeroRepAsMemOp(FALSE),
|
|
_customInstrumentor(0)
|
|
{}
|
|
|
|
/*!
|
|
* Tells the relative position of instrumentation added by the debugger shell
|
|
* for "before" and "after" instrumentation.
|
|
*/
|
|
CALL_ORDER _callOrderBefore;
|
|
CALL_ORDER _callOrderAfter;
|
|
|
|
// The following fields enable breakpoints that require instruction counting.
|
|
// When enabled, the debugger-shell always inserts instrumentation that counts
|
|
// the number of instructions executed by each thread.
|
|
//
|
|
BOOL _enableIcountBreakpoints; ///< Enable instruction-counting breakpoints.
|
|
BOOL _countPrefetchAsMemOp; ///< Count prefetch instructions as memory operations.
|
|
BOOL _countZeroRepAsMemOp; ///< Count zero-repetition REP instructions as one memory operation.
|
|
|
|
/*!
|
|
* Allows client to override some instrumentation.
|
|
*/
|
|
ICUSTOM_INSTRUMENTOR *_customInstrumentor;
|
|
};
|
|
|
|
|
|
/*! @ingroup DEBUGGER_SHELL
|
|
* Predefined categories of help commands.
|
|
*/
|
|
enum HELP_CATEGORY
|
|
{
|
|
HELP_CATEGORY_GENERAL, ///< General commands.
|
|
HELP_CATEGORY_BREAKPOINTS, ///< Breakpoint commands.
|
|
HELP_CATEGORY_TRACEPOINTS, ///< Tracepoint commands.
|
|
HELP_CATEGORY_REGISTERS, ///< Register names.
|
|
HELP_CATEGORY_END ///< Marks the last predefined help category. Custom category
|
|
///< numbers start here.
|
|
};
|
|
|
|
|
|
/*! @ingroup DEBUGGER_SHELL
|
|
* Some tools may need to define their own analysis routine that stops at a debugger
|
|
* breakpoint. Such tools can define their own class, which derives from
|
|
* ICUSTOM_INSTRUMENTOR. Pass a pointer to that object to
|
|
* STARTUP_ARGUMENTS::_customInstrumentor.
|
|
*
|
|
* Most tools do not need to override the default instrumentation, so most tools
|
|
* need not use this interface.
|
|
*/
|
|
class ICUSTOM_INSTRUMENTOR
|
|
{
|
|
public:
|
|
/*!
|
|
* The debugger shell calls this method to insert a "then" instrumentation call
|
|
* to an analysis routine that stops at a debugger breakpoint _before_ an instruction.
|
|
* The default instrumentation looks like this. Tools that implement this method should
|
|
* insert similar instrumentation:
|
|
*
|
|
* @code
|
|
* VOID InsertBreakpointBefore(INST ins, BBL bbl, CALL_ORDER order, const std::string &message)
|
|
* {
|
|
* INS_InsertThenCall(ins, IPOINT_BEFORE, (AFUNPTR)TriggerBreakpointBefore,
|
|
* IARG_CALL_ORDER, order,
|
|
* IARG_CONTEXT, IARG_THREAD_ID,
|
|
* IARG_UINT32, static_cast<UINT32>(RegSkipOne),
|
|
* IARG_PTR, message.c_str(),
|
|
* IARG_END);
|
|
* }
|
|
*
|
|
* VOID TriggerBreakpointBefore(CONTEXT *ctxt, THREADID tid, UINT32 regSkipOne, const char *message)
|
|
* {
|
|
* ADDRINT skipPc = PIN_GetContextReg(ctxt, static_cast<REG>(regSkipOne));
|
|
* ADDRINT pc = PIN_GetContextReg(ctxt, REG_INST_PTR);
|
|
* if (skipPc == pc)
|
|
* return
|
|
*
|
|
* PIN_SetContextReg(ctxt, static_cast<REG>(regSkipOne), pc);
|
|
* PIN_ApplicationBreakpoint(ctxt, tid, FALSE, message);
|
|
* }
|
|
* @endcode
|
|
*
|
|
* See the method ISHELL::GetSkipOneRegister() for the register number to use for \e RegSkipOne.
|
|
*
|
|
* @param[in] ins Insert the instrumentation before this instruction.
|
|
* @param[in] bbl The basic block containing \a ins.
|
|
* @param[in] order The instrumentation call order to use for the instrumentation.
|
|
* @param[in] message String telling why the breakpoint is triggered. The
|
|
* string is allocated in permanent storage, so the
|
|
* client can pass it directly to an analysis routine.
|
|
* If the debugger shell removes instrumentation, it will
|
|
* also deallocate this string.
|
|
*/
|
|
virtual VOID InsertBreakpointBefore(INS ins, BBL bbl, CALL_ORDER order, const std::string &message) = 0;
|
|
|
|
/*!
|
|
* The debugger shell calls this method to insert a "then" instrumentation call
|
|
* to an analysis routine that stops at a debugger breakpoint _after_ an instruction.
|
|
* The default instrumentation looks like this. Tools that implement this method should
|
|
* insert similar instrumentation:
|
|
*
|
|
* @code
|
|
* VOID InsertBreakpointAfter(INST ins, BBL bbl, IPOINT ipoint, CALL_ORDER order,
|
|
* const std::string &message)
|
|
* {
|
|
* INS_InsertThenCall(ins, ipoint, (AFUNPTR)TriggerBreakpointAfter,
|
|
* IARG_CALL_ORDER, order,
|
|
* IARG_CONTEXT, IARG_INST_PTR, IARG_THREAD_ID,
|
|
* IARG_PTR, message.c_str(),
|
|
* IARG_END);
|
|
* }
|
|
*
|
|
* VOID TriggerBreakpointAfter(CONTEXT *ctxt, ADDRINT pc, THREADID tid, const char *message)
|
|
* {
|
|
* std::ostringstream os;
|
|
* os << message << "\n";
|
|
* os << "Breakpoint triggered after instruction at 0x" << std::hex << pc;
|
|
*
|
|
* PIN_ApplicationBreakpoint(ctxt, tid, FALSE, os.str());
|
|
* }
|
|
* @endcode
|
|
*
|
|
* @param[in] ins Insert the instrumentation after this instruction.
|
|
* @param[in] bbl The basic block containing \a ins.
|
|
* @param[in] ipoint Tells whether to instrument IPOINT_AFTER or IPOINT_TAKEN_BRANCH.
|
|
* @param[in] order The instrumentation call order to use for the instrumentation.
|
|
* @param[in] message String telling why the breakpoint is triggered. The
|
|
* string is allocated in permanent storage, so the
|
|
* client can pass it directly to an analysis routine.
|
|
* If the debugger shell removes instrumentation, it will
|
|
* also deallocate this string.
|
|
*/
|
|
virtual VOID InsertBreakpointAfter(INS ins, BBL bbl, IPOINT ipoint, CALL_ORDER order,
|
|
const std::string &message) = 0;
|
|
|
|
virtual inline ~ICUSTOM_INSTRUMENTOR() = 0; ///< Destroys the custom instrumentor object.
|
|
};
|
|
|
|
ICUSTOM_INSTRUMENTOR::~ICUSTOM_INSTRUMENTOR() {}
|
|
|
|
} // namespace
|
|
#endif // file guard
|