fn extract_dwarf_labels(exe_filename: &Path) -> Result<Vec<ykpack::SirLabel>, gimli::Error> {
        let file = fs::File::open(exe_filename).unwrap();
        let mmap = unsafe { memmap::Mmap::map(&file).unwrap() };
        let object = object::File::parse(&*mmap).unwrap();
        let endian = if object.is_little_endian() {
            gimli::RunTimeEndian::Little
        } else {
            gimli::RunTimeEndian::Big
        };
        let loader = |id: gimli::SectionId| -> Result<&[u8], gimli::Error> {
            Ok(object
                .section_by_name(id.name())
                .map(|sec| sec.data().expect("failed to decompress section"))
                .unwrap_or(&[] as &[u8]))
        };
        let sup_loader = |_| Ok(&[] as &[u8]);
        let dwarf_cow = gimli::Dwarf::load(&loader, &sup_loader)?;
        let borrow_section: &dyn for<'a> Fn(
            &&'a [u8],
        )
            -> gimli::EndianSlice<'a, gimli::RunTimeEndian> =
            &|section| gimli::EndianSlice::new(section, endian);
        let dwarf = dwarf_cow.borrow(&borrow_section);
        let mut iter = dwarf.units();
        let mut subaddr = None;
        let mut labels = Vec::new();
        while let Some(header) = iter.next()? {
            let unit = dwarf.unit(header)?;
            let mut entries = unit.entries();
            while let Some((_, entry)) = entries.next_dfs()? {
                if entry.tag() == gimli::DW_TAG_subprogram {
                    if let Some(_name) = entry.attr_value(gimli::DW_AT_linkage_name)? {
                        if let Some(lowpc) = entry.attr_value(gimli::DW_AT_low_pc)? {
                            if let gimli::AttributeValue::Addr(v) = lowpc {
                                // We can not accurately insert labels at the beginning of
                                // functions, because the label is offset by the function headers.
                                // We thus simply remember the subprogram's address so we can later
                                // assign it to the first block (ending with '_0') of this
                                // subprogram.
                                subaddr = Some(u64::try_from(v).unwrap());
                            } else {
                                panic!("Error reading dwarf information. Expected type 'Addr'.")
                            }
                        }
                    }
                } else if entry.tag() == gimli::DW_TAG_label {
                    if let Some(name) = entry.attr_value(gimli::DW_AT_name)? {
                        if let Some(es) = name.string_value(&dwarf.debug_str) {
                            let s = es.to_string()?;
                            if s.starts_with("__YK_") {
                                if let Some(lowpc) = entry.attr_value(gimli::DW_AT_low_pc)? {
                                    if subaddr.is_some() && s.ends_with("_0") {
                                        // This is the first block of the subprogram. Assign its
                                        // label to the subprogram's address.
                                        let (fsym, bb) = split_label_name(s);
                                        labels.push(ykpack::SirLabel {
                                            off: usize::try_from(subaddr.unwrap()).unwrap(),
                                            symbol_name: fsym,
                                            bb,
                                        });
                                        subaddr = None;
                                    } else {
                                        let (fsym, bb) = split_label_name(s);
                                        if let gimli::AttributeValue::Addr(v) = lowpc {
                                            labels.push(ykpack::SirLabel {
                                                off: usize::try_from(u64::try_from(v).unwrap())
                                                    .unwrap(),
                                                symbol_name: fsym,
                                                bb,
                                            });
                                        } else {
                                            panic!(
                                                "Error reading dwarf information. Expected type 'Addr'."
                                            );
                                        }
                                    }
                                } else {
                                    // Ignore labels that have no address.
                                }
                            }
                        }
                    }
                }
            }
        }

        labels.sort_by_key(|l| l.off);
        Ok(labels)
    }
