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

Commit b18f93ea authored by Christopher Ferris's avatar Christopher Ferris Committed by Gerrit Code Review
Browse files

Merge "Move CallStack to libbacktrace."

parents b0751101 038ac694
Loading
Loading
Loading
Loading
+8 −31
Original line number Diff line number Diff line
@@ -18,8 +18,9 @@
#define ANDROID_CALLSTACK_H

#include <android/log.h>
#include <backtrace/backtrace.h>
#include <utils/String8.h>
#include <corkscrew/backtrace.h>
#include <utils/Vector.h>

#include <stdint.h>
#include <sys/types.h>
@@ -31,42 +32,19 @@ class Printer;
// Collect/print the call stack (function, file, line) traces for a single thread.
class CallStack {
public:
    enum {
        // Prune the lowest-most stack frames until we have at most MAX_DEPTH.
        MAX_DEPTH = 31,
        // Placeholder for specifying the current thread when updating the stack.
        CURRENT_THREAD = -1,
    };

    // Create an empty call stack. No-op.
    CallStack();
    // Create a callstack with the current thread's stack trace.
    // Immediately dump it to logcat using the given logtag.
    CallStack(const char* logtag, int32_t ignoreDepth=1,
            int32_t maxDepth=MAX_DEPTH);
    // Copy the existing callstack (no other side effects).
    CallStack(const CallStack& rhs);
    CallStack(const char* logtag, int32_t ignoreDepth=1);
    ~CallStack();

    // Copy the existing callstack (no other side effects).
    CallStack& operator = (const CallStack& rhs);

    // Compare call stacks by their backtrace frame memory.
    bool operator == (const CallStack& rhs) const;
    bool operator != (const CallStack& rhs) const;
    bool operator < (const CallStack& rhs) const;
    bool operator >= (const CallStack& rhs) const;
    bool operator > (const CallStack& rhs) const;
    bool operator <= (const CallStack& rhs) const;

    // Get the PC address for the stack frame specified by index.
    const void* operator [] (int index) const;

    // Reset the stack frames (same as creating an empty call stack).
    void clear();
    void clear() { mFrameLines.clear(); }

    // Immediately collect the stack traces for the specified thread.
    void update(int32_t ignoreDepth=1, int32_t maxDepth=MAX_DEPTH, pid_t tid=CURRENT_THREAD);
    // The default is to dump the stack of the current call.
    void update(int32_t ignoreDepth=1, pid_t tid=BACKTRACE_NO_TID);

