userspace: Rewrite everything

Everything.

Signed-off-by: EnderIce2 <enderice2@protonmail.com>
This commit is contained in:
EnderIce2 2025-01-04 06:27:54 +02:00
parent dea36a0228
commit 6dae34debd
No known key found for this signature in database
GPG Key ID: 2EE20AF089811A5A
135 changed files with 11707 additions and 5286 deletions

View File

@ -1,33 +0,0 @@
# Config file
include ../../../config.mk
cwd := $(CURDIR)
CACHE_DIR := $(cwd)/../../cache
PREFIX := $(cwd)/../../out/
TARGET := x86_64-fennix
export CC := $(cwd)/../../../tools/cross/bin/$(TARGET)-gcc
export LD := $(cwd)/../../../tools/cross/bin/$(TARGET)-ld
export AR := $(cwd)/../../../tools/cross/bin/$(TARGET)-ar
export STRIP := $(cwd)/../../../tools/cross/bin/$(TARGET)-strip
export RANLIB := $(cwd)/../../../tools/cross/bin/$(TARGET)-ranlib
export LD_LIBRARY_PATH := $(cwd)/../../out/lib/
ifeq ($(DEBUG), 1)
export CFLAGS := --sysroot=$(cwd)/../../out/ -I$(cwd)/../../out/include/ -DDEBUG -ggdb3 -O0 -fdiagnostics-color=always -fverbose-asm
export LDFLAGS := -ggdb3 -O0
else
export CFLAGS := --sysroot=$(cwd)/../../out/ -I$(cwd)/../../out/include/
endif
build:
make -C utest build
make -C cross_test build
make -C echo build
make -C fsh build
clean:
make -C utest clean
make -C cross_test clean
make -C echo clean
make -C fsh clean

View File

@ -1,16 +0,0 @@
WORKSPACE := ../../../
# Config file
include ../$(WORKSPACE)config.mk
FILENAME = utest_
CFLAGS = -static -g -ggdb3 -O0
build:
$(info Compiling $(FILENAME)linux)
gcc linux_glibc.c $(CFLAGS) -o $(WORKSPACE)out/bin/$(FILENAME)linux
$(info Compiling $(FILENAME)win)
x86_64-w64-mingw32-gcc win_mingw.c $(CFLAGS) -o $(WORKSPACE)out/bin/$(FILENAME)win.exe
clean:

View File

@ -1,22 +0,0 @@
$ setarch `uname -m` -R strace ./utest_linux
execve("./utest_linux", ["./utest_linux"], 0x7fffffffdec0 /* 56 vars */) = 0
arch_prctl(0x3001 /* ARCH_??? */, 0x7fffffffde40) = -1 EINVAL (Invalid argument)
brk(NULL) = 0x4cd000
brk(0x4cddc0) = 0x4cddc0
arch_prctl(ARCH_SET_FS, 0x4cd3c0) = 0
set_tid_address(0x4cd690) = 68565
set_robust_list(0x4cd6a0, 24) = 0
rseq(0x4cdd60, 0x20, 0, 0x53053053) = 0
uname({sysname="Fennix", nodename="fennix", ...}) = 0
prlimit64(0, RLIMIT_STACK, NULL, {rlim_cur=8192*1024, rlim_max=RLIM64_INFINITY}) = 0
readlink("/proc/self/exe", "/bin/utest_linux"..., 4096) = 50
getrandom("\x1e\x3c\x20\xdd\x09\xe8\x46\x0d", 8, GRND_NONBLOCK) = 8
brk(0x4eedc0) = 0x4eedc0
brk(0x4ef000) = 0x4ef000
mprotect(0x4c1000, 16384, PROT_READ) = 0
newfstatat(1, "", {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0x1), ...}, AT_EMPTY_PATH) = 0
write(1, "Hello, World!\n", 14Hello, World!
) = 14
exit_group(0) = ?
+++ exited with 0 +++

View File

@ -1,66 +0,0 @@
WORKSPACE := ../../../
# Config file
include ../$(WORKSPACE)config.mk
CC = ../$(WORKSPACE)$(COMPILER_PATH)/$(COMPILER_ARCH)gcc
CPP = ../$(WORKSPACE)$(COMPILER_PATH)/$(COMPILER_ARCH)g++
LD = ../$(WORKSPACE)$(COMPILER_PATH)/$(COMPILER_ARCH)ld
AS = ../$(WORKSPACE)$(COMPILER_PATH)/$(COMPILER_ARCH)as
OBJDUMP = ../$(WORKSPACE)$(COMPILER_PATH)/$(COMPILER_ARCH)objdump
GIT_COMMIT = $(shell git rev-parse HEAD)
GIT_COMMIT_SHORT = $(shell git rev-parse --short HEAD)
ifeq ($(OSARCH), amd64)
S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./arch/i386/*" -not -path "./arch/aarch64/*")
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./arch/i386/*" -not -path "./arch/aarch64/*")
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./arch/i386/*" -not -path "./arch/aarch64/*")
else ifeq ($(OSARCH), i386)
S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./arch/amd64/*" -not -path "./arch/aarch64/*")
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./arch/amd64/*" -not -path "./arch/aarch64/*")
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./arch/amd64/*" -not -path "./arch/aarch64/*")
else ifeq ($(OSARCH), aarch64)
S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./arch/amd64/*" -not -path "./arch/i386/*")
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./arch/amd64/*" -not -path "./arch/i386/*")
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./arch/amd64/*" -not -path "./arch/i386/*")
endif
OBJ = $(C_SOURCES:.c=.o) $(CPP_SOURCES:.cpp=.o) $(ASM_SOURCES:.asm=.o) $(S_SOURCES:.S=.o) $(PSF_SOURCES:.psf=.o) $(BMP_SOURCES:.bmp=.o)
SYSROOT = --sysroot=$(WORKSPACE)out/
FILENAME = echo
HEADERS = $(sort $(dir $(wildcard $(WORKSPACE)out/include/*)))
LDFLAGS =
CFLAGS = -I$(WORKSPACE)out/include \
-DGIT_COMMIT='"$(GIT_COMMIT)"' \
-DGIT_COMMIT_SHORT='"$(GIT_COMMIT_SHORT)"'
WARNCFLAG = -Wall -Wextra
ifeq ($(DEBUG), 1)
CFLAGS += -DDEBUG -ggdb3 -O0 -fdiagnostics-color=always -fverbose-asm
LDFLAGS += -ggdb3 -O0
endif
build: $(FILENAME)
mv $(FILENAME) $(WORKSPACE)out/bin/$(FILENAME)
$(FILENAME): $(OBJ)
$(info Linking $@)
$(CC) $(LDFLAGS) $(SYSROOT) $(OBJ) -o $@
%.o: %.c $(HEADERS)
$(info Compiling $<)
$(CC) $(CFLAGS) $(WARNCFLAG) -std=c17 -c $< -o $@
%.o: %.cpp $(HEADERS)
$(info Compiling $<)
$(CPP) $(CFLAGS) $(WARNCFLAG) -std=c++20 -fexceptions -c $< -o $@ -fno-rtti
%.o: %.S
$(info Compiling $<)
$(AS) -o $@ $<
clean:
rm -f $(OBJ)

View File

@ -1,59 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
int main(int argc, char *argv[])
{
int enableEscapes = 0;
int disableNewline = 0;
int opt;
while ((opt = getopt(argc, argv, "neE")) != -1)
{
switch (opt)
{
case 'n':
disableNewline = 1;
break;
case 'e':
enableEscapes = 1;
break;
case 'E':
enableEscapes = 0;
break;
case '?':
default:
exit(EXIT_FAILURE);
}
}
(void)enableEscapes;
size_t totalLength = 0;
for (int i = optind; i < argc; ++i)
totalLength += strlen(argv[i]) + 1;
char *result = (char *)malloc(totalLength);
if (!result)
{
perror("Memory allocation error");
exit(EXIT_FAILURE);
}
result[0] = '\0';
for (int i = optind; i < argc; ++i)
{
strcat(result, argv[i]);
if (i < argc - 1)
strcat(result, " ");
}
printf("%s", result);
if (!disableNewline)
printf("\n");
free(result);
return 0;
}

View File

@ -1,66 +0,0 @@
WORKSPACE := ../../../
# Config file
include ../$(WORKSPACE)config.mk
CC = ../$(WORKSPACE)$(COMPILER_PATH)/$(COMPILER_ARCH)gcc
CPP = ../$(WORKSPACE)$(COMPILER_PATH)/$(COMPILER_ARCH)g++
LD = ../$(WORKSPACE)$(COMPILER_PATH)/$(COMPILER_ARCH)ld
AS = ../$(WORKSPACE)$(COMPILER_PATH)/$(COMPILER_ARCH)as
OBJDUMP = ../$(WORKSPACE)$(COMPILER_PATH)/$(COMPILER_ARCH)objdump
GIT_COMMIT = $(shell git rev-parse HEAD)
GIT_COMMIT_SHORT = $(shell git rev-parse --short HEAD)
ifeq ($(OSARCH), amd64)
S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./arch/i386/*" -not -path "./arch/aarch64/*")
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./arch/i386/*" -not -path "./arch/aarch64/*")
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./arch/i386/*" -not -path "./arch/aarch64/*")
else ifeq ($(OSARCH), i386)
S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./arch/amd64/*" -not -path "./arch/aarch64/*")
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./arch/amd64/*" -not -path "./arch/aarch64/*")
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./arch/amd64/*" -not -path "./arch/aarch64/*")
else ifeq ($(OSARCH), aarch64)
S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./arch/amd64/*" -not -path "./arch/i386/*")
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./arch/amd64/*" -not -path "./arch/i386/*")
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./arch/amd64/*" -not -path "./arch/i386/*")
endif
OBJ = $(C_SOURCES:.c=.o) $(CPP_SOURCES:.cpp=.o) $(ASM_SOURCES:.asm=.o) $(S_SOURCES:.S=.o) $(PSF_SOURCES:.psf=.o) $(BMP_SOURCES:.bmp=.o)
SYSROOT = --sysroot=$(WORKSPACE)out/
FILENAME = sh
HEADERS = $(sort $(dir $(wildcard $(WORKSPACE)out/include/*)))
LDFLAGS =
CFLAGS = -I$(WORKSPACE)out/include \
-DGIT_COMMIT='"$(GIT_COMMIT)"' \
-DGIT_COMMIT_SHORT='"$(GIT_COMMIT_SHORT)"'
WARNCFLAG = -Wall -Wextra
ifeq ($(DEBUG), 1)
CFLAGS += -DDEBUG -ggdb3 -O0 -fdiagnostics-color=always -fverbose-asm
LDFLAGS += -ggdb3 -O0
endif
build: $(FILENAME)
mv $(FILENAME) $(WORKSPACE)out/bin/$(FILENAME)
$(FILENAME): $(OBJ)
$(info Linking $@)
$(CC) $(LDFLAGS) $(SYSROOT) $(OBJ) -o $@
%.o: %.c $(HEADERS)
$(info Compiling $<)
$(CC) $(CFLAGS) $(WARNCFLAG) -std=c17 -c $< -o $@
%.o: %.cpp $(HEADERS)
$(info Compiling $<)
$(CPP) $(CFLAGS) $(WARNCFLAG) -std=c++20 -fexceptions -c $< -o $@ -fno-rtti
%.o: %.S
$(info Compiling $<)
$(AS) -o $@ $<
clean:
rm -f $(OBJ)

View File

@ -1,160 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#define _GNU_SOURCE
#include <signal.h>
#include <termios.h>
#define _POSIX_SOURCE
#include <string.h>
#define MAX_COMMAND_LENGTH 1024
#define MAX_ARGS 10
void DisableInputBuffering()
{
struct termios tty_attr;
tcgetattr(STDIN_FILENO, &tty_attr);
tty_attr.c_lflag &= ~(ICANON | ECHO);
tcsetattr(STDIN_FILENO, TCSANOW, &tty_attr);
}
void EnableInputBuffering()
{
struct termios tty_attr;
tcgetattr(STDIN_FILENO, &tty_attr);
tty_attr.c_lflag |= ICANON | ECHO;
tcsetattr(STDIN_FILENO, TCSANOW, &tty_attr);
}
void ReadLine(char *Buffer, size_t BufferSize)
{
size_t index = 0;
int c;
while (1)
{
c = getchar();
if (c == EOF || c == '\n')
{
Buffer[index] = '\0';
break;
}
else if (c == 127 || c == 8) // Backspace
{
if (index > 0)
{
printf("\b \b");
index--;
}
}
else if (c == 4) // Ctrl + D
{
if (index == 0)
kill(getpid(), SIGQUIT);
else
putchar('\a');
}
else
{
if (index < BufferSize - 1)
{
putchar(c);
Buffer[index] = (char)c;
index++;
}
}
}
}
void ExecuteCommand(char *command)
{
char *args[MAX_ARGS];
int i = 0;
char *token = strtok(command, " ");
while (token != NULL && i < MAX_ARGS - 1)
{
args[i++] = token;
token = strtok(NULL, " ");
}
args[i] = NULL;
pid_t pid = fork();
if (pid == 0)
{
execvp(args[0], args);
perror("execvp");
exit(EXIT_FAILURE);
}
else if (pid > 0)
wait(NULL);
else
{
perror("fork");
exit(EXIT_FAILURE);
}
}
void HandleSignal(int signal)
{
if (signal == SIGQUIT)
{
EnableInputBuffering();
printf("\n");
exit(EXIT_SUCCESS);
}
else if (signal == SIGINT)
{
putchar('\n');
}
else if (signal == SIGHUP)
{
EnableInputBuffering();
exit(EXIT_SUCCESS);
}
else if (signal == SIGCHLD)
wait(NULL);
else if (signal == SIGSEGV)
{
printf("Segmentation fault\n");
while (1)
sleep(1000);
}
else
{
printf("Signal %s(%d) received\n",
strsignal(signal), signal);
}
}
int main()
{
char command[MAX_COMMAND_LENGTH];
for (int i = 0; i < NSIG; ++i)
signal(i, HandleSignal);
char hostname[256];
gethostname(hostname, sizeof(hostname));
while (1)
{
printf("\033[1;32m");
printf("┌──(%s@%s)-[%s]\n", getenv("USER"), hostname, getenv("PWD"));
printf("└$ ");
printf("\033[0m");
DisableInputBuffering();
ReadLine(command, sizeof(command));
EnableInputBuffering();
putchar('\n');
if (strcmp(command, "exit") == 0)
break;
ExecuteCommand(command);
}
return 0;
}

View File

@ -1,66 +0,0 @@
WORKSPACE := ../../../
# Config file
include ../$(WORKSPACE)config.mk
CC = ../$(WORKSPACE)$(COMPILER_PATH)/$(COMPILER_ARCH)gcc
CPP = ../$(WORKSPACE)$(COMPILER_PATH)/$(COMPILER_ARCH)g++
LD = ../$(WORKSPACE)$(COMPILER_PATH)/$(COMPILER_ARCH)ld
AS = ../$(WORKSPACE)$(COMPILER_PATH)/$(COMPILER_ARCH)as
OBJDUMP = ../$(WORKSPACE)$(COMPILER_PATH)/$(COMPILER_ARCH)objdump
GIT_COMMIT = $(shell git rev-parse HEAD)
GIT_COMMIT_SHORT = $(shell git rev-parse --short HEAD)
ifeq ($(OSARCH), amd64)
S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./arch/i386/*" -not -path "./arch/aarch64/*")
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./arch/i386/*" -not -path "./arch/aarch64/*")
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./arch/i386/*" -not -path "./arch/aarch64/*")
else ifeq ($(OSARCH), i386)
S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./arch/amd64/*" -not -path "./arch/aarch64/*")
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./arch/amd64/*" -not -path "./arch/aarch64/*")
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./arch/amd64/*" -not -path "./arch/aarch64/*")
else ifeq ($(OSARCH), aarch64)
S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./arch/amd64/*" -not -path "./arch/i386/*")
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./arch/amd64/*" -not -path "./arch/i386/*")
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./arch/amd64/*" -not -path "./arch/i386/*")
endif
OBJ = $(C_SOURCES:.c=.o) $(CPP_SOURCES:.cpp=.o) $(ASM_SOURCES:.asm=.o) $(S_SOURCES:.S=.o) $(PSF_SOURCES:.psf=.o) $(BMP_SOURCES:.bmp=.o)
SYSROOT = --sysroot=$(WORKSPACE)out/
FILENAME = utest
HEADERS = $(sort $(dir $(wildcard $(WORKSPACE)out/include/*)))
LDFLAGS = -static
CFLAGS = -I$(WORKSPACE)out/include \
-DGIT_COMMIT='"$(GIT_COMMIT)"' \
-DGIT_COMMIT_SHORT='"$(GIT_COMMIT_SHORT)"' -static
WARNCFLAG = -Wall -Wextra
ifeq ($(DEBUG), 1)
CFLAGS += -DDEBUG -ggdb3 -O0 -fdiagnostics-color=always -fverbose-asm
LDFLAGS += -ggdb3 -O0
endif
build: $(FILENAME)
mv $(FILENAME) $(WORKSPACE)out/bin/$(FILENAME)
$(FILENAME): $(OBJ)
$(info Linking $@)
$(CC) $(LDFLAGS) $(SYSROOT) $(OBJ) -o $@
%.o: %.c $(HEADERS)
$(info Compiling $<)
$(CC) $(CFLAGS) $(WARNCFLAG) -std=c17 -c $< -o $@
%.o: %.cpp $(HEADERS)
$(info Compiling $<)
$(CPP) $(CFLAGS) $(WARNCFLAG) -std=c++20 -fexceptions -c $< -o $@ -fno-rtti
%.o: %.S
$(info Compiling $<)
$(AS) -o $@ $<
clean:
rm -f $(OBJ)

View File

@ -0,0 +1,9 @@
MAKE_TARGETS := build clean
DIRECTORIES := $(sort $(dir $(wildcard ./*/)))
.PHONY: $(MAKE_TARGETS) $(DIRECTORIES)
$(MAKE_TARGETS): $(DIRECTORIES)
$(DIRECTORIES):
$(MAKE) -C $@ $(MAKECMDGOALS)

1
Userspace/apps/sys/init/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
init

View File

@ -0,0 +1,33 @@
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)
FILENAME = $(notdir $(shell pwd))
WARNCFLAG = -Wall -Wextra
build: $(FILENAME)
cp $(FILENAME) $(WORKSPACE_DIR)/out/bin/$(FILENAME)
$(FILENAME): $(OBJ)
$(info Linking $@)
$(CC) $(LDFLAGS) $(SYSROOT) $(OBJ) -o $@
%.o: %.c $(HEADERS)
$(info Compiling $<)
$(CC) $(CFLAGS) $(WARNCFLAG) -std=c17 -c $< -o $@
%.o: %.cpp $(HEADERS)
$(info Compiling $<)
$(CXX) $(CFLAGS) $(WARNCFLAG) -std=c++20 -fexceptions -c $< -o $@ -fno-rtti
%.o: %.S
$(info Compiling $<)
$(AS) -o $@ $<
clean:
rm -f $(OBJ) $(FILENAME)

View File

@ -0,0 +1,27 @@
/*
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 <stdio.h>
#include <errno.h>
#include <assert.h>
#include <stdlib.h>
int main(int, char *[], char *[])
{
printf("Hello, World!\n");
return 0;
}

View File

@ -1,5 +0,0 @@
build:
make -C init build
clean:
make -C init clean

View File

@ -1,70 +0,0 @@
WORKSPACE := ../../../
# Config file
include ../$(WORKSPACE)config.mk
CC = ../$(WORKSPACE)$(COMPILER_PATH)/$(COMPILER_ARCH)gcc
CPP = ../$(WORKSPACE)$(COMPILER_PATH)/$(COMPILER_ARCH)g++
LD = ../$(WORKSPACE)$(COMPILER_PATH)/$(COMPILER_ARCH)ld
AS = ../$(WORKSPACE)$(COMPILER_PATH)/$(COMPILER_ARCH)as
OBJDUMP = ../$(WORKSPACE)$(COMPILER_PATH)/$(COMPILER_ARCH)objdump
GIT_COMMIT = $(shell git rev-parse HEAD)
GIT_COMMIT_SHORT = $(shell git rev-parse --short HEAD)
ifeq ($(OSARCH), amd64)
S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./arch/i386/*" -not -path "./arch/aarch64/*")
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./arch/i386/*" -not -path "./arch/aarch64/*")
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./arch/i386/*" -not -path "./arch/aarch64/*")
else ifeq ($(OSARCH), i386)
S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./arch/amd64/*" -not -path "./arch/aarch64/*")
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./arch/amd64/*" -not -path "./arch/aarch64/*")
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./arch/amd64/*" -not -path "./arch/aarch64/*")
else ifeq ($(OSARCH), aarch64)
S_SOURCES = $(shell find ./ -type f -name '*.S' -not -path "./arch/amd64/*" -not -path "./arch/i386/*")
C_SOURCES = $(shell find ./ -type f -name '*.c' -not -path "./arch/amd64/*" -not -path "./arch/i386/*")
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp' -not -path "./arch/amd64/*" -not -path "./arch/i386/*")
endif
OBJ = $(C_SOURCES:.c=.o) $(CPP_SOURCES:.cpp=.o) $(ASM_SOURCES:.asm=.o) $(S_SOURCES:.S=.o) $(PSF_SOURCES:.psf=.o) $(BMP_SOURCES:.bmp=.o)
SYSROOT = --sysroot=$(WORKSPACE)out/
FILENAME = init
HEADERS = $(sort $(dir $(wildcard $(WORKSPACE)out/include/*)))
LDFLAGS =
CFLAGS = -I$(WORKSPACE)out/include \
-DGIT_COMMIT='"$(GIT_COMMIT)"' \
-DGIT_COMMIT_SHORT='"$(GIT_COMMIT_SHORT)"'
WARNCFLAG = -Wall -Wextra
ifneq ($(OSARCH), aarch64)
# CFLAGS += -fstack-protector-all -fstack-clash-protection
endif
ifeq ($(DEBUG), 1)
CFLAGS += -DDEBUG -ggdb3 -O0 -fdiagnostics-color=always -fverbose-asm
LDFLAGS += -ggdb3 -O0
endif
build: $(FILENAME)
mv $(FILENAME) $(WORKSPACE)out/bin/$(FILENAME)
$(FILENAME): $(OBJ)
$(info Linking $@)
$(CC) $(LDFLAGS) $(SYSROOT) $(OBJ) -o $@
%.o: %.c $(HEADERS)
$(info Compiling $<)
$(CC) $(CFLAGS) $(WARNCFLAG) -std=c17 -c $< -o $@
%.o: %.cpp $(HEADERS)
$(info Compiling $<)
$(CPP) $(CFLAGS) $(WARNCFLAG) -std=c++20 -fexceptions -c $< -o $@ -fno-rtti
%.o: %.S
$(info Compiling $<)
$(AS) -o $@ $<
clean:
rm -f $(OBJ)

View File

@ -1,6 +0,0 @@
#include <stdio.h>
int main(int, char *[], char *[])
{
return 0;
}

View File

@ -0,0 +1,9 @@
MAKE_TARGETS := build clean
DIRECTORIES := $(sort $(dir $(wildcard ./*/)))
.PHONY: $(MAKE_TARGETS) $(DIRECTORIES)
$(MAKE_TARGETS): $(DIRECTORIES)
$(DIRECTORIES):
$(MAKE) -C $@ $(MAKECMDGOALS)

View File

@ -0,0 +1,2 @@
utest_linux
utest_win.exe

View File

@ -0,0 +1,30 @@
default:
$(error Do not run this Makefile directly!)
FILENAME = utest_
CFLAGS = -static -g -ggdb3 -O0 -w
UNAME_OS := $(shell uname -s)
$(FILENAME)linux:
ifneq ($(shell uname -s), Linux)
$(info Only Linux is supported)
exit 0
endif
$(info Compiling $(FILENAME)linux)
gcc linux_glibc.c $(CFLAGS) -o $(FILENAME)linux
cp $(FILENAME)linux $(WORKSPACE_DIR)/out/bin/$(FILENAME)linux
$(FILENAME)win.exe:
ifneq ($(shell uname -s), Linux)
$(info Only Linux is supported)
exit 0
endif
$(info Compiling $(FILENAME)win)
x86_64-w64-mingw32-gcc win_mingw.c $(CFLAGS) -o $(FILENAME)win.exe
cp $(FILENAME)win.exe $(WORKSPACE_DIR)/out/bin/$(FILENAME)win.exe
build: $(FILENAME)linux $(FILENAME)win.exe
clean:
rm -f $(FILENAME)linux $(FILENAME)win.exe

1
Userspace/apps/test/utest/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
utest

View File

@ -0,0 +1,36 @@
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)
FILENAME = $(notdir $(shell pwd))
WARNCFLAG = -Wall -Wextra
build: $(FILENAME)
# cp $(FILENAME) $(WORKSPACE_DIR)/out/bin/$(FILENAME)
# Use static linking
LDFLAGS += -static -fno-pic -fno-pie -Wl,-static
$(FILENAME): $(OBJ)
$(info Linking $@)
# $(CC) $(LDFLAGS) $(SYSROOT) $(OBJ) -o $@
%.o: %.c $(HEADERS)
$(info Compiling $<)
$(CC) $(CFLAGS) $(WARNCFLAG) -std=c17 -c $< -o $@
%.o: %.cpp $(HEADERS)
$(info Compiling $<)
$(CXX) $(CFLAGS) $(WARNCFLAG) -std=c++20 -fexceptions -c $< -o $@ -fno-rtti
%.o: %.S
$(info Compiling $<)
$(AS) -o $@ $<
clean:
rm -f $(OBJ) $(FILENAME)

View File

@ -7,15 +7,11 @@
#include <sys/wait.h>
#include <string.h>
#include <errno.h>
#include <sys/inotify.h>
#include <fcntl.h>
#include <pty.h>
#include <stdlib.h>
#include <signal.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/reboot.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <time.h>
#include <pwd.h>
@ -141,10 +137,10 @@ void test_passwd()
else
{
printf("name: %s\n", p->pw_name);
printf("passwd: %s\n", p->pw_passwd);
// printf("passwd: %s\n", p->pw_passwd);
printf("uid: %d\n", p->pw_uid);
printf("gid: %d\n", p->pw_gid);
printf("gecos: %s\n", p->pw_gecos);
// printf("gecos: %s\n", p->pw_gecos);
printf("dir: %s\n", p->pw_dir);
printf("shell: %s\n", p->pw_shell);
}
@ -251,7 +247,9 @@ void test_time()
time_t t = mktime(&time);
if (t != (time_t)-1)
stime(&t);
{
// stime(&t);
}
else
{
perror("mktime");
@ -401,29 +399,29 @@ void test_stat()
void test_ptmx()
{
printf("- Testing PTMX\n");
// printf("- Testing PTMX\n");
int master, slave;
char buffer[256];
// int master, slave;
// char buffer[256];
if (openpty(&master, &slave, NULL, NULL, NULL) == -1)
{
perror("openpty");
fflush(stdout);
fflush(stderr);
return;
}
// if (openpty(&master, &slave, NULL, NULL, NULL) == -1)
// {
// perror("openpty");
// fflush(stdout);
// fflush(stderr);
// return;
// }
write(master, "Hello, pty!\n", 12);
ssize_t bytesRead = read(slave, buffer, sizeof(buffer));
if (bytesRead > 0)
{
buffer[bytesRead] = '\0';
printf("Received from pty: %s", buffer);
}
// write(master, "Hello, pty!\n", 12);
// ssize_t bytesRead = read(slave, buffer, sizeof(buffer));
// if (bytesRead > 0)
// {
// buffer[bytesRead] = '\0';
// printf("Received from pty: %s", buffer);
// }
close(master);
close(slave);
// close(master);
// close(slave);
}
void test_system()
@ -654,6 +652,7 @@ char *create_directory()
return path;
}
#ifndef __fennix__
void test_watch_file()
{
printf("- Testing file watching\n");
@ -788,6 +787,7 @@ void reboot_linux()
sync();
reboot(RB_AUTOBOOT);
}
#endif // __fennix__
void test_stdin()
{
@ -892,10 +892,12 @@ int main(int argc, char *argv[], char *envp[])
test_stat();
test_dirent();
test_execve_fork();
#ifndef __fennix__
test_watch_file();
test_watch_directory();
// shutdown_linux();
// reboot_linux();
shutdown_linux();
reboot_linux();
#endif
int status = 0;
pid_t wpid;

View File

@ -1,5 +0,0 @@
build:
make -C games build
clean:
make -C games clean

View File

@ -1,5 +0,0 @@
build:
# make -C doomgeneric build
clean:
# make -C doomgeneric clean

View File

@ -1,70 +0,0 @@
# Config file
include ../../../config.mk
NAME=ld
OBJECT_NAME=$(NAME).so
SO_NAME=$(OBJECT_NAME)
OUTPUT_DIR=../../out/lib/
SYSROOT = --sysroot=../../out/
CC = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)gcc
AS = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)as
AR = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)ar
OBJDUMP = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)objdump
NASM = /usr/bin/nasm
C_SOURCES = $(shell find ./ -type f -name '*.c')
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp')
S_SOURCES = $(shell find ./ -type f -name '*.S')
ASM_SOURCES = $(shell find ./ -type f -name '*.asm')
OBJ = ${C_SOURCES:.c=.o} ${CPP_SOURCES:.cpp=.o} ${ASM_SOURCES:.asm=.o} ${S_SOURCES:.S=.o}
INCLUDE = ../include
SIMD_FLAGS := -mno-sse -mno-sse2 -mno-sse3 -mno-ssse3 -mno-sse4.1 -mno-sse4.2 -mno-sse4 -mno-avx -mno-avx2 -mno-avx512f
CFLAGS := -I$(INCLUDE) $(SIMD_FLAGS) -fPIC
LDFLAGS := -nostartfiles -nostdlib -Wl,-soname,$(SO_NAME) $(SYSROOT) -fno-pie -fno-PIC
ifeq ($(OSARCH), amd64)
ASM_ARCH := elf64
LDFLAGS += -Ttext=0xFFFFFFFFF0001000
CFLAGS += -m64
else ifeq ($(OSARCH), i386)
ASM_ARCH := elf32
LDFLAGS += -fixme
CFLAGS += -m32
endif
ifeq ($(DEBUG), 1)
CFLAGS += -DDEBUG -ggdb3 -O0 -fdiagnostics-color=always -fverbose-asm
LDFLAGS += -ggdb3 -O0
endif
build: $(OBJECT_NAME)
$(OBJECT_NAME): $(OBJ)
$(info Linking $@)
$(CC) $(LDFLAGS) $(OBJ) -o $(OUTPUT_DIR)$@
$(OBJDUMP) -d $(OUTPUT_DIR)$@ > file_dump.map
%.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 $@
%.o: %.asm
$(info Compiling $<)
$(NASM) $< -f $(ASM_ARCH) -o $@
clean:
rm -f file_dump.map $(OBJ)

