Skip to content

Commit

Permalink
Refacotr BPatch and DyninstRT to use breakpoint as the way of communi…
Browse files Browse the repository at this point in the history
…cation
  • Loading branch information
mxz297 committed Nov 5, 2019
1 parent 4c5254e commit dfa578b
Show file tree
Hide file tree
Showing 8 changed files with 79 additions and 133 deletions.
20 changes: 20 additions & 0 deletions dyninstAPI/src/dynProcess.C
Original file line number Diff line number Diff line change
Expand Up @@ -836,6 +836,18 @@ bool PCProcess::loadRTLib() {
{
startup_printf("%s[%d]: DYNINSTinit not called automatically\n", FILE__, __LINE__);
}

// Install a breakpoint in DYNINSTtrapFunction.
// This is used as RT signal.
Address addr = getRTTrapFuncAddr();
if (addr == 0) {
startup_printf("%s[%d]: Cannot find DYNINSTtrapFunction. Needed as RT signal\n", FILE__, __LINE__);
return false;
}
if (!setBreakpoint(addr)) {
startup_printf("%s[%d]: Cannot set breakpoint in DYNINSTtrapFunction.\n", FILE__, __LINE__);
return false;
}
startup_printf("%s[%d]: DYNINSTinit succeeded\n", FILE__, __LINE__);
return setRTLibInitParams();
}
Expand Down Expand Up @@ -3200,6 +3212,14 @@ Address PCProcess::getRTEventArg3Addr() {
return sync_event_arg3_addr_;
}

Address PCProcess::getRTTrapFuncAddr() {
if (rt_trap_func_addr_ == 0) {
func_instance* func = findOnlyOneFunction("DYNINSTtrapFunction");
rt_trap_func_addr_ = func->addr();
}
return rt_trap_func_addr_;
}

