Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7cc23363 authored by Mark Salyzyn's avatar Mark Salyzyn Committed by Android (Google) Code Review
Browse files

Merge changes Ia6d6821e,I1e1a55d1,Ic26e9dba,Iedc55c13

* changes:
  liblog: Add liblog test suite
  logcat: Incorporate liblog reading API
  debuggerd: Incorporate liblog reading API
  liblog: Interface to support abstracting log read
parents e3f0c079 46abc522
Loading
Loading
Loading
Loading
+34 −66
Original line number Diff line number Diff line
/*
 * Copyright (C) 2012 The Android Open Source Project
 * Copyright (C) 2012-2013 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
@@ -29,6 +29,7 @@

#include <private/android_filesystem_config.h>

#include <log/log.h>
#include <log/logger.h>
#include <cutils/properties.h>

@@ -468,43 +469,38 @@ static bool dump_sibling_thread_report(
 * Reads the contents of the specified log device, filters out the entries
 * that don't match the specified pid, and writes them to the tombstone file.
 *
 * If "tailOnly" is set, we only print the last few lines.
 * If "tail" is set, we only print the last few lines.
 */
static void dump_log_file(log_t* log, pid_t pid, const char* filename,
    bool tailOnly)
    unsigned int tail)
{
    bool first = true;
    struct logger_list *logger_list;

    /* circular buffer, for "tailOnly" mode */
    const int kShortLogMaxLines = 5;
    const int kShortLogLineLen = 256;
    char shortLog[kShortLogMaxLines][kShortLogLineLen];
    int shortLogCount = 0;
    int shortLogNext = 0;
    logger_list = android_logger_list_open(
        android_name_to_log_id(filename), O_RDONLY | O_NONBLOCK, tail, pid);

    int logfd = open(filename, O_RDONLY | O_NONBLOCK);
    if (logfd < 0) {
    if (!logger_list) {
        XLOG("Unable to open %s: %s\n", filename, strerror(errno));
        return;
    }

    union {
        unsigned char buf[LOGGER_ENTRY_MAX_LEN + 1];
        struct logger_entry entry;
    } log_entry;
    struct log_msg log_entry;

    while (true) {
        ssize_t actual = read(logfd, log_entry.buf, LOGGER_ENTRY_MAX_LEN);
        ssize_t actual = android_logger_list_read(logger_list, &log_entry);
        struct logger_entry* entry;

        if (actual < 0) {
            if (errno == EINTR) {
            if (actual == -EINTR) {
                /* interrupted by signal, retry */
                continue;
            } else if (errno == EAGAIN) {
            } else if (actual == -EAGAIN) {
                /* non-blocking EOF; we're done */
                break;
            } else {
                _LOG(log, 0, "Error while reading log: %s\n",
                    strerror(errno));
                    strerror(-actual));
                break;
            }
        } else if (actual == 0) {
@@ -520,16 +516,11 @@ static void dump_log_file(log_t* log, pid_t pid, const char* filename,
         * the tombstone file.
         */

        struct logger_entry* entry = &log_entry.entry;

        if (entry->pid != (int32_t) pid) {
            /* wrong pid, ignore */
            continue;
        }
        entry = &log_entry.entry_v1;

        if (first) {
            _LOG(log, 0, "--------- %slog %s\n",
                tailOnly ? "tail end of " : "", filename);
                tail ? "tail end of " : "", filename);
            first = false;
        }

@@ -543,9 +534,14 @@ static void dump_log_file(log_t* log, pid_t pid, const char* filename,
         * on a separate line, prefixed with the header, like logcat does.
         */
        static const char* kPrioChars = "!.VDIWEFS";
        unsigned char prio = entry->msg[0];
        char* tag = entry->msg + 1;
        char* msg = tag + strlen(tag) + 1;
        unsigned hdr_size = log_entry.entry.hdr_size;
        if (!hdr_size) {
            hdr_size = sizeof(log_entry.entry_v1);
        }
        char* msg = (char *)log_entry.buf + hdr_size;
        unsigned char prio = msg[0];
        char* tag = msg + 1;
        msg = tag + strlen(tag) + 1;

        /* consume any trailing newlines */
        char* eatnl = msg + strlen(msg) - 1;
@@ -562,50 +558,22 @@ static void dump_log_file(log_t* log, pid_t pid, const char* filename,
        ptm = localtime_r(&sec, &tmBuf);
        strftime(timeBuf, sizeof(timeBuf), "%m-%d %H:%M:%S", ptm);

        if (tailOnly) {
            snprintf(shortLog[shortLogNext], kShortLogLineLen,
                "%s.%03d %5d %5d %c %-8s: %s",
                timeBuf, entry->nsec / 1000000, entry->pid, entry->tid,
                prioChar, tag, msg);
            shortLogNext = (shortLogNext + 1) % kShortLogMaxLines;
            shortLogCount++;
        } else {
        _LOG(log, 0, "%s.%03d %5d %5d %c %-8s: %s\n",
             timeBuf, entry->nsec / 1000000, entry->pid, entry->tid,
             prioChar, tag, msg);
    }
    }

    if (tailOnly) {
        int i;

        /*
         * If we filled the buffer, we want to start at "next", which has
         * the oldest entry.  If we didn't, we want to start at zero.
         */
        if (shortLogCount < kShortLogMaxLines) {
            shortLogNext = 0;
        } else {
            shortLogCount = kShortLogMaxLines;  /* cap at window size */
        }

        for (i = 0; i < shortLogCount; i++) {
            _LOG(log, 0, "%s\n", shortLog[shortLogNext]);
            shortLogNext = (shortLogNext + 1) % kShortLogMaxLines;
        }
    }

    close(logfd);
    android_logger_list_free(logger_list);
}

/*
 * Dumps the logs generated by the specified pid to the tombstone, from both
 * "system" and "main" log devices.  Ideally we'd interleave the output.
 */
static void dump_logs(log_t* log, pid_t pid, bool tailOnly)
static void dump_logs(log_t* log, pid_t pid, unsigned tail)
{
    dump_log_file(log, pid, "/dev/log/system", tailOnly);
    dump_log_file(log, pid, "/dev/log/main", tailOnly);
    dump_log_file(log, pid, "system", tail);
    dump_log_file(log, pid, "main", tail);
}

static void dump_abort_message(const backtrace_context_t* context, log_t* log, uintptr_t address) {
@@ -683,7 +651,7 @@ static bool dump_crash(log_t* log, pid_t pid, pid_t tid, int signal, uintptr_t a
    }

    if (want_logs) {
        dump_logs(log, pid, true);
        dump_logs(log, pid, 5);
    }

    bool detach_failed = false;
@@ -692,7 +660,7 @@ static bool dump_crash(log_t* log, pid_t pid, pid_t tid, int signal, uintptr_t a
    }

    if (want_logs) {
        dump_logs(log, pid, false);
        dump_logs(log, pid, 0);
    }

    /* send EOD to the Activity Manager, then wait for its ack to avoid racing ahead
+64 −15
Original line number Diff line number Diff line
/*
 * Copyright (C) 2005 The Android Open Source Project
 * Copyright (C) 2005-2013 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
@@ -28,21 +28,19 @@
#ifndef _LIBS_LOG_LOG_H
#define _LIBS_LOG_LOG_H

#include <stdio.h>
#include <time.h>
#include <sys/cdefs.h>
#include <sys/types.h>
#include <unistd.h>
#ifdef HAVE_PTHREADS
#include <pthread.h>
#endif
#include <stdarg.h>

#include <log/uio.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <log/logd.h>
#include <log/uio.h>

#ifdef __cplusplus
extern "C" {
#endif
__BEGIN_DECLS

// ---------------------------------------------------------------------

@@ -470,7 +468,8 @@ typedef enum {
    EVENT_TYPE_STRING   = 2,
    EVENT_TYPE_LIST     = 3,
} AndroidEventLogType;

#define sizeof_AndroidEventLogType sizeof(typeof_AndroidEventLogType)
#define typeof_AndroidEventLogType unsigned char

#ifndef LOG_EVENT_INT
#define LOG_EVENT_INT(_tag, _value) {                                       \
@@ -540,7 +539,9 @@ typedef enum {
#define android_logToFile(tag, file) (0)
#define android_logToFd(tag, fd) (0)

typedef enum {
typedef enum log_id {
    LOG_ID_MIN = 0,

    LOG_ID_MAIN = 0,
    LOG_ID_RADIO = 1,
    LOG_ID_EVENTS = 2,
@@ -548,6 +549,57 @@ typedef enum {

    LOG_ID_MAX
} log_id_t;
#define sizeof_log_id_t sizeof(typeof_log_id_t)
#define typeof_log_id_t unsigned char

/* Currently helper to liblog unit tests, expect wider use. */
#define NS_PER_SEC 1000000000ULL
#ifdef __cplusplus
typedef struct log_time : public timespec {
public:
    log_time(void)
    {
    }
    log_time(const char *T)
    {
        const uint8_t *c = (const uint8_t *) T;
        tv_sec = c[0] | (c[1] << 8) | (c[2] << 16) | (c[3] << 24);
        tv_nsec = c[4] | (c[5] << 8) | (c[6] << 16) | (c[7] << 24);
    }
    bool operator== (log_time &T)
    {
        return (tv_sec == T.tv_sec) && (tv_nsec == T.tv_nsec);
    }
    bool operator!= (log_time &T)
    {
        return !(*this == T);
    }
    bool operator< (log_time &T)
    {
        return (tv_sec < T.tv_sec)
            || ((tv_sec == T.tv_sec) && (tv_nsec < T.tv_nsec));
    }
    bool operator>= (log_time &T)
    {
        return !(*this < T);
    }
    bool operator> (log_time &T)
    {
        return (tv_sec > T.tv_sec)
            || ((tv_sec == T.tv_sec) && (tv_nsec > T.tv_nsec));
    }
    bool operator<= (log_time &T)
    {
        return !(*this > T);
    }
    uint64_t nsec(void)
    {
        return static_cast<uint64_t>(tv_sec) * NS_PER_SEC + tv_nsec;
    }
} log_time_t;
#else
typedef struct timespec log_time_t;
#endif

/*
 * Send a simple string to the log.
@@ -555,9 +607,6 @@ typedef enum {
int __android_log_buf_write(int bufID, int prio, const char *tag, const char *text);
int __android_log_buf_print(int bufID, int prio, const char *tag, const char *fmt, ...);


#ifdef __cplusplus
}
#endif
__END_DECLS

#endif // _LIBS_CUTILS_LOG_H
+108 −2
Original line number Diff line number Diff line
/* utils/logger.h
/*
**
** Copyright 2007, The Android Open Source Project
**
@@ -10,7 +10,11 @@
#ifndef _UTILS_LOGGER_H
#define _UTILS_LOGGER_H

#include <sys/cdefs.h>
#include <stdint.h>
#include <log/log.h>

__BEGIN_DECLS

/*
 * The userspace structure for version 1 of the logger_entry ABI.
@@ -63,6 +67,106 @@ struct logger_entry_v2 {
 */
#define LOGGER_ENTRY_MAX_LEN		(5*1024)

#define NS_PER_SEC 1000000000ULL

struct log_msg {
    union {
        unsigned char buf[LOGGER_ENTRY_MAX_LEN + 1];
        struct logger_entry_v2 entry;
        struct logger_entry_v2 entry_v2;
        struct logger_entry    entry_v1;
        struct {
            unsigned char buf[LOGGER_ENTRY_MAX_LEN + 1];
            log_id_t id;
        } extra;
    } __attribute__((aligned(4)));
#ifdef __cplusplus
    /* Matching log_time_t operators */
    bool operator== (log_msg &T)
    {
        return (entry.sec == T.entry.sec) && (entry.nsec == T.entry.nsec);
    }
    bool operator!= (log_msg &T)
    {
        return !(*this == T);
    }
    bool operator< (log_msg &T)
    {
        return (entry.sec < T.entry.sec)
            || ((entry.sec == T.entry.sec)
             && (entry.nsec < T.entry.nsec));
    }
    bool operator>= (log_msg &T)
    {
        return !(*this < T);
    }
    bool operator> (log_msg &T)
    {
        return (entry.sec > T.entry.sec)
            || ((entry.sec == T.entry.sec)
             && (entry.nsec > T.entry.nsec));
    }
    bool operator<= (log_msg &T)
    {
        return !(*this > T);
    }
    uint64_t nsec(void)
    {
        return static_cast<uint64_t>(entry.sec) * NS_PER_SEC + entry.nsec;
    }

    /* packet methods */
    log_id_t id(void)
    {
        return extra.id;
    }
    char *msg(void)
    {
        return entry.hdr_size ? (char *) buf + entry.hdr_size : entry_v1.msg;
    }
    unsigned int len(void)
    {
        return (entry.hdr_size ? entry.hdr_size : sizeof(entry_v1)) + entry.len;
    }
#endif
};

struct logger;

log_id_t android_logger_get_id(struct logger *logger);

int android_logger_clear(struct logger *logger);
int android_logger_get_log_size(struct logger *logger);
int android_logger_get_log_readable_size(struct logger *logger);
int android_logger_get_log_version(struct logger *logger);

struct logger_list;

struct logger_list *android_logger_list_alloc(int mode,
                                              unsigned int tail,
                                              pid_t pid);
void android_logger_list_free(struct logger_list *logger_list);
/* In the purest sense, the following two are orthogonal interfaces */
int android_logger_list_read(struct logger_list *logger_list,
                             struct log_msg *log_msg);

/* Multiple log_id_t opens */
struct logger *android_logger_open(struct logger_list *logger_list,
                                   log_id_t id);
#define android_logger_close android_logger_free
/* Single log_id_t open */
struct logger_list *android_logger_list_open(log_id_t id,
                                             int mode,
                                             unsigned int tail,
                                             pid_t pid);
#define android_logger_list_close android_logger_list_free

/*
 * log_id_t helpers
 */
log_id_t android_name_to_log_id(const char *logName);
const char *android_log_id_to_name(log_id_t log_id);

#ifdef HAVE_IOCTL

#include <sys/ioctl.h>
@@ -78,4 +182,6 @@ struct logger_entry_v2 {

#endif // HAVE_IOCTL

__END_DECLS

#endif /* _UTILS_LOGGER_H */
+3 −0
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ endif
ifndef WITH_MINGW
    liblog_sources += \
        logprint.c \
        log_read.c \
        event_tag_map.c
else
    liblog_sources += \
@@ -79,3 +80,5 @@ include $(CLEAR_VARS)
LOCAL_MODULE := liblog
LOCAL_WHOLE_STATIC_LIBRARIES := liblog
include $(BUILD_SHARED_LIBRARY)

include $(call first-makefiles-under,$(LOCAL_PATH))

liblog/log_read.c

0 → 100644
+652 −0

File added.

Preview size limit exceeded, changes collapsed.

Loading