[wasmtime-debug] Update DWARF expression transform to use new format. (#842)
This commit is contained in:
@@ -295,6 +295,16 @@ impl CompiledExpression {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_old_expression_format(buf: &[u8]) -> bool {
|
||||||
|
// Heuristic to detect old variable expression format without DW_OP_fbreg:
|
||||||
|
// DW_OP_plus_uconst op must be present, but not DW_OP_fbreg.
|
||||||
|
if buf.contains(&(gimli::constants::DW_OP_fbreg.0 as u8)) {
|
||||||
|
// Stop check if DW_OP_fbreg exist.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
buf.contains(&(gimli::constants::DW_OP_plus_uconst.0 as u8))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn compile_expression<R>(
|
pub fn compile_expression<R>(
|
||||||
expr: &Expression<R>,
|
expr: &Expression<R>,
|
||||||
encoding: gimli::Encoding,
|
encoding: gimli::Encoding,
|
||||||
@@ -303,16 +313,17 @@ pub fn compile_expression<R>(
|
|||||||
where
|
where
|
||||||
R: Reader,
|
R: Reader,
|
||||||
{
|
{
|
||||||
|
let mut pc = expr.0.clone();
|
||||||
|
let buf = expr.0.to_slice()?;
|
||||||
let mut parts = Vec::new();
|
let mut parts = Vec::new();
|
||||||
let mut need_deref = false;
|
let mut need_deref = false;
|
||||||
if let Some(frame_base) = frame_base {
|
if is_old_expression_format(&buf) && frame_base.is_some() {
|
||||||
parts.extend_from_slice(&frame_base.parts);
|
// Still supporting old DWARF variable expressions without fbreg.
|
||||||
need_deref = frame_base.need_deref;
|
parts.extend_from_slice(&frame_base.unwrap().parts);
|
||||||
|
need_deref = frame_base.unwrap().need_deref;
|
||||||
}
|
}
|
||||||
let base_len = parts.len();
|
let base_len = parts.len();
|
||||||
let mut pc = expr.0.clone();
|
|
||||||
let mut code_chunk = Vec::new();
|
let mut code_chunk = Vec::new();
|
||||||
let buf = expr.0.to_slice()?;
|
|
||||||
while !pc.is_empty() {
|
while !pc.is_empty() {
|
||||||
let next = buf[pc.offset_from(&expr.0).into_u64() as usize];
|
let next = buf[pc.offset_from(&expr.0).into_u64() as usize];
|
||||||
need_deref = true;
|
need_deref = true;
|
||||||
@@ -333,6 +344,26 @@ where
|
|||||||
let pos = pc.offset_from(&expr.0).into_u64() as usize;
|
let pos = pc.offset_from(&expr.0).into_u64() as usize;
|
||||||
let op = Operation::parse(&mut pc, &expr.0, encoding)?;
|
let op = Operation::parse(&mut pc, &expr.0, encoding)?;
|
||||||
match op {
|
match op {
|
||||||
|
Operation::FrameOffset { offset } => {
|
||||||
|
// Expand DW_OP_fpreg into frame location and DW_OP_plus_uconst.
|
||||||
|
use gimli::write::Writer;
|
||||||
|
if frame_base.is_some() {
|
||||||
|
// Add frame base expressions.
|
||||||
|
if !code_chunk.is_empty() {
|
||||||
|
parts.push(CompiledExpressionPart::Code(code_chunk));
|
||||||
|
code_chunk = Vec::new();
|
||||||
|
}
|
||||||
|
parts.extend_from_slice(&frame_base.unwrap().parts);
|
||||||
|
need_deref = frame_base.unwrap().need_deref;
|
||||||
|
}
|
||||||
|
// Append DW_OP_plus_uconst part.
|
||||||
|
let endian = gimli::RunTimeEndian::Little;
|
||||||
|
let mut writer = write::EndianVec::new(endian);
|
||||||
|
writer.write_u8(gimli::constants::DW_OP_plus_uconst.0 as u8)?;
|
||||||
|
writer.write_uleb128(offset as u64)?;
|
||||||
|
code_chunk.extend(writer.into_vec());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
Operation::Literal { .. } | Operation::PlusConstant { .. } => (),
|
Operation::Literal { .. } | Operation::PlusConstant { .. } => (),
|
||||||
Operation::StackValue => {
|
Operation::StackValue => {
|
||||||
need_deref = false;
|
need_deref = false;
|
||||||
|
|||||||
Reference in New Issue
Block a user