Files
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

479 lines
14 KiB
C++

/*
* See the dyninst/COPYRIGHT file for copyright information.
*
* We provide the Paradyn 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.
*
* 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.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _BPatch_process_h_
#define _BPatch_process_h_
#include "BPatch_snippet.h"
#include "BPatch_dll.h"
#include "BPatch_Vector.h"
// #include "BPatch_image.h"
#include "BPatch_addressSpace.h"
#include "BPatch_enums.h"
#include "dyntypes.h"
#include "BPatch_callbacks.h"
#include "PCProcess.h"
#include <map>
#include <set>
#include <stddef.h>
#include <utility>
#include <vector>
#include <cstdio>
#include <csignal>
class PCProcess;
class AddressSpace;
class PCThread;
class miniTrampHandle;
class BPatch;
class BPatch_thread;
class BPatch_process;
class BPatch_point;
class BPatch_funcMap;
class BPatch_instpMap;
class func_instance;
class rpcMgr;
class HybridAnalysis;
struct batchInsertionRecord;
typedef enum {
BPatch_nullEvent,
BPatch_newConnectionEvent,
BPatch_internalShutDownEvent,
BPatch_threadCreateEvent,
BPatch_threadDestroyEvent,
BPatch_dynamicCallEvent,
BPatch_userEvent,
BPatch_errorEvent,
BPatch_dynLibraryEvent,
BPatch_preForkEvent,
BPatch_postForkEvent,
BPatch_execEvent,
BPatch_exitEvent,
BPatch_signalEvent,
BPatch_oneTimeCodeEvent
} BPatch_asyncEventType;
typedef Dyninst::THR_ID dynthread_t;
typedef struct {
BPatch_snippet snip;
BPatchSnippetHandle *sh;
BPatch_thread *thread;
} BPatch_catchupInfo;
/*
* class OneTimeCodeInfo
*
* This is used by the oneTimeCode (inferiorRPC) mechanism to keep per-RPC
* information.
*/
class OneTimeCodeInfo {
bool synchronous;
bool completed;
void *userData;
BPatchOneTimeCodeCallback cb;
void *returnValue;
unsigned thrID;
public:
OneTimeCodeInfo(bool _synchronous, void *_userData, BPatchOneTimeCodeCallback _cb, unsigned _thrID) :
synchronous(_synchronous), completed(false), userData(_userData), cb(_cb),
returnValue(NULL), thrID(_thrID) { }
bool isSynchronous() { return synchronous; }
bool isCompleted() const { return completed; }
void setCompleted(bool _completed) { completed = _completed; }
void *getUserData() { return userData; }
void setReturnValue(void *_returnValue) { returnValue = _returnValue; }
void *getReturnValue() { return returnValue; }
unsigned getThreadID() { return thrID; }
BPatchOneTimeCodeCallback getCallback() { return cb;}
};
/*
* Represents a process
*/
class BPATCH_DLL_EXPORT BPatch_process : public BPatch_addressSpace {
friend class BPatch;
friend class BPatch_image;
friend class BPatch_function;
friend class BPatch_frame;
friend class BPatch_thread;
friend class BPatch_asyncEventHandler;
friend class BPatch_module;
friend class BPatch_basicBlock;
friend class BPatch_flowGraph;
friend class BPatch_loopTreeNode;
friend class BPatch_point;
friend class BPatch_funcCallExpr;
friend class BPatch_eventMailbox;
friend class BPatch_instruction;
friend class BPatch_addressSpace;
friend class AstNode; // AST needs to translate instPoint to
friend class AstOperatorNode;
friend class AstMemoryNode;
friend class PCEventHandler; // to deliver events for callbacks
protected:
void getAS(std::vector<AddressSpace *> &as);
public:
void PDSEP_updateObservedCostAddr(unsigned long a);
private:
//References to lower level objects
PCProcess *llproc;
BPatch_Vector<BPatch_thread *> threads;
int lastSignal;
int exitCode;
int exitSignal;
bool exitedNormally;
bool exitedViaSignal;
bool mutationsActive;
bool createdViaAttach;
bool detached;
// BPatch-level; once the callbacks are sent by the llproc, we're terminated
// Used because callbacks go (and can clean up user code) before the low-level process
// sets flags.
bool terminated;
bool reportedExit;
void setExitedNormally();
void setExitedViaSignal(int signalnumber);
void setExitCode(int exitcode) { exitCode = exitcode; }
void setExitSignal(int exitsignal) { exitSignal = exitsignal; }
bool statusIsTerminated();
void setLastSignal(int signal) { lastSignal = signal; }
processType getType();
bool getTerminated() {return terminated;}
bool getMutationsActive() {return mutationsActive;}
HybridAnalysis *hybridAnalysis_;
static int oneTimeCodeCallbackDispatch(PCProcess *theProc,
unsigned /* rpcid */,
void *userData,
void *returnValue);
void *oneTimeCodeInternal(const BPatch_snippet &expr,
BPatch_thread *thread, // == NULL if proc-wide
void *userData,
BPatchOneTimeCodeCallback cb = NULL,
bool synchronous = true, bool *err = NULL,
bool userRPC = true);
protected:
// for creating a process
BPatch_process(const char *path, const char *argv[],
BPatch_hybridMode mode, const char **envp = NULL,
int stdin_fd = 0, int stdout_fd = 1, int stderr_fd = 2);
// for attaching
BPatch_process(const char *path, int pid, BPatch_hybridMode mode);
// for forking
BPatch_process(PCProcess *proc);
void triggerThreadCreate(PCThread *thread);
void triggerInitialThreadEvents();
void deleteBPThread(BPatch_thread *thrd);
public:
// Begin internal functions, DO NOT USE
//
// this function should go away as soon as Paradyn links against Dyninst
PCProcess *lowlevel_process() const { return llproc; }
// These internal funcs trigger callbacks registered to matching events
bool triggerStopThread(instPoint *intPoint, func_instance *intFunc,
int cb_ID, void *retVal);
bool triggerSignalHandlerCB(instPoint *point, func_instance *func, long signum,
BPatch_Vector<Dyninst::Address> *handlers);
bool triggerCodeOverwriteCB(instPoint * faultPoint,
Dyninst::Address faultTarget);
bool setMemoryAccessRights(Dyninst::Address start, size_t size,
Dyninst::ProcControlAPI::Process::mem_perm rights);
unsigned char *makeShadowPage(Dyninst::Address pageAddress);
void overwriteAnalysisUpdate
( std::map<Dyninst::Address,unsigned char*>& owPages, //input
std::vector<std::pair<Dyninst::Address,int> >& deadBlocks, //output
std::vector<BPatch_function*>& owFuncs, //output
std::set<BPatch_function *> &monitorFuncs, //output
bool &changedPages, bool &changedCode ); //output
HybridAnalysis *getHybridAnalysis() { return hybridAnalysis_; }
bool protectAnalyzedCode();
// DO NOT USE
// This is an internal debugging function
void debugSuicide();
//
// End internal functions
// BPatch_process::~BPatch_process
//
// Destructor
~BPatch_process();
// BPatch_process::getPid
//
// Get id of mutatee process
int getPid();
// BPatch_process::getAddressWidth
//
// Get the address width (4 or 8) of the process
int getAddressWidth();
// BPatch_process::stopExecution
//
// Stop the mutatee process
bool stopExecution();
// BPatch_process::continueExecution
//
// Resume execution of mutatee process
bool continueExecution();
// BPatch_process::terminateExecution
//
// Terminate mutatee process
bool terminateExecution();
// BPatch_process::isStopped
//
// Returns true if mutatee process is currently stopped
bool isStopped();
// BPatch_process::stopSignal
//
// Returns signal number of signal that stopped mutatee process
int stopSignal();
// BPatch_process::isTerminated
//
// Returns true if mutatee process is terminated
bool isTerminated();
// BPatch_process::terminationStatus
//
// Returns information on how mutatee process was terminated
BPatch_exitType terminationStatus();
// BPatch_process::getExitCode
//
// Returns integer exit code of (exited) mutatee process
int getExitCode();
// BPatch_process::getExitSignal
//
// Returns integer signal number of signal that caused mutatee to exit
int getExitSignal();
// BPatch_process::detach
//
// Detach from the mutatee process, optionally leaving it running
bool wasRunningWhenAttached();
// BPatch_process::detach
//
// Detach from the mutatee process, optionally leaving it running
bool detach(bool cont);
// BPatch_process::isDetached
//
// Returns true if DyninstAPI is detached from this mutatee
bool isDetached();
// BPatch_process::getThreads
//
// Fills a vector with the BPatch_thread objects that belong to
// this process
void getThreads(BPatch_Vector<BPatch_thread *> &thrds);
// BPatch_prOcess::isMultithreaded
//
// Returns true if this process has more than one thread
bool isMultithreaded();
// BPatch_prOcess::isMultithreadCapable
//
// Returns true if this process is linked against a thread library
// (and thus might be multithreaded)
bool isMultithreadCapable();
// BPatch_process::getThread
//
// Returns one of this process's threads, given a tid
BPatch_thread * getThread(dynthread_t tid);
// BPatch_process::getThread
//
// Returns one of this process's threads, given an index
BPatch_thread * getThreadByIndex(unsigned index);
// BPatch_process::dumpCore
//
// Produce a core dump file <file> for the mutatee process
bool dumpCore(const char *file, bool terminate);
// BPatch_process::dumpImage
//
// Write contents of memory to <file>
bool dumpImage(const char *file);
// BPatch_process::getInheritedVariable
//
//
BPatch_variableExpr * getInheritedVariable(BPatch_variableExpr &pVar);
// BPatch_process::getInheritedSnippet
//
//
BPatchSnippetHandle * getInheritedSnippet(BPatchSnippetHandle &parentSnippet);
// BPatch_binaryEdit::beginInsertionSet()
//
// Start the batch insertion of multiple points; all calls to insertSnippet*
// after this call will not actually instrument until finalizeInsertionSet is
// called
void beginInsertionSet();
//BPatch_process::finalizeInsertionSet()
// Finalizes all instrumentation logically added since a call to beginInsertionSet.
// Returns true if all instrumentation was successfully inserted; otherwise, none
// was. Individual instrumentation can be manipulated via the BPatchSnippetHandles
// returned from individual calls to insertSnippet.
//
// atomic: if true, all instrumentation will be removed if any fails to go in.
// modified: if provided, and set to true by finalizeInsertionSet, additional
// steps were taken to make the installation work, such as modifying
// process state. Note that such steps will be taken whether or not
// a variable is provided.
bool finalizeInsertionSet(bool atomic, bool *modified = NULL);
bool finalizeInsertionSetWithCatchup(bool atomic, bool *modified,
BPatch_Vector<BPatch_catchupInfo> &catchup_handles);
// BPatch_process::oneTimeCode
//
// Have the specified code be executed by the mutatee once. Wait until done.
void* oneTimeCode(const BPatch_snippet &expr, bool *err = NULL);
// BPatch_process::oneTimeCodeAsync
//
// Have the specified code be executed by the mutatee once. Dont wait until done.
bool oneTimeCodeAsync(const BPatch_snippet &expr, void *userData = NULL,
BPatchOneTimeCodeCallback cb = NULL);
// BPatch_process::hideDebugger()
//
// This is a Windows only function that removes debugging artifacts that
// are added to user-space datastructures and the heap of the debugged
// process, by CreateProcess and DebugActiveProcess. Removing the artifacts
// doesn't have any effect on the process, as the kernel still knows that
// the process is being debugged. Three of the artifacts are flags that can
// be reached through the Process Environment Block of the debuggee (PEB):
// 1. BeingDebugged, one byte at offset 2 in the PEB.
// 2. NtGlobalFlags, at offset 0x68 in the PEB
// 3. There are two consecutive words of heap flags which are at offset 0x0c
// from the beginning of the heap. The heap base address is at offset
// 0x18 from the beginning of the PEB.
// The other thing this method does is clear the 0xabababababababab value that
// it CreateProcess adds to the end of the heap section when creating a debugged
// process, in response to the heap flag: HEAP_TAIL_CHECKING_ENABLED, which it
// sets to true for debugged processes. We are clearing that flag, but by the
// time we do, the value is already written to disk.
//
// Various system calls can still be used by the debuggee to recognize that
// it is being debugged, so this is not a complete solution.
bool hideDebugger();
#if 0
void printDefensiveStats();
#endif
// BPatch_process::loadLibrary
//
// Load a shared library into the mutatee's address space
// Returns true if successful
virtual BPatch_object * loadLibrary(const char *libname, bool reload = false);
bool supportsUserThreadEvents();
};
#endif /* BPatch_process_h_ */