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 19struct 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 25struct 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 44class TraceOutput { 45public: 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); 53 bool IsFull() const { return fSize >= fCapacity; } 54 55 char* Buffer() const { return fBuffer; } 56 size_t Capacity() const { return fCapacity; } 57 size_t Size() const { return fSize; } 58 59 uint32 Flags() const { return fFlags; } 60 61 void SetLastEntryTime(bigtime_t time); 62 bigtime_t LastEntryTime() const; 63 64private: 65 char* fBuffer; 66 size_t fCapacity; 67 size_t fSize; 68 uint32 fFlags; 69 bigtime_t fLastEntryTime; 70}; 71 72 73class TraceEntry { 74 public: 75 TraceEntry(); 76 virtual ~TraceEntry(); 77 78 virtual void Dump(TraceOutput& out); 79 virtual void DumpStackTrace(TraceOutput& out); 80 81 size_t Size() const { return ToTraceEntry()->size; } 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 88 trace_entry* ToTraceEntry() const 89 { 90 return (trace_entry*)this - 1; 91 } 92 93 static TraceEntry* FromTraceEntry(trace_entry* entry) 94 { 95 return (TraceEntry*)(entry + 1); 96 } 97}; 98 99 100class AbstractTraceEntry : public TraceEntry { 101public: 102 AbstractTraceEntry() 103 { 104 _Init(); 105 } 106 107 // dummy, ignores all arguments 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 119 thread_id ThreadID() const { return fThread; } 120 thread_id TeamID() const { return fTeam; } 121 bigtime_t Time() const { return fTime; } 122 123protected: 124 typedef AbstractTraceEntry TraceEntryBase; 125 126private: 127 void _Init(); 128 129protected: 130 thread_id fThread; 131 team_id fTeam; 132 bigtime_t fTime; 133}; 134 135 136class AbstractTraceEntryWithStackTrace : public AbstractTraceEntry { 137public: 138 AbstractTraceEntryWithStackTrace(size_t stackTraceDepth, 139 size_t skipFrames, bool kernelOnly); 140 141 virtual void DumpStackTrace(TraceOutput& out); 142 143 tracing_stack_trace* StackTrace() const 144 { 145 return fStackTrace; 146 } 147 148protected: 149 typedef AbstractTraceEntryWithStackTrace TraceEntryBase; 150 151private: 152 tracing_stack_trace* fStackTrace; 153}; 154 155 156template<bool stackTraceDepth> 157struct AbstractTraceEntrySelector { 158 typedef AbstractTraceEntryWithStackTrace Type; 159}; 160 161 162template<> 163struct AbstractTraceEntrySelector<0> { 164 typedef AbstractTraceEntry Type; 165}; 166 167 168#define TRACE_ENTRY_SELECTOR(stackTraceDepth) \ 169 AbstractTraceEntrySelector<stackTraceDepth>::Type 170 171 172class LazyTraceOutput : public TraceOutput { 173public: 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 191class TraceFilter { 192public: 193 virtual ~TraceFilter(); 194 195 virtual bool Filter(const TraceEntry* entry, LazyTraceOutput& out); 196 197public: 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 211class WrapperTraceFilter : public TraceFilter { 212public: 213 virtual void Init(TraceFilter* filter, int direction, bool continued) = 0; 214}; 215 216 217class TraceEntryIterator { 218public: 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 246private: 247 trace_entry* _NextNonBufferEntry(trace_entry* entry); 248 trace_entry* _PreviousNonBufferEntry(trace_entry* entry); 249 250private: 251 trace_entry* fEntry; 252 int32 fIndex; 253}; 254 255 256inline void 257TraceOutput::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 266int dump_tracing(int argc, char** argv, WrapperTraceFilter* wrapperFilter); 267 268bool tracing_is_entry_valid(AbstractTraceEntry* entry, 269 bigtime_t entryTime = -1); 270 271#endif // __cplusplus 272 273 274#ifdef __cplusplus 275extern "C" { 276#endif 277 278uint8* alloc_tracing_buffer(size_t size); 279uint8* alloc_tracing_buffer_memcpy(const void* source, size_t size, bool user); 280char* alloc_tracing_buffer_strcpy(const char* source, size_t maxSize, 281 bool user); 282 283struct tracing_stack_trace* capture_tracing_stack_trace(int32 maxCount, 284 int32 skipFrames, bool kernelOnly); 285addr_t tracing_find_caller_in_stack_trace( 286 struct tracing_stack_trace* stackTrace, const addr_t excludeRanges[], 287 uint32 excludeRangeCount); 288void tracing_print_stack_trace(struct tracing_stack_trace* stackTrace); 289 290void lock_tracing_buffer(); 291void unlock_tracing_buffer(); 292status_t tracing_init(void); 293 294void _user_ktrace_output(const char *message); 295 296#ifdef __cplusplus 297} 298#endif 299 300#endif /* KERNEL_TRACING_H */ 301