View File

@ -1,296 +0,0 @@
#ifndef __FENNIX_LIB_ELF_LAZY_RESOLVE_H__
#define __FENNIX_LIB_ELF_LAZY_RESOLVE_H__
typedef __UINT32_TYPE__ Elf32_Addr;
typedef __UINT16_TYPE__ Elf32_Half;
typedef __UINT32_TYPE__ Elf32_Off;
typedef __INT32_TYPE__ Elf32_Sword;
typedef __UINT32_TYPE__ Elf32_Word;
typedef __UINT64_TYPE__ Elf64_Addr;
typedef __UINT16_TYPE__ Elf64_Half;
typedef __INT16_TYPE__ Elf64_SHalf;
typedef __UINT64_TYPE__ Elf64_Off;
typedef __INT32_TYPE__ Elf64_Sword;
typedef __UINT32_TYPE__ Elf64_Word;
typedef __UINT64_TYPE__ Elf64_Xword;
typedef __INT64_TYPE__ Elf64_Sxword;
enum SectionHeaderType
{
SHT_NULL = 0,
SHT_PROGBITS = 1,
SHT_SYMTAB = 2,
SHT_STRTAB = 3,
SHT_RELA = 4,
SHT_HASH = 5,
SHT_DYNAMIC = 6,
SHT_NOTE = 7,
SHT_NOBITS = 8,
SHT_REL = 9,
SHT_SHLIB = 10,
SHT_DYNSYM = 11,
SHT_INIT_ARRAY = 14,
SHT_FINI_ARRAY = 15,
SHT_PREINIT_ARRAY = 16,
SHT_GROUP = 17,
SHT_SYMTAB_SHNDX = 18,
SHT_NUM = 19,
SHT_LOOS = 0x60000000,
SHT_GNU_ATTRIBUTES = 0x6ffffff5,
SHT_GNU_HASH = 0x6ffffff6,
SHT_GNU_LIBLIST = 0x6ffffff7,
SHT_CHECKSUM = 0x6ffffff8,
SHT_LOSUNW = 0x6ffffffa,
SHT_SUNW_move = 0x6ffffffa,
SHT_SUNW_COMDAT = 0x6ffffffb,
SHT_SUNW_syminfo = 0x6ffffffc,
SHT_GNU_verdef = 0x6ffffffd,
SHT_GNU_verneed = 0x6ffffffe,
SHT_GNU_versym = 0x6fffffff,
SHT_HISUNW = 0x6fffffff,
SHT_HIOS = 0x6fffffff,
SHT_LOPROC = 0x70000000,
SHT_HIPROC = 0x7fffffff,
SHT_LOUSER = 0x80000000,
SHT_HIUSER = 0x8fffffff
};
#define ELF32_R_SYM(i) ((i) >> 8)
#define ELF32_R_TYPE(i) ((unsigned char)(i))
#define ELF32_R_INFO(s, t) (((s) << 8) + (unsigned char)(t))
#define ELF64_R_SYM(i) ((i) >> 32)
#define ELF64_R_TYPE(i) ((i)&0xffffffffL)
#define ELF64_R_INFO(s, t) (((s) << 32) + ((t)&0xffffffffL))
#define EI_NIDENT 16
#define SHN_UNDEF 0
#define SHN_ABS 0xfff1
enum DynamicTags
{
DT_NULL = 0,
DT_NEEDED = 1,
DT_PLTRELSZ = 2,
DT_PLTGOT = 3,
DT_HASH = 4,
DT_STRTAB = 5,
DT_SYMTAB = 6,
DT_RELA = 7,
DT_RELASZ = 8,
DT_RELAENT = 9,
DT_STRSZ = 10,
DT_SYMENT = 11,
DT_INIT = 12,
DT_FINI = 13,
DT_SONAME = 14,
DT_RPATH = 15,
DT_SYMBOLIC = 16,
DT_REL = 17,
DT_RELSZ = 18,
DT_RELENT = 19,
DT_PLTREL = 20,
DT_DEBUG = 21,
DT_TEXTREL = 22,
DT_JMPREL = 23,
DT_BIND_NOW = 24,
DT_INIT_ARRAY = 25,
DT_FINI_ARRAY = 26,
DT_INIT_ARRAYSZ = 27,
DT_FINI_ARRAYSZ = 28,
DT_RUNPATH = 29,
DT_FLAGS = 30,
DT_ENCODING = 32,
DT_PREINIT_ARRAY = 32,
DT_PREINIT_ARRAYSZ = 33,
DT_LOOS = 0x6000000d,
DT_SUNW_RTLDINF = 0x6000000e,
DT_HIOS = 0x6ffff000,
DT_VALRNGLO = 0x6ffffd00,
DT_CHECKSUM = 0x6ffffdf8,
DT_PLTPADSZ = 0x6ffffdf9,
DT_MOVEENT = 0x6ffffdfa,
DT_MOVESZ = 0x6ffffdfb,
DT_FEATURE_1 = 0x6ffffdfc,
DT_POSFLAG_1 = 0x6ffffdfd,
DT_SYMINSZ = 0x6ffffdfe,
DT_SYMINENT = 0x6ffffdff,
DT_VALRNGHI = 0x6ffffdff,
DT_ADDRRNGLO = 0x6ffffe00,
DT_CONFIG = 0x6ffffefa,
DT_DEPAUDIT = 0x6ffffefb,
DT_AUDIT = 0x6ffffefc,
DT_PLTPAD = 0x6ffffefd,
DT_MOVETAB = 0x6ffffefe,
DT_SYMINFO = 0x6ffffeff,
DT_ADDRRNGHI = 0x6ffffeff,
DT_RELACOUNT = 0x6ffffff9,
DT_RELCOUNT = 0x6ffffffa,
DT_FLAGS_1 = 0x6ffffffb,
DT_VERDEF = 0x6ffffffc,
DT_VERDEFNUM = 0x6ffffffd,
DT_VERNEED = 0x6ffffffe,
DT_VERNEEDNUM = 0x6fffffff,
DT_LOPROC = 0x70000000,
DT_SPARC_REGISTER = 0x70000001,
DT_AUXILIARY = 0x7ffffffd,
DT_USED = 0x7ffffffe,
DT_FILTER = 0x7fffffff,
DT_HIPROC = 0x7fffffff
};
enum SegmentTypes
{
PT_NULL = 0,
PT_LOAD = 1,
PT_DYNAMIC = 2,
PT_INTERP = 3,
PT_NOTE = 4,
PT_SHLIB = 5,
PT_PHDR = 6,
PT_TLS = 7,
PT_LOSUNW = 0x6ffffffa,
PT_SUNWBSS = 0x6ffffffb,
PT_SUNWSTACK = 0x6ffffffa,
PT_HISUNW = 0x6fffffff,
PT_LOPROC = 0x70000000,
PT_HIPROC = 0x7fffffff
};
enum RtT_Types
{
R_386_NONE = 0,
R_386_32 = 1,
R_386_PC32 = 2,
R_X86_64_NONE = 0,
R_X86_64_64 = 1,
R_X86_64_PC32 = 2,
R_X86_64_GOT32 = 3,
R_X86_64_PLT32 = 4,
R_X86_64_COPY = 5,
R_X86_64_GLOB_DAT = 6,
R_X86_64_JUMP_SLOT = 7,
R_X86_64_RELATIVE = 8,
R_X86_64_GOTPCREL = 9,
R_X86_64_32 = 10,
R_X86_64_32S = 11,
R_X86_64_16 = 12,
};
typedef struct elf32_hdr
{
unsigned char e_ident[EI_NIDENT];
Elf32_Half e_type;
Elf32_Half e_machine;
Elf32_Word e_version;
Elf32_Addr e_entry;
Elf32_Off e_phoff;
Elf32_Off e_shoff;
Elf32_Word e_flags;
Elf32_Half e_ehsize;
Elf32_Half e_phentsize;
Elf32_Half e_phnum;
Elf32_Half e_shentsize;
Elf32_Half e_shnum;
Elf32_Half e_shstrndx;
} Elf32_Ehdr;
typedef struct elf64_hdr
{
unsigned char e_ident[EI_NIDENT];
Elf64_Half e_type;
Elf64_Half e_machine;
Elf64_Word e_version;
Elf64_Addr e_entry;
Elf64_Off e_phoff;
Elf64_Off e_shoff;
Elf64_Word e_flags;
Elf64_Half e_ehsize;
Elf64_Half e_phentsize;
Elf64_Half e_phnum;
Elf64_Half e_shentsize;
Elf64_Half e_shnum;
Elf64_Half e_shstrndx;
} Elf64_Ehdr;
typedef struct elf32_shdr
{
Elf32_Word sh_name;
Elf32_Word sh_type;
Elf32_Word sh_flags;
Elf32_Addr sh_addr;
Elf32_Off sh_offset;
Elf32_Word sh_size;
Elf32_Word sh_link;
Elf32_Word sh_info;
Elf32_Word sh_addralign;
Elf32_Word sh_entsize;
} Elf32_Shdr;
typedef struct elf64_shdr
{
Elf64_Word sh_name;
Elf64_Word sh_type;
Elf64_Xword sh_flags;
Elf64_Addr sh_addr;
Elf64_Off sh_offset;
Elf64_Xword sh_size;
Elf64_Word sh_link;
Elf64_Word sh_info;
Elf64_Xword sh_addralign;
Elf64_Xword sh_entsize;
} Elf64_Shdr;
struct Elf32_Dyn
{
Elf32_Sword d_tag;
union
{
Elf32_Word d_val;
Elf32_Addr d_ptr;
} d_un;
};
struct Elf64_Dyn
{
Elf64_Sxword d_tag;
union
{
Elf64_Xword d_val;
Elf64_Addr d_ptr;
} d_un;
};
typedef struct
{
Elf64_Word p_type;
Elf64_Word p_flags;
Elf64_Off p_offset;
Elf64_Addr p_vaddr;
Elf64_Addr p_paddr;
Elf64_Xword p_filesz;
Elf64_Xword p_memsz;
Elf64_Xword p_align;
} Elf64_Phdr;
typedef struct
{
Elf64_Addr r_offset;
Elf64_Xword r_info;
Elf64_Sxword r_addend;
} Elf64_Rela;
typedef struct elf64_sym
{
Elf64_Word st_name;
unsigned char st_info;
unsigned char st_other;
Elf64_Half st_shndx;
Elf64_Addr st_value;
Elf64_Xword st_size;
} Elf64_Sym;
#endif // !__FENNIX_LIB_ELF_LAZY_RESOLVE_H__

View File

@ -1,227 +0,0 @@
#include "fcts.h"
#include "../../../Kernel/syscalls.h"
#include "../../../Kernel/ipc.h"
uintptr_t RequestPages(size_t Count)
{
return syscall6(sc_mmap, NULL, Count * 0x1000,
sc_PROT_READ | sc_PROT_WRITE,
sc_MAP_ANONYMOUS | sc_MAP_PRIVATE,
0, 0);
}
int FreePages(uintptr_t Address, size_t Count)
{
return syscall2(sc_munmap, Address, Count * 0x1000);
}
int abs(int i) { return i < 0 ? -i : i; }
void swap(char *x, char *y)
{
char t = *x;
*x = *y;
*y = t;
}
char *reverse(char *Buffer, int i, int j)
{
while (i < j)
swap(&Buffer[i++], &Buffer[j--]);
return Buffer;
}
char *ltoa(long Value, char *Buffer, int Base)
{
if (Base < 2 || Base > 32)
return Buffer;
long n = (long)abs((int)Value);
int i = 0;
while (n)
{
int r = n % Base;
if (r >= 10)
Buffer[i++] = 65 + (r - 10);
else
Buffer[i++] = 48 + r;
n = n / Base;
}
if (i == 0)
Buffer[i++] = '0';
if (Value < 0 && Base == 10)
Buffer[i++] = '-';
Buffer[i] = '\0';
return reverse(Buffer, 0, i - 1);
}
void PutCharToKernelConsole(char c)
{
__asm__ __volatile__("syscall"
:
: "a"(1), "D"(c), "S"(0)
: "rcx", "r11", "memory");
}
void Print__(char *String)
{
for (short i = 0; String[i] != '\0'; i++)
PutCharToKernelConsole(String[i]);
}
void PrintNL__(char *String)
{
Print__(String);
Print__("\n");
}
void *memcpy(void *dest, const void *src, size_t n)
{
uint8_t *d = dest;
const uint8_t *s = src;
while (n--)
*d++ = *s++;
return dest;
}
void *memset(void *s, int c, size_t n)
{
uint8_t *p = s;
while (n--)
*p++ = c;
}
int strcmp(const char *l, const char *r)
{
for (; *l == *r && *l; l++, r++)
;
return *(unsigned char *)l - *(unsigned char *)r;
}
struct Elf64_Dyn ELFGetDynamicTag(char *Path, enum DynamicTags Tag)
{
int fd = syscall2(sc_open, Path, (long)"r");
if (fd < 0)
syscall1(sc_exit, -0xF17E);
Elf64_Ehdr ELFHeader;
syscall3(sc_read, fd, &ELFHeader, sizeof(Elf64_Ehdr));
Elf64_Phdr ItrProgramHeader;
for (Elf64_Half i = 0; i < ELFHeader.e_phnum; i++)
{
// memcpy(&ItrProgramHeader, (uint8_t *)ElfFile + ELFHeader.e_phoff + ELFHeader.e_phentsize * i, sizeof(Elf64_Phdr));
syscall3(sc_lseek, fd, ELFHeader.e_phoff + ELFHeader.e_phentsize * i, sc_SEEK_SET);
syscall3(sc_read, fd, &ItrProgramHeader, sizeof(Elf64_Phdr));
if (ItrProgramHeader.p_type == PT_DYNAMIC)
{
struct Elf64_Dyn Dynamic; // = (struct Elf64_Dyn *)((uint8_t *)ElfFile + ItrProgramHeader.p_offset);
syscall3(sc_lseek, fd, ItrProgramHeader.p_offset, sc_SEEK_SET);
syscall3(sc_read, fd, &Dynamic, ItrProgramHeader.p_filesz);
for (size_t i = 0; i < ItrProgramHeader.p_filesz / sizeof(struct Elf64_Dyn); i++)
{
if (Dynamic.d_tag == Tag || Dynamic.d_tag == DT_NULL)
{
syscall1(sc_close, fd);
return Dynamic;
}
syscall3(sc_lseek, fd, ItrProgramHeader.p_offset + (i + 1) * sizeof(struct Elf64_Dyn), sc_SEEK_SET);
syscall3(sc_read, fd, &Dynamic, sizeof(struct Elf64_Dyn));
}
}
}
syscall1(sc_close, fd);
return (struct Elf64_Dyn){0};
}
Elf64_Shdr *GetELFSheader(Elf64_Ehdr *Header)
{
Elf64_Off SheaderOffset = Header->e_shoff;
return (Elf64_Shdr *)((uintptr_t)Header + SheaderOffset);
}
Elf64_Shdr *GetELFSection(Elf64_Ehdr *Header, uint64_t Index)
{
Elf64_Shdr *Sheader = GetELFSheader(Header);
return &Sheader[Index];
}
char *GetELFStringTable(Elf64_Ehdr *Header)
{
if (Header->e_shstrndx == SHN_UNDEF)
return NULL;
return (char *)Header + GetELFSection(Header, Header->e_shstrndx)->sh_offset;
}
Elf64_Sym ELFLookupSymbol(char *Path, const char *Name)
{
int fd = syscall2(sc_open, Path, (long)"r");
if (fd < 0)
syscall1(sc_exit, -0xF17E);
Elf64_Ehdr ELFHeader;
syscall3(sc_read, fd, &ELFHeader, sizeof(Elf64_Ehdr));
Elf64_Shdr SymbolTable;
Elf64_Shdr StringTable;
Elf64_Sym Symbol;
char *String = NULL;
for (Elf64_Half i = 0; i < ELFHeader.e_shnum; i++)
{
Elf64_Shdr shdr;
syscall3(sc_lseek, fd,
ELFHeader.e_shoff + ELFHeader.e_shentsize * i,
sc_SEEK_SET);
syscall3(sc_read, fd, &shdr, sizeof(Elf64_Shdr));
switch (shdr.sh_type)
{
case SHT_SYMTAB:
{
SymbolTable = shdr;
syscall3(sc_lseek, fd,
ELFHeader.e_shoff + ELFHeader.e_shentsize * shdr.sh_link,
sc_SEEK_SET);
syscall3(sc_read, fd, &StringTable, sizeof(Elf64_Shdr));
break;
}
default:
{
break;
}
}
}
if (SymbolTable.sh_size == 0 || StringTable.sh_size == 0)
{
syscall1(sc_close, fd);
return (Elf64_Sym){0};
}
for (size_t i = 0; i < (SymbolTable.sh_size / sizeof(Elf64_Sym)); i++)
{
// Symbol = (Elf64_Sym *)((uintptr_t)Header + SymbolTable->sh_offset + (i * sizeof(Elf64_Sym)));
// String = (char *)((uintptr_t)Header + StringTable->sh_offset + Symbol->st_name);
syscall3(sc_lseek, fd, SymbolTable.sh_offset + (i * sizeof(Elf64_Sym)), sc_SEEK_SET);
syscall3(sc_read, fd, &Symbol, sizeof(Elf64_Sym));
syscall3(sc_lseek, fd, StringTable.sh_offset + Symbol.st_name, sc_SEEK_SET);
syscall3(sc_read, fd, &String, sizeof(char *));
if (strcmp(String, Name) == 0)
{
syscall1(sc_close, fd);
return Symbol;
}
}
syscall1(sc_close, fd);
return (Elf64_Sym){0};
}

View File

@ -1,31 +0,0 @@
#ifndef __FENNIX_LIBC_FUNCTIONS_H__
#define __FENNIX_LIBC_FUNCTIONS_H__
#include <types.h>
#include "elf.h"
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
uintptr_t RequestPages(size_t Count);
int FreePages(uintptr_t Address, size_t Count);
int IPC(int Command, int Type, int ID, int Flags, void *Buffer, size_t Size);
uintptr_t KernelCTL(int Command, uint64_t Arg1, uint64_t Arg2, uint64_t Arg3, uint64_t Arg4);
int abs(int i);
void swap(char *x, char *y);
char *reverse(char *Buffer, int i, int j);
char *ltoa(long Value, char *Buffer, int Base);
void PutCharToKernelConsole(char c);
void Print__(char *String);
void PrintNL__(char *String);
void *memcpy(void *dest, const void *src, size_t n);
void *memset(void *s, int c, size_t n);
int strcmp(const char *l, const char *r);
struct Elf64_Dyn ELFGetDynamicTag(char *Path, enum DynamicTags Tag);
Elf64_Shdr *GetELFSheader(Elf64_Ehdr *Header);
Elf64_Shdr *GetELFSection(Elf64_Ehdr *Header, uint64_t Index);
char *GetELFStringTable(Elf64_Ehdr *Header);
Elf64_Sym ELFLookupSymbol(char *Path, const char *Name);
#endif // !__FENNIX_LIBC_FUNCTIONS_H__

View File

@ -1,14 +0,0 @@
#include "ld.h"
uint32_t ElfHash(const unsigned char *Name)
{
uint32_t i = 0, j;
while (*Name)
{
i = (i << 4) + *Name++;
if ((j = i & 0xF0000000) != 0)
i ^= j >> 24;
i &= ~j;
}
return i;
}

View File

@ -1,324 +0,0 @@
#include "ld.h"
#include "fcts.h"
#include "../../../Kernel/syscalls.h"
#include "../../../Kernel/ipc.h"
#include "elf.h"
#define Print(x) Print__(x)
#define PrintNL(x) PrintNL__(x)
#if (1)
#define PrintDbg(x) Print__(x)
#define PrintDbgNL(x) PrintNL__(x)
#define ltoaDbg(x, y, z) ltoa(x, y, z)
#else
#define PrintDbg(x)
#define PrintDbgNL(x)
#define ltoaDbg(x, y, z)
#endif
struct InterpreterIPCDataLibrary
{
char Name[64];
};
typedef struct
{
char Path[256];
void *MemoryImage;
struct InterpreterIPCDataLibrary Libraries[64];
} InterpreterIPCData;
struct LibsCollection
{
char ParentName[32];
char LibraryName[32];
uintptr_t ParentMemoryImage;
uintptr_t LibraryMemoryImage;
struct LibsCollection *Next;
char Valid;
};
static char ParentPath[256];
static char Lock = 0;
__attribute__((naked, used, no_stack_protector)) void ELF_LAZY_RESOLVE_STUB()
{
while (Lock == 1)
;
__asm__ __volatile__("mfence\n");
Lock = 1;
__asm__ __volatile__("pop %r11\n"
"pop %r10\n"
"push %rdi\n"
"push %rsi\n"
"push %rdx\n"
"push %rcx\n"
"push %r8\n"
"push %r9\n"
"mov %r11, %rdi\n" // Move the first argument to rdi (libs collection)
"mov %r10, %rsi\n" // Move the second argument to rsi (rel index)
"call ELF_LAZY_RESOLVE_MAIN\n"
"mov %rax, %r11\n" // Move the return value to r11
"pop %r9\n"
"pop %r8\n"
"pop %rcx\n"
"pop %rdx\n"
"pop %rsi\n"
"pop %rdi\n"
"jmp *%r11\n"); // Jump to the return value
}
void (*ELF_LAZY_RESOLVE_MAIN(struct LibsCollection *Info, long RelIndex))()
{
if (!Info)
goto FailEnd;
char DbgBuff[32];
char LibraryPathBuffer[256];
struct LibsCollection *CurLib = Info;
PrintDbgNL("_______");
/* The last entry is the null entry (Valid == false)
which determines the end of the list. */
while (CurLib->Valid)
{
PrintDbg("-- ");
PrintDbg(LibraryPathBuffer);
PrintDbg(" ");
ltoaDbg(RelIndex, DbgBuff, 10);
PrintDbg(DbgBuff);
PrintDbgNL(" --");
uintptr_t lib_BaseAddress = __UINTPTR_MAX__;
uintptr_t app_BaseAddress = __UINTPTR_MAX__;
Elf64_Ehdr lib_Header;
Elf64_Ehdr app_Header;
int fd_lib = syscall2(sc_open, LibraryPathBuffer, "r");
int fd_app = syscall2(sc_open, ParentPath, "r");
if (fd_lib < 0)
{
PrintNL("Failed to open library");
goto RetryNextLib;
}
if (fd_app < 0)
{
PrintNL("Failed to open application");
goto RetryNextLib;
}
syscall3(sc_read, fd_lib, &lib_Header, sizeof(Elf64_Ehdr));
syscall3(sc_read, fd_app, &app_Header, sizeof(Elf64_Ehdr));
Elf64_Phdr ItrProgramHeader;
for (Elf64_Half i = 0; i < lib_Header.e_phnum; i++)
{
syscall3(sc_lseek, fd_lib,
lib_Header.e_phoff +
lib_Header.e_phentsize * i,
sc_SEEK_SET);
syscall3(sc_read, fd_lib, &ItrProgramHeader, sizeof(Elf64_Phdr));
lib_BaseAddress = MIN(lib_BaseAddress, ItrProgramHeader.p_vaddr);
}
for (Elf64_Half i = 0; i < app_Header.e_phnum; i++)
{
syscall3(sc_lseek, fd_app,
app_Header.e_phoff +
app_Header.e_phentsize * i,
sc_SEEK_SET);
syscall3(sc_read, fd_app, &ItrProgramHeader, sizeof(Elf64_Phdr));
app_BaseAddress = MIN(app_BaseAddress, ItrProgramHeader.p_vaddr);
}
struct Elf64_Dyn lib_JmpRel = ELFGetDynamicTag(LibraryPathBuffer, DT_JMPREL);
struct Elf64_Dyn lib_SymTab = ELFGetDynamicTag(LibraryPathBuffer, DT_SYMTAB);
struct Elf64_Dyn lib_StrTab = ELFGetDynamicTag(LibraryPathBuffer, DT_STRTAB);
struct Elf64_Dyn app_JmpRel = ELFGetDynamicTag(ParentPath, DT_JMPREL);
struct Elf64_Dyn app_SymTab = ELFGetDynamicTag(ParentPath, DT_SYMTAB);
struct Elf64_Dyn app_StrTab = ELFGetDynamicTag(ParentPath, DT_STRTAB);
if (!lib_JmpRel.d_tag == 0)
{
PrintNL("No DT_JMPREL");
// goto RetryNextLib;
}
else if (RelIndex >= lib_JmpRel.d_un.d_val /
sizeof(Elf64_Rela))
{
PrintNL("RelIndex is greater than the number of relocations");
goto RetryNextLib;
}
if (!lib_SymTab.d_tag == 0)
{
PrintNL("No DT_SYMTAB");
goto RetryNextLib;
}
if (!lib_StrTab.d_tag == 0)
{
PrintNL("No DT_STRTAB");
goto RetryNextLib;
}
if (!lib_SymTab.d_tag == 0 &&
!lib_StrTab.d_tag == 0)
goto RetryNextLib;
Elf64_Rela *_lib_JmpRel = (Elf64_Rela *)(CurLib->LibraryMemoryImage + (lib_JmpRel.d_un.d_ptr - lib_BaseAddress));
Elf64_Sym *_lib_SymTab = (Elf64_Sym *)(CurLib->LibraryMemoryImage + (lib_SymTab.d_un.d_ptr - lib_BaseAddress));
Elf64_Rela *_app_JmpRel = (Elf64_Rela *)(CurLib->ParentMemoryImage + (app_JmpRel.d_un.d_ptr - app_BaseAddress));
Elf64_Sym *_app_SymTab = (Elf64_Sym *)(CurLib->ParentMemoryImage + (app_SymTab.d_un.d_ptr - app_BaseAddress));
char *lib_DynStr = (char *)(CurLib->LibraryMemoryImage + (lib_StrTab.d_un.d_ptr - lib_BaseAddress));
char *app_DynStr = (char *)(CurLib->ParentMemoryImage + (app_StrTab.d_un.d_ptr - app_BaseAddress));
Elf64_Rela *Rel = _app_JmpRel + RelIndex;
Elf64_Addr *GOTEntry = (Elf64_Addr *)(Rel->r_offset);
int RelType = ELF64_R_TYPE(Rel->r_info);
switch (RelType)
{
case R_X86_64_NONE:
{
PrintDbgNL("R_X86_64_NONE");
if (*GOTEntry == 0)
{
PrintDbgNL("GOTEntry is 0");
break;
}
Lock = 0;
return (void (*)()) * GOTEntry;
}
case R_X86_64_JUMP_SLOT:
{
PrintDbgNL("R_X86_64_JUMP_SLOT");
int SymIndex = ELF64_R_SYM(Rel->r_info);
Elf64_Sym *Sym = _app_SymTab + SymIndex;
if (Sym->st_name)
{
char *SymName = app_DynStr + Sym->st_name;
PrintDbg("SymName: ");
PrintDbgNL(SymName);
Elf64_Sym LibSym = ELFLookupSymbol(ParentPath, SymName);
PrintDbg("LibSym: 0x");
ltoaDbg((long)LibSym.st_size, DbgBuff, 16);
PrintDbgNL(DbgBuff);
if (LibSym.st_value)
{
*GOTEntry = (Elf64_Addr)(CurLib->LibraryMemoryImage + LibSym.st_value);
ltoa(*GOTEntry, DbgBuff, 16);
PrintDbg("*GOTEntry: 0x");
PrintDbgNL(DbgBuff);
Lock = 0;
return (void (*)()) * GOTEntry;
}
PrintDbgNL("Not found in lib");
}
break;
}
default:
{
ltoa(RelType, DbgBuff, 10);
Print("RelType not supported ");
PrintNL(DbgBuff);
break;
}
}
RetryNextLib:
PrintDbgNL("Retrying next lib");
CurLib = CurLib->Next;
}
FailEnd:
Lock = 0;
__asm__ __volatile__("mfence\n");
Print("Symbol index ");
ltoa(RelIndex, DbgBuff, 10);
Print(DbgBuff);
PrintNL(" not found");
int ExitCode = 0x51801;
syscall1(sc_exit, ExitCode);
while (1) // Make sure we don't return
;
}
/* Preload */
int ld_main()
{
/* Prevent race condition. */
// uintptr_t KCTL_ret = KernelCTL(KCTL_IS_CRITICAL, 0, 0, 0, 0);
// do
// {
// syscall1(sys_Sleep, 250);
// KCTL_ret = KernelCTL(KCTL_IS_CRITICAL, 0, 0, 0, 0);
// } while (KCTL_ret == false);
// if (KCTL_ret == false)
// return -1;
/* Everything is ok, continue. */
return 0;
}
bool ELFAddLazyResolverToGOT(void *MemoryImage, struct LibsCollection *Libs)
{
struct Elf64_Dyn Dyn = ELFGetDynamicTag(ParentPath, DT_PLTGOT);
if (!Dyn.d_tag)
return false;
Elf64_Addr *GOT = (Elf64_Addr *)Dyn.d_un.d_ptr;
GOT[1] = (uintptr_t)Libs;
GOT[2] = (uintptr_t)ELF_LAZY_RESOLVE_STUB;
return true;
}
/* Actual load */
int ld_load(int argc, char *argv[], char *envp[])
{
PrintDbgNL("Calling entry point");
// void *KP = syscall2(sc_open, ParentPath, (long)"r");
// if (KP == NULL)
// {
// PrintNL("Failed to open file");
// syscall1(sys_Exit, -0xF17E);
// }
// Elf64_Ehdr ELFHeader;
// syscall3(sc_read, KP, &ELFHeader, sizeof(Elf64_Ehdr));
// Elf64_Addr Entry = ELFHeader.e_entry;
// syscall1(sys_FileClose, KP);
// return ((int (*)(int, char *[], char *[]))Entry)(argc, argv, envp);
}

