diff --git a/crashtracker-ffi/src/crash_info/datatypes.rs b/crashtracker-ffi/src/crash_info/datatypes.rs index d52139aa4..4bf936d93 100644 --- a/crashtracker-ffi/src/crash_info/datatypes.rs +++ b/crashtracker-ffi/src/crash_info/datatypes.rs @@ -69,12 +69,14 @@ pub enum NormalizedAddressTypes { // Make None 0 so that default construction gives none None = 0, Elf, + Pdb, } #[repr(C)] pub struct NormalizedAddress<'a> { file_offset: u64, build_id: ByteSlice<'a>, + age: u64, path: CharSlice<'a>, typ: NormalizedAddressTypes, } @@ -111,13 +113,16 @@ impl<'a> TryFrom<&NormalizedAddress<'a>> for datadog_crashtracker::NormalizedAdd type Error = anyhow::Error; fn try_from(value: &NormalizedAddress<'a>) -> Result { + let to_opt_bytes = |v: ByteSlice| { + if v.is_empty() { + None + } else { + Some(Vec::from(v.as_bytes())) + } + }; match &value.typ { NormalizedAddressTypes::Elf => { - let build_id = if value.build_id.is_empty() { - None - } else { - Some(Vec::from(value.build_id.as_bytes())) - }; + let build_id = to_opt_bytes(value.build_id); let path = value.path.try_to_utf8()?.into(); let meta = datadog_crashtracker::NormalizedAddressMeta::Elf { build_id, path }; Ok(Self { @@ -125,6 +130,16 @@ impl<'a> TryFrom<&NormalizedAddress<'a>> for datadog_crashtracker::NormalizedAdd meta, }) } + NormalizedAddressTypes::Pdb => { + let guid = to_opt_bytes(value.build_id); + let path = value.path.try_to_utf8()?.into(); + let age = value.age; + let meta = datadog_crashtracker::NormalizedAddressMeta::Pdb { path, guid, age }; + Ok(Self { + file_offset: value.file_offset, + meta, + }) + } _ => anyhow::bail!("Unsupported normalized address type {:?}", value.typ), } } diff --git a/crashtracker/src/crash_info/stacktrace.rs b/crashtracker/src/crash_info/stacktrace.rs index 1d1ca22ce..7c644542b 100644 --- a/crashtracker/src/crash_info/stacktrace.rs +++ b/crashtracker/src/crash_info/stacktrace.rs @@ -50,6 +50,11 @@ pub enum NormalizedAddressMeta { path: PathBuf, build_id: Option>, }, + Pdb { + path: PathBuf, + guid: Option>, + age: u64, + }, Unknown, Unexpected(String), } diff --git a/examples/ffi/crashinfo.cpp b/examples/ffi/crashinfo.cpp index d5f34aefd..167adf767 100644 --- a/examples/ffi/crashinfo.cpp +++ b/examples/ffi/crashinfo.cpp @@ -20,6 +20,11 @@ static ddog_CharSlice to_slice_string(std::string const &s) { return {.ptr = s.data(), .len = s.length()}; } +template +static ddog_ByteSlice to_byte_slice(T const& c) { + return {.ptr = reinterpret_cast(c.data()), .len = c.size()}; +} + struct Deleter { void operator()(ddog_crasht_CrashInfo *object) { ddog_crasht_CrashInfo_drop(object); } }; @@ -73,6 +78,44 @@ void add_stacktrace(std::unique_ptr &crashinfo) .symbol_address = 0}; trace.push_back(frame); } + + std::vector build_id = {42}; + std::string filePath = "/usr/share/somewhere"; + // test with normalized + auto elfFrameWithNormalization = ddog_crasht_StackFrame{ + .ip = 42, + .module_base_address = 0, + .names = {.ptr = &names[0], .len = 1}, // just for the test + .normalized_ip = { + .file_offset = 1, + .build_id = to_byte_slice(build_id), + .path = to_slice_c_char(filePath.c_str(), filePath.size()), + .typ = DDOG_CRASHT_NORMALIZED_ADDRESS_TYPES_ELF, + }, + .sp = 0, + .symbol_address = 0, + }; + + trace.push_back(elfFrameWithNormalization); + + // Windows-kind of frame + auto dllFrameWithNormalization = ddog_crasht_StackFrame{ + .ip = 42, + .module_base_address = 0, + .names = {.ptr = &names[0], .len = 1}, // just for the test + .normalized_ip = { + .file_offset = 1, + .build_id = to_byte_slice(build_id), + .age = 21, + .path = to_slice_c_char(filePath.c_str(), filePath.size()), + .typ = DDOG_CRASHT_NORMALIZED_ADDRESS_TYPES_PDB, + }, + .sp = 0, + .symbol_address = 0, + }; + + trace.push_back(dllFrameWithNormalization); + ddog_crasht_Slice_StackFrame trace_slice = {.ptr = trace.data(), .len = trace.size()}; check_result(