|  | 
|  | 1 | +//@ ignore-windows | 
|  | 2 | +//@ ignore-apple | 
|  | 3 | + | 
|  | 4 | +// This test should be replaced with one in tests/debuginfo once we can easily | 
|  | 5 | +// tell via GDB or LLDB if debuginfo contains source code. Cheap tricks in LLDB | 
|  | 6 | +// like setting an invalid source map path don't appear to work, maybe this'll | 
|  | 7 | +// become easier once GDB supports DWARFv6? | 
|  | 8 | + | 
|  | 9 | +use gimli::{AttributeValue, EndianRcSlice, Reader, RunTimeEndian}; | 
|  | 10 | +use object::{Object, ObjectSection}; | 
|  | 11 | +use run_make_support::{fs_wrapper, gimli, object, rustc}; | 
|  | 12 | +use std::collections::HashMap; | 
|  | 13 | +use std::path::PathBuf; | 
|  | 14 | +use std::rc::Rc; | 
|  | 15 | + | 
|  | 16 | +fn main() { | 
|  | 17 | +    let output = PathBuf::from("embed-source-main"); | 
|  | 18 | +    rustc() | 
|  | 19 | +        .input("main.rs") | 
|  | 20 | +        .output(&output) | 
|  | 21 | +        .arg("-g") | 
|  | 22 | +        .arg("-Zembed-source=yes") | 
|  | 23 | +        .arg("-Zdwarf-version=5") | 
|  | 24 | +        .run(); | 
|  | 25 | +    let output = fs_wrapper::read(output); | 
|  | 26 | +    let obj = object::File::parse(output.as_slice()).unwrap(); | 
|  | 27 | +    let endian = if obj.is_little_endian() { RunTimeEndian::Little } else { RunTimeEndian::Big }; | 
|  | 28 | +    let dwarf = gimli::Dwarf::load(|section| -> Result<_, ()> { | 
|  | 29 | +        let data = obj.section_by_name(section.name()).map(|s| s.uncompressed_data().unwrap()); | 
|  | 30 | +        Ok(EndianRcSlice::new(Rc::from(data.unwrap_or_default().as_ref()), endian)) | 
|  | 31 | +    }) | 
|  | 32 | +    .unwrap(); | 
|  | 33 | + | 
|  | 34 | +    let mut sources = HashMap::new(); | 
|  | 35 | + | 
|  | 36 | +    let mut iter = dwarf.units(); | 
|  | 37 | +    while let Some(header) = iter.next().unwrap() { | 
|  | 38 | +        let unit = dwarf.unit(header).unwrap(); | 
|  | 39 | +        let unit = unit.unit_ref(&dwarf); | 
|  | 40 | + | 
|  | 41 | +        if let Some(program) = &unit.line_program { | 
|  | 42 | +            let header = program.header(); | 
|  | 43 | +            for file in header.file_names() { | 
|  | 44 | +                if let Some(source) = file.source() { | 
|  | 45 | +                    let path = unit | 
|  | 46 | +                        .attr_string(file.path_name()) | 
|  | 47 | +                        .unwrap() | 
|  | 48 | +                        .to_string_lossy() | 
|  | 49 | +                        .unwrap() | 
|  | 50 | +                        .to_string(); | 
|  | 51 | +                    let source = | 
|  | 52 | +                        unit.attr_string(source).unwrap().to_string_lossy().unwrap().to_string(); | 
|  | 53 | +                    if !source.is_empty() { | 
|  | 54 | +                        sources.insert(path, source); | 
|  | 55 | +                    } | 
|  | 56 | +                } | 
|  | 57 | +            } | 
|  | 58 | +        } | 
|  | 59 | +    } | 
|  | 60 | + | 
|  | 61 | +    dbg!(&sources); | 
|  | 62 | +    assert_eq!(sources.len(), 1); | 
|  | 63 | +    assert_eq!(sources.get("main.rs").unwrap(), "// hello\nfn main() {}\n"); | 
|  | 64 | +} | 
0 commit comments