178
|
1 module dmd.TObject;
|
|
2 /*
|
|
3 import core.runtime;
|
|
4 import core.stdc.stdio;
|
|
5 import core.stdc.string;
|
|
6 import core.stdc.stdlib;
|
|
7
|
|
8 import dmd.TObject;
|
|
9
|
|
10 import core.sys.windows.windows;
|
|
11 import core.sys.windows.codeview;
|
|
12 import core.demangle;
|
|
13 import core.memory;
|
|
14 import core.stdc.stdlib;
|
|
15
|
|
16 version = TrackArray;
|
|
17
|
|
18 version (TrackList) {
|
|
19 enum mNull = TObject.pack(0);
|
|
20 __gshared size_t mHead = mNull;
|
|
21 } else version (TrackArray) {
|
|
22 __gshared size_t[] objects;
|
|
23 }
|
|
24 */
|
|
25 class TObject
|
|
26 {
|
|
27 void register()
|
|
28 {
|
|
29 }
|
|
30
|
|
31 void forceRegister()
|
|
32 {
|
|
33 }
|
|
34
|
|
35 /*
|
|
36 this()
|
|
37 {
|
|
38 register();
|
|
39 }
|
|
40
|
|
41 ~this()
|
|
42 {
|
|
43 size_t mThis = pack(this);
|
|
44
|
|
45 version (TrackList) {
|
|
46 if (mPrev != mNull) {
|
|
47 unpack(mPrev).mNext = mNext;
|
|
48 } else {
|
|
49 assert(mHead == mThis);
|
|
50 mHead = mNext;
|
|
51 }
|
|
52
|
|
53 if (mNext != mNull) {
|
|
54 unpack(mNext).mPrev = mPrev;
|
|
55 }
|
|
56 } else version (TrackArray) {
|
|
57 foreach (i, o; objects) {
|
|
58 if (o == mThis) {
|
|
59 size_t newLen = objects.length - 1;
|
|
60 objects[i] = objects[newLen];
|
|
61 objects.length = newLen;
|
|
62
|
|
63 alloc = cast(void*)-1;
|
|
64 return;
|
|
65 }
|
|
66 }
|
|
67 }
|
|
68 }
|
|
69
|
|
70 version (TrackList) {
|
|
71 size_t mPrev;
|
|
72 size_t mNext;
|
|
73 }
|
|
74
|
|
75 void* alloc;
|
|
76
|
|
77 static TObject unpack(size_t m)
|
|
78 {
|
|
79 m &= ~(1 << 31);
|
|
80 return cast(TObject)cast(void*)m;
|
|
81 }
|
|
82
|
|
83 static size_t pack(size_t m)
|
|
84 {
|
|
85 return m |= (1 << 31);
|
|
86 }
|
|
87
|
|
88 static size_t pack(TObject o)
|
|
89 {
|
|
90 return pack(cast(size_t)cast(void*)o);
|
|
91 }
|
|
92
|
|
93 void forceRegister()
|
|
94 {
|
|
95 version (TrackList) {
|
|
96 alloc = alloc_point();
|
|
97 size_t mThis = pack(this);
|
|
98
|
|
99 mNext = mHead;
|
|
100 if (mHead != mNull) {
|
|
101 unpack(mHead).mPrev = mThis;
|
|
102 }
|
|
103
|
|
104 mPrev = mNull;
|
|
105 mHead = mThis;
|
|
106 } else version (TrackArray) {
|
|
107 alloc = alloc_point();
|
|
108 objects ~= pack(this);
|
|
109 }
|
|
110 }
|
|
111
|
|
112 void register()
|
|
113 {
|
|
114 if (alloc !is null) return;
|
|
115 forceRegister();
|
|
116 }
|
|
117
|
|
118 static void dump()
|
|
119 {
|
|
120 int[void*] allocStat;
|
|
121
|
|
122 version (TrackList) {
|
|
123 auto o = unpack(mHead);
|
|
124 while (o !is null) {
|
|
125 allocStat[o.alloc]++;
|
|
126 o = unpack(o.mNext);
|
|
127 }
|
|
128 } else version (TrackArray) {
|
|
129 foreach (i, m; objects) {
|
|
130 allocStat[unpack(m).alloc]++;
|
|
131 }
|
|
132 }
|
|
133
|
|
134 FILE* f = fopen("alloc_stat.txt", "wb");
|
|
135 if (f is null) return;
|
|
136
|
|
137 StackFrameInfo* frame = void;
|
|
138 DebugImage* imageList, image = void;
|
|
139 char[255] buffer = void;
|
|
140
|
|
141 MEMORY_BASIC_INFORMATION mbi = void;
|
|
142
|
|
143 void resolve(const(void)* c) {
|
|
144 StackFrameInfo frame;
|
|
145 frame.va = cast(void*)c;
|
|
146
|
|
147 // mbi.Allocation base is the handle to stack frame's module
|
|
148 VirtualQuery(frame.va, &mbi, MEMORY_BASIC_INFORMATION.sizeof);
|
|
149 if (!mbi.AllocationBase) return;
|
|
150
|
|
151 image = imageList;
|
|
152 while(image) {
|
|
153 if (image.baseAddress == cast(size_t)mbi.AllocationBase) break;
|
|
154 image = image.next;
|
|
155 }
|
|
156
|
|
157 if (!image) {
|
|
158 image = new DebugImage;
|
|
159
|
|
160 with (*image) {
|
|
161 next = imageList;
|
|
162 imageList = image;
|
|
163 baseAddress = cast(size_t)mbi.AllocationBase;
|
|
164
|
|
165 uint len = GetModuleFileNameA(cast(HMODULE)baseAddress, buffer.ptr, buffer.length);
|
|
166 moduleName = buffer[0 .. len].idup;
|
|
167
|
|
168 if (len != 0) {
|
|
169 exeModule = new PEImage(moduleName);
|
|
170 rvaOffset = baseAddress + exeModule.codeOffset;
|
|
171 debugInfo = exeModule.debugInfo;
|
|
172 }
|
|
173 }
|
|
174 }
|
|
175
|
|
176 frame.moduleName = image.moduleName;
|
|
177
|
|
178 size_t va = cast(size_t)frame.va;
|
|
179
|
|
180 if (image.debugInfo) with (image.debugInfo) {
|
|
181 uint rva = va - image.rvaOffset;
|
|
182
|
|
183 frame.symbol = ResolveSymbol(rva);
|
|
184 frame.fileLine = ResolveFileLine(rva);
|
|
185 }
|
|
186
|
|
187 auto s = image.exeModule.closestSymbol(va);
|
|
188 printf("%.*s\n", s);
|
|
189 auto symbol = demangle(s.symbol);
|
|
190
|
|
191 if (frame.fileLine.file.length != 0) {
|
|
192 fprintf(f, "%.*s %.*s:%d\n", symbol, frame.fileLine.file, frame.fileLine.line);
|
|
193 // } else {
|
|
194 // if (symbol.length != 0) {
|
|
195 // fprintf(f, "%.*s", symbol);
|
|
196 // }
|
|
197 }
|
|
198 }
|
|
199
|
|
200 while (imageList) {
|
|
201 image = imageList.next;
|
|
202 delete imageList.debugInfo;
|
|
203 delete imageList.exeModule;
|
|
204 delete imageList;
|
|
205 imageList = image;
|
|
206 }
|
|
207
|
|
208 int max = 0;
|
|
209 int total = 0;
|
|
210 fprintf(f, "%d\n", allocStat.length);
|
|
211 foreach (alloc, count; allocStat) {
|
|
212 resolve(alloc);
|
|
213
|
|
214 fprintf(f, "count: %d\n\n", count);
|
|
215 if (count > max) max = count;
|
|
216 total += count;
|
|
217 }
|
|
218 fprintf(f, "max: %d\n\n", max);
|
|
219 fprintf(f, "total: %d\n\n", total);
|
|
220 fclose(f);
|
|
221 }
|
|
222 */
|
|
223 }
|
|
224 /*
|
|
225 void* alloc_point()
|
|
226 {
|
|
227 void** bp = void;
|
|
228
|
|
229 asm {
|
|
230 mov bp, EBP;
|
|
231 }
|
|
232
|
|
233 bp = cast(void**)*bp;
|
|
234 bp = cast(void**)*bp;
|
|
235 bp = cast(void**)*bp;
|
|
236 return *(bp + 1);
|
|
237 }
|
|
238
|
|
239 void callstack_print(FILE* f, void*[] callstack)
|
|
240 {
|
|
241 char** framelist = backtrace_symbols(callstack.ptr, callstack.length);
|
|
242 for( int i = 0; i < callstack.length; ++i )
|
|
243 {
|
|
244 auto line = framelist[i];
|
|
245 if (strcmp(line, "<no debug info found>") == 0) {
|
|
246 continue;
|
|
247 }
|
|
248 fwrite(line, 1, strlen(line), f);
|
|
249 fwrite("\n".ptr, 1, 1, f);
|
|
250 }
|
|
251 free(framelist);
|
|
252 }
|
|
253 */ |