userspace: Rewrite everything

Everything.

Signed-off-by: EnderIce2 <enderice2@protonmail.com>
This commit is contained in:
2025-01-04 06:27:54 +02:00
parent dea36a0228
commit 6dae34debd
135 changed files with 11707 additions and 5286 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,36 +0,0 @@
void __attribute__((naked, used, no_stack_protector)) _start()
{
__asm__("movq $0, %rbp\n"
"pushq %rbp\n"
"pushq %rbp\n"
"movq %rsp, %rbp\n"
"pushq %rcx\n"
"pushq %rdx\n"
"pushq %rsi\n"
"pushq %rdi\n"
"call ld_main\n"
"movl %eax, %edi\n" // Move return value to edi
"cmp $0, %edi\n" // Check if return value is 0
"jne _exit\n" // If not, jump to _exit
"popq %rdi\n"
"popq %rsi\n"
"popq %rdx\n"
"popq %rcx\n"
"call ld_load\n"
"movl %eax, %edi\n" // Move return value to edi
"call _exit"); // Call _exit
}
void _exit(int Code)
{
__asm__ __volatile__("syscall"
:
: "a"(0), "D"(Code)
: "rcx", "r11", "memory");
while (1)
;
}

View File

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

View File

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

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

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

View File

@ -1,4 +1,43 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _ASSERT_H
#define _ASSERT_H
#endif
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
void __assert_fail(const char *file, int line, const char *func) __attribute__((noreturn));
#ifdef NDEBUG
#define assert(e) ((void)0)
#else // NDEBUG
#define assert(e) \
do \
{ \
if (__builtin_expect(!!(!(e)), 0)) \
__assert_fail(__FILE__, __LINE__, __func__); \
} while (0)
#endif // NDEBUG
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // !_ASSERT_H

View File

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

View File

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

View File

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

View File

@ -0,0 +1,38 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _TIMESPEC_DEFINED
#define _TIMESPEC_DEFINED
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
#include <sys/types.h>
typedef struct timespec
{
time_t tv_sec; /* Whole seconds. */
long tv_nsec; /* Nanoseconds [0, 999999999]. */
} timespec;
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // !_TIMESPEC_DEFINED

View File

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

View File

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

View File

@ -0,0 +1,78 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _DIRENT_H
#define _DIRENT_H
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
#include <sys/types.h>
typedef struct dirent
{
ino_t d_ino; /* File serial number. */
char d_name[]; /* Filename string of entry. */
} dirent;
typedef struct posix_dent
{
ino_t d_ino; /* File serial number. */
reclen_t d_reclen; /* Length of this entry, including trailing padding if necessary. See posix_getdents(). */
unsigned char d_type; /* File type or unknown-file-type indication. */
char d_name[]; /* Filename string of this entry. */
} posix_dent;
typedef struct DIR
{
int __fd;
} DIR;
#define DT_BLK
#define DT_CHR
#define DT_DIR
#define DT_FIFO
#define DT_LNK
#define DT_REG
#define DT_SOCK
#define DT_UNKNOWN
#define DT_MQ
#define DT_SEM
#define DT_SHM
#define DT_TMO
int alphasort(const struct dirent **, const struct dirent **);
int closedir(DIR *);
int dirfd(DIR *);
DIR *fdopendir(int);
DIR *opendir(const char *);
ssize_t posix_getdents(int, void *, size_t, int);
struct dirent *readdir(DIR *);
int readdir_r(DIR *restrict, struct dirent *restrict, struct dirent **restrict);
void rewinddir(DIR *);
int scandir(const char *, struct dirent ***, int (*)(const struct dirent *), int (*)(const struct dirent **, const struct dirent **));
void seekdir(DIR *, long);
long telldir(DIR *);
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // !_DIRENT_H

View File

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

View File

@ -1,137 +1,605 @@
#ifndef _ERRNO_H
#define _ERRNO_H
/*
This file is part of Fennix Kernel.
#define EPERM 1 /* Operation not permitted */
#define ENOENT 2 /* No such file or directory */
#define ESRCH 3 /* No such process */
#define EINTR 4 /* Interrupted system call */
#define EIO 5 /* I/O error */
#define ENXIO 6 /* No such device or address */
#define E2BIG 7 /* Argument list too long */
#define ENOEXEC 8 /* Exec format error */
#define EBADF 9 /* Bad file number */
#define ECHILD 10 /* No child processes */
#define EAGAIN 11 /* Try again */
#define ENOMEM 12 /* Out of memory */
#define EACCES 13 /* Permission denied */
#define EFAULT 14 /* Bad address */
#define ENOTBLK 15 /* Block device required */
#define EBUSY 16 /* Device or resource busy */
#define EEXIST 17 /* File exists */
#define EXDEV 18 /* Cross-device link */
#define ENODEV 19 /* No such device */
#define ENOTDIR 20 /* Not a directory */
#define EISDIR 21 /* Is a directory */
#define EINVAL 22 /* Invalid argument */
#define ENFILE 23 /* File table overflow */
#define EMFILE 24 /* Too many open files */
#define ENOTTY 25 /* Not a typewriter */
#define ETXTBSY 26 /* Text file busy */
#define EFBIG 27 /* File too large */
#define ENOSPC 28 /* No space left on device */
#define ESPIPE 29 /* Illegal seek */
#define EROFS 30 /* Read-only file system */
#define EMLINK 31 /* Too many links */
#define EPIPE 32 /* Broken pipe */
#define EDOM 33 /* Math argument out of domain of func */
#define ERANGE 34 /* Math result not representable */
#define EDEADLK 35 /* Resource deadlock would occur */
#define ENAMETOOLONG 36 /* File name too long */
#define ENOLCK 37 /* No record locks available */
#define ENOSYS 38 /* Function not implemented */
#define ENOTEMPTY 39 /* Directory not empty */
#define ELOOP 40 /* Too many symbolic links encountered */
#define ENOMSG 42 /* No message of desired type */
#define EIDRM 43 /* Identifier removed */
#define ECHRNG 44 /* Channel number out of range */
#define EL2NSYNC 45 /* Level 2 not synchronized */
#define EL3HLT 46 /* Level 3 halted */
#define EL3RST 47 /* Level 3 reset */
#define ELNRNG 48 /* Link number out of range */
#define EUNATCH 49 /* Protocol driver not attached */
#define ENOCSI 50 /* No CSI structure available */
#define EL2HLT 51 /* Level 2 halted */
#define EBADE 52 /* Invalid exchange */
#define EBADR 53 /* Invalid request descriptor */
#define EXFULL 54 /* Exchange full */
#define ENOANO 55 /* No anode */
#define EBADRQC 56 /* Invalid request code */
#define EBADSLT 57 /* Invalid slot */
#define EBFONT 59 /* Bad font file format */
#define ENOSTR 60 /* Device not a stream */
#define ENODATA 61 /* No data available */
#define ETIME 62 /* Timer expired */
#define ENOSR 63 /* Out of streams resources */
#define ENONET 64 /* Machine is not on the network */
#define ENOPKG 65 /* Package not installed */
#define EREMOTE 66 /* Object is remote */
#define ENOLINK 67 /* Link has been severed */
#define EADV 68 /* Advertise error */
#define ESRMNT 69 /* Srmount error */
#define ECOMM 70 /* Communication error on send */
#define EPROTO 71 /* Protocol error */
#define EMULTIHOP 72 /* Multihop attempted */
#define EDOTDOT 73 /* RFS specific error */
#define EBADMSG 74 /* Not a data message */
#define EOVERFLOW 75 /* Value too large for defined data type */
#define ENOTUNIQ 76 /* Name not unique on network */
#define EBADFD 77 /* File descriptor in bad state */
#define EREMCHG 78 /* Remote address changed */
#define ELIBACC 79 /* Can not access a needed shared library */
#define ELIBBAD 80 /* Accessing a corrupted shared library */
#define ELIBSCN 81 /* .lib section in a.out corrupted */
#define ELIBMAX 82 /* Attempting to link in too many shared libraries */
#define ELIBEXEC 83 /* Cannot exec a shared library directly */
#define EILSEQ 84 /* Illegal byte sequence */
#define ERESTART 85 /* Interrupted system call should be restarted */
#define ESTRPIPE 86 /* Streams pipe error */
#define EUSERS 87 /* Too many users */
#define ENOTSOCK 88 /* Socket operation on non-socket */
#define EDESTADDRREQ 89 /* Destination address required */
#define EMSGSIZE 90 /* Message too long */
#define EPROTOTYPE 91 /* Protocol wrong type for socket */
#define ENOPROTOOPT 92 /* Protocol not available */
#define EPROTONOSUPPORT 93 /* Protocol not supported */
#define ESOCKTNOSUPPORT 94 /* Socket type not supported */
#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
#define EPFNOSUPPORT 96 /* Protocol family not supported */
#define EAFNOSUPPORT 97 /* Address family not supported by protocol */
#define EADDRINUSE 98 /* Address already in use */
#define EADDRNOTAVAIL 99 /* Cannot assign requested address */
#define ENETDOWN 100 /* Network is down */
#define ENETUNREACH 101 /* Network is unreachable */
#define ENETRESET 102 /* Network dropped connection because of reset */
#define ECONNABORTED 103 /* Software caused connection abort */
#define ECONNRESET 104 /* Connection reset by peer */
#define ENOBUFS 105 /* No buffer space available */
#define EISCONN 106 /* Transport endpoint is already connected */
#define ENOTCONN 107 /* Transport endpoint is not connected */
#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */
#define ETOOMANYREFS 109 /* Too many references: cannot splice */
#define ETIMEDOUT 110 /* Connection timed out */
#define ECONNREFUSED 111 /* Connection refused */
#define EHOSTDOWN 112 /* Host is down */
#define EHOSTUNREACH 113 /* No route to host */
#define EALREADY 114 /* Operation already in progress */
#define EINPROGRESS 115 /* Operation now in progress */
#define ESTALE 116 /* Stale NFS file handle */
#define EUCLEAN 117 /* Structure needs cleaning */
#define ENOTNAM 118 /* Not a XENIX named type file */
#define ENAVAIL 119 /* No XENIX semaphores available */
#define EISNAM 120 /* Is a named type file */
#define EREMOTEIO 121 /* Remote I/O error */
#define EDQUOT 122 /* Quota exceeded */
#define ENOMEDIUM 123 /* No medium found */
#define EMEDIUMTYPE 124 /* Wrong medium type */
#define ECANCELED 125 /* Operation Canceled */
#define ENOKEY 126 /* Required key not available */
#define EKEYEXPIRED 127 /* Key has expired */
#define EKEYREVOKED 128 /* Key has been revoked */
#define EKEYREJECTED 129 /* Key was rejected by service */
#define EOWNERDEAD 130 /* Owner died */
#define ENOTRECOVERABLE 131 /* State not recoverable */
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_API_ERRNO_H__
#define __FENNIX_API_ERRNO_H__
/**
* The documentation for these error codes are from:
* https://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html
*
* Full list:
* https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/basedefs/errno.h.html
*/
typedef enum
{
/**
* No Error
*/
EOK = 0,
/**
* Argument list too long. The sum of the number of bytes used by the
* new process image's argument list and environment list is greater
* than the system-imposed limit of {ARG_MAX} bytes.
* or:
* Lack of space in an output buffer.
* or:
* Argument is greater than the system-imposed maximum.
*/
E2BIG = 1,
/**
* Permission denied. An attempt was made to access a file in a way
* forbidden by its file access permissions.
*/
EACCES = 2,
/**
* Address in use. The specified address is in use.
*/
EADDRINUSE = 3,
/**
* Address not available. The specified address is not available from
* the local system.
*/
EADDRNOTAVAIL = 4,
/**
* Address family not supported. The implementation does not support
* the specified address family, or the specified address is not a
* valid address for the address family of the specified socket.
*/
EAFNOSUPPORT = 5,
/**
* Resource temporarily unavailable. This is a temporary condition
* and later calls to the same routine may complete normally.
*/
EAGAIN = 6,
/**
* Connection already in progress. A connection request is already in
* progress for the specified socket.
*/
EALREADY = 7,
/**
* Bad file descriptor. A file descriptor argument is out of range,
* refers to no open file, or a read (write) request is made to a
* file that is only open for writing (reading).
*/
EBADF = 8,
/**
* Bad message. During a read(), getmsg(), getpmsg(), or ioctl()
* I_RECVFD request to a STREAMS device, a message arrived at the
* head of the STREAM that is inappropriate for the function
* receiving the message.
* read()
* Message waiting to be read on a STREAM is not a data message.
* getmsg() or getpmsg()
* A file descriptor was received instead of a control message.
* ioctl()
* Control or data information was received instead of a file
* descriptor when I_RECVFD was specified.
*/
EBADMSG = 9,
/**
* Resource busy. An attempt was made to make use of a system
* resource that is not currently available, as it is being
* used by another process in a manner that would have
* conflicted with the request being made by this process.
*/
EBUSY = 10,
/**
* Operation canceled. The associated asynchronous operation was
* canceled before completion.
*/
ECANCELED = 11,
/**
* No child process. A wait(), waitid(), or waitpid() function was
* executed by a process that had no existing or unwaited-for
* child process.
*/
ECHILD = 12,
/**
* Connection aborted. The connection has been aborted.
*/
ECONNABORTED = 13,
/**
* Connection refused. An attempt to connect to a socket was refused
* because there was no process listening or because the queue of
* connection requests was full and the underlying protocol does not
* support retransmissions.
*/
ECONNREFUSED = 14,
/**
* Connection reset. The connection was forcibly closed by the peer.
*/
ECONNRESET = 15,
/**
* Resource deadlock would occur. An attempt was made to lock a system
* resource that would have resulted in a deadlock situation.
*/
EDEADLK = 16,
/**
* Destination address required. No bind address was established.
*/
EDESTADDRREQ = 17,
/**
* Domain error. An input argument is outside the defined domain of the
* mathematical function (defined in the ISO C standard).
*/
EDOM = 18,
/**
* Reserved.
*/
EDQUOT = 19,
/**
* File exists. An existing file was mentioned in an inappropriate
* context; for example, as a new link name in the link() function.
*/
EEXIST = 20,
/**
* Bad address. The system detected an invalid address in attempting
* to use an argument of a call. The reliable detection of this error
* cannot be guaranteed, and when not detected may result in the
* generation of a signal, indicating an address violation, which is
* sent to the process.
*/
EFAULT = 21,
/**
* File too large. The size of a file would exceed the maximum file
* size of an implementation or offset maximum established in the
* corresponding file description.
*/
EFBIG = 22,
/**
* Host is unreachable. The destination host cannot be reached
* (probably because the host is down or a remote router cannot
* reach it).
*/
EHOSTUNREACH = 23,
/**
* Identifier removed. Returned during XSI interprocess communication
* if an identifier has been removed from the system.
*/
EIDRM = 24,
/**
* Illegal byte sequence. A wide-character code has been detected that
* does not correspond to a valid character, or a byte sequence does
* not form a valid wide-character code (defined in the ISO C standard).
*/
EILSEQ = 25,
/**
* Operation in progress. This code is used to indicate that an
* asynchronous operation has not yet completed.
* or:
* O_NONBLOCK is set for the socket file descriptor and the connection
* cannot be immediately established.
*/
EINPROGRESS = 26,
/**
* Interrupted function call. An asynchronous signal was caught by the
* process during the execution of an interruptible function. If the
* signal handler performs a normal return, the interrupted function
* call may return this condition (see the Base Definitions volume
* of POSIX.1-2017, <signal.h>).
*/
EINTR = 27,
/**
* Invalid argument. Some invalid argument was supplied; for example,
* specifying an undefined signal in a signal() function or a
* kill() function.
*/
EINVAL = 28,
/**
* Input/output error. Some physical input or output error has occurred.
* This error may be reported on a subsequent operation on the same
* file descriptor. Any other error-causing operation on the same file
* descriptor may cause the [EIO] error indication to be lost.
*/
EIO = 29,
/**
* Socket is connected. The specified socket is already connected.
*/
EISCONN = 30,
/**
* Is a directory. An attempt was made to open a directory with write
* mode specified.
*/
EISDIR = 31,
/**
* Symbolic link loop. A loop exists in symbolic links encountered
* during pathname resolution. This error may also be returned if
* more than {SYMLOOP_MAX} symbolic links are encountered during
* pathname resolution.
*/
ELOOP = 32,
/**
* File descriptor value too large or too many open streams. An
* attempt was made to open a file descriptor with a value greater
* than or equal to {OPEN_MAX}, or an attempt was made to open more
* than the maximum number of streams allowed in the process.
*/
EMFILE = 33,
/**
* Too many links. An attempt was made to have the link count of a
* single file exceed {LINK_MAX}.
*/
EMLINK = 34,
/**
* Message too large. A message sent on a transport provider was
* larger than an internal message buffer or some other network limit.
* or:
* Inappropriate message buffer length.
*/
EMSGSIZE = 35,
/**
* Reserved.
*/
EMULTIHOP = 36,
/**
* Filename too long. The length of a pathname exceeds {PATH_MAX} and
* the implementation considers this to be an error, or a pathname
* component is longer than {NAME_MAX}. This error may also occur
* when pathname substitution, as a result of encountering a
* symbolic link during pathname resolution, results in a pathname
* string the size of which exceeds {PATH_MAX}.
*/
ENAMETOOLONG = 37,
/**
* Network is down. The local network interface used to reach the
* destination is down.
*/
ENETDOWN = 38,
/**
* The connection was aborted by the network.
*/
ENETRESET = 39,
/**
* Network unreachable. No route to the network is present.
*/
ENETUNREACH = 40,
/**
* Too many files open in system. Too many files are currently open
* in the system. The system has reached its predefined limit for
* simultaneously open files and temporarily cannot accept requests
* to open another one.
*/
ENFILE = 41,
/**
* No buffer space available. Insufficient buffer resources were
* available in the system to perform the socket operation.
*/
ENOBUFS = 42,
/**
* No message available. No message is available on the STREAM head
* read queue.
*/
ENODATA = 43,
/**
* No such device. An attempt was made to apply an inappropriate
* function to a device; for example, trying to read a write-only
* device such as a printer.
*/
ENODEV = 44,
/**
* No such file or directory. A component of a specified pathname
* does not exist, or the pathname is an empty string.
*/
ENOENT = 45,
/**
* Executable file format error. A request is made to execute a file
* that, although it has appropriate privileges, is not in the
* format required by the implementation for executable files.
*/
ENOEXEC = 46,
/**
* No locks available. A system-imposed limit on the number of
* simultaneous file and record locks has been reached and no more
* are currently available.
*/
ENOLCK = 47,
/**
* Reserved.
*/
ENOLINK = 48,
/**
* Not enough space. The new process image requires more memory than
* is allowed by the hardware or system-imposed memory management
* constraints.
*/
ENOMEM = 49,
/**
* No message of the desired type. The message queue does not contain
* a message of the required type during XSI interprocess communication.
*/
ENOMSG = 50,
/**
* Protocol not available. The protocol option specified to
* setsockopt() is not supported by the implementation.
*/
ENOPROTOOPT = 51,
/**
* No space left on a device. During the write() function on a
* regular file or when extending a directory, there is no free
* space left on the device.
*/
ENOSPC = 52,
/**
* No STREAM resources. Insufficient STREAMS memory resources are
* available to perform a STREAMS-related function. This is a
* temporary condition; it may be recovered from if other
* processes release resources.
*/
ENOSR = 53,
/**
* Not a STREAM. A STREAM function was attempted on a file descriptor
* that was not associated with a STREAMS device.
*/
ENOSTR = 54,
/**
* Functionality not supported. An attempt was made to use optional
* functionality that is not supported in this implementation.
*/
ENOSYS = 55,
/**
* Socket not connected. The socket is not connected.
*/
ENOTCONN = 56,
/**
* Not a directory. A component of the specified pathname exists, but
* it is not a directory, when a directory was expected; or an
* attempt was made to create a non-directory file, and the specified
* pathname contains at least one non- \<slash\> character and ends
* with one or more trailing \<slash\> characters.
*/
ENOTDIR = 57,
/**
* Directory not empty. A directory other than an empty directory
* was supplied when an empty directory was expected.
*/
ENOTEMPTY = 58,
/**
* State not recoverable. The state protected by a robust mutex
* is not recoverable.
*/
ENOTRECOVERABLE = 59,
/**
* Not a socket. The file descriptor does not refer to a socket.
*/
ENOTSOCK = 60,
/**
* Not supported. The implementation does not support the requested
* feature or value.
*/
ENOTSUP = 61,
/**
* Inappropriate I/O control operation. A control function has been
* attempted for a file or special file for which the operation
* is inappropriate.
*/
ENOTTY = 62,
/**
* No such device or address. Input or output on a special file
* refers to a device that does not exist, or makes a request
* beyond the capabilities of the device. It may also occur when,
* for example, a tape drive is not on-line.
*/
ENXIO = 63,
/**
* Operation not supported on socket. The type of socket (address
* family or protocol) does not support the requested operation.
*/
EOPNOTSUPP = 64,
/**
* Value too large to be stored in data type. An operation was
* attempted which would generate a value that is outside the
* range of values that can be represented in the relevant data
* type or that are allowed for a given data item.
*/
EOVERFLOW = 65,
/**
* Previous owner died. The owner of a robust mutex terminated
* while holding the mutex lock.
*/
EOWNERDEAD = 66,
/**
* Operation not permitted. An attempt was made to perform an
* operation limited to processes with appropriate privileges or
* to the owner of a file or other resource.
*/
EPERM = 67,
/**
* Broken pipe. A write was attempted on a socket, pipe, or FIFO
* for which there is no process to read the data.
*/
EPIPE = 68,
/**
* Protocol error. Some protocol error occurred. This error is
* device-specific, but is generally not related to a
* hardware failure.
*/
EPROTO = 69,
/**
* Protocol not supported. The protocol is not supported by the
* address family, or the protocol is not supported by
* the implementation.
*/
EPROTONOSUPPORT = 70,
/**
* Protocol wrong type for socket. The socket type is not
* supported by the protocol.
*/
EPROTOTYPE = 71,
/**
* Result too large or too small. The result of the function
* is too large (overflow) or too small (underflow) to be
* represented in the available space.
*/
ERANGE = 72,
/**
* Read-only file system. An attempt was made to modify a file
* or directory on a file system that is read-only.
*/
EROFS = 73,
/**
* Invalid seek. An attempt was made to access the file offset
* associated with a pipe or FIFO.
*/
ESPIPE = 74,
/**
* No such process. No process can be found corresponding to that
* specified by the given process ID.
*/
ESRCH = 75,
/**
* Reserved.
*/
ESTALE = 76,
/**
* STREAM ioctl() timeout. The timer set for a STREAMS ioctl() call
* has expired. The cause of this error is device-specific and could
* indicate either a hardware or software failure, or a timeout
* value that is too short for the specific operation. The status
* of the ioctl() operation is unspecified.
*/
ETIME = 77,
/**
* Connection timed out. The connection to a remote machine has
* timed out.
* If the connection timed out during execution of the function that
* reported this error (as opposed to timing out prior to the
* function being called), it is unspecified whether the function
* has completed some or all of the documented behavior associated
* with a successful completion of the function.
* or:
* Operation timed out. The time limit associated with the operation
* was exceeded before the operation completed.
*/
ETIMEDOUT = 78,
/**
* Text file busy. An attempt was made to execute a pure-procedure
* program that is currently open for writing, or an attempt has
* been made to open for writing a pure-procedure program that
* is being executed.
*/
ETXTBSY = 79,
/**
* Operation would block. An operation on a socket marked as
* non-blocking has encountered a situation such as no data available
* that otherwise would have caused the function to suspend execution.
*/
EWOULDBLOCK = 80,
/**
* Improper link. A link to a file on another file system was attempted.
*/
EXDEV = 81,
__ERRNO_MAX
} KernelErrors;
#ifdef __cplusplus
extern "C"
{
#endif
int *__errno_location(void) __attribute__((const));
char *strerror(int errnum);
#ifdef __cplusplus
}
#endif
extern int *__errno_location(void) __attribute__((const)) __attribute__ ((__nothrow__));
#define errno (*__errno_location())
#endif
#endif // !__FENNIX_API_ERRNO_H__

View File

