Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for FreeBSD-arm64 #71338

Open
sec opened this issue Jun 27, 2022 · 131 comments
Open

Support for FreeBSD-arm64 #71338

sec opened this issue Jun 27, 2022 · 131 comments

Comments

@sec
Copy link
Contributor

sec commented Jun 27, 2022

Hi,
Not to spam #14537 (as it's already quite big) :)
As full native build of either v6 and v7 is possible under FreeBSD-amd64, I went ahead and tried to make the same process work for ARM64.

After getting configure to success, I've tried:

  1. Using Linux arm64 host to cross compile to FreeBSD (with custom rootfs created with libs, etc.)
    As it was used before, to cross compile from Linux-amd64 to Freebsd-x64, this fail at very early stage with:
[  1%] Built target System.Globalization.Native-Static
Scanning dependencies of target coreclrpal
[  1%] Building C object libs-native/System.IO.Compression.Native/CMakeFiles/System.IO.Compression.Native-Static.dir/root/runtime/src/native/external/brotli/dec/state.c.o
[  1%] Building CXX object pal/src/CMakeFiles/coreclrpal.dir/cruntime/file.cpp.o
[  1%] Building C object libs-native/System.Native/CMakeFiles/System.Native-Static.dir/pal_tcpstate.c.o
In file included from /root/runtime/src/coreclr/pal/src/cruntime/file.cpp:21:
/root/runtime/src/coreclr/pal/src/include/pal/palinternal.h:158:10: fatal error: 'type_traits' file not found
#include <type_traits>
         ^~~~~~~~~~~~~
[  1%] Building C object libs-native/System.IO.Compression.Native/CMakeFiles/System.IO.Compression.Native-Static.dir/root/runtime/src/native/external/brotli/enc/backward_references.c.o
[  1%] Building C object libs-native/System.Native/CMakeFiles/System.Native-Static.dir/pal_threading.c.o
1 error generated.
[  1%] Building C object libs-native/System.Native/CMakeFiles/System.Native-Static.dir/pal_time.c.o
make[2]: *** [pal/src/CMakeFiles/coreclrpal.dir/build.make:76: pal/src/CMakeFiles/coreclrpal.dir/cruntime/file.cpp.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:2020: pal/src/CMakeFiles/coreclrpal.dir/all] Error 2

Command I've used ROOTFS_DIR=/home/ubuntu/arm64 ./src/coreclr/build-runtime.sh -arm64 -debug clang14 -cross -os FreeBSD.
This does look like something missing in configure step, as those headers are present on rootfs_dir and host system:

root@instance-20220624-1221:/# find . -name type_traits
./home/ubuntu/arm64/usr/include/c++/v1/tr1/type_traits
./home/ubuntu/arm64/usr/include/c++/v1/experimental/type_traits
./home/ubuntu/arm64/usr/include/c++/v1/type_traits

./usr/include/c++/11/tr2/type_traits
./usr/include/c++/11/tr1/type_traits
./usr/include/c++/11/experimental/type_traits
./usr/include/c++/11/type_traits

./root/runtime/src/coreclr/inc/clr_std/type_traits

so I guess something during configure stage should be added to look in those directories?

  1. Using FreeBSD arm64 host directly to compile
    Trying with both -cross and without, it fails with the same error:
[  4%] Building C object libs-native/System.Security.Cryptography.Native/CMakeFiles/objlib.dir/pal_evp_pkey_ecdh.c.o
In file included from /usr/home/sec/runtime/src/coreclr/pal/src/debug/debug.cpp:32:
/usr/home/sec/runtime/src/coreclr/pal/src/include/pal/context.h:450:1: error: unknown type name 'fpsimd_context'
fpsimd_context* GetNativeSigSimdContext(native_context_t *mc)
^
/usr/home/sec/runtime/src/coreclr/pal/src/include/pal/context.h:456:9: error: unknown type name 'fpsimd_context'
        fpsimd_context* fp = reinterpret_cast<fpsimd_context *>(&mc->uc_mcontext.__reserved[size]);
        ^
/usr/home/sec/runtime/src/coreclr/pal/src/include/pal/context.h:456:47: error: unknown type name 'fpsimd_context'
        fpsimd_context* fp = reinterpret_cast<fpsimd_context *>(&mc->uc_mcontext.__reserved[size]);
                                              ^
/usr/home/sec/runtime/src/coreclr/pal/src/include/pal/context.h:456:82: error: no member named '__reserved' in '__mcontext'
        fpsimd_context* fp = reinterpret_cast<fpsimd_context *>(&mc->uc_mcontext.__reserved[size]);
                                                                 ~~~~~~~~~~~~~~~ ^
/usr/home/sec/runtime/src/coreclr/pal/src/include/pal/context.h:458:30: error: use of undeclared identifier 'FPSIMD_MAGIC'
        if(fp->head.magic == FPSIMD_MAGIC)
                             ^
/usr/home/sec/runtime/src/coreclr/pal/src/include/pal/context.h:460:46: error: use of undeclared identifier 'fpsimd_context'
            _ASSERTE(fp->head.size >= sizeof(fpsimd_context));
                                             ^
/usr/home/sec/runtime/src/coreclr/pal/src/include/pal/context.h:461:69: error: no member named '__reserved' in '__mcontext'
            _ASSERTE(size + fp->head.size <= sizeof(mc->uc_mcontext.__reserved));
                                                    ~~~~~~~~~~~~~~~ ^
/usr/home/sec/runtime/src/coreclr/pal/src/include/pal/dbgmsg.h:362:35: note: expanded from macro '_ASSERTE'
#define _ASSERTE(expr) do { if (!(expr)) { ASSERT("Expression: " #expr "\n"); } } while(0)
                                  ^~~~
In file included from /usr/home/sec/runtime/src/coreclr/pal/src/debug/debug.cpp:32:
/usr/home/sec/runtime/src/coreclr/pal/src/include/pal/context.h:472:28: error: use of undeclared identifier 'fpsimd_context'
    } while (size + sizeof(fpsimd_context) <= sizeof(mc->uc_mcontext.__reserved));
                           ^
/usr/home/sec/runtime/src/coreclr/pal/src/include/pal/context.h:472:70: error: no member named '__reserved' in '__mcontext'
    } while (size + sizeof(fpsimd_context) <= sizeof(mc->uc_mcontext.__reserved));
                                                     ~~~~~~~~~~~~~~~ ^
/usr/home/sec/runtime/src/coreclr/pal/src/include/pal/context.h:480:7: error: unknown type name 'fpsimd_context'
const fpsimd_context* GetConstNativeSigSimdContext(const native_context_t *mc)
      ^
10 errors generated.
[  4%] Linking C static library libSystem.Native.a
--- pal/src/CMakeFiles/coreclrpal.dir/debug/debug.cpp.o ---
*** [pal/src/CMakeFiles/coreclrpal.dir/debug/debug.cpp.o] Error code 1

make[2]: stopped in /usr/home/sec/runtime/artifacts/obj/coreclr/FreeBSD.arm64.Debug
*** [all] Error code 6

make: stopped in /usr/home/sec/runtime/artifacts/obj/coreclr/FreeBSD.arm64.Debug
1 error

make: stopped in /usr/home/sec/runtime/artifacts/obj/coreclr/FreeBSD.arm64.Debug

Command used was the same as with ad. 1. This looks more complicated, as it have something to do with libunwind being used? No idea how to get over that :)

Including patches I've come up with.

If anyone expierenced with cross build could comment on that, to even confirm it's possible in the current state to make that work or would it require far more work?

If someone is interested in helping/testing/making this work I can provide access to either FreeBSD or Linux ARM64 box that I use.

runtime_freebsd_arm64.txt

@ghost ghost added the untriaged New issue has not been triaged by the area owner label Jun 27, 2022
@Thefrank
Copy link
Contributor

OSX/BSD builds use the target system's libunwind:
from src/coreclr/pal/src/CMakeLists.txt

if(CLR_CMAKE_TARGET_OSX OR CLR_CMAKE_TARGET_FREEBSD)
     # On OSX and *BSD, we use the libunwind that's part of the OS
     set(CLR_CMAKE_USE_SYSTEM_LIBUNWIND 1)
endif(CLR_CMAKE_TARGET_OSX OR CLR_CMAKE_TARGET_FREEBSD)

