Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
url = https://github.com/ivanarh/libunwind-ndk.git
[submodule "external/libunwindstack-ndk"]
path = external/libunwindstack-ndk
url = https://github.com/ivanarh/libunwindstack-ndk.git
url = https://github.com/dferret/libunwindstack-ndk.git
[submodule "external/libcorkscrew-ndk"]
path = external/libcorkscrew-ndk
url = https://github.com/ivanarh/libcorkscrew-ndk.git
14 changes: 12 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
cmake_minimum_required(VERSION 3.4.1)
project(ndcrash)
project(ndcrash C CXX ASM)

include(GNUInstallDirs)

set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror=implicit-function-declaration -Werror=incompatible-function-pointer-types")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") #For libunwindstack only.

add_definitions(-D_GNU_SOURCE -D_POSIX_C_SOURCE)
set(NDCRASH_SOURCE_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/src)

include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include ${NDCRASH_SOURCE_ROOT})
Expand Down Expand Up @@ -98,4 +101,11 @@ else()
endif()

add_library(ndcrash STATIC ${NDCRASH_SOURCES})
target_link_libraries(ndcrash ${LINK_LIBRARIES})
target_link_libraries(ndcrash ${LINK_LIBRARIES})

install(TARGETS ndcrash DESTINATION ${CMAKE_INSTALL_LIBDIR})
install(FILES include/ndcrash.h DESTINATION include/ndcrash)

configure_file("${PROJECT_SOURCE_DIR}/libndcrash.pc.in" "${PROJECT_BINARY_DIR}/libndcrash.pc")
install(FILES "${PROJECT_BINARY_DIR}/libndcrash.pc" DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)

294 changes: 6 additions & 288 deletions README.md

Large diffs are not rendered by default.

33 changes: 32 additions & 1 deletion include/ndcrash.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
#include <stdint.h>
#include <stdbool.h>

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

/**
* Enum representing supported unwinders for stack unwinding.
*/
Expand Down Expand Up @@ -45,6 +49,12 @@ enum ndcrash_error {

/// A background out-of-process service has failed to start.
ndcrash_error_service_start_failed,

/// Socket communication with out-of-process daemon failed
ndcrash_error_service_communication_failed,

// Cannot create dump file
ndcrash_file_inaccessible,
};

/**
Expand All @@ -56,6 +66,14 @@ enum ndcrash_error {
*/
enum ndcrash_error ndcrash_in_init(const enum ndcrash_unwinder unwinder, const char *log_file);

/**
* Dump current backtrace into file using unwinder (only libunwindstack supported)
* @param unwinder libunwindstack
* @param log_file Path to backtrace report file where to write it.
* @return generation result
*/
enum ndcrash_error ndcrash_in_dump_backtrace(const enum ndcrash_unwinder unwinder, const char *log_file);

/**
* De-initialize crash reporting library in in-process mode. This call will restore previous signal
* handlers used for crash reporting.
Expand Down Expand Up @@ -132,6 +150,19 @@ bool ndcrash_out_stop_daemon();
* Should be called before ndcrash_out_stop_daemon.
* @return Argument value.
*/
void * ndcrash_out_get_daemon_callbacks_arg();
void *ndcrash_out_get_daemon_callbacks_arg();


/**
* Triggers a manual dump of thread states
* @return dump creation result
*/
enum ndcrash_error ndcrash_out_trigger_dump();

#ifdef __cplusplus
#include <string>
extern "C" void ndcrash_dump_backtrace(std::string &out);
}
#endif // __cplusplus

#endif //NDCRASHDEMO_NDCRASH_H
5 changes: 5 additions & 0 deletions libndcrash.pc.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Name: Ndcrash
Version: @NDCRASH_VERSION@
Description: NDCRASH Library
Libs: -L${CMAKE_INSTALL_FULL_LIBDIR} -lndcrash -lunwindstack -llzma ${EXTRA_LDFLAGS}
Cflags: -I${CMAKE_INSTALL_PREFIX}/include
51 changes: 43 additions & 8 deletions src/ndcrash_dump.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,16 @@
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <android/log.h>
#include <inttypes.h>
#include <string.h>
#include <errno.h>
#ifdef ANDROID
#include <sys/system_properties.h>
#else
#define PROP_VALUE_MAX 256
#endif
#include <sys/ptrace.h>
#include <sys/user.h>
#include <linux/elf.h>