@ -1,4 +1,108 @@
#ifndef _FNCTL_H
#define _FNCTL_H
/*
This file is part of Fennix C Library.
#endif // !_FNCTL_H
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _FCNTL_H
#define _FCNTL_H
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
typedef struct f_owner_ex
{
int type; /* Discriminator for pid. */
pid_t pid; /* Process ID or process group ID. */
} f_owner_ex;
typedef struct flock
{
short l_type; /* Type of lock; F_RDLCK, F_WRLCK, F_UNLCK. */
short l_whence; /* Flag for starting offset. */
off_t l_start; /* Relative offset in bytes. */
off_t l_len; /* Size; if 0 then until EOF. */
pid_t l_pid; /* For a process-owned file lock, ignored on input or the process ID of the owning process on output; for an OFD-owned file lock, zero on input or (pid_t)-1 on output. */
} flock;
#define F_DUPFD
#define F_DUPFD_CLOEXEC
#define F_DUPFD_CLOFORK
#define F_GETFD
#define F_SETFD
#define F_GETFL
#define F_SETFL
#define F_GETLK
#define F_SETLK
#define F_SETLKW
#define F_OFD_GETLK
#define F_OFD_SETLK
#define F_OFD_SETLKW
#define F_GETOWN
#define F_GETOWN_EX
#define F_SETOWN
#define F_SETOWN_EX
#define FD_CLOEXEC
#define FD_CLOFORK
#define F_RDLCK
#define F_UNLCK
#define F_WRLCK
#define F_OWNER_PID
#define F_OWNER_PGRP
#define O_CLOEXEC 02000000
#define O_CLOFORK
#define O_CREAT 0100
#define O_DIRECTORY
#define O_EXCL 0200
#define O_NOCTTY
#define O_NOFOLLOW 0400000
#define O_TRUNC 01000
#define O_TTY_INIT
#define O_APPEND 02000
#define O_DSYNC
#define O_NONBLOCK
#define O_RSYNC
#define O_SYNC
#define O_ACCMODE
#define O_EXEC
#define O_RDONLY 00
#define O_RDWR 02
#define O_SEARCH
#define O_WRONLY 01
#define AT_FDCWD
#define AT_EACCESS
#define AT_SYMLINK_NOFOLLOW
#define AT_SYMLINK_FOLLOW
#define AT_REMOVEDIR
#define POSIX_FADV_DONTNEED
#define POSIX_FADV_NOREUSE
#define POSIX_FADV_NORMAL
#define POSIX_FADV_RANDOM
#define POSIX_FADV_SEQUENTIAL
#define POSIX_FADV_WILLNEED
int creat(const char *, mode_t);
int fcntl(int, int, ...);
int open(const char *, int, ...);
int openat(int, const char *, int, ...);
int posix_fadvise(int, off_t, off_t, int);
int posix_fallocate(int, off_t, off_t);
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // !_FCNTL_H

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,87 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _FLOAT_H
#define _FLOAT_H
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
#define INFINITY (__builtin_inff())
#define NAN (__builtin_nanf(""))
#define FLT_ROUNDS 1
#define FLT_EVAL_METHOD __FLT_EVAL_METHOD__
#define FLT_HAS_SUBNORM __FLT_HAS_DENORM__
#define DBL_HAS_SUBNORM __DBL_HAS_DENORM__
#define LDBL_HAS_SUBNORM __LDBL_HAS_DENORM__
#define FLT_RADIX __FLT_RADIX__
#define FLT_MANT_DIG __FLT_MANT_DIG__
#define DBL_MANT_DIG __DBL_MANT_DIG__
#define LDBL_MANT_DIG __LDBL_MANT_DIG__
#define FLT_DECIMAL_DIG __FLT_DECIMAL_DIG__
#define DBL_DECIMAL_DIG __DBL_DECIMAL_DIG__
#define LDBL_DECIMAL_DIG __LDBL_DECIMAL_DIG__
#define DECIMAL_DIG __DECIMAL_DIG__
#define FLT_DIG __FLT_DIG__
#define DBL_DIG __DBL_DIG__
#define LDBL_DIG __LDBL_DIG__
#define FLT_MIN_EXP __FLT_MIN_EXP__
#define DBL_MIN_EXP __DBL_MIN_EXP__
#define LDBL_MIN_EXP __LDBL_MIN_EXP__
#define FLT_MIN_10_EXP __FLT_MIN_10_EXP__
#define DBL_MIN_10_EXP __DBL_MIN_10_EXP__
#define LDBL_MIN_10_EXP __LDBL_MIN_10_EXP__
#define FLT_MAX_EXP __FLT_MAX_EXP__
#define DBL_MAX_EXP __DBL_MAX_EXP__
#define LDBL_MAX_EXP __LDBL_MAX_EXP__
#define FLT_MAX_10_EXP __FLT_MAX_10_EXP__
#define DBL_MAX_10_EXP __DBL_MAX_10_EXP__
#define LDBL_MAX_10_EXP __LDBL_MAX_10_EXP__
#define FLT_MAX __FLT_MAX__
#define DBL_MAX __DBL_MAX__
#define LDBL_MAX __LDBL_MAX__
#define FLT_EPSILON __FLT_EPSILON__
#define DBL_EPSILON __DBL_EPSILON__
#define LDBL_EPSILON __LDBL_EPSILON__
#define FLT_MIN __FLT_MIN__
#define DBL_MIN __DBL_MIN__
#define LDBL_MIN __LDBL_MIN__
#define FLT_TRUE_MIN __FLT_DENORM_MIN__
#define DBL_TRUE_MIN __DBL_DENORM_MIN__
#define LDBL_TRUE_MIN __LDBL_DENORM_MIN__
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // !_FLOAT_H

View File

@ -1,40 +1,69 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _INTTYPES_H
#define _INTTYPES_H
typedef __INT8_TYPE__ int8_t;
typedef __INT16_TYPE__ int16_t;
typedef __INT32_TYPE__ int32_t;
typedef __INT64_TYPE__ int64_t;
typedef __UINT8_TYPE__ uint8_t;
typedef __UINT16_TYPE__ uint16_t;
typedef __UINT32_TYPE__ uint32_t;
typedef __UINT64_TYPE__ uint64_t;
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
typedef __INT_LEAST8_TYPE__ int_least8_t;
typedef __INT_LEAST16_TYPE__ int_least16_t;
typedef __INT_LEAST32_TYPE__ int_least32_t;
typedef __INT_LEAST64_TYPE__ int_least64_t;
typedef __UINT_LEAST8_TYPE__ uint_least8_t;
typedef __UINT_LEAST16_TYPE__ uint_least16_t;
typedef __UINT_LEAST32_TYPE__ uint_least32_t;
typedef __UINT_LEAST64_TYPE__ uint_least64_t;
typedef __INT8_TYPE__ int8_t;
typedef __INT16_TYPE__ int16_t;
typedef __INT32_TYPE__ int32_t;
typedef __INT64_TYPE__ int64_t;
typedef __INT_FAST8_TYPE__ int_fast8_t;
typedef __INT_FAST16_TYPE__ int_fast16_t;
typedef __INT_FAST32_TYPE__ int_fast32_t;
typedef __INT_FAST64_TYPE__ int_fast64_t;
typedef __UINT_FAST8_TYPE__ uint_fast8_t;
typedef __UINT_FAST16_TYPE__ uint_fast16_t;
typedef __UINT_FAST32_TYPE__ uint_fast32_t;
typedef __UINT_FAST64_TYPE__ uint_fast64_t;
typedef __UINT8_TYPE__ uint8_t;
typedef __UINT16_TYPE__ uint16_t;
typedef __UINT32_TYPE__ uint32_t;
typedef __UINT64_TYPE__ uint64_t;
typedef __INTPTR_TYPE__ intptr_t;
typedef __UINTPTR_TYPE__ uintptr_t;
typedef __INTPTR_TYPE__ intptr_t;
typedef __UINTPTR_TYPE__ uintptr_t;
typedef __INTMAX_TYPE__ intmax_t;
typedef __UINTMAX_TYPE__ uintmax_t;
typedef __INT_LEAST8_TYPE__ int_least8_t;
typedef __INT_LEAST16_TYPE__ int_least16_t;
typedef __INT_LEAST32_TYPE__ int_least32_t;
typedef __INT_LEAST64_TYPE__ int_least64_t;
typedef __PTRDIFF_TYPE__ ptrdiff_t;
typedef __SIZE_TYPE__ size_t;
typedef __UINT_LEAST8_TYPE__ uint_least8_t;
typedef __UINT_LEAST16_TYPE__ uint_least16_t;
typedef __UINT_LEAST32_TYPE__ uint_least32_t;
typedef __UINT_LEAST64_TYPE__ uint_least64_t;
typedef __INT_FAST8_TYPE__ int_fast8_t;
typedef __INT_FAST16_TYPE__ int_fast16_t;
typedef __INT_FAST32_TYPE__ int_fast32_t;
typedef __INT_FAST64_TYPE__ int_fast64_t;
typedef __UINT_FAST8_TYPE__ uint_fast8_t;
typedef __UINT_FAST16_TYPE__ uint_fast16_t;
typedef __UINT_FAST32_TYPE__ uint_fast32_t;
typedef __UINT_FAST64_TYPE__ uint_fast64_t;
typedef __INTPTR_TYPE__ intptr_t;
typedef __UINTPTR_TYPE__ uintptr_t;
typedef __INTMAX_TYPE__ intmax_t;
typedef __UINTMAX_TYPE__ uintmax_t;
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // !_INTTYPES_H

View File

@ -1,119 +1,117 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _LIMITS_H
#define _LIMITS_H
#undef CHAR_BIT
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
#define _POSIX_ARG_MAX 4096
#define _POSIX_CHILD_MAX 25
#define _POSIX_OPEN_MAX 20
#define _POSIX_LINK_MAX 8
#define _POSIX_MAX_CANON 255
#define _POSIX_MAX_INPUT 255
#define _POSIX_NAME_MAX 255
#define _POSIX_PATH_MAX 4096
#define _POSIX_PIPE_BUF 512
#define _POSIX_SYMLOOP_MAX 8
#define _POSIX_HOST_NAME_MAX 255
#define _POSIX_LOGIN_NAME_MAX 9
#define _POSIX_TTY_NAME_MAX 255
#define _POSIX_TZNAME_MAX 6
#define _XOPEN_SHM_MAX 255
#define _XOPEN_IOV_MAX 1024
#define _XOPEN_SSTREAM_MAX 8
#define _XOPEN_NAME_MAX 255
#define _XOPEN_PATH_MAX 4096
#define _XOPEN_SYMLOOP_MAX 8
#define _XOPEN_LOGIN_NAME_MAX 9
#define _POSIX2_BC_BASE_MAX 99
#define _POSIX2_BC_DIM_MAX 2048
#define _POSIX2_BC_SCALE_MAX 99
#define _POSIX2_BC_STRING_MAX 1000
#define _POSIX2_COLL_WEIGHTS_MAX 255
#define _POSIX2_EXPR_NEST_MAX 32
#define _POSIX2_LINE_MAX 2048
#define _POSIX2_RE_DUP_MAX 255
#define CHAR_BIT __CHAR_BIT__
#ifndef MB_LEN_MAX
#define MB_LEN_MAX 1
#endif
#undef SCHAR_MIN
#define SCHAR_MIN (-SCHAR_MAX - 1)
#undef SCHAR_MAX
#define SCHAR_MAX __SCHAR_MAX__
#undef UCHAR_MAX
#if __SCHAR_MAX__ == __INT_MAX__
#define UCHAR_MAX (SCHAR_MAX * 2U + 1U)
#else
#define UCHAR_MAX (SCHAR_MAX * 2 + 1)
#endif
#ifdef __CHAR_UNSIGNED__
#undef CHAR_MIN
#if __SCHAR_MAX__ == __INT_MAX__
#define CHAR_MIN 0U
#else
#define CHAR_MIN 0
#endif
#undef CHAR_MAX
#define CHAR_MAX UCHAR_MAX
#else
#undef CHAR_MIN
#define CHAR_MIN SCHAR_MIN
#undef CHAR_MAX
#define CHAR_MAX SCHAR_MAX
#endif
#undef SHRT_MIN
#define MB_LEN_MAX 1
#define SHRT_MIN (-SHRT_MAX - 1)
#undef SHRT_MAX
#define SHRT_MAX __SHRT_MAX__
#undef USHRT_MAX
#if __SHRT_MAX__ == __INT_MAX__
#define USHRT_MAX (SHRT_MAX * 2U + 1U)
#else
#define USHRT_MAX (SHRT_MAX * 2 + 1)
#endif
#undef INT_MIN
#define INT_MIN (-INT_MAX - 1)
#undef INT_MAX
#define INT_MAX __INT_MAX__
#undef UINT_MAX
#define UINT_MAX (INT_MAX * 2U + 1U)
#undef LONG_MIN
#define LONG_MIN (-LONG_MAX - 1L)
#undef LONG_MAX
#define LONG_MAX __LONG_MAX__
#undef ULONG_MAX
#define ULONG_MAX (LONG_MAX * 2UL + 1UL)
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
#undef LLONG_MIN
#define LLONG_MIN (-LLONG_MAX - 1LL)
#undef LLONG_MAX
#define LLONG_MIN (-__LONG_LONG_MAX__ - 1LL)
#define LLONG_MAX __LONG_LONG_MAX__
#undef ULLONG_MAX
#define ULLONG_MAX (LLONG_MAX * 2ULL + 1ULL)
#endif
#if defined(__GNU_LIBRARY__) ? defined(__USE_GNU) : !defined(__STRICT_ANSI__)
#undef LONG_LONG_MIN
#define LONG_LONG_MIN (-LONG_LONG_MAX - 1LL)
#undef LONG_LONG_MAX
#define LONG_LONG_MAX __LONG_LONG_MAX__
#define ARG_MAX 4096
#define CHILD_MAX 25
#define OPEN_MAX 20
#define LINK_MAX 8
#define MAX_CANON 255
#define MAX_INPUT 255
#define NAME_MAX 255
#define PATH_MAX 4096
#define PIPE_BUF 512
#define SYMLOOP_MAX 8
#define HOST_NAME_MAX 255
#define LOGIN_NAME_MAX 9
#define TTY_NAME_MAX 255
#define TZNAME_MAX 6
#undef ULONG_LONG_MAX
#define ULONG_LONG_MAX (LONG_LONG_MAX * 2ULL + 1ULL)
#endif
#define SSIZE_MAX ((size_t)(-1) / 2)
#if (defined __STDC_WANT_IEC_60559_BFP_EXT__ || (defined(__STDC_VERSION__) && __STDC_VERSION__ > 201710L))
#undef CHAR_WIDTH
#define CHAR_WIDTH __SCHAR_WIDTH__
#undef SCHAR_WIDTH
#define SCHAR_WIDTH __SCHAR_WIDTH__
#undef UCHAR_WIDTH
#define UCHAR_WIDTH __SCHAR_WIDTH__
#undef SHRT_WIDTH
#define SHRT_WIDTH __SHRT_WIDTH__
#undef USHRT_WIDTH
#define USHRT_WIDTH __SHRT_WIDTH__
#undef INT_WIDTH
#define INT_WIDTH __INT_WIDTH__
#undef UINT_WIDTH
#define UINT_WIDTH __INT_WIDTH__
#undef LONG_WIDTH
#define LONG_WIDTH __LONG_WIDTH__
#undef ULONG_WIDTH
#define ULONG_WIDTH __LONG_WIDTH__
#undef LLONG_WIDTH
#define LLONG_WIDTH __LONG_LONG_WIDTH__
#undef ULLONG_WIDTH
#define ULLONG_WIDTH __LONG_LONG_WIDTH__
#endif
#if defined(__STDC_VERSION__) && __STDC_VERSION__ > 201710L
#undef BOOL_MAX
#define BOOL_MAX 1
#undef BOOL_WIDTH
#define BOOL_WIDTH 1
#endif
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // !_LIMITS_H

View File

@ -0,0 +1,79 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _LOCALE_H
#define _LOCALE_H
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
typedef struct lconv
{
char *currency_symbol;
char *decimal_point;
char frac_digits;
char *grouping;
char *int_curr_symbol;
char int_frac_digits;
char int_n_cs_precedes;
char int_n_sep_by_space;
char int_n_sign_posn;
char int_p_cs_precedes;
char int_p_sep_by_space;
char int_p_sign_posn;
char *mon_decimal_point;
char *mon_grouping;
char *mon_thousands_sep;
char *negative_sign;
char n_cs_precedes;
char n_sep_by_space;
char n_sign_posn;
char *positive_sign;
char p_cs_precedes;
char p_sep_by_space;
char p_sign_posn;
char *thousands_sep;
} lconv;
typedef struct locale_t
{
char data[1]; /* FIXME: implement locale_t */
} locale_t;
#define LC_ALL
#define LC_COLLATE
#define LC_CTYPE
#define LC_MESSAGES
#define LC_MONETARY
#define LC_NUMERIC
#define LC_TIME
locale_t duplocale(locale_t);
void freelocale(locale_t);
const char *getlocalename_l(int, locale_t);
struct lconv *localeconv(void);
locale_t newlocale(int, const char *, locale_t);
char *setlocale(int, const char *);
locale_t uselocale(locale_t);
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // !_LOCALE_H

View File

@ -1,4 +1,226 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _MATH_H
#define _MATH_H
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
#define FLT_EVAL_METHOD 0
#if FLT_EVAL_METHOD == 0
typedef float float_t;
typedef double double_t;
#elif FLT_EVAL_METHOD == 1
typedef float float_t;
typedef float double_t;
#elif FLT_EVAL_METHOD == 2
typedef long double float_t;
typedef long double double_t;
#else
#error "Unsupported FLT_EVAL_METHOD"
#endif
double acos(double);
float acosf(float);
double acosh(double);
float acoshf(float);
long double acoshl(long double);
long double acosl(long double);
double asin(double);
float asinf(float);
double asinh(double);
float asinhf(float);
long double asinhl(long double);
long double asinl(long double);
double atan(double);
double atan2(double, double);
float atan2f(float, float);
long double atan2l(long double, long double);
float atanf(float);
double atanh(double);
float atanhf(float);
long double atanhl(long double);
long double atanl(long double);
double cbrt(double);
float cbrtf(float);
long double cbrtl(long double);
double ceil(double);
float ceilf(float);
long double ceill(long double);
double copysign(double, double);
float copysignf(float, float);
long double copysignl(long double, long double);
double cos(double);
float cosf(float);
double cosh(double);
float coshf(float);
long double coshl(long double);
long double cosl(long double);
double erf(double);
double erfc(double);
float erfcf(float);
long double erfcl(long double);
float erff(float);
long double erfl(long double);
double exp(double);
double exp2(double);
float exp2f(float);
long double exp2l(long double);
float expf(float);
long double expl(long double);
double expm1(double);
float expm1f(float);
long double expm1l(long double);
double fabs(double);
float fabsf(float);
long double fabsl(long double);
double fdim(double, double);
float fdimf(float, float);
long double fdiml(long double, long double);
double floor(double);
float floorf(float);
long double floorl(long double);
double fma(double, double, double);
float fmaf(float, float, float);
long double fmal(long double, long double, long double);
double fmax(double, double);
float fmaxf(float, float);
long double fmaxl(long double, long double);
double fmin(double, double);
float fminf(float, float);
long double fminl(long double, long double);
double fmod(double, double);
float fmodf(float, float);
long double fmodl(long double, long double);
double frexp(double, int *);
float frexpf(float value, int *);
long double frexpl(long double value, int *);
double hypot(double, double);
float hypotf(float, float);
long double hypotl(long double, long double);
int ilogb(double);
int ilogbf(float);
int ilogbl(long double);
double j0(double);
double j1(double);
double jn(int, double);
double ldexp(double, int);
float ldexpf(float, int);
long double ldexpl(long double, int);
double lgamma(double);
float lgammaf(float);
long double lgammal(long double);
long long llrint(double);
long long llrintf(float);
long long llrintl(long double);
long long llround(double);
long long llroundf(float);
long long llroundl(long double);
double log(double);
double log10(double);
float log10f(float);
long double log10l(long double);
double log1p(double);
float log1pf(float);
long double log1pl(long double);
double log2(double);
float log2f(float);
long double log2l(long double);
double logb(double);
float logbf(float);
long double logbl(long double);
float logf(float);
long double logl(long double);
long lrint(double);
long lrintf(float);
long lrintl(long double);
long lround(double);
long lroundf(float);
long lroundl(long double);
double modf(double, double *);
float modff(float, float *);
long double modfl(long double, long double *);
double nan(const char *);
float nanf(const char *);
long double nanl(const char *);
double nearbyint(double);
float nearbyintf(float);
long double nearbyintl(long double);
double nextafter(double, double);
float nextafterf(float, float);
long double nextafterl(long double, long double);
double nexttoward(double, long double);
float nexttowardf(float, long double);
long double nexttowardl(long double, long double);
double pow(double, double);
float powf(float, float);
long double powl(long double, long double);
double remainder(double, double);
float remainderf(float, float);
long double remainderl(long double, long double);
double remquo(double, double, int *);
float remquof(float, float, int *);
long double remquol(long double, long double, int *);
double rint(double);
float rintf(float);
long double rintl(long double);
double round(double);
float roundf(float);
long double roundl(long double);
double scalb(double, double);
double scalbln(double, long);
float scalblnf(float, long);
long double scalblnl(long double, long);
double scalbn(double, int);
float scalbnf(float, int);
long double scalbnl(long double, int);
double sin(double);
float sinf(float);
double sinh(double);
float sinhf(float);
long double sinhl(long double);
long double sinl(long double);
double sqrt(double);
float sqrtf(float);
long double sqrtl(long double);
double tan(double);
float tanf(float);
double tanh(double);
float tanhf(float);
long double tanhl(long double);
long double tanl(long double);
double tgamma(double);
float tgammaf(float);
long double tgammal(long double);
double trunc(double);
float truncf(float);
long double truncl(long double);
double y0(double);
double y1(double);
double yn(int, double);
extern int signgam;
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // !_MATH_H

View File

