Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Crashtracker] Use blazesym API to retrieve buildid #6347

Merged
merged 5 commits into from
Nov 29, 2024
Merged
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
10 changes: 5 additions & 5 deletions build/cmake/FindLibdatadog.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,22 @@ endif()

include(FetchContent)

set(LIBDATADOG_VERSION "v13.1.0" CACHE STRING "libdatadog version")
set(LIBDATADOG_VERSION "v14.3.1" CACHE STRING "libdatadog version")

if (CMAKE_SYSTEM_PROCESSOR STREQUAL aarch64 OR CMAKE_SYSTEM_PROCESSOR STREQUAL arm64)
if (DEFINED ENV{IsAlpine} AND "$ENV{IsAlpine}" MATCHES "true")
set(SHA256_LIBDATADOG "9cddbc9ece4c2fe9a1f0ab5a7cfed218d617c5154f318e0bce9a6102b265c989" CACHE STRING "libdatadog sha256")
set(SHA256_LIBDATADOG "57f83aff275628bb1af89c22bb4bd696726daf2a9e09b6cd0d966b29e65a7ad6" CACHE STRING "libdatadog sha256")
set(FILE_TO_DOWNLOAD libdatadog-aarch64-alpine-linux-musl.tar.gz)
else()
set(SHA256_LIBDATADOG "db17a5873d82ef772f969582949b272dcd04044a0cd08b196d3820172a19814d" CACHE STRING "libdatadog sha256")
set(SHA256_LIBDATADOG "36db8d50ccabb71571158ea13835c0f1d05d30b32135385f97c16343cfb6ddd4" CACHE STRING "libdatadog sha256")
set(FILE_TO_DOWNLOAD libdatadog-aarch64-unknown-linux-gnu.tar.gz)
endif()
else()
if (DEFINED ENV{IsAlpine} AND "$ENV{IsAlpine}" MATCHES "true")
set(SHA256_LIBDATADOG "46d0e6445fa1b0fbe8d079e6fa997fa10a4fef4084fe10f4b5886c92effc7be8" CACHE STRING "libdatadog sha256")
set(SHA256_LIBDATADOG "2f61fd21cf2f8147743e414b4a8c77250a17be3aecc42a69ffe54f0a603d5c92" CACHE STRING "libdatadog sha256")
set(FILE_TO_DOWNLOAD libdatadog-${CMAKE_SYSTEM_PROCESSOR}-alpine-linux-musl.tar.gz)
else()
set(SHA256_LIBDATADOG "adaf79470fd0b06ce6d63ae8f231e555fa12b70d5bf82565a96a25f59ea8071d" CACHE STRING "libdatadog sha256")
set(SHA256_LIBDATADOG "f01f05600591063eba4faf388f54c155ab4e6302e5776c7855e3734955f7daf7" CACHE STRING "libdatadog sha256")
set(FILE_TO_DOWNLOAD libdatadog-${CMAKE_SYSTEM_PROCESSOR}-unknown-linux-gnu.tar.gz)
endif()
endif()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,26 @@

#include <algorithm>
#include <cstdint>
#include <vector>
#include <dirent.h>
#include <string>
#include <memory>
#include <string>
#include <vector>

#include <libunwind.h>
#include <libunwind-ptrace.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
#include "FfiHelper.h"
#include <fstream>
#include <sstream>
#include <libunwind-ptrace.h>
#include <libunwind.h>
#include <map>
#include <sstream>
#include <string.h>
#include "FfiHelper.h"
#include <sys/ptrace.h>
#include <sys/wait.h>

extern "C"
{
#include "datadog/common.h"
#include "datadog/profiling.h"
#include "datadog/crashtracker.h"
#include "datadog/profiling.h"
}

#include <shared/src/native-src/dd_filesystem.hpp>
Expand All @@ -35,8 +35,8 @@ CrashReporting* CrashReporting::Create(int32_t pid)
return (CrashReporting*)crashReporting;
}

CrashReportingLinux::CrashReportingLinux(int32_t pid)
: CrashReporting(pid)
CrashReportingLinux::CrashReportingLinux(int32_t pid) :
CrashReporting(pid)
{
}

Expand Down Expand Up @@ -67,17 +67,17 @@ int32_t CrashReportingLinux::Initialize()
return result;
}

std::pair<std::string_view, uintptr_t> CrashReportingLinux::FindModule(uintptr_t ip)
const ModuleInfo* CrashReportingLinux::FindModule(uintptr_t ip)
{
for (auto const& module : _modules)
{
if (ip >= module.startAddress && ip < module.endAddress)
{
return std::make_pair(module.path, module.baseAddress);
return &module;
}
}

return std::make_pair("", 0);
return nullptr;
}

std::vector<ModuleInfo> CrashReportingLinux::GetModules()
Expand All @@ -97,10 +97,9 @@ std::vector<ModuleInfo> CrashReportingLinux::GetModules()
std::getline(iss, path); // Skip whitespace at the start

