linux_perf_data/jitdump/
records.rs1use byteorder::{BigEndian, ByteOrder, LittleEndian};
2use linux_perf_event_reader::{Endianness, RawData};
3
4use super::record::JitDumpRecordHeader;
5
6#[derive(Debug, Clone)]
10pub struct JitCodeLoadRecord<'a> {
11 pub pid: u32,
13 pub tid: u32,
15 pub vma: u64,
17 pub code_addr: u64,
19 pub code_index: u64,
21 pub function_name: RawData<'a>,
23 pub code_bytes: RawData<'a>,
26}
27
28impl<'a> JitCodeLoadRecord<'a> {
29 pub const NAME_OFFSET_FROM_RECORD_START: usize =
32 JitDumpRecordHeader::SIZE + 4 + 4 + 8 + 8 + 8 + 8;
33
34 pub fn parse(endian: Endianness, data: RawData<'a>) -> Result<Self, std::io::Error> {
35 match endian {
36 Endianness::LittleEndian => Self::parse_impl::<LittleEndian>(data),
37 Endianness::BigEndian => Self::parse_impl::<BigEndian>(data),
38 }
39 }
40
41 pub fn parse_impl<O: ByteOrder>(data: RawData<'a>) -> Result<Self, std::io::Error> {
42 let mut cur = data;
43 let pid = cur.read_u32::<O>()?;
44 let tid = cur.read_u32::<O>()?;
45 let vma = cur.read_u64::<O>()?;
46 let code_addr = cur.read_u64::<O>()?;
47 let code_size = cur.read_u64::<O>()?;
48 let code_index = cur.read_u64::<O>()?;
49 let function_name = cur.read_string().ok_or(std::io::ErrorKind::UnexpectedEof)?;
50 let code_bytes = cur.split_off_prefix(code_size as usize)?;
51 Ok(Self {
52 pid,
53 tid,
54 vma,
55 code_addr,
56 code_index,
57 function_name,
58 code_bytes,
59 })
60 }
61
62 pub fn code_bytes_offset_from_record_header_start(&self) -> usize {
69 JitDumpRecordHeader::SIZE + 4 + 4 + 8 + 8 + 8 + 8 + self.function_name.len() + 1
70 }
71}
72
73#[derive(Debug, Clone)]
75pub struct JitCodeMoveRecord {
76 pub pid: u32,
78 pub tid: u32,
80 pub vma: u64,
82 pub old_code_addr: u64,
84 pub new_code_addr: u64,
86 pub code_size: u64,
88 pub code_index: u64,
90}
91
92impl JitCodeMoveRecord {
93 pub fn parse(endian: Endianness, data: RawData) -> Result<Self, std::io::Error> {
94 match endian {
95 Endianness::LittleEndian => Self::parse_impl::<LittleEndian>(data),
96 Endianness::BigEndian => Self::parse_impl::<BigEndian>(data),
97 }
98 }
99
100 pub fn parse_impl<O: ByteOrder>(data: RawData) -> Result<Self, std::io::Error> {
101 let mut cur = data;
102 let pid = cur.read_u32::<O>()?;
103 let tid = cur.read_u32::<O>()?;
104 let vma = cur.read_u64::<O>()?;
105 let old_code_addr = cur.read_u64::<O>()?;
106 let new_code_addr = cur.read_u64::<O>()?;
107 let code_size = cur.read_u64::<O>()?;
108 let code_index = cur.read_u64::<O>()?;
109 Ok(Self {
110 pid,
111 tid,
112 vma,
113 old_code_addr,
114 new_code_addr,
115 code_size,
116 code_index,
117 })
118 }
119}
120
121#[derive(Debug, Clone)]
123pub struct JitCodeDebugInfoRecord<'a> {
124 pub code_addr: u64,
126 pub entries: Vec<JitCodeDebugInfoEntry<'a>>,
128}
129
130#[derive(Debug, Clone)]
136pub struct JitCodeDebugInfoEntry<'a> {
137 pub code_addr: u64,
141 pub line: u32,
143 pub column: u32,
145 pub file_path: RawData<'a>,
147}
148
149impl<'a> JitCodeDebugInfoRecord<'a> {
150 pub fn parse(endian: Endianness, data: RawData<'a>) -> Result<Self, std::io::Error> {
151 match endian {
152 Endianness::LittleEndian => Self::parse_impl::<LittleEndian>(data),
153 Endianness::BigEndian => Self::parse_impl::<BigEndian>(data),
154 }
155 }
156
157 pub fn parse_impl<O: ByteOrder>(data: RawData<'a>) -> Result<Self, std::io::Error> {
158 let mut cur = data;
159 let code_addr = cur.read_u64::<O>()?;
160 let nr_entry = cur.read_u64::<O>()?;
161 let mut entries = Vec::with_capacity(nr_entry as usize);
162 for _ in 0..nr_entry {
163 let code_addr = cur.read_u64::<O>()?;
164 let line = cur.read_u32::<O>()?;
165 let column = cur.read_u32::<O>()?;
166 let file_path = cur.read_string().ok_or(std::io::ErrorKind::UnexpectedEof)?;
167 entries.push(JitCodeDebugInfoEntry {
168 code_addr,
169 line,
170 column,
171 file_path,
172 });
173 }
174
175 Ok(Self { code_addr, entries })
176 }
177
178 pub fn lookup(&self, addr: u64) -> Option<&JitCodeDebugInfoEntry> {
179 let index = match self
180 .entries
181 .binary_search_by_key(&addr, |entry| entry.code_addr)
182 {
183 Ok(i) => i,
184 Err(0) => return None,
185 Err(i) => i - 1,
186 };
187 Some(&self.entries[index])
188 }
189}
190
191#[derive(Debug, Clone)]
193pub struct JitCodeUnwindingInfoRecord<'a> {
194 pub mapped_size: u64,
196 pub eh_frame_hdr: RawData<'a>,
198 pub eh_frame: RawData<'a>,
200}
201
202impl<'a> JitCodeUnwindingInfoRecord<'a> {
203 pub fn parse(endian: Endianness, data: RawData<'a>) -> Result<Self, std::io::Error> {
204 match endian {
205 Endianness::LittleEndian => Self::parse_impl::<LittleEndian>(data),
206 Endianness::BigEndian => Self::parse_impl::<BigEndian>(data),
207 }
208 }
209
210 pub fn parse_impl<O: ByteOrder>(data: RawData<'a>) -> Result<Self, std::io::Error> {
211 let mut cur = data;
212 let unwind_data_size = cur.read_u64::<O>()?;
213 let eh_frame_hdr_size = cur.read_u64::<O>()? as usize;
214 let mapped_size = cur.read_u64::<O>()?;
215 let mut unwind_data = cur.split_off_prefix(unwind_data_size as usize)?;
216 let eh_frame_hdr = unwind_data.split_off_prefix(eh_frame_hdr_size)?;
217 let eh_frame = unwind_data;
218 Ok(Self {
219 mapped_size,
220 eh_frame_hdr,
221 eh_frame,
222 })
223 }
224}