Skip to content
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

Add very basic logging to the debug info transform #9526

Merged
merged 4 commits into from
Nov 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,7 @@ all-arch = ["wasmtime/all-arch"]
winch = ["wasmtime/winch"]
pulley = ["wasmtime/pulley"]
wmemcheck = ["wasmtime/wmemcheck"]
trace-log = ["wasmtime/trace-log"]
memory-protection-keys = ["wasmtime-cli-flags/memory-protection-keys"]

# This feature, when enabled, will statically compile out all logging statements
Expand Down
2 changes: 1 addition & 1 deletion cranelift/codegen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ pub mod incremental_cache;
#[macro_export]
macro_rules! trace {
($($tt:tt)*) => {
if cfg!(feature = "trace-log") {
if cfg!(any(feature = "trace-log", debug_assertions)) {
::log::trace!($($tt)*);
}
};
Expand Down
1 change: 1 addition & 0 deletions crates/cranelift/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ itertools = "0.12"
all-arch = ["cranelift-codegen/all-arch"]
host-arch = ["cranelift-codegen/host-arch"]
pulley = ["cranelift-codegen/pulley"]
trace-log = ["cranelift-codegen/trace-log"]
component-model = ["wasmtime-environ/component-model"]
incremental-cache = ["cranelift-codegen/incremental-cache"]
wmemcheck = ["wasmtime-environ/wmemcheck"]
Expand Down
21 changes: 21 additions & 0 deletions crates/cranelift/src/debug.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! Debug utils for WebAssembly using Cranelift.

use crate::CompiledFunctionMetadata;
use core::fmt;
use cranelift_codegen::isa::TargetIsa;
use object::write::SymbolId;
use std::collections::HashMap;
Expand Down Expand Up @@ -171,6 +172,26 @@ impl<'a> Compilation<'a> {
}
}

impl<'a> fmt::Debug for Compilation<'a> {
// Sample output: '[#0: OneModule, #1: TwoModule, #3]'.
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "[")?;
let mut is_first_module = true;
for (i, translation) in self.translations {
if !is_first_module {
write!(f, ", ")?;
} else {
is_first_module = false;
}
write!(f, "#{}", i.as_u32())?;
if let Some(name) = translation.debuginfo.name_section.module_name {
write!(f, ": {name}")?;
}
}
write!(f, "]")
}
}

pub use write_debuginfo::{emit_dwarf, DwarfSectionRelocTarget};

mod gc;
Expand Down
241 changes: 241 additions & 0 deletions crates/cranelift/src/debug/transform/debug_transform_logging.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,241 @@
use crate::debug::Reader;
use core::fmt;
use gimli::{write, AttributeValue, DebuggingInformationEntry, Dwarf, LittleEndian, Unit};

macro_rules! dbi_log {
($($tt:tt)*) => {
if cfg!(any(feature = "trace-log", debug_assertions)) {
::log::trace!(target: "debug-info-transform", $($tt)*);
}
};
}
pub(crate) use dbi_log;

pub struct CompileUnitSummary<'a> {
unit: &'a Unit<Reader<'a>, usize>,
}

impl<'a> fmt::Debug for CompileUnitSummary<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let unit = self.unit;
let offs: usize = unit.header.offset().as_debug_info_offset().unwrap().0;
write!(f, "0x{offs:08x} [")?;
let comp_dir = match unit.comp_dir {
Some(dir) => &dir.to_string_lossy(),
None => "None",
};
write!(f, "\"{comp_dir}\"")?;
let name = match unit.name {
Some(name) => &name.to_string_lossy(),
None => "None",
};
write!(f, ", \"{name}\"]")
}
}

pub fn log_get_cu_summary<'a>(unit: &'a Unit<Reader<'a>, usize>) -> CompileUnitSummary<'a> {
CompileUnitSummary { unit }
}

struct DieDetailedSummary<'a> {
dwarf: &'a Dwarf<Reader<'a>>,
unit: &'a Unit<Reader<'a>, usize>,
die: &'a DebuggingInformationEntry<'a, 'a, Reader<'a>>,
}

pub fn log_begin_input_die(
dwarf: &Dwarf<Reader<'_>>,
unit: &Unit<Reader<'_>, usize>,
die: &DebuggingInformationEntry<Reader<'_>>,
depth: isize,
) {
dbi_log!(
"=== Begin DIE at 0x{:08x} (depth = {}):\n{:?}",
die.offset().0,
depth,
DieDetailedSummary { dwarf, unit, die }
);
}

