Support outputing correct executables for Termux (a Linux shell for Android)
Running c3c run on Termux gives the following error when executing the output file:
error: ".....": executable's TLS segment is underaligned: alignment is 8, needs to be at least 64 for ARM64 Bionic
https://github.com/termux/termux-elf-cleaner is a project to fix the alignment, but I wonder if it is possible to output the right alignment for bionic libc
After cleaning the elf, then running it again:
ERROR: 'No method 'acquire' could be found on target', in _$main (mem_allocator.c3:86)
fish: Job 1, './nur' terminated by signal SIGTRAP (Trace or breakpoint trap)
You can close this as not planned and declare Termux to be unsupported
Ah, this seems to be duplicate of #1396
No, this is different. The error you get seems to be due to libc not getting started. So I think it's as simple as the wrong libraries are being linked.
Can you show me what compiling with -vv added to compilation outputs?
Can you show me what compiling with
-vvadded to compilation outputs?
$ c3c run -vv
-- AST/EXPR/TYPE INFO --
* Ast size: 56 bytes
* Decl size: 136 bytes
* Expr size: 56 bytes
* TypeInfo size: 40 bytes
* Ast memory use: 4226kb (77286 elements)
* Decl memory use: 5729kb (43141 elements)
* Expr memory use: 19647kb (359273 elements)
* TypeInfo memory use: 1824kb (46718 elements)
-- ARENA INFO --
* Memory used: 42160 Kb
* Allocations: 150648
* String memory used: 389 Kb
cc -o build/c3testproject -rdynamic -pthread build/obj/android-aarch64/std.math.math_rt.o build/obj/android-aarch64/std.math.o build/obj/android-aarch64/libc.o build/obj/android-aarch64/std.io.os.o build/obj/android-aarch64/std.io.file.o build/obj/android-aarch64/std.io.o build/obj/android-aarch64/std.core.types.o build/obj/android-aarch64/std.core.string.o build/obj/android-aarch64/std.core.mem.o build/obj/android-aarch64/std.core.dstring.o build/obj/android-aarch64/std.core.string.conv.o build/obj/android-aarch64/std.core.builtin.o build/obj/android-aarch64/std.core.ascii.o build/obj/android-aarch64/std.core.mem.allocator.o build/obj/android-aarch64/std.atomic.o build/obj/android-aarch64/c3testproject.o -ldl
Program linked to executable 'build/c3testproject'.
--------- Compilation time statistics --------
Frontend -------------------- Time --- % total
Initialization took: 5.918 ms 0.3 %
Parsing took: 321.153 ms 18.0 %
Analysis took: 124.574 ms 7.0 %
TOTAL: 451.645 ms 25.3 %
Backend --------------------- Time --- % total
Ir gen took: 160.757 ms 9.0 %
Codegen took: 932.191 ms 52.2 % (8 threads)
Linking took: 241.381 ms 13.5 %
TOTAL: 1334.328 ms 74.7 %
----------------------------------------------
TOTAL compile time: 1785.973 ms.
----------------------------------------------
Launching ./build/c3testproject
error: "/data/data/com.termux/files/home/c3testproject/build/c3testproject": executable's TLS segment is underaligned: alignment is 8, needs to be at least 64 for ARM64 Bionic
Program interrupted by signal 6.
$ cd build
$ termux-elf-cleaner c3testproject
termux-elf-cleaner: Changing TLS alignment for 'c3testproject' to 64, instead of 8
termux-elf-cleaner: Replacing unsupported DF_1_* flags 134217729 with 1 in 'c3testproject'
$ ./c3testproject
ERROR: 'No method 'acquire' could be found on target', in _$main (mem_allocator.c3:86)
fish: Job 1, './c3testproject' terminated by signal SIGTRAP (Trace or breakpoint trap)
Can you check what the correct arguments are for compiling for termux with cc?
Can you check what the correct arguments are for compiling for termux with cc?
$ cat test.c
#include <stdio.h>
int main(void) {
printf("Hello, World!");
}
$ cc -o test test.c
$ ./test
Hello, World!
This just works, it has nothing to do with clang in particular, the object files it links are the ones with problems
If I use compile-only then link it with the command that showed in c3c run -vv, but remove build/obj/android-aarch64/std.core.mem.allocator.o, it doesn't show the TLS segement alignment error nor the acquire method missing error, but it segfaults though
Running gdb, it segfaults at dyn_search, no source file information provided
(gdb) bt 10
#0 0x00000055555895dc in dyn_search ()
#1 0x0000005555591900 in malloc_try ()
at /data/data/com.termux/files/home/.local/bin/c3/lib/std/core/mem_allocator.c3:8
#2 alloc_array_try ()
at /data/data/com.termux/files/home/.local/bin/c3/lib/std/core/mem_allocator.c3:304
#3 alloc_array ()
at /data/data/com.termux/files/home/.local/bin/c3/lib/std/core/mem_allocator.c3:287
#4 alloc_array ()
at /data/data/com.termux/files/home/.local/bin/c3/lib/std/core/mem.c3:911
#5 args_to_strings ()
at /data/data/com.termux/files/home/.local/bin/c3/lib/std/core/private/main_stub.c3:24
#6 @main_to_int_main_args ()
at /data/data/com.termux/files/home/.local/bin/c3/lib/std/core/private/main_stub.c3:45
#7 main (.anon=0x7fffffee48, .anon=0x7fffffee48) at main.c3:4
How did it find std/core/mem_allocator.c3:86 if I didn't link with it
I'm trying to dig into this to see what Clang does, but so far no luck.
This is the full verbose output of compiling a hello world with gcc (which is just clang lol), hopefully the flags it uses can help:
$ gcc -o main test.c --verbose
clang version 20.1.4
Target: aarch64-unknown-linux-android24
Thread model: posix
InstalledDir: /data/data/com.termux/files/usr/bin
"/data/data/com.termux/files/usr/bin/clang-20" -cc1 -triple aarch64-unknown-linux-android24 -emit-obj -dumpdir main- -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name test.c -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=non-leaf -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu generic -target-feature +v8a -target-feature +fp-armv8 -target-feature +neon -target-feature +fix-cortex-a53-835769 -target-abi aapcs -debugger-tuning=gdb -fdebug-compilation-dir=/data/data/com.termux/files/home -v -fcoverage-compilation-dir=/data/data/com.termux/files/home -resource-dir /data/data/com.termux/files/usr/lib/clang/20 -isysroot /data/data/com.termux/files -internal-isystem /data/data/com.termux/files/usr/lib/clang/20/include -internal-isystem /data/data/com.termux/files/usr/local/include -internal-externc-isystem /data/data/com.termux/files/usr/include/aarch64-linux-android -internal-externc-isystem /data/data/com.termux/files/include -internal-externc-isystem /data/data/com.termux/files/usr/include -ferror-limit 19 -femulated-tls -fno-signed-char -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fcolor-diagnostics -target-feature +outline-atomics -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /data/data/com.termux/files/usr/tmp/test-9c1443.o -x c test.c
clang -cc1 version 20.1.4 based upon LLVM 20.1.4 default target aarch64-unknown-linux-android24
ignoring nonexistent directory "/data/data/com.termux/files/usr/local/include"
ignoring nonexistent directory "/data/data/com.termux/files/include"
#include "..." search starts here:
#include <...> search starts here:
/data/data/com.termux/files/usr/lib/clang/20/include
/data/data/com.termux/files/usr/include/aarch64-linux-android
/data/data/com.termux/files/usr/include
End of search list.
"/data/data/com.termux/files/usr/bin/ld.lld" --sysroot=/data/data/com.termux/files -EL --fix-cortex-a53-843419 -z now -z relro -z max-page-size=16384 --no-rosegment --hash-style=gnu -rpath=/data/data/com.termux/files/usr/lib --eh-frame-hdr -m aarch64linux -pie -dynamic-linker /system/bin/linker64 -o main /data/data/com.termux/files/usr/lib/crtbegin_dynamic.o -L/data/data/com.termux/files/usr/lib -L/system/lib64 /data/data/com.termux/files/usr/tmp/test-9c1443.o /data/data/com.termux/files/usr/lib/clang/20/lib/linux/libclang_rt.builtins-aarch64-android.a -l:libunwind.a -ldl -lc /data/data/com.termux/files/usr/lib/clang/20/lib/linux/libclang_rt.builtins-aarch64-android.a -l:libunwind.a -ldl /data/data/com.termux/files/usr/lib/crtend_android.o
termux - Samsung Android
-
on termux you have clang, lld, cmake, llvm
$ pkg install clang lld llvm cmake
-
I compiled from the source.
removing a bunch of -lLLVMxxxx linker flags adding -lLLVM -lz -lzstd flags
~/c3c/CMakeLists.txt:
set(CMAKE_EXE_LINKER_FLAGS "-lLLVM -lz -lzstd")
#llvm_map_components_to_libname....
c3c binary created successfuly.
- changed all LogPriority to log::LogPriority in runtime_test.c3
~/c3c/build $ ./c3c compile test.c3
(/data/data/com.termux/files/home/c3c/lib/std/core/runtime_test.c3:22:2) Error: The enum 'LogPriority' is defined in both 'std::core::log' and 'std::os::android', please use either std::core::log::LogPriority or std::os::android::LogPriority to resolve the ambiguity.
- ELF cleaning
~/c3c/build $ ./test
error: "./test": executable's TLS segment is underaligned: alignment is 8 (skew 0), needs to be at least 64 for ARM64 Bionic
~/c3c/build $ termux-elf-cleaner ./test
- Error at termination
It worked anyway.
~/c3c/build $ ./test
Hello, World!
ERROR: '@require "self.allocated" violated: 'Only a top level allocator should be freed.'.', in destroy_temp_allocators (mem_allocator.c3:530) Trap ./test
Hey lerno, you could do something about 2., 3., 5.
- ELF cleaning, but still not work
~ $ c3c compile test2.c3 Program linked to executable './test2'.
~ $ termux-elf-cleaner test2 termux-elf-cleaner: Changing TLS alignment for 'test2' to 64, instead of 8 termux-elf-cleaner: Replacing unsupported DF_1_* flags 134217729 with 1 in 'test2'
~ $ ./test2
error: "./test2": executable's TLS segment is underaligned: alignment is 64 (skew 16), needs to be at least 64 for ARM64 Bionic Aborted ./test2
Are we sure it's linking the correct libs?
This patch that enables emulated tls seems to have fixed it for me:
diff --git a/src/compiler/target.c b/src/compiler/target.c
index 087d9d4e..3bacf9ca 100644
--- a/src/compiler/target.c
+++ b/src/compiler/target.c
@@ -1976,6 +1976,7 @@ void *llvm_target_machine_create(void)
(LLVMCodeGenOptLevel)compiler.platform.llvm_opt_level,
reloc_mode, model);
LLVMSetTargetMachineUseInitArray(result, true);
+ LLVMSetTargetMachineEmulatedTLS(result, true);
if (!result) error_exit("Failed to create target machine.");
LLVMSetTargetMachineAsmVerbosity(result, 1);
return result;
diff --git a/wrapper/include/c3_llvm.h b/wrapper/include/c3_llvm.h
index 8862ebb9..33572ed1 100644
--- a/wrapper/include/c3_llvm.h
+++ b/wrapper/include/c3_llvm.h
@@ -78,8 +78,9 @@ LLVMValueRef LLVMConstBswap(LLVMValueRef ConstantVal);
void LLVMBuilderSetFastMathFlags(LLVMBuilderRef Builder, FastMathOption option);
void LLVMSetDSOLocal(LLVMValueRef Global, bool value);
void LLVMSetTargetMachineUseInitArray(LLVMTargetMachineRef ref, bool use_init_array);
+void LLVMSetTargetMachineEmulatedTLS(LLVMTargetMachineRef ref, bool emulated_tls);
void LLVMSetNoSanitizeAddress(LLVMValueRef Global);
#ifdef __cplusplus
}
-#endif
\ No newline at end of file
+#endif
diff --git a/wrapper/src/wrapper.cpp b/wrapper/src/wrapper.cpp
index 786d5d49..81f297db 100644
--- a/wrapper/src/wrapper.cpp
+++ b/wrapper/src/wrapper.cpp
@@ -323,6 +323,11 @@ void LLVMSetTargetMachineUseInitArray(LLVMTargetMachineRef ref, bool use_init_ar
auto machine = (llvm::TargetMachine*)ref;
machine->Options.UseInitArray = use_init_array;
}
+void LLVMSetTargetMachineEmulatedTLS(LLVMTargetMachineRef ref, bool emulated_tls)
+{
+ auto machine = (llvm::TargetMachine*)ref;
+ machine->Options.EmulatedTLS = emulated_tls;
+}
void LLVMSetDSOLocal(LLVMValueRef Global, bool value)
{
llvm::unwrap<llvm::GlobalValue>(Global)->setDSOLocal(value);
emulated tls is also something that was enabled by clang, so it seems to be the correct solution