Test basic DWARF generation (#931)
* Add obj generation with debug info * Add simple transform check
This commit is contained in:
30
tests/debug/dump.rs
Normal file
30
tests/debug/dump.rs
Normal file
@@ -0,0 +1,30 @@
|
||||
use anyhow::{bail, Result};
|
||||
use std::env;
|
||||
use std::process::Command;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
#[allow(dead_code)]
|
||||
pub enum DwarfDumpSection {
|
||||
DebugInfo,
|
||||
DebugLine,
|
||||
}
|
||||
|
||||
pub fn get_dwarfdump(obj: &str, section: DwarfDumpSection) -> Result<String> {
|
||||
let dwarfdump = env::var("DWARFDUMP").unwrap_or("llvm-dwarfdump".to_string());
|
||||
let section_flag = match section {
|
||||
DwarfDumpSection::DebugInfo => "-debug-info",
|
||||
DwarfDumpSection::DebugLine => "-debug-line",
|
||||
};
|
||||
let output = Command::new(&dwarfdump)
|
||||
.args(&[section_flag, obj])
|
||||
.output()
|
||||
.expect("success");
|
||||
if !output.status.success() {
|
||||
bail!(
|
||||
"failed to execute {}: {}",
|
||||
dwarfdump,
|
||||
String::from_utf8_lossy(&output.stderr),
|
||||
);
|
||||
}
|
||||
Ok(String::from_utf8_lossy(&output.stdout).to_string())
|
||||
}
|
||||
4
tests/debug/main.rs
Normal file
4
tests/debug/main.rs
Normal file
@@ -0,0 +1,4 @@
|
||||
mod dump;
|
||||
mod obj;
|
||||
mod simulate;
|
||||
mod translate;
|
||||
34
tests/debug/obj.rs
Normal file
34
tests/debug/obj.rs
Normal file
@@ -0,0 +1,34 @@
|
||||
use anyhow::{Context as _, Result};
|
||||
use std::fs::File;
|
||||
use std::path::Path;
|
||||
use target_lexicon::Triple;
|
||||
use wasmtime::Strategy;
|
||||
use wasmtime_cli::compile_to_obj;
|
||||
use wasmtime_environ::CacheConfig;
|
||||
|
||||
pub fn compile_cranelift(
|
||||
wasm: &[u8],
|
||||
target: Option<Triple>,
|
||||
output: impl AsRef<Path>,
|
||||
) -> Result<()> {
|
||||
let obj = compile_to_obj(
|
||||
wasm,
|
||||
target.as_ref(),
|
||||
Strategy::Cranelift,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
output
|
||||
.as_ref()
|
||||
.file_name()
|
||||
.unwrap()
|
||||
.to_string_lossy()
|
||||
.to_string(),
|
||||
&CacheConfig::new_cache_disabled(),
|
||||
)?;
|
||||
|
||||
let file = File::create(output).context("failed to create object file")?;
|
||||
obj.write(file).context("failed to write object file")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
55
tests/debug/simulate.rs
Normal file
55
tests/debug/simulate.rs
Normal file
@@ -0,0 +1,55 @@
|
||||
use super::dump::{get_dwarfdump, DwarfDumpSection};
|
||||
use super::obj::compile_cranelift;
|
||||
use anyhow::{format_err, Result};
|
||||
use filecheck::{CheckerBuilder, NO_VARIABLES};
|
||||
use tempfile::NamedTempFile;
|
||||
use wat::parse_str;
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn check_wat(wat: &str) -> Result<()> {
|
||||
let wasm = parse_str(wat)?;
|
||||
let obj_file = NamedTempFile::new()?;
|
||||
let obj_path = obj_file.path().to_str().unwrap();
|
||||
compile_cranelift(&wasm, None, obj_path)?;
|
||||
let dump = get_dwarfdump(obj_path, DwarfDumpSection::DebugInfo)?;
|
||||
let mut builder = CheckerBuilder::new();
|
||||
builder
|
||||
.text(wat)
|
||||
.map_err(|e| format_err!("unable to build checker: {:?}", e))?;
|
||||
let checker = builder.finish();
|
||||
let check = checker
|
||||
.explain(&dump, NO_VARIABLES)
|
||||
.map_err(|e| format_err!("{:?}", e))?;
|
||||
assert!(check.0, "didn't pass check {}", check.1);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(all(
|
||||
any(target_os = "linux", target_os = "macos"),
|
||||
target_pointer_width = "64"
|
||||
))]
|
||||
fn test_debug_dwarf_simulate_simple_x86_64() -> Result<()> {
|
||||
check_wat(
|
||||
r#"
|
||||
;; check: DW_TAG_compile_unit
|
||||
(module
|
||||
;; check: DW_TAG_subprogram
|
||||
;; check: DW_AT_name ("wasm-function[0]")
|
||||
;; check: DW_TAG_formal_parameter
|
||||
;; check: DW_AT_name ("var0")
|
||||
;; check: DW_AT_type
|
||||
;; sameln: "i32"
|
||||
;; check: DW_TAG_variable
|
||||
;; check: DW_AT_name ("var1")
|
||||
;; check: DW_AT_type
|
||||
;; sameln: "i32"
|
||||
(func (param i32) (result i32)
|
||||
(local i32)
|
||||
local.get 0
|
||||
local.set 1
|
||||
local.get 1
|
||||
)
|
||||
)"#,
|
||||
)
|
||||
}
|
||||
13
tests/debug/testsuite/fib-wasm.c
Normal file
13
tests/debug/testsuite/fib-wasm.c
Normal file
@@ -0,0 +1,13 @@
|
||||
// Compile with:
|
||||
// clang --target=wasm32 fib-wasm.c -o fib-wasm.wasm -g \
|
||||
// -Wl,--no-entry,--export=fib -nostdlib -fdebug-prefix-map=$PWD=.
|
||||
|
||||
int fib(int n) {
|
||||
int i, t, a = 0, b = 1;
|
||||
for (i = 0; i < n; i++) {
|
||||
t = a;
|
||||
a = b;
|
||||
b += t;
|
||||
}
|
||||
return b;
|
||||
}
|
||||
BIN
tests/debug/testsuite/fib-wasm.wasm
Executable file
BIN
tests/debug/testsuite/fib-wasm.wasm
Executable file
Binary file not shown.
56
tests/debug/translate.rs
Normal file
56
tests/debug/translate.rs
Normal file
@@ -0,0 +1,56 @@
|
||||
use super::dump::{get_dwarfdump, DwarfDumpSection};
|
||||
use super::obj::compile_cranelift;
|
||||
use anyhow::{format_err, Result};
|
||||
use filecheck::{CheckerBuilder, NO_VARIABLES};
|
||||
use std::fs::read;
|
||||
use tempfile::NamedTempFile;
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn check_wasm(wasm_path: &str, directives: &str) -> Result<()> {
|
||||
let wasm = read(wasm_path)?;
|
||||
let obj_file = NamedTempFile::new()?;
|
||||
let obj_path = obj_file.path().to_str().unwrap();
|
||||
compile_cranelift(&wasm, None, obj_path)?;
|
||||
let dump = get_dwarfdump(obj_path, DwarfDumpSection::DebugInfo)?;
|
||||
let mut builder = CheckerBuilder::new();
|
||||
builder
|
||||
.text(directives)
|
||||
.map_err(|e| format_err!("unable to build checker: {:?}", e))?;
|
||||
let checker = builder.finish();
|
||||
let check = checker
|
||||
.explain(&dump, NO_VARIABLES)
|
||||
.map_err(|e| format_err!("{:?}", e))?;
|
||||
assert!(check.0, "didn't pass check {}", check.1);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(all(
|
||||
any(target_os = "linux", target_os = "macos"),
|
||||
target_pointer_width = "64"
|
||||
))]
|
||||
fn test_debug_dwarf_translate() -> Result<()> {
|
||||
check_wasm(
|
||||
"tests/debug/testsuite/fib-wasm.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 (5)
|
||||
# Has four locals: i, t, a, b
|
||||
check: DW_TAG_variable
|
||||
check: DW_AT_name ("i")
|
||||
check: DW_AT_decl_line (6)
|
||||
check: DW_TAG_variable
|
||||
check: DW_AT_name ("t")
|
||||
check: DW_TAG_variable
|
||||
check: DW_AT_name ("a")
|
||||
check: DW_TAG_variable
|
||||
check: DW_AT_name ("b")
|
||||
"##,
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user