1 #ifndef KCT_H_ 2 # define KCT_H_ 3 4 # include <linux/netlink.h> 5 6 /* 7 * warning: structures and constants in this header must match the 8 * ones in libc/kernel/common/linux/kct.h, so that information can 9 * be exchange between kernel and userspace throught netlink socket. 10 */ 11 /* flags to optionally filter events on android property activation */ 12 #define EV_FLAGS_PRIORITY_LOW (1<<0) 13 14 # ifndef MAX_SB_N 15 # define MAX_SB_N 32 16 # endif 17 18 # ifndef MAX_EV_N 19 # define MAX_EV_N 32 20 # endif 21 22 # define NETLINK_CRASHTOOL 27 23 # define ATTCHMT_ALIGN 4U 24 25 /* Type of events supported by crashtool */ 26 enum ct_ev_type { 27 CT_EV_STAT, 28 CT_EV_INFO, 29 CT_EV_ERROR, 30 CT_EV_CRASH, 31 CT_EV_LAST 32 }; 33 34 enum ct_attchmt_type { 35 CT_ATTCHMT_DATA0, 36 CT_ATTCHMT_DATA1, 37 CT_ATTCHMT_DATA2, 38 CT_ATTCHMT_DATA3, 39 CT_ATTCHMT_DATA4, 40 CT_ATTCHMT_DATA5, 41 /* Always add new types after DATA5 */ 42 CT_ATTCHMT_BINARY, 43 CT_ATTCHMT_FILELIST 44 }; 45 46 struct ct_attchmt { 47 __u32 size; /* sizeof(data) */ 48 enum ct_attchmt_type type; 49 char data[]; 50 } __aligned(4); 51 52 struct ct_event { 53 __u64 timestamp; 54 char submitter_name[MAX_SB_N]; 55 char ev_name[MAX_EV_N]; 56 enum ct_ev_type type; 57 __u32 attchmt_size; /* sizeof(all_attachments inc. padding) */ 58 __u32 flags; 59 struct ct_attchmt attachments[]; 60 } __aligned(4); 61 62 enum kct_nlmsg_type { 63 /* kernel -> userland */ 64 KCT_EVENT, 65 /* userland -> kernel */ 66 KCT_SET_PID = 4200, 67 }; 68 69 struct kct_packet { 70 struct nlmsghdr nlh; 71 struct ct_event event; 72 }; 73 74 # define ATTCHMT_ALIGNMENT 4 75 76 # ifndef KCT_ALIGN 77 # define __KCT_ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask)) 78 # define __KCT_ALIGN(x, a) __KCT_ALIGN_MASK(x, (typeof(x))(a) - 1) 79 # define KCT_ALIGN(x, a) __KCT_ALIGN((x), (a)) 80 # endif /* !KCT_ALIGN */ 81 82 # define foreach_attchmt(Event, Attchmt) \ 83 if ((Event)->attchmt_size) \ 84 for ((Attchmt) = (Event)->attachments; \ 85 (Attchmt) < (typeof(Attchmt))(((char *) \ 86 (Event)->attachments) + \ 87 (Event)->attchmt_size); \ 88 (Attchmt) = (typeof(Attchmt))KCT_ALIGN(((size_t)(Attchmt)) \ 89 + sizeof(*(Attchmt)) + \ 90 (Attchmt)->size, ATTCHMT_ALIGNMENT)) 91 92 /* 93 * User should use the macros below rather than those extern functions 94 * directly. Laters' declaration are only to set them __weak so 95 * that the macros works fine. 96 */ 97 /* Raw API (deprecated) */ 98 extern struct ct_event *kct_alloc_event(const char *submitter_name, 99 const char *ev_name, 100 enum ct_ev_type ev_type, 101 gfp_t flags, uint eflags) __weak; 102 extern int kct_add_attchmt(struct ct_event **ev, 103 enum ct_attchmt_type at_type, 104 unsigned int size, 105 char *data, gfp_t flags) __weak; 106 extern void kct_free_event(struct ct_event *ev) __weak; 107 extern int kct_log_event(struct ct_event *ev, gfp_t flags) __weak; 108 109 /* API */ 110 #define MKFN(fn, ...) MKFN_N(fn, ##__VA_ARGS__, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)(__VA_ARGS__) 111 #define MKFN_N(fn, n0, n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n, ...) fn##n 112 #define kct_log(...) MKFN(__kct_log_, ##__VA_ARGS__) 113 114 #define __kct_log_4(Type, Submitter_name, Ev_name, flags) \ 115 do { if (kct_alloc_event) { \ 116 struct ct_event *__ev = \ 117 kct_alloc_event(Submitter_name, Ev_name, Type, \ 118 GFP_ATOMIC, flags); \ 119 if (__ev) { \ 120 kct_log_event(__ev, GFP_ATOMIC); \ 121 } \ 122 } } while (0) 123 124 #define __kct_log_5(Type, Submitter_name, Ev_name, flags, Data0) \ 125 do { if (kct_alloc_event) { \ 126 struct ct_event *__ev = \ 127 kct_alloc_event(Submitter_name, Ev_name, Type, \ 128 GFP_ATOMIC, flags); \ 129 if (__ev) { \ 130 if (Data0) \ 131 kct_add_attchmt(&__ev, CT_ATTCHMT_DATA0, \ 132 strlen(Data0) + 1, Data0, GFP_ATOMIC); \ 133 kct_log_event(__ev, GFP_ATOMIC); \ 134 } \ 135 } } while (0) 136 137 #define __kct_log_6(Type, Submitter_name, Ev_name, flags, Data0, Data1) \ 138 do { if (kct_alloc_event) { \ 139 struct ct_event *__ev = \ 140 kct_alloc_event(Submitter_name, Ev_name, Type, \ 141 GFP_ATOMIC, flags); \ 142 if (__ev) { \ 143 if (Data0) \ 144 kct_add_attchmt(&__ev, CT_ATTCHMT_DATA0, \ 145 strlen(Data0) + 1, Data0, GFP_ATOMIC); \ 146 if (Data1) \ 147 kct_add_attchmt(&__ev, CT_ATTCHMT_DATA1, \ 148 strlen(Data1) + 1, Data1, GFP_ATOMIC); \ 149 kct_log_event(__ev, GFP_ATOMIC); \ 150 } \ 151 } } while (0) 152 153 #define __kct_log_7(Type, Submitter_name, Ev_name, flags, Data0, Data1, Data2) \ 154 do { if (kct_alloc_event) { \ 155 struct ct_event *__ev = \ 156 kct_alloc_event(Submitter_name, Ev_name, Type, \ 157 GFP_ATOMIC, flags); \ 158 if (__ev) { \ 159 if (Data0) \ 160 kct_add_attchmt(&__ev, CT_ATTCHMT_DATA0, \ 161 strlen(Data0) + 1, Data0, GFP_ATOMIC); \ 162 if (Data1) \ 163 kct_add_attchmt(&__ev, CT_ATTCHMT_DATA1, \ 164 strlen(Data1) + 1, Data1, GFP_ATOMIC); \ 165 if (Data2) \ 166 kct_add_attchmt(&__ev, CT_ATTCHMT_DATA2, \ 167 strlen(Data2) + 1, Data2, GFP_ATOMIC); \ 168 kct_log_event(__ev, GFP_ATOMIC); \ 169 } \ 170 } } while (0) 171 172 #define __kct_log_8(Type, Submitter_name, Ev_name, flags, Data0, Data1, Data2, \ 173 Data3) \ 174 do { if (kct_alloc_event) { \ 175 struct ct_event *__ev = \ 176 kct_alloc_event(Submitter_name, Ev_name, Type, \ 177 GFP_ATOMIC, flags); \ 178 if (__ev) { \ 179 if (Data0) \ 180 kct_add_attchmt(&__ev, CT_ATTCHMT_DATA0, \ 181 strlen(Data0) + 1, Data0, GFP_ATOMIC); \ 182 if (Data1) \ 183 kct_add_attchmt(&__ev, CT_ATTCHMT_DATA1, \ 184 strlen(Data1) + 1, Data1, GFP_ATOMIC); \ 185 if (Data2) \ 186 kct_add_attchmt(&__ev, CT_ATTCHMT_DATA2, \ 187 strlen(Data2) + 1, Data2, GFP_ATOMIC); \ 188 if (Data3) \ 189 kct_add_attchmt(&__ev, CT_ATTCHMT_DATA3, \ 190 strlen(Data3) + 1, Data3, GFP_ATOMIC); \ 191 kct_log_event(__ev, GFP_ATOMIC); \ 192 } \ 193 } } while (0) 194 195 #define __kct_log_9(Type, Submitter_name, Ev_name, flags, Data0, Data1, Data2, \ 196 Data3, Data4) \ 197 do { if (kct_alloc_event) { \ 198 struct ct_event *__ev = \ 199 kct_alloc_event(Submitter_name, Ev_name, Type, \ 200 GFP_ATOMIC, flags); \ 201 if (__ev) { \ 202 if (Data0) \ 203 kct_add_attchmt(&__ev, CT_ATTCHMT_DATA0, \ 204 strlen(Data0) + 1, Data0, GFP_ATOMIC); \ 205 if (Data1) \ 206 kct_add_attchmt(&__ev, CT_ATTCHMT_DATA1, \ 207 strlen(Data1) + 1, Data1, GFP_ATOMIC); \ 208 if (Data2) \ 209 kct_add_attchmt(&__ev, CT_ATTCHMT_DATA2, \ 210 strlen(Data2) + 1, Data2, GFP_ATOMIC); \ 211 if (Data3) \ 212 kct_add_attchmt(&__ev, CT_ATTCHMT_DATA3, \ 213 strlen(Data3) + 1, Data3, GFP_ATOMIC); \ 214 if (Data4) \ 215 kct_add_attchmt(&__ev, CT_ATTCHMT_DATA4, \ 216 strlen(Data4) + 1, Data4, GFP_ATOMIC); \ 217 kct_log_event(__ev, GFP_ATOMIC); \ 218 } \ 219 } } while (0) 220 221 #define __kct_log_10(Type, Submitter_name, Ev_name, flags, Data0, Data1, Data2, \ 222 Data3, Data4, Data5) \ 223 do { if (kct_alloc_event) { \ 224 struct ct_event *__ev = \ 225 kct_alloc_event(Submitter_name, Ev_name, Type, \ 226 GFP_ATOMIC, flags); \ 227 if (__ev) { \ 228 if (Data0) \ 229 kct_add_attchmt(&__ev, CT_ATTCHMT_DATA0, \ 230 strlen(Data0) + 1, Data0, GFP_ATOMIC); \ 231 if (Data1) \ 232 kct_add_attchmt(&__ev, CT_ATTCHMT_DATA1, \ 233 strlen(Data1) + 1, Data1, GFP_ATOMIC); \ 234 if (Data2) \ 235 kct_add_attchmt(&__ev, CT_ATTCHMT_DATA2, \ 236 strlen(Data2) + 1, Data2, GFP_ATOMIC); \ 237 if (Data3) \ 238 kct_add_attchmt(&__ev, CT_ATTCHMT_DATA3, \ 239 strlen(Data3) + 1, Data3, GFP_ATOMIC); \ 240 if (Data4) \ 241 kct_add_attchmt(&__ev, CT_ATTCHMT_DATA4, \ 242 strlen(Data4) + 1, Data4, GFP_ATOMIC); \ 243 if (Data5) \ 244 kct_add_attchmt(&__ev, CT_ATTCHMT_DATA5, \ 245 strlen(Data5) + 1, Data5, GFP_ATOMIC); \ 246 kct_log_event(__ev, GFP_ATOMIC); \ 247 } \ 248 } } while (0) 249 250 #define __kct_log_11(Type, Submitter_name, Ev_name, flags, Data0, Data1, Data2, \ 251 Data3, Data4, Data5, filelist) \ 252 do { if (kct_alloc_event) { \ 253 struct ct_event *__ev = \ 254 kct_alloc_event(Submitter_name, Ev_name, Type, \ 255 GFP_ATOMIC, flags); \ 256 if (__ev) { \ 257 if (Data0) \ 258 kct_add_attchmt(&__ev, CT_ATTCHMT_DATA0, \ 259 strlen(Data0) + 1, Data0, GFP_ATOMIC); \ 260 if (Data1) \ 261 kct_add_attchmt(&__ev, CT_ATTCHMT_DATA1, \ 262 strlen(Data1) + 1, Data1, GFP_ATOMIC); \ 263 if (Data2) \ 264 kct_add_attchmt(&__ev, CT_ATTCHMT_DATA2, \ 265 strlen(Data2) + 1, Data2, GFP_ATOMIC); \ 266 if (Data3) \ 267 kct_add_attchmt(&__ev, CT_ATTCHMT_DATA3, \ 268 strlen(Data3) + 1, Data3, GFP_ATOMIC); \ 269 if (Data4) \ 270 kct_add_attchmt(&__ev, CT_ATTCHMT_DATA4, \ 271 strlen(Data4) + 1, Data4, GFP_ATOMIC); \ 272 if (Data5) \ 273 kct_add_attchmt(&__ev, CT_ATTCHMT_DATA5, \ 274 strlen(Data5) + 1, Data5, GFP_ATOMIC); \ 275 if (filelist) \ 276 kct_add_attchmt(&__ev, CT_ATTCHMT_FILELIST, \ 277 strlen(filelist) + 1, filelist, GFP_ATOMIC); \ 278 kct_log_event(__ev, GFP_ATOMIC); \ 279 } \ 280 } } while (0) 281 282 #endif /* !KCT_H_ */ 283