Adjust mips/dl.c for bigendian

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2011-05-13 15:38:42 +02:00
parent 60ddfad3da
commit 11d86592b7

View file

@ -34,7 +34,7 @@ grub_arch_dl_check_header (void *ehdr)
Elf_Ehdr *e = ehdr; Elf_Ehdr *e = ehdr;
/* Check the magic numbers. */ /* Check the magic numbers. */
#ifdef WORDS_BIGENDIAN #ifdef GRUB_CPU_WORDS_BIGENDIAN
if (e->e_ident[EI_CLASS] != ELFCLASS32 if (e->e_ident[EI_CLASS] != ELFCLASS32
|| e->e_ident[EI_DATA] != ELFDATA2MSB || e->e_ident[EI_DATA] != ELFDATA2MSB
|| e->e_machine != EM_MIPS) || e->e_machine != EM_MIPS)
@ -144,14 +144,14 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr)
rel < max; rel < max;
rel++) rel++)
{ {
Elf_Word *addr; grub_uint8_t *addr;
Elf_Sym *sym; Elf_Sym *sym;
if (seg->size < rel->r_offset) if (seg->size < rel->r_offset)
return grub_error (GRUB_ERR_BAD_MODULE, return grub_error (GRUB_ERR_BAD_MODULE,
"reloc offset is out of the segment"); "reloc offset is out of the segment");
addr = (Elf_Word *) ((char *) seg->addr + rel->r_offset); addr = (grub_uint8_t *) ((char *) seg->addr + rel->r_offset);
sym = (Elf_Sym *) ((char *) mod->symtab sym = (Elf_Sym *) ((char *) mod->symtab
+ entsize * ELF_R_SYM (rel->r_info)); + entsize * ELF_R_SYM (rel->r_info));
if (sym->st_value == (grub_addr_t) &__gnu_local_gp_dummy) if (sym->st_value == (grub_addr_t) &__gnu_local_gp_dummy)
@ -164,6 +164,10 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr)
grub_uint32_t value; grub_uint32_t value;
Elf_Rel *rel2; Elf_Rel *rel2;
#ifdef GRUB_CPU_WORDS_BIGENDIAN
addr += 2;
#endif
/* Handle partner lo16 relocation. Lower part is /* Handle partner lo16 relocation. Lower part is
treated as signed. Hence add 0x8000 to compensate. treated as signed. Hence add 0x8000 to compensate.
*/ */
@ -175,13 +179,20 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr)
&& ELF_R_TYPE (rel2->r_info) == R_MIPS_LO16) && ELF_R_TYPE (rel2->r_info) == R_MIPS_LO16)
{ {
value += *(grub_int16_t *) value += *(grub_int16_t *)
((char *) seg->addr + rel2->r_offset); ((char *) seg->addr + rel2->r_offset
#ifdef GRUB_CPU_WORDS_BIGENDIAN
+ 2
#endif
);
break; break;
} }
*(grub_uint16_t *) addr = (value >> 16) & 0xffff; *(grub_uint16_t *) addr = (value >> 16) & 0xffff;
} }
break; break;
case R_MIPS_LO16: case R_MIPS_LO16:
#ifdef GRUB_CPU_WORDS_BIGENDIAN
addr += 2;
#endif
*(grub_uint16_t *) addr += (sym->st_value) & 0xffff; *(grub_uint16_t *) addr += (sym->st_value) & 0xffff;
break; break;
case R_MIPS_32: case R_MIPS_32:
@ -208,6 +219,9 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr)
case R_MIPS_GOT16: case R_MIPS_GOT16:
case R_MIPS_CALL16: case R_MIPS_CALL16:
/* FIXME: reuse*/ /* FIXME: reuse*/
#ifdef GRUB_CPU_WORDS_BIGENDIAN
addr += 2;
#endif
*gpptr = sym->st_value + *(grub_uint16_t *) addr; *gpptr = sym->st_value + *(grub_uint16_t *) addr;
*(grub_uint16_t *) addr *(grub_uint16_t *) addr
= sizeof (grub_uint32_t) * (gpptr - gp); = sizeof (grub_uint32_t) * (gpptr - gp);