dwarf 0.0.3

Read and write DWARF debugging information
Documentation
use super::*;
use constant::*;

#[test]
fn compilation_unit_32() {
    let offset = 0;
    let endian = Endian::Little;
    let data = [0x01, 0x23, 0x45, 0x67];
    let write_val = CompilationUnit {
        offset: offset,
        endian: endian,
        version: 4,
        address_size: 4,
        offset_size: 4,
        abbrev_offset: 0x12,
        data: From::from(&data[..]),
    };

    let mut buf = Vec::new();
    write_val.write(&mut buf).unwrap();

    let mut r = &buf[..];
    let read_val = CompilationUnit::read(&mut r, offset, endian).unwrap();

    assert_eq!(&buf[..], [
        0x0b, 0x00, 0x00, 0x00,
        0x04, 0x00,
        0x12, 0x00, 0x00, 0x00,
        0x04,
        0x01, 0x23, 0x45, 0x67
    ]);
    assert_eq!(r.len(), 0);
    assert_eq!(read_val, write_val);
}

#[test]
fn compilation_unit_64() {
    let offset = 0;
    let endian = Endian::Little;
    let data = [0x01, 0x23, 0x45, 0x67];
    let write_val = CompilationUnit {
        offset: offset,
        endian: endian,
        version: 4,
        address_size: 4,
        offset_size: 8,
        abbrev_offset: 0x12,
        data: From::from(&data[..]),
    };

    let mut buf = Vec::new();
    write_val.write(&mut buf).unwrap();

    let mut r = &buf[..];
    let read_val = CompilationUnit::read(&mut r, offset, endian).unwrap();

    assert_eq!(&buf[..], [
        0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x04, 0x00,
        0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x04,
        0x01, 0x23, 0x45, 0x67
    ]);
    assert_eq!(r.len(), 0);
    assert_eq!(read_val, write_val);
}

#[test]
fn die() {
    let mut abbrev_hash = AbbrevHash::new();
    let code = 1;
    abbrev_hash.insert(Abbrev {
        code: code,
        tag: DW_TAG_namespace,
        children: true,
        attributes: vec![
            AbbrevAttribute { at: DW_AT_name, form: DW_FORM_string },
        ],
    });
    let write_val = Die {
        offset: 0,
        code: code,
        tag: DW_TAG_namespace,
        children: true,
        attributes: vec![
            Attribute { at: DW_AT_name, data: AttributeData::String("test") },
        ],
    };

    let mut unit = CompilationUnit { endian: Endian::Little, ..Default::default() };
    write_val.write(&mut unit, &abbrev_hash).unwrap();

    let mut r = unit.data();
    let read_val = Die::read(&mut r, write_val.offset, &unit, &abbrev_hash).unwrap();

    assert_eq!(unit.data(), [1, b't', b'e', b's', b't', 0]);
    assert_eq!(r.len(), 0);
    assert_eq!(read_val, write_val);
}

#[test]
fn attribute() {
    let abbrev = AbbrevAttribute { at: DW_AT_sibling, form: DW_FORM_ref4 };
    let write_val = Attribute {
        at: DW_AT_sibling,
        data: AttributeData::Ref(0x01234567),
    };

    let mut unit = CompilationUnit { endian: Endian::Little, ..Default::default() };
    write_val.write(&mut unit, &abbrev).unwrap();

    let mut r = unit.data();
    let read_val = Attribute::read(&mut r, &unit, &abbrev).unwrap();

    assert_eq!(unit.data(), [0x67, 0x45, 0x23, 0x01]);
    assert_eq!(r.len(), 0);
    assert_eq!(read_val, write_val);
}

