* [musl] [RFC v2 0/2] xtensa FDPIC port
@ 2024-03-28 20:03 Max Filippov
2024-03-28 20:03 ` [musl] [RFC v2 1/2] xtensa: add port Max Filippov
` (2 more replies)
0 siblings, 3 replies; 15+ messages in thread
From: Max Filippov @ 2024-03-28 20:03 UTC (permalink / raw)
To: musl; +Cc: Rich Felker, Max Filippov
Hello,
this is the second RFC version of the xtensa FDPIC port for musl.
There are two patches: the first adds the port and will likely not
change in the future versions. The second adds two bits of
xtensa-specific GOT initialization for compatibility with the current
binutils/gcc and will go away once binutils and gcc are changed to do
local references differently.
The following binutils and gcc branches can be used to build the
xtensa-linux-muslfdpic toolchain:
https://github.com/jcmvbkbc/binutils-gdb-xtensa xtensa-2.42-fdpic-musl
https://github.com/jcmvbkbc/gcc-xtensa xtensa-14-9655-fdpic-musl
I've tested this version with libc-test using QEMU linux-user and full
system emulation. The results in the linux-user are the following:
FAIL src/functional/dlopen.exe [status 1]
FAIL src/functional/pthread_robust-static.exe [timed out]
FAIL src/functional/pthread_robust.exe [timed out]
FAIL src/functional/strptime-static.exe [status 1]
FAIL src/functional/strptime.exe [status 1]
FAIL src/math/acoshl.exe [status 1]
FAIL src/math/asinhl.exe [status 1]
FAIL src/math/erfcl.exe [status 1]
FAIL src/math/fma.exe [status 1]
FAIL src/math/fmal.exe [status 1]
FAIL src/math/lgammal.exe [status 1]
FAIL src/math/tgammal.exe [status 1]
FAIL src/regression/pthread-robust-detach-static.exe [status 1]
FAIL src/regression/pthread-robust-detach.exe [status 1]
functional/dlopen fails with the
src/functional/dlopen.c:39: dlsym main failed: (null)
There's no failure in the dlsym call, but the pointers don't match.
functional/ and regression/ pthread-related failures are expected
because the robust list functions are not available in the linux-user
mode. These particular tests pass in full system emulation.
math tests fail with ULP differences.
I have also added the following changes to the abi tests to fix the
build:
diff --git a/src/api/sys_sem.c b/src/api/sys_sem.c
index a473cad0a2aa..bd4df9a4fe70 100644
--- a/src/api/sys_sem.c
+++ b/src/api/sys_sem.c
@@ -18,7 +18,11 @@ C(SETALL)
{
struct semid_ds x;
F(struct ipc_perm,sem_perm)
+#ifdef __xtensa__
+F(unsigned long, sem_nsems)
+#else
F(unsigned short, sem_nsems)
+#endif
F(time_t, sem_otime)
F(time_t, sem_ctime)
}
diff --git a/src/api/unistd.c b/src/api/unistd.c
index 522ccdc737cf..f0646ca909c7 100644
--- a/src/api/unistd.c
+++ b/src/api/unistd.c
@@ -114,7 +114,7 @@ C(_PC_REC_MIN_XFER_SIZE)
C(_PC_REC_XFER_ALIGN)
C(_PC_SYMLINK_MAX)
C(_PC_SYNC_IO)
-C(_PC_TIMESTAMP_RESOLUTION)
+//C(_PC_TIMESTAMP_RESOLUTION)
C(_PC_VDISABLE)
C(_SC_2_C_BIND)
C(_SC_2_C_DEV)
@@ -235,7 +235,7 @@ C(_SC_XOPEN_REALTIME_THREADS)
C(_SC_XOPEN_SHM)
C(_SC_XOPEN_STREAMS)
C(_SC_XOPEN_UNIX)
-C(_SC_XOPEN_UUCP)
+//C(_SC_XOPEN_UUCP)
C(_SC_XOPEN_VERSION)
C(STDERR_FILENO)
C(STDIN_FILENO)
---
Max Filippov (2):
xtensa: add port
WIP xtensa bits
arch/xtensa/arch.mak | 1 +
arch/xtensa/atomic_arch.h | 25 ++
arch/xtensa/bits/alltypes.h.in | 27 ++
arch/xtensa/bits/float.h | 16 +
arch/xtensa/bits/ioctl.h | 219 ++++++++++++++
arch/xtensa/bits/ipcstat.h | 1 +
arch/xtensa/bits/limits.h | 1 +
arch/xtensa/bits/mman.h | 20 ++
arch/xtensa/bits/msg.h | 27 ++
arch/xtensa/bits/poll.h | 3 +
arch/xtensa/bits/posix.h | 2 +
arch/xtensa/bits/reg.h | 2 +
arch/xtensa/bits/sem.h | 19 ++
arch/xtensa/bits/setjmp.h | 1 +
arch/xtensa/bits/shm.h | 29 ++
arch/xtensa/bits/signal.h | 92 ++++++
arch/xtensa/bits/stat.h | 23 ++
arch/xtensa/bits/stdint.h | 20 ++
arch/xtensa/bits/syscall.h.in | 407 ++++++++++++++++++++++++++
arch/xtensa/bits/user.h | 4 +
arch/xtensa/crt_arch.h | 48 +++
arch/xtensa/kstat.h | 18 ++
arch/xtensa/pthread_arch.h | 11 +
arch/xtensa/reloc.h | 32 ++
arch/xtensa/syscall_arch.h | 104 +++++++
configure | 8 +
crt/xtensa/crti.S | 21 ++
crt/xtensa/crtn.S | 15 +
include/elf.h | 74 +++++
ldso/dlstart.c | 3 +
ldso/dynlink.c | 8 +-
src/internal/xtensa/syscall.s | 14 +
src/ldso/xtensa/dlsym.s | 6 +
src/ldso/xtensa/dlsym_time64.S | 3 +
src/ldso/xtensa/tlsdesc.s | 25 ++
src/process/xtensa/vfork.s | 13 +
src/setjmp/xtensa/longjmp.s | 18 ++
src/setjmp/xtensa/setjmp.s | 21 ++
src/signal/xtensa/restore.s | 10 +
src/signal/xtensa/sigsetjmp.s | 22 ++
src/thread/xtensa/__set_thread_area.c | 9 +
src/thread/xtensa/__unmapself.s | 9 +
src/thread/xtensa/clone.S | 42 +++
src/thread/xtensa/syscall_cp.s | 34 +++
44 files changed, 1506 insertions(+), 1 deletion(-)
create mode 100644 arch/xtensa/arch.mak
create mode 100644 arch/xtensa/atomic_arch.h
create mode 100644 arch/xtensa/bits/alltypes.h.in
create mode 100644 arch/xtensa/bits/float.h
create mode 100644 arch/xtensa/bits/ioctl.h
create mode 100644 arch/xtensa/bits/ipcstat.h
create mode 100644 arch/xtensa/bits/limits.h
create mode 100644 arch/xtensa/bits/mman.h
create mode 100644 arch/xtensa/bits/msg.h
create mode 100644 arch/xtensa/bits/poll.h
create mode 100644 arch/xtensa/bits/posix.h
create mode 100644 arch/xtensa/bits/reg.h
create mode 100644 arch/xtensa/bits/sem.h
create mode 100644 arch/xtensa/bits/setjmp.h
create mode 100644 arch/xtensa/bits/shm.h
create mode 100644 arch/xtensa/bits/signal.h
create mode 100644 arch/xtensa/bits/stat.h
create mode 100644 arch/xtensa/bits/stdint.h
create mode 100644 arch/xtensa/bits/syscall.h.in
create mode 100644 arch/xtensa/bits/user.h
create mode 100644 arch/xtensa/crt_arch.h
create mode 100644 arch/xtensa/kstat.h
create mode 100644 arch/xtensa/pthread_arch.h
create mode 100644 arch/xtensa/reloc.h
create mode 100644 arch/xtensa/syscall_arch.h
create mode 100644 crt/xtensa/crti.S
create mode 100644 crt/xtensa/crtn.S
create mode 100644 src/internal/xtensa/syscall.s
create mode 100644 src/ldso/xtensa/dlsym.s
create mode 100644 src/ldso/xtensa/dlsym_time64.S
create mode 100644 src/ldso/xtensa/tlsdesc.s
create mode 100644 src/process/xtensa/vfork.s
create mode 100644 src/setjmp/xtensa/longjmp.s
create mode 100644 src/setjmp/xtensa/setjmp.s
create mode 100644 src/signal/xtensa/restore.s
create mode 100644 src/signal/xtensa/sigsetjmp.s
create mode 100644 src/thread/xtensa/__set_thread_area.c
create mode 100644 src/thread/xtensa/__unmapself.s
create mode 100644 src/thread/xtensa/clone.S
create mode 100644 src/thread/xtensa/syscall_cp.s
--
2.39.2
^ permalink raw reply [flat|nested] 15+ messages in thread
* [musl] [RFC v2 1/2] xtensa: add port
2024-03-28 20:03 [musl] [RFC v2 0/2] xtensa FDPIC port Max Filippov
@ 2024-03-28 20:03 ` Max Filippov
2024-03-28 20:03 ` [musl] [RFC v2 2/2] WIP xtensa bits Max Filippov
2024-03-28 23:01 ` [musl] [RFC v2 0/2] xtensa FDPIC port Rich Felker
2 siblings, 0 replies; 15+ messages in thread
From: Max Filippov @ 2024-03-28 20:03 UTC (permalink / raw)
To: musl; +Cc: Rich Felker, Max Filippov
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
Changes v1->v2:
- rebase to 1.2.5
- drop xtensa-config.h, use __XCHAL_* macros directly where needed
- fix max_align_t definition
- drop duplications from arch/xtensa/bits/mman.h
- drop xtensa call0/windowed ABI ifdef checks
- fix mcontext_t definition
- drop endianness indication from the LDSO_ARCH string
- rewrite __tlsdesc_dynamic implementation
- fix sigsetjmp
- rewrite __set_thread_area as C function
- fix ctid argument fetch in __clone implementation
- drop arch/xtensa/bits/termios.h
- add arch/xtensa/bits/msg.h, arch/xtensa/bits/sem.h,
arch/xtensa/bits/shm.h and arch/xtensa/bits/ipcstat.h
- add src/ldso/xtensa/dlsym.s and src/ldso/xtensa/dlsym_time64.S
- add arch/xtensa/bits/poll.h
- replace REL_RELATIVE with REL_SYMBOLIC
---
arch/xtensa/arch.mak | 1 +
arch/xtensa/atomic_arch.h | 25 ++
arch/xtensa/bits/alltypes.h.in | 27 ++
arch/xtensa/bits/float.h | 16 +
arch/xtensa/bits/ioctl.h | 219 ++++++++++++++
arch/xtensa/bits/ipcstat.h | 1 +
arch/xtensa/bits/limits.h | 1 +
arch/xtensa/bits/mman.h | 20 ++
arch/xtensa/bits/msg.h | 27 ++
arch/xtensa/bits/poll.h | 3 +
arch/xtensa/bits/posix.h | 2 +
arch/xtensa/bits/reg.h | 2 +
arch/xtensa/bits/sem.h | 19 ++
arch/xtensa/bits/setjmp.h | 1 +
arch/xtensa/bits/shm.h | 29 ++
arch/xtensa/bits/signal.h | 92 ++++++
arch/xtensa/bits/stat.h | 23 ++
arch/xtensa/bits/stdint.h | 20 ++
arch/xtensa/bits/syscall.h.in | 407 ++++++++++++++++++++++++++
arch/xtensa/bits/user.h | 4 +
arch/xtensa/crt_arch.h | 48 +++
arch/xtensa/kstat.h | 18 ++
arch/xtensa/pthread_arch.h | 11 +
arch/xtensa/reloc.h | 32 ++
arch/xtensa/syscall_arch.h | 104 +++++++
configure | 8 +
crt/xtensa/crti.S | 21 ++
crt/xtensa/crtn.S | 15 +
include/elf.h | 74 +++++
src/internal/xtensa/syscall.s | 14 +
src/ldso/xtensa/dlsym.s | 6 +
src/ldso/xtensa/dlsym_time64.S | 3 +
src/ldso/xtensa/tlsdesc.s | 25 ++
src/process/xtensa/vfork.s | 13 +
src/setjmp/xtensa/longjmp.s | 18 ++
src/setjmp/xtensa/setjmp.s | 21 ++
src/signal/xtensa/restore.s | 10 +
src/signal/xtensa/sigsetjmp.s | 22 ++
src/thread/xtensa/__set_thread_area.c | 9 +
src/thread/xtensa/__unmapself.s | 9 +
src/thread/xtensa/clone.S | 42 +++
src/thread/xtensa/syscall_cp.s | 34 +++
42 files changed, 1496 insertions(+)
create mode 100644 arch/xtensa/arch.mak
create mode 100644 arch/xtensa/atomic_arch.h
create mode 100644 arch/xtensa/bits/alltypes.h.in
create mode 100644 arch/xtensa/bits/float.h
create mode 100644 arch/xtensa/bits/ioctl.h
create mode 100644 arch/xtensa/bits/ipcstat.h
create mode 100644 arch/xtensa/bits/limits.h
create mode 100644 arch/xtensa/bits/mman.h
create mode 100644 arch/xtensa/bits/msg.h
create mode 100644 arch/xtensa/bits/poll.h
create mode 100644 arch/xtensa/bits/posix.h
create mode 100644 arch/xtensa/bits/reg.h
create mode 100644 arch/xtensa/bits/sem.h
create mode 100644 arch/xtensa/bits/setjmp.h
create mode 100644 arch/xtensa/bits/shm.h
create mode 100644 arch/xtensa/bits/signal.h
create mode 100644 arch/xtensa/bits/stat.h
create mode 100644 arch/xtensa/bits/stdint.h
create mode 100644 arch/xtensa/bits/syscall.h.in
create mode 100644 arch/xtensa/bits/user.h
create mode 100644 arch/xtensa/crt_arch.h
create mode 100644 arch/xtensa/kstat.h
create mode 100644 arch/xtensa/pthread_arch.h
create mode 100644 arch/xtensa/reloc.h
create mode 100644 arch/xtensa/syscall_arch.h
create mode 100644 crt/xtensa/crti.S
create mode 100644 crt/xtensa/crtn.S
create mode 100644 src/internal/xtensa/syscall.s
create mode 100644 src/ldso/xtensa/dlsym.s
create mode 100644 src/ldso/xtensa/dlsym_time64.S
create mode 100644 src/ldso/xtensa/tlsdesc.s
create mode 100644 src/process/xtensa/vfork.s
create mode 100644 src/setjmp/xtensa/longjmp.s
create mode 100644 src/setjmp/xtensa/setjmp.s
create mode 100644 src/signal/xtensa/restore.s
create mode 100644 src/signal/xtensa/sigsetjmp.s
create mode 100644 src/thread/xtensa/__set_thread_area.c
create mode 100644 src/thread/xtensa/__unmapself.s
create mode 100644 src/thread/xtensa/clone.S
create mode 100644 src/thread/xtensa/syscall_cp.s
diff --git a/arch/xtensa/arch.mak b/arch/xtensa/arch.mak
new file mode 100644
index 000000000000..aa4d05ceff38
--- /dev/null
+++ b/arch/xtensa/arch.mak
@@ -0,0 +1 @@
+COMPAT_SRC_DIRS = compat/time32
diff --git a/arch/xtensa/atomic_arch.h b/arch/xtensa/atomic_arch.h
new file mode 100644
index 000000000000..ece0f5b19456
--- /dev/null
+++ b/arch/xtensa/atomic_arch.h
@@ -0,0 +1,25 @@
+#if __XCHAL_HAVE_S32C1I
+#define a_cas a_cas
+static inline int a_cas(volatile int *p, int t, int s)
+{
+ __asm__ __volatile__ (
+ " wsr %2, scompare1\n"
+ " s32c1i %0, %1\n"
+ : "+a"(s), "+m"(*p)
+ : "a"(t)
+ : "memory" );
+ return s;
+}
+#endif
+
+#define a_barrier a_barrier
+static inline void a_barrier()
+{
+ __asm__ __volatile__ ("memw" : : : "memory");
+}
+
+#define a_crash a_crash
+static inline void a_crash()
+{
+ __asm__ __volatile__ ("ill" : : : "memory");
+}
diff --git a/arch/xtensa/bits/alltypes.h.in b/arch/xtensa/bits/alltypes.h.in
new file mode 100644
index 000000000000..24f4d20995af
--- /dev/null
+++ b/arch/xtensa/bits/alltypes.h.in
@@ -0,0 +1,27 @@
+#define _REDIR_TIME64 1
+#define _Addr int
+#define _Int64 long long
+#define _Reg int
+
+#if __XTENSA_EB__
+#define __BYTE_ORDER 4321
+#elif __XTENSA_EL__
+#define __BYTE_ORDER 1234
+#else
+#error Unknown endianness
+#endif
+
+#define __LONG_MAX 0x7fffffffL
+
+#ifndef __cplusplus
+#ifdef __WCHAR_TYPE__
+TYPEDEF __WCHAR_TYPE__ wchar_t;
+#else
+TYPEDEF unsigned wchar_t;
+#endif
+#endif
+
+TYPEDEF float float_t;
+TYPEDEF double double_t;
+
+TYPEDEF struct { long long __ll; long double __ld; } max_align_t;
diff --git a/arch/xtensa/bits/float.h b/arch/xtensa/bits/float.h
new file mode 100644
index 000000000000..c4a655e7b58c
--- /dev/null
+++ b/arch/xtensa/bits/float.h
@@ -0,0 +1,16 @@
+#define FLT_EVAL_METHOD 0
+
+#define LDBL_TRUE_MIN 4.94065645841246544177e-324L
+#define LDBL_MIN 2.22507385850720138309e-308L
+#define LDBL_MAX 1.79769313486231570815e+308L
+#define LDBL_EPSILON 2.22044604925031308085e-16L
+
+#define LDBL_MANT_DIG 53
+#define LDBL_MIN_EXP (-1021)
+#define LDBL_MAX_EXP 1024
+
+#define LDBL_DIG 15
+#define LDBL_MIN_10_EXP (-307)
+#define LDBL_MAX_10_EXP 308
+
+#define DECIMAL_DIG 17
diff --git a/arch/xtensa/bits/ioctl.h b/arch/xtensa/bits/ioctl.h
new file mode 100644
index 000000000000..f30e3a699bf8
--- /dev/null
+++ b/arch/xtensa/bits/ioctl.h
@@ -0,0 +1,219 @@
+#define _IOC(a,b,c,d) ( ((a)<<30) | ((b)<<8) | (c) | ((d)<<16) )
+#define _IOC_NONE 0U
+#define _IOC_READ 2U
+#define _IOC_WRITE 1U
+
+#define _IO(a,b) _IOC(_IOC_NONE,(a),(b),0)
+#define _IOW(a,b,c) _IOC(_IOC_WRITE,(a),(b),sizeof(c))
+#define _IOR(a,b,c) _IOC(_IOC_READ,(a),(b),sizeof(c))
+#define _IOWR(a,b,c) _IOC(_IOC_READ|_IOC_WRITE,(a),(b),sizeof(c))
+
+#define FIOCLEX _IO('f', 1)
+#define FIONCLEX _IO('f', 2)
+#define FIOASYNC _IOW('f', 125, int)
+#define FIONBIO _IOW('f', 126, int)
+#define FIONREAD _IOR('f', 127, int)
+#define TIOCINQ FIONREAD
+#define FIOQSIZE _IOR('f', 128, loff_t)
+
+#define TCGETS 0x5401
+#define TCSETS 0x5402
+#define TCSETSW 0x5403
+#define TCSETSF 0x5404
+
+#define TCGETA 0x80127417 /* _IOR('t', 23, struct termio) */
+#define TCSETA 0x40127418 /* _IOW('t', 24, struct termio) */
+#define TCSETAW 0x40127419 /* _IOW('t', 25, struct termio) */
+#define TCSETAF 0x4012741C /* _IOW('t', 28, struct termio) */
+
+#define TCSBRK _IO('t', 29)
+#define TCXONC _IO('t', 30)
+#define TCFLSH _IO('t', 31)
+
+#define TIOCSWINSZ 0x40087467 /* _IOW('t', 103, struct winsize) */
+#define TIOCGWINSZ 0x80087468 /* _IOR('t', 104, struct winsize) */
+#define TIOCSTART _IO('t', 110) /* start output, like ^Q */
+#define TIOCSTOP _IO('t', 111) /* stop output, like ^S */
+#define TIOCOUTQ _IOR('t', 115, int) /* output queue size */
+
+#define TIOCSPGRP _IOW('t', 118, int)
+#define TIOCGPGRP _IOR('t', 119, int)
+
+#define TIOCEXCL _IO('T', 12)
+#define TIOCNXCL _IO('T', 13)
+#define TIOCSCTTY _IO('T', 14)
+
+#define TIOCSTI _IOW('T', 18, char)
+#define TIOCMGET _IOR('T', 21, unsigned int)
+#define TIOCMBIS _IOW('T', 22, unsigned int)
+#define TIOCMBIC _IOW('T', 23, unsigned int)
+#define TIOCMSET _IOW('T', 24, unsigned int)
+# define TIOCM_LE 0x001
+# define TIOCM_DTR 0x002
+# define TIOCM_RTS 0x004
+# define TIOCM_ST 0x008
+# define TIOCM_SR 0x010
+# define TIOCM_CTS 0x020
+# define TIOCM_CAR 0x040
+# define TIOCM_RNG 0x080
+# define TIOCM_DSR 0x100
+# define TIOCM_CD TIOCM_CAR
+# define TIOCM_RI TIOCM_RNG
+
+#define TIOCGSOFTCAR _IOR('T', 25, unsigned int)
+#define TIOCSSOFTCAR _IOW('T', 26, unsigned int)
+#define TIOCLINUX _IOW('T', 28, char)
+#define TIOCCONS _IO('T', 29)
+#define TIOCGSERIAL 0x803C541E /*_IOR('T', 30, struct serial_struct)*/
+#define TIOCSSERIAL 0x403C541F /*_IOW('T', 31, struct serial_struct)*/
+#define TIOCPKT _IOW('T', 32, int)
+# define TIOCPKT_DATA 0
+# define TIOCPKT_FLUSHREAD 1
+# define TIOCPKT_FLUSHWRITE 2
+# define TIOCPKT_STOP 4
+# define TIOCPKT_START 8
+# define TIOCPKT_NOSTOP 16
+# define TIOCPKT_DOSTOP 32
+# define TIOCPKT_IOCTL 64
+
+
+#define TIOCNOTTY _IO('T', 34)
+#define TIOCSETD _IOW('T', 35, int)
+#define TIOCGETD _IOR('T', 36, int)
+#define TCSBRKP _IOW('T', 37, int) /* Needed for POSIX tcsendbreak()*/
+#define TIOCSBRK _IO('T', 39) /* BSD compatibility */
+#define TIOCCBRK _IO('T', 40) /* BSD compatibility */
+#define TIOCGSID _IOR('T', 41, pid_t) /* Return the session ID of FD*/
+#define TCGETS2 _IOR('T', 42, struct termios2)
+#define TCSETS2 _IOW('T', 43, struct termios2)
+#define TCSETSW2 _IOW('T', 44, struct termios2)
+#define TCSETSF2 _IOW('T', 45, struct termios2)
+#define TIOCGRS485 _IOR('T', 46, struct serial_rs485)
+#define TIOCSRS485 _IOWR('T', 47, struct serial_rs485)
+#define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
+#define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
+#define TIOCGDEV _IOR('T',0x32, unsigned int) /* Get primary device node of /dev/console */
+#define TIOCSIG _IOW('T',0x36, int) /* Generate signal on Pty slave */
+#define TIOCVHANGUP _IO('T', 0x37)
+#define TIOCGPKT _IOR('T', 0x38, int) /* Get packet mode state */
+#define TIOCGPTLCK _IOR('T', 0x39, int) /* Get Pty lock state */
+#define TIOCGEXCL _IOR('T', 0x40, int) /* Get exclusive mode state */
+
+#define TIOCSERCONFIG _IO('T', 83)
+#define TIOCSERGWILD _IOR('T', 84, int)
+#define TIOCSERSWILD _IOW('T', 85, int)
+#define TIOCGLCKTRMIOS 0x5456
+#define TIOCSLCKTRMIOS 0x5457
+#define TIOCSERGSTRUCT 0x5458 /* For debugging only */
+#define TIOCSERGETLSR _IOR('T', 89, unsigned int) /* Get line status reg. */
+ /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
+#define TIOCSERGETMULTI 0x80a8545a /* Get multiport config */
+ /* _IOR('T', 90, struct serial_multiport_struct) */
+#define TIOCSERSETMULTI 0x40a8545b /* Set multiport config */
+ /* _IOW('T', 91, struct serial_multiport_struct) */
+
+#define TIOCMIWAIT _IO('T', 92) /* wait for a change on serial input line(s) */
+#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
+
+#define TIOCM_LE 0x001
+#define TIOCM_DTR 0x002
+#define TIOCM_RTS 0x004
+#define TIOCM_ST 0x008
+#define TIOCM_SR 0x010
+#define TIOCM_CTS 0x020
+#define TIOCM_CAR 0x040
+#define TIOCM_RNG 0x080
+#define TIOCM_DSR 0x100
+#define TIOCM_CD TIOCM_CAR
+#define TIOCM_RI TIOCM_RNG
+#define TIOCM_OUT1 0x2000
+#define TIOCM_OUT2 0x4000
+#define TIOCM_LOOP 0x8000
+#define TIOCM_MODEM_BITS TIOCM_OUT2
+
+#define N_TTY 0
+#define N_SLIP 1
+#define N_MOUSE 2
+#define N_PPP 3
+#define N_STRIP 4
+#define N_AX25 5
+#define N_X25 6
+#define N_6PACK 7
+#define N_MASC 8
+#define N_R3964 9
+#define N_PROFIBUS_FDL 10
+#define N_IRDA 11
+#define N_SMSBLOCK 12
+#define N_HDLC 13
+#define N_SYNC_PPP 14
+#define N_HCI 15
+
+#define FIOGETOWN _IOR('f', 123, int)
+#define FIOSETOWN _IOW('f', 124, int)
+#define SIOCATMARK _IOR('s', 7, int)
+#define SIOCSPGRP _IOW('s', 8, pid_t)
+#define SIOCGPGRP _IOR('s', 9, pid_t)
+#define SIOCGSTAMP 0x8906 /* Get stamp (timeval) */
+#define SIOCGSTAMPNS 0x8907 /* Get stamp (timespec) */
+
+#define SIOCADDRT 0x890B
+#define SIOCDELRT 0x890C
+#define SIOCRTMSG 0x890D
+
+#define SIOCGIFNAME 0x8910
+#define SIOCSIFLINK 0x8911
+#define SIOCGIFCONF 0x8912
+#define SIOCGIFFLAGS 0x8913
+#define SIOCSIFFLAGS 0x8914
+#define SIOCGIFADDR 0x8915
+#define SIOCSIFADDR 0x8916
+#define SIOCGIFDSTADDR 0x8917
+#define SIOCSIFDSTADDR 0x8918
+#define SIOCGIFBRDADDR 0x8919
+#define SIOCSIFBRDADDR 0x891a
+#define SIOCGIFNETMASK 0x891b
+#define SIOCSIFNETMASK 0x891c
+#define SIOCGIFMETRIC 0x891d
+#define SIOCSIFMETRIC 0x891e
+#define SIOCGIFMEM 0x891f
+#define SIOCSIFMEM 0x8920
+#define SIOCGIFMTU 0x8921
+#define SIOCSIFMTU 0x8922
+#define SIOCSIFHWADDR 0x8924
+#define SIOCGIFENCAP 0x8925
+#define SIOCSIFENCAP 0x8926
+#define SIOCGIFHWADDR 0x8927
+#define SIOCGIFSLAVE 0x8929
+#define SIOCSIFSLAVE 0x8930
+#define SIOCADDMULTI 0x8931
+#define SIOCDELMULTI 0x8932
+#define SIOCGIFINDEX 0x8933
+#define SIOGIFINDEX SIOCGIFINDEX
+#define SIOCSIFPFLAGS 0x8934
+#define SIOCGIFPFLAGS 0x8935
+#define SIOCDIFADDR 0x8936
+#define SIOCSIFHWBROADCAST 0x8937
+#define SIOCGIFCOUNT 0x8938
+
+#define SIOCGIFBR 0x8940
+#define SIOCSIFBR 0x8941
+
+#define SIOCGIFTXQLEN 0x8942
+#define SIOCSIFTXQLEN 0x8943
+
+#define SIOCDARP 0x8953
+#define SIOCGARP 0x8954
+#define SIOCSARP 0x8955
+
+#define SIOCDRARP 0x8960
+#define SIOCGRARP 0x8961
+#define SIOCSRARP 0x8962
+
+#define SIOCGIFMAP 0x8970
+#define SIOCSIFMAP 0x8971
+
+#define SIOCADDDLCI 0x8980
+#define SIOCDELDLCI 0x8981
+
+#define SIOCDEVPRIVATE 0x89F0
+#define SIOCPROTOPRIVATE 0x89E0
diff --git a/arch/xtensa/bits/ipcstat.h b/arch/xtensa/bits/ipcstat.h
new file mode 100644
index 000000000000..4f4fcb0c5b74
--- /dev/null
+++ b/arch/xtensa/bits/ipcstat.h
@@ -0,0 +1 @@
+#define IPC_STAT 0x102
diff --git a/arch/xtensa/bits/limits.h b/arch/xtensa/bits/limits.h
new file mode 100644
index 000000000000..07743b6fd61f
--- /dev/null
+++ b/arch/xtensa/bits/limits.h
@@ -0,0 +1 @@
+#define PAGESIZE 4096
diff --git a/arch/xtensa/bits/mman.h b/arch/xtensa/bits/mman.h
new file mode 100644
index 000000000000..0cc7b46b0740
--- /dev/null
+++ b/arch/xtensa/bits/mman.h
@@ -0,0 +1,20 @@
+#undef MAP_ANON
+#define MAP_ANON 0x800
+#undef MAP_NORESERVE
+#define MAP_NORESERVE 0x0400
+#undef MAP_GROWSDOWN
+#define MAP_GROWSDOWN 0x1000
+#undef MAP_DENYWRITE
+#define MAP_DENYWRITE 0x2000
+#undef MAP_EXECUTABLE
+#define MAP_EXECUTABLE 0x4000
+#undef MAP_LOCKED
+#define MAP_LOCKED 0x8000
+#undef MAP_POPULATE
+#define MAP_POPULATE 0x10000
+#undef MAP_NONBLOCK
+#define MAP_NONBLOCK 0x20000
+#undef MAP_STACK
+#define MAP_STACK 0x40000
+#undef MAP_HUGETLB
+#define MAP_HUGETLB 0x80000
diff --git a/arch/xtensa/bits/msg.h b/arch/xtensa/bits/msg.h
new file mode 100644
index 000000000000..f05f280b65e1
--- /dev/null
+++ b/arch/xtensa/bits/msg.h
@@ -0,0 +1,27 @@
+struct msqid_ds {
+ struct ipc_perm msg_perm;
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ unsigned long __msg_stime_lo;
+ unsigned long __msg_stime_hi;
+ unsigned long __msg_rtime_lo;
+ unsigned long __msg_rtime_hi;
+ unsigned long __msg_ctime_lo;
+ unsigned long __msg_ctime_hi;
+#else
+ unsigned long __msg_stime_hi;
+ unsigned long __msg_stime_lo;
+ unsigned long __msg_rtime_hi;
+ unsigned long __msg_rtime_lo;
+ unsigned long __msg_ctime_hi;
+ unsigned long __msg_ctime_lo;
+#endif
+ unsigned long msg_cbytes;
+ msgqnum_t msg_qnum;
+ msglen_t msg_qbytes;
+ pid_t msg_lspid;
+ pid_t msg_lrpid;
+ unsigned long __unused[2];
+ time_t msg_stime;
+ time_t msg_rtime;
+ time_t msg_ctime;
+};
diff --git a/arch/xtensa/bits/poll.h b/arch/xtensa/bits/poll.h
new file mode 100644
index 000000000000..939398a79aa2
--- /dev/null
+++ b/arch/xtensa/bits/poll.h
@@ -0,0 +1,3 @@
+#define POLLWRNORM POLLOUT
+#define POLLWRBAND 0x100
+#define POLLREMOVE 0x800
diff --git a/arch/xtensa/bits/posix.h b/arch/xtensa/bits/posix.h
new file mode 100644
index 000000000000..30a38714f36d
--- /dev/null
+++ b/arch/xtensa/bits/posix.h
@@ -0,0 +1,2 @@
+#define _POSIX_V6_ILP32_OFFBIG 1
+#define _POSIX_V7_ILP32_OFFBIG 1
diff --git a/arch/xtensa/bits/reg.h b/arch/xtensa/bits/reg.h
new file mode 100644
index 000000000000..0192a2931bd7
--- /dev/null
+++ b/arch/xtensa/bits/reg.h
@@ -0,0 +1,2 @@
+#undef __WORDSIZE
+#define __WORDSIZE 32
diff --git a/arch/xtensa/bits/sem.h b/arch/xtensa/bits/sem.h
new file mode 100644
index 000000000000..bf634eeb1d45
--- /dev/null
+++ b/arch/xtensa/bits/sem.h
@@ -0,0 +1,19 @@
+struct semid_ds {
+ struct ipc_perm sem_perm;
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ unsigned long __sem_otime_lo;
+ unsigned long __sem_otime_hi;
+ unsigned long __sem_ctime_lo;
+ unsigned long __sem_ctime_hi;
+#else
+ unsigned long __sem_otime_hi;
+ unsigned long __sem_otime_lo;
+ unsigned long __sem_ctime_hi;
+ unsigned long __sem_ctime_lo;
+#endif
+ unsigned long sem_nsems;
+ long __unused3;
+ long __unused4;
+ time_t sem_otime;
+ time_t sem_ctime;
+};
diff --git a/arch/xtensa/bits/setjmp.h b/arch/xtensa/bits/setjmp.h
new file mode 100644
index 000000000000..decd26dca07a
--- /dev/null
+++ b/arch/xtensa/bits/setjmp.h
@@ -0,0 +1 @@
+typedef unsigned long __jmp_buf[6];
diff --git a/arch/xtensa/bits/shm.h b/arch/xtensa/bits/shm.h
new file mode 100644
index 000000000000..2febc663f709
--- /dev/null
+++ b/arch/xtensa/bits/shm.h
@@ -0,0 +1,29 @@
+#define SHMLBA 4096
+
+struct shmid_ds {
+ struct ipc_perm shm_perm;
+ size_t shm_segsz;
+ unsigned long __shm_atime_lo;
+ unsigned long __shm_atime_hi;
+ unsigned long __shm_dtime_lo;
+ unsigned long __shm_dtime_hi;
+ unsigned long __shm_ctime_lo;
+ unsigned long __shm_ctime_hi;
+ pid_t shm_cpid;
+ pid_t shm_lpid;
+ unsigned long shm_nattch;
+ unsigned long __unused[2];
+ time_t shm_atime;
+ time_t shm_dtime;
+ time_t shm_ctime;
+};
+
+struct shminfo {
+ unsigned long shmmax, shmmin, shmmni, shmseg, shmall, __unused[4];
+};
+
+struct shm_info {
+ int __used_ids;
+ unsigned long shm_tot, shm_rss, shm_swp;
+ unsigned long __swap_attempts, __swap_successes;
+};
diff --git a/arch/xtensa/bits/signal.h b/arch/xtensa/bits/signal.h
new file mode 100644
index 000000000000..aa1b958abc9a
--- /dev/null
+++ b/arch/xtensa/bits/signal.h
@@ -0,0 +1,92 @@
+#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \
+ || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
+
+#if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
+#define MINSIGSTKSZ 2048
+#define SIGSTKSZ 8192
+#endif
+
+#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
+typedef struct sigcontext {
+ unsigned long sc_pc;
+ unsigned long sc_ps;
+ unsigned long sc_lbeg;
+ unsigned long sc_lend;
+ unsigned long sc_lcount;
+ unsigned long sc_sar;
+ unsigned long sc_acclo;
+ unsigned long sc_acchi;
+ unsigned long sc_a[16];
+ void *sc_xtregs;
+} mcontext_t;
+#else
+typedef struct {
+ unsigned long __regs[25];
+} mcontext_t;
+#endif
+
+struct sigaltstack {
+ void *ss_sp;
+ int ss_flags;
+ size_t ss_size;
+};
+
+typedef struct __ucontext {
+ unsigned long uc_flags;
+ struct __ucontext *uc_link;
+ stack_t uc_stack;
+ mcontext_t uc_mcontext;
+ sigset_t uc_sigmask;
+} ucontext_t;
+
+#define SA_NOCLDSTOP 0x00000001
+#define SA_NOCLDWAIT 0x00000002 /* not supported yet */
+#define SA_SIGINFO 0x00000004
+#define SA_ONSTACK 0x08000000
+#define SA_RESTART 0x10000000
+#define SA_NODEFER 0x40000000
+#define SA_RESETHAND 0x80000000
+
+#define SA_NOMASK SA_NODEFER
+#define SA_ONESHOT SA_RESETHAND
+
+#define SA_RESTORER 0x04000000
+
+#endif
+
+#define SIGHUP 1
+#define SIGINT 2
+#define SIGQUIT 3
+#define SIGILL 4
+#define SIGTRAP 5
+#define SIGABRT 6
+#define SIGIOT 6
+#define SIGBUS 7
+#define SIGFPE 8
+#define SIGKILL 9
+#define SIGUSR1 10
+#define SIGSEGV 11
+#define SIGUSR2 12
+#define SIGPIPE 13
+#define SIGALRM 14
+#define SIGTERM 15
+#define SIGSTKFLT 16
+#define SIGCHLD 17
+#define SIGCONT 18
+#define SIGSTOP 19
+#define SIGTSTP 20
+#define SIGTTIN 21
+#define SIGTTOU 22
+#define SIGURG 23
+#define SIGXCPU 24
+#define SIGXFSZ 25
+#define SIGVTALRM 26
+#define SIGPROF 27
+#define SIGWINCH 28
+#define SIGIO 29
+#define SIGPOLL SIGIO
+#define SIGPWR 30
+#define SIGSYS 31
+#define SIGUNUSED 31
+
+#define _NSIG 65
diff --git a/arch/xtensa/bits/stat.h b/arch/xtensa/bits/stat.h
new file mode 100644
index 000000000000..31d92fec1232
--- /dev/null
+++ b/arch/xtensa/bits/stat.h
@@ -0,0 +1,23 @@
+/* copied from kernel definition, but with padding replaced
+ * by the corresponding correctly-sized userspace types. */
+
+struct stat {
+ dev_t st_dev;
+ ino_t st_ino;
+ mode_t st_mode;
+ nlink_t st_nlink;
+ uid_t st_uid;
+ gid_t st_gid;
+ dev_t st_rdev;
+ off_t st_size;
+ blksize_t st_blksize;
+ long __st_padding1;
+ blkcnt_t st_blocks;
+ struct {
+ long tv_sec;
+ long tv_nsec;
+ } __st_atim32, __st_mtim32, __st_ctim32;
+ struct timespec st_atim;
+ struct timespec st_mtim;
+ struct timespec st_ctim;
+};
diff --git a/arch/xtensa/bits/stdint.h b/arch/xtensa/bits/stdint.h
new file mode 100644
index 000000000000..d1b2712199ac
--- /dev/null
+++ b/arch/xtensa/bits/stdint.h
@@ -0,0 +1,20 @@
+typedef int32_t int_fast16_t;
+typedef int32_t int_fast32_t;
+typedef uint32_t uint_fast16_t;
+typedef uint32_t uint_fast32_t;
+
+#define INT_FAST16_MIN INT32_MIN
+#define INT_FAST32_MIN INT32_MIN
+
+#define INT_FAST16_MAX INT32_MAX
+#define INT_FAST32_MAX INT32_MAX
+
+#define UINT_FAST16_MAX UINT32_MAX
+#define UINT_FAST32_MAX UINT32_MAX
+
+#define INTPTR_MIN INT32_MIN
+#define INTPTR_MAX INT32_MAX
+#define UINTPTR_MAX UINT32_MAX
+#define PTRDIFF_MIN INT32_MIN
+#define PTRDIFF_MAX INT32_MAX
+#define SIZE_MAX UINT32_MAX
diff --git a/arch/xtensa/bits/syscall.h.in b/arch/xtensa/bits/syscall.h.in
new file mode 100644
index 000000000000..ec3135e12b07
--- /dev/null
+++ b/arch/xtensa/bits/syscall.h.in
@@ -0,0 +1,407 @@
+#define __NR_spill 0
+#define __NR_xtensa 1
+#define __NR_available4 2
+#define __NR_available5 3
+#define __NR_available6 4
+#define __NR_available7 5
+#define __NR_available8 6
+#define __NR_available9 7
+#define __NR_open 8
+#define __NR_close 9
+#define __NR_dup 10
+#define __NR_dup2 11
+#define __NR_read 12
+#define __NR_write 13
+#define __NR_select 14
+#define __NR_lseek 15
+#define __NR_poll 16
+#define __NR__llseek 17
+#define __NR_epoll_wait 18
+#define __NR_epoll_ctl 19
+#define __NR_epoll_create 20
+#define __NR_creat 21
+#define __NR_truncate 22
+#define __NR_ftruncate 23
+#define __NR_readv 24
+#define __NR_writev 25
+#define __NR_fsync 26
+#define __NR_fdatasync 27
+#define __NR_truncate64 28
+#define __NR_ftruncate64 29
+#define __NR_pread64 30
+#define __NR_pwrite64 31
+#define __NR_link 32
+#define __NR_rename 33
+#define __NR_symlink 34
+#define __NR_readlink 35
+#define __NR_mknod 36
+#define __NR_pipe 37
+#define __NR_unlink 38
+#define __NR_rmdir 39
+#define __NR_mkdir 40
+#define __NR_chdir 41
+#define __NR_fchdir 42
+#define __NR_getcwd 43
+#define __NR_chmod 44
+#define __NR_chown 45
+#define __NR_stat 46
+#define __NR_stat64 47
+#define __NR_lchown 48
+#define __NR_lstat 49
+#define __NR_lstat64 50
+#define __NR_available51 51
+#define __NR_fchmod 52
+#define __NR_fchown 53
+#define __NR_fstat 54
+#define __NR_fstat64 55
+#define __NR_flock 56
+#define __NR_access 57
+#define __NR_umask 58
+#define __NR_getdents 59
+#define __NR_getdents64 60
+#define __NR_fcntl64 61
+#define __NR_fallocate 62
+#define __NR_fadvise64_64 63
+#define __NR_utime 64 /* glibc 2.3.3 ?? */
+#define __NR_utimes 65
+#define __NR_ioctl 66
+#define __NR_fcntl 67
+#define __NR_setxattr 68
+#define __NR_getxattr 69
+#define __NR_listxattr 70
+#define __NR_removexattr 71
+#define __NR_lsetxattr 72
+#define __NR_lgetxattr 73
+#define __NR_llistxattr 74
+#define __NR_lremovexattr 75
+#define __NR_fsetxattr 76
+#define __NR_fgetxattr 77
+#define __NR_flistxattr 78
+#define __NR_fremovexattr 79
+#define __NR_mmap2 80
+#define __NR_munmap 81
+#define __NR_mprotect 82
+#define __NR_brk 83
+#define __NR_mlock 84
+#define __NR_munlock 85
+#define __NR_mlockall 86
+#define __NR_munlockall 87
+#define __NR_mremap 88
+#define __NR_msync 89
+#define __NR_mincore 90
+#define __NR_madvise 91
+#define __NR_shmget 92
+#define __NR_shmat 93
+#define __NR_shmctl 94
+#define __NR_shmdt 95
+#define __NR_socket 96
+#define __NR_setsockopt 97
+#define __NR_getsockopt 98
+#define __NR_shutdown 99
+#define __NR_bind 100
+#define __NR_connect 101
+#define __NR_listen 102
+#define __NR_accept 103
+#define __NR_getsockname 104
+#define __NR_getpeername 105
+#define __NR_sendmsg 106
+#define __NR_recvmsg 107
+#define __NR_send 108
+#define __NR_recv 109
+#define __NR_sendto 110
+#define __NR_recvfrom 111
+#define __NR_socketpair 112
+#define __NR_sendfile 113
+#define __NR_sendfile64 114
+#define __NR_sendmmsg 115
+#define __NR_clone 116
+#define __NR_execve 117
+#define __NR_exit 118
+#define __NR_exit_group 119
+#define __NR_getpid 120
+#define __NR_wait4 121
+#define __NR_waitid 122
+#define __NR_kill 123
+#define __NR_tkill 124
+#define __NR_tgkill 125
+#define __NR_set_tid_address 126
+#define __NR_gettid 127
+#define __NR_setsid 128
+#define __NR_getsid 129
+#define __NR_prctl 130
+#define __NR_personality 131
+#define __NR_getpriority 132
+#define __NR_setpriority 133
+#define __NR_setitimer 134
+#define __NR_getitimer 135
+#define __NR_setuid 136
+#define __NR_getuid 137
+#define __NR_setgid 138
+#define __NR_getgid 139
+#define __NR_geteuid 140
+#define __NR_getegid 141
+#define __NR_setreuid 142
+#define __NR_setregid 143
+#define __NR_setresuid 144
+#define __NR_getresuid 145
+#define __NR_setresgid 146
+#define __NR_getresgid 147
+#define __NR_setpgid 148
+#define __NR_getpgid 149
+#define __NR_getppid 150
+#define __NR_getpgrp 151
+#define __NR_reserved152 152 /* set_thread_area */
+#define __NR_reserved153 153 /* get_thread_area */
+#define __NR_times 154
+#define __NR_acct 155
+#define __NR_sched_setaffinity 156
+#define __NR_sched_getaffinity 157
+#define __NR_capget 158
+#define __NR_capset 159
+#define __NR_ptrace 160
+#define __NR_semtimedop 161
+#define __NR_semget 162
+#define __NR_semop 163
+#define __NR_semctl 164
+#define __NR_available165 165
+#define __NR_msgget 166
+#define __NR_msgsnd 167
+#define __NR_msgrcv 168
+#define __NR_msgctl 169
+#define __NR_available170 170
+#define __NR_umount2 171
+#define __NR_mount 172
+#define __NR_swapon 173
+#define __NR_chroot 174
+#define __NR_pivot_root 175
+#define __NR_umount 176
+#define __NR_swapoff 177
+#define __NR_sync 178
+#define __NR_syncfs 179
+#define __NR_setfsuid 180
+#define __NR_setfsgid 181
+#define __NR_sysfs 182
+#define __NR_ustat 183
+#define __NR_statfs 184
+#define __NR_fstatfs 185
+#define __NR_statfs64 186
+#define __NR_fstatfs64 187
+#define __NR_setrlimit 188
+#define __NR_getrlimit 189
+#define __NR_getrusage 190
+#define __NR_futex 191
+#define __NR_gettimeofday 192
+#define __NR_settimeofday 193
+#define __NR_adjtimex 194
+#define __NR_nanosleep 195
+#define __NR_getgroups 196
+#define __NR_setgroups 197
+#define __NR_sethostname 198
+#define __NR_setdomainname 199
+#define __NR_syslog 200
+#define __NR_vhangup 201
+#define __NR_uselib 202
+#define __NR_reboot 203
+#define __NR_quotactl 204
+#define __NR_nfsservctl 205
+#define __NR__sysctl 206
+#define __NR_bdflush 207
+#define __NR_uname 208
+#define __NR_sysinfo 209
+#define __NR_init_module 210
+#define __NR_delete_module 211
+#define __NR_sched_setparam 212
+#define __NR_sched_getparam 213
+#define __NR_sched_setscheduler 214
+#define __NR_sched_getscheduler 215
+#define __NR_sched_get_priority_max 216
+#define __NR_sched_get_priority_min 217
+#define __NR_sched_rr_get_interval 218
+#define __NR_sched_yield 219
+#define __NR_available222 222
+#define __NR_restart_syscall 223
+#define __NR_sigaltstack 224
+#define __NR_rt_sigreturn 225
+#define __NR_rt_sigaction 226
+#define __NR_rt_sigprocmask 227
+#define __NR_rt_sigpending 228
+#define __NR_rt_sigtimedwait 229
+#define __NR_rt_sigqueueinfo 230
+#define __NR_rt_sigsuspend 231
+#define __NR_mq_open 232
+#define __NR_mq_unlink 233
+#define __NR_mq_timedsend 234
+#define __NR_mq_timedreceive 235
+#define __NR_mq_notify 236
+#define __NR_mq_getsetattr 237
+#define __NR_available238 238
+#define __NR_io_setup 239
+#define __NR_io_destroy 240
+#define __NR_io_submit 241
+#define __NR_io_getevents 242
+#define __NR_io_cancel 243
+#define __NR_clock_settime 244
+#define __NR_clock_gettime 245
+#define __NR_clock_getres 246
+#define __NR_clock_nanosleep 247
+#define __NR_timer_create 248
+#define __NR_timer_delete 249
+#define __NR_timer_settime 250
+#define __NR_timer_gettime 251
+#define __NR_timer_getoverrun 252
+#define __NR_reserved253 253
+#define __NR_lookup_dcookie 254
+#define __NR_available255 255
+#define __NR_add_key 256
+#define __NR_request_key 257
+#define __NR_keyctl 258
+#define __NR_available259 259
+#define __NR_readahead 260
+#define __NR_remap_file_pages 261
+#define __NR_migrate_pages 262
+#define __NR_mbind 263
+#define __NR_get_mempolicy 264
+#define __NR_set_mempolicy 265
+#define __NR_unshare 266
+#define __NR_move_pages 267
+#define __NR_splice 268
+#define __NR_tee 269
+#define __NR_vmsplice 270
+#define __NR_available271 271
+#define __NR_pselect6 272
+#define __NR_ppoll 273
+#define __NR_epoll_pwait 274
+#define __NR_epoll_create1 275
+#define __NR_inotify_init 276
+#define __NR_inotify_add_watch 277
+#define __NR_inotify_rm_watch 278
+#define __NR_inotify_init1 279
+#define __NR_getcpu 280
+#define __NR_kexec_load 281
+#define __NR_ioprio_set 282
+#define __NR_ioprio_get 283
+#define __NR_set_robust_list 284
+#define __NR_get_robust_list 285
+#define __NR_available286 286
+#define __NR_available287 287
+#define __NR_openat 288
+#define __NR_mkdirat 289
+#define __NR_mknodat 290
+#define __NR_unlinkat 291
+#define __NR_renameat 292
+#define __NR_linkat 293
+#define __NR_symlinkat 294
+#define __NR_readlinkat 295
+#define __NR_utimensat 296
+#define __NR_fchownat 297
+#define __NR_futimesat 298
+#define __NR_fstatat64 299
+#define __NR_fchmodat 300
+#define __NR_faccessat 301
+#define __NR_available302 302
+#define __NR_available303 303
+#define __NR_signalfd 304
+#define __NR_eventfd 306
+#define __NR_recvmmsg 307
+#define __NR_setns 308
+#define __NR_signalfd4 309
+#define __NR_dup3 310
+#define __NR_pipe2 311
+#define __NR_timerfd_create 312
+#define __NR_timerfd_settime 313
+#define __NR_timerfd_gettime 314
+#define __NR_available315 315
+#define __NR_eventfd2 316
+#define __NR_preadv 317
+#define __NR_pwritev 318
+#define __NR_available319 319
+#define __NR_fanotify_init 320
+#define __NR_fanotify_mark 321
+#define __NR_process_vm_readv 322
+#define __NR_process_vm_writev 323
+#define __NR_name_to_handle_at 324
+#define __NR_open_by_handle_at 325
+#define __NR_sync_file_range2 326
+#define __NR_perf_event_open 327
+#define __NR_rt_tgsigqueueinfo 328
+#define __NR_clock_adjtime 329
+#define __NR_prlimit64 330
+#define __NR_kcmp 331
+#define __NR_finit_module 332
+#define __NR_accept4 333
+#define __NR_sched_setattr 334
+#define __NR_sched_getattr 335
+#define __NR_renameat2 336
+#define __NR_seccomp 337
+#define __NR_getrandom 338
+#define __NR_memfd_create 339
+#define __NR_bpf 340
+#define __NR_execveat 341
+#define __NR_userfaultfd 342
+#define __NR_membarrier 343
+#define __NR_mlock2 344
+#define __NR_copy_file_range 345
+#define __NR_preadv2 346
+#define __NR_pwritev2 347
+#define __NR_pkey_mprotect 348
+#define __NR_pkey_alloc 349
+#define __NR_pkey_free 350
+#define __NR_statx 351
+#define __NR_rseq 352
+#define __NR_clock_gettime64 403
+#define __NR_clock_settime64 404
+#define __NR_clock_adjtime64 405
+#define __NR_clock_getres_time64 406
+#define __NR_clock_nanosleep_time64 407
+#define __NR_timer_gettime64 408
+#define __NR_timer_settime64 409
+#define __NR_timerfd_gettime64 410
+#define __NR_timerfd_settime64 411
+#define __NR_utimensat_time64 412
+#define __NR_pselect6_time64 413
+#define __NR_ppoll_time64 414
+#define __NR_io_pgetevents_time64 416
+#define __NR_recvmmsg_time64 417
+#define __NR_mq_timedsend_time64 418
+#define __NR_mq_timedreceive_time64 419
+#define __NR_semtimedop_time64 420
+#define __NR_rt_sigtimedwait_time64 421
+#define __NR_futex_time64 422
+#define __NR_sched_rr_get_interval_time64 423
+#define __NR_pidfd_send_signal 424
+#define __NR_io_uring_setup 425
+#define __NR_io_uring_enter 426
+#define __NR_io_uring_register 427
+#define __NR_open_tree 428
+#define __NR_move_mount 429
+#define __NR_fsopen 430
+#define __NR_fsconfig 431
+#define __NR_fsmount 432
+#define __NR_fspick 433
+#define __NR_pidfd_open 434
+#define __NR_clone3 435
+#define __NR_close_range 436
+#define __NR_openat2 437
+#define __NR_pidfd_getfd 438
+#define __NR_faccessat2 439
+#define __NR_process_madvise 440
+#define __NR_epoll_pwait2 441
+#define __NR_mount_setattr 442
+#define __NR_quotactl_fd 443
+#define __NR_landlock_create_ruleset 444
+#define __NR_landlock_add_rule 445
+#define __NR_landlock_restrict_self 446
+#define __NR_process_mrelease 448
+#define __NR_futex_waitv 449
+#define __NR_set_mempolicy_home_node 450
+#define __NR_cachestat 451
+#define __NR_fchmodat2 452
+#define __NR_map_shadow_stack 453
+#define __NR_futex_wake 454
+#define __NR_futex_wait 455
+#define __NR_futex_requeue 456
+#define __NR_statmount 457
+#define __NR_listmount 458
+#define __NR_lsm_get_self_attr 459
+#define __NR_lsm_set_self_attr 460
+#define __NR_lsm_list_modules 461
diff --git a/arch/xtensa/bits/user.h b/arch/xtensa/bits/user.h
new file mode 100644
index 000000000000..8ac7526f19e0
--- /dev/null
+++ b/arch/xtensa/bits/user.h
@@ -0,0 +1,4 @@
+#define ELF_NGREG 128
+#define ELF_NFPREG 18
+typedef unsigned long elf_greg_t, elf_gregset_t[ELF_NGREG];
+typedef unsigned int elf_fpreg_t, elf_fpregset_t[ELF_NFPREG];
diff --git a/arch/xtensa/crt_arch.h b/arch/xtensa/crt_arch.h
new file mode 100644
index 000000000000..1019c1860503
--- /dev/null
+++ b/arch/xtensa/crt_arch.h
@@ -0,0 +1,48 @@
+#ifdef __FDPIC__
+
+__asm__(
+".text \n"
+".global " START " \n"
+START ": \n"
+" .begin no-transform\n"
+" call0 1f\n"
+"2:\n"
+" .end no-transform\n"
+" .align 4\n"
+" .literal_position\n"
+"1:\n"
+" movi a15, 2b\n"
+" sub a15, a0, a15\n"
+
+" mov a12, a4\n"
+" mov a13, a5\n"
+" mov a14, a6\n"
+#ifndef SHARED
+" mov a2, a4\n"
+" movi a3, __ROFIXUP_LIST__\n"
+" add a3, a3, a15\n"
+" movi a4, __ROFIXUP_END__\n"
+" add a4, a4, a15\n"
+" movi a0, __fdpic_fixup\n"
+" add a0, a0, a15\n"
+" callx0 a0\n"
+" mov a11, a2\n"
+" s32i a15, a11, 12\n"
+#endif
+" addi a7, a1, -8\n"
+" s32i a12, a7, 0\n"
+" s32i a13, a7, 4\n"
+" mov a2, a1\n"
+" mov a3, a14\n"
+" movi a4, -16\n"
+" and a1, a7, a4\n"
+" movi a0, "START"_c\n"
+" add a0, a0, a15\n"
+" callx0 a0\n"
+);
+
+#ifndef SHARED
+#include "fdpic_crt.h"
+#endif
+
+#endif
diff --git a/arch/xtensa/kstat.h b/arch/xtensa/kstat.h
new file mode 100644
index 000000000000..9aeaf7e37296
--- /dev/null
+++ b/arch/xtensa/kstat.h
@@ -0,0 +1,18 @@
+struct kstat {
+ dev_t st_dev;
+ ino_t st_ino;
+ mode_t st_mode;
+ nlink_t st_nlink;
+ uid_t st_uid;
+ gid_t st_gid;
+ dev_t st_rdev;
+ off_t st_size;
+ blksize_t st_blksize;
+ blkcnt_t st_blocks;
+ long st_atime_sec;
+ long st_atime_nsec;
+ long st_mtime_sec;
+ long st_mtime_nsec;
+ long st_ctime_sec;
+ long st_ctime_nsec;
+};
diff --git a/arch/xtensa/pthread_arch.h b/arch/xtensa/pthread_arch.h
new file mode 100644
index 000000000000..a4bdd02863d6
--- /dev/null
+++ b/arch/xtensa/pthread_arch.h
@@ -0,0 +1,11 @@
+static inline uintptr_t __get_tp()
+{
+ uintptr_t tp;
+ __asm__ __volatile__ ("rur.threadptr %0" : "=a" (tp));
+ return tp;
+}
+
+#define TLS_ABOVE_TP
+#define GAP_ABOVE_TP 8
+
+#define MC_PC sc_pc
diff --git a/arch/xtensa/reloc.h b/arch/xtensa/reloc.h
new file mode 100644
index 000000000000..cd7a455a2d9c
--- /dev/null
+++ b/arch/xtensa/reloc.h
@@ -0,0 +1,32 @@
+#if __FDPIC__
+#define ABI_SUFFIX "-fdpic"
+#else
+#define ABI_SUFFIX ""
+#endif
+
+#define LDSO_ARCH "xtensa" ABI_SUFFIX
+
+#define TPOFF_K 0
+
+#define REL_PLT R_XTENSA_JMP_SLOT
+#define REL_GOT R_XTENSA_GLOB_DAT
+
+#if __FDPIC__
+#define REL_SYMBOLIC R_XTENSA_SYM32
+#define REL_TPOFF R_XTENSA_TLS_TPOFF
+#define REL_TLSDESC R_XTENSA_TLSDESC
+#define REL_FUNCDESC R_XTENSA_FUNCDESC
+#define REL_FUNCDESC_VAL R_XTENSA_FUNCDESC_VALUE
+
+#define DL_FDPIC 1
+#define DL_NOMMU_SUPPORT 1
+
+#define CRTJMP(pc,sp) do { \
+ register size_t a4 __asm__("a4") = ((size_t *)(sp))[-2]; \
+ __asm__ __volatile__( "mov a1, %1 ; jx %0" \
+ : : "r"(pc), "r"(sp), "r"(a4) : "memory" ); } while(0)
+
+#define GETFUNCSYM(fp, sym, got) __asm__ ( \
+ "movi %0, " #sym "@GOTOFFFUNCDESC ; add %0, %0, %1" \
+ : "=&a"(*fp) : "a"(got) : "memory" )
+#endif
diff --git a/arch/xtensa/syscall_arch.h b/arch/xtensa/syscall_arch.h
new file mode 100644
index 000000000000..63ee4e962556
--- /dev/null
+++ b/arch/xtensa/syscall_arch.h
@@ -0,0 +1,104 @@
+#define __SYSCALL_LL_E(x) \
+((union { long long ll; long l[2]; }){ .ll = x }).l[0], \
+((union { long long ll; long l[2]; }){ .ll = x }).l[1]
+#define __SYSCALL_LL_O(x) 0, __SYSCALL_LL_E((x))
+
+static inline long __syscall0(long n)
+{
+ register long a2 __asm__("a2") = n;
+
+ __asm__ __volatile__ ("syscall"
+ : "+&a"(a2)
+ :
+ : "memory");
+ return a2;
+}
+
+static inline long __syscall1(long n, long a)
+{
+ register long a2 __asm__("a2") = n;
+ register long a6 __asm__("a6") = a;
+
+ __asm__ __volatile__ ("syscall"
+ : "+&a"(a2)
+ : "a"(a6)
+ : "memory");
+ return a2;
+}
+
+static inline long __syscall2(long n, long a, long b)
+{
+ register long a2 __asm__("a2") = n;
+ register long a6 __asm__("a6") = a;
+ register long a3 __asm__("a3") = b;
+
+ __asm__ __volatile__ ("syscall"
+ : "+&a"(a2)
+ : "a"(a6), "a"(a3)
+ : "memory");
+ return a2;
+}
+
+static inline long __syscall3(long n, long a, long b, long c)
+{
+ register long a2 __asm__("a2") = n;
+ register long a6 __asm__("a6") = a;
+ register long a3 __asm__("a3") = b;
+ register long a4 __asm__("a4") = c;
+
+ __asm__ __volatile__ ("syscall"
+ : "+&a"(a2)
+ : "a"(a6), "a"(a3), "a"(a4)
+ : "memory");
+ return a2;
+}
+
+static inline long __syscall4(long n, long a, long b, long c, long d)
+{
+ register long a2 __asm__("a2") = n;
+ register long a6 __asm__("a6") = a;
+ register long a3 __asm__("a3") = b;
+ register long a4 __asm__("a4") = c;
+ register long a5 __asm__("a5") = d;
+
+ __asm__ __volatile__ ("syscall"
+ : "+&a"(a2)
+ : "a"(a6), "a"(a3), "a"(a4), "a"(a5)
+ : "memory");
+ return a2;
+}
+
+static inline long __syscall5(long n, long a, long b, long c, long d, long e)
+{
+ register long a2 __asm__("a2") = n;
+ register long a6 __asm__("a6") = a;
+ register long a3 __asm__("a3") = b;
+ register long a4 __asm__("a4") = c;
+ register long a5 __asm__("a5") = d;
+ register long a8 __asm__("a8") = e;
+
+ __asm__ __volatile__ ("syscall"
+ : "+&a"(a2)
+ : "a"(a6), "a"(a3), "a"(a4), "a"(a5), "a"(a8)
+ : "memory");
+ return a2;
+}
+
+static inline long __syscall6(long n, long a, long b, long c, long d, long e, long f)
+{
+ register long a2 __asm__("a2") = n;
+ register long a6 __asm__("a6") = a;
+ register long a3 __asm__("a3") = b;
+ register long a4 __asm__("a4") = c;
+ register long a5 __asm__("a5") = d;
+ register long a8 __asm__("a8") = e;
+ register long a9 __asm__("a9") = f;
+
+ __asm__ __volatile__ ("syscall"
+ : "+&a"(a2)
+ : "a"(a6), "a"(a3), "a"(a4), "a"(a5), "a"(a8), "a"(a9)
+ : "memory");
+ return a2;
+}
+
+#define SYSCALL_FADVISE_6_ARG
diff --git a/configure b/configure
index bc9fbe48cc44..898499ce77ba 100755
--- a/configure
+++ b/configure
@@ -340,6 +340,7 @@ riscv64*) ARCH=riscv64 ;;
riscv32*) ARCH=riscv32 ;;
sh[1-9bel-]*|sh|superh*) ARCH=sh ;;
s390x*) ARCH=s390x ;;
+xtensa*) ARCH=xtensa ;;
unknown) fail "$0: unable to detect target arch; try $0 --target=..." ;;
*) fail "$0: unknown or unsupported target \"$target\"" ;;
esac
@@ -756,6 +757,13 @@ SUBARCH=${SUBARCH}-fdpic
fi
fi
+if test "$ARCH" = "xtensa" ; then
+if trycppif __XTENSA_WINDOWED_ABI__ "$t" ; then
+fail "$0: error: compiler uses unsupported ABI by default"
+fi
+trycppif __FDPIC__ "$t" && SUBARCH=${SUBARCH}-fdpic
+fi
+
test "$SUBARCH" \
&& printf "configured for %s variant: %s\n" "$ARCH" "$ARCH$SUBARCH"
diff --git a/crt/xtensa/crti.S b/crt/xtensa/crti.S
new file mode 100644
index 000000000000..4d4f8f12f1bd
--- /dev/null
+++ b/crt/xtensa/crti.S
@@ -0,0 +1,21 @@
+.section .init
+.global _init
+.type _init, @function
+_init:
+ addi sp, sp, -16
+ s32i a0, sp, 0
+#ifdef __FDPIC__
+ s32i a12, sp, 4
+ mov a12, a11
+#endif
+
+.section .fini
+.global _fini
+.type _fini, @function
+_fini:
+ addi sp, sp, -16
+ s32i a0, sp, 0
+#ifdef __FDPIC__
+ s32i a12, sp, 4
+ mov a12, a11
+#endif
diff --git a/crt/xtensa/crtn.S b/crt/xtensa/crtn.S
new file mode 100644
index 000000000000..656edaa7f146
--- /dev/null
+++ b/crt/xtensa/crtn.S
@@ -0,0 +1,15 @@
+.section .init
+#ifdef __FDPIC__
+ l32i a12, sp, 4
+#endif
+ l32i a0, sp, 0
+ addi sp, sp, 16
+ ret
+
+.section .fini
+#ifdef __FDPIC__
+ l32i a12, sp, 4
+#endif
+ l32i a0, sp, 0
+ addi sp, sp, 16
+ ret
diff --git a/include/elf.h b/include/elf.h
index 3d5e13e4b6e5..fdd1e3163546 100644
--- a/include/elf.h
+++ b/include/elf.h
@@ -3406,6 +3406,80 @@ enum
#define R_LARCH_32_PCREL 99
#define R_LARCH_RELAX 100
+#define R_XTENSA_NONE 0
+#define R_XTENSA_32 1
+#define R_XTENSA_RTLD 2
+#define R_XTENSA_GLOB_DAT 3
+#define R_XTENSA_JMP_SLOT 4
+#define R_XTENSA_RELATIVE 5
+#define R_XTENSA_PLT 6
+#define R_XTENSA_OP0 8
+#define R_XTENSA_OP1 9
+#define R_XTENSA_OP2 10
+#define R_XTENSA_ASM_EXPAND 11
+#define R_XTENSA_ASM_SIMPLIFY 12
+#define R_XTENSA_32_PCREL 14
+#define R_XTENSA_GNU_VTINHERIT 15
+#define R_XTENSA_GNU_VTENTRY 16
+#define R_XTENSA_DIFF8 17
+#define R_XTENSA_DIFF16 18
+#define R_XTENSA_DIFF32 19
+#define R_XTENSA_SLOT0_OP 20
+#define R_XTENSA_SLOT1_OP 21
+#define R_XTENSA_SLOT2_OP 22
+#define R_XTENSA_SLOT3_OP 23
+#define R_XTENSA_SLOT4_OP 24
+#define R_XTENSA_SLOT5_OP 25
+#define R_XTENSA_SLOT6_OP 26
+#define R_XTENSA_SLOT7_OP 27
+#define R_XTENSA_SLOT8_OP 28
+#define R_XTENSA_SLOT9_OP 29
+#define R_XTENSA_SLOT10_OP 30
+#define R_XTENSA_SLOT11_OP 31
+#define R_XTENSA_SLOT12_OP 32
+#define R_XTENSA_SLOT13_OP 33
+#define R_XTENSA_SLOT14_OP 34
+#define R_XTENSA_SLOT0_ALT 35
+#define R_XTENSA_SLOT1_ALT 36
+#define R_XTENSA_SLOT2_ALT 37
+#define R_XTENSA_SLOT3_ALT 38
+#define R_XTENSA_SLOT4_ALT 39
+#define R_XTENSA_SLOT5_ALT 40
+#define R_XTENSA_SLOT6_ALT 41
+#define R_XTENSA_SLOT7_ALT 42
+#define R_XTENSA_SLOT8_ALT 43
+#define R_XTENSA_SLOT9_ALT 44
+#define R_XTENSA_SLOT10_ALT 45
+#define R_XTENSA_SLOT11_ALT 46
+#define R_XTENSA_SLOT12_ALT 47
+#define R_XTENSA_SLOT13_ALT 48
+#define R_XTENSA_SLOT14_ALT 49
+#define R_XTENSA_TLSDESC_FN 50
+#define R_XTENSA_TLSDESC_ARG 51
+#define R_XTENSA_TLS_DTPOFF 52
+#define R_XTENSA_TLS_TPOFF 53
+#define R_XTENSA_TLS_FUNC 54
+#define R_XTENSA_TLS_ARG 55
+#define R_XTENSA_TLS_CALL 56
+#define R_XTENSA_PDIFF8 57
+#define R_XTENSA_PDIFF16 58
+#define R_XTENSA_PDIFF32 59
+#define R_XTENSA_NDIFF8 60
+#define R_XTENSA_NDIFF16 61
+#define R_XTENSA_NDIFF32 62
+#define R_XTENSA_SYM32 63
+#define R_XTENSA_GOT 64
+#define R_XTENSA_GOTOFF 65
+#define R_XTENSA_GOTFUNCDESC 66
+#define R_XTENSA_GOTOFFFUNCDESC 67
+#define R_XTENSA_FUNCDESC 68
+#define R_XTENSA_FUNCDESC_VALUE 69
+#define R_XTENSA_TLS_GOTTPOFF 70
+#define R_XTENSA_GOTTLSDESC 71
+#define R_XTENSA_TLSDESC 72
+
+#define R_XTENSA_NUM 77
+
#ifdef __cplusplus
}
#endif
diff --git a/src/internal/xtensa/syscall.s b/src/internal/xtensa/syscall.s
new file mode 100644
index 000000000000..3112bc3890bc
--- /dev/null
+++ b/src/internal/xtensa/syscall.s
@@ -0,0 +1,14 @@
+.global __syscall
+.hidden __syscall
+.type __syscall,@function
+.align 4
+__syscall:
+ mov a8, a3
+ mov a3, a4
+ mov a4, a5
+ mov a5, a6
+ mov a6, a8
+ mov a8, a7
+ l32i a9, a1, 0
+ syscall
+ ret
diff --git a/src/ldso/xtensa/dlsym.s b/src/ldso/xtensa/dlsym.s
new file mode 100644
index 000000000000..0b5e7256451b
--- /dev/null
+++ b/src/ldso/xtensa/dlsym.s
@@ -0,0 +1,6 @@
+.global dlsym
+.hidden __dlsym
+.type dlsym,@function
+dlsym:
+ mov a4, a0
+ j __dlsym
diff --git a/src/ldso/xtensa/dlsym_time64.S b/src/ldso/xtensa/dlsym_time64.S
new file mode 100644
index 000000000000..bb2e70408f0e
--- /dev/null
+++ b/src/ldso/xtensa/dlsym_time64.S
@@ -0,0 +1,3 @@
+#define __dlsym __dlsym_redir_time64
+#define dlsym __dlsym_time64
+#include "dlsym.s"
diff --git a/src/ldso/xtensa/tlsdesc.s b/src/ldso/xtensa/tlsdesc.s
new file mode 100644
index 000000000000..4dcb78c9e92f
--- /dev/null
+++ b/src/ldso/xtensa/tlsdesc.s
@@ -0,0 +1,25 @@
+.global __tlsdesc_static
+.hidden __tlsdesc_static
+.type __tlsdesc_static,@function
+.align 4
+__tlsdesc_static:
+ l32i a2, a2, 4
+ rur.threadptr a3
+ add a2, a2, a3
+ ret
+
+.global __tlsdesc_dynamic
+.hidden __tlsdesc_dynamic
+.type __tlsdesc_dynamic,@function
+.align 4
+__tlsdesc_dynamic:
+ l32i a2, a2, 4 # a2 = &{modidx, off}
+ rur.threadptr a3
+ addi a3, a3, -4
+ l32i a3, a3, 0 # a3 = dtv
+ l32i a4, a2, 0 # a4 = modidx
+ addx4 a3, a4, a3
+ l32i a3, a3, 0 # a3 = dtv[modidx]
+ l32i a2, a2, 4
+ add a2, a2, a3 # a2 = dtv[modidx] + off
+ ret
diff --git a/src/process/xtensa/vfork.s b/src/process/xtensa/vfork.s
new file mode 100644
index 000000000000..44408d356f12
--- /dev/null
+++ b/src/process/xtensa/vfork.s
@@ -0,0 +1,13 @@
+.global vfork
+.type vfork,@function
+vfork:
+ movi a2, 116 # __NR_clone
+ movi a3, 0
+ movi a6, 0x4111 # CLONE_VM | CLONE_VFORK | SIGCHLD
+ syscall
+
+.hidden __syscall_ret
+ movi a9, __syscall_ret@GOT
+ add a9, a9, a11
+ l32i a9, a9, 0
+ jx a9
diff --git a/src/setjmp/xtensa/longjmp.s b/src/setjmp/xtensa/longjmp.s
new file mode 100644
index 000000000000..c650126c5354
--- /dev/null
+++ b/src/setjmp/xtensa/longjmp.s
@@ -0,0 +1,18 @@
+.global _longjmp
+.global longjmp
+.type _longjmp,@function
+.type longjmp,@function
+.align 4
+_longjmp:
+longjmp:
+ l32i a0, a2, 0
+ l32i a1, a2, 4
+ l32i a12, a2, 8
+ l32i a13, a2, 12
+ l32i a14, a2, 16
+ l32i a15, a2, 20
+
+ movi a2, 1
+ movnez a2, a3, a3
+
+ ret
diff --git a/src/setjmp/xtensa/setjmp.s b/src/setjmp/xtensa/setjmp.s
new file mode 100644
index 000000000000..4d229a86f83a
--- /dev/null
+++ b/src/setjmp/xtensa/setjmp.s
@@ -0,0 +1,21 @@
+.global ___setjmp
+.hidden ___setjmp
+.global __setjmp
+.global _setjmp
+.global setjmp
+.type __setjmp,@function
+.type _setjmp,@function
+.type setjmp,@function
+.align 4
+___setjmp:
+__setjmp:
+_setjmp:
+setjmp:
+ s32i a0, a2, 0
+ s32i a1, a2, 4
+ s32i a12, a2, 8
+ s32i a13, a2, 12
+ s32i a14, a2, 16
+ s32i a15, a2, 20
+ movi a2, 0
+ ret
diff --git a/src/signal/xtensa/restore.s b/src/signal/xtensa/restore.s
new file mode 100644
index 000000000000..e03e0fb798fb
--- /dev/null
+++ b/src/signal/xtensa/restore.s
@@ -0,0 +1,10 @@
+.global __restore
+.global __restore_rt
+.type __restore,@function
+.type __restore_rt,@function
+.space 1
+.align 4
+__restore:
+__restore_rt:
+ movi a2, 225 # SYS_rt_sigreturn
+ syscall
diff --git a/src/signal/xtensa/sigsetjmp.s b/src/signal/xtensa/sigsetjmp.s
new file mode 100644
index 000000000000..796564134886
--- /dev/null
+++ b/src/signal/xtensa/sigsetjmp.s
@@ -0,0 +1,22 @@
+.global sigsetjmp
+.global __sigsetjmp
+.type sigsetjmp,@function
+.type __sigsetjmp,@function
+.align 4
+sigsetjmp:
+__sigsetjmp:
+ bnez a3, 1f
+.hidden ___setjmp
+ j ___setjmp
+1:
+ s32i a0, a2, 24
+ s32i a12, a2, 36
+ mov a12, a2
+ call0 ___setjmp
+ mov a3, a2
+ mov a2, a12
+ l32i a12, a2, 36
+ l32i a0, a2, 24
+
+.hidden __sigsetjmp_tail
+ j __sigsetjmp_tail
diff --git a/src/thread/xtensa/__set_thread_area.c b/src/thread/xtensa/__set_thread_area.c
new file mode 100644
index 000000000000..56be098215c2
--- /dev/null
+++ b/src/thread/xtensa/__set_thread_area.c
@@ -0,0 +1,9 @@
+#include "pthread_impl.h"
+#include "libc.h"
+#include <elf.h>
+
+int __set_thread_area(void *p)
+{
+ __asm__ __volatile__ ("wur.threadptr %0" :: "r"(p) : "memory");
+ return 0;
+}
diff --git a/src/thread/xtensa/__unmapself.s b/src/thread/xtensa/__unmapself.s
new file mode 100644
index 000000000000..8f007e84ec43
--- /dev/null
+++ b/src/thread/xtensa/__unmapself.s
@@ -0,0 +1,9 @@
+.global __unmapself
+.type __unmapself,@function
+.align 4
+__unmapself:
+ mov a6, a2
+ movi a2, 81 # SYS_munmap
+ syscall
+ movi a2, 118 # SYS_exit
+ syscall
diff --git a/src/thread/xtensa/clone.S b/src/thread/xtensa/clone.S
new file mode 100644
index 000000000000..f7400f5c7566
--- /dev/null
+++ b/src/thread/xtensa/clone.S
@@ -0,0 +1,42 @@
+# __clone(func, stack, flags, arg, ptid, tls, ctid)
+# a2, a3, a4, a5, a6, a7, [sp]
+
+# syscall(SYS_clone, flags, stack, ptid, tls, ctid)
+# a2, a6, a3, a4, a5, a8
+
+.global __clone
+.type __clone,@function
+.align 4
+__clone:
+ # align stack and save func,arg
+ srli a3, a3, 4
+ slli a3, a3, 4
+ addi a3, a3, -16
+ s32i a2, a3, 0
+ s32i a5, a3, 4
+
+ # syscall
+ mov a2, a4
+ mov a4, a6
+ mov a6, a2
+ mov a5, a7
+ l32i a8, a1, 0
+ movi a2, 116 # SYS_clone
+ syscall
+
+ beqz a2, 1f
+ # parent
+ ret
+
+ # child
+1:
+ l32i a0, a1, 0
+ l32i a2, a1, 4
+#ifdef __FDPIC__
+ l32i a11, a0, 4
+ l32i a0, a0, 0
+#endif
+ callx0 a0
+ mov a6, a2
+ movi a2, 118 # SYS_exit
+ syscall
diff --git a/src/thread/xtensa/syscall_cp.s b/src/thread/xtensa/syscall_cp.s
new file mode 100644
index 000000000000..55575e359b87
--- /dev/null
+++ b/src/thread/xtensa/syscall_cp.s
@@ -0,0 +1,34 @@
+# __syscall_cp_asm(&self->cancel, nr, u, v, w, x, y, z)
+# a2 a3 a4 a5 a6 a7 [sp] [sp+4]
+
+# syscall(nr, u, v, w, x, y, z)
+# a2 a6 a3 a4 a5 a8 a9
+
+.global __cp_begin
+.hidden __cp_begin
+.global __cp_end
+.hidden __cp_end
+.global __cp_cancel
+.hidden __cp_cancel
+.hidden __cancel
+.global __syscall_cp_asm
+.hidden __syscall_cp_asm
+.type __syscall_cp_asm,@function
+.align 4
+__syscall_cp_asm:
+__cp_begin:
+ l32i a2, a2, 0
+ bnez a2, __cp_cancel
+ mov a2, a4
+ mov a4, a6
+ mov a6, a2
+ mov a2, a3
+ mov a3, a5
+ mov a5, a7
+ l32i a8, a1, 0
+ l32i a9, a1, 4
+ syscall
+__cp_end:
+ ret
+__cp_cancel:
+ j __cancel
--
2.39.2
^ permalink raw reply [flat|nested] 15+ messages in thread
* [musl] [RFC v2 2/2] WIP xtensa bits
2024-03-28 20:03 [musl] [RFC v2 0/2] xtensa FDPIC port Max Filippov
2024-03-28 20:03 ` [musl] [RFC v2 1/2] xtensa: add port Max Filippov
@ 2024-03-28 20:03 ` Max Filippov
2024-03-28 23:01 ` [musl] [RFC v2 0/2] xtensa FDPIC port Rich Felker
2 siblings, 0 replies; 15+ messages in thread
From: Max Filippov @ 2024-03-28 20:03 UTC (permalink / raw)
To: musl; +Cc: Rich Felker, Max Filippov
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
---
ldso/dlstart.c | 3 +++
ldso/dynlink.c | 8 +++++++-
2 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/ldso/dlstart.c b/ldso/dlstart.c
index 259f5e18eecf..a1c257860e96 100644
--- a/ldso/dlstart.c
+++ b/ldso/dlstart.c
@@ -96,6 +96,9 @@ hidden void _dlstart_c(size_t *sp, size_t *dynv)
*rel_addr = rel[2] + segs[j].addr - segs[j].p_vaddr + val;
}
}
+#ifdef __xtensa__
+ ((unsigned long *)dyn[DT_PLTGOT])[3] = segs[0].addr - segs[0].p_vaddr;
+#endif
#else
/* If the dynamic linker is invoked as a command, its load
* address is not available in the aux vector. Instead, compute
diff --git a/ldso/dynlink.c b/ldso/dynlink.c
index 324aa85919f0..9be79c8f8227 100644
--- a/ldso/dynlink.c
+++ b/ldso/dynlink.c
@@ -402,7 +402,11 @@ static void do_relocs(struct dso *dso, size_t *rel, size_t rel_size, size_t stri
reuse_addends = 1;
skip_relative = 1;
}
-
+#ifdef __xtensa__
+ else {
+ dso->got[3] = dso->loadmap->segs[0].addr - dso->loadmap->segs[0].p_vaddr;
+ }
+#endif
for (; rel_size; rel+=stride, rel_size-=stride*sizeof(size_t)) {
if (skip_relative && IS_RELATIVE(rel[1], dso->syms)) continue;
type = R_TYPE(rel[1]);
@@ -1422,6 +1426,7 @@ static void reloc_all(struct dso *p)
if (!DL_FDPIC)
do_relr_relocs(p, laddr(p, dyn[DT_RELR]), dyn[DT_RELRSZ]);
+#if 0
if (head != &ldso && p->relro_start != p->relro_end) {
long ret = __syscall(SYS_mprotect, laddr(p, p->relro_start),
p->relro_end-p->relro_start, PROT_READ);
@@ -1431,6 +1436,7 @@ static void reloc_all(struct dso *p)
if (runtime) longjmp(*rtld_fail, 1);
}
}
+#endif
p->relocated = 1;
}
--
2.39.2
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [musl] [RFC v2 0/2] xtensa FDPIC port
2024-03-28 20:03 [musl] [RFC v2 0/2] xtensa FDPIC port Max Filippov
2024-03-28 20:03 ` [musl] [RFC v2 1/2] xtensa: add port Max Filippov
2024-03-28 20:03 ` [musl] [RFC v2 2/2] WIP xtensa bits Max Filippov
@ 2024-03-28 23:01 ` Rich Felker
2024-03-29 0:48 ` Max Filippov
2 siblings, 1 reply; 15+ messages in thread
From: Rich Felker @ 2024-03-28 23:01 UTC (permalink / raw)
To: Max Filippov; +Cc: musl
On Thu, Mar 28, 2024 at 01:03:17PM -0700, Max Filippov wrote:
> Hello,
>
> this is the second RFC version of the xtensa FDPIC port for musl.
> There are two patches: the first adds the port and will likely not
> change in the future versions. The second adds two bits of
> xtensa-specific GOT initialization for compatibility with the current
> binutils/gcc and will go away once binutils and gcc are changed to do
> local references differently.
>
> The following binutils and gcc branches can be used to build the
> xtensa-linux-muslfdpic toolchain:
>
> https://github.com/jcmvbkbc/binutils-gdb-xtensa xtensa-2.42-fdpic-musl
> https://github.com/jcmvbkbc/gcc-xtensa xtensa-14-9655-fdpic-musl
>
> I've tested this version with libc-test using QEMU linux-user and full
> system emulation. The results in the linux-user are the following:
>
> FAIL src/functional/dlopen.exe [status 1]
> FAIL src/functional/pthread_robust-static.exe [timed out]
> FAIL src/functional/pthread_robust.exe [timed out]
> FAIL src/functional/strptime-static.exe [status 1]
> FAIL src/functional/strptime.exe [status 1]
> FAIL src/math/acoshl.exe [status 1]
> FAIL src/math/asinhl.exe [status 1]
> FAIL src/math/erfcl.exe [status 1]
> FAIL src/math/fma.exe [status 1]
> FAIL src/math/fmal.exe [status 1]
> FAIL src/math/lgammal.exe [status 1]
> FAIL src/math/tgammal.exe [status 1]
> FAIL src/regression/pthread-robust-detach-static.exe [status 1]
> FAIL src/regression/pthread-robust-detach.exe [status 1]
>
> functional/dlopen fails with the
> src/functional/dlopen.c:39: dlsym main failed: (null)
> There's no failure in the dlsym call, but the pointers don't match.
Is this something related to canonical function descriptors? Is it
musl's fault or a bug in the tooling? I suspect the latter.
> functional/ and regression/ pthread-related failures are expected
> because the robust list functions are not available in the linux-user
> mode. These particular tests pass in full system emulation.
>
> math tests fail with ULP differences.
>
> I have also added the following changes to the abi tests to fix the
> build:
>
> diff --git a/src/api/sys_sem.c b/src/api/sys_sem.c
> index a473cad0a2aa..bd4df9a4fe70 100644
> --- a/src/api/sys_sem.c
> +++ b/src/api/sys_sem.c
> @@ -18,7 +18,11 @@ C(SETALL)
> {
> struct semid_ds x;
> F(struct ipc_perm,sem_perm)
> +#ifdef __xtensa__
> +F(unsigned long, sem_nsems)
> +#else
> F(unsigned short, sem_nsems)
> +#endif
This is invalid and indicates an error in the port; the whole point of
the tests is to catch that so it can be fixed. POSIX requires
sem_nsems to have type unsigned short. I believe Linux has this wrong
on some (most? all?) archs and we just fix it by replacing the rest
with padding.
Rich
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [musl] [RFC v2 0/2] xtensa FDPIC port
2024-03-28 23:01 ` [musl] [RFC v2 0/2] xtensa FDPIC port Rich Felker
@ 2024-03-29 0:48 ` Max Filippov
2024-03-29 1:48 ` Rich Felker
0 siblings, 1 reply; 15+ messages in thread
From: Max Filippov @ 2024-03-29 0:48 UTC (permalink / raw)
To: Rich Felker; +Cc: musl
On Thu, Mar 28, 2024 at 4:00 PM Rich Felker <dalias@libc.org> wrote:
> On Thu, Mar 28, 2024 at 01:03:17PM -0700, Max Filippov wrote:
> > functional/dlopen fails with the
> > src/functional/dlopen.c:39: dlsym main failed: (null)
> > There's no failure in the dlsym call, but the pointers don't match.
>
> Is this something related to canonical function descriptors? Is it
> musl's fault or a bug in the tooling? I suspect the latter.
Yes, dlsym() returns the pointer into def.dso->funcdescs,
but (void *)main returns the pointer to the canonical function
descriptor. I understand that the linker must use the
R_XTENSA_FUNCDESC relocation for the locally defined
global symbol instead of the .rofixup entries.
> > functional/ and regression/ pthread-related failures are expected
> > because the robust list functions are not available in the linux-user
> > mode. These particular tests pass in full system emulation.
> >
> > math tests fail with ULP differences.
> >
> > I have also added the following changes to the abi tests to fix the
> > build:
> >
> > diff --git a/src/api/sys_sem.c b/src/api/sys_sem.c
> > index a473cad0a2aa..bd4df9a4fe70 100644
> > --- a/src/api/sys_sem.c
> > +++ b/src/api/sys_sem.c
> > @@ -18,7 +18,11 @@ C(SETALL)
> > {
> > struct semid_ds x;
> > F(struct ipc_perm,sem_perm)
> > +#ifdef __xtensa__
> > +F(unsigned long, sem_nsems)
> > +#else
> > F(unsigned short, sem_nsems)
> > +#endif
>
> This is invalid and indicates an error in the port; the whole point of
> the tests is to catch that so it can be fixed. POSIX requires
I must have misinterpreted that. Will fix it.
> sem_nsems to have type unsigned short. I believe Linux has this wrong
> on some (most? all?) archs and we just fix it by replacing the rest
> with padding.
--
Thanks.
-- Max
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [musl] [RFC v2 0/2] xtensa FDPIC port
2024-03-29 0:48 ` Max Filippov
@ 2024-03-29 1:48 ` Rich Felker
2024-04-03 2:30 ` Max Filippov
0 siblings, 1 reply; 15+ messages in thread
From: Rich Felker @ 2024-03-29 1:48 UTC (permalink / raw)
To: Max Filippov; +Cc: musl
On Thu, Mar 28, 2024 at 05:48:50PM -0700, Max Filippov wrote:
> On Thu, Mar 28, 2024 at 4:00 PM Rich Felker <dalias@libc.org> wrote:
> > On Thu, Mar 28, 2024 at 01:03:17PM -0700, Max Filippov wrote:
> > > functional/dlopen fails with the
> > > src/functional/dlopen.c:39: dlsym main failed: (null)
> > > There's no failure in the dlsym call, but the pointers don't match.
> >
> > Is this something related to canonical function descriptors? Is it
> > musl's fault or a bug in the tooling? I suspect the latter.
>
> Yes, dlsym() returns the pointer into def.dso->funcdescs,
> but (void *)main returns the pointer to the canonical function
> descriptor. I understand that the linker must use the
> R_XTENSA_FUNCDESC relocation for the locally defined
> global symbol instead of the .rofixup entries.
If the xtensa FDPIC ABI is going to be that the linker makes canonical
function descriptors, I think that's workable, but the dynamic linker
would need a way to find and usee them. I'm not sure how that would
work.
The simple (but probably less efficient) way is to copy what SH did
and have the dynamic linker always be responsible for them (load
descriptor address from GOT).
Rich
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [musl] [RFC v2 0/2] xtensa FDPIC port
2024-03-29 1:48 ` Rich Felker
@ 2024-04-03 2:30 ` Max Filippov
2024-04-03 20:55 ` Rich Felker
0 siblings, 1 reply; 15+ messages in thread
From: Max Filippov @ 2024-04-03 2:30 UTC (permalink / raw)
To: Rich Felker; +Cc: musl
On Thu, Mar 28, 2024 at 6:48 PM Rich Felker <dalias@libc.org> wrote:
> On Thu, Mar 28, 2024 at 05:48:50PM -0700, Max Filippov wrote:
> > On Thu, Mar 28, 2024 at 4:00 PM Rich Felker <dalias@libc.org> wrote:
> > > On Thu, Mar 28, 2024 at 01:03:17PM -0700, Max Filippov wrote:
> > > > functional/dlopen fails with the
> > > > src/functional/dlopen.c:39: dlsym main failed: (null)
> > > > There's no failure in the dlsym call, but the pointers don't match.
> > >
> > > Is this something related to canonical function descriptors? Is it
> > > musl's fault or a bug in the tooling? I suspect the latter.
> >
> > Yes, dlsym() returns the pointer into def.dso->funcdescs,
> > but (void *)main returns the pointer to the canonical function
> > descriptor. I understand that the linker must use the
> > R_XTENSA_FUNCDESC relocation for the locally defined
> > global symbol instead of the .rofixup entries.
>
> If the xtensa FDPIC ABI is going to be that the linker makes canonical
> function descriptors, I think that's workable, but the dynamic linker
> would need a way to find and usee them. I'm not sure how that would
> work.
>
> The simple (but probably less efficient) way is to copy what SH did
> and have the dynamic linker always be responsible for them (load
> descriptor address from GOT).
I've built and tested SH FDPIC toolchain, it fails this test in exactly
the same way: pointer loaded directly does not match the pointer
returned by dlsym().
--
Thanks.
-- Max
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [musl] [RFC v2 0/2] xtensa FDPIC port
2024-04-03 2:30 ` Max Filippov
@ 2024-04-03 20:55 ` Rich Felker
2024-04-03 21:45 ` Rich Felker
2024-04-04 8:56 ` Max Filippov
0 siblings, 2 replies; 15+ messages in thread
From: Rich Felker @ 2024-04-03 20:55 UTC (permalink / raw)
To: Max Filippov; +Cc: musl
On Tue, Apr 02, 2024 at 07:30:57PM -0700, Max Filippov wrote:
> On Thu, Mar 28, 2024 at 6:48 PM Rich Felker <dalias@libc.org> wrote:
> > On Thu, Mar 28, 2024 at 05:48:50PM -0700, Max Filippov wrote:
> > > On Thu, Mar 28, 2024 at 4:00 PM Rich Felker <dalias@libc.org> wrote:
> > > > On Thu, Mar 28, 2024 at 01:03:17PM -0700, Max Filippov wrote:
> > > > > functional/dlopen fails with the
> > > > > src/functional/dlopen.c:39: dlsym main failed: (null)
> > > > > There's no failure in the dlsym call, but the pointers don't match.
> > > >
> > > > Is this something related to canonical function descriptors? Is it
> > > > musl's fault or a bug in the tooling? I suspect the latter.
> > >
> > > Yes, dlsym() returns the pointer into def.dso->funcdescs,
> > > but (void *)main returns the pointer to the canonical function
> > > descriptor. I understand that the linker must use the
> > > R_XTENSA_FUNCDESC relocation for the locally defined
> > > global symbol instead of the .rofixup entries.
> >
> > If the xtensa FDPIC ABI is going to be that the linker makes canonical
> > function descriptors, I think that's workable, but the dynamic linker
> > would need a way to find and usee them. I'm not sure how that would
> > work.
> >
> > The simple (but probably less efficient) way is to copy what SH did
> > and have the dynamic linker always be responsible for them (load
> > descriptor address from GOT).
>
> I've built and tested SH FDPIC toolchain, it fails this test in exactly
> the same way: pointer loaded directly does not match the pointer
> returned by dlsym().
Yes, I've been able to reproduce this and it's a clear bug. There does
not seem to be any way the dynamic linker could find these GOTFUNCDESC
slots to use them as a canonical address for the function, and
moreover, they're not even unique; there would be one per library.
The code path for legitimize_pic_address in sh.c that emits
GOTFUNCDESC has the wrong logic. A simple fix would be just making
that path never be taken, but I'm not sure if that would break use of
GOTFUNCDESC for pure-call purposes.
The condition should probably be something like: if it's just used for
a call (if this is even needed; pure call is probably handled
elsewhere) or if the function is static or hidden, use GOTFUNCDESC;
otherwise, use GOT.
I might try patching it and see what happens.
Rich
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [musl] [RFC v2 0/2] xtensa FDPIC port
2024-04-03 20:55 ` Rich Felker
@ 2024-04-03 21:45 ` Rich Felker
2024-04-04 8:44 ` Max Filippov
2024-04-04 8:56 ` Max Filippov
1 sibling, 1 reply; 15+ messages in thread
From: Rich Felker @ 2024-04-03 21:45 UTC (permalink / raw)
To: Max Filippov; +Cc: musl
[-- Attachment #1: Type: text/plain, Size: 2660 bytes --]
On Wed, Apr 03, 2024 at 04:55:56PM -0400, Rich Felker wrote:
> On Tue, Apr 02, 2024 at 07:30:57PM -0700, Max Filippov wrote:
> > On Thu, Mar 28, 2024 at 6:48 PM Rich Felker <dalias@libc.org> wrote:
> > > On Thu, Mar 28, 2024 at 05:48:50PM -0700, Max Filippov wrote:
> > > > On Thu, Mar 28, 2024 at 4:00 PM Rich Felker <dalias@libc.org> wrote:
> > > > > On Thu, Mar 28, 2024 at 01:03:17PM -0700, Max Filippov wrote:
> > > > > > functional/dlopen fails with the
> > > > > > src/functional/dlopen.c:39: dlsym main failed: (null)
> > > > > > There's no failure in the dlsym call, but the pointers don't match.
> > > > >
> > > > > Is this something related to canonical function descriptors? Is it
> > > > > musl's fault or a bug in the tooling? I suspect the latter.
> > > >
> > > > Yes, dlsym() returns the pointer into def.dso->funcdescs,
> > > > but (void *)main returns the pointer to the canonical function
> > > > descriptor. I understand that the linker must use the
> > > > R_XTENSA_FUNCDESC relocation for the locally defined
> > > > global symbol instead of the .rofixup entries.
> > >
> > > If the xtensa FDPIC ABI is going to be that the linker makes canonical
> > > function descriptors, I think that's workable, but the dynamic linker
> > > would need a way to find and usee them. I'm not sure how that would
> > > work.
> > >
> > > The simple (but probably less efficient) way is to copy what SH did
> > > and have the dynamic linker always be responsible for them (load
> > > descriptor address from GOT).
> >
> > I've built and tested SH FDPIC toolchain, it fails this test in exactly
> > the same way: pointer loaded directly does not match the pointer
> > returned by dlsym().
>
> Yes, I've been able to reproduce this and it's a clear bug. There does
> not seem to be any way the dynamic linker could find these GOTFUNCDESC
> slots to use them as a canonical address for the function, and
> moreover, they're not even unique; there would be one per library.
>
> The code path for legitimize_pic_address in sh.c that emits
> GOTFUNCDESC has the wrong logic. A simple fix would be just making
> that path never be taken, but I'm not sure if that would break use of
> GOTFUNCDESC for pure-call purposes.
>
> The condition should probably be something like: if it's just used for
> a call (if this is even needed; pure call is probably handled
> elsewhere) or if the function is static or hidden, use GOTFUNCDESC;
> otherwise, use GOT.
>
> I might try patching it and see what happens.
Attached patch seems to fix it. I'm not sure if this is the most
idiomatic way to write the predicate in gcc sources, but it should be
correct.
Rich
[-- Attachment #2: fdpic-patch.diff --]
[-- Type: text/plain, Size: 1008 bytes --]
--- gcc-11.4.0/gcc/config/sh/sh.c.orig 2024-04-04 05:52:42.125373614 +0900
+++ gcc-11.4.0/gcc/config/sh/sh.c 2024-04-04 06:22:11.737423661 +0900
@@ -9143,7 +9143,8 @@
reg = gen_reg_rtx (Pmode);
if (TARGET_FDPIC
- && GET_CODE (orig) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (orig))
+ && GET_CODE (orig) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (orig)
+ && (!TREE_PUBLIC(SYMBOL_REF_DECL(orig)) || DECL_VISIBILITY (SYMBOL_REF_DECL(orig)) == VISIBILITY_HIDDEN))
{
/* Weak functions may be NULL which doesn't work with
GOTOFFFUNCDESC because the runtime offset is not known. */
@@ -9169,7 +9170,8 @@
if (reg == NULL_RTX)
reg = gen_reg_rtx (Pmode);
- if (TARGET_FDPIC && SYMBOL_REF_FUNCTION_P (orig))
+ if (TARGET_FDPIC && SYMBOL_REF_FUNCTION_P (orig)
+ && (!TREE_PUBLIC(SYMBOL_REF_DECL(orig)) || DECL_VISIBILITY (SYMBOL_REF_DECL(orig)) == VISIBILITY_HIDDEN))
emit_insn (gen_symGOTFUNCDESC2reg (reg, orig));
else
emit_insn (gen_symGOT2reg (reg, orig));
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [musl] [RFC v2 0/2] xtensa FDPIC port
2024-04-03 21:45 ` Rich Felker
@ 2024-04-04 8:44 ` Max Filippov
2024-04-04 14:01 ` Rich Felker
0 siblings, 1 reply; 15+ messages in thread
From: Max Filippov @ 2024-04-04 8:44 UTC (permalink / raw)
To: Rich Felker; +Cc: musl
On Wed, Apr 3, 2024 at 2:45 PM Rich Felker <dalias@libc.org> wrote:
>
> On Wed, Apr 03, 2024 at 04:55:56PM -0400, Rich Felker wrote:
> > On Tue, Apr 02, 2024 at 07:30:57PM -0700, Max Filippov wrote:
> > > On Thu, Mar 28, 2024 at 6:48 PM Rich Felker <dalias@libc.org> wrote:
> > > > On Thu, Mar 28, 2024 at 05:48:50PM -0700, Max Filippov wrote:
> > > > > On Thu, Mar 28, 2024 at 4:00 PM Rich Felker <dalias@libc.org> wrote:
> > > > > > On Thu, Mar 28, 2024 at 01:03:17PM -0700, Max Filippov wrote:
> > > > > > > functional/dlopen fails with the
> > > > > > > src/functional/dlopen.c:39: dlsym main failed: (null)
> > > > > > > There's no failure in the dlsym call, but the pointers don't match.
> > > > > >
> > > > > > Is this something related to canonical function descriptors? Is it
> > > > > > musl's fault or a bug in the tooling? I suspect the latter.
> > > > >
> > > > > Yes, dlsym() returns the pointer into def.dso->funcdescs,
> > > > > but (void *)main returns the pointer to the canonical function
> > > > > descriptor. I understand that the linker must use the
> > > > > R_XTENSA_FUNCDESC relocation for the locally defined
> > > > > global symbol instead of the .rofixup entries.
> > > >
> > > > If the xtensa FDPIC ABI is going to be that the linker makes canonical
> > > > function descriptors, I think that's workable, but the dynamic linker
> > > > would need a way to find and usee them. I'm not sure how that would
> > > > work.
> > > >
> > > > The simple (but probably less efficient) way is to copy what SH did
> > > > and have the dynamic linker always be responsible for them (load
> > > > descriptor address from GOT).
> > >
> > > I've built and tested SH FDPIC toolchain, it fails this test in exactly
> > > the same way: pointer loaded directly does not match the pointer
> > > returned by dlsym().
> >
> > Yes, I've been able to reproduce this and it's a clear bug. There does
> > not seem to be any way the dynamic linker could find these GOTFUNCDESC
> > slots to use them as a canonical address for the function, and
> > moreover, they're not even unique; there would be one per library.
> >
> > The code path for legitimize_pic_address in sh.c that emits
> > GOTFUNCDESC has the wrong logic. A simple fix would be just making
> > that path never be taken, but I'm not sure if that would break use of
> > GOTFUNCDESC for pure-call purposes.
> >
> > The condition should probably be something like: if it's just used for
> > a call (if this is even needed; pure call is probably handled
> > elsewhere) or if the function is static or hidden, use GOTFUNCDESC;
> > otherwise, use GOT.
> >
> > I might try patching it and see what happens.
>
> Attached patch seems to fix it. I'm not sure if this is the most
> idiomatic way to write the predicate in gcc sources, but it should be
> correct.
It's not what I observe. On my side it doesn't change the result of the
dlopen test, and it also breaks building of all statically-linked tests.
There are no relocations against the symbol 'main' neither in the test
built with the original gcc nor in the test built with the patched one.
dlopen.o built with the original gcc had R_SH_GOTOFFFUNCDESC
relocation against the symbol 'main', dlopen.o built with the patched
gcc has R_SH_GOTOFF instead. The code generated with the patched
gcc:
if (dlsym(g, "main") != (void*)main) {
28c: 50 d1 mov.l 3d0 <main+0x3d0>,r1 ! 0 <main>
28e: 8c 31 add r8,r1
290: 12 61 mov.l @r1,r1
292: 13 62 mov r1,r2
294: 8f 91 mov.w 3b6 <main+0x3b6>,r1 ! 1e0
296: ec 31 add r14,r1
298: 23 65 mov r2,r5
29a: 1c 54 mov.l @(48,r1),r4
29c: 83 6c mov r8,r12
29e: 4d d6 mov.l 3d4 <main+0x3d4>,r6 ! 130
2a0: 03 06 bsrf r6
2a2: 09 00 nop
2a4: 03 61 mov r0,r1
2a6: 4c d2 mov.l 3d8 <main+0x3d8>,r2 ! 0 <main>
2a8: 8c 32 add r8,r2
2aa: 20 31 cmp/eq r2,r1
2ac: 27 89 bt 2fe <main+0x2fe>
...
3d8: 00 00 .word 0x0000
3d8: R_SH_GOTOFF main
doesn't look right to me at all. Using R_SH_GOTOFF
for the symbol in text doesn't make sense. Using R_SH_GOT
(AFAIU that's what you meant it to be) doesn't make sense
to me as well, as the value stored in the GOT would be the
address of the main() entry point, not of its descriptor.
I believe that gcc need to generate R_SH_GOTFUNCDESC
instead of R_SH_GOTOFFFUNCDESC for this test to work
correctly, and that the linker need to put R_SH_FUNCDESC
relocation against that GOT entry, so that the dynamic linker
could put there the address of the function descriptor associated
with the symbol.
--
Thanks.
-- Max
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [musl] [RFC v2 0/2] xtensa FDPIC port
2024-04-03 20:55 ` Rich Felker
2024-04-03 21:45 ` Rich Felker
@ 2024-04-04 8:56 ` Max Filippov
1 sibling, 0 replies; 15+ messages in thread
From: Max Filippov @ 2024-04-04 8:56 UTC (permalink / raw)
To: Rich Felker; +Cc: musl
On Wed, Apr 3, 2024 at 1:55 PM Rich Felker <dalias@libc.org> wrote:
> On Tue, Apr 02, 2024 at 07:30:57PM -0700, Max Filippov wrote:
> > On Thu, Mar 28, 2024 at 6:48 PM Rich Felker <dalias@libc.org> wrote:
> > > On Thu, Mar 28, 2024 at 05:48:50PM -0700, Max Filippov wrote:
> > > > On Thu, Mar 28, 2024 at 4:00 PM Rich Felker <dalias@libc.org> wrote:
> > > > > On Thu, Mar 28, 2024 at 01:03:17PM -0700, Max Filippov wrote:
> > > > > > functional/dlopen fails with the
> > > > > > src/functional/dlopen.c:39: dlsym main failed: (null)
> > > > > > There's no failure in the dlsym call, but the pointers don't match.
> > > > >
> > > > > Is this something related to canonical function descriptors? Is it
> > > > > musl's fault or a bug in the tooling? I suspect the latter.
> > > >
> > > > Yes, dlsym() returns the pointer into def.dso->funcdescs,
> > > > but (void *)main returns the pointer to the canonical function
> > > > descriptor. I understand that the linker must use the
> > > > R_XTENSA_FUNCDESC relocation for the locally defined
> > > > global symbol instead of the .rofixup entries.
> > >
> > > If the xtensa FDPIC ABI is going to be that the linker makes canonical
> > > function descriptors, I think that's workable, but the dynamic linker
> > > would need a way to find and usee them. I'm not sure how that would
> > > work.
> > >
> > > The simple (but probably less efficient) way is to copy what SH did
> > > and have the dynamic linker always be responsible for them (load
> > > descriptor address from GOT).
> >
> > I've built and tested SH FDPIC toolchain, it fails this test in exactly
> > the same way: pointer loaded directly does not match the pointer
> > returned by dlsym().
>
> Yes, I've been able to reproduce this and it's a clear bug. There does
> not seem to be any way the dynamic linker could find these GOTFUNCDESC
> slots to use them as a canonical address for the function, and
I agree with that. It seems that it suggests that the SH FDPIC ABI document
section "Function Addresses" needs at least a clarification regarding the
"non-overridable functions".
> moreover, they're not even unique; there would be one per library.
--
Thanks.
-- Max
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [musl] [RFC v2 0/2] xtensa FDPIC port
2024-04-04 8:44 ` Max Filippov
@ 2024-04-04 14:01 ` Rich Felker
2024-04-04 15:00 ` Rich Felker
0 siblings, 1 reply; 15+ messages in thread
From: Rich Felker @ 2024-04-04 14:01 UTC (permalink / raw)
To: Max Filippov; +Cc: musl
On Thu, Apr 04, 2024 at 01:44:13AM -0700, Max Filippov wrote:
> On Wed, Apr 3, 2024 at 2:45 PM Rich Felker <dalias@libc.org> wrote:
> >
> > On Wed, Apr 03, 2024 at 04:55:56PM -0400, Rich Felker wrote:
> > > On Tue, Apr 02, 2024 at 07:30:57PM -0700, Max Filippov wrote:
> > > > On Thu, Mar 28, 2024 at 6:48 PM Rich Felker <dalias@libc.org> wrote:
> > > > > On Thu, Mar 28, 2024 at 05:48:50PM -0700, Max Filippov wrote:
> > > > > > On Thu, Mar 28, 2024 at 4:00 PM Rich Felker <dalias@libc.org> wrote:
> > > > > > > On Thu, Mar 28, 2024 at 01:03:17PM -0700, Max Filippov wrote:
> > > > > > > > functional/dlopen fails with the
> > > > > > > > src/functional/dlopen.c:39: dlsym main failed: (null)
> > > > > > > > There's no failure in the dlsym call, but the pointers don't match.
> > > > > > >
> > > > > > > Is this something related to canonical function descriptors? Is it
> > > > > > > musl's fault or a bug in the tooling? I suspect the latter.
> > > > > >
> > > > > > Yes, dlsym() returns the pointer into def.dso->funcdescs,
> > > > > > but (void *)main returns the pointer to the canonical function
> > > > > > descriptor. I understand that the linker must use the
> > > > > > R_XTENSA_FUNCDESC relocation for the locally defined
> > > > > > global symbol instead of the .rofixup entries.
> > > > >
> > > > > If the xtensa FDPIC ABI is going to be that the linker makes canonical
> > > > > function descriptors, I think that's workable, but the dynamic linker
> > > > > would need a way to find and usee them. I'm not sure how that would
> > > > > work.
> > > > >
> > > > > The simple (but probably less efficient) way is to copy what SH did
> > > > > and have the dynamic linker always be responsible for them (load
> > > > > descriptor address from GOT).
> > > >
> > > > I've built and tested SH FDPIC toolchain, it fails this test in exactly
> > > > the same way: pointer loaded directly does not match the pointer
> > > > returned by dlsym().
> > >
> > > Yes, I've been able to reproduce this and it's a clear bug. There does
> > > not seem to be any way the dynamic linker could find these GOTFUNCDESC
> > > slots to use them as a canonical address for the function, and
> > > moreover, they're not even unique; there would be one per library.
> > >
> > > The code path for legitimize_pic_address in sh.c that emits
> > > GOTFUNCDESC has the wrong logic. A simple fix would be just making
> > > that path never be taken, but I'm not sure if that would break use of
> > > GOTFUNCDESC for pure-call purposes.
> > >
> > > The condition should probably be something like: if it's just used for
> > > a call (if this is even needed; pure call is probably handled
> > > elsewhere) or if the function is static or hidden, use GOTFUNCDESC;
> > > otherwise, use GOT.
> > >
> > > I might try patching it and see what happens.
> >
> > Attached patch seems to fix it. I'm not sure if this is the most
> > idiomatic way to write the predicate in gcc sources, but it should be
> > correct.
>
> It's not what I observe. On my side it doesn't change the result of the
> dlopen test, and it also breaks building of all statically-linked tests.
>
> There are no relocations against the symbol 'main' neither in the test
> built with the original gcc nor in the test built with the patched one.
> dlopen.o built with the original gcc had R_SH_GOTOFFFUNCDESC
> relocation against the symbol 'main', dlopen.o built with the patched
> gcc has R_SH_GOTOFF instead. The code generated with the patched
> gcc:
>
> if (dlsym(g, "main") != (void*)main) {
> 28c: 50 d1 mov.l 3d0 <main+0x3d0>,r1 ! 0 <main>
> 28e: 8c 31 add r8,r1
> 290: 12 61 mov.l @r1,r1
> 292: 13 62 mov r1,r2
> 294: 8f 91 mov.w 3b6 <main+0x3b6>,r1 ! 1e0
> 296: ec 31 add r14,r1
> 298: 23 65 mov r2,r5
> 29a: 1c 54 mov.l @(48,r1),r4
> 29c: 83 6c mov r8,r12
> 29e: 4d d6 mov.l 3d4 <main+0x3d4>,r6 ! 130
> 2a0: 03 06 bsrf r6
> 2a2: 09 00 nop
> 2a4: 03 61 mov r0,r1
> 2a6: 4c d2 mov.l 3d8 <main+0x3d8>,r2 ! 0 <main>
> 2a8: 8c 32 add r8,r2
> 2aa: 20 31 cmp/eq r2,r1
> 2ac: 27 89 bt 2fe <main+0x2fe>
> ....
> 3d8: 00 00 .word 0x0000
> 3d8: R_SH_GOTOFF main
>
> doesn't look right to me at all. Using R_SH_GOTOFF
> for the symbol in text doesn't make sense. Using R_SH_GOT
> (AFAIU that's what you meant it to be) doesn't make sense
> to me as well, as the value stored in the GOT would be the
> address of the main() entry point, not of its descriptor.
>
> I believe that gcc need to generate R_SH_GOTFUNCDESC
> instead of R_SH_GOTOFFFUNCDESC for this test to work
> correctly, and that the linker need to put R_SH_FUNCDESC
> relocation against that GOT entry, so that the dynamic linker
> could put there the address of the function descriptor associated
> with the symbol.
Indeed I messed this up. Ignore that patch. You're right that use of
R_SH_GOTOFFFUNCDESC is wrong -- it's "Used for the FDPIC-relative
offset to the function descriptor itself", which is never a constant
except for static/hidden functions or when static linking.
However, you can test switching it to R_SH_GOTFUNCDESC just by using
-fPIC, and when you link, you still get the same problem, because the
linker is breaking it by binding at ld-time. So there are at least two
bugs in play here.
Rich
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [musl] [RFC v2 0/2] xtensa FDPIC port
2024-04-04 14:01 ` Rich Felker
@ 2024-04-04 15:00 ` Rich Felker
2024-04-08 14:41 ` Rich Felker
0 siblings, 1 reply; 15+ messages in thread
From: Rich Felker @ 2024-04-04 15:00 UTC (permalink / raw)
To: Max Filippov; +Cc: musl
On Thu, Apr 04, 2024 at 10:01:35AM -0400, Rich Felker wrote:
> On Thu, Apr 04, 2024 at 01:44:13AM -0700, Max Filippov wrote:
> > On Wed, Apr 3, 2024 at 2:45 PM Rich Felker <dalias@libc.org> wrote:
> > >
> > > On Wed, Apr 03, 2024 at 04:55:56PM -0400, Rich Felker wrote:
> > > > On Tue, Apr 02, 2024 at 07:30:57PM -0700, Max Filippov wrote:
> > > > > On Thu, Mar 28, 2024 at 6:48 PM Rich Felker <dalias@libc.org> wrote:
> > > > > > On Thu, Mar 28, 2024 at 05:48:50PM -0700, Max Filippov wrote:
> > > > > > > On Thu, Mar 28, 2024 at 4:00 PM Rich Felker <dalias@libc.org> wrote:
> > > > > > > > On Thu, Mar 28, 2024 at 01:03:17PM -0700, Max Filippov wrote:
> > > > > > > > > functional/dlopen fails with the
> > > > > > > > > src/functional/dlopen.c:39: dlsym main failed: (null)
> > > > > > > > > There's no failure in the dlsym call, but the pointers don't match.
> > > > > > > >
> > > > > > > > Is this something related to canonical function descriptors? Is it
> > > > > > > > musl's fault or a bug in the tooling? I suspect the latter.
> > > > > > >
> > > > > > > Yes, dlsym() returns the pointer into def.dso->funcdescs,
> > > > > > > but (void *)main returns the pointer to the canonical function
> > > > > > > descriptor. I understand that the linker must use the
> > > > > > > R_XTENSA_FUNCDESC relocation for the locally defined
> > > > > > > global symbol instead of the .rofixup entries.
> > > > > >
> > > > > > If the xtensa FDPIC ABI is going to be that the linker makes canonical
> > > > > > function descriptors, I think that's workable, but the dynamic linker
> > > > > > would need a way to find and usee them. I'm not sure how that would
> > > > > > work.
> > > > > >
> > > > > > The simple (but probably less efficient) way is to copy what SH did
> > > > > > and have the dynamic linker always be responsible for them (load
> > > > > > descriptor address from GOT).
> > > > >
> > > > > I've built and tested SH FDPIC toolchain, it fails this test in exactly
> > > > > the same way: pointer loaded directly does not match the pointer
> > > > > returned by dlsym().
> > > >
> > > > Yes, I've been able to reproduce this and it's a clear bug. There does
> > > > not seem to be any way the dynamic linker could find these GOTFUNCDESC
> > > > slots to use them as a canonical address for the function, and
> > > > moreover, they're not even unique; there would be one per library.
> > > >
> > > > The code path for legitimize_pic_address in sh.c that emits
> > > > GOTFUNCDESC has the wrong logic. A simple fix would be just making
> > > > that path never be taken, but I'm not sure if that would break use of
> > > > GOTFUNCDESC for pure-call purposes.
> > > >
> > > > The condition should probably be something like: if it's just used for
> > > > a call (if this is even needed; pure call is probably handled
> > > > elsewhere) or if the function is static or hidden, use GOTFUNCDESC;
> > > > otherwise, use GOT.
> > > >
> > > > I might try patching it and see what happens.
> > >
> > > Attached patch seems to fix it. I'm not sure if this is the most
> > > idiomatic way to write the predicate in gcc sources, but it should be
> > > correct.
> >
> > It's not what I observe. On my side it doesn't change the result of the
> > dlopen test, and it also breaks building of all statically-linked tests.
> >
> > There are no relocations against the symbol 'main' neither in the test
> > built with the original gcc nor in the test built with the patched one.
> > dlopen.o built with the original gcc had R_SH_GOTOFFFUNCDESC
> > relocation against the symbol 'main', dlopen.o built with the patched
> > gcc has R_SH_GOTOFF instead. The code generated with the patched
> > gcc:
> >
> > if (dlsym(g, "main") != (void*)main) {
> > 28c: 50 d1 mov.l 3d0 <main+0x3d0>,r1 ! 0 <main>
> > 28e: 8c 31 add r8,r1
> > 290: 12 61 mov.l @r1,r1
> > 292: 13 62 mov r1,r2
> > 294: 8f 91 mov.w 3b6 <main+0x3b6>,r1 ! 1e0
> > 296: ec 31 add r14,r1
> > 298: 23 65 mov r2,r5
> > 29a: 1c 54 mov.l @(48,r1),r4
> > 29c: 83 6c mov r8,r12
> > 29e: 4d d6 mov.l 3d4 <main+0x3d4>,r6 ! 130
> > 2a0: 03 06 bsrf r6
> > 2a2: 09 00 nop
> > 2a4: 03 61 mov r0,r1
> > 2a6: 4c d2 mov.l 3d8 <main+0x3d8>,r2 ! 0 <main>
> > 2a8: 8c 32 add r8,r2
> > 2aa: 20 31 cmp/eq r2,r1
> > 2ac: 27 89 bt 2fe <main+0x2fe>
> > ....
> > 3d8: 00 00 .word 0x0000
> > 3d8: R_SH_GOTOFF main
> >
> > doesn't look right to me at all. Using R_SH_GOTOFF
> > for the symbol in text doesn't make sense. Using R_SH_GOT
> > (AFAIU that's what you meant it to be) doesn't make sense
> > to me as well, as the value stored in the GOT would be the
> > address of the main() entry point, not of its descriptor.
> >
> > I believe that gcc need to generate R_SH_GOTFUNCDESC
> > instead of R_SH_GOTOFFFUNCDESC for this test to work
> > correctly, and that the linker need to put R_SH_FUNCDESC
> > relocation against that GOT entry, so that the dynamic linker
> > could put there the address of the function descriptor associated
> > with the symbol.
>
> Indeed I messed this up. Ignore that patch. You're right that use of
> R_SH_GOTOFFFUNCDESC is wrong -- it's "Used for the FDPIC-relative
> offset to the function descriptor itself", which is never a constant
> except for static/hidden functions or when static linking.
>
> However, you can test switching it to R_SH_GOTFUNCDESC just by using
> -fPIC, and when you link, you still get the same problem, because the
> linker is breaking it by binding at ld-time. So there are at least two
> bugs in play here.
The offending logic in bfd linker is SYMBOL_FUNCDESC_LOCAL macro in
bfd/elf32-sh.c. SYMBOL_REFERENCES_LOCAL is not sufficient to conclude
that the FUNCDESC can be expanded at ld time. I'm not sure how to
write it yet, but the condition is:
!dynamic_linking || (SYMBOL_REFERENCES_LOCAL && !visible_outside_dso)
The existing elf_hash_table (INFO)->dynamic_sections_created clause
covers !dynamic_linking mostly except that it will give the wrong
result for static PIE (which is largely gratuitous for FDPIC, but
should still be expected to work).
Rich
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [musl] [RFC v2 0/2] xtensa FDPIC port
2024-04-04 15:00 ` Rich Felker
@ 2024-04-08 14:41 ` Rich Felker
2024-04-08 15:32 ` Rich Felker
0 siblings, 1 reply; 15+ messages in thread
From: Rich Felker @ 2024-04-08 14:41 UTC (permalink / raw)
To: Max Filippov; +Cc: musl
[-- Attachment #1: Type: text/plain, Size: 7395 bytes --]
On Thu, Apr 04, 2024 at 11:00:54AM -0400, Rich Felker wrote:
> On Thu, Apr 04, 2024 at 10:01:35AM -0400, Rich Felker wrote:
> > On Thu, Apr 04, 2024 at 01:44:13AM -0700, Max Filippov wrote:
> > > On Wed, Apr 3, 2024 at 2:45 PM Rich Felker <dalias@libc.org> wrote:
> > > >
> > > > On Wed, Apr 03, 2024 at 04:55:56PM -0400, Rich Felker wrote:
> > > > > On Tue, Apr 02, 2024 at 07:30:57PM -0700, Max Filippov wrote:
> > > > > > On Thu, Mar 28, 2024 at 6:48 PM Rich Felker <dalias@libc.org> wrote:
> > > > > > > On Thu, Mar 28, 2024 at 05:48:50PM -0700, Max Filippov wrote:
> > > > > > > > On Thu, Mar 28, 2024 at 4:00 PM Rich Felker <dalias@libc.org> wrote:
> > > > > > > > > On Thu, Mar 28, 2024 at 01:03:17PM -0700, Max Filippov wrote:
> > > > > > > > > > functional/dlopen fails with the
> > > > > > > > > > src/functional/dlopen.c:39: dlsym main failed: (null)
> > > > > > > > > > There's no failure in the dlsym call, but the pointers don't match.
> > > > > > > > >
> > > > > > > > > Is this something related to canonical function descriptors? Is it
> > > > > > > > > musl's fault or a bug in the tooling? I suspect the latter.
> > > > > > > >
> > > > > > > > Yes, dlsym() returns the pointer into def.dso->funcdescs,
> > > > > > > > but (void *)main returns the pointer to the canonical function
> > > > > > > > descriptor. I understand that the linker must use the
> > > > > > > > R_XTENSA_FUNCDESC relocation for the locally defined
> > > > > > > > global symbol instead of the .rofixup entries.
> > > > > > >
> > > > > > > If the xtensa FDPIC ABI is going to be that the linker makes canonical
> > > > > > > function descriptors, I think that's workable, but the dynamic linker
> > > > > > > would need a way to find and usee them. I'm not sure how that would
> > > > > > > work.
> > > > > > >
> > > > > > > The simple (but probably less efficient) way is to copy what SH did
> > > > > > > and have the dynamic linker always be responsible for them (load
> > > > > > > descriptor address from GOT).
> > > > > >
> > > > > > I've built and tested SH FDPIC toolchain, it fails this test in exactly
> > > > > > the same way: pointer loaded directly does not match the pointer
> > > > > > returned by dlsym().
> > > > >
> > > > > Yes, I've been able to reproduce this and it's a clear bug. There does
> > > > > not seem to be any way the dynamic linker could find these GOTFUNCDESC
> > > > > slots to use them as a canonical address for the function, and
> > > > > moreover, they're not even unique; there would be one per library.
> > > > >
> > > > > The code path for legitimize_pic_address in sh.c that emits
> > > > > GOTFUNCDESC has the wrong logic. A simple fix would be just making
> > > > > that path never be taken, but I'm not sure if that would break use of
> > > > > GOTFUNCDESC for pure-call purposes.
> > > > >
> > > > > The condition should probably be something like: if it's just used for
> > > > > a call (if this is even needed; pure call is probably handled
> > > > > elsewhere) or if the function is static or hidden, use GOTFUNCDESC;
> > > > > otherwise, use GOT.
> > > > >
> > > > > I might try patching it and see what happens.
> > > >
> > > > Attached patch seems to fix it. I'm not sure if this is the most
> > > > idiomatic way to write the predicate in gcc sources, but it should be
> > > > correct.
> > >
> > > It's not what I observe. On my side it doesn't change the result of the
> > > dlopen test, and it also breaks building of all statically-linked tests.
> > >
> > > There are no relocations against the symbol 'main' neither in the test
> > > built with the original gcc nor in the test built with the patched one.
> > > dlopen.o built with the original gcc had R_SH_GOTOFFFUNCDESC
> > > relocation against the symbol 'main', dlopen.o built with the patched
> > > gcc has R_SH_GOTOFF instead. The code generated with the patched
> > > gcc:
> > >
> > > if (dlsym(g, "main") != (void*)main) {
> > > 28c: 50 d1 mov.l 3d0 <main+0x3d0>,r1 ! 0 <main>
> > > 28e: 8c 31 add r8,r1
> > > 290: 12 61 mov.l @r1,r1
> > > 292: 13 62 mov r1,r2
> > > 294: 8f 91 mov.w 3b6 <main+0x3b6>,r1 ! 1e0
> > > 296: ec 31 add r14,r1
> > > 298: 23 65 mov r2,r5
> > > 29a: 1c 54 mov.l @(48,r1),r4
> > > 29c: 83 6c mov r8,r12
> > > 29e: 4d d6 mov.l 3d4 <main+0x3d4>,r6 ! 130
> > > 2a0: 03 06 bsrf r6
> > > 2a2: 09 00 nop
> > > 2a4: 03 61 mov r0,r1
> > > 2a6: 4c d2 mov.l 3d8 <main+0x3d8>,r2 ! 0 <main>
> > > 2a8: 8c 32 add r8,r2
> > > 2aa: 20 31 cmp/eq r2,r1
> > > 2ac: 27 89 bt 2fe <main+0x2fe>
> > > ....
> > > 3d8: 00 00 .word 0x0000
> > > 3d8: R_SH_GOTOFF main
> > >
> > > doesn't look right to me at all. Using R_SH_GOTOFF
> > > for the symbol in text doesn't make sense. Using R_SH_GOT
> > > (AFAIU that's what you meant it to be) doesn't make sense
> > > to me as well, as the value stored in the GOT would be the
> > > address of the main() entry point, not of its descriptor.
> > >
> > > I believe that gcc need to generate R_SH_GOTFUNCDESC
> > > instead of R_SH_GOTOFFFUNCDESC for this test to work
> > > correctly, and that the linker need to put R_SH_FUNCDESC
> > > relocation against that GOT entry, so that the dynamic linker
> > > could put there the address of the function descriptor associated
> > > with the symbol.
> >
> > Indeed I messed this up. Ignore that patch. You're right that use of
> > R_SH_GOTOFFFUNCDESC is wrong -- it's "Used for the FDPIC-relative
> > offset to the function descriptor itself", which is never a constant
> > except for static/hidden functions or when static linking.
> >
> > However, you can test switching it to R_SH_GOTFUNCDESC just by using
> > -fPIC, and when you link, you still get the same problem, because the
> > linker is breaking it by binding at ld-time. So there are at least two
> > bugs in play here.
>
> The offending logic in bfd linker is SYMBOL_FUNCDESC_LOCAL macro in
> bfd/elf32-sh.c. SYMBOL_REFERENCES_LOCAL is not sufficient to conclude
> that the FUNCDESC can be expanded at ld time. I'm not sure how to
> write it yet, but the condition is:
>
> !dynamic_linking || (SYMBOL_REFERENCES_LOCAL && !visible_outside_dso)
>
> The existing elf_hash_table (INFO)->dynamic_sections_created clause
> covers !dynamic_linking mostly except that it will give the wrong
> result for static PIE (which is largely gratuitous for FDPIC, but
> should still be expected to work).
I have what seem to be working patches for the linker and gcc.
The bfd link code for sh/fdpic was doing two things wrong: using the
condition "locally defined" rather than "externally visible" for
deciding how to handle function descriptors, and "optimizing" out the
symbol reference even once that was fixed. The patch corrects both
behaviors.
GCC was wrongly using GOTOFFFUNCDESC rather than GOTFUNCDESC for
locally defined but externally visible symbols. This could be worked
around with -fPIC, but the patch fixes it. (Probably should do
internal too, but nobody uses internal visibility because it's
underspecified and broken.)
Following the same logic changes should fix the problem on xtensa.
Rich
[-- Attachment #2: bfd-sh.diff --]
[-- Type: text/plain, Size: 1418 bytes --]
--- binutils-2.33.1/bfd/elf32-sh.c.orig 2024-04-04 23:11:28.739136261 +0900
+++ binutils-2.33.1/bfd/elf32-sh.c 2024-04-08 23:14:24.496915074 +0900
@@ -61,7 +61,7 @@
not. If the symbol is protected, we want the local address, but
its function descriptor must be assigned by the dynamic linker. */
#define SYMBOL_FUNCDESC_LOCAL(INFO, H) \
- (SYMBOL_REFERENCES_LOCAL (INFO, H) \
+ (!(H) || (H)->dynindx < 0 || (H)->forced_local \
|| ! elf_hash_table (INFO)->dynamic_sections_created)
\f
#define SH_PARTIAL32 TRUE
@@ -4405,20 +4405,6 @@
/* Undefined weak symbol which will not be dynamically
resolved later; leave it at zero. */
goto funcdesc_leave_zero;
- else if (SYMBOL_CALLS_LOCAL (info, h)
- && ! SYMBOL_FUNCDESC_LOCAL (info, h))
- {
- /* If the symbol needs a non-local function descriptor
- but binds locally (i.e., its visibility is
- protected), emit a dynamic relocation decayed to
- section+offset. This is an optimization; the dynamic
- linker would resolve our function descriptor request
- to our copy of the function anyway. */
- dynindx = elf_section_data (h->root.u.def.section
- ->output_section)->dynindx;
- relocation += h->root.u.def.section->output_offset
- + h->root.u.def.value;
- }
else if (! SYMBOL_FUNCDESC_LOCAL (info, h))
{
/* If the symbol is dynamic and there will be dynamic
[-- Attachment #3: gcc-sh.diff --]
[-- Type: text/plain, Size: 585 bytes --]
--- gcc-11.4.0/gcc/config/sh/sh.c.orig 2024-04-04 05:52:42.125373614 +0900
+++ gcc-11.4.0/gcc/config/sh/sh.c 2024-04-04 22:54:01.875106654 +0900
@@ -9147,7 +9147,7 @@
{
/* Weak functions may be NULL which doesn't work with
GOTOFFFUNCDESC because the runtime offset is not known. */
- if (SYMBOL_REF_WEAK (orig))
+ if (SYMBOL_REF_WEAK (orig) || (TREE_PUBLIC(SYMBOL_REF_DECL(orig)) && DECL_VISIBILITY (SYMBOL_REF_DECL(orig)) != VISIBILITY_HIDDEN))
emit_insn (gen_symGOTFUNCDESC2reg (reg, orig));
else
emit_insn (gen_symGOTOFFFUNCDESC2reg (reg, orig));
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [musl] [RFC v2 0/2] xtensa FDPIC port
2024-04-08 14:41 ` Rich Felker
@ 2024-04-08 15:32 ` Rich Felker
0 siblings, 0 replies; 15+ messages in thread
From: Rich Felker @ 2024-04-08 15:32 UTC (permalink / raw)
To: Max Filippov; +Cc: musl
On Mon, Apr 08, 2024 at 10:41:07AM -0400, Rich Felker wrote:
> On Thu, Apr 04, 2024 at 11:00:54AM -0400, Rich Felker wrote:
> > On Thu, Apr 04, 2024 at 10:01:35AM -0400, Rich Felker wrote:
> > > On Thu, Apr 04, 2024 at 01:44:13AM -0700, Max Filippov wrote:
> > > > On Wed, Apr 3, 2024 at 2:45 PM Rich Felker <dalias@libc.org> wrote:
> > > > >
> > > > > On Wed, Apr 03, 2024 at 04:55:56PM -0400, Rich Felker wrote:
> > > > > > On Tue, Apr 02, 2024 at 07:30:57PM -0700, Max Filippov wrote:
> > > > > > > On Thu, Mar 28, 2024 at 6:48 PM Rich Felker <dalias@libc.org> wrote:
> > > > > > > > On Thu, Mar 28, 2024 at 05:48:50PM -0700, Max Filippov wrote:
> > > > > > > > > On Thu, Mar 28, 2024 at 4:00 PM Rich Felker <dalias@libc.org> wrote:
> > > > > > > > > > On Thu, Mar 28, 2024 at 01:03:17PM -0700, Max Filippov wrote:
> > > > > > > > > > > functional/dlopen fails with the
> > > > > > > > > > > src/functional/dlopen.c:39: dlsym main failed: (null)
> > > > > > > > > > > There's no failure in the dlsym call, but the pointers don't match.
> > > > > > > > > >
> > > > > > > > > > Is this something related to canonical function descriptors? Is it
> > > > > > > > > > musl's fault or a bug in the tooling? I suspect the latter.
> > > > > > > > >
> > > > > > > > > Yes, dlsym() returns the pointer into def.dso->funcdescs,
> > > > > > > > > but (void *)main returns the pointer to the canonical function
> > > > > > > > > descriptor. I understand that the linker must use the
> > > > > > > > > R_XTENSA_FUNCDESC relocation for the locally defined
> > > > > > > > > global symbol instead of the .rofixup entries.
> > > > > > > >
> > > > > > > > If the xtensa FDPIC ABI is going to be that the linker makes canonical
> > > > > > > > function descriptors, I think that's workable, but the dynamic linker
> > > > > > > > would need a way to find and usee them. I'm not sure how that would
> > > > > > > > work.
> > > > > > > >
> > > > > > > > The simple (but probably less efficient) way is to copy what SH did
> > > > > > > > and have the dynamic linker always be responsible for them (load
> > > > > > > > descriptor address from GOT).
> > > > > > >
> > > > > > > I've built and tested SH FDPIC toolchain, it fails this test in exactly
> > > > > > > the same way: pointer loaded directly does not match the pointer
> > > > > > > returned by dlsym().
> > > > > >
> > > > > > Yes, I've been able to reproduce this and it's a clear bug. There does
> > > > > > not seem to be any way the dynamic linker could find these GOTFUNCDESC
> > > > > > slots to use them as a canonical address for the function, and
> > > > > > moreover, they're not even unique; there would be one per library.
> > > > > >
> > > > > > The code path for legitimize_pic_address in sh.c that emits
> > > > > > GOTFUNCDESC has the wrong logic. A simple fix would be just making
> > > > > > that path never be taken, but I'm not sure if that would break use of
> > > > > > GOTFUNCDESC for pure-call purposes.
> > > > > >
> > > > > > The condition should probably be something like: if it's just used for
> > > > > > a call (if this is even needed; pure call is probably handled
> > > > > > elsewhere) or if the function is static or hidden, use GOTFUNCDESC;
> > > > > > otherwise, use GOT.
> > > > > >
> > > > > > I might try patching it and see what happens.
> > > > >
> > > > > Attached patch seems to fix it. I'm not sure if this is the most
> > > > > idiomatic way to write the predicate in gcc sources, but it should be
> > > > > correct.
> > > >
> > > > It's not what I observe. On my side it doesn't change the result of the
> > > > dlopen test, and it also breaks building of all statically-linked tests.
> > > >
> > > > There are no relocations against the symbol 'main' neither in the test
> > > > built with the original gcc nor in the test built with the patched one.
> > > > dlopen.o built with the original gcc had R_SH_GOTOFFFUNCDESC
> > > > relocation against the symbol 'main', dlopen.o built with the patched
> > > > gcc has R_SH_GOTOFF instead. The code generated with the patched
> > > > gcc:
> > > >
> > > > if (dlsym(g, "main") != (void*)main) {
> > > > 28c: 50 d1 mov.l 3d0 <main+0x3d0>,r1 ! 0 <main>
> > > > 28e: 8c 31 add r8,r1
> > > > 290: 12 61 mov.l @r1,r1
> > > > 292: 13 62 mov r1,r2
> > > > 294: 8f 91 mov.w 3b6 <main+0x3b6>,r1 ! 1e0
> > > > 296: ec 31 add r14,r1
> > > > 298: 23 65 mov r2,r5
> > > > 29a: 1c 54 mov.l @(48,r1),r4
> > > > 29c: 83 6c mov r8,r12
> > > > 29e: 4d d6 mov.l 3d4 <main+0x3d4>,r6 ! 130
> > > > 2a0: 03 06 bsrf r6
> > > > 2a2: 09 00 nop
> > > > 2a4: 03 61 mov r0,r1
> > > > 2a6: 4c d2 mov.l 3d8 <main+0x3d8>,r2 ! 0 <main>
> > > > 2a8: 8c 32 add r8,r2
> > > > 2aa: 20 31 cmp/eq r2,r1
> > > > 2ac: 27 89 bt 2fe <main+0x2fe>
> > > > ....
> > > > 3d8: 00 00 .word 0x0000
> > > > 3d8: R_SH_GOTOFF main
> > > >
> > > > doesn't look right to me at all. Using R_SH_GOTOFF
> > > > for the symbol in text doesn't make sense. Using R_SH_GOT
> > > > (AFAIU that's what you meant it to be) doesn't make sense
> > > > to me as well, as the value stored in the GOT would be the
> > > > address of the main() entry point, not of its descriptor.
> > > >
> > > > I believe that gcc need to generate R_SH_GOTFUNCDESC
> > > > instead of R_SH_GOTOFFFUNCDESC for this test to work
> > > > correctly, and that the linker need to put R_SH_FUNCDESC
> > > > relocation against that GOT entry, so that the dynamic linker
> > > > could put there the address of the function descriptor associated
> > > > with the symbol.
> > >
> > > Indeed I messed this up. Ignore that patch. You're right that use of
> > > R_SH_GOTOFFFUNCDESC is wrong -- it's "Used for the FDPIC-relative
> > > offset to the function descriptor itself", which is never a constant
> > > except for static/hidden functions or when static linking.
> > >
> > > However, you can test switching it to R_SH_GOTFUNCDESC just by using
> > > -fPIC, and when you link, you still get the same problem, because the
> > > linker is breaking it by binding at ld-time. So there are at least two
> > > bugs in play here.
> >
> > The offending logic in bfd linker is SYMBOL_FUNCDESC_LOCAL macro in
> > bfd/elf32-sh.c. SYMBOL_REFERENCES_LOCAL is not sufficient to conclude
> > that the FUNCDESC can be expanded at ld time. I'm not sure how to
> > write it yet, but the condition is:
> >
> > !dynamic_linking || (SYMBOL_REFERENCES_LOCAL && !visible_outside_dso)
> >
> > The existing elf_hash_table (INFO)->dynamic_sections_created clause
> > covers !dynamic_linking mostly except that it will give the wrong
> > result for static PIE (which is largely gratuitous for FDPIC, but
> > should still be expected to work).
>
> I have what seem to be working patches for the linker and gcc.
>
> The bfd link code for sh/fdpic was doing two things wrong: using the
> condition "locally defined" rather than "externally visible" for
> deciding how to handle function descriptors, and "optimizing" out the
> symbol reference even once that was fixed. The patch corrects both
> behaviors.
>
> GCC was wrongly using GOTOFFFUNCDESC rather than GOTFUNCDESC for
> locally defined but externally visible symbols. This could be worked
> around with -fPIC, but the patch fixes it. (Probably should do
> internal too, but nobody uses internal visibility because it's
> underspecified and broken.)
>
> Following the same logic changes should fix the problem on xtensa.
>
> Rich
> --- binutils-2.33.1/bfd/elf32-sh.c.orig 2024-04-04 23:11:28.739136261 +0900
> +++ binutils-2.33.1/bfd/elf32-sh.c 2024-04-08 23:14:24.496915074 +0900
> @@ -61,7 +61,7 @@
> not. If the symbol is protected, we want the local address, but
> its function descriptor must be assigned by the dynamic linker. */
> #define SYMBOL_FUNCDESC_LOCAL(INFO, H) \
> - (SYMBOL_REFERENCES_LOCAL (INFO, H) \
> + (!(H) || (H)->dynindx < 0 || (H)->forced_local \
> || ! elf_hash_table (INFO)->dynamic_sections_created)
> \f
> #define SH_PARTIAL32 TRUE
> @@ -4405,20 +4405,6 @@
> /* Undefined weak symbol which will not be dynamically
> resolved later; leave it at zero. */
> goto funcdesc_leave_zero;
> - else if (SYMBOL_CALLS_LOCAL (info, h)
> - && ! SYMBOL_FUNCDESC_LOCAL (info, h))
> - {
> - /* If the symbol needs a non-local function descriptor
> - but binds locally (i.e., its visibility is
> - protected), emit a dynamic relocation decayed to
> - section+offset. This is an optimization; the dynamic
> - linker would resolve our function descriptor request
> - to our copy of the function anyway. */
> - dynindx = elf_section_data (h->root.u.def.section
> - ->output_section)->dynindx;
> - relocation += h->root.u.def.section->output_offset
> - + h->root.u.def.value;
> - }
> else if (! SYMBOL_FUNCDESC_LOCAL (info, h))
> {
> /* If the symbol is dynamic and there will be dynamic
>
> --- gcc-11.4.0/gcc/config/sh/sh.c.orig 2024-04-04 05:52:42.125373614 +0900
> +++ gcc-11.4.0/gcc/config/sh/sh.c 2024-04-04 22:54:01.875106654 +0900
> @@ -9147,7 +9147,7 @@
> {
> /* Weak functions may be NULL which doesn't work with
> GOTOFFFUNCDESC because the runtime offset is not known. */
> - if (SYMBOL_REF_WEAK (orig))
> + if (SYMBOL_REF_WEAK (orig) || (TREE_PUBLIC(SYMBOL_REF_DECL(orig)) && DECL_VISIBILITY (SYMBOL_REF_DECL(orig)) != VISIBILITY_HIDDEN))
> emit_insn (gen_symGOTFUNCDESC2reg (reg, orig));
> else
> emit_insn (gen_symGOTOFFFUNCDESC2reg (reg, orig));
>
Binutils bug report:
https://sourceware.org/bugzilla/show_bug.cgi?id=31619
GCC bug report:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114641
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2024-04-08 15:32 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-03-28 20:03 [musl] [RFC v2 0/2] xtensa FDPIC port Max Filippov
2024-03-28 20:03 ` [musl] [RFC v2 1/2] xtensa: add port Max Filippov
2024-03-28 20:03 ` [musl] [RFC v2 2/2] WIP xtensa bits Max Filippov
2024-03-28 23:01 ` [musl] [RFC v2 0/2] xtensa FDPIC port Rich Felker
2024-03-29 0:48 ` Max Filippov
2024-03-29 1:48 ` Rich Felker
2024-04-03 2:30 ` Max Filippov
2024-04-03 20:55 ` Rich Felker
2024-04-03 21:45 ` Rich Felker
2024-04-04 8:44 ` Max Filippov
2024-04-04 14:01 ` Rich Felker
2024-04-04 15:00 ` Rich Felker
2024-04-08 14:41 ` Rich Felker
2024-04-08 15:32 ` Rich Felker
2024-04-04 8:56 ` Max Filippov
Code repositories for project(s) associated with this public inbox
https://git.vuxu.org/mirror/musl/
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).