Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  relocation.rs   Sprache: unbekannt

 
use core::{fmt, slice};

use crate::endian::Endianness;
use crate::macho;
use crate::read::{
    ReadRef, Relocation, RelocationEncoding, RelocationFlags, RelocationKind, RelocationTarget,
    SectionIndex, SymbolIndex,
};

use super::{MachHeader, MachOFile};

/// An iterator for the relocations in a [`MachOSection32`](super::MachOSection32).
pub type MachORelocationIterator32<'data, 'file, Endian = Endianness, R = &'data [u8]> =
    MachORelocationIterator<'data, 'file, macho::MachHeader32<Endian>, R>;
/// An iterator for the relocations in a [`MachOSection64`](super::MachOSection64).
pub type MachORelocationIterator64<'data, 'file, Endian = Endianness, R = &'data [u8]> =
    MachORelocationIterator<'data, 'file, macho::MachHeader64<Endian>, R>;

/// An iterator for the relocations in a [`MachOSection`](super::MachOSection).
pub struct MachORelocationIterator<'data, 'file, Mach, R = &'data [u8]>
where
    Mach: MachHeader,
    R: ReadRef<'data>,
{
    pub(super) file: &'file MachOFile<'data, Mach, R>,
    pub(super) relocations: slice::Iter<'data, macho::Relocation<Mach::Endian>>,
}

impl<'data, 'file, Mach, R> Iterator for MachORelocationIterator<'data, 'file, Mach, R>
where
    Mach: MachHeader,
    R: ReadRef<'data>,
{
    type Item = (u64, Relocation);

    fn next(&mut self) -> Option<Self::Item> {
        let mut paired_addend = 0;
        loop {
            let reloc = self.relocations.next()?;
            let endian = self.file.endian;
            let cputype = self.file.header.cputype(endian);
            if reloc.r_scattered(endian, cputype) {
                // FIXME: handle scattered relocations
                // We need to add `RelocationTarget::Address` for this.
                continue;
            }
            let reloc = reloc.info(self.file.endian);
            let flags = RelocationFlags::MachO {
                r_type: reloc.r_type,
                r_pcrel: reloc.r_pcrel,
                r_length: reloc.r_length,
            };
            let mut encoding = RelocationEncoding::Generic;
            let kind = match cputype {
                macho::CPU_TYPE_ARM => match (reloc.r_type, reloc.r_pcrel) {
                    (macho::ARM_RELOC_VANILLA, false) => RelocationKind::Absolute,
                    _ => RelocationKind::Unknown,
                },
                macho::CPU_TYPE_ARM64 | macho::CPU_TYPE_ARM64_32 => {
                    match (reloc.r_type, reloc.r_pcrel) {
                        (macho::ARM64_RELOC_UNSIGNED, false) => RelocationKind::Absolute,
                        (macho::ARM64_RELOC_ADDEND, _) => {
                            paired_addend = i64::from(reloc.r_symbolnum)
                                .wrapping_shl(64 - 24)
                                .wrapping_shr(64 - 24);
                            continue;
                        }
                        _ => RelocationKind::Unknown,
                    }
                }
                macho::CPU_TYPE_X86 => match (reloc.r_type, reloc.r_pcrel) {
                    (macho::GENERIC_RELOC_VANILLA, false) => RelocationKind::Absolute,
                    _ => RelocationKind::Unknown,
                },
                macho::CPU_TYPE_X86_64 => match (reloc.r_type, reloc.r_pcrel) {
                    (macho::X86_64_RELOC_UNSIGNED, false) => RelocationKind::Absolute,
                    (macho::X86_64_RELOC_SIGNED, true) => {
                        encoding = RelocationEncoding::X86RipRelative;
                        RelocationKind::Relative
                    }
                    (macho::X86_64_RELOC_BRANCH, true) => {
                        encoding = RelocationEncoding::X86Branch;
                        RelocationKind::Relative
                    }
                    (macho::X86_64_RELOC_GOT, true) => RelocationKind::GotRelative,
                    (macho::X86_64_RELOC_GOT_LOAD, true) => {
                        encoding = RelocationEncoding::X86RipRelativeMovq;
                        RelocationKind::GotRelative
                    }
                    _ => RelocationKind::Unknown,
                },
                _ => RelocationKind::Unknown,
            };
            let size = 8 << reloc.r_length;
            let target = if reloc.r_extern {
                RelocationTarget::Symbol(SymbolIndex(reloc.r_symbolnum as usize))
            } else {
                RelocationTarget::Section(SectionIndex(reloc.r_symbolnum as usize))
            };
            let implicit_addend = paired_addend == 0;
            let mut addend = paired_addend;
            if reloc.r_pcrel {
                // For PC relative relocations on some architectures, the
                // addend does not include the offset required due to the
                // PC being different from the place of the relocation.
                // This differs from other file formats, so adjust the
                // addend here to account for this.
                match cputype {
                    macho::CPU_TYPE_X86 => {
                        addend -= 1 << reloc.r_length;
                    }
                    macho::CPU_TYPE_X86_64 => {
                        addend -= 1 << reloc.r_length;
                        match reloc.r_type {
                            macho::X86_64_RELOC_SIGNED_1 => addend -= 1,
                            macho::X86_64_RELOC_SIGNED_2 => addend -= 2,
                            macho::X86_64_RELOC_SIGNED_4 => addend -= 4,
                            _ => {}
                        }
                    }
                    // TODO: maybe missing support for some architectures and relocations
                    _ => {}
                }
            }
            return Some((
                reloc.r_address as u64,
                Relocation {
                    kind,
                    encoding,
                    size,
                    target,
                    addend,
                    implicit_addend,
                    flags,
                },
            ));
        }
    }
}

impl<'data, 'file, Mach, R> fmt::Debug for MachORelocationIterator<'data, 'file, Mach, R>
where
    Mach: MachHeader,
    R: ReadRef<'data>,
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("MachORelocationIterator").finish()
    }
}

[ Dauer der Verarbeitung: 0.24 Sekunden  (vorverarbeitet)  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge