mmi_sigprint: add death signal debug feature driver

Move death signal debug feature driver from kernel to DLKM.
Ported from (CR)

Change-Id: Icbab4faaa58710a6f99433db7807cc175e5f38d8
Reviewed-on: https://gerrit.mot.com/1519314
SME-Granted: SME Approvals Granted
SLTApproved: Slta Waiver
Tested-by: Jira Key
Reviewed-by: Huosheng Liao <liaohs@motorola.com>
Reviewed-by: Zhenxin Xi <xizx@motorola.com>
Submit-Approved: Jira Key
This commit is contained in:
jixj 2020-03-23 18:18:45 +08:00 • committed by Xiaojun Ji
commit 176d2f2dc0
5 changed files with 254 additions and 0 deletions

View file

@ -0,0 +1,8 @@
DLKM_DIR := motorola/kernel/modules
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := mmi_sigprint.ko
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
include $(DLKM_DIR)/AndroidKernelModule.mk

View file

@ -0,0 +1,5 @@
# add -Wall to try to catch everything we can.
EXTRA_CFLAGS += -Wall
EXTRA_CFLAGS += -I$(TOP)/motorola/kernel/modules/include
obj-m = mmi_sigprint.o

View file

@ -0,0 +1,10 @@
KERNEL_SRC ?= /lib/modules/$(shell uname -r)/build
all:
$(MAKE) -C $(KERNEL_SRC) M=$(shell pwd) modules $(KBUILD_OPTIONS)
modules_install:
$(MAKE) INSTALL_MOD_STRIP=1 -C $(KERNEL_SRC) M=$(shell pwd) modules_install
clean:
$(MAKE) -C $(KERNEL_SRC) M=$(PWD) clean

View file

