]> git.saurik.com Git - apple/system_cmds.git/blob - KDBG/KDEvent.hpp
system_cmds-643.30.1.tar.gz
[apple/system_cmds.git] / KDBG / KDEvent.hpp
1 //
2 // KDEvent.hpp
3 // KDBG
4 //
5 // Created by James McIlree on 10/25/12.
6 // Copyright (c) 2014 Apple. All rights reserved.
7 //
8
9 template <typename SIZE> class KDEventFields {};
10
11 template <>
12 class KDEventFields<Kernel32> {
13 private:
14 static const uint64_t K32_TIMESTAMP_MASK = 0x00ffffffffffffffULL;
15 static const uint64_t K32_CPU_MASK = 0xff00000000000000ULL;
16 static const uint32_t K32_CPU_SHIFT = 56;
17
18 public:
19 uint64_t _timestamp;
20 uint32_t _arg1;
21 uint32_t _arg2;
22 uint32_t _arg3;
23 uint32_t _arg4;
24 uint32_t _thread;
25 uint32_t _debugid;
26
27 int cpu() const { return (int) ((_timestamp & K32_CPU_MASK) >> K32_CPU_SHIFT); }
28 uint64_t timestamp() const { return _timestamp & K32_TIMESTAMP_MASK; }
29
30 uint64_t unused() const { THROW("Calling method for field that does not exist"); }
31 };
32
33 template <>
34 class KDEventFields<Kernel64> {
35 public:
36 uint64_t _timestamp;
37 uint64_t _arg1;
38 uint64_t _arg2;
39 uint64_t _arg3;
40 uint64_t _arg4;
41 uint64_t _thread;
42 uint32_t _debugid;
43 uint32_t _cpuid;
44 uint64_t _unused; // Defined as uintptr in orignal header
45
46 int cpu() const { return (int)_cpuid; }
47 uint64_t timestamp() const { return _timestamp; }
48
49 uint64_t unused() const { return _unused; }
50 };
51
52 /* The debug code consists of the following
53 *
54 * ----------------------------------------------------------------------
55 *| | | |Func |
56 *| Class (8) | SubClass (8) | Code (14) |Qual(2)|
57 * ----------------------------------------------------------------------
58 * The class specifies the higher level
59 */
60
61 template <typename SIZE>
62 class KDEvent {
63 private:
64 KDEventFields<SIZE> _fields;
65
66 static const uint32_t DBG_CLASS_MASK = 0xFF000000;
67 static const uint32_t DBG_CLASS_MASK_SHIFT = 24;
68 static const uint32_t DBG_SUBCLASS_MASK = 0x00FF0000;
69 static const uint32_t DBG_SUBCLASS_MASK_SHIFT = 16;
70 static const uint32_t DBG_CODE_MASK = 0x0000FFFC;
71 static const uint32_t DBG_CODE_MASK_SHIFT = 2;
72 static const uint32_t DBG_FUNC_MASK = DBG_FUNC_START | DBG_FUNC_END;
73
74 public:
75 //
76 // Provided only for lower_bounds/upper_bounds binary searches of event buffers
77 //
78 KDEvent() {}
79 KDEvent(AbsTime timestamp) { _fields._timestamp = timestamp.value(); }
80
81 // Sort by time operator for lower_bounds/upper_bounds
82 bool operator<(const KDEvent& rhs) const { return this->timestamp() < rhs.timestamp(); }
83
84 AbsTime timestamp() const { return AbsTime(_fields.timestamp()); }
85 typename SIZE::ptr_t tid() const { return _fields._thread; }
86 int cpu() const { return _fields.cpu(); }
87
88 uint32_t dbg_class() const { return (_fields._debugid & DBG_CLASS_MASK) >> DBG_CLASS_MASK_SHIFT; }
89 uint32_t dbg_subclass() const { return (_fields._debugid & DBG_SUBCLASS_MASK) >> DBG_SUBCLASS_MASK_SHIFT; }
90 uint32_t dbg_code() const { return (_fields._debugid & DBG_CODE_MASK) >> DBG_CODE_MASK_SHIFT; }
91 uint32_t dbg_cooked() const { return _fields._debugid & ~DBG_FUNC_MASK; }
92 uint32_t dbg_raw() const { return _fields._debugid; }
93
94 typename SIZE::ptr_t arg1() const { return _fields._arg1; }
95 typename SIZE::ptr_t arg2() const { return _fields._arg2; }
96 typename SIZE::ptr_t arg3() const { return _fields._arg3; }
97 typename SIZE::ptr_t arg4() const { return _fields._arg4; }
98
99 uint8_t* arg1_as_pointer() const { return (uint8_t*)&_fields._arg1; }
100 std::string arg1_as_string() const;
101 std::string all_args_as_string() const;
102
103 bool is_func_start() const { return (_fields._debugid & DBG_FUNC_MASK) == DBG_FUNC_START; }
104 bool is_func_end() const { return (_fields._debugid & DBG_FUNC_MASK) == DBG_FUNC_END; }
105 bool is_func_none() const { return (_fields._debugid & DBG_FUNC_MASK) == DBG_FUNC_NONE; }
106
107 uint64_t unused() const { return _fields.unused(); }
108
109 bool is_valid() {
110 // Must have a code set to be valid, no codes are 0x00
111 if (dbg_code() == 0)
112 return false;
113
114 // Legal values are NONE, START, and END.
115 if ((_fields._debugid & DBG_FUNC_MASK) == DBG_FUNC_MASK)
116 return false;
117
118 return true;
119 }
120
121 std::string to_string() const;
122 };
123
124 template <typename SIZE>
125 std::string KDEvent<SIZE>::arg1_as_string() const {
126 // We can't count on the arg being NULL terminated, we have to copy.
127 // Using a uint32_t/uint64_t instead of a char[] guarantees alignment.
128 decltype(_fields._arg1) buf[2];
129
130 buf[0] = _fields._arg1;
131 buf[1] = 0;
132
133 return std::string(reinterpret_cast<char*>(buf));
134 }
135
136 template <typename SIZE>
137 std::string KDEvent<SIZE>::all_args_as_string() const {
138 // We can't count on the arg being NULL terminated, we have to copy.
139 // Using a uint32_t/uint64_t instead of a char[] guarantees alignment.
140 decltype(_fields._arg1) buf[5];
141
142 buf[0] = _fields._arg1;
143 buf[1] = _fields._arg2;
144 buf[2] = _fields._arg3;
145 buf[3] = _fields._arg4;
146 buf[4] = 0;
147
148 return std::string(reinterpret_cast<char*>(buf));
149 }
150