source: lab.git/Dev/utvpn/utvpn-unix-v101-7101-public/src/Mayaqua/Tracking.c @ a1bae3e

trunk
Last change on this file since a1bae3e was a1bae3e, checked in by mitty <mitty@…>, 12 years ago
  • copy vendor drop to trunk

git-svn-id: https://lab.mitty.jp/svn/lab/trunk@147 7d2118f6-f56c-43e7-95a2-4bb3031d96e7

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