#!/bin/bash

set -xefuCo pipefail

# Shared musl binaries contradict cardinally with libfakeroot:
#   Error relocating /usr/lib64/libfakeroot/libfakeroot.so: __snprintf_chk: symbol not found
#   Error relocating /usr/lib64/libfakeroot/libfakeroot.so: __memcpy_chk: symbol not found
#   Error relocating /usr/lib64/libfakeroot/libfakeroot.so: __fprintf_chk: symbol not found
#   Error relocating /usr/lib64/libfakeroot/libfakeroot.so: dlvsym: symbol not found
unset LD_PRELOAD LD_LIBRARY_PATH

T=$(mktemp -d)
cd "$T"
tee hello.c <<-EOF
	#include <fts.h>
	#include <sys/stat.h>
	#include <stdio.h>
	#include <stdlib.h>
	#include <dlfcn.h>
	int main() {
		int stack_var;
		void *heap_var = malloc(64);
		void *libc_base = dlopen("libc.so.6", RTLD_LAZY);
		printf("main  = %p\n", main);
		printf("stack = %p\n", &stack_var);
		printf("heap  = %p\n", heap_var);
		printf("libc  = %p\n", libc_base);
		struct stat sb;
		if (stat("/", &sb)) return 2;
		char *path_argv[] = {"/", NULL};
		FTS *fts = fts_open(path_argv, 0, NULL);
		return fts_close(fts);
	}
EOF

# Priority order:
# 1. musl-gcc with static linking - best use case for musl
# 2. musl-gcc with dynamic linking.
# 3. musl-clang - no promises, since musl itself is compiled with gcc.

# Tests that shall not fail:
musl-gcc hello.c
  file a.out | grep 'LSB pie executable,.* dynamically linked, interpreter /lib/ld-musl-.*, BuildID.* with debug_info, not stripped'
  timeout -v 3 ./a.out
musl-gcc hello.c -static
  file a.out | grep 'LSB executable,.* statically linked,.* BuildID.* with debug_info, not stripped'
  timeout -v 3 ./a.out
musl-gcc hello.c -static-pie
  file a.out | grep 'LSB pie executable,.* static-pie linked,.* BuildID.* with debug_info, not stripped'
  timeout -v 3 ./a.out

{ set +x; } 2>/dev/null
toilet 'PASSED.'

# Additional tests that may fail (for logs and research):
echo 'Following tests are non-fatal and rather informational.'
set +e
for cc in 'gcc' 'clang'; do
	toilet "$cc"
	for shared in '' '-static' '-static-pie' '-shared'; do
		for pie in '' '-pie' '-no-pie'; do
			# Compiler should work on its own.
			{ $cc hello.c $shared $pie && timeout -v 3 ./a.out || continue; } &>/dev/null
			set -x
			musl-$cc hello.c $shared $pie &&
			file a.out &&
			timeout -v 3 ./a.out
			{ set +x; } 2>/dev/null
			echo
			[ "$shared" = '-static-pie' ] && break
		done
	done
done
set -x
rm -rf -- "$T"
exit 0

