/rust/registry/src/index.crates.io-6f17d22bba15001f/object-0.36.1/src/read/elf/relocation.rs
Line | Count | Source (jump to first uncovered line) |
1 | | use alloc::fmt; |
2 | | use alloc::vec::Vec; |
3 | | use core::fmt::Debug; |
4 | | use core::slice; |
5 | | |
6 | | use crate::elf; |
7 | | use crate::endian::{self, Endianness}; |
8 | | use crate::pod::Pod; |
9 | | use crate::read::{ |
10 | | self, Error, ReadRef, Relocation, RelocationEncoding, RelocationFlags, RelocationKind, |
11 | | RelocationTarget, SectionIndex, SymbolIndex, |
12 | | }; |
13 | | |
14 | | use super::{ElfFile, FileHeader, SectionHeader, SectionTable}; |
15 | | |
16 | | /// A mapping from section index to associated relocation sections. |
17 | | #[derive(Debug, Default)] |
18 | | pub struct RelocationSections { |
19 | | relocations: Vec<usize>, |
20 | | } |
21 | | |
22 | | impl RelocationSections { |
23 | | /// Create a new mapping using the section table. |
24 | | /// |
25 | | /// Skips relocation sections that do not use the given symbol table section. |
26 | 0 | pub fn parse<'data, Elf: FileHeader, R: ReadRef<'data>>( |
27 | 0 | endian: Elf::Endian, |
28 | 0 | sections: &SectionTable<'data, Elf, R>, |
29 | 0 | symbol_section: SectionIndex, |
30 | 0 | ) -> read::Result<Self> { |
31 | 0 | let mut relocations = vec![0; sections.len()]; |
32 | 0 | for (index, section) in sections.iter().enumerate().rev() { |
33 | 0 | let sh_type = section.sh_type(endian); |
34 | 0 | if sh_type == elf::SHT_REL || sh_type == elf::SHT_RELA { |
35 | | // The symbol indices used in relocations must be for the symbol table |
36 | | // we are expecting to use. |
37 | 0 | let sh_link = section.link(endian); |
38 | 0 | if sh_link != symbol_section { |
39 | 0 | continue; |
40 | 0 | } |
41 | 0 |
|
42 | 0 | let sh_info = section.info_link(endian); |
43 | 0 | if sh_info == SectionIndex(0) { |
44 | | // Skip dynamic relocations. |
45 | 0 | continue; |
46 | 0 | } |
47 | 0 | if sh_info.0 >= relocations.len() { |
48 | 0 | return Err(Error("Invalid ELF sh_info for relocation section")); |
49 | 0 | } |
50 | | |
51 | | // We don't support relocations that apply to other relocation sections |
52 | | // because it interferes with the chaining of relocation sections below. |
53 | 0 | let sh_info_type = sections.section(sh_info)?.sh_type(endian); |
54 | 0 | if sh_info_type == elf::SHT_REL || sh_info_type == elf::SHT_RELA { |
55 | 0 | return Err(Error("Unsupported ELF sh_info for relocation section")); |
56 | 0 | } |
57 | 0 |
|
58 | 0 | // Handle multiple relocation sections by chaining them. |
59 | 0 | let next = relocations[sh_info.0]; |
60 | 0 | relocations[sh_info.0] = index; |
61 | 0 | relocations[index] = next; |
62 | 0 | } |
63 | | } |
64 | 0 | Ok(Self { relocations }) |
65 | 0 | } |
66 | | |
67 | | /// Given a section index, return the section index of the associated relocation section. |
68 | | /// |
69 | | /// This may also be called with a relocation section index, and it will return the |
70 | | /// next associated relocation section. |
71 | 0 | pub fn get(&self, index: SectionIndex) -> Option<SectionIndex> { |
72 | 0 | self.relocations |
73 | 0 | .get(index.0) |
74 | 0 | .cloned() |
75 | 0 | .filter(|x| *x != 0) |
76 | 0 | .map(SectionIndex) |
77 | 0 | } |
78 | | } |
79 | | |
80 | | pub(super) enum ElfRelaIterator<'data, Elf: FileHeader> { |
81 | | Rel(slice::Iter<'data, Elf::Rel>), |
82 | | Rela(slice::Iter<'data, Elf::Rela>), |
83 | | } |
84 | | |
85 | | impl<'data, Elf: FileHeader> ElfRelaIterator<'data, Elf> { |
86 | 0 | fn is_rel(&self) -> bool { |
87 | 0 | match self { |
88 | 0 | ElfRelaIterator::Rel(_) => true, |
89 | 0 | ElfRelaIterator::Rela(_) => false, |
90 | | } |
91 | 0 | } |
92 | | } |
93 | | |
94 | | impl<'data, Elf: FileHeader> Iterator for ElfRelaIterator<'data, Elf> { |
95 | | type Item = Elf::Rela; |
96 | | |
97 | 0 | fn next(&mut self) -> Option<Self::Item> { |
98 | 0 | match self { |
99 | 0 | ElfRelaIterator::Rel(ref mut i) => i.next().cloned().map(Self::Item::from), |
100 | 0 | ElfRelaIterator::Rela(ref mut i) => i.next().cloned(), |
101 | | } |
102 | 0 | } |
103 | | } |
104 | | |
105 | | /// An iterator for the dynamic relocations in an [`ElfFile32`](super::ElfFile32). |
106 | | pub type ElfDynamicRelocationIterator32<'data, 'file, Endian = Endianness, R = &'data [u8]> = |
107 | | ElfDynamicRelocationIterator<'data, 'file, elf::FileHeader32<Endian>, R>; |
108 | | /// An iterator for the dynamic relocations in an [`ElfFile64`](super::ElfFile64). |
109 | | pub type ElfDynamicRelocationIterator64<'data, 'file, Endian = Endianness, R = &'data [u8]> = |
110 | | ElfDynamicRelocationIterator<'data, 'file, elf::FileHeader64<Endian>, R>; |
111 | | |
112 | | /// An iterator for the dynamic relocations in an [`ElfFile`]. |
113 | | pub struct ElfDynamicRelocationIterator<'data, 'file, Elf, R = &'data [u8]> |
114 | | where |
115 | | Elf: FileHeader, |
116 | | R: ReadRef<'data>, |
117 | | { |
118 | | /// The current relocation section index. |
119 | | pub(super) section_index: SectionIndex, |
120 | | pub(super) file: &'file ElfFile<'data, Elf, R>, |
121 | | pub(super) relocations: Option<ElfRelaIterator<'data, Elf>>, |
122 | | } |
123 | | |
124 | | impl<'data, 'file, Elf, R> Iterator for ElfDynamicRelocationIterator<'data, 'file, Elf, R> |
125 | | where |
126 | | Elf: FileHeader, |
127 | | R: ReadRef<'data>, |
128 | | { |
129 | | type Item = (u64, Relocation); |
130 | | |
131 | 0 | fn next(&mut self) -> Option<Self::Item> { |
132 | 0 | let endian = self.file.endian; |
133 | | loop { |
134 | 0 | if let Some(ref mut relocations) = self.relocations { |
135 | 0 | if let Some(reloc) = relocations.next() { |
136 | 0 | let relocation = |
137 | 0 | parse_relocation(self.file.header, endian, reloc, relocations.is_rel()); |
138 | 0 | return Some((reloc.r_offset(endian).into(), relocation)); |
139 | 0 | } |
140 | 0 | self.relocations = None; |
141 | 0 | } |
142 | | |
143 | 0 | let section = self.file.sections.section(self.section_index).ok()?; |
144 | 0 | self.section_index.0 += 1; |
145 | 0 |
|
146 | 0 | if section.link(endian) != self.file.dynamic_symbols.section() { |
147 | 0 | continue; |
148 | 0 | } |
149 | 0 |
|
150 | 0 | match section.sh_type(endian) { |
151 | | elf::SHT_REL => { |
152 | 0 | if let Ok(relocations) = section.data_as_array(endian, self.file.data) { |
153 | 0 | self.relocations = Some(ElfRelaIterator::Rel(relocations.iter())); |
154 | 0 | } |
155 | | } |
156 | | elf::SHT_RELA => { |
157 | 0 | if let Ok(relocations) = section.data_as_array(endian, self.file.data) { |
158 | 0 | self.relocations = Some(ElfRelaIterator::Rela(relocations.iter())); |
159 | 0 | } |
160 | | } |
161 | 0 | _ => {} |
162 | | } |
163 | | } |
164 | 0 | } |
165 | | } |
166 | | |
167 | | impl<'data, 'file, Elf, R> fmt::Debug for ElfDynamicRelocationIterator<'data, 'file, Elf, R> |
168 | | where |
169 | | Elf: FileHeader, |
170 | | R: ReadRef<'data>, |
171 | | { |
172 | 0 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
173 | 0 | f.debug_struct("ElfDynamicRelocationIterator").finish() |
174 | 0 | } |
175 | | } |
176 | | |
177 | | /// An iterator for the relocations for an [`ElfSection32`](super::ElfSection32). |
178 | | pub type ElfSectionRelocationIterator32<'data, 'file, Endian = Endianness, R = &'data [u8]> = |
179 | | ElfSectionRelocationIterator<'data, 'file, elf::FileHeader32<Endian>, R>; |
180 | | /// An iterator for the relocations for an [`ElfSection64`](super::ElfSection64). |
181 | | pub type ElfSectionRelocationIterator64<'data, 'file, Endian = Endianness, R = &'data [u8]> = |
182 | | ElfSectionRelocationIterator<'data, 'file, elf::FileHeader64<Endian>, R>; |
183 | | |
184 | | /// An iterator for the relocations for an [`ElfSection`](super::ElfSection). |
185 | | pub struct ElfSectionRelocationIterator<'data, 'file, Elf, R = &'data [u8]> |
186 | | where |
187 | | Elf: FileHeader, |
188 | | R: ReadRef<'data>, |
189 | | { |
190 | | /// The current pointer in the chain of relocation sections. |
191 | | pub(super) section_index: SectionIndex, |
192 | | pub(super) file: &'file ElfFile<'data, Elf, R>, |
193 | | pub(super) relocations: Option<ElfRelaIterator<'data, Elf>>, |
194 | | } |
195 | | |
196 | | impl<'data, 'file, Elf, R> Iterator for ElfSectionRelocationIterator<'data, 'file, Elf, R> |
197 | | where |
198 | | Elf: FileHeader, |
199 | | R: ReadRef<'data>, |
200 | | { |
201 | | type Item = (u64, Relocation); |
202 | | |
203 | 0 | fn next(&mut self) -> Option<Self::Item> { |
204 | 0 | let endian = self.file.endian; |
205 | | loop { |
206 | 0 | if let Some(ref mut relocations) = self.relocations { |
207 | 0 | if let Some(reloc) = relocations.next() { |
208 | 0 | let relocation = |
209 | 0 | parse_relocation(self.file.header, endian, reloc, relocations.is_rel()); |
210 | 0 | return Some((reloc.r_offset(endian).into(), relocation)); |
211 | 0 | } |
212 | 0 | self.relocations = None; |
213 | 0 | } |
214 | 0 | self.section_index = self.file.relocations.get(self.section_index)?; |
215 | | // The construction of RelocationSections ensures section_index is valid. |
216 | 0 | let section = self.file.sections.section(self.section_index).unwrap(); |
217 | 0 | match section.sh_type(endian) { |
218 | | elf::SHT_REL => { |
219 | 0 | if let Ok(relocations) = section.data_as_array(endian, self.file.data) { |
220 | 0 | self.relocations = Some(ElfRelaIterator::Rel(relocations.iter())); |
221 | 0 | } |
222 | | } |
223 | | elf::SHT_RELA => { |
224 | 0 | if let Ok(relocations) = section.data_as_array(endian, self.file.data) { |
225 | 0 | self.relocations = Some(ElfRelaIterator::Rela(relocations.iter())); |
226 | 0 | } |
227 | | } |
228 | 0 | _ => {} |
229 | | } |
230 | | } |
231 | 0 | } |
232 | | } |
233 | | |
234 | | impl<'data, 'file, Elf, R> fmt::Debug for ElfSectionRelocationIterator<'data, 'file, Elf, R> |
235 | | where |
236 | | Elf: FileHeader, |
237 | | R: ReadRef<'data>, |
238 | | { |
239 | 0 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
240 | 0 | f.debug_struct("ElfSectionRelocationIterator").finish() |
241 | 0 | } |
242 | | } |
243 | | |
244 | 0 | fn parse_relocation<Elf: FileHeader>( |
245 | 0 | header: &Elf, |
246 | 0 | endian: Elf::Endian, |
247 | 0 | reloc: Elf::Rela, |
248 | 0 | implicit_addend: bool, |
249 | 0 | ) -> Relocation { |
250 | 0 | let mut encoding = RelocationEncoding::Generic; |
251 | 0 | let is_mips64el = header.is_mips64el(endian); |
252 | 0 | let r_type = reloc.r_type(endian, is_mips64el); |
253 | 0 | let flags = RelocationFlags::Elf { r_type }; |
254 | 0 | let (kind, size) = match header.e_machine(endian) { |
255 | | elf::EM_AARCH64 => { |
256 | 0 | if header.is_type_64() { |
257 | 0 | match r_type { |
258 | 0 | elf::R_AARCH64_ABS64 => (RelocationKind::Absolute, 64), |
259 | 0 | elf::R_AARCH64_ABS32 => (RelocationKind::Absolute, 32), |
260 | 0 | elf::R_AARCH64_ABS16 => (RelocationKind::Absolute, 16), |
261 | 0 | elf::R_AARCH64_PREL64 => (RelocationKind::Relative, 64), |
262 | 0 | elf::R_AARCH64_PREL32 => (RelocationKind::Relative, 32), |
263 | 0 | elf::R_AARCH64_PREL16 => (RelocationKind::Relative, 16), |
264 | | elf::R_AARCH64_CALL26 => { |
265 | 0 | encoding = RelocationEncoding::AArch64Call; |
266 | 0 | (RelocationKind::PltRelative, 26) |
267 | | } |
268 | 0 | _ => (RelocationKind::Unknown, 0), |
269 | | } |
270 | | } else { |
271 | 0 | match r_type { |
272 | 0 | elf::R_AARCH64_P32_ABS32 => (RelocationKind::Absolute, 32), |
273 | 0 | _ => (RelocationKind::Unknown, 0), |
274 | | } |
275 | | } |
276 | | } |
277 | 0 | elf::EM_ARM => match r_type { |
278 | 0 | elf::R_ARM_ABS32 => (RelocationKind::Absolute, 32), |
279 | 0 | _ => (RelocationKind::Unknown, 0), |
280 | | }, |
281 | 0 | elf::EM_AVR => match r_type { |
282 | 0 | elf::R_AVR_32 => (RelocationKind::Absolute, 32), |
283 | 0 | elf::R_AVR_16 => (RelocationKind::Absolute, 16), |
284 | 0 | _ => (RelocationKind::Unknown, 0), |
285 | | }, |
286 | 0 | elf::EM_BPF => match r_type { |
287 | 0 | elf::R_BPF_64_64 => (RelocationKind::Absolute, 64), |
288 | 0 | elf::R_BPF_64_32 => (RelocationKind::Absolute, 32), |
289 | 0 | _ => (RelocationKind::Unknown, 0), |
290 | | }, |
291 | 0 | elf::EM_CSKY => match r_type { |
292 | 0 | elf::R_CKCORE_ADDR32 => (RelocationKind::Absolute, 32), |
293 | 0 | elf::R_CKCORE_PCREL32 => (RelocationKind::Relative, 32), |
294 | 0 | _ => (RelocationKind::Unknown, 0), |
295 | | }, |
296 | 0 | elf::EM_386 => match r_type { |
297 | 0 | elf::R_386_32 => (RelocationKind::Absolute, 32), |
298 | 0 | elf::R_386_PC32 => (RelocationKind::Relative, 32), |
299 | 0 | elf::R_386_GOT32 => (RelocationKind::Got, 32), |
300 | 0 | elf::R_386_PLT32 => (RelocationKind::PltRelative, 32), |
301 | 0 | elf::R_386_GOTOFF => (RelocationKind::GotBaseOffset, 32), |
302 | 0 | elf::R_386_GOTPC => (RelocationKind::GotBaseRelative, 32), |
303 | 0 | elf::R_386_16 => (RelocationKind::Absolute, 16), |
304 | 0 | elf::R_386_PC16 => (RelocationKind::Relative, 16), |
305 | 0 | elf::R_386_8 => (RelocationKind::Absolute, 8), |
306 | 0 | elf::R_386_PC8 => (RelocationKind::Relative, 8), |
307 | 0 | _ => (RelocationKind::Unknown, 0), |
308 | | }, |
309 | 0 | elf::EM_X86_64 => match r_type { |
310 | 0 | elf::R_X86_64_64 => (RelocationKind::Absolute, 64), |
311 | 0 | elf::R_X86_64_PC32 => (RelocationKind::Relative, 32), |
312 | 0 | elf::R_X86_64_GOT32 => (RelocationKind::Got, 32), |
313 | 0 | elf::R_X86_64_PLT32 => (RelocationKind::PltRelative, 32), |
314 | 0 | elf::R_X86_64_GOTPCREL => (RelocationKind::GotRelative, 32), |
315 | 0 | elf::R_X86_64_32 => (RelocationKind::Absolute, 32), |
316 | | elf::R_X86_64_32S => { |
317 | 0 | encoding = RelocationEncoding::X86Signed; |
318 | 0 | (RelocationKind::Absolute, 32) |
319 | | } |
320 | 0 | elf::R_X86_64_16 => (RelocationKind::Absolute, 16), |
321 | 0 | elf::R_X86_64_PC16 => (RelocationKind::Relative, 16), |
322 | 0 | elf::R_X86_64_8 => (RelocationKind::Absolute, 8), |
323 | 0 | elf::R_X86_64_PC8 => (RelocationKind::Relative, 8), |
324 | 0 | _ => (RelocationKind::Unknown, 0), |
325 | | }, |
326 | 0 | elf::EM_HEXAGON => match r_type { |
327 | 0 | elf::R_HEX_32 => (RelocationKind::Absolute, 32), |
328 | 0 | _ => (RelocationKind::Unknown, 0), |
329 | | }, |
330 | 0 | elf::EM_LOONGARCH => match r_type { |
331 | 0 | elf::R_LARCH_32 => (RelocationKind::Absolute, 32), |
332 | 0 | elf::R_LARCH_64 => (RelocationKind::Absolute, 64), |
333 | 0 | elf::R_LARCH_32_PCREL => (RelocationKind::Relative, 32), |
334 | 0 | elf::R_LARCH_64_PCREL => (RelocationKind::Relative, 64), |
335 | | elf::R_LARCH_B16 => { |
336 | 0 | encoding = RelocationEncoding::LoongArchBranch; |
337 | 0 | (RelocationKind::Relative, 16) |
338 | | } |
339 | | elf::R_LARCH_B21 => { |
340 | 0 | encoding = RelocationEncoding::LoongArchBranch; |
341 | 0 | (RelocationKind::Relative, 21) |
342 | | } |
343 | | elf::R_LARCH_B26 => { |
344 | 0 | encoding = RelocationEncoding::LoongArchBranch; |
345 | 0 | (RelocationKind::Relative, 26) |
346 | | } |
347 | 0 | _ => (RelocationKind::Unknown, 0), |
348 | | }, |
349 | 0 | elf::EM_MIPS => match r_type { |
350 | 0 | elf::R_MIPS_16 => (RelocationKind::Absolute, 16), |
351 | 0 | elf::R_MIPS_32 => (RelocationKind::Absolute, 32), |
352 | 0 | elf::R_MIPS_64 => (RelocationKind::Absolute, 64), |
353 | 0 | _ => (RelocationKind::Unknown, 0), |
354 | | }, |
355 | 0 | elf::EM_MSP430 => match r_type { |
356 | 0 | elf::R_MSP430_32 => (RelocationKind::Absolute, 32), |
357 | 0 | elf::R_MSP430_16_BYTE => (RelocationKind::Absolute, 16), |
358 | 0 | _ => (RelocationKind::Unknown, 0), |
359 | | }, |
360 | 0 | elf::EM_PPC => match r_type { |
361 | 0 | elf::R_PPC_ADDR32 => (RelocationKind::Absolute, 32), |
362 | 0 | _ => (RelocationKind::Unknown, 0), |
363 | | }, |
364 | 0 | elf::EM_PPC64 => match r_type { |
365 | 0 | elf::R_PPC64_ADDR32 => (RelocationKind::Absolute, 32), |
366 | 0 | elf::R_PPC64_ADDR64 => (RelocationKind::Absolute, 64), |
367 | 0 | _ => (RelocationKind::Unknown, 0), |
368 | | }, |
369 | 0 | elf::EM_RISCV => match r_type { |
370 | 0 | elf::R_RISCV_32 => (RelocationKind::Absolute, 32), |
371 | 0 | elf::R_RISCV_64 => (RelocationKind::Absolute, 64), |
372 | 0 | _ => (RelocationKind::Unknown, 0), |
373 | | }, |
374 | 0 | elf::EM_S390 => match r_type { |
375 | 0 | elf::R_390_8 => (RelocationKind::Absolute, 8), |
376 | 0 | elf::R_390_16 => (RelocationKind::Absolute, 16), |
377 | 0 | elf::R_390_32 => (RelocationKind::Absolute, 32), |
378 | 0 | elf::R_390_64 => (RelocationKind::Absolute, 64), |
379 | 0 | elf::R_390_PC16 => (RelocationKind::Relative, 16), |
380 | 0 | elf::R_390_PC32 => (RelocationKind::Relative, 32), |
381 | 0 | elf::R_390_PC64 => (RelocationKind::Relative, 64), |
382 | | elf::R_390_PC16DBL => { |
383 | 0 | encoding = RelocationEncoding::S390xDbl; |
384 | 0 | (RelocationKind::Relative, 16) |
385 | | } |
386 | | elf::R_390_PC32DBL => { |
387 | 0 | encoding = RelocationEncoding::S390xDbl; |
388 | 0 | (RelocationKind::Relative, 32) |
389 | | } |
390 | | elf::R_390_PLT16DBL => { |
391 | 0 | encoding = RelocationEncoding::S390xDbl; |
392 | 0 | (RelocationKind::PltRelative, 16) |
393 | | } |
394 | | elf::R_390_PLT32DBL => { |
395 | 0 | encoding = RelocationEncoding::S390xDbl; |
396 | 0 | (RelocationKind::PltRelative, 32) |
397 | | } |
398 | 0 | elf::R_390_GOT16 => (RelocationKind::Got, 16), |
399 | 0 | elf::R_390_GOT32 => (RelocationKind::Got, 32), |
400 | 0 | elf::R_390_GOT64 => (RelocationKind::Got, 64), |
401 | | elf::R_390_GOTENT => { |
402 | 0 | encoding = RelocationEncoding::S390xDbl; |
403 | 0 | (RelocationKind::GotRelative, 32) |
404 | | } |
405 | 0 | elf::R_390_GOTOFF16 => (RelocationKind::GotBaseOffset, 16), |
406 | 0 | elf::R_390_GOTOFF32 => (RelocationKind::GotBaseOffset, 32), |
407 | 0 | elf::R_390_GOTOFF64 => (RelocationKind::GotBaseOffset, 64), |
408 | 0 | elf::R_390_GOTPC => (RelocationKind::GotBaseRelative, 64), |
409 | | elf::R_390_GOTPCDBL => { |
410 | 0 | encoding = RelocationEncoding::S390xDbl; |
411 | 0 | (RelocationKind::GotBaseRelative, 32) |
412 | | } |
413 | 0 | _ => (RelocationKind::Unknown, 0), |
414 | | }, |
415 | 0 | elf::EM_SBF => match r_type { |
416 | 0 | elf::R_SBF_64_64 => (RelocationKind::Absolute, 64), |
417 | 0 | elf::R_SBF_64_32 => (RelocationKind::Absolute, 32), |
418 | 0 | _ => (RelocationKind::Unknown, 0), |
419 | | }, |
420 | 0 | elf::EM_SHARC => match r_type { |
421 | | elf::R_SHARC_ADDR24_V3 => { |
422 | 0 | encoding = RelocationEncoding::SharcTypeA; |
423 | 0 | (RelocationKind::Absolute, 24) |
424 | | } |
425 | | elf::R_SHARC_ADDR32_V3 => { |
426 | 0 | encoding = RelocationEncoding::SharcTypeA; |
427 | 0 | (RelocationKind::Absolute, 32) |
428 | | } |
429 | | elf::R_SHARC_ADDR_VAR_V3 => { |
430 | 0 | encoding = RelocationEncoding::Generic; |
431 | 0 | (RelocationKind::Absolute, 32) |
432 | | } |
433 | | elf::R_SHARC_PCRSHORT_V3 => { |
434 | 0 | encoding = RelocationEncoding::SharcTypeA; |
435 | 0 | (RelocationKind::Relative, 6) |
436 | | } |
437 | | elf::R_SHARC_PCRLONG_V3 => { |
438 | 0 | encoding = RelocationEncoding::SharcTypeA; |
439 | 0 | (RelocationKind::Relative, 24) |
440 | | } |
441 | | elf::R_SHARC_DATA6_V3 => { |
442 | 0 | encoding = RelocationEncoding::SharcTypeA; |
443 | 0 | (RelocationKind::Absolute, 6) |
444 | | } |
445 | | elf::R_SHARC_DATA16_V3 => { |
446 | 0 | encoding = RelocationEncoding::SharcTypeA; |
447 | 0 | (RelocationKind::Absolute, 16) |
448 | | } |
449 | | elf::R_SHARC_DATA6_VISA_V3 => { |
450 | 0 | encoding = RelocationEncoding::SharcTypeB; |
451 | 0 | (RelocationKind::Absolute, 6) |
452 | | } |
453 | | elf::R_SHARC_DATA7_VISA_V3 => { |
454 | 0 | encoding = RelocationEncoding::SharcTypeB; |
455 | 0 | (RelocationKind::Absolute, 7) |
456 | | } |
457 | | elf::R_SHARC_DATA16_VISA_V3 => { |
458 | 0 | encoding = RelocationEncoding::SharcTypeB; |
459 | 0 | (RelocationKind::Absolute, 16) |
460 | | } |
461 | | elf::R_SHARC_PCR6_VISA_V3 => { |
462 | 0 | encoding = RelocationEncoding::SharcTypeB; |
463 | 0 | (RelocationKind::Relative, 16) |
464 | | } |
465 | | elf::R_SHARC_ADDR_VAR16_V3 => { |
466 | 0 | encoding = RelocationEncoding::Generic; |
467 | 0 | (RelocationKind::Absolute, 16) |
468 | | } |
469 | 0 | _ => (RelocationKind::Unknown, 0), |
470 | | }, |
471 | 0 | elf::EM_SPARC | elf::EM_SPARC32PLUS | elf::EM_SPARCV9 => match r_type { |
472 | 0 | elf::R_SPARC_32 | elf::R_SPARC_UA32 => (RelocationKind::Absolute, 32), |
473 | 0 | elf::R_SPARC_64 | elf::R_SPARC_UA64 => (RelocationKind::Absolute, 64), |
474 | 0 | _ => (RelocationKind::Unknown, 0), |
475 | | }, |
476 | 0 | elf::EM_XTENSA => match r_type { |
477 | 0 | elf::R_XTENSA_32 => (RelocationKind::Absolute, 32), |
478 | 0 | elf::R_XTENSA_32_PCREL => (RelocationKind::Relative, 32), |
479 | 0 | _ => (RelocationKind::Unknown, 0), |
480 | | }, |
481 | 0 | _ => (RelocationKind::Unknown, 0), |
482 | | }; |
483 | 0 | let target = match reloc.symbol(endian, is_mips64el) { |
484 | 0 | None => RelocationTarget::Absolute, |
485 | 0 | Some(symbol) => RelocationTarget::Symbol(symbol), |
486 | | }; |
487 | 0 | Relocation { |
488 | 0 | kind, |
489 | 0 | encoding, |
490 | 0 | size, |
491 | 0 | target, |
492 | 0 | addend: reloc.r_addend(endian).into(), |
493 | 0 | implicit_addend, |
494 | 0 | flags, |
495 | 0 | } |
496 | 0 | } |
497 | | |
498 | | /// A trait for generic access to [`elf::Rel32`] and [`elf::Rel64`]. |
499 | | #[allow(missing_docs)] |
500 | | pub trait Rel: Debug + Pod + Clone { |
501 | | type Word: Into<u64>; |
502 | | type Sword: Into<i64>; |
503 | | type Endian: endian::Endian; |
504 | | |
505 | | fn r_offset(&self, endian: Self::Endian) -> Self::Word; |
506 | | fn r_info(&self, endian: Self::Endian) -> Self::Word; |
507 | | fn r_sym(&self, endian: Self::Endian) -> u32; |
508 | | fn r_type(&self, endian: Self::Endian) -> u32; |
509 | | |
510 | | /// Get the symbol index referenced by the relocation. |
511 | | /// |
512 | | /// Returns `None` for the null symbol index. |
513 | 0 | fn symbol(&self, endian: Self::Endian) -> Option<SymbolIndex> { |
514 | 0 | let sym = self.r_sym(endian); |
515 | 0 | if sym == 0 { |
516 | 0 | None |
517 | | } else { |
518 | 0 | Some(SymbolIndex(sym as usize)) |
519 | | } |
520 | 0 | } |
521 | | } |
522 | | |
523 | | impl<Endian: endian::Endian> Rel for elf::Rel32<Endian> { |
524 | | type Word = u32; |
525 | | type Sword = i32; |
526 | | type Endian = Endian; |
527 | | |
528 | | #[inline] |
529 | 0 | fn r_offset(&self, endian: Self::Endian) -> Self::Word { |
530 | 0 | self.r_offset.get(endian) |
531 | 0 | } |
532 | | |
533 | | #[inline] |
534 | 0 | fn r_info(&self, endian: Self::Endian) -> Self::Word { |
535 | 0 | self.r_info.get(endian) |
536 | 0 | } |
537 | | |
538 | | #[inline] |
539 | 0 | fn r_sym(&self, endian: Self::Endian) -> u32 { |
540 | 0 | self.r_sym(endian) |
541 | 0 | } |
542 | | |
543 | | #[inline] |
544 | 0 | fn r_type(&self, endian: Self::Endian) -> u32 { |
545 | 0 | self.r_type(endian) |
546 | 0 | } |
547 | | } |
548 | | |
549 | | impl<Endian: endian::Endian> Rel for elf::Rel64<Endian> { |
550 | | type Word = u64; |
551 | | type Sword = i64; |
552 | | type Endian = Endian; |
553 | | |
554 | | #[inline] |
555 | 0 | fn r_offset(&self, endian: Self::Endian) -> Self::Word { |
556 | 0 | self.r_offset.get(endian) |
557 | 0 | } |
558 | | |
559 | | #[inline] |
560 | 0 | fn r_info(&self, endian: Self::Endian) -> Self::Word { |
561 | 0 | self.r_info.get(endian) |
562 | 0 | } |
563 | | |
564 | | #[inline] |
565 | 0 | fn r_sym(&self, endian: Self::Endian) -> u32 { |
566 | 0 | self.r_sym(endian) |
567 | 0 | } |
568 | | |
569 | | #[inline] |
570 | 0 | fn r_type(&self, endian: Self::Endian) -> u32 { |
571 | 0 | self.r_type(endian) |
572 | 0 | } |
573 | | } |
574 | | |
575 | | /// A trait for generic access to [`elf::Rela32`] and [`elf::Rela64`]. |
576 | | #[allow(missing_docs)] |
577 | | pub trait Rela: Debug + Pod + Clone { |
578 | | type Word: Into<u64>; |
579 | | type Sword: Into<i64>; |
580 | | type Endian: endian::Endian; |
581 | | |
582 | | fn r_offset(&self, endian: Self::Endian) -> Self::Word; |
583 | | fn r_info(&self, endian: Self::Endian, is_mips64el: bool) -> Self::Word; |
584 | | fn r_addend(&self, endian: Self::Endian) -> Self::Sword; |
585 | | fn r_sym(&self, endian: Self::Endian, is_mips64el: bool) -> u32; |
586 | | fn r_type(&self, endian: Self::Endian, is_mips64el: bool) -> u32; |
587 | | |
588 | | /// Get the symbol index referenced by the relocation. |
589 | | /// |
590 | | /// Returns `None` for the null symbol index. |
591 | 0 | fn symbol(&self, endian: Self::Endian, is_mips64el: bool) -> Option<SymbolIndex> { |
592 | 0 | let sym = self.r_sym(endian, is_mips64el); |
593 | 0 | if sym == 0 { |
594 | 0 | None |
595 | | } else { |
596 | 0 | Some(SymbolIndex(sym as usize)) |
597 | | } |
598 | 0 | } |
599 | | } |
600 | | |
601 | | impl<Endian: endian::Endian> Rela for elf::Rela32<Endian> { |
602 | | type Word = u32; |
603 | | type Sword = i32; |
604 | | type Endian = Endian; |
605 | | |
606 | | #[inline] |
607 | 0 | fn r_offset(&self, endian: Self::Endian) -> Self::Word { |
608 | 0 | self.r_offset.get(endian) |
609 | 0 | } |
610 | | |
611 | | #[inline] |
612 | 0 | fn r_info(&self, endian: Self::Endian, _is_mips64el: bool) -> Self::Word { |
613 | 0 | self.r_info.get(endian) |
614 | 0 | } |
615 | | |
616 | | #[inline] |
617 | 0 | fn r_addend(&self, endian: Self::Endian) -> Self::Sword { |
618 | 0 | self.r_addend.get(endian) |
619 | 0 | } |
620 | | |
621 | | #[inline] |
622 | 0 | fn r_sym(&self, endian: Self::Endian, _is_mips64el: bool) -> u32 { |
623 | 0 | self.r_sym(endian) |
624 | 0 | } |
625 | | |
626 | | #[inline] |
627 | 0 | fn r_type(&self, endian: Self::Endian, _is_mips64el: bool) -> u32 { |
628 | 0 | self.r_type(endian) |
629 | 0 | } |
630 | | } |
631 | | |
632 | | impl<Endian: endian::Endian> Rela for elf::Rela64<Endian> { |
633 | | type Word = u64; |
634 | | type Sword = i64; |
635 | | type Endian = Endian; |
636 | | |
637 | | #[inline] |
638 | 0 | fn r_offset(&self, endian: Self::Endian) -> Self::Word { |
639 | 0 | self.r_offset.get(endian) |
640 | 0 | } |
641 | | |
642 | | #[inline] |
643 | 0 | fn r_info(&self, endian: Self::Endian, is_mips64el: bool) -> Self::Word { |
644 | 0 | self.get_r_info(endian, is_mips64el) |
645 | 0 | } |
646 | | |
647 | | #[inline] |
648 | 0 | fn r_addend(&self, endian: Self::Endian) -> Self::Sword { |
649 | 0 | self.r_addend.get(endian) |
650 | 0 | } |
651 | | |
652 | | #[inline] |
653 | 0 | fn r_sym(&self, endian: Self::Endian, is_mips64el: bool) -> u32 { |
654 | 0 | self.r_sym(endian, is_mips64el) |
655 | 0 | } |
656 | | |
657 | | #[inline] |
658 | 0 | fn r_type(&self, endian: Self::Endian, is_mips64el: bool) -> u32 { |
659 | 0 | self.r_type(endian, is_mips64el) |
660 | 0 | } |
661 | | } |