mirror of
https://github.com/EnderIce2/Fennix.git
synced 2025-05-25 22:14:34 +00:00
userspace: Rewrite everything
Everything. Signed-off-by: EnderIce2 <enderice2@protonmail.com>
This commit is contained in:
parent
dea36a0228
commit
6dae34debd
@ -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
|
@ -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:
|
@ -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 +++
|
@ -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)
|
@ -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;
|
||||
}
|
@ -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)
|
@ -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;
|
||||
}
|
@ -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)
|
9
Userspace/apps/sys/Makefile
Normal file
9
Userspace/apps/sys/Makefile
Normal 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
1
Userspace/apps/sys/init/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
init
|
33
Userspace/apps/sys/init/Makefile
Normal file
33
Userspace/apps/sys/init/Makefile
Normal 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)
|
27
Userspace/apps/sys/init/init.c
Normal file
27
Userspace/apps/sys/init/init.c
Normal 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;
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
build:
|
||||
make -C init build
|
||||
|
||||
clean:
|
||||
make -C init clean
|
@ -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)
|
@ -1,6 +0,0 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int, char *[], char *[])
|
||||
{
|
||||
return 0;
|
||||
}
|
9
Userspace/apps/test/Makefile
Normal file
9
Userspace/apps/test/Makefile
Normal file
@ -0,0 +1,9 @@
|
||||
MAKE_TARGETS := build clean
|
||||
DIRECTORIES := $(sort $(dir $(wildcard ./*/)))
|
||||
|
||||
.PHONY: $(MAKE_TARGETS) $(DIRECTORIES)
|
||||
|
||||
$(MAKE_TARGETS): $(DIRECTORIES)
|
||||
|
||||
$(DIRECTORIES):
|
||||
$(MAKE) -C $@ $(MAKECMDGOALS)
|
2
Userspace/apps/test/cross_test/.gitignore
vendored
Normal file
2
Userspace/apps/test/cross_test/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
utest_linux
|
||||
utest_win.exe
|
30
Userspace/apps/test/cross_test/Makefile
Normal file
30
Userspace/apps/test/cross_test/Makefile
Normal 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
1
Userspace/apps/test/utest/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
utest
|
36
Userspace/apps/test/utest/Makefile
Normal file
36
Userspace/apps/test/utest/Makefile
Normal 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)
|
@ -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;
|
@ -1,5 +0,0 @@
|
||||
build:
|
||||
make -C games build
|
||||
|
||||
clean:
|
||||
make -C games clean
|
@ -1,5 +0,0 @@
|
||||
build:
|
||||
# make -C doomgeneric build
|
||||
|
||||
clean:
|
||||
# make -C doomgeneric clean
|
@ -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)
|
@ -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__
|
@ -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};
|
||||
}
|
@ -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__
|
@ -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;
|
||||
}
|
@ -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);
|
||||
}
|
@ -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__
|
@ -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)
|
||||
;
|
||||
}
|
@ -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);
|
||||
|
@ -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
39
Userspace/libc/STATUS.md
Normal 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/)
|
@ -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
|
||||
|
@ -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__
|
@ -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
|
@ -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
|
38
Userspace/libc/include/bits/types/timespec.h
Normal file
38
Userspace/libc/include/bits/types/timespec.h
Normal 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
|
@ -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
|
@ -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
|
78
Userspace/libc/include/dirent.h
Normal file
78
Userspace/libc/include/dirent.h
Normal 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
|
@ -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__
|
@ -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__
|
||||
|
@ -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
|
||||
|
@ -1,6 +0,0 @@
|
||||
#ifndef _FEATURES_H
|
||||
#define _FEATURES_H
|
||||
|
||||
#define __FENNIX_LIBC__ 1
|
||||
|
||||
#endif
|
1572
Userspace/libc/include/fennix/syscalls.h
Normal file
1572
Userspace/libc/include/fennix/syscalls.h
Normal file
File diff suppressed because it is too large
Load Diff
87
Userspace/libc/include/float.h
Normal file
87
Userspace/libc/include/float.h
Normal 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
|
@ -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
|
||||
|
@ -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
|
||||
|
79
Userspace/libc/include/locale.h
Normal file
79
Userspace/libc/include/locale.h
Normal 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
|
@ -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
|
||||
|
137
Userspace/libc/include/pthread.h
Normal file
137
Userspace/libc/include/pthread.h
Normal 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
|
49
Userspace/libc/include/pwd.h
Normal file
49
Userspace/libc/include/pwd.h
Normal 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
|
41
Userspace/libc/include/sched.h
Normal file
41
Userspace/libc/include/sched.h
Normal 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
|
@ -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
|
@ -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
|
||||
|
@ -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
|
@ -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
|
||||
|
36
Userspace/libc/include/stdbool.h
Normal file
36
Userspace/libc/include/stdbool.h
Normal 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
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -1,4 +0,0 @@
|
||||
#ifndef _STRINGS_H
|
||||
#define _STRINGS_H
|
||||
|
||||
#endif // !_STRINGS_H
|
73
Userspace/libc/include/sys/mman.h
Normal file
73
Userspace/libc/include/sys/mman.h
Normal 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
|
@ -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
|
||||
|
@ -1,6 +0,0 @@
|
||||
#ifndef _SYS_TIME_H
|
||||
#define _SYS_TIME_H
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#endif
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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__
|
@ -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
|
||||
|
40
Userspace/libc/interpreter/Makefile
Normal file
40
Userspace/libc/interpreter/Makefile
Normal 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)
|
117
Userspace/libc/interpreter/alloc.c
Normal file
117
Userspace/libc/interpreter/alloc.c
Normal 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;
|
||||
}
|
||||
}
|
1013
Userspace/libc/interpreter/elf.h
Normal file
1013
Userspace/libc/interpreter/elf.h
Normal file
File diff suppressed because it is too large
Load Diff
131
Userspace/libc/interpreter/helper.c
Normal file
131
Userspace/libc/interpreter/helper.c
Normal 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;
|
||||
}
|
975
Userspace/libc/interpreter/load.c
Normal file
975
Userspace/libc/interpreter/load.c
Normal 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);
|
||||
}
|
51
Userspace/libc/interpreter/main.c
Normal file
51
Userspace/libc/interpreter/main.c
Normal 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;
|
||||
}
|
50
Userspace/libc/interpreter/misc.h
Normal file
50
Userspace/libc/interpreter/misc.h
Normal 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__
|
1460
Userspace/libc/interpreter/nanoprintf.h
Normal file
1460
Userspace/libc/interpreter/nanoprintf.h
Normal file
File diff suppressed because it is too large
Load Diff
82
Userspace/libc/interpreter/print.c
Normal file
82
Userspace/libc/interpreter/print.c
Normal 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;
|
||||
}
|
139
Userspace/libc/interpreter/start.c
Normal file
139
Userspace/libc/interpreter/start.c
Normal 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); }
|
@ -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)
|
||||
|
100
Userspace/libc/runtime/Scrt1.c
Normal file
100
Userspace/libc/runtime/Scrt1.c
Normal 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},
|
||||
};
|
@ -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");
|
||||
}
|
@ -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},
|
||||
};
|
||||
|
@ -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)();
|
||||
}
|
@ -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;
|
||||
}
|
@ -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)
|
||||
|
@ -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)
|
||||
;
|
||||
}
|
@ -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
34
Userspace/libc/src/init.c
Normal 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)
|
||||
;
|
||||
}
|
@ -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__
|
@ -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;
|
||||
}
|
||||
|
10
Userspace/libc/src/mem/LICENSE
Normal file
10
Userspace/libc/src/mem/LICENSE
Normal 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
Loading…
x
Reference in New Issue
Block a user