Skip to content

Commit 8f16bbc

Browse files
committed
fix: recalculate addresses when lower bits are greater than 0x8000
1 parent bdea152 commit 8f16bbc

File tree

1 file changed

+23
-3
lines changed

1 file changed

+23
-3
lines changed

ee/erl/src/erl.c

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)