From 91b8db1a172dd085555cf85115c48574025ceb76 Mon Sep 17 00:00:00 2001 From: tom-kuchler <87128754+tom-kuchler@users.noreply.github.com> Date: Tue, 23 Sep 2025 15:56:26 +0200 Subject: [PATCH 01/20] Add dev container, fix bugs in compiler setup Features added: * Add clang include directory to cfg * Adding statiging release * Add dev container * Add runtime library interface * Adding first version of unistd.c * Adding print for exit code at debug exit Bug Fixes: * Fix bugs in compiler cfg template * Fix namecmp to recognize substrings as non equal * Fix abi thread local issue, add test program build to top level cmake project * Fix makro in cmake template * Fix debug to handle unlimited number of input items or input-/outputsets --- ...ild_check.yml => release_experimental.yml} | 17 +- CMakeLists.txt | 52 ++++ Dockerfile | 34 ++ README.md | 28 ++ file_system/file_system.c | 32 +- file_system/file_system.h | 4 +- file_system/fs_implementation.c | 4 +- file_system/paths.h | 14 +- newlib_shim/Makefile.inc | 3 +- newlib_shim/patch_script | 1 + newlib_shim/shim.c | 4 + newlib_shim/unistd.c | 243 +++++++++++++++ runtime/CMakeLists.txt | 5 +- runtime/runtime.c | 15 +- runtime/runtime.h | 2 + sdk_install/CMakeLists.txt | 8 +- sdk_install/CMakeTemplate.txt | 3 - sdk_install/clang-template.cmake | 10 +- sdk_install/clangxx-template.cmake | 8 +- sdk_install/script-template.sh | 42 ++- sdk_install/toolchain-template.cmake | 2 +- system/platform/debug/debug.c | 294 +++++++++--------- test_programs/CMakeLists.txt | 12 - test_programs/libc/CMakeLists.txt | 2 + test_programs/libcpp/CMakeLists.txt | 7 + test_programs/libcpp/test.cpp | 2 +- 26 files changed, 641 insertions(+), 207 deletions(-) rename .github/workflows/{build_check.yml => release_experimental.yml} (71%) create mode 100644 Dockerfile create mode 100644 newlib_shim/unistd.c diff --git a/.github/workflows/build_check.yml b/.github/workflows/release_experimental.yml similarity index 71% rename from .github/workflows/build_check.yml rename to .github/workflows/release_experimental.yml index 4262d72..4c81d76 100644 --- a/.github/workflows/build_check.yml +++ b/.github/workflows/release_experimental.yml @@ -1,8 +1,8 @@ -name: make sure it still builds before merging into main +name: release latest with all library versions on: pull_request: - branches: [ "main" ] + branches: [ "dev/staging" ] jobs: build: @@ -57,4 +57,15 @@ jobs: run: cmake --build ${{ steps.build.outputs.dir }} - name: Install - run: cmake --install ${{ steps.build.outputs.dir }} + run: cmake --install ${{ steps.build.outputs.dir }} + + - name: Compress + shell: bash + working-directory: ${{ steps.build.outputs.dir }} + run: tar -czf "dandelion_sdk_${{matrix.build}}_${{matrix.platform}}_${{matrix.cpu}}.tar.gz" dandelion_sdk + + - name: Add to release + shell: bash + run: gh release upload experimental "${{ steps.build.outputs.dir }}/dandelion_sdk_${{matrix.build}}_${{matrix.platform}}_${{matrix.cpu}}.tar.gz" --clobber + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/CMakeLists.txt b/CMakeLists.txt index ae2a447..f18cb68 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,6 +15,7 @@ option(NEWLIB "toggles builing of newlib on top of dandelion interface" OFF) # string options set(ARCHITECTURE ${CMAKE_SYSTEM_PROCESSOR} CACHE STRING "the architecture to build for") set(DANDELION_PLATFORM "debug" CACHE STRING "backend to build for") +set(PAGE_SIZE "4096" CACHE STRING "Page size for the runtime to assume.") message(STATUS "Building for ${DANDELION_PLATFORM} on ${ARCHITECTURE}") # Constants @@ -119,6 +120,33 @@ if(NEWLIB) /${ARCHITECTURE}-dandelion/lib ${CMAKE_INSTALL_PREFIX}/lib ) + # Create folder at configuration time to avoid issues with includes + file(MAKE_DIRECTORY ${CMAKE_INSTALL_PREFIX}/include) + file(MAKE_DIRECTORY ${CMAKE_INSTALL_PREFIX}/include/sys) + + add_library(dlibc INTERFACE IMPORTED) + target_compile_options(dlibc INTERFACE + -D_GNU_SOURCE=1 + -D__GNU__ + -D__rtems__ + ) + target_include_directories(dlibc INTERFACE + ${CMAKE_INSTALL_PREFIX}/include + ${CMAKE_INSTALL_PREFIX}/include/sys + ) + target_link_directories(dlibc INTERFACE ${CMAKE_INSTALL_PREFIX}/lib) + target_link_libraries(dlibc INTERFACE + ${CMAKE_INSTALL_PREFIX}/lib/libc.a + ${CMAKE_INSTALL_PREFIX}/lib/libg.a + ${CMAKE_INSTALL_PREFIX}/lib/libm.a + ) + target_link_options(dlibc INTERFACE + -T${CMAKE_CURRENT_SOURCE_DIR}/sdk_install/linker.ld + -fuse-ld=lld + -static + -nostdlib + ) + add_dependencies(dlibc newlib) set(LLVM_C_FLAGS "-D_GNU_SOURCE=1") string(APPEND LLVM_C_FLAGS " -D_POSIX_TIMERS") @@ -191,13 +219,37 @@ if(NEWLIB) -DLIBCXXABI_BAREMETAL=ON -DLIBCXXABI_ENABLE_SHARED=OFF -DLIBCXXABI_USE_LLVM_UNWINDER=ON + -DLIBCXXABI_ENABLE_THREADS=OFF -DLIBCXX_ENABLE_SHARED=OFF -DLIBCXX_ENABLE_STATIC=ON -DLIBCXX_INCLUDE_BENCHMARKS=OFF -DLIBCXX_CXX_ABI=libcxxabi -DLIBCXX_ENABLE_FILESYSTEM=ON -DLIBCXX_ENABLE_RANDOM_DEVICE=OFF + -DLIBCXX_HAS_PTHREAD_API=ON ) add_dependencies(llvmproject newlib) + # Create folder at configuration time to avoid issues with includes + file(MAKE_DIRECTORY ${CMAKE_INSTALL_PREFIX}/include/c++/v1) + + add_library(dlibcxx INTERFACE IMPORTED) + target_include_directories(dlibcxx INTERFACE + "${CMAKE_INSTALL_PREFIX}/include/c++/v1" + ) + target_link_libraries(dlibcxx INTERFACE + "${CMAKE_INSTALL_PREFIX}/lib/libc++.a" + "${CMAKE_INSTALL_PREFIX}/lib/libc++abi.a" + "${CMAKE_INSTALL_PREFIX}/lib/libunwind.a" + ) + add_dependencies(dlibcxx llvmproject) + + add_library(runtime INTERFACE IMPORTED) + target_link_libraries(runtime INTERFACE + "${CMAKE_INSTALL_PREFIX}/lib/generic/libclang_rt.builtins-${ARCHITECTURE}.a" + ) + add_dependencies(runtime llvmproject) + + add_subdirectory(test_programs) + endif() diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..1db52e2 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,34 @@ +# syntax=docker/dockerfile:1 +FROM ubuntu:24.04 + +# arguments +ARG BUILD="Release" +ARG PLATFORM="debug" +ARG TARGET_ARCH="x86_64" +ARG VERSION="experimental" + +# install packages required packages to get things running +RUN apt update +RUN apt-get install -y wget gpg +RUN apt-get install -y lsb-release +RUN apt-get install -y software-properties-common +RUN apt-get install -y gcc g++ # clang uses gcc to interface with the linker + +# download initial clang +RUN wget https://apt.llvm.org/llvm.sh -O ~/llvm.sh +RUN chmod +x ~/llvm.sh +RUN ~/llvm.sh +RUN ln -s /usr/bin/ld.lld-19 /usr/bin/ld.lld +RUN rm -r /usr/include/* + +# download and set up dandelionSDK +RUN wget https://github.com/eth-easl/dandelionSDK/releases/download/${VERSION}/dandelion_sdk_${BUILD}_${PLATFORM}_${TARGET_ARCH}.tar.gz -O ~/dandelionSDK.tar.gz +RUN tar -xzf ~/dandelionSDK.tar.gz -C ~/ +RUN ~/dandelion_sdk/create-compiler.sh -d -c clang-19 + +ENV CC="clang" +ENV CXX="clang++" + +# additional useful tooling +RUN apt-get install -y cmake +RUN apt-get install -y git \ No newline at end of file diff --git a/README.md b/README.md index 60d9af8..062fb39 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,12 @@ dumping outputs to the terminal when terminating. Fixing it is on our agenda, but not of highest priority. If you want to use Dandelion and need C++ support for aarch64, please get in touch and we may be able to provide experimental builds or bump the priority to get it fixed. +### Other parameters + +Additionally, the following parameters can be used to influence system behaviour. + +- `PAGE_SIZE` sets the page size the runtime will assume to optimize allocation etc. and makes available to others to depend on. Should be a multiple of sizeof(size_t) for the platform compiled for. + ## Interface expectations ### libc When using libc or any system on top of it values can be fed into stdin, argv and environ by specifying a input set called "stdio". @@ -97,6 +103,28 @@ For newlib to be built correctly the autoconf version 2.69. This also enables the build of the in memory file system, which can also be built without the other newlib builds by setting `-DDANDELION_FS=ON` +## Build Container +We also provide a docker file to construct a build container with the correct tools set up in them. +To create the container with docker use the following command: +``` +docker build -t dandelion_dev_docker . [--no-cache] +``` +Use the `--no-cache` if you want to rebuild the container from scratch. + +To use the container use the following command: +``` +docker run --rm -it --mount type=bind,src=,dst=/workspace --workdir=/workspace dandelion_dev_docker:latest bash +``` +You will enter the container and your source folder will be mounted at `/workspace`. +The default clang and clang++ are set up to compile for dandelion debug on the machine you are running. +If you want a different target, you can set build, platform and architecture in the docker file. +Files you build in the container will be visible outside, as long as they are in the workspace directory. + +To add more tools to the build environment, they can be added to the docker file, or you can base your container build on our docker file by importing it with: +``` +FROM dandelion_dev_docker:latest +``` + ## Freestanding The GCC/Clang standard expects 4 functions to allways be provided in any environment (even freestanding), which allow the compiler to always just insert them. (https://gcc.gnu.org/onlinedocs/gcc/Standards.html) diff --git a/file_system/file_system.c b/file_system/file_system.c index 5fd1388..48c6367 100644 --- a/file_system/file_system.c +++ b/file_system/file_system.c @@ -16,7 +16,7 @@ D_File *create_file(Path *name, char *content, size_t length, uint32_t mode) { if (new_file == NULL) { return NULL; } - if (name->length > FS_NAME_LENGHT) { + if (name->length > FS_NAME_LENGTH) { return NULL; } memcpy(new_file->name, name->path, name->length); @@ -43,7 +43,7 @@ D_File *create_file(Path *name, char *content, size_t length, uint32_t mode) { D_File *create_directory(Path *name, uint32_t mode) { D_File *new_file = dandelion_alloc(sizeof(D_File), _Alignof(D_File)); - if (name->length > FS_NAME_LENGHT) { + if (name->length > FS_NAME_LENGTH) { return NULL; } memcpy(new_file->name, name->path, name->length); @@ -69,12 +69,12 @@ int link_file_to_folder(D_File *folder, D_File *file) { file->next = NULL; } else { D_File *current = folder->child; - if (namecmp(file->name, current->name, FS_NAME_LENGHT) < 0) { + if (namecmp(file->name, FS_NAME_LENGTH, current->name, FS_NAME_LENGTH) < 0) { file->next = current; folder->child = file; } else { while (current->next != NULL) { - if (namecmp(file->name, current->next->name, FS_NAME_LENGHT) < 0) { + if (namecmp(file->name, FS_NAME_LENGTH, current->next->name, FS_NAME_LENGTH) < 0) { break; } else { current = current->next; @@ -98,7 +98,7 @@ D_File *find_file_in_dir(D_File *directory, Path file) { for (D_File *current = directory->child; current != NULL; current = current->next) { int cmp_result = - namecmp(current->name, file.path, MIN(file.length, FS_NAME_LENGHT)); + namecmp(current->name, FS_NAME_LENGTH, file.path, file.length); if (cmp_result == 0) { return current; } else if (cmp_result > 0) { @@ -138,7 +138,7 @@ D_File *create_directories(D_File *directory, Path path, char prevent_up) { } for (Path current_path = get_component_advance(&path); current_path.length > 0; current_path = get_component_advance(&path)) { - if (current_path.length > FS_NAME_LENGHT) { + if (current_path.length > FS_NAME_LENGTH) { return NULL; } else if (current_path.length == 1 && current_path.path[0] == '.') { // handle special case of single dot for current directory @@ -483,7 +483,7 @@ int fs_initialize(int *argc, char ***argv, char ***environ) { return -1; } int is_stdio_folder = - namecmp(set_path.path, "stdio", MIN(set_path.length, 5)); + namecmp(set_path.path, set_path.length, "stdio", 5); size_t input_items = dandelion_input_buffer_count(set_index); for (size_t item_index = 0; item_index < input_items; item_index++) { IoBuffer *item_buffer = dandelion_get_input(set_index, item_index); @@ -510,19 +510,19 @@ int fs_initialize(int *argc, char ***argv, char ***environ) { } if (is_stdio_folder == 0) { int is_stdin = - namecmp(file_path.path, "stdin", MIN(file_path.length, 5)); + namecmp(file_path.path, file_path.length, "stdin", 5); if (is_stdin == 0) { error = open_existing_file(STDIN_FILENO, item_file, O_RDONLY, 0, 0); if (error != 0) return error; } - int is_argv = namecmp(file_path.path, "argv", MIN(file_path.length, 4)); + int is_argv = namecmp(file_path.path, file_path.length, "argv", 4); if (is_argv == 0) { setup_charpparray(item_buffer->data, item_buffer->data_len, argc, argv); } int is_environ = - namecmp(file_path.path, "environ", MIN(file_path.length, 7)); + namecmp(file_path.path, file_path.length, "environ", 7); if (is_environ == 0) { int envc; setup_charpparray(item_buffer->data, item_buffer->data_len, &envc, @@ -588,7 +588,7 @@ int add_output_from_file(D_File *file, Path previous_path, size_t set_index) { switch (file->type) { case FILE: // check name length an create string with complete file name - name_length = namelen(file->name, FS_NAME_LENGHT); + name_length = namelen(file->name, FS_NAME_LENGTH); new_buffer = dandelion_alloc(previous_path.length + name_length, 1); if (new_buffer == NULL) { return -1; @@ -631,7 +631,7 @@ int add_output_from_file(D_File *file, Path previous_path, size_t set_index) { return 0; case DIRECTORY: // check name length and create a new string / path to recurse further - name_length = namelen(file->name, FS_NAME_LENGHT); + name_length = namelen(file->name, FS_NAME_LENGTH); new_buffer = dandelion_alloc(previous_path.length + name_length + 1, 1); if (new_buffer == NULL) { dandelion_exit(ENOMEM); @@ -677,10 +677,10 @@ int fs_terminate() { for (D_File *out_file = set_directory->child; out_file != NULL; out_file = out_file->next) { // ignore argv, environ and stdin in the stdio folder - if (namecmp(set_ident.path, "stdio", MIN(set_ident.length, 5)) == 0) { - if (namecmp(out_file->name, "environ", 7) == 0 || - namecmp(out_file->name, "argv", 4) == 0 || - namecmp(out_file->name, "stdin", 5) == 0) + if (namecmp(set_ident.path, set_ident.length, "stdio", 5) == 0) { + if (namecmp(out_file->name, FS_NAME_LENGTH, "environ", 7) == 0 || + namecmp(out_file->name, FS_NAME_LENGTH, "argv", 4) == 0 || + namecmp(out_file->name, FS_NAME_LENGTH, "stdin", 5) == 0) continue; } add_output_from_file(out_file, empty_path, set_index); diff --git a/file_system/file_system.h b/file_system/file_system.h index 4f61050..0df9554 100644 --- a/file_system/file_system.h +++ b/file_system/file_system.h @@ -6,7 +6,7 @@ #include #ifndef FS_NAME_LENGTH -#define FS_NAME_LENGHT 64 +#define FS_NAME_LENGTH 64 #endif #ifndef FS_CHUNK_SIZE @@ -40,7 +40,7 @@ typedef struct FileChunk { // Use D_File instead of File, to avoid potential naming overlap typedef struct D_File { - char name[FS_NAME_LENGHT]; + char name[FS_NAME_LENGTH]; struct D_File *next; struct D_File *parent; FileType type; diff --git a/file_system/fs_implementation.c b/file_system/fs_implementation.c index 5fb2055..8c878c0 100644 --- a/file_system/fs_implementation.c +++ b/file_system/fs_implementation.c @@ -125,7 +125,7 @@ int dandelion_open(const char *name, int flags, uint32_t mode) { Path total_path = path_from_string(name); Path dir_path = get_directories(total_path); Path file_name = get_file(total_path); - if (file_name.length >= FS_NAME_LENGHT) { + if (file_name.length >= FS_NAME_LENGTH) { return -EINVAL; } D_File *parent = create_directories(fs_root, dir_path, 0); @@ -643,7 +643,7 @@ int dandelion_readdir(DIR *directory, struct dirent *dirent) { return -1; } directory->child++; - size_t max_name_length = MIN(256, FS_NAME_LENGHT); + size_t max_name_length = MIN(256, FS_NAME_LENGTH); memcpy(dirent->d_name, current_child->name, max_name_length - 1); dirent->d_name[max_name_length] = 0; dirent->d_ino = 0; diff --git a/file_system/paths.h b/file_system/paths.h index e2b4a1b..1a1a295 100644 --- a/file_system/paths.h +++ b/file_system/paths.h @@ -23,16 +23,24 @@ static inline size_t namelen(const char *const name, size_t max_len) { return length; } -static inline int namecmp(const char *const name1, const char *const name2, - size_t max_length) { +static inline int namecmp(const char *const name1, size_t name1_length, const char *const name2, + size_t name2_length) { + size_t max_length = name1_length < name2_length ? name1_length : name2_length; for (size_t index = 0; index < max_length; index++) { + // this also automatically returns -1 if one of them is null terminated earlier than their length if (name1[index] != name2[index]) return name1[index] < name2[index] ? -1 : 1; // are the same if we got here if (name1[index] == '\0') return 0; } - return 0; + // they are the same until the end of the shorter one or there has not been null termination + if(name1_length < name2_length) + return -1; + else if(name2_length < name1_length) + return 1; + else + return 0; } Path path_from_string(const char *const str); diff --git a/newlib_shim/Makefile.inc b/newlib_shim/Makefile.inc index 50b2230..b8fed40 100644 --- a/newlib_shim/Makefile.inc +++ b/newlib_shim/Makefile.inc @@ -2,4 +2,5 @@ libc_a_SOURCES += \ %D%/dirent.c \ %D%/pthread.c \ %D%/shim.c \ - %D%/time.c \ No newline at end of file + %D%/time.c \ + %D%/unistd.c \ No newline at end of file diff --git a/newlib_shim/patch_script b/newlib_shim/patch_script index 411b160..31f1a81 100755 --- a/newlib_shim/patch_script +++ b/newlib_shim/patch_script @@ -22,6 +22,7 @@ cp $THIS_DIR/shim.c $1/newlib/libc/sys/dandelion/shim.c cp $THIS_DIR/dirent.c $1/newlib/libc/sys/dandelion/dirent.c cp $THIS_DIR/pthread.c $1/newlib/libc/sys/dandelion/pthread.c cp $THIS_DIR/time.c $1/newlib/libc/sys/dandelion/time.c +cp $THIS_DIR/unistd.c $1/newlib/libc/sys/dandelion/unistd.c cp $THIS_DIR/../include/dandelion/crt.h $1/newlib/libc/sys/dandelion/crt.h if ! test -d $1/newlib/libc/sys/dandelion/sys then diff --git a/newlib_shim/shim.c b/newlib_shim/shim.c index e1ff544..4e35d50 100644 --- a/newlib_shim/shim.c +++ b/newlib_shim/shim.c @@ -185,6 +185,10 @@ int access(const char *file, int mode) { int lstat(const char *file, struct stat *buf) { return stat(file, buf); } +mode_t umask(mode_t mask) { + return 0777; +} + int statvfs(const char *file, struct statvfs *st) { errno = ENOSYS; return -1; diff --git a/newlib_shim/unistd.c b/newlib_shim/unistd.c new file mode 100644 index 0000000..b8837a0 --- /dev/null +++ b/newlib_shim/unistd.c @@ -0,0 +1,243 @@ +#include +#include + +// Implement functions from unistd that are not already defined in other parts of newlibs libc +// Or in something we supply + +// unsigned alarm (unsigned __secs); +int chdir (const char *__path) { + *__errno() = EACCES; + return -1; +} +int fchdir (int __fildes) { + *__errno() = EACCES; + return -1; +} + +int chroot (const char *__path) { + *__errno() = EACCES; + return -1; +} + +// int chmod (const char *__path, mode_t __mode); +// int chown (const char *__path, uid_t __owner, gid_t __group); +// int close_range (unsigned int __firstfd, unsigned int __lastfd, int __flags); +// size_t confstr (int __name, char *__buf, size_t __len); +// char * crypt (const char *__key, const char *__salt); +// char * ctermid (char *__s); +// char * cuserid (char *__s); +// int daemon (int nochdir, int noclose); + +// function to duplicate file descriptor to second file number +// the filedescriptors should act as one, meaning if seek is called on one of them, +// the effects should also be visible accessing the file through the new one. +// if the second parameter is -1, the lowest free file descriptor is chosen, +// otherwise the file descriptor in filedes2 is used to duplicate the filedescriptor. +// If filedes2 was open before, it will be closed. +int dup3 (int __fildes, int __fildes2, int flags) { + *__errno() = EMFILE; + return -1; +} +int dup2 (int __fildes, int __fildes2) { + return dup3(__fildes, __fildes2, 0); +} +int dup (int __fildes) { + return dup3(__fildes, -1, 0); +} + +int eaccess (const char *__path, int __mode) { + return access(__path, __mode); +} +int euidaccess (const char *__path, int __mode){ + return eaccess(__path, __mode); +} + +// void encrypt (char *__block, int __edflag); +// void endusershell (void); + +// execve is defined in newlib +// int execl (const char *__path, const char *, ...); +// int execle (const char *__path, const char *, ...); +// int execlp (const char *__file, const char *, ...); +// #if __MISC_VISIBLE +// int execlpe (const char *__file, const char *, ...); +// #endif +int execv (const char *__path, char * const __argv[]) { + return execve(__path,__argv, environ); +} +// already given in newlib +// int execve (const char *__path, char * const __argv[], char * const __envp[]); +// int execvp (const char *__file, char * const __argv[]); +// int execvpe (const char *__file, char * const __argv[], char * const __envp[]); +// #if __ATFILE_VISIBLE +// int faccessat (int __dirfd, const char *__path, int __mode, int __flags); +// #endif +// int fchmod (int __fildes, mode_t __mode); +// int fchown (int __fildes, uid_t __owner, gid_t __group); +// #if __ATFILE_VISIBLE +// int fchownat (int __dirfd, const char *__path, uid_t __owner, gid_t __group, int __flags); +// #endif +// int fexecve (int __fd, char * const __argv[], char * const __envp[]); +// long fpathconf (int __fd, int __name); +int fsync (int __fd) { + return 0; +} +int fdatasync (int __fd) { + return 0; +} +// char * get_current_dir_name (void); +char * getcwd (char *__buf, size_t __size) { + return "/"; +} +// int getdomainname (char *__name, size_t __len); +// gid_t getegid (void); +// uid_t geteuid (void); +// gid_t getgid (void); +// int getgroups (int __gidsetsize, gid_t __grouplist[]); +// long gethostid (void); +// char * getlogin (void); +// #if defined(_POSIX_THREAD_SAFE_FUNCTIONS) +// int getlogin_r (char *name, size_t namesize) ; +// #endif +// char * getpass (const char *__prompt); +// int getpagesize (void); +// pid_t getpgid (pid_t); +// pid_t getpgrp (void); +// pid_t getpid (void); // already implementedc +// pid_t getppid (void); +// pid_t getsid (pid_t); +// uid_t getuid (void); +// char * getusershell (void); +// char * getwd (char *__buf); +// int lchown (const char *__path, uid_t __owner, gid_t __group); +// #if __ATFILE_VISIBLE +// int linkat (int __dirfd1, const char *__path1, int __dirfd2, const char *__path2, int __flags); +// #endif +// #if __MISC_VISIBLE || __XSI_VISIBLE +// int nice (int __nice_value); +// #endif +// #if __MISC_VISIBLE || __XSI_VISIBLE >= 4 +// int lockf (int __fd, int __cmd, off_t __len); +// #endif +// long pathconf (const char *__path, int __name); +// int pause (void); +// #if __POSIX_VISIBLE >= 199506 +// int pthread_atfork (void (*)(void), void (*)(void), void (*)(void)); +// #endif +// int pipe (int __fildes[2]) { +// pipe2(__fileds[2], 0); +// } +// int pipe2 (int __fildes[2], int flags); +// #if __POSIX_VISIBLE >= 200809 || __XSI_VISIBLE >= 500 +// ssize_t pread (int __fd, void *__buf, size_t __nbytes, off_t __offset); +// ssize_t pwrite (int __fd, const void *__buf, size_t __nbytes, off_t __offset); +// #endif +// _READ_WRITE_RETURN_TYPE read (int __fd, void *__buf, size_t __nbyte); +// #if __BSD_VISIBLE +// int rresvport (int *__alport); +// int revoke (char *__path); +// #endif +// int rmdir (const char *__path); +// #if __BSD_VISIBLE +// int ruserok (const char *rhost, int superuser, const char *ruser, const char *luser); +// #endif +// #if __BSD_VISIBLE || (__XSI_VISIBLE >= 4 && __POSIX_VISIBLE < 200112) +// void * sbrk (ptrdiff_t __incr); +// #endif +// #if __BSD_VISIBLE || __POSIX_VISIBLE >= 200112 +// int setegid (gid_t __gid); +// int seteuid (uid_t __uid); +// #endif +// int setgid (gid_t __gid); +int setgroups (int ngroups, const gid_t *grouplist) { + *__errno() = EPERM; + return -1; +} +// #if __BSD_VISIBLE || (__XSI_VISIBLE && __XSI_VISIBLE < 500) +// int sethostname (const char *, size_t); +// #endif +// int setpgid (pid_t __pid, pid_t __pgid); +// #if __SVID_VISIBLE || __XSI_VISIBLE >= 500 +// int setpgrp (void); +// #endif +// #if __BSD_VISIBLE || __XSI_VISIBLE >= 4 +// int setregid (gid_t __rgid, gid_t __egid); +// int setreuid (uid_t __ruid, uid_t __euid); +// #endif +// pid_t setsid (void); +// int setuid (uid_t __uid); +// #if __BSD_VISIBLE || (__XSI_VISIBLE && __XSI_VISIBLE < 500) +// void setusershell (void); +// #endif +// unsigned sleep (unsigned int __seconds); +// #if __XSI_VISIBLE +// void swab (const void *__restrict, void *__restrict, ssize_t); +// #endif +// long sysconf (int __name); +// pid_t tcgetpgrp (int __fildes); +// int tcsetpgrp (int __fildes, pid_t __pgrp_id); +// char * ttyname (int __fildes); +// int ttyname_r (int, char *, size_t); +// int unlink (const char *__path); +// #if __XSI_VISIBLE >= 500 && __POSIX_VISIBLE < 200809 || __BSD_VISIBLE +int usleep (useconds_t __useconds) { + return 0; +} +// #endif +// #if __BSD_VISIBLE +// int vhangup (void); +// #endif +// _READ_WRITE_RETURN_TYPE write (int __fd, const void *__buf, size_t __nbyte); + +// #ifdef __CYGWIN__ +// # define __UNISTD_GETOPT__ +// # include +// # undef __UNISTD_GETOPT__ +// #else +// extern char *optarg; /* getopt(3) external variables */ +// extern int optind, opterr, optopt; +// int getopt(int, char * const [], const char *); +// extern int optreset; /* getopt(3) external variable */ +// #endif + +// #if __BSD_VISIBLE || (__XSI_VISIBLE >= 4 && __POSIX_VISIBLE < 200809) +// pid_t vfork (void); +// #endif + +// #if __BSD_VISIBLE || __POSIX_VISIBLE < 200112 +// int getdtablesize (void); +// #endif +// #if __BSD_VISIBLE || __POSIX_VISIBLE >= 200809 || __XSI_VISIBLE >= 500 +// useconds_t ualarm (useconds_t __useconds, useconds_t __interval); +// #endif + +// #if __BSD_VISIBLE || __POSIX_VISIBLE >= 200112 || __XSI_VISIBLE >= 500 +// #if !(defined (_WINSOCK_H) || defined (_WINSOCKAPI_) || defined (__USE_W32_SOCKETS)) +// /* winsock[2].h defines as __stdcall, and with int as 2nd arg */ +// int gethostname (char *__name, size_t __len); +// #endif +// #endif + +// #if __MISC_VISIBLE +// int setdtablesize (int); +// #endif + +// #if __BSD_VISIBLE || __XSI_VISIBLE >= 500 +// void sync (void); +// #endif + +// #if __BSD_VISIBLE || __POSIX_VISIBLE >= 200112 || __XSI_VISIBLE >= 4 +// ssize_t readlink (const char *__restrict __path, +// char *__restrict __buf, size_t __buflen); + +int symlink (const char *__name1, const char *__name2) { + *__errno() = EPERM; + return -1; +} +// #endif +// #if __ATFILE_VISIBLE +// ssize_t readlinkat (int __dirfd1, const char *__restrict __path, +// char *__restrict __buf, size_t __buflen); +// int symlinkat (const char *, int, const char *); +// int unlinkat (int, const char *, int); +// #endif \ No newline at end of file diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt index 79ee41e..a0d7f2a 100644 --- a/runtime/CMakeLists.txt +++ b/runtime/CMakeLists.txt @@ -15,10 +15,11 @@ target_sources(${RUNTIME_LIB} ${DANDELION_ROOT}/include/dandelion/runtime.h ${DANDELION_ROOT}/include/dandelion/system/system.h ) +target_compile_definitions(${RUNTIME_LIB} PRIVATE + PAGE_SIZE=${PAGE_SIZE} +) get_target_property(header_sets ${RUNTIME_LIB} HEADER_SET_public_headers) -# MESSAGE(FATAL_ERROR "header set: ${header_sets}") - target_link_options(${RUNTIME_LIB} PUBLIC -nostdlib) target_link_libraries(${RUNTIME_LIB} PRIVATE ${SYSTEM_LIB}) diff --git a/runtime/runtime.c b/runtime/runtime.c index 3b2ba01..a56f5c0 100644 --- a/runtime/runtime.c +++ b/runtime/runtime.c @@ -5,6 +5,13 @@ #define sysdata __dandelion_system_data +#ifndef PAGE_SIZE +#define PAGE_SIZE 4096 +#endif + +// assumed to be multiple of sizeof(size_t) +const size_t system_page_size = PAGE_SIZE; + RuntimeData __runtime_global_data; // internal state of the runtime @@ -145,8 +152,6 @@ void *dandelion_sbrk(size_t size) { return result; } -static const size_t DEFAULT_ALLOCATION = - 4096; // assumed to be multiple of sizeof(size_t) static const size_t OCCUPIED_FLAG = ((size_t)-1) << ((sizeof(size_t) * 8 - 1)); static const size_t MAX_VAL = (size_t)-1; @@ -160,9 +165,9 @@ static inline int is_occupied(size_t allocation) { // Rounding up to next multiple of DEFAULT_ALLOCATION static inline size_t get_sbrk_size(size_t size, size_t alignment) { return ((size * sizeof(size_t) + 4 * sizeof(size_t) + alignment + - DEFAULT_ALLOCATION - 1) / - DEFAULT_ALLOCATION) * - DEFAULT_ALLOCATION; + system_page_size - 1) / + system_page_size) * + system_page_size; } /// @brief memmory allocation for internal usage diff --git a/runtime/runtime.h b/runtime/runtime.h index fc2e42e..6f14518 100644 --- a/runtime/runtime.h +++ b/runtime/runtime.h @@ -4,6 +4,8 @@ #include "dandelion/system/system.h" +extern const size_t system_page_size; + typedef struct IoSet { const char *ident; size_t ident_len; diff --git a/sdk_install/CMakeLists.txt b/sdk_install/CMakeLists.txt index df45e9f..b92cad1 100644 --- a/sdk_install/CMakeLists.txt +++ b/sdk_install/CMakeLists.txt @@ -1,7 +1,7 @@ # actions to make the SDK build possible for outside sources if(DANDELION_PLATFORM MATCHES "wasm") - set(DANDELION_TARGET "wasm32-unkown-dandelion") + set(DANDELION_TARGET "wasm32-unknown-dandelion") set(TEMPLATE_TARGET "wasm32-unknown-unknown") else() set(DANDELION_TARGET "${ARCHITECTURE}-unknown-dandelion") @@ -16,19 +16,19 @@ configure_file(CMakeTemplate.txt ${CMAKE_INSTALL_PREFIX}/CMakeLists.txt ) if(NEWLIB) - # Configure ARCHITECTURE-unkown-dandelion-clang + # Configure ARCHITECTURE-unknown-dandelion-clang configure_file(clang-template.cmake ${CMAKE_INSTALL_PREFIX}/${DANDELION_TARGET}-clang.cfg FILE_PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ @ONLY ) - # Configure ARCHITECTURE-unkown-dandelion-clang++ + # Configure ARCHITECTURE-unknown-dandelion-clang++ configure_file(clangxx-template.cmake ${CMAKE_INSTALL_PREFIX}/${DANDELION_TARGET}-clang++.cfg FILE_PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ @ONLY ) - # Configure ARCHITECTURE-unkown-dandelion-clang++ + # Configure ARCHITECTURE-unknown-dandelion-clang++ configure_file(toolchain-template.cmake ${CMAKE_INSTALL_PREFIX}/dandelion-toolchain.cmake FILE_PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ @ONLY diff --git a/sdk_install/CMakeTemplate.txt b/sdk_install/CMakeTemplate.txt index 527137a..3ddcc8a 100644 --- a/sdk_install/CMakeTemplate.txt +++ b/sdk_install/CMakeTemplate.txt @@ -44,8 +44,6 @@ target_include_directories(dlibc INTERFACE target_compile_options(dlibc INTERFACE -D_GNU_SOURCE=1 -D__GNU__ - # __GNUC_PREREQ is necessary so limits.h is included by stdint.h, otherwise size_t is not defined - -D__GNUC_PREREQ(x,y)=0 -D__rtems__ ) target_link_libraries(dlibc INTERFACE @@ -65,7 +63,6 @@ target_include_directories(dlibcxx INTERFACE target_compile_options(dlibcxx INTERFACE -D_GNU_SOURCE=1 -D__GNU__ - -D__GNUC_PREREQ(x,y)=0 -D__rtems__ ) target_link_libraries(dlibcxx INTERFACE diff --git a/sdk_install/clang-template.cmake b/sdk_install/clang-template.cmake index 941b5ce..c389790 100644 --- a/sdk_install/clang-template.cmake +++ b/sdk_install/clang-template.cmake @@ -2,7 +2,6 @@ --target=@TEMPLATE_TARGET@ -D_GNU_SOURCE=1 -D__GNU__ --D__GNUC_PREREQ(x,y)=0 -D__rtems__ # compiler flags @@ -10,8 +9,9 @@ # include flags -nostdinc --idirafter/include --idirafter/include/sys +-isystem/include +-isystem/include/sys +-isystemCOMPILER_INCLUDES # linker flags -T/linker.ld @@ -19,9 +19,11 @@ -static -nostdlib -L/lib +-L/lib/generic -lm -lc -lg -ldandelion_file_system -ldandelion_runtime --ldandelion_system \ No newline at end of file +-ldandelion_system +-lclang_rt.builtins-@ARCHITECTURE@ \ No newline at end of file diff --git a/sdk_install/clangxx-template.cmake b/sdk_install/clangxx-template.cmake index e6c80ec..91e99ba 100644 --- a/sdk_install/clangxx-template.cmake +++ b/sdk_install/clangxx-template.cmake @@ -1,9 +1,9 @@ -@@DANDELION_TARGET@-clang.cfg - # C++ compiler flags --idirafter/include/c++/v1 +-isystem/include/c++/v1 # C++ linker flags -lc++ -lc++abi --lunwind \ No newline at end of file +-lunwind + +@@DANDELION_TARGET@-clang.cfg \ No newline at end of file diff --git a/sdk_install/script-template.sh b/sdk_install/script-template.sh index 2afa0fd..6557545 100644 --- a/sdk_install/script-template.sh +++ b/sdk_install/script-template.sh @@ -2,8 +2,48 @@ set -e +CLANG_NAME="clang" +DEFAULT_CLANG=false + +# option c sets the clang name to look for +# option d makes it so the finished clang is installed as default clang, assuming there is no default clang yet +while getopts "c:d" opt; do + case "$opt" in + c) + echo "Looking for clang at $OPTARG" + CLANG_NAME="$OPTARG" + ;; + d) + echo "Trying to create default clang" + DEFAULT_CLANG=true + ;; + ?) + echo "Unkown argument to scipt" + ;; + esac +done + +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +cd $SCRIPT_DIR + +COMPILER_INCLUDES=$($CLANG_NAME -print-file-name=include) +sed -i "s|COMPILER_INCLUDES|$COMPILER_INCLUDES|g" @DANDELION_TARGET@-clang.cfg + +CLANG_PATH="$(which $CLANG_NAME)" +CLANG_DIR="$(dirname $CLANG_PATH)" + if ! [ -f @DANDELION_TARGET@-clang ]; then - CLANG_PATH=$(which clang) cp $CLANG_PATH @DANDELION_TARGET@-clang ln -s @DANDELION_TARGET@-clang @DANDELION_TARGET@-clang++ +fi + +if [ $DEFAULT_CLANG = true ] && ! [[ -f $CLANG_DIR/clang ]]; then + cp "$CLANG_PATH" "$CLANG_DIR/clang" + ln -s "$CLANG_DIR/clang" "$CLANG_DIR/clang++" + sed "s||$SCRIPT_DIR|g" @DANDELION_TARGET@-clang.cfg >> "$CLANG_DIR/clang.cfg" + # enable stdinc, as we assume it has been cleared when we install our clang as system clang + sed -i "s|-nostdinc||g" "$CLANG_DIR/clang.cfg" + sed "s||$SCRIPT_DIR|g" @DANDELION_TARGET@-clang++.cfg >> "$CLANG_DIR/clang++.cfg" + # need to change the config to use the clang.cfg in the same folder, so remove prefix + sed -i "s|@DANDELION_TARGET@-||g" "$CLANG_DIR/clang++.cfg" fi \ No newline at end of file diff --git a/sdk_install/toolchain-template.cmake b/sdk_install/toolchain-template.cmake index 84303eb..5a5aaba 100644 --- a/sdk_install/toolchain-template.cmake +++ b/sdk_install/toolchain-template.cmake @@ -3,7 +3,7 @@ set(CMAKE_SYSTEM_NAME Generic) # which compilers to use for C and C++ set(CMAKE_C_COMPILER "${CMAKE_CURRENT_LIST_DIR}/@DANDELION_TARGET@-clang") -set(CMAKE_C_COMPILER "${CMAKE_CURRENT_LIST_DIR}/@DANDELION_TARGET@-clang++") +set(CMAKE_CXX_COMPILER "${CMAKE_CURRENT_LIST_DIR}/@DANDELION_TARGET@-clang++") # where is the target environment located set(CMAKE_FIND_ROOT_PATH ) diff --git a/system/platform/debug/debug.c b/system/platform/debug/debug.c index 592314f..d313324 100644 --- a/system/platform/debug/debug.c +++ b/system/platform/debug/debug.c @@ -143,185 +143,180 @@ void __dandelion_platform_init(void) { } linux_dirent; char dirent_buffer[DIRENT_BUF_SIZE]; char set_dirent_buffer[DIRENT_BUF_SIZE]; + char item_dirent_buffer[DIRENT_BUF_SIZE]; - long dirent_read = - __syscall(SYS_getdents64, in_sets_fd, &dirent_buffer, DIRENT_BUF_SIZE); + long dirent_read = 0; + size_t total_buffers = 0; + size_t input_set_index = 0; + struct io_set_info *input_sets = heap_ptr; + + write_all(1, "input_sets:\n", 13); + + while ((dirent_read = __syscall(SYS_getdents64, in_sets_fd, &dirent_buffer, + DIRENT_BUF_SIZE)) > 0) { + // have read one or more entries, need to process them before reading again + for (long dirent_offset = 0; dirent_offset < dirent_read; + dirent_offset += + ((linux_dirent *)&dirent_buffer[dirent_offset])->d_reclen) { + // get the dirent for the current input set + linux_dirent *dirent = (linux_dirent *)&dirent_buffer[dirent_offset]; + size_t ident_len = my_strlen(dirent->d_name); + if ((ident_len == 1 && dirent->d_name[0] == '.') || + (ident_len == 2 && dirent->d_name[0] == '.' && + dirent->d_name[1] == '.')) + continue; + + if (dirent->d_type != DT_DIR) + print_and_exit("file in input_sets not direcotory", -1); + + // setupt the input set descriptor + char *ident_buffer = (char *)debug_alloc(ident_len); + my_memcpy(ident_buffer, dirent->d_name, ident_len); + input_sets[input_set_index].ident = ident_buffer; + input_sets[input_set_index].ident_len = ident_len; + input_set_index++; + } + } if (dirent_read < 0) print_and_exit("getdents failed\n", -dirent_read); - if (dirent_read == DIRENT_BUF_SIZE) - print_and_exit("could not read all child directory entries of in set", -1); - - size_t input_set_num = 0; - for (long dirent_offset = 0; dirent_offset < dirent_read; - dirent_offset += - ((linux_dirent *)&dirent_buffer[dirent_offset])->d_reclen) { - linux_dirent *dirent = (linux_dirent *)&dirent_buffer[dirent_offset]; - size_t ident_len = my_strlen(dirent->d_name); - if ((ident_len == 1 && dirent->d_name[0] == '.') || - (ident_len == 2 && dirent->d_name[0] == '.' && - dirent->d_name[1] == '.')) - continue; - input_set_num++; - } - struct io_set_info *input_sets = heap_ptr; - heap_ptr += (input_set_num + 1) * sizeof(struct io_set_info); + heap_ptr += (input_set_index + 1) * sizeof(struct io_set_info); // prepare for IoBuffer array for input sets heap_ptr = round_up_to(heap_ptr, _Alignof(IoBuffer)); sysdata.input_bufs = heap_ptr; - size_t total_buffers = 0; - size_t input_set_index = 0; - for (long dirent_offset = 0; dirent_offset < dirent_read; - dirent_offset += - ((linux_dirent *)&dirent_buffer[dirent_offset])->d_reclen) { - linux_dirent *dirent = (linux_dirent *)&dirent_buffer[dirent_offset]; - size_t ident_len = my_strlen(dirent->d_name); - write_all(1, dirent->d_name, ident_len); + for (size_t input_set = 0; input_set < input_set_index; input_set++) { + write_all(1, "\t", 1); + write_all(1, input_sets[input_set].ident, input_sets[input_set].ident_len); write_all(1, "\n", 1); - - // check it is a directory - if ((ident_len == 1 && dirent->d_name[0] == '.') || - (ident_len == 2 && dirent->d_name[0] == '.' && - dirent->d_name[1] == '.')) - continue; - if (dirent->d_type != DT_DIR) - print_and_exit("file in input_sets not direcotory", -1); - // open the input set folder - int set_folder_fd = - __syscall(SYS_openat, in_sets_fd, dirent->d_name, O_RDONLY); + int set_folder_fd = __syscall(SYS_openat, in_sets_fd, + input_sets[input_set].ident, O_RDONLY); if (set_folder_fd < 0) print_and_exit("could not open set folder\n", -1); // read the directory - long set_dirent_read = __syscall(SYS_getdents64, set_folder_fd, - &set_dirent_buffer, DIRENT_BUF_SIZE); - if (set_dirent_read < 0) - print_and_exit("getdents failed\n", -dirent_read); - if (set_dirent_read == DIRENT_BUF_SIZE) - print_and_exit("could not read all items in input set, ran out of dirent " - "buffer space", - -1); - char *ident_buffer = (char *)debug_alloc(ident_len); - my_memcpy(ident_buffer, dirent->d_name, ident_len); - input_sets[input_set_index].ident = ident_buffer; - input_sets[input_set_index].ident_len = ident_len; - input_sets[input_set_index].offset = total_buffers; - input_set_index++; - // add items - for (long set_dirent_offset = 0; set_dirent_offset < set_dirent_read; - set_dirent_offset += - ((linux_dirent *)&set_dirent_buffer[set_dirent_offset])->d_reclen) { - linux_dirent *set_dirent = - (linux_dirent *)&set_dirent_buffer[set_dirent_offset]; - size_t item_ident_len = my_strlen(set_dirent->d_name); - if ((item_ident_len == 1 && set_dirent->d_name[0] == '.') || - (item_ident_len == 2 && set_dirent->d_name[0] == '.' && - set_dirent->d_name[1] == '.')) - continue; - write_all(1, "\t", 1); - write_all(1, set_dirent->d_name, item_ident_len); - write_all(1, "\n", 1); - // add one buffer to heap - IoBuffer *current_buffer = heap_ptr; - heap_ptr += sizeof(IoBuffer); - char *item_ident_buffer = (char *)debug_alloc(item_ident_len); - my_memcpy(item_ident_buffer, set_dirent->d_name, item_ident_len); - // pretend the files were in folders - for (size_t index = 0; index < item_ident_len; index++) { - if (item_ident_buffer[index] == '+') { - item_ident_buffer[index] = '/'; + long set_dirent_read = 0; + while ((set_dirent_read = __syscall(SYS_getdents64, set_folder_fd, + &set_dirent_buffer, DIRENT_BUF_SIZE)) > + 0) { + // found one or more items + for (long set_dirent_offset = 0; set_dirent_offset < set_dirent_read; + set_dirent_offset += + ((linux_dirent *)&set_dirent_buffer[set_dirent_offset])->d_reclen) { + linux_dirent *set_dirent = + (linux_dirent *)&set_dirent_buffer[set_dirent_offset]; + size_t item_ident_len = my_strlen(set_dirent->d_name); + if ((item_ident_len == 1 && set_dirent->d_name[0] == '.') || + (item_ident_len == 2 && set_dirent->d_name[0] == '.' && + set_dirent->d_name[1] == '.')) + continue; + + write_all(1, "\t\t", 2); + write_all(1, set_dirent->d_name, item_ident_len); + write_all(1, "\n", 1); + // add one buffer to heap + IoBuffer *current_buffer = heap_ptr; + heap_ptr += sizeof(IoBuffer); + char *item_ident_buffer = (char *)debug_alloc(item_ident_len); + my_memcpy(item_ident_buffer, set_dirent->d_name, item_ident_len); + // pretend the files were in folders + for (size_t index = 0; index < item_ident_len; index++) { + if (item_ident_buffer[index] == '+') { + item_ident_buffer[index] = '/'; + } } + current_buffer->ident = item_ident_buffer; + current_buffer->ident_len = item_ident_len; + current_buffer->key = 0; + int item_fd = + __syscall(SYS_openat, set_folder_fd, set_dirent->d_name, O_RDONLY); + if (item_fd < 0) + print_and_exit("could not open item file", -1); + ptrdiff_t file_size = __syscall(SYS_lseek, item_fd, 0, 2); + if (file_size < 0) + print_and_exit("Could not get file size\n", -1); + char *file_addr = NULL; + if (file_size > 0) { + file_addr = (char *)__syscall(SYS_mmap, NULL, file_size, PROT_READ, + MAP_PRIVATE, item_fd, 0); + if ((long)file_addr < 0) + print_and_exit("Could not map item file\n", -(int)file_addr); + } + current_buffer->data = file_addr; + current_buffer->data_len = file_size; + total_buffers++; } - current_buffer->ident = item_ident_buffer; - current_buffer->ident_len = item_ident_len; - current_buffer->key = 0; - int item_fd = - __syscall(SYS_openat, set_folder_fd, set_dirent->d_name, O_RDONLY); - if (item_fd < 0) - print_and_exit("could not open item file", -1); - ptrdiff_t file_size = __syscall(SYS_lseek, item_fd, 0, 2); - if (file_size < 0) - print_and_exit("Could not get file size\n", -1); - char *file_addr = NULL; - if (file_size > 0) { - file_addr = (char *)__syscall(SYS_mmap, NULL, file_size, PROT_READ, - MAP_PRIVATE, item_fd, 0); - if ((long)file_addr < 0) - print_and_exit("Could not map item file\n", -(int)file_addr); - } - current_buffer->data = file_addr; - current_buffer->data_len = file_size; - total_buffers++; } + if (set_dirent_read < 0) + print_and_exit("getdents failed\n", -dirent_read); + + input_sets[input_set].offset = total_buffers; } + // set up sentinel set - input_sets[input_set_num].ident = NULL; - input_sets[input_set_num].ident_len = 0; - input_sets[input_set_num].offset = total_buffers; + input_sets[input_set_index].ident = NULL; + input_sets[input_set_index].ident_len = 0; + input_sets[input_set_index].offset = total_buffers; sysdata.input_sets = input_sets; - sysdata.input_sets_len = input_set_num; + sysdata.input_sets_len = input_set_index; // start processing output sets + write_all(1, "output_sets:\n", 14); + int out_sets_fd = __syscall(SYS_openat, AT_FDCWD, "output_sets", O_RDONLY); if (out_sets_fd < 0) { print_and_exit("No output set directory in current working directory\n", -1); } - dirent_read = - __syscall(SYS_getdents64, out_sets_fd, &dirent_buffer, DIRENT_BUF_SIZE); - if (dirent_read < 0) { - print_and_exit("getdents failed\n", -dirent_read); - } - - size_t output_set_num = 0; - for (long dirent_offset = 0; dirent_offset < dirent_read; - dirent_offset += - ((linux_dirent *)&dirent_buffer[dirent_offset])->d_reclen) { - linux_dirent *dirent = (linux_dirent *)&dirent_buffer[dirent_offset]; - size_t ident_len = my_strlen(dirent->d_name); - if ((ident_len == 1 && dirent->d_name[0] == '.') || - (ident_len == 2 && dirent->d_name[0] == '.' && - dirent->d_name[1] == '.')) - continue; - output_set_num++; - } heap_ptr = round_up_to(heap_ptr, _Alignof(struct io_set_info)); struct io_set_info *output_sets = heap_ptr; - heap_ptr += (output_set_num + 1) * sizeof(struct io_set_info); size_t output_set_index = 0; - for (long dirent_offset = 0; dirent_offset < dirent_read; - dirent_offset += - ((linux_dirent *)&dirent_buffer[dirent_offset])->d_reclen) { - linux_dirent *dirent = (linux_dirent *)&dirent_buffer[dirent_offset]; - size_t ident_len = my_strlen(dirent->d_name); - write_all(1, dirent->d_name, ident_len); - write_all(1, "\n", 1); - // check it is a directory - if ((ident_len == 1 && dirent->d_name[0] == '.') || - (ident_len == 2 && dirent->d_name[0] == '.' && - dirent->d_name[1] == '.')) - continue; - if (dirent->d_type != DT_DIR) - print_and_exit("file in output_sets not direcotory", -1); - char *ident_buffer = (char *)debug_alloc(ident_len); - my_memcpy(ident_buffer, dirent->d_name, ident_len); - output_sets[output_set_index].ident = ident_buffer; - output_sets[output_set_index].ident_len = ident_len; - output_sets[output_set_index].offset = 0; - output_set_index++; + while ((dirent_read = __syscall(SYS_getdents64, out_sets_fd, &dirent_buffer, + DIRENT_BUF_SIZE)) > 0) { + for (long dirent_offset = 0; dirent_offset < dirent_read; + dirent_offset += + ((linux_dirent *)&dirent_buffer[dirent_offset])->d_reclen) { + linux_dirent *dirent = (linux_dirent *)&dirent_buffer[dirent_offset]; + size_t ident_len = my_strlen(dirent->d_name); + if ((ident_len == 1 && dirent->d_name[0] == '.') || + (ident_len == 2 && dirent->d_name[0] == '.' && + dirent->d_name[1] == '.')) + continue; + + write_all(1, "\t", 1); + write_all(1, dirent->d_name, ident_len); + write_all(1, "\n", 1); + // check it is a directory + if ((ident_len == 1 && dirent->d_name[0] == '.') || + (ident_len == 2 && dirent->d_name[0] == '.' && + dirent->d_name[1] == '.')) + continue; + if (dirent->d_type != DT_DIR) + print_and_exit("file in output_sets not direcotory", -1); + char *ident_buffer = (char *)debug_alloc(ident_len); + my_memcpy(ident_buffer, dirent->d_name, ident_len); + output_sets[output_set_index].ident = ident_buffer; + output_sets[output_set_index].ident_len = ident_len; + output_sets[output_set_index].offset = 0; + output_set_index++; + } } + if (dirent_read < 0) + print_and_exit("getdents failed\n", -dirent_read); + // set up sentinel set - output_sets[output_set_num].ident = NULL; - output_sets[output_set_num].ident_len = 0; - output_sets[output_set_num].offset = 0; + output_sets[output_set_index].ident = NULL; + output_sets[output_set_index].ident_len = 0; + output_sets[output_set_index].offset = 0; + + heap_ptr += (output_set_index + 1) * sizeof(struct io_set_info); sysdata.output_bufs = NULL; sysdata.output_sets = output_sets; - sysdata.output_sets_len = output_set_num; + sysdata.output_sets_len = output_set_index; sysdata.heap_begin = (uintptr_t)heap_ptr; sysdata.heap_end = (uintptr_t)heap_end; @@ -329,7 +324,20 @@ void __dandelion_platform_init(void) { void __dandelion_platform_exit(void) { dump_global_data(); - __syscall(SYS_exit_group, 0); + // print exit code + char exit_message[] = "Exiting with code "; + size_t message_len = my_strlen(exit_message); + write_all(1, exit_message, message_len); + char exit_code_string[11] = " \n"; + // convert int to string + int exit_code = sysdata.exit_code; + for(size_t index = 0; index < 10; index++) { + exit_code_string[9-index] = '0' + (exit_code % 10); + exit_code = exit_code / 10; + if (exit_code == 0) break; + } + write_all(1, exit_code_string, 11); + __syscall(SYS_exit_group, sysdata.exit_code); __builtin_unreachable(); } diff --git a/test_programs/CMakeLists.txt b/test_programs/CMakeLists.txt index 891b780..f74027a 100644 --- a/test_programs/CMakeLists.txt +++ b/test_programs/CMakeLists.txt @@ -1,14 +1,2 @@ -cmake_minimum_required(VERSION 3.23) - -set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY") -set(CMAKE_POSITION_INDEPENDENT_CODE ON) - -project(dandelion-sdk-tests) - -set(SDK_PATH "" CACHE STRING "path to find sdk") - -# add libraries as subdirectory, should also add alternative mode where we compile with cfg files -add_subdirectory("${SDK_PATH}/dandelion_sdk" "${CMAKE_BINARY_DIR}/dandelion_sdk_build") - add_subdirectory(libc) add_subdirectory(libcpp) diff --git a/test_programs/libc/CMakeLists.txt b/test_programs/libc/CMakeLists.txt index 1cd69f0..4baf7a2 100644 --- a/test_programs/libc/CMakeLists.txt +++ b/test_programs/libc/CMakeLists.txt @@ -6,5 +6,7 @@ add_executable(${TEST} target_link_libraries(${TEST} PRIVATE dlibc + dandelion_file_system dandelion_runtime + runtime ) diff --git a/test_programs/libcpp/CMakeLists.txt b/test_programs/libcpp/CMakeLists.txt index ec42ba2..9080e3a 100644 --- a/test_programs/libcpp/CMakeLists.txt +++ b/test_programs/libcpp/CMakeLists.txt @@ -7,5 +7,12 @@ add_executable(${TEST} target_link_libraries(${TEST} PRIVATE dlibcxx dlibc + dandelion_file_system dandelion_runtime + runtime ) + +# prepare files to run the function in debug mode +file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/input_sets) +file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/output_sets) +file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/output_sets/stdio) \ No newline at end of file diff --git a/test_programs/libcpp/test.cpp b/test_programs/libcpp/test.cpp index ddcd017..4511115 100644 --- a/test_programs/libcpp/test.cpp +++ b/test_programs/libcpp/test.cpp @@ -11,7 +11,7 @@ int main(){ fs.close(); cout << "stdout print" << endl; - + cerr << "stderr print" << endl; return 0; } From e2f209e472c3146c11955ba16f4b4c3a1398e4a6 Mon Sep 17 00:00:00 2001 From: Tom Kuchler Date: Tue, 23 Sep 2025 16:19:10 +0200 Subject: [PATCH 02/20] Fix formatting --- .github/workflows/file_checks.yml | 2 + file_system/file_system.c | 12 +-- file_system/paths.h | 16 +-- newlib_shim/shim.c | 4 +- newlib_shim/unistd.c | 160 ++++++++++++------------------ system/platform/debug/debug.c | 11 +- 6 files changed, 88 insertions(+), 117 deletions(-) diff --git a/.github/workflows/file_checks.yml b/.github/workflows/file_checks.yml index 36ee1c8..014a289 100644 --- a/.github/workflows/file_checks.yml +++ b/.github/workflows/file_checks.yml @@ -16,3 +16,5 @@ jobs: - name: C format check run: find . -iname '*.h' -o -iname '*.c' | clang-format --dry-run -Werror --files=/dev/stdin --style=LLVM + # if fails run the following to automatically correct it + # find ./file_system/ ./newlib_shim/ ./runtime/ ./sdk_install/ ./system/ ./test_programs/ -iname '*.h' -o -iname '*.c' | clang-format -Werror --files=/dev/stdin --style=LLVM -i \ No newline at end of file diff --git a/file_system/file_system.c b/file_system/file_system.c index 48c6367..73cb1ed 100644 --- a/file_system/file_system.c +++ b/file_system/file_system.c @@ -69,12 +69,14 @@ int link_file_to_folder(D_File *folder, D_File *file) { file->next = NULL; } else { D_File *current = folder->child; - if (namecmp(file->name, FS_NAME_LENGTH, current->name, FS_NAME_LENGTH) < 0) { + if (namecmp(file->name, FS_NAME_LENGTH, current->name, FS_NAME_LENGTH) < + 0) { file->next = current; folder->child = file; } else { while (current->next != NULL) { - if (namecmp(file->name, FS_NAME_LENGTH, current->next->name, FS_NAME_LENGTH) < 0) { + if (namecmp(file->name, FS_NAME_LENGTH, current->next->name, + FS_NAME_LENGTH) < 0) { break; } else { current = current->next; @@ -482,8 +484,7 @@ int fs_initialize(int *argc, char ***argv, char ***environ) { // TODO write to stderr on what happened return -1; } - int is_stdio_folder = - namecmp(set_path.path, set_path.length, "stdio", 5); + int is_stdio_folder = namecmp(set_path.path, set_path.length, "stdio", 5); size_t input_items = dandelion_input_buffer_count(set_index); for (size_t item_index = 0; item_index < input_items; item_index++) { IoBuffer *item_buffer = dandelion_get_input(set_index, item_index); @@ -509,8 +510,7 @@ int fs_initialize(int *argc, char ***argv, char ***environ) { return -1; } if (is_stdio_folder == 0) { - int is_stdin = - namecmp(file_path.path, file_path.length, "stdin", 5); + int is_stdin = namecmp(file_path.path, file_path.length, "stdin", 5); if (is_stdin == 0) { error = open_existing_file(STDIN_FILENO, item_file, O_RDONLY, 0, 0); if (error != 0) diff --git a/file_system/paths.h b/file_system/paths.h index 1a1a295..35dd676 100644 --- a/file_system/paths.h +++ b/file_system/paths.h @@ -23,23 +23,25 @@ static inline size_t namelen(const char *const name, size_t max_len) { return length; } -static inline int namecmp(const char *const name1, size_t name1_length, const char *const name2, - size_t name2_length) { +static inline int namecmp(const char *const name1, size_t name1_length, + const char *const name2, size_t name2_length) { size_t max_length = name1_length < name2_length ? name1_length : name2_length; for (size_t index = 0; index < max_length; index++) { - // this also automatically returns -1 if one of them is null terminated earlier than their length + // this also automatically returns -1 if one of them is null terminated + // earlier than their length if (name1[index] != name2[index]) return name1[index] < name2[index] ? -1 : 1; // are the same if we got here if (name1[index] == '\0') return 0; } - // they are the same until the end of the shorter one or there has not been null termination - if(name1_length < name2_length) + // they are the same until the end of the shorter one or there has not been + // null termination + if (name1_length < name2_length) return -1; - else if(name2_length < name1_length) + else if (name2_length < name1_length) return 1; - else + else return 0; } diff --git a/newlib_shim/shim.c b/newlib_shim/shim.c index 4e35d50..d2374ab 100644 --- a/newlib_shim/shim.c +++ b/newlib_shim/shim.c @@ -185,9 +185,7 @@ int access(const char *file, int mode) { int lstat(const char *file, struct stat *buf) { return stat(file, buf); } -mode_t umask(mode_t mask) { - return 0777; -} +mode_t umask(mode_t mask) { return 0777; } int statvfs(const char *file, struct statvfs *st) { errno = ENOSYS; diff --git a/newlib_shim/unistd.c b/newlib_shim/unistd.c index b8837a0..d6c5c56 100644 --- a/newlib_shim/unistd.c +++ b/newlib_shim/unistd.c @@ -1,55 +1,48 @@ -#include #include +#include -// Implement functions from unistd that are not already defined in other parts of newlibs libc -// Or in something we supply +// Implement functions from unistd that are not already defined in other parts +// of newlibs libc Or in something we supply // unsigned alarm (unsigned __secs); -int chdir (const char *__path) { - *__errno() = EACCES; - return -1; +int chdir(const char *__path) { + *__errno() = EACCES; + return -1; } -int fchdir (int __fildes) { - *__errno() = EACCES; - return -1; +int fchdir(int __fildes) { + *__errno() = EACCES; + return -1; } -int chroot (const char *__path) { - *__errno() = EACCES; - return -1; +int chroot(const char *__path) { + *__errno() = EACCES; + return -1; } // int chmod (const char *__path, mode_t __mode); // int chown (const char *__path, uid_t __owner, gid_t __group); -// int close_range (unsigned int __firstfd, unsigned int __lastfd, int __flags); -// size_t confstr (int __name, char *__buf, size_t __len); -// char * crypt (const char *__key, const char *__salt); -// char * ctermid (char *__s); +// int close_range (unsigned int __firstfd, unsigned int __lastfd, int +// __flags); size_t confstr (int __name, char *__buf, size_t __len); char * +// crypt (const char *__key, const char *__salt); char * ctermid (char *__s); // char * cuserid (char *__s); // int daemon (int nochdir, int noclose); // function to duplicate file descriptor to second file number -// the filedescriptors should act as one, meaning if seek is called on one of them, -// the effects should also be visible accessing the file through the new one. -// if the second parameter is -1, the lowest free file descriptor is chosen, -// otherwise the file descriptor in filedes2 is used to duplicate the filedescriptor. -// If filedes2 was open before, it will be closed. -int dup3 (int __fildes, int __fildes2, int flags) { - *__errno() = EMFILE; - return -1; -} -int dup2 (int __fildes, int __fildes2) { - return dup3(__fildes, __fildes2, 0); -} -int dup (int __fildes) { - return dup3(__fildes, -1, 0); +// the filedescriptors should act as one, meaning if seek is called on one of +// them, the effects should also be visible accessing the file through the new +// one. if the second parameter is -1, the lowest free file descriptor is +// chosen, otherwise the file descriptor in filedes2 is used to duplicate the +// filedescriptor. If filedes2 was open before, it will be closed. +int dup3(int __fildes, int __fildes2, int flags) { + *__errno() = EMFILE; + return -1; } +int dup2(int __fildes, int __fildes2) { return dup3(__fildes, __fildes2, 0); } +int dup(int __fildes) { return dup3(__fildes, -1, 0); } -int eaccess (const char *__path, int __mode) { - return access(__path, __mode); -} -int euidaccess (const char *__path, int __mode){ - return eaccess(__path, __mode); +int eaccess(const char *__path, int __mode) { return access(__path, __mode); } +int euidaccess(const char *__path, int __mode) { + return eaccess(__path, __mode); } // void encrypt (char *__block, int __edflag); @@ -62,33 +55,26 @@ int euidaccess (const char *__path, int __mode){ // #if __MISC_VISIBLE // int execlpe (const char *__file, const char *, ...); // #endif -int execv (const char *__path, char * const __argv[]) { - return execve(__path,__argv, environ); +int execv(const char *__path, char *const __argv[]) { + return execve(__path, __argv, environ); } // already given in newlib -// int execve (const char *__path, char * const __argv[], char * const __envp[]); -// int execvp (const char *__file, char * const __argv[]); -// int execvpe (const char *__file, char * const __argv[], char * const __envp[]); +// int execve (const char *__path, char * const __argv[], char * const +// __envp[]); int execvp (const char *__file, char * const __argv[]); int +// execvpe (const char *__file, char * const __argv[], char * const __envp[]); // #if __ATFILE_VISIBLE // int faccessat (int __dirfd, const char *__path, int __mode, int __flags); // #endif // int fchmod (int __fildes, mode_t __mode); // int fchown (int __fildes, uid_t __owner, gid_t __group); // #if __ATFILE_VISIBLE -// int fchownat (int __dirfd, const char *__path, uid_t __owner, gid_t __group, int __flags); -// #endif -// int fexecve (int __fd, char * const __argv[], char * const __envp[]); -// long fpathconf (int __fd, int __name); -int fsync (int __fd) { - return 0; -} -int fdatasync (int __fd) { - return 0; -} +// int fchownat (int __dirfd, const char *__path, uid_t __owner, gid_t __group, +// int __flags); #endif int fexecve (int __fd, char * const __argv[], char * +// const __envp[]); long fpathconf (int __fd, int __name); +int fsync(int __fd) { return 0; } +int fdatasync(int __fd) { return 0; } // char * get_current_dir_name (void); -char * getcwd (char *__buf, size_t __size) { - return "/"; -} +char *getcwd(char *__buf, size_t __size) { return "/"; } // int getdomainname (char *__name, size_t __len); // gid_t getegid (void); // uid_t geteuid (void); @@ -111,47 +97,30 @@ char * getcwd (char *__buf, size_t __size) { // char * getwd (char *__buf); // int lchown (const char *__path, uid_t __owner, gid_t __group); // #if __ATFILE_VISIBLE -// int linkat (int __dirfd1, const char *__path1, int __dirfd2, const char *__path2, int __flags); -// #endif -// #if __MISC_VISIBLE || __XSI_VISIBLE -// int nice (int __nice_value); -// #endif -// #if __MISC_VISIBLE || __XSI_VISIBLE >= 4 -// int lockf (int __fd, int __cmd, off_t __len); -// #endif -// long pathconf (const char *__path, int __name); -// int pause (void); -// #if __POSIX_VISIBLE >= 199506 -// int pthread_atfork (void (*)(void), void (*)(void), void (*)(void)); -// #endif -// int pipe (int __fildes[2]) { +// int linkat (int __dirfd1, const char *__path1, int __dirfd2, const char +// *__path2, int __flags); #endif #if __MISC_VISIBLE || __XSI_VISIBLE int +// nice (int __nice_value); #endif #if __MISC_VISIBLE || __XSI_VISIBLE >= 4 int +// lockf (int __fd, int __cmd, off_t __len); #endif long pathconf (const char +// *__path, int __name); int pause (void); #if __POSIX_VISIBLE >= 199506 int +// pthread_atfork (void (*)(void), void (*)(void), void (*)(void)); #endif int +// pipe (int __fildes[2]) { // pipe2(__fileds[2], 0); // } // int pipe2 (int __fildes[2], int flags); // #if __POSIX_VISIBLE >= 200809 || __XSI_VISIBLE >= 500 // ssize_t pread (int __fd, void *__buf, size_t __nbytes, off_t __offset); -// ssize_t pwrite (int __fd, const void *__buf, size_t __nbytes, off_t __offset); -// #endif -// _READ_WRITE_RETURN_TYPE read (int __fd, void *__buf, size_t __nbyte); -// #if __BSD_VISIBLE -// int rresvport (int *__alport); -// int revoke (char *__path); -// #endif -// int rmdir (const char *__path); -// #if __BSD_VISIBLE -// int ruserok (const char *rhost, int superuser, const char *ruser, const char *luser); -// #endif -// #if __BSD_VISIBLE || (__XSI_VISIBLE >= 4 && __POSIX_VISIBLE < 200112) -// void * sbrk (ptrdiff_t __incr); -// #endif -// #if __BSD_VISIBLE || __POSIX_VISIBLE >= 200112 -// int setegid (gid_t __gid); -// int seteuid (uid_t __uid); -// #endif -// int setgid (gid_t __gid); -int setgroups (int ngroups, const gid_t *grouplist) { - *__errno() = EPERM; - return -1; +// ssize_t pwrite (int __fd, const void *__buf, size_t __nbytes, off_t +// __offset); #endif _READ_WRITE_RETURN_TYPE read (int __fd, void *__buf, size_t +// __nbyte); #if __BSD_VISIBLE int rresvport (int *__alport); int revoke +// (char *__path); #endif int rmdir (const char *__path); #if __BSD_VISIBLE +// int ruserok (const char *rhost, int superuser, const char *ruser, const char +// *luser); #endif #if __BSD_VISIBLE || (__XSI_VISIBLE >= 4 && __POSIX_VISIBLE < +// 200112) void * sbrk (ptrdiff_t __incr); #endif #if __BSD_VISIBLE || +// __POSIX_VISIBLE >= 200112 int setegid (gid_t __gid); int seteuid +// (uid_t __uid); #endif int setgid (gid_t __gid); +int setgroups(int ngroups, const gid_t *grouplist) { + *__errno() = EPERM; + return -1; } // #if __BSD_VISIBLE || (__XSI_VISIBLE && __XSI_VISIBLE < 500) // int sethostname (const char *, size_t); @@ -180,9 +149,7 @@ int setgroups (int ngroups, const gid_t *grouplist) { // int ttyname_r (int, char *, size_t); // int unlink (const char *__path); // #if __XSI_VISIBLE >= 500 && __POSIX_VISIBLE < 200809 || __BSD_VISIBLE -int usleep (useconds_t __useconds) { - return 0; -} +int usleep(useconds_t __useconds) { return 0; } // #endif // #if __BSD_VISIBLE // int vhangup (void); @@ -212,7 +179,8 @@ int usleep (useconds_t __useconds) { // #endif // #if __BSD_VISIBLE || __POSIX_VISIBLE >= 200112 || __XSI_VISIBLE >= 500 -// #if !(defined (_WINSOCK_H) || defined (_WINSOCKAPI_) || defined (__USE_W32_SOCKETS)) +// #if !(defined (_WINSOCK_H) || defined (_WINSOCKAPI_) || defined +// (__USE_W32_SOCKETS)) // /* winsock[2].h defines as __stdcall, and with int as 2nd arg */ // int gethostname (char *__name, size_t __len); // #endif @@ -230,9 +198,9 @@ int usleep (useconds_t __useconds) { // ssize_t readlink (const char *__restrict __path, // char *__restrict __buf, size_t __buflen); -int symlink (const char *__name1, const char *__name2) { - *__errno() = EPERM; - return -1; +int symlink(const char *__name1, const char *__name2) { + *__errno() = EPERM; + return -1; } // #endif // #if __ATFILE_VISIBLE diff --git a/system/platform/debug/debug.c b/system/platform/debug/debug.c index d313324..143b347 100644 --- a/system/platform/debug/debug.c +++ b/system/platform/debug/debug.c @@ -326,15 +326,16 @@ void __dandelion_platform_exit(void) { dump_global_data(); // print exit code char exit_message[] = "Exiting with code "; - size_t message_len = my_strlen(exit_message); + size_t message_len = my_strlen(exit_message); write_all(1, exit_message, message_len); char exit_code_string[11] = " \n"; // convert int to string - int exit_code = sysdata.exit_code; - for(size_t index = 0; index < 10; index++) { - exit_code_string[9-index] = '0' + (exit_code % 10); + int exit_code = sysdata.exit_code; + for (size_t index = 0; index < 10; index++) { + exit_code_string[9 - index] = '0' + (exit_code % 10); exit_code = exit_code / 10; - if (exit_code == 0) break; + if (exit_code == 0) + break; } write_all(1, exit_code_string, 11); __syscall(SYS_exit_group, sysdata.exit_code); From 5678648dcd09f85e36fffcd08318464cbf5a58a8 Mon Sep 17 00:00:00 2001 From: Andri McFly <23231408+SleepyMorpheus@users.noreply.github.com> Date: Tue, 29 Jul 2025 10:15:19 +0200 Subject: [PATCH 03/20] add functions time and utime --- newlib_shim/Makefile.inc | 1 + newlib_shim/patch_script | 1 + newlib_shim/time.c | 5 +++++ newlib_shim/utime.c | 11 +++++++++++ 4 files changed, 18 insertions(+) create mode 100644 newlib_shim/utime.c diff --git a/newlib_shim/Makefile.inc b/newlib_shim/Makefile.inc index b8fed40..3fc69bd 100644 --- a/newlib_shim/Makefile.inc +++ b/newlib_shim/Makefile.inc @@ -3,4 +3,5 @@ libc_a_SOURCES += \ %D%/pthread.c \ %D%/shim.c \ %D%/time.c \ + %D%/utime.c \ %D%/unistd.c \ No newline at end of file diff --git a/newlib_shim/patch_script b/newlib_shim/patch_script index 31f1a81..ac23de0 100755 --- a/newlib_shim/patch_script +++ b/newlib_shim/patch_script @@ -23,6 +23,7 @@ cp $THIS_DIR/dirent.c $1/newlib/libc/sys/dandelion/dirent.c cp $THIS_DIR/pthread.c $1/newlib/libc/sys/dandelion/pthread.c cp $THIS_DIR/time.c $1/newlib/libc/sys/dandelion/time.c cp $THIS_DIR/unistd.c $1/newlib/libc/sys/dandelion/unistd.c +cp $THIS_DIR/utime.c $1/newlib/libc/sys/dandelion/utime.c cp $THIS_DIR/../include/dandelion/crt.h $1/newlib/libc/sys/dandelion/crt.h if ! test -d $1/newlib/libc/sys/dandelion/sys then diff --git a/newlib_shim/time.c b/newlib_shim/time.c index a278e54..43564a8 100644 --- a/newlib_shim/time.c +++ b/newlib_shim/time.c @@ -68,3 +68,8 @@ int nanosleep(const struct timespec *rqtp, struct timespec *rmtp) { // always pretend to sleep for that amount return 0; } + +time_t time(time_t *t) { + errno = EINVAL; + return -1; +} \ No newline at end of file diff --git a/newlib_shim/utime.c b/newlib_shim/utime.c new file mode 100644 index 0000000..b708f9a --- /dev/null +++ b/newlib_shim/utime.c @@ -0,0 +1,11 @@ +#include +#include +#include + +#undef errno +extern int errno; + +int utime(const char *filename, const struct utimbuf *buf) { + errno = EINVAL; + return -1; +} From 8f934907ba6829ab129d7e8d23a01691838d31a7 Mon Sep 17 00:00:00 2001 From: Andri Florin Date: Tue, 29 Jul 2025 12:15:44 +0200 Subject: [PATCH 04/20] added pthread functions --- newlib_shim/Makefile.inc | 1 - newlib_shim/patch_script | 1 - newlib_shim/pthread.c | 19 +++++++++++++++++++ newlib_shim/time.c | 6 ++++++ newlib_shim/unistd.c | 14 ++++++++------ newlib_shim/utime.c | 11 ----------- 6 files changed, 33 insertions(+), 19 deletions(-) delete mode 100644 newlib_shim/utime.c diff --git a/newlib_shim/Makefile.inc b/newlib_shim/Makefile.inc index 3fc69bd..b8fed40 100644 --- a/newlib_shim/Makefile.inc +++ b/newlib_shim/Makefile.inc @@ -3,5 +3,4 @@ libc_a_SOURCES += \ %D%/pthread.c \ %D%/shim.c \ %D%/time.c \ - %D%/utime.c \ %D%/unistd.c \ No newline at end of file diff --git a/newlib_shim/patch_script b/newlib_shim/patch_script index ac23de0..31f1a81 100755 --- a/newlib_shim/patch_script +++ b/newlib_shim/patch_script @@ -23,7 +23,6 @@ cp $THIS_DIR/dirent.c $1/newlib/libc/sys/dandelion/dirent.c cp $THIS_DIR/pthread.c $1/newlib/libc/sys/dandelion/pthread.c cp $THIS_DIR/time.c $1/newlib/libc/sys/dandelion/time.c cp $THIS_DIR/unistd.c $1/newlib/libc/sys/dandelion/unistd.c -cp $THIS_DIR/utime.c $1/newlib/libc/sys/dandelion/utime.c cp $THIS_DIR/../include/dandelion/crt.h $1/newlib/libc/sys/dandelion/crt.h if ! test -d $1/newlib/libc/sys/dandelion/sys then diff --git a/newlib_shim/pthread.c b/newlib_shim/pthread.c index d9f5783..a6faf5e 100644 --- a/newlib_shim/pthread.c +++ b/newlib_shim/pthread.c @@ -196,4 +196,23 @@ int pthread_key_delete(pthread_key_t key) { int pthread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void)) { return ENOMEM; +} + +int pthread_attr_init(pthread_attr_t *attr) { + return EINVAL; +} +int pthread_attr_destroy(pthread_attr_t *attr) { + return EINVAL; +} + +int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize) { + return EINVAL; +} +int pthread_attr_getstacksize(const pthread_attr_t *restrict attr, + size_t *restrict stacksize) { + return EINVAL; +} + +void pthread_exit(void *retval) { + return; } \ No newline at end of file diff --git a/newlib_shim/time.c b/newlib_shim/time.c index 43564a8..c7ab289 100644 --- a/newlib_shim/time.c +++ b/newlib_shim/time.c @@ -6,6 +6,7 @@ #define _POSIX_MONOTONIC_CLOCK #include #include +#include #undef errno extern int errno; @@ -72,4 +73,9 @@ int nanosleep(const struct timespec *rqtp, struct timespec *rmtp) { time_t time(time_t *t) { errno = EINVAL; return -1; +} + +int utime(const char *filename, const struct utimbuf *buf) { + errno = EINVAL; + return -1; } \ No newline at end of file diff --git a/newlib_shim/unistd.c b/newlib_shim/unistd.c index d6c5c56..be63924 100644 --- a/newlib_shim/unistd.c +++ b/newlib_shim/unistd.c @@ -96,12 +96,14 @@ char *getcwd(char *__buf, size_t __size) { return "/"; } // char * getusershell (void); // char * getwd (char *__buf); // int lchown (const char *__path, uid_t __owner, gid_t __group); -// #if __ATFILE_VISIBLE -// int linkat (int __dirfd1, const char *__path1, int __dirfd2, const char -// *__path2, int __flags); #endif #if __MISC_VISIBLE || __XSI_VISIBLE int -// nice (int __nice_value); #endif #if __MISC_VISIBLE || __XSI_VISIBLE >= 4 int -// lockf (int __fd, int __cmd, off_t __len); #endif long pathconf (const char -// *__path, int __name); int pause (void); #if __POSIX_VISIBLE >= 199506 int +// #if __ATFILE_VISIBLE int linkat (int __dirfd1, const char *__path1, int __dirfd2, const char *__path2, int __flags); #endif +// #if __MISC_VISIBLE || __XSI_VISIBLE int nice (int __nice_value); #endif +// #if __MISC_VISIBLE || __XSI_VISIBLE >= 4 int lockf (int __fd, int __cmd, off_t __len); #endif +// long pathconf (const char *__path, int __name); +int pause (void) { + return 0; +} +//#if __POSIX_VISIBLE >= 199506 int // pthread_atfork (void (*)(void), void (*)(void), void (*)(void)); #endif int // pipe (int __fildes[2]) { // pipe2(__fileds[2], 0); diff --git a/newlib_shim/utime.c b/newlib_shim/utime.c deleted file mode 100644 index b708f9a..0000000 --- a/newlib_shim/utime.c +++ /dev/null @@ -1,11 +0,0 @@ -#include -#include -#include - -#undef errno -extern int errno; - -int utime(const char *filename, const struct utimbuf *buf) { - errno = EINVAL; - return -1; -} From 7d3abb8d709c3561e592f167e9d6cccf7c13cf6b Mon Sep 17 00:00:00 2001 From: Andri Florin Date: Tue, 29 Jul 2025 23:32:57 +0200 Subject: [PATCH 05/20] getpagesize + dirfd --- newlib_shim/dirent.c | 3 +++ newlib_shim/unistd.c | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/newlib_shim/dirent.c b/newlib_shim/dirent.c index f795cdf..c23212e 100644 --- a/newlib_shim/dirent.c +++ b/newlib_shim/dirent.c @@ -51,3 +51,6 @@ long int telldir(DIR *dir) { extern void dandelion_seekdir(DIR *dir, long int index); void seekdir(DIR *dir, long int index) { return dandelion_seekdir(dir, index); } +int dirfd(DIR *dirp) { + return -1; +} diff --git a/newlib_shim/unistd.c b/newlib_shim/unistd.c index be63924..e89cafb 100644 --- a/newlib_shim/unistd.c +++ b/newlib_shim/unistd.c @@ -86,7 +86,9 @@ char *getcwd(char *__buf, size_t __size) { return "/"; } // int getlogin_r (char *name, size_t namesize) ; // #endif // char * getpass (const char *__prompt); -// int getpagesize (void); +int getpagesize (void) { + return 4096; // assuming a page size of 4096 bytes +} // pid_t getpgid (pid_t); // pid_t getpgrp (void); // pid_t getpid (void); // already implementedc From 5d6c74d7d9476ddf0e5231707c2abc7af0e93d3b Mon Sep 17 00:00:00 2001 From: Andri Florin Date: Wed, 13 Aug 2025 17:55:18 +0200 Subject: [PATCH 06/20] handle dev/urandom --- file_system/file_system.c | 28 ++++++++++++++++++++++++++++ file_system/file_system.h | 1 + file_system/fs_implementation.c | 10 ++++++++++ test_programs/urandom.c | 24 ++++++++++++++++++++++++ 4 files changed, 63 insertions(+) create mode 100644 test_programs/urandom.c diff --git a/file_system/file_system.c b/file_system/file_system.c index 73cb1ed..67beb18 100644 --- a/file_system/file_system.c +++ b/file_system/file_system.c @@ -465,6 +465,34 @@ int fs_initialize(int *argc, char ***argv, char ***environ) { if (error != 0) return error; + // create dev folder and urandom file + D_File *dev_folder = dandelion_alloc(sizeof(D_File), _Alignof(D_File)); + if (dev_folder == NULL) { + dandelion_exit(ENOMEM); + return -1; + } + + memcpy(dev_folder->name, "dev", 4); + dev_folder->type = DIRECTORY; + dev_folder->child = NULL; + dev_folder->hard_links = 0; + if ((error = link_file_to_folder(fs_root, dev_folder)) != 0) { + return error; + } + + // create and open urandom + Path urandom_path = path_from_string("urandom"); + D_File *urandom_file = create_file(&urandom_path, NULL, 0, S_IWUSR); + if (urandom_file == NULL) + return -1; + error = open_existing_file(URANDOM_FILENO, urandom_file, O_WRONLY, 0, 0); + if (error != 0) + return error; + error = link_file_to_folder(dev_folder, urandom_file); + if (error != 0) + return error; + + // set to NULL to be able to check if it was set by inputs *argc = 0; *argv = NULL; diff --git a/file_system/file_system.h b/file_system/file_system.h index 0df9554..b837916 100644 --- a/file_system/file_system.h +++ b/file_system/file_system.h @@ -20,6 +20,7 @@ #define STDIN_FILENO 0 #define STDOUT_FILENO 1 #define STDERR_FILENO 2 +#define URANDOM_FILENO 3 #define USE_OFFSET 1 #define MOVE_OFFSET 2 diff --git a/file_system/fs_implementation.c b/file_system/fs_implementation.c index 8c878c0..9f1a23b 100644 --- a/file_system/fs_implementation.c +++ b/file_system/fs_implementation.c @@ -338,6 +338,16 @@ int64_t dandelion_lseek(int file, int64_t offset, int whence) { size_t dandelion_read(int file, char *ptr, size_t len, int64_t offset, char options) { + + // handle special case /dev/urandom URANDOM_FILENO use fake random data + if (file == URANDOM_FILENO) { + // generate fake random data + for (size_t i = 0; i < len; i++) { + ptr[i] = (offset + i) % 256; + } + return len; + } + // get the file descriptor OpenFile *open_file = &open_files[file]; // check there is a valid file descriptor there and that it is writable diff --git a/test_programs/urandom.c b/test_programs/urandom.c new file mode 100644 index 0000000..a7a72c6 --- /dev/null +++ b/test_programs/urandom.c @@ -0,0 +1,24 @@ +#include +#include +#include "dandelion/runtime.h" + +void _start() +{ + dandelion_init(); + FILE *file = fopen("/dev/urandom", "rb"); + if (file == NULL) { + perror("Error opening /dev/urandom"); + dandelion_exit(1); + } + + unsigned char c; + if (fread(&c, 1, 1, file) == 1) { + printf("First random byte: %u\n", c); // as number + // printf("First random char: %c\n", c); // as ASCII char (may be non-printable) + } else { + perror("Error reading from /dev/urandom"); + } + + fclose(file); + dandelion_exit(c); +} From 6a9b6166333e3521f2031d9ae1f2811d9e684d73 Mon Sep 17 00:00:00 2001 From: Andri Florin Date: Tue, 19 Aug 2025 14:40:06 +0200 Subject: [PATCH 07/20] impl pthread_cond_* --- newlib_shim/pthread.c | 43 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/newlib_shim/pthread.c b/newlib_shim/pthread.c index a6faf5e..4ea67a2 100644 --- a/newlib_shim/pthread.c +++ b/newlib_shim/pthread.c @@ -86,20 +86,51 @@ int pthread_rwlock_unlock(pthread_rwlock_t *rwlock) { return EINVAL; } int pthread_cond_init(pthread_cond_t *restrict cond, const pthread_condattr_t *restrict attr) { - return EAGAIN; + (void)attr; + *cond = _PTHREAD_COND_INITIALIZER; + return 0; +} + +int pthread_cond_destroy(pthread_cond_t *cond) { + pthread_cond_t current = *cond; + if ((current & DESTROYED) == 0) + return EINVAL; + *cond &= ~DESTROYED; + return 0; } -int pthread_cond_destroy(pthread_cond_t *cond) { return EINVAL; } + int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex) { - return ENOTRECOVERABLE; + if ((*cond & DESTROYED) == 0 || (*mutex & DESTROYED) == 0) + return EINVAL; + if ((*mutex & LOCKED) != 0) + return EPERM; + + // "Atomically" release and immediately re-acquire since no other threads exist + int r = pthread_mutex_unlock(mutex); + if (r != 0) return r; + return pthread_mutex_lock(mutex); } + int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, const struct timespec *restrict abstim) { - return ENOTRECOVERABLE; + (void)abstim; + return pthread_cond_wait(cond, mutex); +} + +int pthread_cond_signal(pthread_cond_t *cond) { + if ((*cond & DESTROYED) == 0) + return EINVAL; + return 0; } -int pthread_cond_signal(pthread_cond_t *cond) { return EINVAL; } -int pthread_cond_broadcast(pthread_cond_t *cond) { return EINVAL; } + +int pthread_cond_broadcast(pthread_cond_t *cond) { + if ((*cond & DESTROYED) == 0) + return EINVAL; + return 0; +} + int pthread_once(pthread_once_t *once_control, void (*init_routine)(void)) { if (once_control->init_executed == 0) { From c6ec3ba6e55efc6f3ab30112487aa96bbcc4ea17 Mon Sep 17 00:00:00 2001 From: Andri Florin Date: Wed, 20 Aug 2025 17:04:32 +0200 Subject: [PATCH 08/20] pthread cleanup --- newlib_shim/pthread.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/newlib_shim/pthread.c b/newlib_shim/pthread.c index 4ea67a2..c76bb6f 100644 --- a/newlib_shim/pthread.c +++ b/newlib_shim/pthread.c @@ -106,7 +106,6 @@ int pthread_cond_wait(pthread_cond_t *restrict cond, if ((*mutex & LOCKED) != 0) return EPERM; - // "Atomically" release and immediately re-acquire since no other threads exist int r = pthread_mutex_unlock(mutex); if (r != 0) return r; return pthread_mutex_lock(mutex); @@ -120,8 +119,6 @@ int pthread_cond_timedwait(pthread_cond_t *restrict cond, } int pthread_cond_signal(pthread_cond_t *cond) { - if ((*cond & DESTROYED) == 0) - return EINVAL; return 0; } From 4d4cc0b8cc4506b091e34bdd77d039be72fd17ba Mon Sep 17 00:00:00 2001 From: Andri Florin Date: Wed, 20 Aug 2025 17:05:10 +0200 Subject: [PATCH 09/20] disable COMPILER_RT_BAREMETAL_BUILD (+ added mman.h) --- CMakeLists.txt | 1 - newlib_shim/mman.h | 64 ++++++++++++++++++++++++++++++++++++++++ newlib_shim/patch_script | 1 + 3 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 newlib_shim/mman.h diff --git a/CMakeLists.txt b/CMakeLists.txt index f18cb68..b292bf5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -208,7 +208,6 @@ if(NEWLIB) -DLLVM_INCLUDE_TESTS=OFF -DCOMPILER_RT_DEFAULT_TARGET_ONLY=ON -DCOMPILER_RT_BUILD_BUILTINS=ON - -DCOMPILER_RT_BAREMETAL_BUILD=ON -DCOMPILER_RT_BUILD_XRAY=OFF -DCOMPILER_RT_BUILD_LIBFUZZER=OFF -DCOMPILER_RT_BUILD_MEMPROF=OFF diff --git a/newlib_shim/mman.h b/newlib_shim/mman.h new file mode 100644 index 0000000..535e7eb --- /dev/null +++ b/newlib_shim/mman.h @@ -0,0 +1,64 @@ +/* sys/mman.h + +Copyright 1996, 1997, 1998, 2000, 2001 Red Hat, Inc. + +This file is part of Cygwin. + +This software is a copyrighted work licensed under the terms of the +Cygwin license. Please consult the file "CYGWIN_LICENSE" for +details. */ + +#ifndef _SYS_MMAN_H_ +#define _SYS_MMAN_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include +#include + +#define PROT_NONE 0 +#define PROT_READ 1 +#define PROT_WRITE 2 +#define PROT_EXEC 4 + +#define MAP_FILE 0 +#define MAP_SHARED 1 +#define MAP_PRIVATE 2 +#define MAP_TYPE 0xF +#define MAP_FIXED 0x10 +#define MAP_ANONYMOUS 0x20 +#define MAP_ANON MAP_ANONYMOUS + /* Non-standard flag */ +#if 0 /* Not yet implemented */ +#define MAP_NORESERVE 0x4000 /* Don't reserve swap space for this mapping. +Page protection must be set explicitely +to access page. */ +#endif +#define MAP_AUTOGROW 0x8000 /* Grow underlying object to mapping size. +File must be opened for writing. */ + +#define MAP_FAILED ((void *)-1) + + /* + * Flags for msync. + */ +#define MS_ASYNC 1 +#define MS_SYNC 2 +#define MS_INVALIDATE 4 + +#ifndef __INSIDE_CYGWIN__ + extern void *mmap (void *__addr, size_t __len, int __prot, int __flags, int __fd, off_t __off); +#endif + extern int munmap (void *__addr, size_t __len); + extern int mprotect (void *__addr, size_t __len, int __prot); + extern int msync (void *__addr, size_t __len, int __flags); + extern int mlock (const void *__addr, size_t __len); + extern int munlock (const void *__addr, size_t __len); + +#ifdef __cplusplus +}; +#endif /* __cplusplus */ + +#endif /* _SYS_MMAN_H_ */ \ No newline at end of file diff --git a/newlib_shim/patch_script b/newlib_shim/patch_script index 31f1a81..6c303be 100755 --- a/newlib_shim/patch_script +++ b/newlib_shim/patch_script @@ -32,6 +32,7 @@ cp $THIS_DIR/dirent.h $1/newlib/libc/sys/dandelion/sys/dirent.h cp $THIS_DIR/statvfs.h $1/newlib/libc/sys/dandelion/sys/statvfs.h cp $THIS_DIR/sched.h $1/newlib/libc/sys/dandelion/sys/sched.h cp $THIS_DIR/cpuset.h $1/newlib/libc/sys/dandelion/sys/cpuset.h +cp $THIS_DIR/mman.h $1/newlib/libc/sys/dandelion/sys/mman.h cd $1 autoreconf cd newlib From 3e8bdcf407693fa9535ae190a391a77e26782166 Mon Sep 17 00:00:00 2001 From: Andri Florin Date: Mon, 25 Aug 2025 18:06:46 +0200 Subject: [PATCH 10/20] revert urandom changes --- file_system/file_system.c | 28 ---------------------------- file_system/file_system.h | 1 - file_system/fs_implementation.c | 10 ---------- 3 files changed, 39 deletions(-) diff --git a/file_system/file_system.c b/file_system/file_system.c index 67beb18..73cb1ed 100644 --- a/file_system/file_system.c +++ b/file_system/file_system.c @@ -465,34 +465,6 @@ int fs_initialize(int *argc, char ***argv, char ***environ) { if (error != 0) return error; - // create dev folder and urandom file - D_File *dev_folder = dandelion_alloc(sizeof(D_File), _Alignof(D_File)); - if (dev_folder == NULL) { - dandelion_exit(ENOMEM); - return -1; - } - - memcpy(dev_folder->name, "dev", 4); - dev_folder->type = DIRECTORY; - dev_folder->child = NULL; - dev_folder->hard_links = 0; - if ((error = link_file_to_folder(fs_root, dev_folder)) != 0) { - return error; - } - - // create and open urandom - Path urandom_path = path_from_string("urandom"); - D_File *urandom_file = create_file(&urandom_path, NULL, 0, S_IWUSR); - if (urandom_file == NULL) - return -1; - error = open_existing_file(URANDOM_FILENO, urandom_file, O_WRONLY, 0, 0); - if (error != 0) - return error; - error = link_file_to_folder(dev_folder, urandom_file); - if (error != 0) - return error; - - // set to NULL to be able to check if it was set by inputs *argc = 0; *argv = NULL; diff --git a/file_system/file_system.h b/file_system/file_system.h index b837916..0df9554 100644 --- a/file_system/file_system.h +++ b/file_system/file_system.h @@ -20,7 +20,6 @@ #define STDIN_FILENO 0 #define STDOUT_FILENO 1 #define STDERR_FILENO 2 -#define URANDOM_FILENO 3 #define USE_OFFSET 1 #define MOVE_OFFSET 2 diff --git a/file_system/fs_implementation.c b/file_system/fs_implementation.c index 9f1a23b..8c878c0 100644 --- a/file_system/fs_implementation.c +++ b/file_system/fs_implementation.c @@ -338,16 +338,6 @@ int64_t dandelion_lseek(int file, int64_t offset, int whence) { size_t dandelion_read(int file, char *ptr, size_t len, int64_t offset, char options) { - - // handle special case /dev/urandom URANDOM_FILENO use fake random data - if (file == URANDOM_FILENO) { - // generate fake random data - for (size_t i = 0; i < len; i++) { - ptr[i] = (offset + i) % 256; - } - return len; - } - // get the file descriptor OpenFile *open_file = &open_files[file]; // check there is a valid file descriptor there and that it is writable From be67bca120266d6f3e8f5d9249ca3929bc588f4d Mon Sep 17 00:00:00 2001 From: Andri Florin Date: Tue, 26 Aug 2025 13:15:15 +0200 Subject: [PATCH 11/20] fix file_system and more --- file_system/file_system.c | 50 ++++++++++++++++++++++------------- newlib_shim/unistd.c | 27 ++++++++++++------- system/platform/debug/debug.c | 5 +++- 3 files changed, 54 insertions(+), 28 deletions(-) diff --git a/file_system/file_system.c b/file_system/file_system.c index 73cb1ed..f992444 100644 --- a/file_system/file_system.c +++ b/file_system/file_system.c @@ -50,8 +50,7 @@ D_File *create_directory(Path *name, uint32_t mode) { new_file->type = DIRECTORY; new_file->child = NULL; new_file->hard_links = 0; - // directory where user has full permissions - new_file->mode = S_IFDIR | S_IRUSR | S_IWUSR | S_IXUSR; + new_file->mode = mode | S_IFDIR | S_IRUSR | S_IWUSR | S_IXUSR; return new_file; } @@ -60,6 +59,13 @@ int link_file_to_folder(D_File *folder, D_File *file) { // TODO set proper error number return -1; }; + + // Check if file already exists in this directory to prevent duplicates + D_File *existing = find_file_in_dir(folder, (Path){.path = file->name, .length = namelen(file->name, FS_NAME_LENGTH)}); + if (existing != NULL) { + return -1; + } + // set file parent to folder file->parent = folder; // increase the number of hard links to the file @@ -69,18 +75,24 @@ int link_file_to_folder(D_File *folder, D_File *file) { file->next = NULL; } else { D_File *current = folder->child; - if (namecmp(file->name, FS_NAME_LENGTH, current->name, FS_NAME_LENGTH) < - 0) { + int cmp_first = namecmp(file->name, FS_NAME_LENGTH, current->name, FS_NAME_LENGTH); + if (cmp_first < 0) { file->next = current; folder->child = file; + } else if (cmp_first == 0) { + file->hard_links -= 1; + return -1; } else { + // Find correct position to insert while (current->next != NULL) { - if (namecmp(file->name, FS_NAME_LENGTH, current->next->name, - FS_NAME_LENGTH) < 0) { + int cmp_next = namecmp(file->name, FS_NAME_LENGTH, current->next->name, FS_NAME_LENGTH); + if (cmp_next < 0) { break; - } else { - current = current->next; + } else if (cmp_next == 0) { + file->hard_links -= 1; + return -1; } + current = current->next; } file->next = current->next; current->next = file; @@ -99,8 +111,9 @@ D_File *find_file_in_dir(D_File *directory, Path file) { } for (D_File *current = directory->child; current != NULL; current = current->next) { + size_t stored_name_len = namelen(current->name, FS_NAME_LENGTH); int cmp_result = - namecmp(current->name, FS_NAME_LENGTH, file.path, file.length); + namecmp(current->name, stored_name_len, file.path, file.length); if (cmp_result == 0) { return current; } else if (cmp_result > 0) { @@ -162,10 +175,12 @@ D_File *create_directories(D_File *directory, Path path, char prevent_up) { directory = candidate_dir; continue; } - D_File *new_dir = dandelion_alloc(sizeof(D_File), _Alignof(D_File)); - new_dir->type = DIRECTORY; - memcpy(new_dir->name, current_path.path, current_path.length); - new_dir->child = NULL; + uint32_t dir_mode = S_IRUSR | S_IWUSR | S_IXUSR; + D_File *new_dir = create_directory(¤t_path, dir_mode); + if (new_dir == NULL) { + return NULL; + } + int error = link_file_to_folder(directory, new_dir); if (error < 0) { dandelion_free(new_dir); @@ -414,17 +429,16 @@ int fs_initialize(int *argc, char ***argv, char ***environ) { fs_root->parent = NULL; fs_root->child = NULL; fs_root->hard_links = 1; + // Set proper root directory mode + //fs_root->mode = S_IFDIR | S_IRUSR | S_IWUSR | S_IXUSR; // create stdio folder and stdout/stderr file - D_File *stdio_folder = dandelion_alloc(sizeof(D_File), _Alignof(D_File)); + Path stdio_path = path_from_string("stdio"); + D_File *stdio_folder = create_directory(&stdio_path, S_IRUSR | S_IWUSR | S_IXUSR); if (stdio_folder == NULL) { dandelion_exit(ENOMEM); return -1; } - memcpy(stdio_folder->name, "stdio", 6); - stdio_folder->type = DIRECTORY; - stdio_folder->child = NULL; - stdio_folder->hard_links = 0; if ((error = link_file_to_folder(fs_root, stdio_folder)) != 0) { return error; } diff --git a/newlib_shim/unistd.c b/newlib_shim/unistd.c index e89cafb..48252d9 100644 --- a/newlib_shim/unistd.c +++ b/newlib_shim/unistd.c @@ -1,5 +1,6 @@ #include #include +#include // Implement functions from unistd that are not already defined in other parts // of newlibs libc Or in something we supply @@ -28,14 +29,20 @@ int chroot(const char *__path) { // int daemon (int nochdir, int noclose); // function to duplicate file descriptor to second file number -// the filedescriptors should act as one, meaning if seek is called on one of -// them, the effects should also be visible accessing the file through the new -// one. if the second parameter is -1, the lowest free file descriptor is -// chosen, otherwise the file descriptor in filedes2 is used to duplicate the -// filedescriptor. If filedes2 was open before, it will be closed. -int dup3(int __fildes, int __fildes2, int flags) { - *__errno() = EMFILE; - return -1; +// the filedescriptors should act as one, meaning if seek is called on one of them, +// the effects should also be visible accessing the file through the new one. +// if the second parameter is -1, the lowest free file descriptor is chosen, +// otherwise the file descriptor in filedes2 is used to duplicate the filedescriptor. +// If filedes2 was open before, it will be closed. +int dup3 (int __fildes, int __fildes2, int flags) { + *__errno() = EMFILE; + return -1; +} +int dup2 (int __fildes, int __fildes2) { + return dup3(__fildes, __fildes2, 0); +} +int dup (int __fildes) { + return dup3(__fildes, -1, 0); } int dup2(int __fildes, int __fildes2) { return dup3(__fildes, __fildes2, 0); } int dup(int __fildes) { return dup3(__fildes, -1, 0); } @@ -74,7 +81,9 @@ int execv(const char *__path, char *const __argv[]) { int fsync(int __fd) { return 0; } int fdatasync(int __fd) { return 0; } // char * get_current_dir_name (void); -char *getcwd(char *__buf, size_t __size) { return "/"; } +char * getcwd (char *__buf, size_t __size) { + return (__buf && __size > 1) ? strcpy(__buf, "/") : 0; +} // int getdomainname (char *__name, size_t __len); // gid_t getegid (void); // uid_t geteuid (void); diff --git a/system/platform/debug/debug.c b/system/platform/debug/debug.c index 143b347..01f7a0f 100644 --- a/system/platform/debug/debug.c +++ b/system/platform/debug/debug.c @@ -189,6 +189,10 @@ void __dandelion_platform_init(void) { write_all(1, "\t", 1); write_all(1, input_sets[input_set].ident, input_sets[input_set].ident_len); write_all(1, "\n", 1); + + // Set the starting offset for this set + input_sets[input_set].offset = total_buffers; + // open the input set folder int set_folder_fd = __syscall(SYS_openat, in_sets_fd, input_sets[input_set].ident, O_RDONLY); @@ -251,7 +255,6 @@ void __dandelion_platform_init(void) { if (set_dirent_read < 0) print_and_exit("getdents failed\n", -dirent_read); - input_sets[input_set].offset = total_buffers; } // set up sentinel set From 809ee79d6ac47fe8c4914d1b3217ac040e88284b Mon Sep 17 00:00:00 2001 From: Andri Florin Date: Tue, 26 Aug 2025 14:44:29 +0200 Subject: [PATCH 12/20] added macro SSIZE_MAX and functions headers utime and time to newlib-cygwin-3.5.3.patch --- newlib_shim/newlib-cygwin-3.5.3.patch | 30 +++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/newlib_shim/newlib-cygwin-3.5.3.patch b/newlib_shim/newlib-cygwin-3.5.3.patch index eebcbf6..90449af 100644 --- a/newlib_shim/newlib-cygwin-3.5.3.patch +++ b/newlib_shim/newlib-cygwin-3.5.3.patch @@ -159,3 +159,33 @@ index c99ad395d..109112630 100644 #endif /* defined(__rtems__) */ #endif /* __GNU_VISIBLE */ +diff --git a/newlib/libc/include/limits.h a/newlib/libc/include/limits.h +index 893f108..f07076d 100644 +--- a/newlib/libc/include/limits.h ++++ b/newlib/libc/include/limits.h +@@ -145,3 +145,7 @@ + #ifndef PATH_MAX + #define PATH_MAX 4096 + #endif ++ ++#ifndef SSIZE_MAX ++#define SSIZE_MAX LONG_MAX ++#endif ++ +diff --git a/newlib/libc/include/sys/time.h b/newlib/libc/include/sys/time.h +index 5a3dec7ab..980f3378d 100644 +--- a/newlib/libc/include/sys/time.h ++++ b/newlib/libc/include/sys/time.h +@@ -440,6 +440,9 @@ int futimesat (int, const char *, const struct timeval [2]); + int _gettimeofday (struct timeval *__p, void *__tz); + #endif + ++time_t time(time_t *tloc); ++int utime(const char *filename, const struct utimbuf *times); ++ + __END_DECLS + + #endif /* !_KERNEL */ +-- +2.50.1 + From b37d2014bb58a4c64170df7e4f5644892a4d094f Mon Sep 17 00:00:00 2001 From: Andri Florin Date: Tue, 26 Aug 2025 16:01:04 +0200 Subject: [PATCH 13/20] make script-template.sh bsd-sed compatible --- sdk_install/script-template.sh | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/sdk_install/script-template.sh b/sdk_install/script-template.sh index 6557545..4723191 100644 --- a/sdk_install/script-template.sh +++ b/sdk_install/script-template.sh @@ -18,7 +18,7 @@ while getopts "c:d" opt; do DEFAULT_CLANG=true ;; ?) - echo "Unkown argument to scipt" + echo "Unknown argument to script" ;; esac done @@ -26,8 +26,17 @@ done SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) cd $SCRIPT_DIR +# Detect BSD vs GNU sed +if sed --version >/dev/null 2>&1; then + # GNU sed + SED_INPLACE() { sed -i "$@"; } +else + # BSD sed (macOS) + SED_INPLACE() { sed -i '' "$@"; } +fi + COMPILER_INCLUDES=$($CLANG_NAME -print-file-name=include) -sed -i "s|COMPILER_INCLUDES|$COMPILER_INCLUDES|g" @DANDELION_TARGET@-clang.cfg +SED_INPLACE "s|COMPILER_INCLUDES|$COMPILER_INCLUDES|g" @DANDELION_TARGET@-clang.cfg CLANG_PATH="$(which $CLANG_NAME)" CLANG_DIR="$(dirname $CLANG_PATH)" @@ -40,10 +49,10 @@ fi if [ $DEFAULT_CLANG = true ] && ! [[ -f $CLANG_DIR/clang ]]; then cp "$CLANG_PATH" "$CLANG_DIR/clang" ln -s "$CLANG_DIR/clang" "$CLANG_DIR/clang++" - sed "s||$SCRIPT_DIR|g" @DANDELION_TARGET@-clang.cfg >> "$CLANG_DIR/clang.cfg" + sed "s||$SCRIPT_DIR|g" @DANDELION_TARGET@-clang.cfg >> "$CLANG_DIR/clang.cfg" # enable stdinc, as we assume it has been cleared when we install our clang as system clang - sed -i "s|-nostdinc||g" "$CLANG_DIR/clang.cfg" - sed "s||$SCRIPT_DIR|g" @DANDELION_TARGET@-clang++.cfg >> "$CLANG_DIR/clang++.cfg" + SED_INPLACE "s|-nostdinc||g" "$CLANG_DIR/clang.cfg" + sed "s||$SCRIPT_DIR|g" @DANDELION_TARGET@-clang++.cfg >> "$CLANG_DIR/clang++.cfg" # need to change the config to use the clang.cfg in the same folder, so remove prefix - sed -i "s|@DANDELION_TARGET@-||g" "$CLANG_DIR/clang++.cfg" + SED_INPLACE "s|@DANDELION_TARGET@-||g" "$CLANG_DIR/clang++.cfg" fi \ No newline at end of file From 7ceca0071e57d492a674145ac486deacf1087848 Mon Sep 17 00:00:00 2001 From: Andri Florin Date: Tue, 26 Aug 2025 23:00:20 +0200 Subject: [PATCH 14/20] removed urandom.c because with previously made changes, file support is working again. --- test_programs/urandom.c | 24 ------------------------ 1 file changed, 24 deletions(-) delete mode 100644 test_programs/urandom.c diff --git a/test_programs/urandom.c b/test_programs/urandom.c deleted file mode 100644 index a7a72c6..0000000 --- a/test_programs/urandom.c +++ /dev/null @@ -1,24 +0,0 @@ -#include -#include -#include "dandelion/runtime.h" - -void _start() -{ - dandelion_init(); - FILE *file = fopen("/dev/urandom", "rb"); - if (file == NULL) { - perror("Error opening /dev/urandom"); - dandelion_exit(1); - } - - unsigned char c; - if (fread(&c, 1, 1, file) == 1) { - printf("First random byte: %u\n", c); // as number - // printf("First random char: %c\n", c); // as ASCII char (may be non-printable) - } else { - perror("Error reading from /dev/urandom"); - } - - fclose(file); - dandelion_exit(c); -} From dbabf5211212cfe8689138b422d1a9281df7a59a Mon Sep 17 00:00:00 2001 From: Tom Kuchler Date: Tue, 23 Sep 2025 16:19:10 +0200 Subject: [PATCH 15/20] Fix formatting --- newlib_shim/unistd.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/newlib_shim/unistd.c b/newlib_shim/unistd.c index 2d2eae6..a46c626 100644 --- a/newlib_shim/unistd.c +++ b/newlib_shim/unistd.c @@ -2,7 +2,11 @@ #include // Implement functions from unistd that are not already defined in other parts +<<<<<<< HEAD // of newlibs libc or in something we supply +======= +// of newlibs libc Or in something we supply +>>>>>>> Fix formatting // unsigned alarm (unsigned __secs); int chdir(const char *__path) { @@ -22,6 +26,7 @@ int chroot(const char *__path) { // int chmod (const char *__path, mode_t __mode); // int chown (const char *__path, uid_t __owner, gid_t __group); +<<<<<<< HEAD // int close_range (unsigned int __firstfd, unsigned int __lastfd, int // __flags); @@ -32,6 +37,12 @@ int chroot(const char *__path) { // char * ctermid (char *__s); char * cuserid (char *__s); +======= +// int close_range (unsigned int __firstfd, unsigned int __lastfd, int +// __flags); size_t confstr (int __name, char *__buf, size_t __len); char * +// crypt (const char *__key, const char *__salt); char * ctermid (char *__s); +// char * cuserid (char *__s); +>>>>>>> Fix formatting // int daemon (int nochdir, int noclose); // function to duplicate file descriptor to second file number @@ -67,12 +78,17 @@ int execv(const char *__path, char *const __argv[]) { } // already given in newlib // int execve (const char *__path, char * const __argv[], char * const +<<<<<<< HEAD // __envp[]); // int execvp (const char *__file, char * const __argv[]); // int execvpe (const char *__file, char * const __argv[], char * const // __envp[]); +======= +// __envp[]); int execvp (const char *__file, char * const __argv[]); int +// execvpe (const char *__file, char * const __argv[], char * const __envp[]); +>>>>>>> Fix formatting // #if __ATFILE_VISIBLE // int faccessat (int __dirfd, const char *__path, int __mode, int __flags); // #endif @@ -81,6 +97,7 @@ int execv(const char *__path, char *const __argv[]) { // int fchown (int __fildes, uid_t __owner, gid_t __group); // #if __ATFILE_VISIBLE // int fchownat (int __dirfd, const char *__path, uid_t __owner, gid_t __group, +<<<<<<< HEAD // int __flags); // #endif // int fexecve (int __fd, char * const __argv[], char * const __envp[]); @@ -89,6 +106,12 @@ int execv(const char *__path, char *const __argv[]) { int fsync(int __fd) { return 0; } int fdatasync(int __fd) { return 0; } +======= +// int __flags); #endif int fexecve (int __fd, char * const __argv[], char * +// const __envp[]); long fpathconf (int __fd, int __name); +int fsync(int __fd) { return 0; } +int fdatasync(int __fd) { return 0; } +>>>>>>> Fix formatting // char * get_current_dir_name (void); char *getcwd(char *__buf, size_t __size) { return "/"; } // int getdomainname (char *__name, size_t __len); @@ -113,6 +136,7 @@ char *getcwd(char *__buf, size_t __size) { return "/"; } // char * getwd (char *__buf); // int lchown (const char *__path, uid_t __owner, gid_t __group); // #if __ATFILE_VISIBLE +<<<<<<< HEAD // int linkat (int __dirfd1, const char *__path1, int __dirfd2, const char // *__path2, int __flags); @@ -128,12 +152,22 @@ char *getcwd(char *__buf, size_t __size) { return "/"; } // int pthread_atfork (void (*)(void), void (*)(void), void (*)(void)); // #endif // int pipe (int __fildes[2]) { +======= +// int linkat (int __dirfd1, const char *__path1, int __dirfd2, const char +// *__path2, int __flags); #endif #if __MISC_VISIBLE || __XSI_VISIBLE int +// nice (int __nice_value); #endif #if __MISC_VISIBLE || __XSI_VISIBLE >= 4 int +// lockf (int __fd, int __cmd, off_t __len); #endif long pathconf (const char +// *__path, int __name); int pause (void); #if __POSIX_VISIBLE >= 199506 int +// pthread_atfork (void (*)(void), void (*)(void), void (*)(void)); #endif int +// pipe (int __fildes[2]) { +>>>>>>> Fix formatting // pipe2(__fileds[2], 0); // } // int pipe2 (int __fildes[2], int flags); // #if __POSIX_VISIBLE >= 200809 || __XSI_VISIBLE >= 500 // ssize_t pread (int __fd, void *__buf, size_t __nbytes, off_t __offset); // ssize_t pwrite (int __fd, const void *__buf, size_t __nbytes, off_t +<<<<<<< HEAD // __offset); // #endif _READ_WRITE_RETURN_TYPE @@ -154,6 +188,16 @@ char *getcwd(char *__buf, size_t __size) { return "/"; } // int seteuid(uid_t __uid); // #endif // int setgid(gid_t __gid); +======= +// __offset); #endif _READ_WRITE_RETURN_TYPE read (int __fd, void *__buf, size_t +// __nbyte); #if __BSD_VISIBLE int rresvport (int *__alport); int revoke +// (char *__path); #endif int rmdir (const char *__path); #if __BSD_VISIBLE +// int ruserok (const char *rhost, int superuser, const char *ruser, const char +// *luser); #endif #if __BSD_VISIBLE || (__XSI_VISIBLE >= 4 && __POSIX_VISIBLE < +// 200112) void * sbrk (ptrdiff_t __incr); #endif #if __BSD_VISIBLE || +// __POSIX_VISIBLE >= 200112 int setegid (gid_t __gid); int seteuid +// (uid_t __uid); #endif int setgid (gid_t __gid); +>>>>>>> Fix formatting int setgroups(int ngroups, const gid_t *grouplist) { *__errno() = EPERM; return -1; From 1efb0c90bfd6010930f7bb6dcf9cb400ae2c8389 Mon Sep 17 00:00:00 2001 From: tom-kuchler <87128754+tom-kuchler@users.noreply.github.com> Date: Tue, 23 Sep 2025 15:57:43 +0200 Subject: [PATCH 16/20] Add dev container, fix bugs in compiler setup (#20) Features added: * Add clang include directory to cfg * Adding statiging release * Add dev container * Add runtime library interface * Adding first version of unistd.c * Adding print for exit code at debug exit Bug Fixes: * Fix bugs in compiler cfg template * Fix namecmp to recognize substrings as non equal * Fix abi thread local issue, add test program build to top level cmake project * Fix makro in cmake template * Fix debug to handle unlimited number of input items or input-/outputsets --- .github/workflows/release_experimental.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release_experimental.yml b/.github/workflows/release_experimental.yml index 4c81d76..5d220e9 100644 --- a/.github/workflows/release_experimental.yml +++ b/.github/workflows/release_experimental.yml @@ -1,9 +1,10 @@ -name: release latest with all library versions +name: release experimental with all library versions on: - pull_request: + push: branches: [ "dev/staging" ] + jobs: build: strategy: From 2f1aae3cb488513f2d3d8dd04403ee5ab9661c12 Mon Sep 17 00:00:00 2001 From: tom-kuchler <87128754+tom-kuchler@users.noreply.github.com> Date: Mon, 10 Nov 2025 18:08:15 +0100 Subject: [PATCH 17/20] Dev/staging (#23) * Add dev container * Add clang include directory to cfg * Adding staging release * Add runtime library interface * Adding first version of unistd.c * Adding print for exit code at debug exit Bug Fixes: * Fix bugs in compiler cfg template * Fix namecmp to recognize substrings as non equal * Fix abi thread local issue, add test program build to top level cmake project * Fix makro in cmake template * Fix debug to handle unlimited number of input items or input-/outputsets * Fix formatting * update kvm exit to use interrupt 32 instead of direct halt (#22) --- newlib_shim/unistd.c | 46 +------------------------------------------- 1 file changed, 1 insertion(+), 45 deletions(-) diff --git a/newlib_shim/unistd.c b/newlib_shim/unistd.c index a46c626..afcc9e5 100644 --- a/newlib_shim/unistd.c +++ b/newlib_shim/unistd.c @@ -2,11 +2,7 @@ #include // Implement functions from unistd that are not already defined in other parts -<<<<<<< HEAD // of newlibs libc or in something we supply -======= -// of newlibs libc Or in something we supply ->>>>>>> Fix formatting // unsigned alarm (unsigned __secs); int chdir(const char *__path) { @@ -26,7 +22,6 @@ int chroot(const char *__path) { // int chmod (const char *__path, mode_t __mode); // int chown (const char *__path, uid_t __owner, gid_t __group); -<<<<<<< HEAD // int close_range (unsigned int __firstfd, unsigned int __lastfd, int // __flags); @@ -37,12 +32,6 @@ int chroot(const char *__path) { // char * ctermid (char *__s); char * cuserid (char *__s); -======= -// int close_range (unsigned int __firstfd, unsigned int __lastfd, int -// __flags); size_t confstr (int __name, char *__buf, size_t __len); char * -// crypt (const char *__key, const char *__salt); char * ctermid (char *__s); -// char * cuserid (char *__s); ->>>>>>> Fix formatting // int daemon (int nochdir, int noclose); // function to duplicate file descriptor to second file number @@ -78,17 +67,12 @@ int execv(const char *__path, char *const __argv[]) { } // already given in newlib // int execve (const char *__path, char * const __argv[], char * const -<<<<<<< HEAD // __envp[]); -// int execvp (const char *__file, char * const __argv[]); +// int execvp (const char *__file, char * const __argv[]); // int execvpe (const char *__file, char * const __argv[], char * const // __envp[]); -======= -// __envp[]); int execvp (const char *__file, char * const __argv[]); int -// execvpe (const char *__file, char * const __argv[], char * const __envp[]); ->>>>>>> Fix formatting // #if __ATFILE_VISIBLE // int faccessat (int __dirfd, const char *__path, int __mode, int __flags); // #endif @@ -97,7 +81,6 @@ int execv(const char *__path, char *const __argv[]) { // int fchown (int __fildes, uid_t __owner, gid_t __group); // #if __ATFILE_VISIBLE // int fchownat (int __dirfd, const char *__path, uid_t __owner, gid_t __group, -<<<<<<< HEAD // int __flags); // #endif // int fexecve (int __fd, char * const __argv[], char * const __envp[]); @@ -106,12 +89,6 @@ int execv(const char *__path, char *const __argv[]) { int fsync(int __fd) { return 0; } int fdatasync(int __fd) { return 0; } -======= -// int __flags); #endif int fexecve (int __fd, char * const __argv[], char * -// const __envp[]); long fpathconf (int __fd, int __name); -int fsync(int __fd) { return 0; } -int fdatasync(int __fd) { return 0; } ->>>>>>> Fix formatting // char * get_current_dir_name (void); char *getcwd(char *__buf, size_t __size) { return "/"; } // int getdomainname (char *__name, size_t __len); @@ -136,7 +113,6 @@ char *getcwd(char *__buf, size_t __size) { return "/"; } // char * getwd (char *__buf); // int lchown (const char *__path, uid_t __owner, gid_t __group); // #if __ATFILE_VISIBLE -<<<<<<< HEAD // int linkat (int __dirfd1, const char *__path1, int __dirfd2, const char // *__path2, int __flags); @@ -152,22 +128,12 @@ char *getcwd(char *__buf, size_t __size) { return "/"; } // int pthread_atfork (void (*)(void), void (*)(void), void (*)(void)); // #endif // int pipe (int __fildes[2]) { -======= -// int linkat (int __dirfd1, const char *__path1, int __dirfd2, const char -// *__path2, int __flags); #endif #if __MISC_VISIBLE || __XSI_VISIBLE int -// nice (int __nice_value); #endif #if __MISC_VISIBLE || __XSI_VISIBLE >= 4 int -// lockf (int __fd, int __cmd, off_t __len); #endif long pathconf (const char -// *__path, int __name); int pause (void); #if __POSIX_VISIBLE >= 199506 int -// pthread_atfork (void (*)(void), void (*)(void), void (*)(void)); #endif int -// pipe (int __fildes[2]) { ->>>>>>> Fix formatting // pipe2(__fileds[2], 0); // } // int pipe2 (int __fildes[2], int flags); // #if __POSIX_VISIBLE >= 200809 || __XSI_VISIBLE >= 500 // ssize_t pread (int __fd, void *__buf, size_t __nbytes, off_t __offset); // ssize_t pwrite (int __fd, const void *__buf, size_t __nbytes, off_t -<<<<<<< HEAD // __offset); // #endif _READ_WRITE_RETURN_TYPE @@ -188,16 +154,6 @@ char *getcwd(char *__buf, size_t __size) { return "/"; } // int seteuid(uid_t __uid); // #endif // int setgid(gid_t __gid); -======= -// __offset); #endif _READ_WRITE_RETURN_TYPE read (int __fd, void *__buf, size_t -// __nbyte); #if __BSD_VISIBLE int rresvport (int *__alport); int revoke -// (char *__path); #endif int rmdir (const char *__path); #if __BSD_VISIBLE -// int ruserok (const char *rhost, int superuser, const char *ruser, const char -// *luser); #endif #if __BSD_VISIBLE || (__XSI_VISIBLE >= 4 && __POSIX_VISIBLE < -// 200112) void * sbrk (ptrdiff_t __incr); #endif #if __BSD_VISIBLE || -// __POSIX_VISIBLE >= 200112 int setegid (gid_t __gid); int seteuid -// (uid_t __uid); #endif int setgid (gid_t __gid); ->>>>>>> Fix formatting int setgroups(int ngroups, const gid_t *grouplist) { *__errno() = EPERM; return -1; From 1954ab72bcfdf5fcc81da95180995ad9c31150bd Mon Sep 17 00:00:00 2001 From: tom-kuchler <87128754+tom-kuchler@users.noreply.github.com> Date: Fri, 19 Dec 2025 11:45:18 +0100 Subject: [PATCH 18/20] Fix bug with buffers going to previous sets (#25) * Add dev container, fix bugs in compiler setup Features added: * Add clang include directory to cfg * Adding statiging release * Add dev container * Add runtime library interface * Adding first version of unistd.c * Adding print for exit code at debug exit Bug Fixes: * Fix bugs in compiler cfg template * Fix namecmp to recognize substrings as non equal * Fix abi thread local issue, add test program build to top level cmake project * Fix makro in cmake template * Fix debug to handle unlimited number of input items or input-/outputsets * Fix formatting * update kvm exit to use interrupt 32 instead of direct halt (#22) * Fix bug with buffers going to previous sets --- system/platform/debug/debug.c | 14 +++++++++----- test_programs/libcpp/CMakeLists.txt | 4 ++++ test_programs/libcpp/input_1.txt | 1 + test_programs/libcpp/input_2.txt | 1 + test_programs/libcpp/test.cpp | 23 +++++++++++++++++++++-- 5 files changed, 36 insertions(+), 7 deletions(-) create mode 100644 test_programs/libcpp/input_1.txt create mode 100644 test_programs/libcpp/input_2.txt diff --git a/system/platform/debug/debug.c b/system/platform/debug/debug.c index 143b347..e02bdf0 100644 --- a/system/platform/debug/debug.c +++ b/system/platform/debug/debug.c @@ -186,6 +186,7 @@ void __dandelion_platform_init(void) { sysdata.input_bufs = heap_ptr; for (size_t input_set = 0; input_set < input_set_index; input_set++) { + input_sets[input_set].offset = total_buffers; write_all(1, "\t", 1); write_all(1, input_sets[input_set].ident, input_sets[input_set].ident_len); write_all(1, "\n", 1); @@ -250,8 +251,6 @@ void __dandelion_platform_init(void) { } if (set_dirent_read < 0) print_and_exit("getdents failed\n", -dirent_read); - - input_sets[input_set].offset = total_buffers; } // set up sentinel set @@ -328,16 +327,21 @@ void __dandelion_platform_exit(void) { char exit_message[] = "Exiting with code "; size_t message_len = my_strlen(exit_message); write_all(1, exit_message, message_len); - char exit_code_string[11] = " \n"; + char exit_code_string[12] = " 0000000000\n"; // convert int to string int exit_code = sysdata.exit_code; + // remove sign + if (exit_code < 0) { + exit_code_string[0] = '-'; + exit_code *= -1; + } for (size_t index = 0; index < 10; index++) { - exit_code_string[9 - index] = '0' + (exit_code % 10); + exit_code_string[10 - index] = '0' + (exit_code % 10); exit_code = exit_code / 10; if (exit_code == 0) break; } - write_all(1, exit_code_string, 11); + write_all(1, exit_code_string, 12); __syscall(SYS_exit_group, sysdata.exit_code); __builtin_unreachable(); } diff --git a/test_programs/libcpp/CMakeLists.txt b/test_programs/libcpp/CMakeLists.txt index 9080e3a..8922f48 100644 --- a/test_programs/libcpp/CMakeLists.txt +++ b/test_programs/libcpp/CMakeLists.txt @@ -14,5 +14,9 @@ target_link_libraries(${TEST} PRIVATE # prepare files to run the function in debug mode file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/input_sets) +file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/input_sets/in_a) +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/input_1.txt DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/input_sets/in_a) +file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/input_sets/in_b) +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/input_2.txt DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/input_sets/in_b) file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/output_sets) file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/output_sets/stdio) \ No newline at end of file diff --git a/test_programs/libcpp/input_1.txt b/test_programs/libcpp/input_1.txt new file mode 100644 index 0000000..01db5dd --- /dev/null +++ b/test_programs/libcpp/input_1.txt @@ -0,0 +1 @@ +first input file \ No newline at end of file diff --git a/test_programs/libcpp/input_2.txt b/test_programs/libcpp/input_2.txt new file mode 100644 index 0000000..e98c3f9 --- /dev/null +++ b/test_programs/libcpp/input_2.txt @@ -0,0 +1 @@ +second input file \ No newline at end of file diff --git a/test_programs/libcpp/test.cpp b/test_programs/libcpp/test.cpp index 4511115..dac8884 100644 --- a/test_programs/libcpp/test.cpp +++ b/test_programs/libcpp/test.cpp @@ -1,15 +1,34 @@ #include #include +#include using namespace std; int main(){ - // cout << "Hello World" << endl; std::fstream fs; fs.open("/stdio/stdout", std::fstream::out); - fs << " test print " << endl; + fs << "test print " << endl; fs.close(); + std::fstream in1; + string in_file_1 = "/in_a/input_1.txt"; + in1.open(in_file_1, std::fstream::in); + if (!in1) { + cerr << "Failed to open " << in_file_1 << endl; + return -1; + } + cout << in1.rdbuf() << endl; + in1.close(); + std::fstream in2; + string in_file_2 = "/in_b/input_2.txt"; + in2.open(in_file_2, std::fstream::in); + if (!in2) { + cerr << "Failed to open " << in_file_2 << endl; + return -1; + } + cerr << in2.rdbuf() << endl; + in2.close(); + cout << "stdout print" << endl; cerr << "stderr print" << endl; return 0; From 6bbbd95d6f9e7abb7bbc2ddc079780956e828513 Mon Sep 17 00:00:00 2001 From: tom-kuchler <87128754+tom-kuchler@users.noreply.github.com> Date: Mon, 22 Dec 2025 16:03:56 +0100 Subject: [PATCH 19/20] Dev/libc extension (#26) * Added sys/uio, sys/socket and netdb * Move additional source and header files for libc to separate library --------- Co-authored-by: Tobias Stocker --- CMakeLists.txt | 7 +- libc_extension/CMakeLists.txt | 39 +++ {newlib_shim => libc_extension}/dirent.c | 0 libc_extension/include/netdb.h | 75 +++++ .../include/sys}/cpuset.h | 0 .../include/sys}/dirent.h | 0 .../include/sys}/sched.h | 0 libc_extension/include/sys/socket.h | 269 ++++++++++++++++++ .../include/sys}/statvfs.h | 11 +- libc_extension/include/sys/uio.h | 33 +++ libc_extension/netdb.c | 66 +++++ libc_extension/socket.c | 73 +++++ libc_extension/uio.c | 9 + newlib_shim/Makefile.inc | 1 - newlib_shim/patch_script | 9 - newlib_shim/shim.c | 11 - sdk_install/CMakeTemplate.txt | 1 + sdk_install/clang-template.cmake | 1 + 18 files changed, 581 insertions(+), 24 deletions(-) create mode 100644 libc_extension/CMakeLists.txt rename {newlib_shim => libc_extension}/dirent.c (100%) create mode 100644 libc_extension/include/netdb.h rename {newlib_shim => libc_extension/include/sys}/cpuset.h (100%) rename {newlib_shim => libc_extension/include/sys}/dirent.h (100%) rename {newlib_shim => libc_extension/include/sys}/sched.h (100%) create mode 100644 libc_extension/include/sys/socket.h rename {newlib_shim => libc_extension/include/sys}/statvfs.h (84%) create mode 100644 libc_extension/include/sys/uio.h create mode 100644 libc_extension/netdb.c create mode 100644 libc_extension/socket.c create mode 100644 libc_extension/uio.c diff --git a/CMakeLists.txt b/CMakeLists.txt index f18cb68..e540d7b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -148,6 +148,11 @@ if(NEWLIB) ) add_dependencies(dlibc newlib) + # Additional headers / code needed to get libc to linux compatibility + set(LIBC_EXTENSION "c_extension") + add_subdirectory(libc_extension) + add_dependencies(${LIBC_EXTENSION} dlibc) + set(LLVM_C_FLAGS "-D_GNU_SOURCE=1") string(APPEND LLVM_C_FLAGS " -D_POSIX_TIMERS") string(APPEND LLVM_C_FLAGS " -D_POSIX_THREADS") @@ -228,7 +233,7 @@ if(NEWLIB) -DLIBCXX_ENABLE_RANDOM_DEVICE=OFF -DLIBCXX_HAS_PTHREAD_API=ON ) - add_dependencies(llvmproject newlib) + add_dependencies(llvmproject newlib ${LIBC_EXTENSION}) # Create folder at configuration time to avoid issues with includes file(MAKE_DIRECTORY ${CMAKE_INSTALL_PREFIX}/include/c++/v1) diff --git a/libc_extension/CMakeLists.txt b/libc_extension/CMakeLists.txt new file mode 100644 index 0000000..89b8e8f --- /dev/null +++ b/libc_extension/CMakeLists.txt @@ -0,0 +1,39 @@ +add_library(${LIBC_EXTENSION} STATIC) + +target_sources(${LIBC_EXTENSION} + PRIVATE + dirent.c + netdb.c + socket.c + uio.c + PUBLIC FILE_SET public_headers TYPE HEADERS + BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/include/ + FILES + include/netdb.h + include/sys/cpuset.h + include/sys/dirent.h + include/sys/sched.h + include/sys/socket.h + include/sys/statvfs.h + include/sys/uio.h +) + +if(CMAKE_BUILD_TYPE MATCHES "Debug") + target_compile_definitions(${LIBC_EXTENSION} PRIVATE DEBUG) + target_compile_options(${LIBC_EXTENSION} PRIVATE -g) +endif() + +target_link_libraries(${LIBC_EXTENSION} PRIVATE dlibc) + +include(GNUInstallDirs) +install(TARGETS ${LIBC_EXTENSION} + ARCHIVE FILE_SET public_headers + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/ +) + +# always install after building, so the headers are available for libcxx +add_custom_command( + TARGET ${LIBC_EXTENSION} + POST_BUILD + COMMAND ${CMAKE_COMMAND} --install ${CMAKE_CURRENT_BINARY_DIR} +) \ No newline at end of file diff --git a/newlib_shim/dirent.c b/libc_extension/dirent.c similarity index 100% rename from newlib_shim/dirent.c rename to libc_extension/dirent.c diff --git a/libc_extension/include/netdb.h b/libc_extension/include/netdb.h new file mode 100644 index 0000000..7e6c133 --- /dev/null +++ b/libc_extension/include/netdb.h @@ -0,0 +1,75 @@ +#ifndef _NETDB_H +#define _NETDB_H 1 + +#include +#include + +/* Description of data base entry for a single host. */ +struct hostent +{ + char *h_name; /* Official name of host. */ + char **h_aliases; /* Alias list. */ + int h_addrtype; /* Host address type. */ + int h_length; /* Length of address. */ + char **h_addr_list; /* List of addresses from name server. */ +}; + +/* Description of data base entry for a single network. NOTE: here a + poor assumption is made. The network number is expected to fit + into an unsigned long int variable. */ +struct netent +{ + char *n_name; /* Official name of network. */ + char **n_aliases; /* Alias list. */ + int n_addrtype; /* Net address type. */ + uint32_t n_net; /* Network number. */ +}; + +/* Description of data base entry for a single service. */ +struct protoent +{ + char *p_name; /* Official protocol name. */ + char **p_aliases; /* Alias list. */ + int p_proto; /* Protocol number. */ +}; + +/* Description of data base entry for a single service. */ +struct servent +{ + char *s_name; /* Official service name. */ + char **s_aliases; /* Alias list. */ + int s_port; /* Port number. */ + char *s_proto; /* Protocol to use. */ +}; + +# define IPPORT_RESERVED 1024 + +extern int h_errno; + +# define HOST_NOT_FOUND 1 /* Authoritative Answer Host not found. */ +# define TRY_AGAIN 2 /* Non-Authoritative Host not found, or SERVERFAIL. */ +# define NO_RECOVERY 3 /* Non recoverable errors, FORMERR, REFUSED, NOTIMP. */ +# define NO_DATA 4 /* Valid name, no data record of requested type. */ + +extern void endhostent (void); +extern void endnetent (void); +extern void endprotoent (void); +extern void endservent (void); +extern struct hostent *gethostbyaddr (const void *__addr, __socklen_t __len, int __type); +extern struct hostent *gethostbyname (const char *__name); +extern struct hostent *gethostent (void); +extern struct netent *getnetbyaddr (uint32_t __net, int __type); +extern struct netent *getnetbyname (const char *__name); +extern struct netent *getnetent (void); +extern struct protoent *getprotobyname (const char *__name); +extern struct protoent *getprotobynumber (int __proto); +extern struct protoent *getprotoent (void); +extern struct servent *getservbyname (const char *__name, const char *__proto); +extern struct servent *getservbyport (int __port, const char *__proto); +extern struct servent *getservent (void); +extern void sethostent (int __stay_open); +extern void setnetent (int __stay_open); +extern void setprotoent (int __stay_open); +extern void setservent (int __stay_open); + +#endif // _NETDB_H \ No newline at end of file diff --git a/newlib_shim/cpuset.h b/libc_extension/include/sys/cpuset.h similarity index 100% rename from newlib_shim/cpuset.h rename to libc_extension/include/sys/cpuset.h diff --git a/newlib_shim/dirent.h b/libc_extension/include/sys/dirent.h similarity index 100% rename from newlib_shim/dirent.h rename to libc_extension/include/sys/dirent.h diff --git a/newlib_shim/sched.h b/libc_extension/include/sys/sched.h similarity index 100% rename from newlib_shim/sched.h rename to libc_extension/include/sys/sched.h diff --git a/libc_extension/include/sys/socket.h b/libc_extension/include/sys/socket.h new file mode 100644 index 0000000..b0eb27a --- /dev/null +++ b/libc_extension/include/sys/socket.h @@ -0,0 +1,269 @@ +#ifndef _SYS_SOCKET_H +#define _SYS_SOCKET_H 1 + +#include + +/* Type for length arguments in socket calls. */ +typedef unsigned int socklen_t; + +/* POSIX.1g specifies this type name for the `sa_family' member. */ +typedef unsigned short int sa_family_t; + +/* Structure describing a generic socket address. */ +struct sockaddr +{ + sa_family_t sa_family; /* Common data: address family and length. */ + char sa_data[14]; /* Address data. */ +}; + +/* Structure large enough to hold any socket address (with the historical + exception of AF_UNIX). */ +struct sockaddr_storage +{ + sa_family_t ss_family; /* Address family, etc. */ + char __ss_padding[(128 - (sizeof (unsigned short int)) - sizeof (unsigned long int))]; + unsigned long int __ss_align; /* Force desired alignment. */ +}; + +/* Structure describing messages sent by + `sendmsg' and received by `recvmsg'. */ +struct msghdr +{ + void *msg_name; /* Address to send to/receive from. */ + socklen_t msg_namelen; /* Length of address data. */ + + struct iovec *msg_iov; /* Vector of data to send/receive into. */ + size_t msg_iovlen; /* Number of elements in the vector. */ + + void *msg_control; /* Ancillary data (eg BSD filedesc passing). */ + size_t msg_controllen; /* Ancillary data buffer length. + !! The type should be socklen_t but the + definition of the kernel is incompatible + with this. */ + + int msg_flags; /* Flags on received message. */ +}; + +/* Structure used for storage of ancillary data object information. */ +struct cmsghdr +{ + size_t cmsg_len; /* Length of data in cmsg_data plus length + of cmsghdr structure. + !! The type should be socklen_t but the + definition of the kernel is incompatible + with this. */ + int cmsg_level; /* Originating protocol. */ + int cmsg_type; /* Protocol specific type. */ +}; + +/* Types of sockets. */ +enum __socket_type +{ + SOCK_STREAM = 1, /* Sequenced, reliable, connection-based + byte streams. */ +#define SOCK_STREAM SOCK_STREAM + SOCK_DGRAM = 2, /* Connectionless, unreliable datagrams + of fixed maximum length. */ +#define SOCK_DGRAM SOCK_DGRAM + SOCK_RAW = 3, /* Raw protocol interface. */ +#define SOCK_RAW SOCK_RAW + SOCK_RDM = 4, /* Reliably-delivered messages. */ +#define SOCK_RDM SOCK_RDM + SOCK_SEQPACKET = 5, /* Sequenced, reliable, connection-based, + datagrams of fixed maximum length. */ +#define SOCK_SEQPACKET SOCK_SEQPACKET + SOCK_DCCP = 6, /* Datagram Congestion Control Protocol. */ +#define SOCK_DCCP SOCK_DCCP + SOCK_PACKET = 10, /* Linux specific way of getting packets + at the dev level. For writing rarp and + other similar things on the user level. */ +#define SOCK_PACKET SOCK_PACKET + + /* Flags to be ORed into the type parameter of socket and socketpair and + used for the flags parameter of paccept. */ + + SOCK_CLOEXEC = 02000000, /* Atomically set close-on-exec flag for the + new descriptor(s). */ +#define SOCK_CLOEXEC SOCK_CLOEXEC + SOCK_NONBLOCK = 00004000 /* Atomically mark descriptor(s) as + non-blocking. */ +#define SOCK_NONBLOCK SOCK_NONBLOCK +}; + +/* Protocol families. */ +#define PF_UNSPEC 0 /* Unspecified. */ +#define PF_LOCAL 1 /* Local to host (pipes and file-domain). */ +#define PF_UNIX PF_LOCAL /* POSIX name for PF_LOCAL. */ +#define PF_FILE PF_LOCAL /* Another non-standard name for PF_LOCAL. */ +#define PF_INET 2 /* IP protocol family. */ +#define PF_AX25 3 /* Amateur Radio AX.25. */ +#define PF_IPX 4 /* Novell Internet Protocol. */ +#define PF_APPLETALK 5 /* Appletalk DDP. */ +#define PF_NETROM 6 /* Amateur radio NetROM. */ +#define PF_BRIDGE 7 /* Multiprotocol bridge. */ +#define PF_ATMPVC 8 /* ATM PVCs. */ +#define PF_X25 9 /* Reserved for X.25 project. */ +#define PF_INET6 10 /* IP version 6. */ +#define PF_ROSE 11 /* Amateur Radio X.25 PLP. */ +#define PF_DECnet 12 /* Reserved for DECnet project. */ +#define PF_NETBEUI 13 /* Reserved for 802.2LLC project. */ +#define PF_SECURITY 14 /* Security callback pseudo AF. */ +#define PF_KEY 15 /* PF_KEY key management API. */ +#define PF_NETLINK 16 +#define PF_ROUTE PF_NETLINK /* Alias to emulate 4.4BSD. */ +#define PF_PACKET 17 /* Packet family. */ +#define PF_ASH 18 /* Ash. */ +#define PF_ECONET 19 /* Acorn Econet. */ +#define PF_ATMSVC 20 /* ATM SVCs. */ +#define PF_RDS 21 /* RDS sockets. */ +#define PF_SNA 22 /* Linux SNA Project */ +#define PF_IRDA 23 /* IRDA sockets. */ +#define PF_PPPOX 24 /* PPPoX sockets. */ +#define PF_WANPIPE 25 /* Wanpipe API sockets. */ +#define PF_LLC 26 /* Linux LLC. */ +#define PF_IB 27 /* Native InfiniBand address. */ +#define PF_MPLS 28 /* MPLS. */ +#define PF_CAN 29 /* Controller Area Network. */ +#define PF_TIPC 30 /* TIPC sockets. */ +#define PF_BLUETOOTH 31 /* Bluetooth sockets. */ +#define PF_IUCV 32 /* IUCV sockets. */ +#define PF_RXRPC 33 /* RxRPC sockets. */ +#define PF_ISDN 34 /* mISDN sockets. */ +#define PF_PHONET 35 /* Phonet sockets. */ +#define PF_IEEE802154 36 /* IEEE 802.15.4 sockets. */ +#define PF_CAIF 37 /* CAIF sockets. */ +#define PF_ALG 38 /* Algorithm sockets. */ +#define PF_NFC 39 /* NFC sockets. */ +#define PF_VSOCK 40 /* vSockets. */ +#define PF_KCM 41 /* Kernel Connection Multiplexor. */ +#define PF_QIPCRTR 42 /* Qualcomm IPC Router. */ +#define PF_SMC 43 /* SMC sockets. */ +#define PF_XDP 44 /* XDP sockets. */ +#define PF_MCTP 45 /* Management component transport protocol. */ +#define PF_MAX 46 /* For now.. */ + +/* Address families. */ +#define AF_UNSPEC PF_UNSPEC +#define AF_LOCAL PF_LOCAL +#define AF_UNIX PF_UNIX +#define AF_FILE PF_FILE +#define AF_INET PF_INET +#define AF_AX25 PF_AX25 +#define AF_IPX PF_IPX +#define AF_APPLETALK PF_APPLETALK +#define AF_NETROM PF_NETROM +#define AF_BRIDGE PF_BRIDGE +#define AF_ATMPVC PF_ATMPVC +#define AF_X25 PF_X25 +#define AF_INET6 PF_INET6 +#define AF_ROSE PF_ROSE +#define AF_DECnet PF_DECnet +#define AF_NETBEUI PF_NETBEUI +#define AF_SECURITY PF_SECURITY +#define AF_KEY PF_KEY +#define AF_NETLINK PF_NETLINK +#define AF_ROUTE PF_ROUTE +#define AF_PACKET PF_PACKET +#define AF_ASH PF_ASH +#define AF_ECONET PF_ECONET +#define AF_ATMSVC PF_ATMSVC +#define AF_RDS PF_RDS +#define AF_SNA PF_SNA +#define AF_IRDA PF_IRDA +#define AF_PPPOX PF_PPPOX +#define AF_WANPIPE PF_WANPIPE +#define AF_LLC PF_LLC +#define AF_IB PF_IB +#define AF_MPLS PF_MPLS +#define AF_CAN PF_CAN +#define AF_TIPC PF_TIPC +#define AF_BLUETOOTH PF_BLUETOOTH +#define AF_IUCV PF_IUCV +#define AF_RXRPC PF_RXRPC +#define AF_ISDN PF_ISDN +#define AF_PHONET PF_PHONET +#define AF_IEEE802154 PF_IEEE802154 +#define AF_CAIF PF_CAIF +#define AF_ALG PF_ALG +#define AF_NFC PF_NFC +#define AF_VSOCK PF_VSOCK +#define AF_KCM PF_KCM +#define AF_QIPCRTR PF_QIPCRTR +#define AF_SMC PF_SMC +#define AF_XDP PF_XDP +#define AF_MCTP PF_MCTP +#define AF_MAX PF_MAX + +/* Bits in the FLAGS argument to `send', `recv', et al. */ +enum + { + MSG_OOB = 0x01, /* Process out-of-band data. */ +#define MSG_OOB MSG_OOB + MSG_PEEK = 0x02, /* Peek at incoming messages. */ +#define MSG_PEEK MSG_PEEK + MSG_DONTROUTE = 0x04, /* Don't use local routing. */ +#define MSG_DONTROUTE MSG_DONTROUTE + MSG_CTRUNC = 0x08, /* Control data lost before delivery. */ +#define MSG_CTRUNC MSG_CTRUNC + MSG_PROXY = 0x10, /* Supply or ask second address. */ +#define MSG_PROXY MSG_PROXY + MSG_TRUNC = 0x20, +#define MSG_TRUNC MSG_TRUNC + MSG_DONTWAIT = 0x40, /* Nonblocking IO. */ +#define MSG_DONTWAIT MSG_DONTWAIT + MSG_EOR = 0x80, /* End of record. */ +#define MSG_EOR MSG_EOR + MSG_WAITALL = 0x100, /* Wait for a full request. */ +#define MSG_WAITALL MSG_WAITALL + MSG_FIN = 0x200, +#define MSG_FIN MSG_FIN + MSG_SYN = 0x400, +#define MSG_SYN MSG_SYN + MSG_CONFIRM = 0x800, /* Confirm path validity. */ +#define MSG_CONFIRM MSG_CONFIRM + MSG_RST = 0x1000, +#define MSG_RST MSG_RST + MSG_ERRQUEUE = 0x2000, /* Fetch message from error queue. */ +#define MSG_ERRQUEUE MSG_ERRQUEUE + MSG_NOSIGNAL = 0x4000, /* Do not generate SIGPIPE. */ +#define MSG_NOSIGNAL MSG_NOSIGNAL + MSG_MORE = 0x8000, /* Sender will send more. */ +#define MSG_MORE MSG_MORE + MSG_WAITFORONE = 0x10000, /* Wait for at least one packet to return.*/ +#define MSG_WAITFORONE MSG_WAITFORONE + MSG_BATCH = 0x40000, /* sendmmsg: more messages coming. */ +#define MSG_BATCH MSG_BATCH + MSG_ZEROCOPY = 0x4000000, /* Use user data in kernel path. */ +#define MSG_ZEROCOPY MSG_ZEROCOPY + MSG_FASTOPEN = 0x20000000, /* Send data in TCP SYN. */ +#define MSG_FASTOPEN MSG_FASTOPEN + + MSG_CMSG_CLOEXEC = 0x40000000 /* Set close_on_exit for file + descriptor received through + SCM_RIGHTS. */ +#define MSG_CMSG_CLOEXEC MSG_CMSG_CLOEXEC + }; + +extern int accept (int __fd, struct sockaddr *__addr, socklen_t *__addr_len); +extern int bind (int __fd, const struct sockaddr *__addr, socklen_t __len); +extern int connect (int __fd, const struct sockaddr *__addr, socklen_t __len); +extern int getpeername (int __fd, struct sockaddr __addr, socklen_t *__len); +extern int getsockname (int __fd, struct sockaddr __addr, socklen_t *__len); +extern int getsockopt (int __fd, int __level, int __optname, void *__optval, socklen_t *__optlen); +extern int listen (int __fd, int __n); +extern ssize_t recv (int __fd, void *__buf, size_t __n, int __flags); +extern ssize_t recvfrom (int __fd, void *__buf, size_t __n, int __flags, struct sockaddr __addr, + socklen_t *__addr_len); +extern ssize_t recvmsg (int __fd, struct msghdr *__message, int __flags); +extern ssize_t send (int __fd, const void *__buf, size_t __n, int __flags); +extern ssize_t sendmsg (int __fd, const struct msghdr *__message, int __flags); +extern ssize_t sendto (int __fd, const void *__buf, size_t __n, int __flags, + const struct sockaddr *__addr, socklen_t __addr_len); +extern int setsockopt (int __fd, int __level, int __optname, const void *__optval, + socklen_t __optlen); +extern int shutdown (int __fd, int __how); +extern int socket (int __domain, int __type, int __protocol); +extern int sockatmark (int __fd); +extern int socketpair (int __domain, int __type, int __protocol, int __fds[2]); + +#endif // _SYS_SOCKET_H \ No newline at end of file diff --git a/newlib_shim/statvfs.h b/libc_extension/include/sys/statvfs.h similarity index 84% rename from newlib_shim/statvfs.h rename to libc_extension/include/sys/statvfs.h index 8ce27de..9677900 100644 --- a/newlib_shim/statvfs.h +++ b/libc_extension/include/sys/statvfs.h @@ -6,6 +6,7 @@ extern "C" { #endif #include +#include #define ST_RDONLY 1 #define ST_NOSUID 2 @@ -27,8 +28,14 @@ struct statvfs { unsigned long f_namemax; // Maximum filename length. }; -int statvfs(const char *path, struct statvfs *buf); -int fstatvfs(int fd, struct statvfs *buf); +int statvfs(const char *path, struct statvfs *buf) { + errno = ENOSYS; + return -1; +} +int fstatvfs(int fd, struct statvfs *buf) { + errno = ENOSYS; + return -1; +} #ifdef __cplusplus } diff --git a/libc_extension/include/sys/uio.h b/libc_extension/include/sys/uio.h new file mode 100644 index 0000000..4ddeced --- /dev/null +++ b/libc_extension/include/sys/uio.h @@ -0,0 +1,33 @@ +#ifndef _SYS_UIO_H +#define _SYS_UIO_H 1 + +#include + +/* Structure for scatter/gather I/O. */ +struct iovec +{ + void *iov_base; /* Pointer to data. */ + size_t iov_len; /* Length of data. */ +}; + +/* Read data from file descriptor FD, and put the result in the + buffers described by IOVEC, which is a vector of COUNT 'struct iovec's. + The buffers are filled in the order specified. + Operates just like 'read' (see ) except that data are + put in IOVEC instead of a contiguous buffer. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern ssize_t readv (int __fd, const struct iovec *__iovec, int __count); + +/* Write data pointed by the buffers described by IOVEC, which + is a vector of COUNT 'struct iovec's, to file descriptor FD. + The data is written in the order specified. + Operates just like 'write' (see ) except that the data + are taken from IOVEC instead of a contiguous buffer. + + This function is a cancellation point and therefore not marked with + __THROW. */ +extern ssize_t writev (int __fd, const struct iovec *__iovec, int __count); + +#endif // _SYS_UIO_H diff --git a/libc_extension/netdb.c b/libc_extension/netdb.c new file mode 100644 index 0000000..e697b0e --- /dev/null +++ b/libc_extension/netdb.c @@ -0,0 +1,66 @@ +#include + +void endhostent (void) {} + +void endnetent (void) {} + +void endprotoent (void) {} + +void endservent (void) {} + +struct hostent *gethostbyaddr (const void *__addr, __socklen_t __len, int __type) { + return 0; +} + +struct hostent *gethostbyname (const char *__name) { + return 0; +} + +struct hostent *gethostent (void) { + return 0; +} + +struct netent *getnetbyaddr (uint32_t __net, int __type) { + return 0; +} + +struct netent *getnetbyname (const char *__name) { + return 0; +} + +struct netent *getnetent (void) { + return 0; +} + +struct protoent *getprotobyname (const char *__name) { + return 0; +} + +struct protoent *getprotobynumber (int __proto) { + return 0; +} + +struct protoent *getprotoent (void) { + return 0; +} + +struct servent *getservbyname (const char *__name, const char *__proto) { + return 0; +} + +struct servent *getservbyport (int __port, const char *__proto) { + return 0; +} + +struct servent *getservent (void) { + return 0; +} + +void sethostent (int __stay_open) {} + +void setnetent (int __stay_open) {} + +void setprotoent (int __stay_open) {} + +void setservent (int __stay_open) {} + diff --git a/libc_extension/socket.c b/libc_extension/socket.c new file mode 100644 index 0000000..7d24a11 --- /dev/null +++ b/libc_extension/socket.c @@ -0,0 +1,73 @@ +#include + +int accept (int __fd, struct sockaddr *__addr, socklen_t *__addr_len) { + return -1; +} + +int bind (int __fd, const struct sockaddr *__addr, socklen_t __len) { + return -1; +} + +int connect (int __fd, const struct sockaddr *__addr, socklen_t __len) { + return -1; +} + +int getpeername (int __fd, struct sockaddr __addr, socklen_t *__len) { + return -1; +} + +int getsockname (int __fd, struct sockaddr __addr, socklen_t *__len) { + return -1; +} + +int getsockopt (int __fd, int __level, int __optname, void *__optval, socklen_t *__optlen) { + return -1; +} + +int listen (int __fd, int __n) { + return -1; +} + +ssize_t recv (int __fd, void *__buf, size_t __n, int __flags) { + return -1; +} + +ssize_t recvfrom (int __fd, void *__buf, size_t __n, int __flags, struct sockaddr __addr, socklen_t *__addr_len) { + return -1; +} + +ssize_t recvmsg (int __fd, struct msghdr *__message, int __flags) { + return -1; +} + +ssize_t send (int __fd, const void *__buf, size_t __n, int __flags) { + return -1; +} + +ssize_t sendmsg (int __fd, const struct msghdr *__message, int __flags) { + return -1; +} + +ssize_t sendto (int __fd, const void *__buf, size_t __n, int __flags, const struct sockaddr *__addr, socklen_t __addr_len) { + return -1; +} + +int setsockopt (int __fd, int __level, int __optname, const void *__optval, socklen_t __optlen) { + return -1; +} + +int shutdown (int __fd, int __how) { + return -1; +} + +int socket (int __domain, int __type, int __protocol) { + return -1; +} + +int sockatmark (int __fd) { + return -1; +} + +int socketpair (int __domain, int __type, int __protocol, int __fds[2]) { + return -1; +} diff --git a/libc_extension/uio.c b/libc_extension/uio.c new file mode 100644 index 0000000..590faa1 --- /dev/null +++ b/libc_extension/uio.c @@ -0,0 +1,9 @@ +#include + +ssize_t readv (int __fd, const struct iovec *__iovec, int __count) { + return -1; +} + +ssize_t writev (int __fd, const struct iovec *__iovec, int __count) { + return -1; +} diff --git a/newlib_shim/Makefile.inc b/newlib_shim/Makefile.inc index b8fed40..acbd0d0 100644 --- a/newlib_shim/Makefile.inc +++ b/newlib_shim/Makefile.inc @@ -1,5 +1,4 @@ libc_a_SOURCES += \ - %D%/dirent.c \ %D%/pthread.c \ %D%/shim.c \ %D%/time.c \ diff --git a/newlib_shim/patch_script b/newlib_shim/patch_script index 31f1a81..9f92f72 100755 --- a/newlib_shim/patch_script +++ b/newlib_shim/patch_script @@ -19,19 +19,10 @@ then fi cp $THIS_DIR/Makefile.inc $1/newlib/libc/sys/dandelion/Makefile.inc cp $THIS_DIR/shim.c $1/newlib/libc/sys/dandelion/shim.c -cp $THIS_DIR/dirent.c $1/newlib/libc/sys/dandelion/dirent.c cp $THIS_DIR/pthread.c $1/newlib/libc/sys/dandelion/pthread.c cp $THIS_DIR/time.c $1/newlib/libc/sys/dandelion/time.c cp $THIS_DIR/unistd.c $1/newlib/libc/sys/dandelion/unistd.c cp $THIS_DIR/../include/dandelion/crt.h $1/newlib/libc/sys/dandelion/crt.h -if ! test -d $1/newlib/libc/sys/dandelion/sys -then - mkdir $1/newlib/libc/sys/dandelion/sys -fi -cp $THIS_DIR/dirent.h $1/newlib/libc/sys/dandelion/sys/dirent.h -cp $THIS_DIR/statvfs.h $1/newlib/libc/sys/dandelion/sys/statvfs.h -cp $THIS_DIR/sched.h $1/newlib/libc/sys/dandelion/sys/sched.h -cp $THIS_DIR/cpuset.h $1/newlib/libc/sys/dandelion/sys/cpuset.h cd $1 autoreconf cd newlib diff --git a/newlib_shim/shim.c b/newlib_shim/shim.c index d2374ab..50deac3 100644 --- a/newlib_shim/shim.c +++ b/newlib_shim/shim.c @@ -1,7 +1,6 @@ #include #include #include -#include #include #include #include @@ -187,16 +186,6 @@ int lstat(const char *file, struct stat *buf) { return stat(file, buf); } mode_t umask(mode_t mask) { return 0777; } -int statvfs(const char *file, struct statvfs *st) { - errno = ENOSYS; - return -1; -} - -int fstatvfs(int fd, struct statvfs *buf) { - errno = ENOSYS; - return -1; -} - int posix_memalign(void **memptr, size_t alignment, size_t size) { void *new_allocation = memalign(alignment, size); if (new_allocation == NULL) { diff --git a/sdk_install/CMakeTemplate.txt b/sdk_install/CMakeTemplate.txt index 3ddcc8a..614890b 100644 --- a/sdk_install/CMakeTemplate.txt +++ b/sdk_install/CMakeTemplate.txt @@ -50,6 +50,7 @@ target_link_libraries(dlibc INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/lib/libc.a" "${CMAKE_CURRENT_SOURCE_DIR}/lib/libg.a" "${CMAKE_CURRENT_SOURCE_DIR}/lib/libm.a" + "${CMAKE_CURRENT_SOURCE_DIR}/lib/libc_extension.a" "${CMAKE_CURRENT_SOURCE_DIR}/lib/libdandelion_file_system.a" ) target_link_options(dlibc INTERFACE diff --git a/sdk_install/clang-template.cmake b/sdk_install/clang-template.cmake index c389790..0e2a504 100644 --- a/sdk_install/clang-template.cmake +++ b/sdk_install/clang-template.cmake @@ -23,6 +23,7 @@ -lm -lc -lg +-lc_extension -ldandelion_file_system -ldandelion_runtime -ldandelion_system From 756b7d1c1a15806b8a929cafdaa7cfc99a5b0d1c Mon Sep 17 00:00:00 2001 From: Tom Kuchler Date: Mon, 22 Dec 2025 16:09:29 +0100 Subject: [PATCH 20/20] Add back header that got lost in merging --- libc_extension/include/sys/mman.h | 64 +++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 libc_extension/include/sys/mman.h diff --git a/libc_extension/include/sys/mman.h b/libc_extension/include/sys/mman.h new file mode 100644 index 0000000..535e7eb --- /dev/null +++ b/libc_extension/include/sys/mman.h @@ -0,0 +1,64 @@ +/* sys/mman.h + +Copyright 1996, 1997, 1998, 2000, 2001 Red Hat, Inc. + +This file is part of Cygwin. + +This software is a copyrighted work licensed under the terms of the +Cygwin license. Please consult the file "CYGWIN_LICENSE" for +details. */ + +#ifndef _SYS_MMAN_H_ +#define _SYS_MMAN_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include +#include + +#define PROT_NONE 0 +#define PROT_READ 1 +#define PROT_WRITE 2 +#define PROT_EXEC 4 + +#define MAP_FILE 0 +#define MAP_SHARED 1 +#define MAP_PRIVATE 2 +#define MAP_TYPE 0xF +#define MAP_FIXED 0x10 +#define MAP_ANONYMOUS 0x20 +#define MAP_ANON MAP_ANONYMOUS + /* Non-standard flag */ +#if 0 /* Not yet implemented */ +#define MAP_NORESERVE 0x4000 /* Don't reserve swap space for this mapping. +Page protection must be set explicitely +to access page. */ +#endif +#define MAP_AUTOGROW 0x8000 /* Grow underlying object to mapping size. +File must be opened for writing. */ + +#define MAP_FAILED ((void *)-1) + + /* + * Flags for msync. + */ +#define MS_ASYNC 1 +#define MS_SYNC 2 +#define MS_INVALIDATE 4 + +#ifndef __INSIDE_CYGWIN__ + extern void *mmap (void *__addr, size_t __len, int __prot, int __flags, int __fd, off_t __off); +#endif + extern int munmap (void *__addr, size_t __len); + extern int mprotect (void *__addr, size_t __len, int __prot); + extern int msync (void *__addr, size_t __len, int __flags); + extern int mlock (const void *__addr, size_t __len); + extern int munlock (const void *__addr, size_t __len); + +#ifdef __cplusplus +}; +#endif /* __cplusplus */ + +#endif /* _SYS_MMAN_H_ */ \ No newline at end of file