#if __LP64__
Expand Down Expand Up @@ -67,13 +71,20 @@ void ndcrash_dump_write_line(int fd, const char *format, ...) {
char buffer[NDCRASH_LOG_BUFFER_SIZE];

// First writing to a log as is.
#ifdef ANDROID
{
va_list args;
va_start(args, format);
__android_log_vprint(ANDROID_LOG_ERROR, NDCRASH_LOG_TAG, format, args);
va_end(args);
}

#else
va_list args;
va_start(args, format);
vfprintf(stderr, format, args);
fprintf(stderr, "\n");
va_end(args);
#endif
// Writing file to log may be disabled.
if (fd <= 0) return;

Expand Down Expand Up @@ -193,21 +204,27 @@ static inline void ndcrash_dump_signal_info(
str_buffer);
}

void ndcrash_dump_header(int outfile, pid_t pid, pid_t tid, int signo, int si_code, void *faultaddr,
struct ucontext *context) {
/**
* Writes a process information line to a crash report.
* @param outfile Output file descriptor for a crash report.
* @param pid main process id
* @param tid main thread id
* @param str_buffer A buffer where a fault address is written. Passing as an argument to reduce a stack usage.
* @param str_buffer_size A size of passed process_name_buffer in bytes.
*/
static void ndcrash_dump_process_header(int outfile, pid_t pid, pid_t tid, char *str_buffer, size_t str_buffer_size) {
// A special marker of crash report beginning.
ndcrash_dump_write_line(outfile, "*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***");

// This buffer we use to read data from system properties and to read other data from files.
char str_buffer[PROP_VALUE_MAX];

#ifdef ANDROID
{
// Getting system properties and writing them to report.
__system_property_get("ro.build.fingerprint", str_buffer);
ndcrash_dump_write_line(outfile, "Build fingerprint: %s", str_buffer);
__system_property_get("ro.revision", str_buffer);
ndcrash_dump_write_line(outfile, "Revision: '0'");
}
#endif

// Writing processor architecture.
#ifdef __arm__
Expand All @@ -221,7 +238,17 @@ void ndcrash_dump_header(int outfile, pid_t pid, pid_t tid, int signo, int si_co
#endif

// Writing a line about process and thread. Re-using str_buffer for a process name.
ndcrash_write_process_and_thread_info(outfile, pid, tid, str_buffer, sizeofa(str_buffer));
ndcrash_write_process_and_thread_info(outfile, pid, tid, str_buffer, str_buffer_size);

}

void ndcrash_dump_header(int outfile, pid_t pid, pid_t tid, int signo, int si_code, void *faultaddr,
struct ucontext *context) {
// This buffer we use to read data from system properties and to read other data from files.
char str_buffer[PROP_VALUE_MAX];

// Write process header
ndcrash_dump_process_header(outfile, pid, tid, str_buffer, sizeofa(str_buffer));

// Writing an information about signal.
ndcrash_dump_signal_info(outfile, signo, si_code, faultaddr, str_buffer, sizeofa(str_buffer));
Expand Down Expand Up @@ -293,6 +320,14 @@ void ndcrash_dump_header(int outfile, pid_t pid, pid_t tid, int signo, int si_co
ndcrash_write_backtrace_title(outfile);
}

void ndcrash_dump_short_header(int outfile, pid_t pid, pid_t tid) {
// This buffer we use to read data from system properties and to read other data from files.
char str_buffer[PROP_VALUE_MAX];

// Write process header
ndcrash_dump_process_header(outfile, pid, tid, str_buffer, sizeofa(str_buffer));
}

/**
* Obtains other thread registers by ptrace and dumps them to a report.
* @param outfile Output file for a report.
Expand Down
8 changes: 8 additions & 0 deletions src/ndcrash_dump.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,14 @@ void ndcrash_dump_write_line(int fd, const char *format, ...);
void ndcrash_dump_header(int outfile, pid_t pid, pid_t tid, int signo, int si_code, void *faultaddr,
struct ucontext *context);

/**
* Write a crash report header to a file and to log.
* @param outfile Output file descriptor for a crash report.
* @param pid process identifier.
* @param tid thread identifier.
*/
void ndcrash_dump_short_header(int outfile, pid_t pid, pid_t tid);

/**
* Write an other thread info (which is not crashed) to a file and to a log.
* @param outfile Output file descriptor for a crash report.
Expand Down
1 change: 0 additions & 1 deletion src/ndcrash_fd_utils.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#include "ndcrash_fd_utils.h"
#include "ndcrash_log.h"
#include <fcntl.h>
#include <android/log.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
Expand Down
34 changes: 33 additions & 1 deletion src/ndcrash_in.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <asm/unistd.h>

#ifdef ENABLE_INPROCESS
Expand All @@ -30,7 +31,7 @@ struct ndcrash_in_context {
struct ndcrash_in_context *ndcrash_in_context_instance = NULL;

/// Main signal handling function.
void ndcrash_in_signal_handler(int signo, struct siginfo *siginfo, void *ctxvoid) {
void ndcrash_in_signal_handler(int signo, siginfo_t *siginfo, void *ctxvoid) {
// Restoring an old handler to make built-in Android crash mechanism work.
sigaction(signo, &ndcrash_in_context_instance->old_handlers[signo], NULL);

Expand Down Expand Up @@ -124,6 +125,37 @@ enum ndcrash_error ndcrash_in_init(const enum ndcrash_unwinder unwinder, const c
return ndcrash_ok;
}

enum ndcrash_error ndcrash_in_dump_backtrace(const enum ndcrash_unwinder unwinder, const char *log_file) {
int outfile = 0;
outfile = ndcrash_dump_create_file(log_file);
if (outfile <= 0) {
return ndcrash_file_inaccessible;
}

// Dumping header of a crash dump.
ndcrash_dump_short_header(outfile, getpid(), gettid());

// Calling unwinding function.
switch (unwinder) {
#ifdef ENABLE_LIBUNWINDSTACK
case ndcrash_unwinder_libunwindstack:
ndcrash_in_unwind_libunwindstack_local_btdump(outfile);
break;
#endif
default:
break;
}

// Final new line of crash dump.
ndcrash_dump_write_line(outfile, " ");

// Closing an output file.
if (outfile) {
close(outfile);
}
return ndcrash_ok;
}

bool ndcrash_in_deinit() {
if (!ndcrash_in_context_instance) return false;
ndcrash_unregister_signal_handler(ndcrash_in_context_instance->old_handlers);
Expand Down
11 changes: 10 additions & 1 deletion src/ndcrash_log.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#ifndef NDCRASHDEMO_NDCRASH_LOG_H
#define NDCRASHDEMO_NDCRASH_LOG_H
#include <android/log.h>

#ifndef NDCRASH_LOG_TAG
#define NDCRASH_LOG_TAG "NDCRASH"
Expand All @@ -9,7 +8,17 @@
#ifdef NDCRASH_NO_LOG
#define NDCRASHLOG(level, ...)
#else
#ifdef ANDROID
#include <android/log.h>
#define NDCRASHLOG(level, ...) __android_log_print(ANDROID_LOG_##level, NDCRASH_LOG_TAG, __VA_ARGS__)
#else
#include <stdio.h>
#define NDCRASHLOG(level, ...) do { \
fprintf(stderr, NDCRASH_LOG_TAG": "); \
fprintf(stderr, __VA_ARGS__); \
fprintf(stderr, "\n"); \
} while (0)
#endif
#endif

#endif //NDCRASHDEMO_NDCRASH_LOG_H
Loading