OSDN Git Service

Alexandre Oliva writes:
authorEric Andersen <andersen@codepoet.org>
Wed, 18 Feb 2004 08:04:51 +0000 (08:04 -0000)
committerEric Andersen <andersen@codepoet.org>
Wed, 18 Feb 2004 08:04:51 +0000 (08:04 -0000)
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.

39 files changed:
Rules.mak
extra/Configs/Config.frv [new file with mode: 0644]
extra/Configs/Config.frv.default [new file with mode: 0644]
extra/Configs/Config.in
include/elf.h
ldso/ldso/frv/dl-startup.h [new file with mode: 0644]
ldso/ldso/frv/dl-syscalls.h [new file with mode: 0644]
ldso/ldso/frv/dl-sysdep.h [new file with mode: 0644]
ldso/ldso/frv/elfinterp.c [new file with mode: 0644]
ldso/ldso/frv/resolve.S [new file with mode: 0644]
libc/sysdeps/linux/frv/Makefile [new file with mode: 0644]
libc/sysdeps/linux/frv/__init_brk.c [new file with mode: 0644]
libc/sysdeps/linux/frv/__longjmp.S [new file with mode: 0644]
libc/sysdeps/linux/frv/_mmap.c [new file with mode: 0644]
libc/sysdeps/linux/frv/bits/elf-fdpic.h [new file with mode: 0644]
libc/sysdeps/linux/frv/bits/endian.h [new file with mode: 0644]
libc/sysdeps/linux/frv/bits/fcntl.h [new file with mode: 0644]
libc/sysdeps/linux/frv/bits/kernel_stat.h [new file with mode: 0644]
libc/sysdeps/linux/frv/bits/kernel_types.h [new file with mode: 0644]
libc/sysdeps/linux/frv/bits/mman.h [new file with mode: 0644]
libc/sysdeps/linux/frv/bits/setjmp.h [new file with mode: 0644]
libc/sysdeps/linux/frv/bits/stackinfo.h [new file with mode: 0644]
libc/sysdeps/linux/frv/bits/syscalls.h [new file with mode: 0644]
libc/sysdeps/linux/frv/bits/wordsize.h [new file with mode: 0644]
libc/sysdeps/linux/frv/brk.c [new file with mode: 0644]
libc/sysdeps/linux/frv/clone.S [new file with mode: 0644]
libc/sysdeps/linux/frv/crt0.S [new file with mode: 0644]
libc/sysdeps/linux/frv/crti.S [new file with mode: 0644]
libc/sysdeps/linux/frv/crtn.S [new file with mode: 0644]
libc/sysdeps/linux/frv/crtreloc.c [new file with mode: 0644]
libc/sysdeps/linux/frv/dl-iterate-phdr.c [new file with mode: 0644]
libc/sysdeps/linux/frv/sbrk.c [new file with mode: 0644]
libc/sysdeps/linux/frv/setjmp.S [new file with mode: 0644]
libc/sysdeps/linux/frv/sys/procfs.h [new file with mode: 0644]
libc/sysdeps/linux/frv/sys/ptrace.h [new file with mode: 0644]
libc/sysdeps/linux/frv/sys/ucontext.h [new file with mode: 0644]
libc/sysdeps/linux/frv/sysdep.c [new file with mode: 0644]
libc/sysdeps/linux/frv/vfork.S [new file with mode: 0644]
libpthread/linuxthreads/sysdeps/frv/pt-machine.h [new file with mode: 0644]

index 15c593a..6a1b235 100644 (file)
--- a/Rules.mak
+++ b/Rules.mak
@@ -170,6 +170,20 @@ ifeq ($(strip $(TARGET_ARCH)),cris)
        PICFLAG=-fpic
 endif
 
+ifeq ($(strip $(TARGET_ARCH)),frv)
+       CPU_LDFLAGS-$(CONFIG_FRV)+=-melf32frvfd
+       CPU_CFLAGS-$(CONFIG_FRV)+=-mfdpic
+       PICFLAG=-fPIC -DPIC
+       PIEFLAG=-fpie
+       # Using -pie causes the program to have an interpreter, which is
+       # forbidden, so we must make do with -shared.  Unfortunately,
+       # -shared by itself would get us global function descriptors
+       # and calls through PLTs, dynamic resolution of symbols, etc,
+       # which would break as well, but -Bsymbolic comes to the rescue.
+       LDPIEFLAG=-shared -Bsymbolic
+       UCLIBC_LDSO=ld.so.1
+endif
+
 # Use '-Os' optimization if available, else use -O2, allow Config to override
 OPTIMIZATION+=$(call check_gcc,-Os,-O2)
 # Use the gcc 3.4 -funit-at-a-time optimization when available
