main log导入到uart口
不开机问题调试起来比较麻烦,可能是底层出错,比如KE、preloader崩溃,lk崩溃,也可能是上层崩溃。
如果是上层崩溃,需要抓main log,抓log步骤如下:
1. 先检查adb shell是否可用,如果可用可以用adb shell "logcat -v time -b main -b system > logcat.txt"
2. 如果不能用,则要开uart console,具体请参考:FAQ03891
3. 如果uart console也不能用,那么只能在上层代码里让main log直接导入到uart口了。下面提供方法。
[SOLUTION]
1. 在system/core/liblog/logd_write.c添加代码到__write_to_log_daemon(),将main log导入到kernel buffer:
static int __write_to_log_daemon(log_id_t log_id, struct iovec *vec, size_t nr) { ...... if (!nr) { return -EINVAL; } #if 1 /* add this block */ if (log_id == LOG_ID_MAIN || log_id == LOG_ID_SYSTEM) { static const char* name = "/dev/__kmsg__"; static int klog_fd = -1; if (klog_fd < 0) { klog_fd = open("/dev/kmsg", O_WRONLY|O_CLOEXEC); if (klog_fd < 0 && mknod(name, S_IFCHR | 0600, (1 << 8) | 11) == 0) { klog_fd = open(name, O_WRONLY|O_CLOEXEC); unlink(name); } } if (klog_fd >= 0 && *(unsigned char *)vec[0].iov_base >= ANDROID_LOG_WARN) { char c = '?', str[5 + vec[1].iov_len + vec[2].iov_len]; long rt; switch (*(unsigned char *)vec[0].iov_base) { case ANDROID_LOG_WARN: c = 'W'; break; case ANDROID_LOG_ERROR: c = 'E'; break; case ANDROID_LOG_FATAL: c = 'F'; break; case ANDROID_LOG_SILENT: c = 'S'; break; default: break; } rt = snprintf(str, sizeof(str) - 1, "%c %s %s\n", c, (char *)vec[1].iov_base, (char *)vec[2].iov_base); if (rt > 0) TEMP_FAILURE_RETRY(write(klog_fd, str, rt)); } } #endif ...... }
2. 修改kernel/drivers/char/mem.c里的
[11] = { "kmsg", 0644, &kmsg_fops, NULL },
修改为:
[11] = { "kmsg", 0666, &kmsg_fops, NULL },
3. 在external/sepolicy/domain.te添加:
allow domain kmsg_device:chr_file rw_file_perms;
4. 在external/sepolicy/device.te修改:
type kmsg_device, dev_type;
修改为:
type kmsg_device, dev_type, mlstrustedobject;
5. 全编译:
make -j24
6. 抓到的uart log大致如下:
[14:46:02.401] [ 22.618857] .(1)[388:mediaserver][name:ccci&][ccci1/chr]MD state 2, 3 [14:46:02.401] [ 22.619350] .(2)[787:CCCIReadThread]W SpeechMessengerECCCI ..[MD Reset Notify(MSG_M2A_EM_DATA_REQUEST: 0xaf700000)].. [14:46:02.401] [ 22.622637] E SpeechMessengerECCCI SendMsgFailErrorHandling(), message: 0x2f760000 [14:46:02.429] [ 22.624168] W SpeechMessengerECCCI SendMsgFailErrorHandling(), message: 0x2f760000, ack don't care
7. 注意:O版本后还需下面的修改
为所有进程添加mknodat的权限
/external/minijail/util.c
45#elif defined(__arm__) 46#if defined(__ANDROID__) 47const char *log_syscalls[] = {"clock_gettime", "connect", "fcntl64", "socket", 48 "writev"}; 49#else 50const char *log_syscalls[] = {"connect", "gettimeofday", "send"}; 51#endif 52#elif defined(__aarch64__) 53#if defined(__ANDROID__) 54const char *log_syscalls[] = {"connect", "fcntl", "sendto", "socket", "writev"}; 55#else 56const char *log_syscalls[] = {"connect", "send"};
修改为
45#elif defined(__arm__) 46#if defined(__ANDROID__) 47const char *log_syscalls[] = {"clock_gettime", "connect", "fcntl64", "socket", 48 "writev","mknodat"}; 49#else 50const char *log_syscalls[] = {"connect", "gettimeofday", "send"}; 51#endif 52#elif defined(__aarch64__) 53#if defined(__ANDROID__) 54const char *log_syscalls[] = {"connect", "fcntl", "sendto", "socket", "writev","mknodat"}; 55#else 56const char *log_syscalls[] = {"connect", "send"};