Jelajahi Sumber

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.
Eric Andersen 22 tahun lalu
induk
melakukan
baa67289df
39 mengubah file dengan 3996 tambahan dan 1 penghapusan
  1. 14 0
      Rules.mak
  2. 32 0
      extra/Configs/Config.frv
  3. 140 0
      extra/Configs/Config.frv.default
  4. 7 0
      extra/Configs/Config.in
  5. 15 1
      include/elf.h
  6. 89 0
      ldso/ldso/frv/dl-startup.h
  7. 191 0
      ldso/ldso/frv/dl-syscalls.h
  8. 628 0
      ldso/ldso/frv/dl-sysdep.h
  9. 495 0
      ldso/ldso/frv/elfinterp.c
  10. 71 0
      ldso/ldso/frv/resolve.S
  11. 89 0
      libc/sysdeps/linux/frv/Makefile
  12. 25 0
      libc/sysdeps/linux/frv/__init_brk.c
  13. 75 0
      libc/sysdeps/linux/frv/__longjmp.S
  14. 48 0
      libc/sysdeps/linux/frv/_mmap.c
  15. 104 0
      libc/sysdeps/linux/frv/bits/elf-fdpic.h
  16. 7 0
      libc/sysdeps/linux/frv/bits/endian.h
  17. 156 0
      libc/sysdeps/linux/frv/bits/fcntl.h
  18. 57 0
      libc/sysdeps/linux/frv/bits/kernel_stat.h
  19. 43 0
      libc/sysdeps/linux/frv/bits/kernel_types.h
  20. 75 0
      libc/sysdeps/linux/frv/bits/mman.h
  21. 53 0
      libc/sysdeps/linux/frv/bits/setjmp.h
  22. 28 0
      libc/sysdeps/linux/frv/bits/stackinfo.h
  23. 129 0
      libc/sysdeps/linux/frv/bits/syscalls.h
  24. 19 0
      libc/sysdeps/linux/frv/bits/wordsize.h
  25. 22 0
      libc/sysdeps/linux/frv/brk.c
  26. 83 0
      libc/sysdeps/linux/frv/clone.S
  27. 110 0
      libc/sysdeps/linux/frv/crt0.S
  28. 41 0
      libc/sysdeps/linux/frv/crti.S
  29. 35 0
      libc/sysdeps/linux/frv/crtn.S
  30. 118 0
      libc/sysdeps/linux/frv/crtreloc.c
  31. 43 0
      libc/sysdeps/linux/frv/dl-iterate-phdr.c
  32. 25 0
      libc/sysdeps/linux/frv/sbrk.c
  33. 95 0
      libc/sysdeps/linux/frv/setjmp.S
  34. 125 0
      libc/sysdeps/linux/frv/sys/procfs.h
  35. 139 0
      libc/sysdeps/linux/frv/sys/ptrace.h
  36. 451 0
      libc/sysdeps/linux/frv/sys/ucontext.h
  37. 27 0
      libc/sysdeps/linux/frv/sysdep.c
  38. 44 0
      libc/sysdeps/linux/frv/vfork.S
  39. 48 0
      libpthread/linuxthreads/sysdeps/frv/pt-machine.h

+ 14 - 0
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

+ 32 - 0
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

+ 140 - 0
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

+ 7 - 0
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

+ 15 - 1
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).  */

+ 89 - 0
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;

+ 191 - 0
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

+ 628 - 0
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_point, void *got_value);
+
+#define DL_LOADADDR_TYPE struct elf32_fdpic_loadaddr
+
+#define DL_RELOC_ADDR(ADDR, LOADADDR) \
+  (__reloc_pointer ((void*)(ADDR), (LOADADDR).map))
+
+#define DL_ADDR_TO_FUNC_PTR(ADDR, LOADADDR) \
+  ((void(*)(void)) _dl_funcdesc_for ((void*)(ADDR), (LOADADDR).got_value))
+
+#define _dl_stabilize_funcdesc(val) \
+  ({ asm ("" : "+m" (*(val))); (val); })
+
+#define DL_CALL_FUNC_AT_ADDR(ADDR, LOADADDR, SIGNATURE, ...) \
+  ({ struct funcdesc_value fd = { (void*)(ADDR), (LOADADDR).got_value }; \
+     void (*pf)(void) = (void*) _dl_stabilize_funcdesc (&fd); \
+     (* SIGNATURE pf)(__VA_ARGS__); })
+
+#define DL_INIT_LOADADDR_BOOT(LOADADDR, BASEADDR) \
+  (__dl_init_loadaddr_map (&(LOADADDR), dl_boot_got_pointer, \
+			   dl_boot_ldsomap ?: dl_boot_progmap))
+
+#define DL_INIT_LOADADDR_PROG(LOADADDR, BASEADDR) \
+  (__dl_init_loadaddr_map (&(LOADADDR), 0, dl_boot_progmap))
+
+#define DL_INIT_LOADADDR_EXTRA_DECLS \
+  int dl_init_loadaddr_load_count;
+#define DL_INIT_LOADADDR(LOADADDR, BASEADDR, PHDR, PHDRCNT) \
+  (dl_init_loadaddr_load_count = \
+     __dl_init_loadaddr (&(LOADADDR), (PHDR), (PHDRCNT)))
+#define DL_INIT_LOADADDR_HDR(LOADADDR, ADDR, PHDR) \
+  (__dl_init_loadaddr_hdr ((LOADADDR), (ADDR), (PHDR), \
+			   dl_init_loadaddr_load_count))
+#define DL_LOADADDR_UNMAP(LOADADDR, LEN) \
+  (__dl_loadaddr_unmap ((LOADADDR), (NULL)))
+#define DL_LIB_UNMAP(LIB, LEN) \
+  (__dl_loadaddr_unmap ((LIB)->loadaddr, (LIB)->funcdesc_ht))
+#define DL_LOADADDR_BASE(LOADADDR) \
+  ((LOADADDR).got_value)
+
+#define DL_ADDR_IN_LOADADDR(ADDR, TPNT, TFROM) \
+  (! (TFROM) && __dl_addr_in_loadaddr ((void*)(ADDR), (TPNT)->loadaddr))
+
+/* We only support loading FDPIC independently-relocatable shared
+   libraries.  It probably wouldn't be too hard to support loading
+   shared libraries that require relocation by the same amount, but we
+   don't know that they exist or would be useful, and the dynamic
+   loader code could leak the whole-library map unless we keeping a
+   bit more state for DL_LOADADDR_UNMAP and DL_LIB_UNMAP, so let's
+   keep things simple for now.  */
+#define DL_CHECK_LIB_TYPE(epnt, piclib, _dl_progname, libname) \
+do \
+{ \
+  if (((epnt)->e_flags & EF_FRV_FDPIC) && ! ((epnt)->e_flags & EF_FRV_PIC)) \
+    (piclib) = 2; \
+  else \
+    { \
+      _dl_internal_error_number = LD_ERROR_NOTDYN; \
+      _dl_dprintf(2, "%s: '%s' is not an FDPIC shared library" \
+		  "\n", (_dl_progname), (libname)); \
+      _dl_close(infile); \
+      return NULL; \
+    } \
+} \
+while (0)  
+
+/* We want want to apply all relocations in the interpreter during
+   bootstrap.  Because of this, we have to skip the interpreter
+   relocations in _dl_parse_relocation_information(), see
+   elfinterp.c.  */
+#define DL_SKIP_BOOTSTRAP_RELOC(SYMTAB, INDEX, STRTAB) 0
+
+#ifdef __NR_pread
+#define _DL_PREAD(FD, BUF, SIZE, OFFSET) \
+  (_dl_pread((FD), (BUF), (SIZE), (OFFSET)))
+#endif
+
+#include <dl-hash.h>
+
+/* The hashcode handling code below is heavily inspired in libiberty's
+   hashtab code, but with most adaptation points and support for
+   deleting elements removed.
+
+   Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+   Contributed by Vladimir Makarov (vmakarov@cygnus.com).  */
+
+inline static unsigned long
+higher_prime_number (unsigned long n)
+{
+  /* These are primes that are near, but slightly smaller than, a
+     power of two.  */
+  static const unsigned long primes[] = {
+    (unsigned long) 7,
+    (unsigned long) 13,
+    (unsigned long) 31,
+    (unsigned long) 61,
+    (unsigned long) 127,
+    (unsigned long) 251,
+    (unsigned long) 509,
+    (unsigned long) 1021,
+    (unsigned long) 2039,
+    (unsigned long) 4093,
+    (unsigned long) 8191,
+    (unsigned long) 16381,
+    (unsigned long) 32749,
+    (unsigned long) 65521,
+    (unsigned long) 131071,
+    (unsigned long) 262139,
+    (unsigned long) 524287,
+    (unsigned long) 1048573,
+    (unsigned long) 2097143,
+    (unsigned long) 4194301,
+    (unsigned long) 8388593,
+    (unsigned long) 16777213,
+    (unsigned long) 33554393,
+    (unsigned long) 67108859,
+    (unsigned long) 134217689,
+    (unsigned long) 268435399,
+    (unsigned long) 536870909,
+    (unsigned long) 1073741789,
+    (unsigned long) 2147483647,
+					/* 4294967291L */
+    ((unsigned long) 2147483647) + ((unsigned long) 2147483644),
+  };
+
+  const unsigned long *low = &primes[0];
+  const unsigned long *high = &primes[sizeof(primes) / sizeof(primes[0])];
+
+  while (low != high)
+    {
+      const unsigned long *mid = low + (high - low) / 2;
+      if (n > *mid)
+	low = mid + 1;
+      else
+	high = mid;
+    }
+
+#if 0
+  /* If we've run out of primes, abort.  */
+  if (n > *low)
+    {
+      fprintf (stderr, "Cannot find prime bigger than %lu\n", n);
+      abort ();
+    }
+#endif
+
+  return *low;
+}
+
+struct funcdesc_ht
+{
+  /* Table itself.  */
+  struct funcdesc_value **entries;
+
+  /* Current size (in entries) of the hash table */
+  size_t size;
+
+  /* Current number of elements.  */
+  size_t n_elements;
+};  
+
+inline static int
+hash_pointer (const void *p)
+{
+  return (int) ((long)p >> 3);
+}
+
+inline static struct funcdesc_ht *
+htab_create (void)
+{
+  struct funcdesc_ht *ht = _dl_malloc (sizeof (struct funcdesc_ht));
+
+  if (! ht)
+    return NULL;
+  ht->size = 3;
+  ht->entries = _dl_malloc (sizeof (struct funcdesc_ht_value *) * ht->size);
+  if (! ht->entries)
+    return NULL;
+  
+  ht->n_elements = 0;
+
+  _dl_memset (ht->entries, 0, sizeof (struct funcdesc_ht_value *) * ht->size);
+  
+  return ht;
+}
+
+inline static void
+htab_delete (struct funcdesc_ht *htab)
+{
+  int i;
+
+  for (i = htab->size - 1; i >= 0; i--)
+    if (htab->entries[i])
+      _dl_free (htab->entries[i]);
+
+  _dl_free (htab->entries);
+  _dl_free (htab);
+}
+
+/* Similar to htab_find_slot, but without several unwanted side effects:
+    - Does not call htab->eq_f when it finds an existing entry.
+    - Does not change the count of elements/searches/collisions in the
+      hash table.
+   This function also assumes there are no deleted entries in the table.
+   HASH is the hash value for the element to be inserted.  */
+
+inline static struct funcdesc_value **
+find_empty_slot_for_expand (struct funcdesc_ht *htab, int hash)
+{
+  size_t size = htab->size;
+  unsigned int index = hash % size;
+  struct funcdesc_value **slot = htab->entries + index;
+  int hash2;
+
+  if (! *slot)
+    return slot;
+
+  hash2 = 1 + hash % (size - 2);
+  for (;;)
+    {
+      index += hash2;
+      if (index >= size)
+	index -= size;
+
+      slot = htab->entries + index;
+      if (! *slot)
+	return slot;
+    }
+}
+
+/* The following function changes size of memory allocated for the
+   entries and repeatedly inserts the table elements.  The occupancy
+   of the table after the call will be about 50%.  Naturally the hash
+   table must already exist.  Remember also that the place of the
+   table entries is changed.  If memory allocation failures are allowed,
+   this function will return zero, indicating that the table could not be
+   expanded.  If all goes well, it will return a non-zero value.  */
+
+inline static int
+htab_expand (struct funcdesc_ht *htab)
+{
+  struct funcdesc_value **oentries;
+  struct funcdesc_value **olimit;
+  struct funcdesc_value **p;
+  struct funcdesc_value **nentries;
+  size_t nsize;
+
+  oentries = htab->entries;
+  olimit = oentries + htab->size;
+
+  /* Resize only when table after removal of unused elements is either
+     too full or too empty.  */
+  if (htab->n_elements * 2 > htab->size)
+    nsize = higher_prime_number (htab->n_elements * 2);
+  else
+    nsize = htab->size;
+
+  nentries = _dl_malloc (sizeof (struct funcdesc_value *) * nsize);
+  _dl_memset (nentries, 0, sizeof (struct funcdesc_value *) * nsize);
+  if (nentries == NULL)
+    return 0;
+  htab->entries = nentries;
+  htab->size = nsize;
+
+  p = oentries;
+  do
+    {
+      if (*p)
+	*find_empty_slot_for_expand (htab, hash_pointer ((*p)->entry_point))
+	  = *p;
+
+      p++;
+    }
+  while (p < olimit);
+
+  _dl_free (oentries);
+  return 1;
+}
+
+/* This function searches for a hash table slot containing an entry
+   equal to the given element.  To delete an entry, call this with
+   INSERT = 0, then call htab_clear_slot on the slot returned (possibly
+   after doing some checks).  To insert an entry, call this with
+   INSERT = 1, then write the value you want into the returned slot.
+   When inserting an entry, NULL may be returned if memory allocation
+   fails.  */
+
+inline static struct funcdesc_value **
+htab_find_slot (struct funcdesc_ht *htab, void *ptr)
+{
+  unsigned int index;
+  int hash, hash2;
+  size_t size;
+  struct funcdesc_value **entry;
+
+  if (htab->size * 3 <= htab->n_elements * 4
+      && htab_expand (htab) == 0)
+    return NULL;
+
+  hash = hash_pointer (ptr);
+
+  size = htab->size;
+  index = hash % size;
+
+  entry = &htab->entries[index];
+  if (!*entry)
+    goto empty_entry;
+  else if ((*entry)->entry_point == ptr)
+    return entry;
+      
+  hash2 = 1 + hash % (size - 2);
+  for (;;)
+    {
+      index += hash2;
+      if (index >= size)
+	index -= size;
+      
+      entry = &htab->entries[index];
+      if (!*entry)
+	goto empty_entry;
+      else if ((*entry)->entry_point == ptr)
+	return entry;
+    }
+
+ empty_entry:
+  htab->n_elements++;
+  return entry;
+}
+
+void *
+_dl_funcdesc_for (void *entry_point, void *got_value)
+{
+  struct elf_resolve *tpnt = ((void**)got_value)[2];
+  struct funcdesc_ht *ht = tpnt->funcdesc_ht;
+  struct funcdesc_value **entry;
+
+  _dl_assert (got_value == tpnt->loadaddr.got_value);
+
+  if (! ht)
+    {
+      ht = htab_create ();
+      if (! ht)
+	return (void*)-1;
+      tpnt->funcdesc_ht = ht;
+    }
+
+  entry = htab_find_slot (ht, entry_point);
+  if (*entry)
+    {
+      _dl_assert ((*entry)->entry_point == entry_point);
+      return _dl_stabilize_funcdesc (*entry);
+    }
+
+  *entry = _dl_malloc (sizeof (struct funcdesc_value));
+  (*entry)->entry_point = entry_point;
+  (*entry)->got_value = got_value;
+
+  return _dl_stabilize_funcdesc (*entry);
+}
+
+void
+__dl_loadaddr_unmap (struct elf32_fdpic_loadaddr loadaddr,
+		     struct funcdesc_ht *funcdesc_ht)
+{
+  int i;
+
+  for (i = 0; i < loadaddr.map->nsegs; i++)
+    _dl_munmap ((void*)loadaddr.map->segs[i].addr,
+		loadaddr.map->segs[i].p_memsz);
+
+  _dl_free (loadaddr.map);
+  if (funcdesc_ht)
+    htab_delete (funcdesc_ht);
+}

