玩转安卓10源码开发定制(20)libc中添加日志输出接口

一、libc中日志输出讨论

安卓源码libc中,默认提供了日志调试输出接口。源码位于如下:

//头文件定义
bionic/libc/async_safe/include/async_safe/log.h
//实现文件
bionic/libc/async_safe/async_safe_log.cpp

通过async_safe_log.cpp代码分析,写入日志主要是使用UNIX domain socket建立到域"/dev/socket/logdw"的通信,然后写入日志数据。核心逻辑代码如下:

//正在写入日志的方法,主要调用open_log_socket建立socket连接,然后写数据进去
int async_safe_write_log(int priority, const char* tag, const char* msg) {
  int main_log_fd = open_log_socket();
  if (main_log_fd == -1) {
    // Try stderr instead.
    return write_stderr(tag, msg);
  }

  iovec vec[6];
  char log_id = (priority == ANDROID_LOG_FATAL) ? LOG_ID_CRASH : LOG_ID_MAIN;
  vec[0].iov_base = &log_id;
  vec[0].iov_len = sizeof(log_id);
  uint16_t tid = gettid();
  vec[1].iov_base = &tid;
  vec[1].iov_len = sizeof(tid);
  timespec ts;
  clock_gettime(CLOCK_REALTIME, &ts);
  log_time realtime_ts;
  realtime_ts.tv_sec = ts.tv_sec;
  realtime_ts.tv_nsec = ts.tv_nsec;
  vec[2].iov_base = &realtime_ts;
  vec[2].iov_len = sizeof(realtime_ts);

  vec[3].iov_base = &priority;
  vec[3].iov_len = 1;
  vec[4].iov_base = const_cast<char*>(tag);
  vec[4].iov_len = strlen(tag) + 1;
  vec[5].iov_base = const_cast<char*>(msg);
  vec[5].iov_len = strlen(msg) + 1;

  int result = TEMP_FAILURE_RETRY(writev(main_log_fd, vec, sizeof(vec) / sizeof(vec[0])));
  __close(main_log_fd);
  return result;
}

//建立到/dev/socket/logdw的通信
static int open_log_socket() {
  // ToDo: Ideally we want this to fail if the gid of the current
  // process is AID_LOGD, but will have to wait until we have
  // registered this in private/android_filesystem_config.h. We have
  // found that all logd crashes thus far have had no problem stuffing
  // the UNIX domain socket and moving on so not critical *today*.

  int log_fd = TEMP_FAILURE_RETRY(socket(PF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0));
  if (log_fd == -1) {
    return -1;
  }

  union {
    struct sockaddr addr;
    struct sockaddr_un addrUn;
  } u;
  memset(&u, 0, sizeof(u));
  u.addrUn.sun_family = AF_UNIX;
  strlcpy(u.addrUn.sun_path, "/dev/socket/logdw", sizeof(u.addrUn.sun_path));

  if (TEMP_FAILURE_RETRY(connect(log_fd, &u.addr, sizeof(u.addrUn))) != 0) {
    __close(log_fd);
    return -1;
  }

  return log_fd;
}

由于以上方法用着不是很爽,下面将通过"#define"定义几个常用的日志打印宏定义。

二、方便日志输出接口定义

参照平时ndk开发中LOGD/LOGI/LOGE的宏定义,在bionic/libc/async_safe/include/async_safe/log.h文件中定义如下方便libc中调用的日志接口。如下所示:

图片

三、在libc中的open函数中调用

图片

四、测试效果

编译刷机之后,终端日志输出效果还不错:

图片

安卓系统、安卓ndk开发、安卓应用安全和逆向分析相关、刷机等知识分享交流,系统定制、frida、xposed(sandhook、edxposed)系统集成等等。微信搜索公众号"QDOIRD88888"或者扫描以下二维码关注公众号。第一时间接收更新文章。

图片

猜你喜欢

转载自blog.csdn.net/xiaomaNo01/article/details/112986759