Support MIPS PIC relocations

This commit is contained in:
Luke Street 2023-01-21 12:41:41 -05:00
parent 09bbc534bd
commit 8278d5d207
3 changed files with 72 additions and 52 deletions

View File

@ -1,15 +1,11 @@
use std::{collections::BTreeMap, fs, io::Cursor, path::Path}; use std::{collections::BTreeMap, fs, io::Cursor, path::Path};
use anyhow::{Context, Result}; use anyhow::{anyhow, bail, Context, Result};
use byteorder::{BigEndian, ReadBytesExt}; use byteorder::{BigEndian, ReadBytesExt};
use cwdemangle::demangle; use cwdemangle::demangle;
use flagset::Flags; use flagset::Flags;
use object::{ use object::{
elf::{ elf, Architecture, File, Object, ObjectSection, ObjectSymbol, RelocationKind, RelocationTarget,
R_MIPS_26, R_MIPS_HI16, R_MIPS_LO16, R_PPC_ADDR16_HA, R_PPC_ADDR16_HI, R_PPC_ADDR16_LO,
R_PPC_EMB_SDA21, R_PPC_REL14, R_PPC_REL24,
},
Architecture, File, Object, ObjectSection, ObjectSymbol, RelocationKind, RelocationTarget,
SectionIndex, SectionKind, Symbol, SymbolKind, SymbolSection, SectionIndex, SectionKind, Symbol, SymbolKind, SymbolSection,
}; };
@ -207,12 +203,12 @@ fn relocations_by_section(
RelocationKind::Absolute => ObjRelocKind::Absolute, RelocationKind::Absolute => ObjRelocKind::Absolute,
RelocationKind::Elf(kind) => match arch { RelocationKind::Elf(kind) => match arch {
ObjArchitecture::PowerPc => match kind { ObjArchitecture::PowerPc => match kind {
R_PPC_ADDR16_LO => ObjRelocKind::PpcAddr16Lo, elf::R_PPC_ADDR16_LO => ObjRelocKind::PpcAddr16Lo,
R_PPC_ADDR16_HI => ObjRelocKind::PpcAddr16Hi, elf::R_PPC_ADDR16_HI => ObjRelocKind::PpcAddr16Hi,
R_PPC_ADDR16_HA => ObjRelocKind::PpcAddr16Ha, elf::R_PPC_ADDR16_HA => ObjRelocKind::PpcAddr16Ha,
R_PPC_REL24 => ObjRelocKind::PpcRel24, elf::R_PPC_REL24 => ObjRelocKind::PpcRel24,
R_PPC_REL14 => ObjRelocKind::PpcRel14, elf::R_PPC_REL14 => ObjRelocKind::PpcRel14,
R_PPC_EMB_SDA21 => ObjRelocKind::PpcEmbSda21, elf::R_PPC_EMB_SDA21 => ObjRelocKind::PpcEmbSda21,
_ => { _ => {
return Err(anyhow::Error::msg(format!( return Err(anyhow::Error::msg(format!(
"Unhandled PPC relocation type: {kind}" "Unhandled PPC relocation type: {kind}"
@ -220,14 +216,14 @@ fn relocations_by_section(
} }
}, },
ObjArchitecture::Mips => match kind { ObjArchitecture::Mips => match kind {
R_MIPS_26 => ObjRelocKind::Mips26, elf::R_MIPS_26 => ObjRelocKind::Mips26,
R_MIPS_HI16 => ObjRelocKind::MipsHi16, elf::R_MIPS_HI16 => ObjRelocKind::MipsHi16,
R_MIPS_LO16 => ObjRelocKind::MipsLo16, elf::R_MIPS_LO16 => ObjRelocKind::MipsLo16,
_ => { elf::R_MIPS_GOT16 => ObjRelocKind::MipsGot16,
return Err(anyhow::Error::msg(format!( elf::R_MIPS_CALL16 => ObjRelocKind::MipsCall16,
"Unhandled MIPS relocation type: {kind}" elf::R_MIPS_GPREL16 => ObjRelocKind::MipsGpRel16,
))) elf::R_MIPS_GPREL32 => ObjRelocKind::MipsGpRel32,
} _ => bail!("Unhandled MIPS relocation type: {kind}"),
}, },
}, },
_ => { _ => {
@ -244,37 +240,36 @@ fn relocations_by_section(
} }
_ => None, _ => None,
}; };
// println!("Reloc: {:?}, symbol: {:?}", reloc, symbol);
let target = match symbol.kind() {
SymbolKind::Text | SymbolKind::Data | SymbolKind::Label | SymbolKind::Unknown => {
to_obj_symbol(obj_file, &symbol, reloc.addend())
}
SymbolKind::Section => {
let addend = if reloc.has_implicit_addend() { let addend = if reloc.has_implicit_addend() {
let addend = u32::from_be_bytes( let addend = u32::from_be_bytes(
section.data[address as usize..address as usize + 4].try_into()?, section.data[address as usize..address as usize + 4].try_into()?,
); );
match kind { match kind {
ObjRelocKind::Absolute => addend, ObjRelocKind::Absolute => addend as i64,
ObjRelocKind::MipsHi16 | ObjRelocKind::MipsLo16 => addend & 0x0000FFFF, ObjRelocKind::MipsHi16 => ((addend & 0x0000FFFF) << 16) as i16 as i64,
ObjRelocKind::Mips26 => (addend & 0x03FFFFFF) * 4, ObjRelocKind::MipsLo16
_ => todo!(), | ObjRelocKind::MipsGot16
| ObjRelocKind::MipsCall16
| ObjRelocKind::MipsGpRel16 => (addend & 0x0000FFFF) as i16 as i64,
ObjRelocKind::MipsGpRel32 => addend as i32 as i64,
ObjRelocKind::Mips26 => ((addend & 0x03FFFFFF) << 2) as i64,
_ => bail!("Unsupported implicit relocation {kind:?}"),
} }
} else { } else {
let addend = reloc.addend(); reloc.addend()
if addend < 0 {
return Err(anyhow::Error::msg(format!(
"Negative addend in section reloc: {addend}"
)));
}
addend as u32
}; };
// println!("Reloc: {reloc:?}, symbol: {symbol:?}, addend: {addend:#X}");
let target = match symbol.kind() {
SymbolKind::Text | SymbolKind::Data | SymbolKind::Label | SymbolKind::Unknown => {
to_obj_symbol(obj_file, &symbol, addend)
}
SymbolKind::Section => {
if addend < 0 {
return Err(anyhow::Error::msg(format!("Negative addend in reloc: {addend}")));
}
find_section_symbol(obj_file, &symbol, addend as u64) find_section_symbol(obj_file, &symbol, addend as u64)
} }
_ => Err(anyhow::Error::msg(format!( kind => Err(anyhow!("Unhandled relocation symbol type {kind:?}")),
"Unhandled relocation symbol type {:?}",
symbol.kind()
))),
}?; }?;
relocations.push(ObjReloc { kind, address, target, target_section }); relocations.push(ObjReloc { kind, address, target, target_section });
} }

View File

@ -159,6 +159,10 @@ pub enum ObjRelocKind {
Mips26, Mips26,
MipsHi16, MipsHi16,
MipsLo16, MipsLo16,
MipsGot16,
MipsCall16,
MipsGpRel16,
MipsGpRel32,
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct ObjReloc { pub struct ObjReloc {

View File

@ -1,4 +1,4 @@
use std::default::Default; use std::{cmp::Ordering, default::Default};
use cwdemangle::demangle; use cwdemangle::demangle;
use eframe::emath::Align; use eframe::emath::Align;
@ -20,8 +20,14 @@ use crate::{
fn write_reloc_name(reloc: &ObjReloc, color: Color32, job: &mut LayoutJob, font_id: FontId) { fn write_reloc_name(reloc: &ObjReloc, color: Color32, job: &mut LayoutJob, font_id: FontId) {
let name = reloc.target.demangled_name.as_ref().unwrap_or(&reloc.target.name); let name = reloc.target.demangled_name.as_ref().unwrap_or(&reloc.target.name);
write_text(name, Color32::LIGHT_GRAY, job, font_id.clone()); write_text(name, Color32::LIGHT_GRAY, job, font_id.clone());
if reloc.target.addend != 0 { match reloc.target.addend.cmp(&0i64) {
write_text(&format!("+{:X}", reloc.target.addend), color, job, font_id); Ordering::Greater => {
write_text(&format!("+{:#X}", reloc.target.addend), color, job, font_id)
}
Ordering::Less => {
write_text(&format!("-{:#X}", -reloc.target.addend), color, job, font_id);
}
_ => {}
} }
} }
@ -53,12 +59,27 @@ fn write_reloc(reloc: &ObjReloc, color: Color32, job: &mut LayoutJob, font_id: F
write_reloc_name(reloc, color, job, font_id.clone()); write_reloc_name(reloc, color, job, font_id.clone());
write_text(")", color, job, font_id); write_text(")", color, job, font_id);
} }
ObjRelocKind::Absolute ObjRelocKind::MipsGot16 => {
| ObjRelocKind::PpcRel24 write_text("%got(", color, job, font_id.clone());
| ObjRelocKind::PpcRel14 write_reloc_name(reloc, color, job, font_id.clone());
| ObjRelocKind::Mips26 => { write_text(")", color, job, font_id);
}
ObjRelocKind::MipsCall16 => {
write_text("%call16(", color, job, font_id.clone());
write_reloc_name(reloc, color, job, font_id.clone());
write_text(")", color, job, font_id);
}
ObjRelocKind::MipsGpRel16 => {
write_text("%gp_rel(", color, job, font_id.clone());
write_reloc_name(reloc, color, job, font_id.clone());
write_text(")", color, job, font_id);
}
ObjRelocKind::PpcRel24 | ObjRelocKind::PpcRel14 | ObjRelocKind::Mips26 => {
write_reloc_name(reloc, color, job, font_id); write_reloc_name(reloc, color, job, font_id);
} }
ObjRelocKind::Absolute | ObjRelocKind::MipsGpRel32 => {
write_text("[INVALID]", color, job, font_id);
}
}; };
} }