@ -0,0 +1,137 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _PTHREAD_H
#define _PTHREAD_H
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
#include <sys/types.h>
#include <inttypes.h>
#include <sched.h>
#define PTHREAD_CANCEL_ASYNCHRONOUS {0}
#define PTHREAD_CANCEL_ENABLE {0}
#define PTHREAD_CANCEL_DEFERRED {0}
#define PTHREAD_CANCEL_DISABLE {0}
#define PTHREAD_CANCELED {0}
#define PTHREAD_COND_INITIALIZER {0}
#define PTHREAD_CREATE_DETACHED {0}
#define PTHREAD_CREATE_JOINABLE {0}
#define PTHREAD_EXPLICIT_SCHED {0}
#define PTHREAD_INHERIT_SCHED {0}
#define PTHREAD_MUTEX_DEFAULT {0}
#define PTHREAD_MUTEX_ERRORCHECK {0}
#define PTHREAD_MUTEX_NORMAL {0}
#define PTHREAD_MUTEX_INITIALIZER {0}
#define PTHREAD_MUTEX_RECURSIVE {0}
#define PTHREAD_ONCE_INIT {0}
#define PTHREAD_PRIO_INHERIT {0}
#define PTHREAD_PRIO_NONE {0}
#define PTHREAD_PRIO_PROTECT {0}
#define PTHREAD_PROCESS_SHARED {0}
#define PTHREAD_PROCESS_PRIVATE {0}
#define PTHREAD_RWLOCK_INITIALIZER {0}
#define PTHREAD_SCOPE_PROCESS {0}
#define PTHREAD_SCOPE_SYSTEM {0}
int pthread_attr_destroy(pthread_attr_t *);
int pthread_attr_getdetachstate(const pthread_attr_t *, int *);
int pthread_attr_getguardsize(const pthread_attr_t *, size_t *);
int pthread_attr_getinheritsched(const pthread_attr_t *, int *);
int pthread_attr_getschedparam(const pthread_attr_t *, struct sched_param *);
int pthread_attr_getschedpolicy(const pthread_attr_t *, int *);
int pthread_attr_getscope(const pthread_attr_t *, int *);
int pthread_attr_getstackaddr(const pthread_attr_t *, void **);
int pthread_attr_getstacksize(const pthread_attr_t *, size_t *);
int pthread_attr_init(pthread_attr_t *);
int pthread_attr_setdetachstate(pthread_attr_t *, int);
int pthread_attr_setguardsize(pthread_attr_t *, size_t);
int pthread_attr_setinheritsched(pthread_attr_t *, int);
int pthread_attr_setschedparam(pthread_attr_t *, const struct sched_param *);
int pthread_attr_setschedpolicy(pthread_attr_t *, int);
int pthread_attr_setscope(pthread_attr_t *, int);
int pthread_attr_setstackaddr(pthread_attr_t *, void *);
int pthread_attr_setstacksize(pthread_attr_t *, size_t);
int pthread_cancel(pthread_t);
void pthread_cleanup_push(void (*)(void *), void *);
void pthread_cleanup_pop(int);
int pthread_cond_broadcast(pthread_cond_t *);
int pthread_cond_destroy(pthread_cond_t *);
int pthread_cond_init(pthread_cond_t *, const pthread_condattr_t *);
int pthread_cond_signal(pthread_cond_t *);
int pthread_cond_timedwait(pthread_cond_t *, pthread_mutex_t *, const struct timespec *);
int pthread_cond_wait(pthread_cond_t *, pthread_mutex_t *);
int pthread_condattr_destroy(pthread_condattr_t *);
int pthread_condattr_getpshared(const pthread_condattr_t *, int *);
int pthread_condattr_init(pthread_condattr_t *);
int pthread_condattr_setpshared(pthread_condattr_t *, int);
int pthread_create(pthread_t *, const pthread_attr_t *, void *(*)(void *), void *);
int pthread_detach(pthread_t);
int pthread_equal(pthread_t, pthread_t);
void pthread_exit(void *);
int pthread_getconcurrency(void);
int pthread_getschedparam(pthread_t, int *, struct sched_param *);
void *pthread_getspecific(pthread_key_t);
int pthread_join(pthread_t, void **);
int pthread_key_create(pthread_key_t *, void (*)(void *));
int pthread_key_delete(pthread_key_t);
int pthread_mutex_destroy(pthread_mutex_t *);
int pthread_mutex_getprioceiling(const pthread_mutex_t *, int *);
int pthread_mutex_init(pthread_mutex_t *, const pthread_mutexattr_t *);
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_setprioceiling(pthread_mutex_t *, int, int *);
int pthread_mutex_trylock(pthread_mutex_t *);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
int pthread_mutexattr_destroy(pthread_mutexattr_t *);
int pthread_mutexattr_getprioceiling(const pthread_mutexattr_t *, int *);
int pthread_mutexattr_getprotocol(const pthread_mutexattr_t *, int *);
int pthread_mutexattr_getpshared(const pthread_mutexattr_t *, int *);
int pthread_mutexattr_gettype(const pthread_mutexattr_t *, int *);
int pthread_mutexattr_init(pthread_mutexattr_t *);
int pthread_mutexattr_setprioceiling(pthread_mutexattr_t *, int);
int pthread_mutexattr_setprotocol(pthread_mutexattr_t *, int);
int pthread_mutexattr_setpshared(pthread_mutexattr_t *, int);
int pthread_mutexattr_settype(pthread_mutexattr_t *, int);
int pthread_once(pthread_once_t *, void (*)(void));
int pthread_rwlock_destroy(pthread_rwlock_t *);
int pthread_rwlock_init(pthread_rwlock_t *, const pthread_rwlockattr_t *);
int pthread_rwlock_rdlock(pthread_rwlock_t *);
int pthread_rwlock_tryrdlock(pthread_rwlock_t *);
int pthread_rwlock_trywrlock(pthread_rwlock_t *);
int pthread_rwlock_unlock(pthread_rwlock_t *);
int pthread_rwlock_wrlock(pthread_rwlock_t *);
int pthread_rwlockattr_destroy(pthread_rwlockattr_t *);
int pthread_rwlockattr_getpshared(const pthread_rwlockattr_t *, int *);
int pthread_rwlockattr_init(pthread_rwlockattr_t *);
int pthread_rwlockattr_setpshared(pthread_rwlockattr_t *, int);
pthread_t pthread_self(void);
int pthread_setcancelstate(int, int *);
int pthread_setcanceltype(int, int *);
int pthread_setconcurrency(int);
int pthread_setschedparam(pthread_t, int, const struct sched_param *);
int pthread_setspecific(pthread_key_t, const void *);
void pthread_testcancel(void);
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // !_PTHREAD_H

View File

@ -0,0 +1,49 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _PWD_H
#define _PWD_H
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
#include <sys/types.h>
struct passwd
{
char *pw_name; /* User's login name. */
uid_t pw_uid; /* Numerical user ID. */
gid_t pw_gid; /* Numerical group ID. */
char *pw_dir; /* Initial working directory. */
char *pw_shell; /* Program to use as shell. */
};
void endpwent(void);
struct passwd *getpwent(void);
struct passwd *getpwnam(const char *);
int getpwnam_r(const char *, struct passwd *, char *, size_t, struct passwd **);
struct passwd *getpwuid(uid_t);
int getpwuid_r(uid_t, struct passwd *, char *, size_t, struct passwd **);
void setpwent(void);
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // !_PWD_H

View File

@ -0,0 +1,41 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _SCHED_H
#define _SCHED_H
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
#include <time.h>
typedef struct sched_param
{
int sched_priority; /* Process or thread execution scheduling priority. */
int sched_ss_low_priority; /* Low scheduling priority for sporadic server. */
struct timespec sched_ss_repl_period; /* Replenishment period for sporadic server. */
struct timespec sched_ss_init_budget; /* Initial budget for sporadic server. */
int sched_ss_max_repl; /* Maximum pending replenishments for sporadic server. */
} sched_param_t;
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // !_SCHED_H

View File

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

View File

@ -1,102 +1,221 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _SIGNAL_H
#define _SIGNAL_H
#include <bits/types/sigset_t.h>
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
/* https://www-uxsup.csx.cam.ac.uk/courses/moved.Building/signals.pdf */
/* https://man7.org/linux/man-pages/man7/signal.7.html */
#include <sys/types.h>
#include <fennix/syscalls.h>
#include <bits/types/timespec.h>
/** @brief Hangup detected on controlling or death of controlling process */
#define SIGHUP 1
#define SIGNULL __SYS_SIGNULL
#define SIGABRT __SYS_SIGABRT
#define SIGALRM __SYS_SIGALRM
#define SIGBUS __SYS_SIGBUS
#define SIGCHLD __SYS_SIGCHLD
#define SIGCONT __SYS_SIGCONT
#define SIGFPE __SYS_SIGFPE
#define SIGHUP __SYS_SIGHUP
#define SIGILL __SYS_SIGILL
#define SIGINT __SYS_SIGINT
#define SIGKILL __SYS_SIGKILL
#define SIGPIPE __SYS_SIGPIPE
#define SIGQUIT __SYS_SIGQUIT
#define SIGSEGV __SYS_SIGSEGV
#define SIGSTOP __SYS_SIGSTOP
#define SIGTERM __SYS_SIGTERM
#define SIGTSTP __SYS_SIGTSTP
#define SIGTTIN __SYS_SIGTTIN
#define SIGTTOU __SYS_SIGTTOU
#define SIGUSR1 __SYS_SIGUSR1
#define SIGUSR2 __SYS_SIGUSR2
#define SIGPOLL __SYS_SIGPOLL
#define SIGPROF __SYS_SIGPROF
#define SIGSYS __SYS_SIGSYS
#define SIGTRAP __SYS_SIGTRAP
#define SIGURG __SYS_SIGURG
#define SIGVTALRM __SYS_SIGVTALRM
#define SIGXCPU __SYS_SIGXCPU
#define SIGXFSZ __SYS_SIGXFSZ
#define SIGCOMP1 __SYS_SIGCOMP1
#define SIGCOMP2 __SYS_SIGCOMP2
#define SIGCOMP3 __SYS_SIGCOMP3
#define SIGRTMIN __SYS_SIGRTMIN
#define SIGRT_1 __SYS_SIGRT_1
#define SIGRT_2 __SYS_SIGRT_2
#define SIGRT_3 __SYS_SIGRT_3
#define SIGRT_4 __SYS_SIGRT_4
#define SIGRT_5 __SYS_SIGRT_5
#define SIGRT_6 __SYS_SIGRT_6
#define SIGRT_7 __SYS_SIGRT_7
#define SIGRT_8 __SYS_SIGRT_8
#define SIGRT_9 __SYS_SIGRT_9
#define SIGRT_10 __SYS_SIGRT_10
#define SIGRT_11 __SYS_SIGRT_11
#define SIGRT_12 __SYS_SIGRT_12
#define SIGRT_13 __SYS_SIGRT_13
#define SIGRT_14 __SYS_SIGRT_14
#define SIGRT_15 __SYS_SIGRT_15
#define SIGRT_16 __SYS_SIGRT_16
#define SIGRT_17 __SYS_SIGRT_17
#define SIGRT_18 __SYS_SIGRT_18
#define SIGRT_19 __SYS_SIGRT_19
#define SIGRT_20 __SYS_SIGRT_20
#define SIGRT_21 __SYS_SIGRT_21
#define SIGRT_22 __SYS_SIGRT_22
#define SIGRT_23 __SYS_SIGRT_23
#define SIGRT_24 __SYS_SIGRT_24
#define SIGRT_25 __SYS_SIGRT_25
#define SIGRT_26 __SYS_SIGRT_26
#define SIGRT_27 __SYS_SIGRT_27
#define SIGRT_28 __SYS_SIGRT_28
#define SIGRT_29 __SYS_SIGRT_29
#define SIGRT_30 __SYS_SIGRT_30
#define SIGRT_31 __SYS_SIGRT_31
#define SIGRTMAX __SYS_SIGRTMAX
#define SIGNAL_MAX __SYS_SIGNAL_MAX
/** @brief Interrupt from keyboard */
#define SIGINT 2
#define SIG_TERM __SYS_SIG_TERM
// #define SIG_IGN __SYS_SIG_IGN
#define SIG_CORE __SYS_SIG_CORE
#define SIG_STOP __SYS_SIG_STOP
#define SIG_CONT __SYS_SIG_CONT
/** @brief Quit from keyboard */
#define SIGQUIT 3
#define SIG_BLOCK __SYS_SIG_BLOCK
#define SIG_UNBLOCK __SYS_SIG_UNBLOCK
#define SIG_SETMASK __SYS_SIG_SETMASK
/** @brief Illegal Instruction */
#define SIGILL 4
#define SA_NOCLDSTOP __SYS_SA_NOCLDSTOP
#define SA_ONSTACK __SYS_SA_ONSTACK
#define SA_RESETHAND __SYS_SA_RESETHAND
#define SA_RESTART __SYS_SA_RESTART
#define SA_SIGINFO __SYS_SA_SIGINFO
#define SA_NOCLDWAIT __SYS_SA_NOCLDWAIT
#define SA_NODEFER __SYS_SA_NODEFER
/** @brief Trace/breakpoint trap */
#define SIGTRAP 5
#define SS_ONSTACK
#define SS_DISABLE
/** @brief Abort signal from abort(3) */
#define SIGABRT 6
#define MINSIGSTKSZ
#define SIGSTKSZ
/** @brief Bus error (bad memory access) */
#define SIGBUS 7
#define SIG_ERR ((void (*)(int))__SYS_SIG_ERR)
#define SIG_DFL ((void (*)(int))__SYS_SIG_DFL)
#define SIG_IGN ((void (*)(int))__SYS_SIG_IGN)
/** @brief Floating point exception */
#define SIGFPE 8
#define SIGEV_NONE
#define SIGEV_SIGNAL
#define SIGEV_THREAD
/** @brief Kill signal */
#define SIGKILL 9
typedef unsigned long sigset_t;
/** @brief User-defined signal 1 */
#define SIGUSR1 10
union sigval
{
int sival_int; /* Integer signal value. */
void *sival_ptr; /* Pointer signal value. */
};
/** @brief Invalid memory reference */
#define SIGSEGV 11
typedef struct siginfo_t
{
int si_signo; /* Signal number. */
int si_code; /* Signal code. */
/** @brief User-defined signal 2 */
#define SIGUSR2 12
int si_errno; /* If non-zero, an errno value associated with */
/* this signal, as described in <errno.h>. */
/** @brief Broken pipe: write to pipe with no readers */
#define SIGPIPE 13
pid_t si_pid; /* Sending process ID. */
uid_t si_uid; /* Real user ID of sending process. */
void *si_addr; /* Address that caused fault. */
int si_status; /* Exit value or signal. */
union sigval si_value; /* Signal value. */
} siginfo_t;
/** @brief Timer signal from alarm(2) */
#define SIGALRM 14
typedef struct sigevent
{
int sigev_notify; /* Notification type. */
int sigev_signo; /* Signal number. */
union sigval sigev_value; /* Signal value. */
void (*sigev_notify_function)(union sigval); /* Notification function. */
pthread_attr_t *sigev_notify_attributes; /* Notification attributes. */
} sigevent;
/** @brief Termination signal */
#define SIGTERM 15
struct sigaction
{
void (*sa_handler)(int); /* Pointer to a signal-catching function or one of the SIG_IGN or SIG_DFL. */
sigset_t sa_mask; /* Set of signals to be blocked during execution of the signal handling function. */
int sa_flags; /* Special flags. */
void (*sa_sigaction)(int, siginfo_t *, void *); /* Pointer to a signal-catching function. */
};
/** @brief Stack fault on coprocessor (unused) */
#define SIGSTKFLT 16
typedef struct stack_t
{
void *ss_sp; /* Stack base or pointer. */
size_t ss_size; /* Stack size. */
int ss_flags; /* Flags. */
} stack_t;
/** @brief Child stopped or terminated */
#define SIGCHLD 17
typedef struct mcontext_t
{
__UINTPTR_TYPE__ gregs[32]; /* General-purpose registers. */
__UINTPTR_TYPE__ sp; /* Stack pointer. */
__UINTPTR_TYPE__ pc; /* Program counter. */
__UINTPTR_TYPE__ pstate; /* Processor state. */
} mcontext_t;
/** @brief Continue if stopped */
#define SIGCONT 18
typedef struct ucontext_t
{
struct ucontext_t *uc_link; /* Pointer to the context that is resumed when this context returns. */
sigset_t uc_sigmask; /* The set of signals that are blocked when this context is active. */
stack_t uc_stack; /* The stack used by this context. */
mcontext_t uc_mcontext; /* A machine-specific representation of the saved context. */
} ucontext_t;
/** @brief Stop process */
#define SIGSTOP 19
int kill(pid_t pid, int sig);
int killpg(pid_t, int);
void psiginfo(const siginfo_t *, const char *);
void psignal(int, const char *);
int pthread_kill(pthread_t, int);
int pthread_sigmask(int, const sigset_t *restrict, sigset_t *restrict);
int raise(int);
int sig2str(int, char *);
int sigaction(int, const struct sigaction *restrict, struct sigaction *restrict);
int sigaddset(sigset_t *, int);
int sigaltstack(const stack_t *restrict, stack_t *restrict);
int sigdelset(sigset_t *, int);
int sigemptyset(sigset_t *);
int sigfillset(sigset_t *);
int sigismember(const sigset_t *, int);
void (*signal(int, void (*)(int)))(int);
int sigpending(sigset_t *);
int sigprocmask(int, const sigset_t *restrict, sigset_t *restrict);
int sigqueue(pid_t, int, union sigval);
int sigsuspend(const sigset_t *);
int sigtimedwait(const sigset_t *restrict, siginfo_t *restrict, const struct timespec *restrict);
int sigwait(const sigset_t *restrict, int *restrict);
int sigwaitinfo(const sigset_t *restrict, siginfo_t *restrict);
int str2sig(const char *restrict, int *restrict);
/** @brief Stop typed at terminal */
#define SIGTSTP 20
/** @brief Terminal input for background process */
#define SIGTTIN 21
/** @brief Terminal output for background process */
#define SIGTTOU 22
/** @brief Urgent condition on socket */
#define SIGURG 23
/** @brief CPU time limit exceeded */
#define SIGXCPU 24
/** @brief File size limit exceeded */
#define SIGXFSZ 25
/** @brief Virtual timer expired */
#define SIGVTALRM 26
/** @brief Profiling timer expired */
#define SIGPROF 27
/** @brief Window resize signal */
#define SIGWINCH 28
/** @brief I/O now possible */
#define SIGIO 29
/** @brief Power failure */
#define SIGPWR 30
/** @brief Bad system call */
#define SIGSYS 31
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // !_SIGNAL_H

View File

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

View File

@ -1,13 +1,37 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _STDARG_H
#define _STDARG_H
#ifndef __va_list__
typedef __builtin_va_list va_list;
#endif
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
#define va_start(ap, last) __builtin_va_start(ap, last)
#define va_end(ap) __builtin_va_end(ap)
#define va_arg(ap, type) __builtin_va_arg(ap, type)
typedef __builtin_va_list va_list;
#define va_start(ap, param) __builtin_va_start(ap, param)
#define va_copy(dest, src) __builtin_va_copy(dest, src)
#define va_arg(ap, type) __builtin_va_arg(ap, type)
#define va_end(ap) __builtin_va_end(ap)
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // !_STDARG_H

View File

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

View File

@ -1,47 +1,44 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _STDDEF_H
#define _STDDEF_H
#ifdef __cplusplus
#define NULL 0
#else
extern "C"
{
#endif // __cplusplus
#ifndef NULL
#define NULL ((void *)0)
#define bool _Bool
#endif
typedef __INT8_TYPE__ int8_t;
typedef __INT16_TYPE__ int16_t;
typedef __INT32_TYPE__ int32_t;
typedef __INT64_TYPE__ int64_t;
typedef __UINT8_TYPE__ uint8_t;
typedef __UINT16_TYPE__ uint16_t;
typedef __UINT32_TYPE__ uint32_t;
typedef __UINT64_TYPE__ uint64_t;
typedef struct
{
long long __a;
long double __b;
} max_align_t;
typedef __INT_LEAST8_TYPE__ int_least8_t;
typedef __INT_LEAST16_TYPE__ int_least16_t;
typedef __INT_LEAST32_TYPE__ int_least32_t;
typedef __INT_LEAST64_TYPE__ int_least64_t;
typedef __UINT_LEAST8_TYPE__ uint_least8_t;
typedef __UINT_LEAST16_TYPE__ uint_least16_t;
typedef __UINT_LEAST32_TYPE__ uint_least32_t;
typedef __UINT_LEAST64_TYPE__ uint_least64_t;
typedef __PTRDIFF_TYPE__ ptrdiff_t;
typedef __WCHAR_TYPE__ wchar_t;
typedef __SIZE_TYPE__ size_t;
typedef __INT_FAST8_TYPE__ int_fast8_t;
typedef __INT_FAST16_TYPE__ int_fast16_t;
typedef __INT_FAST32_TYPE__ int_fast32_t;
typedef __INT_FAST64_TYPE__ int_fast64_t;
typedef __UINT_FAST8_TYPE__ uint_fast8_t;
typedef __UINT_FAST16_TYPE__ uint_fast16_t;
typedef __UINT_FAST32_TYPE__ uint_fast32_t;
typedef __UINT_FAST64_TYPE__ uint_fast64_t;
typedef __INTPTR_TYPE__ intptr_t;
typedef __UINTPTR_TYPE__ uintptr_t;
typedef __INTMAX_TYPE__ intmax_t;
typedef __UINTMAX_TYPE__ uintmax_t;
typedef __PTRDIFF_TYPE__ ptrdiff_t;
typedef __SIZE_TYPE__ size_t;
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // !_STDDEF_H

View File

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

View File

@ -1,87 +1,156 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _STDIO_H
#define _STDIO_H
#include <stdarg.h>
#include <stddef.h>
#include <sys/stat.h>
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
/**
* @brief EOF - End of file
*
* The value returned by several functions to indicate the end of file.
*/
#define EOF (-1)
struct _IO_marker
{
struct _IO_marker *_next;
struct _IO_FILE *_sbuf;
int _pos;
};
struct _IO_FILE
{
int _flags;
char *_IO_read_ptr;
char *_IO_read_end;
char *_IO_read_base;
char *_IO_write_base;
char *_IO_write_ptr;
char *_IO_write_end;
char *_IO_buf_base;
char *_IO_buf_end;
__off_t _offset;
struct _IO_marker *_markers;
struct _IO_FILE *_chain;
int _fileno;
};
typedef struct _IO_FILE FILE;
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
#include <sys/types.h>
#include <stddef.h>
#include <stdarg.h>
#define BUFSIZ 512
#define FILENAME_MAX 255
#define FOPEN_MAX 8
#define _IOFBF 0
#define _IOLBF 1
#define _IONBF 2
#define L_ctermid 20
#define L_cuserid 20
#define L_tmpnam 255
#define SEEK_CUR 1
#define SEEK_END 2
#define SEEK_SET 0
#define TMP_MAX 10000
#define EOF (-1)
#ifndef NULL
#define NULL ((void *)0)
#endif
#define P_tmpdir "/tmp/"
typedef long fpos_t;
typedef unsigned long size_t;
struct _IO_FILE
{
int fd;
char *buffer;
size_t buffer_size;
size_t buffer_pos;
int flags;
int error;
int eof;
};
#define _i_READ 1
#define _i_WRITE 2
extern struct _IO_FILE *_i_open_files[256];
typedef struct _IO_FILE FILE;
extern char *optarg;
extern int opterr;
extern int optind;
extern int optopt;
extern FILE *stdin;
extern FILE *stdout;
extern FILE *stderr;
#define stdin stdin
#define stdout stdout
#define stderr stderr
FILE *freopen(const char *filename, const char *mode, FILE *stream);
FILE *fopen(const char *filename, const char *mode);
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
off_t fseek(FILE *stream, long offset, int whence);
long ftell(FILE *stream);
int fclose(FILE *fp);
void clearerr(FILE *);
char *ctermid(char *);
int dprintf(int, const char *restrict, ...);
int fclose(FILE *stream);
FILE *fdopen(int, const char *);
int feof(FILE *);
int ferror(FILE *);
int fflush(FILE *stream);
int fprintf(FILE *stream, const char *format, ...);
int printf(const char *format, ...);
void setbuf(FILE *stream, char *buf);
int vfprintf(FILE *stream, const char *format, va_list arg);
int vsscanf(const char *s, const char *format, va_list arg);
int sscanf(const char *s, const char *format, ...);
int fgetc(FILE *);
int fgetpos(FILE *restrict, fpos_t *restrict);
char *fgets(char *restrict, int, FILE *restrict);
int fileno(FILE *);
void flockfile(FILE *);
FILE *fmemopen(void *restrict, size_t, const char *restrict);
FILE *fopen(const char *restrict pathname, const char *restrict mode);
int fprintf(FILE *restrict, const char *restrict, ...);
int fputc(int c, FILE *stream);
int fputs(const char *restrict s, FILE *restrict stream);
size_t fread(void *restrict ptr, size_t size, size_t nitems, FILE *restrict stream);
FILE *freopen(const char *restrict, const char *restrict, FILE *restrict);
int fscanf(FILE *restrict, const char *restrict, ...);
int fseek(FILE *stream, long offset, int whence);
int fseeko(FILE *, off_t, int);
int fsetpos(FILE *, const fpos_t *);
long ftell(FILE *);
off_t ftello(FILE *);
int ftrylockfile(FILE *);
void funlockfile(FILE *);
size_t fwrite(const void *restrict ptr, size_t size, size_t nitems, FILE *restrict stream);
int getc(FILE *);
int getchar(void);
int getc_unlocked(FILE *);
int getchar_unlocked(void);
ssize_t getdelim(char **restrict, size_t *restrict, int, FILE *restrict);
ssize_t getline(char **restrict, size_t *restrict, FILE *restrict);
FILE *open_memstream(char **, size_t *);
int pclose(FILE *);
void perror(const char *);
FILE *popen(const char *, const char *);
int printf(const char *restrict format, ...);
int putc(int c, FILE *stream);
int fputs(const char *s, FILE *stream);
int puts(const char *s);
int putchar(int c);
int fgetc(FILE *stream);
int putc_unlocked(int c, FILE *stream);
int putchar_unlocked(int c);
int puts(const char *s);
int remove(const char *);
int rename(const char *, const char *);
int renameat(int, const char *, int, const char *);
void rewind(FILE *);
int scanf(const char *restrict, ...);
void setbuf(FILE *restrict, char *restrict);
int setvbuf(FILE *restrict, char *restrict, int, size_t);
int snprintf(char *restrict, size_t, const char *restrict, ...);
int sprintf(char *restrict, const char *restrict, ...);
int sscanf(const char *restrict, const char *restrict, ...);
FILE *tmpfile(void);
char *tmpnam(char *);
int ungetc(int, FILE *);
int vdprintf(int, const char *restrict, va_list);
int vfprintf(FILE *restrict, const char *restrict, va_list);
int vfscanf(FILE *restrict, const char *restrict, va_list);
int vprintf(const char *restrict, va_list);
int vscanf(const char *restrict, va_list);
int vsnprintf(char *restrict, size_t, const char *restrict, va_list);
int vsprintf(char *restrict, const char *restrict, va_list);
int vsscanf(const char *restrict, const char *restrict, va_list);
#ifdef __cplusplus
}
#endif
#endif // __cplusplus
#endif
#endif // !_STDIO_H

