@@ -98,44 +98,45 @@ pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext<'_>) -> Result
9898 let func_start = context. func_start ;
9999 let mut reader = DwarfReader :: new ( lsda) ;
100100
101- let lpad_base = unsafe {
102- let lp_start_encoding = reader . read :: < u8 > ( ) ;
101+ let lpad_start_encoding = unsafe { reader . read :: < u8 > ( ) } ;
102+ log ! ( "(pers) Read LP start encoding {lpad_start_encoding:?}" ) ;
103103
104- log ! ( "(pers) Read LP start encoding {lp_start_encoding:?}" ) ;
104+ let lpad_base = unsafe {
105105 // base address for landing pad offsets
106- if lp_start_encoding != DW_EH_PE_omit {
107- read_encoded_pointer ( & mut reader, context, lp_start_encoding ) ?
106+ if lpad_start_encoding != DW_EH_PE_omit {
107+ read_encoded_pointer ( & mut reader, context, lpad_start_encoding ) ?
108108 } else {
109109 log ! ( "(pers) (is omit)" ) ;
110110 func_start
111111 }
112112 } ;
113113 log ! ( "(pers) read landingpad base: {lpad_base:?}" ) ;
114114
115- let ttype_encoding = unsafe { reader. read :: < u8 > ( ) } ;
116- log ! ( "(pers) read ttype encoding: {ttype_encoding :?}" ) ;
115+ let types_table_encoding = unsafe { reader. read :: < u8 > ( ) } ;
116+ log ! ( "(pers) read ttype encoding: {types_table_encoding :?}" ) ;
117117
118- // If no value for type_table_encoding was given it means that there's no
119- // type_table , therefore we can't possibly use this lpad.
120- if ttype_encoding == DW_EH_PE_omit {
118+ // If no value for types_table_encoding was given it means that there's no
119+ // types_table , therefore we can't possibly use this lpad.
120+ if types_table_encoding == DW_EH_PE_omit {
121121 log ! ( "(pers) ttype is omit, returning None" ) ;
122122 return Ok ( EHAction :: None ) ;
123123 }
124124
125- let class_info = unsafe {
126- let offset = reader. read_uleb128 ( ) ;
127- log ! ( "(pers) read class_info offset {offset:?}" ) ;
128- reader. ptr . wrapping_add ( offset as _ )
125+ let types_table_base_offset = unsafe { reader. read_uleb128 ( ) } ;
126+
127+ let types_table_base = unsafe {
128+ log ! ( "(pers) read class_info offset {types_table_base_offset:?}" ) ;
129+ reader. ptr . wrapping_add ( types_table_base_offset as _ )
129130 } ;
130- log ! ( "(pers) read class_info sits at offset {class_info :?}" ) ;
131+ log ! ( "(pers) read class_info sits at offset {types_table_base :?}" ) ;
131132
132- let call_site_encoding = unsafe { reader. read :: < u8 > ( ) } ;
133- log ! ( "(pers) read call_site_encoding is {call_site_encoding :?}" ) ;
133+ let call_site_table_encoding = unsafe { reader. read :: < u8 > ( ) } ;
134+ log ! ( "(pers) read call_site_encoding is {call_site_table_encoding :?}" ) ;
134135
136+ let call_site_table_size = unsafe { reader. read_uleb128 ( ) } ;
135137 let action_table = unsafe {
136- let call_site_table_length = reader. read_uleb128 ( ) ;
137- log ! ( "(pers) read call_site has length {call_site_table_length:?}" ) ;
138- reader. ptr . wrapping_add ( call_site_table_length as usize )
138+ log ! ( "(pers) read call_site has length {call_site_table_size:?}" ) ;
139+ reader. ptr . wrapping_add ( call_site_table_size as usize )
139140 } ;
140141
141142 log ! ( "(pers) action table sits at offset {action_table:?}" ) ;
@@ -144,79 +145,97 @@ pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext<'_>) -> Result
144145 if !USING_SJLJ_EXCEPTIONS {
145146 // read the callsite table
146147 while reader. ptr < action_table {
148+ let call_site_record_reader = & mut reader;
147149 unsafe {
148- // these are offsets rather than pointers;
149- let cs_start = read_encoded_offset ( & mut reader, call_site_encoding) ?;
150- let cs_len = read_encoded_offset ( & mut reader, call_site_encoding) ?;
151- let cs_lpad = read_encoded_offset ( & mut reader, call_site_encoding) ?;
152- let cs_action_entry = reader. read_uleb128 ( ) ;
153-
154- log ! ( "(pers) read cs_start is {cs_start:?}" ) ;
155- log ! ( "(pers) read cs_len is {cs_len:?}" ) ;
156- log ! ( "(pers) read cs_lpad is {cs_lpad:?}" ) ;
157- log ! ( "(pers) read cs_ae is {cs_action_entry:?}" ) ;
150+ // Offset of the call site relative to the previous call site, counted in number of 16-byte bundles
151+ let call_site_start =
152+ read_encoded_offset ( call_site_record_reader, call_site_table_encoding) ?;
153+ let call_site_length =
154+ read_encoded_offset ( call_site_record_reader, call_site_table_encoding) ?;
155+ // Offset of the landing pad, counted in 16-byte bundles relative to the LPStart address.
156+ let call_site_lpad =
157+ read_encoded_offset ( call_site_record_reader, call_site_table_encoding) ?;
158+ // Offset of the first associated action record, relative to the start of the actions table. This value is biased by 1 (1 indicates the start of the actions table), and 0 indicates that there are no actions.
159+ let call_site_action_entry = call_site_record_reader. read_uleb128 ( ) ;
160+
161+ log ! ( "(pers) read cs_start is {call_site_start:?}" ) ;
162+ log ! ( "(pers) read cs_len is {call_site_length:?}" ) ;
163+ log ! ( "(pers) read cs_lpad is {call_site_lpad:?}" ) ;
164+ log ! ( "(pers) read cs_ae is {call_site_action_entry:?}" ) ;
158165 // Callsite table is sorted by cs_start, so if we've passed the ip, we
159166 // may stop searching.
160- if ip < func_start. wrapping_add ( cs_start ) {
167+ if ip < func_start. wrapping_add ( call_site_start ) {
161168 break ;
162169 }
163170
164- if ip < func_start. wrapping_add ( cs_start + cs_len) {
171+ // Call site matches the current ip. It's a candidate.
172+ if ip < func_start. wrapping_add ( call_site_start + call_site_length) {
165173 log ! (
166174 "(pers) found a matching call site: {func_start:?} <= {ip:?} <= {:?}" ,
167- func_start. wrapping_add( cs_start + cs_len )
175+ func_start. wrapping_add( call_site_start + call_site_length )
168176 ) ;
169- if cs_lpad == 0 {
177+ if call_site_lpad == 0 {
170178 return Ok ( EHAction :: None ) ;
171179 } else {
172- let lpad = lpad_base. wrapping_add ( cs_lpad ) ;
180+ let lpad = lpad_base. wrapping_add ( call_site_lpad ) ;
173181
174182 log ! ( "(pers) lpad sits at {lpad:?}" ) ;
175183
176- if cs_action_entry == 0 {
184+ if call_site_action_entry == 0 {
177185 return Ok ( EHAction :: Cleanup ( lpad) ) ;
178186 }
179187
180- log ! ( "(pers) read cs_action_entry: {cs_action_entry }" ) ;
188+ log ! ( "(pers) read cs_action_entry: {call_site_action_entry }" ) ;
181189 log ! ( "(pers) action_table: {action_table:?}" ) ;
182190
183191 // Convert 1-based byte offset into
184- let mut action : * const u8 =
185- action_table. wrapping_add ( ( cs_action_entry - 1 ) as usize ) ;
192+ let mut action_record : * const u8 =
193+ action_table. wrapping_add ( ( call_site_action_entry - 1 ) as usize ) ;
186194
187- log ! ( "(pers) first action at: {action :?}" ) ;
195+ log ! ( "(pers) first action at: {action_record :?}" ) ;
188196
189197 loop {
190- let mut reader = DwarfReader :: new ( action) ;
191- let ttype_index = reader. read_sleb128 ( ) ;
198+ // Read the action record.
199+ let mut action_record_reader = DwarfReader :: new ( action_record) ;
200+ // The two record kinds have the same format, with only small differences. They are distinguished by the "type_filter" field: Catch clauses have strictly positive switch values, and exception specifications have strictly negative switch values. Value 0 indicates a catch-all clause.
201+ let type_filter = action_record_reader. read_sleb128 ( ) ;
192202 log ! (
193- "(pers) ttype_index for action #{cs_action_entry }: {ttype_index :?}"
203+ "(pers) ttype_index for action #{call_site_action_entry }: {type_filter :?}"
194204 ) ;
195205
196- if ttype_index > 0 {
197- if class_info. is_null ( ) {
206+ if type_filter > 0 {
207+ // This is a catch clause so the type_filter is a index into the types table.
208+ //
209+ // Positive value, starting at 1.
210+ // Index in the types table of the __typeinfo for the catch-clause type.
211+ // 1 is the first word preceding TTBase, 2 is the second word, and so on.
212+ // Used by the runtime to check if the thrown exception type matches the catch-clause type.
213+ let types_table_index = type_filter;
214+ if types_table_base. is_null ( ) {
198215 panic ! ( ) ;
199216 }
200217
201218 let tag_ptr = {
202- let new_ttype_index = match ttype_encoding & 0x0f {
219+ let new_types_table_index = match types_table_encoding & 0x0f {
203220 DW_EH_PE_absptr => {
204- ttype_index * ( size_of :: < * const u8 > ( ) as i64 )
221+ type_filter * ( size_of :: < * const u8 > ( ) as i64 )
205222 }
206- DW_EH_PE_sdata2 | DW_EH_PE_udata2 => ttype_index * 2 ,
207- DW_EH_PE_sdata4 | DW_EH_PE_udata4 => ttype_index * 4 ,
208- DW_EH_PE_sdata8 | DW_EH_PE_udata8 => ttype_index * 8 ,
223+ DW_EH_PE_sdata2 | DW_EH_PE_udata2 => type_filter * 2 ,
224+ DW_EH_PE_sdata4 | DW_EH_PE_udata4 => type_filter * 4 ,
225+ DW_EH_PE_sdata8 | DW_EH_PE_udata8 => type_filter * 8 ,
209226 _ => panic ! ( ) ,
210227 } ;
211228
212- log ! ( "(pers) new_ttype_index for action #{cs_action_entry }: {new_ttype_index :?}" ) ;
229+ log ! ( "(pers) new_ttype_index for action #{call_site_action_entry }: {new_types_table_index :?}" ) ;
213230
214- let i = class_info. wrapping_sub ( new_ttype_index as usize ) ;
215- log ! ( "(pers) reading ttype info from {i:?}" ) ;
231+ let typeinfo = types_table_base
232+ . wrapping_sub ( new_types_table_index as usize ) ;
233+ log ! ( "(pers) reading ttype info from {typeinfo:?}" ) ;
216234 read_encoded_pointer (
217- & mut DwarfReader :: new ( i) ,
235+ // Basically just reader.read() a SLEB128.
236+ & mut DwarfReader :: new ( typeinfo) ,
218237 context,
219- ttype_encoding ,
238+ types_table_encoding ,
220239 )
221240 } ;
222241 let tag_ptr = tag_ptr. unwrap ( ) ;
@@ -231,16 +250,18 @@ pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext<'_>) -> Result
231250 if context. tag == tag {
232251 return Ok ( EHAction :: Catch { lpad, tag } ) ;
233252 }
234- } else if ttype_index == 0 {
253+ } else if type_filter == 0 {
235254 return Ok ( EHAction :: Cleanup ( lpad) ) ;
236255 }
237256
238- let action_offset = reader . clone ( ) . read_sleb128 ( ) ;
239- if action_offset == 0 {
257+ let next_action_record = action_record_reader . clone ( ) . read_sleb128 ( ) ;
258+ if next_action_record == 0 {
240259 return Ok ( EHAction :: None ) ;
241260 }
242261
243- action = reader. ptr . wrapping_add ( action_offset as usize ) ;
262+ action_record = action_record_reader
263+ . ptr
264+ . wrapping_add ( next_action_record as usize ) ;
244265 }
245266 }
246267 }
0 commit comments