Support R_MIPS_GPREL16 relocations correctly (#88)

* Support R_MIPS_GPREL16 relocations correctly

symbols defined in the same file require adding a
special ri_gp_value from the .reginfo section to
their relocation calculations.

* Run nightly rustfmt

* Prevent potential panic when slicing .reginfo
This commit is contained in:
Steven Casper 2024-08-08 22:20:41 -04:00 committed by GitHub
parent fc598af329
commit 09cc9952df
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 46 additions and 8 deletions

View File

@ -227,6 +227,7 @@ impl ObjArch for ObjArchArm {
fn implcit_addend( fn implcit_addend(
&self, &self,
_file: &File<'_>,
section: &ObjSection, section: &ObjSection,
address: u64, address: u64,
reloc: &Relocation, reloc: &Relocation,

View File

@ -1,7 +1,10 @@
use std::{borrow::Cow, collections::BTreeMap, sync::Mutex}; use std::{borrow::Cow, collections::BTreeMap, sync::Mutex};
use anyhow::{anyhow, bail, Result}; use anyhow::{anyhow, bail, Result};
use object::{elf, Endian, Endianness, File, FileFlags, Object, Relocation, RelocationFlags}; use object::{
elf, Endian, Endianness, File, FileFlags, Object, ObjectSection, ObjectSymbol, Relocation,
RelocationFlags, RelocationTarget,
};
use rabbitizer::{config, Abi, InstrCategory, Instruction, OperandType}; use rabbitizer::{config, Abi, InstrCategory, Instruction, OperandType};
use crate::{ use crate::{
@ -22,6 +25,7 @@ pub struct ObjArchMips {
pub endianness: Endianness, pub endianness: Endianness,
pub abi: Abi, pub abi: Abi,
pub instr_category: InstrCategory, pub instr_category: InstrCategory,
pub ri_gp_value: i32,
} }
const EF_MIPS_ABI: u32 = 0x0000F000; const EF_MIPS_ABI: u32 = 0x0000F000;
@ -56,7 +60,19 @@ impl ObjArchMips {
} }
_ => bail!("Unsupported MIPS file flags"), _ => bail!("Unsupported MIPS file flags"),
} }
Ok(Self { endianness: object.endianness(), abi, instr_category })
// Parse the ri_gp_value stored in .reginfo to be able to correctly
// calculate R_MIPS_GPREL16 relocations later. The value is stored
// 0x14 bytes into .reginfo (on 32 bit platforms)
let ri_gp_value = object
.section_by_name(".reginfo")
.and_then(|section| section.data().ok())
.and_then(|data| data.get(0x14..0x18))
.and_then(|s| s.try_into().ok())
.map(|bytes| object.endianness().read_i32_bytes(bytes))
.unwrap_or(0);
Ok(Self { endianness: object.endianness(), abi, instr_category, ri_gp_value })
} }
} }
@ -179,6 +195,7 @@ impl ObjArch for ObjArchMips {
fn implcit_addend( fn implcit_addend(
&self, &self,
file: &File<'_>,
section: &ObjSection, section: &ObjSection,
address: u64, address: u64,
reloc: &Relocation, reloc: &Relocation,
@ -191,9 +208,22 @@ impl ObjArch for ObjArchMips {
((addend & 0x0000FFFF) << 16) as i32 as i64 ((addend & 0x0000FFFF) << 16) as i32 as i64
} }
RelocationFlags::Elf { RelocationFlags::Elf {
r_type: r_type: elf::R_MIPS_LO16 | elf::R_MIPS_GOT16 | elf::R_MIPS_CALL16,
elf::R_MIPS_LO16 | elf::R_MIPS_GOT16 | elf::R_MIPS_CALL16 | elf::R_MIPS_GPREL16,
} => (addend & 0x0000FFFF) as i16 as i64, } => (addend & 0x0000FFFF) as i16 as i64,
RelocationFlags::Elf { r_type: elf::R_MIPS_GPREL16 } => {
let RelocationTarget::Symbol(idx) = reloc.target() else {
bail!("Unsupported R_MIPS_GPREL16 relocation against a non-symbol");
};
let sym = file.symbol_by_index(idx)?;
// if the symbol we are relocating against is in a local section we need to add
// the ri_gp_value from .reginfo to the addend.
if sym.section().index().is_some() {
((addend & 0x0000FFFF) as i16 as i64) + self.ri_gp_value as i64
} else {
(addend & 0x0000FFFF) as i16 as i64
}
}
RelocationFlags::Elf { r_type: elf::R_MIPS_26 } => ((addend & 0x03FFFFFF) << 2) as i64, RelocationFlags::Elf { r_type: elf::R_MIPS_26 } => ((addend & 0x03FFFFFF) << 2) as i64,
flags => bail!("Unsupported MIPS implicit relocation {flags:?}"), flags => bail!("Unsupported MIPS implicit relocation {flags:?}"),
}) })

View File

@ -1,7 +1,7 @@
use std::{borrow::Cow, collections::BTreeMap}; use std::{borrow::Cow, collections::BTreeMap};
use anyhow::{bail, Result}; use anyhow::{bail, Result};
use object::{Architecture, Object, ObjectSymbol, Relocation, RelocationFlags, Symbol}; use object::{Architecture, File, Object, ObjectSymbol, Relocation, RelocationFlags, Symbol};
use crate::{ use crate::{
diff::DiffObjConfig, diff::DiffObjConfig,
@ -28,8 +28,13 @@ pub trait ObjArch: Send + Sync {
config: &DiffObjConfig, config: &DiffObjConfig,
) -> Result<ProcessCodeResult>; ) -> Result<ProcessCodeResult>;
fn implcit_addend(&self, section: &ObjSection, address: u64, reloc: &Relocation) fn implcit_addend(
-> Result<i64>; &self,
file: &File<'_>,
section: &ObjSection,
address: u64,
reloc: &Relocation,
) -> Result<i64>;
fn demangle(&self, _name: &str) -> Option<String> { None } fn demangle(&self, _name: &str) -> Option<String> { None }

View File

@ -150,6 +150,7 @@ impl ObjArch for ObjArchPpc {
fn implcit_addend( fn implcit_addend(
&self, &self,
_file: &File<'_>,
_section: &ObjSection, _section: &ObjSection,
address: u64, address: u64,
reloc: &Relocation, reloc: &Relocation,

View File

@ -128,6 +128,7 @@ impl ObjArch for ObjArchX86 {
fn implcit_addend( fn implcit_addend(
&self, &self,
_file: &File<'_>,
section: &ObjSection, section: &ObjSection,
address: u64, address: u64,
reloc: &Relocation, reloc: &Relocation,

View File

@ -364,7 +364,7 @@ fn relocations_by_section(
_ => None, _ => None,
}; };
let addend = if reloc.has_implicit_addend() { let addend = if reloc.has_implicit_addend() {
arch.implcit_addend(section, address, &reloc)? arch.implcit_addend(obj_file, section, address, &reloc)?
} else { } else {
reloc.addend() reloc.addend()
}; };