impl<'a> fmt::Debug for DieDetailedSummary<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let die = self.die;
let unit = self.unit;
let dwarf = self.dwarf;
write!(f, "{}\n", die.tag())?;

let mut attrs = die.attrs();
while let Some(attr) = attrs.next().unwrap_or(None) {
write!(f, " {} (", attr.name())?;
let attr_value = attr.value();
match attr_value {
AttributeValue::Addr(addr) => {
write!(f, "{addr:08x}")
}
AttributeValue::DebugAddrIndex(index) => {
if let Some(addr) = dwarf.address(unit, index).ok() {
write!(f, "{addr:08x}")
} else {
write!(f, "<error reading address at index: {}>", index.0)
}
}
AttributeValue::Block(d) => write!(f, "{d:?}"),
AttributeValue::Udata(d) => write!(f, "{d}"),
AttributeValue::Data1(d) => write!(f, "{d}"),
AttributeValue::Data2(d) => write!(f, "{d}"),
AttributeValue::Data4(d) => write!(f, "{d}"),
AttributeValue::Data8(d) => write!(f, "{d}"),
AttributeValue::Sdata(d) => write!(f, "{d}"),
AttributeValue::Flag(d) => write!(f, "{d}"),
AttributeValue::DebugLineRef(offset) => write!(f, "0x{:08x}", offset.0),
AttributeValue::FileIndex(index) => write!(f, "0x{index:08x}"),
AttributeValue::String(_)
| AttributeValue::DebugStrRef(_)
| AttributeValue::DebugStrOffsetsIndex(_) => {
if let Ok(s) = dwarf.attr_string(unit, attr_value) {
write!(f, "\"{}\"", &s.to_string_lossy())
} else {
write!(f, "<error reading string>")
}
}
AttributeValue::RangeListsRef(_) | AttributeValue::DebugRngListsIndex(_) => {
let _ = dwarf.attr_ranges_offset(unit, attr_value);
write!(f, "<TODO: rnglist dump>")
}
AttributeValue::LocationListsRef(_) | AttributeValue::DebugLocListsIndex(_) => {
let _ = dwarf.attr_locations_offset(unit, attr_value);
write!(f, "<TODO: loclist dump>")
}
AttributeValue::Exprloc(_) => {
write!(f, "<TODO: exprloc dump>")
}
AttributeValue::Encoding(value) => write!(f, "{value}"),
AttributeValue::DecimalSign(value) => write!(f, "{value}"),
AttributeValue::Endianity(value) => write!(f, "{value}"),
AttributeValue::Accessibility(value) => write!(f, "{value}"),
AttributeValue::Visibility(value) => write!(f, "{value}"),
AttributeValue::Virtuality(value) => write!(f, "{value}"),
AttributeValue::Language(value) => write!(f, "{value}"),
AttributeValue::AddressClass(value) => write!(f, "{value}"),
AttributeValue::IdentifierCase(value) => write!(f, "{value}"),
AttributeValue::CallingConvention(value) => write!(f, "{value}"),
AttributeValue::Inline(value) => write!(f, "{value}"),
AttributeValue::Ordering(value) => write!(f, "{value}"),
AttributeValue::UnitRef(offset) => write!(f, "0x{:08x}", offset.0),
AttributeValue::DebugInfoRef(offset) => write!(f, "0x{:08x}", offset.0),
unexpected_attr => write!(f, "<unexpected attr: {unexpected_attr:?}>"),
}?;
write!(f, ")\n")?;
}
Ok(())
}
}

struct OutDieDetailedSummary<'a> {
die_id: write::UnitEntryId,
unit: &'a write::Unit,
strings: &'a write::StringTable,
}

