mirror of
https://github.com/EnderIce2/Fennix.git
synced 2025-07-02 10:59:15 +00:00
userspace: Rewrite everything
Everything. Signed-off-by: EnderIce2 <enderice2@protonmail.com>
This commit is contained in:
@ -1,70 +0,0 @@
|
||||
# Config file
|
||||
include ../../../config.mk
|
||||
|
||||
NAME=ld
|
||||
|
||||
OBJECT_NAME=$(NAME).so
|
||||
SO_NAME=$(OBJECT_NAME)
|
||||
|
||||
OUTPUT_DIR=../../out/lib/
|
||||
SYSROOT = --sysroot=../../out/
|
||||
|
||||
CC = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)gcc
|
||||
AS = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)as
|
||||
AR = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)ar
|
||||
OBJDUMP = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)objdump
|
||||
NASM = /usr/bin/nasm
|
||||
|
||||
C_SOURCES = $(shell find ./ -type f -name '*.c')
|
||||
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp')
|
||||
S_SOURCES = $(shell find ./ -type f -name '*.S')
|
||||
ASM_SOURCES = $(shell find ./ -type f -name '*.asm')
|
||||
OBJ = ${C_SOURCES:.c=.o} ${CPP_SOURCES:.cpp=.o} ${ASM_SOURCES:.asm=.o} ${S_SOURCES:.S=.o}
|
||||
|
||||
INCLUDE = ../include
|
||||
|
||||
SIMD_FLAGS := -mno-sse -mno-sse2 -mno-sse3 -mno-ssse3 -mno-sse4.1 -mno-sse4.2 -mno-sse4 -mno-avx -mno-avx2 -mno-avx512f
|
||||
|
||||
CFLAGS := -I$(INCLUDE) $(SIMD_FLAGS) -fPIC
|
||||
LDFLAGS := -nostartfiles -nostdlib -Wl,-soname,$(SO_NAME) $(SYSROOT) -fno-pie -fno-PIC
|
||||
|
||||
ifeq ($(OSARCH), amd64)
|
||||
ASM_ARCH := elf64
|
||||
LDFLAGS += -Ttext=0xFFFFFFFFF0001000
|
||||
CFLAGS += -m64
|
||||
else ifeq ($(OSARCH), i386)
|
||||
ASM_ARCH := elf32
|
||||
LDFLAGS += -fixme
|
||||
CFLAGS += -m32
|
||||
endif
|
||||
|
||||
ifeq ($(DEBUG), 1)
|
||||
CFLAGS += -DDEBUG -ggdb3 -O0 -fdiagnostics-color=always -fverbose-asm
|
||||
LDFLAGS += -ggdb3 -O0
|
||||
endif
|
||||
|
||||
build: $(OBJECT_NAME)
|
||||
|
||||
$(OBJECT_NAME): $(OBJ)
|
||||
$(info Linking $@)
|
||||
$(CC) $(LDFLAGS) $(OBJ) -o $(OUTPUT_DIR)$@
|
||||
$(OBJDUMP) -d $(OUTPUT_DIR)$@ > file_dump.map
|
||||
|
||||
%.o: %.c
|
||||
$(info Compiling $<)
|
||||
$(CC) $(CFLAGS) -std=c17 -c $< -o $@
|
||||
|
||||
%.o: %.cpp
|
||||
$(info Compiling $<)
|
||||
$(CC) $(CFLAGS) -std=c++20 -c $< -o $@
|
||||
|
||||
%.o: %.S
|
||||
$(info Compiling $<)
|
||||
$(AS) -c $< -o $@
|
||||
|
||||
%.o: %.asm
|
||||
$(info Compiling $<)
|
||||
$(NASM) $< -f $(ASM_ARCH) -o $@
|
||||
|
||||
clean:
|
||||
rm -f file_dump.map $(OBJ)
|
@ -1,296 +0,0 @@
|
||||
#ifndef __FENNIX_LIB_ELF_LAZY_RESOLVE_H__
|
||||
#define __FENNIX_LIB_ELF_LAZY_RESOLVE_H__
|
||||
|
||||
typedef __UINT32_TYPE__ Elf32_Addr;
|
||||
typedef __UINT16_TYPE__ Elf32_Half;
|
||||
typedef __UINT32_TYPE__ Elf32_Off;
|
||||
typedef __INT32_TYPE__ Elf32_Sword;
|
||||
typedef __UINT32_TYPE__ Elf32_Word;
|
||||
|
||||
typedef __UINT64_TYPE__ Elf64_Addr;
|
||||
typedef __UINT16_TYPE__ Elf64_Half;
|
||||
typedef __INT16_TYPE__ Elf64_SHalf;
|
||||
typedef __UINT64_TYPE__ Elf64_Off;
|
||||
typedef __INT32_TYPE__ Elf64_Sword;
|
||||
typedef __UINT32_TYPE__ Elf64_Word;
|
||||
typedef __UINT64_TYPE__ Elf64_Xword;
|
||||
typedef __INT64_TYPE__ Elf64_Sxword;
|
||||
|
||||
enum SectionHeaderType
|
||||
{
|
||||
SHT_NULL = 0,
|
||||
SHT_PROGBITS = 1,
|
||||
SHT_SYMTAB = 2,
|
||||
SHT_STRTAB = 3,
|
||||
SHT_RELA = 4,
|
||||
SHT_HASH = 5,
|
||||
SHT_DYNAMIC = 6,
|
||||
SHT_NOTE = 7,
|
||||
SHT_NOBITS = 8,
|
||||
SHT_REL = 9,
|
||||
SHT_SHLIB = 10,
|
||||
SHT_DYNSYM = 11,
|
||||
SHT_INIT_ARRAY = 14,
|
||||
SHT_FINI_ARRAY = 15,
|
||||
SHT_PREINIT_ARRAY = 16,
|
||||
SHT_GROUP = 17,
|
||||
SHT_SYMTAB_SHNDX = 18,
|
||||
SHT_NUM = 19,
|
||||
SHT_LOOS = 0x60000000,
|
||||
SHT_GNU_ATTRIBUTES = 0x6ffffff5,
|
||||
SHT_GNU_HASH = 0x6ffffff6,
|
||||
SHT_GNU_LIBLIST = 0x6ffffff7,
|
||||
SHT_CHECKSUM = 0x6ffffff8,
|
||||
SHT_LOSUNW = 0x6ffffffa,
|
||||
SHT_SUNW_move = 0x6ffffffa,
|
||||
SHT_SUNW_COMDAT = 0x6ffffffb,
|
||||
SHT_SUNW_syminfo = 0x6ffffffc,
|
||||
SHT_GNU_verdef = 0x6ffffffd,
|
||||
SHT_GNU_verneed = 0x6ffffffe,
|
||||
SHT_GNU_versym = 0x6fffffff,
|
||||
SHT_HISUNW = 0x6fffffff,
|
||||
SHT_HIOS = 0x6fffffff,
|
||||
SHT_LOPROC = 0x70000000,
|
||||
SHT_HIPROC = 0x7fffffff,
|
||||
SHT_LOUSER = 0x80000000,
|
||||
SHT_HIUSER = 0x8fffffff
|
||||
};
|
||||
|
||||
#define ELF32_R_SYM(i) ((i) >> 8)
|
||||
#define ELF32_R_TYPE(i) ((unsigned char)(i))
|
||||
#define ELF32_R_INFO(s, t) (((s) << 8) + (unsigned char)(t))
|
||||
|
||||
#define ELF64_R_SYM(i) ((i) >> 32)
|
||||
#define ELF64_R_TYPE(i) ((i)&0xffffffffL)
|
||||
#define ELF64_R_INFO(s, t) (((s) << 32) + ((t)&0xffffffffL))
|
||||
|
||||
#define EI_NIDENT 16
|
||||
|
||||
#define SHN_UNDEF 0
|
||||
#define SHN_ABS 0xfff1
|
||||
|
||||
enum DynamicTags
|
||||
{
|
||||
DT_NULL = 0,
|
||||
DT_NEEDED = 1,
|
||||
DT_PLTRELSZ = 2,
|
||||
DT_PLTGOT = 3,
|
||||
DT_HASH = 4,
|
||||
DT_STRTAB = 5,
|
||||
DT_SYMTAB = 6,
|
||||
DT_RELA = 7,
|
||||
DT_RELASZ = 8,
|
||||
DT_RELAENT = 9,
|
||||
DT_STRSZ = 10,
|
||||
DT_SYMENT = 11,
|
||||
DT_INIT = 12,
|
||||
DT_FINI = 13,
|
||||
DT_SONAME = 14,
|
||||
DT_RPATH = 15,
|
||||
DT_SYMBOLIC = 16,
|
||||
DT_REL = 17,
|
||||
DT_RELSZ = 18,
|
||||
DT_RELENT = 19,
|
||||
DT_PLTREL = 20,
|
||||
DT_DEBUG = 21,
|
||||
DT_TEXTREL = 22,
|
||||
DT_JMPREL = 23,
|
||||
DT_BIND_NOW = 24,
|
||||
DT_INIT_ARRAY = 25,
|
||||
DT_FINI_ARRAY = 26,
|
||||
DT_INIT_ARRAYSZ = 27,
|
||||
DT_FINI_ARRAYSZ = 28,
|
||||
DT_RUNPATH = 29,
|
||||
DT_FLAGS = 30,
|
||||
DT_ENCODING = 32,
|
||||
DT_PREINIT_ARRAY = 32,
|
||||
DT_PREINIT_ARRAYSZ = 33,
|
||||
DT_LOOS = 0x6000000d,
|
||||
DT_SUNW_RTLDINF = 0x6000000e,
|
||||
DT_HIOS = 0x6ffff000,
|
||||
DT_VALRNGLO = 0x6ffffd00,
|
||||
DT_CHECKSUM = 0x6ffffdf8,
|
||||
DT_PLTPADSZ = 0x6ffffdf9,
|
||||
DT_MOVEENT = 0x6ffffdfa,
|
||||
DT_MOVESZ = 0x6ffffdfb,
|
||||
DT_FEATURE_1 = 0x6ffffdfc,
|
||||
DT_POSFLAG_1 = 0x6ffffdfd,
|
||||
DT_SYMINSZ = 0x6ffffdfe,
|
||||
DT_SYMINENT = 0x6ffffdff,
|
||||
DT_VALRNGHI = 0x6ffffdff,
|
||||
DT_ADDRRNGLO = 0x6ffffe00,
|
||||
DT_CONFIG = 0x6ffffefa,
|
||||
DT_DEPAUDIT = 0x6ffffefb,
|
||||
DT_AUDIT = 0x6ffffefc,
|
||||
DT_PLTPAD = 0x6ffffefd,
|
||||
DT_MOVETAB = 0x6ffffefe,
|
||||
DT_SYMINFO = 0x6ffffeff,
|
||||
DT_ADDRRNGHI = 0x6ffffeff,
|
||||
DT_RELACOUNT = 0x6ffffff9,
|
||||
DT_RELCOUNT = 0x6ffffffa,
|
||||
DT_FLAGS_1 = 0x6ffffffb,
|
||||
DT_VERDEF = 0x6ffffffc,
|
||||
DT_VERDEFNUM = 0x6ffffffd,
|
||||
DT_VERNEED = 0x6ffffffe,
|
||||
DT_VERNEEDNUM = 0x6fffffff,
|
||||
DT_LOPROC = 0x70000000,
|
||||
DT_SPARC_REGISTER = 0x70000001,
|
||||
DT_AUXILIARY = 0x7ffffffd,
|
||||
DT_USED = 0x7ffffffe,
|
||||
DT_FILTER = 0x7fffffff,
|
||||
DT_HIPROC = 0x7fffffff
|
||||
};
|
||||
|
||||
enum SegmentTypes
|
||||
{
|
||||
PT_NULL = 0,
|
||||
PT_LOAD = 1,
|
||||
PT_DYNAMIC = 2,
|
||||
PT_INTERP = 3,
|
||||
PT_NOTE = 4,
|
||||
PT_SHLIB = 5,
|
||||
PT_PHDR = 6,
|
||||
PT_TLS = 7,
|
||||
PT_LOSUNW = 0x6ffffffa,
|
||||
PT_SUNWBSS = 0x6ffffffb,
|
||||
PT_SUNWSTACK = 0x6ffffffa,
|
||||
PT_HISUNW = 0x6fffffff,
|
||||
PT_LOPROC = 0x70000000,
|
||||
PT_HIPROC = 0x7fffffff
|
||||
};
|
||||
|
||||
enum RtT_Types
|
||||
{
|
||||
R_386_NONE = 0,
|
||||
R_386_32 = 1,
|
||||
R_386_PC32 = 2,
|
||||
|
||||
R_X86_64_NONE = 0,
|
||||
R_X86_64_64 = 1,
|
||||
R_X86_64_PC32 = 2,
|
||||
R_X86_64_GOT32 = 3,
|
||||
R_X86_64_PLT32 = 4,
|
||||
R_X86_64_COPY = 5,
|
||||
R_X86_64_GLOB_DAT = 6,
|
||||
R_X86_64_JUMP_SLOT = 7,
|
||||
R_X86_64_RELATIVE = 8,
|
||||
R_X86_64_GOTPCREL = 9,
|
||||
R_X86_64_32 = 10,
|
||||
R_X86_64_32S = 11,
|
||||
R_X86_64_16 = 12,
|
||||
};
|
||||
|
||||
typedef struct elf32_hdr
|
||||
{
|
||||
unsigned char e_ident[EI_NIDENT];
|
||||
Elf32_Half e_type;
|
||||
Elf32_Half e_machine;
|
||||
Elf32_Word e_version;
|
||||
Elf32_Addr e_entry;
|
||||
Elf32_Off e_phoff;
|
||||
Elf32_Off e_shoff;
|
||||
Elf32_Word e_flags;
|
||||
Elf32_Half e_ehsize;
|
||||
Elf32_Half e_phentsize;
|
||||
Elf32_Half e_phnum;
|
||||
Elf32_Half e_shentsize;
|
||||
Elf32_Half e_shnum;
|
||||
Elf32_Half e_shstrndx;
|
||||
} Elf32_Ehdr;
|
||||
|
||||
typedef struct elf64_hdr
|
||||
{
|
||||
unsigned char e_ident[EI_NIDENT];
|
||||
Elf64_Half e_type;
|
||||
Elf64_Half e_machine;
|
||||
Elf64_Word e_version;
|
||||
Elf64_Addr e_entry;
|
||||
Elf64_Off e_phoff;
|
||||
Elf64_Off e_shoff;
|
||||
Elf64_Word e_flags;
|
||||
Elf64_Half e_ehsize;
|
||||
Elf64_Half e_phentsize;
|
||||
Elf64_Half e_phnum;
|
||||
Elf64_Half e_shentsize;
|
||||
Elf64_Half e_shnum;
|
||||
Elf64_Half e_shstrndx;
|
||||
} Elf64_Ehdr;
|
||||
|
||||
typedef struct elf32_shdr
|
||||
{
|
||||
Elf32_Word sh_name;
|
||||
Elf32_Word sh_type;
|
||||
Elf32_Word sh_flags;
|
||||
Elf32_Addr sh_addr;
|
||||
Elf32_Off sh_offset;
|
||||
Elf32_Word sh_size;
|
||||
Elf32_Word sh_link;
|
||||
Elf32_Word sh_info;
|
||||
Elf32_Word sh_addralign;
|
||||
Elf32_Word sh_entsize;
|
||||
} Elf32_Shdr;
|
||||
|
||||
typedef struct elf64_shdr
|
||||
{
|
||||
Elf64_Word sh_name;
|
||||
Elf64_Word sh_type;
|
||||
Elf64_Xword sh_flags;
|
||||
Elf64_Addr sh_addr;
|
||||
Elf64_Off sh_offset;
|
||||
Elf64_Xword sh_size;
|
||||
Elf64_Word sh_link;
|
||||
Elf64_Word sh_info;
|
||||
Elf64_Xword sh_addralign;
|
||||
Elf64_Xword sh_entsize;
|
||||
} Elf64_Shdr;
|
||||
|
||||
struct Elf32_Dyn
|
||||
{
|
||||
Elf32_Sword d_tag;
|
||||
union
|
||||
{
|
||||
Elf32_Word d_val;
|
||||
Elf32_Addr d_ptr;
|
||||
} d_un;
|
||||
};
|
||||
|
||||
struct Elf64_Dyn
|
||||
{
|
||||
Elf64_Sxword d_tag;
|
||||
union
|
||||
{
|
||||
Elf64_Xword d_val;
|
||||
Elf64_Addr d_ptr;
|
||||
} d_un;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Elf64_Word p_type;
|
||||
Elf64_Word p_flags;
|
||||
Elf64_Off p_offset;
|
||||
Elf64_Addr p_vaddr;
|
||||
Elf64_Addr p_paddr;
|
||||
Elf64_Xword p_filesz;
|
||||
Elf64_Xword p_memsz;
|
||||
Elf64_Xword p_align;
|
||||
} Elf64_Phdr;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Elf64_Addr r_offset;
|
||||
Elf64_Xword r_info;
|
||||
Elf64_Sxword r_addend;
|
||||
} Elf64_Rela;
|
||||
|
||||
typedef struct elf64_sym
|
||||
{
|
||||
Elf64_Word st_name;
|
||||
unsigned char st_info;
|
||||
unsigned char st_other;
|
||||
Elf64_Half st_shndx;
|
||||
Elf64_Addr st_value;
|
||||
Elf64_Xword st_size;
|
||||
} Elf64_Sym;
|
||||
|
||||
#endif // !__FENNIX_LIB_ELF_LAZY_RESOLVE_H__
|
@ -1,227 +0,0 @@
|
||||
#include "fcts.h"
|
||||
|
||||
#include "../../../Kernel/syscalls.h"
|
||||
#include "../../../Kernel/ipc.h"
|
||||
|
||||
uintptr_t RequestPages(size_t Count)
|
||||
{
|
||||
return syscall6(sc_mmap, NULL, Count * 0x1000,
|
||||
sc_PROT_READ | sc_PROT_WRITE,
|
||||
sc_MAP_ANONYMOUS | sc_MAP_PRIVATE,
|
||||
0, 0);
|
||||
}
|
||||
|
||||
int FreePages(uintptr_t Address, size_t Count)
|
||||
{
|
||||
return syscall2(sc_munmap, Address, Count * 0x1000);
|
||||
}
|
||||
|
||||
int abs(int i) { return i < 0 ? -i : i; }
|
||||
|
||||
void swap(char *x, char *y)
|
||||
{
|
||||
char t = *x;
|
||||
*x = *y;
|
||||
*y = t;
|
||||
}
|
||||
|
||||
char *reverse(char *Buffer, int i, int j)
|
||||
{
|
||||
while (i < j)
|
||||
swap(&Buffer[i++], &Buffer[j--]);
|
||||
return Buffer;
|
||||
}
|
||||
|
||||
char *ltoa(long Value, char *Buffer, int Base)
|
||||
{
|
||||
if (Base < 2 || Base > 32)
|
||||
return Buffer;
|
||||
|
||||
long n = (long)abs((int)Value);
|
||||
int i = 0;
|
||||
|
||||
while (n)
|
||||
{
|
||||
int r = n % Base;
|
||||
if (r >= 10)
|
||||
Buffer[i++] = 65 + (r - 10);
|
||||
else
|
||||
Buffer[i++] = 48 + r;
|
||||
n = n / Base;
|
||||
}
|
||||
|
||||
if (i == 0)
|
||||
Buffer[i++] = '0';
|
||||
|
||||
if (Value < 0 && Base == 10)
|
||||
Buffer[i++] = '-';
|
||||
|
||||
Buffer[i] = '\0';
|
||||
return reverse(Buffer, 0, i - 1);
|
||||
}
|
||||
|
||||
void PutCharToKernelConsole(char c)
|
||||
{
|
||||
__asm__ __volatile__("syscall"
|
||||
:
|
||||
: "a"(1), "D"(c), "S"(0)
|
||||
: "rcx", "r11", "memory");
|
||||
}
|
||||
|
||||
void Print__(char *String)
|
||||
{
|
||||
for (short i = 0; String[i] != '\0'; i++)
|
||||
PutCharToKernelConsole(String[i]);
|
||||
}
|
||||
|
||||
void PrintNL__(char *String)
|
||||
{
|
||||
Print__(String);
|
||||
Print__("\n");
|
||||
}
|
||||
|
||||
void *memcpy(void *dest, const void *src, size_t n)
|
||||
{
|
||||
uint8_t *d = dest;
|
||||
const uint8_t *s = src;
|
||||
while (n--)
|
||||
*d++ = *s++;
|
||||
return dest;
|
||||
}
|
||||
|
||||
void *memset(void *s, int c, size_t n)
|
||||
{
|
||||
uint8_t *p = s;
|
||||
while (n--)
|
||||
*p++ = c;
|
||||
}
|
||||
|
||||
int strcmp(const char *l, const char *r)
|
||||
{
|
||||
for (; *l == *r && *l; l++, r++)
|
||||
;
|
||||
return *(unsigned char *)l - *(unsigned char *)r;
|
||||
}
|
||||
|
||||
struct Elf64_Dyn ELFGetDynamicTag(char *Path, enum DynamicTags Tag)
|
||||
{
|
||||
int fd = syscall2(sc_open, Path, (long)"r");
|
||||
if (fd < 0)
|
||||
syscall1(sc_exit, -0xF17E);
|
||||
|
||||
Elf64_Ehdr ELFHeader;
|
||||
syscall3(sc_read, fd, &ELFHeader, sizeof(Elf64_Ehdr));
|
||||
|
||||
Elf64_Phdr ItrProgramHeader;
|
||||
for (Elf64_Half i = 0; i < ELFHeader.e_phnum; i++)
|
||||
{
|
||||
// memcpy(&ItrProgramHeader, (uint8_t *)ElfFile + ELFHeader.e_phoff + ELFHeader.e_phentsize * i, sizeof(Elf64_Phdr));
|
||||
syscall3(sc_lseek, fd, ELFHeader.e_phoff + ELFHeader.e_phentsize * i, sc_SEEK_SET);
|
||||
syscall3(sc_read, fd, &ItrProgramHeader, sizeof(Elf64_Phdr));
|
||||
if (ItrProgramHeader.p_type == PT_DYNAMIC)
|
||||
{
|
||||
struct Elf64_Dyn Dynamic; // = (struct Elf64_Dyn *)((uint8_t *)ElfFile + ItrProgramHeader.p_offset);
|
||||
syscall3(sc_lseek, fd, ItrProgramHeader.p_offset, sc_SEEK_SET);
|
||||
syscall3(sc_read, fd, &Dynamic, ItrProgramHeader.p_filesz);
|
||||
for (size_t i = 0; i < ItrProgramHeader.p_filesz / sizeof(struct Elf64_Dyn); i++)
|
||||
{
|
||||
if (Dynamic.d_tag == Tag || Dynamic.d_tag == DT_NULL)
|
||||
{
|
||||
syscall1(sc_close, fd);
|
||||
return Dynamic;
|
||||
}
|
||||
|
||||
syscall3(sc_lseek, fd, ItrProgramHeader.p_offset + (i + 1) * sizeof(struct Elf64_Dyn), sc_SEEK_SET);
|
||||
syscall3(sc_read, fd, &Dynamic, sizeof(struct Elf64_Dyn));
|
||||
}
|
||||
}
|
||||
}
|
||||
syscall1(sc_close, fd);
|
||||
return (struct Elf64_Dyn){0};
|
||||
}
|
||||
|
||||
Elf64_Shdr *GetELFSheader(Elf64_Ehdr *Header)
|
||||
{
|
||||
Elf64_Off SheaderOffset = Header->e_shoff;
|
||||
return (Elf64_Shdr *)((uintptr_t)Header + SheaderOffset);
|
||||
}
|
||||
|
||||
Elf64_Shdr *GetELFSection(Elf64_Ehdr *Header, uint64_t Index)
|
||||
{
|
||||
Elf64_Shdr *Sheader = GetELFSheader(Header);
|
||||
return &Sheader[Index];
|
||||
}
|
||||
|
||||
char *GetELFStringTable(Elf64_Ehdr *Header)
|
||||
{
|
||||
if (Header->e_shstrndx == SHN_UNDEF)
|
||||
return NULL;
|
||||
return (char *)Header + GetELFSection(Header, Header->e_shstrndx)->sh_offset;
|
||||
}
|
||||
|
||||
Elf64_Sym ELFLookupSymbol(char *Path, const char *Name)
|
||||
{
|
||||
int fd = syscall2(sc_open, Path, (long)"r");
|
||||
if (fd < 0)
|
||||
syscall1(sc_exit, -0xF17E);
|
||||
|
||||
Elf64_Ehdr ELFHeader;
|
||||
syscall3(sc_read, fd, &ELFHeader, sizeof(Elf64_Ehdr));
|
||||
|
||||
Elf64_Shdr SymbolTable;
|
||||
Elf64_Shdr StringTable;
|
||||
Elf64_Sym Symbol;
|
||||
char *String = NULL;
|
||||
|
||||
for (Elf64_Half i = 0; i < ELFHeader.e_shnum; i++)
|
||||
{
|
||||
Elf64_Shdr shdr;
|
||||
syscall3(sc_lseek, fd,
|
||||
ELFHeader.e_shoff + ELFHeader.e_shentsize * i,
|
||||
sc_SEEK_SET);
|
||||
syscall3(sc_read, fd, &shdr, sizeof(Elf64_Shdr));
|
||||
|
||||
switch (shdr.sh_type)
|
||||
{
|
||||
case SHT_SYMTAB:
|
||||
{
|
||||
SymbolTable = shdr;
|
||||
syscall3(sc_lseek, fd,
|
||||
ELFHeader.e_shoff + ELFHeader.e_shentsize * shdr.sh_link,
|
||||
sc_SEEK_SET);
|
||||
syscall3(sc_read, fd, &StringTable, sizeof(Elf64_Shdr));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (SymbolTable.sh_size == 0 || StringTable.sh_size == 0)
|
||||
{
|
||||
syscall1(sc_close, fd);
|
||||
return (Elf64_Sym){0};
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < (SymbolTable.sh_size / sizeof(Elf64_Sym)); i++)
|
||||
{
|
||||
// Symbol = (Elf64_Sym *)((uintptr_t)Header + SymbolTable->sh_offset + (i * sizeof(Elf64_Sym)));
|
||||
// String = (char *)((uintptr_t)Header + StringTable->sh_offset + Symbol->st_name);
|
||||
syscall3(sc_lseek, fd, SymbolTable.sh_offset + (i * sizeof(Elf64_Sym)), sc_SEEK_SET);
|
||||
syscall3(sc_read, fd, &Symbol, sizeof(Elf64_Sym));
|
||||
|
||||
syscall3(sc_lseek, fd, StringTable.sh_offset + Symbol.st_name, sc_SEEK_SET);
|
||||
syscall3(sc_read, fd, &String, sizeof(char *));
|
||||
|
||||
if (strcmp(String, Name) == 0)
|
||||
{
|
||||
syscall1(sc_close, fd);
|
||||
return Symbol;
|
||||
}
|
||||
}
|
||||
|
||||
syscall1(sc_close, fd);
|
||||
return (Elf64_Sym){0};
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
#ifndef __FENNIX_LIBC_FUNCTIONS_H__
|
||||
#define __FENNIX_LIBC_FUNCTIONS_H__
|
||||
|
||||
#include <types.h>
|
||||
#include "elf.h"
|
||||
|
||||
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
||||
|
||||
uintptr_t RequestPages(size_t Count);
|
||||
int FreePages(uintptr_t Address, size_t Count);
|
||||
int IPC(int Command, int Type, int ID, int Flags, void *Buffer, size_t Size);
|
||||
uintptr_t KernelCTL(int Command, uint64_t Arg1, uint64_t Arg2, uint64_t Arg3, uint64_t Arg4);
|
||||
int abs(int i);
|
||||
void swap(char *x, char *y);
|
||||
char *reverse(char *Buffer, int i, int j);
|
||||
char *ltoa(long Value, char *Buffer, int Base);
|
||||
void PutCharToKernelConsole(char c);
|
||||
void Print__(char *String);
|
||||
void PrintNL__(char *String);
|
||||
void *memcpy(void *dest, const void *src, size_t n);
|
||||
void *memset(void *s, int c, size_t n);
|
||||
int strcmp(const char *l, const char *r);
|
||||
|
||||
struct Elf64_Dyn ELFGetDynamicTag(char *Path, enum DynamicTags Tag);
|
||||
Elf64_Shdr *GetELFSheader(Elf64_Ehdr *Header);
|
||||
Elf64_Shdr *GetELFSection(Elf64_Ehdr *Header, uint64_t Index);
|
||||
char *GetELFStringTable(Elf64_Ehdr *Header);
|
||||
Elf64_Sym ELFLookupSymbol(char *Path, const char *Name);
|
||||
|
||||
#endif // !__FENNIX_LIBC_FUNCTIONS_H__
|
@ -1,14 +0,0 @@
|
||||
#include "ld.h"
|
||||
|
||||
uint32_t ElfHash(const unsigned char *Name)
|
||||
{
|
||||
uint32_t i = 0, j;
|
||||
while (*Name)
|
||||
{
|
||||
i = (i << 4) + *Name++;
|
||||
if ((j = i & 0xF0000000) != 0)
|
||||
i ^= j >> 24;
|
||||
i &= ~j;
|
||||
}
|
||||
return i;
|
||||
}
|
@ -1,324 +0,0 @@
|
||||
#include "ld.h"
|
||||
#include "fcts.h"
|
||||
|
||||
#include "../../../Kernel/syscalls.h"
|
||||
#include "../../../Kernel/ipc.h"
|
||||
#include "elf.h"
|
||||
|
||||
#define Print(x) Print__(x)
|
||||
#define PrintNL(x) PrintNL__(x)
|
||||
|
||||
#if (1)
|
||||
#define PrintDbg(x) Print__(x)
|
||||
#define PrintDbgNL(x) PrintNL__(x)
|
||||
#define ltoaDbg(x, y, z) ltoa(x, y, z)
|
||||
#else
|
||||
#define PrintDbg(x)
|
||||
#define PrintDbgNL(x)
|
||||
#define ltoaDbg(x, y, z)
|
||||
#endif
|
||||
|
||||
struct InterpreterIPCDataLibrary
|
||||
{
|
||||
char Name[64];
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char Path[256];
|
||||
void *MemoryImage;
|
||||
struct InterpreterIPCDataLibrary Libraries[64];
|
||||
} InterpreterIPCData;
|
||||
|
||||
struct LibsCollection
|
||||
{
|
||||
char ParentName[32];
|
||||
char LibraryName[32];
|
||||
uintptr_t ParentMemoryImage;
|
||||
uintptr_t LibraryMemoryImage;
|
||||
struct LibsCollection *Next;
|
||||
char Valid;
|
||||
};
|
||||
|
||||
static char ParentPath[256];
|
||||
static char Lock = 0;
|
||||
|
||||
__attribute__((naked, used, no_stack_protector)) void ELF_LAZY_RESOLVE_STUB()
|
||||
{
|
||||
while (Lock == 1)
|
||||
;
|
||||
__asm__ __volatile__("mfence\n");
|
||||
Lock = 1;
|
||||
__asm__ __volatile__("pop %r11\n"
|
||||
"pop %r10\n"
|
||||
|
||||
"push %rdi\n"
|
||||
"push %rsi\n"
|
||||
"push %rdx\n"
|
||||
"push %rcx\n"
|
||||
"push %r8\n"
|
||||
"push %r9\n"
|
||||
|
||||
"mov %r11, %rdi\n" // Move the first argument to rdi (libs collection)
|
||||
"mov %r10, %rsi\n" // Move the second argument to rsi (rel index)
|
||||
|
||||
"call ELF_LAZY_RESOLVE_MAIN\n"
|
||||
|
||||
"mov %rax, %r11\n" // Move the return value to r11
|
||||
|
||||
"pop %r9\n"
|
||||
"pop %r8\n"
|
||||
"pop %rcx\n"
|
||||
"pop %rdx\n"
|
||||
"pop %rsi\n"
|
||||
"pop %rdi\n"
|
||||
|
||||
"jmp *%r11\n"); // Jump to the return value
|
||||
}
|
||||
|
||||
void (*ELF_LAZY_RESOLVE_MAIN(struct LibsCollection *Info, long RelIndex))()
|
||||
{
|
||||
if (!Info)
|
||||
goto FailEnd;
|
||||
|
||||
char DbgBuff[32];
|
||||
char LibraryPathBuffer[256];
|
||||
|
||||
struct LibsCollection *CurLib = Info;
|
||||
PrintDbgNL("_______");
|
||||
/* The last entry is the null entry (Valid == false)
|
||||
which determines the end of the list. */
|
||||
while (CurLib->Valid)
|
||||
{
|
||||
PrintDbg("-- ");
|
||||
PrintDbg(LibraryPathBuffer);
|
||||
PrintDbg(" ");
|
||||
ltoaDbg(RelIndex, DbgBuff, 10);
|
||||
PrintDbg(DbgBuff);
|
||||
PrintDbgNL(" --");
|
||||
uintptr_t lib_BaseAddress = __UINTPTR_MAX__;
|
||||
uintptr_t app_BaseAddress = __UINTPTR_MAX__;
|
||||
|
||||
Elf64_Ehdr lib_Header;
|
||||
Elf64_Ehdr app_Header;
|
||||
|
||||
int fd_lib = syscall2(sc_open, LibraryPathBuffer, "r");
|
||||
int fd_app = syscall2(sc_open, ParentPath, "r");
|
||||
|
||||
if (fd_lib < 0)
|
||||
{
|
||||
PrintNL("Failed to open library");
|
||||
goto RetryNextLib;
|
||||
}
|
||||
|
||||
if (fd_app < 0)
|
||||
{
|
||||
PrintNL("Failed to open application");
|
||||
goto RetryNextLib;
|
||||
}
|
||||
|
||||
syscall3(sc_read, fd_lib, &lib_Header, sizeof(Elf64_Ehdr));
|
||||
syscall3(sc_read, fd_app, &app_Header, sizeof(Elf64_Ehdr));
|
||||
|
||||
Elf64_Phdr ItrProgramHeader;
|
||||
|
||||
for (Elf64_Half i = 0; i < lib_Header.e_phnum; i++)
|
||||
{
|
||||
syscall3(sc_lseek, fd_lib,
|
||||
lib_Header.e_phoff +
|
||||
lib_Header.e_phentsize * i,
|
||||
sc_SEEK_SET);
|
||||
|
||||
syscall3(sc_read, fd_lib, &ItrProgramHeader, sizeof(Elf64_Phdr));
|
||||
|
||||
lib_BaseAddress = MIN(lib_BaseAddress, ItrProgramHeader.p_vaddr);
|
||||
}
|
||||
|
||||
for (Elf64_Half i = 0; i < app_Header.e_phnum; i++)
|
||||
{
|
||||
syscall3(sc_lseek, fd_app,
|
||||
app_Header.e_phoff +
|
||||
app_Header.e_phentsize * i,
|
||||
sc_SEEK_SET);
|
||||
|
||||
syscall3(sc_read, fd_app, &ItrProgramHeader, sizeof(Elf64_Phdr));
|
||||
|
||||
app_BaseAddress = MIN(app_BaseAddress, ItrProgramHeader.p_vaddr);
|
||||
}
|
||||
|
||||
struct Elf64_Dyn lib_JmpRel = ELFGetDynamicTag(LibraryPathBuffer, DT_JMPREL);
|
||||
struct Elf64_Dyn lib_SymTab = ELFGetDynamicTag(LibraryPathBuffer, DT_SYMTAB);
|
||||
struct Elf64_Dyn lib_StrTab = ELFGetDynamicTag(LibraryPathBuffer, DT_STRTAB);
|
||||
|
||||
struct Elf64_Dyn app_JmpRel = ELFGetDynamicTag(ParentPath, DT_JMPREL);
|
||||
struct Elf64_Dyn app_SymTab = ELFGetDynamicTag(ParentPath, DT_SYMTAB);
|
||||
struct Elf64_Dyn app_StrTab = ELFGetDynamicTag(ParentPath, DT_STRTAB);
|
||||
|
||||
if (!lib_JmpRel.d_tag == 0)
|
||||
{
|
||||
PrintNL("No DT_JMPREL");
|
||||
// goto RetryNextLib;
|
||||
}
|
||||
else if (RelIndex >= lib_JmpRel.d_un.d_val /
|
||||
sizeof(Elf64_Rela))
|
||||
{
|
||||
PrintNL("RelIndex is greater than the number of relocations");
|
||||
goto RetryNextLib;
|
||||
}
|
||||
|
||||
if (!lib_SymTab.d_tag == 0)
|
||||
{
|
||||
PrintNL("No DT_SYMTAB");
|
||||
goto RetryNextLib;
|
||||
}
|
||||
|
||||
if (!lib_StrTab.d_tag == 0)
|
||||
{
|
||||
PrintNL("No DT_STRTAB");
|
||||
goto RetryNextLib;
|
||||
}
|
||||
|
||||
if (!lib_SymTab.d_tag == 0 &&
|
||||
!lib_StrTab.d_tag == 0)
|
||||
goto RetryNextLib;
|
||||
|
||||
Elf64_Rela *_lib_JmpRel = (Elf64_Rela *)(CurLib->LibraryMemoryImage + (lib_JmpRel.d_un.d_ptr - lib_BaseAddress));
|
||||
Elf64_Sym *_lib_SymTab = (Elf64_Sym *)(CurLib->LibraryMemoryImage + (lib_SymTab.d_un.d_ptr - lib_BaseAddress));
|
||||
|
||||
Elf64_Rela *_app_JmpRel = (Elf64_Rela *)(CurLib->ParentMemoryImage + (app_JmpRel.d_un.d_ptr - app_BaseAddress));
|
||||
Elf64_Sym *_app_SymTab = (Elf64_Sym *)(CurLib->ParentMemoryImage + (app_SymTab.d_un.d_ptr - app_BaseAddress));
|
||||
|
||||
char *lib_DynStr = (char *)(CurLib->LibraryMemoryImage + (lib_StrTab.d_un.d_ptr - lib_BaseAddress));
|
||||
char *app_DynStr = (char *)(CurLib->ParentMemoryImage + (app_StrTab.d_un.d_ptr - app_BaseAddress));
|
||||
|
||||
Elf64_Rela *Rel = _app_JmpRel + RelIndex;
|
||||
Elf64_Addr *GOTEntry = (Elf64_Addr *)(Rel->r_offset);
|
||||
|
||||
int RelType = ELF64_R_TYPE(Rel->r_info);
|
||||
|
||||
switch (RelType)
|
||||
{
|
||||
case R_X86_64_NONE:
|
||||
{
|
||||
PrintDbgNL("R_X86_64_NONE");
|
||||
if (*GOTEntry == 0)
|
||||
{
|
||||
PrintDbgNL("GOTEntry is 0");
|
||||
break;
|
||||
}
|
||||
Lock = 0;
|
||||
return (void (*)()) * GOTEntry;
|
||||
}
|
||||
case R_X86_64_JUMP_SLOT:
|
||||
{
|
||||
PrintDbgNL("R_X86_64_JUMP_SLOT");
|
||||
int SymIndex = ELF64_R_SYM(Rel->r_info);
|
||||
Elf64_Sym *Sym = _app_SymTab + SymIndex;
|
||||
|
||||
if (Sym->st_name)
|
||||
{
|
||||
char *SymName = app_DynStr + Sym->st_name;
|
||||
PrintDbg("SymName: ");
|
||||
PrintDbgNL(SymName);
|
||||
|
||||
Elf64_Sym LibSym = ELFLookupSymbol(ParentPath, SymName);
|
||||
|
||||
PrintDbg("LibSym: 0x");
|
||||
ltoaDbg((long)LibSym.st_size, DbgBuff, 16);
|
||||
PrintDbgNL(DbgBuff);
|
||||
|
||||
if (LibSym.st_value)
|
||||
{
|
||||
*GOTEntry = (Elf64_Addr)(CurLib->LibraryMemoryImage + LibSym.st_value);
|
||||
|
||||
ltoa(*GOTEntry, DbgBuff, 16);
|
||||
PrintDbg("*GOTEntry: 0x");
|
||||
PrintDbgNL(DbgBuff);
|
||||
|
||||
Lock = 0;
|
||||
return (void (*)()) * GOTEntry;
|
||||
}
|
||||
PrintDbgNL("Not found in lib");
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
ltoa(RelType, DbgBuff, 10);
|
||||
Print("RelType not supported ");
|
||||
PrintNL(DbgBuff);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
RetryNextLib:
|
||||
PrintDbgNL("Retrying next lib");
|
||||
CurLib = CurLib->Next;
|
||||
}
|
||||
|
||||
FailEnd:
|
||||
Lock = 0;
|
||||
__asm__ __volatile__("mfence\n");
|
||||
|
||||
Print("Symbol index ");
|
||||
ltoa(RelIndex, DbgBuff, 10);
|
||||
Print(DbgBuff);
|
||||
PrintNL(" not found");
|
||||
int ExitCode = 0x51801;
|
||||
syscall1(sc_exit, ExitCode);
|
||||
while (1) // Make sure we don't return
|
||||
;
|
||||
}
|
||||
|
||||
/* Preload */
|
||||
int ld_main()
|
||||
{
|
||||
/* Prevent race condition. */
|
||||
// uintptr_t KCTL_ret = KernelCTL(KCTL_IS_CRITICAL, 0, 0, 0, 0);
|
||||
// do
|
||||
// {
|
||||
// syscall1(sys_Sleep, 250);
|
||||
// KCTL_ret = KernelCTL(KCTL_IS_CRITICAL, 0, 0, 0, 0);
|
||||
// } while (KCTL_ret == false);
|
||||
|
||||
// if (KCTL_ret == false)
|
||||
// return -1;
|
||||
|
||||
/* Everything is ok, continue. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool ELFAddLazyResolverToGOT(void *MemoryImage, struct LibsCollection *Libs)
|
||||
{
|
||||
struct Elf64_Dyn Dyn = ELFGetDynamicTag(ParentPath, DT_PLTGOT);
|
||||
if (!Dyn.d_tag)
|
||||
return false;
|
||||
|
||||
Elf64_Addr *GOT = (Elf64_Addr *)Dyn.d_un.d_ptr;
|
||||
|
||||
GOT[1] = (uintptr_t)Libs;
|
||||
GOT[2] = (uintptr_t)ELF_LAZY_RESOLVE_STUB;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Actual load */
|
||||
int ld_load(int argc, char *argv[], char *envp[])
|
||||
{
|
||||
PrintDbgNL("Calling entry point");
|
||||
|
||||
// void *KP = syscall2(sc_open, ParentPath, (long)"r");
|
||||
// if (KP == NULL)
|
||||
// {
|
||||
// PrintNL("Failed to open file");
|
||||
// syscall1(sys_Exit, -0xF17E);
|
||||
// }
|
||||
|
||||
// Elf64_Ehdr ELFHeader;
|
||||
// syscall3(sc_read, KP, &ELFHeader, sizeof(Elf64_Ehdr));
|
||||
|
||||
// Elf64_Addr Entry = ELFHeader.e_entry;
|
||||
|
||||
// syscall1(sys_FileClose, KP);
|
||||
|
||||
// return ((int (*)(int, char *[], char *[]))Entry)(argc, argv, envp);
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
#ifndef __FENNIX_LIBC_LD_H__
|
||||
#define __FENNIX_LIBC_LD_H__
|
||||
|
||||
#include <types.h>
|
||||
|
||||
uint32_t ElfHash(const unsigned char *Name);
|
||||
|
||||
#endif // !__FENNIX_LIBC_LD_H__
|
@ -1,36 +0,0 @@
|
||||
void __attribute__((naked, used, no_stack_protector)) _start()
|
||||
{
|
||||
__asm__("movq $0, %rbp\n"
|
||||
"pushq %rbp\n"
|
||||
"pushq %rbp\n"
|
||||
"movq %rsp, %rbp\n"
|
||||
|
||||
"pushq %rcx\n"
|
||||
"pushq %rdx\n"
|
||||
"pushq %rsi\n"
|
||||
"pushq %rdi\n"
|
||||
|
||||
"call ld_main\n"
|
||||
"movl %eax, %edi\n" // Move return value to edi
|
||||
"cmp $0, %edi\n" // Check if return value is 0
|
||||
"jne _exit\n" // If not, jump to _exit
|
||||
|
||||
"popq %rdi\n"
|
||||
"popq %rsi\n"
|
||||
"popq %rdx\n"
|
||||
"popq %rcx\n"
|
||||
|
||||
"call ld_load\n"
|
||||
"movl %eax, %edi\n" // Move return value to edi
|
||||
"call _exit"); // Call _exit
|
||||
}
|
||||
|
||||
void _exit(int Code)
|
||||
{
|
||||
__asm__ __volatile__("syscall"
|
||||
:
|
||||
: "a"(0), "D"(Code)
|
||||
: "rcx", "r11", "memory");
|
||||
while (1)
|
||||
;
|
||||
}
|
@ -1,250 +0,0 @@
|
||||
|
||||
/* This function is a mess and needs to be cleaned up. */
|
||||
bool ELFDynamicReallocation(void *ElfFile, void *MemoryImage)
|
||||
{
|
||||
debug("ELF dynamic reallocation for image at %#lx.", ElfFile);
|
||||
|
||||
Elf64_Ehdr *ELFHeader = (Elf64_Ehdr *)ElfFile;
|
||||
uintptr_t BaseAddress = UINTPTR_MAX;
|
||||
size_t ElfAppSize = 0;
|
||||
Elf64_Phdr ItrPhdr;
|
||||
|
||||
for (Elf64_Half i = 0; i < ELFHeader->e_phnum; i++)
|
||||
{
|
||||
memcpy(&ItrPhdr,
|
||||
(uint8_t *)ElfFile + ELFHeader->e_phoff + ELFHeader->e_phentsize * i,
|
||||
sizeof(Elf64_Phdr));
|
||||
BaseAddress = MIN(BaseAddress, ItrPhdr.p_vaddr);
|
||||
}
|
||||
|
||||
for (Elf64_Half i = 0; i < ELFHeader->e_phnum; i++)
|
||||
{
|
||||
memcpy(&ItrPhdr,
|
||||
(uint8_t *)ElfFile + ELFHeader->e_phoff + ELFHeader->e_phentsize * i,
|
||||
sizeof(Elf64_Phdr));
|
||||
uintptr_t SegmentEnd = ItrPhdr.p_vaddr - BaseAddress + ItrPhdr.p_memsz;
|
||||
ElfAppSize = MAX(ElfAppSize, SegmentEnd);
|
||||
}
|
||||
|
||||
debug("BaseAddress: %#lx Size: %ld", BaseAddress, ElfAppSize);
|
||||
|
||||
Elf64_Dyn *_GOTEntry = (Elf64_Dyn *)ELFGetDynamicTag(ElfFile, DT_PLTGOT);
|
||||
Elf64_Dyn *_Rela = ELFGetDynamicTag(ElfFile, DT_RELA);
|
||||
Elf64_Dyn *_RelaEnt = ELFGetDynamicTag(ElfFile, DT_RELAENT);
|
||||
Elf64_Dyn *_JmpRel = ELFGetDynamicTag(ElfFile, DT_JMPREL);
|
||||
Elf64_Dyn *_SymTab = ELFGetDynamicTag(ElfFile, DT_SYMTAB);
|
||||
Elf64_Dyn *_StrTab = ELFGetDynamicTag(ElfFile, DT_STRTAB);
|
||||
Elf64_Dyn *RelaSize = ELFGetDynamicTag(ElfFile, DT_RELASZ);
|
||||
Elf64_Dyn *PltRelSize = ELFGetDynamicTag(ElfFile, DT_PLTRELSZ);
|
||||
|
||||
Elf64_Addr *GOTEntry = (Elf64_Addr *)((uintptr_t)(_GOTEntry->d_un.d_ptr - BaseAddress) + (uintptr_t)MemoryImage);
|
||||
Elf64_Dyn *Rela = (Elf64_Dyn *)((uintptr_t)(_Rela->d_un.d_ptr - BaseAddress) + (uintptr_t)MemoryImage);
|
||||
Elf64_Dyn *RelaEnt = (Elf64_Dyn *)((uintptr_t)(_RelaEnt->d_un.d_ptr - BaseAddress) + (uintptr_t)MemoryImage);
|
||||
Elf64_Dyn *JmpRel = (Elf64_Dyn *)((uintptr_t)(_JmpRel->d_un.d_ptr - BaseAddress) + (uintptr_t)MemoryImage);
|
||||
Elf64_Dyn *SymTab = (Elf64_Dyn *)((uintptr_t)(_SymTab->d_un.d_ptr - BaseAddress) + (uintptr_t)MemoryImage);
|
||||
Elf64_Dyn *StrTab = (Elf64_Dyn *)((uintptr_t)(_StrTab->d_un.d_ptr - BaseAddress) + (uintptr_t)MemoryImage);
|
||||
|
||||
debug("GOTEntry: %#lx [%#lx]", _GOTEntry, GOTEntry);
|
||||
debug("Rela: %#lx [%#lx]", _Rela, Rela);
|
||||
debug("RelaEnt: %#lx [%#lx]", _RelaEnt, RelaEnt);
|
||||
debug("JmpRel: %#lx [%#lx]", _JmpRel, JmpRel);
|
||||
debug("SymTab: %#lx [%#lx]", _SymTab, SymTab);
|
||||
debug("StrTab: %#lx [%#lx]", _StrTab, StrTab);
|
||||
if (RelaSize)
|
||||
debug("RelaSize: %ld", RelaSize->d_un.d_val);
|
||||
if (PltRelSize)
|
||||
debug("PltRelSize: %ld", PltRelSize->d_un.d_val);
|
||||
|
||||
Elf64_Xword PltRelSizeVal = PltRelSize ? PltRelSize->d_un.d_val : 0;
|
||||
Elf64_Xword RelaSizeVal = RelaSize ? RelaSize->d_un.d_val : 0;
|
||||
|
||||
Elf64_Xword PltRelSizeValCount = PltRelSizeVal / sizeof(Elf64_Rela);
|
||||
Elf64_Xword RelaSizeValCount = RelaSizeVal / sizeof(Elf64_Rela);
|
||||
|
||||
debug("PltRelSizeVal: %ld", PltRelSizeVal);
|
||||
debug("RelaSizeVal: %ld", RelaSizeVal);
|
||||
debug("PltRelSizeValCount: %ld", PltRelSizeValCount);
|
||||
debug("RelaSizeValCount: %ld", RelaSizeValCount);
|
||||
|
||||
for (Elf64_Xword i = 0; i < PltRelSizeValCount; i++)
|
||||
{
|
||||
Elf64_Rela *RelaF = (Elf64_Rela *)((uintptr_t)JmpRel + i);
|
||||
Elf64_Xword RelaType = ELF64_R_TYPE(RelaF->r_info);
|
||||
debug("Itr %ld Type %ld", i, RelaType);
|
||||
|
||||
switch (RelaType)
|
||||
{
|
||||
case R_X86_64_NONE:
|
||||
{
|
||||
debug("No relocation needed");
|
||||
break;
|
||||
}
|
||||
case R_X86_64_JUMP_SLOT:
|
||||
{
|
||||
debug("Relocation for jump slot");
|
||||
Elf64_Xword SymIndex = ELF64_R_SYM(RelaF->r_info);
|
||||
Elf64_Sym *Sym = (Elf64_Sym *)((uintptr_t)SymTab + SymIndex);
|
||||
char *SymName = (char *)((uintptr_t)StrTab + Sym->st_name);
|
||||
debug("Symbol %s at %#lx", SymName, Sym->st_value);
|
||||
|
||||
Elf64_Addr *GOTEntry = (Elf64_Addr *)RelaF->r_offset;
|
||||
if (Sym->st_value)
|
||||
{
|
||||
fixme("Not implemented");
|
||||
*GOTEntry = (Elf64_Addr)ElfFile + Sym->st_value;
|
||||
}
|
||||
// else
|
||||
// *GOTEntry = (Elf64_Addr)ElfLazyResolver;
|
||||
|
||||
// Elf64_Sym *Sym = (Elf64_Sym *)((uintptr_t)ElfFile + (uintptr_t)SymTab + ELF64_R_SYM(RelaF->r_info) * sizeof(Elf64_Sym));
|
||||
// char *SymName = (char *)((uintptr_t)ElfFile + (uintptr_t)StrTab + Sym->st_name);
|
||||
// void *SymAddr = (void *)Lib->Address + Sym->st_value;
|
||||
// debug("Symbol %s at %#lx", SymName, SymAddr);
|
||||
// *(void **)(RelaF->r_offset + (uintptr_t)ElfFile) = SymAddr;
|
||||
break;
|
||||
}
|
||||
case R_X86_64_RELATIVE:
|
||||
{
|
||||
debug("Relative relocation");
|
||||
uintptr_t *Ptr = (uintptr_t *)((uintptr_t)ElfFile + RelaF->r_offset);
|
||||
*Ptr = (uintptr_t)MemoryImage + RelaF->r_addend;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
fixme("RelaType %d", RelaType);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (Elf64_Xword i = 0; i < RelaSizeValCount; i++)
|
||||
{
|
||||
Elf64_Rela *RelaF = (Elf64_Rela *)((uintptr_t)ElfFile + (uintptr_t)Rela + i);
|
||||
Elf64_Xword RelaType = ELF64_R_TYPE(RelaF->r_info);
|
||||
debug("Itr %ld Type %ld", i, RelaType);
|
||||
|
||||
switch (RelaType)
|
||||
{
|
||||
case R_X86_64_NONE:
|
||||
{
|
||||
debug("No relocation needed");
|
||||
break;
|
||||
}
|
||||
case R_X86_64_64:
|
||||
{
|
||||
debug("64-bit relocation");
|
||||
Elf64_Xword SymIndex = ELF64_R_SYM(RelaF->r_info);
|
||||
Elf64_Sym *Sym = (Elf64_Sym *)((uintptr_t)ElfFile + (uintptr_t)SymTab + SymIndex);
|
||||
char *SymName = (char *)((uintptr_t)ElfFile + (uintptr_t)StrTab + Sym->st_name);
|
||||
debug("Symbol %s at %#lx", SymName, Sym->st_value);
|
||||
|
||||
uintptr_t *Ptr = (uintptr_t *)((uintptr_t)ElfFile + RelaF->r_offset);
|
||||
*Ptr = (uintptr_t)MemoryImage + Sym->st_value + RelaF->r_addend;
|
||||
break;
|
||||
}
|
||||
case R_X86_64_GLOB_DAT:
|
||||
{
|
||||
debug("Global data relocation");
|
||||
Elf64_Xword SymIndex = ELF64_R_SYM(RelaF->r_info);
|
||||
Elf64_Sym *Sym = (Elf64_Sym *)((uintptr_t)ElfFile + (uintptr_t)SymTab + SymIndex);
|
||||
char *SymName = (char *)((uintptr_t)ElfFile + (uintptr_t)StrTab + Sym->st_name);
|
||||
debug("Symbol %s at %#lx", SymName, Sym->st_value);
|
||||
|
||||
uintptr_t *Ptr = (uintptr_t *)((uintptr_t)ElfFile + RelaF->r_offset);
|
||||
*Ptr = (uintptr_t)MemoryImage + Sym->st_value;
|
||||
break;
|
||||
}
|
||||
case R_X86_64_RELATIVE:
|
||||
{
|
||||
debug("Relative relocation");
|
||||
Elf64_Xword SymIndex = ELF64_R_SYM(RelaF->r_info);
|
||||
Elf64_Sym *Sym = (Elf64_Sym *)((uintptr_t)ElfFile + (uintptr_t)SymTab + SymIndex);
|
||||
char *SymName = (char *)((uintptr_t)ElfFile + (uintptr_t)StrTab + Sym->st_name);
|
||||
debug("Symbol %s at %#lx", SymName, Sym->st_value);
|
||||
|
||||
uintptr_t *Ptr = (uintptr_t *)((uintptr_t)ElfFile + RelaF->r_offset);
|
||||
*Ptr = (uintptr_t)MemoryImage + RelaF->r_addend;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
fixme("RelaType %d", RelaType);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
ELFDynamicReallocation(ElfFile, MemoryImage);
|
||||
|
||||
LibAddressCollection *LibsForLazyResolver = (LibAddressCollection *)ELFBase.TmpMem->RequestPages(TO_PAGES(sizeof(LibAddressCollection)), true);
|
||||
memset(LibsForLazyResolver, 0, sizeof(LibAddressCollection));
|
||||
LibAddressCollection *LFLRTmp = LibsForLazyResolver;
|
||||
debug("LibsForLazyResolver: %#lx", LibsForLazyResolver);
|
||||
|
||||
if (NeededLibraries.size() > 0)
|
||||
{
|
||||
VirtualFileSystem::Node *ParentNode = ExFile->Node->Parent; // Working Directory
|
||||
if (ParentNode)
|
||||
{
|
||||
char *WorkingDirAbsolutePath = vfs->GetPathFromNode(ParentNode);
|
||||
debug("Working directory: \"%s\"", WorkingDirAbsolutePath);
|
||||
|
||||
int LibCount = 0;
|
||||
foreach (auto Library in NeededLibraries)
|
||||
{
|
||||
char LibPath[256];
|
||||
strcpy(LibPath, WorkingDirAbsolutePath);
|
||||
strcat(LibPath, "/");
|
||||
strcat(LibPath, Library);
|
||||
debug("Searching for \"%s\"...", LibPath);
|
||||
|
||||
bool AlreadyTried = false;
|
||||
|
||||
LibPathRetry:
|
||||
VirtualFileSystem::FILE *LibNode = vfs->Open(LibPath);
|
||||
|
||||
if (LibNode->Status != VirtualFileSystem::FileStatus::OK)
|
||||
{
|
||||
vfs->Close(LibNode);
|
||||
if (!AlreadyTried)
|
||||
{
|
||||
debug("Library \"%s\" not found, retrying... (%#x)", LibPath, LibNode->Status);
|
||||
memset(LibPath, 0, 256);
|
||||
strcpy(LibPath, "/lib/");
|
||||
strcat(LibPath, Library);
|
||||
AlreadyTried = true;
|
||||
goto LibPathRetry;
|
||||
}
|
||||
else
|
||||
warn("Failed to load library \"%s\" (%#x)", Library, LibNode->Status);
|
||||
}
|
||||
else
|
||||
{
|
||||
debug("Library found \"%s\" (%#x)", LibPath, LibNode->Status);
|
||||
SharedLibraries *sl = AddLibrary(Library, (void *)LibNode->Node->Address, LibNode->Node->Length);
|
||||
strcpy(LFLRTmp->Name, Library);
|
||||
LFLRTmp->ElfFile = (uintptr_t *)sl->Address;
|
||||
LFLRTmp->MemoryImage = (uintptr_t *)sl->MemoryImage;
|
||||
LFLRTmp->ParentElfFile = (uintptr_t *)ElfFile;
|
||||
LFLRTmp->ParentMemoryImage = (uintptr_t *)MemoryImage;
|
||||
LFLRTmp->Valid = true;
|
||||
debug("LIBRARY: %s, %#lx, %#lx", Library, LFLRTmp->ElfFile, LFLRTmp->MemoryImage);
|
||||
|
||||
LFLRTmp->Next = (LibAddressCollection *)ELFBase.TmpMem->RequestPages(TO_PAGES(sizeof(LibAddressCollection)), true);
|
||||
LFLRTmp = LFLRTmp->Next;
|
||||
memset(LFLRTmp, 0, sizeof(LibAddressCollection));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
error("Couldn't get the parent node from path %s", vfs->GetPathFromNode(ExFile->Node));
|
||||
}
|
||||
}
|
||||
|
||||
ELFAddLazyResolverToGOT(ElfFile, MemoryImage, LibsForLazyResolver);
|
||||
|
@ -1,11 +1,12 @@
|
||||
build:
|
||||
cp -r include/* ../out/include
|
||||
cp ../Kernel/include/interface/syscalls.h ../out/include/fennix/syscall.h
|
||||
cp -f $(WORKSPACE_DIR)/../Kernel/include/interface/errno.h $(CURDIR)/include/errno.h
|
||||
cp -f $(WORKSPACE_DIR)/../Kernel/include/interface/syscalls.h $(CURDIR)/include/fennix/syscalls.h
|
||||
cp -a $(CURDIR)/include/. $(WORKSPACE_DIR)/out/include
|
||||
make -C interpreter build
|
||||
make -C runtime build
|
||||
make -C src build
|
||||
make -C ElfInterpreter build
|
||||
|
||||
clean:
|
||||
make -C interpreter clean
|
||||
make -C runtime clean
|
||||
make -C src clean
|
||||
make -C ElfInterpreter clean
|
||||
|
39
Userspace/libc/STATUS.md
Normal file
39
Userspace/libc/STATUS.md
Normal file
@ -0,0 +1,39 @@
|
||||
# FENNIX C LIBRARY STATUS
|
||||
|
||||
[IEEE Std 1003.1™-2024 Edition](https://pubs.opengroup.org/onlinepubs/9799919799/)
|
||||
|
||||
| FILE | STATUS |
|
||||
|---------------|-----------|
|
||||
| | |
|
||||
| fennix/syscalls.h | PROVIDE |
|
||||
| sys/mman.h | TODO |
|
||||
| sys/stat.h | TODO |
|
||||
| sys/types.h | TODO |
|
||||
| sys/wait.h | TODO |
|
||||
| assert.h | COMPLETE|
|
||||
| dirent.h | TODO |
|
||||
| errno.h | PROVIDE |
|
||||
| fcntl.h | TODO |
|
||||
| float.h | TODO |
|
||||
| inttypes.h | TODO |
|
||||
| limits.h | TODO |
|
||||
| locale.h | TODO |
|
||||
| math.h | TODO |
|
||||
| pthread.h | TODO |
|
||||
| pwd.h | TODO |
|
||||
| sched.h | TODO |
|
||||
| signal.h | TODO |
|
||||
| stdarg.h | TODO |
|
||||
| stdbool.h | COMPLETE|
|
||||
| stddef.h | TODO |
|
||||
| stdint.h | TODO |
|
||||
| stdio.h | TODO |
|
||||
| stdlib.h | TODO |
|
||||
| string.h | TODO |
|
||||
| time.h | TODO |
|
||||
| unistd.h | TODO |
|
||||
|
||||
---
|
||||
|
||||
[functions](https://pubs.opengroup.org/onlinepubs/9799919799/functions/)
|
||||
[basedefs](https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/)
|
@ -1,4 +1,43 @@
|
||||
/*
|
||||
This file is part of Fennix C Library.
|
||||
|
||||
Fennix C Library is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _ASSERT_H
|
||||
#define _ASSERT_H
|
||||
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif // __cplusplus
|
||||
|
||||
void __assert_fail(const char *file, int line, const char *func) __attribute__((noreturn));
|
||||
|
||||
#ifdef NDEBUG
|
||||
#define assert(e) ((void)0)
|
||||
#else // NDEBUG
|
||||
#define assert(e) \
|
||||
do \
|
||||
{ \
|
||||
if (__builtin_expect(!!(!(e)), 0)) \
|
||||
__assert_fail(__FILE__, __LINE__, __func__); \
|
||||
} while (0)
|
||||
#endif // NDEBUG
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // !_ASSERT_H
|
||||
|
@ -1,69 +0,0 @@
|
||||
#ifndef __FENNIX_LIBC_AUX_H__
|
||||
#define __FENNIX_LIBC_AUX_H__
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#define AT_NULL 0
|
||||
#define AT_IGNORE 1
|
||||
#define AT_EXECFD 2
|
||||
#define AT_PHDR 3
|
||||
#define AT_PHENT 4
|
||||
#define AT_PHNUM 5
|
||||
#define AT_PAGESZ 6
|
||||
#define AT_BASE 7
|
||||
#define AT_FLAGS 8
|
||||
#define AT_ENTRY 9
|
||||
#define AT_NOTELF 10
|
||||
#define AT_UID 11
|
||||
#define AT_EUID 12
|
||||
#define AT_GID 13
|
||||
#define AT_EGID 14
|
||||
#define AT_PLATFORM 15
|
||||
#define AT_HWCAP 16
|
||||
#define AT_CLKTCK 17
|
||||
#define AT_SECURE 23
|
||||
#define AT_BASE_PLATFORM 24
|
||||
#define AT_RANDOM 25
|
||||
#define AT_HWCAP2 26
|
||||
#define AT_EXECFN 31
|
||||
#define AT_SYSINFO 32
|
||||
#define AT_SYSINFO_EHDR 33
|
||||
#define AT_L1I_CACHESHAPE 34
|
||||
#define AT_L1D_CACHESHAPE 35
|
||||
#define AT_L2_CACHESHAPE 36
|
||||
#define AT_L3_CACHESHAPE 37
|
||||
#define AT_L1I_CACHESIZE 40
|
||||
#define AT_L1I_CACHEGEOMETRY 41
|
||||
#define AT_L1D_CACHESIZE 42
|
||||
#define AT_L1D_CACHEGEOMETRY 43
|
||||
#define AT_L2_CACHESIZE 44
|
||||
#define AT_L2_CACHEGEOMETRY 45
|
||||
#define AT_L3_CACHESIZE 46
|
||||
#define AT_L3_CACHEGEOMETRY 47
|
||||
#define AT_MINSIGSTKSZ 51
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t a_type;
|
||||
union
|
||||
{
|
||||
uint32_t a_val;
|
||||
} a_un;
|
||||
} Elf32_auxv_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint64_t a_type;
|
||||
union
|
||||
{
|
||||
uint64_t a_val;
|
||||
} a_un;
|
||||
} Elf64_auxv_t;
|
||||
|
||||
#ifdef __LP64__
|
||||
#define Elf_auxv_t Elf64_auxv_t
|
||||
#else
|
||||
#define Elf_auxv_t Elf32_auxv_t
|
||||
#endif
|
||||
|
||||
#endif // !__FENNIX_LIBC_AUX_H__
|
@ -1,6 +0,0 @@
|
||||
#ifndef _BITS_TYPES_SIGSET_T_H
|
||||
#define _BITS_TYPES_SIGSET_T_H
|
||||
|
||||
typedef unsigned long sigset_t;
|
||||
|
||||
#endif // !_BITS_TYPES_SIGSET_T_H
|
@ -1,9 +0,0 @@
|
||||
#ifndef _BITS_TYPES_STRUCT_SCHED_PARAM_T_H
|
||||
#define _BITS_TYPES_STRUCT_SCHED_PARAM_T_H
|
||||
|
||||
struct sched_param
|
||||
{
|
||||
int sched_priority;
|
||||
};
|
||||
|
||||
#endif // !_BITS_TYPES_STRUCT_SCHED_PARAM_T_H
|
38
Userspace/libc/include/bits/types/timespec.h
Normal file
38
Userspace/libc/include/bits/types/timespec.h
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
This file is part of Fennix C Library.
|
||||
|
||||
Fennix C Library is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _TIMESPEC_DEFINED
|
||||
#define _TIMESPEC_DEFINED
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif // __cplusplus
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
typedef struct timespec
|
||||
{
|
||||
time_t tv_sec; /* Whole seconds. */
|
||||
long tv_nsec; /* Nanoseconds [0, 999999999]. */
|
||||
} timespec;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // !_TIMESPEC_DEFINED
|
@ -1,14 +0,0 @@
|
||||
#ifndef _BITS_WAITSTATUS_H
|
||||
#define _BITS_WAITSTATUS_H
|
||||
|
||||
#define __W_CONTINUED 0xFFFF
|
||||
|
||||
#define __WEXITSTATUS(status) (((status)&0xFF00) >> 8)
|
||||
#define __WTERMSIG(status) ((status)&0x7F)
|
||||
#define __WSTOPSIG(status) __WEXITSTATUS(status)
|
||||
#define __WIFEXITED(status) (__WTERMSIG(status) == 0)
|
||||
#define __WIFSIGNALED(status) (((signed char)(((status)&0x7F) + 1) >> 1) > 0)
|
||||
#define __WIFSTOPPED(status) (((status)&0xFF) == 0x7F)
|
||||
#define __WIFCONTINUED(status) ((status) == __W_CONTINUED)
|
||||
|
||||
#endif
|
@ -1,8 +0,0 @@
|
||||
#ifndef _CTYPE_H
|
||||
#define _CTYPE_H
|
||||
|
||||
int tolower(int c);
|
||||
int toupper(int c);
|
||||
int isspace(int c);
|
||||
|
||||
#endif // !_CTYPE_H
|
78
Userspace/libc/include/dirent.h
Normal file
78
Userspace/libc/include/dirent.h
Normal file
@ -0,0 +1,78 @@
|
||||
/*
|
||||
This file is part of Fennix C Library.
|
||||
|
||||
Fennix C Library is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _DIRENT_H
|
||||
#define _DIRENT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif // __cplusplus
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
typedef struct dirent
|
||||
{
|
||||
ino_t d_ino; /* File serial number. */
|
||||
char d_name[]; /* Filename string of entry. */
|
||||
} dirent;
|
||||
|
||||
typedef struct posix_dent
|
||||
{
|
||||
ino_t d_ino; /* File serial number. */
|
||||
reclen_t d_reclen; /* Length of this entry, including trailing padding if necessary. See posix_getdents(). */
|
||||
unsigned char d_type; /* File type or unknown-file-type indication. */
|
||||
char d_name[]; /* Filename string of this entry. */
|
||||
} posix_dent;
|
||||
|
||||
typedef struct DIR
|
||||
{
|
||||
int __fd;
|
||||
} DIR;
|
||||
|
||||
#define DT_BLK
|
||||
#define DT_CHR
|
||||
#define DT_DIR
|
||||
#define DT_FIFO
|
||||
#define DT_LNK
|
||||
#define DT_REG
|
||||
#define DT_SOCK
|
||||
#define DT_UNKNOWN
|
||||
|
||||
#define DT_MQ
|
||||
#define DT_SEM
|
||||
#define DT_SHM
|
||||
#define DT_TMO
|
||||
|
||||
int alphasort(const struct dirent **, const struct dirent **);
|
||||
int closedir(DIR *);
|
||||
int dirfd(DIR *);
|
||||
DIR *fdopendir(int);
|
||||
DIR *opendir(const char *);
|
||||
ssize_t posix_getdents(int, void *, size_t, int);
|
||||
struct dirent *readdir(DIR *);
|
||||
int readdir_r(DIR *restrict, struct dirent *restrict, struct dirent **restrict);
|
||||
void rewinddir(DIR *);
|
||||
int scandir(const char *, struct dirent ***, int (*)(const struct dirent *), int (*)(const struct dirent **, const struct dirent **));
|
||||
void seekdir(DIR *, long);
|
||||
long telldir(DIR *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // !_DIRENT_H
|
@ -1,11 +0,0 @@
|
||||
#ifndef __FENNIX_LIBC_DLFCN_H__
|
||||
#define __FENNIX_LIBC_DLFCN_H__
|
||||
|
||||
#include <types.h>
|
||||
|
||||
void *dlopen(const char *filename, int flags);
|
||||
void *dlsym(void *handle, const char *symbol);
|
||||
int dlclose(void *handle);
|
||||
char *dlerror(void);
|
||||
|
||||
#endif // !__FENNIX_LIBC_DLFCN_H__
|
@ -1,137 +1,605 @@
|
||||
#ifndef _ERRNO_H
|
||||
#define _ERRNO_H
|
||||
/*
|
||||
This file is part of Fennix Kernel.
|
||||
|
||||
#define EPERM 1 /* Operation not permitted */
|
||||
#define ENOENT 2 /* No such file or directory */
|
||||
#define ESRCH 3 /* No such process */
|
||||
#define EINTR 4 /* Interrupted system call */
|
||||
#define EIO 5 /* I/O error */
|
||||
#define ENXIO 6 /* No such device or address */
|
||||
#define E2BIG 7 /* Argument list too long */
|
||||
#define ENOEXEC 8 /* Exec format error */
|
||||
#define EBADF 9 /* Bad file number */
|
||||
#define ECHILD 10 /* No child processes */
|
||||
#define EAGAIN 11 /* Try again */
|
||||
#define ENOMEM 12 /* Out of memory */
|
||||
#define EACCES 13 /* Permission denied */
|
||||
#define EFAULT 14 /* Bad address */
|
||||
#define ENOTBLK 15 /* Block device required */
|
||||
#define EBUSY 16 /* Device or resource busy */
|
||||
#define EEXIST 17 /* File exists */
|
||||
#define EXDEV 18 /* Cross-device link */
|
||||
#define ENODEV 19 /* No such device */
|
||||
#define ENOTDIR 20 /* Not a directory */
|
||||
#define EISDIR 21 /* Is a directory */
|
||||
#define EINVAL 22 /* Invalid argument */
|
||||
#define ENFILE 23 /* File table overflow */
|
||||
#define EMFILE 24 /* Too many open files */
|
||||
#define ENOTTY 25 /* Not a typewriter */
|
||||
#define ETXTBSY 26 /* Text file busy */
|
||||
#define EFBIG 27 /* File too large */
|
||||
#define ENOSPC 28 /* No space left on device */
|
||||
#define ESPIPE 29 /* Illegal seek */
|
||||
#define EROFS 30 /* Read-only file system */
|
||||
#define EMLINK 31 /* Too many links */
|
||||
#define EPIPE 32 /* Broken pipe */
|
||||
#define EDOM 33 /* Math argument out of domain of func */
|
||||
#define ERANGE 34 /* Math result not representable */
|
||||
#define EDEADLK 35 /* Resource deadlock would occur */
|
||||
#define ENAMETOOLONG 36 /* File name too long */
|
||||
#define ENOLCK 37 /* No record locks available */
|
||||
#define ENOSYS 38 /* Function not implemented */
|
||||
#define ENOTEMPTY 39 /* Directory not empty */
|
||||
#define ELOOP 40 /* Too many symbolic links encountered */
|
||||
#define ENOMSG 42 /* No message of desired type */
|
||||
#define EIDRM 43 /* Identifier removed */
|
||||
#define ECHRNG 44 /* Channel number out of range */
|
||||
#define EL2NSYNC 45 /* Level 2 not synchronized */
|
||||
#define EL3HLT 46 /* Level 3 halted */
|
||||
#define EL3RST 47 /* Level 3 reset */
|
||||
#define ELNRNG 48 /* Link number out of range */
|
||||
#define EUNATCH 49 /* Protocol driver not attached */
|
||||
#define ENOCSI 50 /* No CSI structure available */
|
||||
#define EL2HLT 51 /* Level 2 halted */
|
||||
#define EBADE 52 /* Invalid exchange */
|
||||
#define EBADR 53 /* Invalid request descriptor */
|
||||
#define EXFULL 54 /* Exchange full */
|
||||
#define ENOANO 55 /* No anode */
|
||||
#define EBADRQC 56 /* Invalid request code */
|
||||
#define EBADSLT 57 /* Invalid slot */
|
||||
#define EBFONT 59 /* Bad font file format */
|
||||
#define ENOSTR 60 /* Device not a stream */
|
||||
#define ENODATA 61 /* No data available */
|
||||
#define ETIME 62 /* Timer expired */
|
||||
#define ENOSR 63 /* Out of streams resources */
|
||||
#define ENONET 64 /* Machine is not on the network */
|
||||
#define ENOPKG 65 /* Package not installed */
|
||||
#define EREMOTE 66 /* Object is remote */
|
||||
#define ENOLINK 67 /* Link has been severed */
|
||||
#define EADV 68 /* Advertise error */
|
||||
#define ESRMNT 69 /* Srmount error */
|
||||
#define ECOMM 70 /* Communication error on send */
|
||||
#define EPROTO 71 /* Protocol error */
|
||||
#define EMULTIHOP 72 /* Multihop attempted */
|
||||
#define EDOTDOT 73 /* RFS specific error */
|
||||
#define EBADMSG 74 /* Not a data message */
|
||||
#define EOVERFLOW 75 /* Value too large for defined data type */
|
||||
#define ENOTUNIQ 76 /* Name not unique on network */
|
||||
#define EBADFD 77 /* File descriptor in bad state */
|
||||
#define EREMCHG 78 /* Remote address changed */
|
||||
#define ELIBACC 79 /* Can not access a needed shared library */
|
||||
#define ELIBBAD 80 /* Accessing a corrupted shared library */
|
||||
#define ELIBSCN 81 /* .lib section in a.out corrupted */
|
||||
#define ELIBMAX 82 /* Attempting to link in too many shared libraries */
|
||||
#define ELIBEXEC 83 /* Cannot exec a shared library directly */
|
||||
#define EILSEQ 84 /* Illegal byte sequence */
|
||||
#define ERESTART 85 /* Interrupted system call should be restarted */
|
||||
#define ESTRPIPE 86 /* Streams pipe error */
|
||||
#define EUSERS 87 /* Too many users */
|
||||
#define ENOTSOCK 88 /* Socket operation on non-socket */
|
||||
#define EDESTADDRREQ 89 /* Destination address required */
|
||||
#define EMSGSIZE 90 /* Message too long */
|
||||
#define EPROTOTYPE 91 /* Protocol wrong type for socket */
|
||||
#define ENOPROTOOPT 92 /* Protocol not available */
|
||||
#define EPROTONOSUPPORT 93 /* Protocol not supported */
|
||||
#define ESOCKTNOSUPPORT 94 /* Socket type not supported */
|
||||
#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */
|
||||
#define EPFNOSUPPORT 96 /* Protocol family not supported */
|
||||
#define EAFNOSUPPORT 97 /* Address family not supported by protocol */
|
||||
#define EADDRINUSE 98 /* Address already in use */
|
||||
#define EADDRNOTAVAIL 99 /* Cannot assign requested address */
|
||||
#define ENETDOWN 100 /* Network is down */
|
||||
#define ENETUNREACH 101 /* Network is unreachable */
|
||||
#define ENETRESET 102 /* Network dropped connection because of reset */
|
||||
#define ECONNABORTED 103 /* Software caused connection abort */
|
||||
#define ECONNRESET 104 /* Connection reset by peer */
|
||||
#define ENOBUFS 105 /* No buffer space available */
|
||||
#define EISCONN 106 /* Transport endpoint is already connected */
|
||||
#define ENOTCONN 107 /* Transport endpoint is not connected */
|
||||
#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */
|
||||
#define ETOOMANYREFS 109 /* Too many references: cannot splice */
|
||||
#define ETIMEDOUT 110 /* Connection timed out */
|
||||
#define ECONNREFUSED 111 /* Connection refused */
|
||||
#define EHOSTDOWN 112 /* Host is down */
|
||||
#define EHOSTUNREACH 113 /* No route to host */
|
||||
#define EALREADY 114 /* Operation already in progress */
|
||||
#define EINPROGRESS 115 /* Operation now in progress */
|
||||
#define ESTALE 116 /* Stale NFS file handle */
|
||||
#define EUCLEAN 117 /* Structure needs cleaning */
|
||||
#define ENOTNAM 118 /* Not a XENIX named type file */
|
||||
#define ENAVAIL 119 /* No XENIX semaphores available */
|
||||
#define EISNAM 120 /* Is a named type file */
|
||||
#define EREMOTEIO 121 /* Remote I/O error */
|
||||
#define EDQUOT 122 /* Quota exceeded */
|
||||
#define ENOMEDIUM 123 /* No medium found */
|
||||
#define EMEDIUMTYPE 124 /* Wrong medium type */
|
||||
#define ECANCELED 125 /* Operation Canceled */
|
||||
#define ENOKEY 126 /* Required key not available */
|
||||
#define EKEYEXPIRED 127 /* Key has expired */
|
||||
#define EKEYREVOKED 128 /* Key has been revoked */
|
||||
#define EKEYREJECTED 129 /* Key was rejected by service */
|
||||
#define EOWNERDEAD 130 /* Owner died */
|
||||
#define ENOTRECOVERABLE 131 /* State not recoverable */
|
||||
Fennix Kernel is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Kernel is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __FENNIX_API_ERRNO_H__
|
||||
#define __FENNIX_API_ERRNO_H__
|
||||
|
||||
/**
|
||||
* The documentation for these error codes are from:
|
||||
* https://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html
|
||||
*
|
||||
* Full list:
|
||||
* https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/basedefs/errno.h.html
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
/**
|
||||
* No Error
|
||||
*/
|
||||
EOK = 0,
|
||||
|
||||
/**
|
||||
* Argument list too long. The sum of the number of bytes used by the
|
||||
* new process image's argument list and environment list is greater
|
||||
* than the system-imposed limit of {ARG_MAX} bytes.
|
||||
* or:
|
||||
* Lack of space in an output buffer.
|
||||
* or:
|
||||
* Argument is greater than the system-imposed maximum.
|
||||
*/
|
||||
E2BIG = 1,
|
||||
|
||||
/**
|
||||
* Permission denied. An attempt was made to access a file in a way
|
||||
* forbidden by its file access permissions.
|
||||
*/
|
||||
EACCES = 2,
|
||||
|
||||
/**
|
||||
* Address in use. The specified address is in use.
|
||||
*/
|
||||
EADDRINUSE = 3,
|
||||
|
||||
/**
|
||||
* Address not available. The specified address is not available from
|
||||
* the local system.
|
||||
*/
|
||||
EADDRNOTAVAIL = 4,
|
||||
|
||||
/**
|
||||
* Address family not supported. The implementation does not support
|
||||
* the specified address family, or the specified address is not a
|
||||
* valid address for the address family of the specified socket.
|
||||
*/
|
||||
EAFNOSUPPORT = 5,
|
||||
|
||||
/**
|
||||
* Resource temporarily unavailable. This is a temporary condition
|
||||
* and later calls to the same routine may complete normally.
|
||||
*/
|
||||
EAGAIN = 6,
|
||||
|
||||
/**
|
||||
* Connection already in progress. A connection request is already in
|
||||
* progress for the specified socket.
|
||||
*/
|
||||
EALREADY = 7,
|
||||
|
||||
/**
|
||||
* Bad file descriptor. A file descriptor argument is out of range,
|
||||
* refers to no open file, or a read (write) request is made to a
|
||||
* file that is only open for writing (reading).
|
||||
*/
|
||||
EBADF = 8,
|
||||
|
||||
/**
|
||||
* Bad message. During a read(), getmsg(), getpmsg(), or ioctl()
|
||||
* I_RECVFD request to a STREAMS device, a message arrived at the
|
||||
* head of the STREAM that is inappropriate for the function
|
||||
* receiving the message.
|
||||
* read()
|
||||
* Message waiting to be read on a STREAM is not a data message.
|
||||
* getmsg() or getpmsg()
|
||||
* A file descriptor was received instead of a control message.
|
||||
* ioctl()
|
||||
* Control or data information was received instead of a file
|
||||
* descriptor when I_RECVFD was specified.
|
||||
*/
|
||||
EBADMSG = 9,
|
||||
|
||||
/**
|
||||
* Resource busy. An attempt was made to make use of a system
|
||||
* resource that is not currently available, as it is being
|
||||
* used by another process in a manner that would have
|
||||
* conflicted with the request being made by this process.
|
||||
*/
|
||||
EBUSY = 10,
|
||||
|
||||
/**
|
||||
* Operation canceled. The associated asynchronous operation was
|
||||
* canceled before completion.
|
||||
*/
|
||||
ECANCELED = 11,
|
||||
|
||||
/**
|
||||
* No child process. A wait(), waitid(), or waitpid() function was
|
||||
* executed by a process that had no existing or unwaited-for
|
||||
* child process.
|
||||
*/
|
||||
ECHILD = 12,
|
||||
|
||||
/**
|
||||
* Connection aborted. The connection has been aborted.
|
||||
*/
|
||||
ECONNABORTED = 13,
|
||||
|
||||
/**
|
||||
* Connection refused. An attempt to connect to a socket was refused
|
||||
* because there was no process listening or because the queue of
|
||||
* connection requests was full and the underlying protocol does not
|
||||
* support retransmissions.
|
||||
*/
|
||||
ECONNREFUSED = 14,
|
||||
|
||||
/**
|
||||
* Connection reset. The connection was forcibly closed by the peer.
|
||||
*/
|
||||
ECONNRESET = 15,
|
||||
|
||||
/**
|
||||
* Resource deadlock would occur. An attempt was made to lock a system
|
||||
* resource that would have resulted in a deadlock situation.
|
||||
*/
|
||||
EDEADLK = 16,
|
||||
|
||||
/**
|
||||
* Destination address required. No bind address was established.
|
||||
*/
|
||||
EDESTADDRREQ = 17,
|
||||
|
||||
/**
|
||||
* Domain error. An input argument is outside the defined domain of the
|
||||
* mathematical function (defined in the ISO C standard).
|
||||
*/
|
||||
EDOM = 18,
|
||||
|
||||
/**
|
||||
* Reserved.
|
||||
*/
|
||||
EDQUOT = 19,
|
||||
|
||||
/**
|
||||
* File exists. An existing file was mentioned in an inappropriate
|
||||
* context; for example, as a new link name in the link() function.
|
||||
*/
|
||||
EEXIST = 20,
|
||||
|
||||
/**
|
||||
* Bad address. The system detected an invalid address in attempting
|
||||
* to use an argument of a call. The reliable detection of this error
|
||||
* cannot be guaranteed, and when not detected may result in the
|
||||
* generation of a signal, indicating an address violation, which is
|
||||
* sent to the process.
|
||||
*/
|
||||
EFAULT = 21,
|
||||
|
||||
/**
|
||||
* File too large. The size of a file would exceed the maximum file
|
||||
* size of an implementation or offset maximum established in the
|
||||
* corresponding file description.
|
||||
*/
|
||||
EFBIG = 22,
|
||||
|
||||
/**
|
||||
* Host is unreachable. The destination host cannot be reached
|
||||
* (probably because the host is down or a remote router cannot
|
||||
* reach it).
|
||||
*/
|
||||
EHOSTUNREACH = 23,
|
||||
|
||||
/**
|
||||
* Identifier removed. Returned during XSI interprocess communication
|
||||
* if an identifier has been removed from the system.
|
||||
*/
|
||||
EIDRM = 24,
|
||||
|
||||
/**
|
||||
* Illegal byte sequence. A wide-character code has been detected that
|
||||
* does not correspond to a valid character, or a byte sequence does
|
||||
* not form a valid wide-character code (defined in the ISO C standard).
|
||||
*/
|
||||
EILSEQ = 25,
|
||||
|
||||
/**
|
||||
* Operation in progress. This code is used to indicate that an
|
||||
* asynchronous operation has not yet completed.
|
||||
* or:
|
||||
* O_NONBLOCK is set for the socket file descriptor and the connection
|
||||
* cannot be immediately established.
|
||||
*/
|
||||
EINPROGRESS = 26,
|
||||
|
||||
/**
|
||||
* Interrupted function call. An asynchronous signal was caught by the
|
||||
* process during the execution of an interruptible function. If the
|
||||
* signal handler performs a normal return, the interrupted function
|
||||
* call may return this condition (see the Base Definitions volume
|
||||
* of POSIX.1-2017, <signal.h>).
|
||||
*/
|
||||
EINTR = 27,
|
||||
|
||||
/**
|
||||
* Invalid argument. Some invalid argument was supplied; for example,
|
||||
* specifying an undefined signal in a signal() function or a
|
||||
* kill() function.
|
||||
*/
|
||||
EINVAL = 28,
|
||||
|
||||
/**
|
||||
* Input/output error. Some physical input or output error has occurred.
|
||||
* This error may be reported on a subsequent operation on the same
|
||||
* file descriptor. Any other error-causing operation on the same file
|
||||
* descriptor may cause the [EIO] error indication to be lost.
|
||||
*/
|
||||
EIO = 29,
|
||||
|
||||
/**
|
||||
* Socket is connected. The specified socket is already connected.
|
||||
*/
|
||||
EISCONN = 30,
|
||||
|
||||
/**
|
||||
* Is a directory. An attempt was made to open a directory with write
|
||||
* mode specified.
|
||||
*/
|
||||
EISDIR = 31,
|
||||
|
||||
/**
|
||||
* Symbolic link loop. A loop exists in symbolic links encountered
|
||||
* during pathname resolution. This error may also be returned if
|
||||
* more than {SYMLOOP_MAX} symbolic links are encountered during
|
||||
* pathname resolution.
|
||||
*/
|
||||
ELOOP = 32,
|
||||
|
||||
/**
|
||||
* File descriptor value too large or too many open streams. An
|
||||
* attempt was made to open a file descriptor with a value greater
|
||||
* than or equal to {OPEN_MAX}, or an attempt was made to open more
|
||||
* than the maximum number of streams allowed in the process.
|
||||
*/
|
||||
EMFILE = 33,
|
||||
|
||||
/**
|
||||
* Too many links. An attempt was made to have the link count of a
|
||||
* single file exceed {LINK_MAX}.
|
||||
*/
|
||||
EMLINK = 34,
|
||||
|
||||
/**
|
||||
* Message too large. A message sent on a transport provider was
|
||||
* larger than an internal message buffer or some other network limit.
|
||||
* or:
|
||||
* Inappropriate message buffer length.
|
||||
*/
|
||||
EMSGSIZE = 35,
|
||||
|
||||
/**
|
||||
* Reserved.
|
||||
*/
|
||||
EMULTIHOP = 36,
|
||||
|
||||
/**
|
||||
* Filename too long. The length of a pathname exceeds {PATH_MAX} and
|
||||
* the implementation considers this to be an error, or a pathname
|
||||
* component is longer than {NAME_MAX}. This error may also occur
|
||||
* when pathname substitution, as a result of encountering a
|
||||
* symbolic link during pathname resolution, results in a pathname
|
||||
* string the size of which exceeds {PATH_MAX}.
|
||||
*/
|
||||
ENAMETOOLONG = 37,
|
||||
|
||||
/**
|
||||
* Network is down. The local network interface used to reach the
|
||||
* destination is down.
|
||||
*/
|
||||
ENETDOWN = 38,
|
||||
|
||||
/**
|
||||
* The connection was aborted by the network.
|
||||
*/
|
||||
ENETRESET = 39,
|
||||
|
||||
/**
|
||||
* Network unreachable. No route to the network is present.
|
||||
*/
|
||||
ENETUNREACH = 40,
|
||||
|
||||
/**
|
||||
* Too many files open in system. Too many files are currently open
|
||||
* in the system. The system has reached its predefined limit for
|
||||
* simultaneously open files and temporarily cannot accept requests
|
||||
* to open another one.
|
||||
*/
|
||||
ENFILE = 41,
|
||||
|
||||
/**
|
||||
* No buffer space available. Insufficient buffer resources were
|
||||
* available in the system to perform the socket operation.
|
||||
*/
|
||||
ENOBUFS = 42,
|
||||
|
||||
/**
|
||||
* No message available. No message is available on the STREAM head
|
||||
* read queue.
|
||||
*/
|
||||
ENODATA = 43,
|
||||
|
||||
/**
|
||||
* No such device. An attempt was made to apply an inappropriate
|
||||
* function to a device; for example, trying to read a write-only
|
||||
* device such as a printer.
|
||||
*/
|
||||
ENODEV = 44,
|
||||
|
||||
/**
|
||||
* No such file or directory. A component of a specified pathname
|
||||
* does not exist, or the pathname is an empty string.
|
||||
*/
|
||||
ENOENT = 45,
|
||||
|
||||
/**
|
||||
* Executable file format error. A request is made to execute a file
|
||||
* that, although it has appropriate privileges, is not in the
|
||||
* format required by the implementation for executable files.
|
||||
*/
|
||||
ENOEXEC = 46,
|
||||
|
||||
/**
|
||||
* No locks available. A system-imposed limit on the number of
|
||||
* simultaneous file and record locks has been reached and no more
|
||||
* are currently available.
|
||||
*/
|
||||
ENOLCK = 47,
|
||||
|
||||
/**
|
||||
* Reserved.
|
||||
*/
|
||||
ENOLINK = 48,
|
||||
|
||||
/**
|
||||
* Not enough space. The new process image requires more memory than
|
||||
* is allowed by the hardware or system-imposed memory management
|
||||
* constraints.
|
||||
*/
|
||||
ENOMEM = 49,
|
||||
|
||||
/**
|
||||
* No message of the desired type. The message queue does not contain
|
||||
* a message of the required type during XSI interprocess communication.
|
||||
*/
|
||||
ENOMSG = 50,
|
||||
|
||||
/**
|
||||
* Protocol not available. The protocol option specified to
|
||||
* setsockopt() is not supported by the implementation.
|
||||
*/
|
||||
ENOPROTOOPT = 51,
|
||||
|
||||
/**
|
||||
* No space left on a device. During the write() function on a
|
||||
* regular file or when extending a directory, there is no free
|
||||
* space left on the device.
|
||||
*/
|
||||
ENOSPC = 52,
|
||||
|
||||
/**
|
||||
* No STREAM resources. Insufficient STREAMS memory resources are
|
||||
* available to perform a STREAMS-related function. This is a
|
||||
* temporary condition; it may be recovered from if other
|
||||
* processes release resources.
|
||||
*/
|
||||
ENOSR = 53,
|
||||
|
||||
/**
|
||||
* Not a STREAM. A STREAM function was attempted on a file descriptor
|
||||
* that was not associated with a STREAMS device.
|
||||
*/
|
||||
ENOSTR = 54,
|
||||
|
||||
/**
|
||||
* Functionality not supported. An attempt was made to use optional
|
||||
* functionality that is not supported in this implementation.
|
||||
*/
|
||||
ENOSYS = 55,
|
||||
|
||||
/**
|
||||
* Socket not connected. The socket is not connected.
|
||||
*/
|
||||
ENOTCONN = 56,
|
||||
|
||||
/**
|
||||
* Not a directory. A component of the specified pathname exists, but
|
||||
* it is not a directory, when a directory was expected; or an
|
||||
* attempt was made to create a non-directory file, and the specified
|
||||
* pathname contains at least one non- \<slash\> character and ends
|
||||
* with one or more trailing \<slash\> characters.
|
||||
*/
|
||||
ENOTDIR = 57,
|
||||
|
||||
/**
|
||||
* Directory not empty. A directory other than an empty directory
|
||||
* was supplied when an empty directory was expected.
|
||||
*/
|
||||
ENOTEMPTY = 58,
|
||||
|
||||
/**
|
||||
* State not recoverable. The state protected by a robust mutex
|
||||
* is not recoverable.
|
||||
*/
|
||||
ENOTRECOVERABLE = 59,
|
||||
|
||||
/**
|
||||
* Not a socket. The file descriptor does not refer to a socket.
|
||||
*/
|
||||
ENOTSOCK = 60,
|
||||
|
||||
/**
|
||||
* Not supported. The implementation does not support the requested
|
||||
* feature or value.
|
||||
*/
|
||||
ENOTSUP = 61,
|
||||
|
||||
/**
|
||||
* Inappropriate I/O control operation. A control function has been
|
||||
* attempted for a file or special file for which the operation
|
||||
* is inappropriate.
|
||||
*/
|
||||
ENOTTY = 62,
|
||||
|
||||
/**
|
||||
* No such device or address. Input or output on a special file
|
||||
* refers to a device that does not exist, or makes a request
|
||||
* beyond the capabilities of the device. It may also occur when,
|
||||
* for example, a tape drive is not on-line.
|
||||
*/
|
||||
ENXIO = 63,
|
||||
|
||||
/**
|
||||
* Operation not supported on socket. The type of socket (address
|
||||
* family or protocol) does not support the requested operation.
|
||||
*/
|
||||
EOPNOTSUPP = 64,
|
||||
|
||||
/**
|
||||
* Value too large to be stored in data type. An operation was
|
||||
* attempted which would generate a value that is outside the
|
||||
* range of values that can be represented in the relevant data
|
||||
* type or that are allowed for a given data item.
|
||||
*/
|
||||
EOVERFLOW = 65,
|
||||
|
||||
/**
|
||||
* Previous owner died. The owner of a robust mutex terminated
|
||||
* while holding the mutex lock.
|
||||
*/
|
||||
EOWNERDEAD = 66,
|
||||
|
||||
/**
|
||||
* Operation not permitted. An attempt was made to perform an
|
||||
* operation limited to processes with appropriate privileges or
|
||||
* to the owner of a file or other resource.
|
||||
*/
|
||||
EPERM = 67,
|
||||
|
||||
/**
|
||||
* Broken pipe. A write was attempted on a socket, pipe, or FIFO
|
||||
* for which there is no process to read the data.
|
||||
*/
|
||||
EPIPE = 68,
|
||||
|
||||
/**
|
||||
* Protocol error. Some protocol error occurred. This error is
|
||||
* device-specific, but is generally not related to a
|
||||
* hardware failure.
|
||||
*/
|
||||
EPROTO = 69,
|
||||
|
||||
/**
|
||||
* Protocol not supported. The protocol is not supported by the
|
||||
* address family, or the protocol is not supported by
|
||||
* the implementation.
|
||||
*/
|
||||
EPROTONOSUPPORT = 70,
|
||||
|
||||
/**
|
||||
* Protocol wrong type for socket. The socket type is not
|
||||
* supported by the protocol.
|
||||
*/
|
||||
EPROTOTYPE = 71,
|
||||
|
||||
/**
|
||||
* Result too large or too small. The result of the function
|
||||
* is too large (overflow) or too small (underflow) to be
|
||||
* represented in the available space.
|
||||
*/
|
||||
ERANGE = 72,
|
||||
|
||||
/**
|
||||
* Read-only file system. An attempt was made to modify a file
|
||||
* or directory on a file system that is read-only.
|
||||
*/
|
||||
EROFS = 73,
|
||||
|
||||
/**
|
||||
* Invalid seek. An attempt was made to access the file offset
|
||||
* associated with a pipe or FIFO.
|
||||
*/
|
||||
ESPIPE = 74,
|
||||
|
||||
/**
|
||||
* No such process. No process can be found corresponding to that
|
||||
* specified by the given process ID.
|
||||
*/
|
||||
ESRCH = 75,
|
||||
|
||||
/**
|
||||
* Reserved.
|
||||
*/
|
||||
ESTALE = 76,
|
||||
|
||||
/**
|
||||
* STREAM ioctl() timeout. The timer set for a STREAMS ioctl() call
|
||||
* has expired. The cause of this error is device-specific and could
|
||||
* indicate either a hardware or software failure, or a timeout
|
||||
* value that is too short for the specific operation. The status
|
||||
* of the ioctl() operation is unspecified.
|
||||
*/
|
||||
ETIME = 77,
|
||||
|
||||
/**
|
||||
* Connection timed out. The connection to a remote machine has
|
||||
* timed out.
|
||||
* If the connection timed out during execution of the function that
|
||||
* reported this error (as opposed to timing out prior to the
|
||||
* function being called), it is unspecified whether the function
|
||||
* has completed some or all of the documented behavior associated
|
||||
* with a successful completion of the function.
|
||||
* or:
|
||||
* Operation timed out. The time limit associated with the operation
|
||||
* was exceeded before the operation completed.
|
||||
*/
|
||||
ETIMEDOUT = 78,
|
||||
|
||||
/**
|
||||
* Text file busy. An attempt was made to execute a pure-procedure
|
||||
* program that is currently open for writing, or an attempt has
|
||||
* been made to open for writing a pure-procedure program that
|
||||
* is being executed.
|
||||
*/
|
||||
ETXTBSY = 79,
|
||||
|
||||
/**
|
||||
* Operation would block. An operation on a socket marked as
|
||||
* non-blocking has encountered a situation such as no data available
|
||||
* that otherwise would have caused the function to suspend execution.
|
||||
*/
|
||||
EWOULDBLOCK = 80,
|
||||
|
||||
/**
|
||||
* Improper link. A link to a file on another file system was attempted.
|
||||
*/
|
||||
EXDEV = 81,
|
||||
|
||||
__ERRNO_MAX
|
||||
} KernelErrors;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
int *__errno_location(void) __attribute__((const));
|
||||
char *strerror(int errnum);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
extern int *__errno_location(void) __attribute__((const)) __attribute__ ((__nothrow__));
|
||||
#define errno (*__errno_location())
|
||||
|
||||
#endif
|
||||
#endif // !__FENNIX_API_ERRNO_H__
|
||||
|
@ -1,4 +1,108 @@
|
||||
#ifndef _FNCTL_H
|
||||
#define _FNCTL_H
|
||||
/*
|
||||
This file is part of Fennix C Library.
|
||||
|
||||
#endif // !_FNCTL_H
|
||||
Fennix C Library is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _FCNTL_H
|
||||
#define _FCNTL_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif // __cplusplus
|
||||
|
||||
typedef struct f_owner_ex
|
||||
{
|
||||
int type; /* Discriminator for pid. */
|
||||
pid_t pid; /* Process ID or process group ID. */
|
||||
} f_owner_ex;
|
||||
|
||||
typedef struct flock
|
||||
{
|
||||
short l_type; /* Type of lock; F_RDLCK, F_WRLCK, F_UNLCK. */
|
||||
short l_whence; /* Flag for starting offset. */
|
||||
off_t l_start; /* Relative offset in bytes. */
|
||||
off_t l_len; /* Size; if 0 then until EOF. */
|
||||
pid_t l_pid; /* For a process-owned file lock, ignored on input or the process ID of the owning process on output; for an OFD-owned file lock, zero on input or (pid_t)-1 on output. */
|
||||
} flock;
|
||||
|
||||
#define F_DUPFD
|
||||
#define F_DUPFD_CLOEXEC
|
||||
#define F_DUPFD_CLOFORK
|
||||
#define F_GETFD
|
||||
#define F_SETFD
|
||||
#define F_GETFL
|
||||
#define F_SETFL
|
||||
#define F_GETLK
|
||||
#define F_SETLK
|
||||
#define F_SETLKW
|
||||
#define F_OFD_GETLK
|
||||
#define F_OFD_SETLK
|
||||
#define F_OFD_SETLKW
|
||||
#define F_GETOWN
|
||||
#define F_GETOWN_EX
|
||||
#define F_SETOWN
|
||||
#define F_SETOWN_EX
|
||||
#define FD_CLOEXEC
|
||||
#define FD_CLOFORK
|
||||
#define F_RDLCK
|
||||
#define F_UNLCK
|
||||
#define F_WRLCK
|
||||
#define F_OWNER_PID
|
||||
#define F_OWNER_PGRP
|
||||
#define O_CLOEXEC 02000000
|
||||
#define O_CLOFORK
|
||||
#define O_CREAT 0100
|
||||
#define O_DIRECTORY
|
||||
#define O_EXCL 0200
|
||||
#define O_NOCTTY
|
||||
#define O_NOFOLLOW 0400000
|
||||
#define O_TRUNC 01000
|
||||
#define O_TTY_INIT
|
||||
#define O_APPEND 02000
|
||||
#define O_DSYNC
|
||||
#define O_NONBLOCK
|
||||
#define O_RSYNC
|
||||
#define O_SYNC
|
||||
#define O_ACCMODE
|
||||
#define O_EXEC
|
||||
#define O_RDONLY 00
|
||||
#define O_RDWR 02
|
||||
#define O_SEARCH
|
||||
#define O_WRONLY 01
|
||||
#define AT_FDCWD
|
||||
#define AT_EACCESS
|
||||
#define AT_SYMLINK_NOFOLLOW
|
||||
#define AT_SYMLINK_FOLLOW
|
||||
#define AT_REMOVEDIR
|
||||
#define POSIX_FADV_DONTNEED
|
||||
#define POSIX_FADV_NOREUSE
|
||||
#define POSIX_FADV_NORMAL
|
||||
#define POSIX_FADV_RANDOM
|
||||
#define POSIX_FADV_SEQUENTIAL
|
||||
#define POSIX_FADV_WILLNEED
|
||||
|
||||
int creat(const char *, mode_t);
|
||||
int fcntl(int, int, ...);
|
||||
int open(const char *, int, ...);
|
||||
int openat(int, const char *, int, ...);
|
||||
int posix_fadvise(int, off_t, off_t, int);
|
||||
int posix_fallocate(int, off_t, off_t);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // !_FCNTL_H
|
||||
|
@ -1,6 +0,0 @@
|
||||
#ifndef _FEATURES_H
|
||||
#define _FEATURES_H
|
||||
|
||||
#define __FENNIX_LIBC__ 1
|
||||
|
||||
#endif
|
1572
Userspace/libc/include/fennix/syscalls.h
Normal file
1572
Userspace/libc/include/fennix/syscalls.h
Normal file
File diff suppressed because it is too large
Load Diff
87
Userspace/libc/include/float.h
Normal file
87
Userspace/libc/include/float.h
Normal file
@ -0,0 +1,87 @@
|
||||
/*
|
||||
This file is part of Fennix C Library.
|
||||
|
||||
Fennix C Library is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _FLOAT_H
|
||||
#define _FLOAT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif // __cplusplus
|
||||
|
||||
#define INFINITY (__builtin_inff())
|
||||
#define NAN (__builtin_nanf(""))
|
||||
#define FLT_ROUNDS 1
|
||||
#define FLT_EVAL_METHOD __FLT_EVAL_METHOD__
|
||||
|
||||
#define FLT_HAS_SUBNORM __FLT_HAS_DENORM__
|
||||
#define DBL_HAS_SUBNORM __DBL_HAS_DENORM__
|
||||
#define LDBL_HAS_SUBNORM __LDBL_HAS_DENORM__
|
||||
|
||||
#define FLT_RADIX __FLT_RADIX__
|
||||
|
||||
#define FLT_MANT_DIG __FLT_MANT_DIG__
|
||||
#define DBL_MANT_DIG __DBL_MANT_DIG__
|
||||
#define LDBL_MANT_DIG __LDBL_MANT_DIG__
|
||||
|
||||
#define FLT_DECIMAL_DIG __FLT_DECIMAL_DIG__
|
||||
#define DBL_DECIMAL_DIG __DBL_DECIMAL_DIG__
|
||||
#define LDBL_DECIMAL_DIG __LDBL_DECIMAL_DIG__
|
||||
|
||||
#define DECIMAL_DIG __DECIMAL_DIG__
|
||||
|
||||
#define FLT_DIG __FLT_DIG__
|
||||
#define DBL_DIG __DBL_DIG__
|
||||
#define LDBL_DIG __LDBL_DIG__
|
||||
|
||||
#define FLT_MIN_EXP __FLT_MIN_EXP__
|
||||
#define DBL_MIN_EXP __DBL_MIN_EXP__
|
||||
#define LDBL_MIN_EXP __LDBL_MIN_EXP__
|
||||
|
||||
#define FLT_MIN_10_EXP __FLT_MIN_10_EXP__
|
||||
#define DBL_MIN_10_EXP __DBL_MIN_10_EXP__
|
||||
#define LDBL_MIN_10_EXP __LDBL_MIN_10_EXP__
|
||||
|
||||
#define FLT_MAX_EXP __FLT_MAX_EXP__
|
||||
#define DBL_MAX_EXP __DBL_MAX_EXP__
|
||||
#define LDBL_MAX_EXP __LDBL_MAX_EXP__
|
||||
|
||||
#define FLT_MAX_10_EXP __FLT_MAX_10_EXP__
|
||||
#define DBL_MAX_10_EXP __DBL_MAX_10_EXP__
|
||||
#define LDBL_MAX_10_EXP __LDBL_MAX_10_EXP__
|
||||
|
||||
#define FLT_MAX __FLT_MAX__
|
||||
#define DBL_MAX __DBL_MAX__
|
||||
#define LDBL_MAX __LDBL_MAX__
|
||||
|
||||
#define FLT_EPSILON __FLT_EPSILON__
|
||||
#define DBL_EPSILON __DBL_EPSILON__
|
||||
#define LDBL_EPSILON __LDBL_EPSILON__
|
||||
|
||||
#define FLT_MIN __FLT_MIN__
|
||||
#define DBL_MIN __DBL_MIN__
|
||||
#define LDBL_MIN __LDBL_MIN__
|
||||
|
||||
#define FLT_TRUE_MIN __FLT_DENORM_MIN__
|
||||
#define DBL_TRUE_MIN __DBL_DENORM_MIN__
|
||||
#define LDBL_TRUE_MIN __LDBL_DENORM_MIN__
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // !_FLOAT_H
|
@ -1,40 +1,69 @@
|
||||
/*
|
||||
This file is part of Fennix C Library.
|
||||
|
||||
Fennix C Library is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _INTTYPES_H
|
||||
#define _INTTYPES_H
|
||||
|
||||
typedef __INT8_TYPE__ int8_t;
|
||||
typedef __INT16_TYPE__ int16_t;
|
||||
typedef __INT32_TYPE__ int32_t;
|
||||
typedef __INT64_TYPE__ int64_t;
|
||||
typedef __UINT8_TYPE__ uint8_t;
|
||||
typedef __UINT16_TYPE__ uint16_t;
|
||||
typedef __UINT32_TYPE__ uint32_t;
|
||||
typedef __UINT64_TYPE__ uint64_t;
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif // __cplusplus
|
||||
|
||||
typedef __INT_LEAST8_TYPE__ int_least8_t;
|
||||
typedef __INT_LEAST16_TYPE__ int_least16_t;
|
||||
typedef __INT_LEAST32_TYPE__ int_least32_t;
|
||||
typedef __INT_LEAST64_TYPE__ int_least64_t;
|
||||
typedef __UINT_LEAST8_TYPE__ uint_least8_t;
|
||||
typedef __UINT_LEAST16_TYPE__ uint_least16_t;
|
||||
typedef __UINT_LEAST32_TYPE__ uint_least32_t;
|
||||
typedef __UINT_LEAST64_TYPE__ uint_least64_t;
|
||||
typedef __INT8_TYPE__ int8_t;
|
||||
typedef __INT16_TYPE__ int16_t;
|
||||
typedef __INT32_TYPE__ int32_t;
|
||||
typedef __INT64_TYPE__ int64_t;
|
||||
|
||||
typedef __INT_FAST8_TYPE__ int_fast8_t;
|
||||
typedef __INT_FAST16_TYPE__ int_fast16_t;
|
||||
typedef __INT_FAST32_TYPE__ int_fast32_t;
|
||||
typedef __INT_FAST64_TYPE__ int_fast64_t;
|
||||
typedef __UINT_FAST8_TYPE__ uint_fast8_t;
|
||||
typedef __UINT_FAST16_TYPE__ uint_fast16_t;
|
||||
typedef __UINT_FAST32_TYPE__ uint_fast32_t;
|
||||
typedef __UINT_FAST64_TYPE__ uint_fast64_t;
|
||||
typedef __UINT8_TYPE__ uint8_t;
|
||||
typedef __UINT16_TYPE__ uint16_t;
|
||||
typedef __UINT32_TYPE__ uint32_t;
|
||||
typedef __UINT64_TYPE__ uint64_t;
|
||||
|
||||
typedef __INTPTR_TYPE__ intptr_t;
|
||||
typedef __UINTPTR_TYPE__ uintptr_t;
|
||||
typedef __INTPTR_TYPE__ intptr_t;
|
||||
typedef __UINTPTR_TYPE__ uintptr_t;
|
||||
|
||||
typedef __INTMAX_TYPE__ intmax_t;
|
||||
typedef __UINTMAX_TYPE__ uintmax_t;
|
||||
typedef __INT_LEAST8_TYPE__ int_least8_t;
|
||||
typedef __INT_LEAST16_TYPE__ int_least16_t;
|
||||
typedef __INT_LEAST32_TYPE__ int_least32_t;
|
||||
typedef __INT_LEAST64_TYPE__ int_least64_t;
|
||||
|
||||
typedef __PTRDIFF_TYPE__ ptrdiff_t;
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
typedef __UINT_LEAST8_TYPE__ uint_least8_t;
|
||||
typedef __UINT_LEAST16_TYPE__ uint_least16_t;
|
||||
typedef __UINT_LEAST32_TYPE__ uint_least32_t;
|
||||
typedef __UINT_LEAST64_TYPE__ uint_least64_t;
|
||||
|
||||
typedef __INT_FAST8_TYPE__ int_fast8_t;
|
||||
typedef __INT_FAST16_TYPE__ int_fast16_t;
|
||||
typedef __INT_FAST32_TYPE__ int_fast32_t;
|
||||
typedef __INT_FAST64_TYPE__ int_fast64_t;
|
||||
|
||||
typedef __UINT_FAST8_TYPE__ uint_fast8_t;
|
||||
typedef __UINT_FAST16_TYPE__ uint_fast16_t;
|
||||
typedef __UINT_FAST32_TYPE__ uint_fast32_t;
|
||||
typedef __UINT_FAST64_TYPE__ uint_fast64_t;
|
||||
|
||||
typedef __INTPTR_TYPE__ intptr_t;
|
||||
typedef __UINTPTR_TYPE__ uintptr_t;
|
||||
|
||||
typedef __INTMAX_TYPE__ intmax_t;
|
||||
typedef __UINTMAX_TYPE__ uintmax_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // !_INTTYPES_H
|
||||
|
@ -1,119 +1,117 @@
|
||||
/*
|
||||
This file is part of Fennix C Library.
|
||||
|
||||
Fennix C Library is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _LIMITS_H
|
||||
#define _LIMITS_H
|
||||
|
||||
#undef CHAR_BIT
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif // __cplusplus
|
||||
|
||||
#define _POSIX_ARG_MAX 4096
|
||||
#define _POSIX_CHILD_MAX 25
|
||||
#define _POSIX_OPEN_MAX 20
|
||||
#define _POSIX_LINK_MAX 8
|
||||
#define _POSIX_MAX_CANON 255
|
||||
#define _POSIX_MAX_INPUT 255
|
||||
#define _POSIX_NAME_MAX 255
|
||||
#define _POSIX_PATH_MAX 4096
|
||||
#define _POSIX_PIPE_BUF 512
|
||||
#define _POSIX_SYMLOOP_MAX 8
|
||||
#define _POSIX_HOST_NAME_MAX 255
|
||||
#define _POSIX_LOGIN_NAME_MAX 9
|
||||
#define _POSIX_TTY_NAME_MAX 255
|
||||
#define _POSIX_TZNAME_MAX 6
|
||||
|
||||
#define _XOPEN_SHM_MAX 255
|
||||
#define _XOPEN_IOV_MAX 1024
|
||||
#define _XOPEN_SSTREAM_MAX 8
|
||||
#define _XOPEN_NAME_MAX 255
|
||||
#define _XOPEN_PATH_MAX 4096
|
||||
#define _XOPEN_SYMLOOP_MAX 8
|
||||
#define _XOPEN_LOGIN_NAME_MAX 9
|
||||
|
||||
#define _POSIX2_BC_BASE_MAX 99
|
||||
#define _POSIX2_BC_DIM_MAX 2048
|
||||
#define _POSIX2_BC_SCALE_MAX 99
|
||||
#define _POSIX2_BC_STRING_MAX 1000
|
||||
#define _POSIX2_COLL_WEIGHTS_MAX 255
|
||||
#define _POSIX2_EXPR_NEST_MAX 32
|
||||
#define _POSIX2_LINE_MAX 2048
|
||||
#define _POSIX2_RE_DUP_MAX 255
|
||||
|
||||
#define CHAR_BIT __CHAR_BIT__
|
||||
|
||||
#ifndef MB_LEN_MAX
|
||||
#define MB_LEN_MAX 1
|
||||
#endif
|
||||
|
||||
#undef SCHAR_MIN
|
||||
#define SCHAR_MIN (-SCHAR_MAX - 1)
|
||||
#undef SCHAR_MAX
|
||||
#define SCHAR_MAX __SCHAR_MAX__
|
||||
|
||||
#undef UCHAR_MAX
|
||||
#if __SCHAR_MAX__ == __INT_MAX__
|
||||
#define UCHAR_MAX (SCHAR_MAX * 2U + 1U)
|
||||
#else
|
||||
#define UCHAR_MAX (SCHAR_MAX * 2 + 1)
|
||||
#endif
|
||||
|
||||
#ifdef __CHAR_UNSIGNED__
|
||||
#undef CHAR_MIN
|
||||
#if __SCHAR_MAX__ == __INT_MAX__
|
||||
#define CHAR_MIN 0U
|
||||
#else
|
||||
#define CHAR_MIN 0
|
||||
#endif
|
||||
#undef CHAR_MAX
|
||||
#define CHAR_MAX UCHAR_MAX
|
||||
#else
|
||||
#undef CHAR_MIN
|
||||
#define CHAR_MIN SCHAR_MIN
|
||||
#undef CHAR_MAX
|
||||
#define CHAR_MAX SCHAR_MAX
|
||||
#endif
|
||||
|
||||
#undef SHRT_MIN
|
||||
#define MB_LEN_MAX 1
|
||||
#define SHRT_MIN (-SHRT_MAX - 1)
|
||||
#undef SHRT_MAX
|
||||
#define SHRT_MAX __SHRT_MAX__
|
||||
|
||||
#undef USHRT_MAX
|
||||
#if __SHRT_MAX__ == __INT_MAX__
|
||||
#define USHRT_MAX (SHRT_MAX * 2U + 1U)
|
||||
#else
|
||||
#define USHRT_MAX (SHRT_MAX * 2 + 1)
|
||||
#endif
|
||||
|
||||
#undef INT_MIN
|
||||
#define INT_MIN (-INT_MAX - 1)
|
||||
#undef INT_MAX
|
||||
#define INT_MAX __INT_MAX__
|
||||
|
||||
#undef UINT_MAX
|
||||
#define UINT_MAX (INT_MAX * 2U + 1U)
|
||||
|
||||
#undef LONG_MIN
|
||||
#define LONG_MIN (-LONG_MAX - 1L)
|
||||
#undef LONG_MAX
|
||||
#define LONG_MAX __LONG_MAX__
|
||||
|
||||
#undef ULONG_MAX
|
||||
#define ULONG_MAX (LONG_MAX * 2UL + 1UL)
|
||||
|
||||
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
|
||||
#undef LLONG_MIN
|
||||
#define LLONG_MIN (-LLONG_MAX - 1LL)
|
||||
#undef LLONG_MAX
|
||||
#define LLONG_MIN (-__LONG_LONG_MAX__ - 1LL)
|
||||
#define LLONG_MAX __LONG_LONG_MAX__
|
||||
|
||||
#undef ULLONG_MAX
|
||||
#define ULLONG_MAX (LLONG_MAX * 2ULL + 1ULL)
|
||||
#endif
|
||||
|
||||
#if defined(__GNU_LIBRARY__) ? defined(__USE_GNU) : !defined(__STRICT_ANSI__)
|
||||
#undef LONG_LONG_MIN
|
||||
#define LONG_LONG_MIN (-LONG_LONG_MAX - 1LL)
|
||||
#undef LONG_LONG_MAX
|
||||
#define LONG_LONG_MAX __LONG_LONG_MAX__
|
||||
#define ARG_MAX 4096
|
||||
#define CHILD_MAX 25
|
||||
#define OPEN_MAX 20
|
||||
#define LINK_MAX 8
|
||||
#define MAX_CANON 255
|
||||
#define MAX_INPUT 255
|
||||
#define NAME_MAX 255
|
||||
#define PATH_MAX 4096
|
||||
#define PIPE_BUF 512
|
||||
#define SYMLOOP_MAX 8
|
||||
#define HOST_NAME_MAX 255
|
||||
#define LOGIN_NAME_MAX 9
|
||||
#define TTY_NAME_MAX 255
|
||||
#define TZNAME_MAX 6
|
||||
|
||||
#undef ULONG_LONG_MAX
|
||||
#define ULONG_LONG_MAX (LONG_LONG_MAX * 2ULL + 1ULL)
|
||||
#endif
|
||||
#define SSIZE_MAX ((size_t)(-1) / 2)
|
||||
|
||||
#if (defined __STDC_WANT_IEC_60559_BFP_EXT__ || (defined(__STDC_VERSION__) && __STDC_VERSION__ > 201710L))
|
||||
#undef CHAR_WIDTH
|
||||
#define CHAR_WIDTH __SCHAR_WIDTH__
|
||||
#undef SCHAR_WIDTH
|
||||
#define SCHAR_WIDTH __SCHAR_WIDTH__
|
||||
#undef UCHAR_WIDTH
|
||||
#define UCHAR_WIDTH __SCHAR_WIDTH__
|
||||
#undef SHRT_WIDTH
|
||||
#define SHRT_WIDTH __SHRT_WIDTH__
|
||||
#undef USHRT_WIDTH
|
||||
#define USHRT_WIDTH __SHRT_WIDTH__
|
||||
#undef INT_WIDTH
|
||||
#define INT_WIDTH __INT_WIDTH__
|
||||
#undef UINT_WIDTH
|
||||
#define UINT_WIDTH __INT_WIDTH__
|
||||
#undef LONG_WIDTH
|
||||
#define LONG_WIDTH __LONG_WIDTH__
|
||||
#undef ULONG_WIDTH
|
||||
#define ULONG_WIDTH __LONG_WIDTH__
|
||||
#undef LLONG_WIDTH
|
||||
#define LLONG_WIDTH __LONG_LONG_WIDTH__
|
||||
#undef ULLONG_WIDTH
|
||||
#define ULLONG_WIDTH __LONG_LONG_WIDTH__
|
||||
#endif
|
||||
|
||||
#if defined(__STDC_VERSION__) && __STDC_VERSION__ > 201710L
|
||||
#undef BOOL_MAX
|
||||
#define BOOL_MAX 1
|
||||
#undef BOOL_WIDTH
|
||||
#define BOOL_WIDTH 1
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // !_LIMITS_H
|
||||
|
79
Userspace/libc/include/locale.h
Normal file
79
Userspace/libc/include/locale.h
Normal file
@ -0,0 +1,79 @@
|
||||
/*
|
||||
This file is part of Fennix C Library.
|
||||
|
||||
Fennix C Library is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _LOCALE_H
|
||||
#define _LOCALE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif // __cplusplus
|
||||
|
||||
typedef struct lconv
|
||||
{
|
||||
char *currency_symbol;
|
||||
char *decimal_point;
|
||||
char frac_digits;
|
||||
char *grouping;
|
||||
char *int_curr_symbol;
|
||||
char int_frac_digits;
|
||||
char int_n_cs_precedes;
|
||||
char int_n_sep_by_space;
|
||||
char int_n_sign_posn;
|
||||
char int_p_cs_precedes;
|
||||
char int_p_sep_by_space;
|
||||
char int_p_sign_posn;
|
||||
char *mon_decimal_point;
|
||||
char *mon_grouping;
|
||||
char *mon_thousands_sep;
|
||||
char *negative_sign;
|
||||
char n_cs_precedes;
|
||||
char n_sep_by_space;
|
||||
char n_sign_posn;
|
||||
char *positive_sign;
|
||||
char p_cs_precedes;
|
||||
char p_sep_by_space;
|
||||
char p_sign_posn;
|
||||
char *thousands_sep;
|
||||
} lconv;
|
||||
|
||||
typedef struct locale_t
|
||||
{
|
||||
char data[1]; /* FIXME: implement locale_t */
|
||||
} locale_t;
|
||||
|
||||
#define LC_ALL
|
||||
#define LC_COLLATE
|
||||
#define LC_CTYPE
|
||||
#define LC_MESSAGES
|
||||
#define LC_MONETARY
|
||||
#define LC_NUMERIC
|
||||
#define LC_TIME
|
||||
|
||||
locale_t duplocale(locale_t);
|
||||
void freelocale(locale_t);
|
||||
const char *getlocalename_l(int, locale_t);
|
||||
struct lconv *localeconv(void);
|
||||
locale_t newlocale(int, const char *, locale_t);
|
||||
char *setlocale(int, const char *);
|
||||
locale_t uselocale(locale_t);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // !_LOCALE_H
|
@ -1,4 +1,226 @@
|
||||
/*
|
||||
This file is part of Fennix C Library.
|
||||
|
||||
Fennix C Library is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _MATH_H
|
||||
#define _MATH_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif // __cplusplus
|
||||
|
||||
#define FLT_EVAL_METHOD 0
|
||||
|
||||
#if FLT_EVAL_METHOD == 0
|
||||
typedef float float_t;
|
||||
typedef double double_t;
|
||||
#elif FLT_EVAL_METHOD == 1
|
||||
typedef float float_t;
|
||||
typedef float double_t;
|
||||
#elif FLT_EVAL_METHOD == 2
|
||||
typedef long double float_t;
|
||||
typedef long double double_t;
|
||||
#else
|
||||
#error "Unsupported FLT_EVAL_METHOD"
|
||||
#endif
|
||||
|
||||
double acos(double);
|
||||
float acosf(float);
|
||||
double acosh(double);
|
||||
float acoshf(float);
|
||||
long double acoshl(long double);
|
||||
long double acosl(long double);
|
||||
double asin(double);
|
||||
float asinf(float);
|
||||
double asinh(double);
|
||||
float asinhf(float);
|
||||
long double asinhl(long double);
|
||||
long double asinl(long double);
|
||||
double atan(double);
|
||||
double atan2(double, double);
|
||||
float atan2f(float, float);
|
||||
long double atan2l(long double, long double);
|
||||
float atanf(float);
|
||||
double atanh(double);
|
||||
float atanhf(float);
|
||||
long double atanhl(long double);
|
||||
long double atanl(long double);
|
||||
double cbrt(double);
|
||||
float cbrtf(float);
|
||||
long double cbrtl(long double);
|
||||
double ceil(double);
|
||||
float ceilf(float);
|
||||
long double ceill(long double);
|
||||
double copysign(double, double);
|
||||
float copysignf(float, float);
|
||||
long double copysignl(long double, long double);
|
||||
double cos(double);
|
||||
float cosf(float);
|
||||
double cosh(double);
|
||||
float coshf(float);
|
||||
long double coshl(long double);
|
||||
long double cosl(long double);
|
||||
double erf(double);
|
||||
double erfc(double);
|
||||
float erfcf(float);
|
||||
long double erfcl(long double);
|
||||
float erff(float);
|
||||
long double erfl(long double);
|
||||
double exp(double);
|
||||
double exp2(double);
|
||||
float exp2f(float);
|
||||
long double exp2l(long double);
|
||||
float expf(float);
|
||||
long double expl(long double);
|
||||
double expm1(double);
|
||||
float expm1f(float);
|
||||
long double expm1l(long double);
|
||||
double fabs(double);
|
||||
float fabsf(float);
|
||||
long double fabsl(long double);
|
||||
double fdim(double, double);
|
||||
float fdimf(float, float);
|
||||
long double fdiml(long double, long double);
|
||||
double floor(double);
|
||||
float floorf(float);
|
||||
long double floorl(long double);
|
||||
double fma(double, double, double);
|
||||
float fmaf(float, float, float);
|
||||
long double fmal(long double, long double, long double);
|
||||
double fmax(double, double);
|
||||
float fmaxf(float, float);
|
||||
long double fmaxl(long double, long double);
|
||||
double fmin(double, double);
|
||||
float fminf(float, float);
|
||||
long double fminl(long double, long double);
|
||||
double fmod(double, double);
|
||||
float fmodf(float, float);
|
||||
long double fmodl(long double, long double);
|
||||
double frexp(double, int *);
|
||||
float frexpf(float value, int *);
|
||||
long double frexpl(long double value, int *);
|
||||
double hypot(double, double);
|
||||
float hypotf(float, float);
|
||||
long double hypotl(long double, long double);
|
||||
int ilogb(double);
|
||||
int ilogbf(float);
|
||||
int ilogbl(long double);
|
||||
double j0(double);
|
||||
double j1(double);
|
||||
double jn(int, double);
|
||||
double ldexp(double, int);
|
||||
float ldexpf(float, int);
|
||||
long double ldexpl(long double, int);
|
||||
double lgamma(double);
|
||||
float lgammaf(float);
|
||||
long double lgammal(long double);
|
||||
long long llrint(double);
|
||||
long long llrintf(float);
|
||||
long long llrintl(long double);
|
||||
long long llround(double);
|
||||
long long llroundf(float);
|
||||
long long llroundl(long double);
|
||||
double log(double);
|
||||
double log10(double);
|
||||
float log10f(float);
|
||||
long double log10l(long double);
|
||||
double log1p(double);
|
||||
float log1pf(float);
|
||||
long double log1pl(long double);
|
||||
double log2(double);
|
||||
float log2f(float);
|
||||
long double log2l(long double);
|
||||
double logb(double);
|
||||
float logbf(float);
|
||||
long double logbl(long double);
|
||||
float logf(float);
|
||||
long double logl(long double);
|
||||
long lrint(double);
|
||||
long lrintf(float);
|
||||
long lrintl(long double);
|
||||
long lround(double);
|
||||
long lroundf(float);
|
||||
long lroundl(long double);
|
||||
double modf(double, double *);
|
||||
float modff(float, float *);
|
||||
long double modfl(long double, long double *);
|
||||
double nan(const char *);
|
||||
float nanf(const char *);
|
||||
long double nanl(const char *);
|
||||
double nearbyint(double);
|
||||
float nearbyintf(float);
|
||||
long double nearbyintl(long double);
|
||||
double nextafter(double, double);
|
||||
float nextafterf(float, float);
|
||||
long double nextafterl(long double, long double);
|
||||
double nexttoward(double, long double);
|
||||
float nexttowardf(float, long double);
|
||||
long double nexttowardl(long double, long double);
|
||||
double pow(double, double);
|
||||
float powf(float, float);
|
||||
long double powl(long double, long double);
|
||||
double remainder(double, double);
|
||||
float remainderf(float, float);
|
||||
long double remainderl(long double, long double);
|
||||
double remquo(double, double, int *);
|
||||
float remquof(float, float, int *);
|
||||
long double remquol(long double, long double, int *);
|
||||
double rint(double);
|
||||
float rintf(float);
|
||||
long double rintl(long double);
|
||||
double round(double);
|
||||
float roundf(float);
|
||||
long double roundl(long double);
|
||||
double scalb(double, double);
|
||||
double scalbln(double, long);
|
||||
float scalblnf(float, long);
|
||||
long double scalblnl(long double, long);
|
||||
double scalbn(double, int);
|
||||
float scalbnf(float, int);
|
||||
long double scalbnl(long double, int);
|
||||
double sin(double);
|
||||
float sinf(float);
|
||||
double sinh(double);
|
||||
float sinhf(float);
|
||||
long double sinhl(long double);
|
||||
long double sinl(long double);
|
||||
double sqrt(double);
|
||||
float sqrtf(float);
|
||||
long double sqrtl(long double);
|
||||
double tan(double);
|
||||
float tanf(float);
|
||||
double tanh(double);
|
||||
float tanhf(float);
|
||||
long double tanhl(long double);
|
||||
long double tanl(long double);
|
||||
double tgamma(double);
|
||||
float tgammaf(float);
|
||||
long double tgammal(long double);
|
||||
double trunc(double);
|
||||
float truncf(float);
|
||||
long double truncl(long double);
|
||||
double y0(double);
|
||||
double y1(double);
|
||||
double yn(int, double);
|
||||
|
||||
extern int signgam;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // !_MATH_H
|
||||
|
137
Userspace/libc/include/pthread.h
Normal file
137
Userspace/libc/include/pthread.h
Normal file
@ -0,0 +1,137 @@
|
||||
/*
|
||||
This file is part of Fennix C Library.
|
||||
|
||||
Fennix C Library is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _PTHREAD_H
|
||||
#define _PTHREAD_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif // __cplusplus
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <inttypes.h>
|
||||
#include <sched.h>
|
||||
|
||||
#define PTHREAD_CANCEL_ASYNCHRONOUS {0}
|
||||
#define PTHREAD_CANCEL_ENABLE {0}
|
||||
#define PTHREAD_CANCEL_DEFERRED {0}
|
||||
#define PTHREAD_CANCEL_DISABLE {0}
|
||||
#define PTHREAD_CANCELED {0}
|
||||
#define PTHREAD_COND_INITIALIZER {0}
|
||||
#define PTHREAD_CREATE_DETACHED {0}
|
||||
#define PTHREAD_CREATE_JOINABLE {0}
|
||||
#define PTHREAD_EXPLICIT_SCHED {0}
|
||||
#define PTHREAD_INHERIT_SCHED {0}
|
||||
#define PTHREAD_MUTEX_DEFAULT {0}
|
||||
#define PTHREAD_MUTEX_ERRORCHECK {0}
|
||||
#define PTHREAD_MUTEX_NORMAL {0}
|
||||
#define PTHREAD_MUTEX_INITIALIZER {0}
|
||||
#define PTHREAD_MUTEX_RECURSIVE {0}
|
||||
#define PTHREAD_ONCE_INIT {0}
|
||||
#define PTHREAD_PRIO_INHERIT {0}
|
||||
#define PTHREAD_PRIO_NONE {0}
|
||||
#define PTHREAD_PRIO_PROTECT {0}
|
||||
#define PTHREAD_PROCESS_SHARED {0}
|
||||
#define PTHREAD_PROCESS_PRIVATE {0}
|
||||
#define PTHREAD_RWLOCK_INITIALIZER {0}
|
||||
#define PTHREAD_SCOPE_PROCESS {0}
|
||||
#define PTHREAD_SCOPE_SYSTEM {0}
|
||||
|
||||
int pthread_attr_destroy(pthread_attr_t *);
|
||||
int pthread_attr_getdetachstate(const pthread_attr_t *, int *);
|
||||
int pthread_attr_getguardsize(const pthread_attr_t *, size_t *);
|
||||
int pthread_attr_getinheritsched(const pthread_attr_t *, int *);
|
||||
int pthread_attr_getschedparam(const pthread_attr_t *, struct sched_param *);
|
||||
int pthread_attr_getschedpolicy(const pthread_attr_t *, int *);
|
||||
int pthread_attr_getscope(const pthread_attr_t *, int *);
|
||||
int pthread_attr_getstackaddr(const pthread_attr_t *, void **);
|
||||
int pthread_attr_getstacksize(const pthread_attr_t *, size_t *);
|
||||
int pthread_attr_init(pthread_attr_t *);
|
||||
int pthread_attr_setdetachstate(pthread_attr_t *, int);
|
||||
int pthread_attr_setguardsize(pthread_attr_t *, size_t);
|
||||
int pthread_attr_setinheritsched(pthread_attr_t *, int);
|
||||
int pthread_attr_setschedparam(pthread_attr_t *, const struct sched_param *);
|
||||
int pthread_attr_setschedpolicy(pthread_attr_t *, int);
|
||||
int pthread_attr_setscope(pthread_attr_t *, int);
|
||||
int pthread_attr_setstackaddr(pthread_attr_t *, void *);
|
||||
int pthread_attr_setstacksize(pthread_attr_t *, size_t);
|
||||
int pthread_cancel(pthread_t);
|
||||
void pthread_cleanup_push(void (*)(void *), void *);
|
||||
void pthread_cleanup_pop(int);
|
||||
int pthread_cond_broadcast(pthread_cond_t *);
|
||||
int pthread_cond_destroy(pthread_cond_t *);
|
||||
int pthread_cond_init(pthread_cond_t *, const pthread_condattr_t *);
|
||||
int pthread_cond_signal(pthread_cond_t *);
|
||||
int pthread_cond_timedwait(pthread_cond_t *, pthread_mutex_t *, const struct timespec *);
|
||||
int pthread_cond_wait(pthread_cond_t *, pthread_mutex_t *);
|
||||
int pthread_condattr_destroy(pthread_condattr_t *);
|
||||
int pthread_condattr_getpshared(const pthread_condattr_t *, int *);
|
||||
int pthread_condattr_init(pthread_condattr_t *);
|
||||
int pthread_condattr_setpshared(pthread_condattr_t *, int);
|
||||
int pthread_create(pthread_t *, const pthread_attr_t *, void *(*)(void *), void *);
|
||||
int pthread_detach(pthread_t);
|
||||
int pthread_equal(pthread_t, pthread_t);
|
||||
void pthread_exit(void *);
|
||||
int pthread_getconcurrency(void);
|
||||
int pthread_getschedparam(pthread_t, int *, struct sched_param *);
|
||||
void *pthread_getspecific(pthread_key_t);
|
||||
int pthread_join(pthread_t, void **);
|
||||
int pthread_key_create(pthread_key_t *, void (*)(void *));
|
||||
int pthread_key_delete(pthread_key_t);
|
||||
int pthread_mutex_destroy(pthread_mutex_t *);
|
||||
int pthread_mutex_getprioceiling(const pthread_mutex_t *, int *);
|
||||
int pthread_mutex_init(pthread_mutex_t *, const pthread_mutexattr_t *);
|
||||
int pthread_mutex_lock(pthread_mutex_t *mutex);
|
||||
int pthread_mutex_setprioceiling(pthread_mutex_t *, int, int *);
|
||||
int pthread_mutex_trylock(pthread_mutex_t *);
|
||||
int pthread_mutex_unlock(pthread_mutex_t *mutex);
|
||||
int pthread_mutexattr_destroy(pthread_mutexattr_t *);
|
||||
int pthread_mutexattr_getprioceiling(const pthread_mutexattr_t *, int *);
|
||||
int pthread_mutexattr_getprotocol(const pthread_mutexattr_t *, int *);
|
||||
int pthread_mutexattr_getpshared(const pthread_mutexattr_t *, int *);
|
||||
int pthread_mutexattr_gettype(const pthread_mutexattr_t *, int *);
|
||||
int pthread_mutexattr_init(pthread_mutexattr_t *);
|
||||
int pthread_mutexattr_setprioceiling(pthread_mutexattr_t *, int);
|
||||
int pthread_mutexattr_setprotocol(pthread_mutexattr_t *, int);
|
||||
int pthread_mutexattr_setpshared(pthread_mutexattr_t *, int);
|
||||
int pthread_mutexattr_settype(pthread_mutexattr_t *, int);
|
||||
int pthread_once(pthread_once_t *, void (*)(void));
|
||||
int pthread_rwlock_destroy(pthread_rwlock_t *);
|
||||
int pthread_rwlock_init(pthread_rwlock_t *, const pthread_rwlockattr_t *);
|
||||
int pthread_rwlock_rdlock(pthread_rwlock_t *);
|
||||
int pthread_rwlock_tryrdlock(pthread_rwlock_t *);
|
||||
int pthread_rwlock_trywrlock(pthread_rwlock_t *);
|
||||
int pthread_rwlock_unlock(pthread_rwlock_t *);
|
||||
int pthread_rwlock_wrlock(pthread_rwlock_t *);
|
||||
int pthread_rwlockattr_destroy(pthread_rwlockattr_t *);
|
||||
int pthread_rwlockattr_getpshared(const pthread_rwlockattr_t *, int *);
|
||||
int pthread_rwlockattr_init(pthread_rwlockattr_t *);
|
||||
int pthread_rwlockattr_setpshared(pthread_rwlockattr_t *, int);
|
||||
pthread_t pthread_self(void);
|
||||
int pthread_setcancelstate(int, int *);
|
||||
int pthread_setcanceltype(int, int *);
|
||||
int pthread_setconcurrency(int);
|
||||
int pthread_setschedparam(pthread_t, int, const struct sched_param *);
|
||||
int pthread_setspecific(pthread_key_t, const void *);
|
||||
void pthread_testcancel(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // !_PTHREAD_H
|
49
Userspace/libc/include/pwd.h
Normal file
49
Userspace/libc/include/pwd.h
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
This file is part of Fennix C Library.
|
||||
|
||||
Fennix C Library is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _PWD_H
|
||||
#define _PWD_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif // __cplusplus
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
struct passwd
|
||||
{
|
||||
char *pw_name; /* User's login name. */
|
||||
uid_t pw_uid; /* Numerical user ID. */
|
||||
gid_t pw_gid; /* Numerical group ID. */
|
||||
char *pw_dir; /* Initial working directory. */
|
||||
char *pw_shell; /* Program to use as shell. */
|
||||
};
|
||||
|
||||
void endpwent(void);
|
||||
struct passwd *getpwent(void);
|
||||
struct passwd *getpwnam(const char *);
|
||||
int getpwnam_r(const char *, struct passwd *, char *, size_t, struct passwd **);
|
||||
struct passwd *getpwuid(uid_t);
|
||||
int getpwuid_r(uid_t, struct passwd *, char *, size_t, struct passwd **);
|
||||
void setpwent(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // !_PWD_H
|
41
Userspace/libc/include/sched.h
Normal file
41
Userspace/libc/include/sched.h
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
This file is part of Fennix C Library.
|
||||
|
||||
Fennix C Library is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _SCHED_H
|
||||
#define _SCHED_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif // __cplusplus
|
||||
|
||||
#include <time.h>
|
||||
|
||||
typedef struct sched_param
|
||||
{
|
||||
int sched_priority; /* Process or thread execution scheduling priority. */
|
||||
int sched_ss_low_priority; /* Low scheduling priority for sporadic server. */
|
||||
struct timespec sched_ss_repl_period; /* Replenishment period for sporadic server. */
|
||||
struct timespec sched_ss_init_budget; /* Initial budget for sporadic server. */
|
||||
int sched_ss_max_repl; /* Maximum pending replenishments for sporadic server. */
|
||||
} sched_param_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // !_SCHED_H
|
@ -1,34 +0,0 @@
|
||||
#ifndef _SETJMP_H
|
||||
#define _SETJMP_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint64_t r15;
|
||||
uint64_t r14;
|
||||
uint64_t r13;
|
||||
uint64_t r12;
|
||||
uint64_t r11;
|
||||
uint64_t r10;
|
||||
uint64_t r9;
|
||||
uint64_t r8;
|
||||
uint64_t rbp;
|
||||
uint64_t rsp;
|
||||
uint64_t rdi;
|
||||
uint64_t rsi;
|
||||
uint64_t rdx;
|
||||
uint64_t rcx;
|
||||
uint64_t rbx;
|
||||
uint64_t rax;
|
||||
uint64_t rip;
|
||||
uint64_t rflags;
|
||||
uint64_t cs;
|
||||
uint64_t fs;
|
||||
uint64_t gs;
|
||||
} jmp_buf[1];
|
||||
|
||||
int setjmp(jmp_buf env);
|
||||
__attribute__((noreturn)) void longjmp(jmp_buf env, int value);
|
||||
|
||||
#endif // !_SETJMP_H
|
@ -1,102 +1,221 @@
|
||||
/*
|
||||
This file is part of Fennix C Library.
|
||||
|
||||
Fennix C Library is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _SIGNAL_H
|
||||
#define _SIGNAL_H
|
||||
|
||||
#include <bits/types/sigset_t.h>
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif // __cplusplus
|
||||
|
||||
/* https://www-uxsup.csx.cam.ac.uk/courses/moved.Building/signals.pdf */
|
||||
/* https://man7.org/linux/man-pages/man7/signal.7.html */
|
||||
#include <sys/types.h>
|
||||
#include <fennix/syscalls.h>
|
||||
#include <bits/types/timespec.h>
|
||||
|
||||
/** @brief Hangup detected on controlling or death of controlling process */
|
||||
#define SIGHUP 1
|
||||
#define SIGNULL __SYS_SIGNULL
|
||||
#define SIGABRT __SYS_SIGABRT
|
||||
#define SIGALRM __SYS_SIGALRM
|
||||
#define SIGBUS __SYS_SIGBUS
|
||||
#define SIGCHLD __SYS_SIGCHLD
|
||||
#define SIGCONT __SYS_SIGCONT
|
||||
#define SIGFPE __SYS_SIGFPE
|
||||
#define SIGHUP __SYS_SIGHUP
|
||||
#define SIGILL __SYS_SIGILL
|
||||
#define SIGINT __SYS_SIGINT
|
||||
#define SIGKILL __SYS_SIGKILL
|
||||
#define SIGPIPE __SYS_SIGPIPE
|
||||
#define SIGQUIT __SYS_SIGQUIT
|
||||
#define SIGSEGV __SYS_SIGSEGV
|
||||
#define SIGSTOP __SYS_SIGSTOP
|
||||
#define SIGTERM __SYS_SIGTERM
|
||||
#define SIGTSTP __SYS_SIGTSTP
|
||||
#define SIGTTIN __SYS_SIGTTIN
|
||||
#define SIGTTOU __SYS_SIGTTOU
|
||||
#define SIGUSR1 __SYS_SIGUSR1
|
||||
#define SIGUSR2 __SYS_SIGUSR2
|
||||
#define SIGPOLL __SYS_SIGPOLL
|
||||
#define SIGPROF __SYS_SIGPROF
|
||||
#define SIGSYS __SYS_SIGSYS
|
||||
#define SIGTRAP __SYS_SIGTRAP
|
||||
#define SIGURG __SYS_SIGURG
|
||||
#define SIGVTALRM __SYS_SIGVTALRM
|
||||
#define SIGXCPU __SYS_SIGXCPU
|
||||
#define SIGXFSZ __SYS_SIGXFSZ
|
||||
#define SIGCOMP1 __SYS_SIGCOMP1
|
||||
#define SIGCOMP2 __SYS_SIGCOMP2
|
||||
#define SIGCOMP3 __SYS_SIGCOMP3
|
||||
#define SIGRTMIN __SYS_SIGRTMIN
|
||||
#define SIGRT_1 __SYS_SIGRT_1
|
||||
#define SIGRT_2 __SYS_SIGRT_2
|
||||
#define SIGRT_3 __SYS_SIGRT_3
|
||||
#define SIGRT_4 __SYS_SIGRT_4
|
||||
#define SIGRT_5 __SYS_SIGRT_5
|
||||
#define SIGRT_6 __SYS_SIGRT_6
|
||||
#define SIGRT_7 __SYS_SIGRT_7
|
||||
#define SIGRT_8 __SYS_SIGRT_8
|
||||
#define SIGRT_9 __SYS_SIGRT_9
|
||||
#define SIGRT_10 __SYS_SIGRT_10
|
||||
#define SIGRT_11 __SYS_SIGRT_11
|
||||
#define SIGRT_12 __SYS_SIGRT_12
|
||||
#define SIGRT_13 __SYS_SIGRT_13
|
||||
#define SIGRT_14 __SYS_SIGRT_14
|
||||
#define SIGRT_15 __SYS_SIGRT_15
|
||||
#define SIGRT_16 __SYS_SIGRT_16
|
||||
#define SIGRT_17 __SYS_SIGRT_17
|
||||
#define SIGRT_18 __SYS_SIGRT_18
|
||||
#define SIGRT_19 __SYS_SIGRT_19
|
||||
#define SIGRT_20 __SYS_SIGRT_20
|
||||
#define SIGRT_21 __SYS_SIGRT_21
|
||||
#define SIGRT_22 __SYS_SIGRT_22
|
||||
#define SIGRT_23 __SYS_SIGRT_23
|
||||
#define SIGRT_24 __SYS_SIGRT_24
|
||||
#define SIGRT_25 __SYS_SIGRT_25
|
||||
#define SIGRT_26 __SYS_SIGRT_26
|
||||
#define SIGRT_27 __SYS_SIGRT_27
|
||||
#define SIGRT_28 __SYS_SIGRT_28
|
||||
#define SIGRT_29 __SYS_SIGRT_29
|
||||
#define SIGRT_30 __SYS_SIGRT_30
|
||||
#define SIGRT_31 __SYS_SIGRT_31
|
||||
#define SIGRTMAX __SYS_SIGRTMAX
|
||||
#define SIGNAL_MAX __SYS_SIGNAL_MAX
|
||||
|
||||
/** @brief Interrupt from keyboard */
|
||||
#define SIGINT 2
|
||||
#define SIG_TERM __SYS_SIG_TERM
|
||||
// #define SIG_IGN __SYS_SIG_IGN
|
||||
#define SIG_CORE __SYS_SIG_CORE
|
||||
#define SIG_STOP __SYS_SIG_STOP
|
||||
#define SIG_CONT __SYS_SIG_CONT
|
||||
|
||||
/** @brief Quit from keyboard */
|
||||
#define SIGQUIT 3
|
||||
#define SIG_BLOCK __SYS_SIG_BLOCK
|
||||
#define SIG_UNBLOCK __SYS_SIG_UNBLOCK
|
||||
#define SIG_SETMASK __SYS_SIG_SETMASK
|
||||
|
||||
/** @brief Illegal Instruction */
|
||||
#define SIGILL 4
|
||||
#define SA_NOCLDSTOP __SYS_SA_NOCLDSTOP
|
||||
#define SA_ONSTACK __SYS_SA_ONSTACK
|
||||
#define SA_RESETHAND __SYS_SA_RESETHAND
|
||||
#define SA_RESTART __SYS_SA_RESTART
|
||||
#define SA_SIGINFO __SYS_SA_SIGINFO
|
||||
#define SA_NOCLDWAIT __SYS_SA_NOCLDWAIT
|
||||
#define SA_NODEFER __SYS_SA_NODEFER
|
||||
|
||||
/** @brief Trace/breakpoint trap */
|
||||
#define SIGTRAP 5
|
||||
#define SS_ONSTACK
|
||||
#define SS_DISABLE
|
||||
|
||||
/** @brief Abort signal from abort(3) */
|
||||
#define SIGABRT 6
|
||||
#define MINSIGSTKSZ
|
||||
#define SIGSTKSZ
|
||||
|
||||
/** @brief Bus error (bad memory access) */
|
||||
#define SIGBUS 7
|
||||
#define SIG_ERR ((void (*)(int))__SYS_SIG_ERR)
|
||||
#define SIG_DFL ((void (*)(int))__SYS_SIG_DFL)
|
||||
#define SIG_IGN ((void (*)(int))__SYS_SIG_IGN)
|
||||
|
||||
/** @brief Floating point exception */
|
||||
#define SIGFPE 8
|
||||
#define SIGEV_NONE
|
||||
#define SIGEV_SIGNAL
|
||||
#define SIGEV_THREAD
|
||||
|
||||
/** @brief Kill signal */
|
||||
#define SIGKILL 9
|
||||
typedef unsigned long sigset_t;
|
||||
|
||||
/** @brief User-defined signal 1 */
|
||||
#define SIGUSR1 10
|
||||
union sigval
|
||||
{
|
||||
int sival_int; /* Integer signal value. */
|
||||
void *sival_ptr; /* Pointer signal value. */
|
||||
};
|
||||
|
||||
/** @brief Invalid memory reference */
|
||||
#define SIGSEGV 11
|
||||
typedef struct siginfo_t
|
||||
{
|
||||
int si_signo; /* Signal number. */
|
||||
int si_code; /* Signal code. */
|
||||
|
||||
/** @brief User-defined signal 2 */
|
||||
#define SIGUSR2 12
|
||||
int si_errno; /* If non-zero, an errno value associated with */
|
||||
/* this signal, as described in <errno.h>. */
|
||||
|
||||
/** @brief Broken pipe: write to pipe with no readers */
|
||||
#define SIGPIPE 13
|
||||
pid_t si_pid; /* Sending process ID. */
|
||||
uid_t si_uid; /* Real user ID of sending process. */
|
||||
void *si_addr; /* Address that caused fault. */
|
||||
int si_status; /* Exit value or signal. */
|
||||
union sigval si_value; /* Signal value. */
|
||||
} siginfo_t;
|
||||
|
||||
/** @brief Timer signal from alarm(2) */
|
||||
#define SIGALRM 14
|
||||
typedef struct sigevent
|
||||
{
|
||||
int sigev_notify; /* Notification type. */
|
||||
int sigev_signo; /* Signal number. */
|
||||
union sigval sigev_value; /* Signal value. */
|
||||
void (*sigev_notify_function)(union sigval); /* Notification function. */
|
||||
pthread_attr_t *sigev_notify_attributes; /* Notification attributes. */
|
||||
} sigevent;
|
||||
|
||||
/** @brief Termination signal */
|
||||
#define SIGTERM 15
|
||||
struct sigaction
|
||||
{
|
||||
void (*sa_handler)(int); /* Pointer to a signal-catching function or one of the SIG_IGN or SIG_DFL. */
|
||||
sigset_t sa_mask; /* Set of signals to be blocked during execution of the signal handling function. */
|
||||
int sa_flags; /* Special flags. */
|
||||
void (*sa_sigaction)(int, siginfo_t *, void *); /* Pointer to a signal-catching function. */
|
||||
};
|
||||
|
||||
/** @brief Stack fault on coprocessor (unused) */
|
||||
#define SIGSTKFLT 16
|
||||
typedef struct stack_t
|
||||
{
|
||||
void *ss_sp; /* Stack base or pointer. */
|
||||
size_t ss_size; /* Stack size. */
|
||||
int ss_flags; /* Flags. */
|
||||
} stack_t;
|
||||
|
||||
/** @brief Child stopped or terminated */
|
||||
#define SIGCHLD 17
|
||||
typedef struct mcontext_t
|
||||
{
|
||||
__UINTPTR_TYPE__ gregs[32]; /* General-purpose registers. */
|
||||
__UINTPTR_TYPE__ sp; /* Stack pointer. */
|
||||
__UINTPTR_TYPE__ pc; /* Program counter. */
|
||||
__UINTPTR_TYPE__ pstate; /* Processor state. */
|
||||
} mcontext_t;
|
||||
|
||||
/** @brief Continue if stopped */
|
||||
#define SIGCONT 18
|
||||
typedef struct ucontext_t
|
||||
{
|
||||
struct ucontext_t *uc_link; /* Pointer to the context that is resumed when this context returns. */
|
||||
sigset_t uc_sigmask; /* The set of signals that are blocked when this context is active. */
|
||||
stack_t uc_stack; /* The stack used by this context. */
|
||||
mcontext_t uc_mcontext; /* A machine-specific representation of the saved context. */
|
||||
} ucontext_t;
|
||||
|
||||
/** @brief Stop process */
|
||||
#define SIGSTOP 19
|
||||
int kill(pid_t pid, int sig);
|
||||
int killpg(pid_t, int);
|
||||
void psiginfo(const siginfo_t *, const char *);
|
||||
void psignal(int, const char *);
|
||||
int pthread_kill(pthread_t, int);
|
||||
int pthread_sigmask(int, const sigset_t *restrict, sigset_t *restrict);
|
||||
int raise(int);
|
||||
int sig2str(int, char *);
|
||||
int sigaction(int, const struct sigaction *restrict, struct sigaction *restrict);
|
||||
int sigaddset(sigset_t *, int);
|
||||
int sigaltstack(const stack_t *restrict, stack_t *restrict);
|
||||
int sigdelset(sigset_t *, int);
|
||||
int sigemptyset(sigset_t *);
|
||||
int sigfillset(sigset_t *);
|
||||
int sigismember(const sigset_t *, int);
|
||||
void (*signal(int, void (*)(int)))(int);
|
||||
int sigpending(sigset_t *);
|
||||
int sigprocmask(int, const sigset_t *restrict, sigset_t *restrict);
|
||||
int sigqueue(pid_t, int, union sigval);
|
||||
int sigsuspend(const sigset_t *);
|
||||
int sigtimedwait(const sigset_t *restrict, siginfo_t *restrict, const struct timespec *restrict);
|
||||
int sigwait(const sigset_t *restrict, int *restrict);
|
||||
int sigwaitinfo(const sigset_t *restrict, siginfo_t *restrict);
|
||||
int str2sig(const char *restrict, int *restrict);
|
||||
|
||||
/** @brief Stop typed at terminal */
|
||||
#define SIGTSTP 20
|
||||
|
||||
/** @brief Terminal input for background process */
|
||||
#define SIGTTIN 21
|
||||
|
||||
/** @brief Terminal output for background process */
|
||||
#define SIGTTOU 22
|
||||
|
||||
/** @brief Urgent condition on socket */
|
||||
#define SIGURG 23
|
||||
|
||||
/** @brief CPU time limit exceeded */
|
||||
#define SIGXCPU 24
|
||||
|
||||
/** @brief File size limit exceeded */
|
||||
#define SIGXFSZ 25
|
||||
|
||||
/** @brief Virtual timer expired */
|
||||
#define SIGVTALRM 26
|
||||
|
||||
/** @brief Profiling timer expired */
|
||||
#define SIGPROF 27
|
||||
|
||||
/** @brief Window resize signal */
|
||||
#define SIGWINCH 28
|
||||
|
||||
/** @brief I/O now possible */
|
||||
#define SIGIO 29
|
||||
|
||||
/** @brief Power failure */
|
||||
#define SIGPWR 30
|
||||
|
||||
/** @brief Bad system call */
|
||||
#define SIGSYS 31
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // !_SIGNAL_H
|
||||
|
@ -1,45 +0,0 @@
|
||||
#ifndef _SPAWN_H
|
||||
#define _SPAWN_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <bits/types/struct_sched_param.h>
|
||||
#include <bits/types/sigset_t.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
struct __spawn_action
|
||||
{
|
||||
int __stub;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
short int __flags;
|
||||
pid_t __pgrp;
|
||||
sigset_t __sd;
|
||||
sigset_t __ss;
|
||||
struct sched_param __sp;
|
||||
int __policy;
|
||||
int __pad[16];
|
||||
} posix_spawnattr_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int __allocated;
|
||||
int __used;
|
||||
struct __spawn_action *__actions;
|
||||
int __pad[16];
|
||||
} posix_spawn_file_actions_t;
|
||||
|
||||
int posix_spawn(pid_t *pid, const char *path,
|
||||
const posix_spawn_file_actions_t *file_actions,
|
||||
const posix_spawnattr_t *attrp,
|
||||
char *const argv[],
|
||||
char *const envp[]);
|
||||
|
||||
int posix_spawnp(pid_t *pid, const char *file,
|
||||
const posix_spawn_file_actions_t *file_actions,
|
||||
const posix_spawnattr_t *attrp,
|
||||
char *const argv[],
|
||||
char *const envp[]);
|
||||
|
||||
#endif // !_SPAWN_H
|
@ -1,13 +1,37 @@
|
||||
/*
|
||||
This file is part of Fennix C Library.
|
||||
|
||||
Fennix C Library is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _STDARG_H
|
||||
#define _STDARG_H
|
||||
|
||||
#ifndef __va_list__
|
||||
typedef __builtin_va_list va_list;
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif // __cplusplus
|
||||
|
||||
#define va_start(ap, last) __builtin_va_start(ap, last)
|
||||
#define va_end(ap) __builtin_va_end(ap)
|
||||
#define va_arg(ap, type) __builtin_va_arg(ap, type)
|
||||
typedef __builtin_va_list va_list;
|
||||
|
||||
#define va_start(ap, param) __builtin_va_start(ap, param)
|
||||
#define va_copy(dest, src) __builtin_va_copy(dest, src)
|
||||
#define va_arg(ap, type) __builtin_va_arg(ap, type)
|
||||
#define va_end(ap) __builtin_va_end(ap)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // !_STDARG_H
|
||||
|
36
Userspace/libc/include/stdbool.h
Normal file
36
Userspace/libc/include/stdbool.h
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
This file is part of Fennix C Library.
|
||||
|
||||
Fennix C Library is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _STDBOOL_H
|
||||
#define _STDBOOL_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif // __cplusplus
|
||||
|
||||
#define bool _Bool
|
||||
#define true 1
|
||||
#define false 0
|
||||
|
||||
#define __bool_true_false_are_defined 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // !_STDBOOL_H
|
@ -1,47 +1,44 @@
|
||||
/*
|
||||
This file is part of Fennix C Library.
|
||||
|
||||
Fennix C Library is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _STDDEF_H
|
||||
#define _STDDEF_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define NULL 0
|
||||
#else
|
||||
extern "C"
|
||||
{
|
||||
#endif // __cplusplus
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL ((void *)0)
|
||||
#define bool _Bool
|
||||
#endif
|
||||
|
||||
typedef __INT8_TYPE__ int8_t;
|
||||
typedef __INT16_TYPE__ int16_t;
|
||||
typedef __INT32_TYPE__ int32_t;
|
||||
typedef __INT64_TYPE__ int64_t;
|
||||
typedef __UINT8_TYPE__ uint8_t;
|
||||
typedef __UINT16_TYPE__ uint16_t;
|
||||
typedef __UINT32_TYPE__ uint32_t;
|
||||
typedef __UINT64_TYPE__ uint64_t;
|
||||
typedef struct
|
||||
{
|
||||
long long __a;
|
||||
long double __b;
|
||||
} max_align_t;
|
||||
|
||||
typedef __INT_LEAST8_TYPE__ int_least8_t;
|
||||
typedef __INT_LEAST16_TYPE__ int_least16_t;
|
||||
typedef __INT_LEAST32_TYPE__ int_least32_t;
|
||||
typedef __INT_LEAST64_TYPE__ int_least64_t;
|
||||
typedef __UINT_LEAST8_TYPE__ uint_least8_t;
|
||||
typedef __UINT_LEAST16_TYPE__ uint_least16_t;
|
||||
typedef __UINT_LEAST32_TYPE__ uint_least32_t;
|
||||
typedef __UINT_LEAST64_TYPE__ uint_least64_t;
|
||||
typedef __PTRDIFF_TYPE__ ptrdiff_t;
|
||||
typedef __WCHAR_TYPE__ wchar_t;
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
|
||||
typedef __INT_FAST8_TYPE__ int_fast8_t;
|
||||
typedef __INT_FAST16_TYPE__ int_fast16_t;
|
||||
typedef __INT_FAST32_TYPE__ int_fast32_t;
|
||||
typedef __INT_FAST64_TYPE__ int_fast64_t;
|
||||
typedef __UINT_FAST8_TYPE__ uint_fast8_t;
|
||||
typedef __UINT_FAST16_TYPE__ uint_fast16_t;
|
||||
typedef __UINT_FAST32_TYPE__ uint_fast32_t;
|
||||
typedef __UINT_FAST64_TYPE__ uint_fast64_t;
|
||||
|
||||
typedef __INTPTR_TYPE__ intptr_t;
|
||||
typedef __UINTPTR_TYPE__ uintptr_t;
|
||||
|
||||
typedef __INTMAX_TYPE__ intmax_t;
|
||||
typedef __UINTMAX_TYPE__ uintmax_t;
|
||||
|
||||
typedef __PTRDIFF_TYPE__ ptrdiff_t;
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // !_STDDEF_H
|
||||
|
@ -1,6 +1,32 @@
|
||||
/*
|
||||
This file is part of Fennix C Library.
|
||||
|
||||
Fennix C Library is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _STDINT_H
|
||||
#define _STDINT_H
|
||||
|
||||
#include <types.h>
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif // __cplusplus
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // !_STDINT_H
|
||||
|
@ -1,87 +1,156 @@
|
||||
/*
|
||||
This file is part of Fennix C Library.
|
||||
|
||||
Fennix C Library is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _STDIO_H
|
||||
#define _STDIO_H
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#define SEEK_SET 0
|
||||
#define SEEK_CUR 1
|
||||
#define SEEK_END 2
|
||||
|
||||
/**
|
||||
* @brief EOF - End of file
|
||||
*
|
||||
* The value returned by several functions to indicate the end of file.
|
||||
*/
|
||||
#define EOF (-1)
|
||||
|
||||
struct _IO_marker
|
||||
{
|
||||
struct _IO_marker *_next;
|
||||
struct _IO_FILE *_sbuf;
|
||||
int _pos;
|
||||
};
|
||||
|
||||
struct _IO_FILE
|
||||
{
|
||||
int _flags;
|
||||
|
||||
char *_IO_read_ptr;
|
||||
char *_IO_read_end;
|
||||
char *_IO_read_base;
|
||||
char *_IO_write_base;
|
||||
char *_IO_write_ptr;
|
||||
char *_IO_write_end;
|
||||
char *_IO_buf_base;
|
||||
char *_IO_buf_end;
|
||||
|
||||
__off_t _offset;
|
||||
|
||||
struct _IO_marker *_markers;
|
||||
struct _IO_FILE *_chain;
|
||||
int _fileno;
|
||||
};
|
||||
|
||||
typedef struct _IO_FILE FILE;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif // __cplusplus
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#define BUFSIZ 512
|
||||
#define FILENAME_MAX 255
|
||||
#define FOPEN_MAX 8
|
||||
#define _IOFBF 0
|
||||
#define _IOLBF 1
|
||||
#define _IONBF 2
|
||||
#define L_ctermid 20
|
||||
#define L_cuserid 20
|
||||
#define L_tmpnam 255
|
||||
#define SEEK_CUR 1
|
||||
#define SEEK_END 2
|
||||
#define SEEK_SET 0
|
||||
#define TMP_MAX 10000
|
||||
|
||||
#define EOF (-1)
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL ((void *)0)
|
||||
#endif
|
||||
|
||||
#define P_tmpdir "/tmp/"
|
||||
|
||||
typedef long fpos_t;
|
||||
typedef unsigned long size_t;
|
||||
|
||||
struct _IO_FILE
|
||||
{
|
||||
int fd;
|
||||
char *buffer;
|
||||
size_t buffer_size;
|
||||
size_t buffer_pos;
|
||||
int flags;
|
||||
int error;
|
||||
int eof;
|
||||
};
|
||||
|
||||
#define _i_READ 1
|
||||
#define _i_WRITE 2
|
||||
extern struct _IO_FILE *_i_open_files[256];
|
||||
|
||||
typedef struct _IO_FILE FILE;
|
||||
|
||||
extern char *optarg;
|
||||
extern int opterr;
|
||||
extern int optind;
|
||||
extern int optopt;
|
||||
|
||||
extern FILE *stdin;
|
||||
extern FILE *stdout;
|
||||
extern FILE *stderr;
|
||||
|
||||
#define stdin stdin
|
||||
#define stdout stdout
|
||||
#define stderr stderr
|
||||
|
||||
FILE *freopen(const char *filename, const char *mode, FILE *stream);
|
||||
FILE *fopen(const char *filename, const char *mode);
|
||||
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
|
||||
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
|
||||
off_t fseek(FILE *stream, long offset, int whence);
|
||||
long ftell(FILE *stream);
|
||||
int fclose(FILE *fp);
|
||||
void clearerr(FILE *);
|
||||
char *ctermid(char *);
|
||||
int dprintf(int, const char *restrict, ...);
|
||||
int fclose(FILE *stream);
|
||||
FILE *fdopen(int, const char *);
|
||||
int feof(FILE *);
|
||||
int ferror(FILE *);
|
||||
int fflush(FILE *stream);
|
||||
int fprintf(FILE *stream, const char *format, ...);
|
||||
int printf(const char *format, ...);
|
||||
void setbuf(FILE *stream, char *buf);
|
||||
int vfprintf(FILE *stream, const char *format, va_list arg);
|
||||
int vsscanf(const char *s, const char *format, va_list arg);
|
||||
int sscanf(const char *s, const char *format, ...);
|
||||
|
||||
int fgetc(FILE *);
|
||||
int fgetpos(FILE *restrict, fpos_t *restrict);
|
||||
char *fgets(char *restrict, int, FILE *restrict);
|
||||
int fileno(FILE *);
|
||||
void flockfile(FILE *);
|
||||
FILE *fmemopen(void *restrict, size_t, const char *restrict);
|
||||
FILE *fopen(const char *restrict pathname, const char *restrict mode);
|
||||
int fprintf(FILE *restrict, const char *restrict, ...);
|
||||
int fputc(int c, FILE *stream);
|
||||
int fputs(const char *restrict s, FILE *restrict stream);
|
||||
size_t fread(void *restrict ptr, size_t size, size_t nitems, FILE *restrict stream);
|
||||
FILE *freopen(const char *restrict, const char *restrict, FILE *restrict);
|
||||
int fscanf(FILE *restrict, const char *restrict, ...);
|
||||
int fseek(FILE *stream, long offset, int whence);
|
||||
int fseeko(FILE *, off_t, int);
|
||||
int fsetpos(FILE *, const fpos_t *);
|
||||
long ftell(FILE *);
|
||||
off_t ftello(FILE *);
|
||||
int ftrylockfile(FILE *);
|
||||
void funlockfile(FILE *);
|
||||
size_t fwrite(const void *restrict ptr, size_t size, size_t nitems, FILE *restrict stream);
|
||||
int getc(FILE *);
|
||||
int getchar(void);
|
||||
int getc_unlocked(FILE *);
|
||||
int getchar_unlocked(void);
|
||||
ssize_t getdelim(char **restrict, size_t *restrict, int, FILE *restrict);
|
||||
ssize_t getline(char **restrict, size_t *restrict, FILE *restrict);
|
||||
FILE *open_memstream(char **, size_t *);
|
||||
int pclose(FILE *);
|
||||
void perror(const char *);
|
||||
FILE *popen(const char *, const char *);
|
||||
int printf(const char *restrict format, ...);
|
||||
int putc(int c, FILE *stream);
|
||||
int fputs(const char *s, FILE *stream);
|
||||
int puts(const char *s);
|
||||
int putchar(int c);
|
||||
|
||||
int fgetc(FILE *stream);
|
||||
int putc_unlocked(int c, FILE *stream);
|
||||
int putchar_unlocked(int c);
|
||||
int puts(const char *s);
|
||||
int remove(const char *);
|
||||
int rename(const char *, const char *);
|
||||
int renameat(int, const char *, int, const char *);
|
||||
void rewind(FILE *);
|
||||
int scanf(const char *restrict, ...);
|
||||
void setbuf(FILE *restrict, char *restrict);
|
||||
int setvbuf(FILE *restrict, char *restrict, int, size_t);
|
||||
int snprintf(char *restrict, size_t, const char *restrict, ...);
|
||||
int sprintf(char *restrict, const char *restrict, ...);
|
||||
int sscanf(const char *restrict, const char *restrict, ...);
|
||||
FILE *tmpfile(void);
|
||||
char *tmpnam(char *);
|
||||
int ungetc(int, FILE *);
|
||||
int vdprintf(int, const char *restrict, va_list);
|
||||
int vfprintf(FILE *restrict, const char *restrict, va_list);
|
||||
int vfscanf(FILE *restrict, const char *restrict, va_list);
|
||||
int vprintf(const char *restrict, va_list);
|
||||
int vscanf(const char *restrict, va_list);
|
||||
int vsnprintf(char *restrict, size_t, const char *restrict, va_list);
|
||||
int vsprintf(char *restrict, const char *restrict, va_list);
|
||||
int vsscanf(const char *restrict, const char *restrict, va_list);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif
|
||||
#endif // !_STDIO_H
|
||||
|
@ -1,34 +1,115 @@
|
||||
/*
|
||||
This file is part of Fennix C Library.
|
||||
|
||||
Fennix C Library is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _STDLIB_H
|
||||
#define _STDLIB_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
#endif // __cplusplus
|
||||
|
||||
#include <stddef.h>
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#define EXIT_FAILURE 1
|
||||
#define EXIT_SUCCESS 0
|
||||
#define NULL ((void *)0)
|
||||
#define RAND_MAX 32767
|
||||
|
||||
#define MB_CUR_MAX 4
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int quot;
|
||||
int rem;
|
||||
} div_t;
|
||||
typedef struct
|
||||
{
|
||||
long quot;
|
||||
long rem;
|
||||
} ldiv_t;
|
||||
|
||||
typedef unsigned long size_t;
|
||||
// typedef __WCHAR_TYPE__ wchar_t;
|
||||
|
||||
long a64l(const char *);
|
||||
void abort(void);
|
||||
int atexit(void (*function)(void));
|
||||
int abs(int);
|
||||
int atexit(void (*func)(void));
|
||||
double atof(const char *);
|
||||
int atoi(const char *);
|
||||
long int atol(const char *);
|
||||
void *bsearch(const void *, const void *, size_t, size_t, int (*)(const void *, const void *));
|
||||
void *calloc(size_t, size_t);
|
||||
div_t div(int, int);
|
||||
double drand48(void);
|
||||
char *ecvt(double, int, int *, int *);
|
||||
double erand48(unsigned short int[3]);
|
||||
void exit(int status);
|
||||
int atoi(const char *nptr);
|
||||
char *getenv(const char *name);
|
||||
|
||||
void *malloc(size_t Size);
|
||||
void *realloc(void *Address, size_t Size);
|
||||
void *calloc(size_t Count, size_t Size);
|
||||
void free(void *Address);
|
||||
int system(const char *command);
|
||||
|
||||
double atof(const char *nptr);
|
||||
|
||||
extern void perror(const char *s);
|
||||
char *fcvt(double, int, int *, int *);
|
||||
void free(void *ptr);
|
||||
char *gcvt(double, int, char *);
|
||||
char *getenv(const char *);
|
||||
int getsubopt(char **, char *const *, char **);
|
||||
int grantpt(int);
|
||||
char *initstate(unsigned int, char *, size_t);
|
||||
long int jrand48(unsigned short int[3]);
|
||||
char *l64a(long);
|
||||
long int labs(long int);
|
||||
void lcong48(unsigned short int[7]);
|
||||
ldiv_t ldiv(long int, long int);
|
||||
long int lrand48(void);
|
||||
void *malloc(size_t size);
|
||||
int mblen(const char *, size_t);
|
||||
size_t mbstowcs(wchar_t *, const char *, size_t);
|
||||
int mbtowc(wchar_t *, const char *, size_t);
|
||||
char *mktemp(char *);
|
||||
int mkstemp(char *);
|
||||
long int mrand48(void);
|
||||
long int nrand48(unsigned short int[3]);
|
||||
char *ptsname(int);
|
||||
int putenv(char *);
|
||||
void qsort(void *, size_t, size_t, int (*)(const void *, const void *));
|
||||
int rand(void);
|
||||
int rand_r(unsigned int *);
|
||||
long random(void);
|
||||
void *realloc(void *, size_t);
|
||||
char *realpath(const char *, char *);
|
||||
unsigned short int seed48(unsigned short int[3]);
|
||||
void setkey(const char *);
|
||||
char *setstate(const char *);
|
||||
void srand(unsigned int);
|
||||
void srand48(long int);
|
||||
void srandom(unsigned);
|
||||
double strtod(const char *, char **);
|
||||
long int strtol(const char *, char **, int);
|
||||
unsigned long int strtoul(const char *, char **, int);
|
||||
int system(const char *);
|
||||
int ttyslot(void);
|
||||
int unlockpt(int);
|
||||
void *valloc(size_t);
|
||||
size_t wcstombs(char *, const wchar_t *, size_t);
|
||||
int wctomb(char *, wchar_t);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif
|
||||
#endif // !_STDLIB_H
|
||||
|
@ -1,30 +1,71 @@
|
||||
/*
|
||||
This file is part of Fennix C Library.
|
||||
|
||||
Fennix C Library is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _STRING_H
|
||||
#define _STRING_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
#endif // __cplusplus
|
||||
|
||||
size_t strlen(const char *str);
|
||||
int strcmp(const char *l, const char *r);
|
||||
int strncmp(const char *s1, const char *s2, size_t n);
|
||||
int strcasecmp(const char *s1, const char *s2);
|
||||
int strncasecmp(const char *string1, const char *string2, size_t count);
|
||||
char *strstr(const char *haystack, const char *needle);
|
||||
char *strncpy(char *destination, const char *source, unsigned long num);
|
||||
char *strdup(const char *s);
|
||||
char *strchr(char const *s, int c);
|
||||
char *strrchr(char const *s, int c);
|
||||
#include <stddef.h>
|
||||
#include <locale.h>
|
||||
|
||||
void *memcpy(void *dest, const void *src, size_t n);
|
||||
void *memset(void *dest, int c, size_t n);
|
||||
void *memmove(void *dest, const void *src, size_t n);
|
||||
void *memccpy(void *restrict, const void *restrict, int, size_t);
|
||||
void *memchr(const void *, int, size_t);
|
||||
int memcmp(const void *, const void *, size_t);
|
||||
void *memcpy(void *restrict s1, const void *restrict s2, size_t n);
|
||||
void *memmem(const void *, size_t, const void *, size_t);
|
||||
void *memmove(void *, const void *, size_t);
|
||||
void *memset(void *, int, size_t);
|
||||
char *stpcpy(char *restrict, const char *restrict);
|
||||
char *stpncpy(char *restrict, const char *restrict, size_t);
|
||||
char *strcat(char *restrict, const char *restrict);
|
||||
char *strchr(const char *, int);
|
||||
int strcmp(const char *s1, const char *s2);
|
||||
int strcoll(const char *, const char *);
|
||||
int strcoll_l(const char *, const char *, locale_t);
|
||||
char *strcpy(char *restrict, const char *restrict);
|
||||
size_t strcspn(const char *, const char *);
|
||||
char *strdup(const char *);
|
||||
char *strerror(int);
|
||||
char *strerror_l(int, locale_t);
|
||||
int strerror_r(int, char *, size_t);
|
||||
size_t strlcat(char *restrict, const char *restrict, size_t);
|
||||
size_t strlcpy(char *restrict, const char *restrict, size_t);
|
||||
size_t strlen(const char *);
|
||||
char *strncat(char *restrict, const char *restrict, size_t);
|
||||
int strncmp(const char *, const char *, size_t);
|
||||
char *strncpy(char *restrict, const char *restrict, size_t);
|
||||
char *strndup(const char *, size_t);
|
||||
size_t strnlen(const char *, size_t);
|
||||
char *strpbrk(const char *, const char *);
|
||||
char *strrchr(const char *, int);
|
||||
char *strsignal(int);
|
||||
size_t strspn(const char *, const char *);
|
||||
char *strstr(const char *, const char *);
|
||||
char *strtok(char *restrict, const char *restrict);
|
||||
char *strtok_r(char *restrict, const char *restrict, char **restrict);
|
||||
size_t strxfrm(char *restrict, const char *restrict, size_t);
|
||||
size_t strxfrm_l(char *restrict, const char *restrict, size_t, locale_t);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif
|
||||
#endif // !_STRING_H
|
||||
|
@ -1,4 +0,0 @@
|
||||
#ifndef _STRINGS_H
|
||||
#define _STRINGS_H
|
||||
|
||||
#endif // !_STRINGS_H
|
73
Userspace/libc/include/sys/mman.h
Normal file
73
Userspace/libc/include/sys/mman.h
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
This file is part of Fennix C Library.
|
||||
|
||||
Fennix C Library is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _SYS_MMAN_H
|
||||
#define _SYS_MMAN_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif // __cplusplus
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#define PROT_READ 0x1
|
||||
#define PROT_WRITE 0x2
|
||||
#define PROT_EXEC 0x4
|
||||
#define PROT_NONE 0x0
|
||||
|
||||
#define MAP_SHARED 0x01
|
||||
#define MAP_PRIVATE 0x02
|
||||
#define MAP_FIXED 0x4
|
||||
#define MAP_ANONYMOUS 0x8
|
||||
#define MAP_ANON MAP_ANONYMOUS
|
||||
|
||||
#define MS_ASYNC 0x01
|
||||
#define MS_SYNC 0x02
|
||||
#define MS_INVALIDATE 0x04
|
||||
|
||||
#define MCL_CURRENT 0x01
|
||||
#define MCL_FUTURE 0x02
|
||||
|
||||
#define MAP_FAILED ((void *)-1)
|
||||
|
||||
typedef struct posix_typed_mem_info
|
||||
{
|
||||
/* Maximum length which may be allocated from a typed memory object. */
|
||||
size_t posix_tmi_length;
|
||||
} posix_typed_mem_info;
|
||||
|
||||
int mlock(const void *, size_t);
|
||||
int mlockall(int);
|
||||
void *mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off);
|
||||
int mprotect(void *addr, size_t len, int prot);
|
||||
int msync(void *, size_t, int);
|
||||
int munlock(const void *, size_t);
|
||||
int munlockall(void);
|
||||
int munmap(void *addr, size_t len);
|
||||
int posix_madvise(void *, size_t, int);
|
||||
int posix_mem_offset(const void *restrict, size_t, off_t *restrict, size_t *restrict, int *restrict);
|
||||
int posix_typed_mem_get_info(int, struct posix_typed_mem_info *);
|
||||
int posix_typed_mem_open(const char *, int, int);
|
||||
int shm_open(const char *, int, mode_t);
|
||||
int shm_unlink(const char *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // !_SYS_MMAN_H
|
@ -1,18 +1,108 @@
|
||||
/*
|
||||
This file is part of Fennix C Library.
|
||||
|
||||
Fennix C Library is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _SYS_STAT_H
|
||||
#define _SYS_STAT_H
|
||||
|
||||
typedef unsigned int __dev_t;
|
||||
typedef unsigned short __ino_t;
|
||||
typedef unsigned short __mode_t;
|
||||
typedef long __off_t;
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif // __cplusplus
|
||||
|
||||
#define dev_t __dev_t
|
||||
#define ino_t __ino_t
|
||||
#define mode_t __mode_t
|
||||
#define off_t __off_t
|
||||
#include <time.h>
|
||||
|
||||
int mkdir(const char *path, mode_t mode);
|
||||
int remove(const char *pathname);
|
||||
int rename(const char *oldpath, const char *newpath);
|
||||
struct stat
|
||||
{
|
||||
dev_t st_dev; /* Device ID of device containing file. */
|
||||
ino_t st_ino; /* File serial number. */
|
||||
mode_t st_mode; /* Mode of file (see below). */
|
||||
nlink_t st_nlink; /* Number of hard links to the file. */
|
||||
uid_t st_uid; /* User ID of file. */
|
||||
gid_t st_gid; /* Group ID of file. */
|
||||
dev_t st_rdev; /* Device ID (if file is character or block special). */
|
||||
off_t st_size; /* For regular files, the file size in bytes. For symbolic links, the length in bytes of the pathname contained in the symbolic link. For a shared memory object, the length in bytes. For a typed memory object, the length in bytes. For other file types, the use of this field is unspecified. */
|
||||
struct timespec st_atim; /* Last data access timestamp. */
|
||||
struct timespec st_mtim; /* Last data modification timestamp. */
|
||||
struct timespec st_ctim; /* Last file status change timestamp. */
|
||||
blksize_t st_blksize; /* A file system-specific preferred I/O block size for this object. In some file system types, this may vary from file to file. */
|
||||
blkcnt_t st_blocks; /* Number of blocks allocated for this object. */
|
||||
};
|
||||
|
||||
#endif
|
||||
#define S_IFMT
|
||||
#define S_IFBLK
|
||||
#define S_IFCHR
|
||||
#define S_IFIFO
|
||||
#define S_IFREG
|
||||
#define S_IFDIR
|
||||
#define S_IFLNK
|
||||
#define S_IFSOCK
|
||||
|
||||
#define S_IRWXU 0700
|
||||
#define S_IRUSR 0400
|
||||
#define S_IWUSR 0200
|
||||
#define S_IXUSR 0100
|
||||
#define S_IRWXG 070
|
||||
#define S_IRGRP 040
|
||||
#define S_IWGRP 020
|
||||
#define S_IXGRP 010
|
||||
#define S_IRWXO 07
|
||||
#define S_IROTH 04
|
||||
#define S_IWOTH 02
|
||||
#define S_IXOTH 01
|
||||
|
||||
#define S_ISUID 04000
|
||||
#define S_ISGID 02000
|
||||
#define S_ISVTX 01000
|
||||
|
||||
#define S_ISBLK(m)
|
||||
#define S_ISCHR(m)
|
||||
#define S_ISDIR(m)
|
||||
#define S_ISFIFO(m)
|
||||
#define S_ISREG(m)
|
||||
#define S_ISLNK(m)
|
||||
#define S_ISSOCK(m)
|
||||
|
||||
#define S_TYPEISMQ(buf)
|
||||
#define S_TYPEISSEM(buf)
|
||||
#define S_TYPEISSHM(buf)
|
||||
#define S_TYPEISTMO(buf)
|
||||
|
||||
#define UTIME_NOW
|
||||
#define UTIME_OMIT
|
||||
|
||||
int chmod(const char *, mode_t);
|
||||
int fchmod(int, mode_t);
|
||||
int fchmodat(int, const char *, mode_t, int);
|
||||
int fstat(int, struct stat *);
|
||||
int fstatat(int, const char *restrict, struct stat *restrict, int);
|
||||
int futimens(int, const struct timespec[2]);
|
||||
int lstat(const char *restrict, struct stat *restrict);
|
||||
int mkdir(const char *, mode_t);
|
||||
int mkdirat(int, const char *, mode_t);
|
||||
int mkfifo(const char *, mode_t);
|
||||
int mkfifoat(int, const char *, mode_t);
|
||||
int mknod(const char *, mode_t, dev_t);
|
||||
int mknodat(int, const char *, mode_t, dev_t);
|
||||
int stat(const char *restrict, struct stat *restrict);
|
||||
mode_t umask(mode_t);
|
||||
int utimensat(int, const char *, const struct timespec[2], int);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // !_SYS_STAT_H
|
||||
|
@ -1,6 +0,0 @@
|
||||
#ifndef _SYS_TIME_H
|
||||
#define _SYS_TIME_H
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#endif
|
@ -1,37 +1,141 @@
|
||||
/*
|
||||
This file is part of Fennix C Library.
|
||||
|
||||
Fennix C Library is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _SYS_TYPES_H
|
||||
#define _SYS_TYPES_H
|
||||
|
||||
#ifndef PUBLIC
|
||||
#define PUBLIC __attribute__((visibility("default")))
|
||||
#endif // !PUBLIC
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif // __cplusplus
|
||||
|
||||
#ifndef PRIVATE
|
||||
#define PRIVATE __attribute__((visibility("hidden")))
|
||||
#endif // !PRIVATE
|
||||
#define __iptr __INTPTR_TYPE__
|
||||
__iptr __check_errno(__iptr status, __iptr err);
|
||||
|
||||
typedef int __pid_t;
|
||||
typedef int __ssize_t;
|
||||
typedef unsigned int __id_t;
|
||||
typedef unsigned int __useconds_t;
|
||||
#ifndef restrict
|
||||
#define restrict __restrict__
|
||||
#endif // restrict
|
||||
|
||||
#ifndef __pid_t_defined
|
||||
typedef __pid_t pid_t;
|
||||
#define __pid_t_defined
|
||||
#ifndef export
|
||||
#define export __attribute__((__visibility__("default")))
|
||||
#endif // export
|
||||
|
||||
typedef long blkcnt_t;
|
||||
|
||||
typedef long blksize_t;
|
||||
|
||||
typedef long clock_t;
|
||||
typedef int clockid_t;
|
||||
|
||||
typedef unsigned long dev_t;
|
||||
|
||||
typedef unsigned long fsblkcnt_t;
|
||||
typedef unsigned long fsfilcnt_t;
|
||||
|
||||
typedef unsigned int gid_t;
|
||||
typedef unsigned int id_t;
|
||||
typedef unsigned long ino_t;
|
||||
typedef unsigned short reclen_t;
|
||||
|
||||
typedef int key_t;
|
||||
|
||||
typedef unsigned int mode_t;
|
||||
typedef unsigned int nlink_t;
|
||||
|
||||
typedef long off_t;
|
||||
|
||||
typedef int pid_t;
|
||||
|
||||
typedef struct pthread_attr_t
|
||||
{
|
||||
char __data;
|
||||
} pthread_attr_t;
|
||||
|
||||
typedef struct pthread_cond_t
|
||||
{
|
||||
char __data;
|
||||
} pthread_cond_t;
|
||||
|
||||
typedef struct pthread_condattr_t
|
||||
{
|
||||
char __data;
|
||||
} pthread_condattr_t;
|
||||
|
||||
typedef unsigned int pthread_key_t;
|
||||
|
||||
typedef struct pthread_mutex_t
|
||||
{
|
||||
short locked;
|
||||
char __data;
|
||||
} pthread_mutex_t;
|
||||
|
||||
typedef struct pthread_mutexattr_t
|
||||
{
|
||||
char __data;
|
||||
} pthread_mutexattr_t;
|
||||
|
||||
typedef struct pthread_once_t
|
||||
{
|
||||
int __initialized;
|
||||
} pthread_once_t;
|
||||
|
||||
typedef struct pthread_rwlock_t
|
||||
{
|
||||
char __data;
|
||||
} pthread_rwlock_t;
|
||||
|
||||
typedef struct pthread_rwlockattr_t
|
||||
{
|
||||
char __data;
|
||||
} pthread_rwlockattr_t;
|
||||
|
||||
typedef struct pthread_barrier_t
|
||||
{
|
||||
char __data;
|
||||
} pthread_barrier_t;
|
||||
|
||||
typedef unsigned long size_t;
|
||||
typedef long ssize_t;
|
||||
|
||||
typedef long suseconds_t;
|
||||
typedef long time_t;
|
||||
|
||||
typedef int timer_t;
|
||||
|
||||
typedef unsigned int uid_t;
|
||||
typedef unsigned int useconds_t;
|
||||
|
||||
typedef struct __pthread
|
||||
{
|
||||
struct __pthread *Self;
|
||||
/* For __tls_get_addr */
|
||||
__UINTPTR_TYPE__ *Storage;
|
||||
|
||||
int CurrentError;
|
||||
} __pthread;
|
||||
|
||||
#ifdef __cplusplus
|
||||
typedef unsigned long pthread_t;
|
||||
#else
|
||||
typedef struct __pthread *pthread_t;
|
||||
#endif
|
||||
|
||||
#ifndef __id_t_defined
|
||||
typedef __id_t id_t;
|
||||
#define __id_t_defined
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
||||
|
||||
#ifndef __useconds_t_defined
|
||||
typedef __useconds_t useconds_t;
|
||||
#define __useconds_t_defined
|
||||
#endif
|
||||
|
||||
#ifndef __ssize_t_defined
|
||||
typedef __ssize_t ssize_t;
|
||||
#define __ssize_t_defined
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif // !_SYS_TYPES_H
|
||||
|
@ -1,108 +1,65 @@
|
||||
/*
|
||||
This file is part of Fennix C Library.
|
||||
|
||||
Fennix C Library is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _SYS_WAIT_H
|
||||
#define _SYS_WAIT_H
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
typedef enum
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
P_ALL, /* Wait for any child. */
|
||||
P_PID, /* Wait for specified process. */
|
||||
P_PGID /* Wait for members of process group. */
|
||||
} idtype_t;
|
||||
#endif // __cplusplus
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int stub;
|
||||
} siginfo_t;
|
||||
#include <signal.h>
|
||||
|
||||
#include <bits/waitstatus.h>
|
||||
/* waitpid() */
|
||||
#define WCONTINUED 0x00000008
|
||||
#define WNOHANG 0x00000001
|
||||
#define WUNTRACED 0x00000002
|
||||
|
||||
#define WCONTINUED 1
|
||||
#define WNOHANG 2
|
||||
#define WUNTRACED 4
|
||||
#define WEXITED 8
|
||||
#define WNOWAIT 16
|
||||
#define WSTOPPED 32
|
||||
/* waitid() */
|
||||
#define WEXITED 0x00000004
|
||||
#define WNOWAIT 0x00000020
|
||||
#define WSTOPPED 0x00000002
|
||||
|
||||
/**
|
||||
* @brief Macro for extracting the exit status from a status value.
|
||||
*
|
||||
* If the child process terminated normally by calling exit(3) or _exit(2),
|
||||
* the macro WEXITSTATUS() returns the low-order 8 bits of the status value.
|
||||
*
|
||||
* @param status The status value to extract the exit status from.
|
||||
* @return The exit status of the child process.
|
||||
*/
|
||||
#define WEXITSTATUS(status) __WEXITSTATUS(status)
|
||||
#define WCOREDUMP(status) ((status) & 0x80)
|
||||
#define WEXITSTATUS(status) (((status) >> 8) & 0xFF)
|
||||
#define WIFCONTINUED(status) ((status) == 0xFFFF)
|
||||
#define WIFEXITED(status) (((status) & 0x7F) == 0)
|
||||
#define WIFSIGNALED(status) (((status) & 0x7F) > 0 && (((status) & 0x7F) != 0x7F))
|
||||
#define WIFSTOPPED(status) (((status) & 0xFF) == 0x7F)
|
||||
#define WSTOPSIG(status) WEXITSTATUS(status)
|
||||
#define WTERMSIG(status) ((status) & 0x7F)
|
||||
|
||||
/**
|
||||
* @brief Macro for extracting the termination signal from a status value.
|
||||
*
|
||||
* If the child process was terminated by a signal, the macro WTERMSIG()
|
||||
* returns the signal number of the terminating signal.
|
||||
*
|
||||
* @param status The status value to extract the termination signal from.
|
||||
* @return The termination signal of the child process.
|
||||
*/
|
||||
#define WTERMSIG(status) __WTERMSIG(status)
|
||||
typedef enum
|
||||
{
|
||||
P_ALL,
|
||||
P_PGID,
|
||||
P_PID
|
||||
} idtype_t;
|
||||
|
||||
/**
|
||||
* @brief Macro for extracting the stop signal from a status value.
|
||||
*
|
||||
* If the child process was stopped by a signal, the macro WSTOPSIG()
|
||||
* returns the signal number of the stop signal.
|
||||
*
|
||||
* @param status The status value to extract the stop signal from.
|
||||
* @return The stop signal of the child process.
|
||||
*/
|
||||
#define WSTOPSIG(status) __WSTOPSIG(status)
|
||||
typedef unsigned int id_t;
|
||||
typedef int pid_t;
|
||||
|
||||
/**
|
||||
* @brief Macro for testing whether a process exited normally.
|
||||
*
|
||||
* If the child process terminated normally by calling exit(3) or _exit(2),
|
||||
* the macro WIFEXITED() returns a nonzero value. Otherwise, it returns 0.
|
||||
*
|
||||
* @param status The status value to test.
|
||||
* @return A nonzero value if the child process exited normally, 0 otherwise.
|
||||
*/
|
||||
#define WIFEXITED(status) __WIFEXITED(status)
|
||||
pid_t wait(int *);
|
||||
int waitid(idtype_t, id_t, siginfo_t *, int);
|
||||
pid_t waitpid(pid_t, int *, int);
|
||||
|
||||
/**
|
||||
* @brief Macro for testing whether a process was terminated by a signal.
|
||||
*
|
||||
* If the child process was terminated by a signal, the macro WIFSIGNALED()
|
||||
* returns a nonzero value. Otherwise, it returns 0.
|
||||
*
|
||||
* @param status The status value to test.
|
||||
* @return A nonzero value if the child process was terminated by a signal, 0 otherwise.
|
||||
*/
|
||||
#define WIFSIGNALED(status) __WIFSIGNALED(status)
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
||||
|
||||
/**
|
||||
* @brief Macro for testing whether a process was stopped by a signal.
|
||||
*
|
||||
* If the child process was stopped by a signal, the macro WIFSTOPPED()
|
||||
* returns a nonzero value. Otherwise, it returns 0.
|
||||
*
|
||||
* @param status The status value to test.
|
||||
* @return A nonzero value if the child process was stopped by a signal, 0 otherwise.
|
||||
*/
|
||||
#define WIFSTOPPED(status) __WIFSTOPPED(status)
|
||||
|
||||
/**
|
||||
* @brief Macro for testing whether a stopped process was continued.
|
||||
*
|
||||
* If the child process was stopped and has been resumed by delivery of SIGCONT,
|
||||
* the macro WIFCONTINUED() returns a nonzero value. Otherwise, it returns 0.
|
||||
*
|
||||
* @param status The status value to test.
|
||||
* @return A nonzero value if the child process was continued, 0 otherwise.
|
||||
*/
|
||||
#define WIFCONTINUED(status) __WIFCONTINUED(status)
|
||||
|
||||
pid_t wait(int *wstatus);
|
||||
pid_t waitpid(pid_t pid, int *wstatus, int options);
|
||||
int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options);
|
||||
|
||||
#endif
|
||||
#endif // !_SYS_WAIT_H
|
||||
|
@ -1,4 +1,96 @@
|
||||
/*
|
||||
This file is part of Fennix C Library.
|
||||
|
||||
Fennix C Library is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _TIME_H
|
||||
#define _TIME_H
|
||||
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif // __cplusplus
|
||||
|
||||
#include <bits/types/timespec.h>
|
||||
#include <sys/types.h>
|
||||
#include <signal.h>
|
||||
#include <locale.h>
|
||||
|
||||
typedef struct tm
|
||||
{
|
||||
int tm_sec; /* Seconds [0,60]. */
|
||||
int tm_min; /* Minutes [0,59]. */
|
||||
int tm_hour; /* Hour [0,23]. */
|
||||
int tm_mday; /* Day of month [1,31]. */
|
||||
int tm_mon; /* Month of year [0,11]. */
|
||||
int tm_year; /* Years since 1900. */
|
||||
int tm_wday; /* Day of week [0,6] (Sunday =0). */
|
||||
int tm_yday; /* Day of year [0,365]. */
|
||||
int tm_isdst; /* Daylight Saving flag. */
|
||||
long tm_gmtoff; /* Seconds east of UTC. */
|
||||
const char *tm_zone; /* Timezone abbreviation. */
|
||||
} tm;
|
||||
|
||||
typedef struct itimerspec
|
||||
{
|
||||
struct timespec it_interval; /* Timer period. */
|
||||
struct timespec it_value; /* Timer expiration. */
|
||||
} itimerspec;
|
||||
|
||||
#define CLOCKS_PER_SEC
|
||||
#define TIME_UTC
|
||||
#define CLOCK_MONOTONIC __SYS_CLOCK_MONOTONIC
|
||||
#define CLOCK_PROCESS_CPUTIME_ID __SYS_CLOCK_PROCESS_CPUTIME_ID
|
||||
#define CLOCK_REALTIME __SYS_CLOCK_REALTIME
|
||||
#define CLOCK_THREAD_CPUTIME_ID __SYS_CLOCK_THREAD_CPUTIME_ID
|
||||
#define TIMER_ABSTIME
|
||||
|
||||
extern int daylight;
|
||||
extern long timezone;
|
||||
extern char *tzname[];
|
||||
|
||||
char *asctime(const struct tm *);
|
||||
clock_t clock(void);
|
||||
int clock_getcpuclockid(pid_t, clockid_t *);
|
||||
int clock_getres(clockid_t, struct timespec *);
|
||||
int clock_gettime(clockid_t, struct timespec *);
|
||||
int clock_nanosleep(clockid_t, int, const struct timespec *, struct timespec *);
|
||||
int clock_settime(clockid_t, const struct timespec *);
|
||||
char *ctime(const time_t *);
|
||||
double difftime(time_t, time_t);
|
||||
struct tm *getdate(const char *);
|
||||
struct tm *gmtime(const time_t *);
|
||||
struct tm *gmtime_r(const time_t *restrict, struct tm *restrict);
|
||||
struct tm *localtime(const time_t *);
|
||||
struct tm *localtime_r(const time_t *restrict, struct tm *restrict);
|
||||
time_t mktime(struct tm *);
|
||||
int nanosleep(const struct timespec *, struct timespec *);
|
||||
size_t strftime(char *restrict, size_t, const char *restrict, const struct tm *restrict);
|
||||
size_t strftime_l(char *restrict, size_t, const char *restrict, const struct tm *restrict, locale_t);
|
||||
char *strptime(const char *restrict, const char *restrict, struct tm *restrict);
|
||||
time_t time(time_t *);
|
||||
int timer_create(clockid_t, struct sigevent *restrict, timer_t *restrict);
|
||||
int timer_delete(timer_t);
|
||||
int timer_getoverrun(timer_t);
|
||||
int timer_gettime(timer_t, struct itimerspec *);
|
||||
int timer_settime(timer_t, int, const struct itimerspec *restrict, struct itimerspec *restrict);
|
||||
int timespec_get(struct timespec *, int);
|
||||
void tzset(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // !_TIME_H
|
||||
|
@ -1,206 +0,0 @@
|
||||
#ifndef __FENNIX_LIBC_TYPES_H__
|
||||
#define __FENNIX_LIBC_TYPES_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define EXTERNC extern "C"
|
||||
#define START_EXTERNC \
|
||||
EXTERNC \
|
||||
{
|
||||
#define END_EXTERNC \
|
||||
}
|
||||
#else
|
||||
#define EXTERNC
|
||||
#define START_EXTERNC
|
||||
#define END_EXTERNC
|
||||
#endif
|
||||
|
||||
#define asm __asm__
|
||||
#define asmv __asm__ volatile
|
||||
|
||||
#define true 1
|
||||
#define false 0
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define foreach for
|
||||
#define in :
|
||||
#endif
|
||||
|
||||
#define UNUSED(x) (void)(x)
|
||||
#define CONCAT(x, y) x##y
|
||||
|
||||
#define toupper(c) ((c)-0x20 * (((c) >= 'a') && ((c) <= 'z')))
|
||||
#define tolower(c) ((c) + 0x20 * (((c) >= 'A') && ((c) <= 'Z')))
|
||||
|
||||
#define ALIGN_UP(x, align) ((__typeof__(x))(((uint64_t)(x) + ((align)-1)) & (~((align)-1))))
|
||||
#define ALIGN_DOWN(x, align) ((__typeof__(x))((x) & (~((align)-1))))
|
||||
|
||||
#define offsetof(type, member) __builtin_offsetof(type, member)
|
||||
|
||||
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
||||
|
||||
#define VPOKE(type, address) (*((volatile type *)(address)))
|
||||
#define POKE(type, address) (*((type *)(address)))
|
||||
|
||||
#ifndef __cplusplus
|
||||
|
||||
#ifdef __STDC__
|
||||
#ifdef __STDC_VERSION__
|
||||
#if (__STDC_VERSION__ >= 201710L)
|
||||
#define C_LANGUAGE_STANDARD 2018
|
||||
#elif (__STDC_VERSION__ >= 201112L)
|
||||
#define C_LANGUAGE_STANDARD 2011
|
||||
#elif (__STDC_VERSION__ >= 199901L)
|
||||
#define C_LANGUAGE_STANDARD 1999
|
||||
#elif (__STDC_VERSION__ >= 199409L)
|
||||
#define C_LANGUAGE_STANDARD 1995
|
||||
#endif
|
||||
#else
|
||||
#define C_LANGUAGE_STANDARD 1990
|
||||
#endif
|
||||
#else
|
||||
#define C_LANGUAGE_STANDARD 1972
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#ifdef __STDC__
|
||||
#ifdef __cplusplus
|
||||
#if (__cplusplus >= 202100L)
|
||||
#define CPP_LANGUAGE_STANDARD 2023
|
||||
#elif (__cplusplus >= 202002L)
|
||||
#define CPP_LANGUAGE_STANDARD 2020
|
||||
#elif (__cplusplus >= 201703L)
|
||||
#define CPP_LANGUAGE_STANDARD 2017
|
||||
#elif (__cplusplus >= 201402L)
|
||||
#define CPP_LANGUAGE_STANDARD 2014
|
||||
#elif (__cplusplus >= 201103L)
|
||||
#define CPP_LANGUAGE_STANDARD 2011
|
||||
#elif (__cplusplus >= 199711L)
|
||||
#define CPP_LANGUAGE_STANDARD 1998
|
||||
#endif
|
||||
#else
|
||||
#define CPP_LANGUAGE_STANDARD __cplusplus
|
||||
#endif
|
||||
#else
|
||||
#define CPP_LANGUAGE_STANDARD __cplusplus
|
||||
#endif
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
typedef __INT8_TYPE__ int8_t;
|
||||
typedef __INT16_TYPE__ int16_t;
|
||||
typedef __INT32_TYPE__ int32_t;
|
||||
typedef __INT64_TYPE__ int64_t;
|
||||
typedef __UINT8_TYPE__ uint8_t;
|
||||
typedef __UINT16_TYPE__ uint16_t;
|
||||
typedef __UINT32_TYPE__ uint32_t;
|
||||
typedef __UINT64_TYPE__ uint64_t;
|
||||
|
||||
typedef __INT_LEAST8_TYPE__ int_least8_t;
|
||||
typedef __INT_LEAST16_TYPE__ int_least16_t;
|
||||
typedef __INT_LEAST32_TYPE__ int_least32_t;
|
||||
typedef __INT_LEAST64_TYPE__ int_least64_t;
|
||||
typedef __UINT_LEAST8_TYPE__ uint_least8_t;
|
||||
typedef __UINT_LEAST16_TYPE__ uint_least16_t;
|
||||
typedef __UINT_LEAST32_TYPE__ uint_least32_t;
|
||||
typedef __UINT_LEAST64_TYPE__ uint_least64_t;
|
||||
|
||||
typedef __INT_FAST8_TYPE__ int_fast8_t;
|
||||
typedef __INT_FAST16_TYPE__ int_fast16_t;
|
||||
typedef __INT_FAST32_TYPE__ int_fast32_t;
|
||||
typedef __INT_FAST64_TYPE__ int_fast64_t;
|
||||
typedef __UINT_FAST8_TYPE__ uint_fast8_t;
|
||||
typedef __UINT_FAST16_TYPE__ uint_fast16_t;
|
||||
typedef __UINT_FAST32_TYPE__ uint_fast32_t;
|
||||
typedef __UINT_FAST64_TYPE__ uint_fast64_t;
|
||||
|
||||
typedef __INTPTR_TYPE__ intptr_t;
|
||||
typedef __UINTPTR_TYPE__ uintptr_t;
|
||||
|
||||
typedef __INTMAX_TYPE__ intmax_t;
|
||||
typedef __UINTMAX_TYPE__ uintmax_t;
|
||||
|
||||
typedef __PTRDIFF_TYPE__ ptrdiff_t;
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
|
||||
#define INT8_MAX __INT8_MAX__
|
||||
#define INT8_MIN (-INT8_MAX - 1)
|
||||
#define UINT8_MAX __UINT8_MAX__
|
||||
#define INT16_MAX __INT16_MAX__
|
||||
#define INT16_MIN (-INT16_MAX - 1)
|
||||
#define UINT16_MAX __UINT16_MAX__
|
||||
#define INT32_MAX __INT32_MAX__
|
||||
#define INT32_MIN (-INT32_MAX - 1)
|
||||
#define UINT32_MAX __UINT32_MAX__
|
||||
#define INT64_MAX __INT64_MAX__
|
||||
#define INT64_MIN (-INT64_MAX - 1)
|
||||
#define UINT64_MAX __UINT64_MAX__
|
||||
|
||||
#define INT_LEAST8_MAX __INT_LEAST8_MAX__
|
||||
#define INT_LEAST8_MIN (-INT_LEAST8_MAX - 1)
|
||||
#define UINT_LEAST8_MAX __UINT_LEAST8_MAX__
|
||||
#define INT_LEAST16_MAX __INT_LEAST16_MAX__
|
||||
#define INT_LEAST16_MIN (-INT_LEAST16_MAX - 1)
|
||||
#define UINT_LEAST16_MAX __UINT_LEAST16_MAX__
|
||||
#define INT_LEAST32_MAX __INT_LEAST32_MAX__
|
||||
#define INT_LEAST32_MIN (-INT_LEAST32_MAX - 1)
|
||||
#define UINT_LEAST32_MAX __UINT_LEAST32_MAX__
|
||||
#define INT_LEAST64_MAX __INT_LEAST64_MAX__
|
||||
#define INT_LEAST64_MIN (-INT_LEAST64_MAX - 1)
|
||||
#define UINT_LEAST64_MAX __UINT_LEAST64_MAX__
|
||||
|
||||
#define INT_FAST8_MAX __INT_FAST8_MAX__
|
||||
#define INT_FAST8_MIN (-INT_FAST8_MAX - 1)
|
||||
#define UINT_FAST8_MAX __UINT_FAST8_MAX__
|
||||
#define INT_FAST16_MAX __INT_FAST16_MAX__
|
||||
#define INT_FAST16_MIN (-INT_FAST16_MAX - 1)
|
||||
#define UINT_FAST16_MAX __UINT_FAST16_MAX__
|
||||
#define INT_FAST32_MAX __INT_FAST32_MAX__
|
||||
#define INT_FAST32_MIN (-INT_FAST32_MAX - 1)
|
||||
#define UINT_FAST32_MAX __UINT_FAST32_MAX__
|
||||
#define INT_FAST64_MAX __INT_FAST64_MAX__
|
||||
#define INT_FAST64_MIN (-INT_FAST64_MAX - 1)
|
||||
#define UINT_FAST64_MAX __UINT_FAST64_MAX__
|
||||
|
||||
#define INTPTR_MAX __INTPTR_MAX__
|
||||
#define INTPTR_MIN (-INTPTR_MAX - 1)
|
||||
#define UINTPTR_MAX __UINTPTR_MAX__
|
||||
|
||||
#define INTMAX_MAX __INTMAX_MAX__
|
||||
#define INTMAX_MIN (-INTMAX_MAX - 1)
|
||||
#define UINTMAX_MAX __UINTMAX_MAX__
|
||||
|
||||
#define PTRDIFF_MAX __PTRDIFF_MAX__
|
||||
#define PTRDIFF_MIN (-PTRDIFF_MAX - 1)
|
||||
|
||||
#define SIG_ATOMIC_MAX __SIG_ATOMIC_MAX__
|
||||
#define SIG_ATOMIC_MIN __SIG_ATOMIC_MIN__
|
||||
|
||||
#define SIZE_MAX __SIZE_MAX__
|
||||
|
||||
#define WCHAR_MAX __WCHAR_MAX__
|
||||
#define WCHAR_MIN __WCHAR_MIN__
|
||||
|
||||
#define WINT_MAX __WINT_MAX__
|
||||
#define WINT_MIN __WINT_MIN__
|
||||
|
||||
#define b4(x) ((x & 0x0F) << 4 | (x & 0xF0) >> 4)
|
||||
#define b8(x) ((x)&0xFF)
|
||||
#define b16(x) __builtin_bswap16(x)
|
||||
#define b32(x) __builtin_bswap32(x)
|
||||
#define b48(x) (((((x)&0x0000000000ff) << 40) | (((x)&0x00000000ff00) << 24) | (((x)&0x000000ff0000) << 8) | (((x)&0x0000ff000000) >> 8) | (((x)&0x00ff00000000) >> 24) | (((x)&0xff0000000000) >> 40)))
|
||||
#define b64(x) __builtin_bswap64(x)
|
||||
|
||||
#ifndef PUBLIC
|
||||
#define PUBLIC __attribute__((visibility("default")))
|
||||
#endif // !PUBLIC
|
||||
|
||||
#ifndef PRIVATE
|
||||
#define PRIVATE __attribute__((visibility("hidden")))
|
||||
#endif // !PRIVATE
|
||||
|
||||
#endif // !__FENNIX_LIBC_TYPES_H__
|
@ -1,29 +1,151 @@
|
||||
/*
|
||||
This file is part of Fennix C Library.
|
||||
|
||||
Fennix C Library is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _UNISTD_H
|
||||
#define _UNISTD_H
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif // __cplusplus
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#define _POSIX_VERSION 200809L
|
||||
#define _POSIX2_VERSION 200809L
|
||||
#define _XOPEN_VERSION 700
|
||||
|
||||
#define F_OK 0
|
||||
#define R_OK 1
|
||||
#define W_OK 2
|
||||
#define X_OK 3
|
||||
|
||||
#define SEEK_SET 0
|
||||
#define SEEK_CUR 1
|
||||
#define SEEK_END 2
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL ((void *)0)
|
||||
#endif
|
||||
|
||||
extern char **environ;
|
||||
#define _POSIX_JOB_CONTROL 1
|
||||
#define _POSIX_SAVED_IDS 1
|
||||
#define _POSIX_NO_TRUNC 1
|
||||
#define _POSIX_VDISABLE '\0'
|
||||
|
||||
int execl(const char *pathname, const char *arg, ...);
|
||||
int execlp(const char *file, const char *arg, ...);
|
||||
int execle(const char *pathname, const char *arg, ...);
|
||||
int execv(const char *pathname, char *const argv[]);
|
||||
int execvp(const char *file, char *const argv[]);
|
||||
int execvpe(const char *file, char *const argv[], char *const envp[]);
|
||||
int execve(const char *pathname, char *const argv[], char *const envp[]);
|
||||
#define ARG_MAX 4096
|
||||
#define CHILD_MAX 25
|
||||
#define CLK_TCK 100
|
||||
|
||||
#define _SC_PAGESIZE 4096
|
||||
#define _SC_OPEN_MAX 256
|
||||
|
||||
extern char *optarg;
|
||||
extern int optind, opterr, optopt;
|
||||
|
||||
int access(const char *, int);
|
||||
unsigned int alarm(unsigned int);
|
||||
int brk(void *);
|
||||
int chdir(const char *);
|
||||
int chroot(const char *);
|
||||
int chown(const char *, uid_t, gid_t);
|
||||
int close(int);
|
||||
size_t confstr(int, char *, size_t);
|
||||
char *crypt(const char *, const char *);
|
||||
char *ctermid(char *);
|
||||
char *cuserid(char *s);
|
||||
int dup(int);
|
||||
int dup2(int, int);
|
||||
void encrypt(char[64], int);
|
||||
int execl(const char *, const char *, ...);
|
||||
int execle(const char *, const char *, ...);
|
||||
int execlp(const char *, const char *, ...);
|
||||
int execv(const char *, char *const[]);
|
||||
int execve(const char *, char *const[], char *const[]);
|
||||
int execvp(const char *, char *const[]);
|
||||
void _exit(int);
|
||||
int fchown(int, uid_t, gid_t);
|
||||
int fchdir(int);
|
||||
int fdatasync(int);
|
||||
pid_t fork(void);
|
||||
|
||||
unsigned int sleep(unsigned int seconds);
|
||||
int usleep(useconds_t usec);
|
||||
long int fpathconf(int, int);
|
||||
int fsync(int);
|
||||
int ftruncate(int, off_t);
|
||||
char *getcwd(char *, size_t);
|
||||
int getdtablesize(void);
|
||||
gid_t getegid(void);
|
||||
uid_t geteuid(void);
|
||||
gid_t getgid(void);
|
||||
int getgroups(int, gid_t[]);
|
||||
long gethostid(void);
|
||||
char *getlogin(void);
|
||||
int getlogin_r(char *, size_t);
|
||||
int getopt(int, char *const[], const char *);
|
||||
int getpagesize(void);
|
||||
char *getpass(const char *);
|
||||
pid_t getpgid(pid_t);
|
||||
pid_t getpgrp(void);
|
||||
pid_t getpid(void);
|
||||
pid_t getppid(void);
|
||||
pid_t getsid(pid_t);
|
||||
uid_t getuid(void);
|
||||
char *getwd(char *);
|
||||
int isatty(int);
|
||||
int lchown(const char *, uid_t, gid_t);
|
||||
int link(const char *, const char *);
|
||||
int lockf(int, int, off_t);
|
||||
off_t lseek(int, off_t, int);
|
||||
int nice(int);
|
||||
long int pathconf(const char *, int);
|
||||
int pause(void);
|
||||
int pipe(int[2]);
|
||||
ssize_t pread(int, void *, size_t, off_t);
|
||||
int pthread_atfork(void (*)(void), void (*)(void), void (*)(void));
|
||||
ssize_t pwrite(int, const void *, size_t, off_t);
|
||||
ssize_t read(int, void *, size_t);
|
||||
int readlink(const char *, char *, size_t);
|
||||
int rmdir(const char *);
|
||||
void *sbrk(intptr_t);
|
||||
int setgid(gid_t);
|
||||
int setpgid(pid_t, pid_t);
|
||||
pid_t setpgrp(void);
|
||||
int setregid(gid_t, gid_t);
|
||||
int setreuid(uid_t, uid_t);
|
||||
pid_t setsid(void);
|
||||
int setuid(uid_t);
|
||||
unsigned int sleep(unsigned int);
|
||||
void swab(const void *, void *, ssize_t);
|
||||
int symlink(const char *, const char *);
|
||||
void sync(void);
|
||||
long int sysconf(int);
|
||||
pid_t tcgetpgrp(int);
|
||||
int tcsetpgrp(int, pid_t);
|
||||
int truncate(const char *, off_t);
|
||||
char *ttyname(int);
|
||||
int ttyname_r(int, char *, size_t);
|
||||
useconds_t ualarm(useconds_t, useconds_t);
|
||||
int unlink(const char *);
|
||||
int usleep(useconds_t);
|
||||
pid_t vfork(void);
|
||||
ssize_t write(int, const void *, size_t);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // !_UNISTD_H
|
||||
|
40
Userspace/libc/interpreter/Makefile
Normal file
40
Userspace/libc/interpreter/Makefile
Normal file
@ -0,0 +1,40 @@
|
||||
default:
|
||||
$(error Do not run this Makefile directly!)
|
||||
|
||||
OBJECT_NAME := ld.so
|
||||
|
||||
OUTPUT_DIR=$(WORKSPACE_DIR)/out/lib/
|
||||
SYSROOT = --sysroot=$(WORKSPACE_DIR)/out/
|
||||
|
||||
S_SOURCES = $(shell find ./ -type f -name '*.S')
|
||||
C_SOURCES = $(shell find ./ -type f -name '*.c')
|
||||
CXX_SOURCES = $(shell find ./ -type f -name '*.cpp')
|
||||
OBJ = ${S_SOURCES:.S=.o} ${C_SOURCES:.c=.o} ${CXX_SOURCES:.cpp=.o}
|
||||
|
||||
CFLAGS := -fvisibility=hidden -fPIC -I$(WORKSPACE_DIR)/out/include -DLIBC_GIT_COMMIT='"$(shell git rev-parse HEAD)"'
|
||||
|
||||
ifeq ($(DEBUG), 1)
|
||||
CFLAGS += -DDEBUG -ggdb3 -O0 -fdiagnostics-color=always -fverbose-asm
|
||||
endif
|
||||
|
||||
build: $(OBJECT_NAME)
|
||||
|
||||
$(OBJECT_NAME): $(OBJ)
|
||||
$(info Linking $@)
|
||||
$(CC) -nostdlib -shared -fPIC -fPIE -fno-plt -Wl,-soname,$(OBJECT_NAME) $(SYSROOT) $(OBJ) -o $(OBJECT_NAME)
|
||||
cp $(OBJECT_NAME) $(OUTPUT_DIR)$(OBJECT_NAME)
|
||||
|
||||
%.o: %.c
|
||||
$(info Compiling $<)
|
||||
$(CC) $(CFLAGS) -std=c17 -c $< -o $@
|
||||
|
||||
%.o: %.cpp
|
||||
$(info Compiling $<)
|
||||
$(CC) $(CFLAGS) -std=c++20 -c $< -o $@
|
||||
|
||||
%.o: %.S
|
||||
$(info Compiling $<)
|
||||
$(AS) -c $< -o $@
|
||||
|
||||
clean:
|
||||
rm -f $(OBJ) $(OBJECT_NAME)
|
117
Userspace/libc/interpreter/alloc.c
Normal file
117
Userspace/libc/interpreter/alloc.c
Normal file
@ -0,0 +1,117 @@
|
||||
/*
|
||||
This file is part of Fennix C Library.
|
||||
|
||||
Fennix C Library is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <fennix/syscalls.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "elf.h"
|
||||
#include "misc.h"
|
||||
|
||||
typedef struct MemoryBlock
|
||||
{
|
||||
struct MemoryBlock *next;
|
||||
void *slots;
|
||||
size_t slot_size;
|
||||
size_t slots_per_block;
|
||||
uint8_t *bitmap;
|
||||
} MemoryBlock;
|
||||
|
||||
MemoryBlock *memory_pool = NULL;
|
||||
#define PAGE_SIZE 0x1000
|
||||
|
||||
void *request_page(size_t size)
|
||||
{
|
||||
size_t aligned_size = (size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
|
||||
void *addr = (void *)call_mmap(NULL, aligned_size, __SYS_PROT_READ | __SYS_PROT_WRITE, __SYS_MAP_ANONYMOUS | __SYS_MAP_PRIVATE, -1, 0);
|
||||
if ((intptr_t)addr < 0)
|
||||
return NULL;
|
||||
return addr;
|
||||
}
|
||||
|
||||
void free_page(void *addr, size_t size)
|
||||
{
|
||||
size_t aligned_size = (size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
|
||||
call_munmap(addr, aligned_size);
|
||||
}
|
||||
|
||||
MemoryBlock *allocate_block(size_t slot_size)
|
||||
{
|
||||
size_t block_size = PAGE_SIZE;
|
||||
size_t slots_per_block = block_size / slot_size;
|
||||
size_t bitmap_size = (slots_per_block + 7) / 8;
|
||||
|
||||
MemoryBlock *block = request_page(block_size);
|
||||
if (!block)
|
||||
return NULL;
|
||||
|
||||
block->slots = (void *)((uintptr_t)block + sizeof(MemoryBlock) + bitmap_size);
|
||||
block->slot_size = slot_size;
|
||||
block->slots_per_block = slots_per_block;
|
||||
block->bitmap = (uint8_t *)((uintptr_t)block + sizeof(MemoryBlock));
|
||||
memset(block->bitmap, 0, bitmap_size);
|
||||
block->next = NULL;
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
void *mini_malloc(size_t size)
|
||||
{
|
||||
MemoryBlock *block = memory_pool;
|
||||
while (block)
|
||||
{
|
||||
for (size_t i = 0; i < block->slots_per_block; i++)
|
||||
{
|
||||
size_t byte = i / 8, bit = i % 8;
|
||||
if (!(block->bitmap[byte] & (1 << bit)))
|
||||
{
|
||||
block->bitmap[byte] |= (1 << bit);
|
||||
return (void *)((uintptr_t)block->slots + i * size);
|
||||
}
|
||||
}
|
||||
block = block->next;
|
||||
}
|
||||
|
||||
block = allocate_block(size);
|
||||
if (!block)
|
||||
return NULL;
|
||||
|
||||
block->next = memory_pool;
|
||||
memory_pool = block;
|
||||
|
||||
block->bitmap[0] |= 1;
|
||||
return block->slots;
|
||||
}
|
||||
|
||||
void mini_free(void *ptr)
|
||||
{
|
||||
MemoryBlock *block = memory_pool;
|
||||
while (block)
|
||||
{
|
||||
if ((uintptr_t)ptr >= (uintptr_t)block->slots &&
|
||||
(uintptr_t)ptr < (uintptr_t)block->slots + block->slots_per_block * block->slot_size)
|
||||
{
|
||||
size_t index = ((uintptr_t)ptr - (uintptr_t)block->slots) / block->slot_size;
|
||||
size_t byte = index / 8, bit = index % 8;
|
||||
block->bitmap[byte] &= ~(1 << bit);
|
||||
return;
|
||||
}
|
||||
block = block->next;
|
||||
}
|
||||
}
|
1013
Userspace/libc/interpreter/elf.h
Normal file
1013
Userspace/libc/interpreter/elf.h
Normal file
File diff suppressed because it is too large
Load Diff
131
Userspace/libc/interpreter/helper.c
Normal file
131
Userspace/libc/interpreter/helper.c
Normal file
@ -0,0 +1,131 @@
|
||||
/*
|
||||
This file is part of Fennix C Library.
|
||||
|
||||
Fennix C Library is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <fennix/syscalls.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "elf.h"
|
||||
#include "misc.h"
|
||||
|
||||
void *memset(void *s, int c, size_t n)
|
||||
{
|
||||
uint8_t *p = s;
|
||||
while (n--)
|
||||
*p++ = c;
|
||||
return s;
|
||||
}
|
||||
|
||||
void *memcpy(void *dest, const void *src, size_t n)
|
||||
{
|
||||
uint8_t *d = dest;
|
||||
const uint8_t *s = src;
|
||||
while (n--)
|
||||
*d++ = *s++;
|
||||
return dest;
|
||||
}
|
||||
|
||||
size_t strlen(const char *s)
|
||||
{
|
||||
const char *p = s;
|
||||
while (*p)
|
||||
p++;
|
||||
return p - s;
|
||||
}
|
||||
|
||||
char *strcpy(char *dest, const char *src)
|
||||
{
|
||||
char *d = dest;
|
||||
while ((*d++ = *src++))
|
||||
;
|
||||
return dest;
|
||||
}
|
||||
|
||||
int strcmp(const char *l, const char *r)
|
||||
{
|
||||
while (*l && *l == *r)
|
||||
{
|
||||
l++;
|
||||
r++;
|
||||
}
|
||||
return *l - *r;
|
||||
}
|
||||
|
||||
char *strcat(char *dest, const char *src)
|
||||
{
|
||||
char *d = dest;
|
||||
while (*d)
|
||||
d++;
|
||||
while ((*d++ = *src++))
|
||||
;
|
||||
return dest;
|
||||
}
|
||||
|
||||
unsigned long elf_hash(const unsigned char *name)
|
||||
{
|
||||
unsigned long hash = 0, high;
|
||||
while (*name)
|
||||
{
|
||||
hash = (hash << 4) + *name++;
|
||||
if ((high = hash & 0xF0000000))
|
||||
hash ^= high >> 24;
|
||||
hash &= ~high;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
uint32_t gnu_hash(const char *name)
|
||||
{
|
||||
uint32_t hash = 5381;
|
||||
for (; *name; name++)
|
||||
{
|
||||
hash = (hash << 5) + hash + (unsigned char)(*name); // hash * 33 + c
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
Elf64_Sym *find_symbol(const char *name, uint32_t *hash_table, Elf64_Sym *symtab, const char *strtab)
|
||||
{
|
||||
/* Symbol Hash Table
|
||||
|-------------------|
|
||||
| nbucket |
|
||||
|-------------------|
|
||||
| nchain |
|
||||
|-------------------|
|
||||
| bucket[0] |
|
||||
| . . . |
|
||||
|bucket[nbucket - 1]|
|
||||
|-------------------|
|
||||
| chain[0] |
|
||||
| . . . |
|
||||
| chain[nchain - 1] |
|
||||
|-------------------|
|
||||
*/
|
||||
unsigned long h = elf_hash(name); // or gnu_hash(name)
|
||||
unsigned long bucket = h % hash_table[0]; // hash_table[0] = nbucket
|
||||
|
||||
for (unsigned long i = hash_table[2 + bucket];
|
||||
i != STN_UNDEF;
|
||||
i = hash_table[2 + hash_table[0] + i])
|
||||
{
|
||||
if (!strcmp(&strtab[symtab[i].st_name], name))
|
||||
return &symtab[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
975
Userspace/libc/interpreter/load.c
Normal file
975
Userspace/libc/interpreter/load.c
Normal file
@ -0,0 +1,975 @@
|
||||
/*
|
||||
This file is part of Fennix C Library.
|
||||
|
||||
Fennix C Library is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <fennix/syscalls.h>
|
||||
#include <sys/types.h>
|
||||
#include <inttypes.h>
|
||||
#include <stddef.h>
|
||||
#include <limits.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "elf.h"
|
||||
#include "misc.h"
|
||||
|
||||
typedef struct ElfInfo
|
||||
{
|
||||
Elf_Ehdr Header;
|
||||
Elf_Phdr DynamicHeader;
|
||||
uintptr_t BaseAddress;
|
||||
Elf_Dyn *Dynamic;
|
||||
char *Path;
|
||||
|
||||
struct
|
||||
{
|
||||
Elf_Addr PLTGOT, HASH, STRTAB, SYMTAB, RELA, REL, TEXTREL, JMPREL;
|
||||
Elf_Addr BIND_NOW, INIT, FINI, RPATH, SYMBOLIC, INIT_ARRAY;
|
||||
Elf_Addr FINI_ARRAY, PREINIT_ARRAY, RUNPATH, FLAGS;
|
||||
} DynamicTable;
|
||||
|
||||
struct
|
||||
{
|
||||
#ifdef __LP64__
|
||||
_Static_assert(sizeof(Elf64_Xword) == sizeof(size_t), "Elf64_Xword and size_t are not the same size");
|
||||
#else
|
||||
_Static_assert(sizeof(Elf32_Word) == sizeof(size_t), "Elf32_Word and size_t are not the same size");
|
||||
#endif
|
||||
size_t PLTRELSZ, RELASZ, RELAENT, STRSZ, SYMENT, RELSZ, RELENT, PLTREL;
|
||||
size_t INIT_ARRAYSZ, FINI_ARRAYSZ, PREINIT_ARRAYSZ;
|
||||
} DynamicSize;
|
||||
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint8_t Relocated : 1;
|
||||
uint8_t IsLibrary : 1;
|
||||
uint8_t __padding : 6;
|
||||
};
|
||||
uint8_t raw;
|
||||
} Flags;
|
||||
|
||||
struct ElfInfo *prev;
|
||||
struct ElfInfo *next;
|
||||
} ElfInfo;
|
||||
|
||||
ElfInfo *elf_list_head = NULL;
|
||||
|
||||
ElfInfo *AllocateLib()
|
||||
{
|
||||
ElfInfo *new_node = mini_malloc(sizeof(ElfInfo));
|
||||
if (!new_node)
|
||||
{
|
||||
printf("Failed to allocate memory for new library\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(new_node, 0, sizeof(ElfInfo));
|
||||
|
||||
if (!elf_list_head)
|
||||
{
|
||||
elf_list_head = new_node;
|
||||
return new_node;
|
||||
}
|
||||
|
||||
ElfInfo *current = elf_list_head;
|
||||
while (current->next)
|
||||
current = current->next;
|
||||
|
||||
current->next = new_node;
|
||||
new_node->prev = current;
|
||||
return new_node;
|
||||
}
|
||||
|
||||
void FreeLib(ElfInfo *node)
|
||||
{
|
||||
if (!node)
|
||||
return;
|
||||
|
||||
if (node->prev)
|
||||
node->prev->next = node->next;
|
||||
else
|
||||
elf_list_head = node->next;
|
||||
|
||||
if (node->next)
|
||||
node->next->prev = node->prev;
|
||||
|
||||
mini_free(node);
|
||||
}
|
||||
|
||||
ElfInfo *SearchLib(char *Path)
|
||||
{
|
||||
ElfInfo *current = elf_list_head;
|
||||
while (current)
|
||||
{
|
||||
if (strcmp(current->Path, Path) == 0)
|
||||
return current;
|
||||
current = current->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
__attribute__((naked, used, no_stack_protector)) void _dl_runtime_resolve()
|
||||
{
|
||||
__asm__(
|
||||
"pop %r11\n" /* Pop lazy resolve arguments */
|
||||
"pop %r10\n"
|
||||
|
||||
"push %rdi\n"
|
||||
"push %rsi\n"
|
||||
"push %rdx\n"
|
||||
"push %rcx\n"
|
||||
"push %r8\n"
|
||||
"push %r9\n"
|
||||
|
||||
"mov %r11, %rdi\n" /* Move the first argument to rdi */
|
||||
"mov %r10, %rsi\n" /* Move the second argument to rsi (rel index) */
|
||||
"call _dl_fixup\n" /* Call _dl_fixup */
|
||||
"mov %rax, %r11\n" /* Move the return value to r11 */
|
||||
|
||||
"pop %r9\n"
|
||||
"pop %r8\n"
|
||||
"pop %rcx\n"
|
||||
"pop %rdx\n"
|
||||
"pop %rsi\n"
|
||||
"pop %rdi\n"
|
||||
|
||||
"jmp *%r11\n"); /* Jump to the return value */
|
||||
}
|
||||
|
||||
int RelocateHelper(ElfInfo *Info, Elf_Rela *Rela, short IsRel, void **Relocated);
|
||||
__attribute__((noinline)) void *_dl_fixup(ElfInfo *Info, long RelIndex)
|
||||
{
|
||||
void *ret = NULL;
|
||||
if (Info->DynamicSize.PLTREL == DT_REL)
|
||||
RelocateHelper(Info, (Elf_Rela *)(Info->DynamicTable.JMPREL + RelIndex), 1, &ret);
|
||||
else if (Info->DynamicSize.PLTREL == DT_RELA)
|
||||
RelocateHelper(Info, &((Elf_Rela *)Info->DynamicTable.JMPREL)[RelIndex], 0, &ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int _dl_preload()
|
||||
{
|
||||
call_api_version(0);
|
||||
|
||||
/* TODO: Do aditional checks for miscellaneous things */
|
||||
|
||||
/* Everything is ok, continue. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
void HandleGOT(ElfInfo *Info, Elf_Addr Offset)
|
||||
{
|
||||
Elf_Addr *got = (Elf_Addr *)Offset;
|
||||
got[0] = (Elf_Addr)Info->Dynamic;
|
||||
got[1] = (Elf_Addr)Info;
|
||||
got[2] = (Elf_Addr)&_dl_runtime_resolve;
|
||||
}
|
||||
|
||||
void AdjustDynamicTable(Elf_Dyn *elem, ElfInfo *Info)
|
||||
{
|
||||
switch (elem->d_tag)
|
||||
{
|
||||
case DT_PLTGOT:
|
||||
case DT_HASH:
|
||||
case DT_STRTAB:
|
||||
case DT_SYMTAB:
|
||||
case DT_RELA:
|
||||
case DT_INIT:
|
||||
case DT_FINI:
|
||||
case DT_REL:
|
||||
case DT_JMPREL:
|
||||
case DT_INIT_ARRAY:
|
||||
case DT_FINI_ARRAY:
|
||||
elem->d_un.d_ptr += Info->BaseAddress;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CreateInfoTables(Elf_Dyn *elem, ElfInfo *Info)
|
||||
{
|
||||
switch (elem->d_tag)
|
||||
{
|
||||
case DT_NEEDED:
|
||||
break;
|
||||
case DT_PLTRELSZ:
|
||||
Info->DynamicSize.PLTRELSZ = elem->d_un.d_val;
|
||||
break;
|
||||
case DT_PLTGOT:
|
||||
HandleGOT(Info, elem->d_un.d_ptr);
|
||||
Info->DynamicTable.PLTGOT = elem->d_un.d_ptr;
|
||||
break;
|
||||
case DT_HASH:
|
||||
Info->DynamicTable.HASH = elem->d_un.d_ptr;
|
||||
break;
|
||||
case DT_STRTAB:
|
||||
Info->DynamicTable.STRTAB = elem->d_un.d_ptr;
|
||||
break;
|
||||
case DT_SYMTAB:
|
||||
Info->DynamicTable.SYMTAB = elem->d_un.d_ptr;
|
||||
break;
|
||||
case DT_RELA:
|
||||
Info->DynamicTable.RELA = elem->d_un.d_ptr;
|
||||
break;
|
||||
case DT_RELASZ:
|
||||
Info->DynamicSize.RELASZ = elem->d_un.d_val;
|
||||
break;
|
||||
case DT_RELAENT:
|
||||
Info->DynamicSize.RELAENT = elem->d_un.d_val;
|
||||
break;
|
||||
case DT_STRSZ:
|
||||
Info->DynamicSize.STRSZ = elem->d_un.d_val;
|
||||
break;
|
||||
case DT_SYMENT:
|
||||
Info->DynamicSize.SYMENT = elem->d_un.d_val;
|
||||
break;
|
||||
case DT_INIT:
|
||||
Info->DynamicTable.INIT = elem->d_un.d_ptr;
|
||||
break;
|
||||
case DT_FINI:
|
||||
Info->DynamicTable.FINI = elem->d_un.d_ptr;
|
||||
break;
|
||||
case DT_RPATH:
|
||||
Info->DynamicTable.RPATH = elem->d_un.d_ptr;
|
||||
break;
|
||||
case DT_SYMBOLIC:
|
||||
Info->DynamicTable.SYMBOLIC = elem->d_un.d_ptr;
|
||||
break;
|
||||
case DT_REL:
|
||||
Info->DynamicTable.REL = elem->d_un.d_ptr;
|
||||
break;
|
||||
case DT_RELSZ:
|
||||
Info->DynamicSize.RELSZ = elem->d_un.d_val;
|
||||
break;
|
||||
case DT_RELENT:
|
||||
Info->DynamicSize.RELENT = elem->d_un.d_val;
|
||||
break;
|
||||
case DT_PLTREL:
|
||||
Info->DynamicSize.PLTREL = elem->d_un.d_val;
|
||||
break;
|
||||
// case DT_DEBUG:
|
||||
case DT_TEXTREL:
|
||||
Info->DynamicTable.TEXTREL = elem->d_un.d_ptr;
|
||||
break;
|
||||
case DT_JMPREL:
|
||||
Info->DynamicTable.JMPREL = elem->d_un.d_ptr;
|
||||
break;
|
||||
case DT_BIND_NOW:
|
||||
Info->DynamicTable.BIND_NOW = elem->d_un.d_ptr;
|
||||
break;
|
||||
case DT_INIT_ARRAY:
|
||||
Info->DynamicTable.INIT_ARRAY = elem->d_un.d_ptr;
|
||||
break;
|
||||
case DT_FINI_ARRAY:
|
||||
Info->DynamicTable.FINI_ARRAY = elem->d_un.d_ptr;
|
||||
break;
|
||||
case DT_INIT_ARRAYSZ:
|
||||
Info->DynamicSize.INIT_ARRAYSZ = elem->d_un.d_val;
|
||||
break;
|
||||
case DT_FINI_ARRAYSZ:
|
||||
Info->DynamicSize.FINI_ARRAYSZ = elem->d_un.d_val;
|
||||
break;
|
||||
case DT_RUNPATH:
|
||||
Info->DynamicTable.RUNPATH = elem->d_un.d_ptr;
|
||||
break;
|
||||
case DT_FLAGS:
|
||||
Info->DynamicTable.FLAGS = elem->d_un.d_ptr;
|
||||
break;
|
||||
// case DT_ENCODING:
|
||||
case DT_PREINIT_ARRAY:
|
||||
Info->DynamicTable.PREINIT_ARRAY = elem->d_un.d_ptr;
|
||||
break;
|
||||
case DT_PREINIT_ARRAYSZ:
|
||||
Info->DynamicSize.PREINIT_ARRAYSZ = elem->d_un.d_val;
|
||||
break;
|
||||
case DT_LOOS:
|
||||
case DT_SUNW_RTLDINF:
|
||||
case DT_HIOS:
|
||||
case DT_VALRNGLO:
|
||||
case DT_CHECKSUM:
|
||||
case DT_PLTPADSZ:
|
||||
case DT_MOVEENT:
|
||||
case DT_MOVESZ:
|
||||
case DT_FEATURE_1:
|
||||
case DT_POSFLAG_1:
|
||||
case DT_SYMINSZ:
|
||||
case DT_SYMINENT:
|
||||
// case DT_VALRNGHI:
|
||||
case DT_ADDRRNGLO:
|
||||
case DT_CONFIG:
|
||||
case DT_DEPAUDIT:
|
||||
case DT_AUDIT:
|
||||
case DT_PLTPAD:
|
||||
case DT_MOVETAB:
|
||||
case DT_SYMINFO:
|
||||
// case DT_ADDRRNGHI:
|
||||
case DT_RELACOUNT:
|
||||
case DT_RELCOUNT:
|
||||
case DT_FLAGS_1:
|
||||
case DT_VERDEF:
|
||||
case DT_VERDEFNUM:
|
||||
case DT_VERNEED:
|
||||
case DT_VERNEEDNUM:
|
||||
case DT_LOPROC:
|
||||
case DT_SPARC_REGISTER:
|
||||
case DT_AUXILIARY:
|
||||
case DT_USED:
|
||||
case DT_FILTER:
|
||||
// case DT_HIPROC:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int LoadElf(int, char *, ElfInfo **);
|
||||
void ProcessNeededLibraries(Elf_Dyn *elem, ElfInfo *Info)
|
||||
{
|
||||
char *libPath = (char *)Info->DynamicTable.STRTAB + elem->d_un.d_val;
|
||||
ElfInfo *info = NULL;
|
||||
|
||||
char fullLibPath[PATH_MAX];
|
||||
strcpy(fullLibPath, "/lib/");
|
||||
strcat(fullLibPath, libPath);
|
||||
/* TODO: more checks and also check environment variables */
|
||||
if (call_access(fullLibPath, __SYS_F_OK) != 0)
|
||||
{
|
||||
printf("dl: Can't access %s\n", fullLibPath);
|
||||
return;
|
||||
}
|
||||
|
||||
int fd = call_open(fullLibPath, __SYS_O_RDONLY, 0644);
|
||||
int status = LoadElf(fd, fullLibPath, &info);
|
||||
elem->d_un.d_ptr = (uintptr_t)info; /* if LoadElf fails, info will still be NULL */
|
||||
call_close(fd);
|
||||
if (status < 0) /* announce that LoadElf failed */
|
||||
printf("dl: Can't load %s\n", fullLibPath);
|
||||
}
|
||||
|
||||
void ProcessDynamicTable(ElfInfo *Info)
|
||||
{
|
||||
for (size_t i = 0;; i++)
|
||||
{
|
||||
Elf_Dyn *elem = &Info->Dynamic[i];
|
||||
if (elem->d_tag == DT_NULL)
|
||||
break;
|
||||
AdjustDynamicTable(elem, Info);
|
||||
CreateInfoTables(elem, Info);
|
||||
}
|
||||
|
||||
/* TODO: Optimize this, we don't have to recheck every element */
|
||||
for (size_t i = 0;; i++)
|
||||
{
|
||||
Elf_Dyn *elem = &Info->Dynamic[i];
|
||||
if (elem->d_tag == DT_NULL)
|
||||
break;
|
||||
if (elem->d_tag != DT_NEEDED)
|
||||
continue;
|
||||
ProcessNeededLibraries(elem, Info);
|
||||
}
|
||||
}
|
||||
|
||||
uintptr_t GetASLR()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
static uintptr_t __aslr_stub_next = 0;
|
||||
__aslr_stub_next += 0x1000000;
|
||||
return __aslr_stub_next;
|
||||
#else
|
||||
/* FIXME: implement real ASLR */
|
||||
static uintptr_t __aslr_stub_next = 0;
|
||||
__aslr_stub_next += 0x1000000;
|
||||
return __aslr_stub_next;
|
||||
#endif
|
||||
}
|
||||
|
||||
int LoadElfPhdrEXEC(int fd, ElfInfo *Info)
|
||||
{
|
||||
printf("dl: ET_EXEC not implemented yet\n");
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
uintptr_t DynamicCreateBase(int fd, ElfInfo *Info)
|
||||
{
|
||||
uintptr_t base = GetASLR();
|
||||
if ((uintptr_t)base <= 0)
|
||||
{
|
||||
printf("dl: Can't get ASLR\n");
|
||||
_Exit(-1);
|
||||
}
|
||||
Info->BaseAddress = base;
|
||||
return base;
|
||||
}
|
||||
|
||||
int LoadElfPhdrDYN(int fd, ElfInfo *Info)
|
||||
{
|
||||
Elf_Ehdr header = Info->Header;
|
||||
Info->Dynamic = NULL;
|
||||
uintptr_t base = 0;
|
||||
Elf_Phdr phdr, lastLOAD;
|
||||
|
||||
for (Elf_Half i = 0; i < header.e_phnum; i++)
|
||||
{
|
||||
ssize_t read = call_pread(fd, &phdr, sizeof(Elf_Phdr), header.e_phoff + (header.e_phentsize * i));
|
||||
if (read != sizeof(Elf_Phdr))
|
||||
{
|
||||
printf("dl: Can't read program header %d\n", i);
|
||||
return (int)read;
|
||||
}
|
||||
|
||||
switch (phdr.p_type)
|
||||
{
|
||||
case PT_LOAD:
|
||||
{
|
||||
if (phdr.p_memsz == 0)
|
||||
continue;
|
||||
|
||||
if (base == 0)
|
||||
base = DynamicCreateBase(fd, Info);
|
||||
|
||||
int mmapProt = 0;
|
||||
if (phdr.p_flags & PF_X)
|
||||
mmapProt |= __SYS_PROT_EXEC;
|
||||
if (phdr.p_flags & PF_W)
|
||||
mmapProt |= __SYS_PROT_WRITE;
|
||||
if (phdr.p_flags & PF_R)
|
||||
mmapProt |= __SYS_PROT_READ;
|
||||
|
||||
off_t sectionOffset = ALIGN_DOWN(phdr.p_vaddr, phdr.p_align);
|
||||
size_t sectionSize = ALIGN_UP(phdr.p_memsz + (phdr.p_vaddr - sectionOffset), phdr.p_align);
|
||||
uintptr_t section = call_mmap(base + sectionOffset,
|
||||
sectionSize, mmapProt,
|
||||
__SYS_MAP_ANONYMOUS | __SYS_MAP_PRIVATE | __SYS_MAP_FIXED,
|
||||
-1, 0);
|
||||
sectionOffset = phdr.p_vaddr - ALIGN_DOWN(phdr.p_vaddr, phdr.p_align);
|
||||
|
||||
if (phdr.p_filesz > 0)
|
||||
{
|
||||
ssize_t read = call_pread(fd, section + sectionOffset, phdr.p_filesz, phdr.p_offset);
|
||||
if (read != phdr.p_filesz)
|
||||
{
|
||||
printf("dl: Can't read segment %d in PT_LOAD\n", i);
|
||||
return (int)read;
|
||||
}
|
||||
}
|
||||
|
||||
if (phdr.p_memsz - phdr.p_filesz > 0)
|
||||
{
|
||||
/* TODO: Do we really have to do this? Kernel already zeros the memory for us */
|
||||
void *zero = (void *)(section + sectionOffset + phdr.p_filesz);
|
||||
memset(zero, 0, phdr.p_memsz - phdr.p_filesz);
|
||||
}
|
||||
lastLOAD = phdr;
|
||||
break;
|
||||
}
|
||||
case PT_DYNAMIC:
|
||||
{
|
||||
Elf_Dyn *dynamicTable = NULL;
|
||||
if (phdr.p_vaddr == lastLOAD.p_vaddr && phdr.p_memsz < lastLOAD.p_memsz)
|
||||
{
|
||||
/* The dynamic section is inside the last LOAD segment */
|
||||
dynamicTable = (Elf_Dyn *)(base + phdr.p_vaddr);
|
||||
}
|
||||
else
|
||||
{
|
||||
int mmapProt = 0;
|
||||
if (phdr.p_flags & PF_X)
|
||||
mmapProt |= __SYS_PROT_EXEC;
|
||||
if (phdr.p_flags & PF_W)
|
||||
mmapProt |= __SYS_PROT_WRITE;
|
||||
if (phdr.p_flags & PF_R)
|
||||
mmapProt |= __SYS_PROT_READ;
|
||||
|
||||
dynamicTable = (Elf_Dyn *)call_mmap(0, ALIGN_UP(phdr.p_memsz, phdr.p_align),
|
||||
mmapProt, __SYS_MAP_ANONYMOUS | __SYS_MAP_PRIVATE | __SYS_MAP_FIXED,
|
||||
-1, 0);
|
||||
|
||||
if ((intptr_t)dynamicTable <= 0)
|
||||
{
|
||||
printf("dl: Can't allocate memory for PT_DYNAMIC\n");
|
||||
return (int)(uintptr_t)dynamicTable;
|
||||
}
|
||||
|
||||
read = call_pread(fd, dynamicTable, phdr.p_memsz, phdr.p_offset);
|
||||
if (read != phdr.p_memsz)
|
||||
{
|
||||
printf("dl: Can't read PT_DYNAMIC\n");
|
||||
return (int)read;
|
||||
}
|
||||
}
|
||||
|
||||
Info->Dynamic = dynamicTable;
|
||||
Info->DynamicHeader = phdr;
|
||||
break;
|
||||
}
|
||||
case PT_INTERP:
|
||||
break;
|
||||
case PT_NOTE:
|
||||
break;
|
||||
case PT_SHLIB:
|
||||
break;
|
||||
case PT_PHDR:
|
||||
break;
|
||||
case PT_TLS:
|
||||
{
|
||||
printf("dl: PT_TLS not implemented yet\n");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
printf("dl: Unimplemented program header type %d\n", phdr.p_type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CheckElfEhdr(Elf_Ehdr *ehdr, char *Path)
|
||||
{
|
||||
if (ehdr->e_ident[EI_MAG0] != ELFMAG0 ||
|
||||
ehdr->e_ident[EI_MAG1] != ELFMAG1 ||
|
||||
ehdr->e_ident[EI_MAG2] != ELFMAG2 ||
|
||||
ehdr->e_ident[EI_MAG3] != ELFMAG3)
|
||||
{
|
||||
printf("dl: %s is not an ELF file\n", Path);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
#ifdef __LP64__
|
||||
const int elfClass = ELFCLASS64;
|
||||
#else
|
||||
const int elfClass = ELFCLASS32;
|
||||
#endif
|
||||
|
||||
if (ehdr->e_ident[EI_CLASS] != elfClass)
|
||||
{
|
||||
printf("dl: %s is not a %s-bit ELF file\n",
|
||||
Path, __LP64__ ? "64" : "32");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* TODO: check LSB MSB */
|
||||
|
||||
if (ehdr->e_ident[EI_VERSION] != EV_CURRENT || ehdr->e_version != EV_CURRENT)
|
||||
{
|
||||
printf("dl: %s has an unsupported ELF version\n", Path);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (ehdr->e_type != ET_DYN && ehdr->e_type != ET_EXEC)
|
||||
{
|
||||
printf("dl: %s is not a shared object or executable\n", Path);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LoadElf(int fd, char *Path, ElfInfo **Out)
|
||||
{
|
||||
ElfInfo *info = SearchLib(Path);
|
||||
if (info != NULL)
|
||||
{
|
||||
*Out = info;
|
||||
return 0;
|
||||
}
|
||||
|
||||
Elf_Ehdr header;
|
||||
call_pread(fd, &header, sizeof(Elf_Ehdr), 0);
|
||||
|
||||
int status = CheckElfEhdr(&header, Path);
|
||||
if (status != 0)
|
||||
return status;
|
||||
|
||||
info = AllocateLib();
|
||||
info->Header = header;
|
||||
info->Path = (char *)call_mmap(0,
|
||||
ALIGN_UP(strlen(Path) + 1, 0x1000 /* TODO: get page size from kernel */),
|
||||
__SYS_PROT_READ,
|
||||
__SYS_MAP_ANONYMOUS | __SYS_MAP_PRIVATE,
|
||||
-1, 0);
|
||||
if ((intptr_t)info->Path <= 0)
|
||||
{
|
||||
printf("dl: Can't allocate memory for path\n");
|
||||
FreeLib(info);
|
||||
return (int)(uintptr_t)info->Path;
|
||||
}
|
||||
|
||||
memcpy(info->Path, Path, strlen(Path) + 1);
|
||||
|
||||
switch (header.e_type)
|
||||
{
|
||||
case ET_REL:
|
||||
printf("dl: ET_REL not implemented yet\n");
|
||||
status = -ENOSYS;
|
||||
break;
|
||||
case ET_EXEC:
|
||||
status = LoadElfPhdrEXEC(fd, info);
|
||||
break;
|
||||
case ET_DYN:
|
||||
status = LoadElfPhdrDYN(fd, info);
|
||||
break;
|
||||
case ET_CORE:
|
||||
printf("dl: ET_CORE not implemented yet\n");
|
||||
status = -ENOSYS;
|
||||
break;
|
||||
case ET_NONE:
|
||||
printf("dl: ET_NONE???\n");
|
||||
status = -EINVAL;
|
||||
break;
|
||||
default:
|
||||
printf("dl: Unsupported ELF type %d\n", header.e_type);
|
||||
status = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (status < 0)
|
||||
{
|
||||
call_munmap((uintptr_t)info->Path, ALIGN_UP(strlen(Path) + 1, 0x1000));
|
||||
FreeLib(info);
|
||||
return status;
|
||||
}
|
||||
|
||||
ProcessDynamicTable(info);
|
||||
*Out = info;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uintptr_t GetSymbolAddress(ElfInfo *Info, const char *SymbolName)
|
||||
{
|
||||
Elf64_Sym *sym = find_symbol(SymbolName,
|
||||
(uint32_t *)Info->DynamicTable.HASH,
|
||||
(Elf64_Sym *)Info->DynamicTable.SYMTAB,
|
||||
(const char *)Info->DynamicTable.STRTAB);
|
||||
if (sym == NULL)
|
||||
return (-ENOSYS);
|
||||
return Info->BaseAddress + sym->st_value;
|
||||
}
|
||||
|
||||
int ResolveExternalSymbol(ElfInfo *Info, uintptr_t *symAddress, Elf_Sym *sym, const char *symName)
|
||||
{
|
||||
*symAddress = (-ENOSYS);
|
||||
|
||||
for (size_t i = 0; *symAddress == (-ENOSYS); i++)
|
||||
{
|
||||
Elf_Dyn *dyn = &Info->Dynamic[i];
|
||||
if (dyn->d_tag == DT_NULL)
|
||||
break;
|
||||
|
||||
if (dyn->d_tag != DT_NEEDED)
|
||||
continue;
|
||||
|
||||
ElfInfo *lib = (ElfInfo *)dyn->d_un.d_ptr;
|
||||
*symAddress = GetSymbolAddress(lib, symName);
|
||||
}
|
||||
|
||||
if (*symAddress != (-ENOSYS))
|
||||
return 0;
|
||||
|
||||
printf("%s: Unresolved symbol: %s\n", Info->Path, symName);
|
||||
if (ELF_ST_BIND(sym->st_info) != STB_WEAK)
|
||||
return -EINVAL;
|
||||
*symAddress = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ApplyRelocation(ElfInfo *Info, uintptr_t *reloc, Elf_Rela *Rela, size_t reloSize)
|
||||
{
|
||||
switch (reloSize)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case sizeof(uint8_t):
|
||||
*reloc += *(uint8_t *)(Info->BaseAddress + Rela->r_offset);
|
||||
break;
|
||||
case sizeof(uint16_t):
|
||||
*reloc += *(uint16_t *)(Info->BaseAddress + Rela->r_offset);
|
||||
break;
|
||||
case sizeof(uint32_t):
|
||||
*reloc += *(uint32_t *)(Info->BaseAddress + Rela->r_offset);
|
||||
break;
|
||||
case sizeof(uint64_t):
|
||||
*reloc += *(uint64_t *)(Info->BaseAddress + Rela->r_offset);
|
||||
break;
|
||||
default:
|
||||
{
|
||||
printf("dl: Unsupported size for relocation\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CalculateRelocation(ElfInfo *Info, uintptr_t *reloc, Elf_Rela *Rela, size_t reloSize)
|
||||
{
|
||||
switch (reloSize)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case sizeof(uint8_t):
|
||||
*(uint8_t *)(Info->BaseAddress + Rela->r_offset) = *reloc;
|
||||
break;
|
||||
case sizeof(uint16_t):
|
||||
*(uint16_t *)(Info->BaseAddress + Rela->r_offset) = *reloc;
|
||||
break;
|
||||
case sizeof(uint32_t):
|
||||
*(uint32_t *)(Info->BaseAddress + Rela->r_offset) = *reloc;
|
||||
break;
|
||||
case sizeof(uint64_t):
|
||||
*(uint64_t *)(Info->BaseAddress + Rela->r_offset) = *reloc;
|
||||
break;
|
||||
default:
|
||||
{
|
||||
printf("dl: Unsupported size for relocation\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int RelocateHelper(ElfInfo *Info, Elf_Rela *Rela, short IsRel, void **Relocated)
|
||||
{
|
||||
uintptr_t reloc = 0;
|
||||
uintptr_t symAddress = 0;
|
||||
size_t symSize = 0;
|
||||
|
||||
uint32_t symIndex = ELF_R_SYM(Rela->r_info);
|
||||
if (symIndex)
|
||||
{
|
||||
Elf_Sym *sym = (Elf_Sym *)(Info->DynamicTable.SYMTAB + symIndex * Info->DynamicSize.SYMENT);
|
||||
const char *symName = (const char *)(Info->DynamicTable.STRTAB + sym->st_name);
|
||||
symSize = sym->st_size;
|
||||
|
||||
if (!(ELF_R_TYPE(Rela->r_info) == R_COPY) && sym->st_shndx)
|
||||
symAddress = Info->BaseAddress + sym->st_value;
|
||||
else if (ResolveExternalSymbol(Info, &symAddress, sym, symName) < 0)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
size_t reloSize = 0;
|
||||
int addAddend = 0;
|
||||
|
||||
enum RelocationTypes relType = ELF_R_TYPE(Rela->r_info);
|
||||
switch (relType)
|
||||
{
|
||||
case R_NONE:
|
||||
break;
|
||||
case R_X86_64_64:
|
||||
{
|
||||
reloSize = 8;
|
||||
reloc = symAddress;
|
||||
addAddend = 1;
|
||||
break;
|
||||
}
|
||||
case R_COPY:
|
||||
{
|
||||
if (symAddress == 0)
|
||||
{
|
||||
printf("dl: Copy undefined weak symbol %d\n", ELF_R_SYM(Rela->r_info));
|
||||
return -EINVAL;
|
||||
}
|
||||
memcpy((void *)(Info->BaseAddress + Rela->r_offset),
|
||||
(void *)symAddress,
|
||||
symSize);
|
||||
break;
|
||||
}
|
||||
case R_GLOB_DAT:
|
||||
case R_JMP_SLOT:
|
||||
{
|
||||
reloSize = 8;
|
||||
reloc = symAddress;
|
||||
break;
|
||||
}
|
||||
case R_RELATIVE:
|
||||
{
|
||||
reloSize = 8;
|
||||
reloc = Info->BaseAddress;
|
||||
addAddend = 1;
|
||||
break;
|
||||
}
|
||||
case R_DTPMOD64:
|
||||
{
|
||||
printf("dl: i don't know what to do with DTPMOD64\n");
|
||||
reloc = Info->BaseAddress;
|
||||
break;
|
||||
}
|
||||
case R_DTPOFF64:
|
||||
{
|
||||
printf("dl: i don't know what to do with DTPOFF64\n");
|
||||
reloc = symAddress + Rela->r_addend;
|
||||
break;
|
||||
}
|
||||
case R_TPOFF64:
|
||||
{
|
||||
printf("dl: i don't know what to do with TPOFF64\n");
|
||||
reloc = symAddress + Rela->r_addend;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
printf("dl: Unsupported relocation type %d\n", relType);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (addAddend)
|
||||
{
|
||||
if (IsRel == 0)
|
||||
reloc += Rela->r_addend;
|
||||
else if (ApplyRelocation(Info, &reloc, Rela, reloSize) < 0)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
CalculateRelocation(Info, &reloc, Rela, reloSize);
|
||||
if (Relocated != NULL)
|
||||
*Relocated = (void *)reloc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int HandleRelocations(ElfInfo *Info);
|
||||
void SearchNeeded(ElfInfo *Info)
|
||||
{
|
||||
for (size_t i = 0;; i++)
|
||||
{
|
||||
Elf_Dyn *elem = &Info->Dynamic[i];
|
||||
if (elem->d_tag == DT_NULL)
|
||||
break;
|
||||
|
||||
if (elem->d_tag != DT_NEEDED)
|
||||
continue;
|
||||
|
||||
HandleRelocations((ElfInfo *)elem->d_un.d_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
int HandleRelocations(ElfInfo *Info)
|
||||
{
|
||||
if (Info->Flags.Relocated)
|
||||
return 0;
|
||||
SearchNeeded(Info);
|
||||
|
||||
if (Info->DynamicTable.REL != ((Elf_Addr)0) && Info->DynamicSize.RELENT != 0)
|
||||
{
|
||||
for (size_t i = 0; i < Info->DynamicSize.RELSZ / Info->DynamicSize.RELENT; i++)
|
||||
RelocateHelper(Info, (Elf_Rela *)(Info->DynamicTable.REL + i * Info->DynamicSize.RELENT), 1, NULL);
|
||||
}
|
||||
|
||||
if (Info->DynamicTable.RELA != ((Elf_Addr)0) && Info->DynamicSize.RELAENT != 0)
|
||||
{
|
||||
for (size_t i = 0; i < Info->DynamicSize.RELASZ / Info->DynamicSize.RELAENT; i++)
|
||||
RelocateHelper(Info, (Elf_Rela *)(Info->DynamicTable.RELA + i * Info->DynamicSize.RELAENT), 0, NULL);
|
||||
}
|
||||
|
||||
if (Info->DynamicTable.JMPREL == ((Elf_Addr)0) || Info->DynamicSize.PLTRELSZ == 0)
|
||||
return 0;
|
||||
|
||||
if (Info->DynamicSize.PLTREL != DT_REL && Info->DynamicSize.PLTREL != DT_RELA)
|
||||
{
|
||||
printf("dl: Wrong PLT relocation type %d\n", Info->DynamicSize.PLTREL);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (Info->DynamicTable.BIND_NOW != ((Elf_Addr)0))
|
||||
{
|
||||
if (Info->DynamicSize.PLTREL == DT_REL)
|
||||
{
|
||||
for (size_t i = 0; i < Info->DynamicSize.PLTRELSZ / sizeof(Elf_Rel); i++)
|
||||
RelocateHelper(Info, (Elf_Rela *)&((Elf_Rel *)Info->DynamicTable.JMPREL)[i], 1, NULL);
|
||||
}
|
||||
else if (Info->DynamicSize.PLTREL == DT_RELA)
|
||||
{
|
||||
for (size_t i = 0; i < Info->DynamicSize.PLTRELSZ / sizeof(Elf_Rela); i++)
|
||||
RelocateHelper(Info, (Elf_Rela *)&((Elf_Rela *)Info->DynamicTable.JMPREL)[i], 0, NULL);
|
||||
}
|
||||
|
||||
Info->Flags.Relocated = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t relsize = Info->DynamicSize.PLTREL == DT_REL ? sizeof(Elf_Rel) : sizeof(Elf_Rela);
|
||||
for (size_t i = 0; i < Info->DynamicSize.PLTRELSZ / relsize; i++)
|
||||
{
|
||||
Elf64_Xword info = (Info->DynamicSize.PLTREL == DT_REL
|
||||
? ((Elf_Rel *)Info->DynamicTable.JMPREL)[i].r_info
|
||||
: ((Elf_Rela *)Info->DynamicTable.JMPREL)[i].r_info);
|
||||
|
||||
Elf_Addr offset = (Info->DynamicSize.PLTREL == DT_REL
|
||||
? ((Elf_Rel *)Info->DynamicTable.JMPREL)[i].r_offset
|
||||
: ((Elf_Rela *)Info->DynamicTable.JMPREL)[i].r_offset);
|
||||
|
||||
if (ELF_R_TYPE(info) != R_JMP_SLOT)
|
||||
{
|
||||
printf("dl: Wrong JMPREL type %d\n", ELF_R_TYPE(info));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* FIXME: HANDLE THIS RIGHT */
|
||||
if (Info->DynamicSize.PLTREL == DT_REL)
|
||||
{
|
||||
Elf_Addr *slot = (Elf_Addr *)(Info->BaseAddress + offset);
|
||||
*slot += Info->BaseAddress;
|
||||
if (*slot == Info->BaseAddress)
|
||||
RelocateHelper(Info, (Elf_Rela *)&((Elf_Rel *)Info->DynamicTable.JMPREL)[i], 1, NULL);
|
||||
}
|
||||
else if (Info->DynamicSize.PLTREL == DT_RELA)
|
||||
{
|
||||
Elf64_Sxword addend = ((Elf_Rela *)Info->DynamicTable.JMPREL)[i].r_addend;
|
||||
Elf_Addr *slot = (Elf_Addr *)(Info->BaseAddress + offset);
|
||||
*slot += Info->BaseAddress + addend;
|
||||
if (*slot == Info->BaseAddress)
|
||||
RelocateHelper(Info, (Elf_Rela *)&((Elf_Rela *)Info->DynamicTable.JMPREL)[i], 0, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
Info->Flags.Relocated = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _dl_main(int argc, char *argv[], char *envp[])
|
||||
{
|
||||
char *path = argv[0];
|
||||
ElfInfo *info = NULL;
|
||||
if (call_access(path, __SYS_F_OK) < 0)
|
||||
{
|
||||
printf("dl: Can't access file %s\n", path);
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
int fd = call_open(path, __SYS_O_RDONLY, 0644);
|
||||
int status = LoadElf(fd, path, &info);
|
||||
if (status < 0)
|
||||
{
|
||||
printf("%s: Can't load ELF file\n", path);
|
||||
call_close(fd);
|
||||
return status;
|
||||
}
|
||||
|
||||
status = HandleRelocations(info);
|
||||
if (status < 0)
|
||||
{
|
||||
printf("%s: Can't relocate ELF file\n", path);
|
||||
call_close(fd);
|
||||
return status;
|
||||
}
|
||||
|
||||
call_close(fd);
|
||||
Elf_Addr entry = info->BaseAddress + info->Header.e_entry;
|
||||
return ((int (*)(int, char *[], char *[]))entry)(argc, argv, envp);
|
||||
}
|
51
Userspace/libc/interpreter/main.c
Normal file
51
Userspace/libc/interpreter/main.c
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
This file is part of Fennix C Library.
|
||||
|
||||
Fennix C Library is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
int printf(const char *, ...);
|
||||
int _dl_main(int, char *[], char *[]);
|
||||
|
||||
void print_help()
|
||||
{
|
||||
printf("Usage: ld.so [options] <program>\n");
|
||||
printf("Options:\n");
|
||||
printf(" --help Display this help message\n");
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[], char *envp[])
|
||||
{
|
||||
if (argc < 2)
|
||||
{
|
||||
printf("Error: No program specified.\n");
|
||||
print_help();
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (int i = 1; i < argc; i++)
|
||||
{
|
||||
if (strcmp(argv[i], "--help") == 0)
|
||||
{
|
||||
print_help();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int status = _dl_main(argc, argv, envp);
|
||||
return status;
|
||||
}
|
50
Userspace/libc/interpreter/misc.h
Normal file
50
Userspace/libc/interpreter/misc.h
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
This file is part of Fennix C Library.
|
||||
|
||||
Fennix C Library is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __FENNIX_DL_HELPER_H__
|
||||
#define __FENNIX_DL_HELPER_H__
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define ALIGN_UP(x, align) ((__typeof__(x))(((uintptr_t)(x) + ((align) - 1)) & (~((align) - 1))))
|
||||
#define ALIGN_DOWN(x, align) ((__typeof__(x))((x) & (~((align) - 1))))
|
||||
|
||||
#ifndef __FENNIX_DL_ELF_H__
|
||||
#error "Please include elf.h before misc.h"
|
||||
#endif
|
||||
|
||||
void *memset(void *s, int c, size_t n);
|
||||
void *memcpy(void *dest, const void *src, size_t n);
|
||||
size_t strlen(const char *s);
|
||||
char *strcpy(char *dest, const char *src);
|
||||
int strcmp(const char *l, const char *r);
|
||||
char *strcat(char *dest, const char *src);
|
||||
|
||||
unsigned long elf_hash(const unsigned char *name);
|
||||
uint32_t gnu_hash(const char *name);
|
||||
Elf64_Sym *find_symbol(const char *name, uint32_t *hash_table, Elf64_Sym *symtab, const char *strtab);
|
||||
|
||||
void __init_print_buffer();
|
||||
void __fini_print_buffer();
|
||||
int printf(const char *format, ...);
|
||||
|
||||
void *mini_malloc(size_t size);
|
||||
void mini_free(void *ptr);
|
||||
|
||||
#endif // !__FENNIX_DL_HELPER_H__
|
1460
Userspace/libc/interpreter/nanoprintf.h
Normal file
1460
Userspace/libc/interpreter/nanoprintf.h
Normal file
File diff suppressed because it is too large
Load Diff
82
Userspace/libc/interpreter/print.c
Normal file
82
Userspace/libc/interpreter/print.c
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
This file is part of Fennix C Library.
|
||||
|
||||
Fennix C Library is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
#include <fennix/syscalls.h>
|
||||
|
||||
#include "elf.h"
|
||||
#include "misc.h"
|
||||
#define NANOPRINTF_IMPLEMENTATION 1
|
||||
#include "nanoprintf.h"
|
||||
|
||||
char *print_buffer;
|
||||
size_t print_buffer_size;
|
||||
size_t print_buffer_offset;
|
||||
void flush_buffer()
|
||||
{
|
||||
if (print_buffer_offset > 0)
|
||||
{
|
||||
call_write(1, print_buffer, print_buffer_offset);
|
||||
print_buffer_offset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void print_wrapper(int c, void *)
|
||||
{
|
||||
if (print_buffer_offset >= print_buffer_size - 1)
|
||||
flush_buffer();
|
||||
print_buffer[print_buffer_offset++] = (char)c;
|
||||
}
|
||||
|
||||
void __init_print_buffer()
|
||||
{
|
||||
print_buffer = (char *)call_mmap(0,
|
||||
0x1000,
|
||||
__SYS_PROT_READ | __SYS_PROT_WRITE,
|
||||
__SYS_MAP_PRIVATE | __SYS_MAP_ANONYMOUS,
|
||||
-1, 0);
|
||||
print_buffer_size = 0x1000;
|
||||
print_buffer_offset = 0;
|
||||
}
|
||||
|
||||
void __fini_print_buffer()
|
||||
{
|
||||
flush_buffer();
|
||||
if (print_buffer != NULL)
|
||||
call_munmap(print_buffer, 0x1000);
|
||||
print_buffer = NULL;
|
||||
}
|
||||
|
||||
int printf(const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
int ret = npf_vpprintf(print_wrapper, NULL, format, args);
|
||||
va_end(args);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int puts(const char *s)
|
||||
{
|
||||
int len = strlen(s);
|
||||
memcpy(print_buffer + print_buffer_offset, s, len);
|
||||
print_buffer_offset += len;
|
||||
print_buffer[print_buffer_offset++] = '\0';
|
||||
flush_buffer();
|
||||
return len + 1;
|
||||
}
|
139
Userspace/libc/interpreter/start.c
Normal file
139
Userspace/libc/interpreter/start.c
Normal file
@ -0,0 +1,139 @@
|
||||
/*
|
||||
This file is part of Fennix C Library.
|
||||
|
||||
Fennix C Library is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <fennix/syscalls.h>
|
||||
|
||||
// const char __interp[] __attribute__((section(".interp"))) = "/boot/fennix.elf";
|
||||
|
||||
#ifndef LIBC_GIT_COMMIT
|
||||
#define LIBC_GIT_COMMIT "0000000000000000000000000000000000000000"
|
||||
#endif
|
||||
|
||||
#define HEX_DIGIT(c) (((c) >= '0' && (c) <= '9') ? ((c) - '0') : ((c) - 'a' + 10))
|
||||
#define CONVERT_TO_BYTE(h, l) ((HEX_DIGIT(h) << 4) | HEX_DIGIT(l))
|
||||
#define HASH_BYTES(hex) \
|
||||
{CONVERT_TO_BYTE(hex[0], hex[1]), \
|
||||
CONVERT_TO_BYTE(hex[2], hex[3]), \
|
||||
CONVERT_TO_BYTE(hex[4], hex[5]), \
|
||||
CONVERT_TO_BYTE(hex[6], hex[7]), \
|
||||
CONVERT_TO_BYTE(hex[8], hex[9]), \
|
||||
CONVERT_TO_BYTE(hex[10], hex[11]), \
|
||||
CONVERT_TO_BYTE(hex[12], hex[13]), \
|
||||
CONVERT_TO_BYTE(hex[14], hex[15]), \
|
||||
CONVERT_TO_BYTE(hex[16], hex[17]), \
|
||||
CONVERT_TO_BYTE(hex[18], hex[19]), \
|
||||
CONVERT_TO_BYTE(hex[20], hex[21]), \
|
||||
CONVERT_TO_BYTE(hex[22], hex[23]), \
|
||||
CONVERT_TO_BYTE(hex[24], hex[25]), \
|
||||
CONVERT_TO_BYTE(hex[26], hex[27]), \
|
||||
CONVERT_TO_BYTE(hex[28], hex[29]), \
|
||||
CONVERT_TO_BYTE(hex[30], hex[31]), \
|
||||
CONVERT_TO_BYTE(hex[32], hex[33]), \
|
||||
CONVERT_TO_BYTE(hex[34], hex[35]), \
|
||||
CONVERT_TO_BYTE(hex[36], hex[37]), \
|
||||
CONVERT_TO_BYTE(hex[38], hex[39])}
|
||||
|
||||
/* These are declared in GNU ld */
|
||||
enum
|
||||
{
|
||||
NT_FNX_ABI_TAG = 1,
|
||||
NT_FNX_VERSION = 2,
|
||||
NT_FNX_BUILD_ID = 3,
|
||||
NT_FNX_ARCH = 4
|
||||
};
|
||||
|
||||
typedef struct Elf_Nhdr
|
||||
{
|
||||
__UINT32_TYPE__ n_namesz;
|
||||
__UINT32_TYPE__ n_descsz;
|
||||
__UINT32_TYPE__ n_type;
|
||||
char n_name[];
|
||||
} __attribute__((packed)) Elf_Nhdr;
|
||||
|
||||
const struct
|
||||
{
|
||||
Elf_Nhdr header;
|
||||
char name[4];
|
||||
__UINT32_TYPE__ desc[4];
|
||||
} __abi_tag __attribute__((aligned(4), section(".note.ABI-tag"))) = {
|
||||
.header = {
|
||||
.n_namesz = 4, /* "FNX" + '\0' */
|
||||
.n_descsz = sizeof(__UINT32_TYPE__) * 4, /* Description Size */
|
||||
.n_type = NT_FNX_ABI_TAG, /* Type */
|
||||
},
|
||||
.name = "FNX",
|
||||
.desc = {0, 0, 0, 0},
|
||||
};
|
||||
|
||||
const struct
|
||||
{
|
||||
Elf_Nhdr header;
|
||||
char name[4];
|
||||
__UINT8_TYPE__ desc[20];
|
||||
} __build_id __attribute__((aligned(4), section(".note.build-id"))) = {
|
||||
.header = {
|
||||
.n_namesz = 4, /* "FNX" + '\0' */
|
||||
.n_descsz = sizeof(__UINT8_TYPE__) * 20, /* Description Size */
|
||||
.n_type = NT_FNX_BUILD_ID, /* Type */
|
||||
},
|
||||
.name = "FNX",
|
||||
.desc = HASH_BYTES(LIBC_GIT_COMMIT),
|
||||
};
|
||||
|
||||
void __init_print_buffer();
|
||||
void __fini_print_buffer();
|
||||
|
||||
__attribute__((naked, used, no_stack_protector)) void _start()
|
||||
{
|
||||
__asm__(
|
||||
"xorq %rbp, %rbp\n" /* Clear rbp */
|
||||
|
||||
"push %rdi\n"
|
||||
"push %rsi\n"
|
||||
"push %rdx\n"
|
||||
"push %rcx\n"
|
||||
"push %r8\n"
|
||||
"push %r9\n"
|
||||
|
||||
"call __init_print_buffer\n" /* Call __init_print_buffer */
|
||||
"call _dl_preload\n" /* Call _dl_preload */
|
||||
"movl %eax, %edi\n" /* Move return value to edi */
|
||||
"cmp $0, %edi\n" /* Check if return value is 0 */
|
||||
"jne _exit\n" /* If not, jump to _exit */
|
||||
|
||||
"pop %r9\n"
|
||||
"pop %r8\n"
|
||||
"pop %rcx\n"
|
||||
"pop %rdx\n"
|
||||
"pop %rsi\n"
|
||||
"pop %rdi\n"
|
||||
|
||||
"call main\n" /* Call _dl_main */
|
||||
"movl %eax, %edi\n" /* Move return value to edi */
|
||||
"call _exit\n"); /* Call _exit */
|
||||
}
|
||||
|
||||
__attribute__((no_stack_protector)) _Noreturn void _exit(int status)
|
||||
{
|
||||
__fini_print_buffer();
|
||||
call_exit(status);
|
||||
/* At this point, the program *SHOULD* have exited. */
|
||||
__asm__("ud2\n");
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
__attribute__((no_stack_protector)) _Noreturn void _Exit(int status) { _exit(status); }
|
@ -1,20 +1,10 @@
|
||||
# Config file
|
||||
include ../../../config.mk
|
||||
default:
|
||||
$(error Do not run this Makefile directly!)
|
||||
|
||||
CC = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)gcc
|
||||
AS = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)as
|
||||
NASM = /usr/bin/nasm
|
||||
|
||||
C_SOURCES = $(shell find ./ -type f -name '*.c')
|
||||
S_SOURCES = $(shell find ./ -type f -name '*.S')
|
||||
ASM_SOURCES = $(shell find ./ -type f -name '*.asm')
|
||||
OBJ = ${C_SOURCES:.c=.o} ${ASM_SOURCES:.asm=.o} ${S_SOURCES:.S=.o}
|
||||
|
||||
ifeq ($(OSARCH), amd64)
|
||||
ASM_ARCH := elf64
|
||||
else ifeq ($(OSARCH), i386)
|
||||
ASM_ARCH := elf32
|
||||
endif
|
||||
C_SOURCES = $(shell find ./ -type f -name '*.c')
|
||||
CXX_SOURCES = $(shell find ./ -type f -name '*.cpp')
|
||||
OBJ = ${S_SOURCES:.S=.o} ${C_SOURCES:.c=.o} ${CXX_SOURCES:.cpp=.o}
|
||||
|
||||
CRTBEGIN_PATH = $(shell $(CC) -print-file-name=crtbegin.o)
|
||||
CRTEND_PATH = $(shell $(CC) -print-file-name=crtend.o)
|
||||
@ -22,20 +12,16 @@ CRTI_PATH = $(shell $(CC) -print-file-name=crti.o)
|
||||
CRTN_PATH = $(shell $(CC) -print-file-name=crtn.o)
|
||||
|
||||
build: $(OBJ)
|
||||
mv $^ ../../out/lib/
|
||||
cp $(CRTBEGIN_PATH) $(CRTEND_PATH) $(CRTI_PATH) $(CRTN_PATH) ../../out/lib/
|
||||
cp $^ ../../out/lib/
|
||||
cp $(CRTBEGIN_PATH) $(CRTEND_PATH) $(CRTI_PATH) $(CRTN_PATH) $(WORKSPACE_DIR)/out/lib/
|
||||
|
||||
%.o: %.c
|
||||
$(info Compiling $<)
|
||||
$(CC) -nostdlib -mno-red-zone -std=c17 -c $< -o $@
|
||||
|
||||
%.o: %.asm
|
||||
$(info Compiling $<)
|
||||
$(NASM) $< -f $(ASM_ARCH) -o $@
|
||||
$(CC) -nostdlib -mno-red-zone -std=c17 -DLIBC_GIT_COMMIT='"$(shell git rev-parse HEAD)"' -c $< -o $@
|
||||
|
||||
%.o: %.S
|
||||
$(info Compiling $<)
|
||||
$(AS) -c $< -o $@
|
||||
|
||||
clean:
|
||||
|
||||
rm -f $(OBJ)
|
||||
|
100
Userspace/libc/runtime/Scrt1.c
Normal file
100
Userspace/libc/runtime/Scrt1.c
Normal file
@ -0,0 +1,100 @@
|
||||
/*
|
||||
This file is part of Fennix Userspace.
|
||||
|
||||
Fennix Userspace is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Userspace is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Userspace. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
typedef void (*fct)(void);
|
||||
#define asm __asm__ __volatile__
|
||||
|
||||
extern void (*__preinit_array_start[])(void) __attribute__((weak));
|
||||
extern void (*__preinit_array_end[])(void) __attribute__((weak));
|
||||
extern void (*__init_array_start[])(void) __attribute__((weak));
|
||||
extern void (*__init_array_end[])(void) __attribute__((weak));
|
||||
extern void (*__fini_array_start[])(void) __attribute__((weak));
|
||||
extern void (*__fini_array_end[])(void) __attribute__((weak));
|
||||
|
||||
void __crt_init_array(void)
|
||||
{
|
||||
for (fct *func = __init_array_start; func != __init_array_end; func++)
|
||||
(*func)();
|
||||
}
|
||||
|
||||
void __crt_fini_array(void)
|
||||
{
|
||||
for (fct *func = __fini_array_start; func != __fini_array_end; func++)
|
||||
(*func)();
|
||||
}
|
||||
|
||||
__attribute__((naked, used, no_stack_protector, section(".text"))) void _start()
|
||||
{
|
||||
asm("movq $0, %rbp\n"
|
||||
"pushq %rbp\n"
|
||||
"pushq %rbp\n"
|
||||
"movq %rsp, %rbp\n"
|
||||
|
||||
"pushq %rcx\n"
|
||||
"pushq %rdx\n"
|
||||
"pushq %rsi\n"
|
||||
"pushq %rdi\n"
|
||||
|
||||
"call __libc_init\n"
|
||||
"call __crt_init_array\n"
|
||||
|
||||
"popq %rdi\n"
|
||||
"popq %rsi\n"
|
||||
"popq %rdx\n"
|
||||
"popq %rcx\n"
|
||||
|
||||
"call main\n"
|
||||
|
||||
"pushq %rax\n"
|
||||
"call __crt_fini_array\n"
|
||||
"popq %rax\n"
|
||||
|
||||
"movl %eax, %edi\n"
|
||||
"call _exit\n");
|
||||
}
|
||||
|
||||
/* These are declared in GNU ld */
|
||||
enum
|
||||
{
|
||||
NT_FNX_ABI_TAG = 1,
|
||||
NT_FNX_VERSION = 2,
|
||||
NT_FNX_BUILD_ID = 3,
|
||||
NT_FNX_ARCH = 4
|
||||
};
|
||||
|
||||
typedef struct Elf_Nhdr
|
||||
{
|
||||
__UINT32_TYPE__ n_namesz;
|
||||
__UINT32_TYPE__ n_descsz;
|
||||
__UINT32_TYPE__ n_type;
|
||||
char n_name[];
|
||||
} __attribute__((packed)) Elf_Nhdr;
|
||||
|
||||
const struct
|
||||
{
|
||||
Elf_Nhdr header;
|
||||
char name[4];
|
||||
__UINT32_TYPE__ desc[4];
|
||||
} __abi_tag __attribute__((aligned(4), section(".note.ABI-tag"))) = {
|
||||
.header = {
|
||||
.n_namesz = 4, /* "FNX" + '\0' */
|
||||
.n_descsz = sizeof(__UINT32_TYPE__) * 4, /* Description Size */
|
||||
.n_type = NT_FNX_ABI_TAG, /* Type */
|
||||
},
|
||||
.name = "FNX",
|
||||
.desc = {0, 0, 0, 0},
|
||||
};
|
@ -1,21 +0,0 @@
|
||||
// https://wiki.osdev.org/Creating_a_C_Library
|
||||
#define asm __asm__ __volatile__
|
||||
__attribute__((naked, used, no_stack_protector, section(".text"))) void _start()
|
||||
{
|
||||
asm("movq $0, %rbp\n");
|
||||
asm("pushq %rbp\n");
|
||||
asm("pushq %rbp\n");
|
||||
asm("movq %rsp, %rbp\n");
|
||||
asm("pushq %rcx\n"
|
||||
"pushq %rdx\n"
|
||||
"pushq %rsi\n"
|
||||
"pushq %rdi\n");
|
||||
asm("call __libc_init\n");
|
||||
asm("popq %rdi\n"
|
||||
"popq %rsi\n"
|
||||
"popq %rdx\n"
|
||||
"popq %rcx\n");
|
||||
asm("call main\n");
|
||||
asm("movl %eax, %edi\n");
|
||||
asm("call _exit\n");
|
||||
}
|
@ -1,21 +1,100 @@
|
||||
// https://wiki.osdev.org/Creating_a_C_Library
|
||||
/*
|
||||
This file is part of Fennix Userspace.
|
||||
|
||||
Fennix Userspace is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Userspace is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Userspace. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
typedef void (*fct)(void);
|
||||
#define asm __asm__ __volatile__
|
||||
|
||||
extern void (*__preinit_array_start[])(void) __attribute__((weak));
|
||||
extern void (*__preinit_array_end[])(void) __attribute__((weak));
|
||||
extern void (*__init_array_start[])(void) __attribute__((weak));
|
||||
extern void (*__init_array_end[])(void) __attribute__((weak));
|
||||
extern void (*__fini_array_start[])(void) __attribute__((weak));
|
||||
extern void (*__fini_array_end[])(void) __attribute__((weak));
|
||||
|
||||
void __crt_init_array(void)
|
||||
{
|
||||
for (fct *func = __init_array_start; func != __init_array_end; func++)
|
||||
(*func)();
|
||||
}
|
||||
|
||||
void __crt_fini_array(void)
|
||||
{
|
||||
for (fct *func = __fini_array_start; func != __fini_array_end; func++)
|
||||
(*func)();
|
||||
}
|
||||
|
||||
__attribute__((naked, used, no_stack_protector, section(".text"))) void _start()
|
||||
{
|
||||
asm("movq $0, %rbp\n");
|
||||
asm("pushq %rbp\n");
|
||||
asm("pushq %rbp\n");
|
||||
asm("movq %rsp, %rbp\n");
|
||||
asm("pushq %rcx\n"
|
||||
asm("movq $0, %rbp\n"
|
||||
"pushq %rbp\n"
|
||||
"pushq %rbp\n"
|
||||
"movq %rsp, %rbp\n"
|
||||
|
||||
"pushq %rcx\n"
|
||||
"pushq %rdx\n"
|
||||
"pushq %rsi\n"
|
||||
"pushq %rdi\n");
|
||||
asm("call __libc_init\n");
|
||||
asm("popq %rdi\n"
|
||||
"pushq %rdi\n"
|
||||
|
||||
"call __libc_init\n"
|
||||
"call __crt_init_array\n"
|
||||
|
||||
"popq %rdi\n"
|
||||
"popq %rsi\n"
|
||||
"popq %rdx\n"
|
||||
"popq %rcx\n");
|
||||
asm("call main\n");
|
||||
asm("movl %eax, %edi\n");
|
||||
asm("call _exit\n");
|
||||
"popq %rcx\n"
|
||||
|
||||
"call main\n"
|
||||
|
||||
"pushq %rax\n"
|
||||
"call __crt_fini_array\n"
|
||||
"popq %rax\n"
|
||||
|
||||
"movl %eax, %edi\n"
|
||||
"call _exit\n");
|
||||
}
|
||||
|
||||
/* These are declared in GNU ld */
|
||||
enum
|
||||
{
|
||||
NT_FNX_ABI_TAG = 1,
|
||||
NT_FNX_VERSION = 2,
|
||||
NT_FNX_BUILD_ID = 3,
|
||||
NT_FNX_ARCH = 4
|
||||
};
|
||||
|
||||
typedef struct Elf_Nhdr
|
||||
{
|
||||
__UINT32_TYPE__ n_namesz;
|
||||
__UINT32_TYPE__ n_descsz;
|
||||
__UINT32_TYPE__ n_type;
|
||||
char n_name[];
|
||||
} __attribute__((packed)) Elf_Nhdr;
|
||||
|
||||
const struct
|
||||
{
|
||||
Elf_Nhdr header;
|
||||
char name[4];
|
||||
__UINT32_TYPE__ desc[4];
|
||||
} __abi_tag __attribute__((aligned(4), section(".note.ABI-tag"))) = {
|
||||
.header = {
|
||||
.n_namesz = 4, /* "FNX" + '\0' */
|
||||
.n_descsz = sizeof(__UINT32_TYPE__) * 4, /* Description Size */
|
||||
.n_type = NT_FNX_ABI_TAG, /* Type */
|
||||
},
|
||||
.name = "FNX",
|
||||
.desc = {0, 0, 0, 0},
|
||||
};
|
||||
|
@ -1,22 +0,0 @@
|
||||
// extern void (*__preinit_array_start[])(void) __attribute__((weak));
|
||||
// extern void (*__preinit_array_end[])(void) __attribute__((weak));
|
||||
// extern void (*__init_array_start[])(void) __attribute__((weak));
|
||||
// extern void (*__init_array_end[])(void) __attribute__((weak));
|
||||
// extern void (*__fini_array_start []) (void) __attribute__((weak));
|
||||
// extern void (*__fini_array_end []) (void) __attribute__((weak));
|
||||
|
||||
typedef void (*fct)(void);
|
||||
extern fct __init_array_start[0], __init_array_end[0];
|
||||
extern fct __fini_array_start[0], __fini_array_end[0];
|
||||
|
||||
void __libc_init_array(void)
|
||||
{
|
||||
for (fct *func = __init_array_start; func != __init_array_end; func++)
|
||||
(*func)();
|
||||
}
|
||||
|
||||
void __libc_fini_array(void)
|
||||
{
|
||||
for (fct *func = __fini_array_start; func != __fini_array_end; func++)
|
||||
(*func)();
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
#include "lock.hpp"
|
||||
#include <stdio.h>
|
||||
|
||||
void LockClass::DeadLock(SpinLockData Lock)
|
||||
{
|
||||
fprintf(stdout, "Potential deadlock in lock '%s' held by '%s'! %ld locks in queue.",
|
||||
Lock.AttemptingToGet, Lock.CurrentHolder, Lock.Count);
|
||||
}
|
||||
|
||||
int LockClass::Lock(const char *FunctionName)
|
||||
{
|
||||
LockData.AttemptingToGet = FunctionName;
|
||||
Retry:
|
||||
unsigned int i = 0;
|
||||
while (__atomic_exchange_n(&IsLocked, true, __ATOMIC_ACQUIRE) && ++i < 0x10000000)
|
||||
;
|
||||
if (i >= 0x10000000)
|
||||
{
|
||||
DeadLock(LockData);
|
||||
goto Retry;
|
||||
}
|
||||
LockData.Count++;
|
||||
LockData.CurrentHolder = FunctionName;
|
||||
__sync_synchronize();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LockClass::Unlock()
|
||||
{
|
||||
__sync_synchronize();
|
||||
__atomic_store_n(&IsLocked, false, __ATOMIC_RELEASE);
|
||||
LockData.Count--;
|
||||
IsLocked = false;
|
||||
return 0;
|
||||
}
|
@ -1,47 +1,36 @@
|
||||
# Config file
|
||||
include ../../../config.mk
|
||||
default:
|
||||
$(error Do not run this Makefile directly!)
|
||||
|
||||
NAME=c
|
||||
DYNAMIC_NAME := libc.so
|
||||
STATIC_NAME := libc.a
|
||||
|
||||
ifeq ($(USERSPACE_STATIC_LIBS), 1)
|
||||
OBJECT_NAME := lib$(NAME).a
|
||||
else
|
||||
OBJECT_NAME := lib$(NAME).so
|
||||
endif
|
||||
OUTPUT_DIR=$(WORKSPACE_DIR)/out/lib/
|
||||
SYSROOT = --sysroot=$(WORKSPACE_DIR)/out/
|
||||
|
||||
OUTPUT_DIR=../../out/lib/
|
||||
SYSROOT = --sysroot=../../out/
|
||||
|
||||
CC = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)gcc
|
||||
AS = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)as
|
||||
AR = ../../../$(COMPILER_PATH)/$(COMPILER_ARCH)ar
|
||||
|
||||
C_SOURCES = $(shell find ./ -type f -name '*.c')
|
||||
CPP_SOURCES = $(shell find ./ -type f -name '*.cpp')
|
||||
S_SOURCES = $(shell find ./ -type f -name '*.S')
|
||||
OBJ = ${C_SOURCES:.c=.o} ${CPP_SOURCES:.cpp=.o} ${S_SOURCES:.S=.o}
|
||||
C_SOURCES = $(shell find ./ -type f -name '*.c')
|
||||
CXX_SOURCES = $(shell find ./ -type f -name '*.cpp')
|
||||
OBJ = ${S_SOURCES:.S=.o} ${C_SOURCES:.c=.o} ${CXX_SOURCES:.cpp=.o}
|
||||
|
||||
ifeq ($(OSARCH), amd64)
|
||||
ASM_ARCH := elf64
|
||||
else ifeq ($(OSARCH), i386)
|
||||
ASM_ARCH := elf32
|
||||
endif
|
||||
|
||||
CFLAGS := -fvisibility=hidden -fPIC -I../include -I../../out/include
|
||||
CFLAGS := -fvisibility=hidden -fPIC -I../include -I$(WORKSPACE_DIR)/out/include -DLIBC_GIT_COMMIT='"$(shell git rev-parse HEAD)"'
|
||||
|
||||
ifeq ($(DEBUG), 1)
|
||||
CFLAGS += -DDEBUG -ggdb3 -O0 -fdiagnostics-color=always -fverbose-asm
|
||||
endif
|
||||
|
||||
build: $(OBJECT_NAME)
|
||||
build: $(DYNAMIC_NAME) $(STATIC_NAME)
|
||||
|
||||
$(OBJECT_NAME): $(OBJ)
|
||||
.PHONY: $(DYNAMIC_NAME) $(STATIC_NAME)
|
||||
|
||||
$(DYNAMIC_NAME): $(OBJ)
|
||||
$(info Linking $@)
|
||||
ifeq ($(USERSPACE_STATIC_LIBS), 1)
|
||||
$(AR) rcs $(OUTPUT_DIR)$@ $(OBJ)
|
||||
else
|
||||
$(CC) -nostdlib -shared -fPIC -fPIE -Wl,-soname,$(OBJECT_NAME) $(SYSROOT) $(OBJ) -o $(OUTPUT_DIR)$@
|
||||
endif
|
||||
$(CC) -nostdlib -shared -fPIC -fPIE -e _start -Wl,-soname,$(DYNAMIC_NAME) $(SYSROOT) $(OBJ) -o $(DYNAMIC_NAME)
|
||||
cp $(DYNAMIC_NAME) $(OUTPUT_DIR)$(DYNAMIC_NAME)
|
||||
|
||||
$(STATIC_NAME): $(OBJ)
|
||||
$(info Linking $@)
|
||||
$(AR) -rcs $(STATIC_NAME) $(OBJ)
|
||||
cp $(STATIC_NAME) $(OUTPUT_DIR)$(STATIC_NAME)
|
||||
|
||||
%.o: %.c
|
||||
$(info Compiling $<)
|
||||
@ -56,4 +45,4 @@ endif
|
||||
$(AS) -c $< -o $@
|
||||
|
||||
clean:
|
||||
rm -f $(OBJ)
|
||||
rm -f $(OBJ) $(DYNAMIC_NAME) $(STATIC_NAME)
|
||||
|
@ -1,23 +0,0 @@
|
||||
#include <fennix/syscall.h>
|
||||
#include <sys/types.h> // For PUBLIC
|
||||
|
||||
extern void __libc_init_array(void);
|
||||
extern void __libc_fini_array(void);
|
||||
|
||||
extern void __libc_init_std(void);
|
||||
extern void __libc_fini_std(void);
|
||||
|
||||
PUBLIC void __libc_init(void)
|
||||
{
|
||||
__libc_init_array();
|
||||
__libc_init_std();
|
||||
}
|
||||
|
||||
PUBLIC void _exit(int Code)
|
||||
{
|
||||
__libc_fini_std();
|
||||
__libc_fini_array();
|
||||
syscall1(sc_exit, (long)Code);
|
||||
while (1)
|
||||
;
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
#include <dlfcn.h>
|
||||
|
||||
static char *error = "Not implemented";
|
||||
|
||||
__attribute__((weak)) void *dlopen(const char *filename, int flags)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
__attribute__((weak)) void *dlsym(void *handle, const char *symbol)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
__attribute__((weak)) int dlclose(void *handle)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
__attribute__((weak)) char *dlerror(void)
|
||||
{
|
||||
return error;
|
||||
}
|
34
Userspace/libc/src/init.c
Normal file
34
Userspace/libc/src/init.c
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
This file is part of Fennix Userspace.
|
||||
|
||||
Fennix Userspace is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Userspace is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Userspace. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <fennix/syscalls.h>
|
||||
|
||||
int __init_pthread(void);
|
||||
void __init_stdio(void);
|
||||
|
||||
__attribute__((visibility("default"))) void __libc_init(void)
|
||||
{
|
||||
__init_pthread();
|
||||
__init_stdio();
|
||||
}
|
||||
|
||||
__attribute__((visibility("default"))) void _exit(int Code)
|
||||
{
|
||||
call_exit(Code);
|
||||
while (1)
|
||||
;
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
#ifndef __FENNIX_KERNEL_LOCK_H__
|
||||
#define __FENNIX_KERNEL_LOCK_H__
|
||||
|
||||
#include <types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
/** @brief Please use this macro to create a new lock. */
|
||||
class LockClass
|
||||
{
|
||||
struct SpinLockData
|
||||
{
|
||||
uint64_t LockData = 0x0;
|
||||
const char *CurrentHolder = "(nul)";
|
||||
const char *AttemptingToGet = "(nul)";
|
||||
uint64_t Count = 0;
|
||||
};
|
||||
void DeadLock(SpinLockData Lock);
|
||||
|
||||
private:
|
||||
SpinLockData LockData;
|
||||
bool IsLocked = false;
|
||||
|
||||
public:
|
||||
SpinLockData *GetLockData() { return &LockData; }
|
||||
int Lock(const char *FunctionName);
|
||||
int Unlock();
|
||||
};
|
||||
|
||||
/** @brief Please use this macro to create a new smart lock. */
|
||||
class SmartLockClass
|
||||
{
|
||||
private:
|
||||
LockClass *LockPointer = nullptr;
|
||||
|
||||
public:
|
||||
SmartLockClass(LockClass &Lock, const char *FunctionName)
|
||||
{
|
||||
this->LockPointer = &Lock;
|
||||
this->LockPointer->Lock(FunctionName);
|
||||
}
|
||||
~SmartLockClass() { this->LockPointer->Unlock(); }
|
||||
};
|
||||
|
||||
/** @brief Create a new lock (can be used with SmartCriticalSection). */
|
||||
#define NewLock(Name) LockClass Name
|
||||
/** @brief Simple lock that is automatically released when the scope ends. */
|
||||
#define SmartLock(LockClassName) SmartLockClass CONCAT(lock##_, __COUNTER__)(LockClassName, __FUNCTION__)
|
||||
|
||||
#endif // __cplusplus
|
||||
#endif // !__FENNIX_KERNEL_LOCK_H__
|
@ -1,5 +1,152 @@
|
||||
/* TODO: Show a message or something */
|
||||
int _start()
|
||||
/*
|
||||
This file is part of Fennix Userspace.
|
||||
|
||||
Fennix Userspace is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix Userspace is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix Userspace. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
typedef void (*fct)(void);
|
||||
#define asm __asm__ __volatile__
|
||||
__attribute__((__visibility__("hidden"))) extern void (*__preinit_array_start[])(void) __attribute__((weak));
|
||||
__attribute__((__visibility__("hidden"))) extern void (*__preinit_array_end[])(void) __attribute__((weak));
|
||||
__attribute__((__visibility__("hidden"))) extern void (*__init_array_start[])(void) __attribute__((weak));
|
||||
__attribute__((__visibility__("hidden"))) extern void (*__init_array_end[])(void) __attribute__((weak));
|
||||
__attribute__((__visibility__("hidden"))) extern void (*__fini_array_start[])(void) __attribute__((weak));
|
||||
__attribute__((__visibility__("hidden"))) extern void (*__fini_array_end[])(void) __attribute__((weak));
|
||||
const char __interp[] __attribute__((section(".interp"))) = "/lib/ld.so";
|
||||
|
||||
#ifndef LIBC_GIT_COMMIT
|
||||
#define LIBC_GIT_COMMIT "0000000000000000000000000000000000000000"
|
||||
#endif
|
||||
|
||||
#define HEX_DIGIT(c) (((c) >= '0' && (c) <= '9') ? ((c) - '0') : ((c) - 'a' + 10))
|
||||
#define CONVERT_TO_BYTE(h, l) ((HEX_DIGIT(h) << 4) | HEX_DIGIT(l))
|
||||
#define HASH_BYTES(hex) \
|
||||
{CONVERT_TO_BYTE(hex[0], hex[1]), \
|
||||
CONVERT_TO_BYTE(hex[2], hex[3]), \
|
||||
CONVERT_TO_BYTE(hex[4], hex[5]), \
|
||||
CONVERT_TO_BYTE(hex[6], hex[7]), \
|
||||
CONVERT_TO_BYTE(hex[8], hex[9]), \
|
||||
CONVERT_TO_BYTE(hex[10], hex[11]), \
|
||||
CONVERT_TO_BYTE(hex[12], hex[13]), \
|
||||
CONVERT_TO_BYTE(hex[14], hex[15]), \
|
||||
CONVERT_TO_BYTE(hex[16], hex[17]), \
|
||||
CONVERT_TO_BYTE(hex[18], hex[19]), \
|
||||
CONVERT_TO_BYTE(hex[20], hex[21]), \
|
||||
CONVERT_TO_BYTE(hex[22], hex[23]), \
|
||||
CONVERT_TO_BYTE(hex[24], hex[25]), \
|
||||
CONVERT_TO_BYTE(hex[26], hex[27]), \
|
||||
CONVERT_TO_BYTE(hex[28], hex[29]), \
|
||||
CONVERT_TO_BYTE(hex[30], hex[31]), \
|
||||
CONVERT_TO_BYTE(hex[32], hex[33]), \
|
||||
CONVERT_TO_BYTE(hex[34], hex[35]), \
|
||||
CONVERT_TO_BYTE(hex[36], hex[37]), \
|
||||
CONVERT_TO_BYTE(hex[38], hex[39])}
|
||||
|
||||
/* These are declared in GNU ld */
|
||||
enum
|
||||
{
|
||||
NT_FNX_ABI_TAG = 1,
|
||||
NT_FNX_VERSION = 2,
|
||||
NT_FNX_BUILD_ID = 3,
|
||||
NT_FNX_ARCH = 4
|
||||
};
|
||||
|
||||
typedef struct Elf_Nhdr
|
||||
{
|
||||
__UINT32_TYPE__ n_namesz;
|
||||
__UINT32_TYPE__ n_descsz;
|
||||
__UINT32_TYPE__ n_type;
|
||||
char n_name[];
|
||||
} __attribute__((packed)) Elf_Nhdr;
|
||||
|
||||
const struct
|
||||
{
|
||||
Elf_Nhdr header;
|
||||
char name[4];
|
||||
__UINT32_TYPE__ desc[4];
|
||||
} __abi_tag __attribute__((aligned(4), section(".note.ABI-tag"))) = {
|
||||
.header = {
|
||||
.n_namesz = 4, /* "FNX" + '\0' */
|
||||
.n_descsz = sizeof(__UINT32_TYPE__) * 4, /* Description Size */
|
||||
.n_type = NT_FNX_ABI_TAG, /* Type */
|
||||
},
|
||||
.name = "FNX",
|
||||
.desc = {0, 0, 0, 0},
|
||||
};
|
||||
|
||||
const struct
|
||||
{
|
||||
Elf_Nhdr header;
|
||||
char name[4];
|
||||
__UINT8_TYPE__ desc[20];
|
||||
} __build_id __attribute__((aligned(4), section(".note.build-id"))) = {
|
||||
.header = {
|
||||
.n_namesz = 4, /* "FNX" + '\0' */
|
||||
.n_descsz = sizeof(__UINT8_TYPE__) * 20, /* Description Size */
|
||||
.n_type = NT_FNX_BUILD_ID, /* Type */
|
||||
},
|
||||
.name = "FNX",
|
||||
.desc = HASH_BYTES(LIBC_GIT_COMMIT),
|
||||
};
|
||||
|
||||
void __crt_init_array(void)
|
||||
{
|
||||
for (fct *func = __init_array_start; func != __init_array_end; func++)
|
||||
(*func)();
|
||||
}
|
||||
|
||||
void __crt_fini_array(void)
|
||||
{
|
||||
for (fct *func = __fini_array_start; func != __fini_array_end; func++)
|
||||
(*func)();
|
||||
}
|
||||
|
||||
__attribute__((naked, used, no_stack_protector, section(".text"))) void _start()
|
||||
{
|
||||
asm("movq $0, %rbp\n"
|
||||
"pushq %rbp\n"
|
||||
"pushq %rbp\n"
|
||||
"movq %rsp, %rbp\n"
|
||||
|
||||
"pushq %rcx\n"
|
||||
"pushq %rdx\n"
|
||||
"pushq %rsi\n"
|
||||
"pushq %rdi\n"
|
||||
|
||||
"call __libc_init\n"
|
||||
"call __crt_init_array\n"
|
||||
|
||||
"popq %rdi\n"
|
||||
"popq %rsi\n"
|
||||
"popq %rdx\n"
|
||||
"popq %rcx\n"
|
||||
|
||||
"call main\n"
|
||||
|
||||
"pushq %rax\n"
|
||||
"call __crt_fini_array\n"
|
||||
"popq %rax\n"
|
||||
|
||||
"movl %eax, %edi\n"
|
||||
"call _exit\n");
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[], char *envp[])
|
||||
{
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
(void)envp;
|
||||
/* FIXME: show printf license notice and some help and commands? */
|
||||
return -1;
|
||||
}
|
||||
|
10
Userspace/libc/src/mem/LICENSE
Normal file
10
Userspace/libc/src/mem/LICENSE
Normal file
@ -0,0 +1,10 @@
|
||||
|
||||
This code is released into the public domain. Use this code at your own
|
||||
risk. Feel free to use it for whatever purpose you want. I take no responsibilty or
|
||||
whatever if anything goes wrong. Use it at your own risk.
|
||||
|
||||
If you have any fixes or patches, please email me.
|
||||
|
||||
Durand Miller <clutter@djm.co.za>
|
||||
|
||||
|
@ -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);
|
||||
}
|
78
Userspace/libc/src/mem/liballoc.c
Normal file
78
Userspace/libc/src/mem/liballoc.c
Normal file
@ -0,0 +1,78 @@
|
||||
/*
|
||||
This file is part of Fennix C Library.
|
||||
|
||||
Fennix C Library is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation, either version 3 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
Fennix C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* 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);
|
||||
}
|
@ -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));
|
||||
|
@ -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
|
||||
|
23
Userspace/libc/src/print/LICENSE
Normal file
23
Userspace/libc/src/print/LICENSE
Normal 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.
|
||||
|
20
Userspace/libc/src/print/print.c
Normal file
20
Userspace/libc/src/print/print.c
Normal 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
@ -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_
|
||||
|
@ -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);
|
||||
}
|
26
Userspace/libc/src/std/assert.c
Normal file
26
Userspace/libc/src/std/assert.c
Normal 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();
|
||||
}
|
@ -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';
|
||||
}
|
@ -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";
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
@ -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)
|
||||
{
|
||||
}
|
@ -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); }
|
@ -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;
|
||||
}
|
121
Userspace/libc/src/std/pthread.c
Normal file
121
Userspace/libc/src/std/pthread.c
Normal 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);
|
47
Userspace/libc/src/std/signal.c
Normal file
47
Userspace/libc/src/std/signal.c
Normal 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);
|
@ -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[])
|
||||
{
|
||||
}
|
@ -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)
|
||||
{
|
||||
}
|
343
Userspace/libc/src/std/stdio.c
Normal file
343
Userspace/libc/src/std/stdio.c
Normal 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);
|
105
Userspace/libc/src/std/stdlib.c
Normal file
105
Userspace/libc/src/std/stdlib.c
Normal 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);
|
86
Userspace/libc/src/std/string.c
Normal file
86
Userspace/libc/src/std/string.c
Normal 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);
|
@ -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;
|
||||
}
|
@ -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
Reference in New Issue
Block a user