summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libc/sysdeps/linux/bfin/bits/elf-fdpic.h115
-rw-r--r--libc/sysdeps/linux/bfin/bits/mman.h11
-rw-r--r--libc/sysdeps/linux/bfin/bits/syscalls.h40
-rw-r--r--libc/sysdeps/linux/bfin/brk.c2
-rw-r--r--libc/sysdeps/linux/bfin/bsd-_setjmp.S9
-rw-r--r--libc/sysdeps/linux/bfin/clone.c24
-rw-r--r--libc/sysdeps/linux/bfin/crt1.S122
-rw-r--r--libc/sysdeps/linux/bfin/crti.S73
-rw-r--r--libc/sysdeps/linux/bfin/crtn.S65
-rw-r--r--libc/sysdeps/linux/bfin/crtreloc.c145
-rw-r--r--libc/sysdeps/linux/bfin/link.h127
-rw-r--r--libc/sysdeps/linux/bfin/setjmp.S9
12 files changed, 650 insertions, 92 deletions
diff --git a/libc/sysdeps/linux/bfin/bits/elf-fdpic.h b/libc/sysdeps/linux/bfin/bits/elf-fdpic.h
new file mode 100644
index 000000000..0dbb54b4c
--- /dev/null
+++ b/libc/sysdeps/linux/bfin/bits/elf-fdpic.h
@@ -0,0 +1,115 @@
+/* Copyright 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 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.
+
+In addition to the permissions in the GNU Lesser General Public
+License, the Free Software Foundation gives you unlimited
+permission to link the compiled version of this file with other
+programs, and to distribute those programs without any restriction
+coming from the use of this file. (The GNU Lesser General Public
+License restrictions do apply in other respects; for example, they
+cover modification of the file, and distribution when not linked
+into another program.)
+
+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 only check for one-past-the-end for the last segment,
+ assumed to be the data segment, because other cases are
+ ambiguous in the absence of padding between segments, and
+ rofixup already serves as padding between text and data.
+ Unfortunately, unless we special-case the last segment, we
+ fail to relocate the _end symbol. */
+ if (offset < map->segs[c].p_memsz
+ || (offset == map->segs[c].p_memsz && c + 1 == map->nsegs))
+ 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/bfin/bits/mman.h b/libc/sysdeps/linux/bfin/bits/mman.h
index d57eeb587..c75ff4b0d 100644
--- a/libc/sysdeps/linux/bfin/bits/mman.h
+++ b/libc/sysdeps/linux/bfin/bits/mman.h
@@ -72,16 +72,15 @@
/* Flags for `mremap'. */
#ifdef __USE_GNU
# define MREMAP_MAYMOVE 1
-# define MREMAP_FIXED 2
#endif
/* Advice to `madvise'. */
#ifdef __USE_BSD
-# define MADV_NORMAL 0 /* No further special treatment. */
-# define MADV_RANDOM 1 /* Expect random page references. */
-# define MADV_SEQUENTIAL 2 /* Expect sequential page references. */
-# define MADV_WILLNEED 3 /* Will need these pages. */
-# define MADV_DONTNEED 4 /* Don't need these pages. */
+# define MADV_NORMAL 0x0 /* No further special treatment. */
+# define MADV_RANDOM 0x1 /* Expect random page references. */
+# define MADV_SEQUENTIAL 0x2 /* Expect sequential page references. */
+# define MADV_WILLNEED 0x3 /* Will need these pages. */
+# define MADV_DONTNEED 0x4 /* Don't need these pages. */
#endif
/* The POSIX people had to invent similar names for the same things. */
diff --git a/libc/sysdeps/linux/bfin/bits/syscalls.h b/libc/sysdeps/linux/bfin/bits/syscalls.h
index d8d628cab..5ffaa7a8b 100644
--- a/libc/sysdeps/linux/bfin/bits/syscalls.h
+++ b/libc/sysdeps/linux/bfin/bits/syscalls.h
@@ -4,25 +4,45 @@
# error "Never use <bits/syscalls.h> directly; include <sys/syscall.h> instead."
#endif
-#include <features.h>
-
/* 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>
-/* This code is mostly cut & paste from the uClinux bfin port */
+#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__
-#define __syscall_return(type, res) \
-do { \
- if ((unsigned long)(res) >= (unsigned long)(-125)) \
- { __set_errno(-(res)); \
- res = -1; \
- } \
- return (type) (res); \
+/* 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 (__builtin_expect ((unsigned long)(__sr2) \
+ >= (unsigned long)(-4095), 0)) { \
+ 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 (__builtin_expect ((unsigned long)(__sr2) \
+ >= (unsigned long)(-4095), 0)) { \
+ __set_errno (-__sr2); \
+ __sr2 = -1; \
+ } \
+ return (type) (__sr2); \
} while (0)
+#endif
#define _syscall0(type,name) \
type name(void) { \
diff --git a/libc/sysdeps/linux/bfin/brk.c b/libc/sysdeps/linux/bfin/brk.c
index 3b261697b..5735321bb 100644
--- a/libc/sysdeps/linux/bfin/brk.c
+++ b/libc/sysdeps/linux/bfin/brk.c
@@ -4,9 +4,9 @@
* Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
*/
+#include <errno.h>
#include <unistd.h>
#include <sys/syscall.h>
-#include <errno.h>
libc_hidden_proto(brk)
diff --git a/libc/sysdeps/linux/bfin/bsd-_setjmp.S b/libc/sysdeps/linux/bfin/bsd-_setjmp.S
index 6f17a6025..69ae8f878 100644
--- a/libc/sysdeps/linux/bfin/bsd-_setjmp.S
+++ b/libc/sysdeps/linux/bfin/bsd-_setjmp.S
@@ -7,11 +7,11 @@
#include <bits/setjmp.h>
.text
-.global _setjmp;
-.type _setjmp,STT_FUNC;
+.global __setjmp;
+.type __setjmp,STT_FUNC;
.align 4;
-_setjmp:
+__setjmp:
[--SP] = P0; // Save P0
P0 = R0;
R0 = [SP++];
@@ -90,8 +90,7 @@ _setjmp:
R0 = RETS;
[P0 + 0x9C] = R0;
- R0 = [P0 + 0x20];
R0 = 0;
RTS;
-.size _setjmp,.-_setjmp
+.size __setjmp,.-__setjmp
diff --git a/libc/sysdeps/linux/bfin/clone.c b/libc/sysdeps/linux/bfin/clone.c
index f326f00a0..fbf43ade9 100644
--- a/libc/sysdeps/linux/bfin/clone.c
+++ b/libc/sysdeps/linux/bfin/clone.c
@@ -15,6 +15,7 @@ clone (int (*fn)(void *arg), void *child_stack, int flags, void *arg)
if (fn && child_stack) {
+#ifdef __BFIN_FDPIC__
__asm__ __volatile__ (
"r1 = %2;"
"r0 = %3;"
@@ -25,6 +26,28 @@ clone (int (*fn)(void *arg), void *child_stack, int flags, void *arg)
"if !cc jump xxx;" /* if (rval != 0) skip to parent */
"r0 = %4;"
"p0 = %5;"
+ "fp = 0;"
+ "p1 = [p0];"
+ "p3 = [p0 + 4];"
+ "call (p1);" /* Call cloned function */
+ "p0 = %6;"
+ "excpt 0;" /* Call sys_exit */
+ "xxx: nop;"
+ : "=d" (rval)
+ : "i" (__NR_clone), "a" (child_stack), "a" (flags), "a" (arg), "a" (fn), "i" (__NR_exit)
+ : "CC", "R0", "R1", "P0");
+#else
+ __asm__ __volatile__ (
+ "r1 = %2;"
+ "r0 = %3;"
+ "P0 = %1;"
+ "excpt 0;" /*Call sys_clone*/
+ "%0 = r0;"
+ "cc = r0 == 0;"
+ "if !cc jump xxx;" /* if (rval != 0) skip to parent */
+ "r0 = %4;"
+ "p0 = %5;"
+ "fp = 0;"
"call (p0);" /* Call cloned function */
"p0 = %6;"
"excpt 0;" /* Call sys_exit */
@@ -32,6 +55,7 @@ clone (int (*fn)(void *arg), void *child_stack, int flags, void *arg)
: "=d" (rval)
: "i" (__NR_clone), "a" (child_stack), "a" (flags), "a" (arg), "a" (fn), "i" (__NR_exit)
: "CC", "R0", "R1", "P0");
+#endif
}
return rval;
}
diff --git a/libc/sysdeps/linux/bfin/crt1.S b/libc/sysdeps/linux/bfin/crt1.S
index b9b6e3b86..ead8dbfbe 100644
--- a/libc/sysdeps/linux/bfin/crt1.S
+++ b/libc/sysdeps/linux/bfin/crt1.S
@@ -1,23 +1,35 @@
-/* Initial C runtime code for Blackfin
- *
- * Copyright (C) 2004-2006 Erik Andersen <andersen@uclibc.org>
- *
- * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
- */
+/* Copyright (C) 1991, 1992 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., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
/* When we enter this piece of code, the user stack looks like this:
-* [SP] argc argument counter (integer)
+* argc argument counter (integer)
* argv[0] program name (pointer)
* argv[1...N] program args (pointers)
* NULL
* env[0...N] environment variables (pointers)
* NULL
-
+
* When we are done here, we want
* R0=argc
-* R1=argv
-* R2=__init
-* SP=__fini
+* R1=*argv[0]
+* R2=*envp[0]
*/
#include <features.h>
@@ -29,44 +41,86 @@
.global ___uClibc_main;
.type ___uClibc_main,STT_FUNC;
-#define __UCLIBC_CTOR_DTOR__
-#if defined(__UCLIBC_CTOR_DTOR__)
-.weak __init;
-.weak __fini;
-#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,STT_FUNC;
__start:
+#ifdef __BFIN_FDPIC__
+ /* P0 contains a pointer to the program's load map. */
+ call .Lcall;
+.Lcall:
+ R4 = RETS;
+ SP += -12;
+ R0.L = .Lcall;
+ R0.H = .Lcall;
+ R1.L = __ROFIXUP_LIST__;
+ R1.H = __ROFIXUP_LIST__;
+ R2.L = __ROFIXUP_END__;
+ R2.H = __ROFIXUP_END__;
+ R1 = R1 - R0;
+ R1 = R1 + R4;
+ R2 = R2 - R0;
+ R2 = R2 + R4;
+ R0 = P0;
+ CALL ___self_reloc;
+ SP += 12;
+ P3 = R0;
+#endif
+
/* clear the frame pointer and the L registers. */
FP = 0;
L0 = 0;
L1 = 0;
L2 = 0;
L3 = 0;
-
-/* Load register R0 (argc) from the stack to its final resting place */
+
+/* Load register R1 (argc) from the stack to its final resting place */
P0 = SP;
- R0 = [P0++];
+ R1 = [P0++];
-/* Copy argv pointer into R1 */
- R1 = P0;
+/* Copy argv pointer into R2 -- which its final resting place */
+ R2 = P0;
-#if defined(__UCLIBC_CTOR_DTOR__)
-/* Load __init into R2 */
- R2.H = __init;
- R2.L = __init;
+/* Skip to the end of argv and put a pointer to the environment in
+ [SP + 12] */
+ R3 = R1;
+ R3 <<= 2;
+ R3 += 4;
+ R3 = R2 + R3;
-/* Load __fini onto the stack */
- SP += -16;
+ SP += -24;
+ [SP + 12] = R3;
+
+/* Ok, now run uClibc's main() -- shouldn't return */
+#if defined L_crt1 && defined __UCLIBC_CTOR_DTOR__
+#ifdef __BFIN_FDPIC__
+ R3 = [P3 + __init@FUNCDESC_GOT17M4];
+#else
+ R3.H = __init;
+ R3.L = __init;
+#endif
+ [SP+16] = R3;
+#ifdef __BFIN_FDPIC__
+ R3 = [P3 + __fini@FUNCDESC_GOT17M4];
+#else
R3.H = __fini;
R3.L = __fini;
- [SP+12] = R3;
-#else
-/* Just fixup the stack */
- sp += -12;
+#endif
+ [SP+20] = R3;
+#else /* no ctor/dtor handling */
+ R3 = 0;
+ [SP + 16] = R3;
+ [SP + 20] = R3;
#endif
-/* Ok, now run uClibc's main() -- shouldn't return */
+#ifdef __BFIN_FDPIC__
+ R0 = [P3 + _main@FUNCDESC_GOT17M4];
+#else
+ R0.H = _main;
+ R0.L = _main;
+#endif
jump.l ___uClibc_main;
-
-.size __start,.-__start
diff --git a/libc/sysdeps/linux/bfin/crti.S b/libc/sysdeps/linux/bfin/crti.S
index 56b268a28..7c10392d8 100644
--- a/libc/sysdeps/linux/bfin/crti.S
+++ b/libc/sysdeps/linux/bfin/crti.S
@@ -1,17 +1,62 @@
- .section .init
- .section .fini
+/* Specialized code needed to support construction and destruction of
+ file-scope objects in C++ and Java code, and to support exception handling.
+ Copyright (C) 1999 Free Software Foundation, Inc.
+ Contributed by Charles-Antoine Gauthier (charles.gauthier@iit.nrc.ca).
-.text;
-.align 2
-.global __init;
-.type __init, STT_FUNC;
-__init:
- LINK 0;
- SP += -12;
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GCC 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
-.align 2
-.global __fini;
-.type __fini, STT_FUNC;
+/* As a special exception, if you link this library with files
+ compiled with GCC to produce an executable, this does not cause
+ the resulting executable to be covered by the GNU General Public License.
+ This exception does not however invalidate any other reasons why
+ the executable file might be covered by the GNU General Public License. */
+
+/*
+ * This file just supplies function prologues for the .init and .fini
+ * sections. It is linked in before crtbegin.o.
+ */
+
+ .file "crti.o"
+ .ident "GNU C crti.o"
+
+ .section .init
+ .globl __init
+ .type __init,@function
+__init:
+#if defined __ID_SHARED_LIB__
+ [--SP] = P5;
+#elif defined __BFIN_FDPIC__
+ [--SP] = P3;
+#endif
+ LINK 12;
+#if defined __ID_SHARED_LIB__
+ P5 = [P5 + _current_shared_library_p5_offset_]
+#endif
+ .section .fini
+ .globl __fini
+ .type __fini,@function
__fini:
- LINK 0;
- SP += -12;
+#if defined __ID_SHARED_LIB__
+ [--SP] = P5;
+#elif defined __BFIN_FDPIC__
+ [--SP] = P3;
+#endif
+ LINK 12;
+#if defined __ID_SHARED_LIB__
+ P5 = [P5 + _current_shared_library_p5_offset_]
+#endif
diff --git a/libc/sysdeps/linux/bfin/crtn.S b/libc/sysdeps/linux/bfin/crtn.S
index 11ba9420d..add0b7162 100644
--- a/libc/sysdeps/linux/bfin/crtn.S
+++ b/libc/sysdeps/linux/bfin/crtn.S
@@ -1,18 +1,53 @@
- .section .init
- .section .fini
+/* Specialized code needed to support construction and destruction of
+ file-scope objects in C++ and Java code, and to support exception handling.
+ Copyright (C) 1999 Free Software Foundation, Inc.
+ Contributed by Charles-Antoine Gauthier (charles.gauthier@iit.nrc.ca).
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GCC 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
-.text;
-.align 2
-.global __init;
-.type __init, STT_FUNC;
- SP += 12;
- UNLINK;
+/* As a special exception, if you link this library with files
+ compiled with GCC to produce an executable, this does not cause
+ the resulting executable to be covered by the GNU General Public License.
+ This exception does not however invalidate any other reasons why
+ the executable file might be covered by the GNU General Public License. */
+
+/*
+ * This file supplies function epilogues for the .init and .fini sections.
+ * It is linked in after all other files.
+ */
+
+ .file "crtn.o"
+ .ident "GNU C crtn.o"
+
+ .section .init
+ unlink;
+#if defined __ID_SHARED_LIB__
+ P5 = [SP++];
+#elif defined __BFIN_FDPIC__
+ P3 = [SP++];
+#endif
rts;
- .size __init, .-__init
-.align 2
-.global __fini;
-.type __fini, STT_FUNC;
- SP += 12;
- UNLINK;
+
+ .section .fini
+ unlink;
+#if defined __ID_SHARED_LIB__
+ P5 = [SP++];
+#elif defined __BFIN_FDPIC__
+ P3 = [SP++];
+#endif
rts;
- .size __fini, .-__fini
diff --git a/libc/sysdeps/linux/bfin/crtreloc.c b/libc/sysdeps/linux/bfin/crtreloc.c
new file mode 100644
index 000000000..4df304346
--- /dev/null
+++ b/libc/sysdeps/linux/bfin/crtreloc.c
@@ -0,0 +1,145 @@
+/* Copyright (C) 2003, 2004 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.
+
+In addition to the permissions in the GNU Lesser General Public
+License, the Free Software Foundation gives you unlimited
+permission to link the compiled version of this file with other
+programs, and to distribute those programs without any restriction
+coming from the use of this file. (The GNU Lesser General Public
+License restrictions do apply in other respects; for example, they
+cover modification of the file, and distribution when not linked
+into another program.)
+
+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. */
+
+#ifdef __BFIN_FDPIC__
+
+#define _GNU_SOURCE 1
+#include <sys/types.h>
+#include <link.h>
+
+/* This file is to be compiled into crt object files, to enable
+ executables to easily self-relocate. */
+
+#define hidden __attribute__((__visibility__("hidden")))
+
+union word {
+ char c[4];
+ void *v;
+};
+
+/* 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)
+ {
+ unsigned char *c = ptr;
+ int i;
+ unsigned long v = 0;
+ for (i = 0; i < 4; i++)
+ v |= c[i] << 8 * i;
+ pt = (void *)v;
+ }
+ else
+ pt = *(void**)ptr;
+ pt = __reloc_pointer (pt, map);
+ if ((long)ptr & 3)
+ {
+ unsigned char *c = ptr;
+ int i;
+ unsigned long v = (unsigned long)pt;
+ for (i = 0; i < 4; i++, v >>= 8)
+ c[i] = v;
+ }
+ 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
+
+#endif /* __BFIN_FDPIC__ */
diff --git a/libc/sysdeps/linux/bfin/link.h b/libc/sysdeps/linux/bfin/link.h
new file mode 100644
index 000000000..59caefc62
--- /dev/null
+++ b/libc/sysdeps/linux/bfin/link.h
@@ -0,0 +1,127 @@
+/* Data structure for communication from the run-time dynamic linker for
+ loaded ELF shared objects.
+ Copyright (C) 1995-1999, 2000, 2001, 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 _LINK_H
+#define _LINK_H 1
+
+#include <features.h>
+#include <elf.h>
+#include <dlfcn.h>
+#include <sys/types.h>
+
+/* We use this macro to refer to ELF types independent of the native wordsize.
+ `ElfW(TYPE)' is used in place of `Elf32_TYPE' or `Elf64_TYPE'. */
+#define ElfW(type) _ElfW (Elf, __ELF_NATIVE_CLASS, type)
+#define _ElfW(e,w,t) _ElfW_1 (e, w, _##t)
+#define _ElfW_1(e,w,t) e##w##t
+
+#include <bits/elfclass.h> /* Defines __ELF_NATIVE_CLASS. */
+
+/* Rendezvous structure used by the run-time dynamic linker to communicate
+ details of shared object loading to the debugger. If the executable's
+ dynamic section has a DT_DEBUG element, the run-time linker sets that
+ element's value to the address where this structure can be found. */
+
+struct r_debug
+ {
+ int r_version; /* Version number for this protocol. */
+
+ struct link_map *r_map; /* Head of the chain of loaded objects. */
+
+ /* This is the address of a function internal to the run-time linker,
+ that will always be called when the linker begins to map in a
+ library or unmap it, and again when the mapping change is complete.
+ The debugger can set a breakpoint at this address if it wants to
+ notice shared object mapping changes. */
+ ElfW(Addr) r_brk;
+ enum
+ {
+ /* This state value describes the mapping change taking place when
+ the `r_brk' address is called. */
+ RT_CONSISTENT, /* Mapping change is complete. */
+ RT_ADD, /* Beginning to add a new object. */
+ RT_DELETE /* Beginning to remove an object mapping. */
+ } r_state;
+
+ ElfW(Addr) r_ldbase; /* Base address the linker is loaded at. */
+ };
+
+/* This is the instance of that structure used by the dynamic linker. */
+extern struct r_debug _r_debug;
+
+/* This symbol refers to the "dynamic structure" in the `.dynamic' section
+ of whatever module refers to `_DYNAMIC'. So, to find its own
+ `struct r_debug', a program could do:
+ for (dyn = _DYNAMIC; dyn->d_tag != DT_NULL; ++dyn)
+ if (dyn->d_tag == DT_DEBUG)
+ r_debug = (struct r_debug *) dyn->d_un.d_ptr;
+ */
+extern ElfW(Dyn) _DYNAMIC[];
+
+#if defined __BFIN_FDPIC__
+# include <bits/elf-fdpic.h>
+#endif
+
+/* Structure describing a loaded shared object. The `l_next' and `l_prev'
+ members form a chain of all the shared objects loaded at startup.
+
+ These data structures exist in space used by the run-time dynamic linker;
+ modifying them may have disastrous results. */
+
+struct link_map
+ {
+ /* These first few members are part of the protocol with the debugger.
+ This is the same format used in SVR4. */
+
+#ifdef __BFIN_FDPIC__
+ struct elf32_fdpic_loadaddr l_addr;
+#else
+ ElfW(Addr) l_addr; /* Base address shared object is loaded at. */
+#endif
+ char *l_name; /* Absolute file name object was found in. */
+ ElfW(Dyn) *l_ld; /* Dynamic section of the shared object. */
+ struct link_map *l_next, *l_prev; /* Chain of loaded objects. */
+ };
+
+#ifdef __USE_GNU
+
+struct dl_phdr_info
+ {
+#ifdef __BFIN_FDPIC__
+ struct elf32_fdpic_loadaddr dlpi_addr;
+#else
+ ElfW(Addr) dlpi_addr;
+#endif
+ const char *dlpi_name;
+ const ElfW(Phdr) *dlpi_phdr;
+ ElfW(Half) dlpi_phnum;
+ };
+
+__BEGIN_DECLS
+
+extern int dl_iterate_phdr (int (*callback) (struct dl_phdr_info *info,
+ size_t size, void *data),
+ void *data) __THROW;
+
+__END_DECLS
+
+#endif
+
+#endif /* link.h */
diff --git a/libc/sysdeps/linux/bfin/setjmp.S b/libc/sysdeps/linux/bfin/setjmp.S
index 7194a1508..7ca92106f 100644
--- a/libc/sysdeps/linux/bfin/setjmp.S
+++ b/libc/sysdeps/linux/bfin/setjmp.S
@@ -98,10 +98,5 @@ ___sigsetjmp:
[P0 + 0x9C] = R0;
R0 = [P0 + 0x20];
- CC = R1 == 1;
- IF CC JUMP finished;
- CALL ___sigjmp_save;
-finished:
- R0 = 0;
- RTS;
-.size ___sigsetjmp,.-___sigsetjmp
+ JUMP.L ___sigjmp_save;
+.size ___sigsetjmp, .-___sigsetjmp