1extern crate simple_endian;
2
3use super::Error;
4use super::binfmt::*;
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, Clone)]
15pub enum PoolValue {
16 Str(CString), Int32(i32), SStr(CString), Int64(i64), Float(f64), BigInt(Vec<u8>), }
23
24#[derive(Debug, Default)]
25pub struct Rite<'a> {
26 pub binary_header: RiteBinaryHeader,
27 pub irep_header: SectionIrepHeader,
28 pub irep: Vec<Irep<'a>>,
29 pub lvar: Option<LVar>,
30}
31
32#[derive(Debug)]
33pub struct Irep<'a> {
34 pub header: IrepRecord,
35 pub insn: &'a [u8],
36 pub plen: usize,
37 pub pool: Vec<PoolValue>,
38 pub slen: usize,
39 pub syms: Vec<CString>,
40 pub catch_handlers: Vec<CatchHandler>,
41 pub lv: Vec<Option<CString>>, }
43
44impl Irep<'_> {
45 pub fn nlocals(&self) -> usize {
46 be16_to_u16(self.header.nlocals) as usize
47 }
48
49 pub fn nregs(&self) -> usize {
50 be16_to_u16(self.header.nregs) as usize
51 }
52
53 pub fn rlen(&self) -> usize {
54 be16_to_u16(self.header.rlen) as usize
55 }
56
57 pub fn clen(&self) -> usize {
58 be16_to_u16(self.header.clen) as usize
59 }
60}
61
62#[derive(Debug)]
63pub struct CatchHandler {
64 pub type_: u8,
65 pub start: usize,
66 pub end: usize,
67 pub target: usize,
68}
69
70#[derive(Debug)]
71pub struct LVar {
72 pub header: SectionMiscHeader,
73 pub syms: Vec<CString>,
74}
75
76const RITE_LV_NULL_MARK: u16 = 0xFFFF;
77
78pub fn load<'a>(src: &'a [u8]) -> Result<Rite<'a>, Error> {
79 let mut rite = Rite::default();
80
81 let mut size = src.len();
82 let mut head = src;
83 let binheader_size = mem::size_of::<RiteBinaryHeader>();
84 if size < binheader_size {
85 dbg!(size < binheader_size);
86 return Err(Error::TooShort);
87 }
88 let binary_header = RiteBinaryHeader::from_bytes(&head[0..binheader_size])?;
89 rite.binary_header = binary_header;
90 size -= binheader_size;
91 head = &head[binheader_size..];
92
93 let irep_header_size = mem::size_of::<SectionIrepHeader>();
96 if size < irep_header_size {
97 dbg!(size, irep_header_size, size < irep_header_size);
98 return Err(Error::TooShort);
99 }
100
101 while let Some(chrs) = peek4(head) {
102 match chrs {
103 IREP => {
104 let (cur, irep_header, irep) = section_irep_1(head)?;
105 rite.irep_header = irep_header;
106 rite.irep = irep;
107 head = &head[cur..];
108 }
109 LVAR => {
110 let (cur, lvar) = section_lvar(head, &mut rite.irep)?;
111 rite.lvar = Some(lvar);
112 head = &head[cur..];
113 }
114 DBG => {
115 let cur = section_skip(head)?;
116 head = &head[cur..];
117 }
118 END => {
119 let cur = section_end(head)?;
120 head = &head[cur..];
121 }
122 _ => {
123 eprintln!("{:?}", chrs);
124 eprint!("{:?}", head);
125 return Err(Error::InvalidFormat);
126 }
127 }
128 }
129
130 Ok(rite)
131}
132
133pub fn section_irep_1(head: &[u8]) -> Result<(usize, SectionIrepHeader, Vec<Irep<'_>>), Error> {
134 let mut cur = 0;
135
136 let irep_header_size = mem::size_of::<SectionIrepHeader>();
137 let irep_header = SectionIrepHeader::from_bytes(&head[cur..irep_header_size])?;
138 let irep_size = be32_to_u32(irep_header.size) as usize;
139 if head.len() < irep_size {
140 dbg!((head.len(), irep_size, head.len() < irep_size));
141 return Err(Error::TooShort);
142 }
143 cur += irep_header_size;
144
145 let mut ireps: Vec<Irep> = Vec::new();
146
147 while cur < irep_size {
148 let mut pool = Vec::<PoolValue>::new();
149 let mut syms = Vec::<CString>::new();
150
151 let start_cur = cur;
152 let record_size = mem::size_of::<IrepRecord>();
154 let irep_record = IrepRecord::from_bytes(&head[cur..cur + record_size])?;
155 let irep_rec_size = be32_to_u32(irep_record.size) as usize;
156 let ilen = be32_to_u32(irep_record.ilen) as usize;
157 cur += record_size;
158
159 let insns = &head[cur..cur + ilen];
160
161 cur += ilen;
162
163 let mut catch_handlers = Vec::<CatchHandler>::new();
164 let clen = be16_to_u16(irep_record.clen) as usize;
165 if clen > 0 {
166 for _ in 0..clen {
167 let value = CatchHandler {
168 type_: head[cur],
169 start: be32_to_u32([head[cur + 1], head[cur + 2], head[cur + 3], head[cur + 4]])
170 as usize,
171 end: be32_to_u32([head[cur + 5], head[cur + 6], head[cur + 7], head[cur + 8]])
172 as usize,
173 target: be32_to_u32([
174 head[cur + 9],
175 head[cur + 10],
176 head[cur + 11],
177 head[cur + 12],
178 ]) as usize,
179 };
180 catch_handlers.push(value);
181 cur += mem::size_of::<IrepCatchHandler>();
182 }
183 }
184
185 let data = &head[cur..cur + 2];
187 let plen = be16_to_u16([data[0], data[1]]) as usize;
188 cur += 2;
189
190 for _ in 0..plen {
191 let typ = head[cur];
192 cur += 1;
193 match typ {
194 0 => {
195 let data = &head[cur..cur + 2];
197 let strlen = be16_to_u16([data[0], data[1]]) as usize + 1;
198 cur += 2;
199 let strval = CStr::from_bytes_with_nul(&head[cur..cur + strlen])
200 .or(Err(Error::InvalidFormat))?;
201 pool.push(PoolValue::Str(strval.to_owned()));
202 cur += strlen;
203 }
204 1 => {
205 let data = &head[cur..cur + 4];
207 let mut bytes = [0u8; 4];
208 bytes.copy_from_slice(data);
209 let intval = i32::from_be_bytes(bytes);
210 pool.push(PoolValue::Int32(intval));
211 cur += 4;
212 }
213 2 => {
214 let data = &head[cur..cur + 2];
216 let strlen = be16_to_u16([data[0], data[1]]) as usize + 1;
217 cur += 2;
218 let strval = CStr::from_bytes_with_nul(&head[cur..cur + strlen])
219 .or(Err(Error::InvalidFormat))?;
220 pool.push(PoolValue::SStr(strval.to_owned()));
221 cur += strlen;
222 }
223 3 => {
224 let data = &head[cur..cur + 8];
226 let mut bytes = [0u8; 8];
227 bytes.copy_from_slice(data);
228 let intval = i64::from_le_bytes(bytes);
229 pool.push(PoolValue::Int64(intval));
230 cur += 8;
231 }
232 5 => {
233 let data = &head[cur..cur + 8];
235 let mut bytes = [0u8; 8];
236 bytes.copy_from_slice(data);
237 let floatval = f64::from_le_bytes(bytes);
238 pool.push(PoolValue::Float(floatval));
239 cur += 8;
240 }
241 7 => {
242 let data = &head[cur..cur + 2];
244 let bigint_len = be16_to_u16([data[0], data[1]]) as usize;
245 cur += 2;
246 let bigint_data = head[cur..cur + bigint_len].to_vec();
247 pool.push(PoolValue::BigInt(bigint_data));
248 cur += bigint_len;
249 }
250 v => {
251 return Err(Error::UnknownPoolType(v));
252 }
253 }
254 }
255
256 let data = &head[cur..cur + 2];
258 let slen = be16_to_u16([data[0], data[1]]) as usize;
259 cur += 2;
260 for _ in 0..slen {
261 let data = &head[cur..cur + 2];
262 let symlen = be16_to_u16([data[0], data[1]]) as usize + 1;
263 cur += 2;
264 let symval = CStr::from_bytes_with_nul(&head[cur..cur + symlen])
265 .or(Err(Error::InvalidFormat))?;
266 syms.push(symval.to_owned());
267 cur += symlen;
268 }
269
270 cur = start_cur + irep_rec_size;
271
272 let irep = Irep {
273 header: irep_record,
274 insn: insns,
275 plen,
276 pool,
277 slen,
278 syms,
279 catch_handlers,
280 lv: Vec::new(), };
282 ireps.push(irep);
283 }
284
285 Ok((irep_size, irep_header, ireps))
286}
287
288pub fn section_end(head: &[u8]) -> Result<usize, Error> {
289 let header = SectionMiscHeader::from_bytes(head)?;
290 Ok(be32_to_u32(header.size) as usize)
292}
293
294pub fn section_lvar(head: &[u8], ireps: &mut [Irep]) -> Result<(usize, LVar), Error> {
295 let mut cur = 0;
296 let header_size = mem::size_of::<SectionMiscHeader>();
297 let header = SectionMiscHeader::from_bytes(&head[cur..cur + header_size])?;
298 cur += header_size;
299
300 let syms_len = be32_to_u32([head[cur], head[cur + 1], head[cur + 2], head[cur + 3]]) as usize;
302 cur += 4;
303
304 let mut syms = Vec::new();
306 for _ in 0..syms_len {
307 let str_len = be16_to_u16([head[cur], head[cur + 1]]) as usize;
308 cur += 2;
309
310 let str_bytes = &head[cur..cur + str_len];
312 let c_str = CString::new(str_bytes).map_err(|_| Error::InvalidFormat)?;
313 syms.push(c_str);
314 cur += str_len;
315 }
316
317 let _ = read_lv_records(&head[cur..], ireps, 0, &syms, syms_len)?;
319
320 let lvar = LVar { header, syms };
321 Ok((be32_to_u32(lvar.header.size) as usize, lvar))
322}
323
324fn read_lv_records(
325 head: &[u8],
326 ireps: &mut [Irep],
327 irep_idx: usize,
328 syms: &[CString],
329 syms_len: usize,
330) -> Result<(usize, usize), Error> {
331 if irep_idx >= ireps.len() {
332 return Ok((0, irep_idx));
333 }
334
335 let mut cur = 0;
336 let nlocals = ireps[irep_idx].nlocals();
337 let rlen = ireps[irep_idx].rlen();
338
339 if nlocals == 0 {
340 return Err(Error::InvalidFormat);
341 }
342
343 let mut lv = Vec::new();
345 for _ in 0..(nlocals - 1) {
346 let sym_idx = be16_to_u16([head[cur], head[cur + 1]]);
347 cur += 2;
348
349 if sym_idx == RITE_LV_NULL_MARK {
350 lv.push(None);
351 } else {
352 let sym_idx = sym_idx as usize;
353 if sym_idx >= syms_len {
354 return Err(Error::InvalidFormat);
355 }
356 lv.push(Some(syms[sym_idx].clone()));
357 }
358 }
359
360 ireps[irep_idx].lv = lv;
361
362 let mut child_irep_idx = irep_idx + 1;
364 for _ in 0..rlen {
365 let (bytes_read, next_irep_idx) =
366 read_lv_records(&head[cur..], ireps, child_irep_idx, syms, syms_len)?;
367 cur += bytes_read;
368 child_irep_idx = next_irep_idx;
369 }
370
371 Ok((cur, child_irep_idx))
372}
373
374pub fn section_skip(head: &[u8]) -> Result<usize, Error> {
375 let header = SectionMiscHeader::from_bytes(head)?;
376 Ok(be32_to_u32(header.size) as usize)
378}
379
380pub fn peek4(src: &[u8]) -> Option<[char; 4]> {
381 if src.len() < 4 {
382 return None;
384 }
385 if let [a, b, c, d] = src[0..4] {
386 let a = char::from_u32(a as u32).unwrap();
387 let b = char::from_u32(b as u32).unwrap();
388 let c = char::from_u32(c as u32).unwrap();
389 let d = char::from_u32(d as u32).unwrap();
390 Some([a, b, c, d])
391 } else {
392 None
393 }
394}
395
396pub fn be32_to_u32(be32: [u8; 4]) -> u32 {
397 let binsize_be = unsafe { mem::transmute::<[u8; 4], u32be>(be32) };
398 let binsize: u32 = binsize_be.into();
399 binsize
400}
401
402pub fn be16_to_u16(be16: [u8; 2]) -> u16 {
403 let binsize_be = unsafe { mem::transmute::<[u8; 2], u16be>(be16) };
404 let binsize: u16 = binsize_be.into();
405 binsize
406}