Skip to content

Commit

Permalink
Merge pull request #207 from philipc/endianbuf
Browse files Browse the repository at this point in the history
WIP Preparation for Reader trait
  • Loading branch information
fitzgen committed Jun 19, 2017
2 parents f63bac1 + d8197fb commit cf3491a
Show file tree
Hide file tree
Showing 15 changed files with 1,617 additions and 1,734 deletions.
13 changes: 6 additions & 7 deletions examples/dwarfdump.rs
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ fn dump_attr_value<Endian>(attr: gimli::Attribute<Endian>,
println!("0x{:08x}", address);
}
gimli::AttributeValue::Block(data) => {
for byte in data.0 {
for byte in data.buf() {
print!("{:02x}", byte);
}
println!("");
Expand Down Expand Up @@ -369,7 +369,7 @@ fn dump_attr_value<Endian>(attr: gimli::Attribute<Endian>,
gimli::AttributeValue::Exprloc(data) => {
if let gimli::AttributeValue::Exprloc(_) = attr.raw_value() {
print!("len 0x{:04x}: ", data.len());
for byte in data.0 {
for byte in data.buf() {
print!("{:02x}", byte);
}
print!(": ");
Expand Down Expand Up @@ -507,15 +507,14 @@ fn dump_exprloc<Endian>(data: gimli::EndianBuf<Endian>, unit: &Unit<Endian>)
let mut space = false;
while pc.len() != 0 {
let dwop = gimli::DwOp(pc[0]);
match gimli::Operation::parse(pc, data, unit.address_size, unit.format) {
Ok((newpc, op)) => {
match gimli::Operation::parse(&mut pc, data, unit.address_size, unit.format) {
Ok(op) => {
if space {
print!(" ");
} else {
space = true;
}
dump_op(dwop, op, newpc.0);
pc = newpc;
dump_op(dwop, op, pc.buf());
}
Err(gimli::Error::InvalidExpression(op)) => {
writeln!(&mut std::io::stderr(),
Expand Down Expand Up @@ -621,7 +620,7 @@ fn dump_op<Endian>(dwop: gimli::DwOp, op: gimli::Operation<Endian>, newpc: &[u8]
}
gimli::Operation::EntryValue { expression } => {
print!(" 0x{:08x} contents 0x", expression.len());
for byte in expression.0 {
for byte in expression.buf() {
print!("{:02x}", byte);
}
}
Expand Down
149 changes: 82 additions & 67 deletions src/abbrev.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,9 @@ impl<'input, Endian> DebugAbbrev<'input, Endian>
///
/// The `offset` should generally be retrieved from a unit header.
pub fn abbreviations(&self, debug_abbrev_offset: DebugAbbrevOffset) -> Result<Abbreviations> {
let input: &[u8] = self.debug_abbrev_section.into();
Abbreviations::parse(&input[debug_abbrev_offset.0..]).map(|(_, abbrevs)| abbrevs)
let input = &mut self.debug_abbrev_section
.range_from(debug_abbrev_offset.0..);
Abbreviations::parse(input)
}
}

Expand Down Expand Up @@ -133,24 +134,18 @@ impl Abbreviations {
}

/// Parse a series of abbreviations, terminated by a null abbreviation.
fn parse(mut input: &[u8]) -> Result<(&[u8], Abbreviations)> {
fn parse<Endian>(input: &mut EndianBuf<Endian>) -> Result<Abbreviations>
where Endian: Endianity
{
let mut abbrevs = Abbreviations::empty();

loop {
let (rest, abbrev) = Abbreviation::parse(input)?;
input = rest;

match abbrev {
None => break,
Some(abbrev) => {
if abbrevs.insert(abbrev).is_err() {
return Err(Error::DuplicateAbbreviationCode);
}
}
while let Some(abbrev) = Abbreviation::parse(input)? {
if abbrevs.insert(abbrev).is_err() {
return Err(Error::DuplicateAbbreviationCode);
}
}

Ok((input, abbrevs))
Ok(abbrevs)
}
}

Expand Down Expand Up @@ -209,57 +204,60 @@ impl Abbreviation {
}

/// Parse an abbreviation's tag.
fn parse_tag(input: &[u8]) -> Result<(&[u8], constants::DwTag)> {
let (rest, val) = parse_unsigned_leb(input)?;
fn parse_tag<Endian>(input: &mut EndianBuf<Endian>) -> Result<constants::DwTag>
where Endian: Endianity
{
let val = parse_unsigned_leb(input)?;
if val == 0 {
Err(Error::AbbreviationTagZero)
} else {
Ok((rest, constants::DwTag(val)))
Ok(constants::DwTag(val))
}
}

/// Parse an abbreviation's "does the type have children?" byte.
fn parse_has_children(input: &[u8]) -> Result<(&[u8], constants::DwChildren)> {
let (rest, val) = parse_u8(input)?;
fn parse_has_children<Endian>(input: &mut EndianBuf<Endian>) -> Result<constants::DwChildren>
where Endian: Endianity
{
let val = parse_u8(input)?;
let val = constants::DwChildren(val);
if val == constants::DW_CHILDREN_no || val == constants::DW_CHILDREN_yes {
Ok((rest, val))
Ok(val)
} else {
Err(Error::BadHasChildren)
}
}

/// Parse a series of attribute specifications, terminated by a null attribute
/// specification.
fn parse_attributes(mut input: &[u8]) -> Result<(&[u8], Vec<AttributeSpecification>)> {
fn parse_attributes<Endian>(input: &mut EndianBuf<Endian>)
-> Result<Vec<AttributeSpecification>>
where Endian: Endianity
{
let mut attrs = Vec::new();

loop {
let (rest, attr) = AttributeSpecification::parse(input)?;
input = rest;

match attr {
None => break,
Some(attr) => attrs.push(attr),
};
while let Some(attr) = AttributeSpecification::parse(input)? {
attrs.push(attr);
}

Ok((input, attrs))
Ok(attrs)
}

/// Parse an abbreviation. Return `None` for the null abbreviation, `Some`
/// for an actual abbreviation.
fn parse(input: &[u8]) -> Result<(&[u8], Option<Abbreviation>)> {
let (rest, code) = parse_unsigned_leb(input)?;
fn parse<Endian>(input: &mut EndianBuf<Endian>) -> Result<Option<Abbreviation>>
where Endian: Endianity
{
let code = parse_unsigned_leb(input)?;
if code == 0 {
return Ok((rest, None));
return Ok(None);
}

let (rest, tag) = Self::parse_tag(rest)?;
let (rest, has_children) = Self::parse_has_children(rest)?;
let (rest, attributes) = Self::parse_attributes(rest)?;
let tag = Self::parse_tag(input)?;
let has_children = Self::parse_has_children(input)?;
let attributes = Self::parse_attributes(input)?;
let abbrev = Abbreviation::new(code, tag, has_children, attributes);
Ok((rest, Some(abbrev)))
Ok(Some(abbrev))
}
}

Expand Down Expand Up @@ -344,33 +342,37 @@ impl AttributeSpecification {
}

/// Parse an attribute's form.
fn parse_form(input: &[u8]) -> Result<(&[u8], constants::DwForm)> {
let (rest, val) = parse_unsigned_leb(input)?;
fn parse_form<Endian>(input: &mut EndianBuf<Endian>) -> Result<constants::DwForm>
where Endian: Endianity
{
let val = parse_unsigned_leb(input)?;
if val == 0 {
Err(Error::AttributeFormZero)
} else {
Ok((rest, constants::DwForm(val)))
Ok(constants::DwForm(val))
}
}

/// Parse an attribute specification. Returns `None` for the null attribute
/// specification, `Some` for an actual attribute specification.
fn parse(input: &[u8]) -> Result<(&[u8], Option<AttributeSpecification>)> {
let (rest, name) = parse_unsigned_leb(input)?;
fn parse<Endian>(input: &mut EndianBuf<Endian>) -> Result<Option<AttributeSpecification>>
where Endian: Endianity
{
let name = parse_unsigned_leb(input)?;
if name == 0 {
// Parse the null attribute specification.
let (rest, form) = parse_unsigned_leb(rest)?;
let form = parse_unsigned_leb(input)?;
return if form == 0 {
Ok((rest, None))
Ok(None)
} else {
Err(Error::ExpectedZero)
};
}

let name = constants::DwAt(name);
let (rest, form) = Self::parse_form(rest)?;
let form = Self::parse_form(input)?;
let spec = AttributeSpecification::new(name, form);
Ok((rest, Some(spec)))
Ok(Some(spec))
}
}

Expand Down Expand Up @@ -563,6 +565,7 @@ pub mod tests {
.append_bytes(&expected_rest)
.get_contents()
.unwrap();
let rest = &mut EndianBuf::<LittleEndian>::new(&*buf);

let abbrev1 =
Abbreviation::new(1,
Expand All @@ -579,10 +582,10 @@ pub mod tests {
vec![AttributeSpecification::new(constants::DW_AT_name,
constants::DW_FORM_string)]);

let (rest, abbrevs) = Abbreviations::parse(&buf).expect("Should parse abbreviations");
let abbrevs = Abbreviations::parse(rest).expect("Should parse abbreviations");
assert_eq!(abbrevs.get(1), Some(&abbrev1));
assert_eq!(abbrevs.get(2), Some(&abbrev2));
assert_eq!(rest, expected_rest);
assert_eq!(*rest, EndianBuf::new(&expected_rest));
}

#[test]
Expand All @@ -602,8 +605,9 @@ pub mod tests {
.append_bytes(&expected_rest)
.get_contents()
.unwrap();
let buf = &mut EndianBuf::<LittleEndian>::new(&*buf);

match Abbreviations::parse(&buf) {
match Abbreviations::parse(buf) {
Err(Error::DuplicateAbbreviationCode) => {}
otherwise => panic!("Unexpected result: {:?}", otherwise),
};
Expand All @@ -612,15 +616,17 @@ pub mod tests {
#[test]
fn test_parse_abbreviation_tag_ok() {
let buf = [0x01, 0x02];
let (rest, tag) = Abbreviation::parse_tag(&buf).expect("Should parse tag");
let rest = &mut EndianBuf::<LittleEndian>::new(&buf);
let tag = Abbreviation::parse_tag(rest).expect("Should parse tag");
assert_eq!(tag, constants::DW_TAG_array_type);
assert_eq!(rest, &buf[1..]);
assert_eq!(*rest, EndianBuf::new(&buf[1..]));
}

#[test]
fn test_parse_abbreviation_tag_zero() {
let buf = [0x00];
match Abbreviation::parse_tag(&buf) {
let buf = &mut EndianBuf::<LittleEndian>::new(&buf);
match Abbreviation::parse_tag(buf) {
Err(Error::AbbreviationTagZero) => {}
otherwise => panic!("Unexpected result: {:?}", otherwise),
};
Expand All @@ -629,9 +635,10 @@ pub mod tests {
#[test]
fn test_parse_abbreviation_has_children() {
let buf = [0x00, 0x01, 0x02];
let (rest, val) = Abbreviation::parse_has_children(&buf).expect("Should parse children");
let rest = &mut EndianBuf::<LittleEndian>::new(&buf);
let val = Abbreviation::parse_has_children(rest).expect("Should parse children");
assert_eq!(val, constants::DW_CHILDREN_no);
let (rest, val) = Abbreviation::parse_has_children(rest).expect("Should parse children");
let val = Abbreviation::parse_has_children(rest).expect("Should parse children");
assert_eq!(val, constants::DW_CHILDREN_yes);
match Abbreviation::parse_has_children(rest) {
Err(Error::BadHasChildren) => {}
Expand All @@ -641,23 +648,25 @@ pub mod tests {

#[test]
fn test_parse_abbreviation_ok() {
let expected_rest = [0x01, 0x02, 0x03, 0x04];
let buf = Section::new()
.abbrev(1, constants::DW_TAG_subprogram, constants::DW_CHILDREN_no)
.abbrev_attr(constants::DW_AT_name, constants::DW_FORM_string)
.abbrev_attr_null()
.append_bytes(&[0x01, 0x02, 0x03, 0x04])
.append_bytes(&expected_rest)
.get_contents()
.unwrap();
let rest = &mut EndianBuf::<LittleEndian>::new(&*buf);

let expect = Some(Abbreviation::new(1,
constants::DW_TAG_subprogram,
constants::DW_CHILDREN_no,
vec![AttributeSpecification::new(constants::DW_AT_name,
constants::DW_FORM_string)]));

let (rest, abbrev) = Abbreviation::parse(&buf).expect("Should parse abbreviation");
let abbrev = Abbreviation::parse(rest).expect("Should parse abbreviation");
assert_eq!(abbrev, expect);
assert_eq!(rest, [0x01, 0x02, 0x03, 0x04]);
assert_eq!(*rest, EndianBuf::new(&expected_rest));
}

#[test]
Expand All @@ -668,24 +677,27 @@ pub mod tests {
.append_bytes(&expected_rest)
.get_contents()
.unwrap();
let rest = &mut EndianBuf::<LittleEndian>::new(&*buf);

let (rest, abbrev) = Abbreviation::parse(&buf).expect("Should parse null abbreviation");
let abbrev = Abbreviation::parse(rest).expect("Should parse null abbreviation");
assert!(abbrev.is_none());
assert_eq!(rest, [0x01, 0x02, 0x03, 0x04]);
assert_eq!(*rest, EndianBuf::new(&expected_rest));
}

#[test]
fn test_parse_attribute_form_ok() {
let buf = [0x01, 0x02];
let (rest, tag) = AttributeSpecification::parse_form(&buf).expect("Should parse form");
let rest = &mut EndianBuf::<LittleEndian>::new(&buf);
let tag = AttributeSpecification::parse_form(rest).expect("Should parse form");
assert_eq!(tag, constants::DW_FORM_addr);
assert_eq!(rest, &buf[1..]);
assert_eq!(*rest, EndianBuf::new(&buf[1..]));
}

#[test]
fn test_parse_attribute_form_zero() {
let buf = [0x00];
match AttributeSpecification::parse_form(&buf) {
let buf = &mut EndianBuf::<LittleEndian>::new(&buf);
match AttributeSpecification::parse_form(buf) {
Err(Error::AttributeFormZero) => {}
otherwise => panic!("Unexpected result: {:?}", otherwise),
};
Expand All @@ -694,16 +706,18 @@ pub mod tests {
#[test]
fn test_parse_null_attribute_specification_ok() {
let buf = [0x00, 0x00, 0x01];
let (rest, attr) = AttributeSpecification::parse(&buf)
let rest = &mut EndianBuf::<LittleEndian>::new(&buf);
let attr = AttributeSpecification::parse(rest)
.expect("Should parse null attribute specification");
assert!(attr.is_none());
assert_eq!(rest, [0x01]);
assert_eq!(*rest, EndianBuf::new(&buf[2..]));
}

#[test]
fn test_parse_attribute_specifications_name_zero() {
let buf = [0x00, 0x01, 0x00, 0x00];
match AttributeSpecification::parse(&buf) {
let buf = &mut EndianBuf::<LittleEndian>::new(&buf);
match AttributeSpecification::parse(buf) {
Err(Error::ExpectedZero) => {}
otherwise => panic!("Unexpected result: {:?}", otherwise),
};
Expand All @@ -712,7 +726,8 @@ pub mod tests {
#[test]
fn test_parse_attribute_specifications_form_zero() {
let buf = [0x01, 0x00, 0x00, 0x00];
match AttributeSpecification::parse(&buf) {
let buf = &mut EndianBuf::<LittleEndian>::new(&buf);
match AttributeSpecification::parse(buf) {
Err(Error::AttributeFormZero) => {}
otherwise => panic!("Unexpected result: {:?}", otherwise),
};
Expand Down

0 comments on commit cf3491a

Please sign in to comment.