diff --git a/extra/Configs/Config.frv b/extra/Configs/Config.frv
new file mode 100644 (file)
index 0000000..1210ad9
--- /dev/null
@@ -0,0 +1,32 @@
+#
+# For a description of the syntax of this configuration file,
+# see extra/config/Kconfig-language.txt
+#
+
+config HAVE_ELF
+       bool
+       select HAS_FPU
+       select ARCH_BIG_ENDIAN
+       select ARCH_HAS_NO_MMU
+       default y
+
+config TARGET_ARCH
+       string
+       default "frv"
+
+config ARCH_CFLAGS
+       string
+
+config ARCH_LDFLAGS
+       string
+
+config LIBGCC_CFLAGS
+       string
+
+config HAVE_DOT_HIDDEN
+        bool
+       default y
+
+config UCLIBC_COMPLETELY_PIC
+        bool
+       default y
diff --git a/extra/Configs/Config.frv.default b/extra/Configs/Config.frv.default
new file mode 100644 (file)
index 0000000..4fd945d
--- /dev/null
@@ -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
index 8ad0073..4f15ea0 100644 (file)
@@ -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
index b4de42e..e2264bd 100644 (file)
@@ -1,5 +1,5 @@
 /* This file defines standard ELF types, structures, and macros.
-   Copyright (C) 1995-1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+   Copyright (C) 1995-1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -254,6 +254,9 @@ typedef struct
    pick large random numbers (0x8523, 0xa7f2, etc.) to minimize the
    chances of collision with official or non-GNU unofficial values.  */
 
+/* Fujitsu FR-V.  */
+#define EM_CYGNUS_FRV  0x5441
+
 #define EM_ALPHA       0x9026
 
 /* V850 backend magic number.  Written in the absense of an ABI.  */
@@ -1116,6 +1119,17 @@ typedef struct
 /* Keep this the last entry.  */
 #define R_386_NUM         38
 
+/* FR-V specific definitions.  */
+#define R_FRV_NONE             0       /* No reloc.  */
+#define R_FRV_32               1       /* Direct 32 bit.  */
+/* Canonical function descriptor address.  */
+#define R_FRV_FUNCDESC         14
+/* Private function descriptor initialization.  */
+#define R_FRV_FUNCDESC_VALUE   18
+
+#define EF_FRV_PIC   0x00000100
+#define EF_FRV_FDPIC 0x00008000
+
 /* SUN SPARC specific definitions.  */
 
 /* Legal values for ST_TYPE subfield of st_info (symbol type).  */
