@@ -7,6 +7,7 @@ use std::fmt::Formatter;
77use std:: fmt:: Result as FmtResult ;
88use std:: fs:: File ;
99use std:: io;
10+ #[ cfg( feature = "xz" ) ]
1011use std:: io:: Read as _;
1112use std:: io:: Seek as _;
1213use std:: io:: SeekFrom ;
@@ -272,7 +273,7 @@ fn decompress_zstd(_data: &[u8]) -> Result<Vec<u8>> {
272273 ) )
273274}
274275
275- #[ cfg( feature = "xz2 " ) ]
276+ #[ cfg( feature = "xz " ) ]
276277fn decompress_xz ( data : & [ u8 ] ) -> Result < Vec < u8 > > {
277278 use xz2:: read:: XzDecoder ;
278279
@@ -285,7 +286,7 @@ fn decompress_xz(data: &[u8]) -> Result<Vec<u8>> {
285286 Ok ( decompressed)
286287}
287288
288- #[ cfg( not( feature = "xz2 " ) ) ]
289+ #[ cfg( not( feature = "xz " ) ) ]
289290fn decompress_xz ( _data : & [ u8 ] ) -> Result < Vec < u8 > > {
290291 Err ( Error :: with_unsupported (
291292 "ELF section is xz compressed but xz compression support is not enabled" ,
@@ -458,8 +459,6 @@ struct Cache<'elf, B> {
458459 dynsym : OnceCell < SymbolTableCache < ' elf > > ,
459460 /// The section data.
460461 section_data : OnceCell < Box < [ OnceCell < Cow < ' elf , [ u8 ] > > ] > > ,
461- /// Potential decompressed `.gnu_debugdata` contents.
462- debugdata : OnceCell < Cow < ' elf , [ u8 ] > > ,
463462}
464463
465464impl < ' elf , B > Cache < ' elf , B >
@@ -477,7 +476,6 @@ where
477476 symtab : OnceCell :: new ( ) ,
478477 dynsym : OnceCell :: new ( ) ,
479478 section_data : OnceCell :: new ( ) ,
480- debugdata : OnceCell :: new ( ) ,
481479 }
482480 }
483481
@@ -832,58 +830,35 @@ where
832830 Ok ( syms)
833831 }
834832
835- #[ cfg( feature = "xz2" ) ]
836- fn parse_debugdata ( & self ) -> Result < Option < Vec < u8 > > > {
837- let idx = if let Some ( idx) = self . find_section ( ".gnu_debugdata" ) ? {
838- idx
833+ fn parse_debugdata ( & self ) -> Result < Vec < u8 > > {
834+ if let Some ( idx) = self . find_section ( ".gnu_debugdata" ) ? {
835+ // NB: We assume here that `.gnu_debugdata` will never be
836+ // of type `SHT_NOBITS`, which just logically doesn't
837+ // make sense to be used.
838+ self . section_data_raw ( idx)
839+ . and_then ( |data| decompress_xz ( & data) )
839840 } else {
840- // The symbol table does not exists. Fake an empty one.
841- return Ok ( None )
842- } ;
843-
844- let shdr = self . section_hdr ( idx) ?;
845- if shdr. type_ ( ) == SHT_NOBITS {
846- return Ok ( None )
841+ Ok ( Vec :: new ( ) )
847842 }
848-
849- let sh_size = shdr. size ( ) ;
850- let sh_offset = shdr. offset ( ) ;
851-
852- let data = self
853- . backend
854- . read_pod_slice :: < u8 > ( sh_offset, sh_size as usize )
855- . context ( "failed to read .gnu_debugdata section data" ) ?;
856-
857- let decompressed = decompress_xz ( & data) ?;
858-
859- Ok ( Some ( decompressed) )
860- }
861-
862- #[ cfg( not( feature = "xz2" ) ) ]
863- fn parse_debugdata ( & self ) -> Result < Option < Vec < u8 > > > {
864- // We don't have the means to decompress it, fake an empty one.
865- return Ok ( None )
866843 }
867844
868845 fn ensure_symtab_cache ( & self ) -> Result < & SymbolTableCache < ' elf > > {
869- self . symtab . get_or_try_init_ ( || {
846+ self . symtab . get_or_try_init_ ( move || {
870847 let mut syms = self . parse_syms ( ".symtab" ) ?;
871848 let mut strtab = self . parse_strs ( ".strtab" ) ?;
849+
872850 if syms. is_empty ( ) {
873- let data = self . debugdata . get_or_try_init_ ( || {
874- if let Some ( data) = self . parse_debugdata ( ) ? {
875- Result :: < _ , Error > :: Ok ( Cow :: Owned ( data) )
876- } else {
877- Ok ( Cow :: Borrowed ( [ ] . as_slice ( ) ) )
878- }
879- } ) ?;
851+ let data = self . parse_debugdata ( ) ?;
880852 if !data. is_empty ( ) {
881- // to allow self-referentiality here, we have to artificially
882- // extend the lifetime of `data` to `'elf`
883- let data_slice = unsafe { mem:: transmute :: < & [ u8 ] , & ' elf [ u8 ] > ( data) } ;
884- let cache = Cache :: new ( data_slice) ;
885- syms = cache. parse_syms ( ".symtab" ) ?;
886- strtab = cache. parse_strs ( ".strtab" ) ?;
853+ let cache = Cache :: new ( data. as_slice ( ) ) ;
854+ // Because we don't store the decompressed data
855+ // anywhere (and we don't want to to avoid
856+ // self-referentiality), convert the parsed data
857+ // into their owned counterparts.
858+ syms = cache. parse_syms ( ".symtab" ) ?. to_owned ( ) ;
859+ strtab = cache
860+ . parse_strs ( ".strtab" )
861+ . map ( |strs| Cow :: Owned ( strs. to_vec ( ) ) ) ?;
887862 }
888863 }
889864 let cache = SymbolTableCache :: new ( syms, strtab) ;
@@ -2127,7 +2102,6 @@ mod tests {
21272102 symtab : OnceCell :: new ( ) ,
21282103 dynsym : OnceCell :: new ( ) ,
21292104 section_data : OnceCell :: new ( ) ,
2130- debugdata : OnceCell :: new ( ) ,
21312105 } ;
21322106
21332107 assert_eq ! ( cache. find_section( ".symtab" ) . unwrap( ) , Some ( 2 ) ) ;
@@ -2234,29 +2208,12 @@ mod tests {
22342208 symtab : OnceCell :: new ( ) ,
22352209 dynsym : OnceCell :: new ( ) ,
22362210 section_data : OnceCell :: from ( vec ! [ OnceCell :: new( ) , OnceCell :: new( ) ] . into_boxed_slice ( ) ) ,
2237- debugdata : OnceCell :: new ( ) ,
22382211 } ;
22392212
22402213 let new_data = cache. section_data ( 1 ) . unwrap ( ) ;
22412214 assert_eq ! ( new_data, data) ;
22422215 }
22432216
2244- /// Make sure that we can look up a symbol residing in `.gnu_debugdata`.
2245- #[ cfg( feature = "xz2" ) ]
2246- #[ test]
2247- fn lookup_from_gnu_debugdata ( ) {
2248- let bin_name = Path :: new ( & env ! ( "CARGO_MANIFEST_DIR" ) )
2249- . join ( "data" )
2250- . join ( "test-debugdata.bin" ) ;
2251-
2252- let parser = ElfParser :: open ( bin_name. as_path ( ) ) . unwrap ( ) ;
2253- let opts = FindAddrOpts :: default ( ) ;
2254- let addr = parser. find_addr ( "fibonacci" , & opts) . unwrap ( ) ;
2255- assert_eq ! ( addr. len( ) , 1 ) ;
2256- let sym = & addr[ 0 ] ;
2257- assert_eq ! ( sym. name, "fibonacci" ) ;
2258- }
2259-
22602217 /// Benchmark creation of our "str2symtab" table.
22612218 ///
22622219 /// Creating this table exercises a lot of the parser code paths and
0 commit comments