File: attach.cpp

package info (click to toggle)
pydevd 2.9.5%2Bds-4
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 10,880 kB
  • sloc: python: 75,138; cpp: 1,851; sh: 310; makefile: 40; ansic: 4
file content (111 lines) | stat: -rw-r--r-- 3,703 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
// This is much simpler than the windows version because we're using gdb and
// we assume that gdb will call things in the correct thread already.

//compile with: g++ -shared -o attach_linux.so -fPIC -nostartfiles attach_linux.c


#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <stdbool.h>

#include "../common/python.h"
#include "../common/ref_utils.hpp"
#include "../common/py_utils.hpp"
#include "../common/py_settrace.hpp"
//#include <unistd.h> used for usleep

// Exported function: hello(): Just to print something and check that we've been
// able to connect.
extern "C" int hello(void);

int hello()
{
    printf("Hello world!\n");

    void *module = dlopen(nullptr, 0x2);

    void *hndl = dlsym (module, "PyGILState_Ensure");
    if(hndl == nullptr){
        printf("nullptr\n");

    }else{
        printf("Worked (found PyGILState_Ensure)!\n");
    }

    printf("%d", GetPythonVersion(module));


    return 2;
}


// Internal function to keep on the tracing
int _PYDEVD_ExecWithGILSetSysStrace(bool showDebugInfo, bool isDebug);

// Implementation details below
typedef PyObject* (PyImport_ImportModuleNoBlock) (const char *name);
typedef int (*PyEval_ThreadsInitialized)();
typedef unsigned long (*_PyEval_GetSwitchInterval)(void);
typedef void (*_PyEval_SetSwitchInterval)(unsigned long microseconds);

// isDebug is pretty important! Must be true on python debug builds (python_d)
// If this value is passed wrongly the program will crash.
extern "C" int DoAttach(bool isDebug, const char *command, bool showDebugInfo);

int DoAttach(bool isDebug, const char *command, bool showDebugInfo)
{
    void *module = dlopen(nullptr, 0x2);
    DEFINE_PROC(isInitFunc, Py_IsInitialized*, "Py_IsInitialized", 1);
    DEFINE_PROC(gilEnsure, PyGILState_Ensure*, "PyGILState_Ensure", 51);
    DEFINE_PROC(gilRelease, PyGILState_Release*, "PyGILState_Release", 51);


    if(!isInitFunc()){
        if(showDebugInfo){
            printf("Py_IsInitialized returned false.\n");
        }
        return 2;
    }

    PythonVersion version = GetPythonVersion(module);

    DEFINE_PROC(interpHead, PyInterpreterState_Head*, "PyInterpreterState_Head", 51);

    auto head = interpHead();
    if (head == nullptr) {
        // this interpreter is loaded but not initialized.
        if(showDebugInfo){
            printf("Interpreter not initialized!\n");
        }
        return 54;
    }

    // Note: unlike windows where we have to do many things to enable threading
    // to work to get the gil, here we'll be executing in an existing thread,
    // so, it's mostly a matter of getting the GIL and running it and we shouldn't
    // have any more problems.

    DEFINE_PROC(pyRun_SimpleString, PyRun_SimpleString*, "PyRun_SimpleString", 51);
    
    GilHolder gilLock(gilEnsure, gilRelease);   // acquire and hold the GIL until done...
    
    pyRun_SimpleString(command);
    return 0;
}


// This is the function which enables us to set the sys.settrace for all the threads
// which are already running.
extern "C" int AttachDebuggerTracing(bool showDebugInfo, void* pSetTraceFunc, void* pTraceFunc, unsigned int threadId, void* pPyNone);

int AttachDebuggerTracing(bool showDebugInfo, void* pSetTraceFunc, void* pTraceFunc, unsigned int threadId, void* pPyNone)
{
    void *module = dlopen(nullptr, 0x2);
    bool isDebug = false;
    PyObjectHolder traceFunc(isDebug, (PyObject*) pTraceFunc, true);
    PyObjectHolder setTraceFunc(isDebug, (PyObject*) pSetTraceFunc, true);
    PyObjectHolder pyNone(isDebug, reinterpret_cast<PyObject*>(pPyNone), true);
    return InternalSetSysTraceFunc(module, isDebug, showDebugInfo, &traceFunc, &setTraceFunc, threadId, &pyNone);
}