support a few DWARF-5 only features (#1410)

Support a few DWARF-5 only features:

* read .debug_addr
* read .debug_rnglists
* read .debug_loclists when present
* add dwarf-5 test
* read .debug_addr
* read .debug_rnglists
* read .debug_loclists when present
* support .debug_line_str and .debug_str_offsets

Co-authored-by: Yury Delendik <ydelendik@mozilla.com>
This commit is contained in:
Gabor Greif
2020-04-28 00:27:22 +02:00
committed by GitHub
parent d6b1589926
commit 1639ed0e2e
12 changed files with 202 additions and 99 deletions

View File

@@ -170,6 +170,9 @@ fn has_valid_code_range<R: Reader<Offset = usize>>(
} else if let Some(low_pc) = die.attr_value(constants::DW_AT_low_pc)? { } else if let Some(low_pc) = die.attr_value(constants::DW_AT_low_pc)? {
if let read::AttributeValue::Addr(a) = low_pc { if let read::AttributeValue::Addr(a) = low_pc {
return Ok(at.can_translate_address(a)); return Ok(at.can_translate_address(a));
} else if let read::AttributeValue::DebugAddrIndex(i) = low_pc {
let a = dwarf.debug_addr.get_address(4, unit.addr_base, i)?;
return Ok(at.can_translate_address(a));
} }
} }
} }

View File