/// Walks the DWARF tree of the specified executable and extracts Yorick location mapping
/// labels. Returns an list of labels ordered by file offset (ascending).
Walks the DWARF tree of the specified executable and extracts Yorick location mapping
labels. Returns an list of labels ordered by file offset (ascending).
Walks the DWARF tree of the specified executable and extracts Yorick location mapping labels . Returns an list of labels ordered by file offset ( ascending ) .
fn extract_dwarf_labels(exe_filename: &Path) -> Result<Vec<ykpack::SirLabel>, gimli::Error> {
        let file = fs::File::open(exe_filename).unwrap();
        let mmap = unsafe { memmap::Mmap::map(&file).unwrap() };
        let object = object::File::parse(&*mmap).unwrap();
        let endian = if object.is_little_endian() {
            gimli::RunTimeEndian::Little
        } else {
            gimli::RunTimeEndian::Big
        };
        let loader = |id: gimli::SectionId| -> Result<&[u8], gimli::Error> {
            Ok(object
                .section_by_name(id.name())
                .map(|sec| sec.data().expect("failed to decompress section"))
                .unwrap_or(&[] as &[u8]))
        };
        let sup_loader = |_| Ok(&[] as &[u8]);
        let dwarf_cow = gimli::Dwarf::load(&loader, &sup_loader)?;
        let borrow_section: &dyn for<'a> Fn(
            &&'a [u8],
        )
            -> gimli::EndianSlice<'a, gimli::RunTimeEndian> =
            &|section| gimli::EndianSlice::new(section, endian);
        let dwarf = dwarf_cow.borrow(&borrow_section);
        let mut iter = dwarf.units();
        let mut subaddr = None;
        let mut labels = Vec::new();
        while let Some(header) = iter.next()? {
            let unit = dwarf.unit(header)?;
            let mut entries = unit.entries();
            while let Some((_, entry)) = entries.next_dfs()? {
                if entry.tag() == gimli::DW_TAG_subprogram {
                    if let Some(_name) = entry.attr_value(gimli::DW_AT_linkage_name)? {
                        if let Some(lowpc) = entry.attr_value(gimli::DW_AT_low_pc)? {
                            if let gimli::AttributeValue::Addr(v) = lowpc {
                                // We can not accurately insert labels at the beginning of
                                // functions, because the label is offset by the function headers.
                                // We thus simply remember the subprogram's address so we can later
                                // assign it to the first block (ending with '_0') of this
                                // subprogram.
                                subaddr = Some(u64::try_from(v).unwrap());
                            } else {
                                panic!("Error reading dwarf information. Expected type 'Addr'.")
                            }
                        }
                    }
                } else if entry.tag() == gimli::DW_TAG_label {
                    if let Some(name) = entry.attr_value(gimli::DW_AT_name)? {
                        if let Some(es) = name.string_value(&dwarf.debug_str) {
                            let s = es.to_string()?;
                            if s.starts_with("__YK_") {
                                if let Some(lowpc) = entry.attr_value(gimli::DW_AT_low_pc)? {
                                    if subaddr.is_some() && s.ends_with("_0") {
                                        // This is the first block of the subprogram. Assign its
                                        // label to the subprogram's address.
                                        let (fsym, bb) = split_label_name(s);
                                        labels.push(ykpack::SirLabel {
                                            off: usize::try_from(subaddr.unwrap()).unwrap(),
                                            symbol_name: fsym,
                                            bb,
                                        });
                                        subaddr = None;
                                    } else {
                                        let (fsym, bb) = split_label_name(s);
                                        if let gimli::AttributeValue::Addr(v) = lowpc {
                                            labels.push(ykpack::SirLabel {
                                                off: usize::try_from(u64::try_from(v).unwrap())
                                                    .unwrap(),
                                                symbol_name: fsym,
                                                bb,
                                            });
                                        } else {
                                            panic!(
                                                "Error reading dwarf information. Expected type 'Addr'."
                                            );
                                        }
                                    }
                                } else {
                                    // Ignore labels that have no address.
                                }
                            }
                        }
                    }
                }
            }
        }
        labels.sort_by_key(|l| l.off);
        Ok(labels)
    }
