Skip to content

Commit 4250409

Browse files
committed
Use range-based datastructure to store modules
1 parent f61c42a commit 4250409

File tree

2 files changed

+24
-14
lines changed

2 files changed

+24
-14
lines changed

datadog-crashtracker/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ thiserror = "1.0"
6464

6565
[target.'cfg(windows)'.dependencies]
6666
windows = { version = "0.59.0", features = ["Win32_System_Diagnostics_Debug", "Win32_System_Diagnostics_ToolHelp", "Win32_System_ErrorReporting", "Win32_System_Kernel", "Win32_System_ProcessStatus", "Win32_System_Registry", "Win32_System_SystemInformation", "Win32_System_SystemServices", "Win32_System_Threading", "Win32_Security"] }
67+
rangemap = "1.6.0"
6768

6869
[dev-dependencies]
6970
criterion = { version = "0.5.1" }

datadog-crashtracker/src/collector_windows/api.rs

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@ use crate::{
1010
use anyhow::{anyhow, Context, Result};
1111
use core::mem::size_of;
1212
use ddcommon::Endpoint;
13+
use rangemap::RangeInclusiveMap;
1314
use serde::{Deserialize, Serialize};
1415
use std::ffi::{c_void, OsString};
1516
use std::fmt;
1617
use std::mem::MaybeUninit;
18+
use std::ops::RangeInclusive;
1719
use std::os::windows::ffi::OsStringExt;
1820
use std::ptr::{addr_of, read_unaligned};
1921
use std::sync::Mutex;
@@ -339,7 +341,7 @@ struct AlignedContext {
339341
fn walk_thread_stack(
340342
process_handle: HANDLE,
341343
thread_id: u32,
342-
modules: &[ModuleInfo],
344+
modules: &RangeInclusiveMap<usize, ModuleInfo>,
343345
) -> Result<StackTrace> {
344346
let mut stacktrace = StackTrace::new_incomplete();
345347
let thread_handle = unsafe { OpenThread(THREAD_ALL_ACCESS, false, thread_id)? };
@@ -403,10 +405,7 @@ fn walk_thread_stack(
403405
frame.sp = Some(format!("{:x}", native_frame.AddrStack.Offset));
404406

405407
// Find the module
406-
let module = modules.iter().find(|module| {
407-
module.base_address <= native_frame.AddrPC.Offset
408-
&& native_frame.AddrPC.Offset < module.base_address + module.size
409-
});
408+
let module = modules.get(&(native_frame.AddrPC.Offset as usize));
410409

411410
if let Some(module) = module {
412411
frame.module_base_address = Some(format!("{:x}", module.base_address));
@@ -417,7 +416,8 @@ fn walk_thread_stack(
417416
frame.path.clone_from(&module.path);
418417

419418
if let Some(pdb_info) = &module.pdb_info {
420-
frame.build_id = Some(format!("{:x}{:x}", pdb_info.signature, pdb_info.age));
419+
// in the backend we expect the AGE to be a uppercase hex number
420+
frame.build_id = Some(format!("{:x}{:X}", pdb_info.signature, pdb_info.age));
421421
frame.build_id_type = Some(BuildIdType::PDB);
422422
frame.file_type = Some(FileType::PE);
423423
}
@@ -432,21 +432,23 @@ fn walk_thread_stack(
432432
Ok(stacktrace)
433433
}
434434

435+
#[derive(Clone, Eq, PartialEq)]
435436
struct ModuleInfo {
436437
base_address: u64,
437438
size: u64,
438439
path: Option<String>,
439440
pdb_info: Option<PdbInfo>,
440441
}
441442

443+
#[derive(Clone, Eq, PartialEq)]
442444
struct PdbInfo {
443445
age: u32,
444446
signature: Guid,
445447
}
446448

447-
fn list_modules(process_handle: HANDLE) -> anyhow::Result<Vec<ModuleInfo>> {
449+
fn list_modules(process_handle: HANDLE) -> anyhow::Result<RangeInclusiveMap<usize, ModuleInfo>> {
448450
// Use EnumProcessModules to get a list of modules
449-
let mut module_infos = Vec::new();
451+
let mut module_infos: RangeInclusiveMap<usize, ModuleInfo> = RangeInclusiveMap::new();
450452

451453
// Get the number of bytes required to store the array of module handles
452454
let mut cb_needed = 0;
@@ -494,12 +496,18 @@ fn list_modules(process_handle: HANDLE) -> anyhow::Result<Vec<ModuleInfo>> {
494496

495497
let module_path = get_module_path(process_handle, hmodule);
496498

497-
module_infos.push(ModuleInfo {
498-
base_address: module_info.lpBaseOfDll as u64,
499-
size: module_info.SizeOfImage as u64,
500-
path: module_path.ok(),
501-
pdb_info: get_pdb_info(process_handle, module_info.lpBaseOfDll as u64).ok(),
502-
});
499+
module_infos.insert(
500+
RangeInclusive::new(
501+
module_info.lpBaseOfDll as usize,
502+
(module_info.lpBaseOfDll as usize).saturating_add(module_info.SizeOfImage as usize),
503+
),
504+
ModuleInfo {
505+
base_address: module_info.lpBaseOfDll as u64,
506+
size: module_info.SizeOfImage as u64,
507+
path: module_path.ok(),
508+
pdb_info: get_pdb_info(process_handle, module_info.lpBaseOfDll as u64).ok(),
509+
},
510+
);
503511
}
504512

505513
Ok(module_infos)
@@ -565,6 +573,7 @@ struct ImageNtHeadersGeneric {
565573

566574
#[repr(C)]
567575
#[derive(Debug)]
576+
#[derive(Clone, Eq, PartialEq)]
568577
struct Guid {
569578
pub data1: u32,
570579
pub data2: u16,

0 commit comments

Comments
 (0)