impl<'a> fmt::Debug for OutDieDetailedSummary<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let die = self.unit.get(self.die_id);
write!(f, "{}\n", die.tag())?;
for attr in die.attrs() {
write!(f, " {} (", attr.name())?;
let attr_value = attr.get();
match attr_value {
write::AttributeValue::Address(addr) => match addr {
write::Address::Constant(addr_value) => write!(f, "{addr_value:08x}"),
write::Address::Symbol { symbol, addend } => {
write!(f, "symbol #{symbol}+{addend}")
}
},
write::AttributeValue::Block(d) => {
write!(f, "{:?}", Reader::new(d.as_slice(), LittleEndian))
}
write::AttributeValue::Udata(d) => write!(f, "{d}"),
write::AttributeValue::Data1(d) => write!(f, "{d}"),
write::AttributeValue::Data2(d) => write!(f, "{d}"),
write::AttributeValue::Data4(d) => write!(f, "{d}"),
write::AttributeValue::Data8(d) => write!(f, "{d}"),
write::AttributeValue::Sdata(d) => write!(f, "{d}"),
write::AttributeValue::Flag(d) => write!(f, "{d}"),
write::AttributeValue::LineProgramRef => write!(f, "LineProgramRef"),
write::AttributeValue::FileIndex(index) => match index {
Some(id) => write!(f, "{id:?}"),
None => write!(f, "<file index missing>"),
},
write::AttributeValue::String(s) => {
write!(f, "\"{}\"", &String::from_utf8_lossy(s))
}
write::AttributeValue::StringRef(id) => {
write!(f, "\"{}\"", &String::from_utf8_lossy(self.strings.get(*id)))
}
write::AttributeValue::RangeListRef(_) => {
write!(f, "<TODO: out rnglist dump>")
}
write::AttributeValue::LocationListRef(_) => {
write!(f, "<TODO: out loclist dump>")
}
write::AttributeValue::Exprloc(_) => {
write!(f, "<TODO: out exprloc dump>")
}
write::AttributeValue::Encoding(value) => write!(f, "{value}"),
write::AttributeValue::DecimalSign(value) => write!(f, "{value}"),
write::AttributeValue::Endianity(value) => write!(f, "{value}"),
write::AttributeValue::Accessibility(value) => write!(f, "{value}"),
write::AttributeValue::Visibility(value) => write!(f, "{value}"),
write::AttributeValue::Virtuality(value) => write!(f, "{value}"),
write::AttributeValue::Language(value) => write!(f, "{value}"),
write::AttributeValue::AddressClass(value) => write!(f, "{value}"),
write::AttributeValue::IdentifierCase(value) => write!(f, "{value}"),
write::AttributeValue::CallingConvention(value) => write!(f, "{value}"),
write::AttributeValue::Inline(value) => write!(f, "{value}"),
write::AttributeValue::Ordering(value) => write!(f, "{value}"),
write::AttributeValue::UnitRef(unit_ref) => write!(f, "{unit_ref:?}>"),
write::AttributeValue::DebugInfoRef(reference) => match reference {
write::Reference::Symbol(index) => write!(f, "symbol #{index}>"),
write::Reference::Entry(unit_id, die_id) => {
write!(f, "{die_id:?} in {unit_id:?}>")
}
},
unexpected_attr => write!(f, "<unexpected attr: {unexpected_attr:?}>"),
}?;
write!(f, ")\n")?;
}
Ok(())
}
}

pub fn log_end_output_die(
input_die: &DebuggingInformationEntry<Reader<'_>>,
die_id: write::UnitEntryId,
unit: &write::Unit,
strings: &write::StringTable,
depth: isize,
) {
dbi_log!(
"=== End DIE at 0x{:08x} (depth = {}):\n{:?}",
input_die.offset().0,
depth,
OutDieDetailedSummary {
die_id,
unit,
strings
}
);
}

pub fn log_end_output_die_skipped(
input_die: &DebuggingInformationEntry<Reader<'_>>,
reason: &str,
depth: isize,
) {
dbi_log!(
"=== End DIE at 0x{:08x} (depth = {}):\n Skipped as {}\n",
input_die.offset().0,
depth,
reason
);
}
6 changes: 6 additions & 0 deletions crates/cranelift/src/debug/transform/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use self::debug_transform_logging::dbi_log;
use self::refs::DebugInfoRefsMap;
use self::simulate::generate_simulated_dwarf;
use self::unit::clone_unit;
Expand All @@ -16,6 +17,7 @@ pub use address_transform::AddressTransform;

mod address_transform;
mod attr;
mod debug_transform_logging;
mod expression;
mod line_program;
mod range_info_builder;
Expand Down Expand Up @@ -141,6 +143,8 @@ pub fn transform_dwarf(
isa: &dyn TargetIsa,
compilation: &mut Compilation<'_>,
) -> Result<write::Dwarf, Error> {
dbi_log!("Commencing DWARF transform for {:?}", compilation);

let mut transforms = PrimaryMap::new();
for (i, _) in compilation.translations.iter() {
transforms.push(AddressTransform::new(compilation, i));
Expand Down Expand Up @@ -176,6 +180,8 @@ pub fn transform_dwarf(
let mut translated = HashSet::new();

for (module, translation) in compilation.translations.iter() {
dbi_log!("[== Transforming CUs for module #{} ==]", module.as_u32());

let addr_tr = &transforms[module];
let di = &translation.debuginfo;
let context = DebugInputContext {
Expand Down
Loading