Skip to content

Commit

Permalink
Haiku: Initial CoreCLR support
Browse files Browse the repository at this point in the history
This contains the code required to build CoreCLR and get
paltests to pass on Haiku.

Co-authored-by: Jessica Hamilton <[email protected]>
  • Loading branch information
trungnt2910 and jessicah committed Nov 5, 2023
1 parent 5c81a06 commit 72e7cc3
Show file tree
Hide file tree
Showing 51 changed files with 542 additions and 93 deletions.
20 changes: 18 additions & 2 deletions src/coreclr/debug/dbgutil/elfreader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,24 @@
#include <inttypes.h>
#include "elfreader.h"

#ifndef Elf_Ehdr
#define Elf_Ehdr ElfW(Ehdr)
#endif
#ifndef Elf_Phdr
#define Elf_Phdr ElfW(Phdr)
#endif
#ifndef Elf_Shdr
#define Elf_Shdr ElfW(Shdr)
#endif
#ifndef Elf_Nhdr
#define Elf_Nhdr ElfW(Nhdr)
#endif
#ifndef Elf_Dyn
#define Elf_Dyn ElfW(Dyn)
#endif
#ifndef Elf_Sym
#define Elf_Sym ElfW(Sym)
#endif

#if TARGET_64BIT
#define PRIx PRIx64
Expand All @@ -34,6 +46,10 @@
static const char ElfMagic[] = { 0x7f, 'E', 'L', 'F', '\0' };
#endif

#ifdef TARGET_HAIKU
#define DT_GNU_HASH DT_HASH
#endif

class ElfReaderExport : public ElfReader
{
private:
Expand Down Expand Up @@ -314,7 +330,7 @@ ElfReader::GetStringAtIndex(int index, std::string& result)
return true;
}

#ifdef HOST_UNIX
#if defined(HOST_UNIX) && !defined(TARGET_HAIKU)

//
// Enumerate all the ELF info starting from the root program header. This
Expand Down Expand Up @@ -414,7 +430,7 @@ ElfReader::EnumerateLinkMapEntries(Elf_Dyn* dynamicAddr)
return true;
}

#endif // HOST_UNIX
#endif // defined(HOST_UNIX) && !defined(TARGET_HAIKU)

bool
ElfReader::EnumerateProgramHeaders(uint64_t baseAddress, uint64_t* ploadbias, Elf_Dyn** pdynamicAddr)
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/debug/dbgutil/elfreader.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class ElfReader
void* m_symbolTableAddr; // DT_SYMTAB

GnuHashTable m_hashTable; // gnu hash table info
int32_t* m_buckets; // gnu hash table buckets
int32_t* m_buckets; // gnu hash table buckets
void* m_chainsAddress;

public:
Expand Down
4 changes: 2 additions & 2 deletions src/coreclr/gc/unix/cgroup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Module Name:
#if defined(__APPLE__) || defined(__FreeBSD__)
#include <sys/param.h>
#include <sys/mount.h>
#else
#elif !defined(__HAIKU__)
#include <sys/vfs.h>
#endif
#include <errno.h>
Expand Down Expand Up @@ -56,7 +56,7 @@ Module Name:

extern bool ReadMemoryValueFromFile(const char* filename, uint64_t* val);