    // Dump a stack trace to the log using the supplied logtag.
    void log(const char* logtag,
@@ -83,11 +61,10 @@ public:
    void print(Printer& printer) const;

    // Get the count of stack frames that are in this call stack.
    size_t size() const { return mCount; }
    size_t size() const { return mFrameLines.size(); }

private:
    size_t mCount;
    backtrace_frame_t mStack[MAX_DEPTH];
    Vector<String8> mFrameLines;
};

}; // namespace android
+1 −1
Original line number Diff line number Diff line
@@ -39,7 +39,7 @@ public:
    ~ProcessCallStack();

    // Immediately collect the stack traces for all threads.
    void update(int32_t maxDepth = CallStack::MAX_DEPTH);
    void update();

    // Print all stack traces to the log using the supplied logtag.
    void log(const char* logtag, android_LogPriority priority = ANDROID_LOG_DEBUG,
+7 −3
Original line number Diff line number Diff line
@@ -116,10 +116,12 @@ LOCAL_STATIC_LIBRARIES := \
	libcutils

LOCAL_SHARED_LIBRARIES := \
        libcorkscrew \
        libbacktrace \
        liblog \
        libdl

include external/stlport/libstlport.mk

LOCAL_MODULE:= libutils
include $(BUILD_STATIC_LIBRARY)

@@ -129,10 +131,12 @@ include $(CLEAR_VARS)
LOCAL_MODULE:= libutils
LOCAL_WHOLE_STATIC_LIBRARIES := libutils
LOCAL_SHARED_LIBRARIES := \
        liblog \
        libbacktrace \
        libcutils \
        libdl \
        libcorkscrew
        liblog \

include external/stlport/libstlport.mk

include $(BUILD_SHARED_LIBRARY)

+15 −82
Original line number Diff line number Diff line
@@ -20,93 +20,33 @@
#include <utils/Printer.h>
#include <utils/Errors.h>
#include <utils/Log.h>
#include <corkscrew/backtrace.h>
#include <UniquePtr.h>

#include <backtrace/Backtrace.h>

namespace android {

CallStack::CallStack() :
        mCount(0) {
CallStack::CallStack() {
}

CallStack::CallStack(const char* logtag, int32_t ignoreDepth, int32_t maxDepth) {
    this->update(ignoreDepth+1, maxDepth, CURRENT_THREAD);
CallStack::CallStack(const char* logtag, int32_t ignoreDepth) {
    this->update(ignoreDepth+1);
    this->log(logtag);
}

CallStack::CallStack(const CallStack& rhs) :
        mCount(rhs.mCount) {
    if (mCount) {
        memcpy(mStack, rhs.mStack, mCount * sizeof(backtrace_frame_t));
    }
}

CallStack::~CallStack() {
}

CallStack& CallStack::operator = (const CallStack& rhs) {
    mCount = rhs.mCount;
    if (mCount) {
        memcpy(mStack, rhs.mStack, mCount * sizeof(backtrace_frame_t));
    }
    return *this;
}

bool CallStack::operator == (const CallStack& rhs) const {
    if (mCount != rhs.mCount)
        return false;
    return !mCount || memcmp(mStack, rhs.mStack, mCount * sizeof(backtrace_frame_t)) == 0;
}

bool CallStack::operator != (const CallStack& rhs) const {
    return !operator == (rhs);
}
void CallStack::update(int32_t ignoreDepth, pid_t tid) {
    mFrameLines.clear();

bool CallStack::operator < (const CallStack& rhs) const {
    if (mCount != rhs.mCount)
        return mCount < rhs.mCount;
    return memcmp(mStack, rhs.mStack, mCount * sizeof(backtrace_frame_t)) < 0;
    UniquePtr<Backtrace> backtrace(Backtrace::Create(BACKTRACE_CURRENT_PROCESS, tid));
    if (!backtrace->Unwind(ignoreDepth)) {
        ALOGW("%s: Failed to unwind callstack.", __FUNCTION__);
    }

bool CallStack::operator >= (const CallStack& rhs) const {
    return !operator < (rhs);
    for (size_t i = 0; i < backtrace->NumFrames(); i++) {
      mFrameLines.push_back(String8(backtrace->FormatFrameData(i).c_str()));
    }

bool CallStack::operator > (const CallStack& rhs) const {
    if (mCount != rhs.mCount)
        return mCount > rhs.mCount;
    return memcmp(mStack, rhs.mStack, mCount * sizeof(backtrace_frame_t)) > 0;
}

bool CallStack::operator <= (const CallStack& rhs) const {
    return !operator > (rhs);
}

const void* CallStack::operator [] (int index) const {
    if (index >= int(mCount))
        return 0;
    return reinterpret_cast<const void*>(mStack[index].absolute_pc);
}

void CallStack::clear() {
    mCount = 0;
}

void CallStack::update(int32_t ignoreDepth, int32_t maxDepth, pid_t tid) {
    if (maxDepth > MAX_DEPTH) {
        maxDepth = MAX_DEPTH;
    }
    ssize_t count;

    if (tid >= 0) {
        count = unwind_backtrace_thread(tid, mStack, ignoreDepth + 1, maxDepth);
    } else if (tid == CURRENT_THREAD) {
        count = unwind_backtrace(mStack, ignoreDepth + 1, maxDepth);
    } else {
        ALOGE("%s: Invalid tid specified (%d)", __FUNCTION__, tid);
        count = 0;
    }

    mCount = count > 0 ? count : 0;
}

void CallStack::log(const char* logtag, android_LogPriority priority, const char* prefix) const {
@@ -129,16 +69,9 @@ String8 CallStack::toString(const char* prefix) const {
}

void CallStack::print(Printer& printer) const {
    backtrace_symbol_t symbols[mCount];

    get_backtrace_symbols(mStack, mCount, symbols);
    for (size_t i = 0; i < mCount; i++) {
        char line[MAX_BACKTRACE_LINE_LENGTH];
        format_backtrace_line(i, &mStack[i], &symbols[i],
                line, MAX_BACKTRACE_LINE_LENGTH);
        printer.printLine(line);
    for (size_t i = 0; i < mFrameLines.size(); i++) {
        printer.printLine(mFrameLines[i]);
    }
    free_backtrace_symbols(symbols, mCount);
}

}; // namespace android
+1 −0
Original line number Diff line number Diff line
@@ -145,6 +145,7 @@ void String8Printer::printLine(const char* string) {
        return;
    }

    mTarget->append(mPrefix);
    mTarget->append(string);
    mTarget->append("\n");
}
Loading