summaryrefslogtreecommitdiff
path: root/ldso/ldso/frv/dl-syscalls.h
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>2004-02-18 08:04:51 +0000
committerEric Andersen <andersen@codepoet.org>2004-02-18 08:04:51 +0000
commitbaa67289df42b1b994092b8312148a6f9e172274 (patch)
tree9a6a60a10a0db9879671cd923e7307c993cfbd40 /ldso/ldso/frv/dl-syscalls.h
parent377c7157a8802c289c5560f1a2ecd1030d571e7d (diff)
Alexandre Oliva writes:
This patch adds code to uClibc to support a new ABI designed for the FR-V architecture, that enables text segments of executables and shared libraries to be shared by multiple processes on an OS such as uClinux, that can run on FR-V processors without an MMU. Patches for binutils and GCC have just been posted in the corresponding mailing lists. The binutils patch was approved, but there's one additional patch pending review, that I posted this week. An updated GCC patch will be posted to gcc-patches@gcc.gnu.org as soon as I complete testing (I used a known-good compiler to test the uClibc patch below). Since the existing dynamic loader code didn't support independent relocation of segments, it required changes that were somewhat extensive. I've added a number of new machine-specific macros to try to keep the platform and ABI-specific details outside the generic code. I hope this is not a problem.
Diffstat (limited to 'ldso/ldso/frv/dl-syscalls.h')
-rw-r--r--ldso/ldso/frv/dl-syscalls.h191
1 files changed, 191 insertions, 0 deletions
diff --git a/ldso/ldso/frv/dl-syscalls.h b/ldso/ldso/frv/dl-syscalls.h
new file mode 100644
index 000000000..bef4f1720
--- /dev/null
+++ b/ldso/ldso/frv/dl-syscalls.h
@@ -0,0 +1,191 @@
+/* Copyright (C) 2003 Red Hat, Inc.
+ Contributed by Alexandre Oliva <aoliva@redhat.com>
+
+This file is part of uClibc.
+
+uClibc is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation; either version 2.1 of the
+License, or (at your option) any later version.
+
+uClibc is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with uClibc; see the file COPYING.LIB. If not, write to
+the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
+USA. */
+
+/* Define the __set_errno macro as nothing so that INLINE_SYSCALL
+ * won't set errno, which is important since we make system calls
+ * before the errno symbol is dynamicly linked. */
+
+#define __set_errno(X) {(void)(X);}
+#include "sys/syscall.h"
+#include <sys/mman.h>
+
+/* The code below is extracted from libc/sysdeps/linux/frv/_mmap.c */
+
+#define __NR___syscall_mmap2 __NR_mmap2
+static inline _syscall6(__ptr_t, __syscall_mmap2, __ptr_t, addr,
+ size_t, len, int, prot, int, flags, int, fd, off_t, offset);
+
+/* This is always 12, even on architectures where PAGE_SHIFT != 12. */
+# ifndef MMAP2_PAGE_SHIFT
+# define MMAP2_PAGE_SHIFT 12
+# endif
+
+#if DYNAMIC_LOADER_IN_SIMULATOR
+#include <asm/page.h> /* for PAGE_SIZE */
+inline static void *_dl_memset(void*,int,size_t);
+inline static ssize_t _dl_pread(int fd, void *buf, size_t count, off_t offset);
+#endif
+
+#ifndef DYNAMIC_LOADER_IN_SIMULATOR
+inline
+#endif
+static __ptr_t
+_dl_mmap(__ptr_t addr, size_t len, int prot, int flags, int fd, __off_t offset)
+{
+#ifdef DYNAMIC_LOADER_IN_SIMULATOR
+ size_t plen = (len + PAGE_SIZE - 1) & -PAGE_SIZE;
+
+/* This is a hack to enable the dynamic loader to run within a
+ simulator that doesn't support mmap, with a number of very ugly
+ tricks. Also, it's not as useful as it sounds, since only dynamic
+ executables without DT_NEEDED dependencies can be run. AFAIK, they
+ can only be created with -pie. This trick suffices to enable the
+ dynamic loader to obtain a blank page that it maps early in the
+ bootstrap. */
+ if ((flags & MAP_FIXED) == 0)
+ {
+ void *_dl_mmap_base = 0;
+ __ptr_t *ret = 0;
+
+ if (! _dl_mmap_base)
+ {
+ void *stack;
+ asm ("mov sp, %0" : "=r" (stack));
+ _dl_mmap_base = (void *)(((long)stack + 2 * PAGE_SIZE) & -PAGE_SIZE);
+ retry:
+ if (((void **)_dl_mmap_base)[0] == _dl_mmap_base
+ && ((void **)_dl_mmap_base)[1023] == _dl_mmap_base
+ && (((void **)_dl_mmap_base)[177]
+ == ((void **)_dl_mmap_base)[771]))
+ {
+ while (((void**)_dl_mmap_base)[177])
+ {
+ _dl_mmap_base = ((void**)_dl_mmap_base)[177];
+ if (!(((void **)_dl_mmap_base)[0] == _dl_mmap_base
+ && ((void **)_dl_mmap_base)[1023] == _dl_mmap_base
+ && (((void **)_dl_mmap_base)[177]
+ == ((void**)_dl_mmap_base)[771])))
+ ((void(*)())0)();
+ }
+ }
+ else
+ {
+ int i;
+ for (i = 0; i < (int)PAGE_SIZE; i++)
+ if (*(char*)(_dl_mmap_base + i))
+ break;
+ if (i != PAGE_SIZE)
+ {
+ _dl_mmap_base = (void*)((long)_dl_mmap_base + PAGE_SIZE);
+ goto retry;
+ }
+ ((void**)_dl_mmap_base)[-1] =
+ ((void**)_dl_mmap_base)[0] =
+ ((void**)_dl_mmap_base)[1023] =
+ _dl_mmap_base;
+ }
+ }
+
+ if (_dl_mmap_base)
+ {
+ if (!(((void **)_dl_mmap_base)[0] == _dl_mmap_base
+ && ((void **)_dl_mmap_base)[1023] == _dl_mmap_base
+ && (((void **)_dl_mmap_base)[177]
+ == ((void**)_dl_mmap_base)[771])))
+ ((void(*)())0)();
+ ret = (__ptr_t)((char*)_dl_mmap_base + PAGE_SIZE);
+ _dl_mmap_base =
+ ((void**)_dl_mmap_base)[177] =
+ ((void**)_dl_mmap_base)[771] =
+ (char*)_dl_mmap_base + plen + PAGE_SIZE;
+ ((void**)_dl_mmap_base)[0] =
+ ((void**)_dl_mmap_base)[1023] =
+ _dl_mmap_base;
+ }
+
+ if ((flags & MAP_ANONYMOUS) != 0)
+ {
+ _dl_memset (ret, 0, plen);
+ return ret;
+ }
+
+ flags |= MAP_FIXED;
+ addr = ret;
+ }
+#endif
+ if (offset & ((1 << MMAP2_PAGE_SHIFT) - 1)) {
+#if 0
+ __set_errno (EINVAL);
+#endif
+ return MAP_FAILED;
+ }
+#ifdef DYNAMIC_LOADER_IN_SIMULATOR
+ if ((flags & MAP_FIXED) != 0)
+ {
+ if (_dl_pread(fd, addr, len, offset) != (ssize_t)len)
+ return (void*)MAP_FAILED;
+ if (plen != len)
+ _dl_memset (addr + len, 0, plen - len);
+ return addr;
+ }
+#endif
+ return(__syscall_mmap2(addr, len, prot, flags, fd, (off_t) (offset >> MMAP2_PAGE_SHIFT)));
+}
+
+#ifdef __NR_pread
+#ifdef DYNAMIC_LOADER_IN_SIMULATOR
+#include <unistd.h>
+
+#define __NR___syscall_lseek __NR_lseek
+inline static unsigned long _dl_read(int fd, const void *buf, unsigned long count);
+
+inline static _syscall3(__off_t, __syscall_lseek, int, fd, __off_t, offset,
+ int, whence);
+inline static ssize_t
+_dl_pread(int fd, void *buf, size_t count, off_t offset)
+{
+ __off_t orig = __syscall_lseek (fd, 0, SEEK_CUR);
+ ssize_t ret;
+
+ if (orig == -1)
+ return -1;
+
+ if (__syscall_lseek (fd, offset, SEEK_SET) != offset)
+ return -1;
+
+ ret = _dl_read (fd, buf, count);
+
+ if (__syscall_lseek (fd, orig, SEEK_SET) != orig)
+ ((void(*)())0)();
+
+ return ret;
+}
+#else
+#define __NR___syscall_pread __NR_pread
+inline static _syscall5(ssize_t, __syscall_pread, int, fd, void *, buf,
+ size_t, count, off_t, offset_hi, off_t, offset_lo);
+
+inline static ssize_t
+_dl_pread(int fd, void *buf, size_t count, off_t offset)
+{
+ return(__syscall_pread(fd,buf,count,__LONG_LONG_PAIR (offset >> 31, offset)));
+}
+#endif
+#endif