pub(crate) fn target(core: &mut Core, elf: &Elf, active_ram_region: &Option<RamRegion>) -> Output {
    let mut output = Output {
        corrupted: true,
        outcome: Outcome::Ok,
        raw_frames: vec![],
        processing_error: None,
    };

    /// Returns all info collected until the error occurred and puts the error into `processing_error`
    macro_rules! unwrap_or_return_output {
        ( $e:expr ) => {
            match $e {
                Ok(x) => x,
                Err(err) => {
                    output.processing_error = Some(anyhow!(err));
                    return output;
                }
            }
        };
    }

    let mut pc = unwrap_or_return_output!(core.read_core_reg(registers::PC));
    let sp = unwrap_or_return_output!(core.read_core_reg(registers::SP));
    let lr = unwrap_or_return_output!(core.read_core_reg(registers::LR));
    let base_addresses = BaseAddresses::default();
    let mut unwind_context = UninitializedUnwindContext::new();
    let mut registers = Registers::new(lr, sp, core);

    loop {
        if let Some(outcome) =
            check_hard_fault(pc, &elf.vector_table, &mut output, sp, active_ram_region)
        {
            output.outcome = outcome;
        }

        output.raw_frames.push(RawFrame::Subroutine { pc });

        let uwt_row = unwrap_or_return_output!(elf
            .debug_frame
            .unwind_info_for_address(
                &base_addresses,
                &mut unwind_context,
                pc.into(),
                DebugFrame::cie_from_offset,
            )
            .with_context(|| missing_debug_info(pc)));

        let cfa_changed = unwrap_or_return_output!(registers.update_cfa(uwt_row.cfa()));

        for (reg, rule) in uwt_row.registers() {
            unwrap_or_return_output!(registers.update(reg, rule));
        }

        let lr = unwrap_or_return_output!(registers.get(registers::LR));

        log::debug!("LR={:#010X} PC={:#010X}", lr, pc);

        if lr == registers::LR_END {
            break;
        }

        // Link Register contains an EXC_RETURN value. This deliberately also includes
        // invalid combinations of final bits 0-4 to prevent futile backtrace re-generation attempts
        let exception_entry = lr >= cortexm::EXC_RETURN_MARKER;

        let program_counter_changed = !cortexm::subroutine_eq(lr, pc);

        // If the frame didn't move, and the program counter didn't change, bail out (otherwise we
        // might print the same frame over and over).
        output.corrupted = !cfa_changed && !program_counter_changed;

        if output.corrupted {
            break;
        }

        if exception_entry {
            output.raw_frames.push(RawFrame::Exception);

            // Read the `FType` field from the `EXC_RETURN` value.
            let fpu = lr & cortexm::EXC_RETURN_FTYPE_MASK == 0;

            let sp = unwrap_or_return_output!(registers.get(registers::SP));
            let ram_bounds = active_ram_region
                .as_ref()
                .map(|ram_region| ram_region.range.clone())
                .unwrap_or(cortexm::VALID_RAM_ADDRESS);
            let stacked = if let Some(stacked) =
                unwrap_or_return_output!(Stacked::read(registers.core, sp, fpu, ram_bounds))
            {
                stacked
            } else {
                output.corrupted = true;
                break;
            };

            registers.insert(registers::LR, stacked.lr);
            // adjust the stack pointer for stacked registers
            registers.insert(registers::SP, sp + stacked.size());

            pc = stacked.pc;
        } else if cortexm::is_thumb_bit_set(lr) {
            pc = cortexm::clear_thumb_bit(lr);
        } else {
            output.processing_error = Some(anyhow!(
                "bug? LR ({:#010x}) didn't have the Thumb bit set",
                lr
            ));
            return output;
        }
    }

    output
}
/// Virtually* unwinds the target's program
/// \* destructors are not run
///
/// This returns as much info as could be collected, even if the collection is interrupted by an error.
/// If an error occurred during processing, it is stored in `Output::processing_error`.
Virtually* unwinds the target's program
\* destructors are not run

