Coverage Report

Created: 2024-10-16 07:58

/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
}