/// Runs the location evaluation of gimli.
///
/// - `location`: The `DW_AT_location` attribute value of the entry of the variable we want to get the location of.
/// This may be a None if the variable has no location attribute.
Runs the location evaluation of gimli.
`location`: The `DW_AT_location` attribute value of the entry of the variable we want to get the location of.
This may be a None if the variable has no location attribute.
Runs the location evaluation of gimli . ` location ` : The ` DW_AT_location ` attribute value of the entry of the variable we want to get the location of . This may be a None if the variable has no location attribute .
fn evaluate_location(
    dwarf: &Dwarf<DefaultReader>,
    unit: &Unit<DefaultReader, usize>,
    device_memory: &DeviceMemory<u32>,
    location: Option<Attribute<DefaultReader>>,
    frame_base: Option<u32>,
) -> Result<VariableLocationResult, TraceError> {
    // First, we need to have the actual value
    let location = match location {
        Some(location) => location.value(),
        None => return Ok(VariableLocationResult::NoLocationAttribute),
    };
    // Then we need to get the location expression. This expression can then later be evaluated by gimli.
    let location_expression = match location {
        AttributeValue::Block(ref data) => gimli::Expression(data.clone()),
        AttributeValue::Exprloc(ref data) => data.clone(),
        AttributeValue::LocationListsRef(l) => {
            let mut locations = dwarf.locations(unit, l)?;
            let mut location = None;
            while let Ok(Some(maybe_location)) = locations.next() {
                // The .debug_loc does not seem to count the thumb bit, so remove it
                let check_pc =
                    u64::from(device_memory.register(gimli::Arm::PC)? & !super::THUMB_BIT);
                if check_pc >= maybe_location.range.begin && check_pc < maybe_location.range.end {
                    location = Some(maybe_location);
                    break;
                }
            }
            if let Some(location) = location {
                location.data
            } else {
                return Ok(VariableLocationResult::LocationListNotFound);
            }
        }
        _ => unreachable!(),
    };
    // Turn the expression into an evaluation
    let mut location_evaluation = location_expression.evaluation(unit.encoding());
    // Now we need to evaluate everything.
    // DWARF has a stack based instruction set that needs to be executed.
    // Luckily, gimli already implements the bulk of it.
    // The evaluation stops when it requires some memory that we need to provide.
    let mut result = location_evaluation.evaluate()?;
    while result != EvaluationResult::Complete {
        log::trace!("Location evaluation result: {:?}", result);
        match result {
            EvaluationResult::RequiresRegister {
                register,
                base_type,
            } => {
                let value = device_memory.register(register)?;
                let value = match base_type.0 {
                    0 => gimli::Value::Generic(value.into()),
                    _ => todo!("Other types than generic haven't been implemented yet"),
                };
                result = location_evaluation.resume_with_register(value)?;
            }
            EvaluationResult::RequiresFrameBase if frame_base.is_some() => {
                result = location_evaluation.resume_with_frame_base(
                    frame_base.ok_or(TraceError::UnknownFrameBase)? as u64,
                )?;
            }
            EvaluationResult::RequiresRelocatedAddress(address) => {
                // We have no relocations of code
                result = location_evaluation.resume_with_relocated_address(address)?;
            }
            r => {
                return Ok(
                    VariableLocationResult::LocationEvaluationStepNotImplemented(std::rc::Rc::new(
                        r,
                    )),
                )
            }
        }
    }
    let result = location_evaluation.result();
    match result.len() {
        0 => Ok(VariableLocationResult::NoLocationFound),
        _ => Ok(VariableLocationResult::LocationsFound(result)),
    }
}
fn evaluate_location ( dwarf : & Dwarf < DefaultReader > , unit : & Unit < DefaultReader , usize > , device_memory : & DeviceMemory < u32 > , location : Option < Attribute < DefaultReader > > , frame_base : Option < u32 > , ) -> Result < VariableLocationResult , TraceError > { // First, we need to have the actual value let location = match location { Some ( location ) => location . value ( ) , None => return Ok ( VariableLocationResult :: NoLocationAttribute ) , } ; // Then we need to get the location expression. This expression can then later be evaluated by gimli. let location_expression = match location { AttributeValue :: Block ( ref data ) => gimli :: Expression ( data . clone ( ) ) , AttributeValue :: Exprloc ( ref data ) => data . clone ( ) , AttributeValue :: LocationListsRef ( l ) => { let mut locations = dwarf . locations ( unit , l ) ? ; let mut location = None ; while let Ok ( Some ( maybe_location ) ) = locations . next ( ) { // The .debug_loc does not seem to count the thumb bit, so remove it let check_pc = u64 :: from ( device_memory . register ( gimli :: Arm :: PC ) ? & ! super :: THUMB_BIT ) ; if check_pc >= maybe_location . range . begin && check_pc < maybe_location . range . end { location = Some ( maybe_location ) ; break ; } } if let Some ( location ) = location { location . data } else { return Ok ( VariableLocationResult :: LocationListNotFound ) ; } } _ => unreachable ! ( ) , } ; // Turn the expression into an evaluation let mut location_evaluation = location_expression . evaluation ( unit . encoding ( ) ) ; // Now we need to evaluate everything. // DWARF has a stack based instruction set that needs to be executed. // Luckily, gimli already implements the bulk of it. // The evaluation stops when it requires some memory that we need to provide. let mut result = location_evaluation . evaluate ( ) ? ; while result != EvaluationResult :: Complete { log :: trace ! ( " " result ) ; match result { EvaluationResult :: RequiresRegister { register , base_type , } => { let value = device_memory . register ( register ) ? ; let value = match base_type . 0 { 0 => gimli :: Value :: Generic ( value . into ( ) ) , _ => todo ! ( " " ) , } ; result = location_evaluation . resume_with_register ( value ) ? ; } EvaluationResult :: RequiresFrameBase if frame_base . is_some ( ) => { result = location_evaluation . resume_with_frame_base ( frame_base . ok_or ( TraceError :: UnknownFrameBase ) ? as u64 , ) ? ; } EvaluationResult :: RequiresRelocatedAddress ( address ) => { // We have no relocations of code result = location_evaluation . resume_with_relocated_address ( address ) ? ; } r => { return Ok ( VariableLocationResult :: LocationEvaluationStepNotImplemented ( std :: rc :: Rc :: new ( r , ) ) , ) } } } let result = location_evaluation . result ( ) ; match result . len ( ) { 0 => Ok ( VariableLocationResult :: NoLocationFound ) , _ => Ok ( VariableLocationResult :: LocationsFound ( result ) ) , } }
Runs the location evaluation of gimli.
Runs the location evaluation of gimli .
dwarf
&Dwarf<DefaultReader>
unit
&Unit<DefaultReader, usize>
device_memory
&DeviceMemory<u32>
location
Option<Attribute<DefaultReader>>
frame_base
Option<u32>