View File

@ -1,8 +0,0 @@
#ifndef __FENNIX_LIBC_LD_H__
#define __FENNIX_LIBC_LD_H__
#include <types.h>
uint32_t ElfHash(const unsigned char *Name);
#endif // !__FENNIX_LIBC_LD_H__

View File

@ -1,36 +0,0 @@
void __attribute__((naked, used, no_stack_protector)) _start()
{
__asm__("movq $0, %rbp\n"
"pushq %rbp\n"
"pushq %rbp\n"
"movq %rsp, %rbp\n"
"pushq %rcx\n"
"pushq %rdx\n"
"pushq %rsi\n"
"pushq %rdi\n"
"call ld_main\n"
"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
"popq %rdi\n"
"popq %rsi\n"
"popq %rdx\n"
"popq %rcx\n"
"call ld_load\n"
"movl %eax, %edi\n" // Move return value to edi
"call _exit"); // Call _exit
}
void _exit(int Code)
{
__asm__ __volatile__("syscall"
:
: "a"(0), "D"(Code)
: "rcx", "r11", "memory");
while (1)
;
}

View File

@ -1,250 +0,0 @@
/* This function is a mess and needs to be cleaned up. */
bool ELFDynamicReallocation(void *ElfFile, void *MemoryImage)
{
debug("ELF dynamic reallocation for image at %#lx.", ElfFile);
Elf64_Ehdr *ELFHeader = (Elf64_Ehdr *)ElfFile;
uintptr_t BaseAddress = UINTPTR_MAX;
size_t ElfAppSize = 0;
Elf64_Phdr ItrPhdr;
for (Elf64_Half i = 0; i < ELFHeader->e_phnum; i++)
{
memcpy(&ItrPhdr,
(uint8_t *)ElfFile + ELFHeader->e_phoff + ELFHeader->e_phentsize * i,
sizeof(Elf64_Phdr));
BaseAddress = MIN(BaseAddress, ItrPhdr.p_vaddr);
}
for (Elf64_Half i = 0; i < ELFHeader->e_phnum; i++)
{
memcpy(&ItrPhdr,
(uint8_t *)ElfFile + ELFHeader->e_phoff + ELFHeader->e_phentsize * i,
sizeof(Elf64_Phdr));
uintptr_t SegmentEnd = ItrPhdr.p_vaddr - BaseAddress + ItrPhdr.p_memsz;
ElfAppSize = MAX(ElfAppSize, SegmentEnd);
}
debug("BaseAddress: %#lx Size: %ld", BaseAddress, ElfAppSize);
Elf64_Dyn *_GOTEntry = (Elf64_Dyn *)ELFGetDynamicTag(ElfFile, DT_PLTGOT);
Elf64_Dyn *_Rela = ELFGetDynamicTag(ElfFile, DT_RELA);
Elf64_Dyn *_RelaEnt = ELFGetDynamicTag(ElfFile, DT_RELAENT);
Elf64_Dyn *_JmpRel = ELFGetDynamicTag(ElfFile, DT_JMPREL);
Elf64_Dyn *_SymTab = ELFGetDynamicTag(ElfFile, DT_SYMTAB);
Elf64_Dyn *_StrTab = ELFGetDynamicTag(ElfFile, DT_STRTAB);
Elf64_Dyn *RelaSize = ELFGetDynamicTag(ElfFile, DT_RELASZ);
Elf64_Dyn *PltRelSize = ELFGetDynamicTag(ElfFile, DT_PLTRELSZ);
Elf64_Addr *GOTEntry = (Elf64_Addr *)((uintptr_t)(_GOTEntry->d_un.d_ptr - BaseAddress) + (uintptr_t)MemoryImage);
Elf64_Dyn *Rela = (Elf64_Dyn *)((uintptr_t)(_Rela->d_un.d_ptr - BaseAddress) + (uintptr_t)MemoryImage);
Elf64_Dyn *RelaEnt = (Elf64_Dyn *)((uintptr_t)(_RelaEnt->d_un.d_ptr - BaseAddress) + (uintptr_t)MemoryImage);
Elf64_Dyn *JmpRel = (Elf64_Dyn *)((uintptr_t)(_JmpRel->d_un.d_ptr - BaseAddress) + (uintptr_t)MemoryImage);
Elf64_Dyn *SymTab = (Elf64_Dyn *)((uintptr_t)(_SymTab->d_un.d_ptr - BaseAddress) + (uintptr_t)MemoryImage);
Elf64_Dyn *StrTab = (Elf64_Dyn *)((uintptr_t)(_StrTab->d_un.d_ptr - BaseAddress) + (uintptr_t)MemoryImage);
debug("GOTEntry: %#lx [%#lx]", _GOTEntry, GOTEntry);
debug("Rela: %#lx [%#lx]", _Rela, Rela);
debug("RelaEnt: %#lx [%#lx]", _RelaEnt, RelaEnt);
debug("JmpRel: %#lx [%#lx]", _JmpRel, JmpRel);
debug("SymTab: %#lx [%#lx]", _SymTab, SymTab);
debug("StrTab: %#lx [%#lx]", _StrTab, StrTab);
if (RelaSize)
debug("RelaSize: %ld", RelaSize->d_un.d_val);
if (PltRelSize)
debug("PltRelSize: %ld", PltRelSize->d_un.d_val);
Elf64_Xword PltRelSizeVal = PltRelSize ? PltRelSize->d_un.d_val : 0;
Elf64_Xword RelaSizeVal = RelaSize ? RelaSize->d_un.d_val : 0;
Elf64_Xword PltRelSizeValCount = PltRelSizeVal / sizeof(Elf64_Rela);
Elf64_Xword RelaSizeValCount = RelaSizeVal / sizeof(Elf64_Rela);
debug("PltRelSizeVal: %ld", PltRelSizeVal);
debug("RelaSizeVal: %ld", RelaSizeVal);
debug("PltRelSizeValCount: %ld", PltRelSizeValCount);
debug("RelaSizeValCount: %ld", RelaSizeValCount);
for (Elf64_Xword i = 0; i < PltRelSizeValCount; i++)
{
Elf64_Rela *RelaF = (Elf64_Rela *)((uintptr_t)JmpRel + i);
Elf64_Xword RelaType = ELF64_R_TYPE(RelaF->r_info);
debug("Itr %ld Type %ld", i, RelaType);
switch (RelaType)
{
case R_X86_64_NONE:
{
debug("No relocation needed");
break;
}
case R_X86_64_JUMP_SLOT:
{
debug("Relocation for jump slot");
Elf64_Xword SymIndex = ELF64_R_SYM(RelaF->r_info);
Elf64_Sym *Sym = (Elf64_Sym *)((uintptr_t)SymTab + SymIndex);
char *SymName = (char *)((uintptr_t)StrTab + Sym->st_name);
debug("Symbol %s at %#lx", SymName, Sym->st_value);
Elf64_Addr *GOTEntry = (Elf64_Addr *)RelaF->r_offset;
if (Sym->st_value)
{
fixme("Not implemented");
*GOTEntry = (Elf64_Addr)ElfFile + Sym->st_value;
}
// else
// *GOTEntry = (Elf64_Addr)ElfLazyResolver;
// Elf64_Sym *Sym = (Elf64_Sym *)((uintptr_t)ElfFile + (uintptr_t)SymTab + ELF64_R_SYM(RelaF->r_info) * sizeof(Elf64_Sym));
// char *SymName = (char *)((uintptr_t)ElfFile + (uintptr_t)StrTab + Sym->st_name);
// void *SymAddr = (void *)Lib->Address + Sym->st_value;
// debug("Symbol %s at %#lx", SymName, SymAddr);
// *(void **)(RelaF->r_offset + (uintptr_t)ElfFile) = SymAddr;
break;
}
case R_X86_64_RELATIVE:
{
debug("Relative relocation");
uintptr_t *Ptr = (uintptr_t *)((uintptr_t)ElfFile + RelaF->r_offset);
*Ptr = (uintptr_t)MemoryImage + RelaF->r_addend;
break;
}
default:
{
fixme("RelaType %d", RelaType);
break;
}
}
}
for (Elf64_Xword i = 0; i < RelaSizeValCount; i++)
{
Elf64_Rela *RelaF = (Elf64_Rela *)((uintptr_t)ElfFile + (uintptr_t)Rela + i);
Elf64_Xword RelaType = ELF64_R_TYPE(RelaF->r_info);
debug("Itr %ld Type %ld", i, RelaType);
switch (RelaType)
{
case R_X86_64_NONE:
{
debug("No relocation needed");
break;
}
case R_X86_64_64:
{
debug("64-bit relocation");
Elf64_Xword SymIndex = ELF64_R_SYM(RelaF->r_info);
Elf64_Sym *Sym = (Elf64_Sym *)((uintptr_t)ElfFile + (uintptr_t)SymTab + SymIndex);
char *SymName = (char *)((uintptr_t)ElfFile + (uintptr_t)StrTab + Sym->st_name);
debug("Symbol %s at %#lx", SymName, Sym->st_value);
uintptr_t *Ptr = (uintptr_t *)((uintptr_t)ElfFile + RelaF->r_offset);
*Ptr = (uintptr_t)MemoryImage + Sym->st_value + RelaF->r_addend;
break;
}
case R_X86_64_GLOB_DAT:
{
debug("Global data relocation");
Elf64_Xword SymIndex = ELF64_R_SYM(RelaF->r_info);
Elf64_Sym *Sym = (Elf64_Sym *)((uintptr_t)ElfFile + (uintptr_t)SymTab + SymIndex);
char *SymName = (char *)((uintptr_t)ElfFile + (uintptr_t)StrTab + Sym->st_name);
debug("Symbol %s at %#lx", SymName, Sym->st_value);
uintptr_t *Ptr = (uintptr_t *)((uintptr_t)ElfFile + RelaF->r_offset);
*Ptr = (uintptr_t)MemoryImage + Sym->st_value;
break;
}
case R_X86_64_RELATIVE:
{
debug("Relative relocation");
Elf64_Xword SymIndex = ELF64_R_SYM(RelaF->r_info);
Elf64_Sym *Sym = (Elf64_Sym *)((uintptr_t)ElfFile + (uintptr_t)SymTab + SymIndex);
char *SymName = (char *)((uintptr_t)ElfFile + (uintptr_t)StrTab + Sym->st_name);
debug("Symbol %s at %#lx", SymName, Sym->st_value);
uintptr_t *Ptr = (uintptr_t *)((uintptr_t)ElfFile + RelaF->r_offset);
*Ptr = (uintptr_t)MemoryImage + RelaF->r_addend;
break;
}
default:
{
fixme("RelaType %d", RelaType);
break;
}
}
}
return true;
}
ELFDynamicReallocation(ElfFile, MemoryImage);
LibAddressCollection *LibsForLazyResolver = (LibAddressCollection *)ELFBase.TmpMem->RequestPages(TO_PAGES(sizeof(LibAddressCollection)), true);
memset(LibsForLazyResolver, 0, sizeof(LibAddressCollection));
LibAddressCollection *LFLRTmp = LibsForLazyResolver;
debug("LibsForLazyResolver: %#lx", LibsForLazyResolver);
if (NeededLibraries.size() > 0)
{
VirtualFileSystem::Node *ParentNode = ExFile->Node->Parent; // Working Directory
if (ParentNode)
{
char *WorkingDirAbsolutePath = vfs->GetPathFromNode(ParentNode);
debug("Working directory: \"%s\"", WorkingDirAbsolutePath);
int LibCount = 0;
foreach (auto Library in NeededLibraries)
{
char LibPath[256];
strcpy(LibPath, WorkingDirAbsolutePath);
strcat(LibPath, "/");
strcat(LibPath, Library);
debug("Searching for \"%s\"...", LibPath);
bool AlreadyTried = false;
LibPathRetry:
VirtualFileSystem::FILE *LibNode = vfs->Open(LibPath);
if (LibNode->Status != VirtualFileSystem::FileStatus::OK)
{
vfs->Close(LibNode);
if (!AlreadyTried)
{
debug("Library \"%s\" not found, retrying... (%#x)", LibPath, LibNode->Status);
memset(LibPath, 0, 256);
strcpy(LibPath, "/lib/");
strcat(LibPath, Library);
AlreadyTried = true;
goto LibPathRetry;
}
else
warn("Failed to load library \"%s\" (%#x)", Library, LibNode->Status);
}
else
{
debug("Library found \"%s\" (%#x)", LibPath, LibNode->Status);
SharedLibraries *sl = AddLibrary(Library, (void *)LibNode->Node->Address, LibNode->Node->Length);
strcpy(LFLRTmp->Name, Library);
LFLRTmp->ElfFile = (uintptr_t *)sl->Address;
LFLRTmp->MemoryImage = (uintptr_t *)sl->MemoryImage;
LFLRTmp->ParentElfFile = (uintptr_t *)ElfFile;
LFLRTmp->ParentMemoryImage = (uintptr_t *)MemoryImage;
LFLRTmp->Valid = true;
debug("LIBRARY: %s, %#lx, %#lx", Library, LFLRTmp->ElfFile, LFLRTmp->MemoryImage);
LFLRTmp->Next = (LibAddressCollection *)ELFBase.TmpMem->RequestPages(TO_PAGES(sizeof(LibAddressCollection)), true);
LFLRTmp = LFLRTmp->Next;
memset(LFLRTmp, 0, sizeof(LibAddressCollection));
}
}
}
else
{
error("Couldn't get the parent node from path %s", vfs->GetPathFromNode(ExFile->Node));
}
}
ELFAddLazyResolverToGOT(ElfFile, MemoryImage, LibsForLazyResolver);

View File

@ -1,11 +1,12 @@
build:
cp -r include/* ../out/include
cp ../Kernel/include/interface/syscalls.h ../out/include/fennix/syscall.h
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
make -C ElfInterpreter build
clean:
make -C interpreter clean
make -C runtime clean
make -C src clean
make -C ElfInterpreter clean

39
Userspace/libc/STATUS.md Normal file
View File

@ -0,0 +1,39 @@
# FENNIX C LIBRARY STATUS
[IEEE Std 1003.1™-2024 Edition](https://pubs.opengroup.org/onlinepubs/9799919799/)
| FILE | STATUS |
|---------------|-----------|
| | |
| fennix/syscalls.h | PROVIDE |
| sys/mman.h | TODO |
| sys/stat.h | TODO |
| sys/types.h | TODO |
| sys/wait.h | TODO |
| assert.h | COMPLETE|
| dirent.h | TODO |
| errno.h | PROVIDE |
| fcntl.h | TODO |
| float.h | TODO |
| inttypes.h | TODO |
| limits.h | TODO |
| locale.h | TODO |
| math.h | TODO |
| pthread.h | TODO |
| pwd.h | TODO |
| sched.h | TODO |
| signal.h | TODO |
| stdarg.h | TODO |
| stdbool.h | COMPLETE|
| stddef.h | TODO |
| stdint.h | TODO |
| stdio.h | TODO |
| stdlib.h | TODO |
| string.h | TODO |
| time.h | TODO |
| unistd.h | TODO |
---
[functions](https://pubs.opengroup.org/onlinepubs/9799919799/functions/)
[basedefs](https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/)

View File

@ -1,4 +1,43 @@
/*
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 _ASSERT_H
#define _ASSERT_H
#endif
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
void __assert_fail(const char *file, int line, const char *func) __attribute__((noreturn));
#ifdef NDEBUG
#define assert(e) ((void)0)
#else // NDEBUG
#define assert(e) \
do \
{ \
if (__builtin_expect(!!(!(e)), 0)) \
__assert_fail(__FILE__, __LINE__, __func__); \
} while (0)
#endif // NDEBUG
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // !_ASSERT_H

View File

@ -1,69 +0,0 @@
#ifndef __FENNIX_LIBC_AUX_H__
#define __FENNIX_LIBC_AUX_H__
#include <stddef.h>
#define AT_NULL 0
#define AT_IGNORE 1
#define AT_EXECFD 2
#define AT_PHDR 3
#define AT_PHENT 4
#define AT_PHNUM 5
#define AT_PAGESZ 6
#define AT_BASE 7
#define AT_FLAGS 8
#define AT_ENTRY 9
#define AT_NOTELF 10
#define AT_UID 11
#define AT_EUID 12
#define AT_GID 13
#define AT_EGID 14
#define AT_PLATFORM 15
#define AT_HWCAP 16
#define AT_CLKTCK 17
#define AT_SECURE 23
#define AT_BASE_PLATFORM 24
#define AT_RANDOM 25
#define AT_HWCAP2 26
#define AT_EXECFN 31
#define AT_SYSINFO 32
#define AT_SYSINFO_EHDR 33
#define AT_L1I_CACHESHAPE 34
#define AT_L1D_CACHESHAPE 35
#define AT_L2_CACHESHAPE 36
#define AT_L3_CACHESHAPE 37
#define AT_L1I_CACHESIZE 40
#define AT_L1I_CACHEGEOMETRY 41
#define AT_L1D_CACHESIZE 42
#define AT_L1D_CACHEGEOMETRY 43
#define AT_L2_CACHESIZE 44
#define AT_L2_CACHEGEOMETRY 45
#define AT_L3_CACHESIZE 46
#define AT_L3_CACHEGEOMETRY 47
#define AT_MINSIGSTKSZ 51
typedef struct
{
uint32_t a_type;
union
{
uint32_t a_val;
} a_un;
} Elf32_auxv_t;
typedef struct
{
uint64_t a_type;
union
{
uint64_t a_val;
} a_un;
} Elf64_auxv_t;
#ifdef __LP64__
#define Elf_auxv_t Elf64_auxv_t
#else
#define Elf_auxv_t Elf32_auxv_t
#endif
#endif // !__FENNIX_LIBC_AUX_H__

View File

@ -1,6 +0,0 @@
#ifndef _BITS_TYPES_SIGSET_T_H
#define _BITS_TYPES_SIGSET_T_H
typedef unsigned long sigset_t;
#endif // !_BITS_TYPES_SIGSET_T_H

View File

@ -1,9 +0,0 @@
#ifndef _BITS_TYPES_STRUCT_SCHED_PARAM_T_H
#define _BITS_TYPES_STRUCT_SCHED_PARAM_T_H
struct sched_param
{
int sched_priority;
};
#endif // !_BITS_TYPES_STRUCT_SCHED_PARAM_T_H

View File

@ -0,0 +1,38 @@
/*
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 _TIMESPEC_DEFINED
#define _TIMESPEC_DEFINED
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
#include <sys/types.h>
typedef struct timespec
{
time_t tv_sec; /* Whole seconds. */
long tv_nsec; /* Nanoseconds [0, 999999999]. */
} timespec;
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // !_TIMESPEC_DEFINED

View File

@ -1,14 +0,0 @@
#ifndef _BITS_WAITSTATUS_H
#define _BITS_WAITSTATUS_H
#define __W_CONTINUED 0xFFFF
#define __WEXITSTATUS(status) (((status)&0xFF00) >> 8)
#define __WTERMSIG(status) ((status)&0x7F)
#define __WSTOPSIG(status) __WEXITSTATUS(status)
#define __WIFEXITED(status) (__WTERMSIG(status) == 0)
#define __WIFSIGNALED(status) (((signed char)(((status)&0x7F) + 1) >> 1) > 0)
#define __WIFSTOPPED(status) (((status)&0xFF) == 0x7F)
#define __WIFCONTINUED(status) ((status) == __W_CONTINUED)
#endif

View File

@ -1,8 +0,0 @@
#ifndef _CTYPE_H
#define _CTYPE_H
int tolower(int c);
int toupper(int c);
int isspace(int c);
#endif // !_CTYPE_H

View File

@ -0,0 +1,78 @@
/*
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 _DIRENT_H
#define _DIRENT_H
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
#include <sys/types.h>
typedef struct dirent
{
ino_t d_ino; /* File serial number. */
char d_name[]; /* Filename string of entry. */
} dirent;
typedef struct posix_dent
{
ino_t d_ino; /* File serial number. */
reclen_t d_reclen; /* Length of this entry, including trailing padding if necessary. See posix_getdents(). */
unsigned char d_type; /* File type or unknown-file-type indication. */
char d_name[]; /* Filename string of this entry. */
} posix_dent;
typedef struct DIR
{
int __fd;
} DIR;
#define DT_BLK
#define DT_CHR
#define DT_DIR
#define DT_FIFO
#define DT_LNK
#define DT_REG
#define DT_SOCK
#define DT_UNKNOWN
#define DT_MQ
#define DT_SEM
#define DT_SHM
#define DT_TMO
int alphasort(const struct dirent **, const struct dirent **);
int closedir(DIR *);
int dirfd(DIR *);
DIR *fdopendir(int);
DIR *opendir(const char *);
ssize_t posix_getdents(int, void *, size_t, int);
struct dirent *readdir(DIR *);
int readdir_r(DIR *restrict, struct dirent *restrict, struct dirent **restrict);
void rewinddir(DIR *);
int scandir(const char *, struct dirent ***, int (*)(const struct dirent *), int (*)(const struct dirent **, const struct dirent **));
void seekdir(DIR *, long);
long telldir(DIR *);
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // !_DIRENT_H

View File

@ -1,11 +0,0 @@
#ifndef __FENNIX_LIBC_DLFCN_H__
#define __FENNIX_LIBC_DLFCN_H__
#include <types.h>
void *dlopen(const char *filename, int flags);
void *dlsym(void *handle, const char *symbol);
int dlclose(void *handle);
char *dlerror(void);
#endif // !__FENNIX_LIBC_DLFCN_H__

View File

@ -1,137 +1,605 @@
#ifndef _ERRNO_H
#define _ERRNO_H
/*
This file is part of Fennix Kernel.
#define EPERM 1 /* Operation not permitted */
#define ENOENT 2 /* No such file or directory */
#define ESRCH 3 /* No such process */
#define EINTR 4 /* Interrupted system call */
#define EIO 5 /* I/O error */
#define ENXIO 6 /* No such device or address */
#define E2BIG 7 /* Argument list too long */
#define ENOEXEC 8 /* Exec format error */
#define EBADF 9 /* Bad file number */
#define ECHILD 10 /* No child processes */
#define EAGAIN 11 /* Try again */
#define ENOMEM 12 /* Out of memory */
#define EACCES 13 /* Permission denied */
#define EFAULT 14 /* Bad address */
#define ENOTBLK 15 /* Block device required */
#define EBUSY 16 /* Device or resource busy */
#define EEXIST 17 /* File exists */
#define EXDEV 18 /* Cross-device link */
#define ENODEV 19 /* No such device */
#define ENOTDIR 20 /* Not a directory */
#define EISDIR 21 /* Is a directory */
#define EINVAL 22 /* Invalid argument */
#define ENFILE 23 /* File table overflow */
#define EMFILE 24 /* Too many open files */
#define ENOTTY 25 /* Not a typewriter */
#define ETXTBSY 26 /* Text file busy */
#define EFBIG 27 /* File too large */
#define ENOSPC 28 /* No space left on device */
#define ESPIPE 29 /* Illegal seek */
#define EROFS 30 /* Read-only file system */
#define EMLINK 31 /* Too many links */
#define EPIPE 32 /* Broken pipe */
#define EDOM 33 /* Math argument out of domain of func */
#define ERANGE 34 /* Math result not representable */
#define EDEADLK 35 /* Resource deadlock would occur */
#define ENAMETOOLONG 36 /* File name too long */
#define ENOLCK 37 /* No record locks available */
#define ENOSYS 38 /* Function not implemented */
#define ENOTEMPTY 39 /* Directory not empty */
#define ELOOP 40 /* Too many symbolic links encountered */
#define ENOMSG 42 /* No message of desired type */
#define EIDRM 43 /* Identifier removed */
#define ECHRNG 44 /* Channel number out of range */
#define EL2NSYNC 45 /* Level 2 not synchronized */
#define EL3HLT 46 /* Level 3 halted */
#define EL3RST 47 /* Level 3 reset */
#define ELNRNG 48 /* Link number out of range */
#define EUNATCH 49 /* Protocol driver not attached */
#define ENOCSI 50 /* No CSI structure available */
#define EL2HLT 51 /* Level 2 halted */
#define EBADE 52 /* Invalid exchange */
#define EBADR 53 /* Invalid request descriptor */
#define EXFULL 54 /* Exchange full */
#define ENOANO 55 /* No anode */
#define EBADRQC 56 /* Invalid request code */
#define EBADSLT 57 /* Invalid slot */
#define EBFONT 59 /* Bad font file format */
#define ENOSTR 60 /* Device not a stream */
#define ENODATA 61 /* No data available */
#define ETIME 62 /* Timer expired */
#define ENOSR 63 /* Out of streams resources */
#define ENONET 64 /* Machine is not on the network */
#define ENOPKG 65 /* Package not installed */
#define EREMOTE 66 /* Object is remote */
#define ENOLINK 67 /* Link has been severed */
#define EADV 68 /* Advertise error */
#define ESRMNT 69 /* Srmount error */
#define ECOMM 70 /* Communication error on send */
#define EPROTO 71 /* Protocol error */
#define EMULTIHOP 72 /* Multihop attempted */
#define EDOTDOT 73 /* RFS specific error */
#define EBADMSG 74 /* Not a data message */
#define EOVERFLOW 75 /* Value too large for defined data type */
#define ENOTUNIQ 76 /* Name not unique on network */
#define EBADFD 77 /* File descriptor in bad state */
#define EREMCHG 78 /* Remote address changed */
#define ELIBACC 79 /* Can not access a needed shared library */
#define ELIBBAD 80 /* Accessing a corrupted shared library */
#define ELIBSCN 81 /* .lib section in a.out corrupted */
#define ELIBMAX 82 /* Attempting to link in too many shared libraries */
#define ELIBEXEC 83 /* Cannot exec a shared library directly */
#define EILSEQ 84 /* Illegal byte sequence */
#define ERESTART 85 /* Interrupted system call should be restarted */
#define ESTRPIPE 86 /* Streams pipe error */
#define EUSERS 87 /* Too many users */
#define ENOTSOCK 88 /* Socket operation on non-socket */
#define EDESTADDRREQ 89 /* Destination address required */
#define EMSGSIZE 90 /* Message too long */
#define EPROTOTYPE 91 /* Protocol wrong type for socket */
#define ENOPROTOOPT 92 /* Protocol not available */
#define EPROTONOSUPPORT 93 /* Protocol not supported */
#define ESOCKTNOSUPPORT 94 /* Socket type not supported */
#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
#define EPFNOSUPPORT 96 /* Protocol family not supported */
#define EAFNOSUPPORT 97 /* Address family not supported by protocol */
#define EADDRINUSE 98 /* Address already in use */
#define EADDRNOTAVAIL 99 /* Cannot assign requested address */
#define ENETDOWN 100 /* Network is down */
#define ENETUNREACH 101 /* Network is unreachable */
#define ENETRESET 102 /* Network dropped connection because of reset */
#define ECONNABORTED 103 /* Software caused connection abort */
#define ECONNRESET 104 /* Connection reset by peer */
#define ENOBUFS 105 /* No buffer space available */
#define EISCONN 106 /* Transport endpoint is already connected */
#define ENOTCONN 107 /* Transport endpoint is not connected */
#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */
#define ETOOMANYREFS 109 /* Too many references: cannot splice */
#define ETIMEDOUT 110 /* Connection timed out */
#define ECONNREFUSED 111 /* Connection refused */
#define EHOSTDOWN 112 /* Host is down */
#define EHOSTUNREACH 113 /* No route to host */
#define EALREADY 114 /* Operation already in progress */
#define EINPROGRESS 115 /* Operation now in progress */
#define ESTALE 116 /* Stale NFS file handle */
#define EUCLEAN 117 /* Structure needs cleaning */
#define ENOTNAM 118 /* Not a XENIX named type file */
#define ENAVAIL 119 /* No XENIX semaphores available */
#define EISNAM 120 /* Is a named type file */
#define EREMOTEIO 121 /* Remote I/O error */
#define EDQUOT 122 /* Quota exceeded */
#define ENOMEDIUM 123 /* No medium found */
#define EMEDIUMTYPE 124 /* Wrong medium type */
#define ECANCELED 125 /* Operation Canceled */
#define ENOKEY 126 /* Required key not available */
#define EKEYEXPIRED 127 /* Key has expired */
#define EKEYREVOKED 128 /* Key has been revoked */
#define EKEYREJECTED 129 /* Key was rejected by service */
#define EOWNERDEAD 130 /* Owner died */
#define ENOTRECOVERABLE 131 /* State not recoverable */
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
*/
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;
#ifdef __cplusplus
extern "C"
{
#endif
int *__errno_location(void) __attribute__((const));
char *strerror(int errnum);
#ifdef __cplusplus
}
#endif
extern int *__errno_location(void) __attribute__((const)) __attribute__ ((__nothrow__));
#define errno (*__errno_location())
#endif
#endif // !__FENNIX_API_ERRNO_H__