bool PCProcess::hasPendingEvents() {
// Go to the muxer as a final arbiter
return PCEventMuxer::muxer().hasPendingEvents(this);
Expand Down
5 changes: 5 additions & 0 deletions dyninstAPI/src/dynProcess.h
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,7 @@ class PCProcess : public AddressSpace {
sync_event_arg2_addr_(0),
sync_event_arg3_addr_(0),
sync_event_breakpoint_addr_(0),
rt_trap_func_addr_(0),
thread_hash_tids(0),
thread_hash_indices(0),
thread_hash_size(0),
Expand Down Expand Up @@ -393,6 +394,7 @@ class PCProcess : public AddressSpace {
sync_event_arg2_addr_(0),
sync_event_arg3_addr_(0),
sync_event_breakpoint_addr_(0),
rt_trap_func_addr_(0),
thread_hash_tids(0),
thread_hash_indices(0),
thread_hash_size(0),
Expand Down Expand Up @@ -436,6 +438,7 @@ class PCProcess : public AddressSpace {
sync_event_arg2_addr_(parent->sync_event_arg2_addr_),
sync_event_arg3_addr_(parent->sync_event_arg3_addr_),
sync_event_breakpoint_addr_(parent->sync_event_breakpoint_addr_),
rt_trap_func_addr_(parent->rt_trap_func_addr_),
thread_hash_tids(parent->thread_hash_tids),
thread_hash_indices(parent->thread_hash_indices),
thread_hash_size(parent->thread_hash_size),
Expand Down Expand Up @@ -487,6 +490,7 @@ class PCProcess : public AddressSpace {
Address getRTEventArg1Addr();
Address getRTEventArg2Addr();
Address getRTEventArg3Addr();
Address getRTTrapFuncAddr();

// Shared library managment
void addASharedObject(mapped_object *newObj);
Expand Down Expand Up @@ -592,6 +596,7 @@ class PCProcess : public AddressSpace {
Address sync_event_arg2_addr_;
Address sync_event_arg3_addr_;
Address sync_event_breakpoint_addr_;
Address rt_trap_func_addr_;
Address thread_hash_tids;
Address thread_hash_indices;
int thread_hash_size;
Expand Down
108 changes: 39 additions & 69 deletions dyninstAPI/src/pcEventHandler.C
Original file line number Diff line number Diff line change
Expand Up @@ -449,22 +449,6 @@ bool PCEventHandler::handleSignal(EventSignal::const_ptr ev, PCProcess *evProc)
FILE__, __LINE__, ev->getProcess()->getPid(), ev->getThread()->getLWP(),
ev->getSignal());

// Check whether it is a signal from the RT library (note: this will internally
// handle any entry/exit to syscalls and make the necessary up calls as appropriate)
RTSignalResult result = handleRTSignal(ev, evProc);
if( result == ErrorInDecoding ) {
proccontrol_printf("%s[%d]: failed to determine whether signal came from RT library\n",
FILE__, __LINE__);
return false;
}

if( result == IsRTSignal ) {
// handleRTSignal internally does all handling for the events in order to keep
// related logic in one place
proccontrol_printf("%s[%d]: signal came from RT library\n", FILE__, __LINE__);
return true;
}

// check if windows access violation, defensive mode, and write permissions.
// unprotect pages if necessary.
if (evProc->getHybridMode() == BPatch_defensiveMode
Expand Down Expand Up @@ -576,86 +560,61 @@ bool PCEventHandler::handleSignal(EventSignal::const_ptr ev, PCProcess *evProc)
return true;
}

PCEventHandler::RTSignalResult
PCEventHandler::handleRTSignal(EventSignal::const_ptr ev, PCProcess *evProc) const {
bool PCEventHandler::handleRTBreakpoint(EventBreakpoint::const_ptr ev, PCProcess *evProc) const {
// Check whether the signal was sent from the RT library by checking variables
// in the library -- if we cannot be determine whether this signal came from
// the RT library, assume it did not.

if( evProc->runtime_lib.size() == 0 ) return NotRTSignal;
if (ev->getSignal() != DYNINST_BREAKPOINT_SIGNUM) {
proccontrol_printf("%s[%d]: signal %d is not RT library signal\n",
FILE__, __LINE__, ev->getSignal());
return NotRTSignal;
}
if( evProc->runtime_lib.size() == 0 ) return false;

Address sync_event_breakpoint_addr = evProc->getRTEventBreakpointAddr();
Address rtTrapFuncAddr = evProc->getRTTrapFuncAddr();
Address sync_event_id_addr = evProc->getRTEventIdAddr();
Address sync_event_arg1_addr = evProc->getRTEventArg1Addr();

int breakpoint = 0;
int status = 0;
Address arg1 = 0;
int zero = 0;

// Check that all addresses could be determined
if( sync_event_breakpoint_addr == 0
if (rtTrapFuncAddr == 0
|| sync_event_id_addr == 0
|| sync_event_arg1_addr == 0 )
{
return NotRTSignal;
}

// First, check breakpoint...
if( !evProc->readDataWord((const void *)sync_event_breakpoint_addr,
sizeof(int), &breakpoint, false) ) return NotRTSignal;
proccontrol_printf("%s[%d]: signal is not RT library breakpoint. Some address is 0: rtTrapFuncAddr %lx, sync_even_id_addr %lx, sync_event_arg1_addr %lx\n",
FILE__, __LINE__, rtTrapFuncAddr, sync_event_id_addr, sync_event_arg1_addr);

switch(breakpoint) {
case NoRTBreakpoint:
proccontrol_printf("%s[%d]: signal is not RT library signal\n",
FILE__, __LINE__);
return NotRTSignal;
case NormalRTBreakpoint:
case SoftRTBreakpoint:
// More work to do
break;
default:
proccontrol_printf("%s[%d]: invalid value for RT library breakpoint variable\n",
FILE__, __LINE__);
return NotRTSignal;
return false;
}

// Make sure we don't get this event twice....
if( !evProc->writeDataWord((void *)sync_event_breakpoint_addr, sizeof(int), &zero) ) {
proccontrol_printf("%s[%d]: failed to reset RT library breakpoint variable\n",
FILE__, __LINE__);
return NotRTSignal;
// On x86, the PC is shifted by one byte when hitting the trap instruction
if (ev->getAddress() != rtTrapFuncAddr && ev->getAddress() != rtTrapFuncAddr + 1) {
proccontrol_printf("%s[%d]: signal is not RT library breakpoint. Breakpoint from address %lx, expected %lx\n",
FILE__, __LINE__, ev->getAddress(), rtTrapFuncAddr);
return false;
}

// Get the type of the event
if( !evProc->readDataWord((const void *)sync_event_id_addr, sizeof(int),
&status, false) ) return NotRTSignal;
&status, false) ) return false;

if( status == DSE_undefined ) {
proccontrol_printf("%s[%d]: signal is not RT library signal\n", FILE__, __LINE__);
return NotRTSignal;
proccontrol_printf("%s[%d]: signal is not RT library breakpointl\n", FILE__, __LINE__);
return false;
}

// get runtime library arg1 address
if( !evProc->readDataWord((const void *)sync_event_arg1_addr,
evProc->getAddressWidth(), &arg1, false) ) {
proccontrol_printf("%s[%d]: failed to read RT library arg1 variable\n",
FILE__, __LINE__);
return NotRTSignal;
return false;
}

if( !isValidRTSignal(ev->getSignal(), (RTBreakpointVal) breakpoint, arg1, status) ) return NotRTSignal;

BPatch_process *bproc = BPatch::bpatch->getProcessByPid(evProc->getPid());
if( bproc == NULL ) {
proccontrol_printf("%s[%d]: no corresponding BPatch_process for process %d\n",
FILE__, __LINE__, evProc->getPid());
return ErrorInDecoding;
return false;
}

// See pcEventHandler.h (SYSCALL HANDLING) for a description of what
Expand Down Expand Up @@ -696,7 +655,7 @@ PCEventHandler::handleRTSignal(EventSignal::const_ptr ev, PCProcess *evProc) con
// This is not currently used by Dyninst internals for anything
// We rely on ProcControlAPI for this and it should be impossible
// to get this via a breakpoint
return ErrorInDecoding;
return false;
case DSE_exitEntry:
proccontrol_printf("%s[%d]: decoded exitEntry, arg = %lx\n",
FILE__, __LINE__, arg1);
Expand All @@ -720,26 +679,26 @@ PCEventHandler::handleRTSignal(EventSignal::const_ptr ev, PCProcess *evProc) con
proccontrol_printf("%s[%d]: decoded loadLibrary (error), arg = %lx\n",
FILE__, __LINE__, arg1);
// This is no longer used
return ErrorInDecoding;
return false;
case DSE_lwpExit:
proccontrol_printf("%s[%d]: decoded lwpExit (error), arg = %lx\n",
FILE__, __LINE__, arg1);
// This is not currently used on any platform
return ErrorInDecoding;
return false;
case DSE_snippetBreakpoint:
proccontrol_printf("%s[%d]: decoded snippetBreak, arg = %lx\n",
FILE__, __LINE__, arg1);
bproc->setLastSignal(ev->getSignal());
bproc->setLastSignal(SIGTRAP);
evProc->setDesiredProcessState(PCProcess::ps_stopped);
break;
case DSE_stopThread:
proccontrol_printf("%s[%d]: decoded stopThread, arg = %lx\n",
FILE__, __LINE__, arg1);
bproc->setLastSignal(ev->getSignal());
bproc->setLastSignal(SIGTRAP);
if( !handleStopThread(evProc, arg1) ) {
proccontrol_printf("%s[%d]: failed to handle stopped thread event\n",
FILE__, __LINE__);
return ErrorInDecoding;
return false;
}
break;
case DSE_dynFuncCall:
Expand All @@ -748,7 +707,7 @@ PCEventHandler::handleRTSignal(EventSignal::const_ptr ev, PCProcess *evProc) con
if( !handleDynFuncCall(evProc, bproc, arg1) ) {
proccontrol_printf("%s[%d]: failed to handle dynamic callsite event\n",
FILE__, __LINE__);
return ErrorInDecoding;
return false;
}
break;
case DSE_userMessage:
Expand All @@ -757,11 +716,11 @@ PCEventHandler::handleRTSignal(EventSignal::const_ptr ev, PCProcess *evProc) con
if( !handleUserMessage(evProc, bproc, arg1) ) {
proccontrol_printf("%s[%d]: failed to handle user message event\n",
FILE__, __LINE__);
return ErrorInDecoding;
return false;
}
break;
default:
return NotRTSignal;
return false;
}

// Behavior common to all syscalls
Expand All @@ -779,7 +738,7 @@ PCEventHandler::handleRTSignal(EventSignal::const_ptr ev, PCProcess *evProc) con
ProcControlAPI::mbox()->enqueue(newEvt);
}

return IsRTSignal;
return true;
}

bool PCEventHandler::handleUserMessage(PCProcess *evProc, BPatch_process *bpProc,
Expand Down Expand Up @@ -972,6 +931,18 @@ bool PCEventHandler::handleLibrary(EventLibrary::const_ptr ev, PCProcess *evProc
}

bool PCEventHandler::handleBreakpoint(EventBreakpoint::const_ptr ev, PCProcess *evProc) const {
proccontrol_printf("Enter PCEventHandler::handleBreakpoint\n");

// Check whether it is a breakpoint in the RT library (note: this will internally
// handle any entry/exit to syscalls and make the necessary up calls as appropriate)
bool result = handleRTBreakpoint(ev, evProc);
if (result) {
// handleRTBreakpoint internally does all handling for the events in order to keep
// related logic in one place
proccontrol_printf("%s[%d]: breakpoint came from RT library\n", FILE__, __LINE__);
return true;
}

if( dyn_debug_proccontrol && evProc->isBootstrapped() ) {
RegisterPool regs;
if( !ev->getThread()->getAllRegisters(regs) ) {
Expand All @@ -983,7 +954,6 @@ bool PCEventHandler::handleBreakpoint(EventBreakpoint::const_ptr ev, PCProcess *
}
}
}

return true;
}

Expand Down
8 changes: 1 addition & 7 deletions dyninstAPI/src/pcEventHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,19 +88,13 @@ class PCEventHandler {
bool handleBreakpoint(ProcControlAPI::EventBreakpoint::const_ptr ev, PCProcess *evProc) const;
bool handleRPC(ProcControlAPI::EventRPC::const_ptr ev, PCProcess *evProc) const;

enum RTSignalResult {
ErrorInDecoding,
NotRTSignal,
IsRTSignal
};

enum RTBreakpointVal {
NoRTBreakpoint,
NormalRTBreakpoint,
SoftRTBreakpoint
};

RTSignalResult handleRTSignal(ProcControlAPI::EventSignal::const_ptr ev, PCProcess *evProc) const;
bool handleRTBreakpoint(ProcControlAPI::EventBreakpoint::const_ptr ev, PCProcess *evProc) const;
bool handleStopThread(PCProcess *evProc, Address rt_arg) const;
bool handleUserMessage(PCProcess *evProc, BPatch_process *bpProc, Address rt_arg) const;
bool handleDynFuncCall(PCProcess *evProc, BPatch_process *bpProc, Address rt_arg) const;
Expand Down
15 changes: 7 additions & 8 deletions dyninstAPI_RT/src/RTcommon.c
Original file line number Diff line number Diff line change
Expand Up @@ -145,10 +145,6 @@ DLLEXPORT void DYNINST_unlock_tramp_guard()
DYNINST_tls_tramp_guard = 1;
}

#if defined(os_linux)
void DYNINSTlinuxBreakPoint();
#endif

DECLARE_DYNINST_LOCK(DYNINST_trace_lock);

/**
Expand Down Expand Up @@ -299,11 +295,7 @@ DLLEXPORT void DYNINST_instExecEntry(void *arg1) {
DYNINST_synch_event_id = DSE_execEntry;
DYNINST_synch_event_arg1 = arg1;
/* Stop ourselves */
#if defined(os_linux)
DYNINSTlinuxBreakPoint();
#else
DYNINSTbreakPoint();
#endif
/* Once the stop completes, clean up */
DYNINST_synch_event_id = DSE_undefined;
DYNINST_synch_event_arg1 = NULL;
Expand Down Expand Up @@ -746,3 +738,10 @@ void* dyninstTrapTranslate(void *source,
return target;
}

DLLEXPORT void DYNINSTtrapFunction(){
__asm__ __volatile__(
"nop\n"
:::);
}


1 change: 1 addition & 0 deletions dyninstAPI_RT/src/RTcommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include "RTthread.h"
#include <stdarg.h>

void DYNINSTtrapFunction();
void DYNINSTbreakPoint();
/* Use a signal that is safe if we're not attached. */
void DYNINSTsafeBreakPoint();
Expand Down

0 comments on commit dfa578b

Please sign in to comment.