Skip to content

Instantly share code, notes, and snippets.

@MrVan
Created May 4, 2013 12:33
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save MrVan/5517361 to your computer and use it in GitHub Desktop.
Save MrVan/5517361 to your computer and use it in GitHub Desktop.
1. Basic Reloc types are implemented. ARM REL TYPE: R_ARM_JUMP24 R_ARM_ABS32 R_ARM_CALL R_ARM_MOVW_ABS_NC R_ARM_MOVT_ABS R_ARM_V4BX //This should be fixed. arm thumb switch? THUMB REL TYPE: R_ARM_THM_CALL R_ARM_ABS32 R_ARM_THM_MOVW_ABS_NC R_ARM_THM_MOVT_ABS R_ARM_THM_JUMP24 2. Implement several group reloc types. But not sure what are they used …
From 516531d199ec2302c0f932c61b9542a70492948b Mon Sep 17 00:00:00 2001
From: Peng Fan <van.freenix@gmail.com>
Date: Sat, 4 May 2013 20:26:59 +0800
Subject: [PATCH] ARM Support
---
.gitignore | 4 +
Makefile | 8 +
bspinit.c | 2 +
libbsd/include/arch/arm/machine/elf_machdep.h | 25 ++
main.c | 3 +
rtems.py | 9 +-
rtl-mdreloc-arm.c | 447 +++++++++++++++++++++++--
rtl-obj.c | 2 +
rtl-rap.c | 110 +++---
rtl-sym.c | 40 ++-
rtl.c | 7 +-
shell-init | 6 +-
wscript | 28 +-
x1.S | 53 +++
x2.S | 32 ++
xa.c | 14 +
16 files changed, 702 insertions(+), 88 deletions(-)
create mode 100644 Makefile
mode change 100644 => 100755 wscript
create mode 100644 x1.S
create mode 100644 x2.S
diff --git a/.gitignore b/.gitignore
index 60089a0..56e23ab 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,7 @@
.lock-waf*
build
*.pyc
+*.sh
+./tags
+cscope.*
+./debug-rld
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..38e5611
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,8 @@
+all: FORCE
+ make -C /home/freenix/work/gsoc/rtems/rtl/rel-test
+ waf
+FORCE:
+
+.phony: clean
+clean:
+ waf clean
diff --git a/bspinit.c b/bspinit.c
index 9c50d03..e10cce4 100644
--- a/bspinit.c
+++ b/bspinit.c
@@ -12,6 +12,7 @@
#include <bsp.h>
#include <bsp/bootcard.h>
+#undef RTEMS_NETWORKING /* commented by freenix */
#ifdef RTEMS_NETWORKING
#include <rtems/rtems_bsdnet.h>
#endif
@@ -76,6 +77,7 @@ void Init (rtems_task_argument arg)
}
}
+ printk("Init\n");
#ifdef RTEMS_NETWORKING
rtems_bsdnet_initialize_network ();
#endif
diff --git a/libbsd/include/arch/arm/machine/elf_machdep.h b/libbsd/include/arch/arm/machine/elf_machdep.h
index 963ff64..09e0995 100644
--- a/libbsd/include/arch/arm/machine/elf_machdep.h
+++ b/libbsd/include/arch/arm/machine/elf_machdep.h
@@ -40,6 +40,7 @@
#define R_ARM_PC24 1
#define R_ARM_ABS32 2
#define R_ARM_REL32 3
+#define R_ARM_LDR_PC_G0 4
#define R_ARM_PC13 4
#define R_ARM_ABS16 5
#define R_ARM_ABS12 6
@@ -47,6 +48,7 @@
#define R_ARM_ABS8 8
#define R_ARM_SBREL32 9
#define R_ARM_THM_PC22 10
+#define R_ARM_THM_CALL 10
#define R_ARM_THM_PC8 11
#define R_ARM_AMP_VCALL9 12
#define R_ARM_SWI24 13
@@ -69,6 +71,11 @@
#define R_ARM_GOT32 26
#define R_ARM_PLT32 27
+#define R_ARM_CALL 28
+#define R_ARM_JUMP24 29
+#define R_ARM_THM_JUMP24 30
+#define R_ARM_BASE_ABS 31
+
#define R_ARM_ALU_PCREL_7_0 32
#define R_ARM_ALU_PCREL_15_8 33
#define R_ARM_ALU_PCREL_23_15 34
@@ -76,6 +83,24 @@
#define R_ARM_ALU_SBREL_19_12 36
#define R_ARM_ALU_SBREL_27_20 37
+#define R_ARM_V4BX 40
+
+#define R_ARM_PREL31 41
+
+#define R_ARM_MOVW_ABS_NC 43
+#define R_ARM_MOVT_ABS 44
+
+#define R_ARM_THM_MOVW_ABS_NC 47
+#define R_ARM_THM_MOVT_ABS 48
+
+#define R_ARM_THM_JUMP19 51
+#define R_ARM_LDR_PC_G1 62
+#define R_ARM_LDR_PC_G2 63
+
+#define R_ARM_LDR_SB_G0 75
+#define R_ARM_LDR_SB_G1 76
+#define R_ARM_LDR_SB_G2 77
+
/* 96-111 are reserved to G++. */
#define R_ARM_GNU_VTENTRY 100
#define R_ARM_GNU_VTINHERIT 101
diff --git a/main.c b/main.c
index a8f8640..d0397ce 100644
--- a/main.c
+++ b/main.c
@@ -375,6 +375,9 @@ main (int argc, char* argv[])
{
struct termios term;
int ret;
+ printf("%s\n", __func__);
+ //__asm__ __volatile__ ("ldr r3, [r1], #4");
+ printf("%s\n", __func__);
#if pc586
int arg;
diff --git a/rtems.py b/rtems.py
index 5558f84..d80cc52 100644
--- a/rtems.py
+++ b/rtems.py
@@ -388,6 +388,9 @@ def _find_installed_archs(config, path, version):
for d in os.listdir(path):
if d.endswith('-rtems' + version):
archs += [d]
+ for d in os.listdir(path):
+ if d.endswith('-rtemseabi' + version):
+ archs += [d]
else:
a = subprocess.check_output([config, '--list-format', '"%(arch)s"'])
a = a[:-1].replace('"', '')
@@ -403,6 +406,10 @@ def _check_archs(config, req, path, version):
arch = a + '-rtems' + version
if arch in installed:
archs += [arch]
+ for a in req.split(','):
+ arch = a + '-rtemseabi' + version
+ if arch in installed:
+ archs += [arch]
archs.sort()
return archs
@@ -429,7 +436,7 @@ def _check_arch_bsps(req, config, path, archs, version):
return []
found = False
for arch in archs:
- a = '%s-rtems%s' % (abl[0], version)
+ a = '%s-rtemseabi%s' % (abl[0], version)
if a == arch:
found = True
break
diff --git a/rtl-mdreloc-arm.c b/rtl-mdreloc-arm.c
index e55da1f..7fc4987 100644
--- a/rtl-mdreloc-arm.c
+++ b/rtl-mdreloc-arm.c
@@ -4,6 +4,14 @@
/* $NetBSD: mdreloc.c,v 1.33 2010/01/14 12:12:07 skrll Exp $ */
+
+/*
+ * Added by Peng Fan
+ * Code Name Type Class Operation Instruction
+ * 29 R_ARM_CALL Static ARM ((S + A) | T) - P
+ * 30 R_ARM_JUMP24 Static ARM ((S + A) | T) - P
+ */
+
#include <sys/cdefs.h>
#include <errno.h>
@@ -40,6 +48,30 @@ store_ptr(void *where, Elf_Addr val)
memcpy(where, &val, sizeof(val));
}
+static inline Elf_Word
+calc_grp_kn(Elf_Word residual)
+{
+ int msb;
+
+ if (residual == 0)
+ return 0;
+ for (msb = 30; (msb >= 0) && !(residual & (3 << msb)); msb -= 2)
+ ;
+ return (((msb - 6) < 0) ? 0 : (msb - 6));
+}
+
+static Elf_Word
+cal_group_reloc_mask(Elf_Word residual, int n)
+{
+ int i;
+
+ for (i = 0; i <= n; i++) {
+ Elf_Word shift = calc_grp_kn(residual);
+ residual &= ~(residual & (0xff << shift));
+ }
+ return residual;
+}
+
bool
rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
{
@@ -68,62 +100,212 @@ rtems_rtl_elf_relocate_rel (const rtems_rtl_obj_t* obj,
{
Elf_Addr *where;
Elf_Addr tmp;
+ Elf32_Sword addend;
+ Elf32_Word val;
where = (Elf_Addr *)(sect->base + rel->r_offset);
switch (ELF_R_TYPE(rel->r_info)) {
case R_TYPE(NONE):
break;
+ case R_TYPE(ABS8): {
+ /*
+ * operation: S + A;
+ * overflow: yes; class: data;
+ * Addend = sign_extend(P[8:0]);
+ */
+ tmp = *where;
+ addend = tmp & 0xff;
+ if (addend & 0x80)
+ addend |= 0xffffff00;
+ if ((addend > 0xff) || (addend < -0x80)) {
+ rtems_rtl_set_error (EINVAL, "%s: Overflow %ld "
+ "ABS8 relocations",
+ sect->name, (uint32_t) ELF_R_TYPE(rel->r_info));
+ return false;
+ }
+ *where = addend + symvalue; /* S + A */
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: ABS8 %p @ %p in %s\n",
+ (void *)tmp, where, rtems_rtl_obj_oname (obj));
+ break;
+ }
+ case R_TYPE(ABS16): {
+ /*
+ * operation: S + A;
+ * overflow: yes; class: data;
+ * Addend = sign_extend(P[16:0]);
+ */
+ tmp = *where;
+ addend = tmp & 0xffff;
+ if (addend & 0x8000)
+ addend |= 0xffff0000;
+ if ((addend > 0xffff) || (addend < -0x8000)) {
+ rtems_rtl_set_error (EINVAL, "%s: Overflow %ld "
+ "ABS16 relocations",
+ sect->name, (uint32_t) ELF_R_TYPE(rel->r_info));
+ return false;
+ }
+ *where = addend + symvalue; /* S + A */
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: ABS16 %p @ %p in %s\n",
+ (void *)tmp, where, rtems_rtl_obj_oname (obj));
+ break;
+ }
+ case R_TYPE(PREL31): {
+ /*
+ * operation: (S + A) | T - P;
+ * class:data;
+ * Addend = sign_extend(P[30:0]);
+ */
+ tmp = *where;
+ addend = tmp & 0x7fffffff;
+ if (addend & 0x40000000);
+ addend |= 0x80000000;
+ if ((addend > 0x7fffffff) || (addend < -0x3fffffff)) {
+ rtems_rtl_set_error (EINVAL, "%s: Overflow %ld "
+ "PREL31 relocations",
+ sect->name, (uint32_t) ELF_R_TYPE(rel->r_info));
+ return false;
+ }
+ tmp = symvalue + addend;
+ if (ELF_ST_TYPE(syminfo) == STT_ARM_TFUNC)
+ tmp |= 1; /* (S + A) | T */
+ *where = tmp - (Elf_Addr)where; /* (S + A) | T - P */
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: PREL31 %p @ %p in %s\n",
+ (void *)tmp, where, rtems_rtl_obj_oname (obj));
+ break;
+ }
#if 1 /* XXX should not occur */
- case R_TYPE(PC24): { /* word32 S - P + A */
- Elf32_Sword addend;
+ /* Thumb will supported in future */
+
+ case R_TYPE(PC24):
+ /* Deprecated */
+ case R_TYPE(CALL):
+ /*
+ * operation: ((S + A) | T - P);
+ * overflow: yes; insn: bl/blx; result mask: X&0x03fffffe;
+ * addend: sign_extend(insn[23:0] << 2);
+ * fall through
+ */
+ case R_TYPE(JUMP24): {
+ /*
+ * operation: ((S + A) | T - P);
+ * overflow: yes; insn: bl<cond>/b; result mask: X&0x03fffffe;
+ * addend: sign_extend(insn[23:0] << 2);
+ */
/*
* Extract addend and sign-extend if needed.
*/
addend = *where;
if (addend & 0x00800000)
- addend |= 0xff000000;
+ addend |= 0xff000000; //sign extended
- tmp = (Elf_Addr)sect->base + symvalue
- - (Elf_Addr)where + (addend << 2);
-
- if ((tmp & 0xfe000000) != 0xfe000000 &&
- (tmp & 0xfe000000) != 0) {
- rtems_rtl_set_error (EINVAL,
- "R_ARM_PC24 in %s relocation @ %p failed " \
- "(displacement %ld (%#lx) out of range)",
- rtems_rtl_obj_oname (obj), where, (long) tmp, (long) tmp);
- return false;
- }
+ tmp = symvalue + (addend << 2);
+ if (ELF_ST_TYPE(syminfo) == STT_ARM_TFUNC)
+ tmp |= 1;
+ tmp -= (Elf_Addr)where;
tmp >>= 2;
*where = (*where & 0xff000000) | (tmp & 0x00ffffff);
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
- printf ("rtl: PC24 %p @ %p in %s",
+ printf ("rtl: JUMP24/PC24/CALL %p @ %p in %s\n",
(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 */
+ case R_TYPE(V4BX): { /* Miscellaneous */
+ /* Note: Not sure whether this should be implemented */
+#if 1
+ tmp = *where;
+ tmp &= 0xf000000f; /* Keep cond and Rm*/
+ tmp |= 0x01a0f000; /* Mov PC, Rm */
+#endif
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: V4BX %p @ %p in %s\n",
+ (void *)*where, where, rtems_rtl_obj_oname (obj));
+ break;
+ }
+
+ /* Encoding of imm16 argument for movt and movw ARM instructions
+ * from ARM ARM:
+ *
+ * imm16 := imm4 | imm12
+ *
+ * f e d c b a 9 8 7 6 5 4 3 2 1 0 f e d c b a 9 8 7 6 5 4 3 2 1 0
+ * +-------+---------------+-------+-------+-----------------------+
+ * | | |imm4 | |imm12 |
+ * +-------+---------------+-------+-------+-----------------------+
+ */
+ case R_TYPE(MOVT_ABS):
+ /*
+ * operation: S + A
+ * overflow:yes; insn: movt; result masks: x&0xffff0000;
+ * insn[19:16] = (Result_Mask(X)>>16)>>12;
+ * insn[11:0] = (Result_Mask(X)>>16)&0xfff;
+ */
+ case R_TYPE(MOVW_ABS_NC): {
+ /*
+ * operation: (S + A) | T;
+ * overflow: no; insn:movw; result mask:x&0xffff;
+ * insn[19:16] = (Result_Mask(X)>>16) >> 12;
+ * insn[11:0] = Result_Mask(X)&0xfff
+ *
+ */
+ tmp = *where;
+ addend = ((val >> 4) & 0xf000) | (val & 0xfff);
+ if (addend & 0x8000)
+ addend |= 0xffff0000;
+ tmp = symvalue + addend; /* S + A */
+ if (ELF_R_TYPE(rel->r_info) == R_ARM_MOVW_ABS_NC ) {
+ if (ELF_ST_TYPE(syminfo) == STT_ARM_TFUNC)
+ tmp |= 1; /* (S + A) | T */
+ tmp &= 0xffff; /* result mask */
+ } else if (ELF_R_TYPE(rel->r_info) == R_ARM_MOVT_ABS) {
+ tmp >>= 16;
+ if (((int)tmp >= 0x8000) || ((int)tmp < -0x8000)) {
+ rtems_rtl_set_error (EINVAL, "%s: Overflow %ld "
+ "MOVT_ABS relocations",
+ sect->name, (uint32_t) ELF_R_TYPE(rel->r_info));
+ return false;
+ }
+
+ }
+ *where = (*where & 0xfff0f000) | ((tmp & 0xf000) << 4) | (tmp & 0xfff);
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: MOVT_ABS/MOVW_ABS_NC %p @ %p in %s\n",
+ (void *)*where, where, rtems_rtl_obj_oname (obj));
+ break;
+ }
+
+
+ case R_TYPE(REL32):/* word32 (S + A) | T - P*/
+ case R_TYPE(ABS32):/* word32 (S + A) | T */
+ case R_TYPE(GLOB_DAT): /* word32 (S + A) | T */
if (__predict_true(RELOC_ALIGNED_P(where))) {
- tmp = *where + (Elf_Addr)sect->base + symvalue;
+ tmp = *where + symvalue; /* S + A */
/* Set the Thumb bit, if needed. */
if (ELF_ST_TYPE(syminfo) == STT_ARM_TFUNC)
tmp |= 1;
+ if (ELF_R_TYPE(rel->r_info) == R_TYPE(REL32))
+ tmp -= (Elf_Addr)where;
*where = tmp;
} else {
tmp = load_ptr(where) + symvalue;
/* Set the Thumb bit, if needed. */
if (ELF_ST_TYPE(syminfo) == STT_ARM_TFUNC)
tmp |= 1;
+ if (ELF_R_TYPE(rel->r_info) == R_TYPE(REL32))
+ tmp -= (Elf_Addr)where;
store_ptr(where, tmp);
}
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
- printf ("rtl: ABS32/GLOB_DAT %p @ %p in %s",
+ printf ("rtl: ABS32/GLOB_DAT %p @ %p in %s\n",
(void *)tmp, where, rtems_rtl_obj_oname (obj));
break;
@@ -136,7 +318,7 @@ rtems_rtl_elf_relocate_rel (const rtems_rtl_obj_t* obj,
store_ptr(where, tmp);
}
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
- printf ("rtl: RELATIVE in %s --> %p",
+ printf ("rtl: RELATIVE in %s --> %p\n",
rtems_rtl_obj_oname (obj), (void *)tmp);
break;
@@ -151,6 +333,228 @@ rtems_rtl_elf_relocate_rel (const rtems_rtl_obj_t* obj,
printf ("rtl: COPY (avoid in main)");
break;
+ /* Group relocation */
+ /* Note: should be checked */
+ case R_TYPE(LDR_PC_G0):
+ case R_TYPE(LDR_PC_G1):
+ case R_TYPE(LDR_PC_G2):
+ case R_TYPE(LDR_SB_G0):
+ case R_TYPE(LDR_SB_G1):
+ case R_TYPE(LDR_SB_G2): {
+ /*
+ * operation: S + A - P;
+ * overflow: yes; insn: ldr/str/ldrb/strb class:ARM; result mask:
+ * ABS(X)&G0(LDR); Addend: insn[11:0] * {(insn[23] == 0)?-1:1};
+ * insn[23] = (X>=0); insn[11:0] = Result_Mask(X);
+ */
+
+ Elf_Word residual;
+ Elf_Word group = 0;
+ Elf_Sword X;
+ Elf_Word r_type;
+ r_type = ELF_R_TYPE(rel->r_info);
+
+ switch (r_type) {
+ case R_TYPE(LDR_PC_G0):
+ case R_TYPE(LDR_SB_G0):
+ group = 0;
+ break;
+ case R_TYPE(LDR_PC_G1):
+ case R_TYPE(LDR_SB_G1):
+ group = 1;
+ break;
+ case R_TYPE(LDR_PC_G2):
+ case R_TYPE(LDR_SB_G2):
+ group = 2;
+ break;
+ default:
+ printf("abort\n");
+ return false;
+ }
+
+ tmp = *where;
+ const int sign = (tmp & 0x00800000) ? 1 : -1;
+ addend = (tmp & 0xfff) * sign;
+ if ((r_type == R_TYPE(LDR_PC_G0)) ||
+ (r_type == R_TYPE(LDR_PC_G1)) ||
+ (r_type == R_TYPE(LDR_PC_G2)))
+ X = symvalue + addend - (Elf_Addr)where;
+ else
+ X = symvalue + addend - (Elf_Addr)where;
+ printf("symvalue %x, addend %x, where %x X %x\n", symvalue, addend, where,X);
+
+ residual = cal_group_reloc_mask(abs(X), group - 1);
+ printf("residual %x\n", residual);
+
+ if (residual >= 0x1000) {
+ rtems_rtl_set_error (EINVAL, "%s: Overflow %ld "
+ "GROUP relocations",
+ sect->name, (uint32_t) ELF_R_TYPE(rel->r_info));
+ return false;
+ }
+
+ tmp &= 0xff7ff000;
+ if (X >= 0)
+ tmp |= 1 << 23;
+ tmp |= residual;
+ *where = tmp;
+
+ break;
+ }
+
+ /*--------------Thumb32----------------*/
+//#ifdef THUMB_SUPPORT
+ /* Encoding of imm16 argument for movt and movw Thumb2 instructions
+ * from ARM ARM:
+ *
+ * imm16 := imm4 | i | imm3 | imm8
+ *
+ * f e d c b a 9 8 7 6 5 4 3 2 1 0 f e d c b a 9 8 7 6 5 4 3 2 1 0
+ * +---------+-+-----------+-------++-+-----+-------+---------------+
+ * | |i| |imm4 || |imm3 | |imm8 |
+ * +---------+-+-----------+-------++-+-----+-------+---------------+
+ */
+ case R_TYPE(THM_MOVT_ABS): /* word32 S + A*/
+ case R_TYPE(THM_MOVW_ABS_NC): { /* word32 (S + A) | T */
+ tmp = *where;
+ addend = (tmp & 0x00ff) | ((tmp >> 4) & 0x0700) |
+ ((tmp >> 15) & 0x0800) | ((tmp >> 4) & 0xf000);
+ if (addend & 0x8000)
+ addend |= 0xffff0000;
+ tmp = symvalue + addend;
+ if (ELF_R_TYPE(rel->r_info) == R_ARM_THM_MOVW_ABS_NC ) {
+ if (ELF_ST_TYPE(syminfo) == STT_ARM_TFUNC)
+ tmp |= 1; /* (S + A) | T */
+ tmp &= 0xffff;
+ } else if (ELF_R_TYPE(rel->r_info) == R_ARM_THM_MOVW_ABS_NC ) {
+ tmp >>= 16;
+ }
+
+ *where = (*where & 0xfbf08f00) | (((tmp >> 11) & 0x1) << 26) |
+ (((tmp >> 12) & 0xf) << 16) | (((tmp >> 8) & 0x7) << 12) |
+ (tmp & 0xff);
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: THM_MOVT_ABS/THM_MOVW_ABS_NC %p @ %p in %s\n",
+ (void *)*where, where, rtems_rtl_obj_oname (obj));
+ break;
+ }
+
+
+ /* Encoding of imm argument for BL/B.W Thumb2 instructions
+ * from ARM ARM:
+ *
+ * imm32 := SignExtend(S:I1:I2:imm10:imm11:'0')
+ * I1 = not (j1 eor S); I2 = not (j2 eor S)
+ *
+ * f e d c b a 9 8 7 6 5 4 3 2 1 0 f e d c b a 9 8 7 6 5 4 3 2 1 0
+ * +---------+-+--------------------+---+--+-+--+---------------------+
+ * |1 1 1 1 0|S| imm10 |1 1|J1|1|J2| imm11 |
+ * +---------+-+--------------------+---+--+-+--+---------------------+
+ */
+ case R_TYPE(THM_JUMP24): /* same to THM_CALL; insn b.w */
+ case R_TYPE(THM_CALL): {
+ /*
+ * operation: (S + A) | T - P;
+ * overflow: yes; insn: bl; class: Thumb32 ;result mask: x & 0x01fffffe;
+ */
+ uint32_t sign, i1, i2;
+ uint16_t lower_insn, upper_insn;
+ upper_insn = *(uint16_t *)where;
+ lower_insn = *((uint16_t *)where + 1);
+ printf("upper_insn 0x%04x lower_insn 0x%04x\n", upper_insn, lower_insn);
+ sign = (upper_insn & (1 << 10)) >> 10;
+ i1 = ((lower_insn >> 13) & 1) ^ sign ? 0 : 1;
+ i2 = ((lower_insn >> 11) & 1) ^ sign ? 0 : 1;
+ tmp = (i1 << 23) | (i2 << 22) | ((upper_insn & 0x3ff) << 12) | ((lower_insn & 0x7ff) << 1);
+ addend = (tmp | ((sign ? 0 : 1) << 24)) - (1 << 24);
+
+ tmp = symvalue + addend;
+ if (ELF_ST_TYPE(syminfo) == STT_ARM_TFUNC)
+ tmp |= 1;
+ tmp = tmp - (Elf_Addr)where;
+
+ if (((int32_t)tmp > (int32_t)(1<<24)) || ((int32_t)tmp < (int32_t)(0xff<<24))) {
+ rtems_rtl_set_error (EINVAL, "%s: Overflow %ld "
+ "THM_CALL/THM_JUMP24 relocations",
+ sect->name, (uint32_t) ELF_R_TYPE(rel->r_info));
+ return false;
+ }
+
+ sign = (tmp >> 24) & 1;
+ *(uint16_t *)where = (uint16_t)((upper_insn & 0xf800) | (sign << 10) |
+ ((tmp >> 12) & 0x3ff));
+ *((uint16_t *)where + 1) = (uint16_t)((lower_insn & 0xd000) |
+ ((sign ^ (~(tmp >> 23) & 1)) << 13) |
+ ((sign ^ (~(tmp >> 22) & 1)) << 11) |
+ ((tmp >> 1) & 0x7ff));
+ upper_insn = *(uint16_t *)where;
+ lower_insn = *((uint16_t *)where + 1);
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: THM_CALL/JUMP24 %p @ %p in %s\n",
+ (void *)*where, where, rtems_rtl_obj_oname (obj));
+ break;
+ }
+
+ /* Encoding of imm argument for B<c>.W Thumb2 instructions
+ * from ARM ARM:
+ *
+ * imm32 := SignExtend(S:J2:J1:imm6:imm11:'0')
+ * I1 = not (j1 eor S); I2 = not (j2 eor S)
+ *
+ * f e d c b a 9 8 7 6 5 4 3 2 1 0 f e d c b a 9 8 7 6 5 4 3 2 1 0
+ * +---------+-+-------+-------------+---+--+-+--+---------------------+
+ * |1 1 1 1 0|S| cond | imm6 |1 0|J1|0|J2| imm11 |
+ * +---------+-+-------+-------------+---+--+-+--+---------------------+
+ */
+ case R_TYPE(THM_JUMP19): {
+ /*
+ * operation ((S + A) | T) - P
+ * overflow: yes;class:Thumb32; insn: B<cond>.W; result mask: X & 0x001ffffe
+ */
+ uint32_t sign, j1, j2;
+ uint16_t lower_insn, upper_insn, upper, lower;
+ upper_insn = *(uint16_t *)where;
+ lower_insn = *((uint16_t *)where + 1);
+ printf("upper_insn 0x%04x lower_insn 0x%04x\n", upper_insn, lower_insn);
+ sign = (upper_insn >> 10) & 0x1;
+ upper = upper_insn & 0x3f;
+ if (((upper >> 7) & 0x7) == 0x7) {
+ printf("THM_JUMP19 failed\n");
+ return false; /*if cond <3:1> == '111', see Related codings*/
+ }
+ j1 = (lower_insn >> 13) & 0x1;
+ j2 = (lower_insn >> 11) & 0x1;
+ lower = lower_insn & 0x7ff;
+
+ tmp = ((j2 << 19) | (j1 << 18) | (upper << 12) | (lower << 1));
+ addend = (tmp | ((sign ? 0 : 1) << 20)) - (1 << 20);
+ tmp = symvalue + addend;
+ if (ELF_ST_TYPE(syminfo) == STT_ARM_TFUNC)
+ tmp |= 1;
+ tmp = tmp - (Elf_Addr)where;
+
+ if (((int32_t)tmp > (int32_t)(1<<20)) || ((int32_t)tmp < (int32_t)(0xfff<<20))) {
+ rtems_rtl_set_error (EINVAL, "%s: Overflow %ld "
+ "THM_JUMP19 relocations",
+ sect->name, (uint32_t) ELF_R_TYPE(rel->r_info));
+ return false;
+ }
+ sign = (tmp >> 20) & 0x1;
+ j2 = (tmp >> 19) & 0x1;
+ j1 = (tmp >> 18) & 0x1;
+ *(uint16_t*)where = (upper_insn & 0xfbc0) | (sign << 10) | ((tmp >> 12) & 0x3f);
+ *((uint16_t*)where + 1) = (lower_insn & 0xd000) | (j1 << 13) |
+ (j2 << 11) | ((tmp >> 1) & 0x7ff);
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: THM_JUMP19 %p @ %p in %s\n",
+ (void *)*where, where, rtems_rtl_obj_oname (obj));
+ break;
+ }
+//#endif
+
+ /*--------------End Thumb32-------------*/
default:
printf ("rtl: reloc unknown: sym = %lu, type = %lu, offset = %p, "
"contents = %p\n",
@@ -161,8 +565,7 @@ rtems_rtl_elf_relocate_rel (const rtems_rtl_obj_t* obj,
"in non-PLT relocations",
sect->name, (uint32_t) ELF_R_TYPE(rel->r_info));
return false;
- }
-
+ }
return true;
}
diff --git a/rtl-obj.c b/rtl-obj.c
index ddf4a0b..6f73d2d 100644
--- a/rtl-obj.c
+++ b/rtl-obj.c
@@ -326,9 +326,11 @@ bool
rtems_rtl_match_name (rtems_rtl_obj_t* obj, const char* name)
{
const char* n1 = obj->oname;
+ printf("obj->oname %s, name %s\n", obj->oname, name);
while ((*n1 != '\0') && (*n1 != '\n') && (*n1 != '/') &&
(*name != '\0') && (*name != '/') && (*n1 == *name))
{
+ printf("%c %c\n", *n1, *name);
++n1;
++name;
}
diff --git a/rtl-rap.c b/rtl-rap.c
index efe2362..9722f02 100644
--- a/rtl-rap.c
+++ b/rtl-rap.c
@@ -317,59 +317,61 @@ rtems_rtl_rap_relocate (rtems_rtl_rap_t* rap, rtems_rtl_obj_t* obj)
type = info & 0xff;
- if ((info & (1 << 31)) == 0)
- {
- rtems_rtl_obj_sect_t* symsect;
-
- symsect = rtems_rtl_obj_find_section_by_index (obj, info >> 8);
- if (!symsect)
- {
- free (symname_buffer);
- return false;
- }
-
- symvalue = (Elf_Word) symsect->base + addend;
- }
- else if (rtems_rtl_elf_rel_resolve_sym (type))
- {
- rtems_rtl_obj_sym_t* symbol;
-
- symname_size = (info & ~(3 << 30)) >> 8;
-
- if ((info & (1 << 30)) != 0)
- {
- symname = rap->strtab + symname_size;
- }
- else
- {
- if (symname_size > (SYMNAME_BUFFER_SIZE - 1))
- {
- free (symname_buffer);
- rtems_rtl_set_error (EINVAL, "reloc symbol too big");
- return false;
- }
-
- if (!rtems_rtl_obj_comp_read (rap->decomp, symname_buffer, symname_size))
- {
- free (symname_buffer);
- return false;
- }
-
- symname_buffer[symname_size] = '\0';
- symname = symname_buffer;
- }
-
- symbol = rtems_rtl_symbol_obj_find (obj, symname);
-
- if (!symbol)
- {
- rtems_rtl_set_error (EINVAL, "global symbol not found: %s", symname);
- free (symname_buffer);
- return false;
- }
-
- symvalue = (Elf_Word) symbol->value;
- }
+ if (type != R_ARM_V4BX) { /* V4BX does not have target symbol */
+ if ((info & (1 << 31)) == 0)
+ {
+ rtems_rtl_obj_sect_t* symsect;
+
+ symsect = rtems_rtl_obj_find_section_by_index (obj, info >> 8);
+ if (!symsect)
+ {
+ free (symname_buffer);
+ return false;
+ }
+
+ symvalue = (Elf_Word) symsect->base + addend;
+ }
+ else if (rtems_rtl_elf_rel_resolve_sym (type))
+ {
+ rtems_rtl_obj_sym_t* symbol;
+
+ symname_size = (info & ~(3 << 30)) >> 8;
+
+ if ((info & (1 << 30)) != 0)
+ {
+ symname = rap->strtab + symname_size;
+ }
+ else
+ {
+ if (symname_size > (SYMNAME_BUFFER_SIZE - 1))
+ {
+ free (symname_buffer);
+ rtems_rtl_set_error (EINVAL, "reloc symbol too big");
+ return false;
+ }
+
+ if (!rtems_rtl_obj_comp_read (rap->decomp, symname_buffer, symname_size))
+ {
+ free (symname_buffer);
+ return false;
+ }
+
+ symname_buffer[symname_size] = '\0';
+ symname = symname_buffer;
+ }
+
+ symbol = rtems_rtl_symbol_obj_find (obj, symname);
+
+ if (!symbol)
+ {
+ rtems_rtl_set_error (EINVAL, "global symbol not found: %s", symname);
+ free (symname_buffer);
+ return false;
+ }
+
+ symvalue = (Elf_Word) symbol->value;
+ }
+ }
if (is_rela)
{
@@ -615,6 +617,7 @@ rtems_rtl_rap_file_check (rtems_rtl_obj_t* obj, int fd)
uint32_t compression = 0;
uint32_t checksum = 0;
+ printf("__func__ %s\n", __func__);
rtems_rtl_obj_caches (&header, NULL, NULL);
if (!rtems_rtl_obj_cache_read (header, fd, obj->ooffset,
@@ -639,6 +642,7 @@ rtems_rtl_rap_file_load (rtems_rtl_obj_t* obj, int fd)
uint8_t* rhdr = NULL;
size_t rlen = 64;
int section;
+ printf("__func__ %s\n", __func__);
rtems_rtl_obj_caches (&rap.file, NULL, NULL);
diff --git a/rtl-sym.c b/rtl-sym.c
index 0e29693..2724c49 100644
--- a/rtl-sym.c
+++ b/rtl-sym.c
@@ -86,6 +86,7 @@ rtems_rtl_symbol_global_add (rtems_rtl_obj_t* obj,
const unsigned char* esyms,
unsigned int size)
{
+ printf("%s size %d\n", __func__, size);
rtems_rtl_symbols_t* symbols;
rtems_rtl_obj_sym_t* sym;
size_t count;
@@ -94,21 +95,42 @@ rtems_rtl_symbol_global_add (rtems_rtl_obj_t* obj,
count = 0;
s = 0;
+ int i = 0;
+#if 0
+ for(i = 0; i< 1024; i++) {
+ if (i%32==0)
+ printf("\n");
+ printf("%02x ", *(esyms+i));
+ }
+ printf("\n");
+#endif
while ((s < size) && (esyms[s] != 0))
{
int l = strlen ((char*) &esyms[s]);
+#if 0
+ printf("%d s %d length %d | ", count,s,l);
+ for (i=0; i< l; i++)
+ {
+ printf("%02x ", *(esyms+s+i));
+ }
+#endif
+ //printf("count %d s %d %s\n",count,s, esyms+s);
+
if ((esyms[s + l] != '\0') || ((s + l) > size))
{
rtems_rtl_set_error (EINVAL, "invalid exported symbol table");
return false;
}
++count;
- s += l + sizeof (unsigned long) + 1;
+ //s += l + sizeof (unsigned long) + 1;
+ s += ((l+1+3)&(~3)) + sizeof (unsigned long);
}
/*
* Check this is the correct end of the table.
*/
+ s=(s+4); //align for arm
+#if 0
marker = esyms[s + 1];
marker <<= 8;
marker |= esyms[s + 2];
@@ -116,6 +138,16 @@ rtems_rtl_symbol_global_add (rtems_rtl_obj_t* obj,
marker |= esyms[s + 3];
marker <<= 8;
marker |= esyms[s + 4];
+#endif
+#if 1
+ marker = esyms[s + 0];
+ marker <<= 8;
+ marker |= esyms[s + 1];
+ marker <<= 8;
+ marker |= esyms[s + 2];
+ marker <<= 8;
+ marker |= esyms[s + 3];
+#endif
if (marker != 0xdeadbeefUL)
{
@@ -155,7 +187,8 @@ rtems_rtl_symbol_global_add (rtems_rtl_obj_t* obj,
int b;
sym->name = (const char*) &esyms[s];
- s += strlen (sym->name) + 1;
+ //s += strlen (sym->name) + 1;
+ s += ((strlen(sym->name)+1+3)&(~3));
for (b = 0; b < sizeof (void*); ++b, ++s)
copy_voidp.data[b] = esyms[s];
sym->value = copy_voidp.value;
@@ -208,9 +241,10 @@ rtems_rtl_symbol_obj_find (rtems_rtl_obj_t* obj, const char* name)
* Check the object file's symbols first. If not found search the
* global symbol table.
*/
- for (s = 0, sym = obj->global_table; s < obj->global_syms; ++s, ++sym)
+ for (s = 0, sym = obj->global_table; s < obj->global_syms; ++s, ++sym){
if (strcmp (name, sym->name) == 0)
return sym;
+ }
return rtems_rtl_symbol_global_find (name);
}
diff --git a/rtl.c b/rtl.c
index 9429046..0a542b3 100644
--- a/rtl.c
+++ b/rtl.c
@@ -201,7 +201,9 @@ rtems_rtl_data_init (void)
return false;
}
+ printf("1111\n");
rtl->base = rtems_rtl_obj_alloc ();
+ printf("2222\n");
if (!rtl->base)
{
rtems_rtl_obj_comp_close (&rtl->decomp);
@@ -381,8 +383,10 @@ rtems_rtl_find_obj (const char* name)
while (!rtems_chain_is_tail (&rtl->objects, node))
{
rtems_rtl_obj_t* obj = (rtems_rtl_obj_t*) node;
- if (rtems_rtl_match_name (obj, name))
+ if (rtems_rtl_match_name (obj, name)) {
+ printf("match %s %s\n", obj->oname, name);
return obj;
+ }
node = rtems_chain_next (node);
}
@@ -401,6 +405,7 @@ rtems_rtl_load_object (const char* name, int mode)
* See if the object module has already been loaded.
*/
obj = rtems_rtl_find_obj (name);
+ printf("111 %x\n", obj);
if (!obj)
{
/*
diff --git a/shell-init b/shell-init
index fcc9784..609d61b 100644
--- a/shell-init
+++ b/shell-init
@@ -1,5 +1,5 @@
#rtl-trace set all
-#rtl-trace set load load-sect symbol reloc #unresolved
+rtl-trace set load load-sect symbol reloc #unresolved
#dlo libx.a:xa.c.1.o
#dlo libx.a:x-long-name-to-create-gnu-extension-in-archive.c.1.o
#dlo x.rap
@@ -9,5 +9,5 @@
#dlo c/bsdport.rap
#dlo bsdport.rap
-rap ld ./bsdport.rap
-rap ls
+#rap ld ./test.rap
+#rap ls
diff --git a/wscript b/wscript
old mode 100644
new mode 100755
index 9f9417a..640c777
--- a/wscript
+++ b/wscript
@@ -52,7 +52,8 @@ def build(bld):
bld.defines = ['PACKAGE_VERSION="' + version + '"',
'RTEMS_RTL_ELF_LOADER=1',
'RTEMS_RTL_RAP_LOADER=1']
- bld.cflags = ['-g', '-O']
+ #bld.cflags = ['-g', '-O', '-DRTEMS_RTL_TRACE=1']
+ bld.cflags = ['-g', '-DRTEMS_RTL_TRACE=1']
if re.match('pc[3456]86', bsp) is not None:
bld.defines += ['RTEMS_APP_IDEDISK=1']
@@ -74,6 +75,13 @@ def build(bld):
source = ['xa.c',
'x-long-name-to-create-gnu-extension-in-archive.c'])
+ bld(target = 'x',
+ features = 'c cstlib',
+ includes = bld.includes,
+ defines = bld.defines,
+ source = ['x1.S',
+ 'x2.S']) #freenix
+
#
# The RTL library.
#
@@ -141,11 +149,12 @@ def build(bld):
# finally the second link occurs with the global symbol table to create the
# executable to install.
#
- # Create the root file system for the prelink.
+ # Create the root file system for the prelink format=gnu fanpeng.
+ # rule = 'tar cf - ${SRC} > ${TGT} --format=gnu')
#
bld(target = 'fs-root.tar',
source = ['shell-init', 'libx.a'],
- rule = 'tar cf - ${SRC} > ${TGT}')
+ rule = 'tar --format=ustar -cf ${TGT} ${SRC}')
bld.objects(name = 'rootfs.prelink',
target = 'fs-root-tarfile.o',
source = 'fs-root.tar',
@@ -181,15 +190,24 @@ def build(bld):
source = ['xa.c',
'x-long-name-to-create-gnu-extension-in-archive.c'])
+ bld(target = 'test.rap',
+ features = 'c rap',
+ xxxx = 'hello',
+ rtems_linkflags = ['--base', 'rtld.prelink',
+ '--entry', 'my_main'],
+ source = ['x1.S',
+ 'x2.S']) #freenix
+
if re.match('pc[3456]86', bsp) is not None:
raps = ['bsdport.rap']
else:
raps = []
+ # rule = 'tar cf - ${SRC} > ${TGT}')
bld(target = 'fs-root.tar',
name = 'fs',
- source = ['shell-init', 'libx.a', 'x.rap'] + raps,
- rule = 'tar cf - ${SRC} > ${TGT}')
+ source = ['shell-init', 'libx.a', 'x.rap', 'test.rap'] + raps,
+ rule = 'tar --format=ustar -cf ${TGT} ${SRC} y.rap')
bld.objects(name = 'rootfs',
target = 'fs-root-tarfile.o',
source = 'fs-root.tar',
diff --git a/x1.S b/x1.S
new file mode 100644
index 0000000..b743b9f
--- /dev/null
+++ b/x1.S
@@ -0,0 +1,53 @@
+@ Tests for LDR group relocations.
+
+ .global localsym
+ .global grouptest
+ .type f, %function
+ .type localsym, %function
+ .type grouptest, %function
+
+ .text
+ .macro ldrtest load store sym offset
+
+ \load r0, [r0, #:pc_g0:(\sym \offset)]
+ \load r0, [r0, #:pc_g1:(\sym \offset)]
+ \load r0, [r0, #:pc_g2:(\sym \offset)]
+ \load r0, [r0, #:sb_g0:(\sym \offset)]
+ \load r0, [r0, #:sb_g1:(\sym \offset)]
+ \load r0, [r0, #:sb_g2:(\sym \offset)]
+
+ \store r0, [r0, #:pc_g0:(\sym \offset)]
+ \store r0, [r0, #:pc_g1:(\sym \offset)]
+ \store r0, [r0, #:pc_g2:(\sym \offset)]
+ \store r0, [r0, #:sb_g0:(\sym \offset)]
+ \store r0, [r0, #:sb_g1:(\sym \offset)]
+ \store r0, [r0, #:sb_g2:(\sym \offset)]
+
+
+ .endm
+grouptest:
+@ LDR/STR/LDRB/STRB only have 12 bits available for the magnitude of the addend.
+@ So these should all (just) work.
+ push {lr}
+ nop
+ nop
+ nop
+ ldrtest ldr str f "+ 1024"
+ ldrtest ldrb strb f "+ 1024"
+ ldrtest ldr str f "- 1024"
+ ldrtest ldrb strb f "- 1024"
+
+@ The same as the above, but for a local symbol. These should not be
+@ resolved by the assembler but instead left to the linker.
+
+ ldrtest ldr str localsym "+ 1024"
+ ldrtest ldrb strb localsym "+ 1024"
+ ldrtest ldr str localsym "- 1024"
+ ldrtest ldrb strb localsym "- 1024"
+ mov r0, #0
+ pop {pc}
+
+
+localsym:
+ mov r0, #0
+
diff --git a/x2.S b/x2.S
new file mode 100644
index 0000000..7deb3dc
--- /dev/null
+++ b/x2.S
@@ -0,0 +1,32 @@
+ .global f
+ .global my_main
+ .global rtems
+ .type f, %function
+ .type my_main, %function
+ .type rtems, %function
+ .text
+ .section .text.f,"ax",%progbits
+f:
+ push {lr}
+ ldr r0, =strstr
+ bl printf
+ mov r0, #0
+ pop {pc}
+ nop
+ .word 0x98765432
+ nop
+ b f
+ .section .text.my_main,"ax",%progbits
+ .type my_main, %function
+my_main:
+ b my_main
+ .section .text.my_main,"ax",%progbits
+ .type my_main, %function
+rtems:
+ push {lr}
+ ldr r0, =strstr
+ bl printf
+ mov r0, #0
+ pop {pc}
+strstr:
+ .string "\r\n12345\r\n\0"
diff --git a/xa.c b/xa.c
index 20c927b..db63987 100644
--- a/xa.c
+++ b/xa.c
@@ -3,9 +3,23 @@
#include "x.h"
void hello(void);
+int z_writeln(int argc, const char* argv[]);
void
hello (void)
{
x_writeln ("hello world");
}
+
+int rtems(int argc, const char **argv)
+{
+ hello();
+ printf("rtems\n");
+ z_writeln(argc, argv);
+#if 0
+ *(volatile unsigned int *)0x7F008800 = 0x11110000;
+ *(volatile unsigned int *)0x7F008808 = ~(0xf<<4);
+#endif
+ return 0;
+}
+
--
1.7.10.4
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment