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