Skip to content

Commit 42aa6c8

Browse files
trungnt2910jessicah
andcommitted
Haiku: Initial runtime support
This contains a part of the code required to build CoreCLR and get `paltests` to pass on Haiku. This commit covers native support code for the host and runtime libraries, which is located in `src/native/**`. Co-authored-by: Jessica Hamilton <[email protected]>
1 parent b9bfce3 commit 42aa6c8

File tree

10 files changed

+190
-12
lines changed

10 files changed

+190
-12
lines changed

src/native/corehost/hostmisc/pal.unix.cpp

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@
3030
#include <sys/types.h>
3131
#include <sys/param.h>
3232
#include <sys/sysctl.h>
33+
#elif defined(TARGET_HAIKU)
34+
#include <image.h>
35+
#include <OS.h>
36+
#include <sys/utsname.h>
3337
#endif
3438

3539
#if !HAVE_DIRENT_D_TYPE
@@ -136,6 +140,7 @@ bool pal::getcwd(pal::string_t* recv)
136140
return true;
137141
}
138142

143+
#if !defined(TARGET_HAIKU)
139144
namespace
140145
{
141146
bool get_loaded_library_from_proc_maps(const pal::char_t* library_name, pal::dll_t* dll, pal::string_t* path)
@@ -183,6 +188,7 @@ namespace
183188
return true;
184189
}
185190
}
191+
#endif // !TARGET_HAIKU
186192

