refactor(userspace): build using cmake

Signed-off-by: EnderIce2 <enderice2@protonmail.com>
This commit is contained in:
EnderIce2 2025-03-15 23:05:17 +00:00
parent 40f46312f8
commit 201ace7eec
No known key found for this signature in database
GPG Key ID: 2EE20AF089811A5A
73 changed files with 2819 additions and 2255 deletions

File diff suppressed because it is too large Load Diff

View File

@ -15,8 +15,8 @@
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_API_SYSCALLS_LIST_H__
#define __FENNIX_API_SYSCALLS_LIST_H__
#ifndef __FENNIX_API_SYSTEM_CALLS_LIST_H__
#define __FENNIX_API_SYSTEM_CALLS_LIST_H__
#pragma region Syscall Wrappers
@ -1809,4 +1809,4 @@ typedef enum
/** @copydoc SYS_UNAME */
#define call_uname(buf) syscall1(SYS_UNAME, (scarg)buf)
#endif // !__FENNIX_API_SYSCALLS_LIST_H__
#endif // !__FENNIX_API_SYSTEM_CALLS_LIST_H__

File diff suppressed because it is too large Load Diff

View File

@ -15,8 +15,8 @@
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_API_SYSCALLS_LIST_H__
#define __FENNIX_API_SYSCALLS_LIST_H__
#ifndef __FENNIX_API_SYSTEM_CALLS_LIST_H__
#define __FENNIX_API_SYSTEM_CALLS_LIST_H__
#pragma region Syscall Wrappers
@ -1809,4 +1809,4 @@ typedef enum
/** @copydoc SYS_UNAME */
#define call_uname(buf) syscall1(SYS_UNAME, (scarg)buf)
#endif // !__FENNIX_API_SYSCALLS_LIST_H__
#endif // !__FENNIX_API_SYSTEM_CALLS_LIST_H__

View File

@ -20,4 +20,18 @@
#include <interface/errno.h>
#ifdef __cplusplus
extern "C"
{
#endif
int *__errno_location(void) __attribute__((const));
char *strerror(int errnum);
#ifdef __cplusplus
}
#endif
#define errno (*__errno_location())
#endif // !__FENNIX_KERNEL_STD_ERRNO_H__

View File

@ -1,5 +1,6 @@
{
"git.openRepositoryInParentFolders": "always",
"git.alwaysSignOff": true,
"git.defaultBranchName": "master"
}
"git.defaultBranchName": "master",
"cmake.ignoreCMakeListsMissing": true
}

View File

@ -0,0 +1,18 @@
{
"folders": [
{
"path": "./libc"
}
],
"settings": {
"terminal.integrated.cwd": "../../",
"debug.allowBreakpointsEverywhere": true,
"git.alwaysSignOff": true,
"git.defaultBranchName": "master",
"git.openRepositoryInParentFolders": "always",
"C_Cpp.autoAddFileAssociations": false,
"conventionalCommits.scopes": [
"userspace/libc"
]
}
}

View File

@ -0,0 +1,18 @@
{
"folders": [
{
"path": "./coreutils"
}
],
"settings": {
"terminal.integrated.cwd": "../../",
"debug.allowBreakpointsEverywhere": true,
"git.alwaysSignOff": true,
"git.defaultBranchName": "master",
"git.openRepositoryInParentFolders": "always",
"C_Cpp.autoAddFileAssociations": false,
"conventionalCommits.scopes": [
"userspace/coreutils"
]
}
}

View File

@ -35,7 +35,7 @@ create_out:
mkdir -p out/usr/share/doc
mkdir -p out/usr/share/info
mkdir -p out/usr/include
cp $(WORKSPACE_DIR)/../Kernel/include/interface/* $(WORKSPACE_DIR)/out/include/fennix/
cp $(WORKSPACE_DIR)/../Kernel/include/interface/* $(WORKSPACE_DIR)/out/include/fennix/
build_coreutils:
mkdir -p cache/coreutils
@ -49,8 +49,23 @@ build_coreutils:
make -j$(shell nproc) && \
make install
build_libc:
cp -f $(WORKSPACE_DIR)/../Kernel/include/interface/errno.h $(WORKSPACE_DIR)/libc/abis/fennix/generic/bits/errno.h
cp -f $(WORKSPACE_DIR)/../Kernel/include/interface/syscalls.h $(WORKSPACE_DIR)/libc/abis/fennix/generic/bits/syscalls.h
mkdir -p cache/libc
cd cache/libc && \
cmake $(WORKSPACE_DIR)/libc \
-DCMAKE_INSTALL_PREFIX:PATH=$(WORKSPACE_DIR)/out \
-DCMAKE_SYSROOT=$(WORKSPACE_DIR)/out \
-DCMAKE_C_STANDARD_INCLUDE_DIRECTORIES=$(WORKSPACE_DIR)/out/include \
-DTARGET_OS=fennix \
-DTARGET_ARCH=$(OSARCH) \
&& \
make -j$(shell nproc) && \
make install
build: create_out
make -C libc build
$(MAKE) build_libc
make -C libs build
$(MAKE) build_coreutils
make -C apps build
@ -62,6 +77,5 @@ clean:
rm -rf out cache
mkdir -p cache
touch cache/.gitkeep
make -C libc clean
make -C libs clean
make -C apps clean

1
Userspace/libc/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
build

View File

@ -0,0 +1,27 @@
{
"C Library License": {
"isFileTemplate": true,
"prefix": [
"license",
],
"body": [
"/*",
"\tThis file is part of Fennix C Library.",
"",
"\tFennix C Library is free software: you can redistribute it and/or",
"\tmodify it under the terms of the GNU General Public License as",
"\tpublished by the Free Software Foundation, either version 3 of",
"\tthe License, or (at your option) any later version.",
"",
"\tFennix C Library is distributed in the hope that it will be useful,",
"\tbut WITHOUT ANY WARRANTY; without even the implied warranty of",
"\tMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the",
"\tGNU General Public License for more details.",
"",
"\tYou should have received a copy of the GNU General Public License",
"\talong with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.",
"*/"
],
"description": "Create libc license."
}
}

View File

@ -0,0 +1,104 @@
cmake_minimum_required(VERSION 3.10)
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
project(FennixCLibrary VERSION 1.0.0)
if(NOT DEFINED ENV{WORKSPACE_DIR})
set(STANDALONE_BUILD ON)
message(STATUS "Compiling standalone")
set(CMAKE_INSTALL_PREFIX "/usr")
else()
set(STANDALONE_BUILD OFF)
set(CMAKE_INSTALL_PREFIX "$ENV{WORKSPACE_DIR}/out")
message(STATUS "Compiling within workspace")
try_compile(
WORKSPACE_TEST
${CMAKE_BINARY_DIR}
${CMAKE_SOURCE_DIR}/workspace_test.c
CMAKE_FLAGS "-DCMAKE_C_COMPILER=$ENV{CC} -DCMAKE_CXX_COMPILER=$ENV{CXX} -DCMAKE_ASM_COMPILER=$ENV{AS} -DCMAKE_AR=$ENV{AR} -DCMAKE_LINKER=$ENV{LD}"
OUTPUT_VARIABLE OUTPUT)
if(NOT WORKSPACE_TEST)
message(FATAL_ERROR "Workspace test failed: ${OUTPUT}")
else()
message(STATUS "Workspace test passed")
endif()
endif()
if(NOT DEFINED TARGET_OS)
if("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
set(TARGET_OS "linux")
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "Fennix")
set(TARGET_OS "fennix")
else()
message(FATAL_ERROR "Unsupported OS: ${CMAKE_SYSTEM_NAME}")
endif()
endif()
if(NOT DEFINED TARGET_ARCH)
set(TARGET_ARCH ${CMAKE_SYSTEM_PROCESSOR})
endif()
message(STATUS "Building for ${TARGET_OS}/${TARGET_ARCH}")
if(DEFINED ENV{CC})
set(CMAKE_C_COMPILER "$ENV{CC}")
endif()
if(DEFINED ENV{CXX})
set(CMAKE_CXX_COMPILER "$ENV{CXX}")
endif()
if(DEFINED ENV{AS})
set(CMAKE_ASM_COMPILER "$ENV{AS}")
endif()
if(DEFINED ENV{AR})
set(CMAKE_AR "$ENV{AR}")
endif()
if(DEFINED ENV{LD})
set(CMAKE_LINKER "$ENV{LD}")
endif()
if(DEFINED ENV{DEBUG} AND "$ENV{DEBUG}" STREQUAL "1")
set(CMAKE_C_FLAGS "-ggdb3 -O0 -DDEBUG")
else()
set(CMAKE_C_FLAGS "-O2")
endif()
set(SYSDEPS_DIR ${CMAKE_SOURCE_DIR}/sysdeps)
set(ABIS_DIR ${CMAKE_SOURCE_DIR}/abis)
set(SYSDEPS_GENERIC ${SYSDEPS_DIR}/${TARGET_OS}/generic)
set(SYSDEPS_PATH ${SYSDEPS_DIR}/${TARGET_OS}/${TARGET_ARCH})
set(ABIS_GENERIC ${ABIS_DIR}/${TARGET_OS}/generic)
set(ABIS_PATH ${ABIS_DIR}/${TARGET_OS}/${TARGET_ARCH})
if(NOT EXISTS ${SYSDEPS_PATH} AND NOT EXISTS ${SYSDEPS_GENERIC})
message(FATAL_ERROR "Missing sysdeps for ${TARGET_OS}: ${SYSDEPS_PATH} or ${SYSDEPS_GENERIC}")
endif()
if(NOT EXISTS ${ABIS_PATH} AND NOT EXISTS ${ABIS_GENERIC})
message(FATAL_ERROR "Missing abis for ${TARGET_OS}: ${ABIS_PATH} or ${ABIS_GENERIC}")
endif()
message(STATUS "Using sysdeps from: ${SYSDEPS_GENERIC} and ${SYSDEPS_PATH}")
message(STATUS "Using abis from: ${ABIS_GENERIC} and ${ABIS_PATH}")
include_directories(${ABIS_GENERIC} ${ABIS_PATH})
include_directories(${CMAKE_SOURCE_DIR}/include)
add_subdirectory(runtime)
add_subdirectory(interpreter)
add_subdirectory(src)
add_subdirectory(libs)
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/
DESTINATION include
FILES_MATCHING
PATTERN "*")
install(DIRECTORY ${ABIS_GENERIC}/
DESTINATION ${CMAKE_INSTALL_PREFIX}/include/
FILES_MATCHING
PATTERN "*")
install(DIRECTORY ${ABIS_PATH}/
DESTINATION ${CMAKE_INSTALL_PREFIX}/include/
FILES_MATCHING
PATTERN "*")

View File

@ -1,12 +0,0 @@
build:
cp -f $(WORKSPACE_DIR)/../Kernel/include/interface/errno.h $(CURDIR)/include/errno.h
cp -f $(WORKSPACE_DIR)/../Kernel/include/interface/syscalls.h $(CURDIR)/include/fennix/syscalls.h
cp -a $(CURDIR)/include/. $(WORKSPACE_DIR)/out/include
make -C interpreter build
make -C runtime build
make -C src build
clean:
make -C interpreter clean
make -C runtime clean
make -C src clean

View File