+ 495 - 0
ldso/ldso/frv/elfinterp.c

@@ -0,0 +1,495 @@
+/* FR-V FDPIC ELF shared library loader suppport
+   Copyright (C) 2003 Red Hat, Inc.
+   Contributed by Alexandre Oliva <aoliva@redhat.com>
+   Lots of code copied from ../i386/elfinterp.c, so:
+   Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald, 
+  				David Engel, Hongjiu Lu and Mitch D'Souza
+   Copyright (C) 2001-2002, Erik Andersen
+   All rights reserved.
+
+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.  */
+
+#ifndef ATTRIBUTE_UNUSED
+# define ATTRIBUTE_UNUSED __attribute__((__unused__))
+#endif
+
+#if defined (__SUPPORT_LD_DEBUG__)
+static const char *_dl_reltypes_tab[] =
+{
+  [0]	"R_FRV_NONE",		"R_FRV_32",
+  [2]	"R_FRV_LABEL16",	"R_FRV_LABEL24",
+  [4]	"R_FRV_LO16",		"R_FRV_HI16",
+  [6]	"R_FRV_GPREL12",	"R_FRV_GPRELU12",
+  [8]	"R_FRV_GPREL32",	"R_FRV_GPRELHI",	"R_FRV_GPRELLO",
+  [11]	"R_FRV_GOT12",		"R_FRV_GOTHI",		"R_FRV_GOTLO",
+  [14]	"R_FRV_FUNCDESC",
+  [15]	"R_FRV_FUNCDESC_GOT12",	"R_FRV_FUNCDESC_GOTHI",	"R_FRV_FUNCDESC_GOTLO",
+  [18]	"R_FRV_FUNCDESC_VALUE", "R_FRV_FUNCDESC_GOTOFF12",
+  [20]	"R_FRV_FUNCDESC_GOTOFFHI", "R_FRV_FUNCDESC_GOTOFFLO",
+  [22]	"R_FRV_GOTOFF12",	"R_FRV_GOTOFFHI",	"R_FRV_GOTOFFLO",
+#if 0
+  [200]	"R_FRV_GNU_VTINHERIT",	"R_FRV_GNU_VTENTRY"
+#endif
+};
+
+static const char *
+_dl_reltypes(int type)
+{
+  static char buf[22];  
+  const char *str;
+  
+  if (type >= (int)(sizeof (_dl_reltypes_tab)/sizeof(_dl_reltypes_tab[0])) ||
+      NULL == (str = _dl_reltypes_tab[type]))
+  {
+    str =_dl_simple_ltoa( buf, (unsigned long)(type));
+  }
+  return str;
+}
+
+static 
+void debug_sym(Elf32_Sym *symtab,char *strtab,int symtab_index)
+{
+  if(_dl_debug_symbols)
+  {
+    if(symtab_index){
+      _dl_dprintf(_dl_debug_file, "\n%s\n\tvalue=%x\tsize=%x\tinfo=%x\tother=%x\tshndx=%x",
+		  strtab + symtab[symtab_index].st_name,
+		  symtab[symtab_index].st_value,
+		  symtab[symtab_index].st_size,
+		  symtab[symtab_index].st_info,
+		  symtab[symtab_index].st_other,
+		  symtab[symtab_index].st_shndx);
+    }
+  }
+}
+
+static void debug_reloc(Elf32_Sym *symtab,char *strtab, ELF_RELOC *rpnt)
+{
+  if(_dl_debug_reloc)
+  {
+    int symtab_index;
+    const char *sym;
+    symtab_index = ELF32_R_SYM(rpnt->r_info);
+    sym = symtab_index ? strtab + symtab[symtab_index].st_name : "sym=0x0";
+    
+  if(_dl_debug_symbols)
+	  _dl_dprintf(_dl_debug_file, "\n\t");
+  else
+	  _dl_dprintf(_dl_debug_file, "\n%s\n\t", sym);
+#ifdef ELF_USES_RELOCA
+    _dl_dprintf(_dl_debug_file, "%s\toffset=%x\taddend=%x",
+		_dl_reltypes(ELF32_R_TYPE(rpnt->r_info)),
+		rpnt->r_offset,
+		rpnt->r_addend);
+#else
+    _dl_dprintf(_dl_debug_file, "%s\toffset=%x\n",
+		_dl_reltypes(ELF32_R_TYPE(rpnt->r_info)),
+		rpnt->r_offset);
+#endif
+  }
+}
+#endif
+
+/* Program to load an ELF binary on a linux system, and run it.
+   References to symbols in sharable libraries can be resolved by either
+   an ELF sharable library or a linux style of shared library. */
+
+/* Disclaimer:  I have never seen any AT&T source code for SVr4, nor have
+   I ever taken any courses on internals.  This program was developed using
+   information available through the book "UNIX SYSTEM V RELEASE 4,
+   Programmers guide: Ansi C and Programming Support Tools", which did
+   a more than adequate job of explaining everything required to get this
+   working. */
+
+struct funcdesc_value volatile *__attribute__((__visibility__("hidden")))
+_dl_linux_resolver (struct elf_resolve *tpnt, int reloc_entry)
+{
+	int reloc_type;
+	ELF_RELOC *this_reloc;
+	char *strtab;
+	Elf32_Sym *symtab;
+	int symtab_index;
+	char *rel_addr;
+	struct elf_resolve *new_tpnt;
+	char *new_addr;
+	struct funcdesc_value funcval;
+	struct funcdesc_value volatile *got_entry;
+	char *symname;
+
+	rel_addr = DL_RELOC_ADDR (tpnt->dynamic_info[DT_JMPREL],
+				  tpnt->loadaddr);
+
+	this_reloc = (ELF_RELOC *)(intptr_t)(rel_addr + reloc_entry);
+	reloc_type = ELF32_R_TYPE(this_reloc->r_info);
+	symtab_index = ELF32_R_SYM(this_reloc->r_info);
+
+	symtab = (Elf32_Sym *)(intptr_t)
+				  DL_RELOC_ADDR (tpnt->dynamic_info[DT_SYMTAB],
+						 tpnt->loadaddr);
+	strtab = DL_RELOC_ADDR (tpnt->dynamic_info[DT_STRTAB], tpnt->loadaddr);
+	symname= strtab + symtab[symtab_index].st_name;
+
+	if (reloc_type != R_FRV_FUNCDESC_VALUE) {
+		_dl_dprintf(2, "%s: Incorrect relocation type in jump relocations\n", 
+				_dl_progname);
+		_dl_exit(1);
+	}
+
+	/* Address of GOT entry fix up */
+	got_entry = (struct funcdesc_value *)
+	  DL_RELOC_ADDR (this_reloc->r_offset, tpnt->loadaddr);
+
+	/* Get the address to be used to fill in the GOT entry.  */
+	new_addr = __dl_find_hash(symname, tpnt->symbol_scope, tpnt, resolver,
+				  &new_tpnt);
+	if (!new_addr) {
+		new_addr = __dl_find_hash(symname, NULL, NULL, resolver,
+					  &new_tpnt);
+		if (!new_addr) {
+			_dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
+				    _dl_progname, symname);
+			_dl_exit(1);
+		}
+	}
+
+	funcval.entry_point = new_addr;
+	funcval.got_value = new_tpnt->loadaddr.got_value;
+
+#if defined (__SUPPORT_LD_DEBUG__)
+		if (_dl_debug_bindings)
+		{
+			_dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname);
+			if(_dl_debug_detail)
+				_dl_dprintf(_dl_debug_file, 
+					    "\n\tpatched (%x,%x) ==> (%x,%x) @ %x\n",
+					    got_entry->entry_point, got_entry->got_value,
+					    funcval.entry_point, funcval.got_value,
+					    got_entry);
+		}
+	if (!_dl_debug_nofixups) {
+		*got_entry = funcval;
+	}
+#else
+	*got_entry = funcval;
+#endif
+
+	return got_entry;
+}
+
+static int
+_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,
+	  unsigned long rel_addr, unsigned long rel_size,
+	  int (*reloc_fnc) (struct elf_resolve *tpnt, struct dyn_elf *scope,
+			    ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab))
+{
+	unsigned int i;
+	char *strtab;
+	Elf32_Sym *symtab;
+	ELF_RELOC *rpnt;
+	int symtab_index;
+
+	/* Now parse the relocation information */
+	rpnt = (ELF_RELOC *)(intptr_t) DL_RELOC_ADDR (rel_addr, tpnt->loadaddr);
+	rel_size = rel_size / sizeof(ELF_RELOC);
+
+	symtab = (Elf32_Sym *)(intptr_t)
+	  DL_RELOC_ADDR (tpnt->dynamic_info[DT_SYMTAB], tpnt->loadaddr);
+	strtab = DL_RELOC_ADDR (tpnt->dynamic_info[DT_STRTAB], tpnt->loadaddr);
+
+	  for (i = 0; i < rel_size; i++, rpnt++) {
+	        int res;
+	    
+		symtab_index = ELF32_R_SYM(rpnt->r_info);
+		
+		/* When the dynamic linker bootstrapped itself, it resolved some symbols.
+		   Make sure we do not do them again */
+		if (!symtab_index && tpnt->libtype == program_interpreter)
+			continue;
+		if (symtab_index && tpnt->libtype == program_interpreter &&
+		    _dl_symbol(strtab + symtab[symtab_index].st_name))
+			continue;
+
+#if defined (__SUPPORT_LD_DEBUG__)
+		debug_sym(symtab,strtab,symtab_index);
+		debug_reloc(symtab,strtab,rpnt);
+#endif
+
+		res = reloc_fnc (tpnt, scope, rpnt, symtab, strtab);
+
+		if (res==0) continue;
+
+		_dl_dprintf(2, "\n%s: ",_dl_progname);
+		
+		if (symtab_index)
+		  _dl_dprintf(2, "symbol '%s': ", strtab + symtab[symtab_index].st_name);
+		  
+		if (res <0)
+		{
+		        int reloc_type = ELF32_R_TYPE(rpnt->r_info);
+#if defined (__SUPPORT_LD_DEBUG__)
+			_dl_dprintf(2, "can't handle reloc type %s\n ", _dl_reltypes(reloc_type));
+#else
+			_dl_dprintf(2, "can't handle reloc type %x\n", reloc_type);
+#endif			
+			_dl_exit(-res);
+		}
+		else if (res >0)
+		{
+			_dl_dprintf(2, "can't resolve symbol\n");
+			return res;
+		}
+	  }
+	  return 0;
+}
+
+static int
+_dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
+	      ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
+{
+	int reloc_type;
+	int symtab_index;
+	char *symname;
+	unsigned long reloc_value = 0, *reloc_addr;
+	struct { unsigned long v; } __attribute__((__packed__))
+					    *reloc_addr_packed;
+	unsigned long symbol_addr;
+	struct elf_resolve *symbol_tpnt;
+	struct funcdesc_value funcval;
+#if defined (__SUPPORT_LD_DEBUG__)
+	unsigned long old_val;
+#endif
+
+	reloc_addr   = (unsigned long *)(intptr_t)
+	  DL_RELOC_ADDR (rpnt->r_offset, tpnt->loadaddr);
+	asm ("" : "=r" (reloc_addr_packed) : "0" (reloc_addr));
+	reloc_type   = ELF32_R_TYPE(rpnt->r_info);
+	symtab_index = ELF32_R_SYM(rpnt->r_info);
+	symbol_addr  = 0;
+	symname      = strtab + symtab[symtab_index].st_name;
+
+	if (ELF32_ST_BIND (symtab[symtab_index].st_info) == STB_LOCAL) {
+		symbol_addr = (unsigned long)
+		  DL_RELOC_ADDR (symtab[symtab_index].st_value,
+				 tpnt->loadaddr);
+		symbol_tpnt = tpnt;
+	} else {
+
+		symbol_addr = (unsigned long)
+		  __dl_find_hash(symname, scope, 
+				 (reloc_type == R_FRV_FUNCDESC_VALUE
+				  ? tpnt : NULL), symbolrel,
+				 &symbol_tpnt);
+
+		/*
+		 * We want to allow undefined references to weak symbols - this might
+		 * have been intentional.  We should not be linking local symbols
+		 * here, so all bases should be covered.
+		 */
+
+		if (!symbol_addr && ELF32_ST_BIND(symtab[symtab_index].st_info) == STB_GLOBAL) {
+#if defined (__SUPPORT_LD_DEBUG__)
+			_dl_dprintf(2, "\tglobal symbol '%s' already defined in '%s'\n",
+					symname, tpnt->libname);
+#endif
+			return 0;
+		}
+	}
+
+#if defined (__SUPPORT_LD_DEBUG__)
+	if (_dl_debug_reloc && _dl_debug_detail)
+	  {
+	    if ((long)reloc_addr_packed & 3)
+	      old_val = reloc_addr_packed->v;
+	    else
+	      old_val = *reloc_addr;
+	  }
+	else
+	  old_val = 0;
+#endif
+	switch (reloc_type) {
+	case R_FRV_NONE:
+		break;
+	case R_FRV_32:
+		if ((long)reloc_addr_packed & 3)
+			reloc_value = reloc_addr_packed->v += symbol_addr;
+		else
+			reloc_value = *reloc_addr += symbol_addr;
+		break;
+	case R_FRV_FUNCDESC_VALUE:
+		funcval.entry_point = (void*)symbol_addr;
+		/* The addend of FUNCDESC_VALUE
+		   relocations referencing global
+		   symbols must be ignored, because it
+		   may hold the address of a lazy PLT
+		   entry.  */
+		if (ELF32_ST_BIND
+		    (symtab[symtab_index].st_info)
+		    == STB_LOCAL)
+			funcval.entry_point += *reloc_addr;
+		reloc_value = (unsigned long)funcval.entry_point;
+		if (symbol_addr)
+			funcval.got_value
+				= symbol_tpnt->loadaddr.got_value;
+		else
+			funcval.got_value = 0;
+		asm ("std%I0\t%1, %M0"
+		     : "=m" (*(struct funcdesc_value *)reloc_addr)
+		     : "r" (funcval));
+		break;
+	case R_FRV_FUNCDESC:
+		if ((long)reloc_addr_packed & 3)
+			reloc_value = reloc_addr_packed->v;
+		else
+			reloc_value = *reloc_addr;
+		if (symbol_addr)
+			reloc_value = (unsigned long)_dl_funcdesc_for
+				((char *)symbol_addr + reloc_value,
+				 symbol_tpnt->loadaddr.got_value);
+		else
+			reloc_value = 0;
+		if ((long)reloc_addr_packed & 3)
+			reloc_addr_packed->v = reloc_value;
+		else
+			*reloc_addr = reloc_value;
+		break;
+	default:
+		return -1; /*call _dl_exit(1) */
+	}
+#if defined (__SUPPORT_LD_DEBUG__)
+	if(_dl_debug_reloc && _dl_debug_detail) {
+		_dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x", old_val, reloc_value, reloc_addr);
+		switch (reloc_type) {
+		case R_FRV_FUNCDESC_VALUE:
+			_dl_dprintf(_dl_debug_file, " got %x", ((struct funcdesc_value *)reloc_value)->got_value);
+			break;
+		case R_FRV_FUNCDESC:
+			if (! reloc_value)
+				break;
+			_dl_dprintf(_dl_debug_file, " funcdesc (%x,%x)",
+				    ((struct funcdesc_value *)reloc_value)->entry_point,
+				    ((struct funcdesc_value *)reloc_value)->got_value);
+			break;
+		}
+	}
+#endif
+
+	return 0;
+}
+
+static int
+_dl_do_lazy_reloc (struct elf_resolve *tpnt,
+		   struct dyn_elf *scope ATTRIBUTE_UNUSED,
+		   ELF_RELOC *rpnt, Elf32_Sym *symtab ATTRIBUTE_UNUSED,
+		   char *strtab ATTRIBUTE_UNUSED)
+{
+	int reloc_type;
+	struct funcdesc_value volatile *reloc_addr;
+	struct funcdesc_value funcval;
+#if defined (__SUPPORT_LD_DEBUG__)
+	unsigned long old_val;
+#endif
+
+	reloc_addr = (struct funcdesc_value *)(intptr_t)
+	  DL_RELOC_ADDR (rpnt->r_offset, tpnt->loadaddr);
+	reloc_type = ELF32_R_TYPE(rpnt->r_info);
+
+#if defined (__SUPPORT_LD_DEBUG__)
+	old_val = (unsigned long)reloc_addr->entry_point;
+#endif
+		switch (reloc_type) {
+			case R_FRV_NONE:
+				break;
+			case R_FRV_FUNCDESC_VALUE:
+				funcval = *reloc_addr;
+				funcval.entry_point =
+				  DL_RELOC_ADDR (funcval.entry_point,
+						 tpnt->loadaddr);
+				funcval.got_value = tpnt->loadaddr.got_value;
+				*reloc_addr = funcval;
+				break;
+			default:
+				return -1; /*call _dl_exit(1) */
+		}
+#if defined (__SUPPORT_LD_DEBUG__)
+	if(_dl_debug_reloc && _dl_debug_detail)
+		_dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x", old_val, reloc_addr->entry_point, reloc_addr);
+#endif
+	return 0;
+
+}
+
+void
+_dl_parse_lazy_relocation_information
+(struct dyn_elf *rpnt, unsigned long rel_addr, unsigned long rel_size,
+ int type ATTRIBUTE_UNUSED)
+{
+  _dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc);
+}
+
+int
+_dl_parse_relocation_information
+(struct dyn_elf *rpnt, unsigned long rel_addr, unsigned long rel_size,
+ int type ATTRIBUTE_UNUSED)
+{
+  /* The interpreter initial self-relocation is complete, and we
+     can't re-apply relocations.  */
+  if (rpnt->dyn->libtype == program_interpreter)
+    return 0;
+
+  return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size, _dl_do_reloc);
+}
+
+/* We don't have copy relocs.  */
+
+int
+_dl_parse_copy_information
+(struct dyn_elf *rpnt ATTRIBUTE_UNUSED,
+ unsigned long rel_addr ATTRIBUTE_UNUSED,
+ unsigned long rel_size ATTRIBUTE_UNUSED,
+ int type ATTRIBUTE_UNUSED)
+{
+  return 0;
+}
+
+#ifndef LIBDL
+# include "../../libc/sysdeps/linux/frv/crtreloc.c"
+#endif
+
+#if ! defined LIBDL || (! defined PIC && ! defined __PIC__)
+int
+__dl_iterate_phdr (int (*callback) (struct dl_phdr_info *info,
+				    size_t size, void *data), void *data)
+{
+  struct elf_resolve *l;
+  struct dl_phdr_info info;
+  int ret = 0;
+
+  for (l = _dl_loaded_modules; l != NULL; l = l->next)
+    {
+      info.dlpi_addr = l->loadaddr;
+      info.dlpi_name = l->libname;
+      info.dlpi_phdr = l->ppnt;
+      info.dlpi_phnum = l->n_phent;
+      ret = callback (&info, sizeof (struct dl_phdr_info), data);
+      if (ret)
+	break;
+    }
+
+  return ret;
+}
+#endif

