@@ -5,48 +5,153 @@ use core::{
55use serde:: { Deserialize , Serialize } ;
66use std:: { hash:: DefaultHasher , ops:: Range } ;
77
8- /// Unwind data for a single module .
8+ /// A versioned enum for `UnwindData` to allow for future extensions while maintaining backward compatibility .
99#[ derive( Serialize , Deserialize ) ]
10- pub struct UnwindData {
11- pub path : String ,
10+ pub enum UnwindData {
11+ V1 ( UnwindDataV1 ) ,
12+ V2 ( UnwindDataV2 ) ,
13+ }
1214
13- pub avma_range : Range < u64 > ,
14- pub base_avma : u64 ,
15- pub eh_frame_hdr : Vec < u8 > ,
16- pub eh_frame_hdr_svma : Range < u64 > ,
15+ impl UnwindData {
16+ pub fn path ( & self ) -> & str {
17+ match self {
18+ UnwindData :: V1 ( data) => & data. path ,
19+ UnwindData :: V2 ( data) => & data. path ,
20+ }
21+ }
1722
18- pub eh_frame : Vec < u8 > ,
19- pub eh_frame_svma : Range < u64 > ,
23+ pub fn avma_range ( & self ) -> & Range < u64 > {
24+ match self {
25+ UnwindData :: V1 ( data) => & data. avma_range ,
26+ UnwindData :: V2 ( data) => & data. avma_range ,
27+ }
28+ }
2029
21- #[ serde( default ) ]
22- pub base_svma : u64 ,
30+ pub fn base_avma ( & self ) -> u64 {
31+ match self {
32+ UnwindData :: V1 ( data) => data. base_avma ,
33+ UnwindData :: V2 ( data) => data. base_avma ,
34+ }
35+ }
36+
37+ pub fn base_svma ( & self ) -> u64 {
38+ match self {
39+ UnwindData :: V1 ( _) => 0 ,
40+ UnwindData :: V2 ( data) => data. base_svma ,
41+ }
42+ }
43+
44+ pub fn eh_frame_hdr ( & self ) -> & Vec < u8 > {
45+ match self {
46+ UnwindData :: V1 ( data) => & data. eh_frame_hdr ,
47+ UnwindData :: V2 ( data) => & data. eh_frame_hdr ,
48+ }
49+ }
50+
51+ pub fn eh_frame_hdr_svma ( & self ) -> & Range < u64 > {
52+ match self {
53+ UnwindData :: V1 ( data) => & data. eh_frame_hdr_svma ,
54+ UnwindData :: V2 ( data) => & data. eh_frame_hdr_svma ,
55+ }
56+ }
57+
58+ pub fn eh_frame ( & self ) -> & Vec < u8 > {
59+ match self {
60+ UnwindData :: V1 ( data) => & data. eh_frame ,
61+ UnwindData :: V2 ( data) => & data. eh_frame ,
62+ }
63+ }
64+
65+ pub fn eh_frame_svma ( & self ) -> & Range < u64 > {
66+ match self {
67+ UnwindData :: V1 ( data) => & data. eh_frame_svma ,
68+ UnwindData :: V2 ( data) => & data. eh_frame_svma ,
69+ }
70+ }
71+
72+ pub fn save_to < P : AsRef < std:: path:: Path > > ( & self , folder : P , pid : i32 ) -> anyhow:: Result < ( ) > {
73+ let unwind_data_path = folder. as_ref ( ) . join ( format ! (
74+ "{}_{:x}_{:x}.unwind2" ,
75+ pid,
76+ self . avma_range( ) . start,
77+ self . avma_range( ) . end
78+ ) ) ;
79+ self . to_file ( unwind_data_path) ?;
80+
81+ Ok ( ( ) )
82+ }
83+
84+ pub fn to_file < P : AsRef < std:: path:: Path > > ( & self , path : P ) -> anyhow:: Result < ( ) > {
85+ if let Ok ( true ) = std:: fs:: exists ( path. as_ref ( ) ) {
86+ log:: warn!(
87+ "{} already exists, file will be truncated" ,
88+ path. as_ref( ) . display( )
89+ ) ;
90+ log:: warn!( "{} {:x?}" , self . path( ) , self . avma_range( ) ) ;
91+ }
92+
93+ let mut writer = std:: fs:: File :: create ( path. as_ref ( ) ) ?;
94+ bincode:: serialize_into ( & mut writer, self ) ?;
95+ Ok ( ( ) )
96+ }
2397}
2498
2599impl Debug for UnwindData {
26100 fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
27101 let eh_frame_hdr_hash = {
28102 let mut hasher = DefaultHasher :: new ( ) ;
29- self . eh_frame_hdr . hash ( & mut hasher) ;
103+ self . eh_frame_hdr ( ) . hash ( & mut hasher) ;
30104 hasher. finish ( )
31105 } ;
32106 let eh_frame_hash = {
33107 let mut hasher = DefaultHasher :: new ( ) ;
34- self . eh_frame . hash ( & mut hasher) ;
108+ self . eh_frame ( ) . hash ( & mut hasher) ;
35109 hasher. finish ( )
36110 } ;
37111
38112 f. debug_struct ( "UnwindData" )
39- . field ( "path" , & self . path )
40- . field ( "avma_range" , & format_args ! ( "{:x?}" , self . avma_range) )
41- . field ( "base_avma" , & format_args ! ( "{:x}" , self . base_avma) )
42- . field ( "base_svma" , & format_args ! ( "{:x}" , self . base_svma) )
113+ . field ( "path" , & self . path ( ) )
114+ . field ( "avma_range" , & format_args ! ( "{:x?}" , self . avma_range( ) ) )
115+ . field ( "base_avma" , & format_args ! ( "{:x}" , self . base_avma( ) ) )
116+ . field ( "base_svma" , & format_args ! ( "{:x}" , self . base_svma( ) ) )
43117 . field (
44118 "eh_frame_hdr_svma" ,
45- & format_args ! ( "{:x?}" , self . eh_frame_hdr_svma) ,
119+ & format_args ! ( "{:x?}" , self . eh_frame_hdr_svma( ) ) ,
46120 )
47121 . field ( "eh_frame_hdr_hash" , & format_args ! ( "{eh_frame_hdr_hash:x}" ) )
48122 . field ( "eh_frame_hash" , & format_args ! ( "{eh_frame_hash:x}" ) )
49- . field ( "eh_frame_svma" , & format_args ! ( "{:x?}" , self . eh_frame_svma) )
123+ . field (
124+ "eh_frame_svma" ,
125+ & format_args ! ( "{:x?}" , self . eh_frame_svma( ) ) ,
126+ )
50127 . finish ( )
51128 }
52129}
130+
131+ #[ derive( Serialize , Deserialize ) ]
132+ pub struct UnwindDataV1 {
133+ pub path : String ,
134+
135+ pub avma_range : Range < u64 > ,
136+ pub base_avma : u64 ,
137+ pub eh_frame_hdr : Vec < u8 > ,
138+ pub eh_frame_hdr_svma : Range < u64 > ,
139+
140+ pub eh_frame : Vec < u8 > ,
141+ pub eh_frame_svma : Range < u64 > ,
142+ }
143+
144+ #[ derive( Serialize , Deserialize , Clone ) ]
145+ pub struct UnwindDataV2 {
146+ pub path : String ,
147+
148+ pub avma_range : Range < u64 > ,
149+ pub base_avma : u64 ,
150+ pub base_svma : u64 ,
151+
152+ pub eh_frame_hdr : Vec < u8 > ,
153+ pub eh_frame_hdr_svma : Range < u64 > ,
154+
155+ pub eh_frame : Vec < u8 > ,
156+ pub eh_frame_svma : Range < u64 > ,
157+ }
0 commit comments