1 use crate::error; 2 use scroll::{IOread, IOwrite, Pread, Pwrite, SizeWith}; 3 4 /// Size of a single COFF relocation. 5 pub const COFF_RELOCATION_SIZE: usize = 10; 6 7 // x86 relocations. 8 9 /// The relocation is ignored. 10 pub const IMAGE_REL_I386_ABSOLUTE: u16 = 0x0000; 11 /// Not supported. 12 pub const IMAGE_REL_I386_DIR16: u16 = 0x0001; 13 /// Not supported. 14 pub const IMAGE_REL_I386_REL16: u16 = 0x0002; 15 /// The target's 32-bit VA. 16 pub const IMAGE_REL_I386_DIR32: u16 = 0x0006; 17 /// The target's 32-bit RVA. 18 pub const IMAGE_REL_I386_DIR32NB: u16 = 0x0007; 19 /// Not supported. 20 pub const IMAGE_REL_I386_SEG12: u16 = 0x0009; 21 /// The 16-bit section index of the section that contains the target. 22 /// 23 /// This is used to support debugging information. 24 pub const IMAGE_REL_I386_SECTION: u16 = 0x000A; 25 /// The 32-bit offset of the target from the beginning of its section. 26 /// 27 /// This is used to support debugging information and static thread local storage. 28 pub const IMAGE_REL_I386_SECREL: u16 = 0x000B; 29 /// The CLR token. 30 pub const IMAGE_REL_I386_TOKEN: u16 = 0x000C; 31 /// A 7-bit offset from the base of the section that contains the target. 32 pub const IMAGE_REL_I386_SECREL7: u16 = 0x000D; 33 /// The 32-bit relative displacement to the target. 34 /// 35 /// This supports the x86 relative branch and call instructions. 36 pub const IMAGE_REL_I386_REL32: u16 = 0x0014; 37 38 // x86-64 relocations. 39 40 /// The relocation is ignored. 41 pub const IMAGE_REL_AMD64_ABSOLUTE: u16 = 0x0000; 42 /// The 64-bit VA of the relocation target. 43 pub const IMAGE_REL_AMD64_ADDR64: u16 = 0x0001; 44 /// The 32-bit VA of the relocation target. 45 pub const IMAGE_REL_AMD64_ADDR32: u16 = 0x0002; 46 /// The 32-bit address without an image base (RVA). 47 pub const IMAGE_REL_AMD64_ADDR32NB: u16 = 0x0003; 48 /// The 32-bit relative address from the byte following the relocation. 49 pub const IMAGE_REL_AMD64_REL32: u16 = 0x0004; 50 /// The 32-bit address relative to byte distance 1 from the relocation. 51 pub const IMAGE_REL_AMD64_REL32_1: u16 = 0x0005; 52 /// The 32-bit address relative to byte distance 2 from the relocation. 53 pub const IMAGE_REL_AMD64_REL32_2: u16 = 0x0006; 54 /// The 32-bit address relative to byte distance 3 from the relocation. 55 pub const IMAGE_REL_AMD64_REL32_3: u16 = 0x0007; 56 /// The 32-bit address relative to byte distance 4 from the relocation. 57 pub const IMAGE_REL_AMD64_REL32_4: u16 = 0x0008; 58 /// The 32-bit address relative to byte distance 5 from the relocation. 59 pub const IMAGE_REL_AMD64_REL32_5: u16 = 0x0009; 60 /// The 16-bit section index of the section that contains the target. 61 /// 62 /// This is used to support debugging information. 63 pub const IMAGE_REL_AMD64_SECTION: u16 = 0x000A; 64 /// The 32-bit offset of the target from the beginning of its section. 65 /// 66 /// This is used to support debugging information and static thread local storage. 67 pub const IMAGE_REL_AMD64_SECREL: u16 = 0x000B; 68 /// A 7-bit unsigned offset from the base of the section that contains the target. 69 pub const IMAGE_REL_AMD64_SECREL7: u16 = 0x000C; 70 /// CLR tokens. 71 pub const IMAGE_REL_AMD64_TOKEN: u16 = 0x000D; 72 /// A 32-bit signed span-dependent value emitted into the object. 73 pub const IMAGE_REL_AMD64_SREL32: u16 = 0x000E; 74 /// A pair that must immediately follow every span-dependent value. 75 pub const IMAGE_REL_AMD64_PAIR: u16 = 0x000F; 76 /// A 32-bit signed span-dependent value that is applied at link time. 77 pub const IMAGE_REL_AMD64_SSPAN32: u16 = 0x0010; 78 79 /// A COFF relocation. 80 #[repr(C)] 81 #[derive(Debug, Copy, Clone, PartialEq, Default, Pread, Pwrite, IOread, IOwrite, SizeWith)] 82 pub struct Relocation { 83 /// The address of the item to which relocation is applied. 84 /// 85 /// This is the offset from the beginning of the section, plus the 86 /// value of the section's `virtual_address` field. 87 pub virtual_address: u32, 88 /// A zero-based index into the symbol table. 89 /// 90 /// This symbol gives the address that is to be used for the relocation. If the specified 91 /// symbol has section storage class, then the symbol's address is the address with the 92 /// first section of the same name. 93 pub symbol_table_index: u32, 94 /// A value that indicates the kind of relocation that should be performed. 95 /// 96 /// Valid relocation types depend on machine type. 97 pub typ: u16, 98 } 99 100 /// An iterator for COFF relocations. 101 #[derive(Default)] 102 pub struct Relocations<'a> { 103 offset: usize, 104 relocations: &'a [u8], 105 } 106 107 impl<'a> Relocations<'a> { 108 /// Parse a COFF relocation table at the given offset. 109 /// 110 /// The offset and number of relocations should be from the COFF section header. parse(bytes: &'a [u8], offset: usize, number: usize) -> error::Result<Relocations<'a>>111 pub fn parse(bytes: &'a [u8], offset: usize, number: usize) -> error::Result<Relocations<'a>> { 112 let relocations = bytes.pread_with(offset, number * COFF_RELOCATION_SIZE)?; 113 Ok(Relocations { 114 offset: 0, 115 relocations, 116 }) 117 } 118 } 119 120 impl<'a> Iterator for Relocations<'a> { 121 type Item = Relocation; next(&mut self) -> Option<Self::Item>122 fn next(&mut self) -> Option<Self::Item> { 123 if self.offset >= self.relocations.len() { 124 None 125 } else { 126 Some( 127 self.relocations 128 .gread_with(&mut self.offset, scroll::LE) 129 .unwrap(), 130 ) 131 } 132 } 133 } 134