@ -0,0 +1,591 @@
/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_API_ERRNO_H__
#define __FENNIX_API_ERRNO_H__
/**
* The documentation for these error codes are from:
* https://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html
*
* Full list:
* https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/basedefs/errno.h.html
*/
/**
* No Error
*/
#define EOK 0
/**
* Argument list too long. The sum of the number of bytes used by the
* new process image's argument list and environment list is greater
* than the system-imposed limit of {ARG_MAX} bytes.
* or:
* Lack of space in an output buffer.
* or:
* Argument is greater than the system-imposed maximum.
*/
#define E2BIG 1
/**
* Permission denied. An attempt was made to access a file in a way
* forbidden by its file access permissions.
*/
#define EACCES 2
/**
* Address in use. The specified address is in use.
*/
#define EADDRINUSE 3
/**
* Address not available. The specified address is not available from
* the local system.
*/
#define EADDRNOTAVAIL 4
/**
* Address family not supported. The implementation does not support
* the specified address family, or the specified address is not a
* valid address for the address family of the specified socket.
*/
#define EAFNOSUPPORT 5
/**
* Resource temporarily unavailable. This is a temporary condition
* and later calls to the same routine may complete normally.
*/
#define EAGAIN 6
/**
* Connection already in progress. A connection request is already in
* progress for the specified socket.
*/
#define EALREADY 7
/**
* Bad file descriptor. A file descriptor argument is out of range,
* refers to no open file, or a read (write) request is made to a
* file that is only open for writing (reading).
*/
#define EBADF 8
/**
* Bad message. During a read(), getmsg(), getpmsg(), or ioctl()
* I_RECVFD request to a STREAMS device, a message arrived at the
* head of the STREAM that is inappropriate for the function
* receiving the message.
* read()
* Message waiting to be read on a STREAM is not a data message.
* getmsg() or getpmsg()
* A file descriptor was received instead of a control message.
* ioctl()
* Control or data information was received instead of a file
* descriptor when I_RECVFD was specified.
*/
#define EBADMSG 9
/**
* Resource busy. An attempt was made to make use of a system
* resource that is not currently available, as it is being
* used by another process in a manner that would have
* conflicted with the request being made by this process.
*/
#define EBUSY 10
/**
* Operation canceled. The associated asynchronous operation was
* canceled before completion.
*/
#define ECANCELED 11
/**
* No child process. A wait(), waitid(), or waitpid() function was
* executed by a process that had no existing or unwaited-for
* child process.
*/
#define ECHILD 12
/**
* Connection aborted. The connection has been aborted.
*/
#define ECONNABORTED 13
/**
* Connection refused. An attempt to connect to a socket was refused
* because there was no process listening or because the queue of
* connection requests was full and the underlying protocol does not
* support retransmissions.
*/
#define ECONNREFUSED 14
/**
* Connection reset. The connection was forcibly closed by the peer.
*/
#define ECONNRESET 15
/**
* Resource deadlock would occur. An attempt was made to lock a system
* resource that would have resulted in a deadlock situation.
*/
#define EDEADLK 16
/**
* Destination address required. No bind address was established.
*/
#define EDESTADDRREQ 17
/**
* Domain error. An input argument is outside the defined domain of the
* mathematical function (defined in the ISO C standard).
*/
#define EDOM 18
/**
* Reserved.
*/
#define EDQUOT 19
/**
* File exists. An existing file was mentioned in an inappropriate
* context; for example, as a new link name in the link() function.
*/
#define EEXIST 20
/**
* Bad address. The system detected an invalid address in attempting
* to use an argument of a call. The reliable detection of this error
* cannot be guaranteed, and when not detected may result in the
* generation of a signal, indicating an address violation, which is
* sent to the process.
*/
#define EFAULT 21
/**
* File too large. The size of a file would exceed the maximum file
* size of an implementation or offset maximum established in the
* corresponding file description.
*/
#define EFBIG 22
/**
* Host is unreachable. The destination host cannot be reached
* (probably because the host is down or a remote router cannot
* reach it).
*/
#define EHOSTUNREACH 23
/**
* Identifier removed. Returned during XSI interprocess communication
* if an identifier has been removed from the system.
*/
#define EIDRM 24
/**
* Illegal byte sequence. A wide-character code has been detected that
* does not correspond to a valid character, or a byte sequence does
* not form a valid wide-character code (defined in the ISO C standard).
*/
#define EILSEQ 25
/**
* Operation in progress. This code is used to indicate that an
* asynchronous operation has not yet completed.
* or:
* O_NONBLOCK is set for the socket file descriptor and the connection
* cannot be immediately established.
*/
#define EINPROGRESS 26
/**
* Interrupted function call. An asynchronous signal was caught by the
* process during the execution of an interruptible function. If the
* signal handler performs a normal return, the interrupted function
* call may return this condition (see the Base Definitions volume
* of POSIX.1-2017, <signal.h>).
*/
#define EINTR 27
/**
* Invalid argument. Some invalid argument was supplied; for example,
* specifying an undefined signal in a signal() function or a
* kill() function.
*/
#define EINVAL 28
/**
* Input/output error. Some physical input or output error has occurred.
* This error may be reported on a subsequent operation on the same
* file descriptor. Any other error-causing operation on the same file
* descriptor may cause the [EIO] error indication to be lost.
*/
#define EIO 29
/**
* Socket is connected. The specified socket is already connected.
*/
#define EISCONN 30
/**
* Is a directory. An attempt was made to open a directory with write
* mode specified.
*/
#define EISDIR 31
/**
* Symbolic link loop. A loop exists in symbolic links encountered
* during pathname resolution. This error may also be returned if
* more than {SYMLOOP_MAX} symbolic links are encountered during
* pathname resolution.
*/
#define ELOOP 32
/**
* File descriptor value too large or too many open streams. An
* attempt was made to open a file descriptor with a value greater
* than or equal to {OPEN_MAX}, or an attempt was made to open more
* than the maximum number of streams allowed in the process.
*/
#define EMFILE 33
/**
* Too many links. An attempt was made to have the link count of a
* single file exceed {LINK_MAX}.
*/
#define EMLINK 34
/**
* Message too large. A message sent on a transport provider was
* larger than an internal message buffer or some other network limit.
* or:
* Inappropriate message buffer length.
*/
#define EMSGSIZE 35
/**
* Reserved.
*/
#define EMULTIHOP 36
/**
* Filename too long. The length of a pathname exceeds {PATH_MAX} and
* the implementation considers this to be an error, or a pathname
* component is longer than {NAME_MAX}. This error may also occur
* when pathname substitution, as a result of encountering a
* symbolic link during pathname resolution, results in a pathname
* string the size of which exceeds {PATH_MAX}.
*/
#define ENAMETOOLONG 37
/**
* Network is down. The local network interface used to reach the
* destination is down.
*/
#define ENETDOWN 38
/**
* The connection was aborted by the network.
*/
#define ENETRESET 39
/**
* Network unreachable. No route to the network is present.
*/
#define ENETUNREACH 40
/**
* Too many files open in system. Too many files are currently open
* in the system. The system has reached its predefined limit for
* simultaneously open files and temporarily cannot accept requests
* to open another one.
*/
#define ENFILE 41
/**
* No buffer space available. Insufficient buffer resources were
* available in the system to perform the socket operation.
*/
#define ENOBUFS 42
/**
* No message available. No message is available on the STREAM head
* read queue.
*/
#define ENODATA 43
/**
* No such device. An attempt was made to apply an inappropriate
* function to a device; for example, trying to read a write-only
* device such as a printer.
*/
#define ENODEV 44
/**
* No such file or directory. A component of a specified pathname
* does not exist, or the pathname is an empty string.
*/
#define ENOENT 45
/**
* Executable file format error. A request is made to execute a file
* that, although it has appropriate privileges, is not in the
* format required by the implementation for executable files.
*/
#define ENOEXEC 46
/**
* No locks available. A system-imposed limit on the number of
* simultaneous file and record locks has been reached and no more
* are currently available.
*/
#define ENOLCK 47
/**
* Reserved.
*/
#define ENOLINK 48
/**
* Not enough space. The new process image requires more memory than
* is allowed by the hardware or system-imposed memory management
* constraints.
*/
#define ENOMEM 49
/**
* No message of the desired type. The message queue does not contain
* a message of the required type during XSI interprocess communication.
*/
#define ENOMSG 50
/**
* Protocol not available. The protocol option specified to
* setsockopt() is not supported by the implementation.
*/
#define ENOPROTOOPT 51
/**
* No space left on a device. During the write() function on a
* regular file or when extending a directory, there is no free
* space left on the device.
*/
#define ENOSPC 52
/**
* No STREAM resources. Insufficient STREAMS memory resources are
* available to perform a STREAMS-related function. This is a
* temporary condition; it may be recovered from if other
* processes release resources.
*/
#define ENOSR 53
/**
* Not a STREAM. A STREAM function was attempted on a file descriptor
* that was not associated with a STREAMS device.
*/
#define ENOSTR 54
/**
* Functionality not supported. An attempt was made to use optional
* functionality that is not supported in this implementation.
*/
#define ENOSYS 55
/**
* Socket not connected. The socket is not connected.
*/
#define ENOTCONN 56
/**
* Not a directory. A component of the specified pathname exists, but
* it is not a directory, when a directory was expected; or an
* attempt was made to create a non-directory file, and the specified
* pathname contains at least one non- \<slash\> character and ends
* with one or more trailing \<slash\> characters.
*/
#define ENOTDIR 57
/**
* Directory not empty. A directory other than an empty directory
* was supplied when an empty directory was expected.
*/
#define ENOTEMPTY 58
/**
* State not recoverable. The state protected by a robust mutex
* is not recoverable.
*/
#define ENOTRECOVERABLE 59
/**
* Not a socket. The file descriptor does not refer to a socket.
*/
#define ENOTSOCK 60
/**
* Not supported. The implementation does not support the requested
* feature or value.
*/
#define ENOTSUP 61
/**
* Inappropriate I/O control operation. A control function has been
* attempted for a file or special file for which the operation
* is inappropriate.
*/
#define ENOTTY 62
/**
* No such device or address. Input or output on a special file
* refers to a device that does not exist, or makes a request
* beyond the capabilities of the device. It may also occur when,
* for example, a tape drive is not on-line.
*/
#define ENXIO 63
/**
* Operation not supported on socket. The type of socket (address
* family or protocol) does not support the requested operation.
*/
#define EOPNOTSUPP 64
/**
* Value too large to be stored in data type. An operation was
* attempted which would generate a value that is outside the
* range of values that can be represented in the relevant data
* type or that are allowed for a given data item.
*/
#define EOVERFLOW 65
/**
* Previous owner died. The owner of a robust mutex terminated
* while holding the mutex lock.
*/
#define EOWNERDEAD 66
/**
* Operation not permitted. An attempt was made to perform an
* operation limited to processes with appropriate privileges or
* to the owner of a file or other resource.
*/
#define EPERM 67
/**
* Broken pipe. A write was attempted on a socket, pipe, or FIFO
* for which there is no process to read the data.
*/
#define EPIPE 68
/**
* Protocol error. Some protocol error occurred. This error is
* device-specific, but is generally not related to a
* hardware failure.
*/
#define EPROTO 69
/**
* Protocol not supported. The protocol is not supported by the
* address family, or the protocol is not supported by
* the implementation.
*/
#define EPROTONOSUPPORT 70
/**
* Protocol wrong type for socket. The socket type is not
* supported by the protocol.
*/
#define EPROTOTYPE 71
/**
* Result too large or too small. The result of the function
* is too large (overflow) or too small (underflow) to be
* represented in the available space.
*/
#define ERANGE 72
/**
* Read-only file system. An attempt was made to modify a file
* or directory on a file system that is read-only.
*/
#define EROFS 73
/**
* Invalid seek. An attempt was made to access the file offset
* associated with a pipe or FIFO.
*/
#define ESPIPE 74
/**
* No such process. No process can be found corresponding to that
* specified by the given process ID.
*/
#define ESRCH 75
/**
* Reserved.
*/
#define ESTALE 76
/**
* STREAM ioctl() timeout. The timer set for a STREAMS ioctl() call
* has expired. The cause of this error is device-specific and could
* indicate either a hardware or software failure, or a timeout
* value that is too short for the specific operation. The status
* of the ioctl() operation is unspecified.
*/
#define ETIME 77
/**
* Connection timed out. The connection to a remote machine has
* timed out.
* If the connection timed out during execution of the function that
* reported this error (as opposed to timing out prior to the
* function being called), it is unspecified whether the function
* has completed some or all of the documented behavior associated
* with a successful completion of the function.
* or:
* Operation timed out. The time limit associated with the operation
* was exceeded before the operation completed.
*/
#define ETIMEDOUT 78
/**
* Text file busy. An attempt was made to execute a pure-procedure
* program that is currently open for writing, or an attempt has
* been made to open for writing a pure-procedure program that
* is being executed.
*/
#define ETXTBSY 79
/**
* Operation would block. An operation on a socket marked as
* non-blocking has encountered a situation such as no data available
* that otherwise would have caused the function to suspend execution.
*/
#define EWOULDBLOCK 80
/**
* Improper link. A link to a file on another file system was attempted.
*/
#define EXDEV 81
#ifdef __kernel__
#define __ERRNO_MAX 82
#endif
#endif // !__FENNIX_API_ERRNO_H__

View File

@ -0,0 +1,124 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __BITS_SIGNAL_H
#define __BITS_SIGNAL_H
#include <bits/syscalls.h>
#define SIGNULL __SYS_SIGNULL
#define SIGABRT __SYS_SIGABRT
#define SIGALRM __SYS_SIGALRM
#define SIGBUS __SYS_SIGBUS
#define SIGCHLD __SYS_SIGCHLD
#define SIGCONT __SYS_SIGCONT
#define SIGFPE __SYS_SIGFPE
#define SIGHUP __SYS_SIGHUP
#define SIGILL __SYS_SIGILL
#define SIGINT __SYS_SIGINT
#define SIGKILL __SYS_SIGKILL
#define SIGPIPE __SYS_SIGPIPE
#define SIGQUIT __SYS_SIGQUIT
#define SIGSEGV __SYS_SIGSEGV
#define SIGSTOP __SYS_SIGSTOP
#define SIGTERM __SYS_SIGTERM
#define SIGTSTP __SYS_SIGTSTP
#define SIGTTIN __SYS_SIGTTIN
#define SIGTTOU __SYS_SIGTTOU
#define SIGUSR1 __SYS_SIGUSR1
#define SIGUSR2 __SYS_SIGUSR2
#define SIGPOLL __SYS_SIGPOLL
#define SIGPROF __SYS_SIGPROF
#define SIGSYS __SYS_SIGSYS
#define SIGTRAP __SYS_SIGTRAP
#define SIGURG __SYS_SIGURG
#define SIGVTALRM __SYS_SIGVTALRM
#define SIGXCPU __SYS_SIGXCPU
#define SIGXFSZ __SYS_SIGXFSZ
#define SIGCOMP1 __SYS_SIGCOMP1
#define SIGCOMP2 __SYS_SIGCOMP2
#define SIGCOMP3 __SYS_SIGCOMP3
#define SIGRTMIN __SYS_SIGRTMIN
#define SIGRT_1 __SYS_SIGRT_1
#define SIGRT_2 __SYS_SIGRT_2
#define SIGRT_3 __SYS_SIGRT_3
#define SIGRT_4 __SYS_SIGRT_4
#define SIGRT_5 __SYS_SIGRT_5
#define SIGRT_6 __SYS_SIGRT_6
#define SIGRT_7 __SYS_SIGRT_7
#define SIGRT_8 __SYS_SIGRT_8
#define SIGRT_9 __SYS_SIGRT_9
#define SIGRT_10 __SYS_SIGRT_10
#define SIGRT_11 __SYS_SIGRT_11
#define SIGRT_12 __SYS_SIGRT_12
#define SIGRT_13 __SYS_SIGRT_13
#define SIGRT_14 __SYS_SIGRT_14
#define SIGRT_15 __SYS_SIGRT_15
#define SIGRT_16 __SYS_SIGRT_16
#define SIGRT_17 __SYS_SIGRT_17
#define SIGRT_18 __SYS_SIGRT_18
#define SIGRT_19 __SYS_SIGRT_19
#define SIGRT_20 __SYS_SIGRT_20
#define SIGRT_21 __SYS_SIGRT_21
#define SIGRT_22 __SYS_SIGRT_22
#define SIGRT_23 __SYS_SIGRT_23
#define SIGRT_24 __SYS_SIGRT_24
#define SIGRT_25 __SYS_SIGRT_25
#define SIGRT_26 __SYS_SIGRT_26
#define SIGRT_27 __SYS_SIGRT_27
#define SIGRT_28 __SYS_SIGRT_28
#define SIGRT_29 __SYS_SIGRT_29
#define SIGRT_30 __SYS_SIGRT_30
#define SIGRT_31 __SYS_SIGRT_31
#define SIGRTMAX __SYS_SIGRTMAX
#define SIGNAL_MAX __SYS_SIGNAL_MAX
#define SIG_TERM __SYS_SIG_TERM
// #define SIG_IGN __SYS_SIG_IGN
#define SIG_CORE __SYS_SIG_CORE
#define SIG_STOP __SYS_SIG_STOP
#define SIG_CONT __SYS_SIG_CONT
#define SIG_BLOCK __SYS_SIG_BLOCK
#define SIG_UNBLOCK __SYS_SIG_UNBLOCK
#define SIG_SETMASK __SYS_SIG_SETMASK
#define SA_NOCLDSTOP __SYS_SA_NOCLDSTOP
#define SA_ONSTACK __SYS_SA_ONSTACK
#define SA_RESETHAND __SYS_SA_RESETHAND
#define SA_RESTART __SYS_SA_RESTART
#define SA_SIGINFO __SYS_SA_SIGINFO
#define SA_NOCLDWAIT __SYS_SA_NOCLDWAIT
#define SA_NODEFER __SYS_SA_NODEFER
#define SS_ONSTACK
#define SS_DISABLE
#define MINSIGSTKSZ
#define SIGSTKSZ
#define SIG_ERR ((void (*)(int))__SYS_SIG_ERR)
#define SIG_DFL ((void (*)(int))__SYS_SIG_DFL)
#define SIG_IGN ((void (*)(int))__SYS_SIG_IGN)
#define SIGEV_NONE
#define SIGEV_SIGNAL
#define SIGEV_THREAD
typedef unsigned long sigset_t;
#endif // __BITS_SIGNAL_H