+ 71 - 0
ldso/ldso/frv/resolve.S

@@ -0,0 +1,71 @@
+     /* 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.  */
+	
+     /* The function below is tail-called by resolver stubs when a
+	lazily-bound function is called.  It must preserve all
+	registers that could be used to pass arguments to the actual
+	function.  Upon _dl_linux_resolve entry, GR14 holds the
+	address of a lazy PLT entry, so @(GR14,-4) is the lazy
+	relocation number that we have to pass to _dl_linux_resolver.
+	GR15 holds the caller's GOT, from which we extract the
+	elf_resolve* that _dl_linux_resolver needs as well.
+
+	_dl_linux_resolver() figures out where the jump symbol is
+	_really_ supposed to have jumped to and returns that to us.
+	Once we have that, we prepare to tail-call the actual
+	function, clean up after ourselves, restoring the original
+	arguments, then jump to the fixed up address.  */
+
+	.text
+	.p2align 4
+
+	.hidden	_dl_linux_resolve
+	.global	_dl_linux_resolve
+	.type	_dl_linux_resolve,@function
+
+_dl_linux_resolve:
+	/* Preserve arguments.  */
+	addi	sp, -8*4, sp
+	stdi	gr8, @(sp, 8)
+	stdi	gr10, @(sp, 16)
+	stdi	gr12, @(sp, 24)
+	movsg	lr,gr8
+	st	gr8, @(sp,gr0)
+
+	/* Prepare to call _dl_linux_resolver.  */
+	ldi	@(gr15, 8), gr8
+	ldi	@(gr14, -4), gr9
+	mov.p	gr5, gr15
+	call	_dl_linux_resolver
+	
+	/* Move aside return value that contains the FUNCDESC_VALUE.  */
+	ldd	@(gr8,gr0),gr14
+
+	/* Restore arguments.  */
+	ld	@(sp, gr0), gr8
+	movgs	gr8,lr
+	lddi	@(sp, 24), gr12
+	lddi	@(sp, 16), gr10
+	lddi	@(sp, 8), gr8
+	addi	sp, 8*4, sp
+
+	/* Now jump to the actual function.  */
+	jmpl	@(gr14, gr0)
+	.size	_dl_linux_resolve, . - _dl_linux_resolve

+ 89 - 0
libc/sysdeps/linux/frv/Makefile

@@ -0,0 +1,89 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2003 Erik Andersen <andersen@uclibc.org>
+#
+# This program is free software; you can redistribute it and/or modify it under
+# the terms of the GNU Library General Public License as published by the Free
+# Software Foundation; either version 2 of the License, or (at your option) any
+# later version.
+#
+# This program 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 Library General Public License
+# along with this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+TOPDIR=../../../../
+include $(TOPDIR)Rules.mak
+ASFLAGS=$(CFLAGS)
+
+CRT0_SRC = crt0.S
+CRT0_OBJ = crt0.o crt1.o # gcrt1.o
+SCRT0_OBJ = $(patsubst %,S%, $(CRT0_OBJ))
+CRT0_DEPS=gmon-start.S
+
+CTOR_TARGETS = crti.o crtn.o
+
+SSRC=__longjmp.S setjmp.S clone.S vfork.S
+ifeq ($(strip $(UCLIBC_PROFILING)),y)
+SSRC+=mcount.S
+endif
+SOBJS=$(patsubst %.S,%.o, $(SSRC))
+
+CSRC=_mmap.c sysdep.c brk.c sbrk.c __init_brk.c dl-iterate-phdr.c
+COBJS=$(patsubst %.c,%.o, $(CSRC))
+
+OBJS=$(SOBJS) $(COBJS)
+
+all: $(OBJS) $(LIBC)
+
+$(LIBC): ar-target 
+
+ar-target: $(OBJS) $(CRT0_OBJ) $(SCRT0_OBJ) $(CTOR_TARGETS)
+	$(AR) $(ARFLAGS) $(LIBC) $(OBJS)
+	$(INSTALL) -d $(TOPDIR)lib
+	cp $(CRT0_OBJ) $(SCRT0_OBJ) $(CTOR_TARGETS) $(TOPDIR)lib/
+
+$(CRT0_OBJ): $(CRT0_SRC) crtreloc.o
+	$(CC) $(CFLAGS) -DL_$* -r -nostdlib $< crtreloc.o -o $*.o
+	$(STRIPTOOL) -x -R .note -R .comment $*.o
+
+crtreloc.o: crtreloc.c
+	$(CC) $(CFLAGS) -c $< -o $@
+
+$(SCRT0_OBJ): $(CRT0_SRC) Scrtreloc.o
+	$(CC) $(CFLAGS) -fPIE -DL_$* -r -nostdlib $< Scrtreloc.o -o $*.o
+	$(STRIPTOOL) -x -R .note -R .comment $*.o
+
+Scrtreloc.o: crtreloc.c
+	$(CC) $(CFLAGS) -fPIE -c $< -o $@
+
+$(CTOR_TARGETS): %.o : %.S
+	$(CC) $(CFLAGS) -c $< -o $@
+	$(STRIPTOOL) -x -R .note -R .comment $*.o
+
+$(SOBJS): %.o : %.S
+	$(CC) $(CFLAGS) -c $< -o $@
+	$(STRIPTOOL) -x -R .note -R .comment $*.o
+
+$(COBJS): %.o : %.c
+	$(CC) $(CFLAGS) -c $< -o $@
+	$(STRIPTOOL) -x -R .note -R .comment $*.o
+
+ifeq ($(strip $(UCLIBC_PROFILING)),y)
+SAFECFLAGS := $(filter-out -g,$(CFLAGS))
+gmon-start.S: ../common/gmon-start.c
+	$(CC) $(SAFECFLAGS) -c $< -S -o $*.S
+gcrt1.o: $(CRT0_DEPS)
+endif
+
+headers:
+
+
+clean:
+	rm -f *.[oa] *~ core
+	rm -f bits/sysnum.h
+

+ 25 - 0
libc/sysdeps/linux/frv/__init_brk.c

@@ -0,0 +1,25 @@
+/* From libc-5.3.12 */
+
+#include <errno.h>
+#include <unistd.h>
+#include <sys/syscall.h>
+
+void * ___brk_addr = 0;
+
+#define __NR__brk __NR_brk
+_syscall1(void *, _brk, void *, ptr);
+
+int
+__init_brk (void)
+{
+    if (___brk_addr == 0)
+    {
+		___brk_addr = _brk(0);
+		if (___brk_addr == 0)
+		{
+		  __set_errno(ENOMEM);
+		  return -1;
+		}
+    }
+    return 0;
+}

+ 75 - 0
libc/sysdeps/linux/frv/__longjmp.S

