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 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 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 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 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 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 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 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}