which makes it add only include_directories(SYSTEM $ENV{ROOTFS_DIR}/usr/local/include)

@am11
Copy link
Member

am11 commented Jun 28, 2022

Yup, I think we just need to update the list of compatible context registers for freebsd-arm64 to make it work.

@sec
Copy link
Contributor Author

sec commented Jun 28, 2022

If that would only make sense to me I would maybe help more, still learing on the fly. I found #40149 and doing quick change:

diff --git a/src/coreclr/pal/src/include/pal/context.h b/src/coreclr/pal/src/include/pal/context.h
index fec5139fd5e..2cc4941d653 100644
--- a/src/coreclr/pal/src/include/pal/context.h
+++ b/src/coreclr/pal/src/include/pal/context.h
@@ -407,7 +407,7 @@ inline void *FPREG_Xstate_Ymmh(const ucontext_t *uc)

 #if defined(HOST_ARM64)

-#ifndef TARGET_OSX
+#if !defined(TARGET_OSX) && !defined(TARGET_FREEBSD)

 #define MCREG_X0(mc)      ((mc).regs[0])
 #define MCREG_X1(mc)      ((mc).regs[1])
@@ -482,7 +482,7 @@ const fpsimd_context* GetConstNativeSigSimdContext(const native_context_t *mc)
     return GetNativeSigSimdContext(const_cast<native_context_t*>(mc));
 }

-#else // TARGET_OSX
+#elif defined(TARGET_OSX) // TARGET_OSX

 #define MCREG_X0(mc)      ((mc)->__ss.__x[0])
 #define MCREG_X1(mc)      ((mc)->__ss.__x[1])

native compile fail with:

In file included from /usr/home/sec/runtime/src/coreclr/pal/src/exception/seh.cpp:407:
/usr/home/sec/runtime/src/coreclr/pal/src/exception/seh-unwind.cpp:177:2: error: unsupported architecture
#error unsupported architecture
 ^
/usr/home/sec/runtime/src/coreclr/pal/src/exception/seh-unwind.cpp:183:5: error: use of undeclared identifier 'ASSIGN_UNWIND_REGS'
    ASSIGN_UNWIND_REGS
    ^
2 errors generated.
--- pal/src/CMakeFiles/coreclrpal.dir/exception/seh.cpp.o ---
*** [pal/src/CMakeFiles/coreclrpal.dir/exception/seh.cpp.o] Error code 1

