mrubyedge/rite/
rite.rs

1extern crate simple_endian;
2
3use super::binfmt::*;
4use super::Error;
5
6use core::ffi::CStr;
7use core::mem;
8use std::ffi::CString;
9
10use super::marker::*;
11
12use simple_endian::{u16be, u32be};
13
14#[derive(Debug, Default)]
15pub struct Rite<'a> {
16    pub binary_header: RiteBinaryHeader,
17    pub irep_header: SectionIrepHeader,
18    pub irep: Vec<Irep<'a>>,
19    pub lvar: Option<LVar>,
20}
21
22#[derive(Debug)]
23pub struct Irep<'a> {
24    pub header: IrepRecord,
25    pub insn: &'a [u8],
26    pub plen: usize,
27    pub strvals: Vec<CString>,
28    pub slen: usize,
29    pub syms: Vec<CString>,
30    pub catch_handlers: Vec<CatchHandler>,
31}
32
33impl Irep<'_> {
34    pub fn nlocals(&self) -> usize {
35        be16_to_u16(self.header.nlocals) as usize
36    }
37
38    pub fn nregs(&self) -> usize {
39        be16_to_u16(self.header.nregs) as usize
40    }
41
42    pub fn rlen(&self) -> usize {
43        be16_to_u16(self.header.rlen) as usize
44    }
45
46    pub fn clen(&self) -> usize {
47        be16_to_u16(self.header.clen) as usize
48    }
49}
50
51#[derive(Debug)]
52pub struct CatchHandler {
53    pub type_: u8,
54    pub start: usize,
55    pub end: usize,
56    pub target: usize,
57}
58
59#[derive(Debug)]
60pub struct LVar {
61    pub header: SectionMiscHeader,
62}
63
64pub fn load<'a>(src: &'a [u8]) -> Result<Rite<'a>, Error> {
65    let mut rite = Rite::default();
66
67    let mut size = src.len();
68    let mut head = src;
69    let binheader_size = mem::size_of::<RiteBinaryHeader>();
70    if size < binheader_size {
71        dbg!(size < binheader_size);
72        return Err(Error::TooShort);
73    }
74    let binary_header = RiteBinaryHeader::from_bytes(&head[0..binheader_size])?;
75    rite.binary_header = binary_header;
76    size -= binheader_size;
77    head = &head[binheader_size..];
78
79    // let binsize: u32 = be32_to_u32(rite.binary_header.size);
80
81    let irep_header_size = mem::size_of::<SectionIrepHeader>();
82    if size < irep_header_size {
83        dbg!(size, irep_header_size, size < irep_header_size);
84        return Err(Error::TooShort);
85    }
86
87    loop {
88        match peek4(head) {
89            Some(chrs) => match chrs {
90                IREP => {
91                    let (cur, irep_header, irep) = section_irep_1(head)?;
92                    rite.irep_header = irep_header;
93                    rite.irep = irep;
94                    head = &head[cur..];
95                }
96                LVAR => {
97                    let (cur, lvar) = section_lvar(head)?;
98                    rite.lvar = Some(lvar);
99                    head = &head[cur..];
100                }
101                DBG => {
102                    let cur = section_skip(head)?;
103                    head = &head[cur..];
104                }
105                END => {
106                    let cur = section_end(head)?;
107                    head = &head[cur..];
108                }
109                _ => {
110                    dbg!(chrs);
111                    dbg!(head);
112                    return Err(Error::InvalidFormat);
113                }
114            },
115            None => {
116                break;
117            }
118        }
119    }
120
121    Ok(rite)
122}
123
124pub fn section_irep_1(head: &[u8]) -> Result<(usize, SectionIrepHeader, Vec<Irep<'_>>), Error> {
125let mut cur = 0;
126
127    let irep_header_size = mem::size_of::<SectionIrepHeader>();
128    let irep_header = SectionIrepHeader::from_bytes(&head[cur..irep_header_size])?;
129    let irep_size = be32_to_u32(irep_header.size) as usize;
130    if head.len() < irep_size {
131        dbg!((head.len(), irep_size, head.len() < irep_size));
132        return Err(Error::TooShort);
133    }
134    cur += irep_header_size;
135
136    let mut ireps: Vec<Irep> = Vec::new();
137
138    while cur < irep_size {
139        let mut strvals = Vec::<CString>::new();
140        let mut syms = Vec::<CString>::new();
141
142        let start_cur = cur;
143        // insn
144        let record_size = mem::size_of::<IrepRecord>();
145        let irep_record = IrepRecord::from_bytes(&head[cur..cur + record_size])?;
146        let irep_rec_size = be32_to_u32(irep_record.size) as usize;
147        let ilen = be32_to_u32(irep_record.ilen) as usize;
148        cur += record_size;
149
150        let insns = &head[cur..cur + ilen];
151
152        cur += ilen;
153
154        let mut catch_handlers = Vec::<CatchHandler>::new();
155        let clen = be16_to_u16(irep_record.clen) as usize;
156        if clen > 0 {
157            for _ in 0..clen {
158                let value = CatchHandler {
159                    type_: head[cur],
160                    start: be32_to_u32([head[cur + 1], head[cur + 2], head[cur + 3], head[cur + 4]])
161                        as usize,
162                    end: be32_to_u32([head[cur + 5], head[cur + 6], head[cur + 7], head[cur + 8]])
163                        as usize,
164                    target: be32_to_u32([head[cur + 9], head[cur + 10], head[cur + 11], head[cur + 12]])
165                        as usize,
166                };
167                catch_handlers.push(value);
168                cur += mem::size_of::<IrepCatchHandler>();
169            }
170        }
171
172        // pool
173        let data = &head[cur..cur + 2];
174        let plen = be16_to_u16([data[0], data[1]]) as usize;
175        cur += 2;
176
177        for _ in 0..plen {
178            let typ = head[cur];
179            match typ {
180                0 => {
181                    cur += 1;
182                    let data = &head[cur..cur + 2];
183                    let strlen = be16_to_u16([data[0], data[1]]) as usize + 1;
184                    cur += 2;
185                    let strval = CStr::from_bytes_with_nul(&head[cur..cur + strlen])
186                        .or(Err(Error::InvalidFormat))?;
187                    strvals.push(strval.to_owned());
188                    cur += strlen;
189                }
190                v => {
191                    unimplemented!("require more support pool type {}", v);
192                }
193            }
194        }
195
196        // syms
197        let data = &head[cur..cur + 2];
198        let slen = be16_to_u16([data[0], data[1]]) as usize;
199        cur += 2;
200        for _ in 0..slen {
201            let data = &head[cur..cur + 2];
202            let symlen = be16_to_u16([data[0], data[1]]) as usize + 1;
203            cur += 2;
204            let symval = CStr::from_bytes_with_nul(&head[cur..cur + symlen])
205                .or(Err(Error::InvalidFormat))?;
206            syms.push(symval.to_owned());
207            cur += symlen;
208        }
209
210        cur = start_cur + irep_rec_size;
211
212        let irep = Irep {
213            header: irep_record,
214            insn: insns,
215            plen,
216            strvals,
217            slen,
218            syms,
219            catch_handlers,
220        };
221        ireps.push(irep);
222    }
223
224    Ok((irep_size, irep_header, ireps))
225}
226
227pub fn section_end(head: &[u8]) -> Result<usize, Error> {
228    let header = SectionMiscHeader::from_bytes(head)?;
229    // eprintln!("end section detected");
230    Ok(be32_to_u32(header.size) as usize)
231}
232
233pub fn section_lvar(head: &[u8]) -> Result<(usize, LVar), Error> {
234    let header = SectionMiscHeader::from_bytes(head)?;
235    let lvar = LVar { header };
236    Ok((be32_to_u32(lvar.header.size) as usize, lvar))
237}
238
239pub fn section_skip(head: &[u8]) -> Result<usize, Error> {
240    let header = SectionMiscHeader::from_bytes(head)?;
241    // eprintln!("skipped section {:?}", header.ident.as_ascii());
242    Ok(be32_to_u32(header.size) as usize)
243}
244
245pub fn peek4<'a>(src: &'a [u8]) -> Option<[char; 4]> {
246    if src.len() < 4 {
247        // EoD
248        return None;
249    }
250    if let [a, b, c, d] = src[0..4] {
251	let a = char::from_u32(a as u32).unwrap();
252	let b = char::from_u32(b as u32).unwrap();
253	let c = char::from_u32(c as u32).unwrap();
254	let d = char::from_u32(d as u32).unwrap();
255	Some([a, b, c, d])
256    } else {
257	None
258    }
259}
260
261pub fn be32_to_u32(be32: [u8; 4]) -> u32 {
262    let binsize_be = unsafe { mem::transmute::<[u8; 4], u32be>(be32) };
263    let binsize: u32 = binsize_be.into();
264    binsize
265}
266
267pub fn be16_to_u16(be16: [u8; 2]) -> u16 {
268    let binsize_be = unsafe { mem::transmute::<[u8; 2], u16be>(be16) };
269    let binsize: u16 = binsize_be.into();
270    binsize
271}