From bde59f1e918d774dfab30b6cbd09a2892fd1582b Mon Sep 17 00:00:00 2001 From: buck Date: Tue, 29 Apr 1997 16:58:15 +0000 Subject: [PATCH] Added features to dyninstAPI library, including the ability to delete inserted snippets and the start of type checking. --- dyninstAPI/h/BPatch.h | 97 +++++++++++ dyninstAPI/h/BPatch_Vector.h | 53 ++++-- dyninstAPI/h/BPatch_image.h | 15 +- dyninstAPI/h/BPatch_point.h | 14 +- dyninstAPI/h/BPatch_snippet.h | 26 +-- dyninstAPI/h/BPatch_thread.h | 68 ++++---- dyninstAPI/make.module.tmpl | 12 +- dyninstAPI/src/BPatch.C | 279 ++++++++++++++++++++++++++++++++ dyninstAPI/src/BPatch_image.C | 85 +++++----- dyninstAPI/src/BPatch_init.C | 16 +- dyninstAPI/src/BPatch_snippet.C | 72 +++++++-- dyninstAPI/src/BPatch_templates.C | 24 ++- dyninstAPI/src/BPatch_thread.C | 262 +++++++++++++++--------------- dyninstAPI/src/BPatch_type.C | 123 ++++++++++++++ dyninstAPI/src/BPatch_type.h | 71 ++++++++ dyninstAPI/src/ast.C | 103 ++++++++++++ dyninstAPI/src/ast.h | 25 +++ dyninstAPI/src/templates1.C | 8 + dyninstAPI/tests/make.module.tmpl | 7 +- dyninstAPI/tests/src/test1.C | 33 +++- dyninstAPI/tests/src/test1.mutatee.c | 12 +- dyninstAPI_RT/make.module.tmpl | 10 +- dyninstAPI_RT/src/DYNINSTAPI_RT_EXPORTS | 6 + dyninstAPI_RT/src/RTcommon.c | 10 -- 24 files changed, 1098 insertions(+), 333 deletions(-) create mode 100644 dyninstAPI/h/BPatch.h create mode 100644 dyninstAPI/src/BPatch.C create mode 100644 dyninstAPI/src/BPatch_type.C create mode 100644 dyninstAPI/src/BPatch_type.h create mode 100644 dyninstAPI_RT/src/DYNINSTAPI_RT_EXPORTS diff --git a/dyninstAPI/h/BPatch.h b/dyninstAPI/h/BPatch.h new file mode 100644 index 0000000..3443436 --- /dev/null +++ b/dyninstAPI/h/BPatch.h @@ -0,0 +1,97 @@ +/* + * Copyright (c) 1996 Barton P. Miller + * + * We provide the Paradyn Parallel Performance Tools (below + * described as Paradyn") on an AS IS basis, and do not warrant its + * validity or performance. We reserve the right to update, modify, + * or discontinue this software at any time. We shall have no + * obligation to supply such updates or modifications or any other + * form of support to you. + * + * This license is for research uses. For such uses, there is no + * charge. We define "research use" to mean you may freely use it + * inside your organization for whatever purposes you see fit. But you + * may not re-distribute Paradyn or parts of Paradyn, in any form + * source or binary (including derivatives), electronic or otherwise, + * to any other organization or entity without our permission. + * + * (for other uses, please contact us at paradyn@cs.wisc.edu) + * + * All warranties, including without limitation, any warranty of + * merchantability or fitness for a particular purpose, are hereby + * excluded. + * + * By your use of Paradyn, you understand and agree that we (or any + * other person or entity with proprietary rights in Paradyn) are + * under no obligation to provide either maintenance services, + * update services, notices of latent defects, or correction of + * defects for Paradyn. + * + * Even if advised of the possibility of such damages, under no + * circumstances shall we (or any other person or entity with + * proprietary rights in the software licensed hereunder) be liable + * to you or any third party for direct, indirect, or consequential + * damages of any character regardless of type of action, including, + * without limitation, loss of profits, loss of use, loss of good + * will, or computer failure or malfunction. You agree to indemnify + * us (and any other person or entity with proprietary rights in the + * software licensed hereunder) for any and all liability it may + * incur to third parties resulting from your use of Paradyn. + */ + +#ifndef _BPatch_h_ +#define _BPatch_h_ + +#include "BPatch_Vector.h" +#include "BPatch_thread.h" + +class BPatch_typeCollection; +class BPatch_type; + +typedef enum BPatchErrorLevel { + BPatchFatal, BPatchSerious, BPatchWarning, BPatchInfo +}; + +typedef void (*BPatchErrorCallback)(BPatchErrorLevel severity, + int number, + const char **params); + +class BPatch { + friend bool pollForStatusChange(); + + BPatch_Vector threadVec; + BPatchErrorCallback errorHandler; + bool typeCheckOn; + + BPatch_thread *pidToThread(int pid); +public: + static BPatch *bpatch; + + BPatch_typeCollection *stdTypes; + BPatch_type *type_Error; + BPatch_type *type_Untyped; + + BPatch(); + ~BPatch(); + + // XXX The following function is a temporary hack until we make + // the error reporing work the way we eventually want it to. + void reportError(BPatchErrorLevel severity, int number, const char *str); + + static const char *getEnglishErrorString(int number); + static void formatErrorString(char *dst, int size, + const char *fmt, const char **params); + BPatchErrorCallback registerErrorCallback(BPatchErrorCallback function); + BPatch_Vector *getThreads(); + + void setTypeChecking(bool x) { typeCheckOn = x; } + + // The following are only to be called by the library: + bool isTypeChecked() { return typeCheckOn; } + + void registerThread(BPatch_thread *thread) { threadVec.push_back(thread); } +}; + +extern bool pollForStatusChange(); + +#endif /* _BPatch_h_ */ diff --git a/dyninstAPI/h/BPatch_Vector.h b/dyninstAPI/h/BPatch_Vector.h index abe18de..5e0176e 100644 --- a/dyninstAPI/h/BPatch_Vector.h +++ b/dyninstAPI/h/BPatch_Vector.h @@ -38,16 +38,6 @@ * software licensed hereunder) for any and all liability it may * incur to third parties resulting from your use of Paradyn. */ -/* - * $Log: BPatch_Vector.h,v $ - * Revision 1.1 1997/03/18 19:43:35 buck - * first commit of dyninst library. Also includes: - * moving templates from paradynd to dyninstAPI - * converting showError into a function (in showerror.C) - * many ifdefs for BPATCH_LIBRARY in dyinstAPI/src. - * - * - */ #ifndef _BPatch_Vector_h_ #define _BPatch_Vector_h_ @@ -66,8 +56,13 @@ class BPatch_Vector { T* data; // Points to the array of objects void reserve(int n); + inline void copy_from(const BPatch_Vector &); public: BPatch_Vector(int n = 0); + BPatch_Vector(const BPatch_Vector &); + ~BPatch_Vector(); + + BPatch_Vector& operator=(const BPatch_Vector &); int size() const { return len; } void push_back(const T& x); @@ -99,6 +94,18 @@ void BPatch_Vector::reserve(int n) assert(data != NULL || n == 0); } +// Copy the contents of another vector into this one. +template +inline void BPatch_Vector::copy_from(const BPatch_Vector &src) +{ + reserved = src.reserved; + len = src.len; + data = new T[reserved]; + + for (int i = 0; i < src.len; i++) + data[i] = src.data[i]; +} + // Contructor. Takes one optional parameter, the number of entries for which // to reserve space. template @@ -108,6 +115,32 @@ BPatch_Vector::BPatch_Vector(int n) : reserved(0), len(0), data(NULL) if (n > 0) reserve(n); } +// Copy constructor. +template +BPatch_Vector::BPatch_Vector(const BPatch_Vector &src) +{ + copy_from(src); +} + +// Destructor. Frees allocated memory. +template +BPatch_Vector::~BPatch_Vector() +{ + delete [] data; +} + +// Assignment operator. Delete the contents of this vector and copy the +// contents of the other vector into it. +template +BPatch_Vector& BPatch_Vector::operator=(const BPatch_Vector &src) +{ + delete [] data; + + copy_from(src); + + return *this; +} + // Add an element to the end of the vector. template void BPatch_Vector::push_back(const T& x) diff --git a/dyninstAPI/h/BPatch_image.h b/dyninstAPI/h/BPatch_image.h index 6f47fcc..297f119 100644 --- a/dyninstAPI/h/BPatch_image.h +++ b/dyninstAPI/h/BPatch_image.h @@ -38,16 +38,6 @@ * software licensed hereunder) for any and all liability it may * incur to third parties resulting from your use of Paradyn. */ -/* - * $Log: BPatch_image.h,v $ - * Revision 1.1 1997/03/18 19:43:36 buck - * first commit of dyninst library. Also includes: - * moving templates from paradynd to dyninstAPI - * converting showError into a function (in showerror.C) - * many ifdefs for BPATCH_LIBRARY in dyinstAPI/src. - * - * - */ #ifndef _BPatch_image_h_ #define _BPatch_image_h_ @@ -56,9 +46,9 @@ #include "BPatch_point.h" #include "BPatch_snippet.h" - class process; class image; +class BPatch_type; /* @@ -76,12 +66,11 @@ typedef enum { class BPatch_image { process *proc; - image *symbols; public: // The following functions are for internal use by the library only: BPatch_image(process *_proc); - BPatch_image() : proc(NULL), symbols(NULL) {}; + BPatch_image() : proc(NULL) {}; // End functions for internal use only BPatch_Vector *getProcedures(); diff --git a/dyninstAPI/h/BPatch_point.h b/dyninstAPI/h/BPatch_point.h index 55b059c..4603055 100644 --- a/dyninstAPI/h/BPatch_point.h +++ b/dyninstAPI/h/BPatch_point.h @@ -38,16 +38,6 @@ * software licensed hereunder) for any and all liability it may * incur to third parties resulting from your use of Paradyn. */ -/* - * $Log: BPatch_point.h,v $ - * Revision 1.1 1997/03/18 19:43:36 buck - * first commit of dyninst library. Also includes: - * moving templates from paradynd to dyninstAPI - * converting showError into a function (in showerror.C) - * many ifdefs for BPATCH_LIBRARY in dyinstAPI/src. - * - * - */ #ifndef _BPatch_point_h_ #define _BPatch_point_h_ @@ -60,9 +50,9 @@ class BPatch_point { friend class BPatch_thread; friend class BPatch_image; - instPoint *point; + const instPoint *point; - BPatch_point(const instPoint *_point) : point((instPoint *)_point) {}; + BPatch_point(const instPoint *_point) : point(_point) {}; }; #endif /* _BPatch_point_h_ */ diff --git a/dyninstAPI/h/BPatch_snippet.h b/dyninstAPI/h/BPatch_snippet.h index 5201daa..b3706a8 100644 --- a/dyninstAPI/h/BPatch_snippet.h +++ b/dyninstAPI/h/BPatch_snippet.h @@ -38,16 +38,6 @@ * software licensed hereunder) for any and all liability it may * incur to third parties resulting from your use of Paradyn. */ -/* - * $Log: BPatch_snippet.h,v $ - * Revision 1.1 1997/03/18 19:43:37 buck - * first commit of dyninst library. Also includes: - * moving templates from paradynd to dyninstAPI - * converting showError into a function (in showerror.C) - * many ifdefs for BPATCH_LIBRARY in dyinstAPI/src. - * - * - */ #ifndef _BPatch_snippet_h_ #define _BPatch_snippet_h_ @@ -55,9 +45,11 @@ #include "BPatch_Vector.h" class AstNode; -class pdFunction; +class function_base; class BPatch_function; +class BPatch_type; + typedef enum { BPatch_lt, @@ -86,18 +78,14 @@ typedef enum { BPatch_address } BPatch_unOp; + class BPatch_function { public: // The following are for internal use by the library only: - pdFunction *func; - BPatch_function(pdFunction *_func) : func(_func) {}; + function_base *func; + BPatch_function(function_base *_func) : func(_func) {}; }; -class BPatch_type { - int dummy; -public: - /* XXX Not yet implemented. */ -}; class BPatch_snippet { public: @@ -168,7 +156,7 @@ class BPatch_variableExpr : public BPatch_snippet { void *address; public: // The following functions are for internal use by the library only: - BPatch_variableExpr(void *in_address); + BPatch_variableExpr(void *in_address, const BPatch_type *type); void *getAddress() const { return address; } }; diff --git a/dyninstAPI/h/BPatch_thread.h b/dyninstAPI/h/BPatch_thread.h index d27cd9b..bcbf21f 100644 --- a/dyninstAPI/h/BPatch_thread.h +++ b/dyninstAPI/h/BPatch_thread.h @@ -38,16 +38,6 @@ * software licensed hereunder) for any and all liability it may * incur to third parties resulting from your use of Paradyn. */ -/* - * $Log: BPatch_thread.h,v $ - * Revision 1.1 1997/03/18 19:43:37 buck - * first commit of dyninst library. Also includes: - * moving templates from paradynd to dyninstAPI - * converting showError into a function (in showerror.C) - * many ifdefs for BPATCH_LIBRARY in dyinstAPI/src. - * - * - */ #ifndef _BPatch_thread_h_ #define _BPatch_thread_h_ @@ -57,6 +47,9 @@ #include "BPatch_snippet.h" class process; +class instInstance; +class BPatch_thread; + /* * Used to specify whether a snippet is to be called before the instructions @@ -78,27 +71,44 @@ typedef enum { } BPatch_snippetOrder; -class BPatch_thread { - friend bool pollForStatusChange(); +/* + * Contains information about the code that was inserted by an earlier call to + * Bpatch_thread::insertSnippet. + */ +class BPatchSnippetHandle { +private: + friend class BPatch_thread; + + process *proc; + BPatch_Vector instance; - static BPatch_Vector threadVec; + BPatchSnippetHandle(process *_proc) : proc(_proc) {}; + ~BPatchSnippetHandle(); + + void add(instInstance *pointInstance); +}; - static BPatch_thread *pidToThread(int pid); - static bool lib_inited; + +/* + * Represents a thread of execution. + */ +class BPatch_thread { + friend bool pollForStatusChange(); process *proc; BPatch_image *image; int lastSignal; + bool mutationsActive; - int getPid(); public: - BPatch_thread(char *path, char *argv[], char *envp[] = NULL); BPatch_thread(char *path, int pid); ~BPatch_thread(); BPatch_image *getImage() { return image; } + int getPid(); + bool stopExecution(); bool continueExecution(); bool terminateExecution(); @@ -107,22 +117,26 @@ public: int stopSignal(); bool isTerminated(); + void detach(bool cont); + bool dumpCore(const char *file, bool terminate); BPatch_variableExpr *malloc(int n); BPatch_variableExpr *malloc(const BPatch_type &type); void free(const BPatch_variableExpr &ptr); - bool insertSnippet(const BPatch_snippet &expr, - const BPatch_point &point, - BPatch_callWhen when = BPatch_callBefore, - BPatch_snippetOrder order = BPatch_firstSnippet); - bool insertSnippet(const BPatch_snippet &expr, - const BPatch_Vector &points, - BPatch_callWhen when = BPatch_callBefore, - BPatch_snippetOrder order = BPatch_firstSnippet); + BPatchSnippetHandle *insertSnippet( + const BPatch_snippet &expr, + const BPatch_point &point, + BPatch_callWhen when = BPatch_callBefore, + BPatch_snippetOrder order = BPatch_firstSnippet); + BPatchSnippetHandle *insertSnippet( + const BPatch_snippet &expr, + const BPatch_Vector &points, + BPatch_callWhen when = BPatch_callBefore, + BPatch_snippetOrder order = BPatch_firstSnippet); + + bool deleteSnippet(BPatchSnippetHandle *handle); }; -extern bool pollForStatusChange(); - #endif /* BPatch_thread_h_ */ diff --git a/dyninstAPI/make.module.tmpl b/dyninstAPI/make.module.tmpl index 629328c..59b2e0c 100644 --- a/dyninstAPI/make.module.tmpl +++ b/dyninstAPI/make.module.tmpl @@ -3,14 +3,6 @@ # intended to be a useful Makefile in isolation; instead, it should be # included from within an architecture-specific Makefile. # -# $Log: make.module.tmpl,v $ -# Revision 1.1 1997/03/18 19:43:26 buck -# first commit of dyninst library. Also includes: -# moving templates from paradynd to dyninstAPI -# converting showError into a function (in showerror.C) -# many ifdefs for BPATCH_LIBRARY in dyinstAPI/src. -# -# # CFLAGS += $(TCLFRIENDLYWARNINGS) -DBPATCH_LIBRARY -UMT_THREAD @@ -22,10 +14,12 @@ TARGET = libdyninstAPI.a VPATH += .././.dyninstAPI/src:../dyninstAPI/h:\ ../../paradynd/src:../../paradyn/h -SRCS += ../src/BPatch_image.C \ +SRCS += ../src/BPatch.C \ + ../src/BPatch_image.C \ ../src/BPatch_snippet.C \ ../src/BPatch_templates.C \ ../src/BPatch_thread.C \ + ../src/BPatch_type.C \ ../src/BPatch_init.C \ ../src/dummy.C \ ../src/api_showerror.C \ diff --git a/dyninstAPI/src/BPatch.C b/dyninstAPI/src/BPatch.C new file mode 100644 index 0000000..effccda --- /dev/null +++ b/dyninstAPI/src/BPatch.C @@ -0,0 +1,279 @@ +/* + * Copyright (c) 1996 Barton P. Miller + * + * We provide the Paradyn Parallel Performance Tools (below + * described as Paradyn") on an AS IS basis, and do not warrant its + * validity or performance. We reserve the right to update, modify, + * or discontinue this software at any time. We shall have no + * obligation to supply such updates or modifications or any other + * form of support to you. + * + * This license is for research uses. For such uses, there is no + * charge. We define "research use" to mean you may freely use it + * inside your organization for whatever purposes you see fit. But you + * may not re-distribute Paradyn or parts of Paradyn, in any form + * source or binary (including derivatives), electronic or otherwise, + * to any other organization or entity without our permission. + * + * (for other uses, please contact us at paradyn@cs.wisc.edu) + * + * All warranties, including without limitation, any warranty of + * merchantability or fitness for a particular purpose, are hereby + * excluded. + * + * By your use of Paradyn, you understand and agree that we (or any + * other person or entity with proprietary rights in Paradyn) are + * under no obligation to provide either maintenance services, + * update services, notices of latent defects, or correction of + * defects for Paradyn. + * + * Even if advised of the possibility of such damages, under no + * circumstances shall we (or any other person or entity with + * proprietary rights in the software licensed hereunder) be liable + * to you or any third party for direct, indirect, or consequential + * damages of any character regardless of type of action, including, + * without limitation, loss of profits, loss of use, loss of good + * will, or computer failure or malfunction. You agree to indemnify + * us (and any other person or entity with proprietary rights in the + * software licensed hereunder) for any and all liability it may + * incur to third parties resulting from your use of Paradyn. + */ + +#include +#include +#include +#include + +#include "BPatch.h" +#include "BPatch_type.h" +#include "process.h" + +extern bool dyninstAPI_init(); +extern int dyninstAPI_handleSigChild(int pid, int status); + + +BPatch *BPatch::bpatch = NULL; + + +/* + * BPatch::BPatch + * + * Constructor for BPatch. Performs one-time initialization needed by the + * library. + */ +BPatch::BPatch() : errorHandler(NULL), typeCheckOn(true) +{ + extern bool init(); + extern double cyclesPerSecond; + extern double timing_loop(const unsigned, const unsigned); + + // Save a pointer to the one-and-only bpatch object. + if (bpatch == NULL) + bpatch = this; + /* XXX else + * (indicate an error somehow) + */ + + // XXX dyninstAPI_init returns success/failure -- should pass on somehow + dyninstAPI_init(); + cyclesPerSecond = timing_loop(1, 100000) * 1000000; + + /* + * Create the "error" and "untyped" types. + */ + type_Error = new BPatch_type("", true); + type_Untyped = new BPatch_type("", true); + + /* + * Initialize hash table of standard types. + */ + stdTypes = new BPatch_typeCollection; + stdTypes->addType(new BPatch_type("int")); + stdTypes->addType(new BPatch_type("char *")); +} + + +/* + * BPatch::~BPatch + * + * Destructor for BPatch. Free allocated memory. + */ +BPatch::~BPatch() +{ + delete type_Error; + delete type_Untyped; + + delete stdTypes; +} + + +/* + * BPatch::registerErrorCallback + * + * Registers a function that is to be called by the library when an error + * occurs or when there is status to report. Returns the address of the + * previously registered error callback function. + * + * function The function to be called. + */ +BPatchErrorCallback BPatch::registerErrorCallback(BPatchErrorCallback function) +{ + BPatchErrorCallback ret; + + ret = errorHandler; + errorHandler = function; + + return ret; +} + + +/* + * BPatch::getEnglishErrorString + * + * Returns the descriptive error string for the passed error number. + * + * number The number that identifies the error. + */ +const char *BPatch::getEnglishErrorString(int /* number */) +{ + return "%s"; +} + + +/* + * BPatch::reportError + * + * Report an error using the callback mechanism. + * + * severity The severity level of the error. + * number Identifies the error. + * str A string to pass as the first element of the list of strings + * given to the callback function. + */ +void BPatch::reportError(BPatchErrorLevel severity, int number, const char *str) +{ + if (errorHandler != NULL) { + errorHandler(severity, number, &str); + } +} + + +/* + * BPatch::formatErrorString + * + * Takes a format string with an error message (obtained from + * getEnglishErrorString) and an array of parameters that were passed to an + * error callback function, and creates a string with the parameters + * substituted into it. + * + * dst The address into which the formatted string should be copied. + * size If the formatted string is equal to or longer than this number + * of characters, then it will be truncated to size-1 characters + * and terminated with a nul ('\0'). + * fmt The format string (returned by a function such as + * getEnglishErrorString). + * params The array of parameters that were passed to an error callback + * function. + */ +void BPatch::formatErrorString(char *dst, int size, + const char *fmt, const char **params) +{ + int cur_param = 0; + + while (size > 1 && *fmt) { + if (*fmt == '%') { + if (fmt[1] == '\0') { + break; + } else if (fmt[1] == '%') { + *dst++ = '%'; + size--; + } else if (fmt[1] == 's') { + char *p = (char *)params[cur_param++]; + while (size > 1 && *p) { + *dst++ = *p++; + size--; + } + } else { + // Illegal specifier + *dst++ = fmt[0]; + *dst++ = fmt[1]; + size -= 2; + } + fmt += 2; + } else { + *dst++ = *fmt++; + size--; + } + } + if (size > 0) + *dst = '\0'; +} + + +/* + * BPatch::pidToThread + * + * Given a process ID, this function returns a pointer to the associated + * BPatch_thread object (or NULL if there is none). + */ +BPatch_thread *BPatch::pidToThread(int pid) +{ + for (int i = 0; i < threadVec.size(); i++) + if (threadVec[i]->getPid() == pid) return threadVec[i]; + + return NULL; +} + + +/* + * BPatch::getThreads + * + * Returns a vector of all threads that are currently defined. Includes + * threads created directly using the library and those created with UNIX fork + * or Windows NT spawn system calls. The caller is responsible for deleting + * the vector when it is no longer needed. + */ +BPatch_Vector *BPatch::getThreads() +{ + BPatch_Vector *result = new BPatch_Vector; + + *result = threadVec; + + return result; +} + + +/* + * pollForStatusChange + * + * Checks for changes in the state of any child process, and returns true if + * it discovers any such changes. Also updates the process object + * representing each process for which a change is detected. + * + * This function is declared as a friend of BPatch_thread so that it can use + * the BPatch_thread::pidToThread call and so that it can set the lastSignal + * member of a BPatch_thread object. + */ +bool pollForStatusChange() +{ + bool result = false; + int pid, status; + + while ((pid = process::waitProcs(&status)) > 0) { + // There's been a change in a child process + result = true; + assert(BPatch::bpatch != NULL); + BPatch_thread *thread = BPatch::bpatch->pidToThread(pid); + assert(thread != NULL); + if (thread != NULL) { + if (WIFSTOPPED(status)) + thread->lastSignal = WSTOPSIG(status); + else if (WIFSIGNALED(status)) + thread->lastSignal = WTERMSIG(status); + else if (WIFEXITED(status)) + thread->lastSignal = 0; /* XXX Make into some constant */ + } + dyninstAPI_handleSigChild(pid, status); + } + return result; +} diff --git a/dyninstAPI/src/BPatch_image.C b/dyninstAPI/src/BPatch_image.C index 0fcf5c4..227805e 100644 --- a/dyninstAPI/src/BPatch_image.C +++ b/dyninstAPI/src/BPatch_image.C @@ -38,16 +38,6 @@ * software licensed hereunder) for any and all liability it may * incur to third parties resulting from your use of Paradyn. */ -/* - * $Log: BPatch_image.C,v $ - * Revision 1.1 1997/03/18 19:44:01 buck - * first commit of dyninst library. Also includes: - * moving templates from paradynd to dyninstAPI - * converting showError into a function (in showerror.C) - * many ifdefs for BPATCH_LIBRARY in dyinstAPI/src. - * - * - */ #include #include @@ -56,7 +46,9 @@ #include "process.h" #include "symtab.h" +#include "BPatch.h" #include "BPatch_image.h" +#include "BPatch_type.h" /* @@ -65,8 +57,7 @@ * Construct a BPatch_image for the given process. */ -BPatch_image::BPatch_image(process *_proc) : - proc(_proc), symbols(_proc->symbols) +BPatch_image::BPatch_image(process *_proc) : proc(_proc) { } @@ -84,12 +75,16 @@ BPatch_Vector *BPatch_image::getProcedures() if (proclist == NULL) return NULL; - for (unsigned int m = 0; m < symbols->mods.size(); m++) { - for (int f = 0; f < symbols->mods[m]->funcs.size(); f++) { - BPatch_function *bpfunc = - new BPatch_function(symbols->mods[m]->funcs[f]); - proclist->push_back(bpfunc); - } + // XXX Maybe getIncludedFunction instead? Depends on what we want + // to do to support the MDL exclude_lib function. + // XXX Also, what should we do about getting rid of this? Should + // the BPatch_functions already be made and kept around as long + // as the process is, so the user doesn't have to delete them? + vector *funcs = proc->getAllFunctions(); + + for (unsigned int f = 0; f < funcs->size(); f++) { + BPatch_function *bpfunc = new BPatch_function((*funcs)[f]); + proclist->push_back(bpfunc); } return proclist; @@ -116,30 +111,33 @@ BPatch_Vector *BPatch_image::getProcedures() BPatch_Vector *BPatch_image::findProcedurePoint( const char *name, const BPatch_procedureLocation loc) { - vector flist; + /* + * XXXX We'd like to get a list of the functions with the name: + vector flist; - if (!symbols->findFunction(name, flist)) + if (!proc->findFunction(name, flist)) return NULL; + * but we don't seem to have a way to do that right now. + */ + + function_base *func = proc->findOneFunction(name); BPatch_Vector *result = new BPatch_Vector; - for (unsigned func_num = 0; func_num < flist.size(); func_num++) { +// for (unsigned func_num = 0; func_num < flist.size(); func_num++) { if (loc == BPatch_entry || loc == BPatch_allLocations) { - BPatch_point *new_point = - new BPatch_point(flist[func_num]->funcEntry(proc)); + BPatch_point *new_point = new BPatch_point(func->funcEntry(proc)); result->push_back(new_point); } if (loc == BPatch_exit || loc == BPatch_allLocations) { - const vector &points = - flist[func_num]->funcExits(proc); + const vector &points = func->funcExits(proc); for (unsigned i = 0; i < points.size(); i++) { BPatch_point *new_point = new BPatch_point(points[i]); result->push_back(new_point); } } if (loc == BPatch_subroutine || loc == BPatch_allLocations) { - const vector &points = - flist[func_num]->funcCalls(proc); + const vector &points = func->funcCalls(proc); for (unsigned i = 0; i < points.size(); i++) { BPatch_point *new_point = new BPatch_point(points[i]); result->push_back(new_point); @@ -149,7 +147,7 @@ BPatch_Vector *BPatch_image::findProcedurePoint( /* XXX Not yet implemented */ assert( 0 ); } - } +// } return result; } @@ -165,12 +163,12 @@ BPatch_Vector *BPatch_image::findProcedurePoint( */ BPatch_function *BPatch_image::findFunction(const char *name) { - pdFunction *pdf = symbols->findOneFunction(name); + function_base *func = proc->findOneFunction(name); - if (pdf == NULL) + if (func == NULL) return NULL; - return new BPatch_function(pdf); + return new BPatch_function(func); } @@ -197,7 +195,10 @@ BPatch_variableExpr *BPatch_image::findVariable(const char *name) } } - return new BPatch_variableExpr((void *)syminfo.addr()); + // XXX Need to find out type and use it + BPatch_type *type = BPatch::bpatch->type_Untyped; + + return new BPatch_variableExpr((void *)syminfo.addr(), type); } /* @@ -207,19 +208,15 @@ BPatch_variableExpr *BPatch_image::findVariable(const char *name) * exists, returns NULL. * * name The name of type to look up. - * - * XXX This function has not yet been implemented. The only type that is - * supported is type "int." */ BPatch_type *BPatch_image::findType(const char *name) { - static BPatch_type type; - - if (strcmp(name, "int") != 0) { - fprintf(stderr, "Call to BPatch_image::findType with a type name other than int.\n"); - fprintf(stderr, "(Types are not yet implemented; only \"int\" is available.\n"); - } - - // The return value is a dummy which will never be used - return &type; + assert(BPatch::bpatch != NULL); + return BPatch::bpatch->stdTypes->findType(name); + + /* + * XXX When we have the info we need from the symbol table, we'll add some + * more code here that checks it if "name" isn't found in the standard + * types. + */ } diff --git a/dyninstAPI/src/BPatch_init.C b/dyninstAPI/src/BPatch_init.C index 2f939b9..1331366 100644 --- a/dyninstAPI/src/BPatch_init.C +++ b/dyninstAPI/src/BPatch_init.C @@ -38,16 +38,6 @@ * software licensed hereunder) for any and all liability it may * incur to third parties resulting from your use of Paradyn. */ -/* - * $Log: BPatch_init.C,v $ - * Revision 1.1 1997/03/18 19:44:02 buck - * first commit of dyninst library. Also includes: - * moving templates from paradynd to dyninstAPI - * converting showError into a function (in showerror.C) - * many ifdefs for BPATCH_LIBRARY in dyinstAPI/src. - * - * - */ #include "dyninstAPI/src/dyninstP.h" // nullString @@ -62,7 +52,7 @@ int numberOfCPUs; vector initialRequests; vector syms_to_find; -bool init() { +bool dyninstAPI_init() { sym_data sd; @@ -77,9 +67,5 @@ bool init() { numberOfCPUs = getNumberOfCPUs(); initDefaultPointFrequencyTable(); - -#if !defined(BPATCH_LIBRARY) - return (initOS()); -#endif } diff --git a/dyninstAPI/src/BPatch_snippet.C b/dyninstAPI/src/BPatch_snippet.C index f8cf9b1..ef2345c 100644 --- a/dyninstAPI/src/BPatch_snippet.C +++ b/dyninstAPI/src/BPatch_snippet.C @@ -38,22 +38,14 @@ * software licensed hereunder) for any and all liability it may * incur to third parties resulting from your use of Paradyn. */ -/* - * $Log: BPatch_snippet.C,v $ - * Revision 1.1 1997/03/18 19:44:02 buck - * first commit of dyninst library. Also includes: - * moving templates from paradynd to dyninstAPI - * converting showError into a function (in showerror.C) - * many ifdefs for BPATCH_LIBRARY in dyinstAPI/src. - * - * - */ #include "ast.h" #include "symtab.h" #include "perfStream.h" +#include "BPatch.h" #include "BPatch_snippet.h" +#include "BPatch_type.h" /* @@ -75,6 +67,10 @@ BPatch_snippet::BPatch_snippet(const BPatch_snippet &src) */ BPatch_snippet &BPatch_snippet::operator=(const BPatch_snippet &src) { + // Check for x = x + if (&src == this) + return *this; + // Since we're copying over this snippet, release the old AST if (ast != NULL) removeAst(ast); @@ -122,6 +118,8 @@ BPatch_snippet::~BPatch_snippet() BPatch_arithExpr::BPatch_arithExpr(BPatch_binOp op, const BPatch_snippet &lOperand, const BPatch_snippet &rOperand) { + assert(BPatch::bpatch != NULL); + opCode astOp; switch(op) { case BPatch_assign: @@ -149,6 +147,7 @@ BPatch_arithExpr::BPatch_arithExpr(BPatch_binOp op, break; case BPatch_seq: ast = new AstNode(lOperand.ast, rOperand.ast); + ast->setTypeChecking(BPatch::bpatch->isTypeChecked()); return; default: /* XXX handle error */ @@ -156,6 +155,7 @@ BPatch_arithExpr::BPatch_arithExpr(BPatch_binOp op, }; ast = new AstNode(astOp, lOperand.ast, rOperand.ast); + ast->setTypeChecking(BPatch::bpatch->isTypeChecked()); } @@ -204,6 +204,8 @@ BPatch_boolExpr::BPatch_boolExpr(BPatch_relOp op, }; ast = new AstNode(astOp, lOperand.ast, rOperand.ast); + assert(BPatch::bpatch != NULL); + ast->setTypeChecking(BPatch::bpatch->isTypeChecked()); } @@ -217,6 +219,14 @@ BPatch_boolExpr::BPatch_boolExpr(BPatch_relOp op, BPatch_constExpr::BPatch_constExpr(int value) { ast = new AstNode(AstNode::Constant, (void *)value); + + assert(BPatch::bpatch != NULL); + ast->setTypeChecking(BPatch::bpatch->isTypeChecked()); + + BPatch_type *type = BPatch::bpatch->stdTypes->findType("int"); + assert(type != NULL); + + ast->setType(type); } @@ -230,6 +240,14 @@ BPatch_constExpr::BPatch_constExpr(int value) BPatch_constExpr::BPatch_constExpr(const char *value) { ast = new AstNode(AstNode::ConstantString, (void *)value); + + assert(BPatch::bpatch != NULL); + ast->setTypeChecking(BPatch::bpatch->isTypeChecked()); + + BPatch_type *type = BPatch::bpatch->stdTypes->findType("char *"); + assert(type != NULL); + + ast->setType(type); } @@ -252,9 +270,11 @@ BPatch_funcCallExpr::BPatch_funcCallExpr( ast = new AstNode(func.func->prettyName(), ast_args); - // XXX Is out reference counting stuff here correct? for (int i = 0; i < args.size(); i++) removeAst(ast_args[i]); + + assert(BPatch::bpatch != NULL); + ast->setTypeChecking(BPatch::bpatch->isTypeChecked()); } @@ -270,6 +290,9 @@ BPatch_ifExpr::BPatch_ifExpr(const BPatch_boolExpr &conditional, const BPatch_snippet &tClause) { ast = new AstNode(ifOp, conditional.ast, tClause.ast); + + assert(BPatch::bpatch != NULL); + ast->setTypeChecking(BPatch::bpatch->isTypeChecked()); } @@ -280,7 +303,10 @@ BPatch_ifExpr::BPatch_ifExpr(const BPatch_boolExpr &conditional, */ BPatch_nullExpr::BPatch_nullExpr() { - ast = NULL; /* XXX This will cause other functions to crash right now. */ + ast = new AstNode; + + assert(BPatch::bpatch != NULL); + ast->setTypeChecking(BPatch::bpatch->isTypeChecked()); } @@ -296,6 +322,9 @@ BPatch_nullExpr::BPatch_nullExpr() BPatch_paramExpr::BPatch_paramExpr(int n) { ast = new AstNode(AstNode::Param, (void *)n); + + assert(BPatch::bpatch != NULL); + ast->setTypeChecking(BPatch::bpatch->isTypeChecked()); } @@ -308,12 +337,19 @@ BPatch_paramExpr::BPatch_paramExpr(int n) */ BPatch_sequence::BPatch_sequence(const BPatch_Vector &items) { - if (items.size() == 0) return; + if (items.size() == 0) { + // XXX do something to indicate an error + return; + } + + assert(BPatch::bpatch != NULL); ast = new AstNode(items[0]->ast); + ast->setTypeChecking(BPatch::bpatch->isTypeChecked()); for (int i = 1; i < items.size(); i++) { AstNode *tempAst = new AstNode(ast, items[i]->ast); + tempAst->setTypeChecking(BPatch::bpatch->isTypeChecked()); removeAst(ast); ast = tempAst; } @@ -324,13 +360,17 @@ BPatch_sequence::BPatch_sequence(const BPatch_Vector &items) * BPatch_variableExpr::BPatch_variableExpr * * Construct a snippet representing a variable at the given address. - * XXX Since the type system has not been implemented, the variable has no - * specific size or type. * * in_address The address of the variable in the inferior's address space. */ -BPatch_variableExpr::BPatch_variableExpr(void *in_address) : +BPatch_variableExpr::BPatch_variableExpr(void *in_address, + const BPatch_type *type) : address(in_address) { ast = new AstNode(AstNode::DataAddr, address); + + assert(BPatch::bpatch != NULL); + ast->setTypeChecking(BPatch::bpatch->isTypeChecked()); + + ast->setType(type); } diff --git a/dyninstAPI/src/BPatch_templates.C b/dyninstAPI/src/BPatch_templates.C index fa6f7e6..44ea99d 100644 --- a/dyninstAPI/src/BPatch_templates.C +++ b/dyninstAPI/src/BPatch_templates.C @@ -38,21 +38,19 @@ * software licensed hereunder) for any and all liability it may * incur to third parties resulting from your use of Paradyn. */ -/* - * $Log: BPatch_templates.C,v $ - * Revision 1.1 1997/03/18 19:44:03 buck - * first commit of dyninst library. Also includes: - * moving templates from paradynd to dyninstAPI - * converting showError into a function (in showerror.C) - * many ifdefs for BPATCH_LIBRARY in dyinstAPI/src. - * - * - */ #pragma implementation "BPatch_Vector.h" - #include "BPatch_Vector.h" -#include "BPatch_thread.h" -template class BPatch_Vector; +class BPatch_function; +class BPatch_point; +class BPatch_snippet; +class BPatch_thread; + +class instInstance; + template class BPatch_Vector; +template class BPatch_Vector; +template class BPatch_Vector; +template class BPatch_Vector; +template class BPatch_Vector; diff --git a/dyninstAPI/src/BPatch_thread.C b/dyninstAPI/src/BPatch_thread.C index fb2b118..36587fa 100644 --- a/dyninstAPI/src/BPatch_thread.C +++ b/dyninstAPI/src/BPatch_thread.C @@ -38,100 +38,18 @@ * software licensed hereunder) for any and all liability it may * incur to third parties resulting from your use of Paradyn. */ -/* - * $Log: BPatch_thread.C,v $ - * Revision 1.1 1997/03/18 19:44:03 buck - * first commit of dyninst library. Also includes: - * moving templates from paradynd to dyninstAPI - * converting showError into a function (in showerror.C) - * many ifdefs for BPATCH_LIBRARY in dyinstAPI/src. - * - * - */ -#include "inst.h" #include "process.h" +#include "inst.h" +#include "instP.h" +#include "BPatch.h" #include "BPatch_thread.h" -extern int dyninstAPI_handleSigChild(int pid, int status); extern process *dyninstAPI_createProcess(const string File, vector argv, vector envp, const string dir = ""); extern process *dyninstAPI_attachProcess(const string &progpath, int pid, int afterAttach); -extern void BPatch_init(); - -BPatch_Vector BPatch_thread::threadVec; -bool BPatch_thread::lib_inited = FALSE; - - -/* - * BPatch_init - * - * Initializes the dyninstAPI lirbary. - * XXX This function really doesn't belong here. It will be moved out as soon - * as we create the BPatch class that represents the library (it will be - * moved to the constructor for that class). - */ -void BPatch_init() -{ - extern bool init(); - extern double cyclesPerSecond; - extern double timing_loop(const unsigned, const unsigned); - - init(); - cyclesPerSecond = timing_loop(1, 100000) * 1000000; -} - - -/* - * pollForStatusChange - * - * Checks for changes in the state of any child process, and returns true if - * it discovers any such changes. Also updates the process object - * representing each process for which a change is detected. - * - * This function is declared as a friend of BPatch_thread so that it can use - * the BPatch_thread::pidToThread call and so that it can set the lastSignal - * member of a BPatch_thread object. - */ -bool pollForStatusChange() -{ - bool result = false; - int pid, status; - - while ((pid = process::waitProcs(&status)) > 0) { - // There's been a change in a child process - result = true; - BPatch_thread *thread = BPatch_thread::pidToThread(pid); - assert(thread != NULL); - if (thread != NULL) { - if (WIFSTOPPED(status)) - thread->lastSignal = WSTOPSIG(status); - else if (WIFSIGNALED(status)) - thread->lastSignal = WTERMSIG(status); - else if (WIFEXITED(status)) - thread->lastSignal = 0; /* XXX Make into some constant */ - } - dyninstAPI_handleSigChild(pid, status); - } - return result; -} - - -/* - * static BPatch_thread::pidToThread - * - * Given a process ID, this function returns a pointer to the associated - * BPatch_thread object (or NULL if there is none). - */ -BPatch_thread *BPatch_thread::pidToThread(int pid) -{ - for (int i = 0; i < threadVec.size(); i++) - if (threadVec[i]->getPid() == pid) return threadVec[i]; - - return NULL; -} /* @@ -163,11 +81,6 @@ int BPatch_thread::getPid() BPatch_thread::BPatch_thread(char *path, char *argv[], char *envp[]) : lastSignal(-1) { - if (!lib_inited) { - BPatch_init(); - lib_inited = TRUE; - } - vector argv_vec; vector envp_vec; @@ -188,7 +101,8 @@ BPatch_thread::BPatch_thread(char *path, char *argv[], char *envp[]) // Add this object to the list of threads // XXX Should be conditional on success of creating process - threadVec.push_back(this); + assert(BPatch::bpatch != NULL); + BPatch::bpatch->registerThread(this); image = new BPatch_image(proc); } @@ -206,18 +120,14 @@ BPatch_thread::BPatch_thread(char *path, char *argv[], char *envp[]) BPatch_thread::BPatch_thread(char *path, int pid) : lastSignal(-1) { - if (!lib_inited) { - BPatch_init(); - lib_inited = TRUE; - } - proc = dyninstAPI_attachProcess(path, pid, 1); // XXX Should do something more sensible if (proc == NULL) return; // Add this object to the list of threads - threadVec.push_back(this); + assert(BPatch::bpatch != NULL); + BPatch::bpatch->registerThread(this); image = new BPatch_image(proc); } @@ -318,6 +228,20 @@ bool BPatch_thread::isTerminated() /* + * BPatch_thread::detach + * + * Detach from the thread represented by this object. + * + * cont True if the thread should be continued as the result of the + * detach, false if it should not. + */ +void BPatch_thread::detach(bool cont) +{ + proc->detach(cont); +} + + +/* * BPatch_thread::dumpCore * * Causes the thread to dump its state to a file, and optionally to terminate. @@ -363,7 +287,11 @@ bool BPatch_thread::dumpCore(const char *file, bool terminate) */ BPatch_variableExpr *BPatch_thread::malloc(int n) { - return new BPatch_variableExpr((void *)inferiorMalloc(proc, n, dataHeap)); + // XXX What to do about the type? + assert(BPatch::bpatch != NULL); + return new BPatch_variableExpr( + (void *)inferiorMalloc(proc, n, dataHeap), + BPatch::bpatch->type_Untyped); } @@ -385,7 +313,7 @@ BPatch_variableExpr *BPatch_thread::malloc(int n) BPatch_variableExpr *BPatch_thread::malloc(const BPatch_type &type) { /* - * XXX For now, the only type supported is "int." + * XXX For now, the only type that will work is "int." */ void *mem = (void *)inferiorMalloc(proc, sizeof(int), dataHeap); @@ -393,7 +321,7 @@ BPatch_variableExpr *BPatch_thread::malloc(const BPatch_type &type) int zero = 0; proc->writeDataSpace((char *)mem, sizeof(int), (char *)&zero); - return new BPatch_variableExpr(mem); + return new BPatch_variableExpr(mem, &type); } @@ -415,15 +343,41 @@ void BPatch_thread::free(const BPatch_variableExpr &ptr) /* * BPatch_thread::insertSnippet * - * Insert a code snippet at a given instrumentation point. + * Insert a code snippet at a given instrumentation point. Upon succes, + * returns a handle to the created instance of the snippet, which can be used + * to delete it. Otherwise returns NULL. * * expr The snippet to insert. * point The point at which to insert it. */ -bool BPatch_thread::insertSnippet(const BPatch_snippet &expr, - const BPatch_point &point, - BPatch_callWhen when, - BPatch_snippetOrder order) +BPatchSnippetHandle *BPatch_thread::insertSnippet(const BPatch_snippet &expr, + const BPatch_point &point, + BPatch_callWhen when, + BPatch_snippetOrder order) +{ + BPatch_Vector point_vec; + + point_vec.push_back((BPatch_point *)&point); + + return insertSnippet(expr, point_vec, when, order); +} + + +/* + * BPatch_thread::insertSnippet + * + * Insert a code snippet at each of a list of instrumentation points. Upon + * success, Returns a handle to the created instances of the snippet, which + * can be used to delete them (as a unit). Otherwise returns NULL. + * + * expr The snippet to insert. + * points The list of points at which to insert it. + */ +BPatchSnippetHandle *BPatch_thread::insertSnippet( + const BPatch_snippet &expr, + const BPatch_Vector &points, + BPatch_callWhen when, + BPatch_snippetOrder order) { callWhen _when; callOrder _order; @@ -436,7 +390,7 @@ bool BPatch_thread::insertSnippet(const BPatch_snippet &expr, _when = callPostInsn; break; default: - return false; + return NULL; }; switch (order) { @@ -447,44 +401,86 @@ bool BPatch_thread::insertSnippet(const BPatch_snippet &expr, _order = orderLastAtPoint; break; default: - return false; + return NULL; } - // XXX We just pass false for the "noCost" parameter here - do we want to - // make that an option? - if (addInstFunc(proc, - ((BPatch_point)point).point, /* XXX Cast away const */ - ((BPatch_snippet)expr).ast, /* XXX Cast away const */ - _when, - _order, - false) != NULL) + assert(BPatch::bpatch != NULL); // We'll use this later + + BPatchSnippetHandle *handle = new BPatchSnippetHandle(proc); + + for (int i = 0; i < points.size(); i++) { + instPoint *point = points[i]->point; + + // XXX Really only need to type check once per function the snippet is + // being inserted into, not necessarily once per point. + if (expr.ast->checkType() == BPatch::bpatch->type_Error) { + // XXX Type check error - should call callback + delete handle; + return NULL; + } + + // XXX We just pass false for the "noCost" parameter here - do we want + // to make that an option? + instInstance *instance; + if ((instance = + addInstFunc(proc, + point, + ((BPatch_snippet)expr).ast, /* XXX no const */ + _when, + _order, + false)) != NULL) { + handle->add(instance); + } else { + delete handle; + return NULL; + } + } + return handle; +} + + +/* + * BPatch_thread::deleteSnippet + * + * Deletes an instance of a snippet. + * + * handle The handle returned by insertSnippet when the instance to + * deleted was created. + */ +bool BPatch_thread::deleteSnippet(BPatchSnippetHandle *handle) +{ + if (handle->proc == proc) { + delete handle; return true; - else + } else { // Handle isn't to a snippet instance in this process return false; + } } /* - * BPatch_thread::insertSnippet + * BPatchSnippetHandle::add * - * Insert a code snippet at each of a list of instrumentation points. + * Add an instance of a snippet to the list of instances held by the + * BPatchSnippetHandle. * - * expr The snippet to insert. - * points The list of points at which to insert it. + * instance The instance to add. */ -bool BPatch_thread::insertSnippet(const BPatch_snippet &expr, - const BPatch_Vector &points, - BPatch_callWhen when, - BPatch_snippetOrder order) +void BPatchSnippetHandle::add(instInstance *pointInstance) { - /* - * XXX We should change this so either all instrumentation gets inserted - * or none of it does. - */ - for (int i = 0; i < points.size(); i++) { - if (!insertSnippet(expr, *points[i], when, order)) - return false; - } + assert(pointInstance->proc == proc); + instance.push_back(pointInstance); +} - return true; + +/* + * BPatchSnippetHandle::~BPatchSnippetHandle + * + * Destructor for BPatchSnippetHandle. Delete the snippet instance(s) + * associated with the BPatchSnippetHandle. + */ +BPatchSnippetHandle::~BPatchSnippetHandle() +{ + for (int i = 0; i < instance.size(); i++) + deleteInst(instance[i], getAllTrampsAtPoint(instance[i])); } diff --git a/dyninstAPI/src/BPatch_type.C b/dyninstAPI/src/BPatch_type.C new file mode 100644 index 0000000..a68d157 --- /dev/null +++ b/dyninstAPI/src/BPatch_type.C @@ -0,0 +1,123 @@ +/* + * Copyright (c) 1996 Barton P. Miller + * + * We provide the Paradyn Parallel Performance Tools (below + * described as Paradyn") on an AS IS basis, and do not warrant its + * validity or performance. We reserve the right to update, modify, + * or discontinue this software at any time. We shall have no + * obligation to supply such updates or modifications or any other + * form of support to you. + * + * This license is for research uses. For such uses, there is no + * charge. We define "research use" to mean you may freely use it + * inside your organization for whatever purposes you see fit. But you + * may not re-distribute Paradyn or parts of Paradyn, in any form + * source or binary (including derivatives), electronic or otherwise, + * to any other organization or entity without our permission. + * + * (for other uses, please contact us at paradyn@cs.wisc.edu) + * + * All warranties, including without limitation, any warranty of + * merchantability or fitness for a particular purpose, are hereby + * excluded. + * + * By your use of Paradyn, you understand and agree that we (or any + * other person or entity with proprietary rights in Paradyn) are + * under no obligation to provide either maintenance services, + * update services, notices of latent defects, or correction of + * defects for Paradyn. + * + * Even if advised of the possibility of such damages, under no + * circumstances shall we (or any other person or entity with + * proprietary rights in the software licensed hereunder) be liable + * to you or any third party for direct, indirect, or consequential + * damages of any character regardless of type of action, including, + * without limitation, loss of profits, loss of use, loss of good + * will, or computer failure or malfunction. You agree to indemnify + * us (and any other person or entity with proprietary rights in the + * software licensed hereunder) for any and all liability it may + * incur to third parties resulting from your use of Paradyn. + */ + +#include + +#include "BPatch_type.h" + + +/* + * BPatch_type::BPatch_type + * + * Constructor for BPatch_type. Creates a type object representing a type + * with the features given in the parameters. + */ +BPatch_type::BPatch_type(const char *_name, bool _nullType) : + nullType(_nullType), name(_name) +{ + /* XXX More later. */ +} + + +/* + * BPatch_type::isCompatible + * + * Returns true of the type is compatible with the other specified type, false + * if it is not. + * + * oType The other type to check for compatibility. + */ +bool BPatch_type::isCompatible(const BPatch_type &otype) +{ + if (nullType || otype.nullType) + return true; + + // XXX Just compare names for now, we'll have to fix this later. + if (name == otype.name) return true; + else return false; +} + + +/* + * BPatch_typeCollection::~BPatch_typeCollection + * + * Destructor for BPatch_typeCollection. Deletes all type objects that have + * been inserted into the collection. + */ +BPatch_typeCollection::~BPatch_typeCollection() +{ + dictionary_hash_iter ti(typesByName); + + string name; + BPatch_type *type; + + while (ti.next(name, type)) + delete type; +} + + +/* + * BPatch_typeCollection::findType + * + * Retrieve a pointer to a BPatch_type object representing the named type from + * the collection. If no such type exists and no such type can be derived + * from existing types, then the function returns NULL. + * + * name The name of the type to look up. + */ +BPatch_type *BPatch_typeCollection::findType(const char *name) +{ + return typesByName[name]; +} + + +/* + * BPatch_typeCollection::addType + * + * Add a new type to the type collection. Note that when a type is added to + * the collection, it becomes the collection's responsibility to delete it + * when it is no longer needed. For one thing, this means that a type + * allocated on the stack should *NEVER* be put into a BPatch_typeCollection. + */ +void BPatch_typeCollection::addType(BPatch_type *type) +{ + typesByName[type->getName()] = type; +} diff --git a/dyninstAPI/src/BPatch_type.h b/dyninstAPI/src/BPatch_type.h new file mode 100644 index 0000000..5cbc8f1 --- /dev/null +++ b/dyninstAPI/src/BPatch_type.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 1996 Barton P. Miller + * + * We provide the Paradyn Parallel Performance Tools (below + * described as Paradyn") on an AS IS basis, and do not warrant its + * validity or performance. We reserve the right to update, modify, + * or discontinue this software at any time. We shall have no + * obligation to supply such updates or modifications or any other + * form of support to you. + * + * This license is for research uses. For such uses, there is no + * charge. We define "research use" to mean you may freely use it + * inside your organization for whatever purposes you see fit. But you + * may not re-distribute Paradyn or parts of Paradyn, in any form + * source or binary (including derivatives), electronic or otherwise, + * to any other organization or entity without our permission. + * + * (for other uses, please contact us at paradyn@cs.wisc.edu) + * + * All warranties, including without limitation, any warranty of + * merchantability or fitness for a particular purpose, are hereby + * excluded. + * + * By your use of Paradyn, you understand and agree that we (or any + * other person or entity with proprietary rights in Paradyn) are + * under no obligation to provide either maintenance services, + * update services, notices of latent defects, or correction of + * defects for Paradyn. + * + * Even if advised of the possibility of such damages, under no + * circumstances shall we (or any other person or entity with + * proprietary rights in the software licensed hereunder) be liable + * to you or any third party for direct, indirect, or consequential + * damages of any character regardless of type of action, including, + * without limitation, loss of profits, loss of use, loss of good + * will, or computer failure or malfunction. You agree to indemnify + * us (and any other person or entity with proprietary rights in the + * software licensed hereunder) for any and all liability it may + * incur to third parties resulting from your use of Paradyn. + */ + +#ifndef _BPatch_type_h_ +#define _BPatch_type_h_ + +#include "util/h/String.h" +#include "util/h/Dictionary.h" + + +class BPatch_type { + bool nullType; + string name; +public: + BPatch_type(const char *_name, bool _nullType = false); + + const char *getName() { return name.string_of(); } + + bool isCompatible(const BPatch_type &otype); +}; + + +class BPatch_typeCollection { + dictionary_hash typesByName; +public: + BPatch_typeCollection() : typesByName(string::hash) {} ; + ~BPatch_typeCollection(); + + BPatch_type *findType(const char *name); + void addType(BPatch_type *type); +}; + +#endif /* _BPatch_type_h_ */ diff --git a/dyninstAPI/src/ast.C b/dyninstAPI/src/ast.C index ab6feaf..f0a1c59 100644 --- a/dyninstAPI/src/ast.C +++ b/dyninstAPI/src/ast.C @@ -41,6 +41,13 @@ /* * $Log: ast.C,v $ + * Revision 1.41 1997/04/29 16:58:50 buck + * Added features to dyninstAPI library, including the ability to delete + * inserted snippets and the start of type checking. + * + * Revision 1.1.1.1 1997/04/01 20:24:59 buck + * Update Maryland repository with latest from Wisconsin. + * * Revision 1.40 1997/03/18 19:44:07 buck * first commit of dyninst library. Also includes: * moving templates from paradynd to dyninstAPI @@ -139,6 +146,8 @@ #include "dyninstAPI/src/ast.h" #include "dyninstAPI/src/util.h" #include "paradynd/src/showerror.h" +#include "dyninstAPI/h/BPatch.h" +#include "dyninstAPI/src/BPatch_type.h" #ifndef BPATCH_LIBRARY #include "rtinst/h/rtinst.h" @@ -401,6 +410,9 @@ AstNode &AstNode::operator=(const AstNode &src) { astFlag = src.astFlag; #endif + bptype = src.bptype; + doTypeCheck = src.doTypeCheck; + return *this; } @@ -435,6 +447,8 @@ AstNode::AstNode() { useCount = 0; kept_register = -1; // "operands" is left as an empty vector + bptype = NULL; + doTypeCheck = true; } AstNode::AstNode(const string &func, AstNode *l, AstNode *r) { @@ -451,6 +465,8 @@ AstNode::AstNode(const string &func, AstNode *l, AstNode *r) { callee = func; if (l) operands += assignAst(l); if (r) operands += assignAst(r); + bptype = NULL; + doTypeCheck = true; } AstNode::AstNode(const string &func, AstNode *l) { @@ -468,6 +484,8 @@ AstNode::AstNode(const string &func, AstNode *l) { type = callNode; callee = func; if (l) operands += assignAst(l); + bptype = NULL; + doTypeCheck = true; } AstNode::AstNode(const string &func, vector &ast_args) { @@ -485,6 +503,8 @@ AstNode::AstNode(const string &func, vector &ast_args) { loperand = roperand = NULL; type = callNode; callee = func; + bptype = NULL; + doTypeCheck = true; } AstNode::AstNode(operandType ot, void *arg) { @@ -504,6 +524,8 @@ AstNode::AstNode(operandType ot, void *arg) { else oValue = (void *) arg; loperand = roperand = NULL; + bptype = NULL; + doTypeCheck = true; }; AstNode::AstNode(operandType ot, AstNode *l) { @@ -521,6 +543,8 @@ AstNode::AstNode(operandType ot, AstNode *l) { oValue = NULL; roperand = NULL; loperand = assignAst(l); + bptype = NULL; + doTypeCheck = true; }; AstNode::AstNode(AstNode *l, AstNode *r) { @@ -536,6 +560,8 @@ AstNode::AstNode(AstNode *l, AstNode *r) { type = sequenceNode; loperand = assignAst(l); roperand = assignAst(r); + bptype = NULL; + doTypeCheck = true; }; AstNode::AstNode(opCode ot) { @@ -552,6 +578,8 @@ AstNode::AstNode(opCode ot) { type = opCodeNode; op = ot; loperand = roperand = NULL; + bptype = NULL; + doTypeCheck = true; } AstNode::AstNode(opCode ot, AstNode *l) { @@ -569,6 +597,8 @@ AstNode::AstNode(opCode ot, AstNode *l) { op = ot; loperand = assignAst(l); roperand = NULL; + bptype = NULL; + doTypeCheck = true; } AstNode::AstNode(opCode ot, AstNode *l, AstNode *r) { @@ -585,6 +615,8 @@ AstNode::AstNode(opCode ot, AstNode *l, AstNode *r) { op = ot; loperand = assignAst(l); roperand = assignAst(r); + bptype = NULL; + doTypeCheck = true; }; AstNode::AstNode(AstNode *src) { @@ -623,6 +655,8 @@ AstNode::AstNode(AstNode *src) { roperand = assignAst(src->roperand); firstInsn = src->firstInsn; lastInsn = src->lastInsn; + bptype = src->bptype; + doTypeCheck = src->doTypeCheck; } #if defined(ASTDEBUG) @@ -1362,3 +1396,72 @@ AstNode *createCounter(const string &func, void *dataPtr, #endif #endif + +#ifdef BPATCH_LIBRARY +BPatch_type *AstNode::checkType() +{ + BPatch_type *ret = NULL; + BPatch_type *lType = NULL, *rType = NULL; + bool errorFlag = false; + + assert(BPatch::bpatch != NULL); /* We'll use this later. */ + + assert( (!loperand && !roperand) || getType() == NULL ); + + if (loperand) + lType = loperand->checkType(); + + if (roperand) + rType = roperand->checkType(); + + if (lType == BPatch::bpatch->type_Error || + rType == BPatch::bpatch->type_Error) + errorFlag = true; + + + switch (type) { // Type here is nodeType, not BPatch library type + case sequenceNode: + ret = rType; + break; + case opCodeNode: + if (lType != NULL && rType != NULL) { + if (!lType->isCompatible(*rType)) { + errorFlag = true; + } + } + // XXX The following line must change to decide based on the types + // and operation involved what the return type of the expression + // will be. + ret = lType; + break; + case operandNode: + assert(loperand == NULL && roperand == NULL); + if (oType == Param) + ret = BPatch::bpatch->type_Untyped; //XXX Params untyped for now + else + ret = getType(); + assert(ret != NULL); + break; + case callNode: + for (int i = 0; i < operands.size(); i++) { + BPatch_type *operandType = operands[i]->checkType(); + /* XXX Check operands for compatibility */ + if (operandType == BPatch::bpatch->type_Error) + errorFlag = true; + } + /* XXX Should set to return type of function. */ + ret = BPatch::bpatch->type_Untyped; + break; + default: + assert(0); + } + + assert(ret != NULL); + + if (errorFlag && doTypeCheck) { + ret = BPatch::bpatch->type_Error; + } + + return ret; +} +#endif diff --git a/dyninstAPI/src/ast.h b/dyninstAPI/src/ast.h index 7815012..618d3a1 100644 --- a/dyninstAPI/src/ast.h +++ b/dyninstAPI/src/ast.h @@ -44,6 +44,17 @@ /* * $Log: ast.h,v $ + * Revision 1.25 1997/04/29 16:58:51 buck + * Added features to dyninstAPI library, including the ability to delete + * inserted snippets and the start of type checking. + * + * Revision 1.2 1997/04/09 17:20:14 buck + * Added getThreads calls to BPatch, support for deleting snippets, + * and the start of support for the type system. + * + * Revision 1.1.1.1 1997/04/01 20:25:00 buck + * Update Maryland repository with latest from Wisconsin. + * * Revision 1.24 1997/03/18 19:44:08 buck * first commit of dyninst library. Also includes: * moving templates from paradynd to dyninstAPI @@ -127,6 +138,8 @@ #include "util/h/Dictionary.h" #include "util/h/String.h" +class BPatch_type; + // a register. typedef int reg; @@ -227,6 +240,8 @@ class AstNode { vector operands; // only for call nodes operandType oType; // for operand nodes void *oValue; // operand value for operand nodes + const BPatch_type *bptype; // type of corresponding BPatch_snippet + bool doTypeCheck; // should operands be type checked // These 2 vrbles must be pointers; otherwise, we'd have a recursive // data structure with an infinite size. @@ -238,6 +253,16 @@ class AstNode { int firstInsn; int lastInsn; + + public: + // Functions for getting and setting type decoration used by the + // dyninst API library +#ifdef BPATCH_LIBRARY + const BPatch_type *getType() { return bptype; }; + void setType(const BPatch_type *t) { bptype = t; } + void setTypeChecking(bool x) { doTypeCheck = x; } + BPatch_type *checkType(); +#endif }; AstNode *assignAst(AstNode *src); diff --git a/dyninstAPI/src/templates1.C b/dyninstAPI/src/templates1.C index 9cf60d5..3b97d8e 100644 --- a/dyninstAPI/src/templates1.C +++ b/dyninstAPI/src/templates1.C @@ -56,6 +56,8 @@ #include "util/h/Object.h" #include "dyninstAPI/src/sharedobject.h" +#include "BPatch_type.h" + template class dictionary ; template class dictionary ; template class dictionary_hash ; @@ -134,3 +136,9 @@ template class vectorSet; #include "fastInferiorHeapMgr.h" template class vector; + +/* ***************************************************************************** */ + +template class dictionary_hash; + +template class dictionary_hash_iter; diff --git a/dyninstAPI/tests/make.module.tmpl b/dyninstAPI/tests/make.module.tmpl index 7406d8f..a6573b1 100644 --- a/dyninstAPI/tests/make.module.tmpl +++ b/dyninstAPI/tests/make.module.tmpl @@ -4,6 +4,10 @@ # from within an architecture-specific Makefile. # # $Log: make.module.tmpl,v $ +# Revision 1.2 1997/04/29 16:58:52 buck +# Added features to dyninstAPI library, including the ability to delete +# inserted snippets and the start of type checking. +# # Revision 1.1 1997/03/18 19:44:52 buck # first commit of dyninst library. Also includes: # moving templates from paradynd to dyninstAPI @@ -26,6 +30,7 @@ CXXFLAGS += -I../../h -DTEST_APP_DIR=$(APP_DIR) CFLAGS += -I../../h -DTEST_APP_DIR=$(APP_DIR) #LDFLAGS += -static $(TO_CORE)/../lib/$(PLATFORM)/libdyninstAPI_RT.o -LIBS += -ldyninstAPI -lpdutil -liberty +LIBS += -ldyninstAPI -lpdutil +SYSLIBS += -liberty all: $(TARGET) $(TARGET2) diff --git a/dyninstAPI/tests/src/test1.C b/dyninstAPI/tests/src/test1.C index 8a0ace6..bc5f806 100644 --- a/dyninstAPI/tests/src/test1.C +++ b/dyninstAPI/tests/src/test1.C @@ -17,6 +17,19 @@ /* * $Log: test1.C,v $ + * Revision 1.2 1997/04/29 16:58:55 buck + * Added features to dyninstAPI library, including the ability to delete + * inserted snippets and the start of type checking. + * + * Revision 1.3 1997/04/09 17:20:51 buck + * Added test for deleting snippets. + * + * Revision 1.2 1997/04/03 20:08:56 buck + * Added BPatch class and moved global library data/functions into it. + * + * Revision 1.1.1.1 1997/04/01 20:25:15 buck + * Update Maryland repository with latest from Wisconsin. + * * Revision 1.1 1997/03/18 19:45:21 buck * first commit of dyninst library. Also includes: * moving templates from paradynd to dyninstAPI @@ -29,12 +42,15 @@ #include #include +#include "BPatch.h" #include "BPatch_Vector.h" #include "BPatch_thread.h" #include "BPatch_snippet.h" int debugPrint = 0; +BPatch *bpatch; + // control debug printf statements #define dprintf if (debugPrint) printf @@ -320,6 +336,7 @@ void mutatorTest11(BPatch_thread *appThread, BPatch_image *appImage) } +BPatchSnippetHandle *snippetHandle12_1; BPatch_variableExpr *varExpr12_1; // @@ -349,7 +366,12 @@ void mutatorTest12a(BPatch_thread *appThread, BPatch_image *appImage) BPatch_Vector nullArgs; BPatch_funcCallExpr call12_1Expr(*call12_1_func, nullArgs); - appThread->insertSnippet(call12_1Expr, *point12_2); + snippetHandle12_1 = appThread->insertSnippet(call12_1Expr, *point12_2); + if (!snippetHandle12_1) { + fprintf(stderr, + "Unable to insert snippet to call function \"call12_1.\"\n"); + exit(-1); + } } void mutatorTest12b(BPatch_thread *appThread, BPatch_image *appImage) @@ -357,6 +379,11 @@ void mutatorTest12b(BPatch_thread *appThread, BPatch_image *appImage) while (!appThread->isStopped() && !appThread->isTerminated()) ; if (appThread->stopSignal() == SIGSTOP) { // remove instrumentation and free memory + if (!appThread->deleteSnippet(snippetHandle12_1)) { + printf("**Failed test #12 (insert/remove and malloc/free)\n"); + printf(" deleteSnippet returned an error\n"); + exit(-1); + } appThread->free(*varExpr12_1); // continue process @@ -409,6 +436,10 @@ void mutatorTest13(BPatch_thread *appThread, BPatch_image *appImage) void mutatorMAIN(char *pathname) { + // Create an instance of the bpatch library + bpatch = new BPatch; + + // Start the mutatee printf("Starting \"%s\"\n", pathname); char *child_argv[] = { pathname, "-verbose", NULL }; diff --git a/dyninstAPI/tests/src/test1.mutatee.c b/dyninstAPI/tests/src/test1.mutatee.c index af05a57..89a2e92 100644 --- a/dyninstAPI/tests/src/test1.mutatee.c +++ b/dyninstAPI/tests/src/test1.mutatee.c @@ -2,6 +2,16 @@ /* * $Log: test1.mutatee.c,v $ + * Revision 1.2 1997/04/29 16:58:55 buck + * Added features to dyninstAPI library, including the ability to delete + * inserted snippets and the start of type checking. + * + * Revision 1.2 1997/04/09 17:20:54 buck + * Added test for deleting snippets. + * + * Revision 1.1.1.1 1997/04/01 20:25:16 buck + * Update Maryland repository with latest from Wisconsin. + * * Revision 1.1 1997/03/18 19:45:22 buck * first commit of dyninst library. Also includes: * moving templates from paradynd to dyninstAPI @@ -273,7 +283,7 @@ void func12_1() func12_2(); kill(getpid(), SIGSTOP); func12_2(); - if (globalVariable12_1 == 2) { + if (globalVariable12_1 == 1) { printf("Passed test #12 (insert/remove and malloc/free)\n"); } else { printf("**Failed test #12 (insert/remove and malloc/free)\n"); diff --git a/dyninstAPI_RT/make.module.tmpl b/dyninstAPI_RT/make.module.tmpl index 5b743e5..e9d3ec0 100644 --- a/dyninstAPI_RT/make.module.tmpl +++ b/dyninstAPI_RT/make.module.tmpl @@ -5,14 +5,6 @@ # intended to be a useful Makefile in isolation; instead, it should be # included from within an architecture-specific Makefile. # -# $Log: make.module.tmpl,v $ -# Revision 1.1 1997/03/18 19:45:25 buck -# first commit of dyninst library. Also includes: -# moving templates from paradynd to dyninstAPI -# converting showError into a function (in showerror.C) -# many ifdefs for BPATCH_LIBRARY in dyinstAPI/src. -# -# # ifndef TARGET @@ -57,7 +49,7 @@ endif UNCOMMON_INSTALL= true -install: $(DEST)/$(TARGET) +install: $(DEST)/$(TARGET) $(SYSEXTRAS) $(DEST)/libdyninstAPI_RT.o: libdyninstAPI_RT.o cp libdyninstAPI_RT.o ../../../lib/$(PLATFORM) diff --git a/dyninstAPI_RT/src/DYNINSTAPI_RT_EXPORTS b/dyninstAPI_RT/src/DYNINSTAPI_RT_EXPORTS new file mode 100644 index 0000000..31e7a2b --- /dev/null +++ b/dyninstAPI_RT/src/DYNINSTAPI_RT_EXPORTS @@ -0,0 +1,6 @@ +main +DYNINSTversion +DYNINSTobsCostLow +DYNINSTdata +DYNINSTtext +DYNINSTglobalData diff --git a/dyninstAPI_RT/src/RTcommon.c b/dyninstAPI_RT/src/RTcommon.c index 53c3fca..6e3f227 100644 --- a/dyninstAPI_RT/src/RTcommon.c +++ b/dyninstAPI_RT/src/RTcommon.c @@ -38,16 +38,6 @@ * software licensed hereunder) for any and all liability it may * incur to third parties resulting from your use of Paradyn. */ -/* - * $Log: RTcommon.c,v $ - * Revision 1.1 1997/03/18 19:45:46 buck - * first commit of dyninst library. Also includes: - * moving templates from paradynd to dyninstAPI - * converting showError into a function (in showerror.C) - * many ifdefs for BPATCH_LIBRARY in dyinstAPI/src. - * - * - */ #include "rtinst/h/rtinst.h" unsigned int DYNINSTversion = 1; -- 1.8.3.1