Is this the context registers that needs to be updated (looked at the code and there's no ARM64 for any of the targets)?

@janvorli
Copy link
Member

@sec, what are the detected features (the HAVE_xxx) for the FreeBSD arm64 build? When you do a clean build, it lists them to the console. From those, I should be able to tell where to update the context registers extraction.

@sec
Copy link
Contributor Author

sec commented Jun 28, 2022

@janvorli There you go:

-- Performing Test COMPILER_SUPPORTS_F_STACK_PROTECTOR_STRONG - Success
-- Performing Test COMPILER_SUPPORTS_W_IMPLICIT_FALLTHROUGH - Success
-- Performing Test HAVE_LTO - Failed
-- Performing Test COMPILER_SUPPORTS_F_ALIGNED_NEW - Success
-- Performing Test HAVE_DIRENT_D_TYPE - Success
-- Performing Test C_SUPPORTS_WUNGUARDED_AVAILABILITY - Success
-- Performing Test HAVE_IN_PKTINFO - Failed
-- Performing Test HAVE_IP_MREQN - Success
-- Performing Test HAVE_STATFS_VFS - Failed
-- Performing Test HAVE_STATFS_MOUNT - Success
-- Performing Test HAVE_FLOCK64 - Failed
-- Performing Test HAVE_IFADDRS - Success
-- Performing Test HAVE_UTSNAME_DOMAINNAME - Failed
-- Performing Test HAVE_STAT_BIRTHTIME - Success
-- Performing Test HAVE_STAT_FLAGS - Success
-- Performing Test HAVE_STAT_TIMESPEC - Success
-- Performing Test HAVE_STAT_TIM - Success
-- Performing Test HAVE_STAT_NSEC - Success
-- Performing Test HAVE_DIRENT_NAME_LEN - Success
-- Performing Test HAVE_STATFS_FSTYPENAME - Success
-- Performing Test HAVE_STATVFS_FSTYPENAME - Failed
-- Performing Test HAVE_GNU_STRERROR_R - Failed
-- Performing Test HAVE_READDIR_R - Success
-- Performing Test KEVENT_HAS_VOID_UDATA - Success
-- Performing Test HAVE_FDS_BITS - Success
-- Performing Test HAVE_PRIVATE_FDS_BITS - Success
-- Performing Test HAVE_SENDFILE_4 - Failed
-- Performing Test HAVE_SENDFILE_6 - Failed
-- Performing Test HAVE_SENDFILE_7 - Success
-- Performing Test HAVE_GETNAMEINFO_SIGNED_FLAGS - Success
-- Performing Test HAVE_SHM_OPEN_THAT_WORKS_WELL_ENOUGH_WITH_MMAP - Success
-- Performing Test HAVE_CLOCK_MONOTONIC - Success
-- Performing Test HAVE_CLOCK_REALTIME - Success
-- Performing Test BIND_ADDRLEN_UNSIGNED - Success
-- Performing Test IPV6MR_INTERFACE_UNSIGNED - Success
-- Performing Test INOTIFY_RM_WATCH_WD_UNSIGNED - Failed
-- Performing Test HAVE_MKSTEMPS - Success
-- Performing Test HAVE_MKSTEMP - Success
-- Performing Test HAVE_NETINET_TCP_VAR_H - Success
-- Performing Test HAVE_NETINET_UDP_VAR_H - Success
-- Performing Test HAVE_NETINET_IP_VAR_H - Success
-- Performing Test HAVE_NETINET_ICMP_VAR_H - Success
-- Performing Test HAVE_TCP_H_TCPSTATE_ENUM - Failed
-- Performing Test HAVE_GETDOMAINNAME_SIZET - Failed
-- Performing Test HAVE_IN_EXCL_UNLINK - Success
-- Performing Test HAVE_TCP_H_TCP_KEEPALIVE - Failed
-- Performing Test HAVE_BUILTIN_MUL_OVERFLOW - Success
-- Performing Test HAVE_UDAT_STANDALONE_SHORTER_WEEKDAYS - Success
-- Performing Test HAVE_VM_FLAGS_SUPERPAGE_SIZE_ANY - Failed
-- Performing Test HAVE_MAP_HUGETLB - Failed
-- Performing Test HAVE_LTTNG_TRACEPOINT_H - Failed
-- Performing Test HAVE_CPUSET_T - Success
-- Performing Test HAVE_TM_GMTOFF - Success
-- Performing Test HAVE_GREGSET_T - Failed
-- Performing Test HAVE___GREGSET_T - Failed
-- Performing Test HAVE_FPSTATE_GLIBC_RESERVED1 - Failed
-- Performing Test HAVE_SYSINFO_WITH_MEM_UNIT - Failed
-- Performing Test HAVE_FPREGS_WITH_CW - Failed
-- Performing Test REALPATH_SUPPORTS_NONEXISTENT_FILES - Failed
-- Performing Test SSCANF_SUPPORT_ll - Success
-- Performing Test SSCANF_CANNOT_HANDLE_MISSING_EXPONENT - Failed
-- Performing Test HAVE_LARGE_SNPRINTF_SUPPORT - Success
-- Performing Test HAVE_BROKEN_FIFO_SELECT - Failed
-- Performing Test HAVE_BROKEN_FIFO_KEVENT - Failed
-- Performing Test HAVE_SCHED_GET_PRIORITY - Success
-- Performing Test HAVE_WORKING_GETTIMEOFDAY - Success
-- Performing Test HAVE_WORKING_CLOCK_GETTIME - Success
-- Performing Test HAVE_CLOCK_MONOTONIC_COARSE - Success
-- Performing Test HAVE_CLOCK_THREAD_CPUTIME - Success
-- Performing Test MMAP_ANON_IGNORES_PROTECTION - Failed
-- Performing Test ONE_SHARED_MAPPING_PER_FILEREGION_PER_PROCESS - Failed
-- Performing Test PTHREAD_CREATE_MODIFIES_ERRNO - Failed
-- Performing Test SEM_INIT_MODIFIES_ERRNO - Failed
-- Performing Test HAVE_PROCFS_CTL - Failed
-- Performing Test HAVE_PROCFS_MAPS - Failed
-- Performing Test HAVE_PROCFS_STAT - Failed
-- Performing Test HAVE_PROCFS_STATUS - Success
-- Performing Test HAVE_COMPATIBLE_ACOS - Success
-- Performing Test HAVE_COMPATIBLE_ASIN - Success
-- Performing Test HAVE_COMPATIBLE_POW - Success
-- Performing Test HAVE_VALID_NEGATIVE_INF_POW - Success
-- Performing Test HAVE_VALID_POSITIVE_INF_POW - Success
-- Performing Test HAVE_COMPATIBLE_ATAN2 - Success
-- Performing Test HAVE_COMPATIBLE_EXP - Failed
-- Performing Test HAVE_COMPATIBLE_ILOGB0 - Failed
-- Performing Test HAVE_COMPATIBLE_ILOGBNAN - Success
-- Performing Test HAVE_COMPATIBLE_LOG - Success
-- Performing Test HAVE_COMPATIBLE_LOG10 - Success
-- Performing Test UNGETC_NOT_RETURN_EOF - Failed
-- Performing Test HAS_POSIX_SEMAPHORES - Success
-- Performing Test GETPWUID_R_SETS_ERRNO - Failed
-- Performing Test FILE_OPS_CHECK_FERROR_OF_PREVIOUS_CALL - Failed
-- Performing Test UNWIND_CONTEXT_IS_UCONTEXT_T - Success
-- Performing Test HAVE_XSWDEV - Success
-- Performing Test HAVE_XSW_USAGE - Failed
-- Performing Test HAVE_PUBLIC_XSTATE_STRUCT - Failed
-- Performing Test HAVE_PR_SET_PTRACER - Failed
-- Performing Test HAVE_FULLY_FEATURED_PTHREAD_MUTEXES - Success
-- Performing Test HAVE_PTHREAD_THREADID_NP - Failed
-- Performing Test HAVE_PTHREAD_GETTHREADID_NP - Success

edit: also attached full log from build attempt.
build_log.txt

@janvorli
Copy link
Member

janvorli commented Jun 28, 2022

It seems to me that your last change was correct. But you also need to add #elif (defined(HOST_UNIX) && defined(HOST_ARM64)) before the #else with #error that fires. In that #elif, you'd add:

    ASSIGN_REG(Pc) \
    ASSIGN_REG(Sp) \
    ASSIGN_REG(Fp) \
    ASSIGN_REG(Lr) \
    ASSIGN_REG(X19) \
    ASSIGN_REG(X20) \
    ASSIGN_REG(X21) \
    ASSIGN_REG(X22) \
    ASSIGN_REG(X23) \
    ASSIGN_REG(X24) \
    ASSIGN_REG(X25) \
    ASSIGN_REG(X26) \
    ASSIGN_REG(X27) \
    ASSIGN_REG(X28)

I hope I got it right.

@sec
Copy link
Contributor Author

sec commented Jun 28, 2022

@janvorli Tried that, it failed with bunch of errors for every register:

In file included from /usr/home/sec/runtime/src/coreclr/pal/src/exception/seh.cpp:407:
/usr/home/sec/runtime/src/coreclr/pal/src/exception/seh-unwind.cpp:190:2: error: use of undeclared identifier 'MCREG_X21'
        ASSIGN_UNWIND_REGS
        ^
/usr/home/sec/runtime/src/coreclr/pal/src/exception/seh-unwind.cpp:178:2: note: expanded from macro 'ASSIGN_UNWIND_REGS'
        ASSIGN_REG(X21) \
        ^
/usr/home/sec/runtime/src/coreclr/pal/src/exception/seh-unwind.cpp:189:25: note: expanded from macro 'ASSIGN_REG'
#define ASSIGN_REG(reg) MCREG_##reg(unwContext->uc_mcontext) = winContext->reg;
                        ^
<scratch space>:95:1: note: expanded from here
MCREG_X21
^

Leaving this empty, will go on but then fail again with similar errors. If I'm looking at this correctly, I think it's missing some #def for HOST_ARM64 and TARGET_FREEBSD inside src/coreclr/pal/src/include/pal/context.h with those registers?

And also there's again error: unknown type name 'fpsimd_context' - which FreeBSD doesn't have, but if I add || defined(TARGET_FREEBSD) next to TARGET_OSX those errors seems to go away (don't know if that will work in the end though, as I going blind in here. Also the undefined registers errors are there, so my bet is that fixing those first would be real fix).

I wodner, if there's libunwind used (which state FreeBSD is supported under x64 and arm64) - shouldn't this be used (if I assume this code here is about that).

As I saw @sdmaclea did the OSX part of changes - maybe some hints? :)

Just to make sure, this is native build under ARM64 FreeBSD host.

@janvorli
Copy link
Member

Ah, I haven't noticed that your change around line 490 was like this:

-#else // TARGET_OSX
+#elif defined(TARGET_OSX) // TARGET_OSX

That way, you have eliminated both definitions of the MCREG_xxx for arm64. What does the ucontext_t struct look like on FreeBSD arm64? We'll either need to define the MCREG_xxx for the FreeBSD separately or reuse the one for Linux / OSX if it happens to be the same.

@janvorli
Copy link
Member

Ah, found it in FreeBSD sources. So it is different and we will need to have another #elif TARGET_FREEBSD there. It seems that the definitions should look like:

#define MCREG_X21(mc) (mc.mc_gpregs.gp_x[21])
#define MCREG_X22(mc) (mc.mc_gpregs.gp_x[22])
#define MCREG_X23(mc) (mc.mc_gpregs.gp_x[23])
#define MCREG_X24(mc) (mc.mc_gpregs.gp_x[24])
#define MCREG_X25(mc) (mc.mc_gpregs.gp_x[25])
#define MCREG_X26(mc) (mc.mc_gpregs.gp_x[26])
#define MCREG_X27(mc) (mc.mc_gpregs.gp_x[27])
#define MCREG_X28(mc) (mc.mc_gpregs.gp_x[28])
#define MCREG_Fp(mc)      (mc.mc_gpregs.gp_fp)
#define MCREG_Lr(mc)      (mc.mc_gpregs.gp_lr)
#define MCREG_Sp(mc)      (mc.mc_gpregs.gp_sp)
#define MCREG_Pc(mc)      (mc.mc_gpregs.gp_pc)

As for the floating point access we will also need an extra code here. Take the following with a grain of salt, it might not be exactly right or might need extra change at another place too:

inline
struct fpregs* GetNativeSigSimdContext(native_context_t *mc)
{
    return &(mc->mc_fpregs);
}

inline
const struct fpregs* GetConstNativeSigSimdContext(const native_context_t *mc)
{
    return GetNativeSigSimdContext(const_cast<native_context_t*>(mc));
}

@janvorli
Copy link
Member

@sec
Copy link
Contributor Author

sec commented Jun 28, 2022

@janvorli Thanks, I was looking at the same files and was about to post :)
Can't find Pc and Fp in ucontext in structs btw.

Managed to get past some errors, but now a lot of:

[  6%] Built target eventpipe_objs
Consolidate compiler generated dependencies of target mdruntimerw_wks_obj
/usr/home/sec/runtime/src/coreclr/pal/src/thread/context.cpp:339:9: error: use of undeclared identifier 'BSDREG_Cpsr'
        ASSIGN_ALL_REGS
        ^
/usr/home/sec/runtime/src/coreclr/pal/src/thread/context.cpp:286:9: note: expanded from macro 'ASSIGN_ALL_REGS'
        ASSIGN_CONTROL_REGS \
        ^
/usr/home/sec/runtime/src/coreclr/pal/src/thread/context.cpp:137:9: note: expanded from macro 'ASSIGN_CONTROL_REGS'
        ASSIGN_REG(Cpsr)    \
        ^
/usr/home/sec/runtime/src/coreclr/pal/src/thread/context.cpp:333:62: note: expanded from macro 'ASSIGN_REG'
#define ASSIGN_REG(reg) MCREG_##reg(registers.uc_mcontext) = BSDREG_##reg(ptrace_registers);
                                                             ^
