summaryrefslogtreecommitdiff
path: root/rtl-mdreloc-powerpc.c
diff options
context:
space:
mode:
authorPeng Fan <van.freenix@gmail.com>2013-07-18 11:38:12 +0800
committerPeng Fan <van.freenix@gmail.com>2013-07-22 10:51:46 +0800
commit20cac2e624ce8f2bc55af38b2b030c92a4aac6d1 (patch)
tree4454a1aa4c5e6508a3020cd83a06063d0f1cf572 /rtl-mdreloc-powerpc.c
parent19b3b6033adfe740038a5cd483f05b7c9273a148 (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.c205
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;