@ -0,0 +1,197 @@
/*
* Copyright (C) 2020 Motorola Mobility Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/proc_fs.h>
#include <linux/sched.h>
#include <linux/kallsyms.h>
#include <linux/utsname.h>
#include <linux/uaccess.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/pid.h>
#include <linux/signal.h>
#include <linux/platform_device.h>
#include <linux/types.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <trace/events/signal.h>
#define CREATE_TRACE_POINTS
#include <trace/events/mmi_sigprint.h>
static struct tracepoint * tracepoint_signal_generate = NULL;
#define STORE_SIGINFO(_errno, _code, info) \
do { \
if (info == SEND_SIG_NOINFO || \
info == SEND_SIG_FORCED) { \
_errno = 0; \
_code = SI_USER; \
} else if (info == SEND_SIG_PRIV) { \
_errno = 0; \
_code = SI_KERNEL; \
} else { \
_errno = info->si_errno; \
_code = info->si_code; \
} \
} while (0)
#ifndef TASK_STATE_TO_CHAR_STR
#define TASK_STATE_TO_CHAR_STR "RSDTtXZxKWPNn"
#endif
static const char stat_nam[] = TASK_STATE_TO_CHAR_STR;
/*
* This portion of the code can be used as template if user want to add specific
* signals to debug msg.
*/
/*
static const char * const signal_deliver_results[] = {
"delivered",
"ignored",
"already_pending",
"overflow_fail",
"lost_info",
};
static void probe_signal_generate(void *ignore, int sig, struct siginfo *info,
struct task_struct *task, int group, int result)
{
unsigned state = task->state ? __ffs(task->state) + 1 : 0;
int errno, code;
// only log delivered signals
STORE_SIGINFO(errno, code, info);
pr_info("[signal][%d:%s]generate sig %d to [%d:%s:%c] errno=%d code=%d grp=%d res=%s\n",
current->pid, current->comm, sig,
task->pid, task->comm,
state < sizeof(stat_nam) - 1 ? stat_nam[state] : '?',
errno, code, group, signal_deliver_results[result]);
}
static void probe_signal_deliver(void *ignore, int sig, struct siginfo *info,
struct k_sigaction *ka)
{
int errno, code;
STORE_SIGINFO(errno, code, info);
pr_info("[signal]sig %d delivered to [%d:%s] errno=%d code=%d sa_handler=%lx sa_flags=%lx\n",
sig, current->pid, current->comm, errno, code,
(unsigned long)ka->sa.sa_handler, ka->sa.sa_flags);
}
*/
static void probe_death_signal(void *ignore, int sig, struct siginfo *info,
struct task_struct *task, int _group, int result)
{
struct signal_struct *signal = task->signal;
unsigned int state;
int group;
/*
* all action will cause process coredump or terminate
* kernel log reduction: only print delivered signals
*/
if (sig_fatal(task, sig) && result == TRACE_SIGNAL_DELIVERED) {
signal = task->signal;
group = _group ||
(signal->flags & (SIGNAL_GROUP_EXIT | SIGNAL_GROUP_COREDUMP));
/*
* kernel log reduction
* skip SIGRTMIN because it's used as timer signal
* skip if the target thread is already dead
*/
if (sig == SIGRTMIN ||
(task->state & (TASK_DEAD | EXIT_DEAD | EXIT_ZOMBIE)))
return;
/*
* Global init gets no signals it doesn't want.
* Container-init gets no signals it doesn't want from same
* container.
*
* Note that if global/container-init sees a sig_kernel_only()
* signal here, the signal must have been generated internally
* or must have come from an ancestor namespace. In either
* case, the signal cannot be dropped.
*/
if (unlikely(signal->flags & SIGNAL_UNKILLABLE) &&
!sig_kernel_only(sig))
return;
/*
* kernel log reduction
* only print process instead of all threads
*/
if (group && (task != task->group_leader))
return;
state = task->state ? __ffs(task->state) + 1 : 0;
pr_info("[signal][%d:%s]send death sig %d to[%d:%s:%c]\n",
current->pid, current->comm,
sig, task->pid, task->comm,
state < sizeof(stat_nam) - 1 ? stat_nam[state] : '?');
} else if ((sig_kernel_stop(sig) && result == TRACE_SIGNAL_DELIVERED) ||
sig == SIGCONT) {
/*
* kernel log reduction
* only print process instead of all threads
*/
if (_group && (task != task->group_leader))
return;
state = task->state ? __ffs(task->state) + 1 : 0;
pr_info("[signal][%d:%s]send %s sig %d to[%d:%s:%c]\n",
current->pid, current->comm,
(sig == SIGCONT) ? "continue" : "stop",
sig, task->pid, task->comm,
state < sizeof(stat_nam) - 1 ? stat_nam[state] : '?');
}
}
static int __init init_signal_log(void)
{
//register_trace_signal_generate(probe_death_signal, NULL);
tracepoint_signal_generate = (struct tracepoint *)kallsyms_lookup_name("__tracepoint_signal_generate");
if (!tracepoint_signal_generate) {
pr_err("Failed to get __tracepoint_signal_generate address\n");
return -ENXIO;
}
tracepoint_probe_register(tracepoint_signal_generate, probe_death_signal, NULL);
// Code example if extra debug msg needed to add.
/*
register_trace_signal_deliver(probe_signal_deliver, NULL);
register_trace_signal_generate(probe_signal_generate, NULL);
*/
return 0;
}
static void exit_signal_log(void)
{
if (tracepoint_signal_generate)
tracepoint_probe_unregister(tracepoint_signal_generate, probe_death_signal, NULL);
}
module_init(init_signal_log);
module_exit(exit_signal_log);
MODULE_DESCRIPTION("Motorola death signal debug");
MODULE_LICENSE("GPL v2");

View file

@ -0,0 +1,34 @@
/*
* Copyright (C) 2020 Motorola Mobility Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#undef TRACE_SYSTEM
#define TRACE_SYSTEM mmi_sigprint
#if !defined(_TRACE_MMI_SIGPRINT_EVENTS_H) || defined(TRACE_HEADER_MULTI_READ)
#define _TRACE_MMI_SIGPRINT_EVENTS_H
#include <linux/tracepoint.h>
/*
DECLARE_TRACE(mmi_sigprint_signal_generate,
TP_PROTO(int firstarg, struct task_struct *p),
TP_ARGS(firstarg, p));
DECLARE_TRACE(mmi_sigprintsignal_deliver,
TP_PROTO(int firstarg, struct task_struct *p),
TP_ARGS(firstarg, p));
*/
#endif /* _TRACE_MMI_SIGPRINT_EVENTS_H */
/* This part must be outside protection */
#include <trace/define_trace.h>