fn extract_dwarf_labels ( exe_filename : & Path ) -> Result < Vec < ykpack :: SirLabel > , gimli :: Error > { let file = fs :: File :: open ( exe_filename ) . unwrap ( ) ; let mmap = unsafe { memmap :: Mmap :: map ( & file ) . unwrap ( ) } ; let object = object :: File :: parse ( & * mmap ) . unwrap ( ) ; let endian = if object . is_little_endian ( ) { gimli :: RunTimeEndian :: Little } else { gimli :: RunTimeEndian :: Big } ; let loader = | id : gimli :: SectionId | -> Result < & [ u8 ] , gimli :: Error > { Ok ( object . section_by_name ( id . name ( ) ) . map ( | sec | sec . data ( ) . expect ( " " ) ) . unwrap_or ( & [ ] as & [ u8 ] ) ) } ; let sup_loader = | _ | Ok ( & [ ] as & [ u8 ] ) ; let dwarf_cow = gimli :: Dwarf :: load ( & loader , & sup_loader ) ? ; let borrow_section : & dyn for < ' a > Fn ( & & ' a [ u8 ] , ) -> gimli :: EndianSlice < ' a , gimli :: RunTimeEndian > = & | section | gimli :: EndianSlice :: new ( section , endian ) ; let dwarf = dwarf_cow . borrow ( & borrow_section ) ; let mut iter = dwarf . units ( ) ; let mut subaddr = None ; let mut labels = Vec :: new ( ) ; while let Some ( header ) = iter . next ( ) ? { let unit = dwarf . unit ( header ) ? ; let mut entries = unit . entries ( ) ; while let Some ( ( _ , entry ) ) = entries . next_dfs ( ) ? { if entry . tag ( ) == gimli :: DW_TAG_subprogram { if let Some ( _name ) = entry . attr_value ( gimli :: DW_AT_linkage_name ) ? { if let Some ( lowpc ) = entry . attr_value ( gimli :: DW_AT_low_pc ) ? { if let gimli :: AttributeValue :: Addr ( v ) = lowpc { // We can not accurately insert labels at the beginning of // functions, because the label is offset by the function headers. // We thus simply remember the subprogram's address so we can later // assign it to the first block (ending with '_0') of this // subprogram. subaddr = Some ( u64 :: try_from ( v ) . unwrap ( ) ) ; } else { panic ! ( " " ) } } } } else if entry . tag ( ) == gimli :: DW_TAG_label { if let Some ( name ) = entry . attr_value ( gimli :: DW_AT_name ) ? { if let Some ( es ) = name . string_value ( & dwarf . debug_str ) { let s = es . to_string ( ) ? ; if s . starts_with ( " " ) { if let Some ( lowpc ) = entry . attr_value ( gimli :: DW_AT_low_pc ) ? { if subaddr . is_some ( ) && s . ends_with ( " " ) { // This is the first block of the subprogram. Assign its // label to the subprogram's address. let ( fsym , bb ) = split_label_name ( s ) ; labels . push ( ykpack :: SirLabel { off : usize :: try_from ( subaddr . unwrap ( ) ) . unwrap ( ) , symbol_name : fsym , bb , } ) ; subaddr = None ; } else { let ( fsym , bb ) = split_label_name ( s ) ; if let gimli :: AttributeValue :: Addr ( v ) = lowpc { labels . push ( ykpack :: SirLabel { off : usize :: try_from ( u64 :: try_from ( v ) . unwrap ( ) ) . unwrap ( ) , symbol_name : fsym , bb , } ) ; } else { panic ! ( " " ) ; } } } else { // Ignore labels that have no address. } } } } } } } labels . sort_by_key ( | l | l . off ) ; Ok ( labels ) }
Walks the DWARF tree of the specified executable and extracts Yorick location mapping
labels.
Walks the DWARF tree of the specified executable and extracts Yorick location mapping labels .
exe_filename
&Path