fxprof_processed_profile/
global_lib_table.rs1use std::collections::BTreeSet;
2use std::sync::Arc;
3
4use serde::ser::{Serialize, Serializer};
5
6use crate::fast_hash_map::FastHashMap;
7use crate::{LibraryInfo, SymbolTable};
8
9#[derive(Debug)]
10pub struct GlobalLibTable {
11 all_libs: Vec<LibraryInfo>, used_libs: Vec<LibraryHandle>, lib_map: FastHashMap<LibraryInfo, LibraryHandle>,
17 used_lib_map: FastHashMap<LibraryHandle, GlobalLibIndex>,
18 used_libs_seen_rvas: Vec<BTreeSet<u32>>,
24}
25
26impl GlobalLibTable {
27 pub fn new() -> Self {
28 Self {
29 all_libs: Vec::new(),
30 used_libs: Vec::new(),
31 lib_map: FastHashMap::default(),
32 used_lib_map: FastHashMap::default(),
33 used_libs_seen_rvas: Vec::new(),
34 }
35 }
36
37 pub fn handle_for_lib(&mut self, lib: LibraryInfo) -> LibraryHandle {
38 let all_libs = &mut self.all_libs;
39 *self.lib_map.entry(lib.clone()).or_insert_with(|| {
40 let handle = LibraryHandle(all_libs.len());
41 all_libs.push(lib);
42 handle
43 })
44 }
45
46 pub fn set_lib_symbol_table(&mut self, library: LibraryHandle, symbol_table: Arc<SymbolTable>) {
47 self.all_libs[library.0].symbol_table = Some(symbol_table);
48 }
49
50 pub fn index_for_used_lib(&mut self, lib_handle: LibraryHandle) -> GlobalLibIndex {
51 let used_libs = &mut self.used_libs;
52 *self.used_lib_map.entry(lib_handle).or_insert_with(|| {
53 let index = GlobalLibIndex(used_libs.len());
54 used_libs.push(lib_handle);
55 self.used_libs_seen_rvas.push(BTreeSet::new());
56 index
57 })
58 }
59
60 pub fn get_lib(&self, index: GlobalLibIndex) -> Option<&LibraryInfo> {
61 let handle = self.used_libs.get(index.0)?;
62 self.all_libs.get(handle.0)
63 }
64
65 pub fn add_lib_used_rva(&mut self, index: GlobalLibIndex, address: u32) {
66 self.used_libs_seen_rvas[index.0].insert(address);
67 }
68
69 pub fn lib_used_rva_iter(&self) -> UsedLibraryAddressesIterator {
70 UsedLibraryAddressesIterator {
71 next_used_lib_index: 0,
72 global_lib_table: self,
73 }
74 }
75}
76
77impl Serialize for GlobalLibTable {
78 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
79 serializer.collect_seq(self.used_libs.iter().map(|handle| &self.all_libs[handle.0]))
80 }
81}
82
83#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash)]
86pub struct GlobalLibIndex(usize);
87
88impl Serialize for GlobalLibIndex {
89 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
90 serializer.serialize_u32(self.0 as u32)
91 }
92}
93
94#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash)]
96pub struct LibraryHandle(usize);
97
98pub struct UsedLibraryAddressesIterator<'a> {
99 next_used_lib_index: usize,
100 global_lib_table: &'a GlobalLibTable,
101}
102
103impl<'a> Iterator for UsedLibraryAddressesIterator<'a> {
104 type Item = (&'a LibraryInfo, &'a BTreeSet<u32>);
105
106 fn next(&mut self) -> Option<Self::Item> {
107 let rvas = self
108 .global_lib_table
109 .used_libs_seen_rvas
110 .get(self.next_used_lib_index)?;
111
112 let lib_handle = self.global_lib_table.used_libs[self.next_used_lib_index];
113 let info = &self.global_lib_table.all_libs[lib_handle.0];
114
115 self.next_used_lib_index += 1;
116
117 Some((info, rvas))
118 }
119}