summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Rules.mak14
-rw-r--r--extra/Configs/Config.frv32
-rw-r--r--extra/Configs/Config.frv.default140
-rw-r--r--extra/Configs/Config.in7
-rw-r--r--include/elf.h16
-rw-r--r--ldso/ldso/frv/dl-startup.h89
-rw-r--r--ldso/ldso/frv/dl-syscalls.h191
-rw-r--r--ldso/ldso/frv/dl-sysdep.h628
-rw-r--r--ldso/ldso/frv/elfinterp.c495
-rw-r--r--ldso/ldso/frv/resolve.S71
-rw-r--r--libc/sysdeps/linux/frv/Makefile89
-rw-r--r--libc/sysdeps/linux/frv/__init_brk.c25
-rw-r--r--libc/sysdeps/linux/frv/__longjmp.S75
-rw-r--r--libc/sysdeps/linux/frv/_mmap.c48
-rw-r--r--libc/sysdeps/linux/frv/bits/elf-fdpic.h104
-rw-r--r--libc/sysdeps/linux/frv/bits/endian.h7
-rw-r--r--libc/sysdeps/linux/frv/bits/fcntl.h156
-rw-r--r--libc/sysdeps/linux/frv/bits/kernel_stat.h57
-rw-r--r--libc/sysdeps/linux/frv/bits/kernel_types.h43
-rw-r--r--libc/sysdeps/linux/frv/bits/mman.h75
-rw-r--r--libc/sysdeps/linux/frv/bits/setjmp.h53
-rw-r--r--libc/sysdeps/linux/frv/bits/stackinfo.h28
-rw-r--r--libc/sysdeps/linux/frv/bits/syscalls.h129
-rw-r--r--libc/sysdeps/linux/frv/bits/wordsize.h19
-rw-r--r--libc/sysdeps/linux/frv/brk.c22
-rw-r--r--libc/sysdeps/linux/frv/clone.S83
-rw-r--r--libc/sysdeps/linux/frv/crt0.S110
-rw-r--r--libc/sysdeps/linux/frv/crti.S41
-rw-r--r--libc/sysdeps/linux/frv/crtn.S35
-rw-r--r--libc/sysdeps/linux/frv/crtreloc.c118
-rw-r--r--libc/sysdeps/linux/frv/dl-iterate-phdr.c43
-rw-r--r--libc/sysdeps/linux/frv/sbrk.c25
-rw-r--r--libc/sysdeps/linux/frv/setjmp.S95
-rw-r--r--libc/sysdeps/linux/frv/sys/procfs.h125
-rw-r--r--libc/sysdeps/linux/frv/sys/ptrace.h139
-rw-r--r--libc/sysdeps/linux/frv/sys/ucontext.h451
-rw-r--r--libc/sysdeps/linux/frv/sysdep.c27
-rw-r--r--libc/sysdeps/linux/frv/vfork.S44
-rw-r--r--libpthread/linuxthreads/sysdeps/frv/pt-machine.h48
39 files changed, 3996 insertions, 1 deletions
diff --git a/Rules.mak b/Rules.mak
index 15c593abc..6a1b235e4 100644
--- a/Rules.mak
+++ b/Rules.mak
@@ -170,6 +170,20 @@ ifeq ($(strip $(TARGET_ARCH)),cris)
PICFLAG=-fpic
endif
+ifeq ($(strip $(TARGET_ARCH)),frv)
+ CPU_LDFLAGS-$(CONFIG_FRV)+=-melf32frvfd
+ CPU_CFLAGS-$(CONFIG_FRV)+=-mfdpic
+ PICFLAG=-fPIC -DPIC
+ PIEFLAG=-fpie
+ # Using -pie causes the program to have an interpreter, which is
+ # forbidden, so we must make do with -shared. Unfortunately,
+ # -shared by itself would get us global function descriptors
+ # and calls through PLTs, dynamic resolution of symbols, etc,
+ # which would break as well, but -Bsymbolic comes to the rescue.
+ LDPIEFLAG=-shared -Bsymbolic
+ UCLIBC_LDSO=ld.so.1
+endif
+
# Use '-Os' optimization if available, else use -O2, allow Config to override
OPTIMIZATION+=$(call check_gcc,-Os,-O2)
# Use the gcc 3.4 -funit-at-a-time optimization when available
diff --git a/extra/Configs/Config.frv b/extra/Configs/Config.frv
new file mode 100644
index 000000000..1210ad92f
--- /dev/null
+++ b/extra/Configs/Config.frv
@@ -0,0 +1,32 @@
+#
+# For a description of the syntax of this configuration file,
+# see extra/config/Kconfig-language.txt
+#
+
+config HAVE_ELF
+ bool
+ select HAS_FPU
+ select ARCH_BIG_ENDIAN
+ select ARCH_HAS_NO_MMU
+ default y
+
+config TARGET_ARCH
+ string
+ default "frv"
+
+config ARCH_CFLAGS
+ string
+
+config ARCH_LDFLAGS
+ string
+
+config LIBGCC_CFLAGS
+ string
+
+config HAVE_DOT_HIDDEN
+ bool
+ default y
+
+config UCLIBC_COMPLETELY_PIC
+ bool
+ default y
diff --git a/extra/Configs/Config.frv.default b/extra/Configs/Config.frv.default
new file mode 100644
index 000000000..4fd945d6d
--- /dev/null
+++ b/extra/Configs/Config.frv.default
@@ -0,0 +1,140 @@
+#
+# Automatically generated make config: don't edit
+#
+# TARGET_alpha is not set
+# TARGET_arm is not set
+# TARGET_cris is not set
+# TARGET_e1 is not set
+TARGET_frv=y
+# TARGET_h8300 is not set
+# TARGET_i386 is not set
+# TARGET_i960 is not set
+# TARGET_m68k is not set
+# TARGET_microblaze is not set
+# TARGET_mips is not set
+# TARGET_powerpc is not set
+# TARGET_sh is not set
+# TARGET_sparc is not set
+# TARGET_v850 is not set
+
+#
+# Target Architecture Features and Options
+#
+HAVE_ELF=y
+TARGET_ARCH="frv"
+HAVE_DOT_HIDDEN=y
+UCLIBC_COMPLETELY_PIC=y
+# ARCH_LITTLE_ENDIAN is not set
+# ARCH_BIG_ENDIAN is not set
+ARCH_HAS_NO_MMU=y
+UCLIBC_HAS_FLOATS=y
+HAS_FPU=y
+DO_C99_MATH=y
+WARNINGS="-Wall"
+KERNEL_SOURCE="$(FRV_KERNEL_DIR)"
+UCLIBC_UCLINUX_BROKEN_MUNMAP=y
+EXCLUDE_BRK=y
+C_SYMBOL_PREFIX=""
+HAVE_DOT_CONFIG=y
+
+#
+# General Library Settings
+#
+# HAVE_NO_PIC is not set
+DOPIC=y
+# HAVE_NO_SHARED is not set
+HAVE_SHARED=y
+# ARCH_HAS_NO_LDSO is not set
+BUILD_UCLIBC_LDSO=y
+FORCE_SHAREABLE_TEXT_SEGMENTS=y
+UCLIBC_PIE_SUPPORT=y
+LDSO_LDD_SUPPORT=y
+UCLIBC_CTOR_DTOR=y
+# UCLIBC_PROPOLICE is not set
+# UCLIBC_PROFILING is not set
+# HAS_NO_THREADS is not set
+UCLIBC_HAS_THREADS=y
+PTHREADS_DEBUG_SUPPORT=y
+UCLIBC_HAS_LFS=y
+MALLOC=y
+# MALLOC_SIMPLE is not set
+# MALLOC_STANDARD is not set
+# MALLOC_GLIBC_COMPAT is not set
+# UCLIBC_DYNAMIC_ATEXIT is not set
+HAS_SHADOW=y
+UNIX98PTY_ONLY=y
+ASSUME_DEVPTS=y
+# UCLIBC_HAS_TM_EXTENSIONS is not set
+UCLIBC_HAS_TZ_CACHING=y
+UCLIBC_HAS_TZ_FILE=y
+UCLIBC_HAS_TZ_FILE_READ_MANY=y
+UCLIBC_TZ_FILE_PATH="/etc/TZ"
+
+#
+# Networking Support
+#
+UCLIBC_HAS_IPV6=y
+UCLIBC_HAS_RPC=y
+UCLIBC_HAS_FULL_RPC=y
+
+#
+# String and Stdio Support
+#
+UCLIBC_HAS_CTYPE_TABLES=y
+UCLIBC_HAS_CTYPE_SIGNED=y
+# UCLIBC_HAS_CTYPE_UNSAFE is not set
+UCLIBC_HAS_CTYPE_CHECKED=y
+# UCLIBC_HAS_CTYPE_ENFORCED is not set
+UCLIBC_HAS_WCHAR=y
+# UCLIBC_HAS_LOCALE is not set
+# UCLIBC_HAS_HEXADECIMAL_FLOATS is not set
+UCLIBC_HAS_GLIBC_CUSTOM_PRINTF=y
+UCLIBC_PRINTF_SCANF_POSITIONAL_ARGS=9
+# UCLIBC_HAS_SCANF_GLIBC_A_FLAG is not set
+# UCLIBC_HAS_STDIO_BUFSIZ_NONE is not set
+# UCLIBC_HAS_STDIO_BUFSIZ_256 is not set
+# UCLIBC_HAS_STDIO_BUFSIZ_512 is not set
+# UCLIBC_HAS_STDIO_BUFSIZ_1024 is not set
+# UCLIBC_HAS_STDIO_BUFSIZ_2048 is not set
+# UCLIBC_HAS_STDIO_BUFSIZ_4096 is not set
+UCLIBC_HAS_STDIO_BUFSIZ_8192=y
+UCLIBC_HAS_STDIO_BUILTIN_BUFFER_NONE=y
+# UCLIBC_HAS_STDIO_BUILTIN_BUFFER_4 is not set
+# UCLIBC_HAS_STDIO_BUILTIN_BUFFER_8 is not set
+UCLIBC_HAS_STDIO_GETC_MACRO=y
+UCLIBC_HAS_STDIO_PUTC_MACRO=y
+UCLIBC_HAS_STDIO_AUTO_RW_TRANSITION=y
+# UCLIBC_HAS_FOPEN_LARGEFILE_MODE is not set
+# UCLIBC_HAS_FOPEN_EXCLUSIVE_MODE is not set
+# UCLIBC_HAS_GLIBC_CUSTOM_STREAMS is not set
+# UCLIBC_HAS_PRINTF_M_SPEC is not set
+UCLIBC_HAS_ERRNO_MESSAGES=y
+UCLIBC_HAS_SYS_ERRLIST=y
+UCLIBC_HAS_SIGNUM_MESSAGES=y
+UCLIBC_HAS_SYS_SIGLIST=y
+UCLIBC_HAS_GNU_GETOPT=y
+
+#
+# Big and Tall
+#
+UCLIBC_HAS_REGEX=y
+# UCLIBC_HAS_WORDEXP is not set
+# UCLIBC_HAS_FTW is not set
+UCLIBC_HAS_GLOB=y
+
+#
+# Library Installation Options
+#
+SHARED_LIB_LOADER_PREFIX="/lib"
+RUNTIME_PREFIX="/"
+DEVEL_PREFIX="/usr/"
+
+#
+# uClibc development/debugging options
+#
+# DODEBUG is not set
+DOASSERTS=y
+SUPPORT_LD_DEBUG=y
+# SUPPORT_LD_DEBUG_EARLY is not set
+UCLIBC_MALLOC_DEBUGGING=y
+# UCLIBC_MJN3_ONLY is not set
diff --git a/extra/Configs/Config.in b/extra/Configs/Config.in
index 8ad0073c3..4f15ea021 100644
--- a/extra/Configs/Config.in
+++ b/extra/Configs/Config.in
@@ -23,6 +23,9 @@ config TARGET_cris
config TARGET_e1
bool "e1"
+config TARGET_frv
+ bool "frv"
+
config TARGET_h8300
bool "h8300"
@@ -74,6 +77,10 @@ if TARGET_e1
source "extra/Configs/Config.e1"
endif
+if TARGET_frv
+source "extra/Configs/Config.frv"
+endif
+
if TARGET_h8300
source "extra/Configs/Config.h8300"
endif
diff --git a/include/elf.h b/include/elf.h
index b4de42e0d..e2264bd6c 100644
--- a/include/elf.h
+++ b/include/elf.h
@@ -1,5 +1,5 @@
/* This file defines standard ELF types, structures, and macros.
- Copyright (C) 1995-1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+ Copyright (C) 1995-1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -254,6 +254,9 @@ typedef struct
pick large random numbers (0x8523, 0xa7f2, etc.) to minimize the
chances of collision with official or non-GNU unofficial values. */
+/* Fujitsu FR-V. */
+#define EM_CYGNUS_FRV 0x5441
+
#define EM_ALPHA 0x9026
/* V850 backend magic number. Written in the absense of an ABI. */
@@ -1116,6 +1119,17 @@ typedef struct
/* Keep this the last entry. */
#define R_386_NUM 38
+/* FR-V specific definitions. */
+#define R_FRV_NONE 0 /* No reloc. */
+#define R_FRV_32 1 /* Direct 32 bit. */
+/* Canonical function descriptor address. */
+#define R_FRV_FUNCDESC 14
+/* Private function descriptor initialization. */
+#define R_FRV_FUNCDESC_VALUE 18
+
+#define EF_FRV_PIC 0x00000100
+#define EF_FRV_FDPIC 0x00008000
+
/* SUN SPARC specific definitions. */
/* Legal values for ST_TYPE subfield of st_info (symbol type). */
diff --git a/ldso/ldso/frv/dl-startup.h b/ldso/ldso/frv/dl-startup.h
new file mode 100644
index 000000000..017efc0ad
--- /dev/null
+++ b/ldso/ldso/frv/dl-startup.h
@@ -0,0 +1,89 @@
+ /* 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. */
+
+/* Any assembly language/system dependent hacks needed to setup
+ * boot1.c so it will work as expected and cope with whatever platform
+ * specific wierdness is needed for this architecture.
+
+ * We override the default _dl_boot function, and replace it with a
+ * bit of asm. Then call the real _dl_boot function, which is now
+ * named _dl_boot2. */
+
+/* At program start-up, gr16 contains a pointer to a
+ elf32_fdpic_loadmap that describes how the executable was loaded
+ into memory. gr17 contains a pointer to the interpreter (our!)
+ loadmap, if there is an interpreter, or 0 if we're being run as an
+ executable. gr18 holds a pointer to the interpreter's dynamic
+ section, if there is an interpreter, or to the executable's dynamic
+ section, otherwise. If the executable is not dynamic, gr18 is 0.
+
+ We rely on the fact that the linker adds a pointer to the
+ _GLOBAL_OFFSET_TABLE_ as the last ROFIXUP entry, and that
+ __self_reloc returns the relocated pointer to us, so that we can
+ use this value to initialize the PIC register. */
+
+asm("" \
+" .text\n" \
+" .global _dl_boot\n" \
+" .type _dl_boot,@function\n" \
+"_dl_boot:\n" \
+" call .Lcall\n" \
+".Lcall:\n" \
+" movsg lr, gr4\n" \
+" sethi.p #gprelhi(.Lcall), gr5\n"\
+" setlo #gprello(.Lcall), gr5\n"\
+" mov.p gr17, gr8\n" \
+" cmp gr17, gr0, icc0\n" \
+" sub.p gr4, gr5, gr4\n" \
+" ckeq icc0, cc4\n" \
+" cmov.p gr16, gr8, cc4, 1\n" \
+" sethi #gprelhi(__ROFIXUP_LIST__), gr9\n" \
+" sethi.p #gprelhi(__ROFIXUP_END__), gr10\n" \
+" setlo #gprello(__ROFIXUP_LIST__), gr9\n" \
+" setlo.p #gprello(__ROFIXUP_END__), gr10\n" \
+" add gr9, gr4, gr9\n" \
+" add.p gr10, gr4, gr10\n" \
+" call __self_reloc\n" \
+" mov.p gr8, gr15\n" \
+" mov gr16, gr9\n" \
+" mov.p gr17, gr10\n" \
+" mov gr18, gr11\n" \
+" addi.p sp, #4, gr13\n" \
+" addi sp, #-8, sp\n" \
+" mov.p sp, gr12\n" \
+" call _dl_boot2\n" \
+" ldd.p @(sp, gr0), gr14\n" \
+" addi sp, #8, sp\n" \
+" movgs gr0, lr\n" \
+" jmpl @(gr14, gr0)\n" \
+" .size _dl_boot,.-_dl_boot\n" \
+);
+
+#define _dl_boot _dl_boot2
+#define DL_BOOT(X) \
+static void __attribute__ ((used)) \
+_dl_boot (void *dl_boot_got_pointer, \
+ struct elf32_fdpic_loadmap *dl_boot_progmap, \
+ struct elf32_fdpic_loadmap *dl_boot_ldsomap, \
+ Elf32_Dyn *dl_boot_ldso_dyn_pointer, \
+ struct funcdesc_value *dl_main_funcdesc, \
+ X)
+
+struct elf32_fdpic_loadmap;
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
diff --git a/ldso/ldso/frv/dl-sysdep.h b/ldso/ldso/frv/dl-sysdep.h
new file mode 100644
index 000000000..ab3b09cd1
--- /dev/null
+++ b/ldso/ldso/frv/dl-sysdep.h
@@ -0,0 +1,628 @@
+ /* Copyright (C) 2003, 2004 Red Hat, Inc.
+ Contributed by Alexandre Oliva <aoliva@redhat.com>
+ Based on ../i386/dl-sysdep.h
+
+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. */
+
+/*
+ * Various assembly language/system dependent hacks that are required
+ * so that we can minimize the amount of platform specific code.
+ */
+
+/*
+ * Define this if the system uses RELOCA.
+ */
+#undef ELF_USES_RELOCA
+
+/*
+ * Get a pointer to the argv array. On many platforms this can be just
+ * the address if the first argument, on other platforms we need to
+ * do something a little more subtle here.
+ */
+#define GET_ARGV(ARGVP, ARGS) ARGVP = ((unsigned long*) ARGS)
+
+/*
+ * Compute the GOT address. On several platforms, we use assembly
+ * here. on FR-V FDPIC, there's no way to compute the GOT address,
+ * since the offset between text and data is not fixed, so we arrange
+ * for the assembly _dl_boot to pass this value as an argument to
+ * _dl_boot. */
+#define DL_BOOT_COMPUTE_GOT(got) ((got) = dl_boot_got_pointer)
+
+#define DL_BOOT_COMPUTE_DYN(dpnt, got, load_addr) \
+ ((dpnt) = dl_boot_ldso_dyn_pointer)
+
+/*
+ * Initialization sequence for a GOT. Copy the resolver function
+ * descriptor and the pointer to the elf_resolve/link_map data
+ * structure. Initialize the got_value in the module while at that.
+ */
+#define INIT_GOT(GOT_BASE,MODULE) \
+{ \
+ (MODULE)->loadaddr.got_value = (GOT_BASE); \
+ GOT_BASE[0] = ((unsigned long *)&_dl_linux_resolve)[0]; \
+ GOT_BASE[1] = ((unsigned long *)&_dl_linux_resolve)[1]; \
+ GOT_BASE[2] = (unsigned long) MODULE; \
+}
+
+/*
+ * Here is a macro to perform a relocation. This is only used when
+ * bootstrapping the dynamic loader. RELP is the relocation that we
+ * are performing, REL is the pointer to the address we are relocating.
+ * SYMBOL is the symbol involved in the relocation, and LOAD is the
+ * load address.
+ */
+#define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD,SYMTAB) \
+ switch(ELF32_R_TYPE((RELP)->r_info)){ \
+ case R_FRV_32: \
+ *(REL) += (SYMBOL); \
+ break; \
+ case R_FRV_FUNCDESC_VALUE: \
+ { \
+ struct funcdesc_value fv = { \
+ (void*)((SYMBOL) + *(REL)), \
+ (LOAD).got_value \
+ }; \
+ *(struct funcdesc_value volatile *)(REL) = fv; \
+ break; \
+ } \
+ default: \
+ _dl_exit(1); \
+ }
+
+/*
+ * Transfer control to the user's application, once the dynamic loader
+ * is done. We return the address of the function's entry point to
+ * _dl_boot, see boot1_arch.h.
+ */
+#define START() do { \
+ struct elf_resolve *exec_mod = _dl_loaded_modules; \
+ dl_main_funcdesc->entry_point = _dl_elf_main; \
+ while (exec_mod->libtype != elf_executable) \
+ exec_mod = exec_mod->next; \
+ dl_main_funcdesc->got_value = exec_mod->loadaddr.got_value; \
+ /* _dl_dprintf(2, "entry point is (%x,%x)\n", dl_main_funcdesc->entry_point, dl_main_funcdesc->got_value); */ \
+ return; \
+} while (0)
+
+
+
+/* Here we define the magic numbers that this dynamic loader should accept */
+
+#define MAGIC1 EM_CYGNUS_FRV
+#undef MAGIC2
+/* Used for error messages */
+#define ELF_TARGET "FR-V"
+
+struct elf_resolve;
+
+struct funcdesc_value
+{
+ void *entry_point;
+ void *got_value;
+} __attribute__((__aligned__(8)));
+
+
+extern int _dl_linux_resolve(void) __attribute__((__visibility__("hidden")));
+
+#define do_rem(result, n, base) result = (n % base)
+
+/* 4096 bytes alignment */
+#define PAGE_ALIGN 0xfffff000
+#define ADDR_ALIGN 0xfff
+#define OFFS_ALIGN 0x7ffff000
+
+struct funcdesc_ht;
+
+/* We must force strings used early in the bootstrap into the data
+ segment, such that they are referenced with GOTOFF instead of
+ GPREL, because GPREL needs the GOT to have already been
+ relocated. */
+#define SEND_EARLY_STDERR(S) \
+ do { static char __s[] = (S); SEND_STDERR (__s); } while (0)
+
+#include <bits/elf-fdpic.h>
+#ifdef __USE_GNU
+# include <link.h>
+#else
+# define __USE_GNU
+# include <link.h>
+# undef __USE_GNU
+#endif
+#include <dl-syscall.h>
+#include <dl-string.h>
+
+/* These are declared in ldso.h, after it includes dl-elf.h that
+ includes ourselves. */
+extern void *_dl_malloc(int size);
+extern void _dl_free(void *);
+extern void _dl_dprintf(int, const char *, ...);
+
+
+#ifndef _dl_assert
+# define _dl_assert(expr)
+#endif
+
+/* Initialize a DL_LOADADDR_TYPE given a got pointer and a complete
+ load map. */
+inline static void
+__dl_init_loadaddr_map (struct elf32_fdpic_loadaddr *loadaddr, void *got_value,
+ struct elf32_fdpic_loadmap *map)
+{
+ if (map->version != 0)
+ {
+ SEND_EARLY_STDERR ("Invalid loadmap version number\n");
+ _dl_exit(-1);
+ }
+ if (map->nsegs == 0)
+ {
+ SEND_EARLY_STDERR ("Invalid segment count in loadmap\n");
+ _dl_exit(-1);
+ }
+ loadaddr->got_value = got_value;
+ loadaddr->map = map;
+}
+
+/* Figure out how many LOAD segments there are in the given headers,
+ and allocate a block for the load map big enough for them.
+ got_value will be properly initialized later on, with INIT_GOT. */
+inline static int
+__dl_init_loadaddr (struct elf32_fdpic_loadaddr *loadaddr, Elf32_Phdr *ppnt,
+ int pcnt)
+{
+ int count = 0, i;
+ size_t size;
+
+ for (i = 0; i < pcnt; i++)
+ if (ppnt[i].p_type == PT_LOAD)
+ count++;
+
+ loadaddr->got_value = 0;
+
+ size = sizeof (struct elf32_fdpic_loadmap)
+ + sizeof (struct elf32_fdpic_loadseg) * count;
+ loadaddr->map = _dl_malloc (size);
+ if (! loadaddr->map)
+ _dl_exit (-1);
+
+ loadaddr->map->version = 0;
+ loadaddr->map->nsegs = 0;
+
+ return count;
+}
+
+/* Incrementally initialize a load map. */
+inline static void
+__dl_init_loadaddr_hdr (struct elf32_fdpic_loadaddr loadaddr, void *addr,
+ Elf32_Phdr *phdr, int maxsegs)
+{
+ struct elf32_fdpic_loadseg *segdata;
+
+ if (loadaddr.map->nsegs == maxsegs)
+ _dl_exit (-1);
+
+ segdata = &loadaddr.map->segs[loadaddr.map->nsegs++];
+ segdata->addr = (Elf32_Addr) addr;
+ segdata->p_vaddr = phdr->p_vaddr;
+ segdata->p_memsz = phdr->p_memsz;
+
+#if defined (__SUPPORT_LD_DEBUG__)
+ {
+ extern char *_dl_debug;
+ extern int _dl_debug_file;
+ if (_dl_debug)
+ _dl_dprintf(_dl_debug_file, "%i: mapped %x at %x, size %x\n",
+ loadaddr.map->nsegs-1,
+ segdata->p_vaddr, segdata->addr, segdata->p_memsz);
+ }
+#endif
+}
+
+inline static void __dl_loadaddr_unmap
+(struct elf32_fdpic_loadaddr loadaddr, struct funcdesc_ht *funcdesc_ht);
+
+/* Figure out whether the given address is in one of the mapped
+ segments. */
+inline static int
+__dl_addr_in_loadaddr (void *p, struct elf32_fdpic_loadaddr loadaddr)
+{
+ struct elf32_fdpic_loadmap *map = loadaddr.map;
+ int c;
+
+ for (c = 0; c < map->nsegs; c++)
+ if ((void*)map->segs[c].addr <= p
+ && (char*)p < (char*)map->segs[c].addr + map->segs[c].p_memsz)
+ return 1;
+
+ return 0;
+}
+
+inline static void * _dl_funcdesc_for (void *entry_po