@@ -2,19 +2,21 @@ use std::{collections::HashSet, fs, io::Cursor, path::Path};
2
2
3
3
use anyhow:: { anyhow, bail, ensure, Context , Result } ;
4
4
use byteorder:: { BigEndian , ReadBytesExt } ;
5
+ use cwextab:: decode_extab;
5
6
use filetime:: FileTime ;
6
7
use flagset:: Flags ;
7
8
use object:: {
8
- BinaryFormat , File , Object , ObjectSection , ObjectSymbol , RelocationTarget , SectionIndex ,
9
- SectionKind , Symbol , SymbolKind , SymbolScope , SymbolSection ,
9
+ Architecture , BinaryFormat , File , Object , ObjectSection , ObjectSymbol , RelocationTarget ,
10
+ SectionIndex , SectionKind , Symbol , SymbolKind , SymbolScope , SymbolSection ,
10
11
} ;
11
12
12
13
use crate :: {
13
14
arch:: { new_arch, ObjArch } ,
14
15
diff:: DiffObjConfig ,
15
16
obj:: {
16
17
split_meta:: { SplitMeta , SPLITMETA_SECTION } ,
17
- ObjInfo , ObjReloc , ObjSection , ObjSectionKind , ObjSymbol , ObjSymbolFlagSet , ObjSymbolFlags ,
18
+ ObjExtab , ObjInfo , ObjReloc , ObjSection , ObjSectionKind , ObjSymbol , ObjSymbolFlagSet ,
19
+ ObjSymbolFlags ,
18
20
} ,
19
21
} ;
20
22
@@ -71,6 +73,9 @@ fn to_obj_symbol(
71
73
Ok ( ObjSymbol {
72
74
name : name. to_string ( ) ,
73
75
demangled_name,
76
+ has_extab : false ,
77
+ extab_name : None ,
78
+ extabindex_name : None ,
74
79
address,
75
80
section_address,
76
81
size : symbol. size ( ) ,
@@ -170,6 +175,111 @@ fn common_symbols(
170
175
. collect :: < Result < Vec < ObjSymbol > > > ( )
171
176
}
172
177
178
+ fn section_by_name < ' a > ( sections : & ' a mut [ ObjSection ] , name : & str ) -> Option < & ' a mut ObjSection > {
179
+ sections. iter_mut ( ) . find ( |section| section. name == name)
180
+ }
181
+
182
+ fn exception_tables (
183
+ sections : & mut [ ObjSection ] ,
184
+ obj_file : & File < ' _ > ,
185
+ ) -> Result < Option < Vec < ObjExtab > > > {
186
+ //PowerPC only
187
+ if obj_file. architecture ( ) != Architecture :: PowerPc {
188
+ return Ok ( None ) ;
189
+ }
190
+
191
+ //Find the extab/extabindex sections
192
+ let extab_section = match section_by_name ( sections, "extab" ) {
193
+ Some ( section) => section. clone ( ) ,
194
+ None => {
195
+ return Ok ( None ) ;
196
+ }
197
+ } ;
198
+ let extabindex_section = match section_by_name ( sections, "extabindex" ) {
199
+ Some ( section) => section. clone ( ) ,
200
+ None => {
201
+ return Ok ( None ) ;
202
+ }
203
+ } ;
204
+ let text_section = match section_by_name ( sections, ".text" ) {
205
+ Some ( section) => section,
206
+ None => bail ! ( ".text section is somehow missing, this should not happen" ) ,
207
+ } ;
208
+
209
+ let mut result: Vec < ObjExtab > = vec ! [ ] ;
210
+ let extab_symbol_count = extab_section. symbols . len ( ) ;
211
+ let extabindex_symbol_count = extabindex_section. symbols . len ( ) ;
212
+ let extab_reloc_count = extab_section. relocations . len ( ) ;
213
+ let table_count = extab_symbol_count;
214
+ let mut extab_reloc_index: usize = 0 ;
215
+
216
+ //Make sure that the number of symbols in the extab/extabindex section matches. If not, exit early
217
+ if extab_symbol_count != extabindex_symbol_count {
218
+ bail ! ( "Extab/Extabindex symbol counts do not match" ) ;
219
+ }
220
+
221
+ //Convert the extab/extabindex section data
222
+
223
+ //Go through each extabindex entry
224
+ for i in 0 ..table_count {
225
+ let extabindex = & extabindex_section. symbols [ i] ;
226
+
227
+ /* Get the function symbol and extab symbol from the extabindex relocations array. Each extabindex
228
+ entry has two relocations (the first for the function, the second for the extab entry) */
229
+ let extab_func = extabindex_section. relocations [ i * 2 ] . target . clone ( ) ;
230
+ let extab = & extabindex_section. relocations [ ( i * 2 ) + 1 ] . target ;
231
+
232
+ let extab_start_addr = extab. address ;
233
+ let extab_end_addr = extab_start_addr + extab. size ;
234
+
235
+ //Find the function in the text section, and set the has extab flag
236
+ for i in 0 ..text_section. symbols . len ( ) {
237
+ let func = & mut text_section. symbols [ i] ;
238
+ if func. name == extab_func. name {
239
+ func. has_extab = true ;
240
+ func. extab_name = Some ( extab. name . clone ( ) ) ;
241
+ func. extabindex_name = Some ( extabindex. name . clone ( ) ) ;
242
+ }
243
+ }
244
+
245
+ /* Iterate through the list of extab relocations, continuing until we hit a relocation
246
+ that isn't within the current extab symbol. Get the target dtor function symbol from
247
+ each relocation used, and add them to the list. */
248
+ let mut dtors: Vec < ObjSymbol > = vec ! [ ] ;
249
+
250
+ while extab_reloc_index < extab_reloc_count {
251
+ let extab_reloc = & extab_section. relocations [ extab_reloc_index] ;
252
+ //If the current entry is past the current extab table, stop here
253
+ if extab_reloc. address >= extab_end_addr {
254
+ break ;
255
+ }
256
+
257
+ //Otherwise, the current relocation is used by the current table
258
+ dtors. push ( extab_reloc. target . clone ( ) ) ;
259
+ //Go to the next entry
260
+ extab_reloc_index += 1 ;
261
+ }
262
+
263
+ //Decode the extab data
264
+ let start_index = extab_start_addr as usize ;
265
+ let end_index = extab_end_addr as usize ;
266
+ let extab_data = extab_section. data [ start_index..end_index] . try_into ( ) . unwrap ( ) ;
267
+ let data = match decode_extab ( extab_data) {
268
+ Some ( decoded_data) => decoded_data,
269
+ None => {
270
+ log:: warn!( "Exception table decoding failed for function {}" , extab_func. name) ;
271
+ return Ok ( None ) ;
272
+ }
273
+ } ;
274
+
275
+ //Add the new entry to the list
276
+ let entry = ObjExtab { func : extab_func, data, dtors } ;
277
+ result. push ( entry) ;
278
+ }
279
+
280
+ Ok ( Some ( result) )
281
+ }
282
+
173
283
fn find_section_symbol (
174
284
arch : & dyn ObjArch ,
175
285
obj_file : & File < ' _ > ,
@@ -205,6 +315,9 @@ fn find_section_symbol(
205
315
Ok ( ObjSymbol {
206
316
name : name. to_string ( ) ,
207
317
demangled_name : None ,
318
+ has_extab : false ,
319
+ extab_name : None ,
320
+ extabindex_name : None ,
208
321
address : offset,
209
322
section_address : address - section. address ( ) ,
210
323
size : 0 ,
@@ -367,6 +480,9 @@ fn update_combined_symbol(symbol: ObjSymbol, address_change: i64) -> Result<ObjS
367
480
Ok ( ObjSymbol {
368
481
name : symbol. name ,
369
482
demangled_name : symbol. demangled_name ,
483
+ has_extab : symbol. has_extab ,
484
+ extab_name : symbol. extab_name ,
485
+ extabindex_name : symbol. extabindex_name ,
370
486
address : ( symbol. address as i64 + address_change) . try_into ( ) ?,
371
487
section_address : ( symbol. section_address as i64 + address_change) . try_into ( ) ?,
372
488
size : symbol. size ,
@@ -482,7 +598,8 @@ pub fn read(obj_path: &Path, config: &DiffObjConfig) -> Result<ObjInfo> {
482
598
}
483
599
line_info ( & obj_file, & mut sections) ?;
484
600
let common = common_symbols ( arch. as_ref ( ) , & obj_file, split_meta. as_ref ( ) ) ?;
485
- Ok ( ObjInfo { arch, path : obj_path. to_owned ( ) , timestamp, sections, common, split_meta } )
601
+ let extab = exception_tables ( & mut sections, & obj_file) ?;
602
+ Ok ( ObjInfo { arch, path : obj_path. to_owned ( ) , timestamp, sections, common, extab, split_meta } )
486
603
}
487
604
488
605
pub fn has_function ( obj_path : & Path , symbol_name : & str ) -> Result < bool > {
0 commit comments