dwarf/
write.rs

1use std;
2use std::io::Write;
3use byteorder::WriteBytesExt;
4
5use super::*;
6use leb128;
7
8#[derive(Debug)]
9pub enum WriteError {
10    Io(std::io::Error),
11    Invalid(String),
12    Unsupported(String),
13}
14
15impl std::convert::From<std::io::Error> for WriteError {
16    fn from(e: std::io::Error) -> Self {
17        WriteError::Io(e)
18    }
19}
20
21impl<'a> CompilationUnit<'a> {
22    pub fn write<W: Write>(&self, w: &mut W) -> Result<(), WriteError> {
23        let len = self.base_len();
24        match self.offset_size {
25            4 => {
26                if len >= 0xfffffff0 {
27                    return Err(WriteError::Invalid(format!("compilation unit length {}", len)));
28                }
29                try!(self.endian.write_u32(w, len as u32));
30            }
31            8 => {
32                try!(self.endian.write_u32(w, 0xffffffff));
33                try!(self.endian.write_u64(w, len as u64));
34            }
35            _ => return Err(WriteError::Unsupported(format!("offset size {}", self.offset_size))),
36        };
37        try!(self.endian.write_u16(w, self.version));
38        try!(write_offset(w, self.endian, self.offset_size, self.abbrev_offset));
39        try!(w.write_u8(self.address_size));
40        try!(w.write_all(&*self.data));
41        Ok(())
42    }
43}
44
45impl<'a, 'b> Die<'a> {
46    pub fn write_null(unit: &mut CompilationUnit<'b>) -> std::io::Result<()> {
47        let w = unit.data.to_mut();
48        leb128::write_u64(w, 0)
49    }
50
51    pub fn write(
52        &self,
53        unit: &mut CompilationUnit<'b>,
54        abbrev_hash: &AbbrevHash,
55    ) -> Result<(), WriteError> {
56        if self.code == 0 {
57            try!(Die::write_null(unit));
58            return Ok(());
59        }
60        let abbrev = match abbrev_hash.get(self.code) {
61            Some(abbrev) => abbrev,
62            None => return Err(WriteError::Invalid(format!("missing abbrev {}", self.code))),
63        };
64        if self.children != abbrev.children {
65            return Err(WriteError::Invalid("die/abbrev children mismatch".to_string()));
66        }
67        if self.attributes.len() != abbrev.attributes.len() {
68            return Err(WriteError::Invalid("die/abbrev attribute length mismatch".to_string()));
69        }
70        try!(leb128::write_u64(unit.data.to_mut(), abbrev.code));
71        for (attribute, abbrev_attribute) in self.attributes.iter().zip(&abbrev.attributes) {
72            try!(attribute.write(unit, abbrev_attribute));
73        }
74        Ok(())
75    }
76}
77
78impl<'a, 'b> Attribute<'a> {
79    pub fn write(
80        &self,
81        unit: &mut CompilationUnit<'b>,
82        abbrev: &AbbrevAttribute,
83    ) -> Result<(), WriteError> {
84        if self.at != abbrev.at {
85            return Err(WriteError::Invalid("attribute type mismatch".to_string()));
86        }
87        try!(self.data.write(unit, abbrev.form, false));
88        Ok(())
89    }
90}
91
92#[cfg_attr(feature = "clippy", allow(match_same_arms))]
93impl<'a, 'b> AttributeData<'a> {
94    pub fn write(
95        &self,
96        unit: &mut CompilationUnit<'b>,
97        form: constant::DwForm,
98        indirect: bool,
99    ) -> Result<(), WriteError> {
100        let w = unit.data.to_mut();
101        if indirect {
102            try!(leb128::write_u16(w, form.0));
103        }
104        match (self, form) {
105            (&AttributeData::Address(ref val), constant::DW_FORM_addr) => {
106                try!(write_address(w, unit.endian, unit.address_size, *val));
107            },
108            (&AttributeData::Block(ref val), constant::DW_FORM_block1) => {
109                try!(w.write_u8(val.len() as u8));
110                try!(w.write_all(val));
111            },
112            (&AttributeData::Block(ref val), constant::DW_FORM_block2) => {
113                try!(unit.endian.write_u16(w, val.len() as u16));
114                try!(w.write_all(val));
115            },
116            (&AttributeData::Block(ref val), constant::DW_FORM_block4) => {
117                try!(unit.endian.write_u32(w, val.len() as u32));
118                try!(w.write_all(val));
119            },
120            (&AttributeData::Block(ref val), constant::DW_FORM_block) => {
121                try!(leb128::write_u64(w, val.len() as u64));
122                try!(w.write_all(val));
123            },
124            (&AttributeData::Data1(ref val), constant::DW_FORM_data1) => {
125                try!(w.write_u8(*val));
126            },
127            (&AttributeData::Data2(ref val), constant::DW_FORM_data2) => {
128                try!(unit.endian.write_u16(w, *val));
129            },
130            (&AttributeData::Data4(ref val), constant::DW_FORM_data4) => {
131                try!(unit.endian.write_u32(w, *val));
132            },
133            (&AttributeData::Data8(ref val), constant::DW_FORM_data8) => {
134                try!(unit.endian.write_u64(w, *val));
135            },
136            (&AttributeData::UData(ref val), constant::DW_FORM_udata) => {
137                try!(leb128::write_u64(w, *val));
138            },
139            (&AttributeData::SData(ref val), constant::DW_FORM_sdata) => {
140                try!(leb128::write_i64(w, *val));
141            },
142            (&AttributeData::Flag(ref val), constant::DW_FORM_flag) => {
143                try!(w.write_u8(if *val { 1 } else { 0 }));
144            },
145            (&AttributeData::Flag(ref val), constant::DW_FORM_flag_present) => {
146                assert!(*val);
147            },
148            (&AttributeData::String(ref val), constant::DW_FORM_string) => {
149                try!(w.write_all(val.as_bytes()));
150                try!(w.write_u8(0));
151            },
152            (&AttributeData::StringOffset(ref val), constant::DW_FORM_strp) => {
153                try!(write_offset(w, unit.endian, unit.offset_size, *val));
154            },
155            (&AttributeData::Ref(ref val), constant::DW_FORM_ref1) => {
156                try!(w.write_u8(*val as u8));
157            },
158            (&AttributeData::Ref(ref val), constant::DW_FORM_ref2) => {
159                try!(unit.endian.write_u16(w, *val as u16));
160            },
161            (&AttributeData::Ref(ref val), constant::DW_FORM_ref4) => {
162                try!(unit.endian.write_u32(w, *val as u32));
163            },
164            (&AttributeData::Ref(ref val), constant::DW_FORM_ref8) => {
165                try!(unit.endian.write_u64(w, *val as u64));
166            },
167            (&AttributeData::Ref(ref val), constant::DW_FORM_ref_udata) => {
168                try!(leb128::write_u64(w, *val as u64));
169            },
170            (&AttributeData::RefAddress(ref val), constant::DW_FORM_ref_addr) => {
171                try!(write_offset(w, unit.endian, unit.offset_size, *val));
172            },
173            (&AttributeData::RefSig(ref val), constant::DW_FORM_ref_sig8) => {
174                try!(unit.endian.write_u64(w, *val));
175            },
176            (&AttributeData::SecOffset(ref val), constant::DW_FORM_sec_offset) => {
177                try!(write_offset(w, unit.endian, unit.offset_size, *val));
178            },
179            (&AttributeData::ExprLoc(ref val), constant::DW_FORM_exprloc) => {
180                try!(leb128::write_u64(w, val.len() as u64));
181                try!(w.write_all(val));
182            },
183            _ => return Err(WriteError::Unsupported(format!("attribute form {}", form.0))),
184        }
185        Ok(())
186    }
187}
188
189fn write_offset<W: Write>(w: &mut W, endian: Endian, offset_size: u8, val: u64) -> Result<(), WriteError> {
190    match offset_size {
191        4 => try!(endian.write_u32(w, val as u32)),
192        8 => try!(endian.write_u64(w, val)),
193        _ => return Err(WriteError::Unsupported(format!("offset size {}", offset_size))),
194    };
195    Ok(())
196}
197
198fn write_address<W: Write>(w: &mut W, endian: Endian, address_size: u8, val: u64) -> Result<(), WriteError> {
199    match address_size {
200        4 => try!(endian.write_u32(w, val as u32)),
201        8 => try!(endian.write_u64(w, val)),
202        _ => return Err(WriteError::Unsupported(format!("address size {}", address_size))),
203    };
204    Ok(())
205}
206
207impl AbbrevVec {
208    pub fn write<W: Write>(&self, w: &mut W) -> std::io::Result<()> {
209        for abbrev in self.iter() {
210            try!(abbrev.write(w));
211        }
212        try!(Abbrev::write_null(w));
213        Ok(())
214    }
215}
216
217impl Abbrev {
218    pub fn write_null<W: Write>(w: &mut W) -> std::io::Result<()> {
219        leb128::write_u64(w, 0)
220    }
221
222    pub fn write<W: Write>(&self, w: &mut W) -> std::io::Result<()> {
223        try!(leb128::write_u64(w, self.code));
224        // This probably should never happen
225        if self.code == 0 {
226            return Ok(());
227        }
228
229        try!(leb128::write_u16(w, self.tag.0));
230
231        let children = if self.children {
232            constant::DW_CHILDREN_yes
233        } else {
234            constant::DW_CHILDREN_no
235        };
236        try!(w.write_u8(children.0));
237
238        for attribute in &self.attributes {
239            try!(attribute.write(w));
240        }
241        try!(AbbrevAttribute::write_null(w));
242
243        Ok(())
244    }
245}
246
247impl AbbrevAttribute {
248    pub fn write_null<W: Write>(w: &mut W) -> std::io::Result<()> {
249        Self::null().write(w)
250    }
251
252    pub fn write<W: Write>(&self, w: &mut W) -> std::io::Result<()> {
253        try!(leb128::write_u16(w, self.at.0));
254        try!(leb128::write_u16(w, self.form.0));
255        Ok(())
256    }
257}