Skip to content

support a few DWARF-5 only features #1410

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 38 commits into from
Apr 27, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
c0110c8
support a few DWARF-5 only features
ggreif Mar 26, 2020
a6137b0
cargo fmt --all
ggreif Mar 26, 2020
bf1cdd7
read .debug_loclists when present
ggreif Mar 26, 2020
c382447
tmp: enforce addr base to be zero
ggreif Mar 26, 2020
f48c00d
fixup: expect 8 as DebugAddrBase
ggreif Apr 15, 2020
683b365
add an early DWARF-5 example
ggreif Apr 17, 2020
8b681f8
add dwarf-5 test
ggreif Apr 18, 2020
7d925db
fix encoding of DW_OP_WASM_location
ggreif Apr 20, 2020
9540084
support a few DWARF-5 only features
ggreif Mar 26, 2020
7067dff
cargo fmt --all
ggreif Mar 26, 2020
281948e
read .debug_loclists when present
ggreif Mar 26, 2020
d328903
tmp: enforce addr base to be zero
ggreif Mar 26, 2020
33c699a
fixup: expect 8 as DebugAddrBase
ggreif Apr 15, 2020
ca5a79b
add an early DWARF-5 example
ggreif Apr 17, 2020
51c9ea4
add dwarf-5 test
ggreif Apr 18, 2020
186f697
fix encoding of DW_OP_WASM_location
ggreif Apr 20, 2020
67c83f7
handle DebugAddrIndex in two places
ggreif Apr 22, 2020
6d12636
Merge branch 'master' of github.com:ggreif/wasmtime
ggreif Apr 22, 2020
fa85b61
detabify
ggreif Apr 22, 2020
efc7aaa
Merge branch 'master' of github.com:bytecodealliance/wasmtime
ggreif Apr 22, 2020
30c0aa2
Merge github.com:ggreif/wasmtime
ggreif Apr 22, 2020
9da793a
update executables
ggreif Apr 22, 2020
9965a4d
skip over DebugAddrIndex DW_AT_low_pc
ggreif Apr 22, 2020
9a729cc
use or-pattern and reformat
ggreif Apr 22, 2020
6f9826f
let RangeInfoBuilder deal with DW_AT_ranges
ggreif Apr 23, 2020
9d7ab27
resolve two more DebugAddrIndex
ggreif Apr 23, 2020
cc1e974
don't keep DebugAddrBase ourselves, since gimli passes it in Unit
ggreif Apr 23, 2020
8fa26c8
cleanups, fmt
ggreif Apr 23, 2020
b01999e
support .debug_line_str and .debug_str_offsets
ggreif Apr 24, 2020
d117d74
accomodate for the fact that DWARF-5 uses zero-based file indexing
ggreif Apr 24, 2020
c65ea34
cargo fmt
ggreif Apr 24, 2020
2e0b30a
don't bail for inconsistency
ggreif Apr 24, 2020
6e465cf
drop redundant imports
ggreif Apr 24, 2020
cfa0ea9
remove local tests
ggreif Apr 25, 2020
b82d7d8
Update lldb wasm test
yurydelendik Apr 27, 2020
5942490
cleanups
ggreif Apr 27, 2020
903fcb4
cargo fmt
ggreif Apr 27, 2020
589b8c2
restore CU FIXME comment
yurydelendik Apr 27, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions crates/debug/src/gc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)? {
if let read::AttributeValue::Addr(a) = low_pc {
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));
}
}
}
Expand Down
46 changes: 20 additions & 26 deletions crates/debug/src/read_debuginfo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,47 +61,41 @@ fn convert_sections<'a>(sections: HashMap<&str, &'a [u8]>) -> Result<Dwarf<'a>>
sections.get(".debug_line").unwrap_or(&EMPTY_SECTION),
endian,
);
let debug_addr = DebugAddr::from(EndianSlice::new(
sections.get(".debug_addr").unwrap_or(&EMPTY_SECTION),
endian,
));