View File

@ -1,4 +1,108 @@
#ifndef _FNCTL_H
#define _FNCTL_H
/*
This file is part of Fennix C Library.
#endif // !_FNCTL_H
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 _FCNTL_H
#define _FCNTL_H
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
typedef struct f_owner_ex
{
int type; /* Discriminator for pid. */
pid_t pid; /* Process ID or process group ID. */
} f_owner_ex;
typedef struct flock
{
short l_type; /* Type of lock; F_RDLCK, F_WRLCK, F_UNLCK. */
short l_whence; /* Flag for starting offset. */
off_t l_start; /* Relative offset in bytes. */
off_t l_len; /* Size; if 0 then until EOF. */
pid_t l_pid; /* For a process-owned file lock, ignored on input or the process ID of the owning process on output; for an OFD-owned file lock, zero on input or (pid_t)-1 on output. */
} flock;
#define F_DUPFD
#define F_DUPFD_CLOEXEC
#define F_DUPFD_CLOFORK
#define F_GETFD
#define F_SETFD
#define F_GETFL
#define F_SETFL
#define F_GETLK
#define F_SETLK
#define F_SETLKW
#define F_OFD_GETLK
#define F_OFD_SETLK
#define F_OFD_SETLKW
#define F_GETOWN
#define F_GETOWN_EX
#define F_SETOWN
#define F_SETOWN_EX
#define FD_CLOEXEC
#define FD_CLOFORK
#define F_RDLCK
#define F_UNLCK
#define F_WRLCK
#define F_OWNER_PID
#define F_OWNER_PGRP
#define O_CLOEXEC 02000000
#define O_CLOFORK
#define O_CREAT 0100
#define O_DIRECTORY
#define O_EXCL 0200
#define O_NOCTTY
#define O_NOFOLLOW 0400000
#define O_TRUNC 01000
#define O_TTY_INIT
#define O_APPEND 02000
#define O_DSYNC
#define O_NONBLOCK
#define O_RSYNC
#define O_SYNC
#define O_ACCMODE
#define O_EXEC
#define O_RDONLY 00
#define O_RDWR 02
#define O_SEARCH
#define O_WRONLY 01
#define AT_FDCWD
#define AT_EACCESS
#define AT_SYMLINK_NOFOLLOW
#define AT_SYMLINK_FOLLOW
#define AT_REMOVEDIR
#define POSIX_FADV_DONTNEED
#define POSIX_FADV_NOREUSE
#define POSIX_FADV_NORMAL
#define POSIX_FADV_RANDOM
#define POSIX_FADV_SEQUENTIAL
#define POSIX_FADV_WILLNEED
int creat(const char *, mode_t);
int fcntl(int, int, ...);
int open(const char *, int, ...);
int openat(int, const char *, int, ...);
int posix_fadvise(int, off_t, off_t, int);
int posix_fallocate(int, off_t, off_t);
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // !_FCNTL_H

View File

@ -1,6 +0,0 @@
#ifndef _FEATURES_H
#define _FEATURES_H
#define __FENNIX_LIBC__ 1
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,87 @@
/*
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 _FLOAT_H
#define _FLOAT_H
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
#define INFINITY (__builtin_inff())
#define NAN (__builtin_nanf(""))
#define FLT_ROUNDS 1
#define FLT_EVAL_METHOD __FLT_EVAL_METHOD__
#define FLT_HAS_SUBNORM __FLT_HAS_DENORM__
#define DBL_HAS_SUBNORM __DBL_HAS_DENORM__
#define LDBL_HAS_SUBNORM __LDBL_HAS_DENORM__
#define FLT_RADIX __FLT_RADIX__
#define FLT_MANT_DIG __FLT_MANT_DIG__
#define DBL_MANT_DIG __DBL_MANT_DIG__
#define LDBL_MANT_DIG __LDBL_MANT_DIG__
#define FLT_DECIMAL_DIG __FLT_DECIMAL_DIG__
#define DBL_DECIMAL_DIG __DBL_DECIMAL_DIG__
#define LDBL_DECIMAL_DIG __LDBL_DECIMAL_DIG__
#define DECIMAL_DIG __DECIMAL_DIG__
#define FLT_DIG __FLT_DIG__
#define DBL_DIG __DBL_DIG__
#define LDBL_DIG __LDBL_DIG__
#define FLT_MIN_EXP __FLT_MIN_EXP__
#define DBL_MIN_EXP __DBL_MIN_EXP__
#define LDBL_MIN_EXP __LDBL_MIN_EXP__
#define FLT_MIN_10_EXP __FLT_MIN_10_EXP__
#define DBL_MIN_10_EXP __DBL_MIN_10_EXP__
#define LDBL_MIN_10_EXP __LDBL_MIN_10_EXP__
#define FLT_MAX_EXP __FLT_MAX_EXP__
#define DBL_MAX_EXP __DBL_MAX_EXP__
#define LDBL_MAX_EXP __LDBL_MAX_EXP__
#define FLT_MAX_10_EXP __FLT_MAX_10_EXP__
#define DBL_MAX_10_EXP __DBL_MAX_10_EXP__
#define LDBL_MAX_10_EXP __LDBL_MAX_10_EXP__
#define FLT_MAX __FLT_MAX__
#define DBL_MAX __DBL_MAX__
#define LDBL_MAX __LDBL_MAX__
#define FLT_EPSILON __FLT_EPSILON__
#define DBL_EPSILON __DBL_EPSILON__
#define LDBL_EPSILON __LDBL_EPSILON__
#define FLT_MIN __FLT_MIN__
#define DBL_MIN __DBL_MIN__
#define LDBL_MIN __LDBL_MIN__
#define FLT_TRUE_MIN __FLT_DENORM_MIN__
#define DBL_TRUE_MIN __DBL_DENORM_MIN__
#define LDBL_TRUE_MIN __LDBL_DENORM_MIN__
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // !_FLOAT_H

View File

@ -1,40 +1,69 @@
/*
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 _INTTYPES_H
#define _INTTYPES_H
typedef __INT8_TYPE__ int8_t;
typedef __INT16_TYPE__ int16_t;
typedef __INT32_TYPE__ int32_t;
typedef __INT64_TYPE__ int64_t;
typedef __UINT8_TYPE__ uint8_t;
typedef __UINT16_TYPE__ uint16_t;
typedef __UINT32_TYPE__ uint32_t;
typedef __UINT64_TYPE__ uint64_t;
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
typedef __INT_LEAST8_TYPE__ int_least8_t;
typedef __INT_LEAST16_TYPE__ int_least16_t;
typedef __INT_LEAST32_TYPE__ int_least32_t;
typedef __INT_LEAST64_TYPE__ int_least64_t;
typedef __UINT_LEAST8_TYPE__ uint_least8_t;
typedef __UINT_LEAST16_TYPE__ uint_least16_t;
typedef __UINT_LEAST32_TYPE__ uint_least32_t;
typedef __UINT_LEAST64_TYPE__ uint_least64_t;
typedef __INT8_TYPE__ int8_t;
typedef __INT16_TYPE__ int16_t;
typedef __INT32_TYPE__ int32_t;
typedef __INT64_TYPE__ int64_t;
typedef __INT_FAST8_TYPE__ int_fast8_t;
typedef __INT_FAST16_TYPE__ int_fast16_t;
typedef __INT_FAST32_TYPE__ int_fast32_t;
typedef __INT_FAST64_TYPE__ int_fast64_t;
typedef __UINT_FAST8_TYPE__ uint_fast8_t;
typedef __UINT_FAST16_TYPE__ uint_fast16_t;
typedef __UINT_FAST32_TYPE__ uint_fast32_t;
typedef __UINT_FAST64_TYPE__ uint_fast64_t;
typedef __UINT8_TYPE__ uint8_t;
typedef __UINT16_TYPE__ uint16_t;
typedef __UINT32_TYPE__ uint32_t;
typedef __UINT64_TYPE__ uint64_t;
typedef __INTPTR_TYPE__ intptr_t;
typedef __UINTPTR_TYPE__ uintptr_t;
typedef __INTPTR_TYPE__ intptr_t;
typedef __UINTPTR_TYPE__ uintptr_t;
typedef __INTMAX_TYPE__ intmax_t;
typedef __UINTMAX_TYPE__ uintmax_t;
typedef __INT_LEAST8_TYPE__ int_least8_t;
typedef __INT_LEAST16_TYPE__ int_least16_t;
typedef __INT_LEAST32_TYPE__ int_least32_t;
typedef __INT_LEAST64_TYPE__ int_least64_t;
typedef __PTRDIFF_TYPE__ ptrdiff_t;
typedef __SIZE_TYPE__ size_t;
typedef __UINT_LEAST8_TYPE__ uint_least8_t;
typedef __UINT_LEAST16_TYPE__ uint_least16_t;
typedef __UINT_LEAST32_TYPE__ uint_least32_t;
typedef __UINT_LEAST64_TYPE__ uint_least64_t;
typedef __INT_FAST8_TYPE__ int_fast8_t;
typedef __INT_FAST16_TYPE__ int_fast16_t;
typedef __INT_FAST32_TYPE__ int_fast32_t;
typedef __INT_FAST64_TYPE__ int_fast64_t;
typedef __UINT_FAST8_TYPE__ uint_fast8_t;
typedef __UINT_FAST16_TYPE__ uint_fast16_t;
typedef __UINT_FAST32_TYPE__ uint_fast32_t;
typedef __UINT_FAST64_TYPE__ uint_fast64_t;
typedef __INTPTR_TYPE__ intptr_t;
typedef __UINTPTR_TYPE__ uintptr_t;
typedef __INTMAX_TYPE__ intmax_t;
typedef __UINTMAX_TYPE__ uintmax_t;
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // !_INTTYPES_H

View File

@ -1,119 +1,117 @@
/*
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 _LIMITS_H
#define _LIMITS_H
#undef CHAR_BIT
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
#define _POSIX_ARG_MAX 4096
#define _POSIX_CHILD_MAX 25
#define _POSIX_OPEN_MAX 20
#define _POSIX_LINK_MAX 8
#define _POSIX_MAX_CANON 255
#define _POSIX_MAX_INPUT 255
#define _POSIX_NAME_MAX 255
#define _POSIX_PATH_MAX 4096
#define _POSIX_PIPE_BUF 512
#define _POSIX_SYMLOOP_MAX 8
#define _POSIX_HOST_NAME_MAX 255
#define _POSIX_LOGIN_NAME_MAX 9
#define _POSIX_TTY_NAME_MAX 255
#define _POSIX_TZNAME_MAX 6
#define _XOPEN_SHM_MAX 255
#define _XOPEN_IOV_MAX 1024
#define _XOPEN_SSTREAM_MAX 8
#define _XOPEN_NAME_MAX 255
#define _XOPEN_PATH_MAX 4096
#define _XOPEN_SYMLOOP_MAX 8
#define _XOPEN_LOGIN_NAME_MAX 9
#define _POSIX2_BC_BASE_MAX 99
#define _POSIX2_BC_DIM_MAX 2048
#define _POSIX2_BC_SCALE_MAX 99
#define _POSIX2_BC_STRING_MAX 1000
#define _POSIX2_COLL_WEIGHTS_MAX 255
#define _POSIX2_EXPR_NEST_MAX 32
#define _POSIX2_LINE_MAX 2048
#define _POSIX2_RE_DUP_MAX 255
#define CHAR_BIT __CHAR_BIT__
#ifndef MB_LEN_MAX
#define MB_LEN_MAX 1
#endif
#undef SCHAR_MIN
#define SCHAR_MIN (-SCHAR_MAX - 1)
#undef SCHAR_MAX
#define SCHAR_MAX __SCHAR_MAX__
#undef UCHAR_MAX
#if __SCHAR_MAX__ == __INT_MAX__
#define UCHAR_MAX (SCHAR_MAX * 2U + 1U)
#else
#define UCHAR_MAX (SCHAR_MAX * 2 + 1)
#endif
#ifdef __CHAR_UNSIGNED__
#undef CHAR_MIN
#if __SCHAR_MAX__ == __INT_MAX__
#define CHAR_MIN 0U
#else
#define CHAR_MIN 0
#endif
#undef CHAR_MAX
#define CHAR_MAX UCHAR_MAX
#else
#undef CHAR_MIN
#define CHAR_MIN SCHAR_MIN
#undef CHAR_MAX
#define CHAR_MAX SCHAR_MAX
#endif
#undef SHRT_MIN
#define MB_LEN_MAX 1
#define SHRT_MIN (-SHRT_MAX - 1)
#undef SHRT_MAX
#define SHRT_MAX __SHRT_MAX__
#undef USHRT_MAX
#if __SHRT_MAX__ == __INT_MAX__
#define USHRT_MAX (SHRT_MAX * 2U + 1U)
#else
#define USHRT_MAX (SHRT_MAX * 2 + 1)
#endif
#undef INT_MIN
#define INT_MIN (-INT_MAX - 1)
#undef INT_MAX
#define INT_MAX __INT_MAX__
#undef UINT_MAX
#define UINT_MAX (INT_MAX * 2U + 1U)
#undef LONG_MIN
#define LONG_MIN (-LONG_MAX - 1L)
#undef LONG_MAX
#define LONG_MAX __LONG_MAX__
#undef ULONG_MAX
#define ULONG_MAX (LONG_MAX * 2UL + 1UL)
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
#undef LLONG_MIN
#define LLONG_MIN (-LLONG_MAX - 1LL)
#undef LLONG_MAX
#define LLONG_MIN (-__LONG_LONG_MAX__ - 1LL)
#define LLONG_MAX __LONG_LONG_MAX__
#undef ULLONG_MAX
#define ULLONG_MAX (LLONG_MAX * 2ULL + 1ULL)
#endif
#if defined(__GNU_LIBRARY__) ? defined(__USE_GNU) : !defined(__STRICT_ANSI__)
#undef LONG_LONG_MIN
#define LONG_LONG_MIN (-LONG_LONG_MAX - 1LL)
#undef LONG_LONG_MAX
#define LONG_LONG_MAX __LONG_LONG_MAX__
#define ARG_MAX 4096
#define CHILD_MAX 25
#define OPEN_MAX 20
#define LINK_MAX 8
#define MAX_CANON 255
#define MAX_INPUT 255
#define NAME_MAX 255
#define PATH_MAX 4096
#define PIPE_BUF 512
#define SYMLOOP_MAX 8
#define HOST_NAME_MAX 255
#define LOGIN_NAME_MAX 9
#define TTY_NAME_MAX 255
#define TZNAME_MAX 6
#undef ULONG_LONG_MAX
#define ULONG_LONG_MAX (LONG_LONG_MAX * 2ULL + 1ULL)
#endif
#define SSIZE_MAX ((size_t)(-1) / 2)
#if (defined __STDC_WANT_IEC_60559_BFP_EXT__ || (defined(__STDC_VERSION__) && __STDC_VERSION__ > 201710L))
#undef CHAR_WIDTH
#define CHAR_WIDTH __SCHAR_WIDTH__
#undef SCHAR_WIDTH
#define SCHAR_WIDTH __SCHAR_WIDTH__
#undef UCHAR_WIDTH
#define UCHAR_WIDTH __SCHAR_WIDTH__
#undef SHRT_WIDTH
#define SHRT_WIDTH __SHRT_WIDTH__
#undef USHRT_WIDTH
#define USHRT_WIDTH __SHRT_WIDTH__
#undef INT_WIDTH
#define INT_WIDTH __INT_WIDTH__
#undef UINT_WIDTH
#define UINT_WIDTH __INT_WIDTH__
#undef LONG_WIDTH
#define LONG_WIDTH __LONG_WIDTH__
#undef ULONG_WIDTH
#define ULONG_WIDTH __LONG_WIDTH__
#undef LLONG_WIDTH
#define LLONG_WIDTH __LONG_LONG_WIDTH__
#undef ULLONG_WIDTH
#define ULLONG_WIDTH __LONG_LONG_WIDTH__
#endif
#if defined(__STDC_VERSION__) && __STDC_VERSION__ > 201710L
#undef BOOL_MAX
#define BOOL_MAX 1
#undef BOOL_WIDTH
#define BOOL_WIDTH 1
#endif
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // !_LIMITS_H

View File

@ -0,0 +1,79 @@
/*
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 _LOCALE_H
#define _LOCALE_H
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
typedef struct lconv
{
char *currency_symbol;
char *decimal_point;
char frac_digits;
char *grouping;
char *int_curr_symbol;
char int_frac_digits;
char int_n_cs_precedes;
char int_n_sep_by_space;
char int_n_sign_posn;
char int_p_cs_precedes;
char int_p_sep_by_space;
char int_p_sign_posn;
char *mon_decimal_point;
char *mon_grouping;
char *mon_thousands_sep;
char *negative_sign;
char n_cs_precedes;
char n_sep_by_space;
char n_sign_posn;
char *positive_sign;
char p_cs_precedes;
char p_sep_by_space;
char p_sign_posn;
char *thousands_sep;
} lconv;
typedef struct locale_t
{
char data[1]; /* FIXME: implement locale_t */
} locale_t;
#define LC_ALL
#define LC_COLLATE
#define LC_CTYPE
#define LC_MESSAGES
#define LC_MONETARY
#define LC_NUMERIC
#define LC_TIME
locale_t duplocale(locale_t);
void freelocale(locale_t);
const char *getlocalename_l(int, locale_t);
struct lconv *localeconv(void);
locale_t newlocale(int, const char *, locale_t);
char *setlocale(int, const char *);
locale_t uselocale(locale_t);
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // !_LOCALE_H

View File

@ -1,4 +1,226 @@
/*
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 _MATH_H
#define _MATH_H
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
#define FLT_EVAL_METHOD 0
#if FLT_EVAL_METHOD == 0
typedef float float_t;
typedef double double_t;
#elif FLT_EVAL_METHOD == 1
typedef float float_t;
typedef float double_t;
#elif FLT_EVAL_METHOD == 2
typedef long double float_t;
typedef long double double_t;
#else
#error "Unsupported FLT_EVAL_METHOD"
#endif
double acos(double);
float acosf(float);
double acosh(double);
float acoshf(float);
long double acoshl(long double);
long double acosl(long double);
double asin(double);
float asinf(float);
double asinh(double);
float asinhf(float);
long double asinhl(long double);
long double asinl(long double);
double atan(double);
double atan2(double, double);
float atan2f(float, float);
long double atan2l(long double, long double);
float atanf(float);
double atanh(double);
float atanhf(float);
long double atanhl(long double);
long double atanl(long double);
double cbrt(double);
float cbrtf(float);
long double cbrtl(long double);
double ceil(double);
float ceilf(float);
long double ceill(long double);
double copysign(double, double);
float copysignf(float, float);
long double copysignl(long double, long double);
double cos(double);
float cosf(float);
double cosh(double);
float coshf(float);
long double coshl(long double);
long double cosl(long double);
double erf(double);
double erfc(double);
float erfcf(float);
long double erfcl(long double);
float erff(float);
long double erfl(long double);
double exp(double);
double exp2(double);
float exp2f(float);
long double exp2l(long double);
float expf(float);
long double expl(long double);
double expm1(double);
float expm1f(float);
long double expm1l(long double);
double fabs(double);
float fabsf(float);
long double fabsl(long double);
double fdim(double, double);
float fdimf(float, float);
long double fdiml(long double, long double);
double floor(double);
float floorf(float);
long double floorl(long double);
double fma(double, double, double);
float fmaf(float, float, float);
long double fmal(long double, long double, long double);
double fmax(double, double);
float fmaxf(float, float);
long double fmaxl(long double, long double);
double fmin(double, double);
float fminf(float, float);
long double fminl(long double, long double);
double fmod(double, double);
float fmodf(float, float);
long double fmodl(long double, long double);
double frexp(double, int *);
float frexpf(float value, int *);
long double frexpl(long double value, int *);
double hypot(double, double);
float hypotf(float, float);
long double hypotl(long double, long double);
int ilogb(double);
int ilogbf(float);
int ilogbl(long double);
double j0(double);
double j1(double);
double jn(int, double);
double ldexp(double, int);
float ldexpf(float, int);
long double ldexpl(long double, int);
double lgamma(double);
float lgammaf(float);
long double lgammal(long double);
long long llrint(double);
long long llrintf(float);
long long llrintl(long double);
long long llround(double);
long long llroundf(float);
long long llroundl(long double);
double log(double);
double log10(double);
float log10f(float);
long double log10l(long double);
double log1p(double);
float log1pf(float);
long double log1pl(long double);
double log2(double);
float log2f(float);
long double log2l(long double);
double logb(double);
float logbf(float);
long double logbl(long double);
float logf(float);
long double logl(long double);
long lrint(double);
long lrintf(float);
long lrintl(long double);
long lround(double);
long lroundf(float);
long lroundl(long double);
double modf(double, double *);
float modff(float, float *);
long double modfl(long double, long double *);
double nan(const char *);
float nanf(const char *);
long double nanl(const char *);
double nearbyint(double);
float nearbyintf(float);
long double nearbyintl(long double);
double nextafter(double, double);
float nextafterf(float, float);
long double nextafterl(long double, long double);
double nexttoward(double, long double);
float nexttowardf(float, long double);
long double nexttowardl(long double, long double);
double pow(double, double);
float powf(float, float);
long double powl(long double, long double);
double remainder(double, double);
float remainderf(float, float);
long double remainderl(long double, long double);
double remquo(double, double, int *);
float remquof(float, float, int *);
long double remquol(long double, long double, int *);
double rint(double);
float rintf(float);
long double rintl(long double);
double round(double);
float roundf(float);
long double roundl(long double);
double scalb(double, double);
double scalbln(double, long);
float scalblnf(float, long);
long double scalblnl(long double, long);
double scalbn(double, int);
float scalbnf(float, int);
long double scalbnl(long double, int);
double sin(double);
float sinf(float);
double sinh(double);
float sinhf(float);
long double sinhl(long double);
long double sinl(long double);
double sqrt(double);
float sqrtf(float);
long double sqrtl(long double);
double tan(double);
float tanf(float);
double tanh(double);
float tanhf(float);
long double tanhl(long double);
long double tanl(long double);
double tgamma(double);
float tgammaf(float);
long double tgammal(long double);
double trunc(double);
float truncf(float);
long double truncl(long double);
double y0(double);
double y1(double);
double yn(int, double);
extern int signgam;
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // !_MATH_H

View File

@ -0,0 +1,137 @@
/*
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 _PTHREAD_H
#define _PTHREAD_H
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
#include <sys/types.h>
#include <inttypes.h>
#include <sched.h>
#define PTHREAD_CANCEL_ASYNCHRONOUS {0}
#define PTHREAD_CANCEL_ENABLE {0}
#define PTHREAD_CANCEL_DEFERRED {0}
#define PTHREAD_CANCEL_DISABLE {0}
#define PTHREAD_CANCELED {0}
#define PTHREAD_COND_INITIALIZER {0}
#define PTHREAD_CREATE_DETACHED {0}
#define PTHREAD_CREATE_JOINABLE {0}
#define PTHREAD_EXPLICIT_SCHED {0}
#define PTHREAD_INHERIT_SCHED {0}
#define PTHREAD_MUTEX_DEFAULT {0}
#define PTHREAD_MUTEX_ERRORCHECK {0}
#define PTHREAD_MUTEX_NORMAL {0}
#define PTHREAD_MUTEX_INITIALIZER {0}
#define PTHREAD_MUTEX_RECURSIVE {0}
#define PTHREAD_ONCE_INIT {0}
#define PTHREAD_PRIO_INHERIT {0}
#define PTHREAD_PRIO_NONE {0}
#define PTHREAD_PRIO_PROTECT {0}
#define PTHREAD_PROCESS_SHARED {0}
#define PTHREAD_PROCESS_PRIVATE {0}
#define PTHREAD_RWLOCK_INITIALIZER {0}
#define PTHREAD_SCOPE_PROCESS {0}
#define PTHREAD_SCOPE_SYSTEM {0}
int pthread_attr_destroy(pthread_attr_t *);
int pthread_attr_getdetachstate(const pthread_attr_t *, int *);
int pthread_attr_getguardsize(const pthread_attr_t *, size_t *);
int pthread_attr_getinheritsched(const pthread_attr_t *, int *);
int pthread_attr_getschedparam(const pthread_attr_t *, struct sched_param *);
int pthread_attr_getschedpolicy(const pthread_attr_t *, int *);
int pthread_attr_getscope(const pthread_attr_t *, int *);
int pthread_attr_getstackaddr(const pthread_attr_t *, void **);
int pthread_attr_getstacksize(const pthread_attr_t *, size_t *);
int pthread_attr_init(pthread_attr_t *);
int pthread_attr_setdetachstate(pthread_attr_t *, int);
int pthread_attr_setguardsize(pthread_attr_t *, size_t);
int pthread_attr_setinheritsched(pthread_attr_t *, int);
int pthread_attr_setschedparam(pthread_attr_t *, const struct sched_param *);
int pthread_attr_setschedpolicy(pthread_attr_t *, int);
int pthread_attr_setscope(pthread_attr_t *, int);
int pthread_attr_setstackaddr(pthread_attr_t *, void *);
int pthread_attr_setstacksize(pthread_attr_t *, size_t);
int pthread_cancel(pthread_t);
void pthread_cleanup_push(void (*)(void *), void *);
void pthread_cleanup_pop(int);
int pthread_cond_broadcast(pthread_cond_t *);
int pthread_cond_destroy(pthread_cond_t *);
int pthread_cond_init(pthread_cond_t *, const pthread_condattr_t *);
int pthread_cond_signal(pthread_cond_t *);
int pthread_cond_timedwait(pthread_cond_t *, pthread_mutex_t *, const struct timespec *);
int pthread_cond_wait(pthread_cond_t *, pthread_mutex_t *);
int pthread_condattr_destroy(pthread_condattr_t *);
int pthread_condattr_getpshared(const pthread_condattr_t *, int *);
int pthread_condattr_init(pthread_condattr_t *);
int pthread_condattr_setpshared(pthread_condattr_t *, int);
int pthread_create(pthread_t *, const pthread_attr_t *, void *(*)(void *), void *);
int pthread_detach(pthread_t);
int pthread_equal(pthread_t, pthread_t);
void pthread_exit(void *);
int pthread_getconcurrency(void);
int pthread_getschedparam(pthread_t, int *, struct sched_param *);
void *pthread_getspecific(pthread_key_t);
int pthread_join(pthread_t, void **);
int pthread_key_create(pthread_key_t *, void (*)(void *));
int pthread_key_delete(pthread_key_t);
int pthread_mutex_destroy(pthread_mutex_t *);
int pthread_mutex_getprioceiling(const pthread_mutex_t *, int *);
int pthread_mutex_init(pthread_mutex_t *, const pthread_mutexattr_t *);
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_setprioceiling(pthread_mutex_t *, int, int *);
int pthread_mutex_trylock(pthread_mutex_t *);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
int pthread_mutexattr_destroy(pthread_mutexattr_t *);
int pthread_mutexattr_getprioceiling(const pthread_mutexattr_t *, int *);
int pthread_mutexattr_getprotocol(const pthread_mutexattr_t *, int *);
int pthread_mutexattr_getpshared(const pthread_mutexattr_t *, int *);
int pthread_mutexattr_gettype(const pthread_mutexattr_t *, int *);
int pthread_mutexattr_init(pthread_mutexattr_t *);
int pthread_mutexattr_setprioceiling(pthread_mutexattr_t *, int);
int pthread_mutexattr_setprotocol(pthread_mutexattr_t *, int);
int pthread_mutexattr_setpshared(pthread_mutexattr_t *, int);
int pthread_mutexattr_settype(pthread_mutexattr_t *, int);
int pthread_once(pthread_once_t *, void (*)(void));
int pthread_rwlock_destroy(pthread_rwlock_t *);
int pthread_rwlock_init(pthread_rwlock_t *, const pthread_rwlockattr_t *);
int pthread_rwlock_rdlock(pthread_rwlock_t *);
int pthread_rwlock_tryrdlock(pthread_rwlock_t *);
int pthread_rwlock_trywrlock(pthread_rwlock_t *);
int pthread_rwlock_unlock(pthread_rwlock_t *);
int pthread_rwlock_wrlock(pthread_rwlock_t *);
int pthread_rwlockattr_destroy(pthread_rwlockattr_t *);
int pthread_rwlockattr_getpshared(const pthread_rwlockattr_t *, int *);
int pthread_rwlockattr_init(pthread_rwlockattr_t *);
int pthread_rwlockattr_setpshared(pthread_rwlockattr_t *, int);
pthread_t pthread_self(void);
int pthread_setcancelstate(int, int *);
int pthread_setcanceltype(int, int *);
int pthread_setconcurrency(int);
int pthread_setschedparam(pthread_t, int, const struct sched_param *);
int pthread_setspecific(pthread_key_t, const void *);
void pthread_testcancel(void);
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // !_PTHREAD_H

View File

@ -0,0 +1,49 @@
/*
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 _PWD_H
#define _PWD_H
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
#include <sys/types.h>
struct passwd
{
char *pw_name; /* User's login name. */
uid_t pw_uid; /* Numerical user ID. */
gid_t pw_gid; /* Numerical group ID. */
char *pw_dir; /* Initial working directory. */
char *pw_shell; /* Program to use as shell. */
};
void endpwent(void);
struct passwd *getpwent(void);
struct passwd *getpwnam(const char *);
int getpwnam_r(const char *, struct passwd *, char *, size_t, struct passwd **);
struct passwd *getpwuid(uid_t);
int getpwuid_r(uid_t, struct passwd *, char *, size_t, struct passwd **);
void setpwent(void);
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // !_PWD_H