<scratch space>:248:1: note: expanded from here
BSDREG_Cpsr
^
[  8%] Built target ceefgen_obj
/usr/home/sec/runtime/src/coreclr/pal/src/thread/context.cpp:339:9: error: use of undeclared identifier 'BSDREG_Fp'
/usr/home/sec/runtime/src/coreclr/pal/src/thread/context.cpp:286:9: note: expanded from macro 'ASSIGN_ALL_REGS'
        ASSIGN_CONTROL_REGS \
        ^
/usr/home/sec/runtime/src/coreclr/pal/src/thread/context.cpp:138:9: note: expanded from macro 'ASSIGN_CONTROL_REGS'
        ASSIGN_REG(Fp)      \
        ^
...

I haven't saw any existing BSDREG_X for defined (even for OSX)

I'm starting to think does this road make sense. Shouldn't this reuse existing ARM64 code and/or use machine specific libunwind for the rest?

@janvorli
Copy link
Member

We cannot reuse the code, because the structure of the ucontext_t is different from all other platforms, using different names of data fields for the registers etc. That's why we are adding new ones.

@janvorli
Copy link
Member

Can you please share the log from the clean build after you've applied my previous fix? It is not clear to me how come we are compiling code using the BSDREG_xxx stuff when the HAVE_BSD_REGS_T doesn't seem to be defined.

@sec
Copy link
Contributor Author

sec commented Jun 28, 2022

build_log.txt
freebsd_arm64_patch.txt

@janvorli Here's build output and git diff of everything I have tweaked :)

edit: accoring to CMakeOutput.txt, BSD_REG check passed:

Run Build Command(s):/usr/local/bin/gmake -f Makefile cmTC_c2fef/fast && /usr/local/bin/gmake -f CMakeFiles/cmTC_c2fef.dir/build.make CMakeFiles/cmTC_c2fef.dir/build
gmake[1]: Entering directory '/usr/home/sec/runtime/artifacts/obj/coreclr/FreeBSD.arm64.Debug/CMakeFiles/CMakeTmp'
Building C object CMakeFiles/cmTC_c2fef.dir/BSD_REGS_T.c.o
/usr/local/bin/clang14 -D_FILE_OFFSET_BITS=64 -I/usr/local/include -fPIE -MD -MT CMakeFiles/cmTC_c2fef.dir/BSD_REGS_T.c.o -MF CMakeFiles/cmTC_c2fef.dir/BSD_REGS_T.c.o.d -o CMakeFiles/cmTC_c2fef.dir/BSD_REGS _T.c.o -c /usr/home/sec/runtime/artifacts/obj/coreclr/FreeBSD.arm64.Debug/CMakeFiles/CheckTypeSize/BSD_REGS_T.c
Linking C executable cmTC_c2fef
/usr/local/bin/cmake -E cmake_link_script CMakeFiles/cmTC_c2fef.dir/link.txt --verbose=1
/usr/local/bin/clang14 -fuse-ld=lld -pie -Wl,--build-id=sha1 CMakeFiles/cmTC_c2fef.dir/BSD_REGS_T.c.o -o cmTC_c2fef
gmake[1]: Leaving directory '/usr/home/sec/runtime/artifacts/obj/coreclr/FreeBSD.arm64.Debug/CMakeFiles/CMakeTmp'
CMakeError.log
CMakeOutput.log

edit 2: added CMakeFiles output, maybe it will help also

@janvorli
Copy link
Member

Ah, I've forgotten that the check_type_size("struct reg" BSD_REGS_T) doesn't log anything. In that case, we need to add definitions for BSDREG_xxx stuff. The HAVE_BSD_REGS_T branch in the source assumes it is either x64 or x86. So in context.h, look for the #if HAVE_BSD_REGS_T and then #ifdef HOST_64BIT under that. Inside that #ifdef, we need to put the current stuff under #ifdef HOST_AMD64 and add #elif defined(HOST_ARM64) branch where we put the following:

#define BSDREG_X0(reg) BSD_REGS_STYLE(reg,X[0],x[0])
.
.
.
#define BSDREG_X29(reg) BSD_REGS_STYLE(reg,X[29],x[29])
#define BSDREG_Fp(reg) BSD_REGS_STYLE(reg,Fp,fp)
#define BSDREG_Sp(reg) BSD_REGS_STYLE(reg,Sp,sp)
#define BSDREG_Pc(reg) BSD_REGS_STYLE(reg,Pc,pc)
#define BSDREG_Lr(reg) BSD_REGS_STYLE(reg,Lr,lr)
#define BSDREG_Cpsr(reg) BSD_REGS_STYLE(reg,Spsr,spsr)

And then in src/coreclr/pal/src/configure.cmake, find elseif(CLR_CMAKE_TARGET_FREEBSD). In that branch, the set(BSD_REGS_STYLE "((reg).r_##rr)") has to be different for amd64 and arm64. For arm64, it needs to be set(BSD_REGS_STYLE "((reg).rr)"), because the naming convention of the registers is different there. So it should be:

if (CLR_CMAKE_HOST_ARCH_AMD64)
  set(BSD_REGS_STYLE "((reg).r_##rr)")
elseif(CLR_CMAKE_HOST_ARCH_ARM64)
  set(BSD_REGS_STYLE "((reg).rr)")
else()
  message(FATAL_ERROR "Unknown FreeBSD architecture")
endif()

@sec
Copy link
Contributor Author

sec commented Jun 28, 2022

Thanks, will try that - any idea what about missing MCREG_Pc and MCREG_Fp - can't see those inside ucontext struct (or the name is not close to that) ?

@janvorli
Copy link
Member

Ah, sorry, the Fp is X29, so it should be

#define MCREG_Fp(mc)      (mc.mc_gpregs.gp_x[29])

And the MCREG_Pc - hmm, that's strange. I can see that there is gp_lr and gp_elr. I think that maybe the gp_elr is in fact the Pc.

Also related to the x29 above, for the most recent change I've suggested, this is wrong:

#define BSDREG_X29(reg) BSD_REGS_STYLE(reg,X[29],x[29])
#define BSDREG_Fp(reg) BSD_REGS_STYLE(reg,Fp,fp)

It should be just

#define BSDREG_Fp(reg) BSD_REGS_STYLE(reg,X[29],x[29])

@Thefrank
Copy link
Contributor

With everything so far:
freebsd_arm_patch.txt

/home/frank/runtime/src/coreclr/pal/src/thread/context.cpp:339:9: error: no member named 'pc' in 'reg'
        ASSIGN_ALL_REGS
        ^~~~~~~~~~~~~~~
/home/frank/runtime/src/coreclr/pal/src/thread/context.cpp:286:9: note: expanded from macro 'ASSIGN_ALL_REGS'
        ASSIGN_CONTROL_REGS \
        ^~~~~~~~~~~~~~~~~~~
/home/frank/runtime/src/coreclr/pal/src/thread/context.cpp:141:9: note: expanded from macro 'ASSIGN_CONTROL_REGS'
        ASSIGN_REG(Pc)
        ^~~~~~~~~~~~~~
/home/frank/runtime/src/coreclr/pal/src/thread/context.cpp:333:62: note: expanded from macro 'ASSIGN_REG'
#define ASSIGN_REG(reg) MCREG_##reg(registers.uc_mcontext) = BSDREG_##reg(ptrace_registers);
                                                             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<scratch space>:310:1: note: expanded from here
BSDREG_Pc
^
/home/frank/runtime/src/coreclr/pal/src/include/pal/context.h:1020:46: note: expanded from macro 'BSDREG_Pc'
#define BSDREG_Pc(reg) BSD_REGS_STYLE(reg,Pc,pc)
                       ~~~~~~~~~~~~~~~~~~~~~~^~~
/home/frank/runtime/artifacts/obj/coreclr/FreeBSD.arm64.Debug/pal/src/config.h:158:44: note: expanded from macro 'BSD_REGS_STYLE'
#define BSD_REGS_STYLE(reg, RR, rr) ((reg).rr)
                                     ~~~~~ ^
/home/frank/runtime/src/coreclr/pal/src/thread/context.cpp:491:13: error: no member named 'pc' in 'reg'
            ASSIGN_CONTROL_REGS
            ^~~~~~~~~~~~~~~~~~~
