1use core::iter::FusedIterator;
2
3use scroll::{IOread, IOwrite, Pread, Pwrite, SizeWith};
4
5use crate::error;
6use crate::pe::data_directories;
7use crate::pe::options;
8use crate::pe::section_table;
9use crate::pe::utils;
10
11pub const COFF_RELOCATION_SIZE: usize = 10;
13
14pub const IMAGE_REL_I386_ABSOLUTE: u16 = 0x0000;
18pub const IMAGE_REL_I386_DIR16: u16 = 0x0001;
20pub const IMAGE_REL_I386_REL16: u16 = 0x0002;
22pub const IMAGE_REL_I386_DIR32: u16 = 0x0006;
24pub const IMAGE_REL_I386_DIR32NB: u16 = 0x0007;
26pub const IMAGE_REL_I386_SEG12: u16 = 0x0009;
28pub const IMAGE_REL_I386_SECTION: u16 = 0x000A;
32pub const IMAGE_REL_I386_SECREL: u16 = 0x000B;
36pub const IMAGE_REL_I386_TOKEN: u16 = 0x000C;
38pub const IMAGE_REL_I386_SECREL7: u16 = 0x000D;
40pub const IMAGE_REL_I386_REL32: u16 = 0x0014;
44
45pub const IMAGE_REL_AMD64_ABSOLUTE: u16 = 0x0000;
49pub const IMAGE_REL_AMD64_ADDR64: u16 = 0x0001;
51pub const IMAGE_REL_AMD64_ADDR32: u16 = 0x0002;
53pub const IMAGE_REL_AMD64_ADDR32NB: u16 = 0x0003;
55pub const IMAGE_REL_AMD64_REL32: u16 = 0x0004;
57pub const IMAGE_REL_AMD64_REL32_1: u16 = 0x0005;
59pub const IMAGE_REL_AMD64_REL32_2: u16 = 0x0006;
61pub const IMAGE_REL_AMD64_REL32_3: u16 = 0x0007;
63pub const IMAGE_REL_AMD64_REL32_4: u16 = 0x0008;
65pub const IMAGE_REL_AMD64_REL32_5: u16 = 0x0009;
67pub const IMAGE_REL_AMD64_SECTION: u16 = 0x000A;
71pub const IMAGE_REL_AMD64_SECREL: u16 = 0x000B;
75pub const IMAGE_REL_AMD64_SECREL7: u16 = 0x000C;
77pub const IMAGE_REL_AMD64_TOKEN: u16 = 0x000D;
79pub const IMAGE_REL_AMD64_SREL32: u16 = 0x000E;
81pub const IMAGE_REL_AMD64_PAIR: u16 = 0x000F;
83pub const IMAGE_REL_AMD64_SSPAN32: u16 = 0x0010;
85
86pub const IMAGE_REL_ARM_ABSOLUTE: u16 = 0x0000;
90pub const IMAGE_REL_ARM_ADDR: u16 = 0x0001;
92pub const IMAGE_REL_ARM_ADDR32NB: u16 = 0x0002;
94pub const IMAGE_REL_ARM_BRANCH24: u16 = 0x0003;
96pub const IMAGE_REL_ARM_BRANCH11: u16 = 0x0004;
98pub const IMAGE_REL_ARM_TOKEN: u16 = 0x0005;
100pub const IMAGE_REL_ARM_GPREL12: u16 = 0x0006;
102pub const IMAGE_REL_ARM_GPREL7: u16 = 0x0007;
104pub const IMAGE_REL_ARM_BLX24: u16 = 0x0008;
106pub const IMAGE_REL_ARM_BLX11: u16 = 0x0009;
108pub const IMAGE_REL_ARM_SECTION: u16 = 0x000E;
110pub const IMAGE_REL_ARM_SECREL: u16 = 0x000F;
112pub const IMAGE_REL_ARM_MOV32A: u16 = 0x0010;
114pub const IMAGE_REL_ARM_MOV32T: u16 = 0x0011;
116pub const IMAGE_REL_ARM_BRANCH20T: u16 = 0x0012;
118pub const IMAGE_REL_ARM_BRANCH24T: u16 = 0x0014;
120pub const IMAGE_REL_ARM_BLX23T: u16 = 0x0015;
122
123pub const IMAGE_REL_ARM64_ABSOLUTE: u16 = 0x0000;
127pub const IMAGE_REL_ARM64_ADDR32: u16 = 0x0001;
129pub const IMAGE_REL_ARM64_ADDR32NB: u16 = 0x0002;
131pub const IMAGE_REL_ARM64_BRANCH26: u16 = 0x0003;
133pub const IMAGE_REL_ARM64_PAGEBASE_REL21: u16 = 0x0004;
135pub const IMAGE_REL_ARM64_REL21: u16 = 0x0005;
137pub const IMAGE_REL_ARM64_PAGEOFFSET_12A: u16 = 0x0006;
139pub const IMAGE_REL_ARM64_PAGEOFFSET_12L: u16 = 0x0007;
141pub const IMAGE_REL_ARM64_SECREL: u16 = 0x0008;
143pub const IMAGE_REL_ARM64_SECREL_LOW12A: u16 = 0x0009;
145pub const IMAGE_REL_ARM64_SECREL_HIGH12A: u16 = 0x000A;
147pub const IMAGE_REL_ARM64_SECREL_LOW12L: u16 = 0x000B;
149pub const IMAGE_REL_ARM64_TOKEN: u16 = 0x000C;
151pub const IMAGE_REL_ARM64_SECTION: u16 = 0x000D;
153pub const IMAGE_REL_ARM64_ADDR64: u16 = 0x000E;
155pub const IMAGE_REL_ARM64_BRANCH19: u16 = 0x000F;
157
158pub const IMAGE_REL_IA64_ABSOLUTE: u16 = 0x0000;
162pub const IMAGE_REL_IA64_IMM14: u16 = 0x0001;
164pub const IMAGE_REL_IA64_IMM22: u16 = 0x0002;
166pub const IMAGE_REL_IA64_IMM64: u16 = 0x0003;
168pub const IMAGE_REL_IA64_DIR: u16 = 0x0004;
170pub const IMAGE_REL_IA64_DIR64: u16 = 0x0005;
172pub const IMAGE_REL_IA64_PCREL21B: u16 = 0x0006;
174pub const IMAGE_REL_IA64_PCREL21M: u16 = 0x0007;
176pub const IMAGE_REL_IA64_PCREL21F: u16 = 0x0008;
178pub const IMAGE_REL_IA64_GPREL22: u16 = 0x0009;
180pub const IMAGE_REL_IA64_LTOFF22: u16 = 0x000A;
182pub const IMAGE_REL_IA64_SECTION: u16 = 0x000B;
184pub const IMAGE_REL_IA64_SECREL22: u16 = 0x000C;
186pub const IMAGE_REL_IA64_SECREL64I: u16 = 0x000D;
188pub const IMAGE_REL_IA64_SECREL: u16 = 0x000E;
190pub const IMAGE_REL_IA64_LTOFF64: u16 = 0x000F;
192pub const IMAGE_REL_IA64_DIR32NB: u16 = 0x0010;
194pub const IMAGE_REL_IA64_SREL14: u16 = 0x0011;
196pub const IMAGE_REL_IA64_SREL22: u16 = 0x0012;
198pub const IMAGE_REL_IA64_SREL32: u16 = 0x0013;
200pub const IMAGE_REL_IA64_UREL32: u16 = 0x0014;
202pub const IMAGE_REL_IA64_PCREL60X: u16 = 0x0015;
204pub const IMAGE_REL_IA64_PCREL60B: u16 = 0x0016;
206pub const IMAGE_REL_IA64_PCREL60F: u16 = 0x0017;
208pub const IMAGE_REL_IA64_PCREL60I: u16 = 0x0018;
210pub const IMAGE_REL_IA64_PCREL60M: u16 = 0x0019;
212pub const IMAGE_REL_IA64_IMMGPREL64: u16 = 0x001A;
214pub const IMAGE_REL_IA64_TOKEN: u16 = 0x001B;
216pub const IMAGE_REL_IA64_GPREL32: u16 = 0x001C;
218pub const IMAGE_REL_IA64_ADDEND: u16 = 0x001F;
220
221pub const IMAGE_REL_BASED_ABSOLUTE: u16 = 0;
225pub const IMAGE_REL_BASED_HIGH: u16 = 1;
227pub const IMAGE_REL_BASED_LOW: u16 = 2;
229pub const IMAGE_REL_BASED_HIGHLOW: u16 = 3;
231pub const IMAGE_REL_BASED_HIGHADJ: u16 = 4;
233pub const IMAGE_REL_BASED_MIPS_JMPADDR: u16 = 5;
235pub const IMAGE_REL_BASED_ARM_MOV32A: u16 = 5;
237pub const IMAGE_REL_BASED_ARM_MOV32: u16 = 5;
239pub const IMAGE_REL_BASED_SECTION: u16 = 6;
241pub const IMAGE_REL_BASED_REL: u16 = 7;
243pub const IMAGE_REL_BASED_ARM_MOV32T: u16 = 7;
245pub const IMAGE_REL_BASED_THUMB_MOV32: u16 = 7;
247pub const IMAGE_REL_BASED_MIPS_JMPADDR16: u16 = 9;
249pub const IMAGE_REL_BASED_IA64_IMM64: u16 = 9;
251pub const IMAGE_REL_BASED_DIR64: u16 = 10;
253pub const IMAGE_REL_BASED_HIGH3ADJ: u16 = 11;
255
256#[repr(C)]
258#[derive(Debug, Copy, Clone, PartialEq, Default, Pread, Pwrite, IOread, IOwrite, SizeWith)]
259pub struct Relocation {
260 pub virtual_address: u32,
265 pub symbol_table_index: u32,
271 pub typ: u16,
275}
276
277#[derive(Default)]
279pub struct Relocations<'a> {
280 offset: usize,
281 relocations: &'a [u8],
282}
283
284impl<'a> Relocations<'a> {
285 pub fn parse(bytes: &'a [u8], offset: usize, number: usize) -> error::Result<Relocations<'a>> {
289 let relocations = bytes.pread_with(offset, number * COFF_RELOCATION_SIZE)?;
290 Ok(Relocations {
291 offset: 0,
292 relocations,
293 })
294 }
295}
296
297impl<'a> Iterator for Relocations<'a> {
298 type Item = Relocation;
299 fn next(&mut self) -> Option<Self::Item> {
300 if self.offset >= self.relocations.len() {
301 None
302 } else {
303 Some(
304 self.relocations
305 .gread_with(&mut self.offset, scroll::LE)
306 .unwrap(),
307 )
308 }
309 }
310}
311
312#[derive(Debug, PartialEq, Clone, Default)]
313pub struct RelocationData<'a> {
314 bytes: &'a [u8],
315}
316
317impl<'a> RelocationData<'a> {
318 pub fn parse(
319 bytes: &'a [u8],
320 dd: data_directories::DataDirectory,
321 sections: &[section_table::SectionTable],
322 file_alignment: u32,
323 ) -> error::Result<Self> {
324 Self::parse_with_opts(
325 bytes,
326 dd,
327 sections,
328 file_alignment,
329 &options::ParseOptions::default(),
330 )
331 }
332
333 pub fn parse_with_opts(
334 bytes: &'a [u8],
335 dd: data_directories::DataDirectory,
336 sections: &[section_table::SectionTable],
337 file_alignment: u32,
338 opts: &options::ParseOptions,
339 ) -> error::Result<Self> {
340 let offset =
341 utils::find_offset(dd.virtual_address as usize, sections, file_alignment, opts)
342 .ok_or_else(|| {
343 error::Error::Malformed(format!(
344 "Cannot map base reloc rva {:#x} into offset",
345 dd.virtual_address
346 ))
347 })?;
348
349 if offset + dd.size as usize > bytes.len() {
351 return Err(error::Error::Malformed(format!(
352 "base reloc offset {:#x} and size {:#x} exceeds the bounds of the bytes size {:#x}",
353 offset,
354 dd.size,
355 bytes.len()
356 )));
357 }
358
359 let bytes = &bytes[offset..offset + dd.size as usize];
360
361 Ok(Self { bytes })
362 }
363
364 pub fn blocks(&self) -> RelocationBlockIterator<'a> {
366 RelocationBlockIterator {
367 bytes: &self.bytes,
368 offset: 0,
369 }
370 }
371}
372
373#[derive(Debug, Copy, Clone, PartialEq, Default)]
386pub struct RelocationBlock<'a> {
387 pub rva: u32,
389 pub size: u32,
391 pub bytes: &'a [u8],
393}
394
395impl RelocationBlock<'_> {
396 pub fn words(&self) -> RelocationWordIterator {
398 RelocationWordIterator {
399 bytes: &self.bytes,
400 offset: 0,
401 }
402 }
403}
404
405pub const RELOCATION_BLOCK_SIZE: usize = 8;
407
408impl<'a> scroll::ctx::TryFromCtx<'a, scroll::Endian> for RelocationBlock<'a> {
409 type Error = crate::error::Error;
410
411 fn try_from_ctx(bytes: &'a [u8], ctx: scroll::Endian) -> Result<(Self, usize), Self::Error> {
412 let mut offset = 0;
413 let rva = bytes.gread_with::<u32>(&mut offset, ctx)?;
414 let size = bytes.gread_with::<u32>(&mut offset, ctx)?;
415 let bytes = &[];
416 Ok((Self { rva, size, bytes }, offset))
417 }
418}
419
420#[derive(Clone, Copy, Debug)]
421pub struct RelocationBlockIterator<'a> {
422 bytes: &'a [u8],
423 offset: usize,
424}
425
426impl<'a> Iterator for RelocationBlockIterator<'a> {
427 type Item = error::Result<RelocationBlock<'a>>;
428
429 fn next(&mut self) -> Option<Self::Item> {
430 if self.offset >= self.bytes.len() {
431 return None;
432 }
433
434 Some(
435 match self
436 .bytes
437 .gread_with::<RelocationBlock>(&mut self.offset, scroll::LE)
438 {
439 Ok(block) => {
440 let word_size = block.size as usize - RELOCATION_BLOCK_SIZE;
441 let word_bytes = &self.bytes[self.offset..self.offset + word_size];
442 self.offset += word_size;
444 Ok(RelocationBlock {
445 bytes: word_bytes,
446 ..block
447 })
448 }
449 Err(error) => {
450 self.bytes = &[];
451 Err(error.into())
452 }
453 },
454 )
455 }
456}
457
458impl FusedIterator for RelocationBlockIterator<'_> {}
459
460#[repr(C)]
470#[derive(Debug, Copy, Clone, PartialEq, Default, Pread, Pwrite, IOread, IOwrite, SizeWith)]
471pub struct RelocationWord {
472 pub value: u16,
477}
478
479impl RelocationWord {
480 pub fn reloc_type(&self) -> u8 {
482 (self.value >> 12) as u8
483 }
484
485 pub fn offset(&self) -> u16 {
487 (self.value & 0xFFF) as u16
488 }
489}
490
491#[derive(Clone, Copy, Debug)]
492pub struct RelocationWordIterator<'a> {
493 bytes: &'a [u8],
494 offset: usize,
495}
496
497impl Iterator for RelocationWordIterator<'_> {
498 type Item = error::Result<RelocationWord>;
499
500 fn next(&mut self) -> Option<Self::Item> {
501 if self.offset >= self.bytes.len() {
502 return None;
503 }
504
505 Some(match self.bytes.gread_with(&mut self.offset, scroll::LE) {
506 Ok(word) => Ok(word),
507 Err(error) => {
508 self.bytes = &[];
509 Err(error.into())
510 }
511 })
512 }
513
514 fn size_hint(&self) -> (usize, Option<usize>) {
515 let count = self.bytes.len() / core::mem::size_of::<RelocationWord>();
516 (count, Some(count))
517 }
518}
519
520impl FusedIterator for RelocationWordIterator<'_> {}
521
522#[cfg(test)]
523mod tests {
524 use super::*;
525
526 static BASERELOC_DATA1: &[u8; 1360] = &[
527 0x00, 0xD0, 0x11, 0x00, 0x34, 0x02, 0x00, 0x00, 0x08, 0xA0, 0x18, 0xA0, 0x28, 0xA0, 0x38,
528 0xA0, 0x48, 0xA0, 0x58, 0xA0, 0x68, 0xA0, 0x78, 0xA0, 0x88, 0xA0, 0x98, 0xA0, 0xA8, 0xA0,
529 0xB8, 0xA0, 0xC8, 0xA0, 0xD8, 0xA0, 0xE0, 0xA0, 0xE8, 0xA0, 0xF0, 0xA0, 0xF8, 0xA0, 0x00,
530 0xA1, 0x08, 0xA1, 0x10, 0xA1, 0x18, 0xA1, 0x20, 0xA1, 0x28, 0xA1, 0x30, 0xA1, 0x38, 0xA1,
531 0x48, 0xA1, 0x50, 0xA1, 0x58, 0xA1, 0x60, 0xA1, 0x68, 0xA1, 0x70, 0xA1, 0x78, 0xA1, 0x80,
532 0xA1, 0x88, 0xA1, 0x98, 0xA1, 0xA0, 0xA1, 0xA8, 0xA1, 0xB8, 0xA1, 0xC0, 0xA1, 0xC8, 0xA1,
533 0xD0, 0xA1, 0xD8, 0xA1, 0xE8, 0xA1, 0xF8, 0xA1, 0x08, 0xA2, 0x18, 0xA2, 0x28, 0xA2, 0x38,
534 0xA2, 0x48, 0xA2, 0x58, 0xA2, 0x68, 0xA2, 0x78, 0xA2, 0x88, 0xA2, 0x98, 0xA2, 0xA8, 0xA2,
535 0xB8, 0xA2, 0xC8, 0xA2, 0xD8, 0xA2, 0xE8, 0xA2, 0x08, 0xA3, 0x28, 0xA3, 0x48, 0xA3, 0x68,
536 0xA3, 0x88, 0xA3, 0x98, 0xA3, 0xA8, 0xA3, 0xB8, 0xA3, 0xC8, 0xA3, 0xD8, 0xA3, 0xE8, 0xA3,
537 0xF8, 0xA3, 0x08, 0xA4, 0x18, 0xA4, 0x28, 0xA4, 0x38, 0xA4, 0x48, 0xA4, 0x58, 0xA4, 0x70,
538 0xA4, 0xA0, 0xA4, 0xA8, 0xA6, 0xB8, 0xA6, 0xC8, 0xA6, 0xD8, 0xA6, 0xE8, 0xA6, 0xF8, 0xA6,
539 0x00, 0xA7, 0x08, 0xA7, 0x30, 0xA7, 0x60, 0xA7, 0x88, 0xA7, 0x98, 0xA7, 0xA8, 0xA7, 0xB8,
540 0xA7, 0xC8, 0xA7, 0xD0, 0xA7, 0xD8, 0xA7, 0xE0, 0xA7, 0xF8, 0xA7, 0x00, 0xA8, 0x08, 0xA8,
541 0x10, 0xA8, 0x28, 0xA8, 0x38, 0xA8, 0x50, 0xA8, 0x70, 0xA8, 0x78, 0xA8, 0x80, 0xA8, 0x88,
542 0xA8, 0x90, 0xA8, 0x98, 0xA8, 0xA0, 0xA8, 0xA8, 0xA8, 0xB0, 0xA8, 0xB8, 0xA8, 0xC0, 0xA8,
543 0xC8, 0xA8, 0xD0, 0xA8, 0xD8, 0xA8, 0xE0, 0xA8, 0xE8, 0xA8, 0xF0, 0xA8, 0xF8, 0xA8, 0x00,
544 0xA9, 0x08, 0xA9, 0x10, 0xA9, 0x18, 0xA9, 0x20, 0xA9, 0x28, 0xA9, 0x30, 0xA9, 0x38, 0xA9,
545 0x40, 0xA9, 0x48, 0xA9, 0x50, 0xA9, 0x58, 0xA9, 0x60, 0xA9, 0x68, 0xA9, 0x70, 0xA9, 0x78,
546 0xA9, 0x80, 0xA9, 0x88, 0xA9, 0x90, 0xA9, 0x98, 0xA9, 0xA0, 0xA9, 0xA8, 0xA9, 0xB0, 0xA9,
547 0xB8, 0xA9, 0xC0, 0xA9, 0xC8, 0xA9, 0xD0, 0xA9, 0xD8, 0xA9, 0xE0, 0xA9, 0xE8, 0xA9, 0xF0,
548 0xA9, 0xF8, 0xA9, 0x00, 0xAA, 0x08, 0xAA, 0x10, 0xAA, 0x18, 0xAA, 0x20, 0xAA, 0x28, 0xAA,
549 0x30, 0xAA, 0x38, 0xAA, 0x40, 0xAA, 0x48, 0xAA, 0x50, 0xAA, 0x58, 0xAA, 0x70, 0xAA, 0x80,
550 0xAA, 0x88, 0xAA, 0x98, 0xAA, 0xB0, 0xAA, 0xC8, 0xAA, 0xE0, 0xAA, 0xF8, 0xAA, 0x08, 0xAB,
551 0x18, 0xAB, 0x28, 0xAB, 0x38, 0xAB, 0x48, 0xAB, 0x58, 0xAB, 0x68, 0xAB, 0x78, 0xAB, 0xD8,
552 0xAB, 0xF0, 0xAB, 0xF8, 0xAB, 0x00, 0xAC, 0x88, 0xAC, 0xA0, 0xAC, 0xA8, 0xAC, 0xB0, 0xAC,
553 0xB8, 0xAC, 0xC0, 0xAC, 0xC8, 0xAC, 0xD0, 0xAC, 0xD8, 0xAC, 0xE0, 0xAC, 0xE8, 0xAC, 0xF8,
554 0xAC, 0x00, 0xAD, 0x08, 0xAD, 0x10, 0xAD, 0x18, 0xAD, 0x20, 0xAD, 0x28, 0xAD, 0x30, 0xAD,
555 0x38, 0xAD, 0x48, 0xAD, 0x50, 0xAD, 0x58, 0xAD, 0x60, 0xAD, 0x70, 0xAD, 0x78, 0xAD, 0x80,
556 0xAD, 0x88, 0xAD, 0x98, 0xAD, 0xA0, 0xAD, 0xA8, 0xAD, 0xB0, 0xAD, 0xC8, 0xAD, 0xD0, 0xAD,
557 0xD8, 0xAD, 0xF0, 0xAD, 0xF8, 0xAD, 0x00, 0xAE, 0x18, 0xAE, 0x20, 0xAE, 0x28, 0xAE, 0x30,
558 0xAE, 0x38, 0xAE, 0x40, 0xAE, 0x48, 0xAE, 0x50, 0xAE, 0x58, 0xAE, 0x60, 0xAE, 0x68, 0xAE,
559 0x70, 0xAE, 0x78, 0xAE, 0x80, 0xAE, 0x88, 0xAE, 0x98, 0xAE, 0xA8, 0xAE, 0xB8, 0xAE, 0xC8,
560 0xAE, 0xD8, 0xAE, 0xE8, 0xAE, 0xF8, 0xAE, 0x08, 0xAF, 0x18, 0xAF, 0x20, 0xAF, 0x28, 0xAF,
561 0x30, 0xAF, 0x38, 0xAF, 0x40, 0xAF, 0x48, 0xAF, 0x50, 0xAF, 0x58, 0xAF, 0x60, 0xAF, 0x68,
562 0xAF, 0x70, 0xAF, 0x78, 0xAF, 0x80, 0xAF, 0x88, 0xAF, 0x90, 0xAF, 0x98, 0xAF, 0xA0, 0xAF,
563 0xA8, 0xAF, 0xB0, 0xAF, 0xB8, 0xAF, 0xC0, 0xAF, 0xC8, 0xAF, 0xD0, 0xAF, 0xD8, 0xAF, 0xE0,
564 0xAF, 0xE8, 0xAF, 0xF0, 0xAF, 0xF8, 0xAF, 0x00, 0x00, 0x00, 0xE0, 0x11, 0x00, 0x58, 0x01,
565 0x00, 0x00, 0x00, 0xA0, 0x08, 0xA0, 0x10, 0xA0, 0x18, 0xA0, 0x20, 0xA0, 0x30, 0xA0, 0x40,
566 0xA0, 0x48, 0xA0, 0x50, 0xA0, 0x58, 0xA0, 0x60, 0xA0, 0x68, 0xA0, 0x70, 0xA0, 0x78, 0xA0,
567 0x80, 0xA0, 0x88, 0xA0, 0x90, 0xA0, 0x98, 0xA0, 0xA0, 0xA0, 0xA8, 0xA0, 0xB0, 0xA0, 0xB8,
568 0xA0, 0xC0, 0xA0, 0xC8, 0xA0, 0xD0, 0xA0, 0xD8, 0xA0, 0xE0, 0xA0, 0xE8, 0xA0, 0xF0, 0xA0,
569 0xF8, 0xA0, 0x00, 0xA1, 0x08, 0xA1, 0x10, 0xA1, 0x18, 0xA1, 0x20, 0xA1, 0x28, 0xA1, 0x30,
570 0xA1, 0x38, 0xA1, 0x40, 0xA1, 0x48, 0xA1, 0x50, 0xA1, 0x58, 0xA1, 0x60, 0xA1, 0x68, 0xA1,
571 0x70, 0xA1, 0x78, 0xA1, 0x80, 0xA1, 0x88, 0xA1, 0x90, 0xA1, 0x98, 0xA1, 0xA0, 0xA1, 0xA8,
572 0xA1, 0xB0, 0xA1, 0xB8, 0xA1, 0xC0, 0xA1, 0xC8, 0xA1, 0xD0, 0xA1, 0xD8, 0xA1, 0xE0, 0xA1,
573 0xF0, 0xA1, 0x08, 0xA2, 0x10, 0xA2, 0x20, 0xA2, 0x30, 0xA2, 0x48, 0xA2, 0x50, 0xA2, 0x58,
574 0xA2, 0x60, 0xA2, 0x68, 0xA2, 0x70, 0xA2, 0x78, 0xA2, 0x88, 0xA2, 0x90, 0xA2, 0xA0, 0xA2,
575 0xA8, 0xA2, 0xB8, 0xA2, 0xC0, 0xA2, 0xD0, 0xA2, 0xD8, 0xA2, 0xE8, 0xA2, 0xF0, 0xA2, 0x08,
576 0xA3, 0x18, 0xA3, 0x28, 0xA3, 0x38, 0xA3, 0x48, 0xA3, 0x58, 0xA3, 0x68, 0xA3, 0x78, 0xA3,
577 0x80, 0xA3, 0x88, 0xA3, 0x90, 0xA3, 0x98, 0xA3, 0xA0, 0xA3, 0xA8, 0xA3, 0xB8, 0xA3, 0xC8,
578 0xA3, 0xD8, 0xA3, 0xF0, 0xA3, 0x18, 0xA4, 0x20, 0xA4, 0x30, 0xA4, 0x40, 0xA4, 0x50, 0xA4,
579 0x60, 0xA4, 0x70, 0xA4, 0x80, 0xA4, 0x90, 0xA4, 0xA0, 0xA4, 0xB0, 0xA4, 0xC0, 0xA4, 0xD0,
580 0xA4, 0xE0, 0xA4, 0xF0, 0xA4, 0x00, 0xA5, 0x10, 0xA5, 0x28, 0xA5, 0x50, 0xA5, 0x60, 0xA5,
581 0x70, 0xA5, 0x80, 0xA5, 0x90, 0xA5, 0xA0, 0xA5, 0xB0, 0xA5, 0xC0, 0xA5, 0xD0, 0xA5, 0xE0,
582 0xA5, 0xF0, 0xA5, 0x00, 0xA6, 0x10, 0xA6, 0x20, 0xA6, 0x28, 0xA6, 0x30, 0xA6, 0x38, 0xA6,
583 0x50, 0xA6, 0x68, 0xA6, 0x78, 0xA6, 0x88, 0xA6, 0x98, 0xA6, 0xA8, 0xA6, 0xB8, 0xA6, 0xC8,
584 0xA6, 0xD8, 0xA6, 0xE8, 0xA6, 0xF8, 0xA6, 0x08, 0xA7, 0x18, 0xA7, 0x28, 0xA7, 0x38, 0xA7,
585 0x48, 0xA7, 0x58, 0xA7, 0x68, 0xA7, 0x78, 0xA7, 0x88, 0xA7, 0x98, 0xA7, 0xA8, 0xA7, 0xB8,
586 0xA7, 0xC8, 0xA7, 0xD8, 0xA7, 0xE8, 0xA7, 0xF8, 0xA7, 0x08, 0xA8, 0x18, 0xA8, 0x28, 0xA8,
587 0x38, 0xA8, 0x58, 0xA8, 0x68, 0xA8, 0x80, 0xA8, 0x00, 0x60, 0x12, 0x00, 0x1C, 0x00, 0x00,
588 0x00, 0xA0, 0xA9, 0xA8, 0xA9, 0xB0, 0xA9, 0xB8, 0xA9, 0xC0, 0xA9, 0xC8, 0xA9, 0xD0, 0xA9,
589 0xD8, 0xA9, 0xE0, 0xA9, 0x00, 0x00, 0x00, 0x20, 0x15, 0x00, 0x28, 0x00, 0x00, 0x00, 0xE8,
590 0xA0, 0xF0, 0xA0, 0xF8, 0xA0, 0x08, 0xA1, 0x10, 0xA1, 0x18, 0xA1, 0x20, 0xA1, 0x38, 0xA1,
591 0x40, 0xA1, 0x48, 0xA1, 0x58, 0xA1, 0x60, 0xA1, 0x68, 0xA1, 0x70, 0xA1, 0x90, 0xA1, 0x00,
592 0x00, 0x00, 0x60, 0x16, 0x00, 0xE8, 0x00, 0x00, 0x00, 0x00, 0xA0, 0x08, 0xA0, 0x78, 0xA0,
593 0x98, 0xA0, 0xB8, 0xA0, 0xD8, 0xA0, 0xF8, 0xA0, 0x38, 0xA1, 0x50, 0xA1, 0x58, 0xA1, 0x60,
594 0xA1, 0x78, 0xA1, 0x88, 0xA1, 0x98, 0xA1, 0xA8, 0xA1, 0xB8, 0xA1, 0xC8, 0xA1, 0xD8, 0xA1,
595 0xE8, 0xA1, 0xF8, 0xA1, 0x08, 0xA2, 0x18, 0xA2, 0x28, 0xA2, 0x38, 0xA2, 0x48, 0xA2, 0x58,
596 0xA2, 0x68, 0xA2, 0x78, 0xA2, 0x88, 0xA2, 0x98, 0xA2, 0xA8, 0xA2, 0xB8, 0xA2, 0xC8, 0xA2,
597 0xD8, 0xA2, 0xE8, 0xA2, 0xF8, 0xA2, 0x08, 0xA3, 0x18, 0xA3, 0x28, 0xA3, 0x38, 0xA3, 0x40,
598 0xA3, 0x48, 0xA3, 0x50, 0xA3, 0x58, 0xA3, 0x60, 0xA3, 0x68, 0xA3, 0x70, 0xA3, 0x78, 0xA3,
599 0x80, 0xA3, 0x88, 0xA3, 0x98, 0xA3, 0xA0, 0xA3, 0xA8, 0xA3, 0xB0, 0xA3, 0xB8, 0xA3, 0xC0,
600 0xA3, 0xC8, 0xA3, 0xD0, 0xA3, 0xE0, 0xA3, 0xA8, 0xA4, 0xB0, 0xA4, 0xC0, 0xA4, 0xF0, 0xA4,
601 0x28, 0xA5, 0x60, 0xA5, 0x98, 0xA5, 0xC8, 0xA5, 0xF0, 0xA5, 0xF8, 0xA5, 0x10, 0xA6, 0x30,
602 0xA6, 0x38, 0xA6, 0x40, 0xA6, 0x48, 0xA6, 0x50, 0xA6, 0x58, 0xA6, 0x68, 0xA6, 0xA0, 0xA6,
603 0xD0, 0xA6, 0xD8, 0xA6, 0xE0, 0xA6, 0xE8, 0xA6, 0xF8, 0xA6, 0x00, 0xA7, 0x08, 0xA7, 0x10,
604 0xA7, 0x48, 0xA7, 0x50, 0xA7, 0x60, 0xA7, 0xC8, 0xA7, 0xD0, 0xA7, 0xE0, 0xA7, 0x48, 0xA8,
605 0x50, 0xA8, 0x60, 0xA8, 0xD0, 0xA8, 0xD8, 0xA8, 0xE0, 0xA8, 0x18, 0xA9, 0x20, 0xA9, 0x30,
606 0xA9, 0x98, 0xA9, 0xA0, 0xA9, 0xB0, 0xA9, 0x20, 0xAA, 0x50, 0xAA, 0x78, 0xAA, 0x80, 0xAA,
607 0x88, 0xAA, 0x98, 0xAA, 0xA0, 0xAA, 0xA8, 0xAA, 0x00, 0x10, 0x18, 0x00, 0x8C, 0x00, 0x00,
608 0x00, 0x00, 0xA0, 0x08, 0xA0, 0x10, 0xA0, 0x18, 0xA0, 0x20, 0xA0, 0x28, 0xA0, 0x30, 0xA0,
609 0x38, 0xA0, 0x40, 0xA0, 0x48, 0xA0, 0x50, 0xA0, 0x58, 0xA0, 0x60, 0xA0, 0x68, 0xA0, 0x70,
610 0xA0, 0x78, 0xA0, 0x80, 0xA0, 0x88, 0xA0, 0x90, 0xA0, 0x98, 0xA0, 0xA0, 0xA0, 0xA8, 0xA0,
611 0xB0, 0xA0, 0xB8, 0xA0, 0xC0, 0xA0, 0xC8, 0xA0, 0xD0, 0xA0, 0xD8, 0xA0, 0xE0, 0xA0, 0xE8,
612 0xA0, 0xF0, 0xA0, 0xF8, 0xA0, 0x00, 0xA1, 0x08, 0xA1, 0x10, 0xA1, 0x18, 0xA1, 0x20, 0xA1,
613 0x28, 0xA1, 0x30, 0xA1, 0x38, 0xA1, 0x40, 0xA1, 0x48, 0xA1, 0x50, 0xA1, 0x58, 0xA1, 0x60,
614 0xA1, 0x68, 0xA1, 0x70, 0xA1, 0x78, 0xA1, 0x80, 0xA1, 0x88, 0xA1, 0x90, 0xA1, 0x98, 0xA1,
615 0xA0, 0xA1, 0xA8, 0xA1, 0xB0, 0xA1, 0xB8, 0xA1, 0xC0, 0xA1, 0xC8, 0xA1, 0xD0, 0xA1, 0xE0,
616 0xA1, 0xF0, 0xA3, 0xF8, 0xA3, 0x00, 0xA4, 0x08, 0xA4, 0x10, 0xA4, 0x18, 0xA4, 0x00, 0x50,
617 0x18, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0xA0, 0x00, 0x00,
618 ];
619
620 #[test]
621 fn parse_baserelocs() {
622 let it = RelocationBlockIterator {
623 bytes: BASERELOC_DATA1,
624 offset: 0,
625 };
626 let blocks = it
627 .collect::<crate::error::Result<Vec<RelocationBlock>>>()
628 .unwrap();
629 assert_eq!(blocks.len(), 7);
630
631 const RELOC_ANY_ABSOLUTE: u8 = 0;
632 let ends_with_absrel = |block: &RelocationBlock| {
633 block
634 .words()
635 .last()
636 .transpose()
637 .unwrap()
638 .map(|x| x.reloc_type() == RELOC_ANY_ABSOLUTE)
639 .unwrap_or(false)
640 };
641
642 assert_eq!(blocks[0].rva, 0x0011D000);
643 assert_eq!(blocks[0].size, 0x234);
644 assert_eq!(ends_with_absrel(&blocks[0]), true);
645 assert_eq!(blocks[1].rva, 0x0011E000);
646 assert_eq!(blocks[1].size, 0x158);
647 assert_eq!(ends_with_absrel(&blocks[1]), false);
648 assert_eq!(blocks[2].rva, 0x00126000);
649 assert_eq!(blocks[2].size, 0x1C);
650 assert_eq!(ends_with_absrel(&blocks[2]), true);
651 assert_eq!(blocks[3].rva, 0x00152000);
652 assert_eq!(blocks[3].size, 0x28);
653 assert_eq!(ends_with_absrel(&blocks[3]), true);
654 assert_eq!(blocks[4].rva, 0x00166000);
655 assert_eq!(blocks[4].size, 0xE8);
656 assert_eq!(ends_with_absrel(&blocks[4]), false);
657 assert_eq!(blocks[5].rva, 0x00181000);
658 assert_eq!(blocks[5].size, 0x8C);
659 assert_eq!(ends_with_absrel(&blocks[5]), false);
660 assert_eq!(blocks[6].rva, 0x00185000);
661 assert_eq!(blocks[6].size, 0xC);
662 assert_eq!(ends_with_absrel(&blocks[6]), true);
663
664 let words = blocks
665 .iter()
666 .flat_map(|b| b.words())
667 .collect::<crate::error::Result<Vec<RelocationWord>>>()
668 .unwrap();
669 assert_eq!(words.len(), 652);
670 }
671}