View File

@ -0,0 +1,34 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __BITS_SOCKET_H
#define __BITS_SOCKET_H
#define __socklen_t_defined
typedef __UINT32_TYPE__ socklen_t;
#define __sa_family_t_defined
typedef unsigned int sa_family_t;
#define __sockaddr_defined
struct sockaddr
{
sa_family_t sa_family;
char sa_data[14];
};
#endif // __BITS_SOCKET_H

View File

@ -15,8 +15,8 @@
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_API_SYSCALLS_LIST_H__
#define __FENNIX_API_SYSCALLS_LIST_H__
#ifndef __FENNIX_API_SYSTEM_CALLS_LIST_H__
#define __FENNIX_API_SYSTEM_CALLS_LIST_H__
#pragma region Syscall Wrappers
@ -1809,4 +1809,4 @@ typedef enum
/** @copydoc SYS_UNAME */
#define call_uname(buf) syscall1(SYS_UNAME, (scarg)buf)
#endif // !__FENNIX_API_SYSCALLS_LIST_H__
#endif // !__FENNIX_API_SYSTEM_CALLS_LIST_H__

View File

@ -0,0 +1,70 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef FENNIX_BITS_LIBC_H
#define FENNIX_BITS_LIBC_H
#include <bits/socket.h>
#include <sys/utsname.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifdef __kernel__
#error "Kernel code should not include this header"
#endif // __kernel__
#ifndef export
#define export __attribute__((__visibility__("default")))
#endif // export
#define sysdep(name) \
__libc_##name
void sysdep(Exit)(int Status);
int sysdep(Accept)(int Socket, struct sockaddr *restrict Address, socklen_t *restrict AddressLength);
int sysdep(Bind)(int Socket, const struct sockaddr *Address, socklen_t AddressLength);
int sysdep(Connect)(int Socket, const struct sockaddr *Address, socklen_t AddressLength);
int sysdep(Listen)(int Socket, int Backlog);
int sysdep(Socket)(int Domain, int Type, int Protocol);
int sysdep(UnixName)(struct utsname *Name);
int sysdep(WaitProcessID)(pid_t ProcessID, int *Status, int Options);
int sysdep(IOControl)(int Descriptor, unsigned long Operation, void *Argument);
void *sysdep(MemoryMap)(void *Address, size_t Length, int Protection, int Flags, int Descriptor, off_t Offset);
int sysdep(MemoryUnmap)(void *Address, size_t Length);
int sysdep(MemoryProtect)(void *Address, size_t Length, int Protection);
int sysdep(Fork)(void);
int sysdep(Read)(int Descriptor, void *Buffer, size_t Size);
int sysdep(Write)(int Descriptor, const void *Buffer, size_t Size);
int sysdep(PRead)(int Descriptor, void *Buffer, size_t Size, off_t Offset);
int sysdep(PWrite)(int Descriptor, const void *Buffer, size_t Size, off_t Offset);
int sysdep(Open)(const char *Pathname, int Flags, mode_t Mode);
int sysdep(Close)(int Descriptor);
int sysdep(Access)(const char *Pathname, int Mode);
int sysdep(Tell)(int Descriptor);
int sysdep(Seek)(int Descriptor, off_t Offset, int Whence);
pid_t sysdep(GetProcessID)(void);
pid_t sysdep(GetParentProcessID)(void);
int sysdep(Execve)(const char *Pathname, char *const *Argv, char *const *Envp);
int sysdep(Kill)(pid_t ProcessID, int Signal);
int sysdep(Stat)(const char *Pathname, struct stat *Statbuf);
int sysdep(FStat)(int Descriptor, struct stat *Statbuf);
int sysdep(LStat)(const char *Pathname, struct stat *Statbuf);
int sysdep(Truncate)(const char *Pathname, off_t Length);
int sysdep(MakeDirectory)(const char *Pathname, mode_t Mode);
int sysdep(ProcessControl)(unsigned long Option, unsigned long Arg1, unsigned long Arg2, unsigned long Arg3, unsigned long Arg4);
#endif // FENNIX_BITS_LIBC_H

View File

@ -0,0 +1,36 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __BITS_TYPES_SIGNAL_H
#define __BITS_TYPES_SIGNAL_H
union sigval
{
int sival_int; /* Integer signal value. */
void *sival_ptr; /* Pointer signal value. */
};
typedef struct sigevent
{
int sigev_notify; /* Notification type. */
int sigev_signo; /* Signal number. */
union sigval sigev_value; /* Signal value. */
void (*sigev_notify_function)(union sigval); /* Notification function. */
pthread_attr_t *sigev_notify_attributes; /* Notification attributes. */
} sigevent;
#endif // __BITS_TYPES_SIGNAL_H

View File

@ -1,592 +1,24 @@
/*
This file is part of Fennix Kernel.
This file is part of Fennix C Library.
Fennix Kernel is free software: you can redistribute it and/or
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_API_ERRNO_H__
#define __FENNIX_API_ERRNO_H__
#ifndef _ERRNO_H
#define _ERRNO_H
/**
* The documentation for these error codes are from:
* https://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html
*
* Full list:
* https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/basedefs/errno.h.html
*/
typedef enum
{
/**
* No Error
*/
EOK = 0,
/**
* Argument list too long. The sum of the number of bytes used by the
* new process image's argument list and environment list is greater
* than the system-imposed limit of {ARG_MAX} bytes.
* or:
* Lack of space in an output buffer.
* or:
* Argument is greater than the system-imposed maximum.
*/
E2BIG = 1,
/**
* Permission denied. An attempt was made to access a file in a way
* forbidden by its file access permissions.
*/
EACCES = 2,
/**
* Address in use. The specified address is in use.
*/
EADDRINUSE = 3,
/**
* Address not available. The specified address is not available from
* the local system.
*/
EADDRNOTAVAIL = 4,
/**
* Address family not supported. The implementation does not support
* the specified address family, or the specified address is not a
* valid address for the address family of the specified socket.
*/
EAFNOSUPPORT = 5,
/**
* Resource temporarily unavailable. This is a temporary condition
* and later calls to the same routine may complete normally.
*/
EAGAIN = 6,
/**
* Connection already in progress. A connection request is already in
* progress for the specified socket.
*/
EALREADY = 7,
/**
* Bad file descriptor. A file descriptor argument is out of range,
* refers to no open file, or a read (write) request is made to a
* file that is only open for writing (reading).
*/
EBADF = 8,
/**
* Bad message. During a read(), getmsg(), getpmsg(), or ioctl()
* I_RECVFD request to a STREAMS device, a message arrived at the
* head of the STREAM that is inappropriate for the function
* receiving the message.
* read()
* Message waiting to be read on a STREAM is not a data message.
* getmsg() or getpmsg()
* A file descriptor was received instead of a control message.
* ioctl()
* Control or data information was received instead of a file
* descriptor when I_RECVFD was specified.
*/
EBADMSG = 9,
/**
* Resource busy. An attempt was made to make use of a system
* resource that is not currently available, as it is being
* used by another process in a manner that would have
* conflicted with the request being made by this process.
*/
EBUSY = 10,
/**
* Operation canceled. The associated asynchronous operation was
* canceled before completion.
*/
ECANCELED = 11,
/**
* No child process. A wait(), waitid(), or waitpid() function was
* executed by a process that had no existing or unwaited-for
* child process.
*/
ECHILD = 12,
/**
* Connection aborted. The connection has been aborted.
*/
ECONNABORTED = 13,
/**
* Connection refused. An attempt to connect to a socket was refused
* because there was no process listening or because the queue of
* connection requests was full and the underlying protocol does not
* support retransmissions.
*/
ECONNREFUSED = 14,
/**
* Connection reset. The connection was forcibly closed by the peer.
*/
ECONNRESET = 15,
/**
* Resource deadlock would occur. An attempt was made to lock a system
* resource that would have resulted in a deadlock situation.
*/
EDEADLK = 16,
/**
* Destination address required. No bind address was established.
*/
EDESTADDRREQ = 17,
/**
* Domain error. An input argument is outside the defined domain of the
* mathematical function (defined in the ISO C standard).
*/
EDOM = 18,
/**
* Reserved.
*/
EDQUOT = 19,
/**
* File exists. An existing file was mentioned in an inappropriate
* context; for example, as a new link name in the link() function.
*/
EEXIST = 20,
/**
* Bad address. The system detected an invalid address in attempting
* to use an argument of a call. The reliable detection of this error
* cannot be guaranteed, and when not detected may result in the
* generation of a signal, indicating an address violation, which is
* sent to the process.
*/
EFAULT = 21,
/**
* File too large. The size of a file would exceed the maximum file
* size of an implementation or offset maximum established in the
* corresponding file description.
*/
EFBIG = 22,
/**
* Host is unreachable. The destination host cannot be reached
* (probably because the host is down or a remote router cannot
* reach it).
*/
EHOSTUNREACH = 23,
/**
* Identifier removed. Returned during XSI interprocess communication
* if an identifier has been removed from the system.
*/
EIDRM = 24,
/**
* Illegal byte sequence. A wide-character code has been detected that
* does not correspond to a valid character, or a byte sequence does
* not form a valid wide-character code (defined in the ISO C standard).
*/
EILSEQ = 25,
/**
* Operation in progress. This code is used to indicate that an
* asynchronous operation has not yet completed.
* or:
* O_NONBLOCK is set for the socket file descriptor and the connection
* cannot be immediately established.
*/
EINPROGRESS = 26,
/**
* Interrupted function call. An asynchronous signal was caught by the
* process during the execution of an interruptible function. If the
* signal handler performs a normal return, the interrupted function
* call may return this condition (see the Base Definitions volume
* of POSIX.1-2017, <signal.h>).
*/
EINTR = 27,
/**
* Invalid argument. Some invalid argument was supplied; for example,
* specifying an undefined signal in a signal() function or a
* kill() function.
*/
EINVAL = 28,
/**
* Input/output error. Some physical input or output error has occurred.
* This error may be reported on a subsequent operation on the same
* file descriptor. Any other error-causing operation on the same file
* descriptor may cause the [EIO] error indication to be lost.
*/
EIO = 29,
/**
* Socket is connected. The specified socket is already connected.
*/
EISCONN = 30,
/**
* Is a directory. An attempt was made to open a directory with write
* mode specified.
*/
EISDIR = 31,
/**
* Symbolic link loop. A loop exists in symbolic links encountered
* during pathname resolution. This error may also be returned if
* more than {SYMLOOP_MAX} symbolic links are encountered during
* pathname resolution.
*/
ELOOP = 32,
/**
* File descriptor value too large or too many open streams. An
* attempt was made to open a file descriptor with a value greater
* than or equal to {OPEN_MAX}, or an attempt was made to open more
* than the maximum number of streams allowed in the process.
*/
EMFILE = 33,
/**
* Too many links. An attempt was made to have the link count of a
* single file exceed {LINK_MAX}.
*/
EMLINK = 34,
/**
* Message too large. A message sent on a transport provider was
* larger than an internal message buffer or some other network limit.
* or:
* Inappropriate message buffer length.
*/
EMSGSIZE = 35,
/**
* Reserved.
*/
EMULTIHOP = 36,
/**
* Filename too long. The length of a pathname exceeds {PATH_MAX} and
* the implementation considers this to be an error, or a pathname
* component is longer than {NAME_MAX}. This error may also occur
* when pathname substitution, as a result of encountering a
* symbolic link during pathname resolution, results in a pathname
* string the size of which exceeds {PATH_MAX}.
*/
ENAMETOOLONG = 37,
/**
* Network is down. The local network interface used to reach the
* destination is down.
*/
ENETDOWN = 38,
/**
* The connection was aborted by the network.
*/
ENETRESET = 39,
/**
* Network unreachable. No route to the network is present.
*/
ENETUNREACH = 40,
/**
* Too many files open in system. Too many files are currently open
* in the system. The system has reached its predefined limit for
* simultaneously open files and temporarily cannot accept requests
* to open another one.
*/
ENFILE = 41,
/**
* No buffer space available. Insufficient buffer resources were
* available in the system to perform the socket operation.
*/
ENOBUFS = 42,
/**
* No message available. No message is available on the STREAM head
* read queue.
*/
ENODATA = 43,
/**
* No such device. An attempt was made to apply an inappropriate
* function to a device; for example, trying to read a write-only
* device such as a printer.
*/
ENODEV = 44,
/**
* No such file or directory. A component of a specified pathname
* does not exist, or the pathname is an empty string.
*/
ENOENT = 45,
/**
* Executable file format error. A request is made to execute a file
* that, although it has appropriate privileges, is not in the
* format required by the implementation for executable files.
*/
ENOEXEC = 46,
/**
* No locks available. A system-imposed limit on the number of
* simultaneous file and record locks has been reached and no more
* are currently available.
*/
ENOLCK = 47,
/**
* Reserved.
*/
ENOLINK = 48,
/**
* Not enough space. The new process image requires more memory than
* is allowed by the hardware or system-imposed memory management
* constraints.
*/
ENOMEM = 49,
/**
* No message of the desired type. The message queue does not contain
* a message of the required type during XSI interprocess communication.
*/
ENOMSG = 50,
/**
* Protocol not available. The protocol option specified to
* setsockopt() is not supported by the implementation.
*/
ENOPROTOOPT = 51,
/**
* No space left on a device. During the write() function on a
* regular file or when extending a directory, there is no free
* space left on the device.
*/
ENOSPC = 52,
/**
* No STREAM resources. Insufficient STREAMS memory resources are
* available to perform a STREAMS-related function. This is a
* temporary condition; it may be recovered from if other
* processes release resources.
*/
ENOSR = 53,
/**
* Not a STREAM. A STREAM function was attempted on a file descriptor
* that was not associated with a STREAMS device.
*/
ENOSTR = 54,
/**
* Functionality not supported. An attempt was made to use optional
* functionality that is not supported in this implementation.
*/
ENOSYS = 55,
/**
* Socket not connected. The socket is not connected.
*/
ENOTCONN = 56,
/**
* Not a directory. A component of the specified pathname exists, but
* it is not a directory, when a directory was expected; or an
* attempt was made to create a non-directory file, and the specified
* pathname contains at least one non- \<slash\> character and ends
* with one or more trailing \<slash\> characters.
*/
ENOTDIR = 57,
/**
* Directory not empty. A directory other than an empty directory
* was supplied when an empty directory was expected.
*/
ENOTEMPTY = 58,
/**
* State not recoverable. The state protected by a robust mutex
* is not recoverable.
*/
ENOTRECOVERABLE = 59,
/**
* Not a socket. The file descriptor does not refer to a socket.
*/
ENOTSOCK = 60,
/**
* Not supported. The implementation does not support the requested
* feature or value.
*/
ENOTSUP = 61,
/**
* Inappropriate I/O control operation. A control function has been
* attempted for a file or special file for which the operation
* is inappropriate.
*/
ENOTTY = 62,
/**
* No such device or address. Input or output on a special file
* refers to a device that does not exist, or makes a request
* beyond the capabilities of the device. It may also occur when,
* for example, a tape drive is not on-line.
*/
ENXIO = 63,
/**
* Operation not supported on socket. The type of socket (address
* family or protocol) does not support the requested operation.
*/
EOPNOTSUPP = 64,
/**
* Value too large to be stored in data type. An operation was
* attempted which would generate a value that is outside the
* range of values that can be represented in the relevant data
* type or that are allowed for a given data item.
*/
EOVERFLOW = 65,
/**
* Previous owner died. The owner of a robust mutex terminated
* while holding the mutex lock.
*/
EOWNERDEAD = 66,
/**
* Operation not permitted. An attempt was made to perform an
* operation limited to processes with appropriate privileges or
* to the owner of a file or other resource.
*/
EPERM = 67,
/**
* Broken pipe. A write was attempted on a socket, pipe, or FIFO
* for which there is no process to read the data.
*/
EPIPE = 68,
/**
* Protocol error. Some protocol error occurred. This error is
* device-specific, but is generally not related to a
* hardware failure.
*/
EPROTO = 69,
/**
* Protocol not supported. The protocol is not supported by the
* address family, or the protocol is not supported by
* the implementation.
*/
EPROTONOSUPPORT = 70,
/**
* Protocol wrong type for socket. The socket type is not
* supported by the protocol.
*/
EPROTOTYPE = 71,
/**
* Result too large or too small. The result of the function
* is too large (overflow) or too small (underflow) to be
* represented in the available space.
*/
ERANGE = 72,
/**
* Read-only file system. An attempt was made to modify a file
* or directory on a file system that is read-only.
*/
EROFS = 73,
/**
* Invalid seek. An attempt was made to access the file offset
* associated with a pipe or FIFO.
*/
ESPIPE = 74,
/**
* No such process. No process can be found corresponding to that
* specified by the given process ID.
*/
ESRCH = 75,
/**
* Reserved.
*/
ESTALE = 76,
/**
* STREAM ioctl() timeout. The timer set for a STREAMS ioctl() call
* has expired. The cause of this error is device-specific and could
* indicate either a hardware or software failure, or a timeout
* value that is too short for the specific operation. The status
* of the ioctl() operation is unspecified.
*/
ETIME = 77,
/**
* Connection timed out. The connection to a remote machine has
* timed out.
* If the connection timed out during execution of the function that
* reported this error (as opposed to timing out prior to the
* function being called), it is unspecified whether the function
* has completed some or all of the documented behavior associated
* with a successful completion of the function.
* or:
* Operation timed out. The time limit associated with the operation
* was exceeded before the operation completed.
*/
ETIMEDOUT = 78,
/**
* Text file busy. An attempt was made to execute a pure-procedure
* program that is currently open for writing, or an attempt has
* been made to open for writing a pure-procedure program that
* is being executed.
*/
ETXTBSY = 79,
/**
* Operation would block. An operation on a socket marked as
* non-blocking has encountered a situation such as no data available
* that otherwise would have caused the function to suspend execution.
*/
EWOULDBLOCK = 80,
/**
* Improper link. A link to a file on another file system was attempted.
*/
EXDEV = 81,
__ERRNO_MAX
} KernelErrors;
#include <bits/errno.h>
#ifdef __cplusplus
extern "C"
@ -602,4 +34,4 @@ extern "C"
#define errno (*__errno_location())
#endif // !__FENNIX_API_ERRNO_H__
#endif // _ERRNO_H