/home/frank/runtime/src/coreclr/pal/src/thread/context.cpp:141:9: note: expanded from macro 'ASSIGN_CONTROL_REGS'
        ASSIGN_REG(Pc)
        ^~~~~~~~~~~~~~
/home/frank/runtime/src/coreclr/pal/src/thread/context.cpp:483:25: note: expanded from macro 'ASSIGN_REG'
#define ASSIGN_REG(reg) BSDREG_##reg(ptrace_registers) = lpContext->reg;
                        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<scratch space>:385:1: note: expanded from here
BSDREG_Pc
^
/home/frank/runtime/src/coreclr/pal/src/include/pal/context.h:1020:46: note: expanded from macro 'BSDREG_Pc'
#define BSDREG_Pc(reg) BSD_REGS_STYLE(reg,Pc,pc)
                       ~~~~~~~~~~~~~~~~~~~~~~^~~
/home/frank/runtime/artifacts/obj/coreclr/FreeBSD.arm64.Debug/pal/src/config.h:158:44: note: expanded from macro 'BSD_REGS_STYLE'
#define BSD_REGS_STYLE(reg, RR, rr) ((reg).rr)
                                     ~~~~~ ^
/home/frank/runtime/src/coreclr/pal/src/thread/context.cpp:600:9: error: unknown type name 'fpsimd_context'
        fpsimd_context* fp = GetNativeSigSimdContext(native);
        ^
/home/frank/runtime/src/coreclr/pal/src/thread/context.cpp:744:15: error: unknown type name 'fpsimd_context'
        const fpsimd_context* fp = GetConstNativeSigSimdContext(native);
              ^
4 errors generated.

(Note: using Ubuntu 18.04 with FreeBSD AARCH64 crossroot)

@janvorli
Copy link
Member

Ok, sounds like again elr vs pc.
So can you please make this change?:

#define BSDREG_Pc(reg) BSD_REGS_STYLE(reg,Elr,elr)

Last thing is the floating point context. In context.cpp at line 743, we'll need to add before the #else:

#elif TARGET_FREEBSD
        const struct fpregs* fp = GetConstNativeSigSimdContext(native);
        if (fp)
        {
            lpContext->Fpsr = fp->fp_sr;
            lpContext->Fpcr = fp->fp_cr;
            for (int i = 0; i < 32; i++)
            {
                lpContext->V[i] = *(NEON128*) &fp->q[i];
            }
        }

Similarly at line 599, we need to add before the #else:

#elif TARGET_FREEBSD
        struct fpregs* fp = GetNativeSigSimdContext(native);
        if (fp)
        {
            fp->fp_sr = lpContext->Fpsr;
            fp->fp_cr = lpContext->Fpcr;
            for (int i = 0; i < 32; i++)
            {
                *(NEON128*) &fp->q[i] = lpContext->V[i];
            }
        }

@Thefrank
Copy link
Contributor

Including above code:

/home/frank/runtime/src/coreclr/pal/src/thread/context.cpp:607:34: error: no member named 'q' in 'fpregs'
                *(NEON128*) &fp->q[i] = lpContext->V[i];
                             ~~  ^
/home/frank/runtime/src/coreclr/pal/src/thread/context.cpp:762:52: error: no member named 'q' in 'fpregs'
                lpContext->V[i] = *(NEON128*) &fp->q[i];
                                               ~~  ^
2 errors generated.

Not sure why its throwing that. usr/include/machine/ucontext.h on the crossrootfs has that member and seen (https://github.com/freebsd/freebsd-src/blob/373ffc62c158e52cde86a5b934ab4a51307f9f2e/sys/arm64/include/ucontext.h#L45)

@sec
Copy link
Contributor Author

sec commented Jun 29, 2022

@janvorli Big thanks for help/pointers. I was able to compile coreclr part (there were some typos to fix):

Repo successfully built.
Product binaries are available at /usr/home/sec/runtime/artifacts/bin/coreclr/FreeBSD.arm64.Debug

Also I've pushed those changes here main...sec:runtime:freebsd.arm64
Any way to test if all those register parts are working correctly (aka how to run the tests for the part that just got compiled) ?

@Thefrank I also took few changes from your patch regarding RID's - thanks :) Would you be able to try to cross compile under Linux? I've tried, but on my setup (Linux ARM64) it fails with:

Scanning dependencies of target coreclrpal
[  1%] Building CXX object pal/src/CMakeFiles/coreclrpal.dir/cruntime/file.cpp.o
[  1%] Building C object libs-native/System.Native/CMakeFiles/System.Native-Static.dir/pal_tcpstate.c.o
In file included from /home/ubuntu/runtime/src/coreclr/pal/src/cruntime/file.cpp:21:
/home/ubuntu/runtime/src/coreclr/pal/src/include/pal/palinternal.h:158:10: fatal error: 'type_traits' file not found
#include <type_traits>
         ^~~~~~~~~~~~~
[  1%] Building C object libs-native/System.IO.Compression.Native/CMakeFiles/System.IO.Compression.Native-Static.dir/home/ubuntu/runtime/src/native/external/brotli/enc/backward_references.c.o
[  1%] Building C object libs-native/System.Native/CMakeFiles/System.Native-Static.dir/pal_threading.c.o
1 error generated.
make[2]: *** [pal/src/CMakeFiles/coreclrpal.dir/build.make:76: pal/src/CMakeFiles/coreclrpal.dir/cruntime/file.cpp.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:2020: pal/src/CMakeFiles/coreclrpal.dir/all] Error 2
make[1]: *** Waiting for unfinished jobs....

Also if you'll take my branch, those can also be needed - don't know if those are needed or it's just my setup:

diff --git a/eng/common/cross/toolchain.cmake b/eng/common/cross/toolchain.cmake
index d5dfc13504b..478029410b7 100644
--- a/eng/common/cross/toolchain.cmake
+++ b/eng/common/cross/toolchain.cmake
@@ -133,7 +133,11 @@ elseif(FREEBSD)
     set(CMAKE_CXX_COMPILER_TARGET ${triple})
     set(CMAKE_ASM_COMPILER_TARGET ${triple})
     set(CMAKE_SYSROOT "${CROSS_ROOTFS}")
-    set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=lld")
+    if(CLR_CMAKE_HOST_OS STREQUAL FreeBSD)
+      set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=lld")
+    else()
+      set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=lld -stdlib=libc++ -Qunused-arguments")
+    endif()
     set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fuse-ld=lld")
     set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -fuse-ld=lld")
 elseif(ILLUMOS)
diff --git a/eng/native/configuretools.cmake b/eng/native/configuretools.cmake
index 6697524c659..b44bcc3417c 100644
--- a/eng/native/configuretools.cmake
+++ b/eng/native/configuretools.cmake
@@ -54,7 +54,11 @@ if(NOT WIN32 AND NOT CLR_CMAKE_TARGET_BROWSER)
       set(TOOLSET_PREFIX ${ANDROID_TOOLCHAIN_PREFIX})
     elseif(CMAKE_CROSSCOMPILING AND NOT DEFINED CLR_CROSS_COMPONENTS_BUILD AND
         CMAKE_SYSTEM_PROCESSOR MATCHES "^(armv8l|armv7l|armv6l|aarch64|arm|s390x|ppc64le)$")
-      set(TOOLSET_PREFIX "${TOOLCHAIN}-")
+      if(FREEBSD)
+        set(TOOLSET_PREFIX "llvm-")
+      else()
+        set(TOOLSET_PREFIX "${TOOLCHAIN}-")
+      endif()
     else()
       set(TOOLSET_PREFIX "")
     endif()

What should be next steps to get full SDK - as under FreeBSD ARM64 I don't have bootstrapped one, I think I will move to AMD64 FreeBSD and try there to cross compile?

edit: @Thefrank for the error, it's fp_q and also sorry I wrongly tagged @wfurt :)

edit 2: cross build under FreeBSD is going well... does this mean I will have working SDK on FreeBSD-arm64? 🤞

@janvorli
Copy link
Member

@sec I was happy to help. As for testing whether these changes are correct, running coreclr tests is the best way. These code paths are exercised by exception handling.
On the target, you can build all coreclr tests (in checked flavor, which means mostly optimized code, but including asserts in PAL / runtime) using

src/tests/build.sh checked -priority1

(Please note that you have to have the runtime clr+libs part built there before building the tests.)

And then run them using

src/tests/run.sh checked

@sec
Copy link
Contributor Author

sec commented Jun 29, 2022

Hm, not that easy @janvorli :) While doing crosscompile under FreeBSD-amd64, using command
ROOTFS_DIR=/home/sec/arm64_rootfs eng/build.sh -ci -c Debug -cross -os FreeBSD -a arm64 /p:IsEligibleForNgenOptimization=false -subset Clr.Native+Host.Native it fails after soem time:

  Repo successfully built.
  Product binaries are available at /usr/home/sec/runtime/artifacts/bin/coreclr/FreeBSD.arm64.Debug
  Executing "/usr/home/sec/runtime/src/coreclr/build-runtime.sh" -arm64 -cmakeargs "-DCLR_CROSS_COMPONENTS_BUILD=1" -debug -ci -os FreeBSD -hostarch x64 -component crosscomponents
  Commencing CoreCLR Repo build
  __DistroRid: freebsd-arm64
  Setting up directories for build
  Checking prerequisites...
  Commencing build of "  crosscomponents " target in "CoreCLR component" for FreeBSD.arm64.Debug in /usr/home/sec/runtime/artifacts/obj/coreclr/FreeBSD.arm64.Debug/x64
  Invoking "/usr/home/sec/runtime/eng/native/gen-buildsys.sh" "/usr/home/sec/runtime/src/coreclr" "/usr/home/sec/runtime/artifacts/obj/coreclr/FreeBSD.arm64.Debug/x64" x64 clang Debug ""  -DCLR_CMAKE_TARGET_ARCH=arm64 -DCLR_CMAKE_PGO_INSTRUMENT=0 -DCLR_CMAKE_OPTDATA_PATH= -DCLR_CMAKE_PGO_OPTIMIZE=0 -DFEATURE_DISTRO_AGNOSTIC_SSL=1 -DCLR_CROSS_COMPONENTS_BUILD=1
  /usr/home/sec/runtime/artifacts/obj/coreclr/FreeBSD.arm64.Debug/x64 /usr/home/sec/runtime/src/coreclr
  Not searching for unused variables given on the command line.
  -- The C compiler identification is Clang 10.0.1
  -- The CXX compiler identification is Clang 10.0.1

