11use std:: { borrow:: Cow , collections:: BTreeMap , sync:: Mutex } ;
22
33use anyhow:: { anyhow, bail, Result } ;
4- use object:: { elf, Endian , Endianness , File , FileFlags , Object , Relocation , RelocationFlags } ;
4+ use object:: {
5+ elf, Endian , Endianness , File , FileFlags , Object , ObjectSection , ObjectSymbol , Relocation ,
6+ RelocationFlags , RelocationTarget ,
7+ } ;
58use rabbitizer:: { config, Abi , InstrCategory , Instruction , OperandType } ;
69
710use crate :: {
@@ -22,6 +25,7 @@ pub struct ObjArchMips {
2225 pub endianness : Endianness ,
2326 pub abi : Abi ,
2427 pub instr_category : InstrCategory ,
28+ pub ri_gp_value : i32 ,
2529}
2630
2731const EF_MIPS_ABI : u32 = 0x0000F000 ;
@@ -56,7 +60,19 @@ impl ObjArchMips {
5660 }
5761 _ => bail ! ( "Unsupported MIPS file flags" ) ,
5862 }
59- Ok ( Self { endianness : object. endianness ( ) , abi, instr_category } )
63+
64+ // Parse the ri_gp_value stored in .reginfo to be able to correctly
65+ // calculate R_MIPS_GPREL16 relocations later. The value is stored
66+ // 0x14 bytes into .reginfo (on 32 bit platforms)
67+ let ri_gp_value = object
68+ . section_by_name ( ".reginfo" )
69+ . and_then ( |section| section. data ( ) . ok ( ) )
70+ . and_then ( |data| data. get ( 0x14 ..0x18 ) )
71+ . and_then ( |s| s. try_into ( ) . ok ( ) )
72+ . map ( |bytes| object. endianness ( ) . read_i32_bytes ( bytes) )
73+ . unwrap_or ( 0 ) ;
74+
75+ Ok ( Self { endianness : object. endianness ( ) , abi, instr_category, ri_gp_value } )
6076 }
6177}
6278
@@ -179,6 +195,7 @@ impl ObjArch for ObjArchMips {
179195
180196 fn implcit_addend (
181197 & self ,
198+ file : & File < ' _ > ,
182199 section : & ObjSection ,
183200 address : u64 ,
184201 reloc : & Relocation ,
@@ -191,9 +208,22 @@ impl ObjArch for ObjArchMips {
191208 ( ( addend & 0x0000FFFF ) << 16 ) as i32 as i64
192209 }
193210 RelocationFlags :: Elf {
194- r_type :
195- elf:: R_MIPS_LO16 | elf:: R_MIPS_GOT16 | elf:: R_MIPS_CALL16 | elf:: R_MIPS_GPREL16 ,
211+ r_type : elf:: R_MIPS_LO16 | elf:: R_MIPS_GOT16 | elf:: R_MIPS_CALL16 ,
196212 } => ( addend & 0x0000FFFF ) as i16 as i64 ,
213+ RelocationFlags :: Elf { r_type : elf:: R_MIPS_GPREL16 } => {
214+ let RelocationTarget :: Symbol ( idx) = reloc. target ( ) else {
215+ bail ! ( "Unsupported R_MIPS_GPREL16 relocation against a non-symbol" ) ;
216+ } ;
217+ let sym = file. symbol_by_index ( idx) ?;
218+
219+ // if the symbol we are relocating against is in a local section we need to add
220+ // the ri_gp_value from .reginfo to the addend.
221+ if sym. section ( ) . index ( ) . is_some ( ) {
222+ ( ( addend & 0x0000FFFF ) as i16 as i64 ) + self . ri_gp_value as i64
223+ } else {
224+ ( addend & 0x0000FFFF ) as i16 as i64
225+ }
226+ }
197227 RelocationFlags :: Elf { r_type : elf:: R_MIPS_26 } => ( ( addend & 0x03FFFFFF ) << 2 ) as i64 ,
198228 flags => bail ! ( "Unsupported MIPS implicit relocation {flags:?}" ) ,
199229 } )
0 commit comments