Date: Sun, 8 Jan 2012 05:44:19 +0000 (UTC) From: Oleksandr Tymoshenko <gonzo@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r229803 - head/sys/mips/mips Message-ID: <201201080544.q085iJUZ072872@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: gonzo Date: Sun Jan 8 05:44:19 2012 New Revision: 229803 URL: http://svn.freebsd.org/changeset/base/229803 Log: Fix relocations for MIPS64: - Use Elf32_Addr as default, the only field that is 64 bitw wide is R_MIPS_64 - Add R_MIPS_HIGHER and R_MIPS_HGHEST handlers - Handle R_MIPS_HI16 and R_MIPS_LO16 for both .rel and .rela sections Modified: head/sys/mips/mips/elf_machdep.c Modified: head/sys/mips/mips/elf_machdep.c ============================================================================== --- head/sys/mips/mips/elf_machdep.c Sun Jan 8 01:54:46 2012 (r229802) +++ head/sys/mips/mips/elf_machdep.c Sun Jan 8 05:44:19 2012 (r229803) @@ -168,25 +168,41 @@ static int elf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data, int type, int local, elf_lookup_fn lookup) { - Elf_Addr *where = (Elf_Addr *)NULL; + Elf32_Addr *where = (Elf32_Addr *)NULL; Elf_Addr addr; Elf_Addr addend = (Elf_Addr)0; Elf_Word rtype = (Elf_Word)0, symidx; - const Elf_Rel *rel; + const Elf_Rel *rel = NULL; + const Elf_Rela *rela = NULL; /* * Stash R_MIPS_HI16 info so we can use it when processing R_MIPS_LO16 */ static Elf_Addr ahl; - static Elf_Addr *where_hi16; + static Elf32_Addr *where_hi16; switch (type) { case ELF_RELOC_REL: rel = (const Elf_Rel *)data; - where = (Elf_Addr *) (relocbase + rel->r_offset); - addend = *where; + where = (Elf32_Addr *) (relocbase + rel->r_offset); rtype = ELF_R_TYPE(rel->r_info); symidx = ELF_R_SYM(rel->r_info); + switch (rtype) { + case R_MIPS_64: + addend = *(Elf64_Addr *)where; + break; + default: + addend = *where; + break; + } + + break; + case ELF_RELOC_RELA: + rela = (const Elf_Rela *)data; + where = (Elf32_Addr *) (relocbase + rela->r_offset); + addend = rela->r_addend; + rtype = ELF_R_TYPE(rela->r_info); + symidx = ELF_R_SYM(rela->r_info); break; default: panic("unknown reloc type %d\n", type); @@ -202,7 +218,7 @@ elf_reloc_internal(linker_file_t lf, Elf return (-1); addr += addend; if (*where != addr) - *where = addr; + *where = (Elf32_Addr)addr; break; case R_MIPS_26: /* ((A << 2) | (P & 0xf0000000) + S) >> 2 */ @@ -220,25 +236,73 @@ elf_reloc_internal(linker_file_t lf, Elf *where |= addr & 0x03ffffff; break; + case R_MIPS_64: /* S + A */ + addr = lookup(lf, symidx, 1); + if (addr == 0) + return (-1); + addr += addend; + if (*(Elf64_Addr*)where != addr) + *(Elf64_Addr*)where = addr; + break; + case R_MIPS_HI16: /* ((AHL + S) - ((short)(AHL + S)) >> 16 */ - ahl = addend << 16; - where_hi16 = where; + if (rela != NULL) { + addr = lookup(lf, symidx, 1); + if (addr == 0) + return (-1); + addr += addend; + *where &= 0xffff0000; + *where |= ((((long long) addr + 0x8000LL) >> 16) & 0xffff); + } + else { + ahl = addend << 16; + where_hi16 = where; + } break; case R_MIPS_LO16: /* AHL + S */ - ahl += (int16_t)addend; + if (rela != NULL) { + addr = lookup(lf, symidx, 1); + if (addr == 0) + return (-1); + addr += addend; + *where &= 0xffff0000; + *where |= addr & 0xffff; + } + else { + ahl += (int16_t)addend; + addr = lookup(lf, symidx, 1); + if (addr == 0) + return (-1); + + addend &= 0xffff0000; + addend |= (uint16_t)(ahl + addr); + *where = addend; + + addend = *where_hi16; + addend &= 0xffff0000; + addend |= ((ahl + addr) - (int16_t)(ahl + addr)) >> 16; + *where_hi16 = addend; + } + + break; + + case R_MIPS_HIGHER: /* %higher(A+S) */ addr = lookup(lf, symidx, 1); if (addr == 0) return (-1); + addr += addend; + *where &= 0xffff0000; + *where |= (((long long)addr + 0x80008000LL) >> 32) & 0xffff; + break; - addend &= 0xffff0000; - addend |= (uint16_t)(ahl + addr); - *where = addend; - - addend = *where_hi16; - addend &= 0xffff0000; - addend |= ((ahl + addr) - (int16_t)(ahl + addr)) >> 16; - *where_hi16 = addend; + case R_MIPS_HIGHEST: /* %highest(A+S) */ + addr = lookup(lf, symidx, 1); + if (addr == 0) + return (-1); + addr += addend; + *where &= 0xffff0000; + *where |= (((long long)addr + 0x800080008000LL) >> 48) & 0xffff; break; default: @@ -246,6 +310,7 @@ elf_reloc_internal(linker_file_t lf, Elf rtype); return (-1); } + return(0); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201201080544.q085iJUZ072872>