...

  [  2%] Linking CXX static library libgcinfo_universal_arm64.a
  In file included from /usr/home/sec/runtime/src/coreclr/pal/src/exception/seh.cpp:407:
  In file included from /usr/home/sec/runtime/src/coreclr/pal/src/exception/seh-unwind.cpp:34:
  /home/sec/arm64_rootfs/usr/local/include/libunwind.h:25:11: fatal error: 'libunwind-x86_64.h' file not found
  # include "libunwind-x86_64.h"
            ^~~~~~~~~~~~~~~~~~~~
  [  2%] Built target gcinfo_universal_arm64
  [  2%] Building CXX object pal/src/CMakeFiles/coreclrpal.dir/file/directory.cpp.o
  1 error generated.
  --- pal/src/CMakeFiles/coreclrpal.dir/exception/seh.cpp.o ---
  *** [pal/src/CMakeFiles/coreclrpal.dir/exception/seh.cpp.o] Error code 1

  make[3]: stopped in /usr/home/sec/runtime/artifacts/obj/coreclr/FreeBSD.arm64.Debug/x64
  --- CMakeFiles/crosscomponents.dir/rule ---
  *** [CMakeFiles/crosscomponents.dir/rule] Error code 6

  make[1]: stopped in /usr/home/sec/runtime/artifacts/obj/coreclr/FreeBSD.arm64.Debug/x64
  1 error

  make[1]: stopped in /usr/home/sec/runtime/artifacts/obj/coreclr/FreeBSD.arm64.Debug/x64
  *** [crosscomponents] Error code 2

  make: stopped in /usr/home/sec/runtime/artifacts/obj/coreclr/FreeBSD.arm64.Debug/x64

  make: stopped in /usr/home/sec/runtime/artifacts/obj/coreclr/FreeBSD.arm64.Debug/x64
  1 error
  /usr/home/sec/runtime/src/coreclr

What's going on in here? @Thefrank how's your Linux crossbuild?

@janvorli
Copy link
Member

The cross components that are failing to build are compiled for x64, so they should be built on the host without the rootfs usage. It seems like there is some problem causing that the rootfs is still being used.

@Thefrank
Copy link
Contributor

Thefrank commented Jun 29, 2022

So for my Ubuntu 18.04 AMD64 -> FreeBSD AARCH64 an old bug has presented itself:
[edit: ROOTFS_DIR=/home/frank/freebsdarm/ ./src/coreclr/build-runtime.sh -arm64 --clang11 -cross -os FreeBSD]

/home/frank/runtime/src/coreclr/debug/daccess/daccess.cpp:6996:38: error: invalid suffix 'x' on integer constant
    *dacTableAddress = baseAddress + DAC_TABLE_RVA;
                                     ^
/home/frank/runtime/artifacts/obj/coreclr/FreeBSD.arm64.Debug/inc/dactablerva.h:1:24: note: expanded from macro 'DAC_TABLE_RVA'
#define DAC_TABLE_RVA 0x          c06bb8
                       ^
1 error generated.

Previously under net6, this could be worked around in eng/native/gen-buildsys.sh

diff --git a/eng/native/gen-buildsys.sh b/eng/native/gen-buildsys.sh
index bf04c26f2b1..7d8793dd92c 100755
--- a/eng/native/gen-buildsys.sh
+++ b/eng/native/gen-buildsys.sh
@@ -97,7 +97,7 @@ if [[ "$build_arch" == "wasm" ]]; then
     cmake_command="emcmake $cmake_command"
 fi

-cmake_args_to_cache="$scan_build\n$SCAN_BUILD_COMMAND\n$generator\n$__UnprocessedCMakeArgs"
+cmake_args_to_cache=$(printf "$scan_build${SCAN_BUILD_COMMAND:+ }${SCAN_BUILD_COMMAND} $generator $__UnprocessedCMakeArgs")
 cmake_args_cache_file="$2/cmake_cmd_line.txt"
 if [[ -z "$__ConfigureOnly" ]]; then
     if [[ -e "$cmake_args_cache_file" ]]; then

This whole codeblock was removed in d22acef so this hacky-workaround won't work.

@sec
Copy link
Contributor Author

sec commented Jan 30, 2024 via email

@sec
Copy link
Contributor Author

sec commented Jan 31, 2024

@arrowd @Thefrank

I did some updates to port and did complete build on clean 14 arm64 VM in Azure (had to comment out this compat line and copy those libs by hand).

Changes here https://github.com/sec/freebsd-ports/tree/lang-dotnet-arm64
Needed bootstrap files you can find here https://github.com/sec/dotnet-core-freebsd-source-build/releases/tag/8.0.100-vmr (dotnet-sdk-8.0.100-freebsd-arm64.tar.gz and Private.SourceBuilt.Artifacts.8.0.100-rtm.23551.1.freebsd.13-arm64.tar.gz)

atm I don't have 13.2 with arm64 available (Azure have only 14 image available) for the build - will try to hack something and test build on that, but it should be the same result.

During the build, I hit one weird error during installer phase build crossgen2[69365]: stack overflow detected; terminated also /root/freebsd-ports/lang/dotnet/work/dotnet-8.0.0/src/installer/artifacts/source-build/self/src/src/redist/targets/Crossgen.targets(171,5): error MSB6006: "crossgen2" exited with code 139. [/root/freebsd-ports/lang/dotnet/work/dotnet-8.0.0/src/installer/artifacts/source-build/self/src/src/redist/redist.csproj].
There were some ghost dotnet build processes left, terminating them and running make again fixed the issue - hope we don't hit that on build servers.

Maybe we should patch the build scripts to terminate hanging processes during build stage of each repo?

@arrowd
Copy link
Contributor

arrowd commented Jan 31, 2024

JFYI, I have updated compat13x to support aarch64.

@Thefrank
Copy link
Contributor

@sec

During the build, I hit one weird error during installer phase build crossgen2[69365]: stack overflow detected; terminated also /root/freebsd-ports/lang/dotnet/work/dotnet-8.0.0/src/installer/artifacts/source-build/self/src/src/redist/targets/Crossgen.targets(171,5): error MSB6006: "crossgen2" exited with code 139. [/root/freebsd-ports/lang/dotnet/work/dotnet-8.0.0/src/installer/artifacts/source-build/self/src/src/redist/redist.csproj]. There were some ghost dotnet build processes left, terminating them and running make again fixed the issue - hope we don't hit that on build servers.

