mirror of
https://github.com/EnderIce2/Fennix.git
synced 2025-05-25 22:14:34 +00:00
fix(userspace/libc): interpreter didn't worked at all
This commit is contained in:
parent
f5c9b561a9
commit
cd23c59c46
@ -15,6 +15,7 @@ if(GIT_COMMIT)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_compile_definitions(FENNIX_DYNAMIC_LOADER="1")
|
add_compile_definitions(FENNIX_DYNAMIC_LOADER="1")
|
||||||
|
add_compile_definitions(PROGRAM_VERSION="${PROJECT_VERSION}")
|
||||||
|
|
||||||
install(TARGETS ld.so DESTINATION lib)
|
install(TARGETS ld.so DESTINATION lib)
|
||||||
target_compile_options(ld.so PRIVATE -fvisibility=hidden -fPIC)
|
target_compile_options(ld.so PRIVATE -fvisibility=hidden -fPIC)
|
||||||
|
@ -25,6 +25,11 @@
|
|||||||
#include "elf.h"
|
#include "elf.h"
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
|
|
||||||
|
#undef PAGE_SIZE
|
||||||
|
#define PAGE_SIZE 0x1000
|
||||||
|
#undef ALIGN_UP
|
||||||
|
#define ALIGN_UP(x, a) (((x) + (a) - 1) & ~((a) - 1))
|
||||||
|
|
||||||
typedef struct MemoryBlock
|
typedef struct MemoryBlock
|
||||||
{
|
{
|
||||||
struct MemoryBlock *next;
|
struct MemoryBlock *next;
|
||||||
@ -32,14 +37,15 @@ typedef struct MemoryBlock
|
|||||||
size_t slot_size;
|
size_t slot_size;
|
||||||
size_t slots_per_block;
|
size_t slots_per_block;
|
||||||
uint8_t *bitmap;
|
uint8_t *bitmap;
|
||||||
|
size_t bitmap_size;
|
||||||
|
size_t total_size;
|
||||||
} MemoryBlock;
|
} MemoryBlock;
|
||||||
|
|
||||||
MemoryBlock *memory_pool = NULL;
|
static MemoryBlock *memory_pool = NULL;
|
||||||
#define PAGE_SIZE 0x1000
|
|
||||||
|
|
||||||
void *request_page(size_t size)
|
void *request_page(size_t size)
|
||||||
{
|
{
|
||||||
size_t aligned_size = (size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
|
size_t aligned_size = ALIGN_UP(size, PAGE_SIZE);
|
||||||
void *addr = (void *)sysdep(MemoryMap)(NULL, aligned_size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
|
void *addr = (void *)sysdep(MemoryMap)(NULL, aligned_size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
|
||||||
if ((intptr_t)addr < 0)
|
if ((intptr_t)addr < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -48,42 +54,60 @@ void *request_page(size_t size)
|
|||||||
|
|
||||||
void free_page(void *addr, size_t size)
|
void free_page(void *addr, size_t size)
|
||||||
{
|
{
|
||||||
size_t aligned_size = (size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
|
size_t aligned_size = ALIGN_UP(size, PAGE_SIZE);
|
||||||
sysdep(MemoryUnmap)(addr, aligned_size);
|
sysdep(MemoryUnmap)(addr, aligned_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryBlock *allocate_block(size_t slot_size)
|
MemoryBlock *allocate_block(size_t slot_size)
|
||||||
{
|
{
|
||||||
size_t block_size = PAGE_SIZE;
|
if (slot_size == 0 || slot_size > PAGE_SIZE / 2)
|
||||||
size_t slots_per_block = block_size / slot_size;
|
return NULL;
|
||||||
size_t bitmap_size = (slots_per_block + 7) / 8;
|
|
||||||
|
|
||||||
MemoryBlock *block = request_page(block_size);
|
size_t estimated_slots = (PAGE_SIZE - sizeof(MemoryBlock)) / (slot_size + 1.0 / 8.0);
|
||||||
|
if (estimated_slots == 0)
|
||||||
|
estimated_slots = 1;
|
||||||
|
|
||||||
|
size_t bitmap_size = ALIGN_UP((estimated_slots + 7) / 8, 8);
|
||||||
|
size_t total_slots_size = estimated_slots * slot_size;
|
||||||
|
size_t total_size = sizeof(MemoryBlock) + bitmap_size + total_slots_size;
|
||||||
|
total_size = ALIGN_UP(total_size, PAGE_SIZE);
|
||||||
|
|
||||||
|
MemoryBlock *block = (MemoryBlock *)request_page(total_size);
|
||||||
if (!block)
|
if (!block)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
block->slots = (void *)((uintptr_t)block + sizeof(MemoryBlock) + bitmap_size);
|
uintptr_t base = (uintptr_t)block + sizeof(MemoryBlock);
|
||||||
|
block->bitmap = (uint8_t *)base;
|
||||||
|
block->bitmap_size = bitmap_size;
|
||||||
|
|
||||||
|
block->slots = (void *)ALIGN_UP(base + bitmap_size, 16);
|
||||||
block->slot_size = slot_size;
|
block->slot_size = slot_size;
|
||||||
block->slots_per_block = slots_per_block;
|
block->slots_per_block = (total_size - ((uintptr_t)block->slots - (uintptr_t)block)) / slot_size;
|
||||||
block->bitmap = (uint8_t *)((uintptr_t)block + sizeof(MemoryBlock));
|
block->total_size = total_size;
|
||||||
memset(block->bitmap, 0, bitmap_size);
|
|
||||||
block->next = NULL;
|
block->next = NULL;
|
||||||
|
|
||||||
|
memset(block->bitmap, 0, bitmap_size);
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *mini_malloc(size_t size)
|
void *mini_malloc(size_t size)
|
||||||
{
|
{
|
||||||
|
if (size == 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
MemoryBlock *block = memory_pool;
|
MemoryBlock *block = memory_pool;
|
||||||
while (block)
|
while (block)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < block->slots_per_block; i++)
|
if (block->slot_size == size)
|
||||||
{
|
{
|
||||||
size_t byte = i / 8, bit = i % 8;
|
for (size_t i = 0; i < block->slots_per_block; i++)
|
||||||
if (!(block->bitmap[byte] & (1 << bit)))
|
|
||||||
{
|
{
|
||||||
block->bitmap[byte] |= (1 << bit);
|
size_t byte = i / 8, bit = i % 8;
|
||||||
return (void *)((uintptr_t)block->slots + i * size);
|
if (!(block->bitmap[byte] & (1 << bit)))
|
||||||
|
{
|
||||||
|
block->bitmap[byte] |= (1 << bit);
|
||||||
|
return (void *)((uintptr_t)block->slots + i * block->slot_size);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
block = block->next;
|
block = block->next;
|
||||||
@ -105,10 +129,12 @@ void mini_free(void *ptr)
|
|||||||
MemoryBlock *block = memory_pool;
|
MemoryBlock *block = memory_pool;
|
||||||
while (block)
|
while (block)
|
||||||
{
|
{
|
||||||
if ((uintptr_t)ptr >= (uintptr_t)block->slots &&
|
uintptr_t start = (uintptr_t)block->slots;
|
||||||
(uintptr_t)ptr < (uintptr_t)block->slots + block->slots_per_block * block->slot_size)
|
uintptr_t end = start + block->slots_per_block * block->slot_size;
|
||||||
|
|
||||||
|
if ((uintptr_t)ptr >= start && (uintptr_t)ptr < end)
|
||||||
{
|
{
|
||||||
size_t index = ((uintptr_t)ptr - (uintptr_t)block->slots) / block->slot_size;
|
size_t index = ((uintptr_t)ptr - start) / block->slot_size;
|
||||||
size_t byte = index / 8, bit = index % 8;
|
size_t byte = index / 8, bit = index % 8;
|
||||||
block->bitmap[byte] &= ~(1 << bit);
|
block->bitmap[byte] &= ~(1 << bit);
|
||||||
return;
|
return;
|
||||||
|
@ -67,6 +67,19 @@ int strcmp(const char *l, const char *r)
|
|||||||
return *l - *r;
|
return *l - *r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
char *strcat(char *dest, const char *src)
|
char *strcat(char *dest, const char *src)
|
||||||
{
|
{
|
||||||
char *d = dest;
|
char *d = dest;
|
||||||
@ -77,6 +90,115 @@ char *strcat(char *dest, const char *src)
|
|||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *strrchr(const char *str, int c)
|
||||||
|
{
|
||||||
|
const char *last_occurrence = NULL;
|
||||||
|
|
||||||
|
while (*str)
|
||||||
|
{
|
||||||
|
if (*str == (char)c)
|
||||||
|
last_occurrence = str;
|
||||||
|
str++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c == '\0')
|
||||||
|
return (char *)str;
|
||||||
|
|
||||||
|
return (char *)last_occurrence;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *strdup(const char *str)
|
||||||
|
{
|
||||||
|
char *buf = (char *)mini_malloc(strlen((char *)str) + 1);
|
||||||
|
strncpy(buf, str, strlen(str) + 1);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int isdelim(char c, const char *delim)
|
||||||
|
{
|
||||||
|
while (*delim != '\0')
|
||||||
|
{
|
||||||
|
if (c == *delim)
|
||||||
|
return 1;
|
||||||
|
delim++;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *strtok(char *src, const char *delim)
|
||||||
|
{
|
||||||
|
static char *src1;
|
||||||
|
if (!src)
|
||||||
|
src = src1;
|
||||||
|
|
||||||
|
if (!src)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
if (isdelim(*src, (char *)delim))
|
||||||
|
{
|
||||||
|
src++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (*src == '\0')
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
char *ret = src;
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
if (*src == '\0')
|
||||||
|
{
|
||||||
|
src1 = src;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
if (isdelim(*src, (char *)delim))
|
||||||
|
{
|
||||||
|
*src = '\0';
|
||||||
|
src1 = src + 1;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
src++;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
char **environ;
|
||||||
|
char *getenv(const char *name)
|
||||||
|
{
|
||||||
|
if (name == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
size_t len = strlen(name);
|
||||||
|
for (char **env = environ; *env != 0; ++env)
|
||||||
|
{
|
||||||
|
char *thisEnv = *env;
|
||||||
|
char cmp = strncmp(thisEnv, name, len) == 0;
|
||||||
|
if (cmp && thisEnv[len] == '=')
|
||||||
|
return thisEnv + len + 1;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned long elf_hash(const unsigned char *name)
|
unsigned long elf_hash(const unsigned char *name)
|
||||||
{
|
{
|
||||||
unsigned long hash = 0, high;
|
unsigned long hash = 0, high;
|
||||||
|
@ -385,7 +385,7 @@ void ProcessNeededLibraries(Elf_Dyn *elem, ElfInfo *Info)
|
|||||||
path = strtok(NULL, ":");
|
path = strtok(NULL, ":");
|
||||||
}
|
}
|
||||||
|
|
||||||
free(pathCopy);
|
mini_free(pathCopy);
|
||||||
if (found)
|
if (found)
|
||||||
goto load_lib;
|
goto load_lib;
|
||||||
}
|
}
|
||||||
|
@ -17,24 +17,55 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#ifndef PROGRAM_VERSION
|
||||||
|
#define PROGRAM_VERSION "<unknown>"
|
||||||
|
#endif
|
||||||
|
|
||||||
int printf(const char *, ...);
|
int printf(const char *, ...);
|
||||||
int _dl_main(int, char *[], char *[]);
|
int _dl_main(int, char *[], char *[]);
|
||||||
|
|
||||||
|
void print_license()
|
||||||
|
{
|
||||||
|
printf("Fennix C Library Interpreter Copyright (C) %s EnderIce2\n", (__DATE__ + 7));
|
||||||
|
printf("This program comes with ABSOLUTELY NO WARRANTY.\n");
|
||||||
|
printf("This is free software, and you are welcome to redistribute it\n");
|
||||||
|
printf("under certain conditions.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_version()
|
||||||
|
{
|
||||||
|
printf("%s\n", PROGRAM_VERSION);
|
||||||
|
}
|
||||||
|
|
||||||
void print_help()
|
void print_help()
|
||||||
{
|
{
|
||||||
printf("Usage: ld.so [options] <program>\n");
|
printf("Usage: ld.so [options] <program>\n");
|
||||||
printf("Options:\n");
|
printf("Options:\n");
|
||||||
printf(" --help Display this help message\n");
|
printf(" --help Display this help message\n");
|
||||||
|
printf(" --version Display version information\n");
|
||||||
|
printf(" --license Display license information\n");
|
||||||
|
printf("\n");
|
||||||
|
print_license();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsManuallyInvoked(const char *argv0)
|
||||||
|
{
|
||||||
|
const char *lastSlash = strrchr(argv0, '/');
|
||||||
|
const char *name = lastSlash ? lastSlash + 1 : argv0;
|
||||||
|
/* TODO: check if exe is actually "ld.so" or it has other name */
|
||||||
|
return strcmp(name, "ld.so") == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern char **environ;
|
||||||
int main(int argc, char *argv[], char *envp[])
|
int main(int argc, char *argv[], char *envp[])
|
||||||
{
|
{
|
||||||
if (argc < 2)
|
environ = envp;
|
||||||
|
if (!IsManuallyInvoked(argv[0]))
|
||||||
{
|
{
|
||||||
printf("Error: No program specified.\n");
|
int status = _dl_main(argc, argv, envp);
|
||||||
print_help();
|
return status;
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 1; i < argc; i++)
|
for (int i = 1; i < argc; i++)
|
||||||
@ -44,8 +75,19 @@ int main(int argc, char *argv[], char *envp[])
|
|||||||
print_help();
|
print_help();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
if (strcmp(argv[i], "--version") == 0)
|
||||||
|
{
|
||||||
|
print_version();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (strcmp(argv[i], "--license") == 0)
|
||||||
|
{
|
||||||
|
print_license();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int status = _dl_main(argc, argv, envp);
|
printf("Error: No program specified.\n");
|
||||||
return status;
|
printf("Try 'ld.so --help' for more information.\n");
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,14 @@ void *memcpy(void *dest, const void *src, size_t n);
|
|||||||
size_t strlen(const char *s);
|
size_t strlen(const char *s);
|
||||||
char *strcpy(char *dest, const char *src);
|
char *strcpy(char *dest, const char *src);
|
||||||
int strcmp(const char *l, const char *r);
|
int strcmp(const char *l, const char *r);
|
||||||
|
int strncmp(const char *s1, const char *s2, size_t n);
|
||||||
char *strcat(char *dest, const char *src);
|
char *strcat(char *dest, const char *src);
|
||||||
|
char *strrchr(const char *str, int c);
|
||||||
|
char *strncpy(char *destination, const char *source, unsigned long num);
|
||||||
|
char *strdup(const char *str);
|
||||||
|
unsigned int isdelim(char c, const char *delim);
|
||||||
|
char *strtok(char *src, const char *delim);
|
||||||
|
char *getenv(const char *name);
|
||||||
|
|
||||||
unsigned long elf_hash(const unsigned char *name);
|
unsigned long elf_hash(const unsigned char *name);
|
||||||
uint32_t gnu_hash(const char *name);
|
uint32_t gnu_hash(const char *name);
|
||||||
|
@ -16,35 +16,35 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef FENNIX_DYNAMIC_LOADER
|
#ifdef FENNIX_DYNAMIC_LOADER
|
||||||
|
#define _s __asm__ __volatile__
|
||||||
__attribute__((naked, used, no_stack_protector)) void _dl_start()
|
__attribute__((naked, used, no_stack_protector)) void _dl_start()
|
||||||
{
|
{
|
||||||
#if defined(__amd64__)
|
#if defined(__amd64__)
|
||||||
__asm__(
|
_s("xorq %rbp, %rbp\n"); /* Clear rbp */
|
||||||
"xorq %rbp, %rbp\n" /* Clear rbp */
|
|
||||||
|
|
||||||
"push %rdi\n"
|
_s("pushq %rdi\n");
|
||||||
"push %rsi\n"
|
_s("pushq %rsi\n");
|
||||||
"push %rdx\n"
|
_s("pushq %rdx\n");
|
||||||
"push %rcx\n"
|
_s("pushq %rcx\n");
|
||||||
"push %r8\n"
|
_s("pushq %r8\n");
|
||||||
"push %r9\n"
|
_s("pushq %r9\n");
|
||||||
|
|
||||||
"call __init_print_buffer\n" /* Call __init_print_buffer */
|
_s("call __init_print_buffer\n"); /* Call __init_print_buffer */
|
||||||
"call _dl_preload\n" /* Call _dl_preload */
|
_s("call _dl_preload\n"); /* Call _dl_preload */
|
||||||
"movl %eax, %edi\n" /* Move return value to edi */
|
_s("movl %eax, %edi\n"); /* Move return value to edi */
|
||||||
"cmp $0, %edi\n" /* Check if return value is 0 */
|
_s("cmp $0, %edi\n"); /* Check if return value is 0 */
|
||||||
"jne _exit\n" /* If not, jump to _exit */
|
_s("jne _exit\n"); /* If not, jump to _exit */
|
||||||
|
|
||||||
"pop %r9\n"
|
_s("popq %r9\n");
|
||||||
"pop %r8\n"
|
_s("popq %r8\n");
|
||||||
"pop %rcx\n"
|
_s("popq %rcx\n");
|
||||||
"pop %rdx\n"
|
_s("popq %rdx\n");
|
||||||
"pop %rsi\n"
|
_s("popq %rsi\n");
|
||||||
"pop %rdi\n"
|
_s("popq %rdi\n");
|
||||||
|
|
||||||
"call main\n" /* Call _dl_main */
|
_s("call main\n"); /* Call _dl_main */
|
||||||
"movl %eax, %edi\n" /* Move return value to edi */
|
_s("movl %eax, %edi\n"); /* Move return value to edi */
|
||||||
"call _exit\n"); /* Call _exit */
|
_s("call _exit\n"); /* Call _exit */
|
||||||
#elif defined(__i386__)
|
#elif defined(__i386__)
|
||||||
#warning "i386 _start not implemented"
|
#warning "i386 _start not implemented"
|
||||||
#elif defined(__arm__)
|
#elif defined(__arm__)
|
||||||
@ -55,4 +55,5 @@ __attribute__((naked, used, no_stack_protector)) void _dl_start()
|
|||||||
#error "Unsupported architecture"
|
#error "Unsupported architecture"
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
#undef _s
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user