| 243 | } |
| 244 | |
| 245 | fn relocation_override( |
| 246 | &self, |
| 247 | file: &object::File<'_>, |
| 248 | section: &object::Section, |
| 249 | address: u64, |
| 250 | relocation: &object::Relocation, |
| 251 | ) -> Result<Option<RelocationOverride>> { |
| 252 | match relocation.flags() { |
| 253 | // Handle ELF implicit relocations |
| 254 | object::RelocationFlags::Elf { r_type } => { |
| 255 | if relocation.has_implicit_addend() { |
| 256 | // Check for paired R_MIPS_HI16 and R_MIPS_LO16 relocations. |
| 257 | if let elf::R_MIPS_HI16 | elf::R_MIPS_LO16 = r_type |
| 258 | && let Some(addend) = self |
| 259 | .paired_relocations |
| 260 | .get(section.index().0) |
| 261 | .and_then(|m| m.get(&address).copied()) |
| 262 | { |
| 263 | return Ok(Some(RelocationOverride { |
| 264 | target: RelocationOverrideTarget::Keep, |
| 265 | addend, |
| 266 | })); |
| 267 | } |
| 268 | |
| 269 | let data = section.data()?; |
| 270 | let code = self |
| 271 | .endianness |
| 272 | .read_u32_bytes(data[address as usize..address as usize + 4].try_into()?); |
| 273 | let addend = match r_type { |
| 274 | elf::R_MIPS_32 => code as i64, |
| 275 | elf::R_MIPS_26 => ((code & 0x03FFFFFF) << 2) as i64, |
| 276 | elf::R_MIPS_HI16 => ((code & 0x0000FFFF) << 16) as i32 as i64, |
| 277 | elf::R_MIPS_LO16 | elf::R_MIPS_GOT16 | elf::R_MIPS_CALL16 => { |
| 278 | (code & 0x0000FFFF) as i16 as i64 |
| 279 | } |
| 280 | elf::R_MIPS_GPREL16 | elf::R_MIPS_LITERAL => { |
| 281 | let object::RelocationTarget::Symbol(idx) = relocation.target() else { |
| 282 | bail!("Unsupported R_MIPS_GPREL16 relocation against a non-symbol"); |
| 283 | }; |
| 284 | let sym = file.symbol_by_index(idx)?; |
| 285 | |
| 286 | // if the symbol we are relocating against is in a local section we need to add |
| 287 | // the ri_gp_value from .reginfo to the addend. |
| 288 | if sym.section().index().is_some() { |
| 289 | ((code & 0x0000FFFF) as i16 as i64) + self.ri_gp_value as i64 |
| 290 | } else { |
| 291 | (code & 0x0000FFFF) as i16 as i64 |
| 292 | } |
| 293 | } |
| 294 | elf::R_MIPS_PC16 => 0, // PC-relative relocation |
| 295 | R_MIPS15_S3 => ((code & 0x001FFFC0) >> 3) as i64, |
| 296 | elf::R_MIPS_GPREL32 => (code as i32 as i64) + self.ri_gp_value as i64, |
| 297 | flags => bail!("Unsupported MIPS implicit relocation {flags:?}"), |
| 298 | }; |
| 299 | Ok(Some(RelocationOverride { target: RelocationOverrideTarget::Keep, addend })) |
| 300 | } else { |
| 301 | Ok(None) |
| 302 | } |