187193
bool pal::get_loaded_library(
188194
const char_t* library_name,
@@ -197,6 +203,33 @@ bool pal::get_loaded_library(
197203
#endif
198204
library_name_local.append(library_name);
199205

206+
#if defined(TARGET_HAIKU)
207+
// Haiku does not have RTLD_NOLOAD so dlopen will attempt to load the library
208+
// instead of fetching a handle to the already loaded one.
209+
int32 cookie = 0;
210+
image_info info;
211+
212+
while (get_next_image_info(0, &cookie, &info) == B_OK)
213+
{
214+
if (info.type != B_LIBRARY_IMAGE)
215+
continue;
216+
217+
pal::string_t path_local(info.name);
218+
size_t pos = path_local.rfind(DIR_SEPARATOR);
219+
if (pos == std::string::npos)
220+
continue;
221+
222+
pos = path_local.find(library_name, pos);
223+
if (pos != std::string::npos)
224+
{
225+
*dll = (pal::dll_t)(intptr_t)info.id;
226+
path->assign(path_local);
227+
return true;
228+
}
229+
}
230+
231+
return false;
232+
#else
200233
dll_t dll_maybe = dlopen(library_name_local.c_str(), RTLD_LAZY | RTLD_NOLOAD);
201234
if (dll_maybe == nullptr)
202235
{
@@ -223,6 +256,7 @@ bool pal::get_loaded_library(
223256
*dll = dll_maybe;
224257
path->assign(info.dli_fname);
225258
return true;
259+
#endif
226260
}
227261

228262
bool pal::load_library(const string_t* path, dll_t* dll)
@@ -768,6 +802,21 @@ pal::string_t pal::get_current_os_rid_platform()
768802

769803
return ridOS;
770804
}
805+
#elif defined(TARGET_HAIKU)
806+
pal::string_t pal::get_current_os_rid_platform()
807+
{
808+
pal::string_t ridOS;
809+
struct utsname utsname_obj;
810+
if (uname(&utsname_obj) < 0)
811+
{
812+
return ridOS;
813+
}
814+
815+
ridOS.append(_X("haiku."))
816+
.append(utsname_obj.release); // e.g. haiku.1
817+
818+
return ridOS;
819+
}
771820
#else
772821
// For some distros, we don't want to use the full version from VERSION_ID. One example is
773822
// Red Hat Enterprise Linux, which includes a minor version in their VERSION_ID but minor

src/native/eventpipe/ds-ipc-pal-socket.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -433,7 +433,7 @@ inline
433433
int
434434
ipc_socket_set_permission (ds_ipc_socket_t s)
435435
{
436-
#if defined(DS_IPC_PAL_AF_UNIX) && !(defined(__APPLE__) || defined(__FreeBSD__))
436+
#if defined(DS_IPC_PAL_AF_UNIX) && !(defined(__APPLE__) || defined(__FreeBSD__) || defined(__HAIKU__))
437437
int result_fchmod;
438438
DS_ENTER_BLOCKING_PAL_SECTION;
439439
do {

src/native/libs/System.Native/pal_dynamicload.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,16 @@ void* SystemNative_LoadLibrary(const char* filename)
2121
// As a result, we have to use the full name (i.e. lib.so.6) that is defined by LIBC_SO.
2222
// * For macOS, use constant value absolute path "/usr/lib/libc.dylib".
2323
// * For FreeBSD, use constant value "libc.so.7".
24+
// * For Haiku, use constant value "libroot.so".
2425
// * For rest of Unices, use constant value "libc.so".
2526
if (strcmp(filename, "libc") == 0)
2627
{
2728
#if defined(__APPLE__)
2829
filename = "/usr/lib/libc.dylib";
2930
#elif defined(__FreeBSD__)
3031
filename = "libc.so.7";
32+
#elif defined(__HAIKU__)
33+
filename = "libroot.so";
3134
#elif defined(LIBC_SO)
3235
filename = LIBC_SO;
3336
#else

src/native/libs/System.Native/pal_io.c

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
#include <sys/vfs.h>
4747
#elif HAVE_STATFS_MOUNT // BSD
4848
#include <sys/mount.h>
49-
#elif HAVE_SYS_STATVFS_H && !HAVE_NON_LEGACY_STATFS // SunOS
49+
#elif HAVE_SYS_STATVFS_H && !HAVE_NON_LEGACY_STATFS && HAVE_STATVFS_BASETYPE // SunOS
5050
#include <sys/types.h>
5151
#include <sys/statvfs.h>
5252
#if HAVE_STATFS_VFS
@@ -58,6 +58,10 @@
5858
#include <sys/param.h>
5959
#endif
6060

61+
#ifdef TARGET_HAIKU
62+
#include <fs_info.h>
63+
#endif
64+
6165
#ifdef _AIX
6266
#include <alloca.h>
6367
// Somehow, AIX mangles the definition for this behind a C++ def
@@ -399,7 +403,7 @@ int32_t SystemNative_IsMemfdSupported(void)
399403
}
400404
#endif
401405

402-
// Note that the name has no affect on file descriptor behavior. From linux manpage:
406+
// Note that the name has no affect on file descriptor behavior. From linux manpage:
403407
// Names do not affect the behavior of the file descriptor, and as such multiple files can have the same name without any side effects.
404408
int32_t fd = (int32_t)syscall(__NR_memfd_create, "test", MFD_CLOEXEC | MFD_ALLOW_SEALING);
405409
if (fd < 0) return 0;
@@ -515,8 +519,13 @@ int32_t SystemNative_GetReadDirRBufferSize(void)
515519
#endif
516520
// dirent should be under 2k in size
517521
assert(result < 2048);
522+
#if HAVE_DIRENT_NAME_SIZE
518523
// add some extra space so we can align the buffer to dirent.
519524
return (int32_t)(result + dirent_alignment - 1);
525+
#else
526+
// add some extra space for the name.
527+
return sizeof(struct dirent) + NAME_MAX + dirent_alignment - 1;
528+
#endif
520529
#else
521530
return 0;
522531
#endif
@@ -882,8 +891,14 @@ void SystemNative_GetDeviceIdentifiers(uint64_t dev, uint32_t* majorNumber, uint
882891
{
883892
#if !defined(TARGET_WASI)
884893
dev_t castedDev = (dev_t)dev;
894+
#if !defined(TARGET_HAIKU)
885895
*majorNumber = (uint32_t)major(castedDev);
886896
*minorNumber = (uint32_t)minor(castedDev);
897+
#else /* TARGET_HAIKU */
898+
// Haiku has no concept of major/minor numbers, but it does have device IDs.
899+
*majorNumber = 0;
900+
*minorNumber = (uint32_t)dev;
901+
#endif /* TARGET_HAIKU */
887902
#else /* TARGET_WASI */
888903
dev_t castedDev = (dev_t)dev;
889904
*majorNumber = 0;
@@ -894,7 +909,12 @@ void SystemNative_GetDeviceIdentifiers(uint64_t dev, uint32_t* majorNumber, uint
894909
int32_t SystemNative_MkNod(const char* pathName, uint32_t mode, uint32_t major, uint32_t minor)
895910
{
896911
#if !defined(TARGET_WASI)
912+
#if !defined(TARGET_HAIKU)
897913
dev_t dev = (dev_t)makedev(major, minor);
914+
#else /* TARGET_HAIKU */
915+
(void)major;
916+
dev_t dev = (dev_t)minor;
917+
#endif /* TARGET_HAIKU */
898918

899919
int32_t result;
900920
while ((result = mknod(pathName, (mode_t)mode, dev)) < 0 && errno == EINTR);
@@ -1641,7 +1661,7 @@ static int16_t ConvertLockType(int16_t managedLockType)
16411661
}
16421662
}
16431663

1644-
#if !HAVE_NON_LEGACY_STATFS || defined(TARGET_APPLE) || defined(TARGET_FREEBSD)
1664+
#if !HAVE_NON_LEGACY_STATFS || defined(TARGET_APPLE) || defined(TARGET_FREEBSD) || defined(TARGET_HAIKU)
16451665
static uint32_t MapFileSystemNameToEnum(const char* fileSystemName)
16461666
{
16471667
uint32_t result = 0;
@@ -1800,9 +1820,28 @@ uint32_t SystemNative_GetFileSystemType(intptr_t fd)
18001820
uint32_t result = (uint32_t)statfsArgs.f_type;
18011821
return result;
18021822
#endif
1823+
#elif defined(TARGET_HAIKU)
1824+
struct stat st;
1825+
int fstatRes;
1826+
while ((fstatRes = fstat(ToFileDescriptor(fd), &st)) == -1 && errno == EINTR) ;
1827+
if (fstatRes == -1) return 0;
1828+
1829+
struct fs_info info;
1830+
int fsStatDevRes;
1831+
while ((fsStatDevRes = fs_stat_dev(st.st_dev, &info)) == -1 && errno == EINTR) ;
1832+
if (fsStatDevRes == -1) return 0;
1833+
1834+
if (strcmp(info.fsh_name, "bfs") == 0)
1835+
{
1836+
// Haiku names its own BFS filesystem "bfs", but on Linux and some other UNIXes
1837+
// it is called "befs" to avoid confusion with Boot File System.
1838+
strncpy(info.fsh_name, "befs", sizeof(info.fsh_name) - 1);
1839+
}
1840+
1841+
return MapFileSystemNameToEnum(info.fsh_name);
18031842
#elif defined(TARGET_WASI)
18041843
return EINTR;
1805-
#elif !HAVE_NON_LEGACY_STATFS
1844+
#elif !HAVE_NON_LEGACY_STATFS && HAVE_STATVFS_BASETYPE
18061845
int statfsRes;
18071846
struct statvfs statfsArgs;
18081847
while ((statfsRes = fstatvfs(ToFileDescriptor(fd), &statfsArgs)) == -1 && errno == EINTR) ;

src/native/libs/System.Native/pal_memory.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
#elif HAVE_MALLOC_USABLE_SIZE_NP
1818
#include <malloc_np.h>
1919
#define MALLOC_SIZE(s) malloc_usable_size(s)
20-
#elif defined(TARGET_SUNOS)
20+
#elif defined(TARGET_SUNOS) || defined(TARGET_HAIKU)
2121
#define MALLOC_SIZE(s) (*((size_t*)(s)-1))
2222
#else
2323
#error "Platform doesn't support malloc_usable_size or malloc_size"

src/native/libs/System.Native/pal_mount.c

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,24 @@
1313
#if HAVE_MNTINFO
1414
#include <sys/mount.h>
1515
#else
16+
#if HAVE_SYS_STATFS_H
1617
#include <sys/statfs.h>
18+
#endif
1719
#if HAVE_SYS_MNTENT_H
1820
#include <sys/mntent.h>
1921
#include <sys/mnttab.h>
20-
#include <sys/statvfs.h>
21-
#else
22+
#elif HAVE_MNTENT_H
2223
#include <mntent.h>
2324
#endif
25+
#include <sys/statvfs.h>
2426
#define STRING_BUFFER_SIZE 8192
2527

28+
#ifdef __HAIKU__
29+
#include <dirent.h>
30+
#include <fs_info.h>
31+
#include <fs_query.h>
32+
#endif
33+
2634
// Android does not define MNTOPT_RO
2735
#ifndef MNTOPT_RO
2836
#define MNTOPT_RO "r"
@@ -68,7 +76,7 @@ int32_t SystemNative_GetAllMountPoints(MountPointFound onFound, void* context)
6876
return result;
6977
}
7078

71-
#else
79+
#elif HAVE_MNTENT_H
7280
int result = -1;
7381
FILE* fp = setmntent("/proc/mounts", MNTOPT_RO);
7482
if (fp != NULL)
@@ -91,6 +99,39 @@ int32_t SystemNative_GetAllMountPoints(MountPointFound onFound, void* context)
9199
return result;
92100
}
93101

102+
#elif defined(__HAIKU__)
103+
(void)MNTOPT_RO;
104+
int32 cookie = 0;
105+
dev_t currentDev;
106+
107+
while ((long)(currentDev = next_dev(&cookie)) >= 0)
108+
{
109+
struct fs_info info;
110+
if (fs_stat_dev(currentDev, &info) != B_OK)
111+
{
112+
continue;
113+
}
114+
115+
char name[STRING_BUFFER_SIZE];
116+
// Two bytes for the name as we're storing "."
117+
char buf[sizeof(struct dirent) + 2];
118+
struct dirent *entry = (struct dirent *)&buf;
119+
strncpy(entry->d_name, ".", 2);
120+
entry->d_pdev = currentDev;
121+
entry->d_pino = info.root;
122+
123+
if (get_path_for_dirent(entry, name, sizeof(name)) != B_OK)
124+
{
125+
continue;
126+
}
127+
128+
onFound(context, name);
129+
}
130+
131+
return 0;
132+
}
133+
#else
134+
#error "Don't know how to enumerate mount points on this platform"
94135
#endif
95136

96137
int32_t SystemNative_GetSpaceInfoForMountPoint(const char* name, MountPointInformation* mpi)
@@ -140,6 +181,9 @@ SystemNative_GetFormatInfoForMountPoint(const char* name, char* formatNameBuffer
140181
#if HAVE_NON_LEGACY_STATFS
141182
struct statfs stats;
142183
int result = statfs(name, &stats);
184+
#elif defined(__HAIKU__)
185+
struct fs_info stats;
186+
int result = fs_stat_dev(dev_for_path(name), &stats);
143187
#else
144188
struct statvfs stats;
145189
int result = statvfs(name, &stats);
@@ -166,6 +210,17 @@ SystemNative_GetFormatInfoForMountPoint(const char* name, char* formatNameBuffer
166210
assert(formatType != NULL);
167211
*formatType = (int64_t)(stats.f_type);
168212
SafeStringCopy(formatNameBuffer, Int32ToSizeT(bufferLength), "");
213+
#elif defined(__HAIKU__)
214+
if (bufferLength < B_OS_NAME_LENGTH)
215+
{
216+
result = ERANGE;
217+
*formatType = 0;
218+
}
219+
else
220+
{
221+
SafeStringCopy(formatNameBuffer, Int32ToSizeT(bufferLength), stats.fsh_name);
222+
*formatType = -1;
223+
}
169224
#else
170225
*formatType = 0;
171226
#endif

src/native/libs/System.Native/pal_networkchange.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
#include <errno.h>
1212
#include <net/if.h>
13+
#include <stdlib.h>
1314
#include <sys/socket.h>
1415
#include <sys/types.h>
1516
#include <sys/uio.h>
@@ -38,6 +39,8 @@ Error SystemNative_CreateNetworkChangeListenerSocket(intptr_t* retSocket)
3839

3940
#elif HAVE_RT_MSGHDR
4041
int32_t sock = socket(PF_ROUTE, SOCK_RAW, 0);
42+
#else
43+
int32_t sock = -1;
4144
#endif
4245
if (sock == -1)
4346
{
@@ -177,6 +180,6 @@ Error SystemNative_ReadEvents(intptr_t sock, NetworkChangeEvent onNetworkChange)
177180
(void)onNetworkChange;
178181
// unreachable
179182
abort();
180-
return Error_SUCCESS;
183+
return Error_EINVAL;
181184
}
182185
#endif

0 commit comments

Comments
 (0)