#[test]
fn attribute_data() {
    let mut unit = CompilationUnit {
        endian: Endian::Little,
        ..Default::default()
    };

    unit.address_size = 4;
    unit.offset_size = 4;
    for &(ref write_val, form, expect) in &[
        (AttributeData::Address(0x12345678), DW_FORM_addr, &[0x78, 0x56, 0x34, 0x12][..]),
        (AttributeData::Block(&[0x11, 0x22, 0x33]), DW_FORM_block1, &[0x3, 0x11, 0x22, 0x33][..]),
        (AttributeData::Block(&[0x11, 0x22, 0x33]), DW_FORM_block2, &[0x3, 0x00, 0x11, 0x22, 0x33][..]),
        (AttributeData::Block(&[0x11, 0x22, 0x33]), DW_FORM_block4, &[0x3, 0x00, 0x00, 0x00, 0x11, 0x22, 0x33][..]),
        (AttributeData::Block(&[0x11, 0x22, 0x33]), DW_FORM_block, &[0x3, 0x11, 0x22, 0x33][..]),
        (AttributeData::Data1(0x01), DW_FORM_data1, &[0x01][..]),
        (AttributeData::Data2(0x0123), DW_FORM_data2, &[0x23, 0x01][..]),
        (AttributeData::Data4(0x01234567), DW_FORM_data4, &[0x67, 0x45, 0x23, 0x01][..]),
        (AttributeData::Data8(0x0123456789abcdef), DW_FORM_data8, &[0xef, 0xcd, 0xab, 0x89, 0x67, 0x45, 0x23, 0x01][..]),
        (AttributeData::UData(0x01234567), DW_FORM_udata, &[231, 138, 141, 9][..]),
        (AttributeData::SData(0x01234567), DW_FORM_sdata, &[231, 138, 141, 9][..]),
        (AttributeData::SData(-0x01234567), DW_FORM_sdata, &[153, 245, 242, 118][..]),
        (AttributeData::Flag(false), DW_FORM_flag, &[0][..]),
        (AttributeData::Flag(true), DW_FORM_flag, &[1][..]),
        (AttributeData::Flag(true), DW_FORM_flag_present, &[][..]),
        (AttributeData::String("test"), DW_FORM_string, &[b't', b'e', b's', b't', 0][..]),
        (AttributeData::StringOffset(0x01234567), DW_FORM_strp, &[0x67, 0x45, 0x23, 0x01][..]),
        (AttributeData::Ref(0x01), DW_FORM_ref1, &[0x01][..]),
        (AttributeData::Ref(0x0123), DW_FORM_ref2, &[0x23, 0x01][..]),
        (AttributeData::Ref(0x01234567), DW_FORM_ref4, &[0x67, 0x45, 0x23, 0x01][..]),
        (AttributeData::Ref(0x0123456789abcdef), DW_FORM_ref8, &[0xef, 0xcd, 0xab, 0x89, 0x67, 0x45, 0x23, 0x01][..]),
        (AttributeData::Ref(0x01234567), DW_FORM_ref_udata, &[231, 138, 141, 9][..]),
        (AttributeData::RefAddress(0x12345678), DW_FORM_ref_addr, &[0x78, 0x56, 0x34, 0x12][..]),
        (AttributeData::RefSig(0x0123456789abcdef), DW_FORM_ref_sig8, &[0xef, 0xcd, 0xab, 0x89, 0x67, 0x45, 0x23, 0x01][..]),
        (AttributeData::SecOffset(0x12345678), DW_FORM_sec_offset, &[0x78, 0x56, 0x34, 0x12][..]),
        (AttributeData::ExprLoc(&[0x11, 0x22, 0x33]), DW_FORM_exprloc, &[0x3, 0x11, 0x22, 0x33][..]),
    ] {
        attribute_data_inner(&mut unit, write_val, form, expect);
    }

    unit.address_size = 8;
    unit.offset_size = 4;
    for &(ref write_val, form, expect) in &[
        (AttributeData::Address(0x0123456789), DW_FORM_addr,
            &[0x89, 0x67, 0x45, 0x23, 0x01, 0x00, 0x00, 0x00][..]),
    ] {
        attribute_data_inner(&mut unit, write_val, form, expect);
    }

    unit.address_size = 4;
    unit.offset_size = 8;
    for &(ref write_val, form, expect) in &[
        (AttributeData::StringOffset(0x0123456789), DW_FORM_strp,
            &[0x89, 0x67, 0x45, 0x23, 0x01, 0x00, 0x00, 0x00][..]),
        (AttributeData::RefAddress(0x0123456789), DW_FORM_ref_addr,
            &[0x89, 0x67, 0x45, 0x23, 0x01, 0x00, 0x00, 0x00][..]),
        (AttributeData::SecOffset(0x0123456789), DW_FORM_sec_offset,
            &[0x89, 0x67, 0x45, 0x23, 0x01, 0x00, 0x00, 0x00][..]),
    ] {
        attribute_data_inner(&mut unit, write_val, form, expect);
    }
}

fn attribute_data_inner<'a, 'b>(unit: &mut CompilationUnit<'a>, write_val: &AttributeData<'b>, form: DwForm, expect: &[u8]) {
    for &indirect in &[false, true] {
        unit.data = Default::default();
        write_val.write(unit, form, indirect).unwrap();
        let buf = unit.data();

        let read_form = if indirect { DW_FORM_indirect } else { form };
        let mut r = buf;
        let read_val = AttributeData::read(&mut r, unit, read_form).unwrap();

        if indirect {
            assert_eq!(buf[0] as u16, form.0);
            assert_eq!(&buf[1..], expect);
        } else {
            assert_eq!(&buf[..], expect);
        }
        assert_eq!(r.len(), 0);
        assert_eq!(read_val, *write_val);
    }
}

#[test]
fn abbrev_container() {
    let write_val = AbbrevVec::new(vec![
        Abbrev {
            code: 1,
            tag: DW_TAG_namespace,
            children: true,
            attributes: vec![
                AbbrevAttribute { at: DW_AT_name, form: DW_FORM_strp },
            ],
        },
    ]);

    let mut buf = Vec::new();
    write_val.write(&mut buf).unwrap();

    let mut r = &buf[..];
    let read_val = AbbrevHash::read(&mut r).unwrap();

    assert_eq!(&buf[..], [1, 57, 1, 3, 14, 0, 0, 0]);
    assert_eq!(r.len(), 0);
    assert_eq!(read_val.len(), write_val.len());
    for abbrev in write_val.iter() {
        assert_eq!(Some(abbrev), read_val.get(abbrev.code));
    }
}

#[test]
fn abbrev() {
    let write_val = Abbrev {
        code: 1,
        tag: DW_TAG_namespace,
        children: true,
        attributes: vec![
            AbbrevAttribute { at: DW_AT_name, form: DW_FORM_strp },
        ],
    };

    let mut buf = Vec::new();
    write_val.write(&mut buf).unwrap();

    let mut r = &buf[..];
    let read_val = Abbrev::read(&mut r).unwrap();

    assert_eq!(&buf[..], [1, 57, 1, 3, 14, 0, 0]);
    assert_eq!(r.len(), 0);
    assert_eq!(read_val, Some(write_val));
}

#[test]
fn abbrev_attribute() {
    let write_val = AbbrevAttribute { at: DW_AT_sibling, form: DW_FORM_ref4 };

    let mut buf = Vec::new();
    write_val.write(&mut buf).unwrap();

    let mut r = &buf[..];
    let read_val = AbbrevAttribute::read(&mut r).unwrap();

    assert_eq!(&buf[..], [1, 19]);
    assert_eq!(r.len(), 0);
    assert_eq!(read_val, Some(write_val));
}