@@ -84,10 +84,12 @@ pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext<'_>) -> Result
84
84
let ip = context. ip ;
85
85
86
86
if !USING_SJLJ_EXCEPTIONS {
87
+ // read the callsite table
87
88
while reader. ptr < action_table {
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 ( ) ;
89
+ // these are offsets rather than pointers;
90
+ let cs_start = read_encoded_offset ( & mut reader, call_site_encoding) ?;
91
+ let cs_len = read_encoded_offset ( & mut reader, call_site_encoding) ?;
92
+ let cs_lpad = read_encoded_offset ( & mut reader, call_site_encoding) ?;
91
93
let cs_action_entry = reader. read_uleb128 ( ) ;
92
94
// Callsite table is sorted by cs_start, so if we've passed the ip, we
93
95
// may stop searching.
@@ -161,23 +163,24 @@ fn round_up(unrounded: usize, align: usize) -> Result<usize, ()> {
161
163
if align. is_power_of_two ( ) { Ok ( ( unrounded + align - 1 ) & !( align - 1 ) ) } else { Err ( ( ) ) }
162
164
}
163
165
164
- unsafe fn read_encoded_pointer (
165
- reader : & mut DwarfReader ,
166
- context : & EHContext < ' _ > ,
167
- encoding : u8 ,
168
- ) -> Result < * const u8 , ( ) > {
169
- if encoding == DW_EH_PE_omit {
166
+ /// Read a offset (`usize`) from `reader` whose encoding is described by `encoding`.
167
+ ///
168
+ /// `encoding` must be a [DWARF Exception Header Encoding as described by the LSB spec][LSB-dwarf-ext].
169
+ /// In addition the upper ("application") part must be zero.
170
+ ///
171
+ /// # Errors
172
+ /// Returns `Err` if `encoding`
173
+ /// * is not a valid DWARF Exception Header Encoding,
174
+ /// * is `DW_EH_PE_omit`, or
175
+ /// * has a non-zero application part.
176
+ ///
177
+ /// [LSB-dwarf-ext]: https://refspecs.linuxfoundation.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/dwarfext.html
178
+ unsafe fn read_encoded_offset ( reader : & mut DwarfReader , encoding : u8 ) -> Result < usize , ( ) > {
179
+ if encoding == DW_EH_PE_omit || encoding & 0xF0 != 0 {
170
180
return Err ( ( ) ) ;
171
181
}
172
-
173
- // DW_EH_PE_aligned implies it's an absolute pointer value
174
- if encoding == DW_EH_PE_aligned {
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 > ( ) ) ;
178
- }
179
-
180
- let mut result = match encoding & 0x0F {
182
+ let result = match encoding & 0x0F {
183
+ // despite the name, LLVM also uses absptr for offsets instead of pointers
181
184
DW_EH_PE_absptr => reader. read :: < usize > ( ) ,
182
185
DW_EH_PE_uleb128 => reader. read_uleb128 ( ) as usize ,
183
186
DW_EH_PE_udata2 => reader. read :: < u16 > ( ) as usize ,
@@ -189,28 +192,66 @@ unsafe fn read_encoded_pointer(
189
192
DW_EH_PE_sdata8 => reader. read :: < i64 > ( ) as usize ,
190
193
_ => return Err ( ( ) ) ,
191
194
} ;
195
+ Ok ( result)
196
+ }
192
197
193
- result += match encoding & 0x70 {
194
- DW_EH_PE_absptr => 0 ,
198
+ /// Read a pointer from `reader` whose encoding is described by `encoding`.
199
+ ///
200
+ /// `encoding` must be a [DWARF Exception Header Encoding as described by the LSB spec][LSB-dwarf-ext].
201
+ ///
202
+ /// # Errors
203
+ /// Returns `Err` if `encoding`
204
+ /// * is not a valid DWARF Exception Header Encoding,
205
+ /// * is `DW_EH_PE_omit`, or
206
+ /// * combines `DW_EH_PE_absptr` or `DW_EH_PE_aligned` application part with an integer encoding
207
+ /// (not `DW_EH_PE_absptr`) in the value format part.
208
+ ///
209
+ /// [LSB-dwarf-ext]: https://refspecs.linuxfoundation.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/dwarfext.html
210
+ unsafe fn read_encoded_pointer (
211
+ reader : & mut DwarfReader ,
212
+ context : & EHContext < ' _ > ,
213
+ encoding : u8 ,
214
+ ) -> Result < * const u8 , ( ) > {
215
+ if encoding == DW_EH_PE_omit {
216
+ return Err ( ( ) ) ;
217
+ }
218
+
219
+ let base_ptr = match encoding & 0x70 {
220
+ DW_EH_PE_absptr => core:: ptr:: null ( ) ,
195
221
// relative to address of the encoded value, despite the name
196
- DW_EH_PE_pcrel => reader. ptr . expose_addr ( ) ,
222
+ DW_EH_PE_pcrel => reader. ptr ,
197
223
DW_EH_PE_funcrel => {
198
224
if context. func_start . is_null ( ) {
199
225
return Err ( ( ) ) ;
200
226
}
201
- context. func_start . expose_addr ( )
227
+ context. func_start
228
+ }
229
+ DW_EH_PE_textrel => ( * context. get_text_start ) ( ) ,
230
+ DW_EH_PE_datarel => ( * context. get_data_start ) ( ) ,
231
+ // aligned means the value is aligned to the size of a pointer
232
+ DW_EH_PE_aligned => {
233
+ reader. ptr =
234
+ reader. ptr . with_addr ( round_up ( reader. ptr . addr ( ) , mem:: size_of :: < * const u8 > ( ) ) ?) ;
235
+ core:: ptr:: null ( )
202
236
}
203
- DW_EH_PE_textrel => ( * context. get_text_start ) ( ) . expose_addr ( ) ,
204
- DW_EH_PE_datarel => ( * context. get_data_start ) ( ) . expose_addr ( ) ,
205
237
_ => return Err ( ( ) ) ,
206
238
} ;
207
239
208
- // FIXME(strict provenance)
209
- let mut result: * const u8 = ptr:: from_exposed_addr :: < u8 > ( result) ;
240
+ let mut ptr = if base_ptr. is_null ( ) {
241
+ // any value encoding other than absptr would be nonsensical here;
242
+ // there would be no source of pointer provenance
243
+ if encoding & 0x0F != DW_EH_PE_absptr {
244
+ return Err ( ( ) ) ;
245
+ }
246
+ reader. read :: < * const u8 > ( )
247
+ } else {
248
+ let offset = read_encoded_offset ( reader, encoding & 0x0F ) ?;
249
+ base_ptr. wrapping_add ( offset)
250
+ } ;
210
251
211
252
if encoding & DW_EH_PE_indirect != 0 {
212
- result = * ( result . cast :: < * const u8 > ( ) ) ;
253
+ ptr = * ( ptr . cast :: < * const u8 > ( ) ) ;
213
254
}
214
255
215
- Ok ( result )
256
+ Ok ( ptr )
216
257
}
0 commit comments