diff options
author | Peng Fan <van.freenix@gmail.com> | 2013-07-18 11:38:12 +0800 |
---|---|---|
committer | Peng Fan <van.freenix@gmail.com> | 2013-07-22 10:51:46 +0800 |
commit | 20cac2e624ce8f2bc55af38b2b030c92a4aac6d1 (patch) | |
tree | 4454a1aa4c5e6508a3020cd83a06063d0f1cf572 /rtl-mdreloc-powerpc.c | |
parent | 19b3b6033adfe740038a5cd483f05b7c9273a148 (diff) |
powerpc support
Signed-off-by: Peng Fan <van.freenix@gmail.com>
Diffstat (limited to 'rtl-mdreloc-powerpc.c')
-rw-r--r-- | rtl-mdreloc-powerpc.c | 205 |
1 files changed, 119 insertions, 86 deletions
diff --git a/rtl-mdreloc-powerpc.c b/rtl-mdreloc-powerpc.c index 719570e..4f009c9 100644 --- a/rtl-mdreloc-powerpc.c +++ b/rtl-mdreloc-powerpc.c @@ -4,34 +4,6 @@ /* $NetBSD: ppc_reloc.c,v 1.44 2010/01/13 20:17:22 christos Exp $ */ -/*- - * Copyright (C) 1998 Tsubai Masanari - * Portions copyright 2002 Charles M. Hannum <root@ihack.net> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - #include <sys/cdefs.h> #include <errno.h> @@ -48,105 +20,166 @@ ((u_int32_t)(x) + 0x10000) : (u_int32_t)(x)) >> 16) #define l(x) ((u_int32_t)(x) & 0xffff) -/* - * The PPC PLT format consists of three sections: - * (1) The "pltcall" and "pltresolve" glue code. This is always 18 words. - * (2) The code part of the PLT entries. There are 2 words per entry for - * up to 8192 entries, then 4 words per entry for any additional entries. - * (3) The data part of the PLT entries, comprising a jump table. - * This section is half the size of the second section (ie. 1 or 2 words - * per entry). - */ -/* - * Setup the plt glue routines. - */ -#define PLTCALL_SIZE 20 -#define PLTRESOLVE_SIZE 24 +bool +rtems_rtl_elf_rel_resolve_sym (Elf_Word type) +{ + return true; +} bool -rtems_rtl_elf_relocate_rela (rtems_rtl_obj_t* obj, - const Elf_Rela* rela, - rtems_rtl_obj_sect_t* sect, - const Elf_Sym* sym, - const char* symname) +rtems_rtl_elf_relocate_rela (const rtems_rtl_obj_t* obj, + const Elf_Rela* rela, + const rtems_rtl_obj_sect_t* sect, + const char* symname, + const Elf_Byte syminfo, + const Elf_Word symvalue) { Elf_Addr target = 0; Elf_Addr* where; - Elf_Word symvalue; + Elf_Word tmp; + uint32_t mask = 0; + uint32_t bits = 0; where = (Elf_Addr *)(sect->base + rela->r_offset); - switch (ELF_R_TYPE(rela->r_info)) { - case R_TYPE(JMP_SLOT): case R_TYPE(NONE): break; - case R_TYPE(PC32): - if (!rtems_rtl_elf_find_symbol (obj, sym, symname, &symvalue)) - return false; - - target = (Elf_Addr) symvalue + rela->r_addend; - *where += target - (Elf_Addr)where; - + case R_TYPE(32): + /* + * value:1; Field: word32; Expression: S + A + */ + *where = symvalue + rela->r_addend; if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) - printf ("rtl: reloc PC32 %s in %s --> %p (%p) in %s\n", - symname, sect->name, (void*) (symvalue + rela->r_addend), - (void *)*where, obj->oname); + printf ("rtl: ADDR32 %p @ %p in %s\n", + (void *)*(where), where, rtems_rtl_obj_oname (obj)); break; - case R_TYPE(32): /* word32 S + A */ - case R_TYPE(GLOB_DAT): /* word32 S + A */ - if (!rtems_rtl_elf_find_symbol (obj, sym, symname, &symvalue)) + case R_TYPE(14): + /* + * value:7; Field: low14*; Expression: (S + A) >> 2 + */ + case R_TYPE(24): + /* + * value:2; Field: low24*; Expression: (S + A) >> 2 + */ + if (ELF_R_TYPE(rela->r_info) == R_TYPE(14)) { + bits = 14; + mask = 0xfffc; + } else { + bits = 24; + mask = 0x3fffffc; + } + tmp = (symvalue + rela->r_addend) >> 2; + if (tmp > (1<<bits -1 )) { + printf("Overflow ADDR14/ADDR24\n"); return false; + } + tmp = *where; + tmp &= ~mask; + tmp |= (symvalue + rela->r_addend) & mask; + *where = tmp; + if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) + printf ("rtl: ADDR14/ADDR24 %p @ %p in %s\n", + (void *)*where, where, rtems_rtl_obj_oname (obj)); + break; - target = (Elf_Addr) symvalue + rela->r_addend; + case R_TYPE(16_HA): + /* + * value:6; Field:half16; Expression: #ha(S+A) + */ - if (*where != target) - *where = target; + tmp = symvalue + rela->r_addend; + *(uint16_t *)where = (((tmp >> 16) + ((tmp & 0x8000) ? 1: 0)) & 0xffff); + if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) + printf ("rtl: 16_HA %p @ %p in %s\n", + (void *)*(where), where, rtems_rtl_obj_oname (obj)); + break; + case R_TYPE(16_HI): + /* + * value:5; Field:half16; Expression: #hi(S+A) + */ + *(uint16_t *)where = ((symvalue + rela->r_addend) >> 16) & 0xffff; + if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) + printf ("rtl: 16_HI %p @ %p in %s\n", + (void *)*where, where, rtems_rtl_obj_oname (obj)); + break; + case R_TYPE(16_LO): + /* + * value:4; Field:half16; Expression: #lo(S+A) + */ + *(uint16_t *)where = (symvalue + (rela->r_addend)) & 0xffff; if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) - printf ("rtl: reloc 32/GLOB_DAT %s in %s --> %p in %s\n", - symname, sect->name, (void *)*where, obj->oname); + printf ("rtl: 16_LO %p @ %p in %s\n", + (void *)*where, where, rtems_rtl_obj_oname (obj)); break; - case R_TYPE(RELATIVE): /* word32 B + A */ - *where += (Elf_Addr) sect->base + rela->r_addend; + case R_TYPE(REL14): + /* + * value:11; Field:low14*; Expression:(S+A-P)>>2 + */ + case R_TYPE(REL24): + /* + * value:10; Field:low24*; Expression:(S+A-P)>>2 + */ + if (ELF_R_TYPE(rela->r_info) == R_TYPE(REL24)) { + mask = 0x3fffffc; + bits = 24; + } + else if (ELF_R_TYPE(rela->r_info) == R_TYPE(REL14)) { + mask = 0xfffc; + bits = 14; + } + + tmp =((int) (symvalue + rela->r_addend - (Elf_Addr)where)) >> 2; + if (((Elf_Sword)tmp > ((1<<(bits-1)) - 1)) || + ((Elf_Sword)tmp < -(1<<(bits-1)))) { + printf("Overflow REL14/REL24\n"); + return false; + } + + tmp = *where; + tmp &= ~mask; + tmp |= (symvalue + rela->r_addend - (Elf_Addr)where) & mask; + *where = tmp; if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) - printf ("rtl: reloc RELATIVE in %s --> %p\n", obj->oname, (void *)*where); + printf ("rtl: REL24/REL14 %p @ %p in %s\n", + (void *)*where, where, rtems_rtl_obj_oname (obj)); break; - case R_TYPE(COPY): + case R_TYPE(REL32): /* - * These are deferred until all other relocations have - * been done. All we do here is make sure that the - * COPY relocation is not in a shared library. They - * are allowed only in executable files. + * value:26; Field:word32*; Expression:S+A-P */ - printf ("rtl: reloc COPY (please report)\n"); + *where = symvalue + rela->r_addend - (Elf_Addr)where; + if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) + printf ("rtl: REL32 %p @ %p in %s\n", + (void *)*where, where, rtems_rtl_obj_oname (obj)); break; default: printf ("rtl: reloc unknown: sym = %lu, type = %lu, offset = %p, " - "contents = %p, symbol = %s\n", + "contents = %p\n", ELF_R_SYM(rela->r_info), (uint32_t) ELF_R_TYPE(rela->r_info), - (void *)rela->r_offset, (void *)*where, symname); + (void *)rela->r_offset, (void *)*where); rtems_rtl_set_error (EINVAL, "%s: Unsupported relocation type %ld " "in non-PLT relocations", sect->name, (uint32_t) ELF_R_TYPE(rela->r_info)); return false; } - - return false; + return true; } bool -rtems_rtl_elf_relocate_rel (rtems_rtl_obj_t* obj, - const Elf_Rel* rel, - rtems_rtl_obj_sect_t* sect, - const Elf_Sym* sym, - const char* symname) +rtems_rtl_elf_relocate_rel (const rtems_rtl_obj_t* obj, + const Elf_Rel* rel, + const rtems_rtl_obj_sect_t* sect, + const char* symname, + const Elf_Byte syminfo, + const Elf_Word symvalue) { printf ("rtl: rel type record not supported; please report\n"); return false; |