1 /* 2 * Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Copyright 2008, Axel Dörfler, axeld@pinc-software.de. 4 * Distributed under the terms of the MIT License. 5 */ 6 #ifndef KERNEL_TRACING_H 7 #define KERNEL_TRACING_H 8 9 10 #include <SupportDefs.h> 11 #include <KernelExport.h> 12 13 #include <stdarg.h> 14 #include <stdio.h> 15 16 #include "tracing_config.h" 17 18 19 struct trace_entry { 20 uint32 size : 13; // actual size is *4 21 uint32 previous_size : 13; // actual size is *4 22 uint32 flags : 6; 23 }; 24 25 struct tracing_stack_trace { 26 int32 depth; 27 addr_t return_addresses[0]; 28 }; 29 30 31 #ifdef __cplusplus 32 33 #include <new> 34 35 36 // trace output flags 37 #define TRACE_OUTPUT_TEAM_ID 0x01 38 // print the team ID 39 #define TRACE_OUTPUT_DIFF_TIME 0x02 40 // print the difference time to the previously printed entry instead of the 41 // absolute time 42 43 44 class TraceOutput { 45 public: 46 TraceOutput(char* buffer, size_t bufferSize, uint32 flags); 47 48 void Clear(); 49 void Print(const char* format,...) 50 __attribute__ ((format (__printf__, 2, 3))); 51 void PrintArgs(const char* format, va_list args); 52 void PrintStackTrace(tracing_stack_trace* stackTrace); IsFull()53 bool IsFull() const { return fSize >= fCapacity; } 54 Buffer()55 char* Buffer() const { return fBuffer; } Capacity()56 size_t Capacity() const { return fCapacity; } Size()57 size_t Size() const { return fSize; } 58 Flags()59 uint32 Flags() const { return fFlags; } 60 61 void SetLastEntryTime(bigtime_t time); 62 bigtime_t LastEntryTime() const; 63 64 private: 65 char* fBuffer; 66 size_t fCapacity; 67 size_t fSize; 68 uint32 fFlags; 69 bigtime_t fLastEntryTime; 70 }; 71 72 73 class TraceEntry { 74 public: 75 TraceEntry(); 76 virtual ~TraceEntry(); 77 78 virtual void Dump(TraceOutput& out); 79 virtual void DumpStackTrace(TraceOutput& out); 80 Size()81 size_t Size() const { return ToTraceEntry()->size; } Flags()82 uint16 Flags() const { return ToTraceEntry()->flags; } 83 84 void Initialized(); 85 86 void* operator new(size_t size, const std::nothrow_t&) throw(); 87 ToTraceEntry()88 trace_entry* ToTraceEntry() const 89 { 90 return (trace_entry*)this - 1; 91 } 92 FromTraceEntry(trace_entry * entry)93 static TraceEntry* FromTraceEntry(trace_entry* entry) 94 { 95 return (TraceEntry*)(entry + 1); 96 } 97 }; 98 99 100 class AbstractTraceEntry : public TraceEntry { 101 public: AbstractTraceEntry()102 AbstractTraceEntry() 103 { 104 _Init(); 105 } 106 107 // dummy, ignores all arguments AbstractTraceEntry(size_t,size_t,bool)108 AbstractTraceEntry(size_t, size_t, bool) 109 { 110 _Init(); 111 } 112 113 virtual ~AbstractTraceEntry(); 114 115 virtual void Dump(TraceOutput& out); 116 117 virtual void AddDump(TraceOutput& out); 118 ThreadID()119 thread_id ThreadID() const { return fThread; } TeamID()120 thread_id TeamID() const { return fTeam; } Time()121 bigtime_t Time() const { return fTime; } 122 123 protected: 124 typedef AbstractTraceEntry TraceEntryBase; 125 126 private: 127 void _Init(); 128 129 protected: 130 thread_id fThread; 131 team_id fTeam; 132 bigtime_t fTime; 133 }; 134 135 136 class AbstractTraceEntryWithStackTrace : public AbstractTraceEntry { 137 public: 138 AbstractTraceEntryWithStackTrace(size_t stackTraceDepth, 139 size_t skipFrames, bool kernelOnly); 140 141 virtual void DumpStackTrace(TraceOutput& out); 142 StackTrace()143 tracing_stack_trace* StackTrace() const 144 { 145 return fStackTrace; 146 } 147 148 protected: 149 typedef AbstractTraceEntryWithStackTrace TraceEntryBase; 150 151 private: 152 tracing_stack_trace* fStackTrace; 153 }; 154 155 156 template<bool stackTraceDepth> 157 struct AbstractTraceEntrySelector { 158 typedef AbstractTraceEntryWithStackTrace Type; 159 }; 160 161 162 template<> 163 struct AbstractTraceEntrySelector<0> { 164 typedef AbstractTraceEntry Type; 165 }; 166 167 168 #define TRACE_ENTRY_SELECTOR(stackTraceDepth) \ 169 AbstractTraceEntrySelector<stackTraceDepth>::Type 170 171 172 class LazyTraceOutput : public TraceOutput { 173 public: 174 LazyTraceOutput(char* buffer, size_t bufferSize, uint32 flags) 175 : TraceOutput(buffer, bufferSize, flags) 176 { 177 } 178 179 const char* DumpEntry(const TraceEntry* entry) 180 { 181 if (Size() == 0) { 182 const_cast<TraceEntry*>(entry)->Dump(*this); 183 // Dump() should probably be const 184 } 185 186 return Buffer(); 187 } 188 }; 189 190 191 class TraceFilter { 192 public: 193 virtual ~TraceFilter(); 194 195 virtual bool Filter(const TraceEntry* entry, LazyTraceOutput& out); 196 197 public: 198 union { 199 thread_id fThread; 200 team_id fTeam; 201 const char* fString; 202 uint64 fValue; 203 struct { 204 TraceFilter* first; 205 TraceFilter* second; 206 } fSubFilters; 207 }; 208 }; 209 210 211 class WrapperTraceFilter : public TraceFilter { 212 public: 213 virtual void Init(TraceFilter* filter, int direction, bool continued) = 0; 214 }; 215 216 217 class TraceEntryIterator { 218 public: 219 TraceEntryIterator() 220 : 221 fEntry(NULL), 222 fIndex(0) 223 { 224 } 225 226 void Reset() 227 { 228 fEntry = NULL; 229 fIndex = 0; 230 } 231 232 int32 Index() const 233 { 234 return fIndex; 235 } 236 237 TraceEntry* Current() const 238 { 239 return fEntry != NULL ? TraceEntry::FromTraceEntry(fEntry) : NULL; 240 } 241 242 TraceEntry* Next(); 243 TraceEntry* Previous(); 244 TraceEntry* MoveTo(int32 index); 245 246 private: 247 trace_entry* _NextNonBufferEntry(trace_entry* entry); 248 trace_entry* _PreviousNonBufferEntry(trace_entry* entry); 249 250 private: 251 trace_entry* fEntry; 252 int32 fIndex; 253 }; 254 255 256 inline void 257 TraceOutput::Print(const char* format,...) 258 { 259 va_list args; 260 va_start(args, format); 261 PrintArgs(format, args); 262 va_end(args); 263 } 264 265 266 int dump_tracing(int argc, char** argv, WrapperTraceFilter* wrapperFilter); 267 268 bool tracing_is_entry_valid(AbstractTraceEntry* entry, 269 bigtime_t entryTime = -1); 270 271 #endif // __cplusplus 272 273 274 #ifdef __cplusplus 275 extern "C" { 276 #endif 277 278 uint8* alloc_tracing_buffer(size_t size); 279 uint8* alloc_tracing_buffer_memcpy(const void* source, size_t size, bool user); 280 char* alloc_tracing_buffer_strcpy(const char* source, size_t maxSize, 281 bool user); 282 283 struct tracing_stack_trace* capture_tracing_stack_trace(int32 maxCount, 284 int32 skipFrames, bool kernelOnly); 285 addr_t tracing_find_caller_in_stack_trace( 286 struct tracing_stack_trace* stackTrace, const addr_t excludeRanges[], 287 uint32 excludeRangeCount); 288 void tracing_print_stack_trace(struct tracing_stack_trace* stackTrace); 289 290 void lock_tracing_buffer(); 291 void unlock_tracing_buffer(); 292 status_t tracing_init(void); 293 294 void _user_ktrace_output(const char *message); 295 296 #ifdef __cplusplus 297 } 298 #endif 299 300 #endif /* KERNEL_TRACING_H */ 301