namespace
namespace
{
class CGroup
{
Expand Down
30 changes: 24 additions & 6 deletions src/coreclr/gc/unix/gcenv.unix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@ extern "C"

#endif // __APPLE__

#ifdef __HAIKU__
#include <OS.h>
#endif // __HAIKU__

#ifdef __linux__
#include <sys/syscall.h> // __NR_membarrier
// Ensure __NR_membarrier is defined for portable builds.
Expand Down Expand Up @@ -527,7 +531,11 @@ static void* VirtualReserveInner(size_t size, size_t alignment, uint32_t flags,
}

size_t alignedSize = size + (alignment - OS_PAGE_SIZE);
void * pRetVal = mmap(nullptr, alignedSize, PROT_NONE, MAP_ANON | MAP_PRIVATE | hugePagesFlag, -1, 0);
int mmapFlags = MAP_ANON | MAP_PRIVATE | hugePagesFlag;
#ifdef __HAIKU__
mmapFlags |= MAP_NORESERVE;
#endif
void * pRetVal = mmap(nullptr, alignedSize, PROT_NONE, mmapFlags, -1, 0);

if (pRetVal != MAP_FAILED)
{
Expand Down Expand Up @@ -661,7 +669,11 @@ bool GCToOSInterface::VirtualDecommit(void* address, size_t size)
// that much more clear to the operating system that we no
// longer need these pages. Also, GC depends on re-committed pages to
// be zeroed-out.
bool bRetVal = mmap(address, size, PROT_NONE, MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0) != MAP_FAILED;
int mmapFlags = MAP_FIXED | MAP_ANON | MAP_PRIVATE;
#ifdef TARGET_HAIKU
mmapFlags |= MAP_NORESERVE;
#endif
bool bRetVal = mmap(address, size, PROT_NONE, mmapFlags, -1, 0) != MAP_FAILED;

#ifdef MADV_DONTDUMP
if (bRetVal)
Expand Down Expand Up @@ -955,7 +967,7 @@ static uint64_t GetMemorySizeMultiplier(char units)
return 1;
}

#ifndef __APPLE__
#if !defined(__APPLE__) && !defined(__HAIKU__)
// Try to read the MemAvailable entry from /proc/meminfo.
// Return true if the /proc/meminfo existed, the entry was present and we were able to parse it.
static bool ReadMemAvailable(uint64_t* memAvailable)
Expand Down Expand Up @@ -988,7 +1000,7 @@ static bool ReadMemAvailable(uint64_t* memAvailable)

return foundMemAvailable;
}
#endif // __APPLE__
#endif // !defined(__APPLE__) && !defined(__HAIKU__)

// Get size of the largest cache on the processor die
// Parameters:
Expand Down Expand Up @@ -1189,15 +1201,21 @@ uint64_t GetAvailablePhysicalMemory()
#elif defined(__FreeBSD__)
size_t inactive_count = 0, laundry_count = 0, free_count = 0;
size_t sz = sizeof(inactive_count);
sysctlbyname("vm.stats.vm.v_inactive_count", &inactive_count, &sz, NULL, 0);
sysctlbyname("vm.stats.vm.v_inactive_count", &inactive_count, &sz, NULL, 0);

sz = sizeof(laundry_count);
sysctlbyname("vm.stats.vm.v_laundry_count", &laundry_count, &sz, NULL, 0);
sysctlbyname("vm.stats.vm.v_laundry_count", &laundry_count, &sz, NULL, 0);

sz = sizeof(free_count);
sysctlbyname("vm.stats.vm.v_free_count", &free_count, &sz, NULL, 0);

available = (inactive_count + laundry_count + free_count) * sysconf(_SC_PAGESIZE);
#elif defined(__HAIKU__)
system_info info;
if (get_system_info(&info) == B_OK)
{
available = info.free_memory;
}
#else // Linux
static volatile bool tryReadMemInfo = true;

Expand Down
5 changes: 4 additions & 1 deletion src/coreclr/gc/unix/numasupport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@
#include <stdio.h>
#include <dirent.h>
#include <string.h>
#include <sys/syscall.h>
#include <minipal/utils.h>

#ifdef TARGET_LINUX
#include <sys/syscall.h>
#endif

// The highest NUMA node available
int g_highestNumaNode = 0;
// Is numa available
Expand Down
13 changes: 13 additions & 0 deletions src/coreclr/hosts/corerun/corerun.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,10 @@ class platform_specific_actions final
#include <ctype.h>
#endif // !__APPLE__

#if defined(__HAIKU__)
#include <OS.h>
#endif // __HAIKU__

// CMake generated
#include <config.h>
#include <minipal/getexepath.h>
Expand Down Expand Up @@ -441,6 +445,15 @@ namespace pal

return ( (info.kp_proc.p_flag & P_TRACED) != 0 ) ? debugger_state_t::attached : debugger_state_t::not_attached;

#elif defined(__HAIKU__)
team_info info;
assert(get_team_info(B_CURRENT_TEAM, &info) == B_OK);

// A "nub thread" is spawned by the debugger when it attaches to a process.
// While being debugged, the id of this thread is recorded in the team_info struct.
// Otherwise the field should be -1.

return (info.debugger_nub_thread > 0) ? debugger_state_t::attached : debugger_state_t::not_attached;
#else // !__APPLE__
// Use procfs to detect if there is a tracer process.
// See https://www.kernel.org/doc/html/latest/filesystems/proc.html
Expand Down
2 changes: 2 additions & 0 deletions src/coreclr/inc/crosscomp.h
Original file line number Diff line number Diff line change
Expand Up @@ -722,6 +722,8 @@ typedef struct _T_KNONVOLATILE_CONTEXT_POINTERS {
#define DAC_CS_NATIVE_DATA_SIZE 56
#elif defined(__sun) && defined(TARGET_AMD64)
#define DAC_CS_NATIVE_DATA_SIZE 48
#elif defined(TARGET_HAIKU) && defined(TARGET_AMD64)
#define DAC_CS_NATIVE_DATA_SIZE 56
#else
#warning
#error DAC_CS_NATIVE_DATA_SIZE is not defined for this architecture. This should be same value as PAL_CS_NATIVE_DATA_SIZE (aka sizeof(PAL_CS_NATIVE_DATA)).
Expand Down
33 changes: 22 additions & 11 deletions src/coreclr/minipal/Unix/doublemapping.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,22 @@ bool VMToOSInterface::CreateDoubleMemoryMapper(void** pHandle, size_t *pMaxExecu

#ifdef TARGET_FREEBSD
int fd = shm_open(SHM_ANON, O_RDWR | O_CREAT, S_IRWXU);
#elif defined(TARGET_SUNOS) // has POSIX implementation
char name[24];
sprintf(name, "/shm-dotnet-%d", getpid());
name[sizeof(name) - 1] = '\0';
shm_unlink(name);
int fd = shm_open(name, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW, 0600);
#else // TARGET_FREEBSD
#elif defined(TARGET_LINUX)
int fd = memfd_create("doublemapper", MFD_CLOEXEC);
#endif // TARGET_FREEBSD
#else
int fd = -1;
#endif

// POSIX fallback
if (fd == -1)
{
char name[24];
sprintf(name, "/shm-dotnet-%d", getpid());
name[sizeof(name) - 1] = '\0';
shm_unlink(name);
fd = shm_open(name, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW, 0600);
shm_unlink(name);
}

if (fd == -1)
{
Expand Down Expand Up @@ -148,10 +155,14 @@ void* VMToOSInterface::ReserveDoubleMappedMemory(void *mapperHandle, size_t offs

void* result = PAL_VirtualReserveFromExecutableMemoryAllocatorWithinRange(rangeStart, rangeEnd, size, 0 /* fStoreAllocationInfo */);
#ifndef TARGET_OSX
int mmapFlags = MAP_SHARED;
#ifdef TARGET_HAIKU
mmapFlags |= MAP_NORESERVE;
#endif // TARGET_HAIKU
if (result != NULL)
{
// Map the shared memory over the range reserved from the executable memory allocator.
result = mmap(result, size, PROT_NONE, MAP_SHARED | MAP_FIXED, fd, offset);
result = mmap(result, size, PROT_NONE, mmapFlags | MAP_FIXED, fd, offset);
if (result == MAP_FAILED)
{
assert(false);
Expand All @@ -167,15 +178,15 @@ void* VMToOSInterface::ReserveDoubleMappedMemory(void *mapperHandle, size_t offs
}

#ifndef TARGET_OSX
result = mmap(NULL, size, PROT_NONE, MAP_SHARED, fd, offset);
result = mmap(NULL, size, PROT_NONE, mmapFlags, fd, offset);
#else
int mmapFlags = MAP_ANON | MAP_PRIVATE;
if (IsMapJitFlagNeeded())
{
mmapFlags |= MAP_JIT;
}
result = mmap(NULL, size, PROT_NONE, mmapFlags, -1, 0);
#endif
#endif
if (result == MAP_FAILED)
{
assert(false);
Expand Down
5 changes: 4 additions & 1 deletion src/coreclr/nativeaot/Runtime/unix/PalCreateDump.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@

// Crash dump generating program arguments. MAX_ARGV_ENTRIES is the max number
// of entries if every createdump option/argument is passed.
#define MAX_ARGV_ENTRIES 32
#define MAX_ARGV_ENTRIES 32
const char* g_argvCreateDump[MAX_ARGV_ENTRIES] = { nullptr };
char* g_szCreateDumpPath = nullptr;
char* g_ppidarg = nullptr;
Expand All @@ -80,6 +80,9 @@ inline uint32_t PlatformGetCurrentThreadId() {
#elif defined(__NetBSD__)
#include <lwp.h>
#define PlatformGetCurrentThreadId() (uint32_t)_lwp_self()
#elif defined(__HAIKU__)
#include <OS.h>
#define PlatformGetCurrentThreadId() (uint32_t)find_thread(NULL)
#else
#define PlatformGetCurrentThreadId() (uint32_t)pthread_self()
#endif
Expand Down
11 changes: 10 additions & 1 deletion src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
#include <sched.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/syscall.h>
#include <dlfcn.h>
#include <dirent.h>
#include <string.h>
Expand All @@ -43,6 +42,10 @@
#include <cstdarg>
#include <signal.h>

#ifdef TARGET_LINUX
#include <sys/syscall.h>
#endif

#if HAVE_PTHREAD_GETTHREADID_NP
#include <pthread_np.h>
#endif
Expand All @@ -60,6 +63,10 @@
#include <mach-o/getsect.h>
#endif

#ifdef TARGET_HAIKU
#include <OS.h>
#endif

using std::nullptr_t;

#define PalRaiseFailFastException RaiseFailFastException
Expand Down Expand Up @@ -1242,6 +1249,8 @@ extern "C" uint64_t PalGetCurrentOSThreadId()
return (uint64_t)pthread_getthreadid_np();
#elif HAVE_LWP_SELF
return (uint64_t)_lwp_self();
#elif defined(__HAIKU__)
return (uint64_t)find_thread(NULL);
#else
// Fallback in case we don't know how to get integer thread id on the current platform
return (uint64_t)pthread_self();
Expand Down
20 changes: 20 additions & 0 deletions src/coreclr/nativeaot/Runtime/unix/UnixContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,26 @@

#endif // HOST_ARM64

#elif defined(__HAIKU__)

#define MCREG_Rip(mc) ((mc).rip)
#define MCREG_Rsp(mc) ((mc).rsp)
#define MCREG_Rax(mc) ((mc).rax)
#define MCREG_Rbx(mc) ((mc).rbx)
#define MCREG_Rcx(mc) ((mc).rcx)
#define MCREG_Rdx(mc) ((mc).rdx)
#define MCREG_Rsi(mc) ((mc).rsi)
#define MCREG_Rdi(mc) ((mc).rdi)
#define MCREG_Rbp(mc) ((mc).rbp)
#define MCREG_R8(mc) ((mc).r8)
#define MCREG_R9(mc) ((mc).r9)
#define MCREG_R10(mc) ((mc).r10)
#define MCREG_R11(mc) ((mc).r11)
#define MCREG_R12(mc) ((mc).r12)
#define MCREG_R13(mc) ((mc).r13)
#define MCREG_R14(mc) ((mc).r14)
#define MCREG_R15(mc) ((mc).r15)

#else

#if HAVE___GREGSET_T
Expand Down
4 changes: 4 additions & 0 deletions src/coreclr/nativeaot/Runtime/unix/UnixContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@
#ifndef __UNIX_CONTEXT_H__
#define __UNIX_CONTEXT_H__

#if HAVE_UCONTEXT_H
#include <ucontext.h>
#else
#include <signal.h>
#endif

// Convert Unix native context to PAL_LIMITED_CONTEXT
void NativeContextToPalContext(const void* context, PAL_LIMITED_CONTEXT* palContext);
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/nativeaot/Runtime/unix/cgroupcpu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ Module Name:
#if defined(__APPLE__) || defined(__FreeBSD__)
#include <sys/param.h>
#include <sys/mount.h>
#else
#elif !defined(__HAIKU__)
#include <sys/vfs.h>
#endif
#include <errno.h>
Expand Down
Loading

0 comments on commit 72e7cc3

Please sign in to comment.