View File

@ -1,34 +1,115 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _STDLIB_H
#define _STDLIB_H
#include <stddef.h>
#ifdef __cplusplus
extern "C"
{
#endif
#endif // __cplusplus
#include <stddef.h>
#include <limits.h>
#include <math.h>
#include <sys/wait.h>
#define EXIT_FAILURE 1
#define EXIT_SUCCESS 0
#define NULL ((void *)0)
#define RAND_MAX 32767
#define MB_CUR_MAX 4
typedef struct
{
int quot;
int rem;
} div_t;
typedef struct
{
long quot;
long rem;
} ldiv_t;
typedef unsigned long size_t;
// typedef __WCHAR_TYPE__ wchar_t;
long a64l(const char *);
void abort(void);
int atexit(void (*function)(void));
int abs(int);
int atexit(void (*func)(void));
double atof(const char *);
int atoi(const char *);
long int atol(const char *);
void *bsearch(const void *, const void *, size_t, size_t, int (*)(const void *, const void *));
void *calloc(size_t, size_t);
div_t div(int, int);
double drand48(void);
char *ecvt(double, int, int *, int *);
double erand48(unsigned short int[3]);
void exit(int status);
int atoi(const char *nptr);
char *getenv(const char *name);
void *malloc(size_t Size);
void *realloc(void *Address, size_t Size);
void *calloc(size_t Count, size_t Size);
void free(void *Address);
int system(const char *command);
double atof(const char *nptr);
extern void perror(const char *s);
char *fcvt(double, int, int *, int *);
void free(void *ptr);
char *gcvt(double, int, char *);
char *getenv(const char *);
int getsubopt(char **, char *const *, char **);
int grantpt(int);
char *initstate(unsigned int, char *, size_t);
long int jrand48(unsigned short int[3]);
char *l64a(long);
long int labs(long int);
void lcong48(unsigned short int[7]);
ldiv_t ldiv(long int, long int);
long int lrand48(void);
void *malloc(size_t size);
int mblen(const char *, size_t);
size_t mbstowcs(wchar_t *, const char *, size_t);
int mbtowc(wchar_t *, const char *, size_t);
char *mktemp(char *);
int mkstemp(char *);
long int mrand48(void);
long int nrand48(unsigned short int[3]);
char *ptsname(int);
int putenv(char *);
void qsort(void *, size_t, size_t, int (*)(const void *, const void *));
int rand(void);
int rand_r(unsigned int *);
long random(void);
void *realloc(void *, size_t);
char *realpath(const char *, char *);
unsigned short int seed48(unsigned short int[3]);
void setkey(const char *);
char *setstate(const char *);
void srand(unsigned int);
void srand48(long int);
void srandom(unsigned);
double strtod(const char *, char **);
long int strtol(const char *, char **, int);
unsigned long int strtoul(const char *, char **, int);
int system(const char *);
int ttyslot(void);
int unlockpt(int);
void *valloc(size_t);
size_t wcstombs(char *, const wchar_t *, size_t);
int wctomb(char *, wchar_t);
#ifdef __cplusplus
}
#endif
#endif // __cplusplus
#endif
#endif // !_STDLIB_H

View File

@ -1,30 +1,71 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _STRING_H
#define _STRING_H
#include <stddef.h>
#ifdef __cplusplus
extern "C"
{
#endif
#endif // __cplusplus
size_t strlen(const char *str);
int strcmp(const char *l, const char *r);
int strncmp(const char *s1, const char *s2, size_t n);
int strcasecmp(const char *s1, const char *s2);
int strncasecmp(const char *string1, const char *string2, size_t count);
char *strstr(const char *haystack, const char *needle);
char *strncpy(char *destination, const char *source, unsigned long num);
char *strdup(const char *s);
char *strchr(char const *s, int c);
char *strrchr(char const *s, int c);
#include <stddef.h>
#include <locale.h>
void *memcpy(void *dest, const void *src, size_t n);
void *memset(void *dest, int c, size_t n);
void *memmove(void *dest, const void *src, size_t n);
void *memccpy(void *restrict, const void *restrict, int, size_t);
void *memchr(const void *, int, size_t);
int memcmp(const void *, const void *, size_t);
void *memcpy(void *restrict s1, const void *restrict s2, size_t n);
void *memmem(const void *, size_t, const void *, size_t);
void *memmove(void *, const void *, size_t);
void *memset(void *, int, size_t);
char *stpcpy(char *restrict, const char *restrict);
char *stpncpy(char *restrict, const char *restrict, size_t);
char *strcat(char *restrict, const char *restrict);
char *strchr(const char *, int);
int strcmp(const char *s1, const char *s2);
int strcoll(const char *, const char *);
int strcoll_l(const char *, const char *, locale_t);
char *strcpy(char *restrict, const char *restrict);
size_t strcspn(const char *, const char *);
char *strdup(const char *);
char *strerror(int);
char *strerror_l(int, locale_t);
int strerror_r(int, char *, size_t);
size_t strlcat(char *restrict, const char *restrict, size_t);
size_t strlcpy(char *restrict, const char *restrict, size_t);
size_t strlen(const char *);
char *strncat(char *restrict, const char *restrict, size_t);
int strncmp(const char *, const char *, size_t);
char *strncpy(char *restrict, const char *restrict, size_t);
char *strndup(const char *, size_t);
size_t strnlen(const char *, size_t);
char *strpbrk(const char *, const char *);
char *strrchr(const char *, int);
char *strsignal(int);
size_t strspn(const char *, const char *);
char *strstr(const char *, const char *);
char *strtok(char *restrict, const char *restrict);
char *strtok_r(char *restrict, const char *restrict, char **restrict);
size_t strxfrm(char *restrict, const char *restrict, size_t);
size_t strxfrm_l(char *restrict, const char *restrict, size_t, locale_t);
#ifdef __cplusplus
}
#endif
#endif // __cplusplus
#endif
#endif // !_STRING_H

View File

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

View File

@ -0,0 +1,73 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _SYS_MMAN_H
#define _SYS_MMAN_H
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
#include <sys/types.h>
#define PROT_READ 0x1
#define PROT_WRITE 0x2
#define PROT_EXEC 0x4
#define PROT_NONE 0x0
#define MAP_SHARED 0x01
#define MAP_PRIVATE 0x02
#define MAP_FIXED 0x4
#define MAP_ANONYMOUS 0x8
#define MAP_ANON MAP_ANONYMOUS
#define MS_ASYNC 0x01
#define MS_SYNC 0x02
#define MS_INVALIDATE 0x04
#define MCL_CURRENT 0x01
#define MCL_FUTURE 0x02
#define MAP_FAILED ((void *)-1)
typedef struct posix_typed_mem_info
{
/* Maximum length which may be allocated from a typed memory object. */
size_t posix_tmi_length;
} posix_typed_mem_info;
int mlock(const void *, size_t);
int mlockall(int);
void *mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off);
int mprotect(void *addr, size_t len, int prot);
int msync(void *, size_t, int);
int munlock(const void *, size_t);
int munlockall(void);
int munmap(void *addr, size_t len);
int posix_madvise(void *, size_t, int);
int posix_mem_offset(const void *restrict, size_t, off_t *restrict, size_t *restrict, int *restrict);
int posix_typed_mem_get_info(int, struct posix_typed_mem_info *);
int posix_typed_mem_open(const char *, int, int);
int shm_open(const char *, int, mode_t);
int shm_unlink(const char *);
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // !_SYS_MMAN_H

View File

@ -1,18 +1,108 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _SYS_STAT_H
#define _SYS_STAT_H
typedef unsigned int __dev_t;
typedef unsigned short __ino_t;
typedef unsigned short __mode_t;
typedef long __off_t;
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
#define dev_t __dev_t
#define ino_t __ino_t
#define mode_t __mode_t
#define off_t __off_t
#include <time.h>
int mkdir(const char *path, mode_t mode);
int remove(const char *pathname);
int rename(const char *oldpath, const char *newpath);
struct stat
{
dev_t st_dev; /* Device ID of device containing file. */
ino_t st_ino; /* File serial number. */
mode_t st_mode; /* Mode of file (see below). */
nlink_t st_nlink; /* Number of hard links to the file. */
uid_t st_uid; /* User ID of file. */
gid_t st_gid; /* Group ID of file. */
dev_t st_rdev; /* Device ID (if file is character or block special). */
off_t st_size; /* For regular files, the file size in bytes. For symbolic links, the length in bytes of the pathname contained in the symbolic link. For a shared memory object, the length in bytes. For a typed memory object, the length in bytes. For other file types, the use of this field is unspecified. */
struct timespec st_atim; /* Last data access timestamp. */
struct timespec st_mtim; /* Last data modification timestamp. */
struct timespec st_ctim; /* Last file status change timestamp. */
blksize_t st_blksize; /* A file system-specific preferred I/O block size for this object. In some file system types, this may vary from file to file. */
blkcnt_t st_blocks; /* Number of blocks allocated for this object. */
};
#endif
#define S_IFMT
#define S_IFBLK
#define S_IFCHR
#define S_IFIFO
#define S_IFREG
#define S_IFDIR
#define S_IFLNK
#define S_IFSOCK
#define S_IRWXU 0700
#define S_IRUSR 0400
#define S_IWUSR 0200
#define S_IXUSR 0100
#define S_IRWXG 070
#define S_IRGRP 040
#define S_IWGRP 020
#define S_IXGRP 010
#define S_IRWXO 07
#define S_IROTH 04
#define S_IWOTH 02
#define S_IXOTH 01
#define S_ISUID 04000
#define S_ISGID 02000
#define S_ISVTX 01000
#define S_ISBLK(m)
#define S_ISCHR(m)
#define S_ISDIR(m)
#define S_ISFIFO(m)
#define S_ISREG(m)
#define S_ISLNK(m)
#define S_ISSOCK(m)
#define S_TYPEISMQ(buf)
#define S_TYPEISSEM(buf)
#define S_TYPEISSHM(buf)
#define S_TYPEISTMO(buf)
#define UTIME_NOW
#define UTIME_OMIT
int chmod(const char *, mode_t);
int fchmod(int, mode_t);
int fchmodat(int, const char *, mode_t, int);
int fstat(int, struct stat *);
int fstatat(int, const char *restrict, struct stat *restrict, int);
int futimens(int, const struct timespec[2]);
int lstat(const char *restrict, struct stat *restrict);
int mkdir(const char *, mode_t);
int mkdirat(int, const char *, mode_t);
int mkfifo(const char *, mode_t);
int mkfifoat(int, const char *, mode_t);
int mknod(const char *, mode_t, dev_t);
int mknodat(int, const char *, mode_t, dev_t);
int stat(const char *restrict, struct stat *restrict);
mode_t umask(mode_t);
int utimensat(int, const char *, const struct timespec[2], int);
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // !_SYS_STAT_H

View File

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

View File

@ -1,37 +1,141 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _SYS_TYPES_H
#define _SYS_TYPES_H
#ifndef PUBLIC
#define PUBLIC __attribute__((visibility("default")))
#endif // !PUBLIC
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
#ifndef PRIVATE
#define PRIVATE __attribute__((visibility("hidden")))
#endif // !PRIVATE
#define __iptr __INTPTR_TYPE__
__iptr __check_errno(__iptr status, __iptr err);
typedef int __pid_t;
typedef int __ssize_t;
typedef unsigned int __id_t;
typedef unsigned int __useconds_t;
#ifndef restrict
#define restrict __restrict__
#endif // restrict
#ifndef __pid_t_defined
typedef __pid_t pid_t;
#define __pid_t_defined
#ifndef export
#define export __attribute__((__visibility__("default")))
#endif // export
typedef long blkcnt_t;
typedef long blksize_t;
typedef long clock_t;
typedef int clockid_t;
typedef unsigned long dev_t;
typedef unsigned long fsblkcnt_t;
typedef unsigned long fsfilcnt_t;
typedef unsigned int gid_t;
typedef unsigned int id_t;
typedef unsigned long ino_t;
typedef unsigned short reclen_t;
typedef int key_t;
typedef unsigned int mode_t;
typedef unsigned int nlink_t;
typedef long off_t;
typedef int pid_t;
typedef struct pthread_attr_t
{
char __data;
} pthread_attr_t;
typedef struct pthread_cond_t
{
char __data;
} pthread_cond_t;
typedef struct pthread_condattr_t
{
char __data;
} pthread_condattr_t;
typedef unsigned int pthread_key_t;
typedef struct pthread_mutex_t
{
short locked;
char __data;
} pthread_mutex_t;
typedef struct pthread_mutexattr_t
{
char __data;
} pthread_mutexattr_t;
typedef struct pthread_once_t
{
int __initialized;
} pthread_once_t;
typedef struct pthread_rwlock_t
{
char __data;
} pthread_rwlock_t;
typedef struct pthread_rwlockattr_t
{
char __data;
} pthread_rwlockattr_t;
typedef struct pthread_barrier_t
{
char __data;
} pthread_barrier_t;
typedef unsigned long size_t;
typedef long ssize_t;
typedef long suseconds_t;
typedef long time_t;
typedef int timer_t;
typedef unsigned int uid_t;
typedef unsigned int useconds_t;
typedef struct __pthread
{
struct __pthread *Self;
/* For __tls_get_addr */
__UINTPTR_TYPE__ *Storage;
int CurrentError;
} __pthread;
#ifdef __cplusplus
typedef unsigned long pthread_t;
#else
typedef struct __pthread *pthread_t;
#endif
#ifndef __id_t_defined
typedef __id_t id_t;
#define __id_t_defined
#endif
#ifdef __cplusplus
}
#endif // __cplusplus
#ifndef __useconds_t_defined
typedef __useconds_t useconds_t;
#define __useconds_t_defined
#endif
#ifndef __ssize_t_defined
typedef __ssize_t ssize_t;
#define __ssize_t_defined
#endif
#endif
#endif // !_SYS_TYPES_H

View File

@ -1,108 +1,65 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _SYS_WAIT_H
#define _SYS_WAIT_H
#include <sys/types.h>
typedef enum
#ifdef __cplusplus
extern "C"
{
P_ALL, /* Wait for any child. */
P_PID, /* Wait for specified process. */
P_PGID /* Wait for members of process group. */
} idtype_t;
#endif // __cplusplus
typedef struct
{
int stub;
} siginfo_t;
#include <signal.h>
#include <bits/waitstatus.h>
/* waitpid() */
#define WCONTINUED 0x00000008
#define WNOHANG 0x00000001
#define WUNTRACED 0x00000002
#define WCONTINUED 1
#define WNOHANG 2
#define WUNTRACED 4
#define WEXITED 8
#define WNOWAIT 16
#define WSTOPPED 32
/* waitid() */
#define WEXITED 0x00000004
#define WNOWAIT 0x00000020
#define WSTOPPED 0x00000002
/**
* @brief Macro for extracting the exit status from a status value.
*
* If the child process terminated normally by calling exit(3) or _exit(2),
* the macro WEXITSTATUS() returns the low-order 8 bits of the status value.
*
* @param status The status value to extract the exit status from.
* @return The exit status of the child process.
*/
#define WEXITSTATUS(status) __WEXITSTATUS(status)
#define WCOREDUMP(status) ((status) & 0x80)
#define WEXITSTATUS(status) (((status) >> 8) & 0xFF)
#define WIFCONTINUED(status) ((status) == 0xFFFF)
#define WIFEXITED(status) (((status) & 0x7F) == 0)
#define WIFSIGNALED(status) (((status) & 0x7F) > 0 && (((status) & 0x7F) != 0x7F))
#define WIFSTOPPED(status) (((status) & 0xFF) == 0x7F)
#define WSTOPSIG(status) WEXITSTATUS(status)
#define WTERMSIG(status) ((status) & 0x7F)
/**
* @brief Macro for extracting the termination signal from a status value.
*
* If the child process was terminated by a signal, the macro WTERMSIG()
* returns the signal number of the terminating signal.
*
* @param status The status value to extract the termination signal from.
* @return The termination signal of the child process.
*/
#define WTERMSIG(status) __WTERMSIG(status)
typedef enum
{
P_ALL,
P_PGID,
P_PID
} idtype_t;
/**
* @brief Macro for extracting the stop signal from a status value.
*
* If the child process was stopped by a signal, the macro WSTOPSIG()
* returns the signal number of the stop signal.
*
* @param status The status value to extract the stop signal from.
* @return The stop signal of the child process.
*/
#define WSTOPSIG(status) __WSTOPSIG(status)
typedef unsigned int id_t;
typedef int pid_t;
/**
* @brief Macro for testing whether a process exited normally.
*
* If the child process terminated normally by calling exit(3) or _exit(2),
* the macro WIFEXITED() returns a nonzero value. Otherwise, it returns 0.
*
* @param status The status value to test.
* @return A nonzero value if the child process exited normally, 0 otherwise.
*/
#define WIFEXITED(status) __WIFEXITED(status)
pid_t wait(int *);
int waitid(idtype_t, id_t, siginfo_t *, int);
pid_t waitpid(pid_t, int *, int);
/**
* @brief Macro for testing whether a process was terminated by a signal.
*
* If the child process was terminated by a signal, the macro WIFSIGNALED()
* returns a nonzero value. Otherwise, it returns 0.
*
* @param status The status value to test.
* @return A nonzero value if the child process was terminated by a signal, 0 otherwise.
*/
#define WIFSIGNALED(status) __WIFSIGNALED(status)
#ifdef __cplusplus
}
#endif // __cplusplus
/**
* @brief Macro for testing whether a process was stopped by a signal.
*
* If the child process was stopped by a signal, the macro WIFSTOPPED()
* returns a nonzero value. Otherwise, it returns 0.
*
* @param status The status value to test.
* @return A nonzero value if the child process was stopped by a signal, 0 otherwise.
*/
#define WIFSTOPPED(status) __WIFSTOPPED(status)
/**
* @brief Macro for testing whether a stopped process was continued.
*
* If the child process was stopped and has been resumed by delivery of SIGCONT,
* the macro WIFCONTINUED() returns a nonzero value. Otherwise, it returns 0.
*
* @param status The status value to test.
* @return A nonzero value if the child process was continued, 0 otherwise.
*/
#define WIFCONTINUED(status) __WIFCONTINUED(status)
pid_t wait(int *wstatus);
pid_t waitpid(pid_t pid, int *wstatus, int options);
int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options);
#endif
#endif // !_SYS_WAIT_H

View File

@ -1,4 +1,96 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _TIME_H
#define _TIME_H
#endif
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
#include <bits/types/timespec.h>
#include <sys/types.h>
#include <signal.h>
#include <locale.h>
typedef struct tm
{
int tm_sec; /* Seconds [0,60]. */
int tm_min; /* Minutes [0,59]. */
int tm_hour; /* Hour [0,23]. */
int tm_mday; /* Day of month [1,31]. */
int tm_mon; /* Month of year [0,11]. */
int tm_year; /* Years since 1900. */
int tm_wday; /* Day of week [0,6] (Sunday =0). */
int tm_yday; /* Day of year [0,365]. */
int tm_isdst; /* Daylight Saving flag. */
long tm_gmtoff; /* Seconds east of UTC. */
const char *tm_zone; /* Timezone abbreviation. */
} tm;
typedef struct itimerspec
{
struct timespec it_interval; /* Timer period. */
struct timespec it_value; /* Timer expiration. */
} itimerspec;
#define CLOCKS_PER_SEC
#define TIME_UTC
#define CLOCK_MONOTONIC __SYS_CLOCK_MONOTONIC
#define CLOCK_PROCESS_CPUTIME_ID __SYS_CLOCK_PROCESS_CPUTIME_ID
#define CLOCK_REALTIME __SYS_CLOCK_REALTIME
#define CLOCK_THREAD_CPUTIME_ID __SYS_CLOCK_THREAD_CPUTIME_ID
#define TIMER_ABSTIME
extern int daylight;
extern long timezone;
extern char *tzname[];
char *asctime(const struct tm *);
clock_t clock(void);
int clock_getcpuclockid(pid_t, clockid_t *);
int clock_getres(clockid_t, struct timespec *);
int clock_gettime(clockid_t, struct timespec *);
int clock_nanosleep(clockid_t, int, const struct timespec *, struct timespec *);
int clock_settime(clockid_t, const struct timespec *);
char *ctime(const time_t *);
double difftime(time_t, time_t);
struct tm *getdate(const char *);
struct tm *gmtime(const time_t *);
struct tm *gmtime_r(const time_t *restrict, struct tm *restrict);
struct tm *localtime(const time_t *);
struct tm *localtime_r(const time_t *restrict, struct tm *restrict);
time_t mktime(struct tm *);
int nanosleep(const struct timespec *, struct timespec *);
size_t strftime(char *restrict, size_t, const char *restrict, const struct tm *restrict);
size_t strftime_l(char *restrict, size_t, const char *restrict, const struct tm *restrict, locale_t);
char *strptime(const char *restrict, const char *restrict, struct tm *restrict);
time_t time(time_t *);
int timer_create(clockid_t, struct sigevent *restrict, timer_t *restrict);
int timer_delete(timer_t);
int timer_getoverrun(timer_t);
int timer_gettime(timer_t, struct itimerspec *);
int timer_settime(timer_t, int, const struct itimerspec *restrict, struct itimerspec *restrict);
int timespec_get(struct timespec *, int);
void tzset(void);
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // !_TIME_H

View File

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

View File

@ -1,29 +1,151 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef _UNISTD_H
#define _UNISTD_H
#include <sys/types.h>
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
#include <sys/types.h>
#include <inttypes.h>
#define _POSIX_VERSION 200809L
#define _POSIX2_VERSION 200809L
#define _XOPEN_VERSION 700
#define F_OK 0
#define R_OK 1
#define W_OK 2
#define X_OK 3
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
#ifndef NULL
#define NULL ((void *)0)
#endif
extern char **environ;
#define _POSIX_JOB_CONTROL 1
#define _POSIX_SAVED_IDS 1
#define _POSIX_NO_TRUNC 1
#define _POSIX_VDISABLE '\0'
int execl(const char *pathname, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *pathname, const char *arg, ...);
int execv(const char *pathname, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execvpe(const char *file, char *const argv[], char *const envp[]);
int execve(const char *pathname, char *const argv[], char *const envp[]);
#define ARG_MAX 4096
#define CHILD_MAX 25
#define CLK_TCK 100
#define _SC_PAGESIZE 4096
#define _SC_OPEN_MAX 256
extern char *optarg;
extern int optind, opterr, optopt;
int access(const char *, int);
unsigned int alarm(unsigned int);
int brk(void *);
int chdir(const char *);
int chroot(const char *);
int chown(const char *, uid_t, gid_t);
int close(int);
size_t confstr(int, char *, size_t);
char *crypt(const char *, const char *);
char *ctermid(char *);
char *cuserid(char *s);
int dup(int);
int dup2(int, int);
void encrypt(char[64], int);
int execl(const char *, const char *, ...);
int execle(const char *, const char *, ...);
int execlp(const char *, const char *, ...);
int execv(const char *, char *const[]);
int execve(const char *, char *const[], char *const[]);
int execvp(const char *, char *const[]);
void _exit(int);
int fchown(int, uid_t, gid_t);
int fchdir(int);
int fdatasync(int);
pid_t fork(void);
unsigned int sleep(unsigned int seconds);
int usleep(useconds_t usec);
long int fpathconf(int, int);
int fsync(int);
int ftruncate(int, off_t);
char *getcwd(char *, size_t);
int getdtablesize(void);
gid_t getegid(void);
uid_t geteuid(void);
gid_t getgid(void);
int getgroups(int, gid_t[]);
long gethostid(void);
char *getlogin(void);
int getlogin_r(char *, size_t);
int getopt(int, char *const[], const char *);
int getpagesize(void);
char *getpass(const char *);
pid_t getpgid(pid_t);
pid_t getpgrp(void);
pid_t getpid(void);
pid_t getppid(void);
pid_t getsid(pid_t);
uid_t getuid(void);
char *getwd(char *);
int isatty(int);
int lchown(const char *, uid_t, gid_t);
int link(const char *, const char *);
int lockf(int, int, off_t);
off_t lseek(int, off_t, int);
int nice(int);
long int pathconf(const char *, int);
int pause(void);
int pipe(int[2]);
ssize_t pread(int, void *, size_t, off_t);
int pthread_atfork(void (*)(void), void (*)(void), void (*)(void));
ssize_t pwrite(int, const void *, size_t, off_t);
ssize_t read(int, void *, size_t);
int readlink(const char *, char *, size_t);
int rmdir(const char *);
void *sbrk(intptr_t);
int setgid(gid_t);
int setpgid(pid_t, pid_t);
pid_t setpgrp(void);
int setregid(gid_t, gid_t);
int setreuid(uid_t, uid_t);
pid_t setsid(void);
int setuid(uid_t);
unsigned int sleep(unsigned int);
void swab(const void *, void *, ssize_t);
int symlink(const char *, const char *);
void sync(void);
long int sysconf(int);
pid_t tcgetpgrp(int);
int tcsetpgrp(int, pid_t);
int truncate(const char *, off_t);
char *ttyname(int);
int ttyname_r(int, char *, size_t);
useconds_t ualarm(useconds_t, useconds_t);
int unlink(const char *);
int usleep(useconds_t);
pid_t vfork(void);
ssize_t write(int, const void *, size_t);
#ifdef __cplusplus
}
#endif
#endif
#endif // __cplusplus
#endif // !_UNISTD_H