View File

@ -0,0 +1,41 @@
/*
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 _SCHED_H
#define _SCHED_H
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
#include <time.h>
typedef struct sched_param
{
int sched_priority; /* Process or thread execution scheduling priority. */
int sched_ss_low_priority; /* Low scheduling priority for sporadic server. */
struct timespec sched_ss_repl_period; /* Replenishment period for sporadic server. */
struct timespec sched_ss_init_budget; /* Initial budget for sporadic server. */
int sched_ss_max_repl; /* Maximum pending replenishments for sporadic server. */
} sched_param_t;
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // !_SCHED_H

View File

@ -1,34 +0,0 @@
#ifndef _SETJMP_H
#define _SETJMP_H
#include <stdint.h>
typedef struct
{
uint64_t r15;
uint64_t r14;
uint64_t r13;
uint64_t r12;
uint64_t r11;
uint64_t r10;
uint64_t r9;
uint64_t r8;
uint64_t rbp;
uint64_t rsp;
uint64_t rdi;
uint64_t rsi;
uint64_t rdx;
uint64_t rcx;
uint64_t rbx;
uint64_t rax;
uint64_t rip;
uint64_t rflags;
uint64_t cs;
uint64_t fs;
uint64_t gs;
} jmp_buf[1];
int setjmp(jmp_buf env);
__attribute__((noreturn)) void longjmp(jmp_buf env, int value);
#endif // !_SETJMP_H

View File

@ -1,102 +1,221 @@
/*
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 _SIGNAL_H
#define _SIGNAL_H
#include <bits/types/sigset_t.h>
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
/* https://www-uxsup.csx.cam.ac.uk/courses/moved.Building/signals.pdf */
/* https://man7.org/linux/man-pages/man7/signal.7.html */
#include <sys/types.h>
#include <fennix/syscalls.h>
#include <bits/types/timespec.h>
/** @brief Hangup detected on controlling or death of controlling process */
#define SIGHUP 1
#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
/** @brief Interrupt from keyboard */
#define SIGINT 2
#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
/** @brief Quit from keyboard */
#define SIGQUIT 3
#define SIG_BLOCK __SYS_SIG_BLOCK
#define SIG_UNBLOCK __SYS_SIG_UNBLOCK
#define SIG_SETMASK __SYS_SIG_SETMASK
/** @brief Illegal Instruction */
#define SIGILL 4
#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
/** @brief Trace/breakpoint trap */
#define SIGTRAP 5
#define SS_ONSTACK
#define SS_DISABLE
/** @brief Abort signal from abort(3) */
#define SIGABRT 6
#define MINSIGSTKSZ
#define SIGSTKSZ
/** @brief Bus error (bad memory access) */
#define SIGBUS 7
#define SIG_ERR ((void (*)(int))__SYS_SIG_ERR)
#define SIG_DFL ((void (*)(int))__SYS_SIG_DFL)
#define SIG_IGN ((void (*)(int))__SYS_SIG_IGN)
/** @brief Floating point exception */
#define SIGFPE 8
#define SIGEV_NONE
#define SIGEV_SIGNAL
#define SIGEV_THREAD
/** @brief Kill signal */
#define SIGKILL 9
typedef unsigned long sigset_t;
/** @brief User-defined signal 1 */
#define SIGUSR1 10
union sigval
{
int sival_int; /* Integer signal value. */
void *sival_ptr; /* Pointer signal value. */
};
/** @brief Invalid memory reference */
#define SIGSEGV 11
typedef struct siginfo_t
{
int si_signo; /* Signal number. */
int si_code; /* Signal code. */
/** @brief User-defined signal 2 */
#define SIGUSR2 12
int si_errno; /* If non-zero, an errno value associated with */
/* this signal, as described in <errno.h>. */
/** @brief Broken pipe: write to pipe with no readers */
#define SIGPIPE 13
pid_t si_pid; /* Sending process ID. */
uid_t si_uid; /* Real user ID of sending process. */
void *si_addr; /* Address that caused fault. */
int si_status; /* Exit value or signal. */
union sigval si_value; /* Signal value. */
} siginfo_t;
/** @brief Timer signal from alarm(2) */
#define SIGALRM 14
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;
/** @brief Termination signal */
#define SIGTERM 15
struct sigaction
{
void (*sa_handler)(int); /* Pointer to a signal-catching function or one of the SIG_IGN or SIG_DFL. */
sigset_t sa_mask; /* Set of signals to be blocked during execution of the signal handling function. */
int sa_flags; /* Special flags. */
void (*sa_sigaction)(int, siginfo_t *, void *); /* Pointer to a signal-catching function. */
};
/** @brief Stack fault on coprocessor (unused) */
#define SIGSTKFLT 16
typedef struct stack_t
{
void *ss_sp; /* Stack base or pointer. */
size_t ss_size; /* Stack size. */
int ss_flags; /* Flags. */
} stack_t;
/** @brief Child stopped or terminated */
#define SIGCHLD 17
typedef struct mcontext_t
{
__UINTPTR_TYPE__ gregs[32]; /* General-purpose registers. */
__UINTPTR_TYPE__ sp; /* Stack pointer. */
__UINTPTR_TYPE__ pc; /* Program counter. */
__UINTPTR_TYPE__ pstate; /* Processor state. */
} mcontext_t;
/** @brief Continue if stopped */
#define SIGCONT 18
typedef struct ucontext_t
{
struct ucontext_t *uc_link; /* Pointer to the context that is resumed when this context returns. */
sigset_t uc_sigmask; /* The set of signals that are blocked when this context is active. */
stack_t uc_stack; /* The stack used by this context. */
mcontext_t uc_mcontext; /* A machine-specific representation of the saved context. */
} ucontext_t;
/** @brief Stop process */
#define SIGSTOP 19
int kill(pid_t pid, int sig);
int killpg(pid_t, int);
void psiginfo(const siginfo_t *, const char *);
void psignal(int, const char *);
int pthread_kill(pthread_t, int);
int pthread_sigmask(int, const sigset_t *restrict, sigset_t *restrict);
int raise(int);
int sig2str(int, char *);
int sigaction(int, const struct sigaction *restrict, struct sigaction *restrict);
int sigaddset(sigset_t *, int);
int sigaltstack(const stack_t *restrict, stack_t *restrict);
int sigdelset(sigset_t *, int);
int sigemptyset(sigset_t *);
int sigfillset(sigset_t *);
int sigismember(const sigset_t *, int);
void (*signal(int, void (*)(int)))(int);
int sigpending(sigset_t *);
int sigprocmask(int, const sigset_t *restrict, sigset_t *restrict);
int sigqueue(pid_t, int, union sigval);
int sigsuspend(const sigset_t *);
int sigtimedwait(const sigset_t *restrict, siginfo_t *restrict, const struct timespec *restrict);
int sigwait(const sigset_t *restrict, int *restrict);
int sigwaitinfo(const sigset_t *restrict, siginfo_t *restrict);
int str2sig(const char *restrict, int *restrict);
/** @brief Stop typed at terminal */
#define SIGTSTP 20
/** @brief Terminal input for background process */
#define SIGTTIN 21
/** @brief Terminal output for background process */
#define SIGTTOU 22
/** @brief Urgent condition on socket */
#define SIGURG 23
/** @brief CPU time limit exceeded */
#define SIGXCPU 24
/** @brief File size limit exceeded */
#define SIGXFSZ 25
/** @brief Virtual timer expired */
#define SIGVTALRM 26
/** @brief Profiling timer expired */
#define SIGPROF 27
/** @brief Window resize signal */
#define SIGWINCH 28
/** @brief I/O now possible */
#define SIGIO 29
/** @brief Power failure */
#define SIGPWR 30
/** @brief Bad system call */
#define SIGSYS 31
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // !_SIGNAL_H

View File

@ -1,45 +0,0 @@
#ifndef _SPAWN_H
#define _SPAWN_H
#include <stddef.h>
#include <bits/types/struct_sched_param.h>
#include <bits/types/sigset_t.h>
#include <sys/types.h>
struct __spawn_action
{
int __stub;
};
typedef struct
{
short int __flags;
pid_t __pgrp;
sigset_t __sd;
sigset_t __ss;
struct sched_param __sp;
int __policy;
int __pad[16];
} posix_spawnattr_t;
typedef struct
{
int __allocated;
int __used;
struct __spawn_action *__actions;
int __pad[16];
} posix_spawn_file_actions_t;
int posix_spawn(pid_t *pid, const char *path,
const posix_spawn_file_actions_t *file_actions,
const posix_spawnattr_t *attrp,
char *const argv[],
char *const envp[]);
int posix_spawnp(pid_t *pid, const char *file,
const posix_spawn_file_actions_t *file_actions,
const posix_spawnattr_t *attrp,
char *const argv[],
char *const envp[]);
#endif // !_SPAWN_H

View File

@ -1,13 +1,37 @@
/*
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 _STDARG_H
#define _STDARG_H
#ifndef __va_list__
typedef __builtin_va_list va_list;
#endif
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
#define va_start(ap, last) __builtin_va_start(ap, last)
#define va_end(ap) __builtin_va_end(ap)
#define va_arg(ap, type) __builtin_va_arg(ap, type)
typedef __builtin_va_list va_list;
#define va_start(ap, param) __builtin_va_start(ap, param)
#define va_copy(dest, src) __builtin_va_copy(dest, src)
#define va_arg(ap, type) __builtin_va_arg(ap, type)
#define va_end(ap) __builtin_va_end(ap)
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // !_STDARG_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 _STDBOOL_H
#define _STDBOOL_H
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
#define bool _Bool
#define true 1
#define false 0
#define __bool_true_false_are_defined 1
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // !_STDBOOL_H

View File

@ -1,47 +1,44 @@
/*
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 _STDDEF_H
#define _STDDEF_H
#ifdef __cplusplus
#define NULL 0
#else
extern "C"
{
#endif // __cplusplus
#ifndef NULL
#define NULL ((void *)0)
#define bool _Bool
#endif
typedef __INT8_TYPE__ int8_t;
typedef __INT16_TYPE__ int16_t;
typedef __INT32_TYPE__ int32_t;
typedef __INT64_TYPE__ int64_t;
typedef __UINT8_TYPE__ uint8_t;
typedef __UINT16_TYPE__ uint16_t;
typedef __UINT32_TYPE__ uint32_t;
typedef __UINT64_TYPE__ uint64_t;
typedef struct
{
long long __a;
long double __b;
} max_align_t;
typedef __INT_LEAST8_TYPE__ int_least8_t;
typedef __INT_LEAST16_TYPE__ int_least16_t;
typedef __INT_LEAST32_TYPE__ int_least32_t;
typedef __INT_LEAST64_TYPE__ int_least64_t;
typedef __UINT_LEAST8_TYPE__ uint_least8_t;
typedef __UINT_LEAST16_TYPE__ uint_least16_t;
typedef __UINT_LEAST32_TYPE__ uint_least32_t;
typedef __UINT_LEAST64_TYPE__ uint_least64_t;
typedef __PTRDIFF_TYPE__ ptrdiff_t;
typedef __WCHAR_TYPE__ wchar_t;
typedef __SIZE_TYPE__ size_t;
typedef __INT_FAST8_TYPE__ int_fast8_t;
typedef __INT_FAST16_TYPE__ int_fast16_t;
typedef __INT_FAST32_TYPE__ int_fast32_t;
typedef __INT_FAST64_TYPE__ int_fast64_t;
typedef __UINT_FAST8_TYPE__ uint_fast8_t;
typedef __UINT_FAST16_TYPE__ uint_fast16_t;
typedef __UINT_FAST32_TYPE__ uint_fast32_t;
typedef __UINT_FAST64_TYPE__ uint_fast64_t;
typedef __INTPTR_TYPE__ intptr_t;
typedef __UINTPTR_TYPE__ uintptr_t;
typedef __INTMAX_TYPE__ intmax_t;
typedef __UINTMAX_TYPE__ uintmax_t;
typedef __PTRDIFF_TYPE__ ptrdiff_t;
typedef __SIZE_TYPE__ size_t;
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // !_STDDEF_H

View File

@ -1,6 +1,32 @@
/*
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 _STDINT_H
#define _STDINT_H
#include <types.h>
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
#include <inttypes.h>
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // !_STDINT_H

View File

@ -1,87 +1,156 @@
/*
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 _STDIO_H
#define _STDIO_H
#include <stdarg.h>
#include <stddef.h>
#include <sys/stat.h>
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
/**
* @brief EOF - End of file
*
* The value returned by several functions to indicate the end of file.
*/
#define EOF (-1)
struct _IO_marker
{
struct _IO_marker *_next;
struct _IO_FILE *_sbuf;
int _pos;
};
struct _IO_FILE
{
int _flags;
char *_IO_read_ptr;
char *_IO_read_end;
char *_IO_read_base;
char *_IO_write_base;
char *_IO_write_ptr;
char *_IO_write_end;
char *_IO_buf_base;
char *_IO_buf_end;
__off_t _offset;
struct _IO_marker *_markers;
struct _IO_FILE *_chain;
int _fileno;
};
typedef struct _IO_FILE FILE;
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
#include <sys/types.h>
#include <stddef.h>
#include <stdarg.h>
#define BUFSIZ 512
#define FILENAME_MAX 255
#define FOPEN_MAX 8
#define _IOFBF 0
#define _IOLBF 1
#define _IONBF 2
#define L_ctermid 20
#define L_cuserid 20
#define L_tmpnam 255
#define SEEK_CUR 1
#define SEEK_END 2
#define SEEK_SET 0
#define TMP_MAX 10000
#define EOF (-1)
#ifndef NULL
#define NULL ((void *)0)
#endif
#define P_tmpdir "/tmp/"
typedef long fpos_t;
typedef unsigned long size_t;
struct _IO_FILE
{
int fd;
char *buffer;
size_t buffer_size;
size_t buffer_pos;
int flags;
int error;
int eof;
};
#define _i_READ 1
#define _i_WRITE 2
extern struct _IO_FILE *_i_open_files[256];
typedef struct _IO_FILE FILE;
extern char *optarg;
extern int opterr;
extern int optind;
extern int optopt;
extern FILE *stdin;
extern FILE *stdout;
extern FILE *stderr;
#define stdin stdin
#define stdout stdout
#define stderr stderr
FILE *freopen(const char *filename, const char *mode, FILE *stream);
FILE *fopen(const char *filename, const char *mode);
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
off_t fseek(FILE *stream, long offset, int whence);
long ftell(FILE *stream);
int fclose(FILE *fp);
void clearerr(FILE *);
char *ctermid(char *);
int dprintf(int, const char *restrict, ...);
int fclose(FILE *stream);
FILE *fdopen(int, const char *);
int feof(FILE *);
int ferror(FILE *);
int fflush(FILE *stream);
int fprintf(FILE *stream, const char *format, ...);
int printf(const char *format, ...);
void setbuf(FILE *stream, char *buf);
int vfprintf(FILE *stream, const char *format, va_list arg);
int vsscanf(const char *s, const char *format, va_list arg);
int sscanf(const char *s, const char *format, ...);
int fgetc(FILE *);
int fgetpos(FILE *restrict, fpos_t *restrict);
char *fgets(char *restrict, int, FILE *restrict);
int fileno(FILE *);
void flockfile(FILE *);
FILE *fmemopen(void *restrict, size_t, const char *restrict);
FILE *fopen(const char *restrict pathname, const char *restrict mode);
int fprintf(FILE *restrict, const char *restrict, ...);
int fputc(int c, FILE *stream);
int fputs(const char *restrict s, FILE *restrict stream);
size_t fread(void *restrict ptr, size_t size, size_t nitems, FILE *restrict stream);
FILE *freopen(const char *restrict, const char *restrict, FILE *restrict);
int fscanf(FILE *restrict, const char *restrict, ...);
int fseek(FILE *stream, long offset, int whence);
int fseeko(FILE *, off_t, int);
int fsetpos(FILE *, const fpos_t *);
long ftell(FILE *);
off_t ftello(FILE *);
int ftrylockfile(FILE *);
void funlockfile(FILE *);
size_t fwrite(const void *restrict ptr, size_t size, size_t nitems, FILE *restrict stream);
int getc(FILE *);
int getchar(void);
int getc_unlocked(FILE *);
int getchar_unlocked(void);
ssize_t getdelim(char **restrict, size_t *restrict, int, FILE *restrict);
ssize_t getline(char **restrict, size_t *restrict, FILE *restrict);
FILE *open_memstream(char **, size_t *);
int pclose(FILE *);
void perror(const char *);
FILE *popen(const char *, const char *);
int printf(const char *restrict format, ...);
int putc(int c, FILE *stream);
int fputs(const char *s, FILE *stream);
int puts(const char *s);
int putchar(int c);
int fgetc(FILE *stream);
int putc_unlocked(int c, FILE *stream);
int putchar_unlocked(int c);
int puts(const char *s);
int remove(const char *);
int rename(const char *, const char *);
int renameat(int, const char *, int, const char *);
void rewind(FILE *);
int scanf(const char *restrict, ...);
void setbuf(FILE *restrict, char *restrict);
int setvbuf(FILE *restrict, char *restrict, int, size_t);
int snprintf(char *restrict, size_t, const char *restrict, ...);
int sprintf(char *restrict, const char *restrict, ...);
int sscanf(const char *restrict, const char *restrict, ...);
FILE *tmpfile(void);
char *tmpnam(char *);
int ungetc(int, FILE *);
int vdprintf(int, const char *restrict, va_list);
int vfprintf(FILE *restrict, const char *restrict, va_list);
int vfscanf(FILE *restrict, const char *restrict, va_list);
int vprintf(const char *restrict, va_list);
int vscanf(const char *restrict, va_list);
int vsnprintf(char *restrict, size_t, const char *restrict, va_list);
int vsprintf(char *restrict, const char *restrict, va_list);
int vsscanf(const char *restrict, const char *restrict, va_list);
#ifdef __cplusplus
}
#endif
#endif // __cplusplus
#endif
#endif // !_STDIO_H

View File

@ -1,34 +1,115 @@
/*
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 _STDLIB_H
#define _STDLIB_H
#include <stddef.h>
#ifdef __cplusplus
extern "C"
{
#endif
#endif // __cplusplus
#include <stddef.h>
#include <limits.h>
#include <math.h>
#include <sys/wait.h>
#define EXIT_FAILURE 1
#define EXIT_SUCCESS 0
#define NULL ((void *)0)
#define RAND_MAX 32767
#define MB_CUR_MAX 4
typedef struct
{
int quot;
int rem;
} div_t;
typedef struct
{
long quot;
long rem;
} ldiv_t;
typedef unsigned long size_t;
// typedef __WCHAR_TYPE__ wchar_t;
long a64l(const char *);
void abort(void);
int atexit(void (*function)(void));
int abs(int);
int atexit(void (*func)(void));
double atof(const char *);
int atoi(const char *);
long int atol(const char *);
void *bsearch(const void *, const void *, size_t, size_t, int (*)(const void *, const void *));
void *calloc(size_t, size_t);
div_t div(int, int);
double drand48(void);
char *ecvt(double, int, int *, int *);
double erand48(unsigned short int[3]);
void exit(int status);
int atoi(const char *nptr);
char *getenv(const char *name);
void *malloc(size_t Size);
void *realloc(void *Address, size_t Size);
void *calloc(size_t Count, size_t Size);
void free(void *Address);
int system(const char *command);
double atof(const char *nptr);
extern void perror(const char *s);
char *fcvt(double, int, int *, int *);
void free(void *ptr);
char *gcvt(double, int, char *);
char *getenv(const char *);
int getsubopt(char **, char *const *, char **);
int grantpt(int);
char *initstate(unsigned int, char *, size_t);
long int jrand48(unsigned short int[3]);
char *l64a(long);
long int labs(long int);
void lcong48(unsigned short int[7]);
ldiv_t ldiv(long int, long int);
long int lrand48(void);
void *malloc(size_t size);
int mblen(const char *, size_t);
size_t mbstowcs(wchar_t *, const char *, size_t);
int mbtowc(wchar_t *, const char *, size_t);
char *mktemp(char *);
int mkstemp(char *);
long int mrand48(void);
long int nrand48(unsigned short int[3]);
char *ptsname(int);
int putenv(char *);
void qsort(void *, size_t, size_t, int (*)(const void *, const void *));
int rand(void);
int rand_r(unsigned int *);
long random(void);
void *realloc(void *, size_t);
char *realpath(const char *, char *);
unsigned short int seed48(unsigned short int[3]);
void setkey(const char *);
char *setstate(const char *);
void srand(unsigned int);
void srand48(long int);
void srandom(unsigned);
double strtod(const char *, char **);
long int strtol(const char *, char **, int);
unsigned long int strtoul(const char *, char **, int);
int system(const char *);
int ttyslot(void);
int unlockpt(int);
void *valloc(size_t);
size_t wcstombs(char *, const wchar_t *, size_t);
int wctomb(char *, wchar_t);
#ifdef __cplusplus
}
#endif
#endif // __cplusplus
#endif
#endif // !_STDLIB_H

View File

@ -1,30 +1,71 @@
/*
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 _STRING_H
#define _STRING_H
#include <stddef.h>
#ifdef __cplusplus
extern "C"
{
#endif
#endif // __cplusplus
size_t strlen(const char *str);
int strcmp(const char *l, const char *r);
int strncmp(const char *s1, const char *s2, size_t n);
int strcasecmp(const char *s1, const char *s2);
int strncasecmp(const char *string1, const char *string2, size_t count);
char *strstr(const char *haystack, const char *needle);
char *strncpy(char *destination, const char *source, unsigned long num);
char *strdup(const char *s);
char *strchr(char const *s, int c);
char *strrchr(char const *s, int c);
#include <stddef.h>
#include <locale.h>
void *memcpy(void *dest, const void *src, size_t n);
void *memset(void *dest, int c, size_t n);
void *memmove(void *dest, const void *src, size_t n);
void *memccpy(void *restrict, const void *restrict, int, size_t);
void *memchr(const void *, int, size_t);
int memcmp(const void *, const void *, size_t);
void *memcpy(void *restrict s1, const void *restrict s2, size_t n);
void *memmem(const void *, size_t, const void *, size_t);
void *memmove(void *, const void *, size_t);
void *memset(void *, int, size_t);
char *stpcpy(char *restrict, const char *restrict);
char *stpncpy(char *restrict, const char *restrict, size_t);
char *strcat(char *restrict, const char *restrict);
char *strchr(const char *, int);
int strcmp(const char *s1, const char *s2);
int strcoll(const char *, const char *);
int strcoll_l(const char *, const char *, locale_t);
char *strcpy(char *restrict, const char *restrict);
size_t strcspn(const char *, const char *);
char *strdup(const char *);
char *strerror(int);
char *strerror_l(int, locale_t);
int strerror_r(int, char *, size_t);
size_t strlcat(char *restrict, const char *restrict, size_t);
size_t strlcpy(char *restrict, const char *restrict, size_t);
size_t strlen(const char *);
char *strncat(char *restrict, const char *restrict, size_t);
int strncmp(const char *, const char *, size_t);
char *strncpy(char *restrict, const char *restrict, size_t);
char *strndup(const char *, size_t);
size_t strnlen(const char *, size_t);
char *strpbrk(const char *, const char *);
char *strrchr(const char *, int);
char *strsignal(int);
size_t strspn(const char *, const char *);
char *strstr(const char *, const char *);
char *strtok(char *restrict, const char *restrict);
char *strtok_r(char *restrict, const char *restrict, char **restrict);
size_t strxfrm(char *restrict, const char *restrict, size_t);
size_t strxfrm_l(char *restrict, const char *restrict, size_t, locale_t);
#ifdef __cplusplus
}
#endif
#endif // __cplusplus
#endif
#endif // !_STRING_H

View File

@ -1,4 +0,0 @@
#ifndef _STRINGS_H
#define _STRINGS_H
#endif // !_STRINGS_H

View File

@ -0,0 +1,73 @@
/*
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 _SYS_MMAN_H
#define _SYS_MMAN_H
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
#include <sys/types.h>
#define PROT_READ 0x1
#define PROT_WRITE 0x2
#define PROT_EXEC 0x4
#define PROT_NONE 0x0
#define MAP_SHARED 0x01
#define MAP_PRIVATE 0x02
#define MAP_FIXED 0x4
#define MAP_ANONYMOUS 0x8
#define MAP_ANON MAP_ANONYMOUS
#define MS_ASYNC 0x01
#define MS_SYNC 0x02
#define MS_INVALIDATE 0x04
#define MCL_CURRENT 0x01
#define MCL_FUTURE 0x02
#define MAP_FAILED ((void *)-1)
typedef struct posix_typed_mem_info
{
/* Maximum length which may be allocated from a typed memory object. */
size_t posix_tmi_length;
} posix_typed_mem_info;
int mlock(const void *, size_t);
int mlockall(int);
void *mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off);
int mprotect(void *addr, size_t len, int prot);
int msync(void *, size_t, int);
int munlock(const void *, size_t);
int munlockall(void);
int munmap(void *addr, size_t len);
int posix_madvise(void *, size_t, int);
int posix_mem_offset(const void *restrict, size_t, off_t *restrict, size_t *restrict, int *restrict);
int posix_typed_mem_get_info(int, struct posix_typed_mem_info *);
int posix_typed_mem_open(const char *, int, int);
int shm_open(const char *, int, mode_t);
int shm_unlink(const char *);
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // !_SYS_MMAN_H

