Browse Source

frv: resurrect port somehow, totally untested

The FR-V port is really broken, and I have no emulator
or hardware for this platform. I tried to get some hardware
from RedHat, who made the FR-V port initially. Unfortunately
Fujitsi didn't agreed to sent me some of their unused spare
hardware lying @RedHat. As I invested some time to get stuff compiled,
I decided to add the code and may be anytime later I can gain
access to some emulator or hardware.

GDB simulator for FR-V doesn't support booting Linux AFAIK.
Waldemar Brodkorb 8 years ago
parent
commit
c0a2d0b7ed

+ 1 - 3
Rules.mak

@@ -473,14 +473,12 @@ endif
 endif
 
 ifeq ($(TARGET_ARCH),frv)
-	CPU_LDFLAGS-$(CONFIG_FRV)+=-Wl,-melf32frvfd
 	# 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.
-	export LDPIEFLAG:=-shared -Wl,-Bsymbolic
-	UCLIBC_LDSO=ld.so.1
+	CPU_LDFLAGS-y += -Wl,-melf32frvfd -Wl,-Bsymbolic
 endif
 
 ifeq ($(strip $(TARGET_ARCH)),avr32)

+ 3 - 3
extra/Configs/Config.in.arch

@@ -20,15 +20,15 @@ config UCLIBC_FORMAT_DSBT_ELF
 	select DOPIC
 config UCLIBC_FORMAT_FLAT
 	bool "STATIC FLAT"
-	depends on !ARCH_USE_MMU
+	depends on !ARCH_USE_MMU && !TARGET_frv
 	select ARCH_HAS_NO_LDSO
 config UCLIBC_FORMAT_FLAT_SEP_DATA
 	bool "STATIC FLAT (sep-data)"
-	depends on !ARCH_USE_MMU
+	depends on !ARCH_USE_MMU && !TARGET_frv
 	select ARCH_HAS_NO_LDSO
 config UCLIBC_FORMAT_SHARED_FLAT
 	bool "SHARED FLAT"
-	depends on !ARCH_USE_MMU
+	depends on !ARCH_USE_MMU && !TARGET_frv
 	select ARCH_HAS_NO_LDSO
 	help
 	  Pick this one if you are using uClinux and wish to build

+ 3 - 3
include/link.h

@@ -79,7 +79,7 @@ extern struct r_debug _r_debug;
    */
 extern ElfW(Dyn) _DYNAMIC[];
 
-#ifdef __FDPIC__
+#if defined(__FRV_FDPIC__) || defined(__BFIN_FDPIC__)
 # include <bits/elf-fdpic.h>
 #endif
 #ifdef __DSBT__
@@ -97,7 +97,7 @@ struct link_map
     /* These first few members are part of the protocol with the debugger.
        This is the same format used in SVR4.  */
 
-#ifdef __FDPIC__
+#if defined(__FRV_FDPIC__) || defined(__BFIN_FDPIC__)
     struct elf32_fdpic_loadaddr l_addr;
 #else
 #ifdef __DSBT__
