Skip to content

Commit

Permalink
Reduce size of DwTag/DwAt/DwForm
Browse files Browse the repository at this point in the history
The standard does not allow larger values, even for user defined values.
  • Loading branch information
philipc committed Nov 20, 2019
1 parent 1fdc2b4 commit 8fbd608
Show file tree
Hide file tree
Showing 8 changed files with 89 additions and 29 deletions.
6 changes: 3 additions & 3 deletions src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ dw!(
/// The tag encodings for DIE attributes.
///
/// See Section 7.5.3, Table 7.3.
DwTag(u64) {
DwTag(u16) {
DW_TAG_null = 0x00,

DW_TAG_array_type = 0x01,
Expand Down Expand Up @@ -308,7 +308,7 @@ dw!(
/// The attribute encodings for DIE attributes.
///
/// See Section 7.5.4, Table 7.5.
DwAt(u64) {
DwAt(u16) {
DW_AT_null = 0x00,

DW_AT_sibling = 0x01,
Expand Down Expand Up @@ -617,7 +617,7 @@ dw!(
/// The attribute form encodings for DIE attributes.
///
/// See Section 7.5.6, Table 7.6.
DwForm(u64) {
DwForm(u16) {
DW_FORM_null = 0x00,

DW_FORM_addr = 0x01,
Expand Down
55 changes: 55 additions & 0 deletions src/leb128.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,29 @@ pub mod read {
}
}

/// Read an LEB128 u16 from the given `Reader` and
/// return it or an error if reading failed.
pub fn u16<R: Reader>(r: &mut R) -> Result<u16> {
let byte = r.read_u8()?;
let mut result = u16::from(low_bits_of_byte(byte));
if byte & CONTINUATION_BIT == 0 {
return Ok(result);
}

let byte = r.read_u8()?;
result |= u16::from(low_bits_of_byte(byte)) << 7;
if byte & CONTINUATION_BIT == 0 {
return Ok(result);
}

let byte = r.read_u8()?;
if byte > 0x03 {
return Err(Error::BadUnsignedLeb128);
}
result += u16::from(byte) << 14;
Ok(result)
}

/// Read a signed LEB128 number from the given `Reader` and
/// return it or an error if reading failed.
pub fn signed<R: Reader>(r: &mut R) -> Result<i64> {
Expand Down Expand Up @@ -516,4 +539,36 @@ mod tests {
1u64
);
}

#[test]
fn test_read_u16() {
for (buf, val) in [
(&[2][..], 2),
(&[0x7f][..], 0x7f),
(&[0x80, 1][..], 0x80),
(&[0x81, 1][..], 0x81),
(&[0x82, 1][..], 0x82),
(&[0xff, 0x7f][..], 0x3fff),
(&[0x80, 0x80, 1][..], 0x4000),
(&[0xff, 0xff, 1][..], 0x7fff),
(&[0xff, 0xff, 3][..], 0xffff),
]
.iter()
{
let mut readable = EndianSlice::new(buf, NativeEndian);
assert_eq!(*val, read::u16(&mut readable).expect("Should read number"));
}

for buf in [
&[0x80][..],
&[0x80, 0x80][..],
&[0x80, 0x80, 4][..],
&[0x80, 0x80, 0x80, 3][..],
]
.iter()
{
let mut readable = EndianSlice::new(buf, NativeEndian);
assert!(read::u16(&mut readable).is_err(), format!("{:?}", buf));
}
}
}
28 changes: 14 additions & 14 deletions src/read/abbrev.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ impl Abbreviation {

/// Parse an abbreviation's tag.
fn parse_tag<R: Reader>(input: &mut R) -> Result<constants::DwTag> {
let val = input.read_uleb128()?;
let val = input.read_uleb128_u16()?;
if val == 0 {
Err(Error::AbbreviationTagZero)
} else {
Expand Down Expand Up @@ -373,7 +373,7 @@ impl AttributeSpecification {

/// Parse an attribute's form.
fn parse_form<R: Reader>(input: &mut R) -> Result<constants::DwForm> {
let val = input.read_uleb128()?;
let val = input.read_uleb128_u16()?;
if val == 0 {
Err(Error::AttributeFormZero)
} else {
Expand All @@ -384,10 +384,10 @@ impl AttributeSpecification {
/// Parse an attribute specification. Returns `None` for the null attribute
/// specification, `Some` for an actual attribute specification.
fn parse<R: Reader>(input: &mut R) -> Result<Option<AttributeSpecification>> {
let name = input.read_uleb128()?;
let name = input.read_uleb128_u16()?;
if name == 0 {
// Parse the null attribute specification.
let form = input.read_uleb128()?;
let form = input.read_uleb128_u16()?;
return if form == 0 {
Ok(None)
} else {
Expand Down Expand Up @@ -428,20 +428,20 @@ pub mod tests {

impl AbbrevSectionMethods for Section {
fn abbrev(self, code: u64, tag: constants::DwTag, children: constants::DwChildren) -> Self {
self.uleb(code).uleb(tag.0).D8(children.0)
self.uleb(code).uleb(tag.0.into()).D8(children.0)
}

fn abbrev_null(self) -> Self {
self.D8(0)
}

fn abbrev_attr(self, name: constants::DwAt, form: constants::DwForm) -> Self {
self.uleb(name.0).uleb(form.0)
self.uleb(name.0.into()).uleb(form.0.into())
}

fn abbrev_attr_implicit_const(self, name: constants::DwAt, value: i64) -> Self {
self.uleb(name.0)
.uleb(constants::DW_FORM_implicit_const.0)
self.uleb(name.0.into())
.uleb(constants::DW_FORM_implicit_const.0.into())
.sleb(value)
}

Expand Down Expand Up @@ -509,17 +509,17 @@ pub mod tests {

#[test]
fn test_abbreviations_insert() {
fn abbrev(code: u64) -> Abbreviation {
fn abbrev(code: u16) -> Abbreviation {
Abbreviation::new(
code,
code.into(),
constants::DwTag(code),
constants::DW_CHILDREN_no,
vec![],
)
}

fn assert_abbrev(abbrevs: &Abbreviations, code: u64) {
let abbrev = abbrevs.get(code).unwrap();
fn assert_abbrev(abbrevs: &Abbreviations, code: u16) {
let abbrev = abbrevs.get(code.into()).unwrap();
assert_eq!(abbrev.tag(), constants::DwTag(code));
}

Expand Down Expand Up @@ -579,15 +579,15 @@ pub mod tests {
fn abbrev(code: u64) -> Abbreviation {
Abbreviation::new(
code,
constants::DwTag(code),
constants::DwTag(code as u16),
constants::DW_CHILDREN_no,
vec![],
)
}

fn assert_abbrev(abbrevs: &Abbreviations, code: u64) {
let abbrev = abbrevs.get(code).unwrap();
assert_eq!(abbrev.tag(), constants::DwTag(code));
assert_eq!(abbrev.tag(), constants::DwTag(code as u16));
}

let mut abbrevs = Abbreviations::empty();
Expand Down
2 changes: 1 addition & 1 deletion src/read/line.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1695,7 +1695,7 @@ impl FileEntryFormat {
path_count += 1;
}

let form = constants::DwForm(input.read_uleb128()?);
let form = constants::DwForm(input.read_uleb128_u16()?);

format.push(FileEntryFormat { content_type, form });
}
Expand Down
5 changes: 5 additions & 0 deletions src/read/reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,11 @@ pub trait Reader: Debug + Clone {
leb128::read::unsigned(self)
}

/// Read an unsigned LEB128 encoded u16.
fn read_uleb128_u16(&mut self) -> Result<u16> {
leb128::read::u16(self)
}

/// Read a signed LEB128 encoded integer.
fn read_sleb128(&mut self) -> Result<i64> {
leb128::read::signed(self)
Expand Down
4 changes: 2 additions & 2 deletions src/read/unit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1862,7 +1862,7 @@ pub(crate) fn parse_attribute<'unit, 'abbrev, R: Reader>(
loop {
let value = match form {
constants::DW_FORM_indirect => {
let dynamic_form = input.read_uleb128()?;
let dynamic_form = input.read_uleb128_u16()?;
form = constants::DwForm(dynamic_form);
continue;
}
Expand Down Expand Up @@ -4416,7 +4416,7 @@ mod tests {

let bytes_written = {
let mut writable = &mut buf[..];
leb128::write::unsigned(&mut writable, constants::DW_FORM_udata.0)
leb128::write::unsigned(&mut writable, constants::DW_FORM_udata.0.into())
.expect("should write udata")
+ leb128::write::unsigned(&mut writable, 9_999_999).expect("should write value")
};
Expand Down
6 changes: 3 additions & 3 deletions src/write/abbrev.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ impl Abbreviation {

/// Write the abbreviation to the `.debug_abbrev` section.
pub fn write<W: Writer>(&self, w: &mut DebugAbbrev<W>) -> Result<()> {
w.write_uleb128(self.tag.0)?;
w.write_uleb128(self.tag.0.into())?;
w.write_u8(if self.has_children {
constants::DW_CHILDREN_yes.0
} else {
Expand Down Expand Up @@ -94,8 +94,8 @@ impl AttributeSpecification {
/// Write the attribute specification to the `.debug_abbrev` section.
#[inline]
pub fn write<W: Writer>(&self, w: &mut DebugAbbrev<W>) -> Result<()> {
w.write_uleb128(self.name.0)?;
w.write_uleb128(self.form.0)
w.write_uleb128(self.name.0.into())?;
w.write_uleb128(self.form.0.into())
}
}

Expand Down
12 changes: 6 additions & 6 deletions src/write/line.rs
Original file line number Diff line number Diff line change
Expand Up @@ -574,7 +574,7 @@ impl LineProgram {
w.write_u8(1)?;
w.write_uleb128(u64::from(constants::DW_LNCT_path.0))?;
let dir_form = self.directories.get_index(0).unwrap().form();
w.write_uleb128(dir_form.0)?;
w.write_uleb128(dir_form.0.into())?;

// Directory entries.
w.write_uleb128(self.directories.len() as u64)?;
Expand All @@ -596,20 +596,20 @@ impl LineProgram {
w.write_u8(count)?;
w.write_uleb128(u64::from(constants::DW_LNCT_path.0))?;
let file_form = self.comp_file.0.form();
w.write_uleb128(file_form.0)?;
w.write_uleb128(file_form.0.into())?;
w.write_uleb128(u64::from(constants::DW_LNCT_directory_index.0))?;
w.write_uleb128(constants::DW_FORM_udata.0)?;
w.write_uleb128(constants::DW_FORM_udata.0.into())?;
if self.file_has_timestamp {
w.write_uleb128(u64::from(constants::DW_LNCT_timestamp.0))?;
w.write_uleb128(constants::DW_FORM_udata.0)?;
w.write_uleb128(constants::DW_FORM_udata.0.into())?;
}
if self.file_has_size {
w.write_uleb128(u64::from(constants::DW_LNCT_size.0))?;
w.write_uleb128(constants::DW_FORM_udata.0)?;
w.write_uleb128(constants::DW_FORM_udata.0.into())?;
}
if self.file_has_md5 {
w.write_uleb128(u64::from(constants::DW_LNCT_MD5.0))?;
w.write_uleb128(constants::DW_FORM_data16.0)?;
w.write_uleb128(constants::DW_FORM_data16.0.into())?;
}

// File name entries.
Expand Down

0 comments on commit 8fbd608

Please sign in to comment.