// Trim path
path.erase(path.begin(), std::find_if(path.begin(), path.end(), [](int ch)
{
return !std::isspace(ch);
}));
path.erase(path.begin(), std::find_if(path.begin(), path.end(), [](int ch) {
return !std::isspace(ch);
}));

if (path.empty())
{
Expand Down Expand Up @@ -133,7 +132,8 @@ std::vector<ModuleInfo> CrashReportingLinux::GetModules()
moduleBaseAddresses[path] = baseAddress;
}

modules.push_back(ModuleInfo{ start, end, baseAddress, std::move(path) });
auto buildId = ElfBuildId(path.data());
modules.push_back(ModuleInfo{ start, end, baseAddress, std::move(path), std::move(buildId) });
}

return modules;
Expand Down Expand Up @@ -196,67 +196,76 @@ std::vector<StackFrame> CrashReportingLinux::GetThreadFrames(int32_t tid, Resolv
stackFrame.sp = sp;
stackFrame.isSuspicious = false;

ResolveMethodData methodData;

auto [moduleName, moduleAddress] = FindModule(ip);
stackFrame.moduleAddress = moduleAddress;

bool hasName = false;

unw_proc_info_t procInfo;
result = unw_get_proc_info(&cursor, &procInfo);

if (result == 0)
auto* module = FindModule(ip);
if (module != nullptr)
{
stackFrame.symbolAddress = procInfo.start_ip;
stackFrame.moduleAddress = module->baseAddress;

unw_word_t offset;
result = unw_get_proc_name(&cursor, methodData.symbolName, sizeof(methodData.symbolName), &offset);
bool hasName = false;

unw_proc_info_t procInfo;
result = unw_get_proc_info(&cursor, &procInfo);

if (result == 0)
{
stackFrame.method = std::string(methodData.symbolName);
hasName = true;
stackFrame.symbolAddress = procInfo.start_ip;

auto demangleResult = ddog_crasht_demangle(libdatadog::to_char_slice(stackFrame.method), DDOG_CRASHT_DEMANGLE_OPTIONS_COMPLETE);
ResolveMethodData methodData;
unw_word_t offset;
result = unw_get_proc_name(&cursor, methodData.symbolName, sizeof(methodData.symbolName), &offset);

if (demangleResult.tag == DDOG_CRASHT_STRING_WRAPPER_RESULT_OK)
if (result == 0)
{
// TODO: There is currently no safe way to free the StringWrapper
auto stringWrapper = demangleResult.ok;
stackFrame.method = std::string(methodData.symbolName);
hasName = true;

auto demangleResult = ddog_crasht_demangle(libdatadog::to_char_slice(stackFrame.method), DDOG_CRASHT_DEMANGLE_OPTIONS_COMPLETE);

if (stringWrapper.message.len > 0)
if (demangleResult.tag == DDOG_CRASHT_STRING_WRAPPER_RESULT_OK)
{
stackFrame.method = std::string((char*)stringWrapper.message.ptr, stringWrapper.message.len);
// TODO: There is currently no safe way to free the StringWrapper
auto stringWrapper = demangleResult.ok;

if (stringWrapper.message.len > 0)
{
stackFrame.method = std::string((char*)stringWrapper.message.ptr, stringWrapper.message.len);
}
}
}
}
}

if (!hasName)
{
std::ostringstream unknownModule;
unknownModule << moduleName << "!<unknown>+" << std::hex << (ip - moduleAddress);
stackFrame.method = unknownModule.str();
}
if (!hasName)
{
std::ostringstream unknownModule;
unknownModule << module->path << "!<unknown>+" << std::hex << (ip - module->baseAddress);
stackFrame.method = unknownModule.str();
}

stackFrame.isSuspicious = false;
stackFrame.isSuspicious = false;

fs::path modulePath(moduleName);
stackFrame.buildId = module->build_id;

if (modulePath.has_filename())
{
const auto moduleFilename = modulePath.stem().string();
fs::path modulePath(module->path);

if ((moduleFilename.rfind("Datadog", 0) == 0 && stackFrame.method != "dd_pthread_entry")
|| moduleFilename == "libdatadog"
|| moduleFilename == "datadog"
|| moduleFilename == "libddwaf"
|| moduleFilename == "ddwaf" )
if (modulePath.has_filename())
{
stackFrame.isSuspicious = true;
const auto moduleFilename = modulePath.stem().string();

if ((moduleFilename.rfind("Datadog", 0) == 0 && stackFrame.method != "dd_pthread_entry")
|| moduleFilename == "libdatadog"
|| moduleFilename == "datadog"
|| moduleFilename == "libddwaf"
|| moduleFilename == "ddwaf" )
{
stackFrame.isSuspicious = true;
}
}
}
else
{
stackFrame.method = "<unknown>";
}

frames.push_back(std::move(stackFrame));

Expand Down Expand Up @@ -325,5 +334,5 @@ std::string CrashReportingLinux::GetThreadName(int32_t tid)
std::string threadName;
std::getline(commFile, threadName);
commFile.close();
return threadName;
return threadName;
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#pragma once
#include "CrashReporting.h"

#include <cstdint>
#include <memory>
#include <string>

#include <libunwind.h>
Expand All @@ -14,6 +16,8 @@ struct ModuleInfo
uintptr_t endAddress;
uintptr_t baseAddress;
std::string path;
// defined in CrashReporting.h
ElfBuildId build_id;
};

