Skip to content

Commit 6dea0d5

Browse files
committed
write/object: adjust addend using relocation flags
Previously we adjusted the addend based on the relocation kind. For cases where the flags are derived from the relocation kind, this should not change the behaviour. For cases where the user supplies the flags, this ensures the adjustment is consistent with the flags that are actually used (since previously the kind and flags did not need to agree). This is preparation for removing the relocation kind field when the user supplies the flags.
1 parent d84dbcf commit 6dea0d5

File tree

5 files changed

+92
-73
lines changed

5 files changed

+92
-73
lines changed

src/write/coff/object.rs

Lines changed: 40 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -166,31 +166,50 @@ impl<'a> Object<'a> {
166166
Ok(RelocationFlags::Coff { typ })
167167
}
168168

169-
pub(crate) fn coff_adjust_addend(&self, relocation: &mut Relocation) -> bool {
170-
let addend = match self.architecture {
171-
Architecture::I386 | Architecture::Arm | Architecture::Aarch64 => match relocation.kind
172-
{
173-
RelocationKind::Relative => {
174-
// IMAGE_REL_I386_REL32, IMAGE_REL_ARM_REL32, IMAGE_REL_ARM64_REL32
175-
relocation.addend + 4
169+
pub(crate) fn coff_adjust_addend(
170+
&self,
171+
relocation: &mut crate::write::RawRelocation,
172+
) -> Result<bool> {
173+
let typ = if let RelocationFlags::Coff { typ } = relocation.flags {
174+
typ
175+
} else {
176+
return Err(Error(format!("invalid relocation flags {:?}", relocation)));
177+
};
178+
let offset = match self.architecture {
179+
Architecture::Arm => {
180+
if typ == coff::IMAGE_REL_ARM_REL32 {
181+
4
182+
} else {
183+
0
176184
}
177-
_ => relocation.addend,
178-
},
179-
Architecture::X86_64 => match relocation.kind {
180-
RelocationKind::Relative => {
181-
// IMAGE_REL_AMD64_REL32 through to IMAGE_REL_AMD64_REL32_5
182-
if relocation.addend <= -4 && relocation.addend >= -9 {
183-
0
184-
} else {
185-
relocation.addend + 4
186-
}
185+
}
186+
Architecture::Aarch64 => {
187+
if typ == coff::IMAGE_REL_ARM64_REL32 {
188+
4
189+
} else {
190+
0
191+
}
192+
}
193+
Architecture::I386 => {
194+
if typ == coff::IMAGE_REL_I386_REL32 {
195+
4
196+
} else {
197+
0
187198
}
188-
_ => relocation.addend,
199+
}
200+
Architecture::X86_64 => match typ {
201+
coff::IMAGE_REL_AMD64_REL32 => 4,
202+
coff::IMAGE_REL_AMD64_REL32_1 => 5,
203+
coff::IMAGE_REL_AMD64_REL32_2 => 6,
204+
coff::IMAGE_REL_AMD64_REL32_3 => 7,
205+
coff::IMAGE_REL_AMD64_REL32_4 => 8,
206+
coff::IMAGE_REL_AMD64_REL32_5 => 9,
207+
_ => 0,
189208
},
190-
_ => unimplemented!(),
209+
_ => return Err(Error(format!("unimplemented relocation {:?}", relocation))),
191210
};
192-
relocation.addend = addend;
193-
true
211+
relocation.addend += offset;
212+
Ok(true)
194213
}
195214

196215
pub(crate) fn coff_relocation_size(&self, reloc: &crate::write::RawRelocation) -> Result<u8> {

src/write/elf/object.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -459,7 +459,10 @@ impl<'a> Object<'a> {
459459
Ok(RelocationFlags::Elf { r_type })
460460
}
461461

462-
pub(crate) fn elf_adjust_addend(&mut self, _relocation: &mut Relocation) -> Result<bool> {
462+
pub(crate) fn elf_adjust_addend(
463+
&mut self,
464+
_relocation: &mut crate::write::RawRelocation,
465+
) -> Result<bool> {
463466
// Determine whether the addend is stored in the relocation or the data.
464467
let implicit = !self.elf_has_relocation_addend()?;
465468
Ok(implicit)

src/write/macho.rs

Lines changed: 27 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -331,58 +331,49 @@ impl<'a> Object<'a> {
331331
})
332332
}
333333

334-
pub(crate) fn macho_adjust_addend(&mut self, relocation: &mut Relocation) -> bool {
335-
let relative = match relocation.kind {
336-
RelocationKind::Relative
337-
| RelocationKind::GotRelative
338-
| RelocationKind::PltRelative
339-
| RelocationKind::MachO { relative: true, .. } => true,
340-
_ => false,
334+
pub(crate) fn macho_adjust_addend(
335+
&mut self,
336+
relocation: &mut crate::write::RawRelocation,
337+
) -> Result<bool> {
338+
let (r_type, r_pcrel) = if let RelocationFlags::MachO {
339+
r_type, r_pcrel, ..
340+
} = relocation.flags
341+
{
342+
(r_type, r_pcrel)
343+
} else {
344+
return Err(Error(format!("invalid relocation flags {:?}", relocation)));
341345
};
342-
if relative {
346+
if r_pcrel {
343347
// For PC relative relocations on some architectures, the
344348
// addend does not include the offset required due to the
345349
// PC being different from the place of the relocation.
346350
// This differs from other file formats, so adjust the
347351
// addend here to account for this.
348352
let pcrel_offset = match self.architecture {
349353
Architecture::I386 => 4,
350-
Architecture::X86_64 => match relocation.kind {
351-
RelocationKind::MachO {
352-
value: macho::X86_64_RELOC_SIGNED_1,
353-
..
354-
} => 5,
355-
RelocationKind::MachO {
356-
value: macho::X86_64_RELOC_SIGNED_2,
357-
..
358-
} => 6,
359-
RelocationKind::MachO {
360-
value: macho::X86_64_RELOC_SIGNED_4,
361-
..
362-
} => 8,
354+
Architecture::X86_64 => match r_type {
355+
macho::X86_64_RELOC_SIGNED_1 => 5,
356+
macho::X86_64_RELOC_SIGNED_2 => 6,
357+
macho::X86_64_RELOC_SIGNED_4 => 8,
363358
_ => 4,
364359
},
365360
// TODO: maybe missing support for some architectures and relocations
366361
_ => 0,
367362
};
368363
relocation.addend += pcrel_offset;
369364
}
370-
// Check for relocations that use an explicit addend.
371-
if self.architecture == Architecture::Aarch64 {
372-
if relocation.encoding == RelocationEncoding::AArch64Call {
373-
return false;
374-
}
375-
if let RelocationKind::MachO { value, .. } = relocation.kind {
376-
match value {
377-
macho::ARM64_RELOC_BRANCH26
378-
| macho::ARM64_RELOC_PAGE21
379-
| macho::ARM64_RELOC_PAGEOFF12 => return false,
380-
_ => {}
381-
}
365+
// Determine if addend is implicit.
366+
let implicit = if self.architecture == Architecture::Aarch64 {
367+
match r_type {
368+
macho::ARM64_RELOC_BRANCH26
369+
| macho::ARM64_RELOC_PAGE21
370+
| macho::ARM64_RELOC_PAGEOFF12 => false,
371+
_ => true,
382372
}
383-
}
384-
// Signify implicit addend.
385-
true
373+
} else {
374+
true
375+
};
376+
Ok(implicit)
386377
}
387378

388379
pub(crate) fn macho_relocation_size(&self, reloc: &crate::write::RawRelocation) -> Result<u8> {

src/write/mod.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -555,23 +555,23 @@ impl<'a> Object<'a> {
555555
BinaryFormat::Xcoff => self.xcoff_relocation_flags(&relocation)?,
556556
_ => unimplemented!(),
557557
};
558+
let mut relocation = RawRelocation {
559+
offset: relocation.offset,
560+
symbol: relocation.symbol,
561+
addend: relocation.addend,
562+
flags,
563+
};
558564
let implicit = match self.format {
559565
#[cfg(feature = "coff")]
560-
BinaryFormat::Coff => self.coff_adjust_addend(&mut relocation),
566+
BinaryFormat::Coff => self.coff_adjust_addend(&mut relocation)?,
561567
#[cfg(feature = "elf")]
562568
BinaryFormat::Elf => self.elf_adjust_addend(&mut relocation)?,
563569
#[cfg(feature = "macho")]
564-
BinaryFormat::MachO => self.macho_adjust_addend(&mut relocation),
570+
BinaryFormat::MachO => self.macho_adjust_addend(&mut relocation)?,
565571
#[cfg(feature = "xcoff")]
566-
BinaryFormat::Xcoff => self.xcoff_adjust_addend(&mut relocation),
572+
BinaryFormat::Xcoff => self.xcoff_adjust_addend(&mut relocation)?,
567573
_ => unimplemented!(),
568574
};
569-
let mut relocation = RawRelocation {
570-
offset: relocation.offset,
571-
symbol: relocation.symbol,
572-
addend: relocation.addend,
573-
flags,
574-
};
575575
if implicit && relocation.addend != 0 {
576576
self.write_relocation_addend(section, &relocation)?;
577577
relocation.addend = 0;

src/write/xcoff.rs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -82,13 +82,19 @@ impl<'a> Object<'a> {
8282
Ok(RelocationFlags::Xcoff { r_rtype, r_rsize })
8383
}
8484

85-
pub(crate) fn xcoff_adjust_addend(&mut self, relocation: &mut Relocation) -> bool {
86-
let addend = match relocation.kind {
87-
RelocationKind::Relative => relocation.addend + 4,
88-
_ => relocation.addend,
85+
pub(crate) fn xcoff_adjust_addend(
86+
&mut self,
87+
relocation: &mut crate::write::RawRelocation,
88+
) -> Result<bool> {
89+
let r_rtype = if let RelocationFlags::Xcoff { r_rtype, .. } = relocation.flags {
90+
r_rtype
91+
} else {
92+
return Err(Error(format!("invalid relocation flags {:?}", relocation)));
8993
};
90-
relocation.addend = addend;
91-
true
94+
if r_rtype == xcoff::R_REL {
95+
relocation.addend += 4;
96+
}
97+
Ok(true)
9298
}
9399

94100
pub(crate) fn xcoff_relocation_size(&self, reloc: &crate::write::RawRelocation) -> Result<u8> {

0 commit comments

Comments
 (0)