View File

@ -1,18 +1,108 @@
/*
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 _SYS_STAT_H
#define _SYS_STAT_H
typedef unsigned int __dev_t;
typedef unsigned short __ino_t;
typedef unsigned short __mode_t;
typedef long __off_t;
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
#define dev_t __dev_t
#define ino_t __ino_t
#define mode_t __mode_t
#define off_t __off_t
#include <time.h>
int mkdir(const char *path, mode_t mode);
int remove(const char *pathname);
int rename(const char *oldpath, const char *newpath);
struct stat
{
dev_t st_dev; /* Device ID of device containing file. */
ino_t st_ino; /* File serial number. */
mode_t st_mode; /* Mode of file (see below). */
nlink_t st_nlink; /* Number of hard links to the file. */
uid_t st_uid; /* User ID of file. */
gid_t st_gid; /* Group ID of file. */
dev_t st_rdev; /* Device ID (if file is character or block special). */
off_t st_size; /* For regular files, the file size in bytes. For symbolic links, the length in bytes of the pathname contained in the symbolic link. For a shared memory object, the length in bytes. For a typed memory object, the length in bytes. For other file types, the use of this field is unspecified. */
struct timespec st_atim; /* Last data access timestamp. */
struct timespec st_mtim; /* Last data modification timestamp. */
struct timespec st_ctim; /* Last file status change timestamp. */
blksize_t st_blksize; /* A file system-specific preferred I/O block size for this object. In some file system types, this may vary from file to file. */
blkcnt_t st_blocks; /* Number of blocks allocated for this object. */
};
#endif
#define S_IFMT
#define S_IFBLK
#define S_IFCHR
#define S_IFIFO
#define S_IFREG
#define S_IFDIR
#define S_IFLNK
#define S_IFSOCK
#define S_IRWXU 0700
#define S_IRUSR 0400
#define S_IWUSR 0200
#define S_IXUSR 0100
#define S_IRWXG 070
#define S_IRGRP 040
#define S_IWGRP 020
#define S_IXGRP 010
#define S_IRWXO 07
#define S_IROTH 04
#define S_IWOTH 02
#define S_IXOTH 01
#define S_ISUID 04000
#define S_ISGID 02000
#define S_ISVTX 01000
#define S_ISBLK(m)
#define S_ISCHR(m)
#define S_ISDIR(m)
#define S_ISFIFO(m)
#define S_ISREG(m)
#define S_ISLNK(m)
#define S_ISSOCK(m)
#define S_TYPEISMQ(buf)
#define S_TYPEISSEM(buf)
#define S_TYPEISSHM(buf)
#define S_TYPEISTMO(buf)
#define UTIME_NOW
#define UTIME_OMIT
int chmod(const char *, mode_t);
int fchmod(int, mode_t);
int fchmodat(int, const char *, mode_t, int);
int fstat(int, struct stat *);
int fstatat(int, const char *restrict, struct stat *restrict, int);
int futimens(int, const struct timespec[2]);
int lstat(const char *restrict, struct stat *restrict);
int mkdir(const char *, mode_t);
int mkdirat(int, const char *, mode_t);
int mkfifo(const char *, mode_t);
int mkfifoat(int, const char *, mode_t);
int mknod(const char *, mode_t, dev_t);
int mknodat(int, const char *, mode_t, dev_t);
int stat(const char *restrict, struct stat *restrict);
mode_t umask(mode_t);
int utimensat(int, const char *, const struct timespec[2], int);
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // !_SYS_STAT_H

View File

@ -1,6 +0,0 @@
#ifndef _SYS_TIME_H
#define _SYS_TIME_H
#include <sys/types.h>
#endif

View File

@ -1,37 +1,141 @@
/*
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 _SYS_TYPES_H
#define _SYS_TYPES_H
#ifndef PUBLIC
#define PUBLIC __attribute__((visibility("default")))
#endif // !PUBLIC
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
#ifndef PRIVATE
#define PRIVATE __attribute__((visibility("hidden")))
#endif // !PRIVATE
#define __iptr __INTPTR_TYPE__
__iptr __check_errno(__iptr status, __iptr err);
typedef int __pid_t;
typedef int __ssize_t;
typedef unsigned int __id_t;
typedef unsigned int __useconds_t;
#ifndef restrict
#define restrict __restrict__
#endif // restrict
#ifndef __pid_t_defined
typedef __pid_t pid_t;
#define __pid_t_defined
#ifndef export
#define export __attribute__((__visibility__("default")))
#endif // export
typedef long blkcnt_t;
typedef long blksize_t;
typedef long clock_t;
typedef int clockid_t;
typedef unsigned long dev_t;
typedef unsigned long fsblkcnt_t;
typedef unsigned long fsfilcnt_t;
typedef unsigned int gid_t;
typedef unsigned int id_t;
typedef unsigned long ino_t;
typedef unsigned short reclen_t;
typedef int key_t;
typedef unsigned int mode_t;
typedef unsigned int nlink_t;
typedef long off_t;
typedef int pid_t;
typedef struct pthread_attr_t
{
char __data;
} pthread_attr_t;
typedef struct pthread_cond_t
{
char __data;
} pthread_cond_t;
typedef struct pthread_condattr_t
{
char __data;
} pthread_condattr_t;
typedef unsigned int pthread_key_t;
typedef struct pthread_mutex_t
{
short locked;
char __data;
} pthread_mutex_t;
typedef struct pthread_mutexattr_t
{
char __data;
} pthread_mutexattr_t;
typedef struct pthread_once_t
{
int __initialized;
} pthread_once_t;
typedef struct pthread_rwlock_t
{
char __data;
} pthread_rwlock_t;
typedef struct pthread_rwlockattr_t
{
char __data;
} pthread_rwlockattr_t;
typedef struct pthread_barrier_t
{
char __data;
} pthread_barrier_t;
typedef unsigned long size_t;
typedef long ssize_t;
typedef long suseconds_t;
typedef long time_t;
typedef int timer_t;
typedef unsigned int uid_t;
typedef unsigned int useconds_t;
typedef struct __pthread
{
struct __pthread *Self;
/* For __tls_get_addr */
__UINTPTR_TYPE__ *Storage;
int CurrentError;
} __pthread;
#ifdef __cplusplus
typedef unsigned long pthread_t;
#else
typedef struct __pthread *pthread_t;
#endif
#ifndef __id_t_defined
typedef __id_t id_t;
#define __id_t_defined
#endif
#ifdef __cplusplus
}
#endif // __cplusplus
#ifndef __useconds_t_defined
typedef __useconds_t useconds_t;
#define __useconds_t_defined
#endif
#ifndef __ssize_t_defined
typedef __ssize_t ssize_t;
#define __ssize_t_defined
#endif
#endif
#endif // !_SYS_TYPES_H

View File

@ -1,108 +1,65 @@
/*
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 _SYS_WAIT_H
#define _SYS_WAIT_H
#include <sys/types.h>
typedef enum
#ifdef __cplusplus
extern "C"
{
P_ALL, /* Wait for any child. */
P_PID, /* Wait for specified process. */
P_PGID /* Wait for members of process group. */
} idtype_t;
#endif // __cplusplus
typedef struct
{
int stub;
} siginfo_t;
#include <signal.h>
#include <bits/waitstatus.h>
/* waitpid() */
#define WCONTINUED 0x00000008
#define WNOHANG 0x00000001
#define WUNTRACED 0x00000002
#define WCONTINUED 1
#define WNOHANG 2
#define WUNTRACED 4
#define WEXITED 8
#define WNOWAIT 16
#define WSTOPPED 32
/* waitid() */
#define WEXITED 0x00000004
#define WNOWAIT 0x00000020
#define WSTOPPED 0x00000002
/**
* @brief Macro for extracting the exit status from a status value.
*
* If the child process terminated normally by calling exit(3) or _exit(2),
* the macro WEXITSTATUS() returns the low-order 8 bits of the status value.
*
* @param status The status value to extract the exit status from.
* @return The exit status of the child process.
*/
#define WEXITSTATUS(status) __WEXITSTATUS(status)
#define WCOREDUMP(status) ((status) & 0x80)
#define WEXITSTATUS(status) (((status) >> 8) & 0xFF)
#define WIFCONTINUED(status) ((status) == 0xFFFF)
#define WIFEXITED(status) (((status) & 0x7F) == 0)
#define WIFSIGNALED(status) (((status) & 0x7F) > 0 && (((status) & 0x7F) != 0x7F))
#define WIFSTOPPED(status) (((status) & 0xFF) == 0x7F)
#define WSTOPSIG(status) WEXITSTATUS(status)
#define WTERMSIG(status) ((status) & 0x7F)
/**
* @brief Macro for extracting the termination signal from a status value.
*
* If the child process was terminated by a signal, the macro WTERMSIG()
* returns the signal number of the terminating signal.
*
* @param status The status value to extract the termination signal from.
* @return The termination signal of the child process.
*/
#define WTERMSIG(status) __WTERMSIG(status)
typedef enum
{
P_ALL,
P_PGID,
P_PID
} idtype_t;
/**
* @brief Macro for extracting the stop signal from a status value.
*
* If the child process was stopped by a signal, the macro WSTOPSIG()
* returns the signal number of the stop signal.
*
* @param status The status value to extract the stop signal from.
* @return The stop signal of the child process.
*/
#define WSTOPSIG(status) __WSTOPSIG(status)
typedef unsigned int id_t;
typedef int pid_t;
/**
* @brief Macro for testing whether a process exited normally.
*
* If the child process terminated normally by calling exit(3) or _exit(2),
* the macro WIFEXITED() returns a nonzero value. Otherwise, it returns 0.
*
* @param status The status value to test.
* @return A nonzero value if the child process exited normally, 0 otherwise.
*/
#define WIFEXITED(status) __WIFEXITED(status)
pid_t wait(int *);
int waitid(idtype_t, id_t, siginfo_t *, int);
pid_t waitpid(pid_t, int *, int);
/**
* @brief Macro for testing whether a process was terminated by a signal.
*
* If the child process was terminated by a signal, the macro WIFSIGNALED()
* returns a nonzero value. Otherwise, it returns 0.
*
* @param status The status value to test.
* @return A nonzero value if the child process was terminated by a signal, 0 otherwise.
*/
#define WIFSIGNALED(status) __WIFSIGNALED(status)
#ifdef __cplusplus
}
#endif // __cplusplus
/**
* @brief Macro for testing whether a process was stopped by a signal.
*
* If the child process was stopped by a signal, the macro WIFSTOPPED()
* returns a nonzero value. Otherwise, it returns 0.
*
* @param status The status value to test.
* @return A nonzero value if the child process was stopped by a signal, 0 otherwise.
*/
#define WIFSTOPPED(status) __WIFSTOPPED(status)
/**
* @brief Macro for testing whether a stopped process was continued.
*
* If the child process was stopped and has been resumed by delivery of SIGCONT,
* the macro WIFCONTINUED() returns a nonzero value. Otherwise, it returns 0.
*
* @param status The status value to test.
* @return A nonzero value if the child process was continued, 0 otherwise.
*/
#define WIFCONTINUED(status) __WIFCONTINUED(status)
pid_t wait(int *wstatus);
pid_t waitpid(pid_t pid, int *wstatus, int options);
int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options);
#endif
#endif // !_SYS_WAIT_H

View File

@ -1,4 +1,96 @@
/*
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 _TIME_H
#define _TIME_H
#endif
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
#include <bits/types/timespec.h>
#include <sys/types.h>
#include <signal.h>
#include <locale.h>
typedef struct tm
{
int tm_sec; /* Seconds [0,60]. */
int tm_min; /* Minutes [0,59]. */
int tm_hour; /* Hour [0,23]. */
int tm_mday; /* Day of month [1,31]. */
int tm_mon; /* Month of year [0,11]. */
int tm_year; /* Years since 1900. */
int tm_wday; /* Day of week [0,6] (Sunday =0). */
int tm_yday; /* Day of year [0,365]. */
int tm_isdst; /* Daylight Saving flag. */
long tm_gmtoff; /* Seconds east of UTC. */
const char *tm_zone; /* Timezone abbreviation. */
} tm;
typedef struct itimerspec
{
struct timespec it_interval; /* Timer period. */
struct timespec it_value; /* Timer expiration. */
} itimerspec;
#define CLOCKS_PER_SEC
#define TIME_UTC
#define CLOCK_MONOTONIC __SYS_CLOCK_MONOTONIC
#define CLOCK_PROCESS_CPUTIME_ID __SYS_CLOCK_PROCESS_CPUTIME_ID
#define CLOCK_REALTIME __SYS_CLOCK_REALTIME
#define CLOCK_THREAD_CPUTIME_ID __SYS_CLOCK_THREAD_CPUTIME_ID
#define TIMER_ABSTIME
extern int daylight;
extern long timezone;
extern char *tzname[];
char *asctime(const struct tm *);
clock_t clock(void);
int clock_getcpuclockid(pid_t, clockid_t *);
int clock_getres(clockid_t, struct timespec *);
int clock_gettime(clockid_t, struct timespec *);
int clock_nanosleep(clockid_t, int, const struct timespec *, struct timespec *);
int clock_settime(clockid_t, const struct timespec *);
char *ctime(const time_t *);
double difftime(time_t, time_t);
struct tm *getdate(const char *);
struct tm *gmtime(const time_t *);
struct tm *gmtime_r(const time_t *restrict, struct tm *restrict);
struct tm *localtime(const time_t *);
struct tm *localtime_r(const time_t *restrict, struct tm *restrict);
time_t mktime(struct tm *);
int nanosleep(const struct timespec *, struct timespec *);
size_t strftime(char *restrict, size_t, const char *restrict, const struct tm *restrict);
size_t strftime_l(char *restrict, size_t, const char *restrict, const struct tm *restrict, locale_t);
char *strptime(const char *restrict, const char *restrict, struct tm *restrict);
time_t time(time_t *);
int timer_create(clockid_t, struct sigevent *restrict, timer_t *restrict);
int timer_delete(timer_t);
int timer_getoverrun(timer_t);
int timer_gettime(timer_t, struct itimerspec *);
int timer_settime(timer_t, int, const struct itimerspec *restrict, struct itimerspec *restrict);
int timespec_get(struct timespec *, int);
void tzset(void);
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // !_TIME_H

View File

@ -1,206 +0,0 @@
#ifndef __FENNIX_LIBC_TYPES_H__
#define __FENNIX_LIBC_TYPES_H__
#include <stddef.h>
#include <stdarg.h>
#ifdef __cplusplus
#define EXTERNC extern "C"
#define START_EXTERNC \
EXTERNC \
{
#define END_EXTERNC \
}
#else
#define EXTERNC
#define START_EXTERNC
#define END_EXTERNC
#endif
#define asm __asm__
#define asmv __asm__ volatile
#define true 1
#define false 0
#ifdef __cplusplus
#define foreach for
#define in :
#endif
#define UNUSED(x) (void)(x)
#define CONCAT(x, y) x##y
#define toupper(c) ((c)-0x20 * (((c) >= 'a') && ((c) <= 'z')))
#define tolower(c) ((c) + 0x20 * (((c) >= 'A') && ((c) <= 'Z')))
#define ALIGN_UP(x, align) ((__typeof__(x))(((uint64_t)(x) + ((align)-1)) & (~((align)-1))))
#define ALIGN_DOWN(x, align) ((__typeof__(x))((x) & (~((align)-1))))
#define offsetof(type, member) __builtin_offsetof(type, member)
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#define VPOKE(type, address) (*((volatile type *)(address)))
#define POKE(type, address) (*((type *)(address)))
#ifndef __cplusplus
#ifdef __STDC__
#ifdef __STDC_VERSION__
#if (__STDC_VERSION__ >= 201710L)
#define C_LANGUAGE_STANDARD 2018
#elif (__STDC_VERSION__ >= 201112L)
#define C_LANGUAGE_STANDARD 2011
#elif (__STDC_VERSION__ >= 199901L)
#define C_LANGUAGE_STANDARD 1999
#elif (__STDC_VERSION__ >= 199409L)
#define C_LANGUAGE_STANDARD 1995
#endif
#else
#define C_LANGUAGE_STANDARD 1990
#endif
#else
#define C_LANGUAGE_STANDARD 1972
#endif
#else
#ifdef __STDC__
#ifdef __cplusplus
#if (__cplusplus >= 202100L)
#define CPP_LANGUAGE_STANDARD 2023
#elif (__cplusplus >= 202002L)
#define CPP_LANGUAGE_STANDARD 2020
#elif (__cplusplus >= 201703L)
#define CPP_LANGUAGE_STANDARD 2017
#elif (__cplusplus >= 201402L)
#define CPP_LANGUAGE_STANDARD 2014
#elif (__cplusplus >= 201103L)
#define CPP_LANGUAGE_STANDARD 2011
#elif (__cplusplus >= 199711L)
#define CPP_LANGUAGE_STANDARD 1998
#endif
#else
#define CPP_LANGUAGE_STANDARD __cplusplus
#endif
#else
#define CPP_LANGUAGE_STANDARD __cplusplus
#endif
#endif // __cplusplus
typedef __INT8_TYPE__ int8_t;
typedef __INT16_TYPE__ int16_t;
typedef __INT32_TYPE__ int32_t;
typedef __INT64_TYPE__ int64_t;
typedef __UINT8_TYPE__ uint8_t;
typedef __UINT16_TYPE__ uint16_t;
typedef __UINT32_TYPE__ uint32_t;
typedef __UINT64_TYPE__ uint64_t;
typedef __INT_LEAST8_TYPE__ int_least8_t;
typedef __INT_LEAST16_TYPE__ int_least16_t;
typedef __INT_LEAST32_TYPE__ int_least32_t;
typedef __INT_LEAST64_TYPE__ int_least64_t;
typedef __UINT_LEAST8_TYPE__ uint_least8_t;
typedef __UINT_LEAST16_TYPE__ uint_least16_t;
typedef __UINT_LEAST32_TYPE__ uint_least32_t;
typedef __UINT_LEAST64_TYPE__ uint_least64_t;
typedef __INT_FAST8_TYPE__ int_fast8_t;
typedef __INT_FAST16_TYPE__ int_fast16_t;
typedef __INT_FAST32_TYPE__ int_fast32_t;
typedef __INT_FAST64_TYPE__ int_fast64_t;
typedef __UINT_FAST8_TYPE__ uint_fast8_t;
typedef __UINT_FAST16_TYPE__ uint_fast16_t;
typedef __UINT_FAST32_TYPE__ uint_fast32_t;
typedef __UINT_FAST64_TYPE__ uint_fast64_t;
typedef __INTPTR_TYPE__ intptr_t;
typedef __UINTPTR_TYPE__ uintptr_t;
typedef __INTMAX_TYPE__ intmax_t;
typedef __UINTMAX_TYPE__ uintmax_t;
typedef __PTRDIFF_TYPE__ ptrdiff_t;
typedef __SIZE_TYPE__ size_t;
#define INT8_MAX __INT8_MAX__
#define INT8_MIN (-INT8_MAX - 1)
#define UINT8_MAX __UINT8_MAX__
#define INT16_MAX __INT16_MAX__
#define INT16_MIN (-INT16_MAX - 1)
#define UINT16_MAX __UINT16_MAX__
#define INT32_MAX __INT32_MAX__
#define INT32_MIN (-INT32_MAX - 1)
#define UINT32_MAX __UINT32_MAX__
#define INT64_MAX __INT64_MAX__
#define INT64_MIN (-INT64_MAX - 1)
#define UINT64_MAX __UINT64_MAX__
#define INT_LEAST8_MAX __INT_LEAST8_MAX__
#define INT_LEAST8_MIN (-INT_LEAST8_MAX - 1)
#define UINT_LEAST8_MAX __UINT_LEAST8_MAX__
#define INT_LEAST16_MAX __INT_LEAST16_MAX__
#define INT_LEAST16_MIN (-INT_LEAST16_MAX - 1)
#define UINT_LEAST16_MAX __UINT_LEAST16_MAX__
#define INT_LEAST32_MAX __INT_LEAST32_MAX__
#define INT_LEAST32_MIN (-INT_LEAST32_MAX - 1)
#define UINT_LEAST32_MAX __UINT_LEAST32_MAX__
#define INT_LEAST64_MAX __INT_LEAST64_MAX__
#define INT_LEAST64_MIN (-INT_LEAST64_MAX - 1)
#define UINT_LEAST64_MAX __UINT_LEAST64_MAX__
#define INT_FAST8_MAX __INT_FAST8_MAX__
#define INT_FAST8_MIN (-INT_FAST8_MAX - 1)
#define UINT_FAST8_MAX __UINT_FAST8_MAX__
#define INT_FAST16_MAX __INT_FAST16_MAX__
#define INT_FAST16_MIN (-INT_FAST16_MAX - 1)
#define UINT_FAST16_MAX __UINT_FAST16_MAX__
#define INT_FAST32_MAX __INT_FAST32_MAX__
#define INT_FAST32_MIN (-INT_FAST32_MAX - 1)
#define UINT_FAST32_MAX __UINT_FAST32_MAX__
#define INT_FAST64_MAX __INT_FAST64_MAX__
#define INT_FAST64_MIN (-INT_FAST64_MAX - 1)
#define UINT_FAST64_MAX __UINT_FAST64_MAX__
#define INTPTR_MAX __INTPTR_MAX__
#define INTPTR_MIN (-INTPTR_MAX - 1)
#define UINTPTR_MAX __UINTPTR_MAX__
#define INTMAX_MAX __INTMAX_MAX__
#define INTMAX_MIN (-INTMAX_MAX - 1)
#define UINTMAX_MAX __UINTMAX_MAX__
#define PTRDIFF_MAX __PTRDIFF_MAX__
#define PTRDIFF_MIN (-PTRDIFF_MAX - 1)
#define SIG_ATOMIC_MAX __SIG_ATOMIC_MAX__
#define SIG_ATOMIC_MIN __SIG_ATOMIC_MIN__
#define SIZE_MAX __SIZE_MAX__
#define WCHAR_MAX __WCHAR_MAX__
#define WCHAR_MIN __WCHAR_MIN__
#define WINT_MAX __WINT_MAX__
#define WINT_MIN __WINT_MIN__
#define b4(x) ((x & 0x0F) << 4 | (x & 0xF0) >> 4)
#define b8(x) ((x)&0xFF)
#define b16(x) __builtin_bswap16(x)
#define b32(x) __builtin_bswap32(x)
#define b48(x) (((((x)&0x0000000000ff) << 40) | (((x)&0x00000000ff00) << 24) | (((x)&0x000000ff0000) << 8) | (((x)&0x0000ff000000) >> 8) | (((x)&0x00ff00000000) >> 24) | (((x)&0xff0000000000) >> 40)))
#define b64(x) __builtin_bswap64(x)
#ifndef PUBLIC
#define PUBLIC __attribute__((visibility("default")))
#endif // !PUBLIC
#ifndef PRIVATE
#define PRIVATE __attribute__((visibility("hidden")))
#endif // !PRIVATE
#endif // !__FENNIX_LIBC_TYPES_H__

View File

@ -1,29 +1,151 @@
/*
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 _UNISTD_H
#define _UNISTD_H
#include <sys/types.h>
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
#include <sys/types.h>
#include <inttypes.h>
#define _POSIX_VERSION 200809L
#define _POSIX2_VERSION 200809L
#define _XOPEN_VERSION 700
#define F_OK 0
#define R_OK 1
#define W_OK 2
#define X_OK 3
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
#ifndef NULL
#define NULL ((void *)0)
#endif
extern char **environ;
#define _POSIX_JOB_CONTROL 1
#define _POSIX_SAVED_IDS 1
#define _POSIX_NO_TRUNC 1
#define _POSIX_VDISABLE '\0'
int execl(const char *pathname, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *pathname, const char *arg, ...);
int execv(const char *pathname, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execvpe(const char *file, char *const argv[], char *const envp[]);
int execve(const char *pathname, char *const argv[], char *const envp[]);
#define ARG_MAX 4096
#define CHILD_MAX 25
#define CLK_TCK 100
#define _SC_PAGESIZE 4096
#define _SC_OPEN_MAX 256
extern char *optarg;
extern int optind, opterr, optopt;
int access(const char *, int);
unsigned int alarm(unsigned int);
int brk(void *);
int chdir(const char *);
int chroot(const char *);
int chown(const char *, uid_t, gid_t);
int close(int);
size_t confstr(int, char *, size_t);
char *crypt(const char *, const char *);
char *ctermid(char *);
char *cuserid(char *s);
int dup(int);
int dup2(int, int);
void encrypt(char[64], int);
int execl(const char *, const char *, ...);
int execle(const char *, const char *, ...);
int execlp(const char *, const char *, ...);
int execv(const char *, char *const[]);
int execve(const char *, char *const[], char *const[]);
int execvp(const char *, char *const[]);
void _exit(int);
int fchown(int, uid_t, gid_t);
int fchdir(int);
int fdatasync(int);
pid_t fork(void);
unsigned int sleep(unsigned int seconds);
int usleep(useconds_t usec);
long int fpathconf(int, int);
int fsync(int);
int ftruncate(int, off_t);
char *getcwd(char *, size_t);
int getdtablesize(void);
gid_t getegid(void);
uid_t geteuid(void);
gid_t getgid(void);
int getgroups(int, gid_t[]);
long gethostid(void);
char *getlogin(void);
int getlogin_r(char *, size_t);
int getopt(int, char *const[], const char *);
int getpagesize(void);
char *getpass(const char *);
pid_t getpgid(pid_t);
pid_t getpgrp(void);
pid_t getpid(void);
pid_t getppid(void);
pid_t getsid(pid_t);
uid_t getuid(void);
char *getwd(char *);
int isatty(int);
int lchown(const char *, uid_t, gid_t);
int link(const char *, const char *);
int lockf(int, int, off_t);
off_t lseek(int, off_t, int);
int nice(int);
long int pathconf(const char *, int);
int pause(void);
int pipe(int[2]);
ssize_t pread(int, void *, size_t, off_t);
int pthread_atfork(void (*)(void), void (*)(void), void (*)(void));
ssize_t pwrite(int, const void *, size_t, off_t);
ssize_t read(int, void *, size_t);
int readlink(const char *, char *, size_t);
int rmdir(const char *);
void *sbrk(intptr_t);
int setgid(gid_t);
int setpgid(pid_t, pid_t);
pid_t setpgrp(void);
int setregid(gid_t, gid_t);
int setreuid(uid_t, uid_t);
pid_t setsid(void);
int setuid(uid_t);
unsigned int sleep(unsigned int);
void swab(const void *, void *, ssize_t);
int symlink(const char *, const char *);
void sync(void);
long int sysconf(int);
pid_t tcgetpgrp(int);
int tcsetpgrp(int, pid_t);
int truncate(const char *, off_t);
char *ttyname(int);
int ttyname_r(int, char *, size_t);
useconds_t ualarm(useconds_t, useconds_t);
int unlink(const char *);
int usleep(useconds_t);
pid_t vfork(void);
ssize_t write(int, const void *, size_t);
#ifdef __cplusplus
}
#endif
#endif
#endif // __cplusplus
#endif // !_UNISTD_H

View File

@ -0,0 +1,40 @@
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 -fverbose-asm
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

@ -0,0 +1,117 @@
/*
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 <fennix/syscalls.h>
#include <sys/types.h>
#include <stdint.h>
#include <stddef.h>
#include <errno.h>
#include "elf.h"
#include "misc.h"
typedef struct MemoryBlock
{
struct MemoryBlock *next;
void *slots;
size_t slot_size;
size_t slots_per_block;
uint8_t *bitmap;
} MemoryBlock;
MemoryBlock *memory_pool = NULL;
#define PAGE_SIZE 0x1000
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);
if ((intptr_t)addr < 0)
return NULL;
return addr;
}
void free_page(void *addr, size_t size)
{
size_t aligned_size = (size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
call_munmap(addr, aligned_size);
}
MemoryBlock *allocate_block(size_t slot_size)
{
size_t block_size = PAGE_SIZE;
size_t slots_per_block = block_size / slot_size;
size_t bitmap_size = (slots_per_block + 7) / 8;
MemoryBlock *block = request_page(block_size);
if (!block)
return NULL;
block->slots = (void *)((uintptr_t)block + sizeof(MemoryBlock) + bitmap_size);
block->slot_size = slot_size;
block->slots_per_block = slots_per_block;
block->bitmap = (uint8_t *)((uintptr_t)block + sizeof(MemoryBlock));
memset(block->bitmap, 0, bitmap_size);
block->next = NULL;
return block;
}
void *mini_malloc(size_t size)
{
MemoryBlock *block = memory_pool;
while (block)
{
for (size_t i = 0; i < block->slots_per_block; i++)
{
size_t byte = i / 8, bit = i % 8;
if (!(block->bitmap[byte] & (1 << bit)))
{
block->bitmap[byte] |= (1 << bit);
return (void *)((uintptr_t)block->slots + i * size);
}
}
block = block->next;
}
block = allocate_block(size);
if (!block)
return NULL;
block->next = memory_pool;
memory_pool = block;
block->bitmap[0] |= 1;
return block->slots;
}
void mini_free(void *ptr)
{
MemoryBlock *block = memory_pool;
while (block)
{
if ((uintptr_t)ptr >= (uintptr_t)block->slots &&
(uintptr_t)ptr < (uintptr_t)block->slots + block->slots_per_block * block->slot_size)
{
size_t index = ((uintptr_t)ptr - (uintptr_t)block->slots) / block->slot_size;
size_t byte = index / 8, bit = index % 8;
block->bitmap[byte] &= ~(1 << bit);
return;
}
block = block->next;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,131 @@
/*
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 <fennix/syscalls.h>
#include <sys/types.h>
#include <stdint.h>
#include <stddef.h>
#include <errno.h>
#include "elf.h"
#include "misc.h"
void *memset(void *s, int c, size_t n)
{
uint8_t *p = s;
while (n--)
*p++ = c;
return s;
}
void *memcpy(void *dest, const void *src, size_t n)
{
uint8_t *d = dest;
const uint8_t *s = src;
while (n--)
*d++ = *s++;
return dest;
}
size_t strlen(const char *s)
{
const char *p = s;
while (*p)
p++;
return p - s;
}
char *strcpy(char *dest, const char *src)
{
char *d = dest;
while ((*d++ = *src++))
;
return dest;
}
int strcmp(const char *l, const char *r)
{
while (*l && *l == *r)
{
l++;
r++;
}
return *l - *r;
}
char *strcat(char *dest, const char *src)
{
char *d = dest;
while (*d)
d++;
while ((*d++ = *src++))
;
return dest;
}
unsigned long elf_hash(const unsigned char *name)
{
unsigned long hash = 0, high;
while (*name)
{
hash = (hash << 4) + *name++;
if ((high = hash & 0xF0000000))
hash ^= high >> 24;
hash &= ~high;
}
return hash;
}
uint32_t gnu_hash(const char *name)
{
uint32_t hash = 5381;
for (; *name; name++)
{
hash = (hash << 5) + hash + (unsigned char)(*name); // hash * 33 + c
}
return hash;
}
Elf64_Sym *find_symbol(const char *name, uint32_t *hash_table, Elf64_Sym *symtab, const char *strtab)
{
/* Symbol Hash Table
|-------------------|
| nbucket |
|-------------------|
| nchain |
|-------------------|
| bucket[0] |
| . . . |
|bucket[nbucket - 1]|
|-------------------|
| chain[0] |
| . . . |
| chain[nchain - 1] |
|-------------------|
*/
unsigned long h = elf_hash(name); // or gnu_hash(name)
unsigned long bucket = h % hash_table[0]; // hash_table[0] = nbucket
for (unsigned long i = hash_table[2 + bucket];
i != STN_UNDEF;
i = hash_table[2 + hash_table[0] + i])
{
if (!strcmp(&strtab[symtab[i].st_name], name))
return &symtab[i];
}
return NULL;
}

