From: John Hodge Date: Tue, 18 Jan 2011 23:48:16 +0000 (+0800) Subject: Renamed ld-acess.so_src directory to ld-acess_src X-Git-Tag: rel0.07~27 X-Git-Url: https://git.ucc.asn.au/?p=tpg%2Facess2.git;a=commitdiff_plain;h=a09032f44bba55ce1e60dfab92a39cf6c909220b Renamed ld-acess.so_src directory to ld-acess_src --- diff --git a/AcessNative/ld-acess.so_src/Makefile b/AcessNative/ld-acess.so_src/Makefile deleted file mode 100644 index 4fb6ae28..00000000 --- a/AcessNative/ld-acess.so_src/Makefile +++ /dev/null @@ -1,39 +0,0 @@ -# -# - -ifeq ($(PLATFORM),) - PLATFORM := lin -endif - -OBJ := main.o syscalls.o request.o binary.o memory.o -OBJ += elf.o -OBJ := $(addsuffix .$(PLATFORM),$(OBJ)) - -ifeq ($(PLATFORM),win) - BIN := ../ld-acess.exe -endif -ifeq ($(PLATFORM),lin) - BIN := ../ld-acess - LD += -m elf_i386 -endif - -CFLAGS += -Wall -Werror -g -m32 - -.PHONY: all clean - -all: $(BIN) - -clean: - $(RM) $(BIN) $(OBJ) - -$(BIN): link.ld.$(PLATFORM) $(OBJ) -# $(LD) -g -o $@ $(OBJ) -T link.ld.$(PLATFORM) - $(CC) -g -o $@ $(OBJ) -m32 -Wl,-T,link.ld.$(PLATFORM) - -%.o.$(PLATFORM): %.c - $(CC) -c $< -o $@ $(CFLAGS) $(CPPFLAGS) - -# Modify the default makefile to put the executable at 1MB instead -link.ld.lin: - $(LD) --verbose | awk '{ if( substr($$0,0,5) == "====="){ bPrint = !bPrint; } else { if(bPrint){ print $$0;} } }' | sed 's/\b0x0[08][0-9]*\b/0x00100000/g' > $@ - diff --git a/AcessNative/ld-acess.so_src/binary.c b/AcessNative/ld-acess.so_src/binary.c deleted file mode 100644 index b8f6e71b..00000000 --- a/AcessNative/ld-acess.so_src/binary.c +++ /dev/null @@ -1,240 +0,0 @@ -/* - * AcessNative - */ -#include "common.h" -#include -#include -#include - -#define LIBRARY_PATH "../Usermode/Output/i386/Libs" - -// === TYPES === -typedef struct sBinary { - struct sBinary *Next; - void *Base; - int Ready; - tBinFmt *Format; - char Path[]; -} tBinary; - -// === IMPORTS === -extern void *Elf_Load(FILE *FP); -extern uintptr_t Elf_Relocate(void *Base); -extern int Elf_GetSymbol(void *Base, char *Name, uintptr_t *ret); -extern int ciNumBuiltinSymbols; -extern tSym caBuiltinSymbols[]; - -// === PROTOTYPES === -void Binary_AddToList(const char *Filename, void *Base, tBinFmt *Format); - -// === GLOBALS === -tBinFmt gElf_FormatDef = { -// .Mask = 0xFFFFFFFF, -// .Magic = "\x7F""ELF", - .Name = "ELF32", - .Load = Elf_Load, - .Relocate = Elf_Relocate, - .GetSymbol = Elf_GetSymbol - }; -tBinary *gLoadedBinaries; - -// === CODE === -char *Binary_LocateLibrary(const char *Name) -{ - char *envPath = getenv("ACESS_LIBRARY_PATH"); - int nameLen = strlen(Name); - FILE *fp; - - if( strcmp(Name, "libld-acess.so") == 0 ) { - return strdup("libld-acess.so"); - } - - // Try the environment ACESS_LIBRARY_PATH - if( envPath && envPath[0] != '\0' ) - { - int len = strlen(envPath)+1+nameLen+1; - char tmp[len]; - - strcpy(tmp, envPath); - strcat(tmp, "/"); - strcat(tmp, Name); - - fp = fopen(tmp, "r"); - if(fp) { - fclose(fp); - return strdup(tmp); - } - } - - { - int len = strlen(LIBRARY_PATH)+1+nameLen+1; - char tmp[len]; - - strcpy(tmp, LIBRARY_PATH); - strcat(tmp, "/"); - strcat(tmp, Name); - - printf("Binary_LocateLibrary: tmp = '%s'\n", tmp); - - fp = fopen(tmp, "r"); - if(fp) { - fclose(fp); - return strdup(tmp); - } - } - - fprintf(stderr, "Unable to locate library '%s'\n", Name); - - return NULL; -} - -void *Binary_LoadLibrary(const char *Name) -{ - char *path; - void *ret; - int (*entry)(int,char*[],char**) = NULL; - - // Find File - path = Binary_LocateLibrary(Name); - printf("Binary_LoadLibrary: path = '%s'\n", path); - if( !path ) { - return NULL; - } - - ret = Binary_Load(path, (uintptr_t*)&entry); - free(path); - - printf("Binary_LoadLibrary: ret = %p, entry = %p\n", ret, entry); - if( entry ) { - char *argv[] = {NULL}; - printf("Calling '%s' entry point %p\n", Name, entry); - entry(0, argv, NULL); - } - - return ret; -} - -void *Binary_Load(const char *Filename, uintptr_t *EntryPoint) -{ - FILE *fp; - uint32_t dword; - void *ret; - uintptr_t entry = 0; - tBinFmt *fmt; - - // Ignore loading ld-acess - if( strcmp(Filename, "libld-acess.so") == 0 ) { - *EntryPoint = 0; - return (void*)-1; - } - - { - tBinary *bin; - for(bin = gLoadedBinaries; bin; bin = bin->Next) - { - if( strcmp(Filename, bin->Path) == 0 ) { - return bin->Base; - } - } - } - - fp = fopen(Filename, "r"); - if( !fp ) { - // TODO: Handle libary directories - perror("Opening binary"); - return NULL; - } - - fread(&dword, 1, 4, fp); - fseek(fp, 0, SEEK_SET); - printf("dword = %08x\n", dword); - - if( memcmp(&dword, "\x7F""ELF", 4) == 0 ) { - fmt = &gElf_FormatDef; - } - else { - fclose(fp); - return NULL; - } - - printf("fmt->Load(%p)...\n", fp); - ret = fmt->Load(fp); - printf("fmt->Load(%p): %p\n", fp, ret); - if( !ret ) { - fclose(fp); - return NULL; - } - - Binary_AddToList(Filename, ret, fmt); - - entry = fmt->Relocate(ret); - printf("fmt->Relocate(%p): %p\n", ret, (void*)entry); - if( !entry ) { - // TODO: Clean up - return NULL; - } - - if( EntryPoint ) - *EntryPoint = entry; - - fclose(fp); - - Binary_SetReadyToUse(ret); - - return ret; -} - -void Binary_AddToList(const char *Filename, void *Base, tBinFmt *Format) -{ - tBinary *bin = malloc(sizeof(tBinary) + strlen(Filename) + 1); - bin->Base = Base; - bin->Format = Format; - strcpy(bin->Path, Filename); - bin->Ready = 0; - - bin->Next = gLoadedBinaries; - gLoadedBinaries = bin; -} - -void Binary_SetReadyToUse(void *Base) -{ - tBinary *bin; - for(bin = gLoadedBinaries; bin; bin = bin->Next) - { - if( bin->Base != Base ) continue ; - bin->Ready = 1; - } -} - -int Binary_GetSymbol(const char *SymbolName, uintptr_t *Value) -{ - int i; - tBinary *bin; - - printf("Binary_GetSymbol: (SymbolName='%s', Value=%p)\n", - SymbolName, Value); - - // Search builtins - // - Placed first to override smartarses that define their own versions - // of system calls - for( i = 0; i < ciNumBuiltinSymbols; i ++ ) - { - if( strcmp(caBuiltinSymbols[i].Name, SymbolName) == 0 ) { - *Value = (uintptr_t)caBuiltinSymbols[i].Value; - return 1; - } - } - - // TODO: Search list of loaded binaries - for(bin = gLoadedBinaries; bin; bin = bin->Next) - { - if( !bin->Ready ) continue; - printf(" Binary_GetSymbol: bin = %p{%p, %s}\n", bin, bin->Base, bin->Path); - if( bin->Format->GetSymbol(bin->Base, (char*)SymbolName, Value) ) - return 1; - } - - printf("Binary_GetSymbol: RETURN 0, not found\n"); - - return 0; -} diff --git a/AcessNative/ld-acess.so_src/common.h b/AcessNative/ld-acess.so_src/common.h deleted file mode 100644 index 4667acba..00000000 --- a/AcessNative/ld-acess.so_src/common.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - */ -#ifndef _COMMON_H_ -#define _COMMON_H_ - -#include -#include -#include - -extern int Binary_GetSymbol(const char *SymbolName, uintptr_t *Value); -extern void *Binary_LoadLibrary(const char *Path); -extern void *Binary_Load(const char *Path, uintptr_t *EntryPoint); -extern void Binary_SetReadyToUse(void *Base); - -extern int AllocateMemory(uintptr_t VirtAddr, size_t ByteCount); -extern uintptr_t FindFreeRange(size_t ByteCount, int MaxBits); - -extern void Warning(const char *Format, ...); -extern void Notice(const char *Format, ...); - -typedef struct { - char *Name; - void *Value; -} tSym; - -typedef struct sBinFmt { - struct sBinFmt *Next; - char *Name; - void *(*Load)(FILE *fp); - uintptr_t (*Relocate)(void *base); - int (*GetSymbol)(void*,char*,uintptr_t*); -} tBinFmt; - -#endif - diff --git a/AcessNative/ld-acess.so_src/elf.c b/AcessNative/ld-acess.so_src/elf.c deleted file mode 100644 index 3ab5a504..00000000 --- a/AcessNative/ld-acess.so_src/elf.c +++ /dev/null @@ -1,529 +0,0 @@ -/* - * Acess v0.1 - * ELF Executable Loader Code - */ -#define DEBUG 0 -#include -#include -#include -#include -#include "common.h" -#include "elf.h" - -#define DEBUG_WARN 1 - -#define MKPTR(_type,_val) ((_type*)(uintptr_t)(_val)) -#define PTRMK(_type,_val) MKPTR(_type,_val) -#define PTR(_val) ((void*)(uintptr_t)(_val)) - -#if DEBUG -# define ENTER(...) -# define LOG(s, ...) printf("%s: " s, __func__, __VA_ARGS__) -# define LOGS(s) printf("%s: " s, __func__) -# define LEAVE(...) -#else -# define ENTER(...) -# define LOG(...) -# define LOGS(...) -# define LEAVE(...) -#endif - -// === PROTOTYPES === -void *Elf_Load(FILE *FP); -uintptr_t Elf_Relocate(void *Base); - int Elf_GetSymbol(void *Base, char *Name, uintptr_t *ret); - int Elf_Int_DoRelocate(uint32_t r_info, uint32_t *ptr, uint32_t addend, Elf32_Sym *symtab, void *Base); -uint32_t Elf_Int_HashString(char *str); - -// === CODE === -void *Elf_Load(FILE *FP) -{ - Elf32_Ehdr hdr; - Elf32_Phdr *phtab; - int i, j; - int iPageCount; - uint32_t max, base = -1; - uint32_t addr; - uint32_t baseDiff = 0; - - ENTER("pFP", FP); - - // Read ELF Header - fread(&hdr, sizeof(hdr), 1, FP); - - // Check the file type - if(hdr.ident[0] != 0x7F || hdr.ident[1] != 'E' || hdr.ident[2] != 'L' || hdr.ident[3] != 'F') { - Warning("Non-ELF File was passed to the ELF loader\n"); - LEAVE('n'); - return NULL; - } - - // Check for a program header - if(hdr.phoff == 0) { - #if DEBUG_WARN - Warning("ELF File does not contain a program header\n"); - #endif - LEAVE('n'); - return NULL; - } - - // Read Program Header Table - phtab = malloc( sizeof(Elf32_Phdr) * hdr.phentcount ); - if( !phtab ) { - LEAVE('n'); - return NULL; - } - LOG("hdr.phoff = 0x%08x\n", hdr.phoff); - fseek(FP, hdr.phoff, SEEK_SET); - fread(phtab, sizeof(Elf32_Phdr), hdr.phentcount, FP); - - // Count Pages - iPageCount = 0; - LOG("hdr.phentcount = %i\n", hdr.phentcount); - for( i = 0; i < hdr.phentcount; i++ ) - { - // Ignore Non-LOAD types - if(phtab[i].Type != PT_LOAD) - continue; - iPageCount += ((phtab[i].VAddr&0xFFF) + phtab[i].MemSize + 0xFFF) >> 12; - LOG("phtab[%i] = {VAddr:0x%x, MemSize:0x%x}\n", i, phtab[i].VAddr, phtab[i].MemSize); - } - - LOG("iPageCount = %i\n", iPageCount); - - // Allocate Information Structure - //ret = malloc( sizeof(tBinary) + sizeof(tBinaryPage)*iPageCount ); - // Fill Info Struct - //ret->Entry = hdr.entrypoint; - //ret->Base = -1; // Set Base to maximum value - //ret->NumPages = iPageCount; - //ret->Interpreter = NULL; - - // Prescan for base and size - for( i = 0; i < hdr.phentcount; i ++) - { - if( phtab[i].Type != PT_LOAD ) - continue; - if( phtab[i].VAddr < base ) - base = phtab[i].VAddr; - if( phtab[i].VAddr > max ) - max = phtab[i].VAddr; - } - - LOG("base = %08x, max = %08x\n", base, max); - - if( base == 0 ) { - // Find a nice space (31 address bits allowed) - base = FindFreeRange( max, 31 ); - LOG("new base = %08x\n", base); - if( base == 0 ) return NULL; - baseDiff = base; - } - - // Load Pages - j = 0; - for( i = 0; i < hdr.phentcount; i++ ) - { - //LOG("phtab[%i].Type = 0x%x", i, phtab[i].Type); - LOG("phtab[%i] = {\n", i); - LOG(" .Type = 0x%08x\n", phtab[i].Type); - LOG(" .Offset = 0x%08x\n", phtab[i].Offset); - LOG(" .VAddr = 0x%08x\n", phtab[i].VAddr); - LOG(" .PAddr = 0x%08x\n", phtab[i].PAddr); - LOG(" .FileSize = 0x%08x\n", phtab[i].FileSize); - LOG(" .MemSize = 0x%08x\n", phtab[i].MemSize); - LOG(" .Flags = 0x%08x\n", phtab[i].Flags); - LOG(" .Align = 0x%08x\n", phtab[i].Align); - LOGS(" }\n"); - // Get Interpreter Name - if( phtab[i].Type == PT_INTERP ) - { - char *tmp; - //if(ret->Interpreter) continue; - tmp = malloc(phtab[i].FileSize); - fseek(FP, phtab[i].Offset, SEEK_SET); - fread(tmp, phtab[i].FileSize, 1, FP); - //ret->Interpreter = Binary_RegInterp(tmp); - LOG("Interpreter '%s'\n", tmp); - free(tmp); - continue; - } - // Ignore non-LOAD types - if(phtab[i].Type != PT_LOAD) continue; - - LOG("phtab[%i] = {VAddr:0x%x,Offset:0x%x,FileSize:0x%x}\n", - i, phtab[i].VAddr+baseDiff, phtab[i].Offset, phtab[i].FileSize); - - addr = phtab[i].VAddr + baseDiff; - - if( AllocateMemory( addr, phtab[i].MemSize ) ) { - return NULL; - } - - fseek(FP, phtab[i].Offset, SEEK_SET); - fread( PTRMK(void, addr), phtab[i].FileSize, 1, FP ); - memset( PTRMK(char, addr) + phtab[i].FileSize, 0, phtab[i].MemSize - phtab[i].FileSize ); - } - - // Clean Up - free(phtab); - // Return - LEAVE('p', base); - return PTRMK(void, base); -} - -// --- ELF RELOCATION --- -/** - * \brief Relocates a loaded ELF Executable - */ -uintptr_t Elf_Relocate(void *Base) -{ - Elf32_Ehdr *hdr = Base; - Elf32_Phdr *phtab; - int i, j; // Counters - char *libPath; - uint32_t iRealBase = -1; - uintptr_t iBaseDiff; - int iSegmentCount; - int iSymCount = 0; - Elf32_Rel *rel = NULL; - Elf32_Rela *rela = NULL; - uint32_t *pltgot = NULL; - void *plt = NULL; - uint32_t *ptr; - int relSz=0, relEntSz=8; - int relaSz=0, relaEntSz=8; - int pltSz=0, pltType=0; - Elf32_Dyn *dynamicTab = NULL; // Dynamic Table Pointer - char *dynstrtab = NULL; // .dynamic String Table - Elf32_Sym *dynsymtab = NULL; - int bFailed = 0; - - ENTER("pBase", Base); - LOG("Base = %p\n", Base); - - // Parse Program Header to get Dynamic Table - phtab = Base + hdr->phoff; - iSegmentCount = hdr->phentcount; - for(i = 0; i < iSegmentCount; i ++ ) - { - // Determine linked base address - if(phtab[i].Type == PT_LOAD && iRealBase > phtab[i].VAddr) - iRealBase = phtab[i].VAddr; - - // Find Dynamic Section - if(phtab[i].Type == PT_DYNAMIC) { - if(dynamicTab) { - Warning("Elf_Relocate - Multiple PT_DYNAMIC segments\n"); - continue; - } - dynamicTab = MKPTR(void, phtab[i].VAddr); - j = i; // Save Dynamic Table ID - break; - } - } - - // Check if a PT_DYNAMIC segement was found - if(!dynamicTab) { - Warning("Elf_Relocate: No PT_DYNAMIC segment in image, returning\n"); - LEAVE('x', hdr->entrypoint); - return hdr->entrypoint; - } - - // Page Align real base - iRealBase &= ~0xFFF; - - LOG("dynamicTab = %p\n", dynamicTab); - // Adjust "Real" Base - iBaseDiff = (uintptr_t)Base - iRealBase; - LOG("iBaseDiff = %p\n", (void*)iBaseDiff); - // Adjust Dynamic Table - dynamicTab = PTR( (uintptr_t)dynamicTab + iBaseDiff); - LOG("dynamicTab = %p\n", dynamicTab); - - hdr->entrypoint += iBaseDiff; - - // === Get Symbol table and String Table === - for( j = 0; dynamicTab[j].d_tag != DT_NULL; j++) - { - switch(dynamicTab[j].d_tag) - { - // --- Symbol Table --- - case DT_SYMTAB: - dynamicTab[j].d_val += iBaseDiff; - dynsymtab = PTRMK(void, dynamicTab[j].d_val); - hdr->misc.SymTable = dynamicTab[j].d_val; // Saved in unused bytes of ident - break; - - // --- String Table --- - case DT_STRTAB: - dynamicTab[j].d_val += iBaseDiff; - dynstrtab = PTRMK(void, dynamicTab[j].d_val); - break; - - // --- Hash Table -- - case DT_HASH: - dynamicTab[j].d_val += iBaseDiff; - iSymCount = (PTRMK(uint32_t, dynamicTab[j].d_val))[1]; - hdr->misc.HashTable = dynamicTab[j].d_val; // Saved in unused bytes of ident - break; - } - } - - - // Alter Symbols to true base - for(i = 0; i < iSymCount; i ++) - { - dynsymtab[i].nameOfs += (uintptr_t)dynstrtab; - if( dynsymtab[i].shndx == SHN_UNDEF ) - { - LOG("Sym '%s' = UNDEF\n", MKPTR(char,dynsymtab[i].name)); - } - else - { - dynsymtab[i].value += iBaseDiff; - LOG("Sym '%s' = 0x%x (relocated)\n", MKPTR(char,dynsymtab[i].name), dynsymtab[i].value); - } - } - - // === Add to loaded list (can be imported now) === - Binary_SetReadyToUse( Base ); - - // === Parse Relocation Data === - for( j = 0; dynamicTab[j].d_tag != DT_NULL; j++) - { - switch(dynamicTab[j].d_tag) - { - // --- Shared Library Name --- - case DT_SONAME: - LOG(".so Name '%s'\n", dynstrtab + dynamicTab[j].d_val); - break; - // --- Needed Library --- - case DT_NEEDED: - libPath = dynstrtab + dynamicTab[j].d_val; - Binary_LoadLibrary(libPath); - break; - // --- PLT/GOT --- - case DT_PLTGOT: pltgot = (void*)(iBaseDiff+dynamicTab[j].d_val); break; - case DT_JMPREL: plt = (void*)(iBaseDiff+dynamicTab[j].d_val); break; - case DT_PLTREL: pltType = dynamicTab[j].d_val; break; - case DT_PLTRELSZ: pltSz = dynamicTab[j].d_val; break; - - // --- Relocation --- - case DT_REL: rel = (void*)(iBaseDiff + dynamicTab[j].d_val); break; - case DT_RELSZ: relSz = dynamicTab[j].d_val; break; - case DT_RELENT: relEntSz = dynamicTab[j].d_val; break; - - case DT_RELA: rela = (void*)(iBaseDiff + dynamicTab[j].d_val); break; - case DT_RELASZ: relaSz = dynamicTab[j].d_val; break; - case DT_RELAENT: relaEntSz = dynamicTab[j].d_val; break; - } - } - - // Parse Relocation Entries - if(rel && relSz) - { - j = relSz / relEntSz; - for( i = 0; i < j; i++ ) - { - ptr = (void*)(iBaseDiff + rel[i].r_offset); - if( !Elf_Int_DoRelocate(rel[i].r_info, ptr, *ptr, dynsymtab, Base) ) { - bFailed = 1; - } - } - } - // Parse Relocation Entries - if(rela && relaSz) - { - j = relaSz / relaEntSz; - for( i = 0; i < j; i++ ) - { - ptr = (void*)(iBaseDiff + rela[i].r_offset); - if( !Elf_Int_DoRelocate(rel[i].r_info, ptr, rela[i].r_addend, dynsymtab, Base) ) { - bFailed = 1; - } - } - } - - // === Process PLT (Procedure Linkage Table) === - if(plt && pltSz) - { - if(pltType == DT_REL) - { - Elf32_Rel *pltRel = plt; - j = pltSz / sizeof(Elf32_Rel); - LOG("PLT Rel - plt = %p, pltSz = %i (%i ents)\n", plt, pltSz, j); - for(i = 0; i < j; i++) - { - ptr = (void*)(iBaseDiff + pltRel[i].r_offset); - if( !Elf_Int_DoRelocate(pltRel[i].r_info, ptr, *ptr, dynsymtab, Base) ) { - bFailed = 1; - } - } - } - else - { - Elf32_Rela *pltRela = plt; - j = pltSz / sizeof(Elf32_Rela); - LOG("PLT RelA - plt = %p, pltSz = %i (%i ents)\n", plt, pltSz, j); - for(i=0;ientrypoint); - return hdr->entrypoint; -} - -/** - * \fn void Elf_Int_DoRelocate(uint32_t r_info, uint32_t *ptr, uint32_t addend, Elf32_Sym *symtab, void *base) - * \brief Performs a relocation - * \param r_info Field from relocation entry - * \param ptr Pointer to location of relocation - * \param addend Value to add to symbol - * \param symtab Symbol Table - * \param base Base of loaded binary - */ -int Elf_Int_DoRelocate(uint32_t r_info, uint32_t *ptr, uint32_t addend, Elf32_Sym *symtab, void *base) -{ - uintptr_t val; - int type = ELF32_R_TYPE(r_info); - int sym = ELF32_R_SYM(r_info); - char *sSymName = PTRMK(char, symtab[sym].name); - - //LogF("Elf_Int_DoRelocate: (r_info=0x%x, ptr=0x%x, addend=0x%x, .., base=0x%x)\n", - // r_info, ptr, addend, base); - - switch( type ) - { - // Standard 32 Bit Relocation (S+A) - case R_386_32: - if( !Elf_GetSymbol( base, sSymName, &val ) && !Binary_GetSymbol( sSymName, &val ) ) { - Warning("Unable to find symbol '%s'", sSymName); - return 0; - } - LOG("%08x R_386_32 *%p += %p('%s')\n", r_info, ptr, (void*)val, sSymName); - *ptr = val + addend; - break; - - // 32 Bit Relocation wrt. Offset (S+A-P) - case R_386_PC32: - if( !Elf_GetSymbol( base, sSymName, &val ) && !Binary_GetSymbol( sSymName, &val ) ) { - Warning("Unable to find symbol '%s'", sSymName); - return 0; - } - LOG("%08x R_386_PC32 *%p = 0x%x + %p('%s') - %p\n", r_info, ptr, *ptr, (void*)val, sSymName, ptr ); - // TODO: Check if it needs the true value of ptr or the compiled value - // NOTE: Testing using true value - *ptr = val + addend - (uintptr_t)ptr; - break; - - // Absolute Value of a symbol (S) - case R_386_GLOB_DAT: - if( !Elf_GetSymbol( base, sSymName, &val ) && !Binary_GetSymbol( sSymName, &val ) ) { - Warning("Unable to find symbol '%s'", sSymName); - return 0; - } - LOG("%08x R_386_GLOB_DAT *%p = 0x%x(%s)\n", r_info, ptr, (unsigned int)val, sSymName); - *ptr = val; - break; - - // Absolute Value of a symbol (S) - case R_386_JMP_SLOT: - if( !Elf_GetSymbol( base, sSymName, &val ) && !Binary_GetSymbol( sSymName, &val ) ) { - Warning("Unable to find symbol '%s'", sSymName); - return 0; - } - LOG("%08x R_386_JMP_SLOT *%p = 0x%x (%s)\n", r_info, ptr, (unsigned int)val, sSymName); - *ptr = val; - break; - - // Base Address (B+A) - case R_386_RELATIVE: - LOG("%08x R_386_RELATIVE *%p = %p + 0x%x\n", r_info, ptr, base, addend); - *ptr = (uintptr_t)base + addend; - break; - - default: - LOG("Rel %p: 0x%x,%i\n", ptr, sym, type); - break; - } - return 1; -} - -/** - * \fn int Elf_GetSymbol(void *Base, char *name, uintptr_t *ret) - * \brief Get a symbol from the loaded binary - */ -int Elf_GetSymbol(void *Base, char *Name, uintptr_t *ret) -{ - Elf32_Ehdr *hdr = (void*)Base; - Elf32_Sym *symtab; - int nbuckets = 0; - int iSymCount = 0; - int i; - uint32_t *pBuckets; - uint32_t *pChains; - uint32_t iNameHash; - - if(!Base) return 0; - - pBuckets = PTR(hdr->misc.HashTable); - symtab = PTR(hdr->misc.SymTable); - - nbuckets = pBuckets[0]; - iSymCount = pBuckets[1]; - pBuckets = &pBuckets[2]; - pChains = &pBuckets[ nbuckets ]; - - // Get hash - iNameHash = Elf_Int_HashString(Name); - iNameHash %= nbuckets; - - // Check Bucket - i = pBuckets[ iNameHash ]; - if(symtab[i].shndx != SHN_UNDEF && strcmp(MKPTR(char,symtab[i].name), Name) == 0) { - if(ret) *ret = symtab[ i ].value; - return 1; - } - - // Walk Chain - while(pChains[i] != STN_UNDEF) - { - i = pChains[i]; - if(symtab[i].shndx != SHN_UNDEF && strcmp(MKPTR(char,symtab[i].name), Name) == 0) { - if(ret) *ret = symtab[ i ].value; - return 1; - } - } - return 0; -} - -/** - * \fn uint32_t Elf_Int_HashString(char *str) - * \brief Hash a string in the ELF format - * \param str String to hash - * \return Hash value - */ -uint32_t Elf_Int_HashString(char *str) -{ - uint32_t h = 0, g; - while(*str) - { - h = (h << 4) + *str++; - if( (g = h & 0xf0000000) ) - h ^= g >> 24; - h &= ~g; - } - return h; -} diff --git a/AcessNative/ld-acess.so_src/elf.h b/AcessNative/ld-acess.so_src/elf.h deleted file mode 100644 index 77be918b..00000000 --- a/AcessNative/ld-acess.so_src/elf.h +++ /dev/null @@ -1,217 +0,0 @@ -/** - * \file elf.h - * \brief ELF Exeutable Loader - */ -#ifndef _BIN_ELF_H -#define _BIN_ELF_H - -#include - -/** - * \brief ELF File Header - */ -struct sElf32_Ehdr -{ - union { - char ident[16]; //!< Identifier Bytes - struct { - uint32_t Ident1; - uint32_t Ident2; - uint32_t HashTable; - uint32_t SymTable; - } misc; - }; - uint16_t filetype; //!< File Type - uint16_t machine; //!< Machine / Arch - uint32_t version; //!< Version (File?) - uint32_t entrypoint; //!< Entry Point - uint32_t phoff; //!< Program Header Offset - uint32_t shoff; //!< Section Header Offset - uint32_t flags; //!< Flags - uint16_t headersize; //!< Header Size - uint16_t phentsize; //!< Program Header Entry Size - uint16_t phentcount; //!< Program Header Entry Count - uint16_t shentsize; //!< Section Header Entry Size - uint16_t shentcount; //!< Section Header Entry Count - uint16_t shstrindex; //!< Section Header String Table Index -} __attribute__ ((packed)); - -/** - * \brief Executable Types - */ -enum eElf32_ExecTypes -{ - ET_NONE = 0, //!< NULL Type - ET_REL = 1, //!< Relocatable (Object) - ET_EXEC = 2, //!< Executable - ET_DYN = 3, //!< Dynamic Library - ET_CORE = 4, //!< Core? - ET_LOPROC = 0xFF00, //!< Low Impl Defined - ET_HIPROC = 0xFFFF //!< High Impl Defined -}; - -/** - \name Section IDs - \{ -*/ -#define SHN_UNDEF 0 //!< Undefined Section -#define SHN_LORESERVE 0xFF00 //!< Low Reserved -#define SHN_LOPROC 0xFF00 //!< Low Impl Defined -#define SHN_HIPROC 0xFF1F //!< High Impl Defined -#define SHN_ABS 0xFFF1 //!< Absolute Address (Base: 0, Size: -1) -#define SHN_COMMON 0xFFF2 //!< Common -#define SHN_HIRESERVE 0xFFFF //!< High Reserved -//! \} - -/** - \enum eElfSectionTypes - \brief ELF Section Types -*/ -enum eElfSectionTypes { - 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, //A - SHT_DYNSYM, //B - SHT_LAST, //C - SHT_LOPROC = 0x70000000, - SHT_HIPROC = 0x7fffffff, - SHT_LOUSER = 0x80000000, - SHT_HIUSER = 0xffffffff -}; - -#define SHF_WRITE 0x1 -#define SHF_ALLOC 0x2 -#define SHF_EXECINSTR 0x4 -#define SHF_MASKPROC 0xf0000000 - -struct sElf32_Shent { - uint32_t name; - uint32_t type; - uint32_t flags; - uint32_t address; - uint32_t offset; - uint32_t size; - uint32_t link; - uint32_t info; - uint32_t addralign; - uint32_t entsize; -} __attribute__ ((packed)); //sizeof = 40 - -struct elf_sym_s { - union { - uint32_t nameOfs; - uint32_t name; - }; - uint32_t value; //Address - uint32_t size; - uint8_t info; - uint8_t other; - uint16_t shndx; -} __attribute__ ((packed)); -#define STN_UNDEF 0 // Undefined Symbol - -enum { - PT_NULL, //0 - PT_LOAD, //1 - PT_DYNAMIC, //2 - PT_INTERP, //3 - PT_NOTE, //4 - PT_SHLIB, //5 - PT_PHDR, //6 - PT_LOPROC = 0x70000000, - PT_HIPROC = 0x7fffffff -}; - -struct sElf32_Phdr { - uint32_t Type; - uint32_t Offset; - uint32_t VAddr; - uint32_t PAddr; - uint32_t FileSize; - uint32_t MemSize; - uint32_t Flags; - uint32_t Align; -} __attribute__ ((packed)); - -struct elf32_rel_s { - uint32_t r_offset; - uint32_t r_info; -} __attribute__ ((packed)); - -struct elf32_rela_s { - uint32_t r_offset; - uint32_t r_info; - int32_t r_addend; -} __attribute__ ((packed)); - -enum { - R_386_NONE = 0, // none - R_386_32, // S+A - R_386_PC32, // S+A-P - R_386_GOT32, // G+A-P - R_386_PLT32, // L+A-P - R_386_COPY, // none - R_386_GLOB_DAT, // S - R_386_JMP_SLOT, // S - R_386_RELATIVE, // B+A - R_386_GOTOFF, // S+A-GOT - R_386_GOTPC, // GOT+A-P - R_386_LAST // none -}; - -#define ELF32_R_SYM(i) ((i)>>8) // Takes an info value and returns a symbol index -#define ELF32_R_TYPE(i) ((i)&0xFF) // Takes an info value and returns a type -#define ELF32_R_INFO(s,t) (((s)<<8)+((t)&0xFF)) // Takes a type and symbol index and returns an info value - -struct elf32_dyn_s { - uint32_t d_tag; - uint32_t d_val; //Also d_ptr -} __attribute__ ((packed)); - -enum { - DT_NULL, //!< Marks End of list - DT_NEEDED, //!< Offset in strtab to needed library - DT_PLTRELSZ, //!< Size in bytes of PLT - DT_PLTGOT, //!< Address of PLT/GOT - DT_HASH, //!< Address of symbol hash table - DT_STRTAB, //!< String Table address - DT_SYMTAB, //!< Symbol Table address - DT_RELA, //!< Relocation table address - DT_RELASZ, //!< Size of relocation table - DT_RELAENT, //!< Size of entry in relocation table - DT_STRSZ, //!< Size of string table - DT_SYMENT, //!< Size of symbol table entry - DT_INIT, //!< Address of initialisation function - DT_FINI, //!< Address of termination function - DT_SONAME, //!< String table offset of so name - DT_RPATH, //!< String table offset of library path - DT_SYMBOLIC,//!< Reverse order of symbol searching for library, search libs first then executable - DT_REL, //!< Relocation Entries (Elf32_Rel instead of Elf32_Rela) - DT_RELSZ, //!< Size of above table (bytes) - DT_RELENT, //!< Size of entry in above table - DT_PLTREL, //!< Relocation entry of PLT - DT_DEBUG, //!< Debugging Entry - Unknown contents - DT_TEXTREL, //!< Indicates that modifcations to a non-writeable segment may occur - DT_JMPREL, //!< Address of PLT only relocation entries - DT_LOPROC = 0x70000000, //!< Low Definable - DT_HIPROC = 0x7FFFFFFF //!< High Definable -}; - -typedef struct sElf32_Ehdr Elf32_Ehdr; -typedef struct sElf32_Phdr Elf32_Phdr; -typedef struct sElf32_Shent Elf32_Shent; -typedef struct elf_sym_s elf_symtab; -typedef struct elf_sym_s Elf32_Sym; -typedef struct elf32_rel_s Elf32_Rel; -typedef struct elf32_rela_s Elf32_Rela; -typedef struct elf32_dyn_s Elf32_Dyn; - -#endif // defined(_EXE_ELF_H) diff --git a/AcessNative/ld-acess.so_src/main.c b/AcessNative/ld-acess.so_src/main.c deleted file mode 100644 index e310a84a..00000000 --- a/AcessNative/ld-acess.so_src/main.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - */ -#include "common.h" -#include -#include -#include - -// === CODE === -int main(int argc, char *argv[], char **envp) -{ - int i; - int appArgc; - char **appArgv; - char *appPath; - int (*appMain)(int, char *[], char **); - void *base; - - for( i = 1; i < argc; i ++ ) - { - if( argv[i][0] != '-' ) break; - } - - if( i >= argc ) { - fprintf(stderr, "Usage: ld-acess [arguments ...]\n"); - return 1; - } - - appPath = argv[i]; - - appArgc = argc - i; - appArgv = &argv[i]; - - printf("Exectutable Path: '%s'\n", appPath); - printf("Executable argc = %i\n", appArgc); - - base = Binary_Load(appPath, (uintptr_t*)&appMain); - printf("base = %p\n", base); - if( !base ) return 127; - - __asm__ __volatile__ ( - "push %0;\n\t" - "push %1;\n\t" - "push %2;\n\t" - "jmp *%3;\n\t" - : : "r" (envp), "r" (appArgv), "r" (appArgc), "r" (appMain) ); - //return appMain(appArgc, appArgv, envp); - return -1; -} - -void Warning(const char *Format, ...) -{ - va_list args; - printf("Warning: "); - va_start(args, Format); - vprintf(Format, args); - va_end(args); - printf("\n"); -} - -void Notice(const char *Format, ...) -{ - va_list args; - printf("Notice: "); - va_start(args, Format); - vprintf(Format, args); - va_end(args); - printf("\n"); -} - diff --git a/AcessNative/ld-acess.so_src/memory.c b/AcessNative/ld-acess.so_src/memory.c deleted file mode 100644 index 627f9024..00000000 --- a/AcessNative/ld-acess.so_src/memory.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - */ -#include "common.h" -#include -#include -#if __WIN32__ -# include -#else -# include -# include -#endif - -// === PROTOTYPES === - int AllocateMemory(uintptr_t VirtAddr, size_t ByteCount); -uintptr_t FindFreeRange(size_t ByteCount, int MaxBits); - -// === CODE === -int AllocateMemory(uintptr_t VirtAddr, size_t ByteCount) -{ - uintptr_t base = (VirtAddr >> 12) << 12; - size_t size = (VirtAddr & 0xFFF) + ByteCount; - void *tmp; - #if __WIN32__ - tmp = VirtualAlloc(base, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE); - if( tmp == NULL ) { - printf("ERROR: Unable to allocate memory (%i)\n", GetLastError()); - return -1; - } - #else - tmp = mmap((void*)base, size, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0); - if( tmp == MAP_FAILED ) { - return -1; - } - #endif - return 0; -} - -uintptr_t FindFreeRange(size_t ByteCount, int MaxBits) -{ - #if __WIN32__ - # error "Windows FindFreeRange() unimplemented" - #else - uintptr_t base, ofs, size; - uintptr_t end = -1; - const int PAGE_SIZE = 0x1000; - - size = (ByteCount + PAGE_SIZE - 1) / PAGE_SIZE; - size *= PAGE_SIZE; - - end <<= (sizeof(intptr_t)*8-MaxBits); - end >>= (sizeof(intptr_t)*8-MaxBits); - printf("end = %p\n", (void*)end); - -// for( base = 0; base < end - size; base -= PAGE_SIZE ) - for( base = end - size + 1; base > 0; base -= PAGE_SIZE ) - { - for( ofs = 0; ofs < size; ofs += PAGE_SIZE ) { - if( msync( (void*)(base+ofs), 1, 0) == 0 ) - break; - if( errno != ENOMEM ) - perror("FindFreeRange, msync"); - } - if( ofs >= size ) { - return base; - } - } - return 0; - #endif -} diff --git a/AcessNative/ld-acess.so_src/request.c b/AcessNative/ld-acess.so_src/request.c deleted file mode 100644 index f9526b3a..00000000 --- a/AcessNative/ld-acess.so_src/request.c +++ /dev/null @@ -1,151 +0,0 @@ -/* - */ -#include -#include -#include -#ifdef __WIN32__ -# include -# include -#else -# include -# include -# include -#endif -#include "request.h" -#include "../syscalls.h" - -#define SERVER_PORT 0xACE - -// === GLOBALS === -#ifdef __WIN32__ -WSADATA gWinsock; -SOCKET gSocket = INVALID_SOCKET; -#else -# define INVALID_SOCKET -1 - int gSocket = INVALID_SOCKET; -#endif -// Client ID to pass to server -// TODO: Implement such that each thread gets a different one -static int siSyscall_ClientID = 0; - -// === CODE === -int _InitSyscalls() -{ - struct sockaddr_in server; - struct sockaddr_in client; - - #ifdef __WIN32__ - /* Open windows connection */ - if (WSAStartup(0x0101, &gWinsock) != 0) - { - fprintf(stderr, "Could not open Windows connection.\n"); - exit(0); - } - #endif - - // Open UDP Connection - gSocket = socket(AF_INET, SOCK_DGRAM, 0); - if (gSocket == INVALID_SOCKET) - { - fprintf(stderr, "Could not create socket.\n"); - #if __WIN32__ - WSACleanup(); - #endif - exit(0); - } - - // Set server address - memset((void *)&server, '\0', sizeof(struct sockaddr_in)); - server.sin_family = AF_INET; - server.sin_port = htons(SERVER_PORT); - server.sin_addr.s_addr = htonl(0x7F00001); - - // Set client address - memset((void *)&client, '\0', sizeof(struct sockaddr_in)); - client.sin_family = AF_INET; - client.sin_port = htons(0); - client.sin_addr.s_addr = htonl(0x7F00001); - - // Bind - if( bind(gSocket, (struct sockaddr *)&client, sizeof(struct sockaddr_in)) == -1 ) - { - fprintf(stderr, "Cannot bind address to socket.\n"); - #if __WIN32__ - closesocket(gSocket); - WSACleanup(); - #else - close(gSocket); - #endif - exit(0); - } - return 0; -} - -int SendRequest(int RequestID, int NumOutput, tOutValue **Output, int NumInput, tInValue **Input) -{ - tRequestHeader *request; - tRequestValue *value; - char *data; - int requestLen; - int i; - - // See ../syscalls.h for details of request format - requestLen = sizeof(tRequestHeader) + (NumOutput + NumInput) * sizeof(tRequestValue); - - // Get total param length - for( i = 0; i < NumOutput; i ++ ) - requestLen += Output[i]->Length; - - // Allocate request - request = malloc( requestLen ); - value = request->Params; - data = (char*)&request->Params[ NumOutput + NumInput ]; - - // Set header - request->ClientID = siSyscall_ClientID; - request->CallID = RequestID; // Syscall - request->NParams = NumOutput; - request->NReturn = NumInput; - - // Set parameters - for( i = 0; i < NumOutput; i ++ ) - { - switch(Output[i]->Type) - { - case 'i': value->Type = ARG_TYPE_INT32; break; - case 'I': value->Type = ARG_TYPE_INT64; break; - case 'd': value->Type = ARG_TYPE_DATA; break; - default: - return -1; - } - value->Length = Output[i]->Length; - - memcpy(data, Output[i]->Data, Output[i]->Length); - - data += Output[i]->Length; - } - - // Set return values - for( i = 0; i < NumInput; i ++ ) - { - switch(Input[i]->Type) - { - case 'i': value->Type = ARG_TYPE_INT32; break; - case 'I': value->Type = ARG_TYPE_INT64; break; - case 'd': value->Type = ARG_TYPE_DATA; break; - default: - return -1; - } - value->Length = Input[i]->Length; - } - - // Send it off - send(gSocket, request, requestLen, 0); - - // Wait for a response - recv(gSocket, request, requestLen, 0); - - // Parse response out - - return 0; -} diff --git a/AcessNative/ld-acess.so_src/request.h b/AcessNative/ld-acess.so_src/request.h deleted file mode 100644 index 8c89e6f6..00000000 --- a/AcessNative/ld-acess.so_src/request.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Acess2 - AcessNative - * ld-acess - * - * request.h - IPC Request common header - */ - -#ifndef _REQUEST_H_ -#define _REQUEST_H_ - -typedef struct { - char Type; - int Length; - char Data[]; -} tOutValue; - -typedef struct { - char Type; - int Length; - void *Data; -} tInValue; - -extern int SendRequest(int RequestID, int NumOutput, tOutValue **Output, - int NumInput, tInValue **Input); - -#endif diff --git a/AcessNative/ld-acess.so_src/syscalls.c b/AcessNative/ld-acess.so_src/syscalls.c deleted file mode 100644 index ec4af017..00000000 --- a/AcessNative/ld-acess.so_src/syscalls.c +++ /dev/null @@ -1,302 +0,0 @@ -/* - */ -#include "../../Usermode/include/acess/sys.h" -#include "common.h" -#include -#include -#include -#include -#include -#include "request.h" - -// === Types === - -// === IMPORTS === - -// === CODE === -const char *ReadEntry(tOutValue **OutDest, tInValue **InDest, - int *Direction, const char *ArgTypes, va_list Args) -{ - uint64_t val64, *ptr64; - uint32_t val32, *ptr32; - int direction = 0; // 0: Invalid, 1: Out, 2: In, 3: Out - char *str; - int len; - - // Eat whitespace - while(*ArgTypes && *ArgTypes == ' ') ArgTypes ++; - if( *ArgTypes == '\0' ) return ArgTypes; - - // Get direction - switch(*ArgTypes) - { - case '>': direction = 1; break; - case '<': direction = 2; break; - case '?': direction = 3; break; - default: - return NULL; - } - ArgTypes ++; - - // Eat whitespace - while(*ArgTypes && *ArgTypes == ' ') ArgTypes ++; - if( *ArgTypes == '\0' ) return ArgTypes; - - // Internal helper macro - #define MAKE_OUT(_dest,_typeChar,_typeName,_value) do{if((_dest)){\ - *(_dest) = (tOutValue*)malloc(sizeof(tOutValue)+sizeof(_typeName));\ - (*(_dest))->Type=(_typeChar);(*(_dest))->Length=sizeof(_typeName);\ - *(_typeName*)((*(_dest))->Data) = (_value);\ - }}while(0) - #define MAKE_IN(_dest,_typeChar,_typeName,_value) do{if((_dest)){\ - *(_dest) = (tInValue*)malloc(sizeof(tInValue));\ - (*(_dest))->Type=(_typeChar);(*(_dest))->Length=sizeof(_typeName);\ - (*(_dest))->Data = (_value);\ - }}while(0) - - // Get type - switch(*ArgTypes) - { - case 'i': // 32-bit integer - // Input? - if( direction & 2 ) - { - ptr32 = va_arg(Args, uint32_t*); - MAKE_IN(InDest, 'i', uint32_t*, ptr32); - if( direction & 1 ) - MAKE_OUT(OutDest, 'i', uint32_t, *ptr32); - } - else - { - val32 = va_arg(Args, uint32_t); - MAKE_OUT(OutDest, 'i', uint32_t, val32); - } - break; - case 'I': // 64-bit integer - // Input? - if( direction & 2 ) - { - ptr64 = va_arg(Args, uint64_t*); - MAKE_IN(InDest, 'I', uint64_t*, ptr64); - if( direction & 1 ) - MAKE_OUT(OutDest, 'I', uint64_t, *ptr64); - } - else - { - val64 = va_arg(Args, uint64_t); - MAKE_OUT(OutDest, 'I', uint64_t, val64); - } - break; - case 's': - // Input string makes no sense! - if( direction & 2 ) { - fprintf(stderr, "ReadEntry: Incoming string is not defined\n"); - return NULL; - } - - str = va_arg(Args, char*); - if( OutDest ) - { - int len = strlen(str) + 1; - *OutDest = malloc( sizeof(tOutValue) + len ); - (*OutDest)->Type = 's'; - (*OutDest)->Length = len; - memcpy((*OutDest)->Data, str, len); - } - break; - - case 'd': - len = va_arg(Args, int); - str = va_arg(Args, char*); - - // Input ? - if( (direction & 2) && InDest ) - { - *InDest = (tInValue*)malloc( sizeof(tInValue) ); - (*InDest)->Type = 'd'; - (*InDest)->Length = len; - (*InDest)->Data = str; - } - - // Output ? - if( (direction & 1) && InDest ) - { - *OutDest = (tOutValue*)malloc( sizeof(tOutValue) + len ); - (*OutDest)->Type = 'd'; - (*OutDest)->Length = len; - memcpy((*OutDest)->Data, str, len); - } - break; - - default: - return NULL; - } - ArgTypes ++; - #undef MAKE_ASSIGN - - *Direction = direction; - - return ArgTypes; -} - -/** - * \param ArgTypes - * - * Whitespace is ignored - * >i: Input Integer (32-bits) - * >I: Input Long Integer (64-bits) - * >s: Input String - * >d: Input Buffer (Preceded by valid size) - * s >i", Path, Flags); -} - -void close(int FD) { - _Syscall(">i", FD); -} - -size_t read(int FD, size_t Bytes, void *Dest) { - return _Syscall(">i >i i >i >d", FD, Bytes, Bytes, Src); -} - -int seek(int FD, int64_t Ofs, int Dir) { - return _Syscall(">i >I >i", FD, Ofs, Dir); -} - -uint64_t tell(int FD) { - uint64_t ret; - _Syscall("i", &ret, FD); - return ret; -} - -int ioctl(int fd, int id, void *data) { - // NOTE: 1024 byte size is a hack - return _Syscall(">i >i ?d", fd, id, 1024, data); -} -int finfo(int fd, t_sysFInfo *info, int maxacls) { - return _Syscall(">i i", fd, maxacls*sizeof(t_sysFInfo), info, maxacls); -} - -int readdir(int fd, char *dest) { - return _Syscall(">i i >s >i", fd, name, flags); -} - -int _SysGetACL(int fd, t_sysACL *dest) { - return _Syscall(">i s >s >s >s", Device, Directory, Type, Options); -} - - -// --- Error Handler -int _SysSetFaultHandler(int (*Handler)(int)) { - return 0; -} - - -// === Symbol List === -#define DEFSYM(name) {#name, name} -const tSym caBuiltinSymbols[] = { - {"_exit", exit}, - - DEFSYM(open), - DEFSYM(close), - DEFSYM(read), - DEFSYM(write), - DEFSYM(seek), - DEFSYM(tell), - DEFSYM(ioctl), - DEFSYM(finfo), - DEFSYM(readdir), - DEFSYM(_SysOpenChild), - DEFSYM(_SysGetACL), - DEFSYM(_SysMount), - - {"_SysSetFaultHandler", _SysSetFaultHandler} -}; - -const int ciNumBuiltinSymbols = sizeof(caBuiltinSymbols)/sizeof(caBuiltinSymbols[0]); - diff --git a/AcessNative/ld-acess_src/Makefile b/AcessNative/ld-acess_src/Makefile new file mode 100644 index 00000000..4fb6ae28 --- /dev/null +++ b/AcessNative/ld-acess_src/Makefile @@ -0,0 +1,39 @@ +# +# + +ifeq ($(PLATFORM),) + PLATFORM := lin +endif + +OBJ := main.o syscalls.o request.o binary.o memory.o +OBJ += elf.o +OBJ := $(addsuffix .$(PLATFORM),$(OBJ)) + +ifeq ($(PLATFORM),win) + BIN := ../ld-acess.exe +endif +ifeq ($(PLATFORM),lin) + BIN := ../ld-acess + LD += -m elf_i386 +endif + +CFLAGS += -Wall -Werror -g -m32 + +.PHONY: all clean + +all: $(BIN) + +clean: + $(RM) $(BIN) $(OBJ) + +$(BIN): link.ld.$(PLATFORM) $(OBJ) +# $(LD) -g -o $@ $(OBJ) -T link.ld.$(PLATFORM) + $(CC) -g -o $@ $(OBJ) -m32 -Wl,-T,link.ld.$(PLATFORM) + +%.o.$(PLATFORM): %.c + $(CC) -c $< -o $@ $(CFLAGS) $(CPPFLAGS) + +# Modify the default makefile to put the executable at 1MB instead +link.ld.lin: + $(LD) --verbose | awk '{ if( substr($$0,0,5) == "====="){ bPrint = !bPrint; } else { if(bPrint){ print $$0;} } }' | sed 's/\b0x0[08][0-9]*\b/0x00100000/g' > $@ + diff --git a/AcessNative/ld-acess_src/binary.c b/AcessNative/ld-acess_src/binary.c new file mode 100644 index 00000000..b8f6e71b --- /dev/null +++ b/AcessNative/ld-acess_src/binary.c @@ -0,0 +1,240 @@ +/* + * AcessNative + */ +#include "common.h" +#include +#include +#include + +#define LIBRARY_PATH "../Usermode/Output/i386/Libs" + +// === TYPES === +typedef struct sBinary { + struct sBinary *Next; + void *Base; + int Ready; + tBinFmt *Format; + char Path[]; +} tBinary; + +// === IMPORTS === +extern void *Elf_Load(FILE *FP); +extern uintptr_t Elf_Relocate(void *Base); +extern int Elf_GetSymbol(void *Base, char *Name, uintptr_t *ret); +extern int ciNumBuiltinSymbols; +extern tSym caBuiltinSymbols[]; + +// === PROTOTYPES === +void Binary_AddToList(const char *Filename, void *Base, tBinFmt *Format); + +// === GLOBALS === +tBinFmt gElf_FormatDef = { +// .Mask = 0xFFFFFFFF, +// .Magic = "\x7F""ELF", + .Name = "ELF32", + .Load = Elf_Load, + .Relocate = Elf_Relocate, + .GetSymbol = Elf_GetSymbol + }; +tBinary *gLoadedBinaries; + +// === CODE === +char *Binary_LocateLibrary(const char *Name) +{ + char *envPath = getenv("ACESS_LIBRARY_PATH"); + int nameLen = strlen(Name); + FILE *fp; + + if( strcmp(Name, "libld-acess.so") == 0 ) { + return strdup("libld-acess.so"); + } + + // Try the environment ACESS_LIBRARY_PATH + if( envPath && envPath[0] != '\0' ) + { + int len = strlen(envPath)+1+nameLen+1; + char tmp[len]; + + strcpy(tmp, envPath); + strcat(tmp, "/"); + strcat(tmp, Name); + + fp = fopen(tmp, "r"); + if(fp) { + fclose(fp); + return strdup(tmp); + } + } + + { + int len = strlen(LIBRARY_PATH)+1+nameLen+1; + char tmp[len]; + + strcpy(tmp, LIBRARY_PATH); + strcat(tmp, "/"); + strcat(tmp, Name); + + printf("Binary_LocateLibrary: tmp = '%s'\n", tmp); + + fp = fopen(tmp, "r"); + if(fp) { + fclose(fp); + return strdup(tmp); + } + } + + fprintf(stderr, "Unable to locate library '%s'\n", Name); + + return NULL; +} + +void *Binary_LoadLibrary(const char *Name) +{ + char *path; + void *ret; + int (*entry)(int,char*[],char**) = NULL; + + // Find File + path = Binary_LocateLibrary(Name); + printf("Binary_LoadLibrary: path = '%s'\n", path); + if( !path ) { + return NULL; + } + + ret = Binary_Load(path, (uintptr_t*)&entry); + free(path); + + printf("Binary_LoadLibrary: ret = %p, entry = %p\n", ret, entry); + if( entry ) { + char *argv[] = {NULL}; + printf("Calling '%s' entry point %p\n", Name, entry); + entry(0, argv, NULL); + } + + return ret; +} + +void *Binary_Load(const char *Filename, uintptr_t *EntryPoint) +{ + FILE *fp; + uint32_t dword; + void *ret; + uintptr_t entry = 0; + tBinFmt *fmt; + + // Ignore loading ld-acess + if( strcmp(Filename, "libld-acess.so") == 0 ) { + *EntryPoint = 0; + return (void*)-1; + } + + { + tBinary *bin; + for(bin = gLoadedBinaries; bin; bin = bin->Next) + { + if( strcmp(Filename, bin->Path) == 0 ) { + return bin->Base; + } + } + } + + fp = fopen(Filename, "r"); + if( !fp ) { + // TODO: Handle libary directories + perror("Opening binary"); + return NULL; + } + + fread(&dword, 1, 4, fp); + fseek(fp, 0, SEEK_SET); + printf("dword = %08x\n", dword); + + if( memcmp(&dword, "\x7F""ELF", 4) == 0 ) { + fmt = &gElf_FormatDef; + } + else { + fclose(fp); + return NULL; + } + + printf("fmt->Load(%p)...\n", fp); + ret = fmt->Load(fp); + printf("fmt->Load(%p): %p\n", fp, ret); + if( !ret ) { + fclose(fp); + return NULL; + } + + Binary_AddToList(Filename, ret, fmt); + + entry = fmt->Relocate(ret); + printf("fmt->Relocate(%p): %p\n", ret, (void*)entry); + if( !entry ) { + // TODO: Clean up + return NULL; + } + + if( EntryPoint ) + *EntryPoint = entry; + + fclose(fp); + + Binary_SetReadyToUse(ret); + + return ret; +} + +void Binary_AddToList(const char *Filename, void *Base, tBinFmt *Format) +{ + tBinary *bin = malloc(sizeof(tBinary) + strlen(Filename) + 1); + bin->Base = Base; + bin->Format = Format; + strcpy(bin->Path, Filename); + bin->Ready = 0; + + bin->Next = gLoadedBinaries; + gLoadedBinaries = bin; +} + +void Binary_SetReadyToUse(void *Base) +{ + tBinary *bin; + for(bin = gLoadedBinaries; bin; bin = bin->Next) + { + if( bin->Base != Base ) continue ; + bin->Ready = 1; + } +} + +int Binary_GetSymbol(const char *SymbolName, uintptr_t *Value) +{ + int i; + tBinary *bin; + + printf("Binary_GetSymbol: (SymbolName='%s', Value=%p)\n", + SymbolName, Value); + + // Search builtins + // - Placed first to override smartarses that define their own versions + // of system calls + for( i = 0; i < ciNumBuiltinSymbols; i ++ ) + { + if( strcmp(caBuiltinSymbols[i].Name, SymbolName) == 0 ) { + *Value = (uintptr_t)caBuiltinSymbols[i].Value; + return 1; + } + } + + // TODO: Search list of loaded binaries + for(bin = gLoadedBinaries; bin; bin = bin->Next) + { + if( !bin->Ready ) continue; + printf(" Binary_GetSymbol: bin = %p{%p, %s}\n", bin, bin->Base, bin->Path); + if( bin->Format->GetSymbol(bin->Base, (char*)SymbolName, Value) ) + return 1; + } + + printf("Binary_GetSymbol: RETURN 0, not found\n"); + + return 0; +} diff --git a/AcessNative/ld-acess_src/common.h b/AcessNative/ld-acess_src/common.h new file mode 100644 index 00000000..4667acba --- /dev/null +++ b/AcessNative/ld-acess_src/common.h @@ -0,0 +1,35 @@ +/* + */ +#ifndef _COMMON_H_ +#define _COMMON_H_ + +#include +#include +#include + +extern int Binary_GetSymbol(const char *SymbolName, uintptr_t *Value); +extern void *Binary_LoadLibrary(const char *Path); +extern void *Binary_Load(const char *Path, uintptr_t *EntryPoint); +extern void Binary_SetReadyToUse(void *Base); + +extern int AllocateMemory(uintptr_t VirtAddr, size_t ByteCount); +extern uintptr_t FindFreeRange(size_t ByteCount, int MaxBits); + +extern void Warning(const char *Format, ...); +extern void Notice(const char *Format, ...); + +typedef struct { + char *Name; + void *Value; +} tSym; + +typedef struct sBinFmt { + struct sBinFmt *Next; + char *Name; + void *(*Load)(FILE *fp); + uintptr_t (*Relocate)(void *base); + int (*GetSymbol)(void*,char*,uintptr_t*); +} tBinFmt; + +#endif + diff --git a/AcessNative/ld-acess_src/elf.c b/AcessNative/ld-acess_src/elf.c new file mode 100644 index 00000000..3ab5a504 --- /dev/null +++ b/AcessNative/ld-acess_src/elf.c @@ -0,0 +1,529 @@ +/* + * Acess v0.1 + * ELF Executable Loader Code + */ +#define DEBUG 0 +#include +#include +#include +#include +#include "common.h" +#include "elf.h" + +#define DEBUG_WARN 1 + +#define MKPTR(_type,_val) ((_type*)(uintptr_t)(_val)) +#define PTRMK(_type,_val) MKPTR(_type,_val) +#define PTR(_val) ((void*)(uintptr_t)(_val)) + +#if DEBUG +# define ENTER(...) +# define LOG(s, ...) printf("%s: " s, __func__, __VA_ARGS__) +# define LOGS(s) printf("%s: " s, __func__) +# define LEAVE(...) +#else +# define ENTER(...) +# define LOG(...) +# define LOGS(...) +# define LEAVE(...) +#endif + +// === PROTOTYPES === +void *Elf_Load(FILE *FP); +uintptr_t Elf_Relocate(void *Base); + int Elf_GetSymbol(void *Base, char *Name, uintptr_t *ret); + int Elf_Int_DoRelocate(uint32_t r_info, uint32_t *ptr, uint32_t addend, Elf32_Sym *symtab, void *Base); +uint32_t Elf_Int_HashString(char *str); + +// === CODE === +void *Elf_Load(FILE *FP) +{ + Elf32_Ehdr hdr; + Elf32_Phdr *phtab; + int i, j; + int iPageCount; + uint32_t max, base = -1; + uint32_t addr; + uint32_t baseDiff = 0; + + ENTER("pFP", FP); + + // Read ELF Header + fread(&hdr, sizeof(hdr), 1, FP); + + // Check the file type + if(hdr.ident[0] != 0x7F || hdr.ident[1] != 'E' || hdr.ident[2] != 'L' || hdr.ident[3] != 'F') { + Warning("Non-ELF File was passed to the ELF loader\n"); + LEAVE('n'); + return NULL; + } + + // Check for a program header + if(hdr.phoff == 0) { + #if DEBUG_WARN + Warning("ELF File does not contain a program header\n"); + #endif + LEAVE('n'); + return NULL; + } + + // Read Program Header Table + phtab = malloc( sizeof(Elf32_Phdr) * hdr.phentcount ); + if( !phtab ) { + LEAVE('n'); + return NULL; + } + LOG("hdr.phoff = 0x%08x\n", hdr.phoff); + fseek(FP, hdr.phoff, SEEK_SET); + fread(phtab, sizeof(Elf32_Phdr), hdr.phentcount, FP); + + // Count Pages + iPageCount = 0; + LOG("hdr.phentcount = %i\n", hdr.phentcount); + for( i = 0; i < hdr.phentcount; i++ ) + { + // Ignore Non-LOAD types + if(phtab[i].Type != PT_LOAD) + continue; + iPageCount += ((phtab[i].VAddr&0xFFF) + phtab[i].MemSize + 0xFFF) >> 12; + LOG("phtab[%i] = {VAddr:0x%x, MemSize:0x%x}\n", i, phtab[i].VAddr, phtab[i].MemSize); + } + + LOG("iPageCount = %i\n", iPageCount); + + // Allocate Information Structure + //ret = malloc( sizeof(tBinary) + sizeof(tBinaryPage)*iPageCount ); + // Fill Info Struct + //ret->Entry = hdr.entrypoint; + //ret->Base = -1; // Set Base to maximum value + //ret->NumPages = iPageCount; + //ret->Interpreter = NULL; + + // Prescan for base and size + for( i = 0; i < hdr.phentcount; i ++) + { + if( phtab[i].Type != PT_LOAD ) + continue; + if( phtab[i].VAddr < base ) + base = phtab[i].VAddr; + if( phtab[i].VAddr > max ) + max = phtab[i].VAddr; + } + + LOG("base = %08x, max = %08x\n", base, max); + + if( base == 0 ) { + // Find a nice space (31 address bits allowed) + base = FindFreeRange( max, 31 ); + LOG("new base = %08x\n", base); + if( base == 0 ) return NULL; + baseDiff = base; + } + + // Load Pages + j = 0; + for( i = 0; i < hdr.phentcount; i++ ) + { + //LOG("phtab[%i].Type = 0x%x", i, phtab[i].Type); + LOG("phtab[%i] = {\n", i); + LOG(" .Type = 0x%08x\n", phtab[i].Type); + LOG(" .Offset = 0x%08x\n", phtab[i].Offset); + LOG(" .VAddr = 0x%08x\n", phtab[i].VAddr); + LOG(" .PAddr = 0x%08x\n", phtab[i].PAddr); + LOG(" .FileSize = 0x%08x\n", phtab[i].FileSize); + LOG(" .MemSize = 0x%08x\n", phtab[i].MemSize); + LOG(" .Flags = 0x%08x\n", phtab[i].Flags); + LOG(" .Align = 0x%08x\n", phtab[i].Align); + LOGS(" }\n"); + // Get Interpreter Name + if( phtab[i].Type == PT_INTERP ) + { + char *tmp; + //if(ret->Interpreter) continue; + tmp = malloc(phtab[i].FileSize); + fseek(FP, phtab[i].Offset, SEEK_SET); + fread(tmp, phtab[i].FileSize, 1, FP); + //ret->Interpreter = Binary_RegInterp(tmp); + LOG("Interpreter '%s'\n", tmp); + free(tmp); + continue; + } + // Ignore non-LOAD types + if(phtab[i].Type != PT_LOAD) continue; + + LOG("phtab[%i] = {VAddr:0x%x,Offset:0x%x,FileSize:0x%x}\n", + i, phtab[i].VAddr+baseDiff, phtab[i].Offset, phtab[i].FileSize); + + addr = phtab[i].VAddr + baseDiff; + + if( AllocateMemory( addr, phtab[i].MemSize ) ) { + return NULL; + } + + fseek(FP, phtab[i].Offset, SEEK_SET); + fread( PTRMK(void, addr), phtab[i].FileSize, 1, FP ); + memset( PTRMK(char, addr) + phtab[i].FileSize, 0, phtab[i].MemSize - phtab[i].FileSize ); + } + + // Clean Up + free(phtab); + // Return + LEAVE('p', base); + return PTRMK(void, base); +} + +// --- ELF RELOCATION --- +/** + * \brief Relocates a loaded ELF Executable + */ +uintptr_t Elf_Relocate(void *Base) +{ + Elf32_Ehdr *hdr = Base; + Elf32_Phdr *phtab; + int i, j; // Counters + char *libPath; + uint32_t iRealBase = -1; + uintptr_t iBaseDiff; + int iSegmentCount; + int iSymCount = 0; + Elf32_Rel *rel = NULL; + Elf32_Rela *rela = NULL; + uint32_t *pltgot = NULL; + void *plt = NULL; + uint32_t *ptr; + int relSz=0, relEntSz=8; + int relaSz=0, relaEntSz=8; + int pltSz=0, pltType=0; + Elf32_Dyn *dynamicTab = NULL; // Dynamic Table Pointer + char *dynstrtab = NULL; // .dynamic String Table + Elf32_Sym *dynsymtab = NULL; + int bFailed = 0; + + ENTER("pBase", Base); + LOG("Base = %p\n", Base); + + // Parse Program Header to get Dynamic Table + phtab = Base + hdr->phoff; + iSegmentCount = hdr->phentcount; + for(i = 0; i < iSegmentCount; i ++ ) + { + // Determine linked base address + if(phtab[i].Type == PT_LOAD && iRealBase > phtab[i].VAddr) + iRealBase = phtab[i].VAddr; + + // Find Dynamic Section + if(phtab[i].Type == PT_DYNAMIC) { + if(dynamicTab) { + Warning("Elf_Relocate - Multiple PT_DYNAMIC segments\n"); + continue; + } + dynamicTab = MKPTR(void, phtab[i].VAddr); + j = i; // Save Dynamic Table ID + break; + } + } + + // Check if a PT_DYNAMIC segement was found + if(!dynamicTab) { + Warning("Elf_Relocate: No PT_DYNAMIC segment in image, returning\n"); + LEAVE('x', hdr->entrypoint); + return hdr->entrypoint; + } + + // Page Align real base + iRealBase &= ~0xFFF; + + LOG("dynamicTab = %p\n", dynamicTab); + // Adjust "Real" Base + iBaseDiff = (uintptr_t)Base - iRealBase; + LOG("iBaseDiff = %p\n", (void*)iBaseDiff); + // Adjust Dynamic Table + dynamicTab = PTR( (uintptr_t)dynamicTab + iBaseDiff); + LOG("dynamicTab = %p\n", dynamicTab); + + hdr->entrypoint += iBaseDiff; + + // === Get Symbol table and String Table === + for( j = 0; dynamicTab[j].d_tag != DT_NULL; j++) + { + switch(dynamicTab[j].d_tag) + { + // --- Symbol Table --- + case DT_SYMTAB: + dynamicTab[j].d_val += iBaseDiff; + dynsymtab = PTRMK(void, dynamicTab[j].d_val); + hdr->misc.SymTable = dynamicTab[j].d_val; // Saved in unused bytes of ident + break; + + // --- String Table --- + case DT_STRTAB: + dynamicTab[j].d_val += iBaseDiff; + dynstrtab = PTRMK(void, dynamicTab[j].d_val); + break; + + // --- Hash Table -- + case DT_HASH: + dynamicTab[j].d_val += iBaseDiff; + iSymCount = (PTRMK(uint32_t, dynamicTab[j].d_val))[1]; + hdr->misc.HashTable = dynamicTab[j].d_val; // Saved in unused bytes of ident + break; + } + } + + + // Alter Symbols to true base + for(i = 0; i < iSymCount; i ++) + { + dynsymtab[i].nameOfs += (uintptr_t)dynstrtab; + if( dynsymtab[i].shndx == SHN_UNDEF ) + { + LOG("Sym '%s' = UNDEF\n", MKPTR(char,dynsymtab[i].name)); + } + else + { + dynsymtab[i].value += iBaseDiff; + LOG("Sym '%s' = 0x%x (relocated)\n", MKPTR(char,dynsymtab[i].name), dynsymtab[i].value); + } + } + + // === Add to loaded list (can be imported now) === + Binary_SetReadyToUse( Base ); + + // === Parse Relocation Data === + for( j = 0; dynamicTab[j].d_tag != DT_NULL; j++) + { + switch(dynamicTab[j].d_tag) + { + // --- Shared Library Name --- + case DT_SONAME: + LOG(".so Name '%s'\n", dynstrtab + dynamicTab[j].d_val); + break; + // --- Needed Library --- + case DT_NEEDED: + libPath = dynstrtab + dynamicTab[j].d_val; + Binary_LoadLibrary(libPath); + break; + // --- PLT/GOT --- + case DT_PLTGOT: pltgot = (void*)(iBaseDiff+dynamicTab[j].d_val); break; + case DT_JMPREL: plt = (void*)(iBaseDiff+dynamicTab[j].d_val); break; + case DT_PLTREL: pltType = dynamicTab[j].d_val; break; + case DT_PLTRELSZ: pltSz = dynamicTab[j].d_val; break; + + // --- Relocation --- + case DT_REL: rel = (void*)(iBaseDiff + dynamicTab[j].d_val); break; + case DT_RELSZ: relSz = dynamicTab[j].d_val; break; + case DT_RELENT: relEntSz = dynamicTab[j].d_val; break; + + case DT_RELA: rela = (void*)(iBaseDiff + dynamicTab[j].d_val); break; + case DT_RELASZ: relaSz = dynamicTab[j].d_val; break; + case DT_RELAENT: relaEntSz = dynamicTab[j].d_val; break; + } + } + + // Parse Relocation Entries + if(rel && relSz) + { + j = relSz / relEntSz; + for( i = 0; i < j; i++ ) + { + ptr = (void*)(iBaseDiff + rel[i].r_offset); + if( !Elf_Int_DoRelocate(rel[i].r_info, ptr, *ptr, dynsymtab, Base) ) { + bFailed = 1; + } + } + } + // Parse Relocation Entries + if(rela && relaSz) + { + j = relaSz / relaEntSz; + for( i = 0; i < j; i++ ) + { + ptr = (void*)(iBaseDiff + rela[i].r_offset); + if( !Elf_Int_DoRelocate(rel[i].r_info, ptr, rela[i].r_addend, dynsymtab, Base) ) { + bFailed = 1; + } + } + } + + // === Process PLT (Procedure Linkage Table) === + if(plt && pltSz) + { + if(pltType == DT_REL) + { + Elf32_Rel *pltRel = plt; + j = pltSz / sizeof(Elf32_Rel); + LOG("PLT Rel - plt = %p, pltSz = %i (%i ents)\n", plt, pltSz, j); + for(i = 0; i < j; i++) + { + ptr = (void*)(iBaseDiff + pltRel[i].r_offset); + if( !Elf_Int_DoRelocate(pltRel[i].r_info, ptr, *ptr, dynsymtab, Base) ) { + bFailed = 1; + } + } + } + else + { + Elf32_Rela *pltRela = plt; + j = pltSz / sizeof(Elf32_Rela); + LOG("PLT RelA - plt = %p, pltSz = %i (%i ents)\n", plt, pltSz, j); + for(i=0;ientrypoint); + return hdr->entrypoint; +} + +/** + * \fn void Elf_Int_DoRelocate(uint32_t r_info, uint32_t *ptr, uint32_t addend, Elf32_Sym *symtab, void *base) + * \brief Performs a relocation + * \param r_info Field from relocation entry + * \param ptr Pointer to location of relocation + * \param addend Value to add to symbol + * \param symtab Symbol Table + * \param base Base of loaded binary + */ +int Elf_Int_DoRelocate(uint32_t r_info, uint32_t *ptr, uint32_t addend, Elf32_Sym *symtab, void *base) +{ + uintptr_t val; + int type = ELF32_R_TYPE(r_info); + int sym = ELF32_R_SYM(r_info); + char *sSymName = PTRMK(char, symtab[sym].name); + + //LogF("Elf_Int_DoRelocate: (r_info=0x%x, ptr=0x%x, addend=0x%x, .., base=0x%x)\n", + // r_info, ptr, addend, base); + + switch( type ) + { + // Standard 32 Bit Relocation (S+A) + case R_386_32: + if( !Elf_GetSymbol( base, sSymName, &val ) && !Binary_GetSymbol( sSymName, &val ) ) { + Warning("Unable to find symbol '%s'", sSymName); + return 0; + } + LOG("%08x R_386_32 *%p += %p('%s')\n", r_info, ptr, (void*)val, sSymName); + *ptr = val + addend; + break; + + // 32 Bit Relocation wrt. Offset (S+A-P) + case R_386_PC32: + if( !Elf_GetSymbol( base, sSymName, &val ) && !Binary_GetSymbol( sSymName, &val ) ) { + Warning("Unable to find symbol '%s'", sSymName); + return 0; + } + LOG("%08x R_386_PC32 *%p = 0x%x + %p('%s') - %p\n", r_info, ptr, *ptr, (void*)val, sSymName, ptr ); + // TODO: Check if it needs the true value of ptr or the compiled value + // NOTE: Testing using true value + *ptr = val + addend - (uintptr_t)ptr; + break; + + // Absolute Value of a symbol (S) + case R_386_GLOB_DAT: + if( !Elf_GetSymbol( base, sSymName, &val ) && !Binary_GetSymbol( sSymName, &val ) ) { + Warning("Unable to find symbol '%s'", sSymName); + return 0; + } + LOG("%08x R_386_GLOB_DAT *%p = 0x%x(%s)\n", r_info, ptr, (unsigned int)val, sSymName); + *ptr = val; + break; + + // Absolute Value of a symbol (S) + case R_386_JMP_SLOT: + if( !Elf_GetSymbol( base, sSymName, &val ) && !Binary_GetSymbol( sSymName, &val ) ) { + Warning("Unable to find symbol '%s'", sSymName); + return 0; + } + LOG("%08x R_386_JMP_SLOT *%p = 0x%x (%s)\n", r_info, ptr, (unsigned int)val, sSymName); + *ptr = val; + break; + + // Base Address (B+A) + case R_386_RELATIVE: + LOG("%08x R_386_RELATIVE *%p = %p + 0x%x\n", r_info, ptr, base, addend); + *ptr = (uintptr_t)base + addend; + break; + + default: + LOG("Rel %p: 0x%x,%i\n", ptr, sym, type); + break; + } + return 1; +} + +/** + * \fn int Elf_GetSymbol(void *Base, char *name, uintptr_t *ret) + * \brief Get a symbol from the loaded binary + */ +int Elf_GetSymbol(void *Base, char *Name, uintptr_t *ret) +{ + Elf32_Ehdr *hdr = (void*)Base; + Elf32_Sym *symtab; + int nbuckets = 0; + int iSymCount = 0; + int i; + uint32_t *pBuckets; + uint32_t *pChains; + uint32_t iNameHash; + + if(!Base) return 0; + + pBuckets = PTR(hdr->misc.HashTable); + symtab = PTR(hdr->misc.SymTable); + + nbuckets = pBuckets[0]; + iSymCount = pBuckets[1]; + pBuckets = &pBuckets[2]; + pChains = &pBuckets[ nbuckets ]; + + // Get hash + iNameHash = Elf_Int_HashString(Name); + iNameHash %= nbuckets; + + // Check Bucket + i = pBuckets[ iNameHash ]; + if(symtab[i].shndx != SHN_UNDEF && strcmp(MKPTR(char,symtab[i].name), Name) == 0) { + if(ret) *ret = symtab[ i ].value; + return 1; + } + + // Walk Chain + while(pChains[i] != STN_UNDEF) + { + i = pChains[i]; + if(symtab[i].shndx != SHN_UNDEF && strcmp(MKPTR(char,symtab[i].name), Name) == 0) { + if(ret) *ret = symtab[ i ].value; + return 1; + } + } + return 0; +} + +/** + * \fn uint32_t Elf_Int_HashString(char *str) + * \brief Hash a string in the ELF format + * \param str String to hash + * \return Hash value + */ +uint32_t Elf_Int_HashString(char *str) +{ + uint32_t h = 0, g; + while(*str) + { + h = (h << 4) + *str++; + if( (g = h & 0xf0000000) ) + h ^= g >> 24; + h &= ~g; + } + return h; +} diff --git a/AcessNative/ld-acess_src/elf.h b/AcessNative/ld-acess_src/elf.h new file mode 100644 index 00000000..77be918b --- /dev/null +++ b/AcessNative/ld-acess_src/elf.h @@ -0,0 +1,217 @@ +/** + * \file elf.h + * \brief ELF Exeutable Loader + */ +#ifndef _BIN_ELF_H +#define _BIN_ELF_H + +#include + +/** + * \brief ELF File Header + */ +struct sElf32_Ehdr +{ + union { + char ident[16]; //!< Identifier Bytes + struct { + uint32_t Ident1; + uint32_t Ident2; + uint32_t HashTable; + uint32_t SymTable; + } misc; + }; + uint16_t filetype; //!< File Type + uint16_t machine; //!< Machine / Arch + uint32_t version; //!< Version (File?) + uint32_t entrypoint; //!< Entry Point + uint32_t phoff; //!< Program Header Offset + uint32_t shoff; //!< Section Header Offset + uint32_t flags; //!< Flags + uint16_t headersize; //!< Header Size + uint16_t phentsize; //!< Program Header Entry Size + uint16_t phentcount; //!< Program Header Entry Count + uint16_t shentsize; //!< Section Header Entry Size + uint16_t shentcount; //!< Section Header Entry Count + uint16_t shstrindex; //!< Section Header String Table Index +} __attribute__ ((packed)); + +/** + * \brief Executable Types + */ +enum eElf32_ExecTypes +{ + ET_NONE = 0, //!< NULL Type + ET_REL = 1, //!< Relocatable (Object) + ET_EXEC = 2, //!< Executable + ET_DYN = 3, //!< Dynamic Library + ET_CORE = 4, //!< Core? + ET_LOPROC = 0xFF00, //!< Low Impl Defined + ET_HIPROC = 0xFFFF //!< High Impl Defined +}; + +/** + \name Section IDs + \{ +*/ +#define SHN_UNDEF 0 //!< Undefined Section +#define SHN_LORESERVE 0xFF00 //!< Low Reserved +#define SHN_LOPROC 0xFF00 //!< Low Impl Defined +#define SHN_HIPROC 0xFF1F //!< High Impl Defined +#define SHN_ABS 0xFFF1 //!< Absolute Address (Base: 0, Size: -1) +#define SHN_COMMON 0xFFF2 //!< Common +#define SHN_HIRESERVE 0xFFFF //!< High Reserved +//! \} + +/** + \enum eElfSectionTypes + \brief ELF Section Types +*/ +enum eElfSectionTypes { + 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, //A + SHT_DYNSYM, //B + SHT_LAST, //C + SHT_LOPROC = 0x70000000, + SHT_HIPROC = 0x7fffffff, + SHT_LOUSER = 0x80000000, + SHT_HIUSER = 0xffffffff +}; + +#define SHF_WRITE 0x1 +#define SHF_ALLOC 0x2 +#define SHF_EXECINSTR 0x4 +#define SHF_MASKPROC 0xf0000000 + +struct sElf32_Shent { + uint32_t name; + uint32_t type; + uint32_t flags; + uint32_t address; + uint32_t offset; + uint32_t size; + uint32_t link; + uint32_t info; + uint32_t addralign; + uint32_t entsize; +} __attribute__ ((packed)); //sizeof = 40 + +struct elf_sym_s { + union { + uint32_t nameOfs; + uint32_t name; + }; + uint32_t value; //Address + uint32_t size; + uint8_t info; + uint8_t other; + uint16_t shndx; +} __attribute__ ((packed)); +#define STN_UNDEF 0 // Undefined Symbol + +enum { + PT_NULL, //0 + PT_LOAD, //1 + PT_DYNAMIC, //2 + PT_INTERP, //3 + PT_NOTE, //4 + PT_SHLIB, //5 + PT_PHDR, //6 + PT_LOPROC = 0x70000000, + PT_HIPROC = 0x7fffffff +}; + +struct sElf32_Phdr { + uint32_t Type; + uint32_t Offset; + uint32_t VAddr; + uint32_t PAddr; + uint32_t FileSize; + uint32_t MemSize; + uint32_t Flags; + uint32_t Align; +} __attribute__ ((packed)); + +struct elf32_rel_s { + uint32_t r_offset; + uint32_t r_info; +} __attribute__ ((packed)); + +struct elf32_rela_s { + uint32_t r_offset; + uint32_t r_info; + int32_t r_addend; +} __attribute__ ((packed)); + +enum { + R_386_NONE = 0, // none + R_386_32, // S+A + R_386_PC32, // S+A-P + R_386_GOT32, // G+A-P + R_386_PLT32, // L+A-P + R_386_COPY, // none + R_386_GLOB_DAT, // S + R_386_JMP_SLOT, // S + R_386_RELATIVE, // B+A + R_386_GOTOFF, // S+A-GOT + R_386_GOTPC, // GOT+A-P + R_386_LAST // none +}; + +#define ELF32_R_SYM(i) ((i)>>8) // Takes an info value and returns a symbol index +#define ELF32_R_TYPE(i) ((i)&0xFF) // Takes an info value and returns a type +#define ELF32_R_INFO(s,t) (((s)<<8)+((t)&0xFF)) // Takes a type and symbol index and returns an info value + +struct elf32_dyn_s { + uint32_t d_tag; + uint32_t d_val; //Also d_ptr +} __attribute__ ((packed)); + +enum { + DT_NULL, //!< Marks End of list + DT_NEEDED, //!< Offset in strtab to needed library + DT_PLTRELSZ, //!< Size in bytes of PLT + DT_PLTGOT, //!< Address of PLT/GOT + DT_HASH, //!< Address of symbol hash table + DT_STRTAB, //!< String Table address + DT_SYMTAB, //!< Symbol Table address + DT_RELA, //!< Relocation table address + DT_RELASZ, //!< Size of relocation table + DT_RELAENT, //!< Size of entry in relocation table + DT_STRSZ, //!< Size of string table + DT_SYMENT, //!< Size of symbol table entry + DT_INIT, //!< Address of initialisation function + DT_FINI, //!< Address of termination function + DT_SONAME, //!< String table offset of so name + DT_RPATH, //!< String table offset of library path + DT_SYMBOLIC,//!< Reverse order of symbol searching for library, search libs first then executable + DT_REL, //!< Relocation Entries (Elf32_Rel instead of Elf32_Rela) + DT_RELSZ, //!< Size of above table (bytes) + DT_RELENT, //!< Size of entry in above table + DT_PLTREL, //!< Relocation entry of PLT + DT_DEBUG, //!< Debugging Entry - Unknown contents + DT_TEXTREL, //!< Indicates that modifcations to a non-writeable segment may occur + DT_JMPREL, //!< Address of PLT only relocation entries + DT_LOPROC = 0x70000000, //!< Low Definable + DT_HIPROC = 0x7FFFFFFF //!< High Definable +}; + +typedef struct sElf32_Ehdr Elf32_Ehdr; +typedef struct sElf32_Phdr Elf32_Phdr; +typedef struct sElf32_Shent Elf32_Shent; +typedef struct elf_sym_s elf_symtab; +typedef struct elf_sym_s Elf32_Sym; +typedef struct elf32_rel_s Elf32_Rel; +typedef struct elf32_rela_s Elf32_Rela; +typedef struct elf32_dyn_s Elf32_Dyn; + +#endif // defined(_EXE_ELF_H) diff --git a/AcessNative/ld-acess_src/main.c b/AcessNative/ld-acess_src/main.c new file mode 100644 index 00000000..e310a84a --- /dev/null +++ b/AcessNative/ld-acess_src/main.c @@ -0,0 +1,69 @@ +/* + */ +#include "common.h" +#include +#include +#include + +// === CODE === +int main(int argc, char *argv[], char **envp) +{ + int i; + int appArgc; + char **appArgv; + char *appPath; + int (*appMain)(int, char *[], char **); + void *base; + + for( i = 1; i < argc; i ++ ) + { + if( argv[i][0] != '-' ) break; + } + + if( i >= argc ) { + fprintf(stderr, "Usage: ld-acess [arguments ...]\n"); + return 1; + } + + appPath = argv[i]; + + appArgc = argc - i; + appArgv = &argv[i]; + + printf("Exectutable Path: '%s'\n", appPath); + printf("Executable argc = %i\n", appArgc); + + base = Binary_Load(appPath, (uintptr_t*)&appMain); + printf("base = %p\n", base); + if( !base ) return 127; + + __asm__ __volatile__ ( + "push %0;\n\t" + "push %1;\n\t" + "push %2;\n\t" + "jmp *%3;\n\t" + : : "r" (envp), "r" (appArgv), "r" (appArgc), "r" (appMain) ); + //return appMain(appArgc, appArgv, envp); + return -1; +} + +void Warning(const char *Format, ...) +{ + va_list args; + printf("Warning: "); + va_start(args, Format); + vprintf(Format, args); + va_end(args); + printf("\n"); +} + +void Notice(const char *Format, ...) +{ + va_list args; + printf("Notice: "); + va_start(args, Format); + vprintf(Format, args); + va_end(args); + printf("\n"); +} + diff --git a/AcessNative/ld-acess_src/memory.c b/AcessNative/ld-acess_src/memory.c new file mode 100644 index 00000000..627f9024 --- /dev/null +++ b/AcessNative/ld-acess_src/memory.c @@ -0,0 +1,69 @@ +/* + */ +#include "common.h" +#include +#include +#if __WIN32__ +# include +#else +# include +# include +#endif + +// === PROTOTYPES === + int AllocateMemory(uintptr_t VirtAddr, size_t ByteCount); +uintptr_t FindFreeRange(size_t ByteCount, int MaxBits); + +// === CODE === +int AllocateMemory(uintptr_t VirtAddr, size_t ByteCount) +{ + uintptr_t base = (VirtAddr >> 12) << 12; + size_t size = (VirtAddr & 0xFFF) + ByteCount; + void *tmp; + #if __WIN32__ + tmp = VirtualAlloc(base, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE); + if( tmp == NULL ) { + printf("ERROR: Unable to allocate memory (%i)\n", GetLastError()); + return -1; + } + #else + tmp = mmap((void*)base, size, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0); + if( tmp == MAP_FAILED ) { + return -1; + } + #endif + return 0; +} + +uintptr_t FindFreeRange(size_t ByteCount, int MaxBits) +{ + #if __WIN32__ + # error "Windows FindFreeRange() unimplemented" + #else + uintptr_t base, ofs, size; + uintptr_t end = -1; + const int PAGE_SIZE = 0x1000; + + size = (ByteCount + PAGE_SIZE - 1) / PAGE_SIZE; + size *= PAGE_SIZE; + + end <<= (sizeof(intptr_t)*8-MaxBits); + end >>= (sizeof(intptr_t)*8-MaxBits); + printf("end = %p\n", (void*)end); + +// for( base = 0; base < end - size; base -= PAGE_SIZE ) + for( base = end - size + 1; base > 0; base -= PAGE_SIZE ) + { + for( ofs = 0; ofs < size; ofs += PAGE_SIZE ) { + if( msync( (void*)(base+ofs), 1, 0) == 0 ) + break; + if( errno != ENOMEM ) + perror("FindFreeRange, msync"); + } + if( ofs >= size ) { + return base; + } + } + return 0; + #endif +} diff --git a/AcessNative/ld-acess_src/request.c b/AcessNative/ld-acess_src/request.c new file mode 100644 index 00000000..f9526b3a --- /dev/null +++ b/AcessNative/ld-acess_src/request.c @@ -0,0 +1,151 @@ +/* + */ +#include +#include +#include +#ifdef __WIN32__ +# include +# include +#else +# include +# include +# include +#endif +#include "request.h" +#include "../syscalls.h" + +#define SERVER_PORT 0xACE + +// === GLOBALS === +#ifdef __WIN32__ +WSADATA gWinsock; +SOCKET gSocket = INVALID_SOCKET; +#else +# define INVALID_SOCKET -1 + int gSocket = INVALID_SOCKET; +#endif +// Client ID to pass to server +// TODO: Implement such that each thread gets a different one +static int siSyscall_ClientID = 0; + +// === CODE === +int _InitSyscalls() +{ + struct sockaddr_in server; + struct sockaddr_in client; + + #ifdef __WIN32__ + /* Open windows connection */ + if (WSAStartup(0x0101, &gWinsock) != 0) + { + fprintf(stderr, "Could not open Windows connection.\n"); + exit(0); + } + #endif + + // Open UDP Connection + gSocket = socket(AF_INET, SOCK_DGRAM, 0); + if (gSocket == INVALID_SOCKET) + { + fprintf(stderr, "Could not create socket.\n"); + #if __WIN32__ + WSACleanup(); + #endif + exit(0); + } + + // Set server address + memset((void *)&server, '\0', sizeof(struct sockaddr_in)); + server.sin_family = AF_INET; + server.sin_port = htons(SERVER_PORT); + server.sin_addr.s_addr = htonl(0x7F00001); + + // Set client address + memset((void *)&client, '\0', sizeof(struct sockaddr_in)); + client.sin_family = AF_INET; + client.sin_port = htons(0); + client.sin_addr.s_addr = htonl(0x7F00001); + + // Bind + if( bind(gSocket, (struct sockaddr *)&client, sizeof(struct sockaddr_in)) == -1 ) + { + fprintf(stderr, "Cannot bind address to socket.\n"); + #if __WIN32__ + closesocket(gSocket); + WSACleanup(); + #else + close(gSocket); + #endif + exit(0); + } + return 0; +} + +int SendRequest(int RequestID, int NumOutput, tOutValue **Output, int NumInput, tInValue **Input) +{ + tRequestHeader *request; + tRequestValue *value; + char *data; + int requestLen; + int i; + + // See ../syscalls.h for details of request format + requestLen = sizeof(tRequestHeader) + (NumOutput + NumInput) * sizeof(tRequestValue); + + // Get total param length + for( i = 0; i < NumOutput; i ++ ) + requestLen += Output[i]->Length; + + // Allocate request + request = malloc( requestLen ); + value = request->Params; + data = (char*)&request->Params[ NumOutput + NumInput ]; + + // Set header + request->ClientID = siSyscall_ClientID; + request->CallID = RequestID; // Syscall + request->NParams = NumOutput; + request->NReturn = NumInput; + + // Set parameters + for( i = 0; i < NumOutput; i ++ ) + { + switch(Output[i]->Type) + { + case 'i': value->Type = ARG_TYPE_INT32; break; + case 'I': value->Type = ARG_TYPE_INT64; break; + case 'd': value->Type = ARG_TYPE_DATA; break; + default: + return -1; + } + value->Length = Output[i]->Length; + + memcpy(data, Output[i]->Data, Output[i]->Length); + + data += Output[i]->Length; + } + + // Set return values + for( i = 0; i < NumInput; i ++ ) + { + switch(Input[i]->Type) + { + case 'i': value->Type = ARG_TYPE_INT32; break; + case 'I': value->Type = ARG_TYPE_INT64; break; + case 'd': value->Type = ARG_TYPE_DATA; break; + default: + return -1; + } + value->Length = Input[i]->Length; + } + + // Send it off + send(gSocket, request, requestLen, 0); + + // Wait for a response + recv(gSocket, request, requestLen, 0); + + // Parse response out + + return 0; +} diff --git a/AcessNative/ld-acess_src/request.h b/AcessNative/ld-acess_src/request.h new file mode 100644 index 00000000..8c89e6f6 --- /dev/null +++ b/AcessNative/ld-acess_src/request.h @@ -0,0 +1,26 @@ +/* + * Acess2 - AcessNative + * ld-acess + * + * request.h - IPC Request common header + */ + +#ifndef _REQUEST_H_ +#define _REQUEST_H_ + +typedef struct { + char Type; + int Length; + char Data[]; +} tOutValue; + +typedef struct { + char Type; + int Length; + void *Data; +} tInValue; + +extern int SendRequest(int RequestID, int NumOutput, tOutValue **Output, + int NumInput, tInValue **Input); + +#endif diff --git a/AcessNative/ld-acess_src/syscalls.c b/AcessNative/ld-acess_src/syscalls.c new file mode 100644 index 00000000..ec4af017 --- /dev/null +++ b/AcessNative/ld-acess_src/syscalls.c @@ -0,0 +1,302 @@ +/* + */ +#include "../../Usermode/include/acess/sys.h" +#include "common.h" +#include +#include +#include +#include +#include +#include "request.h" + +// === Types === + +// === IMPORTS === + +// === CODE === +const char *ReadEntry(tOutValue **OutDest, tInValue **InDest, + int *Direction, const char *ArgTypes, va_list Args) +{ + uint64_t val64, *ptr64; + uint32_t val32, *ptr32; + int direction = 0; // 0: Invalid, 1: Out, 2: In, 3: Out + char *str; + int len; + + // Eat whitespace + while(*ArgTypes && *ArgTypes == ' ') ArgTypes ++; + if( *ArgTypes == '\0' ) return ArgTypes; + + // Get direction + switch(*ArgTypes) + { + case '>': direction = 1; break; + case '<': direction = 2; break; + case '?': direction = 3; break; + default: + return NULL; + } + ArgTypes ++; + + // Eat whitespace + while(*ArgTypes && *ArgTypes == ' ') ArgTypes ++; + if( *ArgTypes == '\0' ) return ArgTypes; + + // Internal helper macro + #define MAKE_OUT(_dest,_typeChar,_typeName,_value) do{if((_dest)){\ + *(_dest) = (tOutValue*)malloc(sizeof(tOutValue)+sizeof(_typeName));\ + (*(_dest))->Type=(_typeChar);(*(_dest))->Length=sizeof(_typeName);\ + *(_typeName*)((*(_dest))->Data) = (_value);\ + }}while(0) + #define MAKE_IN(_dest,_typeChar,_typeName,_value) do{if((_dest)){\ + *(_dest) = (tInValue*)malloc(sizeof(tInValue));\ + (*(_dest))->Type=(_typeChar);(*(_dest))->Length=sizeof(_typeName);\ + (*(_dest))->Data = (_value);\ + }}while(0) + + // Get type + switch(*ArgTypes) + { + case 'i': // 32-bit integer + // Input? + if( direction & 2 ) + { + ptr32 = va_arg(Args, uint32_t*); + MAKE_IN(InDest, 'i', uint32_t*, ptr32); + if( direction & 1 ) + MAKE_OUT(OutDest, 'i', uint32_t, *ptr32); + } + else + { + val32 = va_arg(Args, uint32_t); + MAKE_OUT(OutDest, 'i', uint32_t, val32); + } + break; + case 'I': // 64-bit integer + // Input? + if( direction & 2 ) + { + ptr64 = va_arg(Args, uint64_t*); + MAKE_IN(InDest, 'I', uint64_t*, ptr64); + if( direction & 1 ) + MAKE_OUT(OutDest, 'I', uint64_t, *ptr64); + } + else + { + val64 = va_arg(Args, uint64_t); + MAKE_OUT(OutDest, 'I', uint64_t, val64); + } + break; + case 's': + // Input string makes no sense! + if( direction & 2 ) { + fprintf(stderr, "ReadEntry: Incoming string is not defined\n"); + return NULL; + } + + str = va_arg(Args, char*); + if( OutDest ) + { + int len = strlen(str) + 1; + *OutDest = malloc( sizeof(tOutValue) + len ); + (*OutDest)->Type = 's'; + (*OutDest)->Length = len; + memcpy((*OutDest)->Data, str, len); + } + break; + + case 'd': + len = va_arg(Args, int); + str = va_arg(Args, char*); + + // Input ? + if( (direction & 2) && InDest ) + { + *InDest = (tInValue*)malloc( sizeof(tInValue) ); + (*InDest)->Type = 'd'; + (*InDest)->Length = len; + (*InDest)->Data = str; + } + + // Output ? + if( (direction & 1) && InDest ) + { + *OutDest = (tOutValue*)malloc( sizeof(tOutValue) + len ); + (*OutDest)->Type = 'd'; + (*OutDest)->Length = len; + memcpy((*OutDest)->Data, str, len); + } + break; + + default: + return NULL; + } + ArgTypes ++; + #undef MAKE_ASSIGN + + *Direction = direction; + + return ArgTypes; +} + +/** + * \param ArgTypes + * + * Whitespace is ignored + * >i: Input Integer (32-bits) + * >I: Input Long Integer (64-bits) + * >s: Input String + * >d: Input Buffer (Preceded by valid size) + * s >i", Path, Flags); +} + +void close(int FD) { + _Syscall(">i", FD); +} + +size_t read(int FD, size_t Bytes, void *Dest) { + return _Syscall(">i >i i >i >d", FD, Bytes, Bytes, Src); +} + +int seek(int FD, int64_t Ofs, int Dir) { + return _Syscall(">i >I >i", FD, Ofs, Dir); +} + +uint64_t tell(int FD) { + uint64_t ret; + _Syscall("i", &ret, FD); + return ret; +} + +int ioctl(int fd, int id, void *data) { + // NOTE: 1024 byte size is a hack + return _Syscall(">i >i ?d", fd, id, 1024, data); +} +int finfo(int fd, t_sysFInfo *info, int maxacls) { + return _Syscall(">i i", fd, maxacls*sizeof(t_sysFInfo), info, maxacls); +} + +int readdir(int fd, char *dest) { + return _Syscall(">i i >s >i", fd, name, flags); +} + +int _SysGetACL(int fd, t_sysACL *dest) { + return _Syscall(">i s >s >s >s", Device, Directory, Type, Options); +} + + +// --- Error Handler +int _SysSetFaultHandler(int (*Handler)(int)) { + return 0; +} + + +// === Symbol List === +#define DEFSYM(name) {#name, name} +const tSym caBuiltinSymbols[] = { + {"_exit", exit}, + + DEFSYM(open), + DEFSYM(close), + DEFSYM(read), + DEFSYM(write), + DEFSYM(seek), + DEFSYM(tell), + DEFSYM(ioctl), + DEFSYM(finfo), + DEFSYM(readdir), + DEFSYM(_SysOpenChild), + DEFSYM(_SysGetACL), + DEFSYM(_SysMount), + + {"_SysSetFaultHandler", _SysSetFaultHandler} +}; + +const int ciNumBuiltinSymbols = sizeof(caBuiltinSymbols)/sizeof(caBuiltinSymbols[0]); +