@@ -184,7 +184,7 @@ enum
 
 struct dl_phdr_info
   {
-#ifdef __FDPIC__
+#if defined(__FRV_FDPIC__) || defined(__BFIN_FDPIC__)
     struct elf32_fdpic_loadaddr dlpi_addr;
 #else
 #ifdef __DSBT__

+ 1 - 1
ldso/include/dl-elf.h

@@ -203,7 +203,7 @@ unsigned int __dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info
 	/* Don't adjust .dynamic unnecessarily.  For FDPIC targets,
 	   we'd have to walk all the loadsegs to find out if it was
 	   actually unnecessary, so skip this optimization.  */
-#if !defined __FDPIC__ && !defined __DSBT__
+#if !defined __FRV_FDPIC__ && !defined __BFIN_FDPIC__ && !defined __DSBT__
 	if (load_off != 0)
 #endif
 	{

+ 1 - 1
ldso/include/dl-hash.h

@@ -135,7 +135,7 @@ struct elf_resolve {
   unsigned long data_words;
 #endif
 
-#ifdef __FDPIC__
+#if defined(__FRV_FDPIC__) || defined(__BFIN_FDPIC__)
   /* Every loaded module holds a hashtable of function descriptors of
      functions defined in it, such that it's easy to release the
      memory when the module is dlclose()d.  */

+ 1 - 1
ldso/ldso/bfin/dl-sysdep.h

@@ -79,7 +79,7 @@ while (0)
 #define DL_MAP_SEGMENT(EPNT, PPNT, INFILE, FLAGS) \
   __dl_map_segment (EPNT, PPNT, INFILE, FLAGS)
 
-#if defined(__FDPIC__)
+#if defined(__BFIN_FDPIC__)
 #include "../fdpic/dl-sysdep.h"
 
 static __always_inline Elf32_Addr

+ 2 - 2
ldso/ldso/dl-hash.c

@@ -378,7 +378,7 @@ char *_dl_find_hash(const char *name, struct r_scope_elem *scope, struct elf_res
 				break;
 #endif
 			case STB_GLOBAL:
-#ifdef __FDPIC__
+#if defined(__FRV_FDPIC__) || defined(__BFIN_FDPIC__)
 			if (sym_ref)
 				sym_ref->tpnt = tpnt;
 #endif
@@ -387,7 +387,7 @@ char *_dl_find_hash(const char *name, struct r_scope_elem *scope, struct elf_res
 				break;
 		}
 	}
-#ifdef __FDPIC__
+#if defined(__FRV_FDPIC__) || defined(__BFIN_FDPIC__)
 	if (sym_ref)
 		sym_ref->tpnt = tpnt;
 #endif

+ 4 - 0
ldso/ldso/fdpic/dl-inlines.h

@@ -176,6 +176,10 @@ _dl_funcdesc_for (void *entry_point, void *got_value)
 	}
 
 	entry = htab_find_slot(ht, entry_point, 1, hash_pointer, eq_pointer);
+
+	if (entry == NULL)
+		_dl_exit(1);
+
 	if (*entry) {
 		_dl_assert((*entry)->entry_point == entry_point);
 		return _dl_stabilize_funcdesc(*entry);

+ 9 - 9
ldso/ldso/frv/dl-startup.h

@@ -27,9 +27,10 @@
 
 __asm__("" \
 "	.text\n"			\
-"	.global	_dl_boot\n"		\
-"	.type	_dl_boot,@function\n"	\
-"_dl_boot:\n"				\
+"	.global	_start\n"		\
+"	.type	_start,@function\n"	\
+"	.hidden	_start\n"		\
+"_start:\n"				\
 "	call	.Lcall\n"		\
 ".Lcall:\n"				\
 "	movsg	lr, gr4\n"		\
@@ -54,18 +55,18 @@ __asm__("" \
 "	addi.p	sp, #4, gr13\n"		\
 "	addi	sp, #-8, sp\n"		\
 "	mov.p	sp, gr12\n"		\
-"	call	_dl_boot2\n"		\
+"	call	_dl_start\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"	\
+"	.size	_start,.-_start\n"	\
 );
 
-#define _dl_boot _dl_boot2
-#define DL_BOOT(X)   \
+#undef DL_START
+#define DL_START(X)   \
 static void  __attribute__ ((used)) \
-_dl_boot (void *dl_boot_got_pointer, \
+_dl_start (Elf32_Addr 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, \
@@ -115,6 +116,5 @@ _dl_boot (void *dl_boot_got_pointer, \
   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)

+ 13 - 3
ldso/ldso/frv/dl-sysdep.h

@@ -40,9 +40,6 @@ extern int _dl_linux_resolve(void) __attribute__((__visibility__("hidden")));
 #define SEND_EARLY_STDERR(S) \
   do { static char __s[] = (S); SEND_STDERR (__s); } while (0)
 
-#define DL_RELOC_ADDR(ADDR, LOADADDR) \
-  (__reloc_pointer ((void*)(ADDR), (LOADADDR).map))
-
 /* Make sure we only load libraries that use the same number of
    general-purpose and floating-point registers the dynamic loader was
    compiled for.  */
@@ -85,3 +82,16 @@ do \
 while (0)
 
 #include "../fdpic/dl-sysdep.h"
+
+static __always_inline Elf32_Addr
+elf_machine_load_address (void)
+{
+	return 0;
+}
+
+static __always_inline void
+elf_machine_relative (DL_LOADADDR_TYPE load_off, const Elf32_Addr rel_addr,
+		      Elf32_Word relative_count)
+{
+	;
+}

+ 31 - 36
ldso/ldso/frv/elfinterp.c

@@ -10,6 +10,7 @@
  * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
  */
 
+#include <sys/cdefs.h>	    /* __attribute_used__ */
 #include <features.h>
 
 /* Program to load an ELF binary on a linux system, and run it.
@@ -31,34 +32,30 @@ _dl_linux_resolver (struct elf_resolve *tpnt, int reloc_entry)
 	ElfW(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;
+	struct symbol_ref sym_ref;
 
-	rel_addr = DL_RELOC_ADDR (tpnt->dynamic_info[DT_JMPREL],
-				  tpnt->loadaddr);
+	rel_addr = (char *)tpnt->dynamic_info[DT_JMPREL];
 
 	this_reloc = (ELF_RELOC *)(intptr_t)(rel_addr + reloc_entry);
 	symtab_index = ELF_R_SYM(this_reloc->r_info);
 
-	symtab = (ElfW(Sym) *)(intptr_t)
-				  DL_RELOC_ADDR (tpnt->dynamic_info[DT_SYMTAB],
-						 tpnt->loadaddr);
-	strtab = DL_RELOC_ADDR (tpnt->dynamic_info[DT_STRTAB], tpnt->loadaddr);
+	symtab = (ElfW(Sym) *) tpnt->dynamic_info[DT_SYMTAB];
+	strtab = (char *) tpnt->dynamic_info[DT_STRTAB];
+	sym_ref.sym = &symtab[symtab_index];
+	sym_ref.tpnt = NULL;
 	symname= strtab + symtab[symtab_index].st_name;
 
 	/* Address of GOT entry fix up */
-	got_entry = (struct funcdesc_value *)
-	  DL_RELOC_ADDR (this_reloc->r_offset, tpnt->loadaddr);
+	got_entry = (struct funcdesc_value *) DL_RELOC_ADDR(tpnt->loadaddr, this_reloc->r_offset);
 
 	/* Get the address to be used to fill in the GOT entry.  */
-	new_addr = _dl_find_hash_mod(symname, &_dl_loaded_modules->symbol_scope, NULL, 0,
-				     &new_tpnt);
+	new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, NULL, 0, &sym_ref);
 	if (!new_addr) {
-		new_addr = _dl_find_hash_mod(symname, NULL, NULL, 0,
-					     &new_tpnt);
+		new_addr = _dl_find_hash(symname, NULL, NULL, 0, &sym_ref);
 		if (!new_addr) {
 			_dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
 				    _dl_progname, symname);
@@ -67,7 +64,7 @@ _dl_linux_resolver (struct elf_resolve *tpnt, int reloc_entry)
 	}
 
 	funcval.entry_point = new_addr;
-	funcval.got_value = new_tpnt->loadaddr.got_value;
+	funcval.got_value = sym_ref.tpnt->loadaddr.got_value;
 
 #if defined (__SUPPORT_LD_DEBUG__)
 		if (_dl_debug_bindings)
@@ -103,14 +100,13 @@ _dl_parse(struct elf_resolve *tpnt, struct r_scope_elem *scope,
 	int symtab_index;
 
 	/* Now parse the relocation information */
-	rpnt = (ELF_RELOC *)(intptr_t) DL_RELOC_ADDR (rel_addr, tpnt->loadaddr);
+	rpnt = (ELF_RELOC *) rel_addr;
 	rel_size = rel_size / sizeof(ELF_RELOC);
 
-	symtab = (ElfW(Sym) *)(intptr_t)
-	  DL_RELOC_ADDR (tpnt->dynamic_info[DT_SYMTAB], tpnt->loadaddr);
-	strtab = DL_RELOC_ADDR (tpnt->dynamic_info[DT_STRTAB], tpnt->loadaddr);
+	symtab = (ElfW(Sym) *) tpnt->dynamic_info[DT_SYMTAB];
+	strtab = (char *) tpnt->dynamic_info[DT_STRTAB];
 
-	  for (i = 0; i < rel_size; i++, rpnt++) {
+	for (i = 0; i < rel_size; i++, rpnt++) {
 	        int res;
 
 		symtab_index = ELF_R_SYM(rpnt->r_info);
@@ -161,24 +157,24 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct r_scope_elem *scope,
 #if defined (__SUPPORT_LD_DEBUG__)
 	unsigned long old_val;
 #endif
+	struct symbol_ref sym_ref;
 
-	reloc_addr   = (unsigned long *)(intptr_t)
-	  DL_RELOC_ADDR (rpnt->r_offset, tpnt->loadaddr);
+	reloc_addr   = (unsigned long *) DL_RELOC_ADDR (tpnt->loadaddr, rpnt->r_offset);
 	__asm__ ("" : "=r" (reloc_addr_packed) : "0" (reloc_addr));
 	reloc_type   = ELF_R_TYPE(rpnt->r_info);
 	symtab_index = ELF_R_SYM(rpnt->r_info);
 	symbol_addr  = 0;
+	sym_ref.sym =  &symtab[symtab_index];
+	sym_ref.tpnt =  NULL;
 	symname      = strtab + symtab[symtab_index].st_name;
 
 	if (ELF_ST_BIND (symtab[symtab_index].st_info) == STB_LOCAL) {
-		symbol_addr = (unsigned long)
-		  DL_RELOC_ADDR (symtab[symtab_index].st_value,
-				 tpnt->loadaddr);
+		symbol_addr = (unsigned long) DL_RELOC_ADDR(tpnt->loadaddr, symtab[symtab_index].st_value);
 		symbol_tpnt = tpnt;
 	} else {
 
 		symbol_addr = (unsigned long)
-		  _dl_find_hash_mod(symname, scope, NULL, 0, &symbol_tpnt);
+		  _dl_find_hash(symname, scope, NULL, 0, &sym_ref);
 
 		/*
 		 * We want to allow undefined references to weak symbols - this might
@@ -191,6 +187,7 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct r_scope_elem *scope,
 				     _dl_progname, strtab + symtab[symtab_index].st_name);
 			_dl_exit (1);
 		}
+		symbol_tpnt = sym_ref.tpnt;
 	}
 
 #if defined (__SUPPORT_LD_DEBUG__)
@@ -276,9 +273,9 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct r_scope_elem *scope,
 
 static int
 _dl_do_lazy_reloc (struct elf_resolve *tpnt,
-		   struct r_scope_elem *scope __attribute_used__,
-		   ELF_RELOC *rpnt, ElfW(Sym) *symtab __attribute_used__,
-		   char *strtab __attribute_used__)
+		   struct r_scope_elem *scope __attribute__((unused)),
+		   ELF_RELOC *rpnt, ElfW(Sym) *symtab __attribute__((unused)),
+		   char *strtab __attribute__((unused)))
 {
 	int reloc_type;
 	struct funcdesc_value volatile *reloc_addr;
@@ -288,7 +285,7 @@ _dl_do_lazy_reloc (struct elf_resolve *tpnt,
 #endif
 
 	reloc_addr = (struct funcdesc_value *)(intptr_t)
-	  DL_RELOC_ADDR (rpnt->r_offset, tpnt->loadaddr);
+	  DL_RELOC_ADDR (tpnt->loadaddr, rpnt->r_offset);
 	reloc_type = ELF_R_TYPE(rpnt->r_info);
 
 #if defined (__SUPPORT_LD_DEBUG__)
@@ -299,9 +296,7 @@ _dl_do_lazy_reloc (struct elf_resolve *tpnt,
 				break;
 			case R_FRV_FUNCDESC_VALUE:
 				funcval = *reloc_addr;
-				funcval.entry_point =
-				  DL_RELOC_ADDR (funcval.entry_point,
-						 tpnt->loadaddr);
+				funcval.entry_point = (void *) DL_RELOC_ADDR(tpnt->loadaddr, funcval.entry_point);
 				funcval.got_value = tpnt->loadaddr.got_value;
 				*reloc_addr = funcval;
 				break;
@@ -334,14 +329,14 @@ _dl_parse_relocation_information
 
 int
 _dl_parse_copy_information
-(struct dyn_elf *rpnt __attribute_used__,
- unsigned long rel_addr __attribute_used__,
- unsigned long rel_size __attribute_used__)
+(struct dyn_elf *rpnt __attribute__((unused)),
+ unsigned long rel_addr __attribute__((unused)),
+ unsigned long rel_size __attribute__((unused)))
 {
   return 0;
 }
 
-#ifndef LIBDL
+#ifndef IS_IN_libdl
 # include "../../libc/sysdeps/linux/frv/crtreloc.c"
 #endif
 

+ 1 - 1
libc/misc/elf/dl-iterate-phdr.c

@@ -58,7 +58,7 @@ dl_iterate_phdr (int (*callback) (struct dl_phdr_info *info,
       /* This entry describes this statically-linked program itself.  */
       struct dl_phdr_info info;
       int ret;
-#if defined(__FDPIC__)
+#if defined(__FRV_FDPIC__) || defined(__BFIN_FDPIC__)
       info.dlpi_addr.map = NULL;
       info.dlpi_addr.got_value = NULL;
 #elif defined(__DSBT__)

+ 7 - 52
libc/sysdeps/linux/frv/Makefile

@@ -1,58 +1,13 @@
 # Makefile for uClibc
 #
 # Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
-# ported to FR-V by Alexandre Oliva <aoliva@redhat.com>
 #
 # Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+#
 
-TOPDIR=../../../../
-include $(TOPDIR)Rules.mak
-
-CRT_SRC := crt0.S
-CRT_OBJ := crt0.o crt1.o
-SCRT_OBJ := $(patsubst %,S%, $(CRT_OBJ))
-
-CTOR_TARGETS := crti.o crtn.o
-
-SSRC := __longjmp.S setjmp.S clone.S vfork.S
-SOBJ := $(patsubst %.S,%.o, $(SSRC))
-
-CSRC = sysdep.c syscall.c brk.c sbrk.c __init_brk.c dl-iterate-phdr.c
-CSRC += xstatconv.c stat.c stat64.c fstat.c fstat64.c lstat.c lstat64.c
-COBJ := $(patsubst %.c,%.o, $(CSRC))
-
-OBJS := $(SOBJ) $(COBJ)
-
-OBJ_LIST := ../../../obj.sysdeps.$(TARGET_ARCH)
-
-all: $(OBJ_LIST)
-
-$(OBJ_LIST): $(OBJS) $(CRT_OBJ) $(SCRT_OBJ) $(CTOR_TARGETS)
-	$(STRIPTOOL) -x -R .note -R .comment $^
-	$(INSTALL) -d $(TOPDIR)lib/
-	cp $(CRT_OBJ) $(SCRT_OBJ) $(CTOR_TARGETS) $(TOPDIR)lib/
-	echo $(patsubst %, sysdeps/linux/$(TARGET_ARCH)/%, $(OBJS)) > $@
-
-$(CRT_OBJ): $(CRT_SRC) crtreloc.o
-	$(CC) $(ASFLAGS) -DL_$* -r -nostdlib $^ -o $*.o
-
-crtreloc.o: crtreloc.c
-	$(CC) $(CFLAGS) -c $< -o $@
-
-$(SCRT_OBJ): $(CRT_SRC) Scrtreloc.o
-	$(CC) $(ASFLAGS) $(PIEFLAG) -DL_$* -r -nostdlib $^ -o $*.o
-
-Scrtreloc.o: crtreloc.c
-	$(CC) $(CFLAGS) $(PIEFLAG) -c $< -o $@
-
-$(CTOR_TARGETS): %.o : %.S
-	$(CC) $(ASFLAGS) $(SSP_DISABLE_FLAGS) -c $< -o $@
-
-$(SOBJ): %.o : %.S
-	$(CC) $(ASFLAGS) -c $< -o $@
-
-$(COBJ): %.o : %.c
-	$(CC) $(CFLAGS) -c $< -o $@
-
-clean:
-	$(RM) *.o *~ core
+top_srcdir=../../../../
+top_builddir=../../../../
+all: objs
+include $(top_builddir)Rules.mak
+include Makefile.arch
+include $(top_srcdir)Makerules

+ 11 - 0
libc/sysdeps/linux/frv/Makefile.arch

@@ -0,0 +1,11 @@
+# Makefile for uClibc
+#
+# Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+# ported to FR-V by Alexandre Oliva <aoliva@redhat.com>
+#
+# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+
+CSRC-y := sysdep.c syscall.c brk.c sbrk.c __init_brk.c dl-iterate-phdr.c
+
+SSRC-y := __longjmp.S setjmp.S clone.S vfork.S
+

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

@@ -22,6 +22,9 @@
 
 
 #include <sys/types.h>
+#ifdef __USE_GNU
+# include <bits/uio.h>
+#endif
 
 /* open/fcntl - O_SYNC is only implemented on blocks devices and on files
    located on an ext2 file system */

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

@@ -31,6 +31,9 @@ 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 __kernel_dev_t	__kernel_old_dev_t;
+typedef long		__kernel_long_t;
+typedef unsigned long	__kernel_ulong_t;
 
 typedef struct {
 #ifdef __USE_ALL

+ 30 - 3
libc/sysdeps/linux/frv/bits/stat.h

@@ -70,6 +70,20 @@ struct stat
     __blkcnt64_t st_blocks;		/* Number 512-byte blocks allocated. */
 #endif
 
+#ifdef __USE_MISC
+    /* Nanosecond resolution timestamps are stored in a format
+       equivalent to 'struct timespec'.  This is the type used
+       whenever possible but the Unix namespace rules do not allow the
+       identifier 'timespec' to appear in the <sys/stat.h> header.
+       Therefore we have to handle the use of this header in strictly
+       standard-compliant sources special.  */
+    struct timespec st_atim;		/* Time of last access.  */
+    struct timespec st_mtim;		/* Time of last modification.  */
+    struct timespec st_ctim;		/* Time of last status change.  */
+# define st_atime st_atim.tv_sec	/* Backward compatibility.  */
+# define st_mtime st_mtim.tv_sec
+# define st_ctime st_ctim.tv_sec
+#else
     unsigned long int __unused1;
     __time_t st_atime;			/* Time of last access.  */
 
@@ -78,7 +92,7 @@ struct stat
 
     unsigned long int __unused3;
     __time_t st_ctime;			/* Time of last status change.  */
-
+#endif
     unsigned long long __unused4;
 };
 
@@ -103,7 +117,20 @@ struct stat64
     __blksize_t st_blksize;		/* Optimal block size for I/O.  */
 
     __blkcnt64_t st_blocks;		/* Number 512-byte blocks allocated. */
-
+#ifdef __USE_MISC
+    /* Nanosecond resolution timestamps are stored in a format
+       equivalent to 'struct timespec'.  This is the type used
+       whenever possible but the Unix namespace rules do not allow the
+       identifier 'timespec' to appear in the <sys/stat.h> header.
+       Therefore we have to handle the use of this header in strictly
+       standard-compliant sources special.  */
+    struct timespec st_atim;		/* Time of last access.  */
+    struct timespec st_mtim;		/* Time of last modification.  */
+    struct timespec st_ctim;		/* Time of last status change.  */
+# define st_atime st_atim.tv_sec	/* Backward compatibility.  */
+# define st_mtime st_mtim.tv_sec
+# define st_ctime st_ctim.tv_sec
+#else
     unsigned long int __unused1;
     __time_t st_atime;			/* Time of last access.  */
 
@@ -112,7 +139,7 @@ struct stat64
 
     unsigned long int __unused3;
     __time_t st_ctime;			/* Time of last status change.  */
-
+#endif
     unsigned long long __unused4;
 };
 #endif

+ 62 - 119
libc/sysdeps/linux/frv/bits/syscalls.h

@@ -10,128 +10,71 @@
 
 #define SYS_ify(syscall_name)  (__NR_##syscall_name)
 
-/* user-visible error numbers are in the range -1 - -4095: see <asm-frv/errno.h> */
-#if defined _LIBC && !defined __set_errno
-# define __syscall_return(type, res) \
-do { \
-        unsigned long __sr2 = (res);		    			    \
-	if (unlikely ((unsigned long)(__sr2) >= (unsigned long)(-4095))) {  \
-		extern int __syscall_error (int);			    \
-		return (type) __syscall_error (__sr2);		    	    \
-	}								    \
-	return (type) (__sr2); 						    \
-} while (0)
-#else
-# define __syscall_return(type, res) \
-do { \
-        unsigned long __sr2 = (res);		    			    \
-	if (unlikely ((unsigned long)(__sr2) >= (unsigned long)(-4095))) {  \
-		__set_errno (-__sr2);				    	    \
-		__sr2 = -1; 						    \
-	}								    \
-	return (type) (__sr2); 						    \
-} while (0)
-#endif
-
-#ifndef __set_errno
-# define __set_errno(val) ((*__errno_location ()) = (val))
-#endif
-
-/* 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 INLINE_SYSCALL_NCS(name, nr, args...)				\
+(__extension__								\
+  ({									\
+     unsigned int _inline_sys_result = INTERNAL_SYSCALL_NCS (name, , nr, args);\
+     if (unlikely (INTERNAL_SYSCALL_ERROR_P (_inline_sys_result, )))	\
+       {								\
+	 __set_errno (INTERNAL_SYSCALL_ERRNO (_inline_sys_result, ));	\
+	 _inline_sys_result = (unsigned int) -1;			\
+       }								\
+     (int) _inline_sys_result;						\
+   })									\
+)
 
-#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 INTERNAL_SYSCALL_NCS(name, err, nr, args...)			\
+(__extension__ \
+  ({unsigned int __internal_sys_result;					\
+     {									\
+       register int __a1 __asm__ ("gr8");				\
+       register int _nr __asm__ ("gr7");				\
+       LOAD_ARGS_##nr (args)						\
+       _nr = (name);							\
+       __asm__ __volatile__ ("tra      gr0,gr0"				\
+			     : "=r" (__a1)				\
+			     : "r" (_nr) ASM_ARGS_##nr			\
+			     : "memory");				\
+	       __internal_sys_result = __a1;				\
+     }									\
+     (int) __internal_sys_result; }) \
+)
 
-#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 INTERNAL_SYSCALL_ERROR_P(val, err) \
+  ((unsigned int) (val) >= 0xfffff001u)
 
-#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);	 					    \
-}
+#define LOAD_ARGS_0()
+#define ASM_ARGS_0
+#define LOAD_ARGS_1(a1)				\
+  int __a1tmp = (int) (a1);			\
+  LOAD_ARGS_0 ()				\
+  __a1 = __a1tmp;
+#define ASM_ARGS_1	ASM_ARGS_0, "r" (__a1)
+#define LOAD_ARGS_2(a1, a2)			\
+  int __a2tmp = (int) (a2);			\
+  LOAD_ARGS_1 (a1)				\
+  register int __a2 __asm__ ("gr8") = __a2tmp;
+#define ASM_ARGS_2	ASM_ARGS_1, "r" (__a2)
+#define LOAD_ARGS_3(a1, a2, a3)			\
+  int __a3tmp = (int) (a3);			\
+  LOAD_ARGS_2 (a1, a2)				\
+  register int __a3 __asm__ ("gr9") = __a3tmp;
+#define ASM_ARGS_3	ASM_ARGS_2, "r" (__a3)
+#define LOAD_ARGS_4(a1, a2, a3, a4)		\
+  int __a4tmp = (int) (a4);			\
+  LOAD_ARGS_3 (a1, a2, a3)			\
+  register int __a4 __asm__ ("gr10") = __a4tmp;
+#define ASM_ARGS_4	ASM_ARGS_3, "r" (__a4)
+#define LOAD_ARGS_5(a1, a2, a3, a4, a5)		\
+  int __v1tmp = (int) (a5);			\
+  LOAD_ARGS_4 (a1, a2, a3, a4)			\
+  register int __v1 __asm__ ("gr11") = __v1tmp;
+#define ASM_ARGS_5	ASM_ARGS_4, "r" (__v1)
+#define LOAD_ARGS_6(a1, a2, a3, a4, a5, a6)	\
+  int __v2tmp = (int) (a6);			\
+  LOAD_ARGS_5 (a1, a2, a3, a4, a5)		\
+  register int __v2 __asm__ ("gr12") = __v2tmp;
+#define ASM_ARGS_6	ASM_ARGS_5, "r" (__v2)
 
 #endif /* __ASSEMBLER__ */
 #endif /* _BITS_SYSCALLS_H */

+ 1 - 1
libc/sysdeps/linux/frv/bits/uClibc_arch_features.h

@@ -37,6 +37,6 @@
 #define __UCLIBC_HAVE_SIGNED_ZERO__
 
 /* only weird assemblers generally need this */
-#undef __UCLIBC_ASM_LINE_SEP__
+#define __UCLIBC_ASM_LINE_SEP__ !
 
 #endif /* _BITS_UCLIBC_ARCH_FEATURES_H */

+ 3 - 6
libc/sysdeps/linux/frv/crt0.S → libc/sysdeps/linux/frv/crt1.S

@@ -44,13 +44,10 @@ not, see <http://www.gnu.org/licenses/>.  */
 	.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
+	.type	__uClibc_main,%function
+
 _start:
 	/* Make sure the stack pointer is properly aligned.  Save the
 	   original value in gr21 such that we can get to arguments and
@@ -104,7 +101,7 @@ _start:
 	ld.p	@(gr11, gr17), gr11
 	mov	gr17, gr15
 	ld.p	@(gr12, gr17), gr12
-	call	__uClibc_start_main
+	call	__uClibc_main
 #else
 	mov.p	gr17, gr15
 	call	__uClibc_main

+ 4 - 46
libc/sysdeps/linux/frv/crtreloc.c

@@ -25,6 +25,8 @@ 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, see <http://www.gnu.org/licenses/>.  */
 
+#ifdef __FRV_FDPIC__
+
 #include <sys/types.h>
 #include <link.h>
 
@@ -61,7 +63,7 @@ reloc_range_indirect (void ***p, void ***e,
 /* 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* attribute_hidden
+attribute_hidden void*
 __self_reloc (const struct elf32_fdpic_loadmap *map,
 	      void ***p, void ***e)
 {
@@ -72,48 +74,4 @@ __self_reloc (const struct elf32_fdpic_loadmap *map,
 
   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).  */
-static __always_inline 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 attribute_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* attribute_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
+#endif /* __FRV_FDPIC__ */

+ 0 - 2
libc/sysdeps/linux/frv/jmpbuf-unwind.h

@@ -10,5 +10,3 @@
    containing a local variable at ADDRESS.  */
 #define _JMPBUF_UNWINDS(jmpbuf, address) \
   ((void *) (address) < (void *) (jmpbuf)->__sp)
-
-#endif	/* bits/setjmp.h */

+ 1 - 1
libc/sysdeps/linux/frv/syscall.c

@@ -37,5 +37,5 @@ long syscall(long sysnum, long arg1, long arg2, long arg3,
 			: "+r" (__sc0)
 			: "r" (__scnum), "r" (__sc1), "r" (__sc2),
 			"r" (__sc3), "r" (__sc4), "r" (__sc5));
-  __syscall_return(long,__sc0);
+  return (long) __sc0;
 }