diff --git a/ldso/ldso/frv/dl-startup.h b/ldso/ldso/frv/dl-startup.h
new file mode 100644 (file)
index 0000000..017efc0
--- /dev/null
@@ -0,0 +1,89 @@
+     /* Copyright (C) 2003 Red Hat, Inc.
+       Contributed by Alexandre Oliva <aoliva@redhat.com>
+
+This file is part of uClibc.
+
+uClibc is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation; either version 2.1 of the
+License, or (at your option) any later version.
+
+uClibc is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with uClibc; see the file COPYING.LIB.  If not, write to
+the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
+USA.  */
+       
+/* Any assembly language/system dependent hacks needed to setup
+ * boot1.c so it will work as expected and cope with whatever platform
+ * specific wierdness is needed for this architecture.
+
+ * We override the default _dl_boot function, and replace it with a
+ * bit of asm.  Then call the real _dl_boot function, which is now
+ * named _dl_boot2.  */
+
+/* At program start-up, gr16 contains a pointer to a
+   elf32_fdpic_loadmap that describes how the executable was loaded
+   into memory.  gr17 contains a pointer to the interpreter (our!)
+   loadmap, if there is an interpreter, or 0 if we're being run as an
+   executable.  gr18 holds a pointer to the interpreter's dynamic
+   section, if there is an interpreter, or to the executable's dynamic
+   section, otherwise.  If the executable is not dynamic, gr18 is 0.
+
+   We rely on the fact that the linker adds a pointer to the
+   _GLOBAL_OFFSET_TABLE_ as the last ROFIXUP entry, and that
+   __self_reloc returns the relocated pointer to us, so that we can
+   use this value to initialize the PIC register.  */
+
+asm("" \
+"      .text\n"                        \
+"      .global _dl_boot\n"             \
+"      .type   _dl_boot,@function\n"   \
+"_dl_boot:\n"                          \
+"      call    .Lcall\n"               \
+".Lcall:\n"                            \
+"      movsg   lr, gr4\n"              \
+"      sethi.p #gprelhi(.Lcall), gr5\n"\
+"      setlo   #gprello(.Lcall), gr5\n"\
+"      mov.p   gr17, gr8\n"            \
+"      cmp     gr17, gr0, icc0\n"      \
+"      sub.p   gr4, gr5, gr4\n"        \
+"      ckeq    icc0, cc4\n"            \
+"      cmov.p  gr16, gr8, cc4, 1\n"    \
+"      sethi   #gprelhi(__ROFIXUP_LIST__), gr9\n"      \
+"      sethi.p #gprelhi(__ROFIXUP_END__), gr10\n"      \
+"      setlo   #gprello(__ROFIXUP_LIST__), gr9\n"      \
+"      setlo.p #gprello(__ROFIXUP_END__), gr10\n"      \
+"      add     gr9, gr4, gr9\n"        \
+"      add.p   gr10, gr4, gr10\n"      \
+"      call    __self_reloc\n"         \
+"      mov.p   gr8, gr15\n"            \
+"      mov     gr16, gr9\n"            \
+"      mov.p   gr17, gr10\n"           \
+"      mov     gr18, gr11\n"           \
+"      addi.p  sp, #4, gr13\n"         \
+"      addi    sp, #-8, sp\n"          \
+"      mov.p   sp, gr12\n"             \
+"      call    _dl_boot2\n"            \
+"      ldd.p   @(sp, gr0), gr14\n"     \
+"      addi    sp, #8, sp\n"           \
+"      movgs   gr0, lr\n"              \
+"      jmpl    @(gr14, gr0)\n"         \
+"      .size   _dl_boot,.-_dl_boot\n"  \
+);
+
+#define _dl_boot _dl_boot2
+#define DL_BOOT(X)   \
+static void  __attribute__ ((used)) \
+_dl_boot (void *dl_boot_got_pointer, \
+         struct elf32_fdpic_loadmap *dl_boot_progmap, \
+         struct elf32_fdpic_loadmap *dl_boot_ldsomap, \
+         Elf32_Dyn *dl_boot_ldso_dyn_pointer, \
+         struct funcdesc_value *dl_main_funcdesc, \
+         X)
+
+struct elf32_fdpic_loadmap;
diff --git a/ldso/ldso/frv/dl-syscalls.h b/ldso/ldso/frv/dl-syscalls.h
new file mode 100644 (file)
index 0000000..bef4f17
--- /dev/null
@@ -0,0 +1,191 @@
+/* Copyright (C) 2003 Red Hat, Inc.
+   Contributed by Alexandre Oliva <aoliva@redhat.com>
+
+This file is part of uClibc.
+
+uClibc is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser General Public License as
+published by the Free Software Foundation; either version 2.1 of the
+License, or (at your option) any later version.
+
+uClibc is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with uClibc; see the file COPYING.LIB.  If not, write to
+the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
+USA.  */
+       
+/* Define the __set_errno macro as nothing so that INLINE_SYSCALL
+ * won't set errno, which is important since we make system calls
+ * before the errno symbol is dynamicly linked. */
+
+#define __set_errno(X) {(void)(X);}
+#include "sys/syscall.h"
+#include <sys/mman.h>
+
+/* The code below is extracted from libc/sysdeps/linux/frv/_mmap.c */
+
+#define __NR___syscall_mmap2       __NR_mmap2
+static inline _syscall6(__ptr_t, __syscall_mmap2, __ptr_t, addr, 
+       size_t, len, int, prot, int, flags, int, fd, off_t, offset);
+
+/* This is always 12, even on architectures where PAGE_SHIFT != 12.  */
+# ifndef MMAP2_PAGE_SHIFT
+#  define MMAP2_PAGE_SHIFT 12
+# endif
+
+#if DYNAMIC_LOADER_IN_SIMULATOR
+#include <asm/page.h> /* for PAGE_SIZE */
+inline static void *_dl_memset(void*,int,size_t);
+inline static ssize_t _dl_pread(int fd, void *buf, size_t count, off_t offset);
+#endif
+
+#ifndef DYNAMIC_LOADER_IN_SIMULATOR
+inline
+#endif
+static __ptr_t
+_dl_mmap(__ptr_t addr, size_t len, int prot, int flags, int fd, __off_t offset)
+{
+#ifdef DYNAMIC_LOADER_IN_SIMULATOR
+  size_t plen = (len + PAGE_SIZE - 1) & -PAGE_SIZE;
+
+/* This is a hack to enable the dynamic loader to run within a
+   simulator that doesn't support mmap, with a number of very ugly
+   tricks.  Also, it's not as useful as it sounds, since only dynamic
+   executables without DT_NEEDED dependencies can be run.  AFAIK, they
+   can only be created with -pie.  This trick suffices to enable the
+   dynamic loader to obtain a blank page that it maps early in the
+   bootstrap. */
+  if ((flags & MAP_FIXED) == 0)
+    {
+      void *_dl_mmap_base = 0;
+      __ptr_t *ret = 0;
+
+      if (! _dl_mmap_base)
+       {
+         void *stack;
+         asm ("mov sp, %0" : "=r" (stack));
+         _dl_mmap_base = (void *)(((long)stack + 2 * PAGE_SIZE) & -PAGE_SIZE);
+       retry:
+         if (((void **)_dl_mmap_base)[0] == _dl_mmap_base
+             && ((void **)_dl_mmap_base)[1023] == _dl_mmap_base
+             && (((void **)_dl_mmap_base)[177]
+                 == ((void **)_dl_mmap_base)[771]))
+           {
+             while (((void**)_dl_mmap_base)[177])
+               {
+                 _dl_mmap_base = ((void**)_dl_mmap_base)[177];
+                 if (!(((void **)_dl_mmap_base)[0] == _dl_mmap_base
+                       && ((void **)_dl_mmap_base)[1023] == _dl_mmap_base
+                       && (((void **)_dl_mmap_base)[177]
+                           == ((void**)_dl_mmap_base)[771])))
+                   ((void(*)())0)();
+               }
+           }
+         else
+           {
+             int i;
+             for (i = 0; i < (int)PAGE_SIZE; i++)
+               if (*(char*)(_dl_mmap_base + i))
+                 break;
+             if (i != PAGE_SIZE)
+               {
+                 _dl_mmap_base = (void*)((long)_dl_mmap_base + PAGE_SIZE);
+                 goto retry;
+               }
+             ((void**)_dl_mmap_base)[-1] =
+               ((void**)_dl_mmap_base)[0] =
+               ((void**)_dl_mmap_base)[1023] =
+               _dl_mmap_base;
+           }
+       }
+
+      if (_dl_mmap_base)
+       {
+         if (!(((void **)_dl_mmap_base)[0] == _dl_mmap_base
+               && ((void **)_dl_mmap_base)[1023] == _dl_mmap_base
+               && (((void **)_dl_mmap_base)[177]
+                   == ((void**)_dl_mmap_base)[771])))
+           ((void(*)())0)();
+         ret = (__ptr_t)((char*)_dl_mmap_base + PAGE_SIZE);
+         _dl_mmap_base =
+           ((void**)_dl_mmap_base)[177] =
+           ((void**)_dl_mmap_base)[771] =
+           (char*)_dl_mmap_base + plen + PAGE_SIZE;
+         ((void**)_dl_mmap_base)[0] =
+           ((void**)_dl_mmap_base)[1023] =
+           _dl_mmap_base;
+       }
+
+      if ((flags & MAP_ANONYMOUS) != 0)
+       {
+         _dl_memset (ret, 0, plen);
+         return ret;
+       }
+
+      flags |= MAP_FIXED;
+      addr = ret;
+    }
+#endif
+    if (offset & ((1 << MMAP2_PAGE_SHIFT) - 1)) {
+#if 0
+       __set_errno (EINVAL);
+#endif
+       return MAP_FAILED;
+    }
+#ifdef DYNAMIC_LOADER_IN_SIMULATOR
+    if ((flags & MAP_FIXED) != 0)
+      {
+       if (_dl_pread(fd, addr, len, offset) != (ssize_t)len)
+         return (void*)MAP_FAILED;
+       if (plen != len)
+         _dl_memset (addr + len, 0, plen - len);
+       return addr;
+      }
+#endif
+    return(__syscall_mmap2(addr, len, prot, flags, fd, (off_t) (offset >> MMAP2_PAGE_SHIFT)));
+}
+
+#ifdef __NR_pread
+#ifdef DYNAMIC_LOADER_IN_SIMULATOR
+#include <unistd.h>
+
+#define __NR___syscall_lseek __NR_lseek
+inline static unsigned long _dl_read(int fd, const void *buf, unsigned long count);
+
+inline static _syscall3(__off_t, __syscall_lseek, int, fd, __off_t, offset,
+                       int, whence);
+inline static ssize_t
+_dl_pread(int fd, void *buf, size_t count, off_t offset)
+{
+  __off_t orig = __syscall_lseek (fd, 0, SEEK_CUR);
+  ssize_t ret;
+
+  if (orig == -1)
+    return -1;
+
+  if (__syscall_lseek (fd, offset, SEEK_SET) != offset)
+    return -1;
+
+  ret = _dl_read (fd, buf, count);
+
+  if (__syscall_lseek (fd, orig, SEEK_SET) != orig)
+    ((void(*)())0)();
+
+  return ret;
+}
+#else
+#define __NR___syscall_pread __NR_pread
+inline static _syscall5(ssize_t, __syscall_pread, int, fd, void *, buf,
+                       size_t, count, off_t, offset_hi, off_t, offset_lo);
+
+inline static ssize_t
+_dl_pread(int fd, void *buf, size_t count, off_t offset)
+{
+  return(__syscall_pread(fd,buf,count,__LONG_LONG_PAIR (offset >> 31, offset)));
+}
+#endif
+#endif
diff --git a/ldso/ldso/frv/dl-sysdep.h b/ldso/ldso/frv/dl-sysdep.h
new file mode 100644 (file)
index 0000000..ab3b09c
--- /dev/null
@@ -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);
+}
diff --git a/ldso/ldso/frv/elfinterp.c b/ldso/ldso/frv/elfinterp.c
new file mode 100644 (file)
index 0000000..270a5a6
--- /dev/null
@@ -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
diff --git a/ldso/ldso/frv/resolve.S b/ldso/ldso/frv/resolve.S
new file mode 100644 (file)
index 0000000..d9706c7
--- /dev/null
@@ -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
diff --git a/libc/sysdeps/linux/frv/Makefile b/libc/sysdeps/linux/frv/Makefile
new file mode 100644 (file)
index 0000000..77d1326
--- /dev/null
@@ -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
+
diff --git a/libc/sysdeps/linux/frv/__init_brk.c b/libc/sysdeps/linux/frv/__init_brk.c
new file mode 100644 (file)
index 0000000..7f9cd3c
--- /dev/null
@@ -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;
+}
diff --git a/libc/sysdeps/linux/frv/__longjmp.S b/libc/sysdeps/linux/frv/__longjmp.S
new file mode 100644 (file)
index 0000000..a61f8d4
--- /dev/null
@@ -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
diff --git a/libc/sysdeps/linux/frv/_mmap.c b/libc/sysdeps/linux/frv/_mmap.c
new file mode 100644 (file)
index 0000000..b3fd7c3
--- /dev/null
@@ -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)));
+}
diff --git a/libc/sysdeps/linux/frv/bits/elf-fdpic.h b/libc/sysdeps/linux/frv/bits/elf-fdpic.h
new file mode 100644 (file)
index 0000000..f47d949
--- /dev/null
@@ -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 */
diff --git a/libc/sysdeps/linux/frv/bits/endian.h b/libc/sysdeps/linux/frv/bits/endian.h
new file mode 100644 (file)
index 0000000..0564c59
--- /dev/null
@@ -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
diff --git a/libc/sysdeps/linux/frv/bits/fcntl.h b/libc/sysdeps/linux/frv/bits/fcntl.h
new file mode 100644 (file)
index 0000000..69a2096
--- /dev/null
@@ -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
diff --git a/libc/sysdeps/linux/frv/bits/kernel_stat.h b/libc/sysdeps/linux/frv/bits/kernel_stat.h
new file mode 100644 (file)
index 0000000..c6fc953
--- /dev/null
@@ -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 */
diff --git a/libc/sysdeps/linux/frv/bits/kernel_types.h b/libc/sysdeps/linux/frv/bits/kernel_types.h
new file mode 100644 (file)
index 0000000..3d3f630
--- /dev/null
@@ -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 */
diff --git a/libc/sysdeps/linux/frv/bits/mman.h b/libc/sysdeps/linux/frv/bits/mman.h
new file mode 100644 (file)
index 0000000..9e87f80
--- /dev/null
@@ -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
diff --git a/libc/sysdeps/linux/frv/bits/setjmp.h b/libc/sysdeps/linux/frv/bits/setjmp.h
new file mode 100644 (file)
index 0000000..5c20c4f
--- /dev/null
@@ -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)
diff --git a/libc/sysdeps/linux/frv/bits/stackinfo.h b/libc/sysdeps/linux/frv/bits/stackinfo.h
new file mode 100644 (file)
index 0000000..03412e0
--- /dev/null
@@ -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 */
diff --git a/libc/sysdeps/linux/frv/bits/syscalls.h b/libc/sysdeps/linux/frv/bits/syscalls.h
new file mode 100644 (file)
index 0000000..552f7e7
--- /dev/null
@@ -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 */
diff --git a/libc/sysdeps/linux/frv/bits/wordsize.h b/libc/sysdeps/linux/frv/bits/wordsize.h
new file mode 100644 (file)
index 0000000..ba643b6
--- /dev/null
@@ -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
diff --git a/libc/sysdeps/linux/frv/brk.c b/libc/sysdeps/linux/frv/brk.c
new file mode 100644 (file)
index 0000000..4f97fb0
--- /dev/null
@@ -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;
+}
diff --git a/libc/sysdeps/linux/frv/clone.S b/libc/sysdeps/linux/frv/clone.S
new file mode 100644 (file)
index 0000000..2e3c6b7
--- /dev/null
@@ -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
diff --git a/libc/sysdeps/linux/frv/crt0.S b/libc/sysdeps/linux/frv/crt0.S
new file mode 100644 (file)
index 0000000..8a42515
--- /dev/null
@@ -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
diff --git a/libc/sysdeps/linux/frv/crti.S b/libc/sysdeps/linux/frv/crti.S
new file mode 100644 (file)
index 0000000..715ce4a
--- /dev/null
@@ -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)
diff --git a/libc/sysdeps/linux/frv/crtn.S b/libc/sysdeps/linux/frv/crtn.S
new file mode 100644 (file)
index 0000000..b495bbe
--- /dev/null
@@ -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
diff --git a/libc/sysdeps/linux/frv/crtreloc.c b/libc/sysdeps/linux/frv/crtreloc.c
new file mode 100644 (file)
index 0000000..38af68c
--- /dev/null
@@ -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
diff --git a/libc/sysdeps/linux/frv/dl-iterate-phdr.c b/libc/sysdeps/linux/frv/dl-iterate-phdr.c
new file mode 100644 (file)
index 0000000..ebb3b9c
--- /dev/null
@@ -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;
+}
diff --git a/libc/sysdeps/linux/frv/sbrk.c b/libc/sysdeps/linux/frv/sbrk.c
new file mode 100644 (file)
index 0000000..c39d600
--- /dev/null
@@ -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);
+}
diff --git a/libc/sysdeps/linux/frv/setjmp.S b/libc/sysdeps/linux/frv/setjmp.S
new file mode 100644 (file)
index 0000000..455e611
--- /dev/null
@@ -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
diff --git a/libc/sysdeps/linux/frv/sys/procfs.h b/libc/sysdeps/linux/frv/sys/procfs.h
new file mode 100644 (file)
index 0000000..f075233
--- /dev/null
@@ -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 */
diff --git a/libc/sysdeps/linux/frv/sys/ptrace.h b/libc/sysdeps/linux/frv/sys/ptrace.h
new file mode 100644 (file)
index 0000000..6b0eca7
--- /dev/null
@@ -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 */
diff --git a/libc/sysdeps/linux/frv/sys/ucontext.h b/libc/sysdeps/linux/frv/sys/ucontext.h
new file mode 100644 (file)
index 0000000..2385a07
--- /dev/null
@@ -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 */
diff --git a/libc/sysdeps/linux/frv/sysdep.c b/libc/sysdeps/linux/frv/sysdep.c
new file mode 100644 (file)
index 0000000..17260f7
--- /dev/null
@@ -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;
+}
diff --git a/libc/sysdeps/linux/frv/vfork.S b/libc/sysdeps/linux/frv/vfork.S
new file mode 100644 (file)
index 0000000..2f97b2a
--- /dev/null
@@ -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
diff --git a/libpthread/linuxthreads/sysdeps/frv/pt-machine.h b/libpthread/linuxthreads/sysdeps/frv/pt-machine.h
new file mode 100644 (file)
index 0000000..0679280
--- /dev/null
@@ -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 */