Left over processes during build can happen. The stack overflow is an odd one. I thought most of the crossgen issues were resolved in libunwind 1.8.0. The log generated by the sourcebuild process for that leg of the build should have more info. check artifacts/logs/installer.log

Maybe we should patch the build scripts to terminate hanging processes during build stage of each repo?

I think most build systems clean up left over processes on their own. It might be rather challenging determining which of the numerous dotnet processes started and shutdown during the build process is leftover without killing the grandparent dotnet

Changing gears a bit: can the ARM64 version use NativeAOT? This mostly pertains to patching in RIDs to installer.

@janvorli
Copy link
Member

stack overflow detected

I don't know what is the default size of stack for secondary threads on FreeBSD. It might be too small (e.g. for Linux MUSL, we had to explicitly change the default to about 1.5MB since the default was around 100kB IIRC). You could possibly enable the same code path for FreeBSD if it has a small secondary stack size. You can also override it for testing by setting the DOTNET_DefaultStackSize env variable. The value you set it to is in hexadecimal. so e.g. 180000 sets it to 1.5MB.

@sec
Copy link
Contributor Author

sec commented Feb 1, 2024

@Thefrank you mean can I do this?

sec@amper:~/aot % ~/dotnet8/dotnet publish -r freebsd-arm64 -c release /p:PublishAot=true
MSBuild version 17.8.3+195e7f5a3 for .NET
  Determining projects to restore...
  Restored /usr/home/sec/aot/aot.csproj (in 4.48 sec).
  aot -> /usr/home/sec/aot/bin/release/net8.0/freebsd-arm64/aot.dll
  Generating native code
  aot -> /usr/home/sec/aot/bin/release/net8.0/freebsd-arm64/publish/
sec@amper:~/aot % /usr/home/sec/aot/bin/release/net8.0/freebsd-arm64/publish/aot
aot*     aot.dbg*
sec@amper:~/aot % /usr/home/sec/aot/bin/release/net8.0/freebsd-arm64/publish/aot
Hello, World!
sec@amper:~/aot % uname -a
FreeBSD amper 13.2-RELEASE-p8 FreeBSD 13.2-RELEASE-p8 GENERIC arm64
sec@amper:~/aot % ldd /usr/home/sec/aot/bin/release/net8.0/freebsd-arm64/publish/aot
/usr/home/sec/aot/bin/release/net8.0/freebsd-arm64/publish/aot:
        libdl.so.1 => /usr/lib/libdl.so.1 (0x135a4017a000)
        libthr.so.3 => /lib/libthr.so.3 (0x135a40b74000)
        libc.so.7 => /lib/libc.so.7 (0x135a42234000)

@janvorli looking at man libthr looks like main thread stack is limited by kernel (and my box don't have that limit set). It can be reduced to 4MB on 64bit by setting LIBPTHREAD_SPLITSTACK_MAIN. Default stack size for threads created by main process is 2MB for 64bit - so this should be fine, right?

I did build on 13.2 under QEMU and hit that stack overflow on crossgen2 during runtime build. Have coredump for that, looked at bt but that's magic for me how to debug this stuff :)

And clean build on 14 just finished without any errors - @arrowd would it be OK to merge the changes I made into the port to enable arm64 builds also?

Also I tried to build 8.0.1 using the same port - no errors :)

@arrowd
Copy link
Contributor

arrowd commented Feb 3, 2024

@sec I have started building your port on my RockPro64. Hope it won't hit a resource cap.

@arrowd
Copy link
Contributor

arrowd commented Feb 4, 2024

I wasn't able to build .NET on my hardware because of out-of-memory issues. But the bootstrap provided by @sec seems to work, so I pushed these changes to the tree. Thanks Szczepan, we should now have .NET on FreeBSD aarch64 too!

@arrowd
Copy link
Contributor

arrowd commented Feb 17, 2024

Ugh, it failed on FreeBSD 15 in the crossgen2: https://pkg-status.freebsd.org/ampere2/data/main-arm64-default/pe9c9c73181b5_sbd45bbe440f/logs/dotnet-8.0.0.log

Not sure what to do with it now apart from marking it BROKEN for now.

@Thefrank
Copy link
Contributor

Thefrank commented Feb 18, 2024

From the log: "/wrkdirs/usr/ports/lang/dotnet/work/dotnet-8.0.0/src/installer/artifacts/source-build/self/src/artifacts/sourcebuild.binlog" should give a good idea what exactly happened.

edit: it also lists /wrkdirs/usr/ports/lang/dotnet/work/dotnet-8.0.0/artifacts/logs/installer.log which should also work but might not be as detailed

@sec
Copy link
Contributor Author

sec commented Feb 18, 2024

Looking at this error MSB6006: "crossgen2" exited with code 139 - this could be the same issue I git while building under qemu, could be that stack overflow error (would need to see dmesg logs, as this was SIGSEGV for sure). This could be related to zombie dotnet processes left during previous stages or something broken in runtime.

The failed stage was in installer - if you could gather logs/binlogs from that stage and post them, maybe we could find something inside. Maybe /wrkdirs/usr/ports/lang/dotnet/work/dotnet-8.0.0/src/installer/artifacts/log/Release/Build.binlog ?

Maybe some verbose flags could be added to build to have more info?
Are there builds planned/done for 13 and/or 14 - I haven't done any build on CURRENT.

As for BROKEN - I'm afraid if you do that, it will stay that way for a long time, as I don't have idea how to even start to debug this issue, as it's not 100% reproducable - some help from .net team on this topic would be valueable, if possible.

edit: maybe it will give more info to add --verbose to crossgen2 run if that's possible

@arrowd
Copy link
Contributor

arrowd commented Feb 21, 2024

edit: maybe it will give more info to add --verbose to crossgen2 run if that's possible

Can you give me a patch that plugs this flag in? I have no idea where to put it.

@sec
Copy link
Contributor Author

sec commented Feb 21, 2024

edit: maybe it will give more info to add --verbose to crossgen2 run if that's possible

Can you give me a patch that plugs this flag in? I have no idea where to put it.

The problem is somewhere deeper, for now leave it as it is - I saw that port build went fine under 13 arm64, so maybe it will catch up later.

I am a new user hit up. I don't know how can I use this one actually, somebody help me.

Make sure to use latest packages and pkg install lang/dotnet should get you up and running.

@arrowd
Copy link
Contributor

arrowd commented Feb 28, 2024

I don't have a hardware to reproduce this locally and I wasn't able to arrange access to the FreeBSD builder. I ended up marking dotnet as broken on 15-CURRENT AArch64.

@sec
Copy link
Contributor Author

sec commented Mar 13, 2024

Back to exited on signal 11 (core dumped) ... Like before it was random, now I have 100% reproduce rate, while trying to source-build 8.0.3 using SDK 8.0.2.

Error happen at almost latest stage of the build, while building installer repo.
It's pid 77281 (crossgen2), jid 0, uid 1001: exited on signal 11 (core dumped).

I have both binlog's and coredump.

Looking at binlog, it fail at one of the Task Crossgen, the command user is for example (DLL change):

> /mnt/sec/freebsd-ports/lang/dotnet/work/dotnet-8.0.3/src/installer/artifacts/source-build/self/package-cache//microsoft.netcore.app.crossgen2.freebsd-arm64/8.0.3/tools/crossgen2 "/mnt/sec/freebsd-ports/lang/dotnet/work/dotnet-8.0.3/src/installer/artifacts/source-build/self/src/artifacts/bin/redist/Release/dotnet/sdk/8.0.103/Roslyn/bincore/Microsoft.CodeAnalysis.dll" -o "/tmp/zjde05vv.eap/Microsoft.CodeAnalysis.dll" --targetarch arm64 -r /mnt/sec/freebsd-ports/lang/dotnet/work/dotnet-8.0.3/src/installer/artifacts/source-build/self/src/artifacts/bin/redist/Release/dotnet/sdk/8.0.103/Roslyn/bincore/*.dll -r /mnt/sec/freebsd-ports/lang/dotnet/work/dotnet-8.0.3/src/installer/artifacts/source-build/self/src/artifacts/bin/redist/Release/dotnet/shared/Microsoft.NETCore.App/8.0.3/*.dll  --perfmap 