@@ -0,0 +1,75 @@
+#define _SETJMP_H
+#define _ASM
+#include <bits/setjmp.h>
+
+# setjmp/longjmp for Frv.  The jmpbuf looks like this:
+#	
+# Register	jmpbuf offset
+# R16-R31	0x0-0x03c
+# R48-R63	0x40-0x7c
+# FR16-FR31     0x80-0xbc
+# FR48-FR63     0xc0-0xfc
+# LR            0x100
+# SP            0x104
+# FP            0x108
+#
+# R8 contains the pointer to jmpbuf
+
+	.text
+	.global	__longjmp
+	.type	__longjmp,@function
+__longjmp:
+	lddi	@(gr8,0), gr16
+	lddi	@(gr8,8), gr18
+	lddi 	@(gr8,16), gr20
+	lddi	@(gr8,24), gr22
+	lddi	@(gr8,32), gr24
+	lddi	@(gr8,40), gr26
+	lddi	@(gr8,48), gr28
+	lddi	@(gr8,56), gr30
+#if __FRV_GPR__ != 32
+	lddi	@(gr8,64), gr48
+	lddi	@(gr8,72), gr50
+	lddi	@(gr8,80), gr52
+	lddi	@(gr8,88), gr54
+	lddi	@(gr8,96), gr56
+	lddi	@(gr8,104), gr58
+	lddi	@(gr8,112), gr60
+	lddi	@(gr8,120), gr62
+#endif
+
+#if __FRV_FPR__ != 0
+	lddfi	@(gr8,128), fr16
+	lddfi	@(gr8,136), fr18
+	lddfi 	@(gr8,144), fr20
+	lddfi	@(gr8,152), fr22
+	lddfi	@(gr8,160), fr24
+	lddfi	@(gr8,168), fr26
+	lddfi	@(gr8,176), fr28
+	lddfi	@(gr8,184), fr30
+#if __FRV_FPR__ != 32
+	lddfi	@(gr8,192), fr48
+	lddfi	@(gr8,200), fr50
+	lddfi	@(gr8,208), fr52
+	lddfi	@(gr8,216), fr54
+	lddfi	@(gr8,224), fr56
+	lddfi	@(gr8,232), fr58
+	lddfi	@(gr8,240), fr60
+	lddfi	@(gr8,248), fr62
+#endif
+#endif
+
+        ldi     @(gr8,256), gr4
+	movgs   gr4,lr
+
+        ldi     @(gr8,260), sp
+        ldi     @(gr8,264), fp
+	
+# Value to return is in r9.  If zero, return 1
+	cmp	gr9, gr0, icc0
+	setlos	#1, gr8
+	ckne	icc0, cc4
+	cmov	gr9, gr8, cc4, 1
+	ret
+.Lend2:
+	.size	__longjmp,.Lend2-__longjmp

+ 48 - 0
libc/sysdeps/linux/frv/_mmap.c

@@ -0,0 +1,48 @@
+/* Copyright (C) 1997, 1998, 1999, 2002, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Daniel Jacobowitz <dan@debian.org>, 1999.
+
+   The GNU C Library 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.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+/* Massivly hacked up for uClibc by Erik Andersen */
+
+/* Extracted from ../common/mmap64.c by Alexandre Oliva <aoliva@redhat.com>
+
+   We don't want to use the old mmap interface.  */
+
+#include <features.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/syscall.h>
+#include <sys/mman.h>
+
+#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
+
+__ptr_t mmap(__ptr_t addr, size_t len, int prot, int flags, int fd, __off_t offset)
+{
+    if (offset & ((1 << MMAP2_PAGE_SHIFT) - 1)) {
+	__set_errno (EINVAL);
+	return MAP_FAILED;
+    }
+    return(__syscall_mmap2(addr, len, prot, flags, fd, (off_t) (offset >> MMAP2_PAGE_SHIFT)));
+}

+ 104 - 0
libc/sysdeps/linux/frv/bits/elf-fdpic.h

@@ -0,0 +1,104 @@
+/* Copyright 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
+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.
+
+The GNU C Library 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 the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#ifndef _BITS_ELF_FDPIC_H
+#define _BITS_ELF_FDPIC_H
+
+/* These data structures are described in the FDPIC ABI extension.
+   The kernel passes a process a memory map, such that for every LOAD
+   segment there is an elf32_fdpic_loadseg entry.  A pointer to an
+   elf32_fdpic_loadmap is passed in GR8 at start-up, and a pointer to
+   an additional such map is passed in GR9 for the interpreter, when
+   there is one.  */
+
+#include <elf.h>
+
+/* This data structure represents a PT_LOAD segment.  */
+struct elf32_fdpic_loadseg
+{
+  /* Core address to which the segment is mapped.  */
+  Elf32_Addr addr;
+  /* VMA recorded in the program header.  */
+  Elf32_Addr p_vaddr;
+  /* Size of this segment in memory.  */
+  Elf32_Word p_memsz;
+};
+
+struct elf32_fdpic_loadmap {
+  /* Protocol version number, must be zero.  */
+  Elf32_Half version;
+  /* Number of segments in this map.  */
+  Elf32_Half nsegs;
+  /* The actual memory map.  */
+  struct elf32_fdpic_loadseg segs[/*nsegs*/];
+};
+
+struct elf32_fdpic_loadaddr {
+  struct elf32_fdpic_loadmap *map;
+  void *got_value;
+};
+
+/* Map a pointer's VMA to its corresponding address according to the
+   load map.  */
+inline static void *
+__reloc_pointer (void *p,
+		 const struct elf32_fdpic_loadmap *map)
+{
+  int c;
+
+#if 0
+  if (map->version != 0)
+    /* Crash.  */
+    ((void(*)())0)();
+#endif
+
+  /* No special provision is made for NULL.  We don't want NULL
+     addresses to go through relocation, so they shouldn't be in
+     .rofixup sections, and, if they're present in dynamic
+     relocations, they shall be mapped to the NULL address without
+     undergoing relocations.  */
+
+  for (c = 0;
+       /* Take advantage of the fact that the loadmap is ordered by
+	  virtual addresses.  In general there will only be 2 entries,
+	  so it's not profitable to do a binary search.  */
+       c < map->nsegs && p >= (void*)map->segs[c].p_vaddr;
+       c++)
+    {
+      /* This should be computed as part of the pointer comparison
+	 above, but we want to use the carry in the comparison, so we
+	 can't convert it to an integer type beforehand.  */
+      unsigned long offset = p - (void*)map->segs[c].p_vaddr;
+      /* We explicitly refrain from checking for one-past-the-end.
+	 Zero-sized objects aren't legal, and it's expected that array
+	 addresses will be relocated before the addend that would make
+	 it one-past-the-end is added.  This gives us a reasonable speed
+	 up, and we couldn't possibly disambiguate all cases anyway.  */
+      if (offset < map->segs[c].p_memsz)
+	return (char*)map->segs[c].addr + offset;
+    }
+	     
+  /* We might want to crash instead.  */
+  return (void*)-1;
+}
+
+# define __RELOC_POINTER(ptr, loadaddr) \
+  (__reloc_pointer ((void*)(ptr), \
+		    (loadaddr).map))
+
+#endif /* _BITS_ELF_FDPIC_H */

+ 7 - 0
libc/sysdeps/linux/frv/bits/endian.h

@@ -0,0 +1,7 @@
+/* frv is little-endian.  */
+
+#ifndef _ENDIAN_H
+# error "Never use <bits/endian.h> directly; include <endian.h> instead."
+#endif
+
+#define __BYTE_ORDER __BIG_ENDIAN

+ 156 - 0
libc/sysdeps/linux/frv/bits/fcntl.h

@@ -0,0 +1,156 @@
+/* O_*, F_*, FD_* bit values for Linux.
+   Copyright (C) 1995, 1996, 1997, 1998, 2000 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
+   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.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#ifndef	_FCNTL_H
+# error "Never use <bits/fcntl.h> directly; include <fcntl.h> instead."
+#endif
+
+
+#include <sys/types.h>
+
+/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
+   located on an ext2 file system */
+#define O_ACCMODE	   0003
+#define O_RDONLY	     00
+#define O_WRONLY	     01
+#define O_RDWR		     02
+#define O_CREAT		   0100	/* not fcntl */
+#define O_EXCL		   0200	/* not fcntl */
+#define O_NOCTTY	   0400	/* not fcntl */
+#define O_TRUNC		  01000	/* not fcntl */
+#define O_APPEND	  02000
+#define O_NONBLOCK	  04000
+#define O_NDELAY	O_NONBLOCK
+#define O_SYNC		 010000
+#define O_FSYNC		 O_SYNC
+#define O_ASYNC		 020000
+
+#ifdef __USE_GNU
+# define O_DIRECT	 040000	/* Direct disk access.  */
+# define O_DIRECTORY	0200000	/* Must be a directory.  */
+# define O_NOFOLLOW	0400000	/* Do not follow links.  */
+# define O_STREAMING	04000000/* streaming access */
+#endif
+
+/* For now Linux has synchronisity options for data and read operations.
+   We define the symbols here but let them do the same as O_SYNC since
+   this is a superset.  */
+#if defined __USE_POSIX199309 || defined __USE_UNIX98
+# define O_DSYNC	O_SYNC	/* Synchronize data.  */
+# define O_RSYNC	O_SYNC	/* Synchronize read operations.  */
+#endif
+
+#ifdef __USE_LARGEFILE64
+# define O_LARGEFILE	0100000
+#endif
+
+/* Values for the second argument to `fcntl'.  */
+#define F_DUPFD		0	/* Duplicate file descriptor.  */
+#define F_GETFD		1	/* Get file descriptor flags.  */
+#define F_SETFD		2	/* Set file descriptor flags.  */
+#define F_GETFL		3	/* Get file status flags.  */
+#define F_SETFL		4	/* Set file status flags.  */
+#ifndef __USE_FILE_OFFSET64
+# define F_GETLK	5	/* Get record locking info.  */
+# define F_SETLK	6	/* Set record locking info (non-blocking).  */
+# define F_SETLKW	7	/* Set record locking info (blocking).  */
+#else
+# define F_GETLK	F_GETLK64  /* Get record locking info.  */
+# define F_SETLK	F_SETLK64  /* Set record locking info (non-blocking).*/
+# define F_SETLKW	F_SETLKW64 /* Set record locking info (blocking).  */
+#endif
+#define F_GETLK64	12	/* Get record locking info.  */
+#define F_SETLK64	13	/* Set record locking info (non-blocking).  */
+#define F_SETLKW64	14	/* Set record locking info (blocking).  */
+
+#if defined __USE_BSD || defined __USE_XOPEN2K
+# define F_SETOWN	8	/* Get owner of socket (receiver of SIGIO).  */
+# define F_GETOWN	9	/* Set owner of socket (receiver of SIGIO).  */
+#endif
+
+#ifdef __USE_GNU
+# define F_SETSIG	10	/* Set number of signal to be sent.  */
+# define F_GETSIG	11	/* Get number of signal to be sent.  */
+#endif
+
+/* For F_[GET|SET]FL.  */
+#define FD_CLOEXEC	1	/* actually anything with low bit set goes */
+
+/* For posix fcntl() and `l_type' field of a `struct flock' for lockf().  */
+#define F_RDLCK		0	/* Read lock.  */
+#define F_WRLCK		1	/* Write lock.  */
+#define F_UNLCK		2	/* Remove lock.  */
+
+/* For old implementation of bsd flock().  */
+#define F_EXLCK		4	/* or 3 */
+#define F_SHLCK		8	/* or 4 */
+
+#ifdef __USE_BSD
+/* Operations for bsd flock(), also used by the kernel implementation.  */
+# define LOCK_SH	1	/* shared lock */
+# define LOCK_EX	2	/* exclusive lock */
+# define LOCK_NB	4	/* or'd with one of the above to prevent
+				   blocking */
+# define LOCK_UN	8	/* remove lock */
+#endif
+
+struct flock
+  {
+    short int l_type;	/* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK.  */
+    short int l_whence;	/* Where `l_start' is relative to (like `lseek').  */
+#ifndef __USE_FILE_OFFSET64
+    __off_t l_start;	/* Offset where the lock begins.  */
+    __off_t l_len;	/* Size of the locked area; zero means until EOF.  */
+#else
+    __off64_t l_start;	/* Offset where the lock begins.  */
+    __off64_t l_len;	/* Size of the locked area; zero means until EOF.  */
+#endif
+    __pid_t l_pid;	/* Process holding the lock.  */
+  };
+
+#ifdef __USE_LARGEFILE64
+struct flock64
+  {
+    short int l_type;	/* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK.  */
+    short int l_whence;	/* Where `l_start' is relative to (like `lseek').  */
+    __off64_t l_start;	/* Offset where the lock begins.  */
+    __off64_t l_len;	/* Size of the locked area; zero means until EOF.  */
+    __pid_t l_pid;	/* Process holding the lock.  */
+  };
+#endif
+
+/* Define some more compatibility macros to be backward compatible with
+   BSD systems which did not managed to hide these kernel macros.  */
+#ifdef	__USE_BSD
+# define FAPPEND	O_APPEND
+# define FFSYNC		O_FSYNC
+# define FASYNC		O_ASYNC
+# define FNONBLOCK	O_NONBLOCK
+# define FNDELAY	O_NDELAY
+#endif /* Use BSD.  */
+
+/* Advise to `posix_fadvise'.  */
+#ifdef __USE_XOPEN2K
+# define POSIX_FADV_NORMAL	0 /* No further special treatment.  */
+# define POSIX_FADV_RANDOM	1 /* Expect random page references.  */
+# define POSIX_FADV_SEQUENTIAL	2 /* Expect sequential page references.  */
+# define POSIX_FADV_WILLNEED	3 /* Will need these pages.  */
+# define POSIX_FADV_DONTNEED	4 /* Don't need these pages.  */
+# define POSIX_FADV_NOREUSE	5 /* Data will be accessed once.  */
+#endif

+ 57 - 0
libc/sysdeps/linux/frv/bits/kernel_stat.h