@@ -61,47 +61,41 @@ fn convert_sections<'a>(sections: HashMap<&str, &'a [u8]>) -> Result<Dwarf<'a>>
sections.get(".debug_line").unwrap_or(&EMPTY_SECTION), sections.get(".debug_line").unwrap_or(&EMPTY_SECTION),
endian, endian,
); );
let debug_addr = DebugAddr::from(EndianSlice::new(
sections.get(".debug_addr").unwrap_or(&EMPTY_SECTION),
endian,
));
if sections.contains_key(".debug_addr") { let debug_line_str = DebugLineStr::from(EndianSlice::new(
bail!("Unexpected .debug_addr"); sections.get(".debug_line_str").unwrap_or(&EMPTY_SECTION),
} endian,
));
let debug_addr = DebugAddr::from(EndianSlice::new(EMPTY_SECTION, endian));
if sections.contains_key(".debug_line_str") {
bail!("Unexpected .debug_line_str");
}
let debug_line_str = DebugLineStr::from(EndianSlice::new(EMPTY_SECTION, endian));
let debug_str_sup = DebugStr::from(EndianSlice::new(EMPTY_SECTION, endian)); let debug_str_sup = DebugStr::from(EndianSlice::new(EMPTY_SECTION, endian));
if sections.contains_key(".debug_rnglists") {
bail!("Unexpected .debug_rnglists");
}
let debug_ranges = match sections.get(".debug_ranges") { let debug_ranges = match sections.get(".debug_ranges") {
Some(section) => DebugRanges::new(section, endian), Some(section) => DebugRanges::new(section, endian),
None => DebugRanges::new(EMPTY_SECTION, endian), None => DebugRanges::new(EMPTY_SECTION, endian),
}; };
let debug_rnglists = DebugRngLists::new(EMPTY_SECTION, endian); let debug_rnglists = match sections.get(".debug_rnglists") {
Some(section) => DebugRngLists::new(section, endian),
None => DebugRngLists::new(EMPTY_SECTION, endian),
};
let ranges = RangeLists::new(debug_ranges, debug_rnglists); let ranges = RangeLists::new(debug_ranges, debug_rnglists);
if sections.contains_key(".debug_loclists") {
bail!("Unexpected .debug_loclists");
}
let debug_loc = match sections.get(".debug_loc") { let debug_loc = match sections.get(".debug_loc") {
Some(section) => DebugLoc::new(section, endian), Some(section) => DebugLoc::new(section, endian),
None => DebugLoc::new(EMPTY_SECTION, endian), None => DebugLoc::new(EMPTY_SECTION, endian),
}; };
let debug_loclists = DebugLocLists::new(EMPTY_SECTION, endian); let debug_loclists = match sections.get(".debug_loclists") {
Some(section) => DebugLocLists::new(section, endian),
None => DebugLocLists::new(EMPTY_SECTION, endian),
};
let locations = LocationLists::new(debug_loc, debug_loclists); let locations = LocationLists::new(debug_loc, debug_loclists);
if sections.contains_key(".debug_str_offsets") { let debug_str_offsets = DebugStrOffsets::from(EndianSlice::new(
bail!("Unexpected .debug_str_offsets"); sections.get(".debug_str_offsets").unwrap_or(&EMPTY_SECTION),
} endian,
));
let debug_str_offsets = DebugStrOffsets::from(EndianSlice::new(EMPTY_SECTION, endian));
if sections.contains_key(".debug_types") { if sections.contains_key(".debug_types") {
bail!("Unexpected .debug_types"); bail!("Unexpected .debug_types");

View File

@@ -4,12 +4,20 @@ use super::range_info_builder::RangeInfoBuilder;
use super::refs::{PendingDebugInfoRefs, PendingUnitRefs}; use super::refs::{PendingDebugInfoRefs, PendingUnitRefs};
use super::{DebugInputContext, Reader, TransformError}; use super::{DebugInputContext, Reader, TransformError};
use anyhow::{bail, Error}; use anyhow::{bail, Error};
use gimli::{write, AttributeValue, DebugLineOffset, DebugStr, DebuggingInformationEntry}; use gimli::{
write, AttributeValue, DebugLineOffset, DebugLineStr, DebugStr, DebugStrOffsets,
DebuggingInformationEntry, Unit,
};
use wasmtime_environ::isa::TargetIsa; use wasmtime_environ::isa::TargetIsa;
#[derive(Debug)]
pub(crate) enum FileAttributeContext<'a> { pub(crate) enum FileAttributeContext<'a> {
Root(Option<DebugLineOffset>), Root(Option<DebugLineOffset>),
Children(&'a Vec<write::FileId>, Option<&'a CompiledExpression<'a>>), Children(
&'a Vec<write::FileId>,
u64,
Option<&'a CompiledExpression<'a>>,
),
} }
fn is_exprloc_to_loclist_allowed(attr_name: gimli::constants::DwAt) -> bool { fn is_exprloc_to_loclist_allowed(attr_name: gimli::constants::DwAt) -> bool {
@@ -28,11 +36,11 @@ fn is_exprloc_to_loclist_allowed(attr_name: gimli::constants::DwAt) -> bool {
} }
pub(crate) fn clone_die_attributes<'a, R>( pub(crate) fn clone_die_attributes<'a, R>(
unit: &Unit<R, R::Offset>,
entry: &DebuggingInformationEntry<R>, entry: &DebuggingInformationEntry<R>,
context: &DebugInputContext<R>, context: &DebugInputContext<R>,
addr_tr: &'a AddressTransform, addr_tr: &'a AddressTransform,
frame_info: Option<&FunctionFrameInfo>, frame_info: Option<&FunctionFrameInfo>,
unit_encoding: gimli::Encoding,
out_unit: &mut write::Unit, out_unit: &mut write::Unit,
current_scope_id: write::UnitEntryId, current_scope_id: write::UnitEntryId,
subprogram_range_builder: Option<RangeInfoBuilder>, subprogram_range_builder: Option<RangeInfoBuilder>,
@@ -49,23 +57,24 @@ where
{ {
let _tag = &entry.tag(); let _tag = &entry.tag();
let endian = gimli::RunTimeEndian::Little; let endian = gimli::RunTimeEndian::Little;
let unit_encoding = unit.encoding();
let range_info = if let Some(subprogram_range_builder) = subprogram_range_builder { let range_info = if let Some(subprogram_range_builder) = subprogram_range_builder {
subprogram_range_builder subprogram_range_builder
} else if entry.tag() == gimli::DW_TAG_compile_unit {
// FIXME currently address_transform operate on a single func range,
// once it is fixed we can properly set DW_AT_ranges attribute.
// Using for now DW_AT_low_pc = 0.
RangeInfoBuilder::Position(0)
} else { } else {
RangeInfoBuilder::from(entry, context, unit_encoding, cu_low_pc)? // FIXME for CU: currently address_transform operate on a single
// function range, and when CU spans multiple ranges the
// transformation may be incomplete.
RangeInfoBuilder::from(unit, entry, context, cu_low_pc)?
}; };
range_info.build(addr_tr, out_unit, current_scope_id); range_info.build(addr_tr, out_unit, current_scope_id);
let mut attrs = entry.attrs(); let mut attrs = entry.attrs();
while let Some(attr) = attrs.next()? { while let Some(attr) = attrs.next()? {
let attr_value = match attr.value() { let attr_value = match attr.value() {
AttributeValue::Addr(_) if attr.name() == gimli::DW_AT_low_pc => { AttributeValue::Addr(_) | AttributeValue::DebugAddrIndex(_)
if attr.name() == gimli::DW_AT_low_pc =>
{
continue; continue;
} }
AttributeValue::Udata(_) if attr.name() == gimli::DW_AT_high_pc => { AttributeValue::Udata(_) if attr.name() == gimli::DW_AT_high_pc => {
@@ -77,11 +86,19 @@ where
AttributeValue::Exprloc(_) if attr.name() == gimli::DW_AT_frame_base => { AttributeValue::Exprloc(_) if attr.name() == gimli::DW_AT_frame_base => {
continue; continue;
} }
AttributeValue::DebugAddrBase(_) | AttributeValue::DebugStrOffsetsBase(_) => {
continue;
}
AttributeValue::Addr(u) => { AttributeValue::Addr(u) => {
let addr = addr_tr.translate(u).unwrap_or(write::Address::Constant(0)); let addr = addr_tr.translate(u).unwrap_or(write::Address::Constant(0));
write::AttributeValue::Address(addr) write::AttributeValue::Address(addr)
} }
AttributeValue::DebugAddrIndex(i) => {
let u = context.debug_addr.get_address(4, unit.addr_base, i)?;
let addr = addr_tr.translate(u).unwrap_or(write::Address::Constant(0));
write::AttributeValue::Address(addr)
}
AttributeValue::Udata(u) => write::AttributeValue::Udata(u), AttributeValue::Udata(u) => write::AttributeValue::Udata(u),
AttributeValue::Data1(d) => write::AttributeValue::Data1(d), AttributeValue::Data1(d) => write::AttributeValue::Data1(d),
AttributeValue::Data2(d) => write::AttributeValue::Data2(d), AttributeValue::Data2(d) => write::AttributeValue::Data2(d),
@@ -99,8 +116,8 @@ where
} }
} }
AttributeValue::FileIndex(i) => { AttributeValue::FileIndex(i) => {
if let FileAttributeContext::Children(file_map, _) = file_context { if let FileAttributeContext::Children(file_map, file_index_base, _) = file_context {
write::AttributeValue::FileIndex(Some(file_map[(i - 1) as usize])) write::AttributeValue::FileIndex(Some(file_map[(i - file_index_base) as usize]))
} else { } else {
return Err(TransformError("unexpected file index attribute").into()); return Err(TransformError("unexpected file index attribute").into());
} }
@@ -109,9 +126,17 @@ where
let s = context.debug_str.get_str(str_offset)?.to_slice()?.to_vec(); let s = context.debug_str.get_str(str_offset)?.to_slice()?.to_vec();
write::AttributeValue::StringRef(out_strings.add(s)) write::AttributeValue::StringRef(out_strings.add(s))
} }
AttributeValue::DebugStrOffsetsIndex(i) => {
let str_offset = context.debug_str_offsets.get_str_offset(
gimli::Format::Dwarf32,
unit.str_offsets_base,
i,
)?;
let s = context.debug_str.get_str(str_offset)?.to_slice()?.to_vec();
write::AttributeValue::StringRef(out_strings.add(s))
}
AttributeValue::RangeListsRef(r) => { AttributeValue::RangeListsRef(r) => {
let range_info = let range_info = RangeInfoBuilder::from_ranges_ref(unit, r, context, cu_low_pc)?;
RangeInfoBuilder::from_ranges_ref(r, context, unit_encoding, cu_low_pc)?;
let range_list_id = range_info.build_ranges(addr_tr, &mut out_unit.ranges); let range_list_id = range_info.build_ranges(addr_tr, &mut out_unit.ranges);
write::AttributeValue::RangeListRef(range_list_id) write::AttributeValue::RangeListRef(range_list_id)
} }
@@ -122,10 +147,10 @@ where
unit_encoding, unit_encoding,
low_pc, low_pc,
&context.debug_addr, &context.debug_addr,
context.debug_addr_base, unit.addr_base,
)?; )?;
let frame_base = if let FileAttributeContext::Children(_, frame_base) = file_context let frame_base =
{ if let FileAttributeContext::Children(_, _, frame_base) = file_context {
frame_base frame_base
} else { } else {
None None
@@ -166,8 +191,8 @@ where
write::AttributeValue::LocationListRef(list_id) write::AttributeValue::LocationListRef(list_id)
} }
AttributeValue::Exprloc(ref expr) => { AttributeValue::Exprloc(ref expr) => {
let frame_base = if let FileAttributeContext::Children(_, frame_base) = file_context let frame_base =
{ if let FileAttributeContext::Children(_, _, frame_base) = file_context {
frame_base frame_base
} else { } else {
None None
@@ -263,7 +288,10 @@ where
pub(crate) fn clone_attr_string<R>( pub(crate) fn clone_attr_string<R>(
attr_value: &AttributeValue<R>, attr_value: &AttributeValue<R>,
form: gimli::DwForm, form: gimli::DwForm,
unit: &Unit<R, R::Offset>,
debug_str: &DebugStr<R>, debug_str: &DebugStr<R>,
debug_str_offsets: &DebugStrOffsets<R>,
debug_line_str: &DebugLineStr<R>,
out_strings: &mut write::StringTable, out_strings: &mut write::StringTable,
) -> Result<write::LineString, Error> ) -> Result<write::LineString, Error>
where where
@@ -273,6 +301,17 @@ where
AttributeValue::DebugStrRef(str_offset) => { AttributeValue::DebugStrRef(str_offset) => {
debug_str.get_str(*str_offset)?.to_slice()?.to_vec() debug_str.get_str(*str_offset)?.to_slice()?.to_vec()
} }
AttributeValue::DebugStrOffsetsIndex(i) => {
let str_offset = debug_str_offsets.get_str_offset(
gimli::Format::Dwarf32,
unit.str_offsets_base,
*i,
)?;
debug_str.get_str(str_offset)?.to_slice()?.to_vec()
}
AttributeValue::DebugLineStrRef(str_offset) => {
debug_line_str.get_str(*str_offset)?.to_slice()?.to_vec()
}
AttributeValue::String(b) => b.to_slice()?.to_vec(), AttributeValue::String(b) => b.to_slice()?.to_vec(),
v => bail!("Unexpected attribute value: {:?}", v), v => bail!("Unexpected attribute value: {:?}", v),
}; };

View File

@@ -3,7 +3,8 @@ use super::attr::clone_attr_string;
use super::{Reader, TransformError}; use super::{Reader, TransformError};
use anyhow::{Context, Error}; use anyhow::{Context, Error};
use gimli::{ use gimli::{
write, DebugLine, DebugLineOffset, DebugStr, DebuggingInformationEntry, LineEncoding, Unit, write, DebugLine, DebugLineOffset, DebugLineStr, DebugStr, DebugStrOffsets,
DebuggingInformationEntry, LineEncoding, Unit,
}; };
use more_asserts::assert_le; use more_asserts::assert_le;
use wasmtime_environ::entity::EntityRef; use wasmtime_environ::entity::EntityRef;
@@ -46,9 +47,11 @@ pub(crate) fn clone_line_program<R>(
addr_tr: &AddressTransform, addr_tr: &AddressTransform,
out_encoding: gimli::Encoding, out_encoding: gimli::Encoding,
debug_str: &DebugStr<R>, debug_str: &DebugStr<R>,
debug_str_offsets: &DebugStrOffsets<R>,
debug_line_str: &DebugLineStr<R>,
debug_line: &DebugLine<R>, debug_line: &DebugLine<R>,
out_strings: &mut write::StringTable, out_strings: &mut write::StringTable,
) -> Result<(write::LineProgram, DebugLineOffset, Vec<write::FileId>), Error> ) -> Result<(write::LineProgram, DebugLineOffset, Vec<write::FileId>, u64), Error>
where where
R: Reader, R: Reader,
{ {
@@ -63,13 +66,19 @@ where
let out_comp_dir = clone_attr_string( let out_comp_dir = clone_attr_string(
comp_dir.as_ref().context("comp_dir")?, comp_dir.as_ref().context("comp_dir")?,
gimli::DW_FORM_strp, gimli::DW_FORM_strp,
unit,
debug_str, debug_str,
debug_str_offsets,
debug_line_str,
out_strings, out_strings,
)?; )?;
let out_comp_name = clone_attr_string( let out_comp_name = clone_attr_string(
comp_name.as_ref().context("comp_name")?, comp_name.as_ref().context("comp_name")?,
gimli::DW_FORM_strp, gimli::DW_FORM_strp,
unit,
debug_str, debug_str,
debug_str_offsets,
debug_line_str,
out_strings, out_strings,
)?; )?;
@@ -81,7 +90,8 @@ where
); );
if let Ok(program) = program { if let Ok(program) = program {
let header = program.header(); let header = program.header();
assert_le!(header.version(), 4, "not supported 5"); let file_index_base = if header.version() < 5 { 1 } else { 0 };
assert_le!(header.version(), 5, "not supported 6");
let line_encoding = LineEncoding { let line_encoding = LineEncoding {
minimum_instruction_length: header.minimum_instruction_length(), minimum_instruction_length: header.minimum_instruction_length(),
maximum_operations_per_instruction: header.maximum_operations_per_instruction(), maximum_operations_per_instruction: header.maximum_operations_per_instruction(),
@@ -102,7 +112,10 @@ where
let dir_id = out_program.add_directory(clone_attr_string( let dir_id = out_program.add_directory(clone_attr_string(
dir_attr, dir_attr,
gimli::DW_FORM_string, gimli::DW_FORM_string,
unit,
debug_str, debug_str,
debug_str_offsets,
debug_line_str,
out_strings, out_strings,
)?); )?);
dirs.push(dir_id); dirs.push(dir_id);
@@ -114,7 +127,10 @@ where
clone_attr_string( clone_attr_string(
&file_entry.path_name(), &file_entry.path_name(),
gimli::DW_FORM_string, gimli::DW_FORM_string,
unit,
debug_str, debug_str,
debug_str_offsets,
debug_line_str,
out_strings, out_strings,
)?, )?,
dir_id, dir_id,
@@ -238,7 +254,7 @@ where
}; };
out_program.row().address_offset = address_offset; out_program.row().address_offset = address_offset;
out_program.row().op_index = *op_index; out_program.row().op_index = *op_index;
out_program.row().file = files[(file_index - 1) as usize]; out_program.row().file = files[(file_index - file_index_base) as usize];
out_program.row().line = *line; out_program.row().line = *line;
out_program.row().column = *column; out_program.row().column = *column;
out_program.row().discriminator = *discriminator; out_program.row().discriminator = *discriminator;
@@ -255,7 +271,7 @@ where
let end_addr = (map.offset + map.len - 1) as u64; let end_addr = (map.offset + map.len - 1) as u64;
out_program.end_sequence(end_addr); out_program.end_sequence(end_addr);
} }
Ok((out_program, offset, files)) Ok((out_program, offset, files, file_index_base))
} else { } else {
Err(TransformError("Valid line program not found").into()) Err(TransformError("Valid line program not found").into())
} }

View File

@@ -5,8 +5,8 @@ use crate::gc::build_dependencies;
use crate::DebugInfoData; use crate::DebugInfoData;
use anyhow::Error; use anyhow::Error;
use gimli::{ use gimli::{
write, DebugAddr, DebugAddrBase, DebugLine, DebugStr, LocationLists, RangeLists, write, DebugAddr, DebugLine, DebugLineStr, DebugStr, DebugStrOffsets, LocationLists,
UnitSectionOffset, RangeLists, UnitSectionOffset,
}; };
use std::collections::HashSet; use std::collections::HashSet;
use thiserror::Error; use thiserror::Error;
@@ -38,9 +38,10 @@ where
R: Reader, R: Reader,
{ {
debug_str: &'a DebugStr<R>, debug_str: &'a DebugStr<R>,
debug_str_offsets: &'a DebugStrOffsets<R>,
debug_line_str: &'a DebugLineStr<R>,
debug_line: &'a DebugLine<R>, debug_line: &'a DebugLine<R>,
debug_addr: &'a DebugAddr<R>, debug_addr: &'a DebugAddr<R>,
debug_addr_base: DebugAddrBase<R::Offset>,
rnglists: &'a RangeLists<R>, rnglists: &'a RangeLists<R>,
loclists: &'a LocationLists<R>, loclists: &'a LocationLists<R>,
reachable: &'a HashSet<UnitSectionOffset>, reachable: &'a HashSet<UnitSectionOffset>,
@@ -58,9 +59,10 @@ pub fn transform_dwarf(
let context = DebugInputContext { let context = DebugInputContext {
debug_str: &di.dwarf.debug_str, debug_str: &di.dwarf.debug_str,
debug_str_offsets: &di.dwarf.debug_str_offsets,
debug_line_str: &di.dwarf.debug_line_str,
debug_line: &di.dwarf.debug_line, debug_line: &di.dwarf.debug_line,
debug_addr: &di.dwarf.debug_addr, debug_addr: &di.dwarf.debug_addr,
debug_addr_base: DebugAddrBase(0),
rnglists: &di.dwarf.ranges, rnglists: &di.dwarf.ranges,
loclists: &di.dwarf.locations, loclists: &di.dwarf.locations,
reachable: &reachable, reachable: &reachable,

View File

@@ -1,7 +1,7 @@
use super::address_transform::AddressTransform; use super::address_transform::AddressTransform;
use super::{DebugInputContext, Reader}; use super::{DebugInputContext, Reader};
use anyhow::Error; use anyhow::Error;
use gimli::{write, AttributeValue, DebuggingInformationEntry, RangeListsOffset}; use gimli::{write, AttributeValue, DebuggingInformationEntry, RangeListsOffset, Unit};
use more_asserts::assert_lt; use more_asserts::assert_lt;
use wasmtime_environ::entity::EntityRef; use wasmtime_environ::entity::EntityRef;
use wasmtime_environ::wasm::DefinedFuncIndex; use wasmtime_environ::wasm::DefinedFuncIndex;
@@ -15,21 +15,25 @@ pub(crate) enum RangeInfoBuilder {
impl RangeInfoBuilder { impl RangeInfoBuilder {
pub(crate) fn from<R>( pub(crate) fn from<R>(
unit: &Unit<R, R::Offset>,
entry: &DebuggingInformationEntry<R>, entry: &DebuggingInformationEntry<R>,
context: &DebugInputContext<R>, context: &DebugInputContext<R>,
unit_encoding: gimli::Encoding,
cu_low_pc: u64, cu_low_pc: u64,
) -> Result<Self, Error> ) -> Result<Self, Error>
where where
R: Reader, R: Reader,
{ {
if let Some(AttributeValue::RangeListsRef(r)) = entry.attr_value(gimli::DW_AT_ranges)? { if let Some(AttributeValue::RangeListsRef(r)) = entry.attr_value(gimli::DW_AT_ranges)? {
return RangeInfoBuilder::from_ranges_ref(r, context, unit_encoding, cu_low_pc); return RangeInfoBuilder::from_ranges_ref(unit, r, context, cu_low_pc);
}; };
let low_pc = let low_pc =
if let Some(AttributeValue::Addr(addr)) = entry.attr_value(gimli::DW_AT_low_pc)? { if let Some(AttributeValue::Addr(addr)) = entry.attr_value(gimli::DW_AT_low_pc)? {
addr addr
} else if let Some(AttributeValue::DebugAddrIndex(i)) =
entry.attr_value(gimli::DW_AT_low_pc)?
{
context.debug_addr.get_address(4, unit.addr_base, i)?
} else { } else {
return Ok(RangeInfoBuilder::Undefined); return Ok(RangeInfoBuilder::Undefined);
}; };
@@ -44,20 +48,21 @@ impl RangeInfoBuilder {
} }
pub(crate) fn from_ranges_ref<R>( pub(crate) fn from_ranges_ref<R>(
unit: &Unit<R, R::Offset>,
ranges: RangeListsOffset, ranges: RangeListsOffset,
context: &DebugInputContext<R>, context: &DebugInputContext<R>,
unit_encoding: gimli::Encoding,
cu_low_pc: u64, cu_low_pc: u64,
) -> Result<Self, Error> ) -> Result<Self, Error>
where where
R: Reader, R: Reader,
{ {
let unit_encoding = unit.encoding();
let mut ranges = context.rnglists.ranges( let mut ranges = context.rnglists.ranges(
ranges, ranges,
unit_encoding, unit_encoding,
cu_low_pc, cu_low_pc,
&context.debug_addr, &context.debug_addr,
context.debug_addr_base, unit.addr_base,
)?; )?;
let mut result = Vec::new(); let mut result = Vec::new();
while let Some(range) = ranges.next()? { while let Some(range) = ranges.next()? {
@@ -75,18 +80,23 @@ impl RangeInfoBuilder {
} }
pub(crate) fn from_subprogram_die<R>( pub(crate) fn from_subprogram_die<R>(
unit: &Unit<R, R::Offset>,
entry: &DebuggingInformationEntry<R>, entry: &DebuggingInformationEntry<R>,
context: &DebugInputContext<R>, context: &DebugInputContext<R>,
unit_encoding: gimli::Encoding,
addr_tr: &AddressTransform, addr_tr: &AddressTransform,
cu_low_pc: u64, cu_low_pc: u64,
) -> Result<Self, Error> ) -> Result<Self, Error>
where where
R: Reader, R: Reader,
{ {
let unit_encoding = unit.encoding();
let addr = let addr =
if let Some(AttributeValue::Addr(addr)) = entry.attr_value(gimli::DW_AT_low_pc)? { if let Some(AttributeValue::Addr(addr)) = entry.attr_value(gimli::DW_AT_low_pc)? {
addr addr
} else if let Some(AttributeValue::DebugAddrIndex(i)) =
entry.attr_value(gimli::DW_AT_low_pc)?
{
context.debug_addr.get_address(4, unit.addr_base, i)?
} else if let Some(AttributeValue::RangeListsRef(r)) = } else if let Some(AttributeValue::RangeListsRef(r)) =
entry.attr_value(gimli::DW_AT_ranges)? entry.attr_value(gimli::DW_AT_ranges)?
{ {
@@ -95,7 +105,7 @@ impl RangeInfoBuilder {
unit_encoding, unit_encoding,
cu_low_pc, cu_low_pc,
&context.debug_addr, &context.debug_addr,
context.debug_addr_base, unit.addr_base,
)?; )?;
if let Some(range) = ranges.next()? { if let Some(range) = ranges.next()? {
range.begin range.begin

View File

@@ -246,15 +246,18 @@ where
// Iterate over all of this compilation unit's entries. // Iterate over all of this compilation unit's entries.
let mut entries = unit.entries(); let mut entries = unit.entries();
let (mut comp_unit, unit_id, file_map, cu_low_pc, wp_die_id, vmctx_die_id) = let (mut comp_unit, unit_id, file_map, file_index_base, cu_low_pc, wp_die_id, vmctx_die_id) =
if let Some((depth_delta, entry)) = entries.next_dfs()? { if let Some((depth_delta, entry)) = entries.next_dfs()? {
assert_eq!(depth_delta, 0); assert_eq!(depth_delta, 0);
let (out_line_program, debug_line_offset, file_map) = clone_line_program( let (out_line_program, debug_line_offset, file_map, file_index_base) =
clone_line_program(
&unit, &unit,
entry, entry,
addr_tr, addr_tr,
out_encoding, out_encoding,
context.debug_str, context.debug_str,
context.debug_str_offsets,
context.debug_line_str,
context.debug_line, context.debug_line,
out_strings, out_strings,
)?; )?;
@@ -270,17 +273,21 @@ where
entry.attr_value(gimli::DW_AT_low_pc)? entry.attr_value(gimli::DW_AT_low_pc)?
{ {
addr addr
} else if let Some(AttributeValue::DebugAddrIndex(i)) =
entry.attr_value(gimli::DW_AT_low_pc)?
{
context.debug_addr.get_address(4, unit.addr_base, i)?
} else { } else {
// FIXME? return Err(TransformError("No low_pc for unit header").into()); // FIXME? return Err(TransformError("No low_pc for unit header").into());
0 0
}; };
clone_die_attributes( clone_die_attributes(
&unit,
entry, entry,
context, context,
addr_tr, addr_tr,
None, None,
unit.encoding(),
comp_unit, comp_unit,
root_id, root_id,
None, None,
@@ -301,6 +308,7 @@ where
comp_unit, comp_unit,
unit_id, unit_id,
file_map, file_map,
file_index_base,
cu_low_pc, cu_low_pc,
wp_die_id, wp_die_id,
vmctx_die_id, vmctx_die_id,
@@ -342,13 +350,8 @@ where
current_scope_ranges.update(new_stack_len); current_scope_ranges.update(new_stack_len);
current_value_range.update(new_stack_len); current_value_range.update(new_stack_len);
let range_builder = if entry.tag() == gimli::DW_TAG_subprogram { let range_builder = if entry.tag() == gimli::DW_TAG_subprogram {
let range_builder = RangeInfoBuilder::from_subprogram_die( let range_builder =
entry, RangeInfoBuilder::from_subprogram_die(&unit, entry, context, addr_tr, cu_low_pc)?;
context,
unit.encoding(),
addr_tr,
cu_low_pc,
)?;
if let RangeInfoBuilder::Function(func_index) = range_builder { if let RangeInfoBuilder::Function(func_index) = range_builder {
if let Some(frame_info) = if let Some(frame_info) =
get_function_frame_info(module_info, func_index, value_ranges) get_function_frame_info(module_info, func_index, value_ranges)
@@ -366,8 +369,7 @@ where
let high_pc = entry.attr_value(gimli::DW_AT_high_pc)?; let high_pc = entry.attr_value(gimli::DW_AT_high_pc)?;
let ranges = entry.attr_value(gimli::DW_AT_ranges)?; let ranges = entry.attr_value(gimli::DW_AT_ranges)?;
if high_pc.is_some() || ranges.is_some() { if high_pc.is_some() || ranges.is_some() {
let range_builder = let range_builder = RangeInfoBuilder::from(&unit, entry, context, cu_low_pc)?;
RangeInfoBuilder::from(entry, context, unit.encoding(), cu_low_pc)?;
current_scope_ranges.push(new_stack_len, range_builder.get_ranges(addr_tr)); current_scope_ranges.push(new_stack_len, range_builder.get_ranges(addr_tr));
Some(range_builder) Some(range_builder)
} else { } else {
@@ -417,11 +419,11 @@ where
die_ref_map.insert(entry.offset(), die_id); die_ref_map.insert(entry.offset(), die_id);
clone_die_attributes( clone_die_attributes(
&unit,
entry, entry,
context, context,
addr_tr, addr_tr,
current_value_range.top(), current_value_range.top(),
unit.encoding(),
&mut comp_unit, &mut comp_unit,
die_id, die_id,
range_builder, range_builder,
@@ -430,7 +432,7 @@ where
out_strings, out_strings,
&mut pending_die_refs, &mut pending_die_refs,
&mut pending_di_refs, &mut pending_di_refs,
FileAttributeContext::Children(&file_map, current_frame_base.top()), FileAttributeContext::Children(&file_map, file_index_base, current_frame_base.top()),
isa, isa,
)?; )?;

Binary file not shown.

View File

@@ -1,10 +1,13 @@
// Compile with: // Compile with:
// clang --target=wasm32 fib-wasm.c -o fib-wasm.wasm -g \ // clang --target=wasm32 fib-wasm.c -o fib-wasm.wasm -gdwarf-4 \
// -Wl,--no-entry,--export=fib -nostdlib -fdebug-prefix-map=$PWD=.
//
// clang --target=wasm32 fib-wasm.c -o fib-wasm-dwarf5.wasm -gdwarf-5 \
// -Wl,--no-entry,--export=fib -nostdlib -fdebug-prefix-map=$PWD=. // -Wl,--no-entry,--export=fib -nostdlib -fdebug-prefix-map=$PWD=.
int fib(int n) { int fib(int n) {
int i, t, a = 0, b = 1; int t, a = 0, b = 1;
for (i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
t = a; t = a;
a = b; a = b;
b += t; b += t;

View File

@@ -41,17 +41,51 @@ check: DW_AT_name ("fib")
# Accepts one parameter # Accepts one parameter
check: DW_TAG_formal_parameter check: DW_TAG_formal_parameter
check: DW_AT_name ("n") check: DW_AT_name ("n")
check: DW_AT_decl_line (5) check: DW_AT_decl_line (8)
# Has four locals: i, t, a, b # Has four locals: t, a, b, i
check: DW_TAG_variable
check: DW_AT_name ("i")
check: DW_AT_decl_line (6)
check: DW_TAG_variable check: DW_TAG_variable
check: DW_AT_name ("t") check: DW_AT_name ("t")
check: DW_AT_decl_line (9)
check: DW_TAG_variable check: DW_TAG_variable
check: DW_AT_name ("a") check: DW_AT_name ("a")
check: DW_TAG_variable check: DW_TAG_variable
check: DW_AT_name ("b") check: DW_AT_name ("b")
check: DW_TAG_variable
check: DW_AT_name ("i")
check: DW_AT_decl_line (10)
"##,
)
}
#[test]
#[ignore]
#[cfg(all(
any(target_os = "linux", target_os = "macos"),
target_pointer_width = "64"
))]
fn test_debug_dwarf5_translate() -> Result<()> {
check_wasm(
"tests/debug/testsuite/fib-wasm-dwarf5.wasm",
r##"
check: DW_TAG_compile_unit
# We have "fib" function
check: DW_TAG_subprogram
check: DW_AT_name ("fib")
# Accepts one parameter
check: DW_TAG_formal_parameter
check: DW_AT_name ("n")
check: DW_AT_decl_line (8)
# Has four locals: t, a, b, i
check: DW_TAG_variable
check: DW_AT_name ("t")
check: DW_AT_decl_line (9)
check: DW_TAG_variable
check: DW_AT_name ("a")
check: DW_TAG_variable
check: DW_AT_name ("b")
check: DW_TAG_variable
check: DW_AT_name ("i")
check: DW_AT_decl_line (10)
"##, "##,
) )
} }

Binary file not shown.