Fun fact - when I try to run this by hand, it works and emit proper files, but during build it fails with /mnt/sec/freebsd-ports/lang/dotnet/work/dotnet-8.0.3/src/installer/artifacts/source-build/self/src/src/redist/targets/Crossgen.targets(162,5): error MSB6006: "crossgen2" exited with code 139. [/mnt/sec/freebsd-ports/lang/dotnet/work/dotnet-8.0.3/src/installer/artifacts/source-build/self/src/src/redist/redist.csproj] - just need to add " around -r - but that's not it...

After build fail, there's one zombie dotnet process

/mnt/sec/freebsd-ports/lang/dotnet/work/bootstrap_sdk/dotnet exec /mnt/sec/freebsd-ports/lang/dotnet/work/bootstrap_sdk/sdk/8.0.102/Roslyn/bincore/VBCSCompiler.dll -pipename:QRZYlXzbMHXDLklcN9BMYGKX6fW4KPULnNkej0O97P8

It's using crossgen2 from the build itself, right? CrossgenPath = /mnt/sec/freebsd-ports/lang/dotnet/work/dotnet-8.0.3/src/installer/artifacts/source-build/self/package-cache//microsoft.netcore.app.crossgen2.freebsd-arm64/8.0.3/tools/crossgen2

No idea how to debug this further :/
Doing build under x64 without any problems.

Machine have enough disk space and almost 20GB+ RAM free (and 4 cores).

Any idea? Suggestions? Any magic switch?
Any place where I could add --verbose for crossgen2 that's being run or do I need to edit tasks code for that?

Binlog attached.

803_arm64.zip

@Thefrank
Copy link
Contributor

AFAIK Runtime, ASPNetCore, and Installer all use crossgen2. This has hopefully changed but runtime previously used the restored NuGet for crossgen2 (the other two used the freshly built one from runtime)

ASPNetCore handles it all in one project: https://github.com/dotnet/aspnetcore/blob/268a2dfc29b33e3fdb73cbac6eb198c05314d77e/src/Framework/App.Runtime/src/Microsoft.AspNetCore.App.Runtime.csproj

Installer handles crossgen targets here: https://github.com/dotnet/installer/blob/33549194e255cbaff0eda0d3cf688677b07e42ba/src/redist/targets/Crossgen.targets

The functioning and command line parameters of it here: https://github.com/dotnet/installer/blob/33549194e255cbaff0eda0d3cf688677b07e42ba/src/core-sdk-tasks/Crossgen.cs

Binlog is already -d diag or higher level of detail but this only applies to dotNET related functions (e.g. using make will not be verbose unless the command is manually told to be)

@janvorli
Copy link
Member

I think that binlog won't help much in figuring out the culprit. A crashdump would be helpful though. From the call stack, we should at least get some idea on where it is crashing.

@sec
Copy link
Contributor Author

sec commented Mar 14, 2024

Here's the bt all from the current fail (atm it's crashing during runtime build) - https://gist.github.com/sec/d2ab457eb8308bca2628a264a14a80b0

edit: runtime went ok after few tries, here's another one from aspnet stage - https://gist.github.com/sec/76d5d4d6565fe07940890be862bee31f

@janvorli
Copy link
Member

Hmm, the crashes are interesting, the crashing thread has zero instruction pointer, so it looks some context restoring went astray or some indirect jump went there or something like that. I think you may still be able to dig out details from the stack of that thread. I'd try to dump piece of the stack at current sp as data and search for addresses that can be looked up as being in libcoreclr.so (return addresses on the stack). That could allow us to reconstruct where it came from to that place.

@sec
Copy link
Contributor Author

sec commented Mar 14, 2024

@janvorli Thanks (again) for looking into this - anything more I could provide/extract (and how) to maybe help?

@janvorli
Copy link
Member

You can use x/32a $sp to dump 32 addresses at the current sp. That will dump addresses and also symbols for ones that are native code addresses.

@sec
Copy link
Contributor Author

sec commented Mar 14, 2024

Here you go

(lldb) x/32a $sp
0x436cc7d4ef0: 0x0000000000000000
0x436cc7d4ef8: 0x0000000000000000
0x436cc7d4f00: 0x0000000000000000
0x436cc7d4f08: 0x0000000000000000
0x436cc7d4f10: 0x0000000000000000
0x436cc7d4f18: 0x0000000000000000
0x436cc7d4f20: 0x0000000000000000
0x436cc7d4f28: 0x0000000000000000
0x436cc7d4f30: 0x0000000000000000
0x436cc7d4f38: 0x0000000000000000
0x436cc7d4f40: 0x0000000000000000
0x436cc7d4f48: 0x4010040140100401
0x436cc7d4f50: 0xa000000000000000
0x436cc7d4f58: 0xa000000000000000
0x436cc7d4f60: 0x0000000000000000
0x436cc7d4f68: 0x8020000000000000
0x436cc7d4f70: 0x0000000500000005
0x436cc7d4f78: 0x0000000000000000
0x436cc7d4f80: 0x03c903c903c903c9
0x436cc7d4f88: 0x03c903c903c903c9
0x436cc7d4f90: 0x0000000000000002
0x436cc7d4f98: 0x0000000000000001
0x436cc7d4fa0: 0x0000000000000000
0x436cc7d4fa8: 0x0000000000000000
0x436cc7d4fb0: 0x0000000000000000
0x436cc7d4fb8: 0x0000000000000000
0x436cc7d4fc0: 0x0000000000000000
0x436cc7d4fc8: 0x0000000000000000
0x436cc7d4fd0: 0x0000000000000000
0x436cc7d4fd8: 0x0000000000000000
0x436cc7d4fe0: 0x0000000000000000
0x436cc7d4fe8: 0x0000000000000000

@janvorli Isn't this connected with dotnet/source-build#4007 - just saw this...

edit: using crossgen2 binary from 8.0.100 SDK makes the build complete without errors... so the issue is still in 8.0.3 (as I assume this crossgen2 was built during the vmr build) ?

edit 2: also hitting the issue with cross-compiled 9.0.100-preview.2.24103.2 used to compile 9-preview.2 from vmr :(

@Thefrank
Copy link
Contributor

Thefrank commented May 4, 2024

Has this been resolved in net9p3?

@sec
Copy link
Contributor Author

sec commented May 5, 2024

The bug is in libunwind, fix for .net was to revert some recent changes in internal lib they use, but for FreeBSD we use the ports version which have this bug for some time now :(

@janvorli
Copy link
Member

janvorli commented May 6, 2024

You can possibly temporarily switch to using the internal libunwind copy. It is essentially the same code as upstream with a couple of patches that we remove as soon as a fix is made upstream.

@Thefrank
Copy link
Contributor

Thefrank commented May 7, 2024

AFAIK there should only be two places that need changes:

if(CLR_CMAKE_TARGET_OSX OR CLR_CMAKE_TARGET_FREEBSD OR CLR_CMAKE_TARGET_HAIKU)
# On OSX and *BSD, we use the libunwind that's part of the OS
# On Haiku, we used a special port of libunwind
set(CLR_CMAKE_USE_SYSTEM_LIBUNWIND 1)
endif(CLR_CMAKE_TARGET_OSX OR CLR_CMAKE_TARGET_FREEBSD OR CLR_CMAKE_TARGET_HAIKU)

if(CLR_CMAKE_TARGET_FREEBSD)
set(CLR_CMAKE_USE_SYSTEM_LIBUNWIND 1)
endif()

That should change the behavior back to using the internal version

@janvorli
Copy link
Member

janvorli commented May 7, 2024

Right, that should be all that's needed.

@sec
Copy link
Contributor Author

sec commented Aug 21, 2024

Small update for arm64 interested. Doing crossbuild for 9-preview.7 is possible (there are 2 patches needed for ILC, more here #104497). Using that as bootstrap for building natively runtime and aspnet mostly work - produced ILC segfaults becuase of missing symbols export. sdk/installer build and produce working SDK and the rest. Should be possible to perform VMR build, when ILC thing is resolved.

edit: ilc bug was resolved, it was my fault not to replace old nuget, so building all repos is a go.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

10 participants