Skip to content

Commit

Permalink
Merge pull request #356 from DataDog/mconstantin/rumm-684/ndk-crash-r…
Browse files Browse the repository at this point in the history
…eporter-stacktrace-improvements

RUMM-684 Cleanup the NDK code
  • Loading branch information
mariusc83 authored Sep 1, 2020
2 parents 791b412 + 355d7cc commit c57c1cd
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 35 deletions.
4 changes: 4 additions & 0 deletions dd-sdk-android-ndk/src/main/cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,7 @@ target_link_libraries( # Specifies the target library.
# Links the target library to the log library
# included in the NDK.
${log-lib})
set_target_properties(datadog-native-lib
PROPERTIES
COMPILE_OPTIONS
-Werror -Wall -pedantic)
5 changes: 5 additions & 0 deletions dd-sdk-android-ndk/src/main/cpp/datadog-native-lib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,13 @@ void crash_signal_intercepted(int signal, const char *signal_name, const char *e

// dump the log into a new file
char filename[200];
// The ARM_32 processors will use an unsigned long long to represent the uint_64. We will pick the
// String format that fits both ARM_32 and ARM_64 (llu).
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wformat"
snprintf(filename, sizeof(filename), "%s/%llu", main_context.storage_dir.c_str(),
time_since_epoch());
#pragma clang diagnostic pop
std::ofstream logs_file_output_stream(filename, std::ofstream::out | std::ofstream::app);
const char *text = serialized_log.c_str();
if (logs_file_output_stream.is_open()) {
Expand Down
65 changes: 46 additions & 19 deletions dd-sdk-android-ndk/src/main/cpp/utils/backtrace-handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,51 +41,78 @@ namespace {
return _URC_NO_REASON;
}


size_t capture_backtrace(uintptr_t *buffer, size_t max) {
BacktraceState state = {buffer, buffer + max};
// unwinds the backtrace and fills the buffer with stack lines addresses
_Unwind_Backtrace(unwind_callback, &state);
return state.current - buffer;
}

const char *get_line_symbol(const void *addr) {
const char *symbol = "";
std::string address_to_hexa(uintptr_t address) {
char address_as_hexa[20];
// The ARM_32 processors will use an unsigned long long to represent a pointer so we will choose the
// String format that fits both ARM_32 and ARM_64 (lx).
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wformat"
std::snprintf(address_as_hexa, sizeof(address_as_hexa), "0x%lx", address);
#pragma clang diagnostic pop
return std::string(address_as_hexa);
}

void get_info_from_address(const uintptr_t address, std::string *backtrace) {
backtrace->append(std::to_string(address));
Dl_info info;
if (dladdr(addr, &info) && info.dli_sname) {
symbol = info.dli_sname;
int fetch_info_success = dladdr(reinterpret_cast<void *>(address), &info);
if (fetch_info_success) {

if (info.dli_fname) {
backtrace->append(" ");
backtrace->append(info.dli_fname);
}

backtrace->append(" ");
backtrace->append(address_to_hexa(address));

if (info.dli_sname) {
backtrace->append(" ");
backtrace->append(info.dli_sname);
}

if (info.dli_fbase) {
backtrace->append(" ");
backtrace->append("+");
backtrace->append(" ");
const uintptr_t address_offset =
address - reinterpret_cast<uintptr_t>(info.dli_fbase);
backtrace->append(std::to_string(address_offset));
}

}
return symbol;

backtrace->append("\\n");
}

}

namespace backtrace {

std::string generate_backtrace() {
// define the buffer which will hold pointers to stack memory addresses
uintptr_t buffer[STACK_SIZE];
// we will now unwind the stack and capture all the memory addresses up to STACK_SIZE in
// the buffer
const size_t captured_stacksize = capture_backtrace(buffer, STACK_SIZE);

std::string backtrace;
for (size_t idx = 0; idx < captured_stacksize; ++idx) {
// we will iterate through all the stack addresses and translate each address in
// readable information
void *addr = reinterpret_cast<void *>(buffer[idx]);
const int hexa_address_buffer_size = 20;
char address_as_hexa[20];
std::snprintf(address_as_hexa, hexa_address_buffer_size, "0x%x", buffer[idx]);
const char *lineSymbol = get_line_symbol(addr);
backtrace.append(std::to_string(idx));
backtrace.append(":");
backtrace.append(address_as_hexa);
backtrace.append(" ");
backtrace.append(lineSymbol);
backtrace.append("\\n");
// readable informationdsadsa
get_info_from_address(buffer[idx], &backtrace);

}
return backtrace;
}


}


7 changes: 0 additions & 7 deletions dd-sdk-android-ndk/src/main/cpp/utils/backtrace-handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,9 @@
#ifndef BACKTRACE_HANDLER_H
#define BACKTRACE_HANDLER_H

#ifdef __cplusplus
extern "C" {
#endif

namespace backtrace {

std::string generate_backtrace();
}

#ifdef __cplusplus
}
#endif
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ TEST test_generate_backtrace(void) {
backtrace.c_str());
// we don't know if the stack is big enough to cover the required max size of 30
unsigned int lines_count = backtrace_lines.size();
const char *regex = "(\\d+):0[xX][0-9a-fA-F]+(\\s*)(.*)";
const char *regex = "(\\d+)(.*)0[xX][0-9a-fA-F]+(.*)";
ASSERT(lines_count > 0 && lines_count <= 30);
for (auto it = backtrace_lines.begin(); it != backtrace_lines.end(); ++it) {
ASSERT(std::regex_match(it->c_str(), std::regex(regex)));
Expand Down
8 changes: 0 additions & 8 deletions dd-sdk-android-ndk/src/test/cpp/test_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,7 @@
#include <string>
#include <list>

#ifdef __cplusplus
extern "C" {
#endif

namespace testutils {

std::list<std::string> split_backtrace_into_lines(const char *buffer);
}

#ifdef __cplusplus
}
#endif

0 comments on commit c57c1cd

Please sign in to comment.