@@ -0,0 +1,57 @@
+#ifndef _BITS_STAT_STRUCT_H
+#define _BITS_STAT_STRUCT_H
+
+/* This file provides whatever this particular arch's kernel thinks 
+ * struct kernel_stat should look like...  It turns out each arch has a 
+ * different opinion on the subject... */
+
+struct kernel_stat {
+	unsigned short st_dev;
+	unsigned short __pad1;
+	unsigned long st_ino;
+	unsigned short st_mode;
+	unsigned short st_nlink;
+	unsigned short st_uid;
+	unsigned short st_gid;
+	unsigned short st_rdev;
+	unsigned short __pad2;
+	unsigned long  st_size;
+	unsigned long  st_blksize;
+	unsigned long  st_blocks;
+	unsigned long  st_atime;
+	unsigned long  __unused1;
+	unsigned long  st_mtime;
+	unsigned long  __unused2;
+	unsigned long  st_ctime;
+	unsigned long  __unused3;
+	unsigned long  __unused4;
+	unsigned long  __unused5;
+};
+
+struct kernel_stat64 {
+	unsigned char	__pad0[6];
+	unsigned short	st_dev;
+	unsigned char	__pad1[2];
+#define _HAVE_STAT64___ST_INO
+	unsigned long	__st_ino;
+	unsigned int	st_mode;
+	unsigned int	st_nlink;
+	unsigned long	st_uid;
+	unsigned long	st_gid;
+	unsigned char	__pad2[6];
+	unsigned short	st_rdev;
+	unsigned char	__pad3[2];
+	long long	st_size;
+	unsigned long	st_blksize;
+	unsigned long	__pad4;		/* future possible st_blocks high bits */
+	unsigned long	st_blocks;	/* Number 512-byte blocks allocated. */
+	unsigned long	st_atime;
+	unsigned long	__pad5;
+	unsigned long	st_mtime;
+	unsigned long	__pad6;
+	unsigned long	st_ctime;
+	unsigned long	__pad7;		/* will be high 32 bits of ctime someday */
+	unsigned long long	st_ino;
+};
+
+#endif	/*  _BITS_STAT_STRUCT_H */

+ 43 - 0
libc/sysdeps/linux/frv/bits/kernel_types.h

@@ -0,0 +1,43 @@
+/* Note that we use the exact same include guard #define names
+ * as asm/posix_types.h.  This will avoid gratuitous conflicts 
+ * with the posix_types.h kernel header, and will ensure that 
+ * our private content, and not the kernel header, will win.
+ *  -Erik
+ */
+#ifndef _ASM_POSIX_TYPES_H
+#define _ASM_POSIX_TYPES_H
+
+typedef unsigned short	__kernel_dev_t;
+typedef unsigned long	__kernel_ino_t;
+typedef unsigned short	__kernel_mode_t;
+typedef unsigned short	__kernel_nlink_t;
+typedef long		__kernel_off_t;
+typedef int		__kernel_pid_t;
+typedef unsigned short	__kernel_ipc_pid_t;
+typedef unsigned short	__kernel_uid_t;
+typedef unsigned short	__kernel_gid_t;
+typedef unsigned int	__kernel_size_t;
+typedef int		__kernel_ssize_t;
+typedef int		__kernel_ptrdiff_t;
+typedef long		__kernel_time_t;
+typedef long		__kernel_suseconds_t;
+typedef long		__kernel_clock_t;
+typedef int		__kernel_daddr_t;
+typedef char *		__kernel_caddr_t;
+typedef unsigned short	__kernel_uid16_t;
+typedef unsigned short	__kernel_gid16_t;
+typedef unsigned int	__kernel_uid32_t;
+typedef unsigned int	__kernel_gid32_t;
+typedef unsigned short	__kernel_old_uid_t;
+typedef unsigned short	__kernel_old_gid_t;
+typedef long long	__kernel_loff_t;
+
+typedef struct {
+#ifdef __USE_ALL
+	int val[2];
+#else
+	int __val[2];
+#endif
+} __kernel_fsid_t;
+
+#endif /* _ASM_POSIX_TYPES_H */

+ 75 - 0
libc/sysdeps/linux/frv/bits/mman.h

@@ -0,0 +1,75 @@
+/* Definitions for POSIX memory map interface.  Linux/frv version.
+   Copyright (C) 1997 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
+   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.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#ifndef _SYS_MMAN_H
+# error "Never use <bits/mman.h> directly; include <sys/mman.h> instead."
+#endif
+
+/* The following definitions basically come from the kernel headers.
+   But the kernel header is not namespace clean.  */
+
+
+/* Protections are chosen from these bits, OR'd together.  The
+   implementation does not necessarily support PROT_EXEC or PROT_WRITE
+   without PROT_READ.  The only guarantees are that no writing will be
+   allowed without PROT_WRITE and no access will be allowed for PROT_NONE. */
+
+#define PROT_READ	0x1		/* Page can be read.  */
+#define PROT_WRITE	0x2		/* Page can be written.  */
+#define PROT_EXEC	0x4		/* Page can be executed.  */
+#define PROT_NONE	0x0		/* Page can not be accessed.  */
+
+/* Sharing types (must choose one and only one of these).  */
+#define MAP_SHARED	0x01		/* Share changes.  */
+#define MAP_PRIVATE	0x02		/* Changes are private.  */
+#ifdef __USE_MISC
+# define MAP_TYPE	0x0f		/* Mask for type of mapping.  */
+#endif
+
+/* Other flags.  */
+#define MAP_FIXED	0x10		/* Interpret addr exactly.  */
+#ifdef __USE_MISC
+# define MAP_FILE	0
+# define MAP_ANONYMOUS	0x20		/* Don't use a file.  */
+# define MAP_ANON	MAP_ANONYMOUS
+#endif
+
+/* These are Linux-specific.  */
+#ifdef __USE_MISC
+# define MAP_GROWSDOWN	0x0100		/* Stack-like segment.  */
+# define MAP_DENYWRITE	0x0800		/* ETXTBSY */
+# define MAP_EXECUTABLE	0x1000		/* Mark it as an executable.  */
+# define MAP_LOCKED	0x2000		/* Lock the mapping.  */
+# define MAP_NORESERVE	0x4000		/* Don't check for reservations.  */
+#endif
+
+/* Flags to `msync'.  */
+#define MS_ASYNC	1		/* Sync memory asynchronously.  */
+#define MS_SYNC		4		/* Synchronous memory sync.  */
+#define MS_INVALIDATE	2		/* Invalidate the caches.  */
+
+/* Flags for `mlockall'.  */
+#define MCL_CURRENT	1		/* Lock all currently mapped pages.  */
+#define MCL_FUTURE	2		/* Lock all additions to address
+					   space.  */
+
+/* Flags for `mremap'.  */
+#ifdef __USE_GNU
+# define MREMAP_MAYMOVE	1
+#endif

+ 53 - 0
libc/sysdeps/linux/frv/bits/setjmp.h

@@ -0,0 +1,53 @@
+/* Copyright (C) 1999, 2000, 2003, 2004 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
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library 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 Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+/* Define the machine-dependent type `jmp_buf'.  FRV version. */
+
+#ifndef _SETJMP_H
+# error "Never include <bits/setjmp.h> directly; use <setjmp.h> instead."
+#endif
+
+#define	__SETJMP_NUM_INT	32		/* number of integer registers to save */
+#define	__SETJMP_NUM_DBL	32		/* number of double registers to save */
+
+#define	__SETJMP_INT(x)	(x)
+#define	__SETJMP_DBL(x)	(__SETJMP_NUM_INT+(x))
+#define	__SETJMP_LR	(__SETJMP_NUM_INT+__SETJMP_NUM_DBL)
+#define __SETJMP_SP	(__SETJMP_LR+1)
+#define __SETJMP_FP	(__SETJMP_SP+1)
+
+
+#ifndef _ASM
+typedef struct
+/* Demand 64-bit alignment such that we can use std/ldd in
+   setjmp/longjmp.  */
+__attribute__((__aligned__(8)))
+  {
+    /* Callee-saved registers.  */
+    unsigned long __ints[__SETJMP_NUM_INT];	/* integer registers */
+    unsigned long __dbls[__SETJMP_NUM_DBL];	/* double registers */
+    unsigned long __lr;				/* linkage register */
+    unsigned long __sp;				/* stack pointer */
+    unsigned long __fp;				/* frame pointer */
+  } __jmp_buf[1];
+#endif
+
+/* Test if longjmp to JMPBUF would unwind the frame
+   containing a local variable at ADDRESS.  */
+#define _JMPBUF_UNWINDS(jmpbuf, address) \
+  ((unsigned long) (address) < (jmpbuf)->__sp)

+ 28 - 0
libc/sysdeps/linux/frv/bits/stackinfo.h

@@ -0,0 +1,28 @@
+/* Copyright (C) 2001 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
+   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.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+/* This file contains a bit of information about the stack allocation
+   of the processor.  */
+
+#ifndef _STACKINFO_H
+#define _STACKINFO_H	1
+
+/* On FRV the stack grows down.  */
+#define _STACK_GROWS_DOWN	1
+
+#endif	/* stackinfo.h */

+ 129 - 0
libc/sysdeps/linux/frv/bits/syscalls.h