if sections.contains_key(".debug_addr") {
bail!("Unexpected .debug_addr");
}

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_line_str = DebugLineStr::from(EndianSlice::new(
sections.get(".debug_line_str").unwrap_or(&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") {
Some(section) => DebugRanges::new(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);

if sections.contains_key(".debug_loclists") {
bail!("Unexpected .debug_loclists");
}

let debug_loc = match sections.get(".debug_loc") {
Some(section) => DebugLoc::new(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);

if sections.contains_key(".debug_str_offsets") {
bail!("Unexpected .debug_str_offsets");
}

let debug_str_offsets = DebugStrOffsets::from(EndianSlice::new(EMPTY_SECTION, endian));
let debug_str_offsets = DebugStrOffsets::from(EndianSlice::new(
sections.get(".debug_str_offsets").unwrap_or(&EMPTY_SECTION),
endian,
));

if sections.contains_key(".debug_types") {
bail!("Unexpected .debug_types");
Expand Down
93 changes: 66 additions & 27 deletions crates/debug/src/transform/attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,20 @@ use super::range_info_builder::RangeInfoBuilder;
use super::refs::{PendingDebugInfoRefs, PendingUnitRefs};
use super::{DebugInputContext, Reader, TransformError};
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;

#[derive(Debug)]
pub(crate) enum FileAttributeContext<'a> {
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 {
Expand All @@ -28,11 +36,11 @@ fn is_exprloc_to_loclist_allowed(attr_name: gimli::constants::DwAt) -> bool {
}

pub(crate) fn clone_die_attributes<'a, R>(
unit: &Unit<R, R::Offset>,
entry: &DebuggingInformationEntry<R>,
context: &DebugInputContext<R>,
addr_tr: &'a AddressTransform,
frame_info: Option<&FunctionFrameInfo>,
unit_encoding: gimli::Encoding,
out_unit: &mut write::Unit,
current_scope_id: write::UnitEntryId,
subprogram_range_builder: Option<RangeInfoBuilder>,
Expand All @@ -49,23 +57,24 @@ where
{
let _tag = &entry.tag();
let endian = gimli::RunTimeEndian::Little;
let unit_encoding = unit.encoding();

let range_info = if let Some(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 {
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);

let mut attrs = entry.attrs();
while let Some(attr) = attrs.next()? {
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;
}
AttributeValue::Udata(_) if attr.name() == gimli::DW_AT_high_pc => {
Expand All @@ -77,11 +86,19 @@ where
AttributeValue::Exprloc(_) if attr.name() == gimli::DW_AT_frame_base => {
continue;
}
AttributeValue::DebugAddrBase(_) | AttributeValue::DebugStrOffsetsBase(_) => {
continue;
}

AttributeValue::Addr(u) => {
let addr = addr_tr.translate(u).unwrap_or(write::Address::Constant(0));
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::Data1(d) => write::AttributeValue::Data1(d),
AttributeValue::Data2(d) => write::AttributeValue::Data2(d),
Expand All @@ -99,8 +116,8 @@ where
}
}
AttributeValue::FileIndex(i) => {
if let FileAttributeContext::Children(file_map, _) = file_context {
write::AttributeValue::FileIndex(Some(file_map[(i - 1) as usize]))
if let FileAttributeContext::Children(file_map, file_index_base, _) = file_context {
write::AttributeValue::FileIndex(Some(file_map[(i - file_index_base) as usize]))
} else {
return Err(TransformError("unexpected file index attribute").into());
}
Expand All @@ -109,9 +126,17 @@ where
let s = context.debug_str.get_str(str_offset)?.to_slice()?.to_vec();
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) => {
let range_info =
RangeInfoBuilder::from_ranges_ref(r, context, unit_encoding, cu_low_pc)?;
let range_info = RangeInfoBuilder::from_ranges_ref(unit, r, context, cu_low_pc)?;
let range_list_id = range_info.build_ranges(addr_tr, &mut out_unit.ranges);
write::AttributeValue::RangeListRef(range_list_id)
}
Expand All @@ -122,14 +147,14 @@ where
unit_encoding,
low_pc,
&context.debug_addr,
context.debug_addr_base,
unit.addr_base,
)?;
let frame_base = if let FileAttributeContext::Children(_, frame_base) = file_context
{
frame_base
} else {
None
};
let frame_base =
if let FileAttributeContext::Children(_, _, frame_base) = file_context {
frame_base
} else {
None
};
let mut result = None;
while let Some(loc) = locs.next()? {
if let Some(expr) =
Expand Down Expand Up @@ -166,12 +191,12 @@ where
write::AttributeValue::LocationListRef(list_id)
}
AttributeValue::Exprloc(ref expr) => {
let frame_base = if let FileAttributeContext::Children(_, frame_base) = file_context
{
frame_base
} else {
None
};
let frame_base =
if let FileAttributeContext::Children(_, _, frame_base) = file_context {
frame_base
} else {
None
};
if let Some(expr) = compile_expression(expr, unit_encoding, frame_base, isa)? {
if expr.is_simple() {
if let Some(expr) = expr.build() {
Expand Down Expand Up @@ -263,7 +288,10 @@ where
pub(crate) fn clone_attr_string<R>(
attr_value: &AttributeValue<R>,
form: gimli::DwForm,
unit: &Unit<R, R::Offset>,
debug_str: &DebugStr<R>,
debug_str_offsets: &DebugStrOffsets<R>,
debug_line_str: &DebugLineStr<R>,
out_strings: &mut write::StringTable,
) -> Result<write::LineString, Error>
where
Expand All @@ -273,6 +301,17 @@ where
AttributeValue::DebugStrRef(str_offset) => {
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(),
v => bail!("Unexpected attribute value: {:?}", v),
};
Expand Down
26 changes: 21 additions & 5 deletions crates/debug/src/transform/line_program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ use super::attr::clone_attr_string;
use super::{Reader, TransformError};
use anyhow::{Context, Error};
use gimli::{
write, DebugLine, DebugLineOffset, DebugStr, DebuggingInformationEntry, LineEncoding, Unit,
write, DebugLine, DebugLineOffset, DebugLineStr, DebugStr, DebugStrOffsets,
DebuggingInformationEntry, LineEncoding, Unit,
};
use more_asserts::assert_le;
use wasmtime_environ::entity::EntityRef;
Expand Down Expand Up @@ -46,9 +47,11 @@ pub(crate) fn clone_line_program<R>(
addr_tr: &AddressTransform,
out_encoding: gimli::Encoding,
debug_str: &DebugStr<R>,
debug_str_offsets: &DebugStrOffsets<R>,
debug_line_str: &DebugLineStr<R>,
debug_line: &DebugLine<R>,
out_strings: &mut write::StringTable,
) -> Result<(write::LineProgram, DebugLineOffset, Vec<write::FileId>), Error>
) -> Result<(write::LineProgram, DebugLineOffset, Vec<write::FileId>, u64), Error>
where
R: Reader,
{
Expand All @@ -63,13 +66,19 @@ where
let out_comp_dir = clone_attr_string(
comp_dir.as_ref().context("comp_dir")?,
gimli::DW_FORM_strp,
unit,
debug_str,
debug_str_offsets,
debug_line_str,
out_strings,
)?;
let out_comp_name = clone_attr_string(
comp_name.as_ref().context("comp_name")?,
gimli::DW_FORM_strp,
unit,
debug_str,
debug_str_offsets,
debug_line_str,
out_strings,
)?;

Expand All @@ -81,7 +90,8 @@ where
);
if let Ok(program) = program {
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 {
minimum_instruction_length: header.minimum_instruction_length(),
maximum_operations_per_instruction: header.maximum_operations_per_instruction(),
Expand All @@ -102,7 +112,10 @@ where
let dir_id = out_program.add_directory(clone_attr_string(
dir_attr,
gimli::DW_FORM_string,
unit,
debug_str,
debug_str_offsets,
debug_line_str,
out_strings,
)?);
dirs.push(dir_id);
Expand All @@ -114,7 +127,10 @@ where
clone_attr_string(
&file_entry.path_name(),
gimli::DW_FORM_string,
unit,
debug_str,
debug_str_offsets,
debug_line_str,
out_strings,
)?,
dir_id,
Expand Down Expand Up @@ -238,7 +254,7 @@ where
};
out_program.row().address_offset = address_offset;
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().column = *column;
out_program.row().discriminator = *discriminator;
Expand All @@ -255,7 +271,7 @@ where
let end_addr = (map.offset + map.len - 1) as u64;
out_program.end_sequence(end_addr);
}
Ok((out_program, offset, files))
Ok((out_program, offset, files, file_index_base))
} else {
Err(TransformError("Valid line program not found").into())
}
Expand Down
10 changes: 6 additions & 4 deletions crates/debug/src/transform/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ use crate::gc::build_dependencies;
use crate::DebugInfoData;
use anyhow::Error;
use gimli::{
write, DebugAddr, DebugAddrBase, DebugLine, DebugStr, LocationLists, RangeLists,
UnitSectionOffset,
write, DebugAddr, DebugLine, DebugLineStr, DebugStr, DebugStrOffsets, LocationLists,
RangeLists, UnitSectionOffset,
};
use std::collections::HashSet;
use thiserror::Error;
Expand Down Expand Up @@ -38,9 +38,10 @@ where
R: Reader,
{
debug_str: &'a DebugStr<R>,
debug_str_offsets: &'a DebugStrOffsets<R>,
debug_line_str: &'a DebugLineStr<R>,
debug_line: &'a DebugLine<R>,
debug_addr: &'a DebugAddr<R>,
debug_addr_base: DebugAddrBase<R::Offset>,
rnglists: &'a RangeLists<R>,
loclists: &'a LocationLists<R>,
reachable: &'a HashSet<UnitSectionOffset>,
Expand All @@ -58,9 +59,10 @@ pub fn transform_dwarf(

let context = DebugInputContext {
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_addr: &di.dwarf.debug_addr,
debug_addr_base: DebugAddrBase(0),
rnglists: &di.dwarf.ranges,
loclists: &di.dwarf.locations,
reachable: &reachable,
Expand Down
Loading