Skip to content

Commit

Permalink
Reformat relocation parsing
Browse files Browse the repository at this point in the history
This matches changes previously done for ELF.
  • Loading branch information
philipc committed Oct 4, 2024
1 parent 2cc795e commit 12ceed6
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 152 deletions.
86 changes: 43 additions & 43 deletions src/read/coff/relocation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,67 +31,67 @@ impl<'data, 'file, R: ReadRef<'data>, Coff: CoffHeader> Iterator
type Item = (u64, Relocation);

fn next(&mut self) -> Option<Self::Item> {
use RelocationEncoding as E;
use RelocationKind as K;

self.iter.next().map(|relocation| {
let typ = relocation.typ.get(LE);
let flags = RelocationFlags::Coff { typ };
let g = E::Generic;
let unknown = (K::Unknown, E::Generic, 0, 0);
let (kind, encoding, size, addend) = match self.file.header.machine() {
pe::IMAGE_FILE_MACHINE_ARMNT => match typ {
pe::IMAGE_REL_ARM_ADDR32 => (RelocationKind::Absolute, None, 32, 0),
pe::IMAGE_REL_ARM_ADDR32NB => (RelocationKind::ImageOffset, None, 32, 0),
pe::IMAGE_REL_ARM_REL32 => (RelocationKind::Relative, None, 32, -4),
pe::IMAGE_REL_ARM_SECTION => (RelocationKind::SectionIndex, None, 16, 0),
pe::IMAGE_REL_ARM_SECREL => (RelocationKind::SectionOffset, None, 32, 0),
_ => (RelocationKind::Unknown, None, 0, 0),
pe::IMAGE_REL_ARM_ADDR32 => (K::Absolute, g, 32, 0),
pe::IMAGE_REL_ARM_ADDR32NB => (K::ImageOffset, g, 32, 0),
pe::IMAGE_REL_ARM_REL32 => (K::Relative, g, 32, -4),
pe::IMAGE_REL_ARM_SECTION => (K::SectionIndex, g, 16, 0),
pe::IMAGE_REL_ARM_SECREL => (K::SectionOffset, g, 32, 0),
_ => unknown,
},
pe::IMAGE_FILE_MACHINE_ARM64 | pe::IMAGE_FILE_MACHINE_ARM64EC => match typ {
pe::IMAGE_REL_ARM64_ADDR32 => (RelocationKind::Absolute, None, 32, 0),
pe::IMAGE_REL_ARM64_ADDR32NB => (RelocationKind::ImageOffset, None, 32, 0),
pe::IMAGE_REL_ARM64_SECREL => (RelocationKind::SectionOffset, None, 32, 0),
pe::IMAGE_REL_ARM64_SECTION => (RelocationKind::SectionIndex, None, 16, 0),
pe::IMAGE_REL_ARM64_ADDR64 => (RelocationKind::Absolute, None, 64, 0),
pe::IMAGE_REL_ARM64_REL32 => (RelocationKind::Relative, None, 32, -4),
pe::IMAGE_REL_ARM64_BRANCH26 => (
RelocationKind::Relative,
Some(RelocationEncoding::AArch64Call),
26,
0,
),
_ => (RelocationKind::Unknown, None, 0, 0),
pe::IMAGE_REL_ARM64_ADDR32 => (K::Absolute, g, 32, 0),
pe::IMAGE_REL_ARM64_ADDR32NB => (K::ImageOffset, g, 32, 0),
pe::IMAGE_REL_ARM64_SECREL => (K::SectionOffset, g, 32, 0),
pe::IMAGE_REL_ARM64_SECTION => (K::SectionIndex, g, 16, 0),
pe::IMAGE_REL_ARM64_ADDR64 => (K::Absolute, g, 64, 0),
pe::IMAGE_REL_ARM64_REL32 => (K::Relative, g, 32, -4),
pe::IMAGE_REL_ARM64_BRANCH26 => (K::Relative, E::AArch64Call, 26, 0),
_ => unknown,
},
pe::IMAGE_FILE_MACHINE_I386 => match typ {
pe::IMAGE_REL_I386_DIR16 => (RelocationKind::Absolute, None, 16, 0),
pe::IMAGE_REL_I386_REL16 => (RelocationKind::Relative, None, 16, 0),
pe::IMAGE_REL_I386_DIR32 => (RelocationKind::Absolute, None, 32, 0),
pe::IMAGE_REL_I386_DIR32NB => (RelocationKind::ImageOffset, None, 32, 0),
pe::IMAGE_REL_I386_SECTION => (RelocationKind::SectionIndex, None, 16, 0),
pe::IMAGE_REL_I386_SECREL => (RelocationKind::SectionOffset, None, 32, 0),
pe::IMAGE_REL_I386_SECREL7 => (RelocationKind::SectionOffset, None, 7, 0),
pe::IMAGE_REL_I386_REL32 => (RelocationKind::Relative, None, 32, -4),
_ => (RelocationKind::Unknown, None, 0, 0),
pe::IMAGE_REL_I386_DIR16 => (K::Absolute, g, 16, 0),
pe::IMAGE_REL_I386_REL16 => (K::Relative, g, 16, 0),
pe::IMAGE_REL_I386_DIR32 => (K::Absolute, g, 32, 0),
pe::IMAGE_REL_I386_DIR32NB => (K::ImageOffset, g, 32, 0),
pe::IMAGE_REL_I386_SECTION => (K::SectionIndex, g, 16, 0),
pe::IMAGE_REL_I386_SECREL => (K::SectionOffset, g, 32, 0),
pe::IMAGE_REL_I386_SECREL7 => (K::SectionOffset, g, 7, 0),
pe::IMAGE_REL_I386_REL32 => (K::Relative, g, 32, -4),
_ => unknown,
},
pe::IMAGE_FILE_MACHINE_AMD64 => match typ {
pe::IMAGE_REL_AMD64_ADDR64 => (RelocationKind::Absolute, None, 64, 0),
pe::IMAGE_REL_AMD64_ADDR32 => (RelocationKind::Absolute, None, 32, 0),
pe::IMAGE_REL_AMD64_ADDR32NB => (RelocationKind::ImageOffset, None, 32, 0),
pe::IMAGE_REL_AMD64_REL32 => (RelocationKind::Relative, None, 32, -4),
pe::IMAGE_REL_AMD64_REL32_1 => (RelocationKind::Relative, None, 32, -5),
pe::IMAGE_REL_AMD64_REL32_2 => (RelocationKind::Relative, None, 32, -6),
pe::IMAGE_REL_AMD64_REL32_3 => (RelocationKind::Relative, None, 32, -7),
pe::IMAGE_REL_AMD64_REL32_4 => (RelocationKind::Relative, None, 32, -8),
pe::IMAGE_REL_AMD64_REL32_5 => (RelocationKind::Relative, None, 32, -9),
pe::IMAGE_REL_AMD64_SECTION => (RelocationKind::SectionIndex, None, 16, 0),
pe::IMAGE_REL_AMD64_SECREL => (RelocationKind::SectionOffset, None, 32, 0),
pe::IMAGE_REL_AMD64_SECREL7 => (RelocationKind::SectionOffset, None, 7, 0),
_ => (RelocationKind::Unknown, None, 0, 0),
pe::IMAGE_REL_AMD64_ADDR64 => (K::Absolute, g, 64, 0),
pe::IMAGE_REL_AMD64_ADDR32 => (K::Absolute, g, 32, 0),
pe::IMAGE_REL_AMD64_ADDR32NB => (K::ImageOffset, g, 32, 0),
pe::IMAGE_REL_AMD64_REL32 => (K::Relative, g, 32, -4),
pe::IMAGE_REL_AMD64_REL32_1 => (K::Relative, g, 32, -5),
pe::IMAGE_REL_AMD64_REL32_2 => (K::Relative, g, 32, -6),
pe::IMAGE_REL_AMD64_REL32_3 => (K::Relative, g, 32, -7),
pe::IMAGE_REL_AMD64_REL32_4 => (K::Relative, g, 32, -8),
pe::IMAGE_REL_AMD64_REL32_5 => (K::Relative, g, 32, -9),
pe::IMAGE_REL_AMD64_SECTION => (K::SectionIndex, g, 16, 0),
pe::IMAGE_REL_AMD64_SECREL => (K::SectionOffset, g, 32, 0),
pe::IMAGE_REL_AMD64_SECREL7 => (K::SectionOffset, g, 7, 0),
_ => unknown,
},
_ => (RelocationKind::Unknown, None, 0, 0),
_ => unknown,
};
let target = RelocationTarget::Symbol(relocation.symbol());
(
u64::from(relocation.virtual_address.get(LE)),
Relocation {
kind,
encoding: encoding.unwrap_or(RelocationEncoding::Generic),
encoding,
size,
target,
addend,
Expand Down
43 changes: 19 additions & 24 deletions src/read/macho/relocation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ where
type Item = (u64, Relocation);

fn next(&mut self) -> Option<Self::Item> {
use RelocationEncoding as E;
use RelocationKind as K;

let mut paired_addend = 0;
loop {
let reloc = self.relocations.next()?;
Expand All @@ -50,46 +53,38 @@ where
r_pcrel: reloc.r_pcrel,
r_length: reloc.r_length,
};
let mut encoding = RelocationEncoding::Generic;
let kind = match cputype {
let g = E::Generic;
let unknown = (K::Unknown, E::Generic);
let (kind, encoding) = match cputype {
macho::CPU_TYPE_ARM => match (reloc.r_type, reloc.r_pcrel) {
(macho::ARM_RELOC_VANILLA, false) => RelocationKind::Absolute,
_ => RelocationKind::Unknown,
(macho::ARM_RELOC_VANILLA, false) => (K::Absolute, g),
_ => 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_UNSIGNED, false) => (K::Absolute, g),
(macho::ARM64_RELOC_ADDEND, _) => {
paired_addend = i64::from(reloc.r_symbolnum)
.wrapping_shl(64 - 24)
.wrapping_shr(64 - 24);
continue;
}
_ => RelocationKind::Unknown,
_ => unknown,
}
}
macho::CPU_TYPE_X86 => match (reloc.r_type, reloc.r_pcrel) {
(macho::GENERIC_RELOC_VANILLA, false) => RelocationKind::Absolute,
_ => RelocationKind::Unknown,
(macho::GENERIC_RELOC_VANILLA, false) => (K::Absolute, g),
_ => 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,
(macho::X86_64_RELOC_UNSIGNED, false) => (K::Absolute, g),
(macho::X86_64_RELOC_SIGNED, true) => (K::Relative, E::X86RipRelative),
(macho::X86_64_RELOC_BRANCH, true) => (K::Relative, E::X86Branch),
(macho::X86_64_RELOC_GOT, true) => (K::GotRelative, g),
(macho::X86_64_RELOC_GOT_LOAD, true) => (K::GotRelative, E::X86RipRelativeMovq),
_ => unknown,
},
_ => RelocationKind::Unknown,
_ => unknown,
};
let size = 8 << reloc.r_length;
let target = if reloc.r_extern {
Expand Down
84 changes: 39 additions & 45 deletions src/write/coff/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ impl<'a> Object<'a> {
}

pub(crate) fn coff_translate_relocation(&mut self, reloc: &mut Relocation) -> Result<()> {
use RelocationEncoding as E;
use RelocationKind as K;

let (mut kind, encoding, size) = if let RelocationFlags::Generic {
kind,
encoding,
Expand All @@ -92,75 +95,66 @@ impl<'a> Object<'a> {
} else {
return Ok(());
};
if kind == RelocationKind::GotRelative {
if kind == K::GotRelative {
// Use a stub symbol for the relocation instead.
// This isn't really a GOT, but it's a similar purpose.
// TODO: need to handle DLL imports differently?
kind = RelocationKind::Relative;
kind = K::Relative;
reloc.symbol = self.coff_add_stub_symbol(reloc.symbol)?;
} else if kind == RelocationKind::PltRelative {
} else if kind == K::PltRelative {
// Windows doesn't need a separate relocation type for
// references to functions in import libraries.
// For convenience, treat this the same as Relative.
kind = RelocationKind::Relative;
kind = K::Relative;
}

let unsupported_reloc = || Err(Error(format!("unimplemented relocation {:?}", reloc)));
let typ = match self.architecture {
Architecture::I386 => match (kind, size) {
(RelocationKind::Absolute, 16) => coff::IMAGE_REL_I386_DIR16,
(RelocationKind::Relative, 16) => coff::IMAGE_REL_I386_REL16,
(RelocationKind::Absolute, 32) => coff::IMAGE_REL_I386_DIR32,
(RelocationKind::ImageOffset, 32) => coff::IMAGE_REL_I386_DIR32NB,
(RelocationKind::SectionIndex, 16) => coff::IMAGE_REL_I386_SECTION,
(RelocationKind::SectionOffset, 32) => coff::IMAGE_REL_I386_SECREL,
(RelocationKind::SectionOffset, 7) => coff::IMAGE_REL_I386_SECREL7,
(RelocationKind::Relative, 32) => coff::IMAGE_REL_I386_REL32,
_ => {
return Err(Error(format!("unimplemented relocation {:?}", reloc)));
}
(K::Absolute, 16) => coff::IMAGE_REL_I386_DIR16,
(K::Relative, 16) => coff::IMAGE_REL_I386_REL16,
(K::Absolute, 32) => coff::IMAGE_REL_I386_DIR32,
(K::ImageOffset, 32) => coff::IMAGE_REL_I386_DIR32NB,
(K::SectionIndex, 16) => coff::IMAGE_REL_I386_SECTION,
(K::SectionOffset, 32) => coff::IMAGE_REL_I386_SECREL,
(K::SectionOffset, 7) => coff::IMAGE_REL_I386_SECREL7,
(K::Relative, 32) => coff::IMAGE_REL_I386_REL32,
_ => return unsupported_reloc(),
},
Architecture::X86_64 => match (kind, size) {
(RelocationKind::Absolute, 64) => coff::IMAGE_REL_AMD64_ADDR64,
(RelocationKind::Absolute, 32) => coff::IMAGE_REL_AMD64_ADDR32,
(RelocationKind::ImageOffset, 32) => coff::IMAGE_REL_AMD64_ADDR32NB,
(RelocationKind::Relative, 32) => match reloc.addend {
(K::Absolute, 64) => coff::IMAGE_REL_AMD64_ADDR64,
(K::Absolute, 32) => coff::IMAGE_REL_AMD64_ADDR32,
(K::ImageOffset, 32) => coff::IMAGE_REL_AMD64_ADDR32NB,
(K::Relative, 32) => match reloc.addend {
-5 => coff::IMAGE_REL_AMD64_REL32_1,
-6 => coff::IMAGE_REL_AMD64_REL32_2,
-7 => coff::IMAGE_REL_AMD64_REL32_3,
-8 => coff::IMAGE_REL_AMD64_REL32_4,
-9 => coff::IMAGE_REL_AMD64_REL32_5,
_ => coff::IMAGE_REL_AMD64_REL32,
},
(RelocationKind::SectionIndex, 16) => coff::IMAGE_REL_AMD64_SECTION,
(RelocationKind::SectionOffset, 32) => coff::IMAGE_REL_AMD64_SECREL,
(RelocationKind::SectionOffset, 7) => coff::IMAGE_REL_AMD64_SECREL7,
_ => {
return Err(Error(format!("unimplemented relocation {:?}", reloc)));
}
(K::SectionIndex, 16) => coff::IMAGE_REL_AMD64_SECTION,
(K::SectionOffset, 32) => coff::IMAGE_REL_AMD64_SECREL,
(K::SectionOffset, 7) => coff::IMAGE_REL_AMD64_SECREL7,
_ => return unsupported_reloc(),
},
Architecture::Arm => match (kind, size) {
(RelocationKind::Absolute, 32) => coff::IMAGE_REL_ARM_ADDR32,
(RelocationKind::ImageOffset, 32) => coff::IMAGE_REL_ARM_ADDR32NB,
(RelocationKind::Relative, 32) => coff::IMAGE_REL_ARM_REL32,
(RelocationKind::SectionIndex, 16) => coff::IMAGE_REL_ARM_SECTION,
(RelocationKind::SectionOffset, 32) => coff::IMAGE_REL_ARM_SECREL,
_ => {
return Err(Error(format!("unimplemented relocation {:?}", reloc)));
}
(K::Absolute, 32) => coff::IMAGE_REL_ARM_ADDR32,
(K::ImageOffset, 32) => coff::IMAGE_REL_ARM_ADDR32NB,
(K::Relative, 32) => coff::IMAGE_REL_ARM_REL32,
(K::SectionIndex, 16) => coff::IMAGE_REL_ARM_SECTION,
(K::SectionOffset, 32) => coff::IMAGE_REL_ARM_SECREL,
_ => return unsupported_reloc(),
},
Architecture::Aarch64 => match (kind, encoding, size) {
(RelocationKind::Absolute, _, 32) => coff::IMAGE_REL_ARM64_ADDR32,
(RelocationKind::ImageOffset, _, 32) => coff::IMAGE_REL_ARM64_ADDR32NB,
(RelocationKind::SectionIndex, _, 16) => coff::IMAGE_REL_ARM64_SECTION,
(RelocationKind::SectionOffset, _, 32) => coff::IMAGE_REL_ARM64_SECREL,
(RelocationKind::Absolute, _, 64) => coff::IMAGE_REL_ARM64_ADDR64,
(RelocationKind::Relative, _, 32) => coff::IMAGE_REL_ARM64_REL32,
(RelocationKind::Relative, RelocationEncoding::AArch64Call, 26) => {
coff::IMAGE_REL_ARM64_BRANCH26
}
_ => {
return Err(Error(format!("unimplemented relocation {:?}", reloc)));
}
(K::Absolute, _, 32) => coff::IMAGE_REL_ARM64_ADDR32,
(K::ImageOffset, _, 32) => coff::IMAGE_REL_ARM64_ADDR32NB,
(K::SectionIndex, _, 16) => coff::IMAGE_REL_ARM64_SECTION,
(K::SectionOffset, _, 32) => coff::IMAGE_REL_ARM64_SECREL,
(K::Absolute, _, 64) => coff::IMAGE_REL_ARM64_ADDR64,
(K::Relative, _, 32) => coff::IMAGE_REL_ARM64_REL32,
(K::Relative, E::AArch64Call, 26) => coff::IMAGE_REL_ARM64_BRANCH26,
_ => return unsupported_reloc(),
},
_ => {
return Err(Error(format!(
Expand Down
9 changes: 7 additions & 2 deletions src/write/elf/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ impl<'a> Object<'a> {
return Ok(());
};

let unsupported_reloc = || Err(Error(format!("unimplemented relocation {:?}", reloc)));
let unsupported_reloc = || Err(Error(format!("unimplemented ELF relocation {:?}", reloc)));
let r_type = match self.architecture {
Architecture::Aarch64 => match (kind, encoding, size) {
(K::Absolute, E::Generic, 64) => elf::R_AARCH64_ABS64,
Expand Down Expand Up @@ -345,7 +345,12 @@ impl<'a> Object<'a> {
(K::Relative, E::Generic, 32) => elf::R_XTENSA_32_PCREL,
_ => return unsupported_reloc(),
},
_ => return unsupported_reloc(),
_ => {
return Err(Error(format!(
"unimplemented architecture {:?}",
self.architecture
)));
}
};
reloc.flags = RelocationFlags::Elf { r_type };
Ok(())
Expand Down
Loading

0 comments on commit 12ceed6

Please sign in to comment.