class CrashReportingLinux : public CrashReporting
Expand All @@ -28,7 +32,7 @@ class CrashReportingLinux : public CrashReporting
private:
std::vector<std::pair<int32_t, std::string>> GetThreads() override;
std::vector<StackFrame> GetThreadFrames(int32_t tid, ResolveManagedCallstack resolveManagedCallstack, void* context) override;
std::pair<std::string_view, uintptr_t> FindModule(uintptr_t ip);
const ModuleInfo* FindModule(uintptr_t ip);
std::vector<ModuleInfo> GetModules();
std::string GetSignalInfo(int32_t signal) override;
std::string GetThreadName(int32_t tid);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,17 @@ int32_t CrashReporting::Initialize()
return 1;
}

#ifdef LINUX
// temporary: will remove it when windows will target libdatadog >= 14.3.0
auto otherResult = ddog_crasht_CrashInfo_set_procinfo(&_crashInfo, { _pid });

if (otherResult.tag == DDOG_CRASHT_RESULT_ERR)
{
SetLastError(otherResult.err);
return 1;
}
#endif

return AddTag("severity", "crash");
}

Expand Down Expand Up @@ -222,12 +233,22 @@ int32_t CrashReporting::ResolveStacks(int32_t crashingThreadId, ResolveManagedCa
.symbol_address = symbolAddress,
};

#ifdef _WINDOWS
if (frame.hasPdbInfo)
{
stackFrames[i].normalized_ip.typ = DDOG_CRASHT_NORMALIZED_ADDRESS_TYPES_PDB;
stackFrames[i].normalized_ip.age = frame.pdbAge;
stackFrames[i].normalized_ip.build_id = { (uint8_t*)&frame.pdbSig, 16 };
}
#else
const auto buildId = frame.buildId.AsSpan();
if (buildId.size() != 0)
{
stackFrames[i].normalized_ip.typ = DDOG_CRASHT_NORMALIZED_ADDRESS_TYPES_ELF;
stackFrames[i].normalized_ip.build_id = {buildId.data(), buildId.size()};
stackFrames[i].normalized_ip.file_offset = ip - moduleAddress;
}
#endif
}

auto threadIdStr = std::to_string(threadId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,18 @@
#include <string>
#include <memory>
#include <optional>
#include <utility>

#include "cor.h"
#include "corprof.h"

#include "shared/src/native-src/dd_span.hpp"

extern "C"
{
#ifdef LINUX
#include "datadog/blazesym.h"
#endif
#include "datadog/common.h"
#include "datadog/profiling.h"
}
Expand All @@ -30,6 +36,51 @@ struct ResolveMethodData
char symbolName[1024];
};

#ifdef LINUX
class ElfBuildId
{
private:
struct ElfBuildIdImpl {
ElfBuildIdImpl() : ElfBuildIdImpl(nullptr) {}
ElfBuildIdImpl(const char* path) : _ptr{nullptr}, _size{0} {
if (path != nullptr)
{
_ptr = blaze_read_elf_build_id(path, &_size);
}
};
~ElfBuildIdImpl()
{
auto* ptr = std::exchange(_ptr, nullptr);
if (ptr != nullptr && _size != 0)
{
_size = 0;
::free(ptr);
}
}

ElfBuildIdImpl(ElfBuildIdImpl const&) = delete;
ElfBuildIdImpl(ElfBuildIdImpl&&) = delete;
ElfBuildIdImpl& operator=(ElfBuildIdImpl const&) = delete;
ElfBuildIdImpl& operator=(ElfBuildIdImpl&&) = delete;

std::uint8_t* _ptr;
std::size_t _size;
};
public:
ElfBuildId() : ElfBuildId(nullptr) {}
ElfBuildId(const char* path)
: _impl{std::make_shared<ElfBuildIdImpl>(path)} {}

shared::span<std::uint8_t> AsSpan() const
{
return shared::span(_impl->_ptr, _impl->_size);
}

private:
std::shared_ptr<ElfBuildIdImpl> _impl;
};
#endif

struct StackFrame
{
uint64_t ip;
Expand All @@ -38,9 +89,13 @@ struct StackFrame
uint64_t symbolAddress;
uint64_t moduleAddress;
bool isSuspicious;
#ifdef _WINDOWS
bool hasPdbInfo;
DWORD pdbAge;
GUID pdbSig;
#else
ElfBuildId buildId;
#endif
};

struct Tag
Expand Down
Loading
Loading