View File

@ -0,0 +1,975 @@
/*
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 <fennix/syscalls.h>
#include <sys/types.h>
#include <inttypes.h>
#include <stddef.h>
#include <limits.h>
#include <errno.h>
#include "elf.h"
#include "misc.h"
typedef struct ElfInfo
{
Elf_Ehdr Header;
Elf_Phdr DynamicHeader;
uintptr_t BaseAddress;
Elf_Dyn *Dynamic;
char *Path;
struct
{
Elf_Addr PLTGOT, HASH, STRTAB, SYMTAB, RELA, REL, TEXTREL, JMPREL;
Elf_Addr BIND_NOW, INIT, FINI, RPATH, SYMBOLIC, INIT_ARRAY;
Elf_Addr FINI_ARRAY, PREINIT_ARRAY, RUNPATH, FLAGS;
} DynamicTable;
struct
{
#ifdef __LP64__
_Static_assert(sizeof(Elf64_Xword) == sizeof(size_t), "Elf64_Xword and size_t are not the same size");
#else
_Static_assert(sizeof(Elf32_Word) == sizeof(size_t), "Elf32_Word and size_t are not the same size");
#endif
size_t PLTRELSZ, RELASZ, RELAENT, STRSZ, SYMENT, RELSZ, RELENT, PLTREL;
size_t INIT_ARRAYSZ, FINI_ARRAYSZ, PREINIT_ARRAYSZ;
} DynamicSize;
union
{
struct
{
uint8_t Relocated : 1;
uint8_t IsLibrary : 1;
uint8_t __padding : 6;
};
uint8_t raw;
} Flags;
struct ElfInfo *prev;
struct ElfInfo *next;
} ElfInfo;
ElfInfo *elf_list_head = NULL;
ElfInfo *AllocateLib()
{
ElfInfo *new_node = mini_malloc(sizeof(ElfInfo));
if (!new_node)
{
printf("Failed to allocate memory for new library\n");
return NULL;
}
memset(new_node, 0, sizeof(ElfInfo));
if (!elf_list_head)
{
elf_list_head = new_node;
return new_node;
}
ElfInfo *current = elf_list_head;
while (current->next)
current = current->next;
current->next = new_node;
new_node->prev = current;
return new_node;
}
void FreeLib(ElfInfo *node)
{
if (!node)
return;
if (node->prev)
node->prev->next = node->next;
else
elf_list_head = node->next;
if (node->next)
node->next->prev = node->prev;
mini_free(node);
}
ElfInfo *SearchLib(char *Path)
{
ElfInfo *current = elf_list_head;
while (current)
{
if (strcmp(current->Path, Path) == 0)
return current;
current = current->next;
}
return NULL;
}
__attribute__((naked, used, no_stack_protector)) void _dl_runtime_resolve()
{
__asm__(
"pop %r11\n" /* Pop lazy resolve arguments */
"pop %r10\n"
"push %rdi\n"
"push %rsi\n"
"push %rdx\n"
"push %rcx\n"
"push %r8\n"
"push %r9\n"
"mov %r11, %rdi\n" /* Move the first argument to rdi */
"mov %r10, %rsi\n" /* Move the second argument to rsi (rel index) */
"call _dl_fixup\n" /* Call _dl_fixup */
"mov %rax, %r11\n" /* Move the return value to r11 */
"pop %r9\n"
"pop %r8\n"
"pop %rcx\n"
"pop %rdx\n"
"pop %rsi\n"
"pop %rdi\n"
"jmp *%r11\n"); /* Jump to the return value */
}
int RelocateHelper(ElfInfo *Info, Elf_Rela *Rela, short IsRel, void **Relocated);
__attribute__((noinline)) void *_dl_fixup(ElfInfo *Info, long RelIndex)
{
void *ret = NULL;
if (Info->DynamicSize.PLTREL == DT_REL)
RelocateHelper(Info, (Elf_Rela *)(Info->DynamicTable.JMPREL + RelIndex), 1, &ret);
else if (Info->DynamicSize.PLTREL == DT_RELA)
RelocateHelper(Info, &((Elf_Rela *)Info->DynamicTable.JMPREL)[RelIndex], 0, &ret);
return ret;
}
int _dl_preload()
{
call_api_version(0);
/* TODO: Do aditional checks for miscellaneous things */
/* Everything is ok, continue. */
return 0;
}
void HandleGOT(ElfInfo *Info, Elf_Addr Offset)
{
Elf_Addr *got = (Elf_Addr *)Offset;
got[0] = (Elf_Addr)Info->Dynamic;
got[1] = (Elf_Addr)Info;
got[2] = (Elf_Addr)&_dl_runtime_resolve;
}
void AdjustDynamicTable(Elf_Dyn *elem, ElfInfo *Info)
{
switch (elem->d_tag)
{
case DT_PLTGOT:
case DT_HASH:
case DT_STRTAB:
case DT_SYMTAB:
case DT_RELA:
case DT_INIT:
case DT_FINI:
case DT_REL:
case DT_JMPREL:
case DT_INIT_ARRAY:
case DT_FINI_ARRAY:
elem->d_un.d_ptr += Info->BaseAddress;
break;
default:
break;
}
}
void CreateInfoTables(Elf_Dyn *elem, ElfInfo *Info)
{
switch (elem->d_tag)
{
case DT_NEEDED:
break;
case DT_PLTRELSZ:
Info->DynamicSize.PLTRELSZ = elem->d_un.d_val;
break;
case DT_PLTGOT:
HandleGOT(Info, elem->d_un.d_ptr);
Info->DynamicTable.PLTGOT = elem->d_un.d_ptr;
break;
case DT_HASH:
Info->DynamicTable.HASH = elem->d_un.d_ptr;
break;
case DT_STRTAB:
Info->DynamicTable.STRTAB = elem->d_un.d_ptr;
break;
case DT_SYMTAB:
Info->DynamicTable.SYMTAB = elem->d_un.d_ptr;
break;
case DT_RELA:
Info->DynamicTable.RELA = elem->d_un.d_ptr;
break;
case DT_RELASZ:
Info->DynamicSize.RELASZ = elem->d_un.d_val;
break;
case DT_RELAENT:
Info->DynamicSize.RELAENT = elem->d_un.d_val;
break;
case DT_STRSZ:
Info->DynamicSize.STRSZ = elem->d_un.d_val;
break;
case DT_SYMENT:
Info->DynamicSize.SYMENT = elem->d_un.d_val;
break;
case DT_INIT:
Info->DynamicTable.INIT = elem->d_un.d_ptr;
break;
case DT_FINI:
Info->DynamicTable.FINI = elem->d_un.d_ptr;
break;
case DT_RPATH:
Info->DynamicTable.RPATH = elem->d_un.d_ptr;
break;
case DT_SYMBOLIC:
Info->DynamicTable.SYMBOLIC = elem->d_un.d_ptr;
break;
case DT_REL:
Info->DynamicTable.REL = elem->d_un.d_ptr;
break;
case DT_RELSZ:
Info->DynamicSize.RELSZ = elem->d_un.d_val;
break;
case DT_RELENT:
Info->DynamicSize.RELENT = elem->d_un.d_val;
break;
case DT_PLTREL:
Info->DynamicSize.PLTREL = elem->d_un.d_val;
break;
// case DT_DEBUG:
case DT_TEXTREL:
Info->DynamicTable.TEXTREL = elem->d_un.d_ptr;
break;
case DT_JMPREL:
Info->DynamicTable.JMPREL = elem->d_un.d_ptr;
break;
case DT_BIND_NOW:
Info->DynamicTable.BIND_NOW = elem->d_un.d_ptr;
break;
case DT_INIT_ARRAY:
Info->DynamicTable.INIT_ARRAY = elem->d_un.d_ptr;
break;
case DT_FINI_ARRAY:
Info->DynamicTable.FINI_ARRAY = elem->d_un.d_ptr;
break;
case DT_INIT_ARRAYSZ:
Info->DynamicSize.INIT_ARRAYSZ = elem->d_un.d_val;
break;
case DT_FINI_ARRAYSZ:
Info->DynamicSize.FINI_ARRAYSZ = elem->d_un.d_val;
break;
case DT_RUNPATH:
Info->DynamicTable.RUNPATH = elem->d_un.d_ptr;
break;
case DT_FLAGS:
Info->DynamicTable.FLAGS = elem->d_un.d_ptr;
break;
// case DT_ENCODING:
case DT_PREINIT_ARRAY:
Info->DynamicTable.PREINIT_ARRAY = elem->d_un.d_ptr;
break;
case DT_PREINIT_ARRAYSZ:
Info->DynamicSize.PREINIT_ARRAYSZ = elem->d_un.d_val;
break;
case DT_LOOS:
case DT_SUNW_RTLDINF:
case DT_HIOS:
case DT_VALRNGLO:
case DT_CHECKSUM:
case DT_PLTPADSZ:
case DT_MOVEENT:
case DT_MOVESZ:
case DT_FEATURE_1:
case DT_POSFLAG_1:
case DT_SYMINSZ:
case DT_SYMINENT:
// case DT_VALRNGHI:
case DT_ADDRRNGLO:
case DT_CONFIG:
case DT_DEPAUDIT:
case DT_AUDIT:
case DT_PLTPAD:
case DT_MOVETAB:
case DT_SYMINFO:
// case DT_ADDRRNGHI:
case DT_RELACOUNT:
case DT_RELCOUNT:
case DT_FLAGS_1:
case DT_VERDEF:
case DT_VERDEFNUM:
case DT_VERNEED:
case DT_VERNEEDNUM:
case DT_LOPROC:
case DT_SPARC_REGISTER:
case DT_AUXILIARY:
case DT_USED:
case DT_FILTER:
// case DT_HIPROC:
default:
break;
}
}
int LoadElf(int, char *, ElfInfo **);
void ProcessNeededLibraries(Elf_Dyn *elem, ElfInfo *Info)
{
char *libPath = (char *)Info->DynamicTable.STRTAB + elem->d_un.d_val;
ElfInfo *info = NULL;
char fullLibPath[PATH_MAX];
strcpy(fullLibPath, "/lib/");
strcat(fullLibPath, libPath);
/* TODO: more checks and also check environment variables */
if (call_access(fullLibPath, __SYS_F_OK) != 0)
{
printf("dl: Can't access %s\n", fullLibPath);
return;
}
int fd = call_open(fullLibPath, __SYS_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);
if (status < 0) /* announce that LoadElf failed */
printf("dl: Can't load %s\n", fullLibPath);
}
void ProcessDynamicTable(ElfInfo *Info)
{
for (size_t i = 0;; i++)
{
Elf_Dyn *elem = &Info->Dynamic[i];
if (elem->d_tag == DT_NULL)
break;
AdjustDynamicTable(elem, Info);
CreateInfoTables(elem, Info);
}
/* TODO: Optimize this, we don't have to recheck every element */
for (size_t i = 0;; i++)
{
Elf_Dyn *elem = &Info->Dynamic[i];
if (elem->d_tag == DT_NULL)
break;
if (elem->d_tag != DT_NEEDED)
continue;
ProcessNeededLibraries(elem, Info);
}
}
uintptr_t GetASLR()
{
#ifdef DEBUG
static uintptr_t __aslr_stub_next = 0;
__aslr_stub_next += 0x1000000;
return __aslr_stub_next;
#else
/* FIXME: implement real ASLR */
static uintptr_t __aslr_stub_next = 0;
__aslr_stub_next += 0x1000000;
return __aslr_stub_next;
#endif
}
int LoadElfPhdrEXEC(int fd, ElfInfo *Info)
{
printf("dl: ET_EXEC not implemented yet\n");
return -ENOSYS;
}
uintptr_t DynamicCreateBase(int fd, ElfInfo *Info)
{
uintptr_t base = GetASLR();
if ((uintptr_t)base <= 0)
{
printf("dl: Can't get ASLR\n");
_Exit(-1);
}
Info->BaseAddress = base;
return base;
}
int LoadElfPhdrDYN(int fd, ElfInfo *Info)
{
Elf_Ehdr header = Info->Header;
Info->Dynamic = NULL;
uintptr_t base = 0;
Elf_Phdr phdr, lastLOAD;
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));
if (read != sizeof(Elf_Phdr))
{
printf("dl: Can't read program header %d\n", i);
return (int)read;
}
switch (phdr.p_type)
{
case PT_LOAD:
{
if (phdr.p_memsz == 0)
continue;
if (base == 0)
base = DynamicCreateBase(fd, Info);
int mmapProt = 0;
if (phdr.p_flags & PF_X)
mmapProt |= __SYS_PROT_EXEC;
if (phdr.p_flags & PF_W)
mmapProt |= __SYS_PROT_WRITE;
if (phdr.p_flags & PF_R)
mmapProt |= __SYS_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);
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);
if (read != phdr.p_filesz)
{
printf("dl: Can't read segment %d in PT_LOAD\n", i);
return (int)read;
}
}
if (phdr.p_memsz - phdr.p_filesz > 0)
{
/* TODO: Do we really have to do this? Kernel already zeros the memory for us */
void *zero = (void *)(section + sectionOffset + phdr.p_filesz);
memset(zero, 0, phdr.p_memsz - phdr.p_filesz);
}
lastLOAD = phdr;
break;
}
case PT_DYNAMIC:
{
Elf_Dyn *dynamicTable = NULL;
if (phdr.p_vaddr == lastLOAD.p_vaddr && phdr.p_memsz < lastLOAD.p_memsz)
{
/* The dynamic section is inside the last LOAD segment */
dynamicTable = (Elf_Dyn *)(base + phdr.p_vaddr);
}
else
{
int mmapProt = 0;
if (phdr.p_flags & PF_X)
mmapProt |= __SYS_PROT_EXEC;
if (phdr.p_flags & PF_W)
mmapProt |= __SYS_PROT_WRITE;
if (phdr.p_flags & PF_R)
mmapProt |= __SYS_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);
if ((intptr_t)dynamicTable <= 0)
{
printf("dl: Can't allocate memory for PT_DYNAMIC\n");
return (int)(uintptr_t)dynamicTable;
}
read = call_pread(fd, dynamicTable, phdr.p_memsz, phdr.p_offset);
if (read != phdr.p_memsz)
{
printf("dl: Can't read PT_DYNAMIC\n");
return (int)read;
}
}
Info->Dynamic = dynamicTable;
Info->DynamicHeader = phdr;
break;
}
case PT_INTERP:
break;
case PT_NOTE:
break;
case PT_SHLIB:
break;
case PT_PHDR:
break;
case PT_TLS:
{
printf("dl: PT_TLS not implemented yet\n");
break;
}
default:
{
printf("dl: Unimplemented program header type %d\n", phdr.p_type);
break;
}
}
}
return 0;
}
int CheckElfEhdr(Elf_Ehdr *ehdr, char *Path)
{
if (ehdr->e_ident[EI_MAG0] != ELFMAG0 ||
ehdr->e_ident[EI_MAG1] != ELFMAG1 ||
ehdr->e_ident[EI_MAG2] != ELFMAG2 ||
ehdr->e_ident[EI_MAG3] != ELFMAG3)
{
printf("dl: %s is not an ELF file\n", Path);
return -EINVAL;
}
#ifdef __LP64__
const int elfClass = ELFCLASS64;
#else
const int elfClass = ELFCLASS32;
#endif
if (ehdr->e_ident[EI_CLASS] != elfClass)
{
printf("dl: %s is not a %s-bit ELF file\n",
Path, __LP64__ ? "64" : "32");
return -EINVAL;
}
/* TODO: check LSB MSB */
if (ehdr->e_ident[EI_VERSION] != EV_CURRENT || ehdr->e_version != EV_CURRENT)
{
printf("dl: %s has an unsupported ELF version\n", Path);
return -EINVAL;
}
if (ehdr->e_type != ET_DYN && ehdr->e_type != ET_EXEC)
{
printf("dl: %s is not a shared object or executable\n", Path);
return -EINVAL;
}
return 0;
}
int LoadElf(int fd, char *Path, ElfInfo **Out)
{
ElfInfo *info = SearchLib(Path);
if (info != NULL)
{
*Out = info;
return 0;
}
Elf_Ehdr header;
call_pread(fd, &header, sizeof(Elf_Ehdr), 0);
int status = CheckElfEhdr(&header, Path);
if (status != 0)
return status;
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);
if ((intptr_t)info->Path <= 0)
{
printf("dl: Can't allocate memory for path\n");
FreeLib(info);
return (int)(uintptr_t)info->Path;
}
memcpy(info->Path, Path, strlen(Path) + 1);
switch (header.e_type)
{
case ET_REL:
printf("dl: ET_REL not implemented yet\n");
status = -ENOSYS;
break;
case ET_EXEC:
status = LoadElfPhdrEXEC(fd, info);
break;
case ET_DYN:
status = LoadElfPhdrDYN(fd, info);
break;
case ET_CORE:
printf("dl: ET_CORE not implemented yet\n");
status = -ENOSYS;
break;
case ET_NONE:
printf("dl: ET_NONE???\n");
status = -EINVAL;
break;
default:
printf("dl: Unsupported ELF type %d\n", header.e_type);
status = -EINVAL;
break;
}
if (status < 0)
{
call_munmap((uintptr_t)info->Path, ALIGN_UP(strlen(Path) + 1, 0x1000));
FreeLib(info);
return status;
}
ProcessDynamicTable(info);
*Out = info;
return 0;
}
uintptr_t GetSymbolAddress(ElfInfo *Info, const char *SymbolName)
{
Elf64_Sym *sym = find_symbol(SymbolName,
(uint32_t *)Info->DynamicTable.HASH,
(Elf64_Sym *)Info->DynamicTable.SYMTAB,
(const char *)Info->DynamicTable.STRTAB);
if (sym == NULL)
return (-ENOSYS);
return Info->BaseAddress + sym->st_value;
}
int ResolveExternalSymbol(ElfInfo *Info, uintptr_t *symAddress, Elf_Sym *sym, const char *symName)
{
*symAddress = (-ENOSYS);
for (size_t i = 0; *symAddress == (-ENOSYS); i++)
{
Elf_Dyn *dyn = &Info->Dynamic[i];
if (dyn->d_tag == DT_NULL)
break;
if (dyn->d_tag != DT_NEEDED)
continue;
ElfInfo *lib = (ElfInfo *)dyn->d_un.d_ptr;
*symAddress = GetSymbolAddress(lib, symName);
}
if (*symAddress != (-ENOSYS))
return 0;
printf("%s: Unresolved symbol: %s\n", Info->Path, symName);
if (ELF_ST_BIND(sym->st_info) != STB_WEAK)
return -EINVAL;
*symAddress = 0;
return 0;
}
int ApplyRelocation(ElfInfo *Info, uintptr_t *reloc, Elf_Rela *Rela, size_t reloSize)
{
switch (reloSize)
{
case 0:
break;
case sizeof(uint8_t):
*reloc += *(uint8_t *)(Info->BaseAddress + Rela->r_offset);
break;
case sizeof(uint16_t):
*reloc += *(uint16_t *)(Info->BaseAddress + Rela->r_offset);
break;
case sizeof(uint32_t):
*reloc += *(uint32_t *)(Info->BaseAddress + Rela->r_offset);
break;
case sizeof(uint64_t):
*reloc += *(uint64_t *)(Info->BaseAddress + Rela->r_offset);
break;
default:
{
printf("dl: Unsupported size for relocation\n");
return -EINVAL;
}
}
return 0;
}
int CalculateRelocation(ElfInfo *Info, uintptr_t *reloc, Elf_Rela *Rela, size_t reloSize)
{
switch (reloSize)
{
case 0:
break;
case sizeof(uint8_t):
*(uint8_t *)(Info->BaseAddress + Rela->r_offset) = *reloc;
break;
case sizeof(uint16_t):
*(uint16_t *)(Info->BaseAddress + Rela->r_offset) = *reloc;
break;
case sizeof(uint32_t):
*(uint32_t *)(Info->BaseAddress + Rela->r_offset) = *reloc;
break;
case sizeof(uint64_t):
*(uint64_t *)(Info->BaseAddress + Rela->r_offset) = *reloc;
break;
default:
{
printf("dl: Unsupported size for relocation\n");
return -EINVAL;
}
}
return 0;
}
int RelocateHelper(ElfInfo *Info, Elf_Rela *Rela, short IsRel, void **Relocated)
{
uintptr_t reloc = 0;
uintptr_t symAddress = 0;
size_t symSize = 0;
uint32_t symIndex = ELF_R_SYM(Rela->r_info);
if (symIndex)
{
Elf_Sym *sym = (Elf_Sym *)(Info->DynamicTable.SYMTAB + symIndex * Info->DynamicSize.SYMENT);
const char *symName = (const char *)(Info->DynamicTable.STRTAB + sym->st_name);
symSize = sym->st_size;
if (!(ELF_R_TYPE(Rela->r_info) == R_COPY) && sym->st_shndx)
symAddress = Info->BaseAddress + sym->st_value;
else if (ResolveExternalSymbol(Info, &symAddress, sym, symName) < 0)
return -EINVAL;
}
size_t reloSize = 0;
int addAddend = 0;
enum RelocationTypes relType = ELF_R_TYPE(Rela->r_info);
switch (relType)
{
case R_NONE:
break;
case R_X86_64_64:
{
reloSize = 8;
reloc = symAddress;
addAddend = 1;
break;
}
case R_COPY:
{
if (symAddress == 0)
{
printf("dl: Copy undefined weak symbol %d\n", ELF_R_SYM(Rela->r_info));
return -EINVAL;
}
memcpy((void *)(Info->BaseAddress + Rela->r_offset),
(void *)symAddress,
symSize);
break;
}
case R_GLOB_DAT:
case R_JMP_SLOT:
{
reloSize = 8;
reloc = symAddress;
break;
}
case R_RELATIVE:
{
reloSize = 8;
reloc = Info->BaseAddress;
addAddend = 1;
break;
}
case R_DTPMOD64:
{
printf("dl: i don't know what to do with DTPMOD64\n");
reloc = Info->BaseAddress;
break;
}
case R_DTPOFF64:
{
printf("dl: i don't know what to do with DTPOFF64\n");
reloc = symAddress + Rela->r_addend;
break;
}
case R_TPOFF64:
{
printf("dl: i don't know what to do with TPOFF64\n");
reloc = symAddress + Rela->r_addend;
break;
}
default:
{
printf("dl: Unsupported relocation type %d\n", relType);
return -EINVAL;
}
}
if (addAddend)
{
if (IsRel == 0)
reloc += Rela->r_addend;
else if (ApplyRelocation(Info, &reloc, Rela, reloSize) < 0)
return -EINVAL;
}
CalculateRelocation(Info, &reloc, Rela, reloSize);
if (Relocated != NULL)
*Relocated = (void *)reloc;
return 0;
}
int HandleRelocations(ElfInfo *Info);
void SearchNeeded(ElfInfo *Info)
{
for (size_t i = 0;; i++)
{
Elf_Dyn *elem = &Info->Dynamic[i];
if (elem->d_tag == DT_NULL)
break;
if (elem->d_tag != DT_NEEDED)
continue;
HandleRelocations((ElfInfo *)elem->d_un.d_ptr);
}
}
int HandleRelocations(ElfInfo *Info)
{
if (Info->Flags.Relocated)
return 0;
SearchNeeded(Info);
if (Info->DynamicTable.REL != ((Elf_Addr)0) && Info->DynamicSize.RELENT != 0)
{
for (size_t i = 0; i < Info->DynamicSize.RELSZ / Info->DynamicSize.RELENT; i++)
RelocateHelper(Info, (Elf_Rela *)(Info->DynamicTable.REL + i * Info->DynamicSize.RELENT), 1, NULL);
}
if (Info->DynamicTable.RELA != ((Elf_Addr)0) && Info->DynamicSize.RELAENT != 0)
{
for (size_t i = 0; i < Info->DynamicSize.RELASZ / Info->DynamicSize.RELAENT; i++)
RelocateHelper(Info, (Elf_Rela *)(Info->DynamicTable.RELA + i * Info->DynamicSize.RELAENT), 0, NULL);
}
if (Info->DynamicTable.JMPREL == ((Elf_Addr)0) || Info->DynamicSize.PLTRELSZ == 0)
return 0;
if (Info->DynamicSize.PLTREL != DT_REL && Info->DynamicSize.PLTREL != DT_RELA)
{
printf("dl: Wrong PLT relocation type %d\n", Info->DynamicSize.PLTREL);
return -EINVAL;
}
if (Info->DynamicTable.BIND_NOW != ((Elf_Addr)0))
{
if (Info->DynamicSize.PLTREL == DT_REL)
{
for (size_t i = 0; i < Info->DynamicSize.PLTRELSZ / sizeof(Elf_Rel); i++)
RelocateHelper(Info, (Elf_Rela *)&((Elf_Rel *)Info->DynamicTable.JMPREL)[i], 1, NULL);
}
else if (Info->DynamicSize.PLTREL == DT_RELA)
{
for (size_t i = 0; i < Info->DynamicSize.PLTRELSZ / sizeof(Elf_Rela); i++)
RelocateHelper(Info, (Elf_Rela *)&((Elf_Rela *)Info->DynamicTable.JMPREL)[i], 0, NULL);
}
Info->Flags.Relocated = 1;
return 0;
}
size_t relsize = Info->DynamicSize.PLTREL == DT_REL ? sizeof(Elf_Rel) : sizeof(Elf_Rela);
for (size_t i = 0; i < Info->DynamicSize.PLTRELSZ / relsize; i++)
{
Elf64_Xword info = (Info->DynamicSize.PLTREL == DT_REL
? ((Elf_Rel *)Info->DynamicTable.JMPREL)[i].r_info
: ((Elf_Rela *)Info->DynamicTable.JMPREL)[i].r_info);
Elf_Addr offset = (Info->DynamicSize.PLTREL == DT_REL
? ((Elf_Rel *)Info->DynamicTable.JMPREL)[i].r_offset
: ((Elf_Rela *)Info->DynamicTable.JMPREL)[i].r_offset);
if (ELF_R_TYPE(info) != R_JMP_SLOT)
{
printf("dl: Wrong JMPREL type %d\n", ELF_R_TYPE(info));
return -EINVAL;
}
/* FIXME: HANDLE THIS RIGHT */
if (Info->DynamicSize.PLTREL == DT_REL)
{
Elf_Addr *slot = (Elf_Addr *)(Info->BaseAddress + offset);
*slot += Info->BaseAddress;
if (*slot == Info->BaseAddress)
RelocateHelper(Info, (Elf_Rela *)&((Elf_Rel *)Info->DynamicTable.JMPREL)[i], 1, NULL);
}
else if (Info->DynamicSize.PLTREL == DT_RELA)
{
Elf64_Sxword addend = ((Elf_Rela *)Info->DynamicTable.JMPREL)[i].r_addend;
Elf_Addr *slot = (Elf_Addr *)(Info->BaseAddress + offset);
*slot += Info->BaseAddress + addend;
if (*slot == Info->BaseAddress)
RelocateHelper(Info, (Elf_Rela *)&((Elf_Rela *)Info->DynamicTable.JMPREL)[i], 0, NULL);
}
}
Info->Flags.Relocated = 1;
return 0;
}
int _dl_main(int argc, char *argv[], char *envp[])
{
char *path = argv[0];
ElfInfo *info = NULL;
if (call_access(path, __SYS_F_OK) < 0)
{
printf("dl: Can't access file %s\n", path);
return -EACCES;
}
int fd = call_open(path, __SYS_O_RDONLY, 0644);
int status = LoadElf(fd, path, &info);
if (status < 0)
{
printf("%s: Can't load ELF file\n", path);
call_close(fd);
return status;
}
status = HandleRelocations(info);
if (status < 0)
{
printf("%s: Can't relocate ELF file\n", path);
call_close(fd);
return status;
}
call_close(fd);
Elf_Addr entry = info->BaseAddress + info->Header.e_entry;
return ((int (*)(int, char *[], char *[]))entry)(argc, argv, envp);
}