# So far (2023-08-06) test results:
#
#             aarch64   armh    i586    ppc64le  x86_64
#  musl-gcc      +/+     +/+     +/+      +/+      +/+
#  musl-clang   LD*1    LD*2   +/DIV*3   SEGV*4    +/+
#
# Legend: static/dynamic linking, '+' is success.
# __
# *1 Errors of musl-clang on aarch64:
#  ld: /usr/lib64/musl/lib/libc.a(vfprintf.lo): in function `pop_arg':
#  /usr/src/RPM/BUILD/musl-1.2.4/src/stdio/vfprintf.c:128: undefined reference to `__extenddftf2'
#  ld: /usr/lib64/musl/lib/libc.a(vfprintf.lo): in function `fmt_fp':
#  /usr/src/RPM/BUILD/musl-1.2.4/src/stdio/vfprintf.c:210: undefined reference to `__addtf3'
#  ld: /usr/src/RPM/BUILD/musl-1.2.4/src/stdio/vfprintf.c:211: undefined reference to `__netf2'
#  ld: /usr/src/RPM/BUILD/musl-1.2.4/src/stdio/vfprintf.c:268: undefined reference to `__multf3'
#  ld: /usr/src/RPM/BUILD/musl-1.2.4/src/stdio/vfprintf.c:274: undefined reference to `__fixunstfsi'
#  ld: /usr/src/RPM/BUILD/musl-1.2.4/src/stdio/vfprintf.c:275: undefined reference to `__floatunsitf'
#  ld: /usr/src/RPM/BUILD/musl-1.2.4/src/stdio/vfprintf.c:275: undefined reference to `__subtf3'
#  ld: /usr/src/RPM/BUILD/musl-1.2.4/src/stdio/vfprintf.c:275: undefined reference to `__multf3'
#  ld: /usr/src/RPM/BUILD/musl-1.2.4/src/stdio/vfprintf.c:276: undefined reference to `__netf2'
#  ld: /usr/src/RPM/BUILD/musl-1.2.4/src/stdio/vfprintf.c:331: undefined reference to `__addtf3'
#  ld: /usr/src/RPM/BUILD/musl-1.2.4/src/stdio/vfprintf.c:331: undefined reference to `__netf2'
#  ld: /usr/src/RPM/BUILD/musl-1.2.4/src/stdio/vfprintf.c:202: undefined reference to `__netf2'
#  ld: /usr/src/RPM/BUILD/musl-1.2.4/src/stdio/vfprintf.c:202: undefined reference to `__netf2'
#  ld: /usr/src/RPM/BUILD/musl-1.2.4/src/stdio/vfprintf.c:225: undefined reference to `__multf3'
#  ld: /usr/src/RPM/BUILD/musl-1.2.4/src/stdio/vfprintf.c:232: undefined reference to `__addtf3'
#  ld: /usr/src/RPM/BUILD/musl-1.2.4/src/stdio/vfprintf.c:233: undefined reference to `__subtf3'
#  ld: /usr/src/RPM/BUILD/musl-1.2.4/src/stdio/vfprintf.c:248: undefined reference to `__netf2'
#  ld: /usr/src/RPM/BUILD/musl-1.2.4/src/stdio/vfprintf.c:244: undefined reference to `__fixtfsi'
#  ld: /usr/src/RPM/BUILD/musl-1.2.4/src/stdio/vfprintf.c:246: undefined reference to `__floatsitf'
#  ld: /usr/src/RPM/BUILD/musl-1.2.4/src/stdio/vfprintf.c:246: undefined reference to `__subtf3'
#  ld: /usr/src/RPM/BUILD/musl-1.2.4/src/stdio/vfprintf.c:246: undefined reference to `__multf3'
#  ld: /usr/src/RPM/BUILD/musl-1.2.4/src/stdio/vfprintf.c:247: undefined reference to `__netf2'
#  ld: /usr/src/RPM/BUILD/musl-1.2.4/src/stdio/vfprintf.c:228: undefined reference to `__subtf3'
#  ld: /usr/src/RPM/BUILD/musl-1.2.4/src/stdio/vfprintf.c:229: undefined reference to `__addtf3'
#  ld: /usr/lib64/musl/lib/libc.a(frexpl.lo): in function `frexpl':
#  /usr/src/RPM/BUILD/musl-1.2.4/src/math/frexpl.c:15: undefined reference to `__netf2'
#  ld: /usr/src/RPM/BUILD/musl-1.2.4/src/math/frexpl.c:16: undefined reference to `__multf3'
#  clang: error: linker command failed with exit code 1 (use -v to see invocation)
#
# *2 Errors of musl-clang on armh:
#  ld: /usr/lib/musl/lib/libc.a(malloc.lo): in function `alloc_group':
#  /usr/src/RPM/BUILD/musl-1.2.4/src/malloc/mallocng/malloc.c:256: undefined reference to `__aeabi_uidiv'
#  ld: /usr/lib/musl/lib/libc.a(vfprintf.lo): in function `fmt_fp':
#  /usr/src/RPM/BUILD/musl-1.2.4/src/stdio/vfprintf.c:282: undefined reference to `__aeabi_uldivmod'
#  ld: /usr/src/RPM/BUILD/musl-1.2.4/src/stdio/vfprintf.c:318: undefined reference to `__aeabi_uidivmod'
#  ld: /usr/src/RPM/BUILD/musl-1.2.4/src/stdio/vfprintf.c:356: undefined reference to `__aeabi_uidivmod'
#  ld: /usr/src/RPM/BUILD/musl-1.2.4/src/stdio/vfprintf.c:356: undefined reference to `__aeabi_uidivmod'
#  ld: /usr/lib/musl/lib/libc.a(fwrite.lo): in function `fwrite':
#  /usr/src/RPM/BUILD/musl-1.2.4/src/stdio/fwrite.c:35: undefined reference to `__aeabi_uidiv'
#  clang: error: linker command failed with exit code 1 (use -v to see invocation)
#
# *3 Errors on musl-clang on i586 for non -static compilation:
#  clang: warning: argument unused during compilation: '-no-pie' [-Wunused-command-line-argument]
#  ld: /usr/lib/musl/lib/libc.a(vfprintf.lo): in function `fmt_fp':
#  /usr/src/RPM/BUILD/musl-1.2.4/src/stdio/vfprintf.c:281: undefined reference to `__udivmoddi4'
#  clang: error: linker command failed with exit code 1 (use -v to see invocation)
#
# *4 Errors of musl-clang on ppc64le:
#  /usr/share/musl-checkinstall/_post: line 51: 2897857 Segmentation fault      ./a.out

