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)]
314pub struct RelocationData<'a> {
315 bytes: &'a [u8],
317}
318
319impl<'a> RelocationData<'a> {
320 pub fn parse(
321 bytes: &'a [u8],
322 dd: data_directories::DataDirectory,
323 sections: &[section_table::SectionTable],
324 file_alignment: u32,
325 ) -> error::Result<Self> {
326 Self::parse_with_opts(
327 bytes,
328 dd,
329 sections,
330 file_alignment,
331 &options::ParseOptions::default(),
332 )
333 }
334
335 pub fn parse_with_opts(
336 bytes: &'a [u8],
337 dd: data_directories::DataDirectory,
338 sections: &[section_table::SectionTable],
339 file_alignment: u32,
340 opts: &options::ParseOptions,
341 ) -> error::Result<Self> {
342 let offset =
343 match utils::find_offset(dd.virtual_address as usize, sections, file_alignment, opts) {
344 Some(offset) => offset,
345 None => {
346 return Err(error::Error::Malformed(format!(
347 "Cannot map base reloc rva {:#x} into offset",
348 dd.virtual_address
349 )));
350 }
351 };
352
353 let available_size = if offset + (dd.size as usize) <= bytes.len() {
354 dd.size as usize
355 } else {
356 return Err(error::Error::Malformed(format!(
357 "base reloc offset {:#x} and size {:#x} exceeds the bounds of the bytes size {:#x}",
358 offset,
359 dd.size,
360 bytes.len()
361 )));
362 };
363
364 if offset >= bytes.len() {
365 return Err(error::Error::Malformed(format!(
366 "Relocation offset {:#x} is beyond file bounds (file size: {:#x})",
367 offset,
368 bytes.len()
369 )));
370 }
371
372 let remaining_bytes = bytes.len() - offset;
374 let safe_available_size = available_size.min(remaining_bytes);
375
376 if safe_available_size != available_size {
377 return Err(error::Error::Malformed(format!(
378 "Relocation size {:#x} at offset {:#x} exceeds remaining file data ({:#x} bytes)",
379 available_size, offset, remaining_bytes
380 )));
381 }
382
383 let bytes = bytes
384 .pread_with::<&[u8]>(offset, safe_available_size)
385 .map_err(|_| {
386 error::Error::Malformed(format!(
387 "base reloc offset {:#x} and size {:#x} exceeds the bounds of the bytes size {:#x}",
388 offset,
389 safe_available_size,
390 bytes.len()
391 ))
392 })?;
393
394 Ok(Self { bytes })
395 }
396
397 pub fn blocks(&self) -> RelocationBlockIterator<'a> {
399 RelocationBlockIterator {
400 bytes: &self.bytes,
401 offset: 0,
402 }
403 }
404}
405
406#[derive(Debug, Copy, Clone, PartialEq, Default)]
419pub struct RelocationBlock<'a> {
420 pub rva: u32,
422 pub size: u32,
424 pub bytes: &'a [u8],
426}
427
428impl RelocationBlock<'_> {
429 pub fn words(&self) -> RelocationWordIterator<'_> {
431 RelocationWordIterator {
432 bytes: &self.bytes,
433 offset: 0,
434 }
435 }
436}
437
438pub const RELOCATION_BLOCK_SIZE: usize = 8;
440
441impl<'a> scroll::ctx::TryFromCtx<'a, scroll::Endian> for RelocationBlock<'a> {
442 type Error = crate::error::Error;
443
444 fn try_from_ctx(bytes: &'a [u8], ctx: scroll::Endian) -> Result<(Self, usize), Self::Error> {
445 let mut offset = 0;
446 let rva = bytes.gread_with::<u32>(&mut offset, ctx)?;
447 let size = bytes.gread_with::<u32>(&mut offset, ctx)?;
448 if (size as usize) < RELOCATION_BLOCK_SIZE {
449 return Err(error::Error::Malformed(format!(
450 "base reloc size {size} is less than a block {RELOCATION_BLOCK_SIZE}"
451 )));
452 }
453 let word_size = size as usize - RELOCATION_BLOCK_SIZE;
454 let word_data = bytes.gread_with::<&[u8]>(&mut offset, word_size).map_err(|_| error::Error::Malformed(format!(
455 "base reloc block offset {:#x} and size {:#x} exceeds the bounds of the bytes size {:#x}",
456 offset,
457 word_size,
458 bytes.len()
459 )))?;
460 Ok((
461 Self {
462 rva,
463 size,
464 bytes: word_data,
465 },
466 offset,
467 ))
468 }
469}
470
471#[derive(Clone, Copy, Debug)]
472pub struct RelocationBlockIterator<'a> {
473 bytes: &'a [u8],
474 offset: usize,
475}
476
477impl<'a> Iterator for RelocationBlockIterator<'a> {
478 type Item = error::Result<RelocationBlock<'a>>;
479
480 fn next(&mut self) -> Option<Self::Item> {
481 if self.offset >= self.bytes.len() {
482 return None;
483 }
484
485 Some(
486 match self
487 .bytes
488 .gread_with::<RelocationBlock>(&mut self.offset, scroll::LE)
489 {
490 Ok(block) => Ok(block),
491 Err(error) => {
492 self.bytes = &[];
493 Err(error.into())
494 }
495 },
496 )
497 }
498}
499
500impl FusedIterator for RelocationBlockIterator<'_> {}
501
502#[derive(Debug, Copy, Clone, PartialEq, Default, Pread, Pwrite, IOread, IOwrite, SizeWith)]
512pub struct RelocationWord {
513 pub value: u16,
518}
519
520impl RelocationWord {
521 pub fn reloc_type(&self) -> u8 {
523 (self.value >> 12) as u8
524 }
525
526 pub fn offset(&self) -> u16 {
528 (self.value & 0xFFF) as u16
529 }
530}
531
532#[derive(Clone, Copy, Debug)]
533pub struct RelocationWordIterator<'a> {
534 bytes: &'a [u8],
535 offset: usize,
536}
537
538impl Iterator for RelocationWordIterator<'_> {
539 type Item = error::Result<RelocationWord>;
540
541 fn next(&mut self) -> Option<Self::Item> {
542 if self.offset >= self.bytes.len() {
543 return None;
544 }
545
546 Some(match self.bytes.gread_with(&mut self.offset, scroll::LE) {
547 Ok(word) => Ok(word),
548 Err(error) => {
549 self.bytes = &[];
550 Err(error.into())
551 }
552 })
553 }
554
555 fn size_hint(&self) -> (usize, Option<usize>) {
556 let count = self.bytes.len() / core::mem::size_of::<RelocationWord>();
557 (count, Some(count))
558 }
559}
560
561impl FusedIterator for RelocationWordIterator<'_> {}
562
563#[cfg(test)]
564mod tests {
565 use super::*;
566
567 static BASERELOC_DATA1: &[u8; 1360] = &[
568 0x00, 0xD0, 0x11, 0x00, 0x34, 0x02, 0x00, 0x00, 0x08, 0xA0, 0x18, 0xA0, 0x28, 0xA0, 0x38,
569 0xA0, 0x48, 0xA0, 0x58, 0xA0, 0x68, 0xA0, 0x78, 0xA0, 0x88, 0xA0, 0x98, 0xA0, 0xA8, 0xA0,
570 0xB8, 0xA0, 0xC8, 0xA0, 0xD8, 0xA0, 0xE0, 0xA0, 0xE8, 0xA0, 0xF0, 0xA0, 0xF8, 0xA0, 0x00,
571 0xA1, 0x08, 0xA1, 0x10, 0xA1, 0x18, 0xA1, 0x20, 0xA1, 0x28, 0xA1, 0x30, 0xA1, 0x38, 0xA1,
572 0x48, 0xA1, 0x50, 0xA1, 0x58, 0xA1, 0x60, 0xA1, 0x68, 0xA1, 0x70, 0xA1, 0x78, 0xA1, 0x80,
573 0xA1, 0x88, 0xA1, 0x98, 0xA1, 0xA0, 0xA1, 0xA8, 0xA1, 0xB8, 0xA1, 0xC0, 0xA1, 0xC8, 0xA1,
574 0xD0, 0xA1, 0xD8, 0xA1, 0xE8, 0xA1, 0xF8, 0xA1, 0x08, 0xA2, 0x18, 0xA2, 0x28, 0xA2, 0x38,
575 0xA2, 0x48, 0xA2, 0x58, 0xA2, 0x68, 0xA2, 0x78, 0xA2, 0x88, 0xA2, 0x98, 0xA2, 0xA8, 0xA2,
576 0xB8, 0xA2, 0xC8, 0xA2, 0xD8, 0xA2, 0xE8, 0xA2, 0x08, 0xA3, 0x28, 0xA3, 0x48, 0xA3, 0x68,
577 0xA3, 0x88, 0xA3, 0x98, 0xA3, 0xA8, 0xA3, 0xB8, 0xA3, 0xC8, 0xA3, 0xD8, 0xA3, 0xE8, 0xA3,
578 0xF8, 0xA3, 0x08, 0xA4, 0x18, 0xA4, 0x28, 0xA4, 0x38, 0xA4, 0x48, 0xA4, 0x58, 0xA4, 0x70,
579 0xA4, 0xA0, 0xA4, 0xA8, 0xA6, 0xB8, 0xA6, 0xC8, 0xA6, 0xD8, 0xA6, 0xE8, 0xA6, 0xF8, 0xA6,
580 0x00, 0xA7, 0x08, 0xA7, 0x30, 0xA7, 0x60, 0xA7, 0x88, 0xA7, 0x98, 0xA7, 0xA8, 0xA7, 0xB8,
581 0xA7, 0xC8, 0xA7, 0xD0, 0xA7, 0xD8, 0xA7, 0xE0, 0xA7, 0xF8, 0xA7, 0x00, 0xA8, 0x08, 0xA8,
582 0x10, 0xA8, 0x28, 0xA8, 0x38, 0xA8, 0x50, 0xA8, 0x70, 0xA8, 0x78, 0xA8, 0x80, 0xA8, 0x88,
583 0xA8, 0x90, 0xA8, 0x98, 0xA8, 0xA0, 0xA8, 0xA8, 0xA8, 0xB0, 0xA8, 0xB8, 0xA8, 0xC0, 0xA8,
584 0xC8, 0xA8, 0xD0, 0xA8, 0xD8, 0xA8, 0xE0, 0xA8, 0xE8, 0xA8, 0xF0, 0xA8, 0xF8, 0xA8, 0x00,
585 0xA9, 0x08, 0xA9, 0x10, 0xA9, 0x18, 0xA9, 0x20, 0xA9, 0x28, 0xA9, 0x30, 0xA9, 0x38, 0xA9,
586 0x40, 0xA9, 0x48, 0xA9, 0x50, 0xA9, 0x58, 0xA9, 0x60, 0xA9, 0x68, 0xA9, 0x70, 0xA9, 0x78,
587 0xA9, 0x80, 0xA9, 0x88, 0xA9, 0x90, 0xA9, 0x98, 0xA9, 0xA0, 0xA9, 0xA8, 0xA9, 0xB0, 0xA9,
588 0xB8, 0xA9, 0xC0, 0xA9, 0xC8, 0xA9, 0xD0, 0xA9, 0xD8, 0xA9, 0xE0, 0xA9, 0xE8, 0xA9, 0xF0,
589 0xA9, 0xF8, 0xA9, 0x00, 0xAA, 0x08, 0xAA, 0x10, 0xAA, 0x18, 0xAA, 0x20, 0xAA, 0x28, 0xAA,
590 0x30, 0xAA, 0x38, 0xAA, 0x40, 0xAA, 0x48, 0xAA, 0x50, 0xAA, 0x58, 0xAA, 0x70, 0xAA, 0x80,
591 0xAA, 0x88, 0xAA, 0x98, 0xAA, 0xB0, 0xAA, 0xC8, 0xAA, 0xE0, 0xAA, 0xF8, 0xAA, 0x08, 0xAB,
592 0x18, 0xAB, 0x28, 0xAB, 0x38, 0xAB, 0x48, 0xAB, 0x58, 0xAB, 0x68, 0xAB, 0x78, 0xAB, 0xD8,
593 0xAB, 0xF0, 0xAB, 0xF8, 0xAB, 0x00, 0xAC, 0x88, 0xAC, 0xA0, 0xAC, 0xA8, 0xAC, 0xB0, 0xAC,
594 0xB8, 0xAC, 0xC0, 0xAC, 0xC8, 0xAC, 0xD0, 0xAC, 0xD8, 0xAC, 0xE0, 0xAC, 0xE8, 0xAC, 0xF8,
595 0xAC, 0x00, 0xAD, 0x08, 0xAD, 0x10, 0xAD, 0x18, 0xAD, 0x20, 0xAD, 0x28, 0xAD, 0x30, 0xAD,
596 0x38, 0xAD, 0x48, 0xAD, 0x50, 0xAD, 0x58, 0xAD, 0x60, 0xAD, 0x70, 0xAD, 0x78, 0xAD, 0x80,
597 0xAD, 0x88, 0xAD, 0x98, 0xAD, 0xA0, 0xAD, 0xA8, 0xAD, 0xB0, 0xAD, 0xC8, 0xAD, 0xD0, 0xAD,
598 0xD8, 0xAD, 0xF0, 0xAD, 0xF8, 0xAD, 0x00, 0xAE, 0x18, 0xAE, 0x20, 0xAE, 0x28, 0xAE, 0x30,
599 0xAE, 0x38, 0xAE, 0x40, 0xAE, 0x48, 0xAE, 0x50, 0xAE, 0x58, 0xAE, 0x60, 0xAE, 0x68, 0xAE,
600 0x70, 0xAE, 0x78, 0xAE, 0x80, 0xAE, 0x88, 0xAE, 0x98, 0xAE, 0xA8, 0xAE, 0xB8, 0xAE, 0xC8,
601 0xAE, 0xD8, 0xAE, 0xE8, 0xAE, 0xF8, 0xAE, 0x08, 0xAF, 0x18, 0xAF, 0x20, 0xAF, 0x28, 0xAF,
602 0x30, 0xAF, 0x38, 0xAF, 0x40, 0xAF, 0x48, 0xAF, 0x50, 0xAF, 0x58, 0xAF, 0x60, 0xAF, 0x68,
603 0xAF, 0x70, 0xAF, 0x78, 0xAF, 0x80, 0xAF, 0x88, 0xAF, 0x90, 0xAF, 0x98, 0xAF, 0xA0, 0xAF,
604 0xA8, 0xAF, 0xB0, 0xAF, 0xB8, 0xAF, 0xC0, 0xAF, 0xC8, 0xAF, 0xD0, 0xAF, 0xD8, 0xAF, 0xE0,
605 0xAF, 0xE8, 0xAF, 0xF0, 0xAF, 0xF8, 0xAF, 0x00, 0x00, 0x00, 0xE0, 0x11, 0x00, 0x58, 0x01,
606 0x00, 0x00, 0x00, 0xA0, 0x08, 0xA0, 0x10, 0xA0, 0x18, 0xA0, 0x20, 0xA0, 0x30, 0xA0, 0x40,
607 0xA0, 0x48, 0xA0, 0x50, 0xA0, 0x58, 0xA0, 0x60, 0xA0, 0x68, 0xA0, 0x70, 0xA0, 0x78, 0xA0,
608 0x80, 0xA0, 0x88, 0xA0, 0x90, 0xA0, 0x98, 0xA0, 0xA0, 0xA0, 0xA8, 0xA0, 0xB0, 0xA0, 0xB8,
609 0xA0, 0xC0, 0xA0, 0xC8, 0xA0, 0xD0, 0xA0, 0xD8, 0xA0, 0xE0, 0xA0, 0xE8, 0xA0, 0xF0, 0xA0,
610 0xF8, 0xA0, 0x00, 0xA1, 0x08, 0xA1, 0x10, 0xA1, 0x18, 0xA1, 0x20, 0xA1, 0x28, 0xA1, 0x30,
611 0xA1, 0x38, 0xA1, 0x40, 0xA1, 0x48, 0xA1, 0x50, 0xA1, 0x58, 0xA1, 0x60, 0xA1, 0x68, 0xA1,
612 0x70, 0xA1, 0x78, 0xA1, 0x80, 0xA1, 0x88, 0xA1, 0x90, 0xA1, 0x98, 0xA1, 0xA0, 0xA1, 0xA8,
613 0xA1, 0xB0, 0xA1, 0xB8, 0xA1, 0xC0, 0xA1, 0xC8, 0xA1, 0xD0, 0xA1, 0xD8, 0xA1, 0xE0, 0xA1,
614 0xF0, 0xA1, 0x08, 0xA2, 0x10, 0xA2, 0x20, 0xA2, 0x30, 0xA2, 0x48, 0xA2, 0x50, 0xA2, 0x58,
615 0xA2, 0x60, 0xA2, 0x68, 0xA2, 0x70, 0xA2, 0x78, 0xA2, 0x88, 0xA2, 0x90, 0xA2, 0xA0, 0xA2,
616 0xA8, 0xA2, 0xB8, 0xA2, 0xC0, 0xA2, 0xD0, 0xA2, 0xD8, 0xA2, 0xE8, 0xA2, 0xF0, 0xA2, 0x08,
617 0xA3, 0x18, 0xA3, 0x28, 0xA3, 0x38, 0xA3, 0x48, 0xA3, 0x58, 0xA3, 0x68, 0xA3, 0x78, 0xA3,
618 0x80, 0xA3, 0x88, 0xA3, 0x90, 0xA3, 0x98, 0xA3, 0xA0, 0xA3, 0xA8, 0xA3, 0xB8, 0xA3, 0xC8,
619 0xA3, 0xD8, 0xA3, 0xF0, 0xA3, 0x18, 0xA4, 0x20, 0xA4, 0x30, 0xA4, 0x40, 0xA4, 0x50, 0xA4,
620 0x60, 0xA4, 0x70, 0xA4, 0x80, 0xA4, 0x90, 0xA4, 0xA0, 0xA4, 0xB0, 0xA4, 0xC0, 0xA4, 0xD0,
621 0xA4, 0xE0, 0xA4, 0xF0, 0xA4, 0x00, 0xA5, 0x10, 0xA5, 0x28, 0xA5, 0x50, 0xA5, 0x60, 0xA5,
622 0x70, 0xA5, 0x80, 0xA5, 0x90, 0xA5, 0xA0, 0xA5, 0xB0, 0xA5, 0xC0, 0xA5, 0xD0, 0xA5, 0xE0,
623 0xA5, 0xF0, 0xA5, 0x00, 0xA6, 0x10, 0xA6, 0x20, 0xA6, 0x28, 0xA6, 0x30, 0xA6, 0x38, 0xA6,
624 0x50, 0xA6, 0x68, 0xA6, 0x78, 0xA6, 0x88, 0xA6, 0x98, 0xA6, 0xA8, 0xA6, 0xB8, 0xA6, 0xC8,
625 0xA6, 0xD8, 0xA6, 0xE8, 0xA6, 0xF8, 0xA6, 0x08, 0xA7, 0x18, 0xA7, 0x28, 0xA7, 0x38, 0xA7,
626 0x48, 0xA7, 0x58, 0xA7, 0x68, 0xA7, 0x78, 0xA7, 0x88, 0xA7, 0x98, 0xA7, 0xA8, 0xA7, 0xB8,
627 0xA7, 0xC8, 0xA7, 0xD8, 0xA7, 0xE8, 0xA7, 0xF8, 0xA7, 0x08, 0xA8, 0x18, 0xA8, 0x28, 0xA8,
628 0x38, 0xA8, 0x58, 0xA8, 0x68, 0xA8, 0x80, 0xA8, 0x00, 0x60, 0x12, 0x00, 0x1C, 0x00, 0x00,
629 0x00, 0xA0, 0xA9, 0xA8, 0xA9, 0xB0, 0xA9, 0xB8, 0xA9, 0xC0, 0xA9, 0xC8, 0xA9, 0xD0, 0xA9,
630 0xD8, 0xA9, 0xE0, 0xA9, 0x00, 0x00, 0x00, 0x20, 0x15, 0x00, 0x28, 0x00, 0x00, 0x00, 0xE8,
631 0xA0, 0xF0, 0xA0, 0xF8, 0xA0, 0x08, 0xA1, 0x10, 0xA1, 0x18, 0xA1, 0x20, 0xA1, 0x38, 0xA1,
632 0x40, 0xA1, 0x48, 0xA1, 0x58, 0xA1, 0x60, 0xA1, 0x68, 0xA1, 0x70, 0xA1, 0x90, 0xA1, 0x00,
633 0x00, 0x00, 0x60, 0x16, 0x00, 0xE8, 0x00, 0x00, 0x00, 0x00, 0xA0, 0x08, 0xA0, 0x78, 0xA0,
634 0x98, 0xA0, 0xB8, 0xA0, 0xD8, 0xA0, 0xF8, 0xA0, 0x38, 0xA1, 0x50, 0xA1, 0x58, 0xA1, 0x60,
635 0xA1, 0x78, 0xA1, 0x88, 0xA1, 0x98, 0xA1, 0xA8, 0xA1, 0xB8, 0xA1, 0xC8, 0xA1, 0xD8, 0xA1,
636 0xE8, 0xA1, 0xF8, 0xA1, 0x08, 0xA2, 0x18, 0xA2, 0x28, 0xA2, 0x38, 0xA2, 0x48, 0xA2, 0x58,
637 0xA2, 0x68, 0xA2, 0x78, 0xA2, 0x88, 0xA2, 0x98, 0xA2, 0xA8, 0xA2, 0xB8, 0xA2, 0xC8, 0xA2,
638 0xD8, 0xA2, 0xE8, 0xA2, 0xF8, 0xA2, 0x08, 0xA3, 0x18, 0xA3, 0x28, 0xA3, 0x38, 0xA3, 0x40,
639 0xA3, 0x48, 0xA3, 0x50, 0xA3, 0x58, 0xA3, 0x60, 0xA3, 0x68, 0xA3, 0x70, 0xA3, 0x78, 0xA3,
640 0x80, 0xA3, 0x88, 0xA3, 0x98, 0xA3, 0xA0, 0xA3, 0xA8, 0xA3, 0xB0, 0xA3, 0xB8, 0xA3, 0xC0,
641 0xA3, 0xC8, 0xA3, 0xD0, 0xA3, 0xE0, 0xA3, 0xA8, 0xA4, 0xB0, 0xA4, 0xC0, 0xA4, 0xF0, 0xA4,
642 0x28, 0xA5, 0x60, 0xA5, 0x98, 0xA5, 0xC8, 0xA5, 0xF0, 0xA5, 0xF8, 0xA5, 0x10, 0xA6, 0x30,
643 0xA6, 0x38, 0xA6, 0x40, 0xA6, 0x48, 0xA6, 0x50, 0xA6, 0x58, 0xA6, 0x68, 0xA6, 0xA0, 0xA6,
644 0xD0, 0xA6, 0xD8, 0xA6, 0xE0, 0xA6, 0xE8, 0xA6, 0xF8, 0xA6, 0x00, 0xA7, 0x08, 0xA7, 0x10,
645 0xA7, 0x48, 0xA7, 0x50, 0xA7, 0x60, 0xA7, 0xC8, 0xA7, 0xD0, 0xA7, 0xE0, 0xA7, 0x48, 0xA8,
646 0x50, 0xA8, 0x60, 0xA8, 0xD0, 0xA8, 0xD8, 0xA8, 0xE0, 0xA8, 0x18, 0xA9, 0x20, 0xA9, 0x30,
647 0xA9, 0x98, 0xA9, 0xA0, 0xA9, 0xB0, 0xA9, 0x20, 0xAA, 0x50, 0xAA, 0x78, 0xAA, 0x80, 0xAA,
648 0x88, 0xAA, 0x98, 0xAA, 0xA0, 0xAA, 0xA8, 0xAA, 0x00, 0x10, 0x18, 0x00, 0x8C, 0x00, 0x00,
649 0x00, 0x00, 0xA0, 0x08, 0xA0, 0x10, 0xA0, 0x18, 0xA0, 0x20, 0xA0, 0x28, 0xA0, 0x30, 0xA0,
650 0x38, 0xA0, 0x40, 0xA0, 0x48, 0xA0, 0x50, 0xA0, 0x58, 0xA0, 0x60, 0xA0, 0x68, 0xA0, 0x70,
651 0xA0, 0x78, 0xA0, 0x80, 0xA0, 0x88, 0xA0, 0x90, 0xA0, 0x98, 0xA0, 0xA0, 0xA0, 0xA8, 0xA0,
652 0xB0, 0xA0, 0xB8, 0xA0, 0xC0, 0xA0, 0xC8, 0xA0, 0xD0, 0xA0, 0xD8, 0xA0, 0xE0, 0xA0, 0xE8,
653 0xA0, 0xF0, 0xA0, 0xF8, 0xA0, 0x00, 0xA1, 0x08, 0xA1, 0x10, 0xA1, 0x18, 0xA1, 0x20, 0xA1,
654 0x28, 0xA1, 0x30, 0xA1, 0x38, 0xA1, 0x40, 0xA1, 0x48, 0xA1, 0x50, 0xA1, 0x58, 0xA1, 0x60,
655 0xA1, 0x68, 0xA1, 0x70, 0xA1, 0x78, 0xA1, 0x80, 0xA1, 0x88, 0xA1, 0x90, 0xA1, 0x98, 0xA1,
656 0xA0, 0xA1, 0xA8, 0xA1, 0xB0, 0xA1, 0xB8, 0xA1, 0xC0, 0xA1, 0xC8, 0xA1, 0xD0, 0xA1, 0xE0,
657 0xA1, 0xF0, 0xA3, 0xF8, 0xA3, 0x00, 0xA4, 0x08, 0xA4, 0x10, 0xA4, 0x18, 0xA4, 0x00, 0x50,
658 0x18, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0xA0, 0x00, 0x00,
659 ];
660
661 #[test]
662 fn parse_baserelocs() {
663 let it = RelocationBlockIterator {
664 bytes: BASERELOC_DATA1,
665 offset: 0,
666 };
667 let blocks = it
668 .collect::<crate::error::Result<Vec<RelocationBlock>>>()
669 .unwrap();
670 assert_eq!(blocks.len(), 7);
671
672 const RELOC_ANY_ABSOLUTE: u8 = 0;
673 let ends_with_absrel = |block: &RelocationBlock| {
674 block
675 .words()
676 .last()
677 .transpose()
678 .unwrap()
679 .map(|x| x.reloc_type() == RELOC_ANY_ABSOLUTE)
680 .unwrap_or(false)
681 };
682
683 assert_eq!(blocks[0].rva, 0x0011D000);
684 assert_eq!(blocks[0].size, 0x234);
685 assert_eq!(ends_with_absrel(&blocks[0]), true);
686 assert_eq!(blocks[1].rva, 0x0011E000);
687 assert_eq!(blocks[1].size, 0x158);
688 assert_eq!(ends_with_absrel(&blocks[1]), false);
689 assert_eq!(blocks[2].rva, 0x00126000);
690 assert_eq!(blocks[2].size, 0x1C);
691 assert_eq!(ends_with_absrel(&blocks[2]), true);
692 assert_eq!(blocks[3].rva, 0x00152000);
693 assert_eq!(blocks[3].size, 0x28);
694 assert_eq!(ends_with_absrel(&blocks[3]), true);
695 assert_eq!(blocks[4].rva, 0x00166000);
696 assert_eq!(blocks[4].size, 0xE8);
697 assert_eq!(ends_with_absrel(&blocks[4]), false);
698 assert_eq!(blocks[5].rva, 0x00181000);
699 assert_eq!(blocks[5].size, 0x8C);
700 assert_eq!(ends_with_absrel(&blocks[5]), false);
701 assert_eq!(blocks[6].rva, 0x00185000);
702 assert_eq!(blocks[6].size, 0xC);
703 assert_eq!(ends_with_absrel(&blocks[6]), true);
704
705 let words = blocks
706 .iter()
707 .flat_map(|b| b.words())
708 .collect::<crate::error::Result<Vec<RelocationWord>>>()
709 .unwrap();
710 assert_eq!(words.len(), 652);
711 }
712}