@@ -0,0 +1,129 @@
+#ifndef _BITS_SYSCALLS_H
+#define _BITS_SYSCALLS_H
+#ifndef _SYSCALL_H
+# error "Never use <bits/syscalls.h> directly; include <sys/syscall.h> instead."
+#endif
+
+/* This includes the `__NR_<name>' syscall numbers taken from the Linux kernel
+ * header files.  It also defines the traditional `SYS_<name>' macros for older
+ * programs.  */
+#include <bits/sysnum.h>
+
+#ifndef __set_errno
+# define __set_errno(val) ((*__errno_location ()) = (val))
+#endif
+#ifndef SYS_ify
+# define SYS_ify(syscall_name)  (__NR_##syscall_name)
+#endif
+
+#ifndef __ASSEMBLER__
+
+/* user-visible error numbers are in the range -1 - -4095: see <asm-frv/errno.h> */
+#define __syscall_return(type, res) \
+do { \
+        unsigned long __sr2 = (res);		    			    \
+	if ((unsigned long)(__sr2) >= (unsigned long)(-4095)) {		    \
+		__set_errno (-(__sr2));					    \
+		__sr2 = -1; 						    \
+	}								    \
+	return (type) (__sr2); 						    \
+} while (0)
+
+/* XXX - _foo needs to be __foo, while __NR_bar could be _NR_bar. */
+
+#define _syscall0(type,name) \
+type name(void) \
+{ \
+register unsigned long __scnum __asm__ ("gr7") = (__NR_##name); 	    \
+register unsigned long __sc0 __asm__ ("gr8");				    \
+__asm__ __volatile__ ("tra	gr0,gr0"				    \
+	: "=r" (__sc0) 							    \
+	: "r" (__scnum)); 						    \
+__syscall_return(type,__sc0); 						    \
+}
+
+#define _syscall1(type,name,type1,arg1) \
+type name(type1 arg1) \
+{ \
+register unsigned long __scnum __asm__ ("gr7") = (__NR_##name);		    \
+register unsigned long __sc0 __asm__ ("gr8") = (unsigned long) arg1;	    \
+__asm__ __volatile__ ("tra	gr0,gr0"				    \
+	: "+r" (__sc0) 							    \
+	: "r" (__scnum));						    \
+__syscall_return(type,__sc0);	 					    \
+}
+
+#define _syscall2(type,name,type1,arg1,type2,arg2) \
+type name(type1 arg1,type2 arg2) \
+{ \
+register unsigned long __scnum __asm__ ("gr7") = (__NR_##name);		    \
+register unsigned long __sc0 __asm__ ("gr8") = (unsigned long) arg1;	    \
+register unsigned long __sc1 __asm__ ("gr9") = (unsigned long) arg2;	    \
+__asm__ __volatile__ ("tra	gr0,gr0"				    \
+	: "+r" (__sc0)	 						    \
+	: "r" (__scnum), "r" (__sc1));					    \
+__syscall_return(type,__sc0);	 					    \
+}
+
+#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
+type name(type1 arg1,type2 arg2,type3 arg3) \
+{ \
+register unsigned long __scnum __asm__ ("gr7") = (__NR_##name);		    \
+register unsigned long __sc0 __asm__ ("gr8") = (unsigned long) arg1;	    \
+register unsigned long __sc1 __asm__ ("gr9") = (unsigned long) arg2;	    \
+register unsigned long __sc2 __asm__ ("gr10") = (unsigned long) arg3;	    \
+__asm__ __volatile__ ("tra	gr0,gr0"				    \
+	: "+r" (__sc0)	 						    \
+	: "r" (__scnum), "r" (__sc1), "r" (__sc2));			    \
+__syscall_return(type,__sc0);	 					    \
+}
+
+#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
+type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
+{ \
+register unsigned long __scnum __asm__ ("gr7") = (__NR_##name);		    \
+register unsigned long __sc0 __asm__ ("gr8") = (unsigned long) arg1;	    \
+register unsigned long __sc1 __asm__ ("gr9") = (unsigned long) arg2;	    \
+register unsigned long __sc2 __asm__ ("gr10") = (unsigned long) arg3;	    \
+register unsigned long __sc3 __asm__ ("gr11") = (unsigned long) arg4;	    \
+__asm__ __volatile__ ("tra	gr0,gr0"				    \
+	: "+r" (__sc0)	 						    \
+	: "r" (__scnum), "r" (__sc1), "r" (__sc2), "r" (__sc3));	    \
+__syscall_return(type,__sc0);	 					    \
+}
+
+#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \
+type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \
+{ \
+register unsigned long __scnum __asm__ ("gr7") = (__NR_##name);		    \
+register unsigned long __sc0 __asm__ ("gr8") = (unsigned long) arg1;	    \
+register unsigned long __sc1 __asm__ ("gr9") = (unsigned long) arg2;	    \
+register unsigned long __sc2 __asm__ ("gr10") = (unsigned long) arg3;	    \
+register unsigned long __sc3 __asm__ ("gr11") = (unsigned long) arg4;	    \
+register unsigned long __sc4 __asm__ ("gr12") = (unsigned long) arg5;	    \
+__asm__ __volatile__ ("tra	gr0,gr0"				    \
+	: "+r" (__sc0)	 						    \
+	: "r" (__scnum), "r" (__sc1), "r" (__sc2),		 	    \
+	  "r" (__sc3), "r" (__sc4));					    \
+__syscall_return(type,__sc0);	 					    \
+}
+
+#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5, type6, arg6) \
+type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5, type6 arg6) \
+{ \
+register unsigned long __scnum __asm__ ("gr7") = (__NR_##name);		    \
+register unsigned long __sc0 __asm__ ("gr8") = (unsigned long) arg1;	    \
+register unsigned long __sc1 __asm__ ("gr9") = (unsigned long) arg2;	    \
+register unsigned long __sc2 __asm__ ("gr10") = (unsigned long) arg3;	    \
+register unsigned long __sc3 __asm__ ("gr11") = (unsigned long) arg4;	    \
+register unsigned long __sc4 __asm__ ("gr12") = (unsigned long) arg5;	    \
+register unsigned long __sc5 __asm__ ("gr13") = (unsigned long) arg6;	    \
+__asm__ __volatile__ ("tra	gr0,gr0"				    \
+	: "+r" (__sc0)	 						    \
+	: "r" (__scnum), "r" (__sc1), "r" (__sc2),			    \
+	  "r" (__sc3), "r" (__sc4), "r" (__sc5));			    \
+__syscall_return(type,__sc0);	 					    \
+}
+
+#endif /* __ASSEMBLER__ */
+#endif /* _BITS_SYSCALLS_H */

+ 19 - 0
libc/sysdeps/linux/frv/bits/wordsize.h

@@ -0,0 +1,19 @@
+/* Copyright (C) 1999 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
+   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.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#define __WORDSIZE	32

+ 22 - 0
libc/sysdeps/linux/frv/brk.c

@@ -0,0 +1,22 @@
+/* From libc-5.3.12 */
+
+#include <errno.h>
+#include <unistd.h>
+#include <sys/syscall.h>
+
+extern void * ___brk_addr;
+
+extern int __init_brk (void);
+extern void *_brk(void *ptr);
+
+int brk(void * end_data_seg)
+{
+    if (__init_brk () == 0)
+    {
+		___brk_addr = _brk(end_data_seg);
+		if (___brk_addr == end_data_seg)
+			return 0;
+		__set_errno(ENOMEM);
+    }
+    return -1;
+}

+ 83 - 0
libc/sysdeps/linux/frv/clone.S

@@ -0,0 +1,83 @@
+/* Copyright (C) 2003 Free Software Foudnation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Alexandre Oliva <aoliva@redhat.com>, 2003.
+
+   The GNU C Library 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.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+/* clone() is even more special than fork() as it mucks with stacks
+   and invokes a function in the right context after its all over.  */
+
+#include <asm/unistd.h>
+#define _ERRNO_H	1
+#include <bits/errno.h>
+
+	.text
+	.globl	__clone
+	.type __clone,@function
+/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg) */
+__clone:
+	/* Sanity check arguments.  */
+	cmp.p	gr8, gr0, icc0
+	cmp	gr9, gr0, icc1
+	mov.p	gr8, gr4
+	beq	icc0, #0, .Lerror
+	mov.p	gr11, gr5
+	beq	icc1, #0, .Lerror
+
+	mov.p	gr10, gr8
+	setlos	#__NR_clone, gr7
+	tra	gr0,gr0
+
+	cmp	gr8, gr0, icc0
+	bgtlr	icc0, #1
+	beq	icc0, #0, .Lthread_start
+
+.Lsys_error:
+	sethi.p	#gotofffuncdeschi(__syscall_error), gr14
+	setlo	#gotofffuncdesclo(__syscall_error), gr14
+	ldd	@(gr14, gr15), gr14
+	jmpl	@(gr14, gr0)
+
+.Lerror:
+	setlos.p #-EINVAL, gr7
+	bra	.Lsys_error
+
+###############################################################################
+#
+# come here as the new thread [GR4 is fn, GR5 is arg]
+#
+###############################################################################
+.Lthread_start:
+	/* Save the PIC register.  */
+	mov	gr15, gr17
+
+	/* Call the user's function.  */
+	ldd.p	@(gr4, gr0), gr14
+	mov	gr5, gr8
+	calll	@(gr14, gr0)
+
+	/* Call _exit, rather simply inlining the syscall, such that
+	   breakpoints work.*/
+
+	mov.p	gr17, gr15
+	call	_exit
+
+	/* Should never get here.  */
+	jmpl	@(gr0, gr0)
+	.size	__clone,.-__clone
+
+.weak	clone
+	clone = __clone

+ 110 - 0
libc/sysdeps/linux/frv/crt0.S

@@ -0,0 +1,110 @@
+/* Copyright (C) 1991, 1992, 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
+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.
+
+The GNU C Library 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 the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+
+/*  Based on ../i386/crt0.S and newlib's libgloss/frv/crt0.S  */
+
+/*
+    When we enter this piece of code, the program stack looks like this:
+        argc            argument counter (integer)
+        argv[0]         program name (pointer)
+        argv[1...N]     program args (pointers)
+        argv[argc-1]    end of args (integer)
+	NULL
+        env[0...N]      environment variables (pointers)
+        NULL
+
+    Also, GR16 holds a pointer to a memory map.  */
+
+#include <features.h>
+
+	.text
+	.global _start
+	.type	_start,%function
+#if defined L_crt0 || defined L_Scrt0 || ! defined __UCLIBC_CTOR_DTOR__
+	.type __uClibc_main,%function
+#else
+	.weak	_init
+	.weak	_fini
+	.type	__uClibc_start_main,%function
+#endif
+/* Stick in a dummy reference to main(), so that if an application
+ * is linking when the main() function is in a static library (.a)
+ * we can be sure that main() actually gets linked in */
+	.type	main,%function
+_start:
+	/* At program start-up, gr16 contains a pointer to a memory
+	   map, that we use to relocate addresses.  */
+	call	.Lcall
+.Lcall:
+	movsg	lr, gr4
+	sethi.p	#gprelhi(.Lcall), gr5
+	setlo	#gprello(.Lcall), gr5
+	sub.p	gr4, gr5, gr4
+	/* gr4 now holds the _gp address.  */
+	
+	mov	gr16, gr8
+	sethi.p #gprelhi(__ROFIXUP_LIST__), gr9
+	sethi	#gprelhi(__ROFIXUP_END__), gr10
+	setlo.p #gprello(__ROFIXUP_LIST__), gr9
+	setlo	#gprello(__ROFIXUP_END__), gr10
+	add.p	gr9, gr4, gr9
+	add	gr10, gr4, gr10
+	call	__self_reloc
+	mov.p	gr8, gr17
+	mov	gr8, gr15
+	/* gr17 now holds the self-relocated _GLOBAL_OFFSET_TABLE_
+	address, because the linker added its unrelocated address as
+	the last entry in the ROFIXUP list, and __self_reloc returns
+	the last entry, relocated.  */
+
+	/* Prepare arguments for uClibc main.  */
+	ld	@(sp, gr0), gr8
+	slli	gr8, #2, gr10
+	add	sp, gr10, gr10
+	addi.p	sp, #4, gr9
+	addi	gr10, #8, gr10
+
+	/* Set up an invalid (NULL return address, NULL frame pointer)
+	   callers stack frame so anybody unrolling the stack knows where
+	   to stop */
+	mov	gr0, fp
+	movgs	gr0, lr
+
+#if (defined L_crt1 || defined L_gcrt1 || defined L_Scrt1) && defined __UCLIBC_CTOR_DTOR__
+	/* Pass .init and .fini arguments to __uClibc_start_main().  */
+	sethi.p	#gotfuncdeschi(_init), gr11
+	sethi	#gotfuncdeschi(_fini), gr12
+	setlo.p	#gotfuncdesclo(_init), gr11
+	setlo	#gotfuncdesclo(_fini), gr12
+	ld.p	@(gr11, gr17), gr11
+	mov	gr17, gr15
+	ld.p	@(gr12, gr17), gr12
+	call	__uClibc_start_main
+#else
+	mov.p	gr17, gr15
+	call	__uClibc_main
+#endif	
+
+	/* Crash if somehow `exit' returns anyways.  */
+	jmpl	@(gr0,gr0)
+.size _start,.-_start
+
+#if defined L_gcrt1 && defined __UCLIBC_PROFILING__
+# include "./gmon-start.S"
+#endif

+ 41 - 0
libc/sysdeps/linux/frv/crti.S

@@ -0,0 +1,41 @@
+/* Copyright (C) 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
+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.
+
+The GNU C Library 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 the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+	.section .init,"x"
+	.p2align 2
+	.globl _init
+	.type	_init, @function
+_init:
+	addi sp,#-16,sp
+	st.p fp, @(sp,gr0)
+	mov sp, fp
+	movsg lr, gr5
+	sti gr15, @(fp,4) 
+	sti gr5, @(fp,8)
+	
+	.section .fini,"x"
+	.p2align 2
+	.globl _fini
+	.type	_fini, @function
+_fini:
+	addi sp,#-16,sp
+	st.p fp, @(sp,gr0)
+	mov sp, fp
+	movsg lr, gr5
+	sti gr15, @(fp,4)
+	sti gr5, @(fp,8)

+ 35 - 0
libc/sysdeps/linux/frv/crtn.S

@@ -0,0 +1,35 @@
+/* Copyright (C) 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
+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.
+
+The GNU C Library 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 the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+	.section .init,"x"
+	.globl _init
+	.type	_init, @function
+	ldi @(fp,8), gr5
+	ld @(sp,gr0), fp
+	addi sp,#16,sp
+	jmpl @(gr5,gr0)
+	.size	_init, .-_init
+	
+	.section .fini,"x"
+	.globl _fini
+	.type	_fini, @function
+	ldi @(fp,8), gr5
+	ld @(sp,gr0), fp
+	addi sp,#16,sp
+	jmpl @(gr5,gr0)
+	.size	_fini, .-_fini

+ 118 - 0
libc/sysdeps/linux/frv/crtreloc.c

@@ -0,0 +1,118 @@
+/* Copyright (C) 2003 Free Software Foundation, Inc.
+   written by Alexandre Oliva <aoliva@redhat.com>
+This file is part of the GNU C Library.
+
+The GNU C Library 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.
+
+The GNU C Library 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 the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#define _GNU_SOURCE
+#include <link.h>
+
+#include <sys/types.h>
+
+#include <elf.h>
+#include <bits/elf-fdpic.h>
+
+/* This file is to be compiled into crt object files, to enable
+   executables to easily self-relocate.  */
+
+#define hidden __attribute__((__visibility__("hidden")))
+
+/* Compute the runtime address of pointer in the range [p,e), and then
+   map the pointer pointed by it.  */
+inline static void ***
+reloc_range_indirect (void ***p, void ***e,
+		      const struct elf32_fdpic_loadmap *map)
+{
+  while (p < e)
+    {
+      void *ptr = __reloc_pointer (*p, map);
+      if (ptr)
+	{
+	  void *pt;
+	  if ((long)ptr & 3)
+	    __builtin_memcpy(&pt, ptr, sizeof(pt));
+	  else
+	    pt = *(void**)ptr;
+	  pt = __reloc_pointer (pt, map);
+	  if ((long)ptr & 3)
+	    __builtin_memcpy(ptr, &pt, sizeof(pt));
+	  else
+	    *(void**)ptr = pt;
+	}
+      p++;
+    }
+  return p;
+}
+
+/* Call __reloc_range_indirect for the given range except for the last
+   entry, whose contents are only relocated.  It's expected to hold
+   the GOT value.  */
+void* hidden
+__self_reloc (const struct elf32_fdpic_loadmap *map,
+	      void ***p, void ***e)
+{
+  p = reloc_range_indirect (p, e-1, map);
+
+  if (p >= e)
+    return (void*)-1;
+  
+  return __reloc_pointer (*p, map);
+}
+
+#if 0
+/* These are other functions that might be useful, but that we don't
+   need.  */
+
+/* Remap pointers in [p,e).  */
+inline static void**
+reloc_range (void **p, void **e,
+	     const struct elf32_fdpic_loadmap *map)
+{
+  while (p < e)
+    {
+      *p = __reloc_pointer (*p, map);
+      p++;
+    }
+  return p;
+}
+
+/* Remap p, adjust e by the same offset, then map the pointers in the
+   range determined by them.  */
+void hidden
+__reloc_range (const struct elf32_fdpic_loadmap *map,
+	       void **p, void **e)
+{
+  void **old = p;
+
+  p = __reloc_pointer (p, map);
+  e += p - old;
+  reloc_range (p, e, map);
+}
+
+/* Remap p, adjust e by the same offset, then map pointers referenced
+   by the (unadjusted) pointers in the range.  Return the relocated
+   value of the last pointer in the range.  */
+void* hidden
+__reloc_range_indirect (const struct elf32_fdpic_loadmap *map,
+			void ***p, void ***e)
+{
+  void ***old = p;
+
+  p = __reloc_pointer (p, map);
+  e += p - old;
+  return reloc_range_indirect (p, e, map);
+}
+#endif

+ 43 - 0
libc/sysdeps/linux/frv/dl-iterate-phdr.c

@@ -0,0 +1,43 @@
+/* Copyright 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
+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.
+
+The GNU C Library 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 the GNU C Library; see the file COPYING.LIB.  If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA.  */
+
+#define _GNU_SOURCE
+#include <link.h>
+
+extern int __attribute__((__weak__))
+__dl_iterate_phdr (int (*callback) (struct dl_phdr_info *info,
+				    size_t size, void *data),
+		   void *data);
+
+/* Define it as a pointer, such that we get a pointer to the global
+   function descriptor, that won't be optimized away by the
+   linker.  */
+static int (*ptr) (int (*callback) (struct dl_phdr_info *info,
+				    size_t size, void *data),
+		   void *data) = __dl_iterate_phdr;
+
+int
+dl_iterate_phdr (int (*callback) (struct dl_phdr_info *info,
+				  size_t size, void *data),
+		 void *data)
+{
+  if (ptr)
+    return ptr (callback, data);
+
+  return 0;
+}

+ 25 - 0
libc/sysdeps/linux/frv/sbrk.c

@@ -0,0 +1,25 @@
+/* From libc-5.3.12 */
+
+#include <errno.h>
+#include <unistd.h>
+#include <sys/syscall.h>
+
+extern void * ___brk_addr;
+
+extern int __init_brk (void);
+extern void *_brk(void *ptr);
+
+void *
+sbrk(intptr_t increment)
+{
+    if (__init_brk () == 0)
+    {
+		char * tmp = (char*)___brk_addr+increment;
+		___brk_addr = _brk(tmp);
+		if (___brk_addr == tmp)
+			return tmp-increment;
+		__set_errno(ENOMEM);
+		return ((void *) -1);
+    }
+    return ((void *) -1);
+}

+ 95 - 0
libc/sysdeps/linux/frv/setjmp.S

@@ -0,0 +1,95 @@
+#include <features.h>
+#define _SETJMP_H
+#define _ASM
+#include <bits/setjmp.h>
+
+	.text
+
+/* This just does a tail-call to `__sigsetjmp (ARG, 0)'.
+   We cannot do it in C because it must be a tail-call, so frame-unwinding
+   in setjmp doesn't clobber the state restored by longjmp.  */
+
+	.global _setjmp
+	.type	_setjmp,@function
+_setjmp:
+	setlos	#0, gr9
+	bra	.Lsigsetjmp_intern
+	.size	_setjmp,.-_setjmp
+	
+/* This just does a tail-call to `__sigsetjmp (ARG, 1)'.
+   We cannot do it in C because it must be a tail-call, so frame-unwinding
+   in setjmp doesn't clobber the state restored by longjmp.  */
+
+	.align 4
+	.type	setjmp,@function
+	.globl	setjmp
+setjmp:	
+	setlos	#1, gr9
+	bra	.Lsigsetjmp_intern
+	.size	setjmp,.-setjmp
+	
+# setjmp/longjmp for Frv.  The jmpbuf looks like this:
+#	
+# Register	jmpbuf offset
+# R16-R31	0x0-0x03c
+# R48-R63	0x40-0x7c
+# FR16-FR31     0x80-0xbc
+# FR48-FR63     0xc0-0xfc
+# LR            0x100
+# SP            0x104
+# FP            0x108
+
+	.global	__sigsetjmp
+	.type	__sigsetjmp,@function
+__sigsetjmp:
+.Lsigsetjmp_intern:
+	stdi	gr16, @(gr8,0)
+	stdi	gr18, @(gr8,8)
+	stdi 	gr20, @(gr8,16)
+	stdi	gr22, @(gr8,24)
+	stdi	gr24, @(gr8,32)
+	stdi	gr26, @(gr8,40)
+	stdi	gr28, @(gr8,48)
+	stdi	gr30, @(gr8,56)
+#if __FRV_GPR__ != 32
+	stdi	gr48, @(gr8,64)
+	stdi	gr50, @(gr8,72)
+	stdi	gr52, @(gr8,80)
+	stdi	gr54, @(gr8,88)
+	stdi	gr56, @(gr8,96)
+	stdi	gr58, @(gr8,104)
+	stdi	gr60, @(gr8,112)
+	stdi	gr62, @(gr8,120)
+#endif
+
+#if __FRV_FPR__ != 0
+	stdfi	fr16, @(gr8,128)
+	stdfi	fr18, @(gr8,136)
+	stdfi 	fr20, @(gr8,144)
+	stdfi	fr22, @(gr8,152)
+	stdfi	fr24, @(gr8,160)
+	stdfi	fr26, @(gr8,168)
+	stdfi	fr28, @(gr8,176)
+	stdfi	fr30, @(gr8,184)
+#if __FRV_FPR__ != 32
+	stdfi	fr48, @(gr8,192)
+	stdfi	fr50, @(gr8,200)
+	stdfi	fr52, @(gr8,208)
+	stdfi	fr54, @(gr8,216)
+	stdfi	fr56, @(gr8,224)
+	stdfi	fr58, @(gr8,232)
+	stdfi	fr60, @(gr8,240)
+	stdfi	fr62, @(gr8,248)
+#endif
+#endif
+
+        movsg	lr, gr4
+	sti     gr4, @(gr8,256)
+	sti     sp, @(gr8,260)
+	sti     fp, @(gr8,264)
+	
+	sethi.p	#gotofffuncdeschi(__sigjmp_save), gr4
+	setlo	#gotofffuncdesclo(__sigjmp_save), gr4
+	ldd	@(gr15, gr4), gr14
+	jmpl	@(gr14, gr0)
+	.size	__sigsetjmp,.-__sigsetjmp

+ 125 - 0
libc/sysdeps/linux/frv/sys/procfs.h

@@ -0,0 +1,125 @@
+/* Copyright (C) 1996, 1997, 1999, 2000, 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
+   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.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#ifndef _SYS_PROCFS_H
+#define _SYS_PROCFS_H	1
+
+/* This is somewhat modelled after the file of the same name on SVR4
+   systems.  It provides a definition of the core file format for ELF
+   used on Linux.  It doesn't have anything to do with the /proc file
+   system, even though Linux has one.
+
+   Anyway, the whole purpose of this file is for GDB and GDB only.
+   Don't read too much into it.  Don't use it for anything other than
+   GDB unless you know what you are doing.  */
+
+#include <features.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/user.h>
+
+__BEGIN_DECLS
+
+/* Type for a general-purpose register.  */
+typedef unsigned long elf_greg_t;
+
+/* And the whole bunch of them.  We could have used `struct
+   user_regs_struct' directly in the typedef, but tradition says that
+   the register set is an array, which does have some peculiar
+   semantics, so leave it that way.  */
+#define ELF_NGREG (sizeof (struct user_int_regs) / sizeof(elf_greg_t))
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+
+/* Register set for the floating-point registers.  */
+typedef struct user_fpmedia_regs elf_fpregset_t;
+
+/* Signal info.  */
+struct elf_siginfo
+  {
+    int si_signo;			/* Signal number.  */
+    int si_code;			/* Extra code.  */
+    int si_errno;			/* Errno.  */
+  };
+
+
+/* Definitions to generate Intel SVR4-like core files.  These mostly
+   have the same names as the SVR4 types with "elf_" tacked on the
+   front to prevent clashes with Linux definitions, and the typedef
+   forms have been avoided.  This is mostly like the SVR4 structure,
+   but more Linuxy, with things that Linux does not support and which
+   GDB doesn't really use excluded.  */
+
+struct elf_prstatus
+  {
+    struct elf_siginfo pr_info;		/* Info associated with signal.  */
+    short int pr_cursig;		/* Current signal.  */
+    unsigned long int pr_sigpend;	/* Set of pending signals.  */
+    unsigned long int pr_sighold;	/* Set of held signals.  */
+    __pid_t pr_pid;
+    __pid_t pr_ppid;
+    __pid_t pr_pgrp;
+    __pid_t pr_sid;
+    struct timeval pr_utime;		/* User time.  */
+    struct timeval pr_stime;		/* System time.  */
+    struct timeval pr_cutime;		/* Cumulative user time.  */
+    struct timeval pr_cstime;		/* Cumulative system time.  */
+    elf_gregset_t pr_reg;		/* GP registers.  */
+    int pr_fpvalid;			/* True if math copro being used.  */
+  };
+
+
+#define ELF_PRARGSZ     (80)    /* Number of chars for args.  */
+
+struct elf_prpsinfo
+  {
+    char pr_state;			/* Numeric process state.  */
+    char pr_sname;			/* Char for pr_state.  */
+    char pr_zomb;			/* Zombie.  */
+    char pr_nice;			/* Nice val.  */
+    unsigned long int pr_flag;		/* Flags.  */
+    unsigned short int pr_uid;
+    unsigned short int pr_gid;
+    int pr_pid, pr_ppid, pr_pgrp, pr_sid;
+    /* Lots missing */
+    char pr_fname[16];			/* Filename of executable.  */
+    char pr_psargs[ELF_PRARGSZ];	/* Initial part of arg list.  */
+  };
+
+
+/* The rest of this file provides the types for emulation of the
+   Solaris <proc_service.h> interfaces that should be implemented by
+   users of libthread_db.  */
+
+/* Addresses.  */
+typedef void *psaddr_t;
+
+/* Register sets.  Linux has different names.  */
+typedef elf_gregset_t prgregset_t;
+typedef elf_fpregset_t prfpregset_t;
+
+/* We don't have any differences between processes and threads,
+   therefore have only one PID type.  */
+typedef __pid_t lwpid_t;
+
+/* Process status and info.  In the end we do provide typedefs for them.  */
+typedef struct elf_prstatus prstatus_t;
+typedef struct elf_prpsinfo prpsinfo_t;
+
+__END_DECLS
+
+#endif	/* sys/procfs.h */

+ 139 - 0
libc/sysdeps/linux/frv/sys/ptrace.h

@@ -0,0 +1,139 @@
+/* `ptrace' debugger support interface.  FRV-Linux version.
+   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2004
+   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
+   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.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#ifndef _SYS_PTRACE_H
+#define _SYS_PTRACE_H	1
+
+#include <features.h>
+
+__BEGIN_DECLS
+
+/* Type of the REQUEST argument to `ptrace.'  */
+enum __ptrace_request
+{
+  /* Indicate that the process making this request should be traced.
+     All signals received by this process can be intercepted by its
+     parent, and its parent can use the other `ptrace' requests.  */
+  PTRACE_TRACEME = 0,
+#define PT_TRACE_ME PTRACE_TRACEME
+
+  /* Return the word in the process's text space at address ADDR.  */
+  PTRACE_PEEKTEXT = 1,
+#define PT_READ_I PTRACE_PEEKTEXT
+
+  /* Return the word in the process's data space at address ADDR.  */
+  PTRACE_PEEKDATA = 2,
+#define PT_READ_D PTRACE_PEEKDATA
+
+  /* Return the word in the process's user area at offset ADDR.  */
+  PTRACE_PEEKUSER = 3,
+#define PT_READ_U PTRACE_PEEKUSER
+
+  /* Write the word DATA into the process's text space at address ADDR.  */
+  PTRACE_POKETEXT = 4,
+#define PT_WRITE_I PTRACE_POKETEXT
+
+  /* Write the word DATA into the process's data space at address ADDR.  */
+  PTRACE_POKEDATA = 5,
+#define PT_WRITE_D PTRACE_POKEDATA
+
+  /* Write the word DATA into the process's user area at offset ADDR.  */
+  PTRACE_POKEUSER = 6,
+#define PT_WRITE_U PTRACE_POKEUSER
+
+  /* Continue the process.  */
+  PTRACE_CONT = 7,
+#define PT_CONTINUE PTRACE_CONT
+
+  /* Kill the process.  */
+  PTRACE_KILL = 8,
+#define PT_KILL PTRACE_KILL
+
+  /* Single step the process.
+     This is not supported on all machines.  */
+  PTRACE_SINGLESTEP = 9,
+#define PT_STEP PTRACE_SINGLESTEP
+
+  /* Get all general purpose registers used by a processes.
+     This is not supported on all machines.  */
+   PTRACE_GETREGS = 12,
+#define PT_GETREGS PTRACE_GETREGS
+
+  /* Set all general purpose registers used by a processes.
+     This is not supported on all machines.  */
+   PTRACE_SETREGS = 13,
+#define PT_SETREGS PTRACE_SETREGS
+
+  /* Get all floating point registers used by a processes.
+     This is not supported on all machines.  */
+   PTRACE_GETFPREGS = 14,
+#define PT_GETFPREGS PTRACE_GETFPREGS
+
+  /* Set all floating point registers used by a processes.
+     This is not supported on all machines.  */
+   PTRACE_SETFPREGS = 15,
+#define PT_SETFPREGS PTRACE_SETFPREGS
+
+  /* Attach to a process that is already running. */
+  PTRACE_ATTACH = 16,
+#define PT_ATTACH PTRACE_ATTACH
+
+  /* Detach from a process attached to with PTRACE_ATTACH.  */
+  PTRACE_DETACH = 17,
+#define PT_DETACH PTRACE_DETACH
+
+  /* Get all extended floating point registers used by a processes.
+     This is not supported on all machines.  */
+   PTRACE_GETFPXREGS = 18,
+#define PT_GETFPXREGS PTRACE_GETFPXREGS
+
+  /* Set all extended floating point registers used by a processes.
+     This is not supported on all machines.  */
+   PTRACE_SETFPXREGS = 19,
+#define PT_SETFPXREGS PTRACE_SETFPXREGS
+
+  /* Continue and stop at the next (return from) syscall.  */
+  PTRACE_SYSCALL = 24,
+#define PT_SYSCALL PTRACE_SYSCALL
+
+  /* Obtain the load map of the main program or the interpreter of the
+     ptraced process, depending on whether the addr argument is
+     (void*)0 or (void*)1, respectively.  */
+  PTRACE_GETFDPIC = 31
+#define PT_GETFDPIC PTRACE_GETFDPIC
+};
+
+#define PTRACE_GETFDPIC_EXEC      ((void*)0)	/* [addr] request the executable loadmap */
+#define PTRACE_GETFDPIC_INTERP    ((void*)1)	/* [addr] request the interpreter loadmap */
+
+/* Perform process tracing functions.  REQUEST is one of the values
+   above, and determines the action to be taken.
+   For all requests except PTRACE_TRACEME, PID specifies the process to be
+   traced.
+
+   PID and the other arguments described above for the various requests should
+   appear (those that are used for the particular request) as:
+     pid_t PID, void *ADDR, int DATA, void *ADDR2
+   after REQUEST.  */
+extern long int ptrace (enum __ptrace_request __request, ...) __THROW;
+
+__END_DECLS
+
+#endif /* _SYS_PTRACE_H */

+ 451 - 0
libc/sysdeps/linux/frv/sys/ucontext.h

@@ -0,0 +1,451 @@
+/* Copyright (C) 1999, 2000, 2001, 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
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library 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 Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifndef _SYS_UCONTEXT_H
+#define _SYS_UCONTEXT_H	1
+
+#include <features.h>
+#include <signal.h>
+
+/* We need the signal context definitions even if they are not used
+   included in <signal.h>.  */
+#include <bits/sigcontext.h>
+
+
+typedef unsigned long greg_t;
+
+/* Number of general registers.  */
+#define NGREG	(10+2+64)
+
+/* Container for all general registers.  */
+typedef greg_t gregset_t[NGREG];
+
+#ifdef __USE_GNU
+/* Number of each register is the `gregset_t' array.  */
+enum
+{
+  PSR = 0,
+#define PSR	PSR
+  ISR = 1,
+#define ISR	ISR
+  CCR = 2,
+#define CCR	CCR
+  CCCR = 3,
+#define CCCR	CCCR
+  LR = 4,
+#define LR	LR
+  LCR = 5,
+#define LCR	LCR
+  PC = 6,
+#define PC	PC
+  __STATUS = 7,
+#define __STATUS	__STATUS
+  SYSCALLNO = 8,
+#define SYSCALLNO	SYSCALLNO
+  ORIG_GR8 = 9,
+#define ORIG_GR8	ORIG_GR8
+  GNER0 = 10,
+#define GNER0	GNER0
+  GNER1 = 11,
+#define GNER1	GNER1
+  GR0 = 12,
+#define GR0	GR0
+  GR1 = 13,
+#define GR1	GR1
+  GR2 = 14,
+#define GR2	GR2
+  GR3 = 15,
+#define GR3	GR3
+  GR4 = 16,
+#define GR4	GR4
+  GR5 = 17,
+#define GR5	GR5
+  GR6 = 18,
+#define GR6	GR6
+  GR7 = 19,
+#define GR7	GR7
+  GR8 = 20,
+#define GR8	GR8
+  GR9 = 21,
+#define GR9	GR9
+  GR10 = 22,
+#define GR10	GR10
+  GR11 = 23,
+#define GR11	GR11
+  GR12 = 24,
+#define GR12	GR12
+  GR13 = 25,
+#define GR13	GR13
+  GR14 = 26,
+#define GR14	GR14
+  GR15 = 27,
+#define GR15	GR15
+  GR16 = 28,
+#define GR16	GR16
+  GR17 = 29,
+#define GR17	GR17
+  GR18 = 30,
+#define GR18	GR18
+  GR19 = 31,
+#define GR19	GR19
+  GR20 = 32,
+#define GR20	GR20
+  GR21 = 33,
+#define GR21	GR21
+  GR22 = 34,
+#define GR22	GR22
+  GR23 = 35,
+#define GR23	GR23
+  GR24 = 36,
+#define GR24	GR24
+  GR25 = 37,
+#define GR25	GR25
+  GR26 = 38,
+#define GR26	GR26
+  GR27 = 39,
+#define GR27	GR27
+  GR28 = 40,
+#define GR28	GR28
+  GR29 = 41,
+#define GR29	GR29
+  GR30 = 42,
+#define GR30	GR30
+  GR31 = 43,
+#define GR31	GR31
+  GR32 = 44,
+#define GR32	GR32
+  GR33 = 45,
+#define GR33	GR33
+  GR34 = 46,
+#define GR34	GR34
+  GR35 = 47,
+#define GR35	GR35
+  GR36 = 48,
+#define GR36	GR36
+  GR37 = 49,
+#define GR37	GR37
+  GR38 = 50,
+#define GR38	GR38
+  GR39 = 51,
+#define GR39	GR39
+  GR40 = 52,
+#define GR40	GR40
+  GR41 = 53,
+#define GR41	GR41
+  GR42 = 54,
+#define GR42	GR42
+  GR43 = 55,
+#define GR43	GR43
+  GR44 = 56,
+#define GR44	GR44
+  GR45 = 57,
+#define GR45	GR45
+  GR46 = 58,
+#define GR46	GR46
+  GR47 = 59,
+#define GR47	GR47
+  GR48 = 60,
+#define GR48	GR48
+  GR49 = 61,
+#define GR49	GR49
+  GR50 = 62,
+#define GR50	GR50
+  GR51 = 63,
+#define GR51	GR51
+  GR52 = 64,
+#define GR52	GR52
+  GR53 = 65,
+#define GR53	GR53
+  GR54 = 66,
+#define GR54	GR54
+  GR55 = 67,
+#define GR55	GR55
+  GR56 = 68,
+#define GR56	GR56
+  GR57 = 69,
+#define GR57	GR57
+  GR58 = 70,
+#define GR58	GR58
+  GR59 = 71,
+#define GR59	GR59
+  GR60 = 72,
+#define GR60	GR60
+  GR61 = 73,
+#define GR61	GR61
+  GR62 = 74,
+#define GR62	GR62
+  GR63 = 75,
+#define GR63	GR63
+};
+#endif
+
+typedef unsigned long freg_t;
+
+/* Number of FPU registers.  */
+#define NFPREG	(64+2+2+8+2+1)
+
+#ifdef __USE_GNU
+/* Number of each register is the `gregset_t' array.  */
+enum
+{
+  FR0 = 0,
+#define FR0	FR0
+  FR1 = 1,
+#define FR1	FR1
+  FR2 = 2,
+#define FR2	FR2
+  FR3 = 3,
+#define FR3	FR3
+  FR4 = 4,
+#define FR4	FR4
+  FR5 = 5,
+#define FR5	FR5
+  FR6 = 6,
+#define FR6	FR6
+  FR7 = 7,
+#define FR7	FR7
+  FR8 = 8,
+#define FR8	FR8
+  FR9 = 9,
+#define FR9	FR9
+  FR10 = 10,
+#define FR10	FR10
+  FR11 = 11,
+#define FR11	FR11
+  FR12 = 12,
+#define FR12	FR12
+  FR13 = 13,
+#define FR13	FR13
+  FR14 = 14,
+#define FR14	FR14
+  FR15 = 15,
+#define FR15	FR15
+  FR16 = 16,
+#define FR16	FR16
+  FR17 = 17,
+#define FR17	FR17
+  FR18 = 18,
+#define FR18	FR18
+  FR19 = 19,
+#define FR19	FR19
+  FR20 = 20,
+#define FR20	FR20
+  FR21 = 21,
+#define FR21	FR21
+  FR22 = 22,
+#define FR22	FR22
+  FR23 = 23,
+#define FR23	FR23
+  FR24 = 24,
+#define FR24	FR24
+  FR25 = 25,
+#define FR25	FR25
+  FR26 = 26,
+#define FR26	FR26
+  FR27 = 27,
+#define FR27	FR27
+  FR28 = 28,
+#define FR28	FR28
+  FR29 = 29,
+#define FR29	FR29
+  FR30 = 30,
+#define FR30	FR30
+  FR31 = 31,
+#define FR31	FR31
+  FR32 = 32,
+#define FR32	FR32
+  FR33 = 33,
+#define FR33	FR33
+  FR34 = 34,
+#define FR34	FR34
+  FR35 = 35,
+#define FR35	FR35
+  FR36 = 36,
+#define FR36	FR36
+  FR37 = 37,
+#define FR37	FR37
+  FR38 = 38,
+#define FR38	FR38
+  FR39 = 39,
+#define FR39	FR39
+  FR40 = 40,
+#define FR40	FR40
+  FR41 = 41,
+#define FR41	FR41
+  FR42 = 42,
+#define FR42	FR42
+  FR43 = 43,
+#define FR43	FR43
+  FR44 = 44,
+#define FR44	FR44
+  FR45 = 45,
+#define FR45	FR45
+  FR46 = 46,
+#define FR46	FR46
+  FR47 = 47,
+#define FR47	FR47
+  FR48 = 48,
+#define FR48	FR48
+  FR49 = 49,
+#define FR49	FR49
+  FR50 = 50,
+#define FR50	FR50
+  FR51 = 51,
+#define FR51	FR51
+  FR52 = 52,
+#define FR52	FR52
+  FR53 = 53,
+#define FR53	FR53
+  FR54 = 54,
+#define FR54	FR54
+  FR55 = 55,
+#define FR55	FR55
+  FR56 = 56,
+#define FR56	FR56
+  FR57 = 57,
+#define FR57	FR57
+  FR58 = 58,
+#define FR58	FR58
+  FR59 = 59,
+#define FR59	FR59
+  FR60 = 60,
+#define FR60	FR60
+  FR61 = 61,
+#define FR61	FR61
+  FR62 = 62,
+#define FR62	FR62
+  FR63 = 63,
+#define FR63	FR63
+  FNER0 = 64,
+#define FNER0	FNER0
+  FNER1 = 65,
+#define FNER1	FNER1
+  MSR0 = 66,
+#define MSR0	MSR0
+  MSR1 = 67,
+#define MSR1	MSR1
+  ACC0 = 68,
+#define ACC0	ACC0
+  ACC1 = 69,
+#define ACC1	ACC1
+  ACC2 = 70,
+#define ACC2	ACC2
+  ACC3 = 71,
+#define ACC3	ACC3
+  ACC4 = 72,
+#define ACC4	ACC4
+  ACC5 = 73,
+#define ACC5	ACC5
+  ACC6 = 74,
+#define ACC6	ACC6
+  ACC7 = 75,
+#define ACC7	ACC7
+  ACCG0123 = 76,
+#define ACCG0123	ACCG0123
+  ACCG4567 = 77,
+#define ACCG4567	ACCG4567
+  FSR0 = 78,
+#define FSR0	FSR0
+};
+#endif
+
+/* Structure to describe FPU registers.  */
+typedef freg_t fpregset_t[NFPREG];
+
+/* Context to describe whole processor state.  */
+typedef struct
+  {
+    gregset_t gregs;
+    fpregset_t fpregs;
+    void *extension;
+    unsigned long sc_oldmask; 	/* old sigmask */
+  } __attribute__((aligned(8))) mcontext_t;
+
+#ifdef __USE_GNU
+struct kernel_user_int_regs
+{
+  /* integer registers
+   * - up to gr[31] mirror pt_regs in the kernel
+   */
+  unsigned long		psr;		/* Processor Status Register */
+  unsigned long		isr;		/* Integer Status Register */
+  unsigned long		ccr;		/* Condition Code Register */
+  unsigned long		cccr;		/* Condition Code for Conditional Insns Register */
+  unsigned long		lr;		/* Link Register */
+  unsigned long		lcr;		/* Loop Count Register */
+  unsigned long		pc;		/* Program Counter Register */
+  unsigned long		__status;	/* exception status */
+  unsigned long		syscallno;	/* syscall number or -1 */
+  unsigned long		orig_gr8;	/* original syscall arg #1 */
+  unsigned long		gner[2];
+
+  union {
+    unsigned long	tbr;
+    unsigned long	gr[64];
+  };
+};
+
+struct kernel_user_fpmedia_regs
+{
+  /* FP/Media registers */
+  unsigned long	fr[64];
+  unsigned long	fner[2];
+  unsigned long	msr[2];
+  unsigned long	acc[8];
+  unsigned char	accg[8];
+  unsigned long	fsr[1];
+};
+
+struct kernel_user_context
+{
+  struct kernel_user_int_regs i;
+  struct kernel_user_fpmedia_regs f;
+
+  /* we provide a context extension so that we can save the regs for CPUs that
+   * implement many more of Fujitsu's lavish register spec
+   */
+  void			*extension;
+
+  /* This is not part of the kernel's struct user_context, but
+     rather of the enclosing struct sigcontext, but we add it
+     here to parallel mcontext_t, just for completeness.  */
+  unsigned long sc_oldmask; 	/* old sigmask */
+} __attribute__((aligned(8)));
+
+/* This union enables alias-safe casts from mcontext_t* to the union
+   type, that can then be dereferenced as_aliases.  */
+union kmcontext_t
+{
+  mcontext_t as_regsets;
+  /* as_aliases is actually missing sc_oldmask, that is present in
+     mcontext_t.  */
+  struct kernel_user_context as_aliases;
+};
+#endif
+
+/* Userlevel context.  */
+typedef struct ucontext
+  {
+    unsigned long int uc_flags;
+    struct ucontext *uc_link;
+    stack_t uc_stack;
+    mcontext_t uc_mcontext;
+    __sigset_t uc_sigmask;
+  } ucontext_t;
+
+#endif /* sys/ucontext.h */

+ 27 - 0
libc/sysdeps/linux/frv/sysdep.c

@@ -0,0 +1,27 @@
+/* Copyright (C) 1997, 1998 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
+   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.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <errno.h>
+
+/* This routine is jumped to by all the syscall handlers, to stash
+   an error number into errno.  */
+int __syscall_error (int err_no)
+{
+  __set_errno (err_no);
+  return -1;
+}

+ 44 - 0
libc/sysdeps/linux/frv/vfork.S

@@ -0,0 +1,44 @@
+/* Copyright (C) 2003 Free Software Foudnation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by David Howells <dhowells@redhat.com>, 2003.
+
+   The GNU C Library 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.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <asm/unistd.h>
+#define _ERRNO_H       1
+#include <bits/errno.h>
+
+       .text
+       .globl  __libc_vfork
+       .type __libc_vfork,@function
+/* int vfork(void) */
+__libc_vfork:
+       setlos  #__NR_vfork, gr7
+       tira    gr0, #0
+
+       cmp     gr8, gr0, icc0
+       bplr    icc0, #2
+
+       sethi.p #gotofffuncdeschi(__syscall_error), gr14
+       setlo   #gotofffuncdesclo(__syscall_error), gr14
+       ldd     @(gr14, gr15), gr14
+       jmpl    @(gr14, gr0)
+
+       .size   vfork,.-vfork
+
+.weak vfork
+.global vfork
+.set vfork, __libc_vfork

+ 48 - 0
libpthread/linuxthreads/sysdeps/frv/pt-machine.h

@@ -0,0 +1,48 @@
+/* Machine-dependent pthreads configuration and inline functions.
+   ARM version.
+   Copyright (C) 1997, 1998, 2000, 2002, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Alexandre Oliva <aoliva@redhat.com>
+
+   The GNU C Library 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.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#ifndef _PT_MACHINE_H
+#define _PT_MACHINE_H   1
+
+#ifndef PT_EI
+# define PT_EI extern inline
+#endif
+
+/* Get some notion of the current stack.  Need not be exactly the top
+   of the stack, just something somewhere in the current frame.  */
+#define CURRENT_STACK_FRAME  __builtin_frame_address (0)
+
+
+extern long int testandset (int *spinlock);
+
+/* Spinlock implementation; required.  */
+PT_EI long int
+testandset (int *spinlock)
+{
+  register long int ret = 1;
+
+  __asm__ __volatile__("swap%I1\t%M1,%0"
+		       : "+r"(ret), "+m"(*spinlock));
+
+  return ret;
+}
+
+#endif /* pt-machine.h */