summaryrefslogtreecommitdiff
path: root/ldso/ldso/xtensa/dl-startup.h
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2008-01-05 10:05:27 +0000
committerMike Frysinger <vapier@gentoo.org>2008-01-05 10:05:27 +0000
commit124ec188720b6bdea85ade49e7ea195161b12fce (patch)
tree2bce39bc1e51bd587e010a61419b47d122be3165 /ldso/ldso/xtensa/dl-startup.h
parent9c95d5d28d8d40f7b826c9399f5ce781bbc61567 (diff)
Chris Zankel writes:
The following patches add support for the Xtensa processor architecture to uClibc. They are based on a recent SVN checkout (12/05/2007). The first patch (attached to this post) adds Xtensa support to various shared configuration and make files. The following patches then include the Xtensa specific files and directories. I welcome any feedback and would appreciate it if you could include the patches into the mainline tree. I am certainly committed to maintain the port. Bob Wilson was kind enough to review the patches. Some notes about the architecture: Xtensa is a configurable and extensible processor architecture developed by Tensilica. For more information, please visit: www.linux-xtensa.org.
Diffstat (limited to 'ldso/ldso/xtensa/dl-startup.h')
-rw-r--r--ldso/ldso/xtensa/dl-startup.h106
1 files changed, 106 insertions, 0 deletions
diff --git a/ldso/ldso/xtensa/dl-startup.h b/ldso/ldso/xtensa/dl-startup.h
new file mode 100644
index 000000000..2fd012846
--- /dev/null
+++ b/ldso/ldso/xtensa/dl-startup.h
@@ -0,0 +1,106 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * Xtensa ELF code used by dl-startup.c.
+ *
+ * Copyright (C) 2007 Tensilica Inc.
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ * Parts taken from glibc/sysdeps/xtensa/dl-machine.h.
+ */
+
+__asm__ (
+ " .text\n"
+ " .align 4\n"
+ " .global _start\n"
+ " .type _start, @function\n"
+ "_start:\n"
+ " # Compute load offset in a2: the GOT has not yet been relocated\n"
+ " # but the entries for local symbols contain the relative offsets\n"
+ " # and we can explicitly add the load offset in this code.\n"
+ " _call0 0f\n"
+ " .align 4\n"
+ "0: movi a3, _start+3\n"
+ " sub a2, a0, a3\n"
+ " # Make sure a0 is cleared to mark the top of stack.\n"
+ " movi a0, 0\n"
+ " # user_entry_point = _dl_start(pointer to argument block)\n"
+ " movi a4, _dl_start\n"
+ " mov a6, sp\n"
+ " add a4, a4, a2\n"
+ " callx4 a4\n"
+ " # Save user_entry_point so we can jump to it.\n"
+ " mov a3, a6\n"
+ " l32i a7, sp, 0 # load argc\n"
+ " # Load _dl_skip_args into a4.\n"
+ " movi a4, _dl_skip_args\n"
+ " l32i a4, a4, 0\n"
+ " bnez a4, .Lfixup_stack\n"
+ ".Lfixup_stack_ret:\n"
+ " # Pass finalizer (_dl_fini) in a2 to the user entry point.\n"
+ " movi a2, _dl_fini\n"
+ " # Jump to user's entry point (_start).\n"
+ " jx a3\n"
+ ".Lfixup_stack:\n"
+ " # argc -= _dl_skip_args (with argc @ sp+0)\n"
+ " sub a7, a7, a4\n"
+ " s32i a7, sp, 0\n"
+ " # Shift everything by _dl_skip_args.\n"
+ " addi a5, sp, 4 # a5 = destination ptr = argv\n"
+ " add a4, a5, a4 # a4 = source ptr = argv + _dl_skip_args\n"
+ " # Shift argv.\n"
+ "1: l32i a6, a4, 0\n"
+ " addi a4, a4, 4\n"
+ " s32i a6, a5, 0\n"
+ " addi a5, a5, 4\n"
+ " bnez a6, 1b\n"
+ " # Shift envp.\n"
+ "2: l32i a6, a4, 0\n"
+ " addi a4, a4, 4\n"
+ " s32i a6, a5, 0\n"
+ " addi a5, a5, 4\n"
+ " bnez a6, 2b\n"
+ " # Shift auxiliary table.\n"
+ "3: l32i a6, a4, 0\n"
+ " l32i a8, a4, 4\n"
+ " addi a4, a4, 8\n"
+ " s32i a6, a5, 0\n"
+ " s32i a8, a5, 4\n"
+ " addi a5, a5, 8\n"
+ " bnez a6, 3b\n"
+ " j .Lfixup_stack_ret");
+
+/* Get a pointer to the argv value. */
+#define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long *) ARGS) + 1)
+
+/* Function calls are not safe until the GOT relocations have been done. */
+#define NO_FUNCS_BEFORE_BOOTSTRAP
+
+#define PERFORM_BOOTSTRAP_GOT(tpnt) \
+do { \
+ xtensa_got_location *got_loc; \
+ unsigned long l_addr = tpnt->loadaddr; \
+ Elf32_Word relative_count; \
+ unsigned long rel_addr; \
+ int x; \
+\
+ got_loc = (xtensa_got_location *) \
+ (tpnt->dynamic_info[DT_XTENSA (GOT_LOC_OFF)] + l_addr); \
+\
+ for (x = 0; x < tpnt->dynamic_info[DT_XTENSA (GOT_LOC_SZ)]; x++) { \
+ Elf32_Addr got_start, got_end; \
+ got_start = got_loc[x].offset & ~(PAGE_SIZE - 1); \
+ got_end = ((got_loc[x].offset + got_loc[x].length + PAGE_SIZE - 1) \
+ & ~(PAGE_SIZE - 1)); \
+ _dl_mprotect ((void *)(got_start + l_addr), got_end - got_start, \
+ PROT_READ | PROT_WRITE | PROT_EXEC); \
+ } \
+\
+ /* The following is a stripped down version of the code following \
+ the invocation of PERFORM_BOOTSTRAP_GOT in dl-startup.c. That \
+ code is skipped when PERFORM_BOOTSTRAP_GOT is defined, so it has \
+ to be done here instead. */ \
+ relative_count = tpnt->dynamic_info[DT_RELCONT_IDX]; \
+ rel_addr = tpnt->dynamic_info[DT_RELOC_TABLE_ADDR]; \
+ if (rel_addr) \
+ elf_machine_relative(load_addr, rel_addr, relative_count); \
+} while (0)