summaryrefslogtreecommitdiff
path: root/rtl-mdreloc-arm.c
diff options
context:
space:
mode:
authorChris Johns <chrisj@rtems.org>2012-07-31 15:17:21 +1000
committerChris Johns <chrisj@rtems.org>2012-07-31 15:17:21 +1000
commit99bdd39271de093920b34d217a5a4b7f0a6f2e80 (patch)
treef73c646e5eb6173b63dacc4097794d5c8d1af274 /rtl-mdreloc-arm.c
parent328fbd26ed0213af7e328de105921f4eb7927e55 (diff)
Add ARM support. Cleaned up the waf support.
Adding ARM support has changed the architecture relocation interface. All architectures updated. Cleaned up the RTEMS waf support to only look for tools when the arch is being processed. Add filter support to allow a user to make sure a BSP is present or to remove BSPs that will not build. Added the Init support because ARM BSPs do not contain the support.
Diffstat (limited to 'rtl-mdreloc-arm.c')
-rw-r--r--rtl-mdreloc-arm.c195
1 files changed, 106 insertions, 89 deletions
diff --git a/rtl-mdreloc-arm.c b/rtl-mdreloc-arm.c
index 0e4f3e9..e55da1f 100644
--- a/rtl-mdreloc-arm.c
+++ b/rtl-mdreloc-arm.c
@@ -20,132 +20,149 @@
* It is possible for the compiler to emit relocations for unaligned data.
* We handle this situation with these inlines.
*/
-#define RELOC_ALIGNED_P(x) \
- (((uintptr_t)(x) & (sizeof(void *) - 1)) == 0)
+#define RELOC_ALIGNED_P(x) \
+ (((uintptr_t)(x) & (sizeof(void *) - 1)) == 0)
static inline Elf_Addr
-load_ptr (void *where)
+load_ptr(void *where)
{
- Elf_Addr res;
- memcpy (&res, where, sizeof(res));
- return (res);
+ Elf_Addr res;
+
+ memcpy(&res, where, sizeof(res));
+
+ return (res);
}
static inline void
-store_ptr (void *where, Elf_Addr val)
+store_ptr(void *where, Elf_Addr val)
+{
+
+ memcpy(where, &val, sizeof(val));
+}
+
+bool
+rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
{
- memcpy(where, &val, sizeof(val));
+ 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)
{
- printf ("rtl: rela record not supported; please report\n");
+ rtems_rtl_set_error (EINVAL, "rela type record not supported");
return false;
}
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)
{
- Elf_Addr target = 0;
- Elf_Addr* where;
+ Elf_Addr *where;
Elf_Addr tmp;
- Elf_Word symvalue;
where = (Elf_Addr *)(sect->base + rel->r_offset);
switch (ELF_R_TYPE(rel->r_info)) {
- case R_TYPE(NONE):
- break;
+ case R_TYPE(NONE):
+ break;
- case R_TYPE(PC24): { /* word32 S - P + A */
- Elf32_Sword addend;
+#if 1 /* XXX should not occur */
+ case R_TYPE(PC24): { /* word32 S - P + A */
+ Elf32_Sword addend;
- /*
- * Extract addend and sign-extend if needed.
- */
- addend = *where;
- if (addend & 0x00800000)
- addend |= 0xff000000;
+ /*
+ * Extract addend and sign-extend if needed.
+ */
+ addend = *where;
+ if (addend & 0x00800000)
+ addend |= 0xff000000;
- if (!rtems_rtl_elf_find_symbol (obj, sym, symname, &symvalue))
- return false;
+ tmp = (Elf_Addr)sect->base + symvalue
+ - (Elf_Addr)where + (addend << 2);
- tmp = (Elf_Addr) symvalue - (Elf_Addr) where + (addend << 2);
if ((tmp & 0xfe000000) != 0xfe000000 &&
- (tmp & 0xfe000000) != 0) {
- rtems_rtl_set_error ("%s: R_ARM_PC24 relocation @ %p to %s failed "
+ (tmp & 0xfe000000) != 0) {
+ rtems_rtl_set_error (EINVAL,
+ "R_ARM_PC24 in %s relocation @ %p failed " \
"(displacement %ld (%#lx) out of range)",
- obj->oname, where, symname,
- (long) tmp, (long) tmp);
- return false;
- }
- tmp >>= 2;
- *where = (*where & 0xff000000) | (tmp & 0x00ffffff);
+ rtems_rtl_obj_oname (obj), where, (long) tmp, (long) tmp);
+ return false;
+ }
+
+ tmp >>= 2;
+ *where = (*where & 0xff000000) | (tmp & 0x00ffffff);
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
- printf ("rtl: reloc PC24 %s in %s --> %p @ %p\n",
- symname, obj->oname, (void *)*where, where);
- break;
- }
-
- case R_TYPE(ABS32): /* word32 B + S + A */
- case R_TYPE(GLOB_DAT): /* word32 B + S */
- if (!rtems_rtl_elf_find_symbol (obj, sym, symname, &symvalue))
- return false;
-
- if (__predict_true (RELOC_ALIGNED_P (where))) {
- tmp = *where + symvalue;
- /* Set the Thumb bit, if needed. */
- if (ELF_ST_TYPE(def->st_info) == STT_ARM_TFUNC)
- tmp |= 1;
- *where = tmp;
- } else {
- tmp = load_ptr (where) + symvalue;
- /* Set the Thumb bit, if needed. */
- if (ELF_ST_TYPE(def->st_info) == STT_ARM_TFUNC)
+ printf ("rtl: PC24 %p @ %p in %s",
+ (void *)*where, where, rtems_rtl_obj_oname (obj));
+ break;
+ }
+#endif
+
+ case R_TYPE(ABS32): /* word32 B + S + A */
+ case R_TYPE(GLOB_DAT): /* word32 B + S */
+ if (__predict_true(RELOC_ALIGNED_P(where))) {
+ tmp = *where + (Elf_Addr)sect->base + symvalue;
+ /* Set the Thumb bit, if needed. */
+ if (ELF_ST_TYPE(syminfo) == STT_ARM_TFUNC)
tmp |= 1;
- store_ptr (where, tmp);
- }
+ *where = tmp;
+ } else {
+ tmp = load_ptr(where) + symvalue;
+ /* Set the Thumb bit, if needed. */
+ if (ELF_ST_TYPE(syminfo) == STT_ARM_TFUNC)
+ tmp |= 1;
+ store_ptr(where, tmp);
+ }
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
- printf ("rtl: reloc ABS32/GLOB_DAT %s in %s --> %p @ %p\n",
- symname, obj->oname, (void *)tmp, where);
- break;
-
- case R_TYPE(RELATIVE): /* word32 B + A */
- if (__predict_true (RELOC_ALIGNED_P (where))) {
- tmp = *where + (Elf_Addr) sect->base;
- *where = tmp;
- } else {
- tmp = load_ptr (where) + (Elf_Addr) sect->base;
- store_ptr (where, tmp);
- }
+ printf ("rtl: ABS32/GLOB_DAT %p @ %p in %s",
+ (void *)tmp, where, rtems_rtl_obj_oname (obj));
+ break;
+
+ case R_TYPE(RELATIVE): /* word32 B + A */
+ if (__predict_true(RELOC_ALIGNED_P(where))) {
+ tmp = *where + (Elf_Addr)sect->base;
+ *where = tmp;
+ } else {
+ tmp = load_ptr(where) + (Elf_Addr)sect->base;
+ store_ptr(where, tmp);
+ }
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
- printf ("rtl: reloc RELATIVE in %s --> %p", obj->oname, (void *)tmp));
- break;
-
- case R_TYPE(COPY):
- printf ("rtl: reloc COPY (please report)\n");
- break;
+ printf ("rtl: RELATIVE in %s --> %p",
+ rtems_rtl_obj_oname (obj), (void *)tmp);
+ break;
+
+ case R_TYPE(COPY):
+ /*
+ * 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.
+ */
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: COPY (avoid in main)");
+ break;
- default:
+ default:
printf ("rtl: reloc unknown: sym = %lu, type = %lu, offset = %p, "
- "contents = %p, symbol = %s\n",
+ "contents = %p\n",
ELF_R_SYM(rel->r_info), (uint32_t) ELF_R_TYPE(rel->r_info),
- (void *)rel->r_offset, (void *)*where, symname);
+ (void *)rel->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(rel->r_info));
- return false;
+ return false;
}
-
- return true;
+
+ return true;
}
+