| 213 | } |
| 214 | |
| 215 | fn relocation_override( |
| 216 | &self, |
| 217 | file: &object::File<'_>, |
| 218 | section: &object::Section, |
| 219 | address: u64, |
| 220 | relocation: &object::Relocation, |
| 221 | ) -> Result<Option<RelocationOverride>> { |
| 222 | match relocation.flags() { |
| 223 | // IMAGE_REL_PPC_PAIR contains the REF{HI,LO} displacement instead of a symbol index |
| 224 | object::RelocationFlags::Coff { |
| 225 | typ: pe::IMAGE_REL_PPC_REFHI | pe::IMAGE_REL_PPC_REFLO, |
| 226 | } => section |
| 227 | .relocations() |
| 228 | .skip_while(|&(a, _)| a < address) |
| 229 | .take_while(|&(a, _)| a == address) |
| 230 | .find(|(_, reloc)| { |
| 231 | matches!(reloc.flags(), object::RelocationFlags::Coff { |
| 232 | typ: pe::IMAGE_REL_PPC_PAIR |
| 233 | }) |
| 234 | }) |
| 235 | .map_or( |
| 236 | Ok(Some(RelocationOverride { |
| 237 | target: RelocationOverrideTarget::Keep, |
| 238 | addend: 0, |
| 239 | })), |
| 240 | |(_, reloc)| match reloc.target() { |
| 241 | object::RelocationTarget::Symbol(_) => Ok(Some(RelocationOverride { |
| 242 | target: RelocationOverrideTarget::Keep, |
| 243 | addend: 0, |
| 244 | })), |
| 245 | target => Err(anyhow!("Unsupported IMAGE_REL_PPC_PAIR target {target:?}")), |
| 246 | }, |
| 247 | ), |
| 248 | // Skip PAIR relocations as they are handled by the previous case |
| 249 | object::RelocationFlags::Coff { typ: pe::IMAGE_REL_PPC_PAIR } => { |
| 250 | Ok(Some(RelocationOverride { target: RelocationOverrideTarget::Skip, addend: 0 })) |
| 251 | } |
| 252 | // Any other COFF relocation has an addend of 0 |
| 253 | object::RelocationFlags::Coff { .. } => { |
| 254 | Ok(Some(RelocationOverride { target: RelocationOverrideTarget::Keep, addend: 0 })) |
| 255 | } |
| 256 | // Handle ELF implicit relocations |
| 257 | flags @ object::RelocationFlags::Elf { r_type } => { |
| 258 | ensure!( |
| 259 | !relocation.has_implicit_addend(), |
| 260 | "Unsupported implicit relocation {:?}", |
| 261 | flags |
| 262 | ); |
| 263 | match r_type { |
| 264 | elf::R_PPC64_TOC16 => { |
| 265 | let offset = u64::try_from(relocation.addend()) |
| 266 | .map_err(|_| anyhow!("Negative addend for R_PPC64_TOC16 relocation"))?; |
| 267 | let Some(toc_section) = file.section_by_name(".toc") else { |
| 268 | bail!("Missing .toc section for R_PPC64_TOC16 relocation"); |
| 269 | }; |
| 270 | // If TOC target is a relocation, replace it with the target symbol |
| 271 | let Some((_, toc_relocation)) = |
| 272 | toc_section.relocations().find(|&(a, _)| a == offset) |