| #ifndef KCT_H_ |
| # define KCT_H_ |
| |
| # include <linux/netlink.h> |
| |
| /* |
| * warning: structures and constants in this header must match the |
| * ones in libc/kernel/common/linux/kct.h, so that information can |
| * be exchange between kernel and userspace throught netlink socket. |
| */ |
| /* flags to optionally filter events on android property activation */ |
| #define EV_FLAGS_PRIORITY_LOW (1<<0) |
| |
| # ifndef MAX_SB_N |
| # define MAX_SB_N 32 |
| # endif |
| |
| # ifndef MAX_EV_N |
| # define MAX_EV_N 32 |
| # endif |
| |
| # define NETLINK_CRASHTOOL 27 |
| # define ATTCHMT_ALIGN 4U |
| |
| /* Type of events supported by crashtool */ |
| enum ct_ev_type { |
| CT_EV_STAT, |
| CT_EV_INFO, |
| CT_EV_ERROR, |
| CT_EV_CRASH, |
| CT_EV_LAST |
| }; |
| |
| enum ct_attchmt_type { |
| CT_ATTCHMT_DATA0, |
| CT_ATTCHMT_DATA1, |
| CT_ATTCHMT_DATA2, |
| CT_ATTCHMT_DATA3, |
| CT_ATTCHMT_DATA4, |
| CT_ATTCHMT_DATA5, |
| /* Always add new types after DATA5 */ |
| CT_ATTCHMT_BINARY, |
| CT_ATTCHMT_FILELIST |
| }; |
| |
| struct ct_attchmt { |
| __u32 size; /* sizeof(data) */ |
| enum ct_attchmt_type type; |
| char data[]; |
| } __aligned(4); |
| |
| struct ct_event { |
| __u64 timestamp; |
| char submitter_name[MAX_SB_N]; |
| char ev_name[MAX_EV_N]; |
| enum ct_ev_type type; |
| __u32 attchmt_size; /* sizeof(all_attachments inc. padding) */ |
| __u32 flags; |
| struct ct_attchmt attachments[]; |
| } __aligned(4); |
| |
| enum kct_nlmsg_type { |
| /* kernel -> userland */ |
| KCT_EVENT, |
| /* userland -> kernel */ |
| KCT_SET_PID = 4200, |
| }; |
| |
| struct kct_packet { |
| struct nlmsghdr nlh; |
| struct ct_event event; |
| }; |
| |
| # define ATTCHMT_ALIGNMENT 4 |
| |
| # ifndef KCT_ALIGN |
| # define __KCT_ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask)) |
| # define __KCT_ALIGN(x, a) __KCT_ALIGN_MASK(x, (typeof(x))(a) - 1) |
| # define KCT_ALIGN(x, a) __KCT_ALIGN((x), (a)) |
| # endif /* !KCT_ALIGN */ |
| |
| # define foreach_attchmt(Event, Attchmt) \ |
| if ((Event)->attchmt_size) \ |
| for ((Attchmt) = (Event)->attachments; \ |
| (Attchmt) < (typeof(Attchmt))(((char *) \ |
| (Event)->attachments) + \ |
| (Event)->attchmt_size); \ |
| (Attchmt) = (typeof(Attchmt))KCT_ALIGN(((size_t)(Attchmt)) \ |
| + sizeof(*(Attchmt)) + \ |
| (Attchmt)->size, ATTCHMT_ALIGNMENT)) |
| |
| /* |
| * User should use the macros below rather than those extern functions |
| * directly. Laters' declaration are only to set them __weak so |
| * that the macros works fine. |
| */ |
| /* Raw API (deprecated) */ |
| extern struct ct_event *kct_alloc_event(const char *submitter_name, |
| const char *ev_name, |
| enum ct_ev_type ev_type, |
| gfp_t flags, uint eflags) __weak; |
| extern int kct_add_attchmt(struct ct_event **ev, |
| enum ct_attchmt_type at_type, |
| unsigned int size, |
| char *data, gfp_t flags) __weak; |
| extern void kct_free_event(struct ct_event *ev) __weak; |
| extern int kct_log_event(struct ct_event *ev, gfp_t flags) __weak; |
| |
| /* API */ |
| #define MKFN(fn, ...) MKFN_N(fn, ##__VA_ARGS__, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)(__VA_ARGS__) |
| #define MKFN_N(fn, n0, n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n, ...) fn##n |
| #define kct_log(...) MKFN(__kct_log_, ##__VA_ARGS__) |
| |
| #define __kct_log_4(Type, Submitter_name, Ev_name, flags) \ |
| do { if (kct_alloc_event) { \ |
| struct ct_event *__ev = \ |
| kct_alloc_event(Submitter_name, Ev_name, Type, \ |
| GFP_ATOMIC, flags); \ |
| if (__ev) { \ |
| kct_log_event(__ev, GFP_ATOMIC); \ |
| } \ |
| } } while (0) |
| |
| #define __kct_log_5(Type, Submitter_name, Ev_name, flags, Data0) \ |
| do { if (kct_alloc_event) { \ |
| struct ct_event *__ev = \ |
| kct_alloc_event(Submitter_name, Ev_name, Type, \ |
| GFP_ATOMIC, flags); \ |
| if (__ev) { \ |
| if (Data0) \ |
| kct_add_attchmt(&__ev, CT_ATTCHMT_DATA0, \ |
| strlen(Data0) + 1, Data0, GFP_ATOMIC); \ |
| kct_log_event(__ev, GFP_ATOMIC); \ |
| } \ |
| } } while (0) |
| |
| #define __kct_log_6(Type, Submitter_name, Ev_name, flags, Data0, Data1) \ |
| do { if (kct_alloc_event) { \ |
| struct ct_event *__ev = \ |
| kct_alloc_event(Submitter_name, Ev_name, Type, \ |
| GFP_ATOMIC, flags); \ |
| if (__ev) { \ |
| if (Data0) \ |
| kct_add_attchmt(&__ev, CT_ATTCHMT_DATA0, \ |
| strlen(Data0) + 1, Data0, GFP_ATOMIC); \ |
| if (Data1) \ |
| kct_add_attchmt(&__ev, CT_ATTCHMT_DATA1, \ |
| strlen(Data1) + 1, Data1, GFP_ATOMIC); \ |
| kct_log_event(__ev, GFP_ATOMIC); \ |
| } \ |
| } } while (0) |
| |
| #define __kct_log_7(Type, Submitter_name, Ev_name, flags, Data0, Data1, Data2) \ |
| do { if (kct_alloc_event) { \ |
| struct ct_event *__ev = \ |
| kct_alloc_event(Submitter_name, Ev_name, Type, \ |
| GFP_ATOMIC, flags); \ |
| if (__ev) { \ |
| if (Data0) \ |
| kct_add_attchmt(&__ev, CT_ATTCHMT_DATA0, \ |
| strlen(Data0) + 1, Data0, GFP_ATOMIC); \ |
| if (Data1) \ |
| kct_add_attchmt(&__ev, CT_ATTCHMT_DATA1, \ |
| strlen(Data1) + 1, Data1, GFP_ATOMIC); \ |
| if (Data2) \ |
| kct_add_attchmt(&__ev, CT_ATTCHMT_DATA2, \ |
| strlen(Data2) + 1, Data2, GFP_ATOMIC); \ |
| kct_log_event(__ev, GFP_ATOMIC); \ |
| } \ |
| } } while (0) |
| |
| #define __kct_log_8(Type, Submitter_name, Ev_name, flags, Data0, Data1, Data2, \ |
| Data3) \ |
| do { if (kct_alloc_event) { \ |
| struct ct_event *__ev = \ |
| kct_alloc_event(Submitter_name, Ev_name, Type, \ |
| GFP_ATOMIC, flags); \ |
| if (__ev) { \ |
| if (Data0) \ |
| kct_add_attchmt(&__ev, CT_ATTCHMT_DATA0, \ |
| strlen(Data0) + 1, Data0, GFP_ATOMIC); \ |
| if (Data1) \ |
| kct_add_attchmt(&__ev, CT_ATTCHMT_DATA1, \ |
| strlen(Data1) + 1, Data1, GFP_ATOMIC); \ |
| if (Data2) \ |
| kct_add_attchmt(&__ev, CT_ATTCHMT_DATA2, \ |
| strlen(Data2) + 1, Data2, GFP_ATOMIC); \ |
| if (Data3) \ |
| kct_add_attchmt(&__ev, CT_ATTCHMT_DATA3, \ |
| strlen(Data3) + 1, Data3, GFP_ATOMIC); \ |
| kct_log_event(__ev, GFP_ATOMIC); \ |
| } \ |
| } } while (0) |
| |
| #define __kct_log_9(Type, Submitter_name, Ev_name, flags, Data0, Data1, Data2, \ |
| Data3, Data4) \ |
| do { if (kct_alloc_event) { \ |
| struct ct_event *__ev = \ |
| kct_alloc_event(Submitter_name, Ev_name, Type, \ |
| GFP_ATOMIC, flags); \ |
| if (__ev) { \ |
| if (Data0) \ |
| kct_add_attchmt(&__ev, CT_ATTCHMT_DATA0, \ |
| strlen(Data0) + 1, Data0, GFP_ATOMIC); \ |
| if (Data1) \ |
| kct_add_attchmt(&__ev, CT_ATTCHMT_DATA1, \ |
| strlen(Data1) + 1, Data1, GFP_ATOMIC); \ |
| if (Data2) \ |
| kct_add_attchmt(&__ev, CT_ATTCHMT_DATA2, \ |
| strlen(Data2) + 1, Data2, GFP_ATOMIC); \ |
| if (Data3) \ |
| kct_add_attchmt(&__ev, CT_ATTCHMT_DATA3, \ |
| strlen(Data3) + 1, Data3, GFP_ATOMIC); \ |
| if (Data4) \ |
| kct_add_attchmt(&__ev, CT_ATTCHMT_DATA4, \ |
| strlen(Data4) + 1, Data4, GFP_ATOMIC); \ |
| kct_log_event(__ev, GFP_ATOMIC); \ |
| } \ |
| } } while (0) |
| |
| #define __kct_log_10(Type, Submitter_name, Ev_name, flags, Data0, Data1, Data2, \ |
| Data3, Data4, Data5) \ |
| do { if (kct_alloc_event) { \ |
| struct ct_event *__ev = \ |
| kct_alloc_event(Submitter_name, Ev_name, Type, \ |
| GFP_ATOMIC, flags); \ |
| if (__ev) { \ |
| if (Data0) \ |
| kct_add_attchmt(&__ev, CT_ATTCHMT_DATA0, \ |
| strlen(Data0) + 1, Data0, GFP_ATOMIC); \ |
| if (Data1) \ |
| kct_add_attchmt(&__ev, CT_ATTCHMT_DATA1, \ |
| strlen(Data1) + 1, Data1, GFP_ATOMIC); \ |
| if (Data2) \ |
| kct_add_attchmt(&__ev, CT_ATTCHMT_DATA2, \ |
| strlen(Data2) + 1, Data2, GFP_ATOMIC); \ |
| if (Data3) \ |
| kct_add_attchmt(&__ev, CT_ATTCHMT_DATA3, \ |
| strlen(Data3) + 1, Data3, GFP_ATOMIC); \ |
| if (Data4) \ |
| kct_add_attchmt(&__ev, CT_ATTCHMT_DATA4, \ |
| strlen(Data4) + 1, Data4, GFP_ATOMIC); \ |
| if (Data5) \ |
| kct_add_attchmt(&__ev, CT_ATTCHMT_DATA5, \ |
| strlen(Data5) + 1, Data5, GFP_ATOMIC); \ |
| kct_log_event(__ev, GFP_ATOMIC); \ |
| } \ |
| } } while (0) |
| |
| #define __kct_log_11(Type, Submitter_name, Ev_name, flags, Data0, Data1, Data2, \ |
| Data3, Data4, Data5, filelist) \ |
| do { if (kct_alloc_event) { \ |
| struct ct_event *__ev = \ |
| kct_alloc_event(Submitter_name, Ev_name, Type, \ |
| GFP_ATOMIC, flags); \ |
| if (__ev) { \ |
| if (Data0) \ |
| kct_add_attchmt(&__ev, CT_ATTCHMT_DATA0, \ |
| strlen(Data0) + 1, Data0, GFP_ATOMIC); \ |
| if (Data1) \ |
| kct_add_attchmt(&__ev, CT_ATTCHMT_DATA1, \ |
| strlen(Data1) + 1, Data1, GFP_ATOMIC); \ |
| if (Data2) \ |
| kct_add_attchmt(&__ev, CT_ATTCHMT_DATA2, \ |
| strlen(Data2) + 1, Data2, GFP_ATOMIC); \ |
| if (Data3) \ |
| kct_add_attchmt(&__ev, CT_ATTCHMT_DATA3, \ |
| strlen(Data3) + 1, Data3, GFP_ATOMIC); \ |
| if (Data4) \ |
| kct_add_attchmt(&__ev, CT_ATTCHMT_DATA4, \ |
| strlen(Data4) + 1, Data4, GFP_ATOMIC); \ |
| if (Data5) \ |
| kct_add_attchmt(&__ev, CT_ATTCHMT_DATA5, \ |
| strlen(Data5) + 1, Data5, GFP_ATOMIC); \ |
| if (filelist) \ |
| kct_add_attchmt(&__ev, CT_ATTCHMT_FILELIST, \ |
| strlen(filelist) + 1, filelist, GFP_ATOMIC); \ |
| kct_log_event(__ev, GFP_ATOMIC); \ |
| } \ |
| } } while (0) |
| |
| #endif /* !KCT_H_ */ |