This returns as much info as could be collected, even if the collection is interrupted by an error.
If an error occurred during processing, it is stored in `Output::processing_error`.
Virtually * unwinds the target ' s program \ * destructors are not run This returns as much info as could be collected even if the collection is interrupted by an error . If an error occurred during processing it is stored in ` Output :: processing_error ` .
pub(crate) fn target(core: &mut Core, elf: &Elf, active_ram_region: &Option<RamRegion>) -> Output {
    let mut output = Output {
        corrupted: true,
        outcome: Outcome::Ok,
        raw_frames: vec![],
        processing_error: None,
    };
    /// Returns all info collected until the error occurred and puts the error into `processing_error`
    macro_rules! unwrap_or_return_output {
        ( $e:expr ) => {
            match $e {
                Ok(x) => x,
                Err(err) => {
                    output.processing_error = Some(anyhow!(err));
                    return output;
                }
            }
        };
    }
    let mut pc = unwrap_or_return_output!(core.read_core_reg(registers::PC));
    let sp = unwrap_or_return_output!(core.read_core_reg(registers::SP));
    let lr = unwrap_or_return_output!(core.read_core_reg(registers::LR));
    let base_addresses = BaseAddresses::default();
    let mut unwind_context = UninitializedUnwindContext::new();
    let mut registers = Registers::new(lr, sp, core);
    loop {
        if let Some(outcome) =
            check_hard_fault(pc, &elf.vector_table, &mut output, sp, active_ram_region)
        {
            output.outcome = outcome;
        }
        output.raw_frames.push(RawFrame::Subroutine { pc });
        let uwt_row = unwrap_or_return_output!(elf
            .debug_frame
            .unwind_info_for_address(
                &base_addresses,
                &mut unwind_context,
                pc.into(),
                DebugFrame::cie_from_offset,
            )
            .with_context(|| missing_debug_info(pc)));
        let cfa_changed = unwrap_or_return_output!(registers.update_cfa(uwt_row.cfa()));
        for (reg, rule) in uwt_row.registers() {
            unwrap_or_return_output!(registers.update(reg, rule));
        }
        let lr = unwrap_or_return_output!(registers.get(registers::LR));
        log::debug!("LR={:#010X} PC={:#010X}", lr, pc);
        if lr == registers::LR_END {
            break;
        }
        // Link Register contains an EXC_RETURN value. This deliberately also includes
        // invalid combinations of final bits 0-4 to prevent futile backtrace re-generation attempts
        let exception_entry = lr >= cortexm::EXC_RETURN_MARKER;
        let program_counter_changed = !cortexm::subroutine_eq(lr, pc);
        // If the frame didn't move, and the program counter didn't change, bail out (otherwise we
        // might print the same frame over and over).
        output.corrupted = !cfa_changed && !program_counter_changed;
        if output.corrupted {
            break;
        }
        if exception_entry {
            output.raw_frames.push(RawFrame::Exception);
            // Read the `FType` field from the `EXC_RETURN` value.
            let fpu = lr & cortexm::EXC_RETURN_FTYPE_MASK == 0;
            let sp = unwrap_or_return_output!(registers.get(registers::SP));
            let ram_bounds = active_ram_region
                .as_ref()
                .map(|ram_region| ram_region.range.clone())
                .unwrap_or(cortexm::VALID_RAM_ADDRESS);
            let stacked = if let Some(stacked) =
                unwrap_or_return_output!(Stacked::read(registers.core, sp, fpu, ram_bounds))
            {
                stacked
            } else {
                output.corrupted = true;
                break;
            };
            registers.insert(registers::LR, stacked.lr);
            // adjust the stack pointer for stacked registers
            registers.insert(registers::SP, sp + stacked.size());
            pc = stacked.pc;
        } else if cortexm::is_thumb_bit_set(lr) {
            pc = cortexm::clear_thumb_bit(lr);
        } else {
            output.processing_error = Some(anyhow!(
                "bug? LR ({:#010x}) didn't have the Thumb bit set",
                lr
            ));
            return output;
        }
    }
    output
}
pub ( crate ) fn target ( core : & mut Core , elf : & Elf , active_ram_region : & Option < RamRegion > ) -> Output { let mut output = Output { corrupted : true , outcome : Outcome :: Ok , raw_frames : vec ! [ ] , processing_error : None , } ; /// Returns all info collected until the error occurred and puts the error into `processing_error` macro_rules! unwrap_or_return_output { ( $e : expr ) => { match $e { Ok ( x ) x Err ( err ) { output processing_error Some ( anyhow ( err ) ) return output } } } ; } let mut pc = unwrap_or_return_output ! ( core read_core_reg ( registers PC ) ) ; let sp = unwrap_or_return_output ! ( core read_core_reg ( registers SP ) ) ; let lr = unwrap_or_return_output ! ( core read_core_reg ( registers LR ) ) ; let base_addresses = BaseAddresses :: default ( ) ; let mut unwind_context = UninitializedUnwindContext :: new ( ) ; let mut registers = Registers :: new ( lr , sp , core ) ; loop { if let Some ( outcome ) = check_hard_fault ( pc , & elf . vector_table , & mut output , sp , active_ram_region ) { output . outcome = outcome ; } output . raw_frames . push ( RawFrame :: Subroutine { pc } ) ; let uwt_row = unwrap_or_return_output ! ( elf debug_frame unwind_info_for_address ( base_addresses mut unwind_context pc into ( ) DebugFrame cie_from_offset ) with_context ( missing_debug_info ( pc ) ) ) ; let cfa_changed = unwrap_or_return_output ! ( registers update_cfa ( uwt_row cfa ( ) ) ) ; for ( reg , rule ) in uwt_row . registers ( ) { unwrap_or_return_output ! ( registers update ( reg rule ) ) ; } let lr = unwrap_or_return_output ! ( registers get ( registers LR ) ) ; log :: debug ! ( " " lr pc ) ; if lr == registers :: LR_END { break ; } // Link Register contains an EXC_RETURN value. This deliberately also includes // invalid combinations of final bits 0-4 to prevent futile backtrace re-generation attempts let exception_entry = lr >= cortexm :: EXC_RETURN_MARKER ; let program_counter_changed = ! cortexm :: subroutine_eq ( lr , pc ) ; // If the frame didn't move, and the program counter didn't change, bail out (otherwise we // might print the same frame over and over). output . corrupted = ! cfa_changed && ! program_counter_changed ; if output . corrupted { break ; } if exception_entry { output . raw_frames . push ( RawFrame :: Exception ) ; // Read the `FType` field from the `EXC_RETURN` value. let fpu = lr & cortexm :: EXC_RETURN_FTYPE_MASK == 0 ; let sp = unwrap_or_return_output ! ( registers get ( registers SP ) ) ; let ram_bounds = active_ram_region . as_ref ( ) . map ( | ram_region | ram_region . range . clone ( ) ) . unwrap_or ( cortexm :: VALID_RAM_ADDRESS ) ; let stacked = if let Some ( stacked ) = unwrap_or_return_output ! ( Stacked read ( registers core sp fpu ram_bounds ) ) { stacked } else { output . corrupted = true ; break ; } ; registers . insert ( registers :: LR , stacked . lr ) ; // adjust the stack pointer for stacked registers registers . insert ( registers :: SP , sp + stacked . size ( ) ) ; pc = stacked . pc ; } else if cortexm :: is_thumb_bit_set ( lr ) { pc = cortexm :: clear_thumb_bit ( lr ) ; } else { output . processing_error = Some ( anyhow ! ( " " lr ) ) ; return output ; } } output }
Virtually* unwinds the target's program
\* destructors are not run
Virtually * unwinds the target ' s program \ * destructors are not run
core
&mut Core
elf
&Elf
active_ram_region
&Option<RamRegion>
core
&mut Core
elf
&Elf
active_ram_region
&Option<RamRegion>