View File

@ -24,115 +24,11 @@ extern "C"
#endif // __cplusplus
#include <sys/types.h>
#include <fennix/syscalls.h>
#include <bits/libc.h>
#include <bits/types/timespec.h>
#define SIGNULL __SYS_SIGNULL
#define SIGABRT __SYS_SIGABRT
#define SIGALRM __SYS_SIGALRM
#define SIGBUS __SYS_SIGBUS
#define SIGCHLD __SYS_SIGCHLD
#define SIGCONT __SYS_SIGCONT
#define SIGFPE __SYS_SIGFPE
#define SIGHUP __SYS_SIGHUP
#define SIGILL __SYS_SIGILL
#define SIGINT __SYS_SIGINT
#define SIGKILL __SYS_SIGKILL
#define SIGPIPE __SYS_SIGPIPE
#define SIGQUIT __SYS_SIGQUIT
#define SIGSEGV __SYS_SIGSEGV
#define SIGSTOP __SYS_SIGSTOP
#define SIGTERM __SYS_SIGTERM
#define SIGTSTP __SYS_SIGTSTP
#define SIGTTIN __SYS_SIGTTIN
#define SIGTTOU __SYS_SIGTTOU
#define SIGUSR1 __SYS_SIGUSR1
#define SIGUSR2 __SYS_SIGUSR2
#define SIGPOLL __SYS_SIGPOLL
#define SIGPROF __SYS_SIGPROF
#define SIGSYS __SYS_SIGSYS
#define SIGTRAP __SYS_SIGTRAP
#define SIGURG __SYS_SIGURG
#define SIGVTALRM __SYS_SIGVTALRM
#define SIGXCPU __SYS_SIGXCPU
#define SIGXFSZ __SYS_SIGXFSZ
#define SIGCOMP1 __SYS_SIGCOMP1
#define SIGCOMP2 __SYS_SIGCOMP2
#define SIGCOMP3 __SYS_SIGCOMP3
#define SIGRTMIN __SYS_SIGRTMIN
#define SIGRT_1 __SYS_SIGRT_1
#define SIGRT_2 __SYS_SIGRT_2
#define SIGRT_3 __SYS_SIGRT_3
#define SIGRT_4 __SYS_SIGRT_4
#define SIGRT_5 __SYS_SIGRT_5
#define SIGRT_6 __SYS_SIGRT_6
#define SIGRT_7 __SYS_SIGRT_7
#define SIGRT_8 __SYS_SIGRT_8
#define SIGRT_9 __SYS_SIGRT_9
#define SIGRT_10 __SYS_SIGRT_10
#define SIGRT_11 __SYS_SIGRT_11
#define SIGRT_12 __SYS_SIGRT_12
#define SIGRT_13 __SYS_SIGRT_13
#define SIGRT_14 __SYS_SIGRT_14
#define SIGRT_15 __SYS_SIGRT_15
#define SIGRT_16 __SYS_SIGRT_16
#define SIGRT_17 __SYS_SIGRT_17
#define SIGRT_18 __SYS_SIGRT_18
#define SIGRT_19 __SYS_SIGRT_19
#define SIGRT_20 __SYS_SIGRT_20
#define SIGRT_21 __SYS_SIGRT_21
#define SIGRT_22 __SYS_SIGRT_22
#define SIGRT_23 __SYS_SIGRT_23
#define SIGRT_24 __SYS_SIGRT_24
#define SIGRT_25 __SYS_SIGRT_25
#define SIGRT_26 __SYS_SIGRT_26
#define SIGRT_27 __SYS_SIGRT_27
#define SIGRT_28 __SYS_SIGRT_28
#define SIGRT_29 __SYS_SIGRT_29
#define SIGRT_30 __SYS_SIGRT_30
#define SIGRT_31 __SYS_SIGRT_31
#define SIGRTMAX __SYS_SIGRTMAX
#define SIGNAL_MAX __SYS_SIGNAL_MAX
#define SIG_TERM __SYS_SIG_TERM
// #define SIG_IGN __SYS_SIG_IGN
#define SIG_CORE __SYS_SIG_CORE
#define SIG_STOP __SYS_SIG_STOP
#define SIG_CONT __SYS_SIG_CONT
#define SIG_BLOCK __SYS_SIG_BLOCK
#define SIG_UNBLOCK __SYS_SIG_UNBLOCK
#define SIG_SETMASK __SYS_SIG_SETMASK
#define SA_NOCLDSTOP __SYS_SA_NOCLDSTOP
#define SA_ONSTACK __SYS_SA_ONSTACK
#define SA_RESETHAND __SYS_SA_RESETHAND
#define SA_RESTART __SYS_SA_RESTART
#define SA_SIGINFO __SYS_SA_SIGINFO
#define SA_NOCLDWAIT __SYS_SA_NOCLDWAIT
#define SA_NODEFER __SYS_SA_NODEFER
#define SS_ONSTACK
#define SS_DISABLE
#define MINSIGSTKSZ
#define SIGSTKSZ
#define SIG_ERR ((void (*)(int))__SYS_SIG_ERR)
#define SIG_DFL ((void (*)(int))__SYS_SIG_DFL)
#define SIG_IGN ((void (*)(int))__SYS_SIG_IGN)
#define SIGEV_NONE
#define SIGEV_SIGNAL
#define SIGEV_THREAD
typedef unsigned long sigset_t;
union sigval
{
int sival_int; /* Integer signal value. */
void *sival_ptr; /* Pointer signal value. */
};
#include <bits/signal.h>
#include <bits/types/signal.h>
typedef struct siginfo_t
{
@ -149,15 +45,6 @@ extern "C"
union sigval si_value; /* Signal value. */
} siginfo_t;
typedef struct sigevent
{
int sigev_notify; /* Notification type. */
int sigev_signo; /* Signal number. */
union sigval sigev_value; /* Signal value. */
void (*sigev_notify_function)(union sigval); /* Notification function. */
pthread_attr_t *sigev_notify_attributes; /* Notification attributes. */
} sigevent;
struct sigaction
{
void (*sa_handler)(int); /* Pointer to a signal-catching function or one of the SIG_IGN or SIG_DFL. */

View File

@ -21,15 +21,26 @@
#include <stdint.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <bits/socket.h>
typedef uint32_t socklen_t;
#ifndef __socklen_t_defined
#define __socklen_t_defined
typedef __UINT32_TYPE__ socklen_t;
#endif
#ifndef __sa_family_t_defined
#define __sa_family_t_defined
typedef unsigned int sa_family_t;
#endif
#ifndef __sockaddr_defined
#define __sockaddr_defined
struct sockaddr
{
sa_family_t sa_family;
char sa_data[14];
};
#endif
#define _SS_MAXSIZE 128
#define _SS_ALIGNSIZE (sizeof(int64_t))

View File

@ -30,10 +30,6 @@ extern "C"
#define restrict __restrict__
#endif // restrict
#ifndef export
#define export __attribute__((__visibility__("default")))
#endif // export
typedef long blkcnt_t;
typedef long blksize_t;

View File

@ -25,7 +25,7 @@ extern "C"
#include <bits/types/timespec.h>
#include <sys/types.h>
#include <signal.h>
#include <bits/types/signal.h>
#include <locale.h>
typedef struct tm

View File

@ -0,0 +1,21 @@
file(GLOB_RECURSE SYSDEPS_SOURCES ${SYSDEPS_PATH}/*.c ${SYSDEPS_GENERIC}/*.c)
file(GLOB_RECURSE INTERPRETER_FILES "${CMAKE_CURRENT_SOURCE_DIR}/*.c")
list(APPEND INTERPRETER_FILES ${SYSDEPS_SOURCES})
add_executable(ld.so ${INTERPRETER_FILES})
execute_process(COMMAND git rev-parse HEAD
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE GIT_COMMIT
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE)
if(GIT_COMMIT)
add_compile_definitions(LIBC_GIT_COMMIT="${GIT_COMMIT}")
endif()
add_compile_definitions(FENNIX_DYNAMIC_LOADER="1")
install(TARGETS ld.so DESTINATION lib)
target_compile_options(ld.so PRIVATE -fvisibility=hidden -fPIC)
target_link_options(ld.so PRIVATE -nostdlib -shared -fPIC -fPIE -fno-plt -Wl,-e,_dl_start)

View File

@ -1,40 +0,0 @@
default:
$(error Do not run this Makefile directly!)
OBJECT_NAME := ld.so
OUTPUT_DIR=$(WORKSPACE_DIR)/out/lib/
SYSROOT = --sysroot=$(WORKSPACE_DIR)/out/
S_SOURCES = $(shell find ./ -type f -name '*.S')
C_SOURCES = $(shell find ./ -type f -name '*.c')
CXX_SOURCES = $(shell find ./ -type f -name '*.cpp')
OBJ = ${S_SOURCES:.S=.o} ${C_SOURCES:.c=.o} ${CXX_SOURCES:.cpp=.o}
CFLAGS := -fvisibility=hidden -fPIC -I$(WORKSPACE_DIR)/out/include -DLIBC_GIT_COMMIT='"$(shell git rev-parse HEAD)"'
ifeq ($(DEBUG), 1)
CFLAGS += -DDEBUG -ggdb3 -O0 -fdiagnostics-color=always
endif
build: $(OBJECT_NAME)
$(OBJECT_NAME): $(OBJ)
$(info Linking $@)
$(CC) -nostdlib -shared -fPIC -fPIE -fno-plt -Wl,-soname,$(OBJECT_NAME) $(SYSROOT) $(OBJ) -o $(OBJECT_NAME)
cp $(OBJECT_NAME) $(OUTPUT_DIR)$(OBJECT_NAME)
%.o: %.c
$(info Compiling $<)
$(CC) $(CFLAGS) -std=c17 -c $< -o $@
%.o: %.cpp
$(info Compiling $<)
$(CC) $(CFLAGS) -std=c++20 -c $< -o $@
%.o: %.S
$(info Compiling $<)
$(AS) -c $< -o $@
clean:
rm -f $(OBJ) $(OBJECT_NAME)

View File

@ -15,8 +15,9 @@
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#include <fennix/syscalls.h>
#include <bits/libc.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <stdint.h>
#include <stddef.h>
#include <errno.h>
@ -39,7 +40,7 @@ MemoryBlock *memory_pool = NULL;
void *request_page(size_t size)
{
size_t aligned_size = (size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
void *addr = (void *)call_mmap(NULL, aligned_size, __SYS_PROT_READ | __SYS_PROT_WRITE, __SYS_MAP_ANONYMOUS | __SYS_MAP_PRIVATE, -1, 0);
void *addr = (void *)sysdep(MemoryMap)(NULL, aligned_size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
if ((intptr_t)addr < 0)
return NULL;
return addr;
@ -48,7 +49,7 @@ void *request_page(size_t size)
void free_page(void *addr, size_t size)
{
size_t aligned_size = (size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
call_munmap(addr, aligned_size);
sysdep(MemoryUnmap)(addr, aligned_size);
}
MemoryBlock *allocate_block(size_t slot_size)

View File

@ -15,7 +15,7 @@
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#include <fennix/syscalls.h>
#include <bits/libc.h>
#include <sys/types.h>
#include <stdint.h>
#include <stddef.h>

View File

@ -15,11 +15,14 @@
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#include <fennix/syscalls.h>
#include <bits/libc.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <inttypes.h>
#include <stddef.h>
#include <limits.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include "elf.h"
@ -167,9 +170,15 @@ __attribute__((noinline)) void *_dl_fixup(ElfInfo *Info, long RelIndex)
return ret;
}
#ifdef __fennix__
#include <fennix/syscalls.h>
#endif
int _dl_preload()
{
#ifdef __fennix__
call_api_version(0);
#endif
/* TODO: Do aditional checks for miscellaneous things */
@ -353,16 +362,16 @@ void ProcessNeededLibraries(Elf_Dyn *elem, ElfInfo *Info)
strcpy(fullLibPath, "/lib/");
strcat(fullLibPath, libPath);
/* TODO: more checks and also check environment variables */
if (call_access(fullLibPath, __SYS_F_OK) != 0)
if (sysdep(Access)(fullLibPath, F_OK) != 0)
{
printf("dl: Can't access %s\n", fullLibPath);
return;
}
int fd = call_open(fullLibPath, __SYS_O_RDONLY, 0644);
int fd = sysdep(Open)(fullLibPath, O_RDONLY, 0644);
int status = LoadElf(fd, fullLibPath, &info);
elem->d_un.d_ptr = (uintptr_t)info; /* if LoadElf fails, info will still be NULL */
call_close(fd);
sysdep(Close)(fd);
if (status < 0) /* announce that LoadElf failed */
printf("dl: Can't load %s\n", fullLibPath);
}
@ -431,7 +440,7 @@ int LoadElfPhdrDYN(int fd, ElfInfo *Info)
for (Elf_Half i = 0; i < header.e_phnum; i++)
{
ssize_t read = call_pread(fd, &phdr, sizeof(Elf_Phdr), header.e_phoff + (header.e_phentsize * i));
ssize_t read = sysdep(PRead)(fd, &phdr, sizeof(Elf_Phdr), header.e_phoff + (header.e_phentsize * i));
if (read != sizeof(Elf_Phdr))
{
printf("dl: Can't read program header %d\n", i);
@ -450,23 +459,23 @@ int LoadElfPhdrDYN(int fd, ElfInfo *Info)
int mmapProt = 0;
if (phdr.p_flags & PF_X)
mmapProt |= __SYS_PROT_EXEC;
mmapProt |= PROT_EXEC;
if (phdr.p_flags & PF_W)
mmapProt |= __SYS_PROT_WRITE;
mmapProt |= PROT_WRITE;
if (phdr.p_flags & PF_R)
mmapProt |= __SYS_PROT_READ;
mmapProt |= PROT_READ;
off_t sectionOffset = ALIGN_DOWN(phdr.p_vaddr, phdr.p_align);
size_t sectionSize = ALIGN_UP(phdr.p_memsz + (phdr.p_vaddr - sectionOffset), phdr.p_align);
uintptr_t section = call_mmap(base + sectionOffset,
sectionSize, mmapProt,
__SYS_MAP_ANONYMOUS | __SYS_MAP_PRIVATE | __SYS_MAP_FIXED,
-1, 0);
uintptr_t section = (uintptr_t)sysdep(MemoryMap)((void *)(base + sectionOffset),
sectionSize, mmapProt,
MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED,
-1, 0);
sectionOffset = phdr.p_vaddr - ALIGN_DOWN(phdr.p_vaddr, phdr.p_align);
if (phdr.p_filesz > 0)
{
ssize_t read = call_pread(fd, section + sectionOffset, phdr.p_filesz, phdr.p_offset);
ssize_t read = sysdep(PRead)(fd, (void *)(section + sectionOffset), phdr.p_filesz, phdr.p_offset);
if (read != phdr.p_filesz)
{
printf("dl: Can't read segment %d in PT_LOAD\n", i);
@ -495,15 +504,15 @@ int LoadElfPhdrDYN(int fd, ElfInfo *Info)
{
int mmapProt = 0;
if (phdr.p_flags & PF_X)
mmapProt |= __SYS_PROT_EXEC;
mmapProt |= PROT_EXEC;
if (phdr.p_flags & PF_W)
mmapProt |= __SYS_PROT_WRITE;
mmapProt |= PROT_WRITE;
if (phdr.p_flags & PF_R)
mmapProt |= __SYS_PROT_READ;
mmapProt |= PROT_READ;
dynamicTable = (Elf_Dyn *)call_mmap(0, ALIGN_UP(phdr.p_memsz, phdr.p_align),
mmapProt, __SYS_MAP_ANONYMOUS | __SYS_MAP_PRIVATE | __SYS_MAP_FIXED,
-1, 0);
dynamicTable = (Elf_Dyn *)sysdep(MemoryMap)(0, ALIGN_UP(phdr.p_memsz, phdr.p_align),
mmapProt, MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED,
-1, 0);
if ((intptr_t)dynamicTable <= 0)
{
@ -511,7 +520,7 @@ int LoadElfPhdrDYN(int fd, ElfInfo *Info)
return (int)(uintptr_t)dynamicTable;
}
read = call_pread(fd, dynamicTable, phdr.p_memsz, phdr.p_offset);
read = sysdep(PRead)(fd, dynamicTable, phdr.p_memsz, phdr.p_offset);
if (read != phdr.p_memsz)
{
printf("dl: Can't read PT_DYNAMIC\n");
@ -598,7 +607,7 @@ int LoadElf(int fd, char *Path, ElfInfo **Out)
}
Elf_Ehdr header;
call_pread(fd, &header, sizeof(Elf_Ehdr), 0);
sysdep(PRead)(fd, &header, sizeof(Elf_Ehdr), 0);
int status = CheckElfEhdr(&header, Path);
if (status != 0)
@ -606,11 +615,11 @@ int LoadElf(int fd, char *Path, ElfInfo **Out)
info = AllocateLib();
info->Header = header;
info->Path = (char *)call_mmap(0,
ALIGN_UP(strlen(Path) + 1, 0x1000 /* TODO: get page size from kernel */),
__SYS_PROT_READ,
__SYS_MAP_ANONYMOUS | __SYS_MAP_PRIVATE,
-1, 0);
info->Path = (char *)sysdep(MemoryMap)(0,
ALIGN_UP(strlen(Path) + 1, 0x1000 /* TODO: get page size from kernel */),
PROT_READ,
MAP_ANONYMOUS | MAP_PRIVATE,
-1, 0);
if ((intptr_t)info->Path <= 0)
{
printf("dl: Can't allocate memory for path\n");
@ -648,7 +657,7 @@ int LoadElf(int fd, char *Path, ElfInfo **Out)
if (status < 0)
{
call_munmap((uintptr_t)info->Path, ALIGN_UP(strlen(Path) + 1, 0x1000));
sysdep(MemoryUnmap)((void *)info->Path, ALIGN_UP(strlen(Path) + 1, 0x1000));
FreeLib(info);
return status;
}
@ -956,18 +965,18 @@ int _dl_main(int argc, char *argv[], char *envp[])
{
char *path = argv[0];
ElfInfo *info = NULL;
if (call_access(path, __SYS_F_OK) < 0)
if (sysdep(Access)(path, F_OK) < 0)
{
printf("dl: Can't access file %s\n", path);
return -EACCES;
}
int fd = call_open(path, __SYS_O_RDONLY, 0644);
int fd = sysdep(Open)(path, O_RDONLY, 0644);
int status = LoadElf(fd, path, &info);
if (status < 0)
{
printf("%s: Can't load ELF file\n", path);
call_close(fd);
sysdep(Close)(fd);
return status;
}
@ -975,11 +984,11 @@ int _dl_main(int argc, char *argv[], char *envp[])
if (status < 0)
{
printf("%s: Can't relocate ELF file\n", path);
call_close(fd);
sysdep(Close)(fd);
return status;
}
call_close(fd);
sysdep(Close)(fd);
Elf_Addr entry = info->BaseAddress + info->Header.e_entry;
return ((int (*)(int, char *[], char *[]))entry)(argc, argv, envp);
}

View File

@ -1,4 +1,4 @@
/* nanoprintf v0.5.3: a tiny embeddable printf replacement written in C.
/* nanoprintf v0.5.4: a tiny embeddable printf replacement written in C.
https://github.com/charlesnicholson/nanoprintf
charles.nicholson+nanoprintf@gmail.com
dual-licensed under 0bsd and unlicense, take your pick. see eof for details. */
@ -336,6 +336,7 @@ static int npf_parse_format_spec(char const *format, npf_format_spec_t *out_spec
}
#if NANOPRINTF_USE_FIELD_WIDTH_FORMAT_SPECIFIERS == 1
out_spec->field_width = 0;
out_spec->field_width_opt = NPF_FMT_SPEC_OPT_NONE;
if (*cur == '*')
{
@ -344,7 +345,6 @@ static int npf_parse_format_spec(char const *format, npf_format_spec_t *out_spec
}
else
{
out_spec->field_width = 0;
while ((*cur >= '0') && (*cur <= '9'))
{
out_spec->field_width_opt = NPF_FMT_SPEC_OPT_LITERAL;

View File

@ -17,7 +17,8 @@
#include <stddef.h>
#include <stdarg.h>
#include <fennix/syscalls.h>
#include <bits/libc.h>
#include <sys/mman.h>
#include "elf.h"
#include "misc.h"
@ -31,7 +32,7 @@ void flush_buffer()
{
if (print_buffer_offset > 0)
{
call_write(1, print_buffer, print_buffer_offset);
sysdep(Write)(1, print_buffer, print_buffer_offset);
print_buffer_offset = 0;
}
}
@ -45,11 +46,11 @@ void print_wrapper(int c, void *)
void __init_print_buffer()
{
print_buffer = (char *)call_mmap(0,
0x1000,
__SYS_PROT_READ | __SYS_PROT_WRITE,
__SYS_MAP_PRIVATE | __SYS_MAP_ANONYMOUS,
-1, 0);
print_buffer = (char *)sysdep(MemoryMap)(0,
0x1000,
PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS,
-1, 0);
print_buffer_size = 0x1000;
print_buffer_offset = 0;
}
@ -58,7 +59,7 @@ void __fini_print_buffer()
{
flush_buffer();
if (print_buffer != NULL)
call_munmap(print_buffer, 0x1000);
sysdep(MemoryUnmap)(print_buffer, 0x1000);
print_buffer = NULL;
}

View File

@ -15,7 +15,7 @@
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#include <fennix/syscalls.h>
#include <bits/libc.h>
// const char __interp[] __attribute__((section(".interp"))) = "/boot/fennix.elf";
@ -97,54 +97,11 @@ const struct
void __init_print_buffer();
void __fini_print_buffer();
__attribute__((naked, used, no_stack_protector)) void _start()
{
#if defined(__amd64__)
__asm__(
"xorq %rbp, %rbp\n" /* Clear rbp */
"push %rdi\n"
"push %rsi\n"
"push %rdx\n"
"push %rcx\n"
"push %r8\n"
"push %r9\n"
"call __init_print_buffer\n" /* Call __init_print_buffer */
"call _dl_preload\n" /* Call _dl_preload */
"movl %eax, %edi\n" /* Move return value to edi */
"cmp $0, %edi\n" /* Check if return value is 0 */
"jne _exit\n" /* If not, jump to _exit */
"pop %r9\n"
"pop %r8\n"
"pop %rcx\n"
"pop %rdx\n"
"pop %rsi\n"
"pop %rdi\n"
"call main\n" /* Call _dl_main */
"movl %eax, %edi\n" /* Move return value to edi */
"call _exit\n"); /* Call _exit */
#elif defined(__i386__)
#warning "i386 _start not implemented"
#elif defined(__arm__)
#warning "arm _start not implemented"
#elif defined(__aarch64__)
#warning "aarch64 _start not implemented"
#else
#error "Unsupported architecture"
#endif
}
__attribute__((no_stack_protector)) _Noreturn void _exit(int status)
{
__fini_print_buffer();
call_exit(status);
/* At this point, the program *SHOULD* have exited. */
#if defined(__amd64__) || defined(__i386__)
__asm__("ud2\n");
#endif
sysdep(Exit)(status);
/* At this point, the program *SHOULD* have exited. */
__builtin_unreachable();
}

View File

@ -0,0 +1,5 @@
cmake_minimum_required(VERSION 3.10)
project(FennixStandardLibraries)
add_subdirectory(libm)
add_subdirectory(libstdc++)

View File

@ -0,0 +1,15 @@
cmake_minimum_required(VERSION 3.10)
project(FennixMathLibrary)
set(SOURCES libm.c)
add_library(m STATIC ${SOURCES})
add_library(m_shared SHARED ${SOURCES})
target_link_options(m_shared PRIVATE -nostdlib)
set_target_properties(m_shared PROPERTIES OUTPUT_NAME "m")
install(TARGETS m m_shared
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
PUBLIC_HEADER DESTINATION include)

View File

@ -0,0 +1,15 @@
cmake_minimum_required(VERSION 3.10)
project(FennixStandardC++Library)
set(SOURCES libstdc++.cpp)
add_library(stdc++ STATIC ${SOURCES})
add_library(stdc++_shared SHARED ${SOURCES})
target_link_options(stdc++_shared PRIVATE -nostdlib)
set_target_properties(stdc++_shared PROPERTIES OUTPUT_NAME "stdc++")
install(TARGETS stdc++ stdc++_shared
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
PUBLIC_HEADER DESTINATION include)

View File

@ -0,0 +1,18 @@
cmake_minimum_required(VERSION 3.10)
project(FennixRuntime)
if(NOT DEFINED TARGET_OS)
message(FATAL_ERROR "TARGET_OS is not set")
endif()
if(NOT DEFINED TARGET_ARCH)
message(FATAL_ERROR "TARGET_ARCH is not set")
endif()
set(RUNTIME_DIR "${CMAKE_CURRENT_SOURCE_DIR}/${TARGET_OS}/${TARGET_ARCH}")
if(NOT EXISTS "${RUNTIME_DIR}/CMakeLists.txt")
message(FATAL_ERROR "No runtime support for ${TARGET_OS}/${TARGET_ARCH}")
endif()
add_subdirectory(${RUNTIME_DIR})

View File

@ -1,27 +0,0 @@
default:
$(error Do not run this Makefile directly!)
S_SOURCES = $(shell find ./ -type f -name '*.S')
C_SOURCES = $(shell find ./ -type f -name '*.c')
CXX_SOURCES = $(shell find ./ -type f -name '*.cpp')
OBJ = ${S_SOURCES:.S=.o} ${C_SOURCES:.c=.o} ${CXX_SOURCES:.cpp=.o}
CRTBEGIN_PATH = $(shell $(CC) -print-file-name=crtbegin.o)
CRTEND_PATH = $(shell $(CC) -print-file-name=crtend.o)
CRTI_PATH = $(shell $(CC) -print-file-name=crti.o)
CRTN_PATH = $(shell $(CC) -print-file-name=crtn.o)
build: $(OBJ)
cp $^ ../../out/lib/
cp $(CRTBEGIN_PATH) $(CRTEND_PATH) $(CRTI_PATH) $(CRTN_PATH) $(WORKSPACE_DIR)/out/lib/
%.o: %.c
$(info Compiling $<)
$(CC) -nostdlib -std=c17 -DLIBC_GIT_COMMIT='"$(shell git rev-parse HEAD)"' -c $< -o $@
%.o: %.S
$(info Compiling $<)
$(AS) -c $< -o $@
clean:
rm -f $(OBJ)

View File

@ -0,0 +1,34 @@
cmake_minimum_required(VERSION 3.10)
project(FennixRuntime_${TARGET_OS}_${TARGET_ARCH})
find_program(COMPILER_PATH NAMES $ENV{CC} gcc REQUIRED)
set(LIB_OUTPUT_DIR "${CMAKE_INSTALL_PREFIX}/lib")
file(MAKE_DIRECTORY ${LIB_OUTPUT_DIR})
add_custom_target(copy_crt_files ALL
COMMAND ${COMPILER_PATH} -print-file-name=libgcc.a | xargs cp -t ${LIB_OUTPUT_DIR}
COMMAND ${COMPILER_PATH} -print-file-name=crtbegin.o | xargs cp -t ${LIB_OUTPUT_DIR}
COMMAND ${COMPILER_PATH} -print-file-name=crtend.o | xargs cp -t ${LIB_OUTPUT_DIR}
COMMAND ${COMPILER_PATH} -print-file-name=crti.o | xargs cp -t ${LIB_OUTPUT_DIR}
COMMAND ${COMPILER_PATH} -print-file-name=crtn.o | xargs cp -t ${LIB_OUTPUT_DIR}
COMMENT "Copying CRT files"
)
file(GLOB CRT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.c")
set(OBJECT_FILES "")
foreach(source ${CRT_SOURCES})
get_filename_component(name ${source} NAME_WE)
set(obj "${CMAKE_BINARY_DIR}/${name}.o")
add_custom_command(
OUTPUT ${obj}
COMMAND ${COMPILER_PATH} -c ${source} -o ${obj}
DEPENDS ${source}
)
list(APPEND OBJECT_FILES ${obj})
endforeach()
if(OBJECT_FILES)
add_custom_target(crt_objects ALL DEPENDS ${OBJECT_FILES})
install(FILES ${OBJECT_FILES} DESTINATION lib)
endif()

View File

@ -0,0 +1,43 @@
cmake_minimum_required(VERSION 3.10)
project(FennixRuntime_${TARGET_OS}_${TARGET_ARCH})
find_program(COMPILER_PATH NAMES $ENV{CC} gcc REQUIRED)
set(BUILD_OUTPUT_DIR "${CMAKE_BINARY_DIR}/lib")
set(INSTALL_OUTPUT_DIR "${CMAKE_INSTALL_PREFIX}/lib")
file(MAKE_DIRECTORY ${BUILD_OUTPUT_DIR})
execute_process(COMMAND ${COMPILER_PATH} -print-file-name=crtbegin.o OUTPUT_VARIABLE CRTBEGIN_PATH OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(COMMAND ${COMPILER_PATH} -print-file-name=crtend.o OUTPUT_VARIABLE CRTEND_PATH OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(COMMAND ${COMPILER_PATH} -print-file-name=crti.o OUTPUT_VARIABLE CRTI_PATH OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(COMMAND ${COMPILER_PATH} -print-file-name=crtn.o OUTPUT_VARIABLE CRTN_PATH OUTPUT_STRIP_TRAILING_WHITESPACE)
add_custom_target(copy_crt_files ALL
COMMAND cp ${CRTBEGIN_PATH} ${CRTEND_PATH} ${CRTI_PATH} ${CRTN_PATH} ${BUILD_OUTPUT_DIR}
COMMENT "Copying CRT files"
)
file(GLOB CRT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.c")
set(OBJECT_FILES "")
foreach(source ${CRT_SOURCES})
get_filename_component(name ${source} NAME_WE)
set(obj "${BUILD_OUTPUT_DIR}/${name}.o")
add_custom_command(
OUTPUT ${obj}
COMMAND ${COMPILER_PATH} -c ${source} -o ${obj}
DEPENDS ${source}
)
list(APPEND OBJECT_FILES ${obj})
endforeach()
if(OBJECT_FILES)
add_custom_target(crt_objects ALL DEPENDS ${OBJECT_FILES})
endif()
install(FILES ${BUILD_OUTPUT_DIR}/crtbegin.o ${BUILD_OUTPUT_DIR}/crtend.o ${BUILD_OUTPUT_DIR}/crti.o ${BUILD_OUTPUT_DIR}/crtn.o
DESTINATION lib
)
install(FILES ${OBJECT_FILES} DESTINATION lib)

View File

@ -0,0 +1,33 @@
file(GLOB_RECURSE SRC_FILES ${CMAKE_CURRENT_SOURCE_DIR}/*.c ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
file(GLOB_RECURSE SYSDEPS_SOURCES ${SYSDEPS_PATH}/*.c ${SYSDEPS_GENERIC}/*.c ${SYSDEPS_PATH}/*.cpp ${SYSDEPS_GENERIC}/*.cpp)
list(APPEND SRC_FILES ${SYSDEPS_SOURCES})
add_library(libc_obj OBJECT ${SRC_FILES})
set_target_properties(libc_obj PROPERTIES POSITION_INDEPENDENT_CODE 1)
message(STATUS "Adding sysdeps sources: ${SYSDEPS_SOURCES}")
add_library(libc_shared SHARED $<TARGET_OBJECTS:libc_obj>)
set_target_properties(libc_shared PROPERTIES OUTPUT_NAME "c")
target_compile_definitions(libc_shared PRIVATE PROGRAM_VERSION="${PROJECT_VERSION}")
execute_process(
COMMAND git rev-parse HEAD
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE GIT_COMMIT
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE
)
if(GIT_COMMIT)
target_compile_definitions(libc_shared PRIVATE LIBC_GIT_COMMIT="${GIT_COMMIT}")
endif()
target_compile_options(libc_shared PRIVATE -fvisibility=hidden -fPIC)
target_link_options(libc_shared PRIVATE -nostdlib -shared -fPIC -fPIE -e _start -Wl,-soname,libc.so -lgcc)
add_library(libc_static STATIC $<TARGET_OBJECTS:libc_obj>)
set_target_properties(libc_static PROPERTIES OUTPUT_NAME "c")
target_compile_options(libc_static PRIVATE -fvisibility=hidden -fPIC)
install(TARGETS libc_shared libc_static DESTINATION lib)

View File

@ -1,48 +0,0 @@
default:
$(error Do not run this Makefile directly!)
DYNAMIC_NAME := libc.so
STATIC_NAME := libc.a
OUTPUT_DIR=$(WORKSPACE_DIR)/out/lib/
SYSROOT = --sysroot=$(WORKSPACE_DIR)/out/
S_SOURCES = $(shell find ./ -type f -name '*.S')
C_SOURCES = $(shell find ./ -type f -name '*.c')
CXX_SOURCES = $(shell find ./ -type f -name '*.cpp')
OBJ = ${S_SOURCES:.S=.o} ${C_SOURCES:.c=.o} ${CXX_SOURCES:.cpp=.o}
CFLAGS := -fvisibility=hidden -fPIC -I../include -I$(WORKSPACE_DIR)/out/include -DLIBC_GIT_COMMIT='"$(shell git rev-parse HEAD)"'
ifeq ($(DEBUG), 1)
CFLAGS += -DDEBUG -ggdb3 -O0 -fdiagnostics-color=always
endif
build: $(DYNAMIC_NAME) $(STATIC_NAME)
.PHONY: $(DYNAMIC_NAME) $(STATIC_NAME)
$(DYNAMIC_NAME): $(OBJ)
$(info Linking $@)
$(CC) -nostdlib -shared -fPIC -fPIE -e _start -Wl,-soname,$(DYNAMIC_NAME) $(SYSROOT) $(OBJ) -o $(DYNAMIC_NAME) -lgcc
cp $(DYNAMIC_NAME) $(OUTPUT_DIR)$(DYNAMIC_NAME)
$(STATIC_NAME): $(OBJ)
$(info Linking $@)
$(AR) -rcs $(STATIC_NAME) $(OBJ)
cp $(STATIC_NAME) $(OUTPUT_DIR)$(STATIC_NAME)
%.o: %.c
$(info Compiling $<)
$(CC) $(CFLAGS) -std=c17 -c $< -o $@
%.o: %.cpp
$(info Compiling $<)
$(CC) $(CFLAGS) -std=c++20 -c $< -o $@
%.o: %.S
$(info Compiling $<)
$(AS) -c $< -o $@
clean:
rm -f $(OBJ) $(DYNAMIC_NAME) $(STATIC_NAME)

View File

@ -15,8 +15,7 @@
along with Fennix Userspace. If not, see <https://www.gnu.org/licenses/>.
*/
#include <fennix/syscalls.h>
#include <bits/libc.h>
#include <stdio.h>
int __init_pthread(void);
@ -34,7 +33,7 @@ __attribute__((visibility("default"))) void _exit(int Code)
{
fflush(stdout);
fflush(stderr);
call_exit(Code);
sysdep(Exit)(Code);
while (1)
;
}

View File

@ -15,8 +15,6 @@
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#include "../runtime/crt1.c"
const char __interp[] __attribute__((section(".interp"))) = "/lib/ld.so";
#ifndef LIBC_GIT_COMMIT
@ -47,6 +45,23 @@ const char __interp[] __attribute__((section(".interp"))) = "/lib/ld.so";
CONVERT_TO_BYTE(hex[36], hex[37]), \
CONVERT_TO_BYTE(hex[38], hex[39])}
typedef struct Elf_Nhdr
{
__UINT32_TYPE__ n_namesz;
__UINT32_TYPE__ n_descsz;
__UINT32_TYPE__ n_type;
char n_name[];
} __attribute__((packed)) Elf_Nhdr;
/* These are declared in GNU ld */
enum
{
NT_FNX_ABI_TAG = 1,
NT_FNX_VERSION = 2,
NT_FNX_BUILD_ID = 3,
NT_FNX_ARCH = 4
};
const struct
{
Elf_Nhdr header;

View File

@ -15,6 +15,7 @@
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#include <bits/libc.h>
#include <arpa/inet.h>
#include <stdint.h>

View File

@ -15,10 +15,15 @@
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#include <bits/libc.h>
#include <sys/types.h>
#include <pthread.h>
#include <errno.h>
#ifndef EOK
#define EOK 0
#endif
__iptr __check_errno(__iptr status, __iptr err)
{
if ((int)status >= EOK)
@ -37,9 +42,6 @@ export char *strerror(int errnum)
if (errnum < 0)
errnum = -errnum;
if (errnum > __ERRNO_MAX)
return (char *)"Not a valid error number";
switch (errnum)
{
case EOK:

View File

@ -15,8 +15,8 @@
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#include <bits/libc.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
@ -37,7 +37,7 @@ export int open(const char *path, int oflag, ...)
mode = va_arg(args, mode_t);
va_end(args);
}
return __check_errno(call_open(path, oflag, mode), -1);
return __check_errno(sysdep(Open)(path, oflag, mode), -1);
}
export int openat(int fd, const char *path, int oflag, ...);

View File

@ -15,6 +15,7 @@
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#include <bits/libc.h>
#include <sys/types.h>
#include <fenv.h>

View File

@ -20,6 +20,7 @@
#include <float.h>
#include <errno.h>
#include <inttypes.h>
#include <bits/libc.h>
#include <fenv.h>
export int signgam;

View File

@ -15,6 +15,7 @@
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#include <bits/libc.h>
#include <pthread.h>
#include <errno.h>

View File

@ -15,13 +15,14 @@
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#include <bits/libc.h>
#include <signal.h>
#include <errno.h>
#include <stdio.h>
export int kill(pid_t pid, int sig)
{
return call_kill(pid, sig);
return sysdep(Kill)(pid, sig);
}
export int killpg(pid_t, int);

View File

@ -19,7 +19,8 @@
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fennix/syscalls.h>
#include <bits/libc.h>
#include <fcntl.h>
#include "../print/printf.h"
struct _IO_FILE *_i_open_files[256];
@ -74,7 +75,7 @@ export int fclose(FILE *stream)
if (stream->buffer)
free(stream->buffer);
call_close(stream->fd);
sysdep(Close)(stream->fd);
_i_open_files[stream->fd] = NULL;
free(stream);
return 0;
@ -105,7 +106,7 @@ export int fflush(FILE *stream)
{
if (stream->buffer_pos > 0)
{
ssize_t written = call_write(stream->fd, stream->buffer, stream->buffer_pos);
ssize_t written = sysdep(Write)(stream->fd, stream->buffer, stream->buffer_pos);
if (written < 0)
{
stream->error = 1;
@ -129,7 +130,7 @@ export int fgetc(FILE *stream)
if (stream->buffer_pos >= stream->buffer_size)
{
int res = call_read(stream->fd, stream->buffer, 4096);
int res = sysdep(Read)(stream->fd, stream->buffer, 4096);
if (res <= 0)
{
if (res == 0)
@ -180,33 +181,33 @@ export FILE *fopen(const char *restrict pathname, const char *restrict mode)
mode_t perm = 0;
if (strcmp(mode, "r") == 0)
flags = __SYS_O_RDONLY;
flags = O_RDONLY;
else if (strcmp(mode, "r+") == 0)
flags = __SYS_O_RDWR;
flags = O_RDWR;
else if (strcmp(mode, "w") == 0)
{
flags = __SYS_O_WRONLY | __SYS_O_CREAT | __SYS_O_TRUNC;
flags = O_WRONLY | O_CREAT | O_TRUNC;
perm = 0644;
}
else if (strcmp(mode, "w+") == 0)
{
flags = __SYS_O_RDWR | __SYS_O_CREAT | __SYS_O_TRUNC;
flags = O_RDWR | O_CREAT | O_TRUNC;
perm = 0644;
}
else if (strcmp(mode, "a") == 0)
{
flags = __SYS_O_WRONLY | __SYS_O_CREAT | __SYS_O_APPEND;
flags = O_WRONLY | O_CREAT | O_APPEND;
perm = 0644;
}
else if (strcmp(mode, "a+") == 0)
{
flags = __SYS_O_RDWR | __SYS_O_CREAT | __SYS_O_APPEND;
flags = O_RDWR | O_CREAT | O_APPEND;
perm = 0644;
}
else
return NULL;
int fd = call_open(pathname, flags, perm);
int fd = sysdep(Open)(pathname, flags, perm);
if (fd < 0)
return NULL;
@ -274,7 +275,7 @@ export size_t fread(void *restrict ptr, size_t size, size_t nitems, FILE *restri
{
if (stream->buffer_pos >= stream->buffer_size)
{
int res = call_read(stream->fd, stream->buffer, stream->buffer_size);
int res = sysdep(Read)(stream->fd, stream->buffer, stream->buffer_size);
if (res <= 0)
{
if (res == 0)
@ -305,7 +306,7 @@ export int fscanf(FILE *restrict, const char *restrict, ...);
export int fseek(FILE *stream, long offset, int whence)
{
int res = call_seek(stream->fd, offset, whence);
int res = sysdep(Seek)(stream->fd, offset, whence);
if (res < 0)
{
stream->error = 1;
@ -321,7 +322,7 @@ export int fsetpos(FILE *, const fpos_t *);
export long ftell(FILE *stream)
{
return call_tell(stream->fd);
return sysdep(Tell)(stream->fd);
}
export off_t ftello(FILE *);
@ -347,7 +348,7 @@ export size_t fwrite(const void *restrict ptr, size_t size, size_t nitems, FILE
if (stream->buffer_pos == stream->buffer_size)
{
if (call_write(stream->fd, stream->buffer, stream->buffer_size) != stream->buffer_size)
if (sysdep(Write)(stream->fd, stream->buffer, stream->buffer_size) != stream->buffer_size)
{
stream->error = 1;
break;

View File

@ -17,7 +17,7 @@
#include <sys/types.h>
#include <string.h>
#include <fennix/syscalls.h>
#include <bits/libc.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>

View File

@ -16,7 +16,7 @@
*/
#include <sys/ioctl.h>
#include <fennix/syscalls.h>
#include <bits/libc.h>
#include <stdarg.h>
#include <errno.h>
@ -27,6 +27,6 @@ export int ioctl(int fd, unsigned long op, ...)
va_start(args, op);
arg = va_arg(args, void *);
va_end(args);
int ret = call_ioctl(fd, op, arg);
int ret = sysdep(IOControl)(fd, op, arg);
return __check_errno(ret, -1);
}

View File

@ -16,7 +16,7 @@
*/
#include <sys/mman.h>
#include <fennix/syscalls.h>
#include <bits/libc.h>
#include <errno.h>
export int mlock(const void *, size_t);
@ -24,12 +24,12 @@ export int mlockall(int);
export void *mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off)
{
return (void *)__check_errno((__iptr)call_mmap(addr, len, prot, flags, fildes, off), (__iptr)MAP_FAILED);
return (void *)__check_errno((__iptr)sysdep(MemoryMap)(addr, len, prot, flags, fildes, off), (__iptr)MAP_FAILED);
}
export int mprotect(void *addr, size_t len, int prot)
{
return __check_errno(call_mprotect(addr, len, prot), -1);
return __check_errno(sysdep(MemoryProtect)(addr, len, prot), -1);
}
export int msync(void *, size_t, int);
@ -38,7 +38,7 @@ export int munlockall(void);
export int munmap(void *addr, size_t len)
{
return __check_errno(call_munmap(addr, len), -1);
return __check_errno(sysdep(MemoryUnmap)(addr, len), -1);
}
export int posix_madvise(void *, size_t, int);

View File

@ -17,23 +17,23 @@
#include <sys/socket.h>
#include <errno.h>
#include <fennix/syscalls.h>
#include <bits/libc.h>
export int accept(int socket, struct sockaddr *restrict address, socklen_t *restrict address_len)
{
return __check_errno(call_accept(socket, address, address_len), -1);
return __check_errno(sysdep(Accept)(socket, address, address_len), -1);
}
export int accept4(int socket, struct sockaddr *restrict address, socklen_t *restrict address_len, int flag);
export int bind(int socket, const struct sockaddr *address, socklen_t address_len)
{
return __check_errno(call_bind(socket, address, address_len), -1);
return __check_errno(sysdep(Bind)(socket, address, address_len), -1);
}
export int connect(int socket, const struct sockaddr *address, socklen_t address_len)
{
return __check_errno(call_connect(socket, address, address_len), -1);
return __check_errno(sysdep(Connect)(socket, address, address_len), -1);
}
export int getpeername(int, struct sockaddr *restrict, socklen_t *restrict);
@ -42,7 +42,7 @@ export int getsockopt(int, int, int, void *restrict, socklen_t *restrict);
export int listen(int socket, int backlog)
{
return __check_errno(call_listen(socket, backlog), -1);
return __check_errno(sysdep(Listen)(socket, backlog), -1);
}
export ssize_t recv(int, void *, size_t, int);
@ -57,7 +57,7 @@ export int sockatmark(int);
export int socket(int domain, int type, int protocol)
{
return __check_errno(call_socket(domain, type, protocol), -1);
return __check_errno(sysdep(Socket)(domain, type, protocol), -1);
}
export int socketpair(int, int, int, int[2]);

View File

@ -15,6 +15,7 @@
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#include <bits/libc.h>
#include <sys/stat.h>
#include <errno.h>
#include <stdio.h>
@ -31,7 +32,7 @@ export int fstat(int fildes, struct stat *buf)
return -1;
}
return __check_errno(call_fstat(fildes, buf), -1);
return __check_errno(sysdep(FStat)(fildes, buf), -1);
}
export int fstatat(int fd, const char *restrict path, struct stat *restrict buf, int flag)
@ -58,12 +59,12 @@ export int lstat(const char *restrict path, struct stat *restrict buf)
return -1;
}
return __check_errno(call_lstat(path, buf), -1);
return __check_errno(sysdep(LStat)(path, buf), -1);
}
export int mkdir(const char *path, mode_t mode)
{
return __check_errno(call_mkdir(path, mode), -1);
return __check_errno(sysdep(MakeDirectory)(path, mode), -1);
}
export int mkdirat(int fd, const char *path, mode_t mode)
@ -85,7 +86,7 @@ export int stat(const char *restrict path, struct stat *restrict buf)
return -1;
}
return __check_errno(call_stat(path, buf), -1);
return __check_errno(sysdep(Stat)(path, buf), -1);
}
export mode_t umask(mode_t);

View File

@ -21,7 +21,7 @@
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <fennix/syscalls.h>
#include <bits/libc.h>
export int uname(struct utsname *name)
{
@ -31,16 +31,8 @@ export int uname(struct utsname *name)
return -1;
}
struct kutsname kname;
int result = call_uname(&kname);
if (result == 0)
{
strcpy(name->sysname, kname.sysname);
strcpy(name->release, kname.release);
strcpy(name->version, kname.version);
strcpy(name->machine, kname.machine);
}
else
int result = sysdep(UnixName)(name);
if (result != 0)
{
errno = result;
return -1;

View File

@ -16,7 +16,7 @@
*/
#include <sys/wait.h>
#include <fennix/syscalls.h>
#include <bits/libc.h>
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
@ -34,5 +34,5 @@ export int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options)
export pid_t waitpid(pid_t pid, int *stat_loc, int options)
{
return __check_errno(call_waitpid(pid, stat_loc, options), -1);
return __check_errno(sysdep(WaitProcessID)(pid, stat_loc, options), -1);
}

View File

@ -15,6 +15,7 @@
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#include <bits/libc.h>
#include <sys/ioctl.h>
#include <termios.h>
#include <errno.h>

View File

@ -22,7 +22,7 @@
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <fennix/syscalls.h>
#include <bits/libc.h>
#include <fcntl.h>
export char *optarg;
@ -44,7 +44,7 @@ export int chown(const char *, uid_t, gid_t);
export int close(int fildes)
{
return __check_errno(call_close(fildes), -1);
return __check_errno(sysdep(Close)(fildes), -1);
}
export size_t confstr(int, char *, size_t);
@ -130,7 +130,7 @@ export int execv(const char *path, char *const argv[])
export int execve(const char *path, char *const argv[], char *const envp[])
{
return __check_errno(call_execve(path, argv, envp), -1);
return __check_errno(sysdep(Execve)(path, argv, envp), -1);
}
export int execvp(const char *file, char *const argv[])
@ -167,7 +167,7 @@ export int fdatasync(int);
export pid_t fork(void)
{
return __check_errno(call_fork(), -1);
return __check_errno(sysdep(Fork)(), -1);
}
export long int fpathconf(int, int);
@ -225,12 +225,12 @@ export pid_t getpgrp(void);
export pid_t getpid(void)
{
return call_getpid();
return sysdep(GetProcessID)();
}
export pid_t getppid(void)
{
return call_getppid();
return sysdep(GetParentProcessID)();
}
export pid_t getsid(pid_t);
@ -261,19 +261,19 @@ export int pipe(int[2]);
export ssize_t pread(int fildes, void *buf, size_t nbyte, off_t offset)
{
return __check_errno(call_pread(fildes, buf, nbyte, offset), -1);
return __check_errno(sysdep(PRead)(fildes, buf, nbyte, offset), -1);
}
export int pthread_atfork(void (*)(void), void (*)(void), void (*)(void));
export ssize_t pwrite(int fildes, const void *buf, size_t nbyte, off_t offset)
{
return __check_errno(call_pwrite(fildes, buf, nbyte, offset), -1);
return __check_errno(sysdep(PWrite)(fildes, buf, nbyte, offset), -1);
}
export ssize_t read(int fildes, void *buf, size_t nbyte)
{
return __check_errno(call_read(fildes, buf, nbyte), -1);
return __check_errno(sysdep(Read)(fildes, buf, nbyte), -1);
}
export int readlink(const char *, char *, size_t);
@ -324,5 +324,5 @@ export pid_t vfork(void);
export ssize_t write(int fildes, const void *buf, size_t nbyte)
{
return __check_errno(call_write(fildes, buf, nbyte), -1);
return __check_errno(sysdep(Write)(fildes, buf, nbyte), -1);
}

View File

@ -0,0 +1,58 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#ifdef FENNIX_DYNAMIC_LOADER
__attribute__((naked, used, no_stack_protector)) void _dl_start()
{
#if defined(__amd64__)
__asm__(
"xorq %rbp, %rbp\n" /* Clear rbp */
"push %rdi\n"
"push %rsi\n"
"push %rdx\n"
"push %rcx\n"
"push %r8\n"
"push %r9\n"
"call __init_print_buffer\n" /* Call __init_print_buffer */
"call _dl_preload\n" /* Call _dl_preload */
"movl %eax, %edi\n" /* Move return value to edi */
"cmp $0, %edi\n" /* Check if return value is 0 */
"jne _exit\n" /* If not, jump to _exit */
"pop %r9\n"
"pop %r8\n"
"pop %rcx\n"
"pop %rdx\n"
"pop %rsi\n"
"pop %rdi\n"
"call main\n" /* Call _dl_main */
"movl %eax, %edi\n" /* Move return value to edi */
"call _exit\n"); /* Call _exit */
#elif defined(__i386__)
#warning "i386 _start not implemented"
#elif defined(__arm__)
#warning "arm _start not implemented"
#elif defined(__aarch64__)
#warning "aarch64 _start not implemented"
#else
#error "Unsupported architecture"
#endif
}
#endif

View File

@ -15,7 +15,7 @@
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#include <fennix/syscalls.h>
#include <bits/syscalls.h>
#include <sys/mman.h>
#include <unistd.h>
#include <signal.h>
@ -38,7 +38,7 @@ static_assert(__SYS_W_OK == W_OK);
static_assert(__SYS_X_OK == X_OK);
static_assert(sizeof(__SYS_clockid_t) == sizeof(clockid_t));
// static_assert(sizeof(__SYS_socklen_t) == sizeof(socklen_t));
static_assert(sizeof(__SYS_socklen_t) == sizeof(socklen_t));
static_assert(__SYS_SEEK_SET == SEEK_SET);
static_assert(__SYS_SEEK_CUR == SEEK_CUR);

View File

@ -0,0 +1,191 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#include <bits/syscalls.h>
#include <bits/libc.h>
#include <string.h>
void sysdep(Exit)(int Status)
{
call_exit(Status);
}
int sysdep(Accept)(int Socket, struct sockaddr *restrict Address, socklen_t *restrict AddressLength)
{
return call_accept(Socket, Address, AddressLength);
}
int sysdep(Bind)(int Socket, const struct sockaddr *Address, socklen_t AddressLength)
{
return call_bind(Socket, Address, AddressLength);
}
int sysdep(Connect)(int Socket, const struct sockaddr *Address, socklen_t AddressLength)
{
return call_connect(Socket, Address, AddressLength);
}
int sysdep(Listen)(int Socket, int Backlog)
{
return call_listen(Socket, Backlog);
}
int sysdep(Socket)(int Domain, int Type, int Protocol)
{
return call_socket(Domain, Type, Protocol);
}
int sysdep(UnixName)(struct utsname *Name)
{
struct kutsname kname;
int result = call_uname(&kname);
if (result == 0)
{
strcpy(Name->sysname, kname.sysname);
strcpy(Name->release, kname.release);
strcpy(Name->version, kname.version);
strcpy(Name->machine, kname.machine);
return 0;
}
return result;
}
int sysdep(WaitProcessID)(pid_t ProcessID, int *Status, int Options)
{
return call_waitpid(ProcessID, Status, Options);
}
int sysdep(IOControl)(int Descriptor, unsigned long Operation, void *Argument)
{
return call_ioctl(Descriptor, Operation, Argument);
}
void *sysdep(MemoryMap)(void *Address, size_t Length, int Protection, int Flags, int Descriptor, off_t Offset)
{
return (void *)call_mmap(Address, Length, Protection, Flags, Descriptor, Offset);
}
int sysdep(MemoryUnmap)(void *Address, size_t Length)
{
return call_munmap(Address, Length);
}
int sysdep(MemoryProtect)(void *Address, size_t Length, int Protection)
{
return call_mprotect(Address, Length, Protection);
}
int sysdep(Fork)(void)
{
return call_fork();
}
int sysdep(Read)(int Descriptor, void *Buffer, size_t Size)
{
return call_read(Descriptor, Buffer, Size);
}
int sysdep(Write)(int Descriptor, const void *Buffer, size_t Size)
{
return call_write(Descriptor, Buffer, Size);
}
int sysdep(PRead)(int Descriptor, void *Buffer, size_t Size, off_t Offset)
{
return call_pread(Descriptor, Buffer, Size, Offset);
}
int sysdep(PWrite)(int Descriptor, const void *Buffer, size_t Size, off_t Offset)
{
return call_pwrite(Descriptor, Buffer, Size, Offset);
}
int sysdep(Open)(const char *Pathname, int Flags, mode_t Mode)
{
return call_open(Pathname, Flags, Mode);
}
int sysdep(Close)(int Descriptor)
{
return call_close(Descriptor);
}
int sysdep(Access)(const char *Pathname, int Mode)
{
return call_access(Pathname, Mode);
}
int sysdep(Tell)(int Descriptor)
{
return call_tell(Descriptor);
}
int sysdep(Seek)(int Descriptor, off_t Offset, int Whence)
{
return call_seek(Descriptor, Offset, Whence);
}
pid_t sysdep(GetProcessID)(void)
{
return call_getpid();
}
pid_t sysdep(GetParentProcessID)(void)
{
return call_getppid();
}
int sysdep(Execve)(const char *Pathname, char *const *Argv, char *const *Envp)
{
return call_execve(Pathname, Argv, Envp);
}
int sysdep(Kill)(pid_t ProcessID, int Signal)
{
return call_kill(ProcessID, Signal);
}
int sysdep(Stat)(const char *Pathname, struct stat *Statbuf)
{
return call_stat(Pathname, Statbuf);
}
int sysdep(FStat)(int Descriptor, struct stat *Statbuf)
{
return call_fstat(Descriptor, Statbuf);
}
int sysdep(LStat)(const char *Pathname, struct stat *Statbuf)
{
return call_lstat(Pathname, Statbuf);
}
int sysdep(Truncate)(const char *Pathname, off_t Length)
{
return call_truncate(Pathname, Length);
}
int sysdep(MakeDirectory)(const char *Pathname, mode_t Mode)
{
return call_mkdir(Pathname, Mode);
}
int sysdep(ProcessControl)(unsigned long Option, unsigned long Arg1, unsigned long Arg2, unsigned long Arg3, unsigned long Arg4)
{
return call_prctl(Option, Arg1, Arg2, Arg3, Arg4);
}

View File

@ -15,13 +15,14 @@
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#include <fennix/syscalls.h>
#include <bits/syscalls.h>
#include <bits/libc.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <inttypes.h>
#include <stddef.h>
#include <fennix/syscalls.h>
#ifndef FENNIX_DYNAMIC_LOADER
export __attribute__((naked, used, no_stack_protector)) void *__tls_get_addr(void *__data)
{
#warning "__tls_get_addr not implemented"
@ -34,11 +35,12 @@ int __init_pthread(void)
{
__pthread *ptr = (__pthread *)call_mmap(0,
0x1000,
__SYS_PROT_READ | __SYS_PROT_WRITE,
__SYS_MAP_ANONYMOUS | __SYS_MAP_PRIVATE,
PROT_READ | PROT_WRITE,
MAP_ANONYMOUS | MAP_PRIVATE,
-1, 0);
call_prctl(__SYS_SET_FS, ptr, 0, 0, 0);
ptr->Self = ptr;
ptr->CurrentError = 0;
return 0;
}
#endif

View File

@ -0,0 +1,22 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __fennix__
#error "Macro __fennix__ is not defined."
#endif
int main() { return 0; }

View File

@ -1,12 +1,8 @@
build:
cp -a $(CURDIR)/include/. $(WORKSPACE_DIR)/out/include
make -C libgcc build
make -C libm build
make -C libstdc++ build
make -C libexample build
clean:
make -C libgcc clean
make -C libm clean
make -C libstdc++ clean
make -C libexample clean

View File

@ -15,7 +15,7 @@
along with Fennix Userspace. If not, see <https://www.gnu.org/licenses/>.
*/
#include <sys/types.h>
#include <bits/libc.h>
export int foo()
{

View File

@ -1,48 +0,0 @@
default:
$(error Do not run this Makefile directly!)
DYNAMIC_NAME := $(notdir $(shell pwd)).so
STATIC_NAME := $(notdir $(shell pwd)).a
OUTPUT_DIR=$(WORKSPACE_DIR)/out/lib/
SYSROOT = --sysroot=$(WORKSPACE_DIR)/out/
S_SOURCES = $(shell find ./ -type f -name '*.S')
C_SOURCES = $(shell find ./ -type f -name '*.c')
CXX_SOURCES = $(shell find ./ -type f -name '*.cpp')
OBJ = ${S_SOURCES:.S=.o} ${C_SOURCES:.c=.o} ${CXX_SOURCES:.cpp=.o}
CFLAGS := -fvisibility=hidden -fPIC -I../include -I$(WORKSPACE_DIR)/out/include -DLIBC_GIT_COMMIT='"$(shell git rev-parse HEAD)"'
ifeq ($(DEBUG), 1)
CFLAGS += -DDEBUG -ggdb3 -O0 -fdiagnostics-color=always
endif
build: $(DYNAMIC_NAME) $(STATIC_NAME)
.PHONY: $(DYNAMIC_NAME) $(STATIC_NAME)
$(DYNAMIC_NAME): $(OBJ)
$(info Linking $@)
$(CC) -nostdlib -shared -fPIC -fPIE -Wl,-soname,$(DYNAMIC_NAME) $(SYSROOT) $(OBJ) -o $(DYNAMIC_NAME)
cp $(DYNAMIC_NAME) $(OUTPUT_DIR)$(DYNAMIC_NAME)
$(STATIC_NAME): $(OBJ)
$(info Linking $@)
$(AR) -rcs $(STATIC_NAME) $(OBJ)
cp $(STATIC_NAME) $(OUTPUT_DIR)$(STATIC_NAME)
%.o: %.c
$(info Compiling $<)
$(CC) $(CFLAGS) -std=c17 -c $< -o $@
%.o: %.cpp
$(info Compiling $<)
$(CC) $(CFLAGS) -std=c++20 -c $< -o $@
%.o: %.S
$(info Compiling $<)
$(AS) -c $< -o $@
clean:
rm -f $(OBJ) $(DYNAMIC_NAME) $(STATIC_NAME)

View File

@ -1,48 +0,0 @@
default:
$(error Do not run this Makefile directly!)
DYNAMIC_NAME := $(notdir $(shell pwd)).so
STATIC_NAME := $(notdir $(shell pwd)).a
OUTPUT_DIR=$(WORKSPACE_DIR)/out/lib/
SYSROOT = --sysroot=$(WORKSPACE_DIR)/out/
S_SOURCES = $(shell find ./ -type f -name '*.S')
C_SOURCES = $(shell find ./ -type f -name '*.c')
CXX_SOURCES = $(shell find ./ -type f -name '*.cpp')
OBJ = ${S_SOURCES:.S=.o} ${C_SOURCES:.c=.o} ${CXX_SOURCES:.cpp=.o}
CFLAGS := -fvisibility=hidden -fPIC -I../include -I$(WORKSPACE_DIR)/out/include -DLIBC_GIT_COMMIT='"$(shell git rev-parse HEAD)"'
ifeq ($(DEBUG), 1)
CFLAGS += -DDEBUG -ggdb3 -O0 -fdiagnostics-color=always
endif
build: $(DYNAMIC_NAME) $(STATIC_NAME)
.PHONY: $(DYNAMIC_NAME) $(STATIC_NAME)
$(DYNAMIC_NAME): $(OBJ)
$(info Linking $@)
$(CC) -nostdlib -shared -fPIC -fPIE -Wl,-soname,$(DYNAMIC_NAME) $(SYSROOT) $(OBJ) -o $(DYNAMIC_NAME)
cp $(DYNAMIC_NAME) $(OUTPUT_DIR)$(DYNAMIC_NAME)
$(STATIC_NAME): $(OBJ)
$(info Linking $@)
$(AR) -rcs $(STATIC_NAME) $(OBJ)
cp $(STATIC_NAME) $(OUTPUT_DIR)$(STATIC_NAME)
%.o: %.c
$(info Compiling $<)
$(CC) $(CFLAGS) -std=c17 -c $< -o $@
%.o: %.cpp
$(info Compiling $<)
$(CC) $(CFLAGS) -std=c++20 -c $< -o $@
%.o: %.S
$(info Compiling $<)
$(AS) -c $< -o $@
clean:
rm -f $(OBJ) $(DYNAMIC_NAME) $(STATIC_NAME)