frame.rs 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. use gimli::{
  2. BaseAddresses, CfaRule, EvaluationResult, Expression, Location, RegisterRule,
  3. UninitializedUnwindContext, UnwindTableRow, Value,
  4. };
  5. use crate::abi::PersonalityRoutine;
  6. use crate::arch::*;
  7. use crate::find_fde::{self, FDEFinder, FDESearchResult};
  8. use crate::util::*;
  9. #[derive(Debug)]
  10. pub struct Frame {
  11. fde_result: FDESearchResult,
  12. row: UnwindTableRow<StaticSlice>,
  13. }
  14. impl Frame {
  15. pub fn from_context(ctx: &Context) -> Result<Option<Self>, gimli::Error> {
  16. let mut ra = ctx[Arch::RA];
  17. // Reached end of stack
  18. if ra == 0 {
  19. return Ok(None);
  20. }
  21. // RA points to the *next* instruction, so move it back 1 byte for the call instruction.
  22. ra -= 1;
  23. let fde_result = match find_fde::get_finder().find_fde(ra as _) {
  24. Some(v) => v,
  25. None => return Ok(None),
  26. };
  27. let mut unwinder = UninitializedUnwindContext::new();
  28. let row = fde_result
  29. .fde
  30. .unwind_info_for_address(
  31. &fde_result.eh_frame,
  32. &fde_result.bases,
  33. &mut unwinder,
  34. ra as _,
  35. )?
  36. .clone();
  37. Ok(Some(Self { fde_result, row }))
  38. }
  39. #[cfg(feature = "dwarf-expr")]
  40. fn evaluate_expression(
  41. &self,
  42. ctx: &Context,
  43. expr: Expression<StaticSlice>,
  44. ) -> Result<usize, gimli::Error> {
  45. let mut eval = expr.evaluation(self.fde_result.fde.cie().encoding());
  46. let mut result = eval.evaluate()?;
  47. loop {
  48. match result {
  49. EvaluationResult::Complete => break,
  50. EvaluationResult::RequiresMemory { address, .. } => {
  51. let value = unsafe { (address as usize as *const usize).read_unaligned() };
  52. result = eval.resume_with_memory(Value::Generic(value as _))?;
  53. }
  54. EvaluationResult::RequiresRegister { register, .. } => {
  55. let value = ctx[register];
  56. result = eval.resume_with_register(Value::Generic(value as _))?;
  57. }
  58. EvaluationResult::RequiresRelocatedAddress(address) => {
  59. let value = unsafe { (address as usize as *const usize).read_unaligned() };
  60. result = eval.resume_with_memory(Value::Generic(value as _))?;
  61. }
  62. _ => unreachable!(),
  63. }
  64. }
  65. Ok(
  66. match eval
  67. .result()
  68. .pop()
  69. .ok_or(gimli::Error::PopWithEmptyStack)?
  70. .location
  71. {
  72. Location::Address { address } => address as usize,
  73. _ => unreachable!(),
  74. },
  75. )
  76. }
  77. #[cfg(not(feature = "dwarf-expr"))]
  78. fn evaluate_expression(
  79. &self,
  80. ctx: &Context,
  81. expr: Expression<StaticSlice>,
  82. ) -> Result<usize, gimli::Error> {
  83. Err(gimli::Error::UnsupportedEvaluation)
  84. }
  85. pub fn unwind(&self, ctx: &Context) -> Result<Context, gimli::Error> {
  86. let row = &self.row;
  87. let mut new_ctx = ctx.clone();
  88. let cfa = match *row.cfa() {
  89. CfaRule::RegisterAndOffset { register, offset } => {
  90. ctx[register].wrapping_add(offset as usize)
  91. }
  92. CfaRule::Expression(expr) => self.evaluate_expression(ctx, expr)?,
  93. };
  94. new_ctx[Arch::SP] = cfa as _;
  95. new_ctx[Arch::RA] = 0;
  96. for (reg, rule) in row.registers() {
  97. let value = match *rule {
  98. RegisterRule::Undefined | RegisterRule::SameValue => ctx[*reg],
  99. RegisterRule::Offset(offset) => unsafe {
  100. *((cfa.wrapping_add(offset as usize)) as *const usize)
  101. },
  102. RegisterRule::ValOffset(offset) => cfa.wrapping_add(offset as usize),
  103. RegisterRule::Register(r) => ctx[r],
  104. RegisterRule::Expression(expr) => {
  105. let addr = self.evaluate_expression(ctx, expr)?;
  106. unsafe { *(addr as *const usize) }
  107. }
  108. RegisterRule::ValExpression(expr) => self.evaluate_expression(ctx, expr)?,
  109. RegisterRule::Architectural => unreachable!(),
  110. };
  111. new_ctx[*reg] = value;
  112. }
  113. Ok(new_ctx)
  114. }
  115. pub fn bases(&self) -> &BaseAddresses {
  116. &self.fde_result.bases
  117. }
  118. pub fn personality(&self) -> Option<PersonalityRoutine> {
  119. self.fde_result
  120. .fde
  121. .personality()
  122. .map(|x| unsafe { deref_pointer(x) })
  123. .map(|x| unsafe { core::mem::transmute(x) })
  124. }
  125. pub fn lsda(&self) -> usize {
  126. self.fde_result
  127. .fde
  128. .lsda()
  129. .map(|x| unsafe { deref_pointer(x) })
  130. .unwrap_or(0)
  131. }
  132. pub fn initial_address(&self) -> usize {
  133. self.fde_result.fde.initial_address() as _
  134. }
  135. }