View File

@ -0,0 +1,51 @@
/*
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 <stdio.h>
#include <string.h>
int printf(const char *, ...);
int _dl_main(int, char *[], char *[]);
void print_help()
{
printf("Usage: ld.so [options] <program>\n");
printf("Options:\n");
printf(" --help Display this help message\n");
}
int main(int argc, char *argv[], char *envp[])
{
if (argc < 2)
{
printf("Error: No program specified.\n");
print_help();
return -1;
}
for (int i = 1; i < argc; i++)
{
if (strcmp(argv[i], "--help") == 0)
{
print_help();
return 0;
}
}
int status = _dl_main(argc, argv, envp);
return status;
}

View File

@ -0,0 +1,50 @@
/*
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_DL_HELPER_H__
#define __FENNIX_DL_HELPER_H__
#include <sys/types.h>
#include <stdint.h>
#include <stddef.h>
#define ALIGN_UP(x, align) ((__typeof__(x))(((uintptr_t)(x) + ((align) - 1)) & (~((align) - 1))))
#define ALIGN_DOWN(x, align) ((__typeof__(x))((x) & (~((align) - 1))))
#ifndef __FENNIX_DL_ELF_H__
#error "Please include elf.h before misc.h"
#endif
void *memset(void *s, int c, size_t n);
void *memcpy(void *dest, const void *src, size_t n);
size_t strlen(const char *s);
char *strcpy(char *dest, const char *src);
int strcmp(const char *l, const char *r);
char *strcat(char *dest, const char *src);
unsigned long elf_hash(const unsigned char *name);
uint32_t gnu_hash(const char *name);
Elf64_Sym *find_symbol(const char *name, uint32_t *hash_table, Elf64_Sym *symtab, const char *strtab);
void __init_print_buffer();
void __fini_print_buffer();
int printf(const char *format, ...);
void *mini_malloc(size_t size);
void mini_free(void *ptr);
#endif // !__FENNIX_DL_HELPER_H__

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,82 @@
/*
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 <stddef.h>
#include <stdarg.h>
#include <fennix/syscalls.h>
#include "elf.h"
#include "misc.h"
#define NANOPRINTF_IMPLEMENTATION 1
#include "nanoprintf.h"
char *print_buffer;
size_t print_buffer_size;
size_t print_buffer_offset;
void flush_buffer()
{
if (print_buffer_offset > 0)
{
call_write(1, print_buffer, print_buffer_offset);
print_buffer_offset = 0;
}
}
void print_wrapper(int c, void *)
{
if (print_buffer_offset >= print_buffer_size - 1)
flush_buffer();
print_buffer[print_buffer_offset++] = (char)c;
}
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_size = 0x1000;
print_buffer_offset = 0;
}
void __fini_print_buffer()
{
flush_buffer();
if (print_buffer != NULL)
call_munmap(print_buffer, 0x1000);
print_buffer = NULL;
}
int printf(const char *format, ...)
{
va_list args;
va_start(args, format);
int ret = npf_vpprintf(print_wrapper, NULL, format, args);
va_end(args);
return ret;
}
int puts(const char *s)
{
int len = strlen(s);
memcpy(print_buffer + print_buffer_offset, s, len);
print_buffer_offset += len;
print_buffer[print_buffer_offset++] = '\0';
flush_buffer();
return len + 1;
}

View File

@ -0,0 +1,139 @@
/*
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 <fennix/syscalls.h>
// const char __interp[] __attribute__((section(".interp"))) = "/boot/fennix.elf";
#ifndef LIBC_GIT_COMMIT
#define LIBC_GIT_COMMIT "0000000000000000000000000000000000000000"
#endif
#define HEX_DIGIT(c) (((c) >= '0' && (c) <= '9') ? ((c) - '0') : ((c) - 'a' + 10))
#define CONVERT_TO_BYTE(h, l) ((HEX_DIGIT(h) << 4) | HEX_DIGIT(l))
#define HASH_BYTES(hex) \
{CONVERT_TO_BYTE(hex[0], hex[1]), \
CONVERT_TO_BYTE(hex[2], hex[3]), \
CONVERT_TO_BYTE(hex[4], hex[5]), \
CONVERT_TO_BYTE(hex[6], hex[7]), \
CONVERT_TO_BYTE(hex[8], hex[9]), \
CONVERT_TO_BYTE(hex[10], hex[11]), \
CONVERT_TO_BYTE(hex[12], hex[13]), \
CONVERT_TO_BYTE(hex[14], hex[15]), \
CONVERT_TO_BYTE(hex[16], hex[17]), \
CONVERT_TO_BYTE(hex[18], hex[19]), \
CONVERT_TO_BYTE(hex[20], hex[21]), \
CONVERT_TO_BYTE(hex[22], hex[23]), \
CONVERT_TO_BYTE(hex[24], hex[25]), \
CONVERT_TO_BYTE(hex[26], hex[27]), \
CONVERT_TO_BYTE(hex[28], hex[29]), \
CONVERT_TO_BYTE(hex[30], hex[31]), \
CONVERT_TO_BYTE(hex[32], hex[33]), \
CONVERT_TO_BYTE(hex[34], hex[35]), \
CONVERT_TO_BYTE(hex[36], hex[37]), \
CONVERT_TO_BYTE(hex[38], hex[39])}
/* 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
};
typedef struct Elf_Nhdr
{
__UINT32_TYPE__ n_namesz;
__UINT32_TYPE__ n_descsz;
__UINT32_TYPE__ n_type;
char n_name[];
} __attribute__((packed)) Elf_Nhdr;
const struct
{
Elf_Nhdr header;
char name[4];
__UINT32_TYPE__ desc[4];
} __abi_tag __attribute__((aligned(4), section(".note.ABI-tag"))) = {
.header = {
.n_namesz = 4, /* "FNX" + '\0' */
.n_descsz = sizeof(__UINT32_TYPE__) * 4, /* Description Size */
.n_type = NT_FNX_ABI_TAG, /* Type */
},
.name = "FNX",
.desc = {0, 0, 0, 0},
};
const struct
{
Elf_Nhdr header;
char name[4];
__UINT8_TYPE__ desc[20];
} __build_id __attribute__((aligned(4), section(".note.build-id"))) = {
.header = {
.n_namesz = 4, /* "FNX" + '\0' */
.n_descsz = sizeof(__UINT8_TYPE__) * 20, /* Description Size */
.n_type = NT_FNX_BUILD_ID, /* Type */
},
.name = "FNX",
.desc = HASH_BYTES(LIBC_GIT_COMMIT),
};
void __init_print_buffer();
void __fini_print_buffer();
__attribute__((naked, used, no_stack_protector)) void _start()
{
__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 */
}
__attribute__((no_stack_protector)) _Noreturn void _exit(int status)
{
__fini_print_buffer();
call_exit(status);
/* At this point, the program *SHOULD* have exited. */
__asm__("ud2\n");
__builtin_unreachable();
}
__attribute__((no_stack_protector)) _Noreturn void _Exit(int status) { _exit(status); }

View File

@ -1,20 +1,10 @@
# Config file
include ../../../config.mk
default:
$(error Do not run this Makefile directly!)
CC = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)gcc
AS = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)as
NASM = /usr/bin/nasm
C_SOURCES = $(shell find ./ -type f -name '*.c')
S_SOURCES = $(shell find ./ -type f -name '*.S')
ASM_SOURCES = $(shell find ./ -type f -name '*.asm')
OBJ = ${C_SOURCES:.c=.o} ${ASM_SOURCES:.asm=.o} ${S_SOURCES:.S=.o}
ifeq ($(OSARCH), amd64)
ASM_ARCH := elf64
else ifeq ($(OSARCH), i386)
ASM_ARCH := elf32
endif
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)
@ -22,20 +12,16 @@ CRTI_PATH = $(shell $(CC) -print-file-name=crti.o)
CRTN_PATH = $(shell $(CC) -print-file-name=crtn.o)
build: $(OBJ)
mv $^ ../../out/lib/
cp $(CRTBEGIN_PATH) $(CRTEND_PATH) $(CRTI_PATH) $(CRTN_PATH) ../../out/lib/
cp $^ ../../out/lib/
cp $(CRTBEGIN_PATH) $(CRTEND_PATH) $(CRTI_PATH) $(CRTN_PATH) $(WORKSPACE_DIR)/out/lib/
%.o: %.c
$(info Compiling $<)
$(CC) -nostdlib -mno-red-zone -std=c17 -c $< -o $@
%.o: %.asm
$(info Compiling $<)
$(NASM) $< -f $(ASM_ARCH) -o $@
$(CC) -nostdlib -mno-red-zone -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,100 @@
/*
This file is part of Fennix Userspace.
Fennix Userspace 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 Userspace 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 Userspace. If not, see <https://www.gnu.org/licenses/>.
*/
typedef void (*fct)(void);
#define asm __asm__ __volatile__
extern void (*__preinit_array_start[])(void) __attribute__((weak));
extern void (*__preinit_array_end[])(void) __attribute__((weak));
extern void (*__init_array_start[])(void) __attribute__((weak));
extern void (*__init_array_end[])(void) __attribute__((weak));
extern void (*__fini_array_start[])(void) __attribute__((weak));
extern void (*__fini_array_end[])(void) __attribute__((weak));
void __crt_init_array(void)
{
for (fct *func = __init_array_start; func != __init_array_end; func++)
(*func)();
}
void __crt_fini_array(void)
{
for (fct *func = __fini_array_start; func != __fini_array_end; func++)
(*func)();
}
__attribute__((naked, used, no_stack_protector, section(".text"))) void _start()
{
asm("movq $0, %rbp\n"
"pushq %rbp\n"
"pushq %rbp\n"
"movq %rsp, %rbp\n"
"pushq %rcx\n"
"pushq %rdx\n"
"pushq %rsi\n"
"pushq %rdi\n"
"call __libc_init\n"
"call __crt_init_array\n"
"popq %rdi\n"
"popq %rsi\n"
"popq %rdx\n"
"popq %rcx\n"
"call main\n"
"pushq %rax\n"
"call __crt_fini_array\n"
"popq %rax\n"
"movl %eax, %edi\n"
"call _exit\n");
}
/* 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
};
typedef struct Elf_Nhdr
{
__UINT32_TYPE__ n_namesz;
__UINT32_TYPE__ n_descsz;
__UINT32_TYPE__ n_type;
char n_name[];
} __attribute__((packed)) Elf_Nhdr;
const struct
{
Elf_Nhdr header;
char name[4];
__UINT32_TYPE__ desc[4];
} __abi_tag __attribute__((aligned(4), section(".note.ABI-tag"))) = {
.header = {
.n_namesz = 4, /* "FNX" + '\0' */
.n_descsz = sizeof(__UINT32_TYPE__) * 4, /* Description Size */
.n_type = NT_FNX_ABI_TAG, /* Type */
},
.name = "FNX",
.desc = {0, 0, 0, 0},
};

View File

@ -1,21 +0,0 @@
// https://wiki.osdev.org/Creating_a_C_Library
#define asm __asm__ __volatile__
__attribute__((naked, used, no_stack_protector, section(".text"))) void _start()
{
asm("movq $0, %rbp\n");
asm("pushq %rbp\n");
asm("pushq %rbp\n");
asm("movq %rsp, %rbp\n");
asm("pushq %rcx\n"
"pushq %rdx\n"
"pushq %rsi\n"
"pushq %rdi\n");
asm("call __libc_init\n");
asm("popq %rdi\n"
"popq %rsi\n"
"popq %rdx\n"
"popq %rcx\n");
asm("call main\n");
asm("movl %eax, %edi\n");
asm("call _exit\n");
}

View File

@ -1,21 +1,100 @@
// https://wiki.osdev.org/Creating_a_C_Library
/*
This file is part of Fennix Userspace.
Fennix Userspace 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 Userspace 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 Userspace. If not, see <https://www.gnu.org/licenses/>.
*/
typedef void (*fct)(void);
#define asm __asm__ __volatile__
extern void (*__preinit_array_start[])(void) __attribute__((weak));
extern void (*__preinit_array_end[])(void) __attribute__((weak));
extern void (*__init_array_start[])(void) __attribute__((weak));
extern void (*__init_array_end[])(void) __attribute__((weak));
extern void (*__fini_array_start[])(void) __attribute__((weak));
extern void (*__fini_array_end[])(void) __attribute__((weak));
void __crt_init_array(void)
{
for (fct *func = __init_array_start; func != __init_array_end; func++)
(*func)();
}
void __crt_fini_array(void)
{
for (fct *func = __fini_array_start; func != __fini_array_end; func++)
(*func)();
}
__attribute__((naked, used, no_stack_protector, section(".text"))) void _start()
{
asm("movq $0, %rbp\n");
asm("pushq %rbp\n");
asm("pushq %rbp\n");
asm("movq %rsp, %rbp\n");
asm("pushq %rcx\n"
asm("movq $0, %rbp\n"
"pushq %rbp\n"
"pushq %rbp\n"
"movq %rsp, %rbp\n"
"pushq %rcx\n"
"pushq %rdx\n"
"pushq %rsi\n"
"pushq %rdi\n");
asm("call __libc_init\n");
asm("popq %rdi\n"
"pushq %rdi\n"
"call __libc_init\n"
"call __crt_init_array\n"
"popq %rdi\n"
"popq %rsi\n"
"popq %rdx\n"
"popq %rcx\n");
asm("call main\n");
asm("movl %eax, %edi\n");
asm("call _exit\n");
"popq %rcx\n"
"call main\n"
"pushq %rax\n"
"call __crt_fini_array\n"
"popq %rax\n"
"movl %eax, %edi\n"
"call _exit\n");
}
/* 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
};
typedef struct Elf_Nhdr
{
__UINT32_TYPE__ n_namesz;
__UINT32_TYPE__ n_descsz;
__UINT32_TYPE__ n_type;
char n_name[];
} __attribute__((packed)) Elf_Nhdr;
const struct
{
Elf_Nhdr header;
char name[4];
__UINT32_TYPE__ desc[4];
} __abi_tag __attribute__((aligned(4), section(".note.ABI-tag"))) = {
.header = {
.n_namesz = 4, /* "FNX" + '\0' */
.n_descsz = sizeof(__UINT32_TYPE__) * 4, /* Description Size */
.n_type = NT_FNX_ABI_TAG, /* Type */
},
.name = "FNX",
.desc = {0, 0, 0, 0},
};

View File

@ -1,22 +0,0 @@
// extern void (*__preinit_array_start[])(void) __attribute__((weak));
// extern void (*__preinit_array_end[])(void) __attribute__((weak));
// extern void (*__init_array_start[])(void) __attribute__((weak));
// extern void (*__init_array_end[])(void) __attribute__((weak));
// extern void (*__fini_array_start []) (void) __attribute__((weak));
// extern void (*__fini_array_end []) (void) __attribute__((weak));
typedef void (*fct)(void);
extern fct __init_array_start[0], __init_array_end[0];
extern fct __fini_array_start[0], __fini_array_end[0];
void __libc_init_array(void)
{
for (fct *func = __init_array_start; func != __init_array_end; func++)
(*func)();
}
void __libc_fini_array(void)
{
for (fct *func = __fini_array_start; func != __fini_array_end; func++)
(*func)();
}

View File

@ -1,35 +0,0 @@
#include "lock.hpp"
#include <stdio.h>
void LockClass::DeadLock(SpinLockData Lock)
{
fprintf(stdout, "Potential deadlock in lock '%s' held by '%s'! %ld locks in queue.",
Lock.AttemptingToGet, Lock.CurrentHolder, Lock.Count);
}
int LockClass::Lock(const char *FunctionName)
{
LockData.AttemptingToGet = FunctionName;
Retry:
unsigned int i = 0;
while (__atomic_exchange_n(&IsLocked, true, __ATOMIC_ACQUIRE) && ++i < 0x10000000)
;
if (i >= 0x10000000)
{
DeadLock(LockData);
goto Retry;
}
LockData.Count++;
LockData.CurrentHolder = FunctionName;
__sync_synchronize();
return 0;
}
int LockClass::Unlock()
{
__sync_synchronize();
__atomic_store_n(&IsLocked, false, __ATOMIC_RELEASE);
LockData.Count--;
IsLocked = false;
return 0;
}

View File

@ -1,47 +1,36 @@
# Config file
include ../../../config.mk
default:
$(error Do not run this Makefile directly!)
NAME=c
DYNAMIC_NAME := libc.so
STATIC_NAME := libc.a
ifeq ($(USERSPACE_STATIC_LIBS), 1)
OBJECT_NAME := lib$(NAME).a
else
OBJECT_NAME := lib$(NAME).so
endif
OUTPUT_DIR=$(WORKSPACE_DIR)/out/lib/
SYSROOT = --sysroot=$(WORKSPACE_DIR)/out/
OUTPUT_DIR=../../out/lib/
SYSROOT = --sysroot=../../out/
CC = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)gcc
AS = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)as
AR = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)ar
C_SOURCES = $(shell find ./ -type f -name '*.c')
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp')
S_SOURCES = $(shell find ./ -type f -name '*.S')
OBJ = ${C_SOURCES:.c=.o} ${CPP_SOURCES:.cpp=.o} ${S_SOURCES:.S=.o}
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}
ifeq ($(OSARCH), amd64)
ASM_ARCH := elf64
else ifeq ($(OSARCH), i386)
ASM_ARCH := elf32
endif
CFLAGS := -fvisibility=hidden -fPIC -I../include -I../../out/include
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 -fverbose-asm
endif
build: $(OBJECT_NAME)
build: $(DYNAMIC_NAME) $(STATIC_NAME)
$(OBJECT_NAME): $(OBJ)
.PHONY: $(DYNAMIC_NAME) $(STATIC_NAME)
$(DYNAMIC_NAME): $(OBJ)
$(info Linking $@)
ifeq ($(USERSPACE_STATIC_LIBS), 1)
$(AR) rcs $(OUTPUT_DIR)$@ $(OBJ)
else
$(CC) -nostdlib -shared -fPIC -fPIE -Wl,-soname,$(OBJECT_NAME) $(SYSROOT) $(OBJ) -o $(OUTPUT_DIR)$@
endif
$(CC) -nostdlib -shared -fPIC -fPIE -e _start -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 $<)
@ -56,4 +45,4 @@ endif
$(AS) -c $< -o $@
clean:
rm -f $(OBJ)
rm -f $(OBJ) $(DYNAMIC_NAME) $(STATIC_NAME)

View File

@ -1,23 +0,0 @@
#include <fennix/syscall.h>
#include <sys/types.h> // For PUBLIC
extern void __libc_init_array(void);
extern void __libc_fini_array(void);
extern void __libc_init_std(void);
extern void __libc_fini_std(void);
PUBLIC void __libc_init(void)
{
__libc_init_array();
__libc_init_std();
}
PUBLIC void _exit(int Code)
{
__libc_fini_std();
__libc_fini_array();
syscall1(sc_exit, (long)Code);
while (1)
;
}

View File

@ -1,23 +0,0 @@
#include <dlfcn.h>
static char *error = "Not implemented";
__attribute__((weak)) void *dlopen(const char *filename, int flags)
{
return NULL;
}
__attribute__((weak)) void *dlsym(void *handle, const char *symbol)
{
return NULL;
}
__attribute__((weak)) int dlclose(void *handle)
{
return -1;
}
__attribute__((weak)) char *dlerror(void)
{
return error;
}

34
Userspace/libc/src/init.c Normal file
View File

@ -0,0 +1,34 @@
/*
This file is part of Fennix Userspace.
Fennix Userspace 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 Userspace 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 Userspace. If not, see <https://www.gnu.org/licenses/>.
*/
#include <fennix/syscalls.h>
int __init_pthread(void);
void __init_stdio(void);
__attribute__((visibility("default"))) void __libc_init(void)
{
__init_pthread();
__init_stdio();
}
__attribute__((visibility("default"))) void _exit(int Code)
{
call_exit(Code);
while (1)
;
}

View File

@ -1,50 +0,0 @@
#ifndef __FENNIX_KERNEL_LOCK_H__
#define __FENNIX_KERNEL_LOCK_H__
#include <types.h>
#ifdef __cplusplus
/** @brief Please use this macro to create a new lock. */
class LockClass
{
struct SpinLockData
{
uint64_t LockData = 0x0;
const char *CurrentHolder = "(nul)";
const char *AttemptingToGet = "(nul)";
uint64_t Count = 0;
};
void DeadLock(SpinLockData Lock);
private:
SpinLockData LockData;
bool IsLocked = false;
public:
SpinLockData *GetLockData() { return &LockData; }
int Lock(const char *FunctionName);
int Unlock();
};
/** @brief Please use this macro to create a new smart lock. */
class SmartLockClass
{
private:
LockClass *LockPointer = nullptr;
public:
SmartLockClass(LockClass &Lock, const char *FunctionName)
{
this->LockPointer = &Lock;
this->LockPointer->Lock(FunctionName);
}
~SmartLockClass() { this->LockPointer->Unlock(); }
};
/** @brief Create a new lock (can be used with SmartCriticalSection). */
#define NewLock(Name) LockClass Name
/** @brief Simple lock that is automatically released when the scope ends. */
#define SmartLock(LockClassName) SmartLockClass CONCAT(lock##_, __COUNTER__)(LockClassName, __FUNCTION__)
#endif // __cplusplus
#endif // !__FENNIX_KERNEL_LOCK_H__

View File

@ -1,5 +1,152 @@
/* TODO: Show a message or something */
int _start()
/*
This file is part of Fennix Userspace.
Fennix Userspace 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 Userspace 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 Userspace. If not, see <https://www.gnu.org/licenses/>.
*/
typedef void (*fct)(void);
#define asm __asm__ __volatile__
__attribute__((__visibility__("hidden"))) extern void (*__preinit_array_start[])(void) __attribute__((weak));
__attribute__((__visibility__("hidden"))) extern void (*__preinit_array_end[])(void) __attribute__((weak));
__attribute__((__visibility__("hidden"))) extern void (*__init_array_start[])(void) __attribute__((weak));
__attribute__((__visibility__("hidden"))) extern void (*__init_array_end[])(void) __attribute__((weak));
__attribute__((__visibility__("hidden"))) extern void (*__fini_array_start[])(void) __attribute__((weak));
__attribute__((__visibility__("hidden"))) extern void (*__fini_array_end[])(void) __attribute__((weak));
const char __interp[] __attribute__((section(".interp"))) = "/lib/ld.so";
#ifndef LIBC_GIT_COMMIT
#define LIBC_GIT_COMMIT "0000000000000000000000000000000000000000"
#endif
#define HEX_DIGIT(c) (((c) >= '0' && (c) <= '9') ? ((c) - '0') : ((c) - 'a' + 10))
#define CONVERT_TO_BYTE(h, l) ((HEX_DIGIT(h) << 4) | HEX_DIGIT(l))
#define HASH_BYTES(hex) \
{CONVERT_TO_BYTE(hex[0], hex[1]), \
CONVERT_TO_BYTE(hex[2], hex[3]), \
CONVERT_TO_BYTE(hex[4], hex[5]), \
CONVERT_TO_BYTE(hex[6], hex[7]), \
CONVERT_TO_BYTE(hex[8], hex[9]), \
CONVERT_TO_BYTE(hex[10], hex[11]), \
CONVERT_TO_BYTE(hex[12], hex[13]), \
CONVERT_TO_BYTE(hex[14], hex[15]), \
CONVERT_TO_BYTE(hex[16], hex[17]), \
CONVERT_TO_BYTE(hex[18], hex[19]), \
CONVERT_TO_BYTE(hex[20], hex[21]), \
CONVERT_TO_BYTE(hex[22], hex[23]), \
CONVERT_TO_BYTE(hex[24], hex[25]), \
CONVERT_TO_BYTE(hex[26], hex[27]), \
CONVERT_TO_BYTE(hex[28], hex[29]), \
CONVERT_TO_BYTE(hex[30], hex[31]), \
CONVERT_TO_BYTE(hex[32], hex[33]), \
CONVERT_TO_BYTE(hex[34], hex[35]), \
CONVERT_TO_BYTE(hex[36], hex[37]), \
CONVERT_TO_BYTE(hex[38], hex[39])}
/* 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
};
typedef struct Elf_Nhdr
{
__UINT32_TYPE__ n_namesz;
__UINT32_TYPE__ n_descsz;
__UINT32_TYPE__ n_type;
char n_name[];
} __attribute__((packed)) Elf_Nhdr;
const struct
{
Elf_Nhdr header;
char name[4];
__UINT32_TYPE__ desc[4];
} __abi_tag __attribute__((aligned(4), section(".note.ABI-tag"))) = {
.header = {
.n_namesz = 4, /* "FNX" + '\0' */
.n_descsz = sizeof(__UINT32_TYPE__) * 4, /* Description Size */
.n_type = NT_FNX_ABI_TAG, /* Type */
},
.name = "FNX",
.desc = {0, 0, 0, 0},
};
const struct
{
Elf_Nhdr header;
char name[4];
__UINT8_TYPE__ desc[20];
} __build_id __attribute__((aligned(4), section(".note.build-id"))) = {
.header = {
.n_namesz = 4, /* "FNX" + '\0' */
.n_descsz = sizeof(__UINT8_TYPE__) * 20, /* Description Size */
.n_type = NT_FNX_BUILD_ID, /* Type */
},
.name = "FNX",
.desc = HASH_BYTES(LIBC_GIT_COMMIT),
};
void __crt_init_array(void)
{
for (fct *func = __init_array_start; func != __init_array_end; func++)
(*func)();
}
void __crt_fini_array(void)
{
for (fct *func = __fini_array_start; func != __fini_array_end; func++)
(*func)();
}
__attribute__((naked, used, no_stack_protector, section(".text"))) void _start()
{
asm("movq $0, %rbp\n"
"pushq %rbp\n"
"pushq %rbp\n"
"movq %rsp, %rbp\n"
"pushq %rcx\n"
"pushq %rdx\n"
"pushq %rsi\n"
"pushq %rdi\n"
"call __libc_init\n"
"call __crt_init_array\n"
"popq %rdi\n"
"popq %rsi\n"
"popq %rdx\n"
"popq %rcx\n"
"call main\n"
"pushq %rax\n"
"call __crt_fini_array\n"
"popq %rax\n"
"movl %eax, %edi\n"
"call _exit\n");
}
int main(int argc, char *argv[], char *envp[])
{
(void)argc;
(void)argv;
(void)envp;
/* FIXME: show printf license notice and some help and commands? */
return -1;
}

View File

@ -0,0 +1,10 @@
This code is released into the public domain. Use this code at your own
risk. Feel free to use it for whatever purpose you want. I take no responsibilty or
whatever if anything goes wrong. Use it at your own risk.
If you have any fixes or patches, please email me.
Durand Miller <clutter@djm.co.za>

Some files were not shown because too many files have changed in this diff Show More