Print call stack in C and CXX - tonykwok/made-mistakes-again GitHub Wiki

Build callstackhelper.so

  1. Create a folder and name it callstackhelper

  2. Create callstackhelper.h

#ifndef __CALLSTACK_HELPER_H__
#define __CALLSTACK_HELPER_H__

#ifdef __cplusplus
#if __cplusplus
extern "C"{
#endif
#endif /* __cplusplus */

void dump_callstack(const char* logtag);

struct export_vtable {
    void (*callstack)(const char* logtag);
};

#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* __cplusplus */

#endif
  1. Create callstackhelper.cpp
#include <utils/CallStack.h>
#include "callstackhelper.h"

struct export_vtable exports = {
    dump_callstack,
};

void dump_callstack(const char* logtag)
{
    android::CallStack cs(logtag);
}
  1. Android.bp
cc_library_shared{
    name: "libcallstackhelper",
    srcs: [
        "libcallstackhelper/callstackhelper.cpp",
    ],
    cflags: [
        "-Wall",
        "-Werror",
        "-Wno-error=date-time",
    ],
    include_dirs: [
        "libcallstackhelper",
    ],
    shared_libs: [
        "libcutils",
        "libutils",
        "libutilscallstack",
    ],
}

Usecase: C

#include <stdio.h>
#include <dlfcn.h>

struct export_vtable {
    void (*callstack)(const char* logtag);
};

static void invoke_callstack(const char* logtag)
{
    void* dlhandle = NULL;
    struct export_vtable* imports = NULL;
    const char DUMPTEST_SO_NAME[] = "/system/lib/libdumpstack.so";

    async_safe_format_log(ANDROID_LOG_WARN, "libc", "%s: dump callstack for %s\n", __func__, logtag);
    dlhandle = dlopen(DUMPTEST_SO_NAME, RTLD_NOW);
    if (!dlhandle) {
        async_safe_format_log(ANDROID_LOG_ERROR, "libc", "%s dlopen error\n", __func__);
        return ;
    }

    imports = static_cast<struct export_vtable *>(dlsym(dlhandle, "exports"));
    if (imports) {
        async_safe_format_log(ANDROID_LOG_ERROR, "libc", "%s dlsym error\n", __func__);
        imports->callstack(logtag);
    }
    dlclose(dlhandle);
}

__BIONIC_WEAK_FOR_NATIVE_BRIDGE
int __system_property_set(const char* key, const char* value) {
    ...
    invoke_callstack("__system_property_set callstack");
    ...
}

OR

#include "callstackhelper.h"
...
int __blabla(const char* key, const char* value) {
    ...
    dump_callstack("blabla_callstack");
    ...
}

Usecase: CPP

  1. Add dependencies into the corresponding Android.bp file:
...
shared_libs: [
    ...
    "libcutils",
    "libutils",
    "libutilscallstack",
],
...
  1. Modify your source file
#include <utils/CallStack.h>
...
bool Layer::setTransform(uint32_t transform) {
    android::CallStack stack("Layer::setTransform callstack");
    if (mDrawingState.bufferTransform == transform) return false;
    mDrawingState.bufferTransform = transform;
    mDrawingState.modified = true;
    setTransactionFlags(eTransactionNeeded);
    return true;
}
...

References

  1. https://juejin.cn/post/7052901054580523016/
⚠️ **GitHub.com Fallback** ⚠️