From d68de66ea754d8b49815d20b10e69d162ca0a7e1 Mon Sep 17 00:00:00 2001 From: Maunik Shah Date: Tue, 22 Sep 2015 16:15:39 +0530 Subject: Copy the ETB dumps and maps file to /data/core On enabling the persist.debug.trace, ETB maps and dumps will be copied to /data/core only for the first crash. Change-Id: I521ee02e30ce1b4ebaca2c6b398c828286a5115d --- debuggerd/debuggerd.cpp | 80 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/debuggerd/debuggerd.cpp b/debuggerd/debuggerd.cpp index 984b931..4e1f53e 100644 --- a/debuggerd/debuggerd.cpp +++ b/debuggerd/debuggerd.cpp @@ -1,5 +1,6 @@ /* * Copyright 2006, The Android Open Source Project + * Copyright (c) 2015, The Linux Foundation. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -138,6 +139,84 @@ static int get_process_info(pid_t tid, pid_t* out_pid, uid_t* out_uid, uid_t* ou return fields == 7 ? 0 : -1; } +static bool copy_file(const char* src, char* dest) +{ + #define BUF_SIZE 64 + ssize_t bytes; + int source_fh, dest_fh; + int total_size = 0; + char buffer[BUF_SIZE]; + + if ((source_fh = open(src, O_RDONLY, O_NOFOLLOW)) == -1) { + ALOGE("Unable to open source file %s\n", src); + } else { + if((dest_fh = open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_NOFOLLOW, 0640)) == -1) { + ALOGE("Unable to write destination file %s\n", dest); + } else { + while ((bytes = read(source_fh, buffer, BUF_SIZE)) > 0) { + if (write(dest_fh, buffer, bytes) < 0) { + ALOGE("Write failed for destination file %s. Copied %d bytes\n", + dest, total_size); + break; + } + total_size += bytes; + } + ALOGI("Copied %s to %s - size: %d\n", src, dest, total_size); + fsync(dest_fh); + close(dest_fh); + } + close(source_fh); + if (total_size > 0) { + return true; + } + } + return false; +} + +static void collect_etb_map(int cr_pid) +{ + struct stat s; + char src_buf[64]; + char dest_buf[64]; + + snprintf(dest_buf, sizeof dest_buf, "/data/core/etb.%d", cr_pid); + if (!copy_file("/dev/coresight-tmc-etf", dest_buf)) { + ALOGE("Unable to copy ETB buffer file /dev/coresight-tmc-etf\n"); + } else { + memset(src_buf, 0, sizeof(src_buf)); + snprintf(src_buf, sizeof(src_buf), "/proc/%d/maps", cr_pid); + if(stat(src_buf, &s)) { + ALOGE("map file /proc/%d/maps does not exist for pid %d\n", + cr_pid, cr_pid); + } else { + snprintf(dest_buf, sizeof dest_buf, "/data/core/maps.%d", cr_pid); + if (!copy_file(src_buf, dest_buf)) { + ALOGE("Unable to copy map file /proc/%d/maps", cr_pid); + } + } + } +} + +static void enable_etb_trace(struct ucred cr) { + char value[PROPERTY_VALUE_MAX]; + property_get("persist.debug.trace", value, ""); + if ((strcmp(value,"1") == 0)) { + /* Allow ETB collection only once; Note: in future this behavior can be changed + * To allow this, use a property to indicate whether the ETB has been collected */ + property_get("debug.etb.collected", value, ""); + if(strcmp(value,"1")) { + ALOGI("Collecting ETB dumps (from pid=%d uid=%d)\n", + cr.pid, cr.uid); + property_set("debug.etb.collected", "1"); + collect_etb_map(cr.pid); + } + else { + ALOGI("ETB already collected once, skipping (from pid=%d uid=%d)\n", + cr.pid, cr.uid); + } + } +} + static int selinux_enabled; /* @@ -231,6 +310,7 @@ static int read_request(int fd, debugger_request_t* out_request) { // Ensure that the tid reported by the crashing process is valid. char buf[64]; struct stat s; + enable_etb_trace(cr); snprintf(buf, sizeof buf, "/proc/%d/task/%d", out_request->pid, out_request->tid); if (stat(buf, &s)) { ALOGE("tid %d does not exist in pid %d. ignoring debug request\n", -- cgit v1.1