forked from adobe-flash/avmplus
-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathSpyUtilsWin.cpp
157 lines (126 loc) · 3.98 KB
/
SpyUtilsWin.cpp
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */
/* vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "MMgc.h"
#ifdef MMGC_MEMORY_PROFILER
#include <io.h>
/**
* compiled with the /W4 warning level
* which is quite picky. Disable warnings we don't care about.
*/
#ifdef _MSC_VER
#pragma warning(disable:4127) //conditional expression is constant
#endif
class SignalData : public MMgc::GCAllocObject
{
public:
SignalData(uint32_t *addr, HANDLE handle)
: profilerAddr(addr), eventHandle(handle) {}
uint32_t *profilerAddr;
HANDLE eventHandle;
};
static bool spyRunning=false;
static SignalData *sig_data;
static vmpi_spin_lock_t lock;
DWORD WINAPI WaitForMemorySignal(LPVOID)
{
while(spyRunning) {
WaitForSingleObject(sig_data->eventHandle, INFINITE);
if(spyRunning)
*(sig_data->profilerAddr) = true;
}
CloseHandle(sig_data->eventHandle);
delete sig_data;
return 0;
}
void WriteOnNamedSignal(const char *name, uint32_t *addr)
{
HANDLE m_namedSharedObject;
SECURITY_DESCRIPTOR sd;
InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
SetSecurityDescriptorDacl(&sd, TRUE, 0, FALSE);
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle = FALSE;
sa.lpSecurityDescriptor = &sd;
m_namedSharedObject = CreateEventA(&sa, FALSE, FALSE, name);
if(m_namedSharedObject == NULL){
LPVOID lpMsgBuf;
FormatMessageA( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPSTR) &lpMsgBuf, 0, NULL );
fputs((const char*)lpMsgBuf, stderr);
return;
}
sig_data = new SignalData(addr, m_namedSharedObject);
spyRunning = true;
CreateThread(NULL, 0, WaitForMemorySignal, NULL, 0, NULL);
}
#include "windows.h"
FILE *HandleToStream(void *handle)
{
return _fdopen(_open_osfhandle((intptr_t)handle, 0), "w");
}
void* OpenAndConnectToNamedPipe(const char *pipeName)
{
char name[256];
VMPI_snprintf(name, sizeof(name), "\\\\.\\pipe\\%s", pipeName);
HANDLE pipe = CreateNamedPipeA((LPCSTR)name, PIPE_ACCESS_OUTBOUND, PIPE_TYPE_BYTE, 1, 4096, 4096, 100, NULL);
ConnectNamedPipe(pipe, NULL);
return (void*)pipe;
}
void CloseNamedPipe(void *handle)
{
FlushFileBuffers(handle);
CloseHandle((HANDLE)handle);
}
static uint32_t mmgc_spy_signal = 0;
//log redirector function for outputting log messages to the spy
FILE* spyStream = NULL;
void SpyLog(const char* message)
{
fprintf(spyStream, "%s", message);
}
typedef void (*LoggingFunction)(const char*);
extern LoggingFunction GetCurrentLogFunction();
extern void RedirectLogOutput(void (*)(const char*));
void AVMPI_spyCallback()
{
if(mmgc_spy_signal)
{
VMPI_lockAcquire(&lock);
if(mmgc_spy_signal)
{
mmgc_spy_signal = 0;
void *pipe = OpenAndConnectToNamedPipe("MMgc_Spy");
spyStream = HandleToStream(pipe);
GCAssert(spyStream != NULL);
LoggingFunction oldLogFunc = GetCurrentLogFunction();
RedirectLogOutput(SpyLog);
MMgc::GCHeap::GetGCHeap()->DumpMemoryInfo();
fflush(spyStream);
CloseNamedPipe(pipe);
RedirectLogOutput(oldLogFunc);
spyStream = NULL;
}
VMPI_lockRelease(&lock);
}
}
bool AVMPI_spySetup()
{
VMPI_lockInit(&lock);
WriteOnNamedSignal("MMgc::MemoryProfiler::DumpFatties", &mmgc_spy_signal);
return true;
}
void AVMPI_spyTeardown()
{
VMPI_lockDestroy(&lock);
spyRunning = false;
}
bool AVMPI_hasSymbols()
{
return true;
}
#endif //MMGC_MEMORY_PROFILER