@@ -583,7 +583,7 @@ static int read_erl(int elf_handle, u8 * elf_mem, u32 addr, struct erl_record_t
583583 struct elf_header_t head ;
584584 struct elf_section_t * sec = 0 ;
585585 struct elf_symbol_t * sym = 0 ;
586- struct elf_reloc_t reloc ;
586+ struct elf_reloc_t reloc , next_reloc ;
587587 int i , j ;
588588 // int erx_compressed; // Not used
589589 char * names = 0 , * strtab_names = 0 , * reloc_section = 0 ;
@@ -593,6 +593,8 @@ static int read_erl(int elf_handle, u8 * elf_mem, u32 addr, struct erl_record_t
593593 struct erl_record_t * erl_record = 0 ;
594594 struct symbol_t * s ;
595595
596+ int has_next_reloc = 0 ;
597+
596598 * p_erl_record = 0 ;
597599
598600#define free_and_return (code ) if (!elf_mem) { \
@@ -839,11 +841,19 @@ return code
839841 // We found one relocation section, let's parse it to relocate.
840842 dprintf (" Num: Offset Type Symbol\n" );
841843 for (j = 0 ; (u32 )j < (sec [i ].sh_size / sec [i ].sh_entsize ); j ++ ) {
842- int sym_n ;
844+ int sym_n , next_sym_n ;
843845
844846 reloc = * ((struct elf_reloc_t * ) (reloc_section + j * sec [i ].sh_entsize ));
845847
846848 sym_n = reloc .r_info >> 8 ;
849+
850+ has_next_reloc = 0 ;
851+ if ((u32 )j + 1 < (sec [i ].sh_size / sec [i ].sh_entsize )) {
852+ next_reloc = * ((struct elf_reloc_t * ) (reloc_section + ((j + 1 ) * sec [i ].sh_entsize )));
853+ next_sym_n = reloc .r_info >> 8 ;
854+ has_next_reloc = 1 ;
855+ }
856+
847857 dprintf ("%6i: %08X %-14s %3i: " , j , reloc .r_offset , reloc_types [reloc .r_info & 255 ], sym_n );
848858
849859 switch (sym [sym_n ].st_info & 15 ) {
@@ -864,7 +874,17 @@ return code
864874 case SECTION :
865875 rprintf ("internal section reloc to section %i (%s)\n" , sym [sym_n ].st_shndx , names + sec [sym [sym_n ].st_shndx ].sh_name );
866876 dprintf ("Relocating at %08X.\n" , erl_record -> bytes + sec [sym [sym_n ].st_shndx ].sh_addr );
867- if (apply_reloc (erl_record -> bytes + sec [sec [i ].sh_info ].sh_addr + reloc .r_offset , reloc .r_info & 255 , (u32 ) (erl_record -> bytes + sec [sym [sym_n ].st_shndx ].sh_addr )) < 0 ) {
877+
878+ if ((reloc .r_info & 255 ) == R_MIPS_HI16 &&
879+ (has_next_reloc && ((next_reloc .r_info & 255 ) == R_MIPS_LO16 )) &&
880+ (sec [sym [sym_n ].st_shndx ].sh_addr == sec [sym [next_sym_n ].st_shndx ].sh_addr ) &&
881+ (* (u16 * )(erl_record -> bytes + sec [sec [i ].sh_info ].sh_addr + next_reloc .r_offset ) + ((u32 ) (erl_record -> bytes + sec [sym [sym_n ].st_shndx ].sh_addr ) & 0x0000ffff )) >= 0x8000
882+ ) {
883+ u32 data = * (u32 * )(erl_record -> bytes + sec [sec [i ].sh_info ].sh_addr + reloc .r_offset );
884+ * (u32 * )(erl_record -> bytes + sec [sec [i ].sh_info ].sh_addr + reloc .r_offset ) = data + !(data & 0xf );
885+ }
886+
887+ if (apply_reloc (erl_record -> bytes + sec [sec [i ].sh_info ].sh_addr + reloc .r_offset , reloc .r_info & 255 , (u32 ) (erl_record -> bytes + sec [sym [sym_n ].st_shndx ].sh_addr )) < 0 ) {
868888 dprintf ("Something went wrong in relocation." );
869889 free_and_return (-1 );
870890 }
0 commit comments