1
1
//! Parsing of GCC-style Language-Specific Data Area (LSDA)
2
2
//! For details see:
3
3
//! * <https://refspecs.linuxfoundation.org/LSB_3.0.0/LSB-PDA/LSB-PDA/ehframechpt.html>
4
+ //! * <https://refspecs.linuxfoundation.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/dwarfext.html>
4
5
//! * <https://itanium-cxx-abi.github.io/cxx-abi/exceptions.pdf>
5
6
//! * <https://www.airs.com/blog/archives/460>
6
7
//! * <https://www.airs.com/blog/archives/464>
@@ -37,17 +38,19 @@ pub const DW_EH_PE_indirect: u8 = 0x80;
37
38
38
39
#[ derive( Copy , Clone ) ]
39
40
pub struct EHContext < ' a > {
40
- pub ip : usize , // Current instruction pointer
41
- pub func_start : usize , // Address of the current function
42
- pub get_text_start : & ' a dyn Fn ( ) -> usize , // Get address of the code section
43
- pub get_data_start : & ' a dyn Fn ( ) -> usize , // Get address of the data section
41
+ pub ip : * const u8 , // Current instruction pointer
42
+ pub func_start : * const u8 , // Pointer to the current function
43
+ pub get_text_start : & ' a dyn Fn ( ) -> * const u8 , // Get pointer to the code section
44
+ pub get_data_start : & ' a dyn Fn ( ) -> * const u8 , // Get pointer to the data section
44
45
}
45
46
47
+ /// Landing pad.
48
+ type LPad = * const u8 ;
46
49
pub enum EHAction {
47
50
None ,
48
- Cleanup ( usize ) ,
49
- Catch ( usize ) ,
50
- Filter ( usize ) ,
51
+ Cleanup ( LPad ) ,
52
+ Catch ( LPad ) ,
53
+ Filter ( LPad ) ,
51
54
Terminate ,
52
55
}
53
56
@@ -82,21 +85,21 @@ pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext<'_>) -> Result
82
85
83
86
if !USING_SJLJ_EXCEPTIONS {
84
87
while reader. ptr < action_table {
85
- let cs_start = read_encoded_pointer ( & mut reader, context, call_site_encoding) ?;
86
- let cs_len = read_encoded_pointer ( & mut reader, context, call_site_encoding) ?;
87
- let cs_lpad = read_encoded_pointer ( & mut reader, context, call_site_encoding) ?;
88
+ let cs_start = read_encoded_pointer ( & mut reader, context, call_site_encoding) ?. addr ( ) ;
89
+ let cs_len = read_encoded_pointer ( & mut reader, context, call_site_encoding) ?. addr ( ) ;
90
+ let cs_lpad = read_encoded_pointer ( & mut reader, context, call_site_encoding) ?. addr ( ) ;
88
91
let cs_action_entry = reader. read_uleb128 ( ) ;
89
92
// Callsite table is sorted by cs_start, so if we've passed the ip, we
90
93
// may stop searching.
91
- if ip < func_start + cs_start {
94
+ if ip < func_start. wrapping_add ( cs_start) {
92
95
break ;
93
96
}
94
- if ip < func_start + cs_start + cs_len {
97
+ if ip < func_start. wrapping_add ( cs_start + cs_len) {
95
98
if cs_lpad == 0 {
96
99
return Ok ( EHAction :: None ) ;
97
100
} else {
98
- let lpad = lpad_base + cs_lpad;
99
- return Ok ( interpret_cs_action ( action_table as * mut u8 , cs_action_entry, lpad) ) ;
101
+ let lpad = lpad_base. wrapping_add ( cs_lpad) ;
102
+ return Ok ( interpret_cs_action ( action_table, cs_action_entry, lpad) ) ;
100
103
}
101
104
}
102
105
}
@@ -106,30 +109,31 @@ pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext<'_>) -> Result
106
109
// SjLj version:
107
110
// The "IP" is an index into the call-site table, with two exceptions:
108
111
// -1 means 'no-action', and 0 means 'terminate'.
109
- match ip as isize {
112
+ match ip. addr ( ) as isize {
110
113
-1 => return Ok ( EHAction :: None ) ,
111
114
0 => return Ok ( EHAction :: Terminate ) ,
112
115
_ => ( ) ,
113
116
}
114
- let mut idx = ip;
117
+ let mut idx = ip. addr ( ) ;
115
118
loop {
116
119
let cs_lpad = reader. read_uleb128 ( ) ;
117
120
let cs_action_entry = reader. read_uleb128 ( ) ;
118
121
idx -= 1 ;
119
122
if idx == 0 {
120
123
// Can never have null landing pad for sjlj -- that would have
121
124
// been indicated by a -1 call site index.
122
- let lpad = ( cs_lpad + 1 ) as usize ;
123
- return Ok ( interpret_cs_action ( action_table as * mut u8 , cs_action_entry, lpad) ) ;
125
+ // FIXME(strict provenance)
126
+ let lpad = ptr:: from_exposed_addr ( ( cs_lpad + 1 ) as usize ) ;
127
+ return Ok ( interpret_cs_action ( action_table, cs_action_entry, lpad) ) ;
124
128
}
125
129
}
126
130
}
127
131
}
128
132
129
133
unsafe fn interpret_cs_action (
130
- action_table : * mut u8 ,
134
+ action_table : * const u8 ,
131
135
cs_action_entry : u64 ,
132
- lpad : usize ,
136
+ lpad : LPad ,
133
137
) -> EHAction {
134
138
if cs_action_entry == 0 {
135
139
// If cs_action_entry is 0 then this is a cleanup (Drop::drop). We run these
@@ -138,7 +142,7 @@ unsafe fn interpret_cs_action(
138
142
} else {
139
143
// If lpad != 0 and cs_action_entry != 0, we have to check ttype_index.
140
144
// If ttype_index == 0 under the condition, we take cleanup action.
141
- let action_record = ( action_table as * mut u8 ) . offset ( cs_action_entry as isize - 1 ) ;
145
+ let action_record = action_table. offset ( cs_action_entry as isize - 1 ) ;
142
146
let mut action_reader = DwarfReader :: new ( action_record) ;
143
147
let ttype_index = action_reader. read_sleb128 ( ) ;
144
148
if ttype_index == 0 {
@@ -161,15 +165,16 @@ unsafe fn read_encoded_pointer(
161
165
reader : & mut DwarfReader ,
162
166
context : & EHContext < ' _ > ,
163
167
encoding : u8 ,
164
- ) -> Result < usize , ( ) > {
168
+ ) -> Result < * const u8 , ( ) > {
165
169
if encoding == DW_EH_PE_omit {
166
170
return Err ( ( ) ) ;
167
171
}
168
172
169
173
// DW_EH_PE_aligned implies it's an absolute pointer value
170
174
if encoding == DW_EH_PE_aligned {
171
- reader. ptr = reader. ptr . with_addr ( round_up ( reader. ptr . addr ( ) , mem:: size_of :: < usize > ( ) ) ?) ;
172
- return Ok ( reader. read :: < usize > ( ) ) ;
175
+ reader. ptr =
176
+ reader. ptr . with_addr ( round_up ( reader. ptr . addr ( ) , mem:: size_of :: < * const u8 > ( ) ) ?) ;
177
+ return Ok ( reader. read :: < * const u8 > ( ) ) ;
173
178
}
174
179
175
180
let mut result = match encoding & 0x0F {
@@ -190,18 +195,21 @@ unsafe fn read_encoded_pointer(
190
195
// relative to address of the encoded value, despite the name
191
196
DW_EH_PE_pcrel => reader. ptr . expose_addr ( ) ,
192
197
DW_EH_PE_funcrel => {
193
- if context. func_start == 0 {
198
+ if context. func_start . is_null ( ) {
194
199
return Err ( ( ) ) ;
195
200
}
196
- context. func_start
201
+ context. func_start . expose_addr ( )
197
202
}
198
- DW_EH_PE_textrel => ( * context. get_text_start ) ( ) ,
199
- DW_EH_PE_datarel => ( * context. get_data_start ) ( ) ,
203
+ DW_EH_PE_textrel => ( * context. get_text_start ) ( ) . expose_addr ( ) ,
204
+ DW_EH_PE_datarel => ( * context. get_data_start ) ( ) . expose_addr ( ) ,
200
205
_ => return Err ( ( ) ) ,
201
206
} ;
202
207
208
+ // FIXME(strict provenance)
209
+ let mut result: * const u8 = ptr:: from_exposed_addr :: < u8 > ( result) ;
210
+
203
211
if encoding & DW_EH_PE_indirect != 0 {
204
- result = * ptr :: from_exposed_addr :: < usize > ( result ) ;
212
+ result = * ( result . cast :: < * const u8 > ( ) ) ;
205
213
}
206
214
207
215
Ok ( result)
0 commit comments