From ee92c0fe5c1b9d59508273916e2c9a75b68dbc13 Mon Sep 17 00:00:00 2001 From: Waldemar Brodkorb Date: Thu, 21 Apr 2016 01:25:29 +0200 Subject: nds32: add support for new architecture Add support for Andes Technology NDS32 architecture. See here http://www.andestech.com/en/index/index.htm for more informaton. Verification of the port from an older uClibc port was done on a sponsored AG101p board. The testsuite only has 5 errors, three are related to an existing bug in dlclose() with LT.old, also happening on cris32 and m68k. Failures to fallocate/posix_fallocate are unresolved. Thanks to Andes Technology sponsoring the hardware and being very helpful while doing the uClibc-ng porting. Signed-off-by: Waldemar Brodkorb --- README | 8 +- Rules.mak | 9 + extra/Configs/Config.in | 12 +- extra/Configs/Config.nds32 | 31 ++ include/elf.h | 173 ++++++++++- ldso/ldso/nds32/dl-debug.h | 25 ++ ldso/ldso/nds32/dl-startup.h | 175 ++++++++++++ ldso/ldso/nds32/dl-syscalls.h | 11 + ldso/ldso/nds32/dl-sysdep.h | 99 +++++++ ldso/ldso/nds32/elfinterp.c | 315 +++++++++++++++++++++ ldso/ldso/nds32/resolve.S | 76 +++++ libc/string/nds32/Makefile | 13 + libc/string/nds32/memcpy.S | 88 ++++++ libc/string/nds32/memset.S | 66 +++++ libc/sysdeps/linux/nds32/Makefile | 13 + libc/sysdeps/linux/nds32/Makefile.arch | 5 + libc/sysdeps/linux/nds32/__longjmp.S | 90 ++++++ libc/sysdeps/linux/nds32/__syscall_error.c | 16 ++ libc/sysdeps/linux/nds32/bits/byteswap.h | 121 ++++++++ libc/sysdeps/linux/nds32/bits/endian.h | 16 ++ libc/sysdeps/linux/nds32/bits/fcntl.h | 241 ++++++++++++++++ libc/sysdeps/linux/nds32/bits/kernel_stat.h | 57 ++++ libc/sysdeps/linux/nds32/bits/kernel_types.h | 52 ++++ libc/sysdeps/linux/nds32/bits/mathdef.h | 40 +++ libc/sysdeps/linux/nds32/bits/mman.h | 106 +++++++ libc/sysdeps/linux/nds32/bits/setjmp.h | 42 +++ libc/sysdeps/linux/nds32/bits/shm.h | 106 +++++++ libc/sysdeps/linux/nds32/bits/sigcontext.h | 59 ++++ libc/sysdeps/linux/nds32/bits/stackinfo.h | 31 ++ libc/sysdeps/linux/nds32/bits/stat.h | 172 +++++++++++ libc/sysdeps/linux/nds32/bits/syscalls.h | 103 +++++++ .../linux/nds32/bits/uClibc_arch_features.h | 37 +++ libc/sysdeps/linux/nds32/bits/uClibc_page.h | 31 ++ libc/sysdeps/linux/nds32/bits/wordsize.h | 23 ++ libc/sysdeps/linux/nds32/brk.c | 67 +++++ libc/sysdeps/linux/nds32/bsd-_setjmp.S | 35 +++ libc/sysdeps/linux/nds32/bsd-setjmp.S | 34 +++ libc/sysdeps/linux/nds32/clone.S | 93 ++++++ libc/sysdeps/linux/nds32/crt1.S | 96 +++++++ libc/sysdeps/linux/nds32/crti.S | 81 ++++++ libc/sysdeps/linux/nds32/crtn.S | 24 ++ libc/sysdeps/linux/nds32/jmpbuf-offsets.h | 28 ++ libc/sysdeps/linux/nds32/jmpbuf-unwind.h | 12 + libc/sysdeps/linux/nds32/mmap.S | 101 +++++++ libc/sysdeps/linux/nds32/setjmp.S | 109 +++++++ libc/sysdeps/linux/nds32/sigaction.c | 40 +++ libc/sysdeps/linux/nds32/sigrestorer.S | 42 +++ libc/sysdeps/linux/nds32/sys/elf.h | 13 + libc/sysdeps/linux/nds32/sys/io.h | 48 ++++ libc/sysdeps/linux/nds32/sys/procfs.h | 127 +++++++++ libc/sysdeps/linux/nds32/sys/ptrace.h | 133 +++++++++ libc/sysdeps/linux/nds32/sys/regdef.h | 90 ++++++ libc/sysdeps/linux/nds32/sys/ucontext.h | 112 ++++++++ libc/sysdeps/linux/nds32/sys/user.h | 83 ++++++ libc/sysdeps/linux/nds32/syscall.S | 60 ++++ libc/sysdeps/linux/nds32/sysdep.S | 125 ++++++++ libc/sysdeps/linux/nds32/sysdep.h | 271 ++++++++++++++++++ libc/sysdeps/linux/nds32/vfork.S | 87 ++++++ libpthread/linuxthreads/sysdeps/nds32/pspinlock.c | 102 +++++++ libpthread/linuxthreads/sysdeps/nds32/pt-machine.h | 66 +++++ librt/spawn.c | 1 + test/math/libm-test-ulps-nds32 | 145 ++++++++++ 62 files changed, 4679 insertions(+), 8 deletions(-) create mode 100644 extra/Configs/Config.nds32 create mode 100644 ldso/ldso/nds32/dl-debug.h create mode 100644 ldso/ldso/nds32/dl-startup.h create mode 100644 ldso/ldso/nds32/dl-syscalls.h create mode 100644 ldso/ldso/nds32/dl-sysdep.h create mode 100644 ldso/ldso/nds32/elfinterp.c create mode 100644 ldso/ldso/nds32/resolve.S create mode 100644 libc/string/nds32/Makefile create mode 100644 libc/string/nds32/memcpy.S create mode 100644 libc/string/nds32/memset.S create mode 100644 libc/sysdeps/linux/nds32/Makefile create mode 100644 libc/sysdeps/linux/nds32/Makefile.arch create mode 100644 libc/sysdeps/linux/nds32/__longjmp.S create mode 100644 libc/sysdeps/linux/nds32/__syscall_error.c create mode 100644 libc/sysdeps/linux/nds32/bits/byteswap.h create mode 100644 libc/sysdeps/linux/nds32/bits/endian.h create mode 100644 libc/sysdeps/linux/nds32/bits/fcntl.h create mode 100644 libc/sysdeps/linux/nds32/bits/kernel_stat.h create mode 100644 libc/sysdeps/linux/nds32/bits/kernel_types.h create mode 100644 libc/sysdeps/linux/nds32/bits/mathdef.h create mode 100644 libc/sysdeps/linux/nds32/bits/mman.h create mode 100644 libc/sysdeps/linux/nds32/bits/setjmp.h create mode 100644 libc/sysdeps/linux/nds32/bits/shm.h create mode 100644 libc/sysdeps/linux/nds32/bits/sigcontext.h create mode 100644 libc/sysdeps/linux/nds32/bits/stackinfo.h create mode 100644 libc/sysdeps/linux/nds32/bits/stat.h create mode 100644 libc/sysdeps/linux/nds32/bits/syscalls.h create mode 100644 libc/sysdeps/linux/nds32/bits/uClibc_arch_features.h create mode 100644 libc/sysdeps/linux/nds32/bits/uClibc_page.h create mode 100644 libc/sysdeps/linux/nds32/bits/wordsize.h create mode 100644 libc/sysdeps/linux/nds32/brk.c create mode 100644 libc/sysdeps/linux/nds32/bsd-_setjmp.S create mode 100644 libc/sysdeps/linux/nds32/bsd-setjmp.S create mode 100644 libc/sysdeps/linux/nds32/clone.S create mode 100644 libc/sysdeps/linux/nds32/crt1.S create mode 100644 libc/sysdeps/linux/nds32/crti.S create mode 100644 libc/sysdeps/linux/nds32/crtn.S create mode 100644 libc/sysdeps/linux/nds32/jmpbuf-offsets.h create mode 100644 libc/sysdeps/linux/nds32/jmpbuf-unwind.h create mode 100644 libc/sysdeps/linux/nds32/mmap.S create mode 100644 libc/sysdeps/linux/nds32/setjmp.S create mode 100644 libc/sysdeps/linux/nds32/sigaction.c create mode 100644 libc/sysdeps/linux/nds32/sigrestorer.S create mode 100644 libc/sysdeps/linux/nds32/sys/elf.h create mode 100644 libc/sysdeps/linux/nds32/sys/io.h create mode 100644 libc/sysdeps/linux/nds32/sys/procfs.h create mode 100644 libc/sysdeps/linux/nds32/sys/ptrace.h create mode 100644 libc/sysdeps/linux/nds32/sys/regdef.h create mode 100644 libc/sysdeps/linux/nds32/sys/ucontext.h create mode 100644 libc/sysdeps/linux/nds32/sys/user.h create mode 100644 libc/sysdeps/linux/nds32/syscall.S create mode 100644 libc/sysdeps/linux/nds32/sysdep.S create mode 100644 libc/sysdeps/linux/nds32/sysdep.h create mode 100644 libc/sysdeps/linux/nds32/vfork.S create mode 100644 libpthread/linuxthreads/sysdeps/nds32/pspinlock.c create mode 100644 libpthread/linuxthreads/sysdeps/nds32/pt-machine.h create mode 100644 test/math/libm-test-ulps-nds32 diff --git a/README b/README index 002b6f9e8..9395b65cf 100644 --- a/README +++ b/README @@ -12,7 +12,7 @@ Porting applications from glibc to uClibc-ng typically involves just recompiling the source code. uClibc-ng even supports shared libraries and threading. It currently runs on standard Linux and MMU-less (also known as µClinux) systems with support for ARC, ARM, Blackfin, i386, M68K/Coldfire -MIPS, MIPS64, PowerPC, SH, Sparc, X86_64 and XTENSA processors. +MIPS, MIPS64, NDS32, PowerPC, SH, Sparc, X86_64 and XTENSA processors. If you are building an embedded Linux system and you find that glibc is eating up too much space, you should consider using @@ -22,10 +22,10 @@ example, that 12 Terabytes will be Network Attached Storage and you plan to burn Linux into the system's firmware... uClibc-ng is maintained by Waldemar Brodkorb and is licensed under the -GNU LESSER GENERAL PUBLIC LICENSE. This license allows you to +GNU LESSER GENERAL PUBLIC LICENSE. This license allows you to make closed source commercial applications using an unmodified version of uClibc-ng. You do not need to give away all your source code just -because you use uClibc-ng and/or run on Linux. You should, however, +because you use uClibc-ng and/or run on Linux. You should, however, carefuly review the license and make certain you understand and abide by it strictly. @@ -42,7 +42,7 @@ Additional information can be found at http://www.uclibc-ng.org/. uClibc-ng may be freely modified and distributed under the terms of the GNU Lesser General Public License, which can be found in the -file COPYING. +file COPYING.LIB. And most of all, be sure to have some fun! :-) -Waldemar diff --git a/Rules.mak b/Rules.mak index 3e4e6c03c..894d4dc28 100644 --- a/Rules.mak +++ b/Rules.mak @@ -104,6 +104,7 @@ ifeq ($(TARGET_ARCH),) ARCH ?= $(shell uname -m | $(SED) -e s/i.86/i386/ \ -e s/sun.*/sparc/ -e s/sparc.*/sparc/ \ -e s/arm.*/arm/ -e s/sa110/arm/ \ + -e s/nds32.*/nds32/ \ -e s/sh.*/sh/ \ -e s/s390x/s390/ -e s/parisc.*/hppa/ \ -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \ @@ -300,6 +301,7 @@ ifeq ($(UCLIBC_HAS_SOFT_FLOAT),y) ifneq ($(TARGET_ARCH),bfin) ifneq ($(TARGET_ARCH),lm32) ifneq ($(TARGET_ARCH),nios2) +ifneq ($(TARGET_ARCH),nds32) ifneq ($(TARGET_ARCH),sh) ifneq ($(TARGET_ARCH),c6x) ifneq ($(TARGET_ARCH),h8300) @@ -313,6 +315,7 @@ endif endif endif endif +endif $(eval $(call check-gcc-var,-std=gnu99)) CPU_CFLAGS-y += $(CFLAG_-std=gnu99) @@ -410,6 +413,12 @@ ifeq ($(TARGET_ARCH),mips) CPU_LDFLAGS-y += $(CPU_CFLAGS) endif +ifeq ($(TARGET_ARCH),nds32) + CPU_CFLAGS-$(CONFIG_NDS32_ISA)+=-march=nds32 + CFLAGS-.os+= -DPIC + CFLAGS-.oS+= -DPIC +endif + ifeq ($(TARGET_ARCH),sh) $(eval $(call check-gcc-var,-mprefergot)) OPTIMIZATION += $(CFLAG_-mprefergot) diff --git a/extra/Configs/Config.in b/extra/Configs/Config.in index 4a1509d88..1d97e784e 100644 --- a/extra/Configs/Config.in +++ b/extra/Configs/Config.in @@ -31,6 +31,7 @@ choice default TARGET_metag if DESIRED_TARGET_ARCH = "metag" default TARGET_microblaze if DESIRED_TARGET_ARCH = "microblaze" default TARGET_mips if DESIRED_TARGET_ARCH = "mips" + default TARGET_nds32 if DESIRED_TARGET_ARCH = "nds32" default TARGET_nios2 if DESIRED_TARGET_ARCH = "nios2" default TARGET_or1k if DESIRED_TARGET_ARCH = "or1k" default TARGET_powerpc if DESIRED_TARGET_ARCH = "powerpc" @@ -94,6 +95,9 @@ config TARGET_microblaze config TARGET_mips bool "mips" +config TARGET_nds32 + bool "nds32" + config TARGET_nios2 bool "nios2" @@ -172,6 +176,10 @@ if TARGET_metag source "extra/Configs/Config.metag" endif +if TARGET_nds32 +source "extra/Configs/Config.nds32" +endif + if TARGET_nios2 source "extra/Configs/Config.nios2" endif @@ -476,7 +484,6 @@ config LDSO_GNU_HASH_SUPPORT choice prompt "Thread support" - #default UCLIBC_HAS_THREADS_NATIVE if (TARGET_alpha || TARGET_arm || TARGET_i386 || TARGET_mips || TARGET_powerpc || TARGET_sh || TARGET_sh64) default HAS_NO_THREADS help If you want to compile uClibc with pthread support, then answer Y. @@ -524,6 +531,7 @@ config UCLIBC_HAS_THREADS_NATIVE !TARGET_ia64 && \ !TARGET_m68k && \ !TARGET_microblaze && \ + !TARGET_nds32 && \ !TARGET_nios2 && \ !TARGET_or1k && \ ARCH_USE_MMU @@ -2094,7 +2102,7 @@ menu "Security options" config UCLIBC_BUILD_PIE bool "Build utilities as ET_DYN/PIE executables" depends on HAVE_SHARED - depends on TARGET_arm || TARGET_frv || TARGET_i386 || TARGET_mips || TARGET_powerpc + depends on TARGET_arm || TARGET_frv || TARGET_i386 || TARGET_mips || TARGET_powerpc || TARGET_nds32 select FORCE_SHAREABLE_TEXT_SEGMENTS help If you answer Y here, ldd and iconv are built as ET_DYN/PIE diff --git a/extra/Configs/Config.nds32 b/extra/Configs/Config.nds32 new file mode 100644 index 000000000..a74249947 --- /dev/null +++ b/extra/Configs/Config.nds32 @@ -0,0 +1,31 @@ +# +# For a description of the syntax of this configuration file, +# see extra/config/Kconfig-language.txt +# + +config TARGET_ARCH + string + default "nds32" + +config FORCE_OPTIONS_FOR_ARCH + bool + default y + select ARCH_ANY_ENDIAN + select ARCH_HAS_DEPRECATED_SYSCALLS + select ARCH_HAS_MMU + +choice + prompt "MMU Page Size" + default CONFIG_NDS32_PAGE_SIZE_4K + +config CONFIG_NDS32_PAGE_SIZE_4K + bool "4KB" + help + Use 4k pagesize. + +config CONFIG_NDS32_PAGE_SIZE_8K + bool "8KB" + help + Use 8k pagesize. + +endchoice diff --git a/include/elf.h b/include/elf.h index 4a0280b80..17a6143b5 100644 --- a/include/elf.h +++ b/include/elf.h @@ -264,11 +264,12 @@ typedef struct #define EM_CR 103 /* National Semiconductor CompactRISC */ #define EM_MSP430 105 /* TI msp430 micro controller */ #define EM_BLACKFIN 106 /* Analog Devices Blackfin */ -#define EM_ALTERA_NIOS2 113 /* Altera Nios II soft-core processor */ +#define EM_ALTERA_NIOS2 113 /* Altera Nios II soft-core processor */ #define EM_CRX 114 /* National Semiconductor CRX */ #define EM_TI_C6000 140 +#define EM_NDS32 167 /* Andes Tech NDS32 */ #define EM_METAG 174 /* Imagination Technologies Meta */ -#define EM_MICROBLAZE 189 /* Xilinx Microblaze */ +#define EM_MICROBLAZE 189 /* Xilinx Microblaze */ #define EM_ARCV2 195 /* ARCv2 Cores */ /* NEXT FREE NUMBER: Increment this after adding your official arch number */ @@ -2912,6 +2913,174 @@ typedef Elf32_Addr Elf32_Conflict; #define R_H8_ABS32A16 127 #define R_H8_NUM 128 +/* NDS32 relocs. */ +#define R_NDS32_NONE 0 +/* REL relocations */ +#define R_NDS32_16 1 +#define R_NDS32_32 2 +#define R_NDS32_20 3 +#define R_NDS32_9_PCREL 4 +#define R_NDS32_15_PCREL 5 +#define R_NDS32_17_PCREL 6 +#define R_NDS32_25_PCREL 7 +#define R_NDS32_HI20 8 +#define R_NDS32_LO12S3 9 +#define R_NDS32_LO12S2 10 +#define R_NDS32_LO12S1 11 +#define R_NDS32_LO12S0 12 +#define R_NDS32_SDA15S3 13 +#define R_NDS32_SDA15S2 14 +#define R_NDS32_SDA15S1 15 +#define R_NDS32_SDA15S0 16 +#define R_NDS32_GNU_VTINHERIT 17 +#define R_NDS32_GNU_VTENTRY 18 + +/* RELA relocations */ +#define R_NDS32_16_RELA 19 +#define R_NDS32_32_RELA 20 +#define R_NDS32_20_RELA 21 +#define R_NDS32_9_PCREL_RELA 22 +#define R_NDS32_15_PCREL_RELA 23 +#define R_NDS32_17_PCREL_RELA 24 +#define R_NDS32_25_PCREL_RELA 25 +#define R_NDS32_HI20_RELA 26 +#define R_NDS32_LO12S3_RELA 27 +#define R_NDS32_LO12S2_RELA 28 +#define R_NDS32_LO12S1_RELA 29 +#define R_NDS32_LO12S0_RELA 30 +#define R_NDS32_SDA15S3_RELA 31 +#define R_NDS32_SDA15S2_RELA 32 +#define R_NDS32_SDA15S1_RELA 33 +#define R_NDS32_SDA15S0_RELA 34 +#define R_NDS32_RELA_GNU_VTINHERIT 35 +#define R_NDS32_RELA_GNU_VTENTRY 36 +#define R_NDS32_GOT20 37 +#define R_NDS32_25_PLTREL 38 +#define R_NDS32_COPY 39 +#define R_NDS32_GLOB_DAT 40 +#define R_NDS32_JMP_SLOT 41 +#define R_NDS32_RELATIVE 42 +#define R_NDS32_GOTOFF 43 +#define R_NDS32_GOTPC20 44 +#define R_NDS32_GOT_HI20 45 +#define R_NDS32_GOT_LO12 46 +#define R_NDS32_GOTPC_HI20 47 +#define R_NDS32_GOTPC_LO12 48 +#define R_NDS32_GOTOFF_HI20 49 +#define R_NDS32_GOTOFF_LO12 50 +#define R_NDS32_INSN16 51 +#define R_NDS32_LABEL 52 +#define R_NDS32_LONGCALL1 53 +#define R_NDS32_LONGCALL2 54 +#define R_NDS32_LONGCALL3 55 +#define R_NDS32_LONGJUMP1 56 +#define R_NDS32_LONGJUMP2 57 +#define R_NDS32_LONGJUMP3 58 +#define R_NDS32_LOADSTORE 59 +#define R_NDS32_9_FIXED_RELA 60 +#define R_NDS32_15_FIXED_RELA 61 +#define R_NDS32_17_FIXED_RELA 62 +#define R_NDS32_25_FIXED_RELA 63 +#define R_NDS32_PLTREL_HI20 64 +#define R_NDS32_PLTREL_LO12 65 +#define R_NDS32_PLT_GOTREL_HI20 66 +#define R_NDS32_PLT_GOTREL_LO12 67 + +/* Processor specific section indices. These sections do not actually + exist. Symbols with a st_shndx field corresponding to one of these + values have a special meaning. */ + +/* Small common symbol. */ +#define SHN_NDS32_SCOMMON 0xff00 + +/* Processor specific section flags. */ + +/* This section contains sufficient relocs to be relaxed. + When relaxing, even relocs of branch instructions the assembler could + complete must be present because relaxing may cause the branch target to + move. */ +#define SHF_NDS32_CAN_RELAX 0x10000000 + +/* ----------------------------------------------------------- */ +/* Processor specific flags for the ELF header e_flags field. */ +/* ----------------------------------------------------------- */ +/* 31 28 27 8 7 4 3 0 */ +/* ---------------------------------------------- */ +/* | ARCH | CONFUGURAION FIELD | ABI | VERSION | */ +/* ---------------------------------------------- */ + +/* ----------------------------------------------------------- */ +/* ARCHITECHURE DEFINITION */ +/* ----------------------------------------------------------- */ +/* 4-bit (b31-b28) nds32 architecture field. */ +/* we can have up to 15 architectures; 0000 is for unknown */ +#define EF_NDS_ARCH 0xF0000000 +/* 0x80000000 is for no 16-bit */ +/* there could be more architectures. but for now, only n1 and n1h */ +#define E_NDS_ARCH_STAR_RESERVED 0x00000000 /* for future extension */ +#define E_NDS_ARCH_STAR_V1_0 0x10000000 +#define E_NDS_ARCH_STAR_V0_9 0x90000000 /* old arch */ + +/* n1 code. */ +#define E_N1_ARCH E_NDS_ARCH_STAR_V0_9 +/* n1h code. */ +#define E_N1H_ARCH E_NDS_ARCH_STAR_V1_0 + +/* ----------------------------------------------------------- */ +/* CONFIGURATION FIELD DEFINITION FOR EACH ARCHITECTURE */ +/* ----------------------------------------------------------- */ +#define EF_NDS_INST 0x0FFFFF00 + +/* E_NDS_ARCH_STAR_V1_0 configuration fields */ + +/* MFUSR rt, PC and correct ISYNC, MSYNC instructions. */ +/* old N1213HC has no such instructions */ +#define E_NDS32_HAS_MFUSR_PC_INST 0x00000100 +/* C/C++ performance extension instructions. */ +#define E_NDS32_HAS_EXT_INST 0x00000200 +/* performance extension set II instructions. */ +#define E_NDS32_HAS_EXT2_INST 0x00000400 +/* Floating point processor instructions. */ +#define E_NDS32_HAS_FPU_INST 0x00000800 +/* audio instructions. */ +#define E_NDS32_HAS_AUDIO_INST 0x00001000 +/* DIV instructions. */ +#define E_NDS32_HAS_DIV_INST 0x00002000 +/* 16-bit instructions. */ +#define E_NDS32_HAS_16BIT_INST 0x00004000 +/* string operation instructions. */ +#define E_NDS32_HAS_STRING_INST 0x00008000 +/* reduced register file */ +#define E_NDS32_HAS_REDUCED_REGS 0x00010000 +/* video instructions */ +#define E_NDS32_HAS_VIDEO_INST 0x00020000 +/* encription instructions */ +#define E_NDS32_HAS_ENCRIPT_INST 0x00040000 +/* Single/Doulbe Precision Floating point processor instructions. */ +#define E_NDS32_HAS_FPU_DP_INST 0x00080000 +/* no MAC instruction used */ +#define E_NDS32_HAS_NO_MAC_INST 0x00100000 +/* L2 cache instruction */ +#define E_NDS32_HAS_L2C_INST 0x00200000 + + +/* 4-bit for ABI signature, allow up to 16 ABIs */ +/* 0 is for OLD ABI V0, 1 is for V1, the rest is reserved */ +/* only old N1213HC use V0 */ +/* New ABI is used due to return register is changed to r0 from r5 */ +#define EF_NDS_ABI 0x000000F0 +#define E_NDS_ABI_V0 0x00000000 +#define E_NDS_ABI_V1 0x00000010 + +/* this flag signifies the version of Andes ELF */ +/* some more information may exist somewhere which is TBD */ +#define EF_NDS32_ELF_VERSION 0x0000000F + +/* Andes ELF Version 1.2 and before */ +#define E_NDS32_ELF_VER_1_2 0x0 +/* Andes ELF Version 1.3 and after */ +#define E_NDS32_ELF_VER_1_3 0x1 + /* NIOS relocations. */ #define R_NIOS_NONE 0 #define R_NIOS_32 1 /* A 32 bit absolute relocation.*/ diff --git a/ldso/ldso/nds32/dl-debug.h b/ldso/ldso/nds32/dl-debug.h new file mode 100644 index 000000000..ef4c57d91 --- /dev/null +++ b/ldso/ldso/nds32/dl-debug.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2016 Andes Technology, Inc. + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +static const char *_dl_reltypes_tab[] = +{ + [0] "R_NDS32_NONE", "R_NDS32_16", "R_NDS32_32", "R_NDS32_20", + [4] "R_NDS32_9_PCREL", "R_NDS32_15_PCREL", "R_NDS32_17_PCREL", "R_NDS32_25_PCREL", + [8] "R_NDS32_HI20", "R_NDS32_LO12S3", "R_NDS32_LO12S2", "R_NDS32_LO12S1", + [12] "R_NDS32_LO12S0", "R_NDS32_SDA15S3", "R_NDS32_SDA15S2", "R_NDS32_SDA15S1", + [16] "R_NDS32_SDA15S0", "R_NDS32_GNU_VTINHERIT", "R_NDS32_GNU_VTENTRY", "R_NDS32_16_RELA", + [20] "R_NDS32_32_RELA" "R_NDS32_20_RELA", "R_NDS32_9_PCREL_RELA", "R_NDS32_15_PCREL_RELA", + [24] "R_NDS32_17_PCREL_RELA", "R_NDS32_25_PCREL_RELA", "R_NDS32_HI20_RELA", "R_NDS32_LO12S3_RELA", + [28] "R_NDS32_LO12S2_RELA", "R_NDS32_LO12S1_RELA", "R_NDS32_LO12S0_RELA", "R_NDS32_SDA15S3_RELA", + [32] "R_NDS32_SDA15S2_RELA", "R_NDS32_SDA15S1_RELA", "R_NDS32_SDA15S0_RELA", "R_NDS32_RELA_GNU_VTINHERIT", + [36] "R_NDS32_RELA_GNU_VTENTRY", "R_NDS32_GOT20", "R_NDS32_25_PLTREL", "R_NDS32_COPY", + [40] "R_NDS32_GLOB_DAT", "R_NDS32_JMP_SLOT", "R_NDS32_RELATIVE", "R_NDS32_GOTOFF", + [44] "R_NDS32_GOTPC20", "R_NDS32_GOT_HI20", "R_NDS32_GOT_LO12", "R_NDS32_GOTPC_HI20", + [48] "R_NDS32_GOTPC_LO12", "R_NDS32_GOTOFF_HI20", "R_NDS32_GOTOFF_LO12", "R_NDS32_INSN16", + [52] "R_NDS32_LABEL", "R_NDS32_LONGCALL1", "R_NDS32_LONGCALL2", "R_NDS32_LONGCALL3", + [56] "R_NDS32_LONGJUMP1", "R_NDS32_LONGJUMP2", "R_NDS32_LONGJUMP3", "R_NDS32_LOADSTORE", + [60] "R_NDS32_9_FIXED_RELA", "R_NDS32_15_FIXED_RELA", "R_NDS32_17_FIXED_RELA", "R_NDS32_25_FIXED_RELA", + [64] "R_NDS32_PLTREL_HI20", "R_NDS32_PLTREL_LO12", "R_NDS32_PLT_GOTREL_HI20", "R_NDS32_PLT_GOTREL_LO12", +}; diff --git a/ldso/ldso/nds32/dl-startup.h b/ldso/ldso/nds32/dl-startup.h new file mode 100644 index 000000000..f700531ca --- /dev/null +++ b/ldso/ldso/nds32/dl-startup.h @@ -0,0 +1,175 @@ +/* + * Copyright (C) 2016 Andes Technology, Inc. + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* Need bootstrap relocations */ +#define ARCH_NEEDS_BOOTSTRAP_RELOCS + +#if defined(NDS32_ABI_2) || defined(NDS32_ABI_2FP) +# define STACK_PUSH +# define STACK_POP +#else +# define STACK_PUSH "addi $sp, $sp, -24" +# define STACK_POP "addi $sp, $sp, 24" +#endif + + +#ifdef __NDS32_N1213_43U1H__ +__asm__("\ + .text\n\ + .globl _start\n\ + .globl _dl_start\n\ + .globl _dl_start_user\n\ + .type _start,#function\n\ + .type _dl_start,#function\n\ + .type _dl_start_user,#function\n\ + .align 4\n\ + .pic\n\ +1:\n\ + ret\n\ +_start:\n\ + ! we are PIC code, so get global offset table\n\ + jal 1b\n\ + sethi $gp, HI20(_GLOBAL_OFFSET_TABLE_)\n\ + ori $gp, $gp, LO12(_GLOBAL_OFFSET_TABLE_+4)\n\ + add $gp, $lp, $gp\n\ +\n\ + ! at start time, all the args are on the stack\n\ + addi $r0, $sp, 0\n\ + ! adjust stack\n\ + !addi $sp, $sp, -24\n\ + "STACK_PUSH"\n\ + bal _dl_start@PLT\n\ + ! save user entry point in r6\n\ + addi $r6, $r0, 0\n\ + ! adjust sp and reload registers\n\ + !addi $sp, $sp, 24\n\ + "STACK_POP"\n\ +\n\ +_dl_start_user:\n\ +\n\ + ! See if we were run as a command with the executable file\n\ + ! name as an extra leading argument.\n\ + ! skip these arguments\n\ + l.w $r2, _dl_skip_args@GOTOFF ! args to skip\n\ + lwi $r0, [$sp+0] ! original argc\n\ + slli $r1, $r2, 2 ! offset for new sp\n\ + add $sp, $sp, $r1 ! adjust sp to skip args\n\ + sub $r0, $r0, $r2 ! set new argc\n\ + swi $r0, [$sp+0] ! save new argc\n\ +\n\ + ! load address of _dl_fini finalizer function\n\ + la $r5, _dl_fini@GOTOFF\n\ + ! jump to the user_s entry point\n\ + addi $r15, $r6, 0\n\ + jr $r15\n\ + .size _dl_start_user, . - _dl_start_user\n\ + .previous\n\ +"); +#else +__asm__("\ + .text\n\ + .globl _start\n\ + .globl _dl_start\n\ + .globl _dl_start_user\n\ + .type _start,#function\n\ + .type _dl_start,#function\n\ + .type _dl_start_user,#function\n\ + .align 4\n\ + .pic\n\ +_start:\n\ + ! we are PIC code, so get global offset table\n\ + mfusr $r15, $PC \n\ + sethi $gp, HI20(_GLOBAL_OFFSET_TABLE_ + 4)\n\ + ori $gp, $gp, LO12(_GLOBAL_OFFSET_TABLE_ + 8)\n\ + add $gp, $r15, $gp\n\ +\n\ + ! at start time, all the args are on the stack\n\ + addi $r0, $sp, 0\n\ + ! adjust stack\n\ + !addi $sp, $sp, -24\n\ + "STACK_PUSH"\n\ + bal _dl_start@PLT\n\ + ! save user entry point in r6\n\ + addi $r6, $r0, 0\n\ + ! adjust sp and reload registers\n\ + !addi $sp, $sp, 24\n\ + "STACK_POP"\n\ +\n\ +_dl_start_user:\n\ + ! See if we were run as a command with the executable file\n\ + ! name as an extra leading argument.\n\ + ! skip these arguments\n\ + l.w $r2, _dl_skip_args@GOTOFF ! args to skip\n\ + lwi $r0, [$sp+0] ! original argc\n\ + slli $r1, $r2, 2 ! offset for new sp\n\ + add $sp, $sp, $r1 ! adjust sp to skip args\n\ + sub $r0, $r0, $r2 ! set new argc\n\ + swi $r0, [$sp+0] ! save new argc\n\ +\n\ + ! load address of _dl_fini finalizer function\n\ + la $r5, _dl_fini@GOTOFF\n\ + ! jump to the user_s entry point\n\ + jr $r6\n\ + .size _dl_start_user, . - _dl_start_user\n\ + .previous\n\ +"); +#endif + +#define COPY_UNALIGNED_WORD(swp, twp, align) \ + { \ + void *__s = (swp), *__t = (twp); \ + unsigned char *__s1 = __s, *__t1 = __t; \ + unsigned short *__s2 = __s, *__t2 = __t; \ + unsigned long *__s4 = __s, *__t4 = __t; \ + switch ((align)) \ + { \ + case 0: \ + *__t4 = *__s4; \ + break; \ + case 2: \ + *__t2++ = *__s2++; \ + *__t2 = *__s2; \ + break; \ + default: \ + *__t1++ = *__s1++; \ + *__t1++ = *__s1++; \ + *__t1++ = *__s1++; \ + *__t1 = *__s1; \ + break; \ + } \ + } + +/* 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)+1) + +/* Handle relocation of the symbols in the dynamic loader. */ +static __always_inline +void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, unsigned long *reloc_addr, + unsigned long symbol_addr, unsigned long load_addr, Elf32_Sym *symtab) +{ + Elf32_Addr value; + switch (ELF32_R_TYPE(rpnt->r_info)) { + case R_NDS32_NONE: + break; + case R_NDS32_32: + case R_NDS32_GLOB_DAT: + case R_NDS32_JMP_SLOT: + *reloc_addr = symbol_addr + rpnt->r_addend; + break; + case R_NDS32_32_RELA: + value = symbol_addr + rpnt->r_addend; + COPY_UNALIGNED_WORD (&value, reloc_addr, (int) reloc_addr & 3); + break; +#undef COPY_UNALIGNED_WORD + case R_NDS32_RELATIVE: + *reloc_addr = load_addr + rpnt->r_addend; + break; + default: + SEND_STDERR("Unsupported relocation type\n"); + _dl_exit(1); + } +} diff --git a/ldso/ldso/nds32/dl-syscalls.h b/ldso/ldso/nds32/dl-syscalls.h new file mode 100644 index 000000000..54b8839d8 --- /dev/null +++ b/ldso/ldso/nds32/dl-syscalls.h @@ -0,0 +1,11 @@ +/* + * Copyright (C) 2016 Andes Technology, Inc. + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* We can't use the real errno in ldso, since it has not yet + * been dynamicly linked in yet. */ +#include "sys/syscall.h" +extern int _dl_errno; +#undef __set_errno +#define __set_errno(X) {(_dl_errno) = (X);} diff --git a/ldso/ldso/nds32/dl-sysdep.h b/ldso/ldso/nds32/dl-sysdep.h new file mode 100644 index 000000000..c4a32ca71 --- /dev/null +++ b/ldso/ldso/nds32/dl-sysdep.h @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2016 Andes Technology, Inc. + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* Define this if the system uses RELOCA. */ +#define ELF_USES_RELOCA +#include +/* Initialization sequence for the GOT. */ +#define INIT_GOT(GOT_BASE,MODULE) \ +{ \ + GOT_BASE[2] = (unsigned long) _dl_linux_resolve; \ + GOT_BASE[1] = (unsigned long) MODULE; \ +} + +static __inline__ unsigned long nds32_modulus(unsigned long m, unsigned long p) +{ + unsigned long i,t,inc; + i=p; t=0; + while (!(i&(1<<31))) { + i<<=1; + t++; + } + t--; + for (inc=t;inc>2;inc--) { + i=p<=i) { + m-=i; + i<<=1; + if (i&(1<<31)) + break; + if (i=p) { + m-=p; + } + return m; +} +#define do_rem(result, n, base) ((result) = nds32_modulus(n, base)) + +/* Here we define the magic numbers that this dynamic loader should accept */ +#define MAGIC1 EM_NDS32 +#undef MAGIC2 + +/* Used for error messages */ +#define ELF_TARGET "NDS32" + +struct elf_resolve; +unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry); + +/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so + PLT entries should not be allowed to define the value. + ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one + of the main executable's symbols, as for a COPY reloc. */ +#define elf_machine_type_class(type) \ + ((((type) == R_NDS32_JMP_SLOT) * ELF_RTYPE_CLASS_PLT) \ + | (((type) == R_NDS32_COPY) * ELF_RTYPE_CLASS_COPY)) + +/* Return the link-time address of _DYNAMIC. Conveniently, this is the + first element of the GOT. We used to use the PIC register to do this + without a constant pool reference, but GCC 4.2 will use a pseudo-register + for the PIC base, so it may not be in r10. */ +static __inline__ Elf32_Addr __attribute__ ((unused)) +elf_machine_dynamic (void) +{ + Elf32_Addr link_addr; + __asm__ ( "l.w %0, _GLOBAL_OFFSET_TABLE_@GOTOFF": "=r" (link_addr) ); + return link_addr; +} + +/* Return the run-time load address of the shared object. */ +static __inline__ Elf32_Addr __attribute__ ((unused)) +elf_machine_load_address (void) +{ + /* It doesn't matter what variable this is, the reference never makes + it to assembly. We need a dummy reference to some global variable + via the GOT to make sure the compiler initialized %ebx in time. */ + + Elf32_Addr addr; + __asm__ ("la %0, _dl_start@GOTOFF\n" : "=r" (addr) ); + return addr - elf_machine_dynamic(); +} + +static __inline__ void +elf_machine_relative (Elf32_Addr load_off, const Elf32_Addr rel_addr, + Elf32_Word relative_count) +{ + Elf32_Rela * rpnt = (void *) rel_addr; + --rpnt; + do { + Elf32_Addr *const reloc_addr = (void *) (load_off + (++rpnt)->r_offset); + + *reloc_addr = load_off + rpnt->r_addend; + } while (--relative_count); +} diff --git a/ldso/ldso/nds32/elfinterp.c b/ldso/ldso/nds32/elfinterp.c new file mode 100644 index 000000000..bf5c901d1 --- /dev/null +++ b/ldso/ldso/nds32/elfinterp.c @@ -0,0 +1,315 @@ +/* + * Copyright (C) 2016 Andes Technology, Inc. + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* NDS32 ELF shared library loader suppport + * + * Copyright (C) 2001-2004 Erik Andersen + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the above contributors may not be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* 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. */ + +#include "ldso.h" + +extern int _dl_linux_resolve(void); + +unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry) +{ + int reloc_type; + ELF_RELOC *this_reloc; + char *strtab; + char *symname; + Elf32_Sym *symtab; + ELF_RELOC *rel_addr; + int symtab_index; + char *new_addr; + char **got_addr; + unsigned long instr_addr; + + rel_addr = (ELF_RELOC *) tpnt->dynamic_info[DT_JMPREL]; + + this_reloc = rel_addr + reloc_entry/sizeof(ELF_RELOC); + reloc_type = ELF32_R_TYPE(this_reloc->r_info); + symtab_index = ELF32_R_SYM(this_reloc->r_info); + + symtab = (Elf32_Sym *) tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *) tpnt->dynamic_info[DT_STRTAB]; + symname = strtab + symtab[symtab_index].st_name; + + if (unlikely(reloc_type != R_NDS32_JMP_SLOT)) { + _dl_dprintf(2, "%s: Incorrect relocation type in jump relocations\n", + _dl_progname); + _dl_exit(1); + } + + /* Address of jump instruction to fix up */ + instr_addr = ((unsigned long) this_reloc->r_offset + + (unsigned long) tpnt->loadaddr); + got_addr = (char **) instr_addr; + + /* Get the address of the GOT entry */ + new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, tpnt, + ELF_RTYPE_CLASS_PLT, NULL); + if (unlikely(!new_addr)) { + _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", + _dl_progname, symname); + _dl_exit(1); + } +#if defined (__SUPPORT_LD_DEBUG__) + if ((unsigned long) got_addr < 0x40000000) + { + if (_dl_debug_bindings) + { + _dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname); + if (_dl_debug_detail) _dl_dprintf(_dl_debug_file, + "\tpatch %x ==> %x @ %x", *got_addr, new_addr, got_addr); + } + } + if (!_dl_debug_nofixups) { + *got_addr = new_addr; + } +#else + *got_addr = new_addr; +#endif + + return (unsigned long) new_addr; +} + +static int +_dl_parse(struct elf_resolve *tpnt, struct r_scope_elem *scope, + unsigned long rel_addr, unsigned long rel_size, + int (*reloc_fnc) (struct elf_resolve *tpnt, struct r_scope_elem *scope, + ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)) +{ + int symtab_index; + int i; + char *strtab; + int goof = 0; + ElfW(Sym) *symtab; + ELF_RELOC *rpnt; + + /* Now parse the relocation information */ + rpnt = (ELF_RELOC *) rel_addr; + rel_size = rel_size / sizeof(ELF_RELOC); + + symtab = (Elf32_Sym *) tpnt->dynamic_info[DT_SYMTAB]; + strtab = (char *) tpnt->dynamic_info[DT_STRTAB]; + + for (i = 0; i < rel_size; i++, rpnt++) { + int res; + + symtab_index = ELF32_R_SYM(rpnt->r_info); + + debug_sym(symtab,strtab,symtab_index); + debug_reloc(symtab,strtab,rpnt); + + 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 (unlikely(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); + } + if (unlikely(res >0)) + { + _dl_dprintf(2, "can't resolve symbol\n"); + goof += res; + } + } + return goof; +} + + +static int +_dl_do_reloc (struct elf_resolve *tpnt, struct r_scope_elem *scope, + ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab) +{ + int reloc_type; + int symtab_index; + char *symname = NULL; + unsigned long *reloc_addr; + unsigned long symbol_addr; + int goof = 0; + struct symbol_ref sym_ref; + + reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset); + reloc_type = ELF32_R_TYPE(rpnt->r_info); + symtab_index = ELF32_R_SYM(rpnt->r_info); + symbol_addr = 0; + sym_ref.sym = &symtab[symtab_index]; + sym_ref.tpnt = NULL; + + if (symtab_index) { + symname = strtab + symtab[symtab_index].st_name; + symbol_addr = (unsigned long)_dl_find_hash(symname, scope, tpnt, + elf_machine_type_class(reloc_type), &sym_ref); + + /* + * 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_WEAK) { + _dl_dprintf (2, "%s: can't resolve symbol '%s'\n", + _dl_progname, strtab + symtab[symtab_index].st_name); + _dl_exit (1); + } + } + +#define COPY_UNALIGNED_WORD(swp, twp, align) \ + { \ + void *__s = (swp), *__t = (twp); \ + unsigned char *__s1 = __s, *__t1 = __t; \ + unsigned short *__s2 = __s, *__t2 = __t; \ + unsigned long *__s4 = __s, *__t4 = __t; \ + switch ((align)) \ + { \ + case 0: \ + *__t4 = *__s4; \ + break; \ + case 2: \ + *__t2++ = *__s2++; \ + *__t2 = *__s2; \ + break; \ + default: \ + *__t1++ = *__s1++; \ + *__t1++ = *__s1++; \ + *__t1++ = *__s1++; \ + *__t1 = *__s1; \ + break; \ + } \ + } + +#if defined (__SUPPORT_LD_DEBUG__) + { + unsigned long old_val = *reloc_addr; +#endif + symbol_addr += rpnt->r_addend ; + switch (reloc_type) { + case R_NDS32_NONE: + break; + case R_NDS32_32: + case R_NDS32_GLOB_DAT: + case R_NDS32_JMP_SLOT: + *reloc_addr = symbol_addr; + break; + case R_NDS32_32_RELA: + COPY_UNALIGNED_WORD (&symbol_addr, reloc_addr,(int) reloc_addr & 3); + break; +#undef COPY_UNALIGNED_WORD + case R_NDS32_RELATIVE: + *reloc_addr = (unsigned long) tpnt->loadaddr + rpnt->r_addend; + break; + case R_NDS32_COPY: + _dl_memcpy((void *) reloc_addr, + (void *) symbol_addr, symtab[symtab_index].st_size); + 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, "\tpatch: %x ==> %x @ %x", old_val, *reloc_addr, reloc_addr); + } + +#endif + + return goof; +} + +static int +_dl_do_lazy_reloc (struct elf_resolve *tpnt, struct r_scope_elem *scope, + ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab) +{ + int reloc_type; + unsigned long *reloc_addr; + + reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset); + reloc_type = ELF32_R_TYPE(rpnt->r_info); + +#if defined (__SUPPORT_LD_DEBUG__) + { + unsigned long old_val = *reloc_addr; +#endif + switch (reloc_type) { + case R_NDS32_NONE: + break; + case R_NDS32_JMP_SLOT: + *reloc_addr += (unsigned long) tpnt->loadaddr; + 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, "\tpatch: %x ==> %x @ %x", old_val, *reloc_addr, reloc_addr); + } + +#endif + return 0; + +} + +void +_dl_parse_lazy_relocation_information(struct dyn_elf *rpnt, + unsigned long rel_addr, + unsigned long rel_size) +{ + _dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc); +} + +int +_dl_parse_relocation_information(struct dyn_elf *rpnt, + struct r_scope_elem *scope, + unsigned long rel_addr, + unsigned long rel_size) +{ + return _dl_parse(rpnt->dyn, scope, rel_addr, + rel_size, _dl_do_reloc); +} + diff --git a/ldso/ldso/nds32/resolve.S b/ldso/ldso/nds32/resolve.S new file mode 100644 index 000000000..8c53850d7 --- /dev/null +++ b/ldso/ldso/nds32/resolve.S @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2016 Andes Technology, Inc. + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#if defined(NDS32_ABI_2) || defined(NDS32_ABI_2FP) +# define STACK_PUSH +# define STACK_POP +#else +# define STACK_PUSH addi $sp, $sp, -24 +# define STACK_POP addi $sp, $sp, 24 +#endif + + .text + .align 4 ! 16 byte boundary + .globl _dl_linux_resolve + .type _dl_linux_resolve,#function + .pic + +_dl_linux_resolve: + ! we get called with + ! lp contains the return address from this call + ! r16 contains offset to target reloc entry + ! r17 contains GOT[1] (identity of taget lib) + ! ta is GOT[2] (starting address of this function) + + ! save arguments r0 - r5 and gp, lp + smw.adm $r0, [$sp], $r5, 6 + + ! init gp +#ifdef __NDS32_N1213_43U1H__ + sethi $gp, HI20(_GLOBAL_OFFSET_TABLE_+4) + ori $gp, $gp, LO12(_GLOBAL_OFFSET_TABLE_+8) + add $gp, $ta, $gp +#else + mfusr $ta, $PC + sethi $gp, HI20(_GLOBAL_OFFSET_TABLE_+4) + ori $gp, $gp, LO12(_GLOBAL_OFFSET_TABLE_+8) + add $gp, $ta, $gp +#endif + + ! #ifdef __NDS32_ABI_1__ + ! adjust stack + !addi $sp, $sp, -24 + STACK_PUSH + ! #endif + + ! set arguments + addi $r0, $r17, 0 + !addi $r1, $r16, 0 + slli $r1, $r16, 2 + slli $r16, $r16, 3 + add $r1, $r1, $r16 + + ! comment out profiling argument + !addi $r2, $lp, 0 + + ! call fixup routine + bal _dl_linux_resolver@PLT + + ! save the return + addi $ta, $r0, 0 + + ! #ifdef __NDS32_ABI_1__ + ! adjust sp + !addi $sp, $sp, 24 + STACK_POP + ! #endif + + ! reload registers + lmw.bim $r0, [$sp], $r5, 6 + + ! jump to the newly found address + jr $ta + +.size _dl_linux_resolve, .-_dl_linux_resolve diff --git a/libc/string/nds32/Makefile b/libc/string/nds32/Makefile new file mode 100644 index 000000000..0a95346fd --- /dev/null +++ b/libc/string/nds32/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir:=../../../ +top_builddir:=../../../ +all: objs +include $(top_builddir)Rules.mak +include ../Makefile.in +include $(top_srcdir)Makerules diff --git a/libc/string/nds32/memcpy.S b/libc/string/nds32/memcpy.S new file mode 100644 index 000000000..4f285b5ee --- /dev/null +++ b/libc/string/nds32/memcpy.S @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2016 Andes Technology, Inc. + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +!========================================================== +! void *memcpy(void *dst, const void *src, int n); +! +! dst: $r0 +! src: $r1 +! n : $r2 +! ret: $r0 - pointer to the memory area dst. +!========================================================== +.weak memcpy +ENTRY(memcpy) + move $r5, $r0 + beq $r0, $r1, .Lquit_memcpy + beqz $r2, .Lquit_memcpy + srli $r3, $r2, #5 ! check if len < cache-line size 32 + beqz $r3, .Lword_copy_entry + andi $r4, $r0, #0x3 ! check byte-align + beqz $r4, .Lunalign_word_copy_entry + + addi $r4, $r4, #-4 + abs $r4, $r4 ! check how many un-align byte to copy + sub $r2, $r2, $r4 ! update $R2 + +.Lunalign_byte_copy: + lbi.bi $r3, [$r1], #1 + addi $r4, $r4, #-1 + sbi.bi $r3, [$r0], #1 + bnez $r4, .Lunalign_byte_copy + beqz $r2, .Lquit_memcpy + +.Lunalign_word_copy_entry: + andi $r3, $r0, 0x1f ! check cache-line unaligncount + beqz $r3, .Lcache_copy + + addi $r3, $r3, #-32 + abs $r3, $r3 + sub $r2, $r2, $r3 ! update $R2 + +.Lunalign_word_copy: + lmw.bim $r4, [$r1], $r4 + addi $r3, $r3, #-4 + smw.bim $r4, [$r0], $r4 + bnez $r3, .Lunalign_word_copy + beqz $r2, .Lquit_memcpy + + addi $r3, $r2, #-32 ! to check $r2 < cache_line, than go to .Lword_copy + bltz $r3, .Lword_copy_entry +.Lcache_copy: + srli $r3, $r2, #5 + beqz $r3, .Lword_copy_entry + pushm $r6, $r13 +.L3: + lmw.bim $r6, [$r1], $r13 + addi $r3, $r3, #-1 + smw.bim $r6, [$r0], $r13 + bnez $r3, .L3 + popm $r6, $r13 + +.Lword_copy_entry: + andi $r2, $r2, #31 + beqz $r2, .Lquit_memcpy + srli $r3, $r2, #2 + beqz $r3, .Lbyte_copy +.Lword_copy: + lmw.bim $r4, [$r1], $r4 + addi $r3, $r3, #-1 + smw.bim $r4, [$r0], $r4 + bnez $r3, .Lword_copy + andi $r2, $r2, #3 + beqz $r2, .Lquit_memcpy + +.Lbyte_copy: + lbi.bi $r3, [$r1], #1 + addi $r2, $r2, #-1 + sbi.bi $r3, [$r0], #1 + bnez $r2, .Lbyte_copy + +.Lquit_memcpy: + move $r0, $r5 + ret + +END(memcpy) +libc_hidden_def(memcpy) diff --git a/libc/string/nds32/memset.S b/libc/string/nds32/memset.S new file mode 100644 index 000000000..edd15a410 --- /dev/null +++ b/libc/string/nds32/memset.S @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2016 Andes Technology, Inc. + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* Copyright (C) 1998, 2003 Free Software Foundation, Inc. + * Contributed by Philip Blundell + * + * 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 +#include +!========================================================== +! void *memset(void *dst, int val, int len); +! +! dst: $r0 +! val: $r1 +! len: $r2 +! ret: $r0 - pointer to the memory area dst. +!========================================================== +.weak memset +ENTRY(memset) + move $r5, $r0 ! Return value + beqz $r2, .Lend_memset ! Exit when len = 0 + srli $r3, $r2, 2 ! r3 is how many words to copy + andi $r2, $r2, 3 ! How many bytes are less than a word + beqz $r3, .Lbyte_set ! When n is less than a word + + ! set r1 from to abababab + andi $r1, $r1, 0x00ff ! r1 = 000000ab + slli $r4, $r1, 8 ! r4 = 0000ab00 + or $r1, $r1, $r4 ! r1 = 0000abab + slli $r4, $r1, 16 ! r4 = abab0000 + or $r1, $r1, $r4 ! r1 = abababab + +.Lword_set: + addi $r3, $r3, -1 ! How many words left to copy + smw.bim $r1, [$r5], $r1 ! Copy the word to det + bnez $r3, .Lword_set ! Still words to set, continue looping + beqz $r2, .Lend_memset ! No left byte to set + +.Lbyte_set: + ! Less than 4 bytes left to set + addi $r2, $r2, -1 ! Decrease len by 1 + sbi.p $r1, [$r5], 1 ! Set data of the next byte to r1 + bnez $r2, .Lbyte_set ! Still bytes left to set + +.Lend_memset: + ret + +END(memset) +libc_hidden_def(memset) diff --git a/libc/sysdeps/linux/nds32/Makefile b/libc/sysdeps/linux/nds32/Makefile new file mode 100644 index 000000000..633c91f3e --- /dev/null +++ b/libc/sysdeps/linux/nds32/Makefile @@ -0,0 +1,13 @@ +# Makefile for uClibc +# +# Copyright (C) 2000-2005 Erik Andersen +# +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. +# + +top_srcdir=../../../../ +top_builddir=../../../../ +all: objs +include $(top_builddir)Rules.mak +include Makefile.arch +include $(top_srcdir)Makerules diff --git a/libc/sysdeps/linux/nds32/Makefile.arch b/libc/sysdeps/linux/nds32/Makefile.arch new file mode 100644 index 000000000..8691875ee --- /dev/null +++ b/libc/sysdeps/linux/nds32/Makefile.arch @@ -0,0 +1,5 @@ +# Copyright (C) 2016 Andes Technology, Inc. +# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + +CSRC-y := brk.c sigaction.c +SSRC-y := setjmp.S __longjmp.S bsd-setjmp.S bsd-_setjmp.S clone.S mmap.S sigrestorer.S vfork.S sysdep.S syscall.S diff --git a/libc/sysdeps/linux/nds32/__longjmp.S b/libc/sysdeps/linux/nds32/__longjmp.S new file mode 100644 index 000000000..fbea6f6f4 --- /dev/null +++ b/libc/sysdeps/linux/nds32/__longjmp.S @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2016 Andes Technology, Inc. + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* + setjmp/longjmp for nds32. + r0 - r5 are for paramter passing - no need to save + r6 - r14 are callee saved - needs to save + r15 is temp register for assembler - no need to save + r16 - r25 are caller saved - no need to save + r26 - r27 are temp registers for OS - no need to save + r28 is fp - need to save + r29 is gp - need to save + r30 is ra - need to save + r31 is sp - need to save + so we need to save r6 - r14 and r28 - r31 + The jmpbuf looks like this: + r6 + r7 + r8 + r9 + r10 + r11 + r12 + r13 + r14 + fp + gp + ra + sp +#ifdef NDS32_ABI_2FP_PLUS + ($fpcfg.freg) + (callee-saved FPU regs) +#endif + reserved(for 8-byte align if needed) +*/ + +#include +#define _SETJMP_H +#define _ASM +#include + .section .text + +/* __longjmp (env[0].__jmpbuf, val ?: 1); */ +ENTRY(__longjmp) + ! restore registers + lmw.bim $r6, [$r0], $r14, #0xf + +#ifdef NDS32_ABI_2FP_PLUS + lwi.bi $r20, [$r0], #4 /* Load $fpcfg.freg to $r20. */ + + /* Case switch for $r20 as $fpcfg.freg. */ + beqz $r20, .LCFG0 /* Branch if $fpcfg.freg = 0b00. */ + xori $r15, $r20, #0b10 + beqz $r15, .LCFG2 /* Branch if $fpcfg.freg = 0b10. */ + srli $r20, $r20, #0b01 + beqz $r20, .LCFG1 /* Branch if $fpcfg.freg = 0b01. */ + /* Fall-through if $fpcfg.freg = 0b11. */ +.LCFG3: + fldi.bi $fd31, [$r0], #8 + fldi.bi $fd30, [$r0], #8 + fldi.bi $fd29, [$r0], #8 + fldi.bi $fd28, [$r0], #8 + fldi.bi $fd27, [$r0], #8 + fldi.bi $fd26, [$r0], #8 + fldi.bi $fd25, [$r0], #8 + fldi.bi $fd24, [$r0], #8 +.LCFG2: + fldi.bi $fd10, [$r0], #8 + fldi.bi $fd9, [$r0], #8 + fldi.bi $fd8, [$r0], #8 +.LCFG1: + fldi.bi $fd7, [$r0], #8 + fldi.bi $fd6, [$r0], #8 + fldi.bi $fd5, [$r0], #8 + fldi.bi $fd4, [$r0], #8 +.LCFG0: + fldi.bi $fd3, [$r0], #8 +#endif /* NDS32_ABI_2FP_PLUS */ + + + ! return error code; make sure error code is not 0 + bnez $r1, .Ldone + movi $r1, #1 +.Ldone: + addi $r0, $r1, #0 + ret +END(__longjmp) +libc_hidden_def(__longjmp) diff --git a/libc/sysdeps/linux/nds32/__syscall_error.c b/libc/sysdeps/linux/nds32/__syscall_error.c new file mode 100644 index 000000000..2aa6903e2 --- /dev/null +++ b/libc/sysdeps/linux/nds32/__syscall_error.c @@ -0,0 +1,16 @@ +/* + * Copyright (C) 2016 Andes Technology, Inc. + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#include +#include + +/* This routine is jumped to by all the syscall handlers, to stash + * an error number into errno. */ +int __syscall_error(int err_no) attribute_hidden; +int __syscall_error(int err_no) +{ + __set_errno(err_no); + return -1; +} diff --git a/libc/sysdeps/linux/nds32/bits/byteswap.h b/libc/sysdeps/linux/nds32/bits/byteswap.h new file mode 100644 index 000000000..0f43cbb4e --- /dev/null +++ b/libc/sysdeps/linux/nds32/bits/byteswap.h @@ -0,0 +1,121 @@ +/* + * Copyright (C) 2016 Andes Technology, Inc. + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +/* Macros to swap the order of bytes in integer values. + Copyright (C) 1997, 1998, 2000, 2002, 2003, 2006, 2007 + Free Software Foundation, Inc. + + 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. */ + +#if !defined _BYTESWAP_H && !defined _NETINET_IN_H +# error "Never use directly; include instead." +#endif + +#ifndef _BITS_BYTESWAP_H +#define _BITS_BYTESWAP_H 1 + +/* Swap bytes in 16 bit value. */ +#define __bswap_constant_16(x) \ + ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8)) + +#ifdef __GNUC__ +# if __GNUC__ >= 2 +# define __bswap_16(x) \ + (__extension__ \ + ({ register unsigned short int __v, __x = (x); \ + if (__builtin_constant_p (__x)) \ + __v = __bswap_constant_16 (__x); \ + else \ + __asm__ ("wsbh %0, %0\n\t" \ + : "=r" (__v) \ + : "0" (__x)); \ + __v; })) +# else +/* This is better than nothing. */ +# define __bswap_16(x) \ + (__extension__ \ + ({ register unsigned short int __x = (x); __bswap_constant_16 (__x); })) +# endif +#else +static __inline unsigned short int +__bswap_16 (unsigned short int __bsx) +{ + return __bswap_constant_16 (__bsx); +} +#endif + +/* Swap bytes in 32 bit value. */ +#define __bswap_constant_32(x) \ + ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \ + (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24)) + +#ifdef __GNUC__ +# if __GNUC__ >= 2 +# define __bswap_32(x) \ + (__extension__ \ + ({ register unsigned int __v, __x = (x); \ + if (__builtin_constant_p (__x)) \ + __v = __bswap_constant_32 (__x); \ + else \ + __asm__ ("wsbh %0, %0\n\t" \ + "rotri %0, %0, #16\n\t" \ + : "=r" (__v) \ + : "0" (__x)); \ + __v; })) +# else +# define __bswap_32(x) \ + (__extension__ \ + ({ register unsigned int __x = (x); __bswap_constant_32 (__x); })) +# endif +#else +static __inline unsigned int +__bswap_32 (unsigned int __bsx) +{ + return __bswap_constant_32 (__bsx); +} +#endif + + +#if defined __GNUC__ && __GNUC__ >= 2 +/* Swap bytes in 64 bit value. */ +#define __bswap_constant_64(x) \ + ((((x) & 0xff00000000000000ull) >> 56) \ + | (((x) & 0x00ff000000000000ull) >> 40) \ + | (((x) & 0x0000ff0000000000ull) >> 24) \ + | (((x) & 0x000000ff00000000ull) >> 8) \ + | (((x) & 0x00000000ff000000ull) << 8) \ + | (((x) & 0x0000000000ff0000ull) << 24) \ + | (((x) & 0x000000000000ff00ull) << 40) \ + | (((x) & 0x00000000000000ffull) << 56)) + +# define __bswap_64(x) \ + (__extension__ \ + ({ union { __extension__ unsigned long long int __ll; \ + unsigned long int __l[2]; } __w, __r; \ + if (__builtin_constant_p (x)) \ + __r.__ll = __bswap_constant_64 (x); \ + else \ + { \ + __w.__ll = (x); \ + __r.__l[0] = __bswap_32 (__w.__l[1]); \ + __r.__l[1] = __bswap_32 (__w.__l[0]); \ + } \ + __r.__ll; })) +#endif + +#endif /* _BITS_BYTESWAP_H */ diff --git a/libc/sysdeps/linux/nds32/bits/endian.h b/libc/sysdeps/linux/nds32/bits/endian.h new file mode 100644 index 000000000..989d752d4 --- /dev/null +++ b/libc/sysdeps/linux/nds32/bits/endian.h @@ -0,0 +1,16 @@ +/* + * Copyright (C) 2016 Andes Technology, Inc. + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. + */ + +#ifndef _ENDIAN_H +# error "Never use directly; include instead." +#endif /* _ENDIAN_H */ + +#ifdef __NDS32_EB__ +#define __BYTE_ORDER __BIG_ENDIAN +#else /* ! __NDS32_EB__ */ +#define __BYTE_ORDER __LITTLE_ENDIAN +#endif /* ! __NDS32_EB__ */ + +#define __FLOAT_WORD_ORDER __BYTE_ORDER diff --git a/libc/sysdeps/linux/nds32/bits/fcntl.h b/libc/sysdeps/linux/nds32/bits/fcntl.h new file mode 100644 index 000000000..d21c4e03c --- /dev/null +++ b/libc/sysdeps/linux/nds32/bits/fcntl.h @@ -0,0 +1,241 @@ +/* O_*, F_*, FD_* bit values for Linux. + Copyright (C) 1995, 1996, 1997, 1998, 2000, 2004, 2007 + 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, see + . */ + +#ifndef _FCNTL_H +# error "Never use directly; include instead." +#endif + +#include +#ifdef __USE_GNU +# include +#endif + + +/* 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_NOATIME 01000000 /* Do not set atime. */ +# define O_CLOEXEC 02000000 /* set close_on_exec */ +# define O_PATH 010000000 /* Resolve pathname but do not open file. */ +#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_UNIX98 +# 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 + +#ifdef __USE_GNU +# define F_SETLEASE 1024 /* Set a lease. */ +# define F_GETLEASE 1025 /* Enquire what lease is active. */ +# define F_NOTIFY 1026 /* Request notfications on a directory. */ +# define F_DUPFD_CLOEXEC 1030 /* Duplicate file descriptor with + close-on-exit set on new fd. */ +# define F_SETPIPE_SZ 1031 /* Set pipe page size array. */ +# define F_GETPIPE_SZ 1032 /* Get pipe page size array. */ +#endif + +/* For F_[GET|SET]FD. */ +#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 + +#ifdef __USE_GNU +# define LOCK_MAND 32 /* This is a mandatory flock: */ +# define LOCK_READ 64 /* ... which allows concurrent read operations. */ +# define LOCK_WRITE 128 /* ... which allows concurrent write operations. */ +# define LOCK_RW 192 /* ... Which allows concurrent read & write operations. */ +#endif + +#ifdef __USE_GNU +/* Types of directory notifications that may be requested with F_NOTIFY. */ +# define DN_ACCESS 0x00000001 /* File accessed. */ +# define DN_MODIFY 0x00000002 /* File modified. */ +# define DN_CREATE 0x00000004 /* File created. */ +# define DN_DELETE 0x00000008 /* File removed. */ +# define DN_RENAME 0x00000010 /* File renamed. */ +# define DN_ATTRIB 0x00000020 /* File changed attibutes. */ +# define DN_MULTISHOT 0x80000000 /* Don't remove notifier. */ +#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 + + +#if defined __USE_GNU && defined __UCLIBC_LINUX_SPECIFIC__ +/* Flags for SYNC_FILE_RANGE. */ +# define SYNC_FILE_RANGE_WAIT_BEFORE 1 /* Wait upon writeout of all pages + in