@@ -2,19 +2,21 @@ use std::{collections::HashSet, fs, io::Cursor, path::Path};
22
33use anyhow:: { anyhow, bail, ensure, Context , Result } ;
44use byteorder:: { BigEndian , ReadBytesExt } ;
5+ use cwextab:: decode_extab;
56use filetime:: FileTime ;
67use flagset:: Flags ;
78use 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 ,
1011} ;
1112
1213use crate :: {
1314 arch:: { new_arch, ObjArch } ,
1415 diff:: DiffObjConfig ,
1516 obj:: {
1617 split_meta:: { SplitMeta , SPLITMETA_SECTION } ,
17- ObjInfo , ObjReloc , ObjSection , ObjSectionKind , ObjSymbol , ObjSymbolFlagSet , ObjSymbolFlags ,
18+ ObjExtab , ObjInfo , ObjReloc , ObjSection , ObjSectionKind , ObjSymbol , ObjSymbolFlagSet ,
19+ ObjSymbolFlags ,
1820 } ,
1921} ;
2022
@@ -71,6 +73,9 @@ fn to_obj_symbol(
7173 Ok ( ObjSymbol {
7274 name : name. to_string ( ) ,
7375 demangled_name,
76+ has_extab : false ,
77+ extab_name : None ,
78+ extabindex_name : None ,
7479 address,
7580 section_address,
7681 size : symbol. size ( ) ,
@@ -170,6 +175,111 @@ fn common_symbols(
170175 . collect :: < Result < Vec < ObjSymbol > > > ( )
171176}
172177
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+
173283fn find_section_symbol (
174284 arch : & dyn ObjArch ,
175285 obj_file : & File < ' _ > ,
@@ -205,6 +315,9 @@ fn find_section_symbol(
205315 Ok ( ObjSymbol {
206316 name : name. to_string ( ) ,
207317 demangled_name : None ,
318+ has_extab : false ,
319+ extab_name : None ,
320+ extabindex_name : None ,
208321 address : offset,
209322 section_address : address - section. address ( ) ,
210323 size : 0 ,
@@ -367,6 +480,9 @@ fn update_combined_symbol(symbol: ObjSymbol, address_change: i64) -> Result<ObjS
367480 Ok ( ObjSymbol {
368481 name : symbol. name ,
369482 demangled_name : symbol. demangled_name ,
483+ has_extab : symbol. has_extab ,
484+ extab_name : symbol. extab_name ,
485+ extabindex_name : symbol. extabindex_name ,
370486 address : ( symbol. address as i64 + address_change) . try_into ( ) ?,
371487 section_address : ( symbol. section_address as i64 + address_change) . try_into ( ) ?,
372488 size : symbol. size ,
@@ -482,7 +598,8 @@ pub fn read(obj_path: &Path, config: &DiffObjConfig) -> Result<ObjInfo> {
482598 }
483599 line_info ( & obj_file, & mut sections) ?;
484600 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 } )
486603}
487604
488605pub fn has_function ( obj_path : & Path , symbol_name : & str ) -> Result < bool > {
0 commit comments