* copy vendor drop to trunk
[lab.git] / Dev / utvpn / utvpn-unix-v101-7101-public / src / Mayaqua / Tracking.c
1 // SoftEther UT-VPN SourceCode\r
2 // \r
3 // Copyright (C) 2004-2010 SoftEther Corporation.\r
4 // Copyright (C) 2004-2010 University of Tsukuba, Japan.\r
5 // Copyright (C) 2003-2010 Daiyuu Nobori.\r
6 // All Rights Reserved.\r
7 // \r
8 // http://utvpn.tsukuba.ac.jp/\r
9 // \r
10 // This program is free software; you can redistribute it and/or\r
11 // modify it under the terms of the GNU General Public License\r
12 // version 2 as published by the Free Software Foundation.\r
13 // \r
14 // This program is distributed in the hope that it will be useful,\r
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of\r
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
17 // GNU General Public License for more details.\r
18 // \r
19 // You should have received a copy of the GNU General Public License version 2\r
20 // along with this program; if not, write to the Free Software\r
21 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\r
22 // \r
23 // このファイルは GPL バージョン 2 ライセンスで公開されています。\r
24 // 誰でもこのファイルの内容を複製、改変したり、改変したバージョンを再配布\r
25 // することができます。ただし、原著作物を改変した場合は、原著作物の著作権表示\r
26 // を除去することはできません。改変した著作物を配布する場合は、改変実施者の\r
27 // 著作権表示を原著作物の著作権表示に付随して記載するようにしてください。\r
28 // \r
29 // この SoftEther UT-VPN オープンソース・プロジェクトは、日本国の\r
30 // ソフトイーサ株式会社 (SoftEther Corporation, http://www.softether.co.jp/ )\r
31 // および筑波大学 (University of Tsukuba, http://www.tsukuba.ac.jp/ ) によって\r
32 // ホストされています。\r
33 // 本プログラムの配布者は、本プログラムを、業としての利用以外のため、\r
34 // および、試験または研究のために利用が行われることを想定して配布\r
35 // しています。\r
36 // SoftEther UT-VPN プロジェクトの Web サイトは http://utvpn.tsukuba.ac.jp/ に\r
37 // あります。\r
38 // 本ソフトウェアの不具合の修正、機能改良、セキュリティホールの修復などのコード\r
39 // の改変を行った場合で、その成果物を SoftEther UT-VPN プロジェクトに提出して\r
40 // いただける場合は、 http://utvpn.tsukuba.ac.jp/ までソースコードを送付して\r
41 // ください。SoftEther UT-VPN プロジェクトの本体リリースまたはブランチリリース\r
42 // に組み込みさせていただきます。\r
43 // \r
44 // GPL に基づいて原著作物が提供される本ソフトウェアの改良版を配布、販売する\r
45 // 場合は、そのソースコードを GPL に基づいて誰にでも開示する義務が生じます。\r
46 // \r
47 // 本ソフトウェアに関連する著作権、特許権、商標権はソフトイーサ株式会社\r
48 // (SoftEther Corporation) およびその他の著作権保持者が保有しています。\r
49 // ソフトイーサ株式会社等はこれらの権利を放棄していません。本ソフトウェアの\r
50 // 二次著作物を配布、販売する場合は、これらの権利を侵害しないようにご注意\r
51 // ください。\r
52 // \r
53 // お願い: どのような通信ソフトウェアにも通常は必ず未発見の\r
54 // セキュリティホールが潜んでいます。本ソースコードをご覧いただいた結果、\r
55 // UT-VPN にセキュリティホールを発見された場合は、当該セキュリティホールの\r
56 // 情報を不特定多数に開示される前に、必ず、ソフトイーサ株式会社\r
57 // および脆弱性情報の届出を受け付ける公的機関まで通報いただき、\r
58 // 公益保護にご協力いただきますようお願い申し上げます。\r
59 // \r
60 // ソフトイーサ株式会社は、当該セキュリティホールについて迅速に対処を\r
61 // 行い、UT-VPN および UT-VPN に関連するソフトウェアのユーザー・顧客\r
62 // を保護するための努力を行います。\r
63 // \r
64 // ソフトイーサへの届出先: http://www.softether.co.jp/jp/contact/\r
65 // 日本国内の脆弱性情報届出受付公的機関:\r
66 //         独立行政法人 情報処理推進機構\r
67 //         http://www.ipa.go.jp/security/vuln/report/\r
68 // \r
69 // 上記各事項について不明な点は、ソフトイーサ株式会社までご連絡ください。\r
70 // 連絡先: http://www.softether.co.jp/jp/contact/\r
71 \r
72 // -----------------------------------------------\r
73 // [ChangeLog]\r
74 // 2010.05.20\r
75 //  新規リリース by SoftEther\r
76 // -----------------------------------------------\r
77 \r
78 // Tracking.c\r
79 // オブジェクト追跡モジュール\r
80 \r
81 #include <stdio.h>\r
82 #include <stdlib.h>\r
83 #include <string.h>\r
84 #include <wchar.h>\r
85 #include <stdarg.h>\r
86 #include <time.h>\r
87 #include <errno.h>\r
88 #include <Mayaqua/Mayaqua.h>\r
89 \r
90 // グローバル変数\r
91 static LOCK *obj_lock;\r
92 static LOCK *obj_id_lock;\r
93 static UINT obj_id;\r
94 static LOCK *cs_lock;\r
95 static bool disable_tracking = false;\r
96 static TRACKING_LIST **hashlist;\r
97 \r
98 static bool do_not_get_callstack;\r
99 \r
100 // 追跡を有効にする\r
101 void TrackingEnable()\r
102 {\r
103         disable_tracking = false;\r
104 }\r
105 \r
106 // 追跡を無効にする\r
107 void TrackingDisable()\r
108 {\r
109         disable_tracking = true;\r
110 }\r
111 \r
112 // 追跡が有効かどうか取得\r
113 bool IsTrackingEnabled()\r
114 {\r
115         return !disable_tracking;\r
116 }\r
117 \r
118 // メモリデバッグメニュー\r
119 void MemoryDebugMenu()\r
120 {\r
121         char tmp[MAX_SIZE];\r
122         TOKEN_LIST *t;\r
123         char *cmd;\r
124         Print("Mayaqua Kernel Memory Debug Tools\n"\r
125                 "Copyright (C) SoftEther Corporation. All Rights Reserved.\n\n");\r
126         g_memcheck = false;\r
127         while (true)\r
128         {\r
129                 Print("debug>");\r
130                 GetLine(tmp, sizeof(tmp));\r
131                 t = ParseToken(tmp, " \t");\r
132                 if (t->NumTokens == 0)\r
133                 {\r
134                         FreeToken(t);\r
135                         DebugPrintAllObjects();\r
136                         continue;\r
137                 }\r
138                 cmd = t->Token[0];\r
139                 if (!StrCmpi(cmd, "?"))\r
140                 {\r
141                         DebugPrintCommandList();\r
142                 }\r
143                 else if (!StrCmpi(cmd, "a"))\r
144                 {\r
145                         DebugPrintAllObjects();\r
146                 }\r
147                 else if (!StrCmpi(cmd, "i"))\r
148                 {\r
149                         if (t->NumTokens == 1)\r
150                         {\r
151                                 Print("Usage: i <obj_id>\n\n");\r
152                         }\r
153                         else\r
154                         {\r
155                                 DebugPrintObjectInfo(ToInt(t->Token[1]));\r
156                         }\r
157                 }\r
158                 else if (!StrCmpi(cmd, "q"))\r
159                 {\r
160                         break;\r
161                 }\r
162                 else if (ToInt(cmd) != 0)\r
163                 {\r
164                         DebugPrintObjectInfo(ToInt(t->Token[0]));\r
165                 }\r
166                 else\r
167                 {\r
168                         Print("Command Not Found,\n\n");\r
169                 }\r
170                 FreeToken(t);\r
171         }\r
172         FreeToken(t);\r
173         g_memcheck = true;\r
174 }\r
175 \r
176 // オブジェクトを時間順にソートする\r
177 int SortObjectView(void *p1, void *p2)\r
178 {\r
179         TRACKING_OBJECT *o1, *o2;\r
180         if (p1 == NULL || p2 == NULL)\r
181         {\r
182                 return 0;\r
183         }\r
184         o1 = *(TRACKING_OBJECT **)p1;\r
185         o2 = *(TRACKING_OBJECT **)p2;\r
186         if (o1 == NULL || o2 == NULL)\r
187         {\r
188                 return 0;\r
189         }\r
190 \r
191         if (o1->Id > o2->Id)\r
192         {\r
193                 return 1;\r
194         }\r
195         else if (o1->Id == o2->Id)\r
196         {\r
197                 return 0;\r
198         }\r
199         return -1;\r
200 }\r
201 \r
202 // オブジェクト情報の表示\r
203 void PrintObjectInfo(TRACKING_OBJECT *o)\r
204 {\r
205         SYSTEMTIME t;\r
206         char tmp[MAX_SIZE];\r
207         // 引数チェック\r
208         if (o == NULL)\r
209         {\r
210                 return;\r
211         }\r
212 \r
213         UINT64ToSystem(&t, o->CreatedDate);\r
214         GetDateTimeStrMilli(tmp, sizeof(tmp), &t);\r
215 \r
216         Print("    TRACKING_OBJECT ID: %u\n"\r
217                 "  TRACKING_OBJECT TYPE: %s\n"\r
218                 "      ADDRESS: 0x%p\n"\r
219                 "  TRACKING_OBJECT SIZE: %u bytes\n"\r
220                 " CREATED DATE: %s\n",\r
221                 o->Id, o->Name, UINT64_TO_POINTER(o->Address), o->Size, tmp);\r
222 \r
223         PrintCallStack(o->CallStack);\r
224 }\r
225 \r
226 // オブジェクト情報を表示する\r
227 void DebugPrintObjectInfo(UINT id)\r
228 {\r
229         UINT i;\r
230         TRACKING_OBJECT *o;\r
231 \r
232         // 検索\r
233         o = NULL;\r
234         LockTrackingList();\r
235         {\r
236                 for (i = 0;i < TRACKING_NUM_ARRAY;i++)\r
237                 {\r
238                         if (hashlist[i] != NULL)\r
239                         {\r
240                                 TRACKING_LIST *t = hashlist[i];\r
241 \r
242                                 while (true)\r
243                                 {\r
244                                         if (t->Object->Id == id)\r
245                                         {\r
246                                                 o = t->Object;\r
247                                                 break;\r
248                                         }\r
249 \r
250                                         if (t->Next == NULL)\r
251                                         {\r
252                                                 break;\r
253                                         }\r
254 \r
255                                         t = t->Next;\r
256                                 }\r
257 \r
258                                 if (o != NULL)\r
259                                 {\r
260                                         break;\r
261                                 }\r
262                         }\r
263                 }\r
264         }\r
265         UnlockTrackingList();\r
266 \r
267         if (o == NULL)\r
268         {\r
269                 // ID が発見できなかった\r
270                 Print("obj_id %u Not Found.\n\n", id);\r
271                 return;\r
272         }\r
273 \r
274         PrintObjectInfo(o);\r
275         Print("\n");\r
276 }\r
277 \r
278 // オブジェクトのサマリーの表示\r
279 void PrintObjectList(TRACKING_OBJECT *o)\r
280 {\r
281         char tmp[MAX_SIZE];\r
282         SYSTEMTIME t;\r
283         UINT64ToSystem(&t, o->CreatedDate);\r
284         GetTimeStrMilli(tmp, sizeof(tmp), &t);\r
285         TrackGetObjSymbolInfo(o);\r
286         Print("%-4u - [%-6s] %s 0x%p size=%-5u %11s %u\n",\r
287                 o->Id, o->Name, tmp, UINT64_TO_POINTER(o->Address), o->Size, o->FileName, o->LineNumber);\r
288 }\r
289 \r
290 // すべてのオブジェクトの表示\r
291 void DebugPrintAllObjects()\r
292 {\r
293         UINT i;\r
294         LIST *view;\r
295 \r
296         // リスト作成\r
297         view = NewListFast(SortObjectView);\r
298         LockTrackingList();\r
299         {\r
300                 for (i = 0;i < TRACKING_NUM_ARRAY;i++)\r
301                 {\r
302                         if (hashlist[i] != NULL)\r
303                         {\r
304                                 TRACKING_LIST *t = hashlist[i];\r
305 \r
306                                 while (true)\r
307                                 {\r
308                                         Add(view, t->Object);\r
309 \r
310                                         if (t->Next == NULL)\r
311                                         {\r
312                                                 break;\r
313                                         }\r
314 \r
315                                         t = t->Next;\r
316                                 }\r
317                         }\r
318                 }\r
319         }\r
320         UnlockTrackingList();\r
321 \r
322         // ソート\r
323         Sort(view);\r
324 \r
325         // 描画\r
326         for (i = 0;i < LIST_NUM(view);i++)\r
327         {\r
328                 TRACKING_OBJECT *o = (TRACKING_OBJECT *)LIST_DATA(view, i);\r
329                 PrintObjectList(o);\r
330         }\r
331 \r
332         // リスト解放\r
333         ReleaseList(view);\r
334 \r
335         Print("\n");\r
336 }\r
337 \r
338 // コマンド一覧\r
339 void DebugPrintCommandList()\r
340 {\r
341         Print(\r
342                 "a - All Objects\n"\r
343                 "i - Object Information\n"\r
344                 "? - Help\n"\r
345                 "q - Quit\n\n"\r
346                 );\r
347 }\r
348 \r
349 // メモリの使用状態を表示する\r
350 void PrintMemoryStatus()\r
351 {\r
352         MEMORY_STATUS s;\r
353         GetMemoryStatus(&s);\r
354         Print("MEMORY STATUS:\n"\r
355                 " NUM_OF_MEMORY_BLOCKS: %u\n"\r
356                 " SIZE_OF_TOTAL_MEMORY: %u bytes\n",\r
357                 s.MemoryBlocksNum, s.MemorySize);\r
358 }\r
359 \r
360 // メモリの使用状態を取得する\r
361 void GetMemoryStatus(MEMORY_STATUS *status)\r
362 {\r
363         UINT i, num, size;\r
364         // 引数チェック\r
365         if (status == NULL)\r
366         {\r
367                 return;\r
368         }\r
369 \r
370         LockTrackingList();\r
371         {\r
372                 size = num = 0;\r
373 \r
374                 for (i = 0;i < TRACKING_NUM_ARRAY;i++)\r
375                 {\r
376                         if (hashlist[i] != NULL)\r
377                         {\r
378                                 TRACKING_LIST *t = hashlist[i];\r
379 \r
380                                 while (true)\r
381                                 {\r
382                                         TRACKING_OBJECT *o = t->Object;\r
383 \r
384                                         if (StrCmpi(o->Name, "MEM") == 0)\r
385                                         {\r
386                                                 num++;\r
387                                                 size += o->Size;\r
388                                         }\r
389 \r
390                                         if (t->Next == NULL)\r
391                                         {\r
392                                                 break;\r
393                                         }\r
394 \r
395                                         t = t->Next;\r
396                                 }\r
397                         }\r
398                 }\r
399         }\r
400         UnlockTrackingList();\r
401 \r
402         status->MemoryBlocksNum = num;\r
403         status->MemorySize = size;\r
404 }\r
405 \r
406 // オブジェクトからシンボル情報を取得する\r
407 void TrackGetObjSymbolInfo(TRACKING_OBJECT *o)\r
408 {\r
409         // 引数チェック\r
410         if (o == NULL)\r
411         {\r
412                 return;\r
413         }\r
414 \r
415         if (!(o->LineNumber == 0 && o->FileName[0] == 0))\r
416         {\r
417                 return;\r
418         }\r
419 \r
420         if (o->CallStack != NULL)\r
421         {\r
422                 GetCallStackSymbolInfo(o->CallStack);\r
423                 if (StrLen(o->CallStack->filename) != 0 && o->CallStack->line != 0)\r
424                 {\r
425                         StrCpy(o->FileName, sizeof(o->FileName), o->CallStack->filename);\r
426                         o->LineNumber = o->CallStack->line;\r
427                 }\r
428         }\r
429 }\r
430 \r
431 // 新しいオブジェクトを追跡リストに入れる\r
432 void TrackNewObj(UINT64 addr, char *name, UINT size)\r
433 {\r
434         TRACKING_OBJECT *o;\r
435         UINT new_id;\r
436         // 引数チェック\r
437         if (addr == 0 || name == NULL)\r
438         {\r
439                 return;\r
440         }\r
441 \r
442         if (IsMemCheck() == false)\r
443         {\r
444                 // リリースモードでは追跡しない\r
445                 return;\r
446         }\r
447 \r
448         if (disable_tracking)\r
449         {\r
450                 return;\r
451         }\r
452 \r
453         // 新しい ID の生成\r
454         OSLock(obj_id_lock);\r
455         {\r
456                 new_id = ++obj_id;\r
457         }\r
458         OSUnlock(obj_id_lock);\r
459 \r
460         o = OSMemoryAlloc(sizeof(TRACKING_OBJECT));\r
461         o->Id = new_id;\r
462         o->Address = addr;\r
463         o->Name = name;\r
464         o->Size = size;\r
465         o->CreatedDate = LocalTime64();\r
466         o->CallStack = WalkDownCallStack(GetCallStack(), 2);\r
467 \r
468         o->FileName[0] = 0;\r
469         o->LineNumber = 0;\r
470 \r
471         LockTrackingList();\r
472         {\r
473                 InsertTrackingList(o);\r
474         }\r
475         UnlockTrackingList();\r
476 }\r
477 \r
478 // 追跡リストからオブジェクトを削除する\r
479 void TrackDeleteObj(UINT64 addr)\r
480 {\r
481         TRACKING_OBJECT *o;\r
482         // 引数チェック\r
483         if (addr == 0)\r
484         {\r
485                 return;\r
486         }\r
487 \r
488         if (IsMemCheck() == false)\r
489         {\r
490                 // リリースモードでは追跡しない\r
491                 return;\r
492         }\r
493 \r
494         if (disable_tracking)\r
495         {\r
496                 return;\r
497         }\r
498 \r
499         LockTrackingList();\r
500         {\r
501                 o = SearchTrackingList(addr);\r
502                 if (o == NULL)\r
503                 {\r
504                         UnlockTrackingList();\r
505 \r
506                         if (IsDebug())\r
507                         {\r
508                                 printf("TrackDeleteObj: 0x%x is not Object!!\n", (void *)addr);\r
509                         }\r
510                         return;\r
511                 }\r
512                 DeleteTrackingList(o, true);\r
513         }\r
514         UnlockTrackingList();\r
515 }\r
516 \r
517 // 追跡しているオブジェクトのサイズを変更する\r
518 void TrackChangeObjSize(UINT64 addr, UINT size, UINT64 new_addr)\r
519 {\r
520         TRACKING_OBJECT *o;\r
521         // 引数チェック\r
522         if (addr == 0)\r
523         {\r
524                 return;\r
525         }\r
526 \r
527         if (IsMemCheck() == false)\r
528         {\r
529                 // リリースモードでは追跡しない\r
530                 return;\r
531         }\r
532 \r
533         if (disable_tracking)\r
534         {\r
535                 return;\r
536         }\r
537 \r
538         LockTrackingList();\r
539         {\r
540                 o = SearchTrackingList(addr);\r
541                 if (o == NULL)\r
542                 {\r
543                         UnlockTrackingList();\r
544                         return;\r
545                 }\r
546 \r
547                 DeleteTrackingList(o, false);\r
548 \r
549                 o->Size = size;\r
550                 o->Address = new_addr;\r
551 \r
552                 InsertTrackingList(o);\r
553         }\r
554         UnlockTrackingList();\r
555 }\r
556 \r
557 // メモリアドレス比較関数\r
558 int CompareTrackingObject(const void *p1, const void *p2)\r
559 {\r
560         TRACKING_OBJECT *o1, *o2;\r
561         // 引数チェック\r
562         if (p1 == NULL || p2 == NULL)\r
563         {\r
564                 return 0;\r
565         }\r
566         o1 = *(TRACKING_OBJECT **)p1;\r
567         o2 = *(TRACKING_OBJECT **)p2;\r
568         if (o1 == NULL || o2 == NULL)\r
569         {\r
570                 return 0;\r
571         }\r
572 \r
573         if (o1->Address > o2->Address)\r
574         {\r
575                 return 1;\r
576         }\r
577         if (o1->Address == o2->Address)\r
578         {\r
579                 return 0;\r
580         }\r
581         return -1;\r
582 }\r
583 \r
584 // オブジェクトをトラッキングリストから検索\r
585 TRACKING_OBJECT *SearchTrackingList(UINT64 Address)\r
586 {\r
587         UINT i;\r
588         // 引数チェック\r
589         if (Address == 0)\r
590         {\r
591                 return NULL;\r
592         }\r
593 \r
594         i = TRACKING_HASH(Address);\r
595 \r
596         if (hashlist[i] != NULL)\r
597         {\r
598                 TRACKING_LIST *tt = hashlist[i];\r
599 \r
600                 while (true)\r
601                 {\r
602                         if (tt->Object->Address == Address)\r
603                         {\r
604                                 return tt->Object;\r
605                         }\r
606 \r
607                         tt = tt->Next;\r
608 \r
609                         if (tt == NULL)\r
610                         {\r
611                                 break;\r
612                         }\r
613                 }\r
614         }\r
615 \r
616         return NULL;\r
617 }\r
618 \r
619 // オブジェクトをトラッキングリストから削除\r
620 void DeleteTrackingList(TRACKING_OBJECT *o, bool free_object_memory)\r
621 {\r
622         UINT i;\r
623         // 引数チェック\r
624         if (o == NULL)\r
625         {\r
626                 return;\r
627         }\r
628 \r
629         i = TRACKING_HASH(o->Address);\r
630 \r
631         if (hashlist[i] != NULL)\r
632         {\r
633                 TRACKING_LIST *ft = NULL;\r
634 \r
635                 if (hashlist[i]->Object == o)\r
636                 {\r
637                         ft = hashlist[i];\r
638                         hashlist[i] = hashlist[i]->Next;\r
639                 }\r
640                 else\r
641                 {\r
642                         TRACKING_LIST *tt = hashlist[i];\r
643                         TRACKING_LIST *prev = NULL;\r
644 \r
645                         while (true)\r
646                         {\r
647                                 if (tt->Object == o)\r
648                                 {\r
649                                         prev->Next = tt->Next;\r
650                                         ft = tt;\r
651                                         break;\r
652                                 }\r
653 \r
654                                 if (tt->Next == NULL)\r
655                                 {\r
656                                         break;\r
657                                 }\r
658 \r
659                                 prev = tt;\r
660                                 tt = tt->Next;\r
661                         }\r
662                 }\r
663 \r
664                 if (ft != NULL)\r
665                 {\r
666                         OSMemoryFree(ft);\r
667 \r
668                         if (free_object_memory)\r
669                         {\r
670                                 FreeCallStack(o->CallStack);\r
671                                 OSMemoryFree(o);\r
672                         }\r
673                 }\r
674         }\r
675 }\r
676 \r
677 // オブジェクトをトラッキングリストに挿入\r
678 void InsertTrackingList(TRACKING_OBJECT *o)\r
679 {\r
680         UINT i;\r
681         TRACKING_LIST *t;\r
682         // 引数チェック\r
683         if (o == NULL)\r
684         {\r
685                 return;\r
686         }\r
687 \r
688         t = OSMemoryAlloc(sizeof(TRACKING_LIST));\r
689         t->Object = o;\r
690         t->Next = NULL;\r
691 \r
692         i = TRACKING_HASH(o->Address);\r
693 \r
694         if (hashlist[i] == NULL)\r
695         {\r
696                 hashlist[i] = t;\r
697         }\r
698         else\r
699         {\r
700                 TRACKING_LIST *tt = hashlist[i];\r
701                 while (true)\r
702                 {\r
703                         if (tt->Next == NULL)\r
704                         {\r
705                                 tt->Next = t;\r
706                                 break;\r
707                         }\r
708 \r
709                         tt = tt->Next;\r
710                 }\r
711         }\r
712 }\r
713 \r
714 // トラッキングリストのロック\r
715 void LockTrackingList()\r
716 {\r
717         OSLock(obj_lock);\r
718 }\r
719 \r
720 // トラッキングリストのロック解除\r
721 void UnlockTrackingList()\r
722 {\r
723         OSUnlock(obj_lock);\r
724 }\r
725 \r
726 // トラッキングの初期化\r
727 void InitTracking()\r
728 {\r
729         UINT i;\r
730         CALLSTACK_DATA *s;\r
731 \r
732         // ハッシュリスト初期化\r
733         hashlist = (TRACKING_LIST **)OSMemoryAlloc(sizeof(TRACKING_LIST *) * TRACKING_NUM_ARRAY);\r
734 \r
735         for (i = 0;i < TRACKING_NUM_ARRAY;i++)\r
736         {\r
737                 hashlist[i] = NULL;\r
738         }\r
739 \r
740         obj_id = 0;\r
741 \r
742         // ロック作成\r
743         obj_lock = OSNewLock();\r
744         obj_id_lock = OSNewLock();\r
745         cs_lock = OSNewLock();\r
746 \r
747         s = GetCallStack();\r
748         if (s == NULL)\r
749         {\r
750                 do_not_get_callstack = true;\r
751         }\r
752         else\r
753         {\r
754                 do_not_get_callstack = false;\r
755                 FreeCallStack(s);\r
756         }\r
757 }\r
758 \r
759 // トラッキングの解放\r
760 void FreeTracking()\r
761 {\r
762         UINT i;\r
763         // ロック削除\r
764         OSDeleteLock(obj_lock);\r
765         OSDeleteLock(obj_id_lock);\r
766         OSDeleteLock(cs_lock);\r
767         cs_lock = NULL;\r
768         obj_id_lock = NULL;\r
769         obj_lock = NULL;\r
770 \r
771         // すべての要素を解放\r
772         for (i = 0;i < TRACKING_NUM_ARRAY;i++)\r
773         {\r
774                 if (hashlist[i] != NULL)\r
775                 {\r
776                         TRACKING_LIST *t = hashlist[i];\r
777 \r
778                         while (true)\r
779                         {\r
780                                 TRACKING_LIST *t2 = t;\r
781                                 TRACKING_OBJECT *o = t->Object;\r
782 \r
783                                 FreeCallStack(o->CallStack);\r
784                                 OSMemoryFree(o);\r
785 \r
786                                 t = t->Next;\r
787 \r
788                                 OSMemoryFree(t2);\r
789 \r
790                                 if (t == NULL)\r
791                                 {\r
792                                         break;\r
793                                 }\r
794                         }\r
795                 }\r
796         }\r
797 \r
798         // リスト解放\r
799         OSMemoryFree(hashlist);\r
800 }\r
801 \r
802 // コールスタックを表示する\r
803 void PrintCallStack(CALLSTACK_DATA *s)\r
804 {\r
805         char tmp[MAX_SIZE * 2];\r
806 \r
807         GetCallStackStr(tmp, sizeof(tmp), s);\r
808         Print("%s", tmp);\r
809 }\r
810 \r
811 // コールスタックを文字列に変換する\r
812 void GetCallStackStr(char *str, UINT size, CALLSTACK_DATA *s)\r
813 {\r
814         char tmp[MAX_SIZE];\r
815         char tmp2[MAX_SIZE];\r
816         char tmp3[MAX_SIZE];\r
817         UINT num, i;\r
818         // 引数チェック\r
819         if (str == NULL)\r
820         {\r
821                 return;\r
822         }\r
823 \r
824         if (s == NULL)\r
825         {\r
826                 StrCpy(str, size, "(Unknown)\n");\r
827         }\r
828         else\r
829         {\r
830                 num = 0;\r
831                 str[0] = 0;\r
832                 while (true)\r
833                 {\r
834                         if (s == NULL)\r
835                         {\r
836                                 break;\r
837                         }\r
838 \r
839                         GetCallStackSymbolInfo(s);\r
840 \r
841                         if (s->name == NULL)\r
842                         {\r
843                                 Format(tmp, sizeof(tmp), "0x%p ---", UINT64_TO_POINTER(s->offset));\r
844                         }\r
845                         else\r
846                         {\r
847                                 Format(tmp, sizeof(tmp), "0x%p %s() + 0x%02x",\r
848                                         (void *)s->offset, s->name, UINT64_TO_POINTER(s->disp));\r
849                         }\r
850                         for (i = 0;i < num;i++)\r
851                         {\r
852                                 tmp2[i] = ' ';\r
853                         }\r
854                         tmp2[i] = '\0';\r
855                         StrCpy(tmp3, sizeof(tmp3), tmp2);\r
856                         StrCat(tmp3, sizeof(tmp3), tmp);\r
857                         Format(tmp, sizeof(tmp), "%-55s %11s %u\n", tmp3, s->filename, s->line);\r
858                         StrCat(str, size, tmp);\r
859                         num++;\r
860                         s = s->next;\r
861                 }\r
862         }\r
863 }\r
864 \r
865 // 現在のコールスタックの取得\r
866 CALLSTACK_DATA *GetCallStack()\r
867 {\r
868         CALLSTACK_DATA *s;\r
869         if (do_not_get_callstack)\r
870         {\r
871                 // コールスタックは取得しない\r
872                 return NULL;\r
873         }\r
874 \r
875         OSLock(cs_lock);\r
876         {\r
877                 // コールスタックの取得\r
878                 s = OSGetCallStack();\r
879         }\r
880         OSUnlock(cs_lock);\r
881         if (s == NULL)\r
882         {\r
883                 return NULL;\r
884         }\r
885 \r
886         // コールスタックを 3 つ分だけ下降する\r
887         s = WalkDownCallStack(s, 3);\r
888 \r
889         return s;\r
890 }\r
891 \r
892 // コールスタックのシンボル情報を取得\r
893 bool GetCallStackSymbolInfo(CALLSTACK_DATA *s)\r
894 {\r
895         bool ret;\r
896         // 引数チェック\r
897         if (s == NULL)\r
898         {\r
899                 return false;\r
900         }\r
901 \r
902         OSLock(cs_lock);\r
903         {\r
904                 ret = OSGetCallStackSymbolInfo(s);\r
905         }\r
906         OSUnlock(cs_lock);\r
907 \r
908         return ret;\r
909 }\r
910 \r
911 // コールスタックを指定された数だけ下降する\r
912 CALLSTACK_DATA *WalkDownCallStack(CALLSTACK_DATA *s, UINT num)\r
913 {\r
914         CALLSTACK_DATA *cs, *tmp;\r
915         UINT i;\r
916         // 引数チェック\r
917         if (s == NULL)\r
918         {\r
919                 return NULL;\r
920         }\r
921 \r
922         cs = s;\r
923         i = 0;\r
924 \r
925         while (true)\r
926         {\r
927                 if (i >= num)\r
928                 {\r
929                         return cs;\r
930                 }\r
931                 i++;\r
932                 tmp = cs;\r
933                 cs = tmp->next;\r
934                 OSMemoryFree(tmp->name);\r
935                 OSMemoryFree(tmp);\r
936 \r
937                 if (cs == NULL)\r
938                 {\r
939                         return NULL;\r
940                 }\r
941         }\r
942 }\r
943 \r
944 // コールスタックの解放\r
945 void FreeCallStack(CALLSTACK_DATA *s)\r
946 {\r
947         // 引数チェック\r
948         if (s == NULL)\r
949         {\r
950                 return;\r
951         }\r
952 \r
953         while (true)\r
954         {\r
955                 CALLSTACK_DATA *next = s->next;\r
956                 OSMemoryFree(s->name);\r
957                 OSMemoryFree(s);\r
958                 if (next == NULL)\r
959                 {\r
960                         break;\r
961                 }\r
962                 s = next;\r
963         }\r
964 }\r
965 \r
966 \r