|
1 // LoggingAllocator.h |
|
2 // |
|
3 // Copyright (c) 2010 Accenture. All rights reserved. |
|
4 // This component and the accompanying materials are made available |
|
5 // under the terms of the "Eclipse Public License v1.0" |
|
6 // which accompanies this distribution, and is available |
|
7 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 // |
|
9 // Initial Contributors: |
|
10 // Accenture - Initial contribution |
|
11 // |
|
12 #ifndef LOGGING_ALLOCATOR_H |
|
13 #define LOGGING_ALLOCATOR_H |
|
14 |
|
15 #include <e32cmn.h> |
|
16 #include <fshell/clogger.h> |
|
17 #include <fshell/heaputils.h> |
|
18 using LtkUtils::RAllocatorHelper; |
|
19 |
|
20 NONSHARABLE_CLASS(RLoggingAllocator) : public RAllocator |
|
21 { |
|
22 public: |
|
23 IMPORT_C static TInt Install(); |
|
24 IMPORT_C static TInt Install(TUint aFlags); |
|
25 IMPORT_C static TInt Uninstall(); |
|
26 |
|
27 // These don't require you to actually link against RLoggingAllocator |
|
28 inline static TInt Install_WeakLink(TUint aFlags=0); |
|
29 inline static TInt Uninstall_WeakLink(); |
|
30 |
|
31 // Doesn't require the allocator to be installed, just dumps a stacktrace frame for the given cell |
|
32 static IMPORT_C void StaticTraceAlloc(RAllocator* aAllocator, TAny* aCellPtr, TInt aRequestedSize); |
|
33 static IMPORT_C void StaticTraceFree(RAllocator* aAllocator, TAny* aCellPtr); |
|
34 |
|
35 // Create a new logging allocator without changing the current User::Allocator |
|
36 IMPORT_C static TInt New(TUint aFlags, RAllocator* aOrigAllocator, RLoggingAllocator*& aResult); |
|
37 |
|
38 enum TFlags |
|
39 { |
|
40 EScribbleFrees = 1, |
|
41 EDeferFree = 2, |
|
42 EDeferFreeAndCheckScribbles = EDeferFree | EScribbleFrees, |
|
43 EOldFormatLogging = 4, // Use Symbian-defined BTrace::EAlloc and BTrace::ETest1 rather than the new range atrace defines extending THeap |
|
44 }; |
|
45 |
|
46 static const TInt KTempDisableLogging = 0x10286F5E; |
|
47 |
|
48 static TAny* DisableLogging() |
|
49 { |
|
50 TAny* result = NULL; |
|
51 User::Allocator().DebugFunction(KTempDisableLogging, &result); |
|
52 return result; |
|
53 } |
|
54 |
|
55 static void RestoreLogging(TAny* aAllocator) |
|
56 { |
|
57 if (aAllocator) |
|
58 { |
|
59 User::SwitchAllocator((RAllocator*)aAllocator); |
|
60 } |
|
61 } |
|
62 |
|
63 protected: |
|
64 TAny* Alloc(TInt aSize); |
|
65 void Free(TAny* aPtr); |
|
66 TAny* ReAlloc(TAny* aPtr, TInt aSize, TInt aMode=0); |
|
67 TInt AllocLen(const TAny* aCell) const; |
|
68 TInt Compress(); |
|
69 void Reset(); |
|
70 TInt AllocSize(TInt& aTotalAllocSize) const; |
|
71 TInt Available(TInt& aBiggestBlock) const; |
|
72 TInt DebugFunction(TInt aFunc, TAny* a1=NULL, TAny* a2=NULL); |
|
73 |
|
74 private: |
|
75 RLoggingAllocator(TUint aFlags); |
|
76 static TBool HeavenWalk(LtkUtils::RAllocatorHelper& aHelper, TAny* aPtr, RAllocatorHelper::TCellType aType, TLinAddr aCell, TInt aLen); |
|
77 |
|
78 static TBool TraceExistingAllocs(TAny* aContext, RAllocatorHelper::TCellType aType, TLinAddr aCell, TInt aLen); |
|
79 inline void TraceAlloc(RAllocator* aAllocator, TAny* aCellPtr, TInt aRequestedSize); |
|
80 inline void TraceFree(RAllocator* aAllocator, TAny* aCellPtr, TBool aCellIsAlreadyFreed=EFalse); |
|
81 inline void TraceRealloc(TAny *aNewPtr, TAny* aOldPtr, TInt aNewRequestedSize); |
|
82 void DoTraceAllocEvent(RAllocator* aAllocator, TAny* aCellPtr, TInt aEvent, TInt aRequestedSize, TAny* aOldPtr=NULL); // RequestedSize only relevant for aEvent==EHeapAlloc or EHeapReAlloc, aOldPtr only for realloc |
|
83 void CheckDeferredFrees(); |
|
84 void Destroy(); |
|
85 virtual ~RLoggingAllocator(); // Made this virtual to shut up GCCE (even GCC 4 complains about this) |
|
86 |
|
87 public: |
|
88 RAllocator* iA; // The original allocator |
|
89 |
|
90 private: |
|
91 TInt iBreakOnAllocCount; // Useful when running in a debugger |
|
92 #ifndef __KERNEL_MODE__ |
|
93 RLibrary iLib; // Needed to keep the plugin DLL loaded past the time when ecom is cleaned up |
|
94 #endif |
|
95 TUint iFlags; |
|
96 RFastLock iLock; // For locking around iFlags and iDeferredFrees |
|
97 struct SDeferredFreeCell { void* iPtr; TInt iLen; }; |
|
98 RArray<SDeferredFreeCell> iDeferredFrees; |
|
99 TUint iPid; |
|
100 RAllocatorHelper iHelper; |
|
101 }; |
|
102 |
|
103 inline TInt RLoggingAllocator::Install_WeakLink(TUint aFlags) |
|
104 { |
|
105 const TInt KInstallOrdinal = 5; // Happily this is the same on bwins and eabi (and probably bmarm if I get round to rebuilding it) |
|
106 RLibrary lib; |
|
107 TInt err = lib.Load(_L("loggingallocator")); |
|
108 if (err) return err; |
|
109 |
|
110 typedef TInt (*InstallFn)(TUint); |
|
111 InstallFn InstallLoggingAllocator = (InstallFn)lib.Lookup(KInstallOrdinal); |
|
112 if (!InstallLoggingAllocator) err = KErrBadLibraryEntryPoint; |
|
113 |
|
114 if (!err) err = InstallLoggingAllocator(aFlags); |
|
115 lib.Close(); // If the allocator installed itself, it makes sure to keep itself loaded via an RLibrary of its own |
|
116 return err; |
|
117 } |
|
118 |
|
119 inline TInt RLoggingAllocator::Uninstall_WeakLink() |
|
120 { |
|
121 const TInt KUninstallOrdinal = 2; // Happily this is the same on bwins and eabi (and probably bmarm if I get round to rebuilding it) |
|
122 RLibrary lib; |
|
123 TInt err = lib.Load(_L("loggingallocator")); |
|
124 if (err) return err; |
|
125 |
|
126 typedef TInt (*UninstallFn)(); |
|
127 UninstallFn UninstallLoggingAllocator = (UninstallFn)lib.Lookup(KUninstallOrdinal); |
|
128 if (!UninstallLoggingAllocator) err = KErrBadLibraryEntryPoint; |
|
129 |
|
130 if (!err) err = UninstallLoggingAllocator(); |
|
131 lib.Close(); // If the allocator installed itself, it makes sure to keep itself loaded via an RLibrary of its own |
|
132 return err; |
|
133 } |
|
134 |
|
135 #endif |