From 3388d62a2b09416dde592e38a518a8ce81c6b80a Mon Sep 17 00:00:00 2001 From: buck Date: Thu, 26 Mar 1998 01:06:42 +0000 Subject: [PATCH] Added BPatch_thread::oneTimeCode, BPatch_thread::loadLibrary, and other minor features to the Dyninst API. --- dyninstAPI/h/BPatch.h | 4 +- dyninstAPI/h/BPatch_point.h | 24 ++++++- dyninstAPI/h/BPatch_snippet.h | 19 ++--- dyninstAPI/h/BPatch_thread.h | 18 +++++ dyninstAPI/src/BPatch.C | 6 +- dyninstAPI/src/BPatch_point.C | 40 ++++++++++- dyninstAPI/src/BPatch_snippet.C | 28 +++++++- dyninstAPI/src/BPatch_thread.C | 120 ++++++++++++++++++++++++++++++- dyninstAPI/tests/src/test1.C | 24 +++++++ dyninstAPI/tests/src/test1.mutatee.c | 25 +++++++ dyninstAPI/tests/src/test2.C | 134 +++++++++++++++++++++++++++++++---- dyninstAPI/tests/src/test2.h | 1 + dyninstAPI/tests/src/test2.mutatee.c | 11 +++ dyninstAPI_RT/src/RTsolaris.c | 9 +++ 14 files changed, 423 insertions(+), 40 deletions(-) diff --git a/dyninstAPI/h/BPatch.h b/dyninstAPI/h/BPatch.h index bbba50a..0a055cd 100644 --- a/dyninstAPI/h/BPatch.h +++ b/dyninstAPI/h/BPatch.h @@ -69,8 +69,6 @@ class BPatch { bool typeCheckOn; int lastError; - BPatch_thread *pidToThread(int pid, bool *exists = NULL); - bool getThreadEvent(bool block); bool havePendingEvent(); public: @@ -101,6 +99,8 @@ public: void registerThread(BPatch_thread *thread); void unRegisterThread(int pid); + BPatch_thread *getThreadByPid(int pid, bool *exists = NULL); + void reportError(BPatchErrorLevel severity, int number, const char *str); void clearError() { lastError = 0; } diff --git a/dyninstAPI/h/BPatch_point.h b/dyninstAPI/h/BPatch_point.h index f96aea2..311b428 100644 --- a/dyninstAPI/h/BPatch_point.h +++ b/dyninstAPI/h/BPatch_point.h @@ -48,17 +48,37 @@ class BPatch_thread; class BPatch_image; class BPatch_function; + +/* + * Used with BPatch_function::findPoint to specify which of the possible + * instrumentation points within a procedure should be returned. + */ +typedef enum { + BPatch_entry, + BPatch_exit, + BPatch_subroutine, + BPatch_longJump, + BPatch_allLocations +} BPatch_procedureLocation; + + class BPatch_point { friend class BPatch_thread; friend class BPatch_function; process *proc; instPoint *point; + BPatch_procedureLocation pointType; - BPatch_point(process *_proc, instPoint *_point) : - proc(_proc), point(_point) {}; + BPatch_point(process *_proc, instPoint *_point, + BPatch_procedureLocation _pointType) : + proc(_proc), point(_point), pointType(_pointType) {}; public: + BPatch_procedureLocation getPointType() { return pointType; } BPatch_function *getCalledFunction(); + void *getAddress(); + int getDisplacedInstructions(int maxSize, void *insns); + bool usesTrap_NP(); }; diff --git a/dyninstAPI/h/BPatch_snippet.h b/dyninstAPI/h/BPatch_snippet.h index f0a808d..97e3b8d 100644 --- a/dyninstAPI/h/BPatch_snippet.h +++ b/dyninstAPI/h/BPatch_snippet.h @@ -43,6 +43,7 @@ #define _BPatch_snippet_h_ #include "BPatch_Vector.h" +#include "BPatch_point.h" class AstNode; class function_base; @@ -80,19 +81,6 @@ typedef enum { } BPatch_unOp; -/* - * Used with BPatch_function::findPoint to specify which of the possible - * instrumentation points within a procedure should be returned. - */ -typedef enum { - BPatch_entry, - BPatch_exit, - BPatch_subroutine, - BPatch_longJump, - BPatch_allLocations -} BPatch_procedureLocation; - - class BPatch_function { process *proc; public: @@ -201,4 +189,9 @@ public: void *getBaseAddr() const { return address; } }; +class BPatch_breakPointExpr : public BPatch_snippet { +public: + BPatch_breakPointExpr(); +}; + #endif /* _BPatch_snippet_h_ */ diff --git a/dyninstAPI/h/BPatch_thread.h b/dyninstAPI/h/BPatch_thread.h index 44ac7b1..9c0c6e7 100644 --- a/dyninstAPI/h/BPatch_thread.h +++ b/dyninstAPI/h/BPatch_thread.h @@ -111,6 +111,9 @@ class BPatch_thread { bool createdViaAttach; bool detached; + bool waitingForOneTimeCode; + unsigned lastOneTimeCodeReturnValue; + bool unreportedStop; bool unreportedTermination; @@ -126,6 +129,15 @@ class BPatch_thread { bool statusIsStopped(); bool statusIsTerminated(); + + static void oneTimeCodeCallbackDispatch(process *theProc, + void *userData, + unsigned returnValue); + + void oneTimeCodeCallback(void *userData, + unsigned returnValue); + + int oneTimeCodeInternal(const BPatch_snippet &expr); protected: BPatch_thread(char *path, char *argv[], char *envp[] = NULL); BPatch_thread(char *path, int pid); @@ -172,6 +184,12 @@ public: bool replaceFunctionCall(BPatch_point &point, BPatch_function &newFunc); bool removeFunctionCall(BPatch_point &point); + + void oneTimeCode(const BPatch_snippet &expr) { + oneTimeCodeInternal(expr); + }; + + bool loadLibrary(char *libname); }; #endif /* BPatch_thread_h_ */ diff --git a/dyninstAPI/src/BPatch.C b/dyninstAPI/src/BPatch.C index 5917647..fa8e49e 100644 --- a/dyninstAPI/src/BPatch.C +++ b/dyninstAPI/src/BPatch.C @@ -227,7 +227,7 @@ void BPatch::formatErrorString(char *dst, int size, /* - * BPatch::pidToThread + * BPatch::getThreadByPid * * Given a process ID, this function returns a pointer to the associated * BPatch_thread object (or NULL if there is none). Since a process may be @@ -240,7 +240,7 @@ void BPatch::formatErrorString(char *dst, int size, * in the table and false if it does not. NULL may be passed in * if this information is not required. */ -BPatch_thread *BPatch::pidToThread(int pid, bool *exists) +BPatch_thread *BPatch::getThreadByPid(int pid, bool *exists) { if (info->threadsByPid.defines(pid)) { if (exists) *exists = true; @@ -398,7 +398,7 @@ bool BPatch::getThreadEvent(bool block) block = false; bool exists; - BPatch_thread *thread = pidToThread(pid, &exists); + BPatch_thread *thread = getThreadByPid(pid, &exists); if (thread == NULL) { if (exists) { if (WIFSIGNALED(status) || WIFEXITED(status)) diff --git a/dyninstAPI/src/BPatch_point.C b/dyninstAPI/src/BPatch_point.C index 4567fa1..c537a2c 100644 --- a/dyninstAPI/src/BPatch_point.C +++ b/dyninstAPI/src/BPatch_point.C @@ -40,6 +40,9 @@ */ #include +#ifdef rs6000_ibm_aix4_1 +#include +#endif #include "BPatch_point.h" #include "BPatch_snippet.h" @@ -47,6 +50,7 @@ #include "symtab.h" #include "instPoint.h" + /* * BPatch_point::getCalledFunction * @@ -82,7 +86,41 @@ BPatch_function *BPatch_point::getCalledFunction() /* - * usesTrap_NP + * BPatch_point::getAddress + * + * Returns the original address of the first instruction at this point. + */ +void *BPatch_point::getAddress() +{ + return point->iPgetAddress(); +} + + +/* + * BPatch_point::getDisplacedInstructions + * + * Returns the instructions to be relocated when instrumentation is inserted + * at this point. Returns the number of bytes taken up by these instructions. + * + * maxSize The maximum number of bytes of instructions to return. + * insns A pointer to a buffer in which to return the instructions. + */ +int BPatch_point::getDisplacedInstructions(int maxSize, void *insns) +{ +#ifdef rs6000_ibm_aix4_1 + if (maxSize >= sizeof(instruction)) + memcpy(insns, &point->originalInstruction.raw, sizeof(instruction)); + + return sizeof(instruction); +#else + // Not implemented except on AIX + return -1; +#endif +} + + +/* + * BPatch_point::usesTrap_NP * * Returns true if this point is or would be instrumented with a trap, rather * than a jump to the base tramp, false otherwise. On platforms that do not diff --git a/dyninstAPI/src/BPatch_snippet.C b/dyninstAPI/src/BPatch_snippet.C index 66b0345..6073074 100644 --- a/dyninstAPI/src/BPatch_snippet.C +++ b/dyninstAPI/src/BPatch_snippet.C @@ -504,6 +504,25 @@ void BPatch_variableExpr::writeValue(const void *src, int len) } +/* + * BPatch_breakPointExpr::BPatch_breakPointExpr + * + * Construct a snippet representing a breakpoint. + * + */ +BPatch_breakPointExpr::BPatch_breakPointExpr() +{ + vector null_args; + + ast = new AstNode("DYNINSTbreakPoint", null_args); + + assert(BPatch::bpatch != NULL); + + ast->setType(BPatch::bpatch->type_Untyped); + ast->setTypeChecking(BPatch::bpatch->isTypeChecked()); +} + + /************************************************************************** * BPatch_function *************************************************************************/ @@ -553,20 +572,23 @@ BPatch_Vector *BPatch_function::findPoint( if (loc == BPatch_entry || loc == BPatch_allLocations) { BPatch_point *new_point = new BPatch_point(proc, - (instPoint *)func->funcEntry(proc)); + (instPoint *)func->funcEntry(proc), + BPatch_entry); result->push_back(new_point); } if (loc == BPatch_exit || loc == BPatch_allLocations) { const vector &points = func->funcExits(proc); for (unsigned i = 0; i < points.size(); i++) { - BPatch_point *new_point = new BPatch_point(proc, points[i]); + BPatch_point *new_point = new BPatch_point(proc, points[i], + BPatch_exit); result->push_back(new_point); } } if (loc == BPatch_subroutine || loc == BPatch_allLocations) { const vector &points = func->funcCalls(proc); for (unsigned i = 0; i < points.size(); i++) { - BPatch_point *new_point = new BPatch_point(proc, points[i]); + BPatch_point *new_point = new BPatch_point(proc, points[i], + BPatch_subroutine); result->push_back(new_point); } } diff --git a/dyninstAPI/src/BPatch_thread.C b/dyninstAPI/src/BPatch_thread.C index bf00984..50bf55d 100644 --- a/dyninstAPI/src/BPatch_thread.C +++ b/dyninstAPI/src/BPatch_thread.C @@ -39,6 +39,10 @@ * incur to third parties resulting from your use of Paradyn. */ +#ifdef sparc_sun_solaris2_4 +#include +#endif + #include "process.h" #include "inst.h" #include "instP.h" @@ -76,7 +80,8 @@ int BPatch_thread::getPid() BPatch_thread::BPatch_thread(char *path, char *argv[], char *envp[]) : lastSignal(-1), mutationsActive(true), createdViaAttach(false), detached(false), proc(NULL), image(NULL), - unreportedStop(false), unreportedTermination(false) + unreportedStop(false), unreportedTermination(false), + waitingForOneTimeCode(false) { vector argv_vec; vector envp_vec; @@ -120,7 +125,8 @@ BPatch_thread::BPatch_thread(char *path, char *argv[], char *envp[]) BPatch_thread::BPatch_thread(char *path, int pid) : lastSignal(-1), mutationsActive(true), createdViaAttach(true), detached(false), proc(NULL), image(NULL), - unreportedStop(false), unreportedTermination(false) + unreportedStop(false), unreportedTermination(false), + waitingForOneTimeCode(false) { if (!attachProcess(path, pid, 1, proc)) { // XXX Should do something more sensible @@ -667,6 +673,116 @@ bool BPatch_thread::removeFunctionCall(BPatch_point &point) } +/* + * BPatch_thread::oneTimeCodeCallbackDispatch + * + * This function is registered with the lower-level code as the callback for + * inferior RPC completion. It determines what thread the RPC was executed on + * and then calls the API's higher-level callback routine for that thread. + * + * theProc The process in which the RPC completed. + * userData This is a value that can be set when we invoke an inferior RPC + * and which will be returned to us in this callback. + * returnValue The value returned by the RPC. + */ +void BPatch_thread::oneTimeCodeCallbackDispatch(process *theProc, + void *userData, + unsigned returnValue) +{ + assert(BPatch::bpatch != NULL); + + BPatch_thread *theThread = + BPatch::bpatch->getThreadByPid(theProc->getPid()); + + assert(theThread != NULL); + + theThread->oneTimeCodeCallback(userData, returnValue); +} + + +/* + * BPatch_thread::oneTimeCodeCallback + * + * This function is called by BPatch_thread:::oneTimeCodeCallbackDispatch + * when in inferior RPC completes. + * + * userData This is a value that can be set when we invoke an inferior RPC + * and which will be returned to us in this callback. + * returnValue The value returned by the RPC. + */ +void BPatch_thread::oneTimeCodeCallback(void */*userData*/, unsigned returnValue) +{ + assert(waitingForOneTimeCode); + + lastOneTimeCodeReturnValue = returnValue; + waitingForOneTimeCode = false; +} + + +/* + * BPatch_thread::oneTimeCode + * + * Causes a snippet expression to be evaluated once in the mutatee at the next + * available opportunity. + * + * snippet The snippet to evaluate. + */ +int BPatch_thread::oneTimeCodeInternal(const BPatch_snippet &expr) +{ + if (!statusIsStopped()) + return; + + proc->postRPCtoDo(expr.ast, + false, // XXX = calculate cost - is this what we want? + BPatch_thread::oneTimeCodeCallbackDispatch, // Callback + NULL, // User data + -1); // This isn't a metric definition - we shouldn't + // really have this parameter in the API. + + waitingForOneTimeCode = true; + + do { + proc->launchRPCifAppropriate(false, false); + BPatch::bpatch->getThreadEvent(false); + } while (waitingForOneTimeCode && !statusIsTerminated()); + + return lastOneTimeCodeReturnValue; +} + + +/* + * BPatch_thread::loadLibrary + * + * Load a dynamically linked library into the address space of the mutatee. + * + * libname The name of the library to load. + */ +bool BPatch_thread::loadLibrary(char *libname) +{ +#ifdef sparc_sun_solaris2_4 + BPatch_Vector args; + + BPatch_constExpr nameArg(libname); + BPatch_constExpr modeArg(RTLD_NOW | RTLD_GLOBAL); + + args.push_back(&nameArg); + args.push_back(&modeArg); + + BPatch_function *dlopen_func = image->findFunction("DYNINSTloadLibrary"); + if (dlopen_func == NULL) return false; + + BPatch_funcCallExpr call_dlopen(*dlopen_func, args); + + if (!oneTimeCodeInternal(call_dlopen)) + return false; + + return true; +#else + return false; +#endif +} + + /*************************************************************************** * BPatch_snippetHandle ***************************************************************************/ diff --git a/dyninstAPI/tests/src/test1.C b/dyninstAPI/tests/src/test1.C index d7c8773..7cd4529 100644 --- a/dyninstAPI/tests/src/test1.C +++ b/dyninstAPI/tests/src/test1.C @@ -806,6 +806,28 @@ void mutatorTest18(BPatch_thread *appThread, BPatch_image *appImage) expr18_1->writeValue(&n); } +// +// Start Test Case #19 - mutator side (oneTimeCode) +// +void mutatorTest19(BPatch_thread *appThread, BPatch_image *appImage) +{ + waitUntilStopped(appThread, 19, "oneTimeCode"); + + BPatch_function *call19_1func = appImage->findFunction("call19_1"); + if (call19_1func == NULL) { + fprintf(stderr, "Unable to find function \"call19_1.\"\n"); + exit(1); + } + + BPatch_Vector nullArgs; + BPatch_funcCallExpr call19_1Expr(*call19_1func, nullArgs); + checkCost(call19_1Expr); + + appThread->oneTimeCode(call19_1Expr); + + appThread->continueExecution(); +} + void mutatorMAIN(char *pathname, bool useAttach) { BPatch_thread *appThread; @@ -1071,6 +1093,8 @@ void mutatorMAIN(char *pathname, bool useAttach) mutatorTest15b(appThread, appImage); + mutatorTest19(appThread, appImage); + while (!appThread->isTerminated()) waitForStatusChange(); diff --git a/dyninstAPI/tests/src/test1.mutatee.c b/dyninstAPI/tests/src/test1.mutatee.c index 3ca8ae6..d0be426 100644 --- a/dyninstAPI/tests/src/test1.mutatee.c +++ b/dyninstAPI/tests/src/test1.mutatee.c @@ -32,6 +32,8 @@ int debugPrint = 0; #define RET17_1 1700100 #define RET17_2 1700200 +#define MAGIC19_1 1900100 + #define TRUE 1 #define FALSE 0 @@ -89,6 +91,8 @@ int globalVariable17_2 = 0; int globalVariable18_1 = 42; +int globalVariable19_1 = 0xdeadbeef; + /* * Check to see if the mutator has attached to us. */ @@ -296,6 +300,12 @@ int call17_2(int p1) return a7; } +void call19_1() +{ + globalVariable19_1 = MAGIC19_1; +} + + // // This is a series of nearly empty functions to attach code to // @@ -607,6 +617,19 @@ void func18_1() } } +void func19_1() +{ + stop_process(); + + if (globalVariable19_1 == MAGIC19_1) { + printf("Passed test #19 (oneTimeCode)\n"); + } else { + printf("**Failed test #19 (oneTimeCode)\n"); + printf(" globalVariable19_1 contained %d, not %d as expected\n", + globalVariable19_1, MAGIC19_1); + } +} + void fail7Print(int tCase, int fCase, char *op) { if (tCase != 72) @@ -764,5 +787,7 @@ void main(int argc, char *argv[]) func18_1(); + func19_1(); + exit(0); } diff --git a/dyninstAPI/tests/src/test2.C b/dyninstAPI/tests/src/test2.C index b538951..09f7e8b 100644 --- a/dyninstAPI/tests/src/test2.C +++ b/dyninstAPI/tests/src/test2.C @@ -54,6 +54,62 @@ BPatch *bpatch; // control debug printf statements #define dprintf if (debugPrint) printf +void test10a(BPatch_thread *appThread, BPatch_image *appImage) +{ + /* + * Instrument a function with a BPatch_breakPointExpr. + */ + BPatch_Vector *points = + appImage->findProcedurePoint("func10_1", BPatch_entry); + if (points == NULL) { + printf("**Failed** test #10 (BPatch_breakPointExpr)\n"); + printf(" unable to locate function \"func10_1\".\n"); + exit(1); + } + + BPatch_breakPointExpr bp; + + if (appThread->insertSnippet(bp, *points) == NULL) { + printf("**Failed** test #10 (BPatch_breakPointExpr)\n"); + printf(" unable to insert breakpoint snippet\n"); + exit(1); + } +} + +void test11(BPatch_thread */*appThread*/, BPatch_image *appImage) +{ +#if !defined(rs6000_ibm_aix4_1) + // Test getDisplacedInstructions + printf("Skipping test #11 (getDisplacedInstructions)\n"); + printf(" BPatch_point::getDisplacedInstructions not implemented on this platform\n"); +#else + BPatch_Vector *points = + appImage->findProcedurePoint("func11_1", BPatch_entry); + if (points == NULL) { + printf("**Failed** test #11 (getDisplacedInstructions)\n"); + printf(" unable to locate function \"func11_1\".\n"); + exit(1); + } + + char buf[128]; + memset(buf, 128, 0); + int nbytes = (*points)[0]->getDisplacedInstructions(128, buf); + if (nbytes < 0 || nbytes > 128) { + printf("**Failed** test #11 (getDisplacedInstructions)\n"); + printf(" getDisplacedInstructions returned a strange number of bytes (%d)\n", nbytes); + } + int i; + for (i = 0; i < nbytes; i++) { + if (buf[i] != 0) break; + } + if (i == nbytes) { + printf("**Failed** test #11 (getDisplacedInstructions)\n"); + printf(" getDisplacedInstructions doesn't seem to have returned any instructions\n"); + } + printf("Passed test #11 (getDisplacedInstructions)\n"); +#endif +} + BPatch_thread *mutatorMAIN(char *pathname, bool useAttach) { BPatch_thread *appThread; @@ -232,10 +288,15 @@ main(int argc, char *argv[]) printf("Passed test #5 (look up nonexistent function)\n"); } + test10a(ret, img); + ret->continueExecution(); -#ifndef sparc_sun_solaris2_4 - printf("Skipping test #6 (load a dynamically linked library)\n"); +#if !defined(sparc_sun_solaris2_4) + printf("Skipping test #6 (load a dynamically linked library from the mutatee)\n"); + printf(" feature not implemented on this platform\n"); + + printf("Skipping test #7 (load a dynamically linked library from the mutator)\n"); printf(" feature not implemented on this platform\n"); #else waitUntilStopped(ret, 6, "load a dynamically linked library"); @@ -252,21 +313,47 @@ main(int argc, char *argv[]) } } if (found) { - printf("Passed test #6 (load a dynamically linked library)\n"); + printf("Passed test #6 (load a dynamically linked library from the mutatee)\n"); } else { - printf("**Failed** test #6 (load a dynamically linked library)\n"); + printf("**Failed** test #6 (load a dynamically linked library from the mutatee)\n"); printf(" image::getModules() did not indicate that the library had been loaded\n"); failed = true; } + // make our own dlopen call + if (!ret->loadLibrary(TEST_DYNAMIC_LIB2)) { + printf("**Failed** test #7 (load a dynamically linked library from the mutator)\n"); + printf(" BPatch_thread::loadLibrary returned an error\n"); + failed = true; + } else { + // see if it worked + found = false; + BPatch_Vector *m = img->getModules(); + for (i=0; i < m->size(); i++) { + char name[80]; + (*m)[i]->getName(name, sizeof(name)); + if (strcmp(name, TEST_DYNAMIC_LIB2) == 0) { + found = true; + break; + } + } + if (found) { + printf("Passed test #7 (load a dynamically linked library from the mutator)\n"); + } else { + printf("**Failed** test #7 (load a dynamically linked library from the mutator)\n"); + printf(" image::getModules() did not indicate that the library had been loaded\n"); + failed = true; + } + } + ret->continueExecution(); #endif ret->stopExecution(); #ifndef sparc_sun_sunos4_1_3 - printf("Skipping test #7 (dump core but do not terminate)\n"); - printf(" BPatch_thread::dumpCore() not implemented on this platform\n"); + printf("Skipping test #8 (dump core but do not terminate)\n"); + printf(" BPatch_thread::dumpCore not implemented on this platform\n"); #else // dump core, but do not terminate. // this doesn't seem to do anything - jkh 7/12/97 @@ -282,20 +369,21 @@ main(int argc, char *argv[]) ret->dumpCore("mycore", true); bool coreExists = (access("mycore", F_OK) == 0); if (gotError || !coreExists) { - printf("**Failed** test #7 (dump core but do not terminate)\n"); + printf("**Failed** test #8 (dump core but do not terminate)\n"); failed = true; if (gotError) printf(" error reported by dumpCore\n"); if (!coreExists) printf(" the core file wasn't written\n"); } else { - printf("Passed test #7 (dump core but do not terminate)\n"); + printf("Passed test #8 (dump core but do not terminate)\n"); } #endif -#if !defined(rs6000_ibm_aix4_1) && !defined(sparc_sun_sunos4_1_3) - printf("Skipping test #8 (dump image)\n"); - printf(" BPatch_thread::dumpImage() not implemented on this platform\n"); +// #if !defined(rs6000_ibm_aix4_1) && !defined(sparc_sun_sunos4_1_3) +#if 1 + printf("Skipping test #9 (dump image)\n"); + printf(" BPatch_thread::dumpImage not implemented on this platform\n"); #else // dump image if (access("myimage", F_OK) == 0) { @@ -310,17 +398,29 @@ main(int argc, char *argv[]) ret->dumpImage("myimage"); bool imageExists = (access("myimage", F_OK) == 0); if (gotError || !imageExists) { - printf("**Failed** test #8 (dump image)\n"); + printf("**Failed** test #9 (dump image)\n"); failed = true; if (gotError) printf(" error reported by dumpImage\n"); if (!imageExists) printf(" the image file wasn't written\n"); } else { - printf("Passed test #8 (dump image)\n"); + printf("Passed test #9 (dump image)\n"); } #endif + // Wait for process to hit breakpoint + waitUntilStopped(ret, 10, "BPatch_breakPointExpr"); + // waitUntilStopped would not return is we didn't stop + printf("Passed test #10 (BPatch_breakPointExpr)\n"); + + // Test getDisplacedInstructions + test11(ret, img); + + /********************************************************************** + * Kill process and make sure it goes away + **********************************************************************/ + int pid = ret->getPid(); #ifndef i386_unknown_nt4_0 /* Not yet implemented on NT. */ @@ -340,16 +440,22 @@ main(int argc, char *argv[]) #endif delete (ret); + bool failed_this = false; BPatch_Vector *threads = bpatch->getThreads(); for (i=0; i < threads->size(); i++) { if ((*threads)[i] == ret) { - printf("**Failed** test #7 (delete thread)\n"); + printf("**Failed** test #12 (delete thread)\n"); // LAST TEST printf(" thread %d was deleted, but getThreads found it\n", ret->getPid()); failed = true; + failed_this = true; } } + if (!failed_this) { + printf("Passed test #12 (delete thread)\n"); // LAST TEST + } + delete (bpatch); if (failed) { diff --git a/dyninstAPI/tests/src/test2.h b/dyninstAPI/tests/src/test2.h index 4af05c2..60414b3 100644 --- a/dyninstAPI/tests/src/test2.h +++ b/dyninstAPI/tests/src/test2.h @@ -3,5 +3,6 @@ #define _test2_h_ #define TEST_DYNAMIC_LIB "libX11.so.4" +#define TEST_DYNAMIC_LIB2 "libXt.so.4" #endif /* _test2_h_ */ diff --git a/dyninstAPI/tests/src/test2.mutatee.c b/dyninstAPI/tests/src/test2.mutatee.c index ddfd78d..c830c92 100644 --- a/dyninstAPI/tests/src/test2.mutatee.c +++ b/dyninstAPI/tests/src/test2.mutatee.c @@ -58,6 +58,15 @@ void stop_process() #endif } +void func10_1() +{ + // Does nothing. Will be instrumented with a BPatch_breakPointExpr +} + +void func11_1() +{ + // Does nothing. +} void main(int argc, char *argv[]) { @@ -95,6 +104,8 @@ void main(int argc, char *argv[]) stop_process(); #endif + func10_1(); + while(1); exit(0); diff --git a/dyninstAPI_RT/src/RTsolaris.c b/dyninstAPI_RT/src/RTsolaris.c index 3e866b2..65167d4 100644 --- a/dyninstAPI_RT/src/RTsolaris.c +++ b/dyninstAPI_RT/src/RTsolaris.c @@ -47,6 +47,7 @@ #include #include #include +#include #include "dyninstAPI_RT/h/rtinst.h" @@ -132,3 +133,11 @@ void DYNINSTtrapHandler(int sig, siginfo_t *info, ucontext_t *uap) { DYNINSTtotalTraps++; } #endif + +int DYNINSTloadLibrary(char *libname) +{ + if (dlopen(libname, RTLD_NOW | RTLD_GLOBAL) != NULL) + return 1; + else + return 0; +} -- 1.8.3.1