View File

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

View File

@ -0,0 +1,117 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#include <fennix/syscalls.h>
#include <sys/types.h>
#include <stdint.h>
#include <stddef.h>
#include <errno.h>
#include "elf.h"
#include "misc.h"
typedef struct MemoryBlock
{
struct MemoryBlock *next;
void *slots;
size_t slot_size;
size_t slots_per_block;
uint8_t *bitmap;
} MemoryBlock;
MemoryBlock *memory_pool = NULL;
#define PAGE_SIZE 0x1000
void *request_page(size_t size)
{
size_t aligned_size = (size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
void *addr = (void *)call_mmap(NULL, aligned_size, __SYS_PROT_READ | __SYS_PROT_WRITE, __SYS_MAP_ANONYMOUS | __SYS_MAP_PRIVATE, -1, 0);
if ((intptr_t)addr < 0)
return NULL;
return addr;
}
void free_page(void *addr, size_t size)
{
size_t aligned_size = (size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
call_munmap(addr, aligned_size);
}
MemoryBlock *allocate_block(size_t slot_size)
{
size_t block_size = PAGE_SIZE;
size_t slots_per_block = block_size / slot_size;
size_t bitmap_size = (slots_per_block + 7) / 8;
MemoryBlock *block = request_page(block_size);
if (!block)
return NULL;
block->slots = (void *)((uintptr_t)block + sizeof(MemoryBlock) + bitmap_size);
block->slot_size = slot_size;
block->slots_per_block = slots_per_block;
block->bitmap = (uint8_t *)((uintptr_t)block + sizeof(MemoryBlock));
memset(block->bitmap, 0, bitmap_size);
block->next = NULL;
return block;
}
void *mini_malloc(size_t size)
{
MemoryBlock *block = memory_pool;
while (block)
{
for (size_t i = 0; i < block->slots_per_block; i++)
{
size_t byte = i / 8, bit = i % 8;
if (!(block->bitmap[byte] & (1 << bit)))
{
block->bitmap[byte] |= (1 << bit);
return (void *)((uintptr_t)block->slots + i * size);
}
}
block = block->next;
}
block = allocate_block(size);
if (!block)
return NULL;
block->next = memory_pool;
memory_pool = block;
block->bitmap[0] |= 1;
return block->slots;
}
void mini_free(void *ptr)
{
MemoryBlock *block = memory_pool;
while (block)
{
if ((uintptr_t)ptr >= (uintptr_t)block->slots &&
(uintptr_t)ptr < (uintptr_t)block->slots + block->slots_per_block * block->slot_size)
{
size_t index = ((uintptr_t)ptr - (uintptr_t)block->slots) / block->slot_size;
size_t byte = index / 8, bit = index % 8;
block->bitmap[byte] &= ~(1 << bit);
return;
}
block = block->next;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,131 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#include <fennix/syscalls.h>
#include <sys/types.h>
#include <stdint.h>
#include <stddef.h>
#include <errno.h>
#include "elf.h"
#include "misc.h"
void *memset(void *s, int c, size_t n)
{
uint8_t *p = s;
while (n--)
*p++ = c;
return s;
}
void *memcpy(void *dest, const void *src, size_t n)
{
uint8_t *d = dest;
const uint8_t *s = src;
while (n--)
*d++ = *s++;
return dest;
}
size_t strlen(const char *s)
{
const char *p = s;
while (*p)
p++;
return p - s;
}
char *strcpy(char *dest, const char *src)
{
char *d = dest;
while ((*d++ = *src++))
;
return dest;
}
int strcmp(const char *l, const char *r)
{
while (*l && *l == *r)
{
l++;
r++;
}
return *l - *r;
}
char *strcat(char *dest, const char *src)
{
char *d = dest;
while (*d)
d++;
while ((*d++ = *src++))
;
return dest;
}
unsigned long elf_hash(const unsigned char *name)
{
unsigned long hash = 0, high;
while (*name)
{
hash = (hash << 4) + *name++;
if ((high = hash & 0xF0000000))
hash ^= high >> 24;
hash &= ~high;
}
return hash;
}
uint32_t gnu_hash(const char *name)
{
uint32_t hash = 5381;
for (; *name; name++)
{
hash = (hash << 5) + hash + (unsigned char)(*name); // hash * 33 + c
}
return hash;
}
Elf64_Sym *find_symbol(const char *name, uint32_t *hash_table, Elf64_Sym *symtab, const char *strtab)
{
/* Symbol Hash Table
|-------------------|
| nbucket |
|-------------------|
| nchain |
|-------------------|
| bucket[0] |
| . . . |
|bucket[nbucket - 1]|
|-------------------|
| chain[0] |
| . . . |
| chain[nchain - 1] |
|-------------------|
*/
unsigned long h = elf_hash(name); // or gnu_hash(name)
unsigned long bucket = h % hash_table[0]; // hash_table[0] = nbucket
for (unsigned long i = hash_table[2 + bucket];
i != STN_UNDEF;
i = hash_table[2 + hash_table[0] + i])
{
if (!strcmp(&strtab[symtab[i].st_name], name))
return &symtab[i];
}
return NULL;
}

View File

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

View File

@ -0,0 +1,51 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <string.h>
int printf(const char *, ...);
int _dl_main(int, char *[], char *[]);
void print_help()
{
printf("Usage: ld.so [options] <program>\n");
printf("Options:\n");
printf(" --help Display this help message\n");
}
int main(int argc, char *argv[], char *envp[])
{
if (argc < 2)
{
printf("Error: No program specified.\n");
print_help();
return -1;
}
for (int i = 1; i < argc; i++)
{
if (strcmp(argv[i], "--help") == 0)
{
print_help();
return 0;
}
}
int status = _dl_main(argc, argv, envp);
return status;
}

View File

@ -0,0 +1,50 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_DL_HELPER_H__
#define __FENNIX_DL_HELPER_H__
#include <sys/types.h>
#include <stdint.h>
#include <stddef.h>
#define ALIGN_UP(x, align) ((__typeof__(x))(((uintptr_t)(x) + ((align) - 1)) & (~((align) - 1))))
#define ALIGN_DOWN(x, align) ((__typeof__(x))((x) & (~((align) - 1))))
#ifndef __FENNIX_DL_ELF_H__
#error "Please include elf.h before misc.h"
#endif
void *memset(void *s, int c, size_t n);
void *memcpy(void *dest, const void *src, size_t n);
size_t strlen(const char *s);
char *strcpy(char *dest, const char *src);
int strcmp(const char *l, const char *r);
char *strcat(char *dest, const char *src);
unsigned long elf_hash(const unsigned char *name);
uint32_t gnu_hash(const char *name);
Elf64_Sym *find_symbol(const char *name, uint32_t *hash_table, Elf64_Sym *symtab, const char *strtab);
void __init_print_buffer();
void __fini_print_buffer();
int printf(const char *format, ...);
void *mini_malloc(size_t size);
void mini_free(void *ptr);
#endif // !__FENNIX_DL_HELPER_H__

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,82 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#include <stddef.h>
#include <stdarg.h>
#include <fennix/syscalls.h>
#include "elf.h"
#include "misc.h"
#define NANOPRINTF_IMPLEMENTATION 1
#include "nanoprintf.h"
char *print_buffer;
size_t print_buffer_size;
size_t print_buffer_offset;
void flush_buffer()
{
if (print_buffer_offset > 0)
{
call_write(1, print_buffer, print_buffer_offset);
print_buffer_offset = 0;
}
}
void print_wrapper(int c, void *)
{
if (print_buffer_offset >= print_buffer_size - 1)
flush_buffer();
print_buffer[print_buffer_offset++] = (char)c;
}
void __init_print_buffer()
{
print_buffer = (char *)call_mmap(0,
0x1000,
__SYS_PROT_READ | __SYS_PROT_WRITE,
__SYS_MAP_PRIVATE | __SYS_MAP_ANONYMOUS,
-1, 0);
print_buffer_size = 0x1000;
print_buffer_offset = 0;
}
void __fini_print_buffer()
{
flush_buffer();
if (print_buffer != NULL)
call_munmap(print_buffer, 0x1000);
print_buffer = NULL;
}
int printf(const char *format, ...)
{
va_list args;
va_start(args, format);
int ret = npf_vpprintf(print_wrapper, NULL, format, args);
va_end(args);
return ret;
}
int puts(const char *s)
{
int len = strlen(s);
memcpy(print_buffer + print_buffer_offset, s, len);
print_buffer_offset += len;
print_buffer[print_buffer_offset++] = '\0';
flush_buffer();
return len + 1;
}

View File

@ -0,0 +1,139 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#include <fennix/syscalls.h>
// const char __interp[] __attribute__((section(".interp"))) = "/boot/fennix.elf";
#ifndef LIBC_GIT_COMMIT
#define LIBC_GIT_COMMIT "0000000000000000000000000000000000000000"
#endif
#define HEX_DIGIT(c) (((c) >= '0' && (c) <= '9') ? ((c) - '0') : ((c) - 'a' + 10))
#define CONVERT_TO_BYTE(h, l) ((HEX_DIGIT(h) << 4) | HEX_DIGIT(l))
#define HASH_BYTES(hex) \
{CONVERT_TO_BYTE(hex[0], hex[1]), \
CONVERT_TO_BYTE(hex[2], hex[3]), \
CONVERT_TO_BYTE(hex[4], hex[5]), \
CONVERT_TO_BYTE(hex[6], hex[7]), \
CONVERT_TO_BYTE(hex[8], hex[9]), \
CONVERT_TO_BYTE(hex[10], hex[11]), \
CONVERT_TO_BYTE(hex[12], hex[13]), \
CONVERT_TO_BYTE(hex[14], hex[15]), \
CONVERT_TO_BYTE(hex[16], hex[17]), \
CONVERT_TO_BYTE(hex[18], hex[19]), \
CONVERT_TO_BYTE(hex[20], hex[21]), \
CONVERT_TO_BYTE(hex[22], hex[23]), \
CONVERT_TO_BYTE(hex[24], hex[25]), \
CONVERT_TO_BYTE(hex[26], hex[27]), \
CONVERT_TO_BYTE(hex[28], hex[29]), \
CONVERT_TO_BYTE(hex[30], hex[31]), \
CONVERT_TO_BYTE(hex[32], hex[33]), \
CONVERT_TO_BYTE(hex[34], hex[35]), \
CONVERT_TO_BYTE(hex[36], hex[37]), \
CONVERT_TO_BYTE(hex[38], hex[39])}
/* These are declared in GNU ld */
enum
{
NT_FNX_ABI_TAG = 1,
NT_FNX_VERSION = 2,
NT_FNX_BUILD_ID = 3,
NT_FNX_ARCH = 4
};
typedef struct Elf_Nhdr
{
__UINT32_TYPE__ n_namesz;
__UINT32_TYPE__ n_descsz;
__UINT32_TYPE__ n_type;
char n_name[];
} __attribute__((packed)) Elf_Nhdr;
const struct
{
Elf_Nhdr header;
char name[4];
__UINT32_TYPE__ desc[4];
} __abi_tag __attribute__((aligned(4), section(".note.ABI-tag"))) = {
.header = {
.n_namesz = 4, /* "FNX" + '\0' */
.n_descsz = sizeof(__UINT32_TYPE__) * 4, /* Description Size */
.n_type = NT_FNX_ABI_TAG, /* Type */
},
.name = "FNX",
.desc = {0, 0, 0, 0},
};
const struct
{
Elf_Nhdr header;
char name[4];
__UINT8_TYPE__ desc[20];
} __build_id __attribute__((aligned(4), section(".note.build-id"))) = {
.header = {
.n_namesz = 4, /* "FNX" + '\0' */
.n_descsz = sizeof(__UINT8_TYPE__) * 20, /* Description Size */
.n_type = NT_FNX_BUILD_ID, /* Type */
},
.name = "FNX",
.desc = HASH_BYTES(LIBC_GIT_COMMIT),
};
void __init_print_buffer();
void __fini_print_buffer();
__attribute__((naked, used, no_stack_protector)) void _start()
{
__asm__(
"xorq %rbp, %rbp\n" /* Clear rbp */
"push %rdi\n"
"push %rsi\n"
"push %rdx\n"
"push %rcx\n"
"push %r8\n"
"push %r9\n"
"call __init_print_buffer\n" /* Call __init_print_buffer */
"call _dl_preload\n" /* Call _dl_preload */
"movl %eax, %edi\n" /* Move return value to edi */
"cmp $0, %edi\n" /* Check if return value is 0 */
"jne _exit\n" /* If not, jump to _exit */
"pop %r9\n"
"pop %r8\n"
"pop %rcx\n"
"pop %rdx\n"
"pop %rsi\n"
"pop %rdi\n"
"call main\n" /* Call _dl_main */
"movl %eax, %edi\n" /* Move return value to edi */
"call _exit\n"); /* Call _exit */
}
__attribute__((no_stack_protector)) _Noreturn void _exit(int status)
{
__fini_print_buffer();
call_exit(status);
/* At this point, the program *SHOULD* have exited. */
__asm__("ud2\n");
__builtin_unreachable();
}
__attribute__((no_stack_protector)) _Noreturn void _Exit(int status) { _exit(status); }

View File

@ -1,20 +1,10 @@
# Config file
include ../../../config.mk
default:
$(error Do not run this Makefile directly!)
CC = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)gcc
AS = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)as
NASM = /usr/bin/nasm
C_SOURCES = $(shell find ./ -type f -name '*.c')
S_SOURCES = $(shell find ./ -type f -name '*.S')
ASM_SOURCES = $(shell find ./ -type f -name '*.asm')
OBJ = ${C_SOURCES:.c=.o} ${ASM_SOURCES:.asm=.o} ${S_SOURCES:.S=.o}
ifeq ($(OSARCH), amd64)
ASM_ARCH := elf64
else ifeq ($(OSARCH), i386)
ASM_ARCH := elf32
endif
C_SOURCES = $(shell find ./ -type f -name '*.c')
CXX_SOURCES = $(shell find ./ -type f -name '*.cpp')
OBJ = ${S_SOURCES:.S=.o} ${C_SOURCES:.c=.o} ${CXX_SOURCES:.cpp=.o}
CRTBEGIN_PATH = $(shell $(CC) -print-file-name=crtbegin.o)
CRTEND_PATH = $(shell $(CC) -print-file-name=crtend.o)
@ -22,20 +12,16 @@ CRTI_PATH = $(shell $(CC) -print-file-name=crti.o)
CRTN_PATH = $(shell $(CC) -print-file-name=crtn.o)
build: $(OBJ)
mv $^ ../../out/lib/
cp $(CRTBEGIN_PATH) $(CRTEND_PATH) $(CRTI_PATH) $(CRTN_PATH) ../../out/lib/
cp $^ ../../out/lib/
cp $(CRTBEGIN_PATH) $(CRTEND_PATH) $(CRTI_PATH) $(CRTN_PATH) $(WORKSPACE_DIR)/out/lib/
%.o: %.c
$(info Compiling $<)
$(CC) -nostdlib -mno-red-zone -std=c17 -c $< -o $@
%.o: %.asm
$(info Compiling $<)
$(NASM) $< -f $(ASM_ARCH) -o $@
$(CC) -nostdlib -mno-red-zone -std=c17 -DLIBC_GIT_COMMIT='"$(shell git rev-parse HEAD)"' -c $< -o $@
%.o: %.S
$(info Compiling $<)
$(AS) -c $< -o $@
clean:
rm -f $(OBJ)

View File

@ -0,0 +1,100 @@
/*
This file is part of Fennix Userspace.
Fennix Userspace is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Userspace is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Userspace. If not, see <https://www.gnu.org/licenses/>.
*/
typedef void (*fct)(void);
#define asm __asm__ __volatile__
extern void (*__preinit_array_start[])(void) __attribute__((weak));
extern void (*__preinit_array_end[])(void) __attribute__((weak));
extern void (*__init_array_start[])(void) __attribute__((weak));
extern void (*__init_array_end[])(void) __attribute__((weak));
extern void (*__fini_array_start[])(void) __attribute__((weak));
extern void (*__fini_array_end[])(void) __attribute__((weak));
void __crt_init_array(void)
{
for (fct *func = __init_array_start; func != __init_array_end; func++)
(*func)();
}
void __crt_fini_array(void)
{
for (fct *func = __fini_array_start; func != __fini_array_end; func++)
(*func)();
}
__attribute__((naked, used, no_stack_protector, section(".text"))) void _start()
{
asm("movq $0, %rbp\n"
"pushq %rbp\n"
"pushq %rbp\n"
"movq %rsp, %rbp\n"
"pushq %rcx\n"
"pushq %rdx\n"
"pushq %rsi\n"
"pushq %rdi\n"
"call __libc_init\n"
"call __crt_init_array\n"
"popq %rdi\n"
"popq %rsi\n"
"popq %rdx\n"
"popq %rcx\n"
"call main\n"
"pushq %rax\n"
"call __crt_fini_array\n"
"popq %rax\n"
"movl %eax, %edi\n"
"call _exit\n");
}
/* These are declared in GNU ld */
enum
{
NT_FNX_ABI_TAG = 1,
NT_FNX_VERSION = 2,
NT_FNX_BUILD_ID = 3,
NT_FNX_ARCH = 4
};
typedef struct Elf_Nhdr
{
__UINT32_TYPE__ n_namesz;
__UINT32_TYPE__ n_descsz;
__UINT32_TYPE__ n_type;
char n_name[];
} __attribute__((packed)) Elf_Nhdr;
const struct
{
Elf_Nhdr header;
char name[4];
__UINT32_TYPE__ desc[4];
} __abi_tag __attribute__((aligned(4), section(".note.ABI-tag"))) = {
.header = {
.n_namesz = 4, /* "FNX" + '\0' */
.n_descsz = sizeof(__UINT32_TYPE__) * 4, /* Description Size */
.n_type = NT_FNX_ABI_TAG, /* Type */
},
.name = "FNX",
.desc = {0, 0, 0, 0},
};

View File

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

View File

@ -1,21 +1,100 @@
// https://wiki.osdev.org/Creating_a_C_Library
/*
This file is part of Fennix Userspace.
Fennix Userspace is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Userspace is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Userspace. If not, see <https://www.gnu.org/licenses/>.
*/
typedef void (*fct)(void);
#define asm __asm__ __volatile__
extern void (*__preinit_array_start[])(void) __attribute__((weak));
extern void (*__preinit_array_end[])(void) __attribute__((weak));
extern void (*__init_array_start[])(void) __attribute__((weak));
extern void (*__init_array_end[])(void) __attribute__((weak));
extern void (*__fini_array_start[])(void) __attribute__((weak));
extern void (*__fini_array_end[])(void) __attribute__((weak));
void __crt_init_array(void)
{
for (fct *func = __init_array_start; func != __init_array_end; func++)
(*func)();
}
void __crt_fini_array(void)
{
for (fct *func = __fini_array_start; func != __fini_array_end; func++)
(*func)();
}
__attribute__((naked, used, no_stack_protector, section(".text"))) void _start()
{
asm("movq $0, %rbp\n");
asm("pushq %rbp\n");
asm("pushq %rbp\n");
asm("movq %rsp, %rbp\n");
asm("pushq %rcx\n"
asm("movq $0, %rbp\n"
"pushq %rbp\n"
"pushq %rbp\n"
"movq %rsp, %rbp\n"
"pushq %rcx\n"
"pushq %rdx\n"
"pushq %rsi\n"
"pushq %rdi\n");
asm("call __libc_init\n");
asm("popq %rdi\n"
"pushq %rdi\n"
"call __libc_init\n"
"call __crt_init_array\n"
"popq %rdi\n"
"popq %rsi\n"
"popq %rdx\n"
"popq %rcx\n");
asm("call main\n");
asm("movl %eax, %edi\n");
asm("call _exit\n");
"popq %rcx\n"
"call main\n"
"pushq %rax\n"
"call __crt_fini_array\n"
"popq %rax\n"
"movl %eax, %edi\n"
"call _exit\n");
}
/* These are declared in GNU ld */
enum
{
NT_FNX_ABI_TAG = 1,
NT_FNX_VERSION = 2,
NT_FNX_BUILD_ID = 3,
NT_FNX_ARCH = 4
};
typedef struct Elf_Nhdr
{
__UINT32_TYPE__ n_namesz;
__UINT32_TYPE__ n_descsz;
__UINT32_TYPE__ n_type;
char n_name[];
} __attribute__((packed)) Elf_Nhdr;
const struct
{
Elf_Nhdr header;
char name[4];
__UINT32_TYPE__ desc[4];
} __abi_tag __attribute__((aligned(4), section(".note.ABI-tag"))) = {
.header = {
.n_namesz = 4, /* "FNX" + '\0' */
.n_descsz = sizeof(__UINT32_TYPE__) * 4, /* Description Size */
.n_type = NT_FNX_ABI_TAG, /* Type */
},
.name = "FNX",
.desc = {0, 0, 0, 0},
};

View File

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

View File

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

View File

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

View File

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

View File

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

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

@ -0,0 +1,34 @@
/*
This file is part of Fennix Userspace.
Fennix Userspace is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Userspace is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Userspace. If not, see <https://www.gnu.org/licenses/>.
*/
#include <fennix/syscalls.h>
int __init_pthread(void);
void __init_stdio(void);
__attribute__((visibility("default"))) void __libc_init(void)
{
__init_pthread();
__init_stdio();
}
__attribute__((visibility("default"))) void _exit(int Code)
{
call_exit(Code);
while (1)
;
}

View File

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

View File

@ -1,5 +1,152 @@
/* TODO: Show a message or something */
int _start()
/*
This file is part of Fennix Userspace.
Fennix Userspace is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Userspace is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Userspace. If not, see <https://www.gnu.org/licenses/>.
*/
typedef void (*fct)(void);
#define asm __asm__ __volatile__
__attribute__((__visibility__("hidden"))) extern void (*__preinit_array_start[])(void) __attribute__((weak));
__attribute__((__visibility__("hidden"))) extern void (*__preinit_array_end[])(void) __attribute__((weak));
__attribute__((__visibility__("hidden"))) extern void (*__init_array_start[])(void) __attribute__((weak));
__attribute__((__visibility__("hidden"))) extern void (*__init_array_end[])(void) __attribute__((weak));
__attribute__((__visibility__("hidden"))) extern void (*__fini_array_start[])(void) __attribute__((weak));
__attribute__((__visibility__("hidden"))) extern void (*__fini_array_end[])(void) __attribute__((weak));
const char __interp[] __attribute__((section(".interp"))) = "/lib/ld.so";
#ifndef LIBC_GIT_COMMIT
#define LIBC_GIT_COMMIT "0000000000000000000000000000000000000000"
#endif
#define HEX_DIGIT(c) (((c) >= '0' && (c) <= '9') ? ((c) - '0') : ((c) - 'a' + 10))
#define CONVERT_TO_BYTE(h, l) ((HEX_DIGIT(h) << 4) | HEX_DIGIT(l))
#define HASH_BYTES(hex) \
{CONVERT_TO_BYTE(hex[0], hex[1]), \
CONVERT_TO_BYTE(hex[2], hex[3]), \
CONVERT_TO_BYTE(hex[4], hex[5]), \
CONVERT_TO_BYTE(hex[6], hex[7]), \
CONVERT_TO_BYTE(hex[8], hex[9]), \
CONVERT_TO_BYTE(hex[10], hex[11]), \
CONVERT_TO_BYTE(hex[12], hex[13]), \
CONVERT_TO_BYTE(hex[14], hex[15]), \
CONVERT_TO_BYTE(hex[16], hex[17]), \
CONVERT_TO_BYTE(hex[18], hex[19]), \
CONVERT_TO_BYTE(hex[20], hex[21]), \
CONVERT_TO_BYTE(hex[22], hex[23]), \
CONVERT_TO_BYTE(hex[24], hex[25]), \
CONVERT_TO_BYTE(hex[26], hex[27]), \
CONVERT_TO_BYTE(hex[28], hex[29]), \
CONVERT_TO_BYTE(hex[30], hex[31]), \
CONVERT_TO_BYTE(hex[32], hex[33]), \
CONVERT_TO_BYTE(hex[34], hex[35]), \
CONVERT_TO_BYTE(hex[36], hex[37]), \
CONVERT_TO_BYTE(hex[38], hex[39])}
/* These are declared in GNU ld */
enum
{
NT_FNX_ABI_TAG = 1,
NT_FNX_VERSION = 2,
NT_FNX_BUILD_ID = 3,
NT_FNX_ARCH = 4
};
typedef struct Elf_Nhdr
{
__UINT32_TYPE__ n_namesz;
__UINT32_TYPE__ n_descsz;
__UINT32_TYPE__ n_type;
char n_name[];
} __attribute__((packed)) Elf_Nhdr;
const struct
{
Elf_Nhdr header;
char name[4];
__UINT32_TYPE__ desc[4];
} __abi_tag __attribute__((aligned(4), section(".note.ABI-tag"))) = {
.header = {
.n_namesz = 4, /* "FNX" + '\0' */
.n_descsz = sizeof(__UINT32_TYPE__) * 4, /* Description Size */
.n_type = NT_FNX_ABI_TAG, /* Type */
},
.name = "FNX",
.desc = {0, 0, 0, 0},
};
const struct
{
Elf_Nhdr header;
char name[4];
__UINT8_TYPE__ desc[20];
} __build_id __attribute__((aligned(4), section(".note.build-id"))) = {
.header = {
.n_namesz = 4, /* "FNX" + '\0' */
.n_descsz = sizeof(__UINT8_TYPE__) * 20, /* Description Size */
.n_type = NT_FNX_BUILD_ID, /* Type */
},
.name = "FNX",
.desc = HASH_BYTES(LIBC_GIT_COMMIT),
};
void __crt_init_array(void)
{
for (fct *func = __init_array_start; func != __init_array_end; func++)
(*func)();
}
void __crt_fini_array(void)
{
for (fct *func = __fini_array_start; func != __fini_array_end; func++)
(*func)();
}
__attribute__((naked, used, no_stack_protector, section(".text"))) void _start()
{
asm("movq $0, %rbp\n"
"pushq %rbp\n"
"pushq %rbp\n"
"movq %rsp, %rbp\n"
"pushq %rcx\n"
"pushq %rdx\n"
"pushq %rsi\n"
"pushq %rdi\n"
"call __libc_init\n"
"call __crt_init_array\n"
"popq %rdi\n"
"popq %rsi\n"
"popq %rdx\n"
"popq %rcx\n"
"call main\n"
"pushq %rax\n"
"call __crt_fini_array\n"
"popq %rax\n"
"movl %eax, %edi\n"
"call _exit\n");
}
int main(int argc, char *argv[], char *envp[])
{
(void)argc;
(void)argv;
(void)envp;
/* FIXME: show printf license notice and some help and commands? */
return -1;
}

View File

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

View File

@ -1,30 +0,0 @@
#include <types.h>
#include "../lock.hpp"
#include "../../../../Kernel/syscalls.h"
NewLock(liballocLock);
extern "C" int liballoc_lock()
{
return liballocLock.Lock(__FUNCTION__);
}
extern "C" int liballoc_unlock()
{
return liballocLock.Unlock();
}
extern "C" void *liballoc_alloc(size_t Pages)
{
return (void *)syscall6(sc_mmap, NULL,
Pages * 0x1000,
sc_PROT_READ | sc_PROT_WRITE,
sc_MAP_ANONYMOUS | sc_MAP_PRIVATE,
-1, 0);
}
extern "C" int liballoc_free(void *Address, size_t Pages)
{
return syscall2(sc_munmap, (uintptr_t)Address, Pages * 0x1000);
}

View File

@ -0,0 +1,78 @@
/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
/* Taken directly from https://github.com/blanham/liballoc/blob/master/linux.c */
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/mman.h>
#include <unistd.h>
#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
#define MAP_ANONYMOUS MAP_ANON
#endif
#if !defined(MAP_FAILED)
#define MAP_FAILED ((char *)-1)
#endif
#ifndef MAP_NORESERVE
#ifdef MAP_AUTORESRV
#define MAP_NORESERVE MAP_AUTORESRV
#else
#define MAP_NORESERVE 0
#endif
#endif
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
static int page_size = -1;
int liballoc_lock()
{
pthread_mutex_lock(&mutex);
return 0;
}
int liballoc_unlock()
{
pthread_mutex_unlock(&mutex);
return 0;
}
void *liballoc_alloc(int pages)
{
if (page_size < 0)
page_size = getpagesize();
unsigned int size = pages * page_size;
char *p2 = (char *)mmap(0, size, PROT_NONE, MAP_PRIVATE | MAP_NORESERVE | MAP_ANONYMOUS, -1, 0);
if (p2 == MAP_FAILED)
return NULL;
if (mprotect(p2, size, PROT_READ | PROT_WRITE) != 0)
{
munmap(p2, size);
return NULL;
}
return p2;
}
int liballoc_free(void *ptr, int pages)
{
return munmap(ptr, pages * page_size);
}

View File

@ -43,17 +43,11 @@
#define LIBALLOC_MAGIC 0xc001c0de
#define LIBALLOC_DEAD 0xdeaddead
// #define LIBALLOCDEBUG 1
#define LIBALLOCINFO 1
#if defined LIBALLOCDEBUG || defined LIBALLOCINFO
#if defined DEBUG || defined INFO
#include <stdio.h>
#include <stdlib.h>
// #include <debug.h>
#define FLUSH() fflush(stdout)
#define atexit(x) atexit(x)
// #define printf(m, ...) trace(m, ##__VA_ARGS__)
#endif
@ -131,10 +125,10 @@ static void *liballoc_memcpy(void *s1, const void *s2, size_t n)
return s1;
}
#if defined LIBALLOCDEBUG || defined LIBALLOCINFO
#if defined DEBUG || defined INFO
static void liballoc_dump()
{
#ifdef LIBALLOCDEBUG
#ifdef DEBUG
struct liballoc_major *maj = l_memRoot;
struct liballoc_minor *min = NULL;
#endif
@ -146,7 +140,7 @@ static void liballoc_dump()
printf("liballoc: Error count: %i\n", l_errorCount);
printf("liballoc: Possible overruns: %i\n", l_possibleOverruns);
#ifdef LIBALLOCDEBUG
#ifdef DEBUG
while (maj != NULL)
{
printf("liballoc: %x: total = %i, used = %i\n",
@ -198,7 +192,7 @@ static struct liballoc_major *allocate_new_page(unsigned int size)
if (maj == NULL)
{
l_warningCount += 1;
#if defined LIBALLOCDEBUG || defined LIBALLOCINFO
#if defined DEBUG || defined INFO
printf("liballoc: WARNING: liballoc_alloc( %i ) return NULL\n", st);
FLUSH();
#endif
@ -214,7 +208,7 @@ static struct liballoc_major *allocate_new_page(unsigned int size)
l_allocated += maj->size;
#ifdef LIBALLOCDEBUG
#ifdef DEBUG
printf("liballoc: Resource allocated %x of %i pages (%i bytes) for %i size.\n", maj, st, maj->size, size);
printf("liballoc: Total memory usage = %i KB\n", (int)((l_allocated / (1024))));
@ -248,7 +242,7 @@ void *PREFIX(malloc)(size_t req_size)
if (size == 0)
{
l_warningCount += 1;
#if defined LIBALLOCDEBUG || defined LIBALLOCINFO
#if defined DEBUG || defined INFO
printf("liballoc: WARNING: alloc( 0 ) called from %x\n",
__builtin_return_address(0));
FLUSH();
@ -259,8 +253,8 @@ void *PREFIX(malloc)(size_t req_size)
if (l_memRoot == NULL)
{
#if defined LIBALLOCDEBUG || defined LIBALLOCINFO
#ifdef LIBALLOCDEBUG
#if defined DEBUG || defined INFO
#ifdef DEBUG
printf("liballoc: initialization of liballoc " VERSION "\n");
#endif
atexit(liballoc_dump);
@ -272,20 +266,20 @@ void *PREFIX(malloc)(size_t req_size)
if (l_memRoot == NULL)
{
liballoc_unlock();
#ifdef LIBALLOCDEBUG
#ifdef DEBUG
printf("liballoc: initial l_memRoot initialization failed\n", p);
FLUSH();
#endif
return NULL;
}
#ifdef LIBALLOCDEBUG
#ifdef DEBUG
printf("liballoc: set up first memory major %x\n", l_memRoot);
FLUSH();
#endif
}
#ifdef LIBALLOCDEBUG
#ifdef DEBUG
printf("liballoc: %x PREFIX(malloc)( %i ): ",
__builtin_return_address(0),
size);
@ -326,7 +320,7 @@ void *PREFIX(malloc)(size_t req_size)
// CASE 1: There is not enough space in this major block.
if (diff < (size + sizeof(struct liballoc_minor)))
{
#ifdef LIBALLOCDEBUG
#ifdef DEBUG
printf("CASE 1: Insufficient space in block %x\n", maj);
FLUSH();
#endif
@ -378,7 +372,7 @@ void *PREFIX(malloc)(size_t req_size)
ALIGN(p);
#ifdef LIBALLOCDEBUG
#ifdef DEBUG
printf("CASE 2: returning %x\n", p);
FLUSH();
#endif
@ -414,7 +408,7 @@ void *PREFIX(malloc)(size_t req_size)
p = (void *)((uintptr_t)(maj->first) + sizeof(struct liballoc_minor));
ALIGN(p);
#ifdef LIBALLOCDEBUG
#ifdef DEBUG
printf("CASE 3: returning %x\n", p);
FLUSH();
#endif
@ -460,7 +454,7 @@ void *PREFIX(malloc)(size_t req_size)
p = (void *)((uintptr_t)min + sizeof(struct liballoc_minor));
ALIGN(p);
#ifdef LIBALLOCDEBUG
#ifdef DEBUG
printf("CASE 4.1: returning %x\n", p);
FLUSH();
#endif
@ -499,7 +493,7 @@ void *PREFIX(malloc)(size_t req_size)
p = (void *)((uintptr_t)new_min + sizeof(struct liballoc_minor));
ALIGN(p);
#ifdef LIBALLOCDEBUG
#ifdef DEBUG
printf("CASE 4.2: returning %x\n", p);
FLUSH();
#endif
@ -519,7 +513,7 @@ void *PREFIX(malloc)(size_t req_size)
// CASE 5: Block full! Ensure next block and loop.
if (maj->next == NULL)
{
#ifdef LIBALLOCDEBUG
#ifdef DEBUG
printf("CASE 5: block full\n");
FLUSH();
#endif
@ -545,11 +539,11 @@ void *PREFIX(malloc)(size_t req_size)
liballoc_unlock(); // release the lock
#ifdef LIBALLOCDEBUG
#ifdef DEBUG
printf("All cases exhausted. No memory available.\n");
FLUSH();
#endif
#if defined LIBALLOCDEBUG || defined LIBALLOCINFO
#if defined DEBUG || defined INFO
printf("liballoc: WARNING: PREFIX(malloc)( %i ) returning NULL.\n", size);
liballoc_dump();
FLUSH();
@ -565,7 +559,7 @@ void PREFIX(free)(void *ptr)
if (ptr == NULL)
{
l_warningCount += 1;
#if defined LIBALLOCDEBUG || defined LIBALLOCINFO
#if defined DEBUG || defined INFO
printf("liballoc: WARNING: PREFIX(free)( NULL ) called from %x\n",
__builtin_return_address(0));
FLUSH();
@ -590,7 +584,7 @@ void PREFIX(free)(void *ptr)
((min->magic & 0xFF) == (LIBALLOC_MAGIC & 0xFF)))
{
l_possibleOverruns += 1;
#if defined LIBALLOCDEBUG || defined LIBALLOCINFO
#if defined DEBUG || defined INFO
printf("liballoc: ERROR: Possible 1-3 byte overrun for magic %x != %x\n",
min->magic,
LIBALLOC_MAGIC);
@ -600,7 +594,7 @@ void PREFIX(free)(void *ptr)
if (min->magic == LIBALLOC_DEAD)
{
#if defined LIBALLOCDEBUG || defined LIBALLOCINFO
#if defined DEBUG || defined INFO
printf("liballoc: ERROR: multiple PREFIX(free)() attempt on %x from %x.\n",
ptr,
__builtin_return_address(0));
@ -609,7 +603,7 @@ void PREFIX(free)(void *ptr)
}
else
{
#if defined LIBALLOCDEBUG || defined LIBALLOCINFO
#if defined DEBUG || defined INFO
printf("liballoc: ERROR: Bad PREFIX(free)( %x ) called from %x\n",
ptr,
__builtin_return_address(0));
@ -622,7 +616,7 @@ void PREFIX(free)(void *ptr)
return;
}
#ifdef LIBALLOCDEBUG
#ifdef DEBUG
printf("liballoc: %x PREFIX(free)( %x ): ",
__builtin_return_address(0),
ptr);
@ -674,7 +668,7 @@ void PREFIX(free)(void *ptr)
}
}
#ifdef LIBALLOCDEBUG
#ifdef DEBUG
printf("OK\n");
FLUSH();
#endif
@ -734,7 +728,7 @@ void *PREFIX(realloc)(void *p, size_t size)
((min->magic & 0xFF) == (LIBALLOC_MAGIC & 0xFF)))
{
l_possibleOverruns += 1;
#if defined LIBALLOCDEBUG || defined LIBALLOCINFO
#if defined DEBUG || defined INFO
printf("liballoc: ERROR: Possible 1-3 byte overrun for magic %x != %x\n",
min->magic,
LIBALLOC_MAGIC);
@ -744,7 +738,7 @@ void *PREFIX(realloc)(void *p, size_t size)
if (min->magic == LIBALLOC_DEAD)
{
#if defined LIBALLOCDEBUG || defined LIBALLOCINFO
#if defined DEBUG || defined INFO
printf("liballoc: ERROR: multiple PREFIX(free)() attempt on %x from %x.\n",
ptr,
__builtin_return_address(0));
@ -753,7 +747,7 @@ void *PREFIX(realloc)(void *p, size_t size)
}
else
{
#if defined LIBALLOCDEBUG || defined LIBALLOCINFO
#if defined DEBUG || defined INFO
printf("liballoc: ERROR: Bad PREFIX(free)( %x ) called from %x\n",
ptr,
__builtin_return_address(0));

View File

@ -1,7 +1,9 @@
#ifndef _LIBALLOC_H
#define _LIBALLOC_H
#include <types.h>
#include <inttypes.h>
#include <stddef.h>
#include <stdio.h>
/** \defgroup ALLOCHOOKS liballoc hooks
*
@ -17,6 +19,7 @@
// typedef unsigned long uintptr_t;
// This lets you prefix malloc and friends
// #define PREFIX(func) k##func
#define PREFIX(func) __##func
#ifdef __cplusplus

View File

@ -0,0 +1,23 @@
The MIT License (MIT)
Copyright (c) 2014 Marco Paland
Copyright (c) 2021 Eyal Rozenberg
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,20 @@
/*
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>
void putchar_(char c) { putc(c, stdout); }

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
/**
* @author (c) Eyal Rozenberg <eyalroz1@gmx.com>
* 2021-2022, Haifa, Palestine/Israel
* 2021-2023, Haifa, Palestine/Israel
* @author (c) Marco Paland (info@paland.com)
* 2014-2019, PALANDesign Hannover, Germany
*
@ -9,8 +9,8 @@
* or ask one of the authors.
*
* @brief Small stand-alone implementation of the printf family of functions
* (`(v)printf`, `(v)s(n)printf` etc., geared towards use on embedded systems with
* a very limited resources.
* (`(v)printf`, `(v)s(n)printf` etc., geared towards use on embedded systems
* with a very limited resources.
*
* @note the implementations are thread-safe; re-entrant; use no functions from
* the standard library; and do not dynamically allocate any memory.
@ -39,27 +39,40 @@
#ifndef PRINTF_H_
#define PRINTF_H_
#include <types.h>
#ifdef __cplusplus
#include <cstdarg>
#include <cstddef>
extern "C"
{
#else
#include <stdarg.h>
#include <stddef.h>
#endif
#ifdef __GNUC__
#if ((__GNUC__ == 4 && __GNUC_MINOR__ >= 4) || __GNUC__ > 4)
#define ATTR_PRINTF(one_based_format_index, first_arg) \
__attribute__((format(__printf__, (one_based_format_index), (first_arg))))
#define ATTR_VPRINTF(one_based_format_index) ATTR_PRINTF((one_based_format_index), 0)
__attribute__((format(gnu_printf, (one_based_format_index), (first_arg))))
#else
#define ATTR_PRINTF((one_based_format_index), (first_arg))
#define ATTR_PRINTF(one_based_format_index, first_arg) \
__attribute__((format(printf, (one_based_format_index), (first_arg))))
#endif
#define ATTR_VPRINTF(one_based_format_index) \
ATTR_PRINTF((one_based_format_index), 0)
#else
#define ATTR_PRINTF(one_based_format_index, first_arg)
#define ATTR_VPRINTF(one_based_format_index)
#endif
#ifndef PRINTF_ALIAS_STANDARD_FUNCTION_NAMES
#define PRINTF_ALIAS_STANDARD_FUNCTION_NAMES 0
#ifndef PRINTF_ALIAS_STANDARD_FUNCTION_NAMES_SOFT
#define PRINTF_ALIAS_STANDARD_FUNCTION_NAMES_SOFT 0
#endif
#if PRINTF_ALIAS_STANDARD_FUNCTION_NAMES
#ifndef PRINTF_ALIAS_STANDARD_FUNCTION_NAMES_HARD
#define PRINTF_ALIAS_STANDARD_FUNCTION_NAMES_HARD 0
#endif
#if PRINTF_ALIAS_STANDARD_FUNCTION_NAMES_HARD
#define printf_ printf
#define sprintf_ sprintf
#define vsprintf_ vsprintf
@ -69,126 +82,153 @@ extern "C"
#endif
// If you want to include this implementation file directly rather than
// link against, this will let you control the functions' visibility,
// link against it, this will let you control the functions' visibility,
// e.g. make them static so as not to clash with other objects also
// using them.
#ifndef PRINTF_VISIBILITY
#define PRINTF_VISIBILITY __attribute__((visibility("default")))
#define PRINTF_VISIBILITY
#endif
/**
* Prints/send a single character to some opaque output entity
*
* @note This function is not implemented by the library, only declared; you must provide an
* implementation if you wish to use the @ref printf / @ref vprintf function (and possibly
* for linking against the library, if your toolchain does not support discarding unused functions)
*
* @note The output could be as simple as a wrapper for the `write()` system call on a Unix-like
* system, or even libc's @ref putchar , for replicating actual functionality of libc's @ref printf
* function; but on an embedded system it may involve interaction with a special output device,
* like a UART, etc.
*
* @note in libc's @ref putchar, the parameter type is an int; this was intended to support the
* representation of either a proper character or EOF in a variable - but this is really not
* meaningful to pass into @ref putchar and is discouraged today. See further discussion in:
* @link https://stackoverflow.com/q/17452847/1593077
*
* @param c the single character to print
*/
PRINTF_VISIBILITY
int putchar(int c);
/**
* Prints/send a single character to some opaque output entity
*
* @note This function is not implemented by the library, only declared; you
* must provide an implementation if you wish to use the @ref printf / @ref
* vprintf function (and possibly for linking against the library, if your
* toolchain does not support discarding unused functions)
*
* @note The output could be as simple as a wrapper for the `write()` system
* call on a Unix-like * system, or even libc's @ref putchar , for replicating
* actual functionality of libc's @ref printf * function; but on an embedded
* system it may involve interaction with a special output device, like a UART,
* etc.
*
* @note in libc's @ref putchar, the parameter type is an int; this was intended
* to support the representation of either a proper character or EOF in a
* variable - but this is really not meaningful to pass into @ref putchar and is
* discouraged today. See further discussion in:
* @link https://stackoverflow.com/q/17452847/1593077
*
* @param c the single character to print
*/
PRINTF_VISIBILITY
void putchar_(char c);
/**
* An implementation of the C standard's printf/vprintf
*
* @note you must implement a @ref putchar_ function for using this function - it invokes @ref putchar_
* rather than directly performing any I/O (which insulates it from any dependence on the operating system
* and external libraries).
*
* @param format A string specifying the format of the output, with %-marked specifiers of how to interpret
* additional arguments.
* @param arg Additional arguments to the function, one for each %-specifier in @p format string
* @return The number of characters written into @p s, not counting the terminating null character
*/
///@{
PRINTF_VISIBILITY
int printf(const char *format, ...) ATTR_PRINTF(1, 2);
PRINTF_VISIBILITY
int vprintf(const char *format, va_list arg) ATTR_VPRINTF(1);
///@}
/**
* An implementation of the C standard's printf/vprintf
*
* @note you must implement a @ref putchar_ function for using this function -
* it invokes @ref putchar_ * rather than directly performing any I/O (which
* insulates it from any dependence on the operating system * and external
* libraries).
*
* @param format A string specifying the format of the output, with %-marked
* specifiers of how to interpret additional arguments.
* @param arg Additional arguments to the function, one for each %-specifier in
* @p format
* @return The number of characters written into @p s, not counting the
* terminating null character
*/
///@{
PRINTF_VISIBILITY
int printf_(const char *format, ...) ATTR_PRINTF(1, 2);
PRINTF_VISIBILITY
int vprintf_(const char *format, va_list arg) ATTR_VPRINTF(1);
///@}
/**
* An implementation of the C standard's sprintf/vsprintf
*
* @note For security considerations (the potential for exceeding the buffer bounds), please consider using
* the size-constrained variant, @ref snprintf / @ref vsnprintf , instead.
*
* @param s An array in which to store the formatted string. It must be large enough to fit the formatted
* output!
* @param format A string specifying the format of the output, with %-marked specifiers of how to interpret
* additional arguments.
* @param arg Additional arguments to the function, one for each specifier in @p format
* @return The number of characters written into @p s, not counting the terminating null character
*/
///@{
PRINTF_VISIBILITY
int sprintf(char *s, const char *format, ...) ATTR_PRINTF(2, 3);
PRINTF_VISIBILITY
int vsprintf(char *s, const char *format, va_list arg) ATTR_VPRINTF(2);
///@}
/**
* An implementation of the C standard's sprintf/vsprintf
*
* @note For security considerations (the potential for exceeding the buffer
* bounds), please consider using the size-constrained variant, @ref snprintf /
* @ref vsnprintf, instead.
*
* @param s An array in which to store the formatted string. It must be large
* enough to fit the formatted output!
* @param format A string specifying the format of the output, with %-marked
* specifiers of how to interpret additional arguments
* @param arg Additional arguments to the function, one for each specifier in
* @p format
* @return The number of characters written into @p s, not counting the
* terminating null character
*/
///@{
PRINTF_VISIBILITY
int sprintf_(char *s, const char *format, ...) ATTR_PRINTF(2, 3);
PRINTF_VISIBILITY
int vsprintf_(char *s, const char *format, va_list arg) ATTR_VPRINTF(2);
///@}
/**
* An implementation of the C standard's snprintf/vsnprintf
*
* @param s An array in which to store the formatted string. It must be large enough to fit either the
* entire formatted output, or at least @p n characters. Alternatively, it can be NULL, in which case
* nothing will be printed, and only the number of characters which _could_ have been printed is
* tallied and returned.
* @param n The maximum number of characters to write to the array, including a terminating null character
* @param format A string specifying the format of the output, with %-marked specifiers of how to interpret
* additional arguments.
* @param arg Additional arguments to the function, one for each specifier in @p format
* @return The number of characters that COULD have been written into @p s, not counting the terminating
* null character. A value equal or larger than @p n indicates truncation. Only when the returned value
* is non-negative and less than @p n, the null-terminated string has been fully and successfully printed.
*/
///@{
PRINTF_VISIBILITY
int snprintf(char *s, size_t count, const char *format, ...) ATTR_PRINTF(3, 4);
PRINTF_VISIBILITY
int vsnprintf(char *s, size_t count, const char *format, va_list arg) ATTR_VPRINTF(3);
///@}
/**
* An implementation of the C standard's snprintf/vsnprintf
*
* @param s An array in which to store the formatted string. It must be large
* enough to fit either the entire formatted output, or at least @p n
* characters. Alternatively, it can be NULL, in which case nothing will
* be printed, and only the number of characters which _could_ have been
* printed is tallied and returned.
* @param n The maximum number of characters to write to the array, including
* a terminating null character
* @param format A string specifying the format of the output, with %-marked
* specifiers of how to interpret additional arguments.
* @param arg Additional arguments to the function, one for each specifier in
* @p format
* @return The number of characters that COULD have been written into @p s, not
* counting the terminating null character. A value equal or larger than
* @p n indicates truncation. Only when the returned value is non-negative
* and less than @p n, the null-terminated string has been fully and
* successfully printed.
*/
///@{
PRINTF_VISIBILITY
int snprintf_(char *s, size_t count, const char *format, ...) ATTR_PRINTF(3, 4);
PRINTF_VISIBILITY
int vsnprintf_(char *s, size_t count, const char *format, va_list arg) ATTR_VPRINTF(3);
///@}
/**
* printf/vprintf with user-specified output function
*
* An alternative to @ref printf_, in which the output function is specified dynamically
* (rather than @ref putchar_ being used)
*
* @param out An output function which takes one character and a type-erased additional parameters
* @param extra_arg The type-erased argument to pass to the output function @p out with each call
* @param format A string specifying the format of the output, with %-marked specifiers of how to interpret
* additional arguments.
* @param arg Additional arguments to the function, one for each specifier in @p format
* @return The number of characters for which the output f unction was invoked, not counting the terminating null character
*
*/
PRINTF_VISIBILITY
int fctprintf(void (*out)(char c, void *extra_arg), void *extra_arg, const char *format, ...) ATTR_PRINTF(3, 4);
PRINTF_VISIBILITY
int vfctprintf(void (*out)(char c, void *extra_arg), void *extra_arg, const char *format, va_list arg) ATTR_VPRINTF(3);
/**
* printf/vprintf with user-specified output function
*
* An alternative to @ref printf_, in which the output function is specified
* dynamically (rather than @ref putchar_ being used)
*
* @param out An output function which takes one character and a type-erased
* additional parameters
* @param extra_arg The type-erased argument to pass to the output function @p
* out with each call
* @param format A string specifying the format of the output, with %-marked
* specifiers of how to interpret additional arguments.
* @param arg Additional arguments to the function, one for each specifier in
* @p format
* @return The number of characters for which the output f unction was invoked,
* not counting the terminating null character
*
*/
PRINTF_VISIBILITY
int fctprintf(void (*out)(char c, void *extra_arg), void *extra_arg, const char *format, ...) ATTR_PRINTF(3, 4);
PRINTF_VISIBILITY
int vfctprintf(void (*out)(char c, void *extra_arg), void *extra_arg, const char *format, va_list arg) ATTR_VPRINTF(3);
#if PRINTF_ALIAS_STANDARD_FUNCTION_NAMES
#ifdef __cplusplus
} // extern "C"
#endif
#if PRINTF_ALIAS_STANDARD_FUNCTION_NAMES_HARD
#undef printf_
#undef sprintf_
#undef vsprintf_
#undef snprintf_
#undef vsnprintf_
#undef vprintf_
#else
#if PRINTF_ALIAS_STANDARD_FUNCTION_NAMES_SOFT
#define printf printf_
#define sprintf sprintf_
#define vsprintf vsprintf_
#define snprintf snprintf_
#define vsnprintf vsnprintf_
#define vprintf vprintf_
#endif
#endif
#ifdef __cplusplus
}
#endif
#endif // PRINTF_H_
#endif // PRINTF_H_

View File

@ -1,11 +0,0 @@
#include <setjmp.h>
PUBLIC int setjmp(jmp_buf env)
{
return 0;
}
PUBLIC __attribute__((noreturn)) void longjmp(jmp_buf env, int value)
{
_exit(value);
}

View File

@ -0,0 +1,26 @@
/*
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 <assert.h>
#include <stdlib.h>
#include <stdio.h>
export void __assert_fail(const char *file, int line, const char *func)
{
printf("assertion failed: %s:%d:%s\n", file, line, func);
abort();
}

View File

@ -1,29 +0,0 @@
#include <ctype.h>
#include <sys/types.h> // For PUBLIC
PUBLIC int tolower(int c)
{
if (c >= 'A' && c <= 'Z')
{
c -= 'A';
c += 'a';
}
return c;
}
PUBLIC int toupper(int c)
{
if (c >= 'a' && c <= 'z')
{
c -= 'a';
c += 'A';
}
return c;
}
PUBLIC int isspace(int c)
{
return c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == '\f' || c == '\v';
}

View File

@ -1,10 +1,212 @@
/*
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 <sys/types.h>
#include <pthread.h>
#include <errno.h>
#include <sys/types.h> // For PUBLIC
int __local_stub_errno = 0;
PUBLIC int *__errno_location(void)
__iptr __check_errno(__iptr status, __iptr err)
{
return &__local_stub_errno;
if (status >= EOK)
return status;
pthread_self()->CurrentError = status;
return err;
}
export int *__errno_location(void)
{
return &pthread_self()->CurrentError;
}
export char *strerror(int errnum)
{
if (errnum < 0)
errnum = -errnum;
if (errnum > __ERRNO_MAX)
return (char *)"Not a valid error number";
switch (errnum)
{
case EOK:
return (char *)"No error";
case E2BIG:
return (char *)"Argument list too long";
case EACCES:
return (char *)"Permission denied";
case EADDRINUSE:
return (char *)"Address in use";
case EADDRNOTAVAIL:
return (char *)"Address not available";
case EAFNOSUPPORT:
return (char *)"Address family not supported";
case EAGAIN:
return (char *)"Resource unavailable, try again";
case EALREADY:
return (char *)"Connection already in progress";
case EBADF:
return (char *)"Bad file descriptor";
case EBADMSG:
return (char *)"Bad message";
case EBUSY:
return (char *)"Device or resource busy";
case ECANCELED:
return (char *)"Operation canceled";
case ECHILD:
return (char *)"No child processes";
case ECONNABORTED:
return (char *)"Connection aborted";
case ECONNREFUSED:
return (char *)"Connection refused";
case ECONNRESET:
return (char *)"Connection reset";
case EDEADLK:
return (char *)"Resource deadlock would occur";
case EDESTADDRREQ:
return (char *)"Destination address required";
case EDOM:
return (char *)"Mathematics argument out of domain of function";
case EDQUOT:
return (char *)"Reserved";
case EEXIST:
return (char *)"File exists";
case EFAULT:
return (char *)"Bad address";
case EFBIG:
return (char *)"File too large";
case EHOSTUNREACH:
return (char *)"Host is unreachable";
case EIDRM:
return (char *)"Identifier removed";
case EILSEQ:
return (char *)"Illegal byte sequence";
case EINPROGRESS:
return (char *)"Operation in progress";
case EINTR:
return (char *)"Interrupted function";
case EINVAL:
return (char *)"Invalid argument";
case EIO:
return (char *)"I/O error";
case EISCONN:
return (char *)"Socket is connected";
case EISDIR:
return (char *)"Is a directory";
case ELOOP:
return (char *)"Too many levels of symbolic links";
case EMFILE:
return (char *)"File descriptor value too large";
case EMLINK:
return (char *)"Too many links";
case EMSGSIZE:
return (char *)"Message too large";
case EMULTIHOP:
return (char *)"Reserved";
case ENAMETOOLONG:
return (char *)"Filename too long";
case ENETDOWN:
return (char *)"Network is down";
case ENETRESET:
return (char *)"Connection aborted by network";
case ENETUNREACH:
return (char *)"Network unreachable";
case ENFILE:
return (char *)"Too many files open in system";
case ENOBUFS:
return (char *)"No buffer space available";
case ENODATA:
return (char *)"No message available on the STREAM head read queue";
case ENODEV:
return (char *)"No such device";
case ENOENT:
return (char *)"No such file or directory";
case ENOEXEC:
return (char *)"Executable file format error";
case ENOLCK:
return (char *)"No locks available";
case ENOLINK:
return (char *)"Reserved";
case ENOMEM:
return (char *)"Not enough space";
case ENOMSG:
return (char *)"No message of the desired type";
case ENOPROTOOPT:
return (char *)"Protocol not available";
case ENOSPC:
return (char *)"No space left on device";
case ENOSR:
return (char *)"No STREAM resources";
case ENOSTR:
return (char *)"Not a STREAM";
case ENOSYS:
return (char *)"Functionality not supported";
case ENOTCONN:
return (char *)"The socket is not connected";
case ENOTDIR:
return (char *)"Not a directory or a symbolic link to a directory";
case ENOTEMPTY:
return (char *)"Directory not empty";
case ENOTRECOVERABLE:
return (char *)"State not recoverable";
case ENOTSOCK:
return (char *)"Not a socket";
case ENOTSUP:
return (char *)"Not supported";
case ENOTTY:
return (char *)"Inappropriate I/O control operation";
case ENXIO:
return (char *)"No such device or address";
case EOPNOTSUPP:
return (char *)"Operation not supported on socket";
case EOVERFLOW:
return (char *)"Value too large to be stored in data type";
case EOWNERDEAD:
return (char *)"Previous owner died";
case EPERM:
return (char *)"Operation not permitted";
case EPIPE:
return (char *)"Broken pipe";
case EPROTO:
return (char *)"Protocol error";
case EPROTONOSUPPORT:
return (char *)"Protocol not supported";
case EPROTOTYPE:
return (char *)"Protocol wrong type for socket";
case ERANGE:
return (char *)"Result too large";
case EROFS:
return (char *)"Read-only file system";
case ESPIPE:
return (char *)"Invalid seek";
case ESRCH:
return (char *)"No such process";
case ESTALE:
return (char *)"Reserved";
case ETIME:
return (char *)"Stream ioctl() timeout";
case ETIMEDOUT:
return (char *)"Connection timed out";
case ETXTBSY:
return (char *)"Text file busy";
case EWOULDBLOCK:
return (char *)"Operation would block";
case EXDEV:
return (char *)"Cross-device link";
default:
return (char *)"Unknown error";
}
}

View File

@ -1,132 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <errno.h>
#include <fennix/syscall.h>
#include <sys/types.h> // For PUBLIC
PUBLIC FILE *stdin = NULL;
PUBLIC FILE *stdout = NULL;
PUBLIC FILE *stderr = NULL;
PUBLIC FILE *freopen(const char *filename, const char *mode, FILE *stream)
{
errno = ENOSYS;
return NULL;
}
PUBLIC FILE *fopen(const char *filename, const char *mode)
{
int fd = syscall2(sc_open, (uint64_t)filename, (uint64_t)mode);
if (fd < 0)
return NULL;
FILE *FilePtr = malloc(sizeof(FILE));
FilePtr->_fileno = fd;
return FilePtr;
}
PUBLIC size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream)
{
if (ptr == NULL || stream == NULL || size == 0 || nmemb == 0)
{
errno = EINVAL;
return 0;
}
syscall3(sc_lseek, stream->_fileno, stream->_offset, SEEK_SET);
return syscall3(sc_read, (uint64_t)stream->_fileno, (uint64_t)ptr, size * nmemb);
}
PUBLIC size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
{
if (ptr == NULL || stream == NULL || size == 0 || nmemb == 0)
{
errno = EINVAL;
return 0;
}
syscall3(sc_lseek, stream->_fileno, stream->_offset, SEEK_SET);
return syscall3(sc_write, (uint64_t)stream->_fileno, (uint64_t)ptr, size * nmemb);
}
PUBLIC int fclose(FILE *fp)
{
if (fp == NULL)
{
errno = EINVAL;
return EOF;
}
return syscall1(sc_close, fp->_fileno);
}
PUBLIC off_t fseek(FILE *stream, off_t offset, int whence)
{
if (stream == NULL || whence < 0 || whence > 2)
{
errno = EINVAL;
return -1;
}
off_t new_offset = syscall3(sc_lseek, stream->_fileno, offset, whence);
if (new_offset < 0)
return -1;
stream->_offset = new_offset;
return new_offset;
}
PUBLIC long ftell(FILE *stream)
{
return stream->_offset;
}
PUBLIC int fflush(FILE *stream)
{
if (stream == NULL)
{
errno = EINVAL;
return EOF;
}
errno = ENOSYS;
return EOF;
}
PUBLIC int fprintf(FILE *stream, const char *format, ...)
{
if (stream == NULL || format == NULL)
{
errno = EINVAL;
return -1;
}
va_list args;
va_start(args, format);
const int ret = vfprintf(stream, format, args);
va_end(args);
return ret;
}
PUBLIC void setbuf(FILE *stream, char *buf)
{
}
PUBLIC int vfprintf(FILE *stream, const char *format, va_list arg)
{
return 0;
}
PUBLIC int vsscanf(const char *s, const char *format, va_list arg)
{
}
PUBLIC int sscanf(const char *s, const char *format, ...)
{
va_list args;
va_start(args, format);
const int ret = vsscanf(s, format, args);
va_end(args);
return ret;
}

View File

@ -1,9 +0,0 @@
#include <stdio.h>
#include <stdarg.h>
#include <fennix/syscall.h>
#include <sys/types.h> // For PUBLIC
PUBLIC int fgetc(FILE *stream)
{
}

View File

@ -1,34 +0,0 @@
#include <stdio.h>
#include <stdarg.h>
#include <fennix/syscall.h>
#include <sys/types.h> // For PUBLIC
PUBLIC int fputc(int c, FILE *stream)
{
// FIXME
// if (stream == NULL)
// {
// errno = EBADF;
// return EOF;
// }
char str[2] = {c, '\0'};
// return syscall3(sys_KernelCTL, KCTL_PRINT, str, 0);
}
PUBLIC int putc(int c, FILE *stream) { return fputc(c, stream); }
PUBLIC int fputs(const char *s, FILE *stream)
{
for (int i = 0; s[i] != '\0'; i++)
fputc(s[i], stream);
}
PUBLIC int puts(const char *s)
{
for (int i = 0; s[i] != '\0'; i++)
fputc(s[i], stdout);
}
PUBLIC int putchar(int c) { return fputc(c, stdout); }
PUBLIC void perror(const char *s) { fputs(s, stderr); }

View File

@ -1,87 +0,0 @@
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <fennix/syscall.h>
#include "../mem/liballoc_1_1.h"
PUBLIC void abort(void)
{
syscall1(sc_exit, -0xAB057);
while (1)
;
}
PUBLIC int atexit(void (*function)(void))
{
return 1;
}
PUBLIC void exit(int status)
{
_exit(status);
}
PUBLIC int atoi(const char *nptr)
{
uint64_t Length = strlen((char *)nptr);
if (nptr)
while (nptr[Length] != '\0')
++Length;
uint64_t OutBuffer = 0;
uint64_t Power = 1;
for (uint64_t i = Length; i > 0; --i)
{
OutBuffer += (nptr[i - 1] - 48) * Power;
Power *= 10;
}
return OutBuffer;
}
PUBLIC char **environ = NULL;
PUBLIC char *getenv(const char *name)
{
char **env = environ;
if (env == NULL)
return NULL;
size_t len = strlen(name);
while (*env != NULL)
{
if ((strncmp(*env, name, len) == 0) && ((*env)[len] == '='))
return &(*env)[len + 1];
++env;
}
}
PUBLIC void *malloc(size_t Size) { return PREFIX(malloc)(Size); }
PUBLIC void *realloc(void *Address, size_t Size) { return PREFIX(realloc)(Address, Size); }
PUBLIC void *calloc(size_t Count, size_t Size) { return PREFIX(calloc)(Count, Size); }
PUBLIC void free(void *Address)
{
PREFIX(free)
(Address);
}
PUBLIC int system(const char *command)
{
return -1;
}
PUBLIC double atof(const char *nptr)
{
// FIXME: This is a very bad implementation of atof.
uint64_t Length = strlen((char *)nptr);
if (nptr)
while (nptr[Length] != '\0')
++Length;
double OutBuffer = 0;
double Power = 1;
for (uint64_t i = Length; i > 0; --i)
{
OutBuffer += (nptr[i - 1] - 48) * Power;
Power *= 10;
}
return OutBuffer;
}

View File

@ -0,0 +1,121 @@
/*
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 <pthread.h>
#include <errno.h>
export int pthread_attr_destroy(pthread_attr_t *);
export int pthread_attr_getdetachstate(const pthread_attr_t *, int *);
export int pthread_attr_getguardsize(const pthread_attr_t *, size_t *);
export int pthread_attr_getinheritsched(const pthread_attr_t *, int *);
export int pthread_attr_getschedparam(const pthread_attr_t *, struct sched_param *);
export int pthread_attr_getschedpolicy(const pthread_attr_t *, int *);
export int pthread_attr_getscope(const pthread_attr_t *, int *);
export int pthread_attr_getstackaddr(const pthread_attr_t *, void **);
export int pthread_attr_getstacksize(const pthread_attr_t *, size_t *);
export int pthread_attr_init(pthread_attr_t *);
export int pthread_attr_setdetachstate(pthread_attr_t *, int);
export int pthread_attr_setguardsize(pthread_attr_t *, size_t);
export int pthread_attr_setinheritsched(pthread_attr_t *, int);
export int pthread_attr_setschedparam(pthread_attr_t *, const struct sched_param *);
export int pthread_attr_setschedpolicy(pthread_attr_t *, int);
export int pthread_attr_setscope(pthread_attr_t *, int);
export int pthread_attr_setstackaddr(pthread_attr_t *, void *);
export int pthread_attr_setstacksize(pthread_attr_t *, size_t);
export int pthread_cancel(pthread_t);
export void pthread_cleanup_push(void (*)(void *), void *);
export void pthread_cleanup_pop(int);
export int pthread_cond_broadcast(pthread_cond_t *);
export int pthread_cond_destroy(pthread_cond_t *);
export int pthread_cond_init(pthread_cond_t *, const pthread_condattr_t *);
export int pthread_cond_signal(pthread_cond_t *);
export int pthread_cond_timedwait(pthread_cond_t *, pthread_mutex_t *, const struct timespec *);
export int pthread_cond_wait(pthread_cond_t *, pthread_mutex_t *);
export int pthread_condattr_destroy(pthread_condattr_t *);
export int pthread_condattr_getpshared(const pthread_condattr_t *, int *);
export int pthread_condattr_init(pthread_condattr_t *);
export int pthread_condattr_setpshared(pthread_condattr_t *, int);
export int pthread_create(pthread_t *, const pthread_attr_t *, void *(*)(void *), void *);
export int pthread_detach(pthread_t);
export int pthread_equal(pthread_t, pthread_t);
export void pthread_exit(void *);
export int pthread_getconcurrency(void);
export int pthread_getschedparam(pthread_t, int *, struct sched_param *);
export void *pthread_getspecific(pthread_key_t);
export int pthread_join(pthread_t, void **);
export int pthread_key_create(pthread_key_t *, void (*)(void *));
export int pthread_key_delete(pthread_key_t);
export int pthread_mutex_destroy(pthread_mutex_t *);
export int pthread_mutex_getprioceiling(const pthread_mutex_t *, int *);
export int pthread_mutex_init(pthread_mutex_t *, const pthread_mutexattr_t *);
export int pthread_mutex_lock(pthread_mutex_t *mutex)
{
if (mutex->locked)
return EBUSY;
mutex->locked = 1;
return 0;
}
export int pthread_mutex_setprioceiling(pthread_mutex_t *, int, int *);
export int pthread_mutex_trylock(pthread_mutex_t *);
export int pthread_mutex_unlock(pthread_mutex_t *mutex)
{
if (!mutex->locked)
return EPERM;
mutex->locked = 0;
return 0;
}
export int pthread_mutexattr_destroy(pthread_mutexattr_t *);
export int pthread_mutexattr_getprioceiling(const pthread_mutexattr_t *, int *);
export int pthread_mutexattr_getprotocol(const pthread_mutexattr_t *, int *);
export int pthread_mutexattr_getpshared(const pthread_mutexattr_t *, int *);
export int pthread_mutexattr_gettype(const pthread_mutexattr_t *, int *);
export int pthread_mutexattr_init(pthread_mutexattr_t *);
export int pthread_mutexattr_setprioceiling(pthread_mutexattr_t *, int);
export int pthread_mutexattr_setprotocol(pthread_mutexattr_t *, int);
export int pthread_mutexattr_setpshared(pthread_mutexattr_t *, int);
export int pthread_mutexattr_settype(pthread_mutexattr_t *, int);
export int pthread_once(pthread_once_t *, void (*)(void));
export int pthread_rwlock_destroy(pthread_rwlock_t *);
export int pthread_rwlock_init(pthread_rwlock_t *, const pthread_rwlockattr_t *);
export int pthread_rwlock_rdlock(pthread_rwlock_t *);
export int pthread_rwlock_tryrdlock(pthread_rwlock_t *);
export int pthread_rwlock_trywrlock(pthread_rwlock_t *);
export int pthread_rwlock_unlock(pthread_rwlock_t *);
export int pthread_rwlock_wrlock(pthread_rwlock_t *);
export int pthread_rwlockattr_destroy(pthread_rwlockattr_t *);
export int pthread_rwlockattr_getpshared(const pthread_rwlockattr_t *, int *);
export int pthread_rwlockattr_init(pthread_rwlockattr_t *);
export int pthread_rwlockattr_setpshared(pthread_rwlockattr_t *, int);
export pthread_t pthread_self(void)
{
pthread_t tid;
__asm__ __volatile__("mov %%fs:0, %0"
: "=r"(tid));
return tid;
}
export int pthread_setcancelstate(int, int *);
export int pthread_setcanceltype(int, int *);
export int pthread_setconcurrency(int);
export int pthread_setschedparam(pthread_t, int, const struct sched_param *);
export int pthread_setspecific(pthread_key_t, const void *);
export void pthread_testcancel(void);

View File

@ -0,0 +1,47 @@
/*
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 <signal.h>
export int kill(pid_t pid, int sig)
{
return syscall2(SYS_KILL, pid, sig);
}
export int killpg(pid_t, int);
export void psiginfo(const siginfo_t *, const char *);
export void psignal(int, const char *);
export int pthread_kill(pthread_t, int);
export int pthread_sigmask(int, const sigset_t *restrict, sigset_t *restrict);
export int raise(int);
export int sig2str(int, char *);
export int sigaction(int, const struct sigaction *restrict, struct sigaction *restrict);
export int sigaddset(sigset_t *, int);
export int sigaltstack(const stack_t *restrict, stack_t *restrict);
export int sigdelset(sigset_t *, int);
export int sigemptyset(sigset_t *);
export int sigfillset(sigset_t *);
export int sigismember(const sigset_t *, int);
export void (*signal(int, void (*)(int)))(int);
export int sigpending(sigset_t *);
export int sigprocmask(int, const sigset_t *restrict, sigset_t *restrict);
export int sigqueue(pid_t, int, union sigval);
export int sigsuspend(const sigset_t *);
export int sigtimedwait(const sigset_t *restrict, siginfo_t *restrict, const struct timespec *restrict);
export int sigwait(const sigset_t *restrict, int *restrict);
export int sigwaitinfo(const sigset_t *restrict, siginfo_t *restrict);
export int str2sig(const char *restrict, int *restrict);

View File

@ -1,17 +0,0 @@
#include <spawn.h>
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[])
{
}

View File

@ -1,13 +0,0 @@
#include <stdio.h>
#include "../../../Kernel/syscalls.h"
void __libc_init_std(void)
{
/* FIXME: Temporal workaround */
// int IsCritical = syscall1(_KernelCTL, 6 /* KCTL_IS_CRITICAL */);
}
void __libc_fini_std(void)
{
}

View File

@ -0,0 +1,343 @@
/*
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 <stdlib.h>
#include <string.h>
#include <fennix/syscalls.h>
#include "../print/printf.h"
struct _IO_FILE *_i_open_files[256];
export FILE *stdin;
export FILE *stdout;
export FILE *stderr;
void __init_stdio(void)
{
stdin = malloc(sizeof(FILE));
stdin->fd = 0;
stdin->buffer = malloc(4096);
stdin->buffer_size = 4096;
stdin->buffer_pos = 0;
stdin->flags = _i_READ;
stdin->error = 0;
stdin->eof = 0;
stdout = malloc(sizeof(FILE));
stdout->fd = 1;
stdout->buffer = malloc(4096);
stdout->buffer_size = 4096;
stdout->buffer_pos = 0;
stdout->flags = _i_WRITE;
stdout->error = 0;
stdout->eof = 0;
stderr = malloc(sizeof(FILE));
stderr->fd = 2;
stderr->buffer = malloc(4096);
stderr->buffer_size = 4096;
stderr->buffer_pos = 0;
stderr->flags = _i_WRITE;
stderr->error = 0;
stderr->eof = 0;
_i_open_files[0] = stdin;
_i_open_files[1] = stdout;
_i_open_files[2] = stderr;
}
export void clearerr(FILE *);
export char *ctermid(char *);
export int dprintf(int, const char *restrict, ...);
export int fclose(FILE *stream)
{
if (!stream)
return EOF;
if (stream->buffer)
free(stream->buffer);
call_close(stream->fd);
_i_open_files[stream->fd] = NULL;
free(stream);
return 0;
}
export FILE *fdopen(int, const char *);
export int feof(FILE *);
export int ferror(FILE *);
export int fflush(FILE *stream)
{
if (!stream)
return EOF;
if (stream->flags & _i_WRITE)
{
if (stream->buffer_pos > 0)
{
ssize_t written = call_write(stream->fd, stream->buffer, stream->buffer_pos);
if (written < 0)
{
stream->error = 1;
return EOF;
}
stream->buffer_pos = 0;
}
}
else if (stream->flags & _i_READ)
{
stream->buffer_pos = 0;
stream->buffer_size = 0;
}
return 0;
}
export int fgetc(FILE *);
export int fgetpos(FILE *restrict, fpos_t *restrict);
export char *fgets(char *restrict, int, FILE *restrict);
export int fileno(FILE *);
export void flockfile(FILE *);
export FILE *fmemopen(void *restrict, size_t, const char *restrict);
export FILE *fopen(const char *restrict pathname, const char *restrict mode)
{
int flags = 0;
mode_t perm = 0;
if (strcmp(mode, "r") == 0)
flags = __SYS_O_RDONLY;
else if (strcmp(mode, "r+") == 0)
flags = __SYS_O_RDWR;
else if (strcmp(mode, "w") == 0)
{
flags = __SYS_O_WRONLY | __SYS_O_CREAT | __SYS_O_TRUNC;
perm = 0644;
}
else if (strcmp(mode, "w+") == 0)
{
flags = __SYS_O_RDWR | __SYS_O_CREAT | __SYS_O_TRUNC;
perm = 0644;
}
else if (strcmp(mode, "a") == 0)
{
flags = __SYS_O_WRONLY | __SYS_O_CREAT | __SYS_O_APPEND;
perm = 0644;
}
else if (strcmp(mode, "a+") == 0)
{
flags = __SYS_O_RDWR | __SYS_O_CREAT | __SYS_O_APPEND;
perm = 0644;
}
else
return NULL;
int fd = call_open(pathname, flags, perm);
if (fd < 0)
return NULL;
FILE *file = malloc(sizeof(FILE));
if (!file)
return NULL;
file->fd = fd;
file->buffer = malloc(4096);
file->buffer_size = 4096;
file->buffer_pos = 0;
file->flags = flags;
file->error = 0;
file->eof = 0;
_i_open_files[fd] = file;
return file;
}
export int fprintf(FILE *restrict, const char *restrict, ...);
export int fputc(int c, FILE *stream)
{
if (!stream || !(stream->flags & _i_WRITE))
return EOF;
stream->buffer[stream->buffer_pos++] = (char)c;
if (stream->buffer_pos >= stream->buffer_size)
{
if (fflush(stream) == EOF)
return EOF;
}
return (unsigned char)c;
}
export int fputs(const char *restrict s, FILE *restrict stream)
{
if (!stream || !(stream->flags & _i_WRITE))
return EOF;
while (*s)
{
if (fputc(*s++, stream) == EOF)
return EOF;
}
return 0;
}
export size_t fread(void *restrict ptr, size_t size, size_t nitems, FILE *restrict stream)
{
size_t total_bytes = size * nitems;
size_t bytes_read = 0;
while (bytes_read < total_bytes)
{
if (stream->buffer_pos >= stream->buffer_size)
{
int res = call_read(stream->fd, stream->buffer, stream->buffer_size);
if (res <= 0)
{
if (res == 0)
stream->eof = 1;
else
stream->error = 1;
break;
}
stream->buffer_pos = 0;
stream->buffer_size = res;
}
size_t bytes_to_copy = total_bytes - bytes_read;
size_t available = stream->buffer_size - stream->buffer_pos;
if (bytes_to_copy > available)
bytes_to_copy = available;
memcpy((char *)ptr + bytes_read, stream->buffer + stream->buffer_pos, bytes_to_copy);
stream->buffer_pos += bytes_to_copy;
bytes_read += bytes_to_copy;
}
return bytes_read / size;
}
export FILE *freopen(const char *restrict, const char *restrict, FILE *restrict);
export int fscanf(FILE *restrict, const char *restrict, ...);
export int fseek(FILE *stream, long offset, int whence)
{
int res = call_seek(stream->fd, offset, whence);
if (res < 0)
{
stream->error = 1;
return EOF;
}
stream->buffer_pos = 0;
stream->buffer_size = 0;
return 0;
}
export int fseeko(FILE *, off_t, int);
export int fsetpos(FILE *, const fpos_t *);
export long ftell(FILE *stream)
{
return call_tell(stream->fd);
}
export off_t ftello(FILE *);
export int ftrylockfile(FILE *);
export void funlockfile(FILE *);
export size_t fwrite(const void *restrict ptr, size_t size, size_t nitems, FILE *restrict stream)
{
size_t total_bytes = size * nitems;
size_t bytes_written = 0;
while (bytes_written < total_bytes)
{
size_t bytes_to_copy = total_bytes - bytes_written;
size_t space_available = stream->buffer_size - stream->buffer_pos;
if (bytes_to_copy > space_available)
bytes_to_copy = space_available;
memcpy(stream->buffer + stream->buffer_pos, (const char *)ptr + bytes_written, bytes_to_copy);
stream->buffer_pos += bytes_to_copy;
bytes_written += bytes_to_copy;
if (stream->buffer_pos == stream->buffer_size)
{
if (call_write(stream->fd, stream->buffer, stream->buffer_size) != stream->buffer_size)
{
stream->error = 1;
break;
}
stream->buffer_pos = 0;
}
}
return bytes_written / size;
}
export int getc(FILE *);
export int getchar(void);
export int getc_unlocked(FILE *);
export int getchar_unlocked(void);
export ssize_t getdelim(char **restrict, size_t *restrict, int, FILE *restrict);
export ssize_t getline(char **restrict, size_t *restrict, FILE *restrict);
export FILE *open_memstream(char **, size_t *);
export int pclose(FILE *);
export void perror(const char *);
export FILE *popen(const char *, const char *);
export int printf(const char *restrict format, ...)
{
va_list args;
va_start(args, format);
int ret = vprintf_(format, args);
va_end(args);
return ret;
}
export int putc(int c, FILE *stream) { return fputc(c, stream); }
export int putchar(int c) { return putc(c, stdout); }
export int putc_unlocked(int c, FILE *stream) { return fputc(c, stream); }
export int putchar_unlocked(int c) { return putc_unlocked(c, stdout); }
export int puts(const char *s) { return fputs(s, stdout); }
export int remove(const char *);
export int rename(const char *, const char *);
export int renameat(int, const char *, int, const char *);
export void rewind(FILE *);
export int scanf(const char *restrict, ...);
export void setbuf(FILE *restrict, char *restrict);
export int setvbuf(FILE *restrict, char *restrict, int, size_t);
export int snprintf(char *restrict, size_t, const char *restrict, ...);
export int sprintf(char *restrict, const char *restrict, ...);
export int sscanf(const char *restrict, const char *restrict, ...);
export FILE *tmpfile(void);
export char *tmpnam(char *);
export int ungetc(int, FILE *);
export int vdprintf(int, const char *restrict, va_list);
export int vfprintf(FILE *restrict, const char *restrict, va_list);
export int vfscanf(FILE *restrict, const char *restrict, va_list);
export int vprintf(const char *restrict, va_list);
export int vscanf(const char *restrict, va_list);
export int vsnprintf(char *restrict, size_t, const char *restrict, va_list);
export int vsprintf(char *restrict, const char *restrict, va_list);
export int vsscanf(const char *restrict, const char *restrict, va_list);

View File

@ -0,0 +1,105 @@
/*
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 <stdlib.h>
#include <unistd.h>
#include "../mem/liballoc_1_1.h"
#define MAX_ATEXIT_FUNCS 32
typedef void (*atexit_func_t)(void);
static atexit_func_t __atexit_funcs[MAX_ATEXIT_FUNCS];
static int __num_atexit_funcs = 0;
export long a64l(const char *);
export _Noreturn void abort(void)
{
kill(getpid(), SIGABRT);
__builtin_unreachable();
}
export int abs(int);
export int atexit(void (*func)(void))
{
if (__num_atexit_funcs >= MAX_ATEXIT_FUNCS)
return -1;
__atexit_funcs[__num_atexit_funcs++] = func;
return 0;
}
export double atof(const char *);
export int atoi(const char *);
export long int atol(const char *);
export void *bsearch(const void *, const void *, size_t, size_t, int (*)(const void *, const void *));
export void *calloc(size_t, size_t);
export div_t div(int, int);
export double drand48(void);
export char *ecvt(double, int, int *, int *);
export double erand48(unsigned short int[3]);
export void exit(int status)
{
for (int i = __num_atexit_funcs - 1; i >= 0; --i)
__atexit_funcs[i]();
_exit(status);
__builtin_unreachable();
}
export char *fcvt(double, int, int *, int *);
export void free(void *ptr) { return PREFIX(free)(ptr); }
export char *gcvt(double, int, char *);
export char *getenv(const char *);
export int getsubopt(char **, char *const *, char **);
export int grantpt(int);
export char *initstate(unsigned int, char *, size_t);
export long int jrand48(unsigned short int[3]);
export char *l64a(long);
export long int labs(long int);
export void lcong48(unsigned short int[7]);
export ldiv_t ldiv(long int, long int);
export long int lrand48(void);
export void *malloc(size_t size) { return PREFIX(malloc)(size); }
export int mblen(const char *, size_t);
export size_t mbstowcs(wchar_t *, const char *, size_t);
export int mbtowc(wchar_t *, const char *, size_t);
export char *mktemp(char *);
export int mkstemp(char *);
export long int mrand48(void);
export long int nrand48(unsigned short int[3]);
export char *ptsname(int);
export int putenv(char *);
export void qsort(void *, size_t, size_t, int (*)(const void *, const void *));
export int rand(void);
export int rand_r(unsigned int *);
export long random(void);
export void *realloc(void *, size_t);
export char *realpath(const char *, char *);
export unsigned short int seed48(unsigned short int[3]);
export void setkey(const char *);
export char *setstate(const char *);
export void srand(unsigned int);
export void srand48(long int);
export void srandom(unsigned);
export double strtod(const char *, char **);
export long int strtol(const char *, char **, int);
export unsigned long int strtoul(const char *, char **, int);
export int system(const char *);
export int ttyslot(void);
export int unlockpt(int);
export void *valloc(size_t);
export size_t wcstombs(char *, const wchar_t *, size_t);
export int wctomb(char *, wchar_t);

View File

@ -0,0 +1,86 @@
/*
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 <sys/types.h>
#include <string.h>
export void *memccpy(void *restrict, const void *restrict, int, size_t);
export void *memchr(const void *, int, size_t);
export int memcmp(const void *, const void *, size_t);
export void *memcpy(void *restrict s1, const void *restrict s2, size_t n)
{
unsigned char *dest = (unsigned char *)s1;
const unsigned char *src = (const unsigned char *)s2;
while (n >= sizeof(unsigned long))
{
*(unsigned long *)dest = *(const unsigned long *)src;
dest += sizeof(unsigned long);
src += sizeof(unsigned long);
n -= sizeof(unsigned long);
}
while (n--)
*dest++ = *src++;
return s1;
}
export void *memmem(const void *, size_t, const void *, size_t);
export void *memmove(void *, const void *, size_t);
export void *memset(void *, int, size_t);
export char *stpcpy(char *restrict, const char *restrict);
export char *stpncpy(char *restrict, const char *restrict, size_t);
export char *strcat(char *restrict, const char *restrict);
export char *strchr(const char *, int);
export int strcmp(const char *s1, const char *s2)
{
while (*s1 && (*s1 == *s2))
{
s1++;
s2++;
}
return *(unsigned char *)s1 - *(unsigned char *)s2;
}
export int strcoll(const char *, const char *);
export int strcoll_l(const char *, const char *, locale_t);
export char *strcpy(char *restrict, const char *restrict);
export size_t strcspn(const char *, const char *);
export char *strdup(const char *);
export char *strerror(int);
export char *strerror_l(int, locale_t);
export int strerror_r(int, char *, size_t);
export size_t strlcat(char *restrict, const char *restrict, size_t);
export size_t strlcpy(char *restrict, const char *restrict, size_t);
export size_t strlen(const char *);
export char *strncat(char *restrict, const char *restrict, size_t);
export int strncmp(const char *, const char *, size_t);
export char *strncpy(char *restrict, const char *restrict, size_t);
export char *strndup(const char *, size_t);
export size_t strnlen(const char *, size_t);
export char *strpbrk(const char *, const char *);
export char *strrchr(const char *, int);
export char *strsignal(int);
export size_t strspn(const char *, const char *);
export char *strstr(const char *, const char *);
export char *strtok(char *restrict, const char *restrict);
export char *strtok_r(char *restrict, const char *restrict, char **restrict);
export size_t strxfrm(char *restrict, const char *restrict, size_t);
export size_t strxfrm_l(char *restrict, const char *restrict, size_t, locale_t);

View File

@ -1,346 +0,0 @@
#include <stddef.h>
#include <sys/types.h> // For PUBLIC
/* Some of the functions are from musl library */
/* https://www.musl-libc.org/ */
/*
Copyright © 2005-2020 Rich Felker, et al.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
PUBLIC void *memcpy(void *dest, const void *src, size_t n)
{
unsigned char *d = dest;
const unsigned char *s = src;
#ifdef __GNUC__
#if __BYTE_ORDER == __LITTLE_ENDIAN
#define LS >>
#define RS <<
#else
#define LS <<
#define RS >>
#endif
typedef uint32_t __attribute__((__may_alias__)) u32;
uint32_t w, x;
for (; (uintptr_t)s % 4 && n; n--)
*d++ = *s++;
if ((uintptr_t)d % 4 == 0)
{
for (; n >= 16; s += 16, d += 16, n -= 16)
{
*(u32 *)(d + 0) = *(u32 *)(s + 0);
*(u32 *)(d + 4) = *(u32 *)(s + 4);
*(u32 *)(d + 8) = *(u32 *)(s + 8);
*(u32 *)(d + 12) = *(u32 *)(s + 12);
}
if (n & 8)
{
*(u32 *)(d + 0) = *(u32 *)(s + 0);
*(u32 *)(d + 4) = *(u32 *)(s + 4);
d += 8;
s += 8;
}
if (n & 4)
{
*(u32 *)(d + 0) = *(u32 *)(s + 0);
d += 4;
s += 4;
}
if (n & 2)
{
*d++ = *s++;
*d++ = *s++;
}
if (n & 1)
{
*d = *s;
}
return dest;
}
if (n >= 32)
{
switch ((uintptr_t)d % 4)
{
case 1:
{
w = *(u32 *)s;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
n -= 3;
for (; n >= 17; s += 16, d += 16, n -= 16)
{
x = *(u32 *)(s + 1);
*(u32 *)(d + 0) = (w LS 24) | (x RS 8);
w = *(u32 *)(s + 5);
*(u32 *)(d + 4) = (x LS 24) | (w RS 8);
x = *(u32 *)(s + 9);
*(u32 *)(d + 8) = (w LS 24) | (x RS 8);
w = *(u32 *)(s + 13);
*(u32 *)(d + 12) = (x LS 24) | (w RS 8);
}
break;
}
case 2:
{
w = *(u32 *)s;
*d++ = *s++;
*d++ = *s++;
n -= 2;
for (; n >= 18; s += 16, d += 16, n -= 16)
{
x = *(u32 *)(s + 2);
*(u32 *)(d + 0) = (w LS 16) | (x RS 16);
w = *(u32 *)(s + 6);
*(u32 *)(d + 4) = (x LS 16) | (w RS 16);
x = *(u32 *)(s + 10);
*(u32 *)(d + 8) = (w LS 16) | (x RS 16);
w = *(u32 *)(s + 14);
*(u32 *)(d + 12) = (x LS 16) | (w RS 16);
}
break;
}
case 3:
{
w = *(u32 *)s;
*d++ = *s++;
n -= 1;
for (; n >= 19; s += 16, d += 16, n -= 16)
{
x = *(u32 *)(s + 3);
*(u32 *)(d + 0) = (w LS 8) | (x RS 24);
w = *(u32 *)(s + 7);
*(u32 *)(d + 4) = (x LS 8) | (w RS 24);
x = *(u32 *)(s + 11);
*(u32 *)(d + 8) = (w LS 8) | (x RS 24);
w = *(u32 *)(s + 15);
*(u32 *)(d + 12) = (x LS 8) | (w RS 24);
}
break;
}
default:
break;
}
}
if (n & 16)
{
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
}
if (n & 8)
{
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
}
if (n & 4)
{
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
}
if (n & 2)
{
*d++ = *s++;
*d++ = *s++;
}
if (n & 1)
{
*d = *s;
}
return dest;
#endif
for (; n; n--)
*d++ = *s++;
return dest;
}
PUBLIC void *memset(void *dest, int c, size_t n)
{
unsigned char *s = dest;
size_t k;
if (!n)
return dest;
s[0] = c;
s[n - 1] = c;
if (n <= 2)
return dest;
s[1] = c;
s[2] = c;
s[n - 2] = c;
s[n - 3] = c;
if (n <= 6)
return dest;
s[3] = c;
s[n - 4] = c;
if (n <= 8)
return dest;
k = -(uintptr_t)s & 3;
s += k;
n -= k;
n &= -4;
#ifdef __GNUC__
typedef uint32_t __attribute__((__may_alias__)) u32;
typedef uint64_t __attribute__((__may_alias__)) u64;
u32 c32 = ((u32)-1) / 255 * (unsigned char)c;
*(u32 *)(s + 0) = c32;
*(u32 *)(s + n - 4) = c32;
if (n <= 8)
return dest;
*(u32 *)(s + 4) = c32;
*(u32 *)(s + 8) = c32;
*(u32 *)(s + n - 12) = c32;
*(u32 *)(s + n - 8) = c32;
if (n <= 24)
return dest;
*(u32 *)(s + 12) = c32;
*(u32 *)(s + 16) = c32;
*(u32 *)(s + 20) = c32;
*(u32 *)(s + 24) = c32;
*(u32 *)(s + n - 28) = c32;
*(u32 *)(s + n - 24) = c32;
*(u32 *)(s + n - 20) = c32;
*(u32 *)(s + n - 16) = c32;
k = 24 + ((uintptr_t)s & 4);
s += k;
n -= k;
u64 c64 = c32 | ((u64)c32 << 32);
for (; n >= 32; n -= 32, s += 32)
{
*(u64 *)(s + 0) = c64;
*(u64 *)(s + 8) = c64;
*(u64 *)(s + 16) = c64;
*(u64 *)(s + 24) = c64;
}
#else
for (; n; n--, s++)
*s = c;
#endif
return dest;
}
PUBLIC void *memmove(void *dest, const void *src, size_t n)
{
#ifdef __GNUC__
typedef __attribute__((__may_alias__)) size_t WT;
#define WS (sizeof(WT))
#endif
char *d = dest;
const char *s = src;
if (d == s)
return d;
if ((uintptr_t)s - (uintptr_t)d - n <= -2 * n)
return memcpy(d, s, n);
if (d < s)
{
#ifdef __GNUC__
if ((uintptr_t)s % WS == (uintptr_t)d % WS)
{
while ((uintptr_t)d % WS)
{
if (!n--)
return dest;
*d++ = *s++;
}
for (; n >= WS; n -= WS, d += WS, s += WS)
*(WT *)d = *(WT *)s;
}
#endif
for (; n; n--)
*d++ = *s++;
}
else
{
#ifdef __GNUC__
if ((uintptr_t)s % WS == (uintptr_t)d % WS)
{
while ((uintptr_t)(d + n) % WS)
{
if (!n--)
return dest;
d[n] = s[n];
}
while (n >= WS)
n -= WS, *(WT *)(d + n) = *(WT *)(s + n);
}
#endif
while (n)
n--, d[n] = s[n];
}
return dest;
}

View File

@ -1,125 +0,0 @@
#include <string.h>
#include "../../mem/liballoc_1_1.h"
PUBLIC size_t strlen(const char *str)
{
long unsigned i = 0;
if (str)
while (str[i] != '\0')
++i;
return i;
}
PUBLIC int strcmp(const char *l, const char *r)
{
for (; *l == *r && *l; l++, r++)
;
return *(unsigned char *)l - *(unsigned char *)r;
}
PUBLIC int strncmp(const char *s1, const char *s2, size_t n)
{
for (size_t i = 0; i < n; i++)
{
char c1 = s1[i], c2 = s2[i];
if (c1 != c2)
return c1 - c2;
if (!c1)
return 0;
}
return 0;
}
PUBLIC int strcasecmp(const char *s1, const char *s2)
{
const unsigned char *p1 = (const unsigned char *)s1;
const unsigned char *p2 = (const unsigned char *)s2;
int result;
if (p1 == p2)
return 0;
while ((result = tolower(*p1) - tolower(*p2++)) == 0)
if (*p1++ == '\0')
break;
return result;
}
PUBLIC int strncasecmp(const char *string1, const char *string2, size_t count)
{
if (count)
{
const unsigned char *s1 = (const unsigned char *)string1;
const unsigned char *s2 = (const unsigned char *)string2;
int result;
do
{
if ((result = tolower(*s1) - tolower(*s2++)) != 0 || !*s1++)
break;
} while (--count);
return result;
}
return 0;
}
PUBLIC char *strstr(const char *haystack, const char *needle)
{
const char *a = haystack, *b = needle;
while (1)
{
if (!*b)
return (char *)haystack;
if (!*a)
return NULL;
if (*a++ != *b++)
{
a = ++haystack;
b = needle;
}
}
}
PUBLIC char *strncpy(char *destination, const char *source, unsigned long num)
{
if (destination == NULL)
return NULL;
char *ptr = destination;
while (*source && num--)
{
*destination = *source;
destination++;
source++;
}
*destination = '\0';
return ptr;
}
PUBLIC char *strdup(const char *s)
{
char *buf = (char *)__malloc(strlen((char *)s) + 1);
strncpy(buf, s, strlen(s) + 1);
return buf;
}
PUBLIC char *strchr(char const *s, int c)
{
size_t len = strlen(s);
for (size_t i = 0; i < len; i++)
if (s[i] == c)
return (char *)s + i;
return NULL;
}
PUBLIC char *strrchr(char const *s, int c)
{
size_t len = strlen(s);
size_t pos = len;
while (s[pos] != c && pos-- != 0)
;
if (pos == len)
return NULL;
return (char *)s + pos;
}

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