+++ /dev/null
-#
-#
-
-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' > $@
-
+++ /dev/null
-/*
- * AcessNative
- */
-#include "common.h"
-#include <stdint.h>
-#include <stdio.h>
-#include <string.h>
-
-#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;
-}
+++ /dev/null
-/*
- */
-#ifndef _COMMON_H_
-#define _COMMON_H_
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdint.h>
-
-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
-
+++ /dev/null
-/*\r
- * Acess v0.1\r
- * ELF Executable Loader Code\r
- */\r
-#define DEBUG 0\r
-#include <stdlib.h>\r
-#include <stdio.h>\r
-#include <string.h>\r
-#include <unistd.h>\r
-#include "common.h"\r
-#include "elf.h"\r
-\r
-#define DEBUG_WARN 1\r
-\r
-#define MKPTR(_type,_val) ((_type*)(uintptr_t)(_val))\r
-#define PTRMK(_type,_val) MKPTR(_type,_val)\r
-#define PTR(_val) ((void*)(uintptr_t)(_val))\r
-\r
-#if DEBUG\r
-# define ENTER(...)\r
-# define LOG(s, ...) printf("%s: " s, __func__, __VA_ARGS__)\r
-# define LOGS(s) printf("%s: " s, __func__)\r
-# define LEAVE(...)\r
-#else\r
-# define ENTER(...)\r
-# define LOG(...)\r
-# define LOGS(...)\r
-# define LEAVE(...)\r
-#endif\r
-\r
-// === PROTOTYPES ===\r
-void *Elf_Load(FILE *FP);\r
-uintptr_t Elf_Relocate(void *Base);\r
- int Elf_GetSymbol(void *Base, char *Name, uintptr_t *ret);\r
- int Elf_Int_DoRelocate(uint32_t r_info, uint32_t *ptr, uint32_t addend, Elf32_Sym *symtab, void *Base);\r
-uint32_t Elf_Int_HashString(char *str);\r
-\r
-// === CODE ===\r
-void *Elf_Load(FILE *FP)\r
-{\r
- Elf32_Ehdr hdr;\r
- Elf32_Phdr *phtab;\r
- int i, j;\r
- int iPageCount;\r
- uint32_t max, base = -1;\r
- uint32_t addr;\r
- uint32_t baseDiff = 0;\r
- \r
- ENTER("pFP", FP);\r
- \r
- // Read ELF Header\r
- fread(&hdr, sizeof(hdr), 1, FP);\r
- \r
- // Check the file type\r
- if(hdr.ident[0] != 0x7F || hdr.ident[1] != 'E' || hdr.ident[2] != 'L' || hdr.ident[3] != 'F') {\r
- Warning("Non-ELF File was passed to the ELF loader\n");\r
- LEAVE('n');\r
- return NULL;\r
- }\r
- \r
- // Check for a program header\r
- if(hdr.phoff == 0) {\r
- #if DEBUG_WARN\r
- Warning("ELF File does not contain a program header\n");\r
- #endif\r
- LEAVE('n');\r
- return NULL;\r
- }\r
- \r
- // Read Program Header Table\r
- phtab = malloc( sizeof(Elf32_Phdr) * hdr.phentcount );\r
- if( !phtab ) {\r
- LEAVE('n');\r
- return NULL;\r
- }\r
- LOG("hdr.phoff = 0x%08x\n", hdr.phoff);\r
- fseek(FP, hdr.phoff, SEEK_SET);\r
- fread(phtab, sizeof(Elf32_Phdr), hdr.phentcount, FP);\r
- \r
- // Count Pages\r
- iPageCount = 0;\r
- LOG("hdr.phentcount = %i\n", hdr.phentcount);\r
- for( i = 0; i < hdr.phentcount; i++ )\r
- {\r
- // Ignore Non-LOAD types\r
- if(phtab[i].Type != PT_LOAD)\r
- continue;\r
- iPageCount += ((phtab[i].VAddr&0xFFF) + phtab[i].MemSize + 0xFFF) >> 12;\r
- LOG("phtab[%i] = {VAddr:0x%x, MemSize:0x%x}\n", i, phtab[i].VAddr, phtab[i].MemSize);\r
- }\r
- \r
- LOG("iPageCount = %i\n", iPageCount);\r
- \r
- // Allocate Information Structure\r
- //ret = malloc( sizeof(tBinary) + sizeof(tBinaryPage)*iPageCount );\r
- // Fill Info Struct\r
- //ret->Entry = hdr.entrypoint;\r
- //ret->Base = -1; // Set Base to maximum value\r
- //ret->NumPages = iPageCount;\r
- //ret->Interpreter = NULL;\r
-\r
- // Prescan for base and size\r
- for( i = 0; i < hdr.phentcount; i ++)\r
- {\r
- if( phtab[i].Type != PT_LOAD )\r
- continue;\r
- if( phtab[i].VAddr < base )\r
- base = phtab[i].VAddr;\r
- if( phtab[i].VAddr > max )\r
- max = phtab[i].VAddr;\r
- }\r
-\r
- LOG("base = %08x, max = %08x\n", base, max);\r
-\r
- if( base == 0 ) {\r
- // Find a nice space (31 address bits allowed)\r
- base = FindFreeRange( max, 31 );\r
- LOG("new base = %08x\n", base);\r
- if( base == 0 ) return NULL;\r
- baseDiff = base;\r
- }\r
- \r
- // Load Pages\r
- j = 0;\r
- for( i = 0; i < hdr.phentcount; i++ )\r
- {\r
- //LOG("phtab[%i].Type = 0x%x", i, phtab[i].Type);\r
- LOG("phtab[%i] = {\n", i);\r
- LOG(" .Type = 0x%08x\n", phtab[i].Type);\r
- LOG(" .Offset = 0x%08x\n", phtab[i].Offset);\r
- LOG(" .VAddr = 0x%08x\n", phtab[i].VAddr);\r
- LOG(" .PAddr = 0x%08x\n", phtab[i].PAddr);\r
- LOG(" .FileSize = 0x%08x\n", phtab[i].FileSize);\r
- LOG(" .MemSize = 0x%08x\n", phtab[i].MemSize);\r
- LOG(" .Flags = 0x%08x\n", phtab[i].Flags);\r
- LOG(" .Align = 0x%08x\n", phtab[i].Align);\r
- LOGS(" }\n");\r
- // Get Interpreter Name\r
- if( phtab[i].Type == PT_INTERP )\r
- {\r
- char *tmp;\r
- //if(ret->Interpreter) continue;\r
- tmp = malloc(phtab[i].FileSize);\r
- fseek(FP, phtab[i].Offset, SEEK_SET);\r
- fread(tmp, phtab[i].FileSize, 1, FP);\r
- //ret->Interpreter = Binary_RegInterp(tmp);\r
- LOG("Interpreter '%s'\n", tmp);\r
- free(tmp);\r
- continue;\r
- }\r
- // Ignore non-LOAD types\r
- if(phtab[i].Type != PT_LOAD) continue;\r
- \r
- LOG("phtab[%i] = {VAddr:0x%x,Offset:0x%x,FileSize:0x%x}\n",\r
- i, phtab[i].VAddr+baseDiff, phtab[i].Offset, phtab[i].FileSize);\r
- \r
- addr = phtab[i].VAddr + baseDiff;\r
-\r
- if( AllocateMemory( addr, phtab[i].MemSize ) ) {\r
- return NULL;\r
- }\r
- \r
- fseek(FP, phtab[i].Offset, SEEK_SET);\r
- fread( PTRMK(void, addr), phtab[i].FileSize, 1, FP );\r
- memset( PTRMK(char, addr) + phtab[i].FileSize, 0, phtab[i].MemSize - phtab[i].FileSize );\r
- }\r
- \r
- // Clean Up\r
- free(phtab);\r
- // Return\r
- LEAVE('p', base);\r
- return PTRMK(void, base);\r
-}\r
-\r
-// --- ELF RELOCATION ---\r
-/**\r
- * \brief Relocates a loaded ELF Executable\r
- */\r
-uintptr_t Elf_Relocate(void *Base)\r
-{\r
- Elf32_Ehdr *hdr = Base;\r
- Elf32_Phdr *phtab;\r
- int i, j; // Counters\r
- char *libPath;\r
- uint32_t iRealBase = -1;\r
- uintptr_t iBaseDiff;\r
- int iSegmentCount;\r
- int iSymCount = 0;\r
- Elf32_Rel *rel = NULL;\r
- Elf32_Rela *rela = NULL;\r
- uint32_t *pltgot = NULL;\r
- void *plt = NULL;\r
- uint32_t *ptr;\r
- int relSz=0, relEntSz=8;\r
- int relaSz=0, relaEntSz=8;\r
- int pltSz=0, pltType=0;\r
- Elf32_Dyn *dynamicTab = NULL; // Dynamic Table Pointer\r
- char *dynstrtab = NULL; // .dynamic String Table\r
- Elf32_Sym *dynsymtab = NULL;\r
- int bFailed = 0;\r
- \r
- ENTER("pBase", Base);\r
- LOG("Base = %p\n", Base);\r
- \r
- // Parse Program Header to get Dynamic Table\r
- phtab = Base + hdr->phoff;\r
- iSegmentCount = hdr->phentcount;\r
- for(i = 0; i < iSegmentCount; i ++ )\r
- {\r
- // Determine linked base address\r
- if(phtab[i].Type == PT_LOAD && iRealBase > phtab[i].VAddr)\r
- iRealBase = phtab[i].VAddr;\r
- \r
- // Find Dynamic Section\r
- if(phtab[i].Type == PT_DYNAMIC) {\r
- if(dynamicTab) {\r
- Warning("Elf_Relocate - Multiple PT_DYNAMIC segments\n");\r
- continue;\r
- }\r
- dynamicTab = MKPTR(void, phtab[i].VAddr);\r
- j = i; // Save Dynamic Table ID\r
- break;\r
- }\r
- }\r
- \r
- // Check if a PT_DYNAMIC segement was found\r
- if(!dynamicTab) {\r
- Warning("Elf_Relocate: No PT_DYNAMIC segment in image, returning\n");\r
- LEAVE('x', hdr->entrypoint);\r
- return hdr->entrypoint;\r
- }\r
- \r
- // Page Align real base\r
- iRealBase &= ~0xFFF;\r
- \r
- LOG("dynamicTab = %p\n", dynamicTab);\r
- // Adjust "Real" Base\r
- iBaseDiff = (uintptr_t)Base - iRealBase;\r
- LOG("iBaseDiff = %p\n", (void*)iBaseDiff);\r
- // Adjust Dynamic Table\r
- dynamicTab = PTR( (uintptr_t)dynamicTab + iBaseDiff);\r
- LOG("dynamicTab = %p\n", dynamicTab);\r
-\r
- hdr->entrypoint += iBaseDiff;\r
- \r
- // === Get Symbol table and String Table ===\r
- for( j = 0; dynamicTab[j].d_tag != DT_NULL; j++)\r
- {\r
- switch(dynamicTab[j].d_tag)\r
- {\r
- // --- Symbol Table ---\r
- case DT_SYMTAB:\r
- dynamicTab[j].d_val += iBaseDiff;\r
- dynsymtab = PTRMK(void, dynamicTab[j].d_val);\r
- hdr->misc.SymTable = dynamicTab[j].d_val; // Saved in unused bytes of ident\r
- break;\r
- \r
- // --- String Table ---\r
- case DT_STRTAB:\r
- dynamicTab[j].d_val += iBaseDiff;\r
- dynstrtab = PTRMK(void, dynamicTab[j].d_val);\r
- break;\r
- \r
- // --- Hash Table --\r
- case DT_HASH:\r
- dynamicTab[j].d_val += iBaseDiff;\r
- iSymCount = (PTRMK(uint32_t, dynamicTab[j].d_val))[1];\r
- hdr->misc.HashTable = dynamicTab[j].d_val; // Saved in unused bytes of ident\r
- break;\r
- }\r
- }\r
-\r
-\r
- // Alter Symbols to true base\r
- for(i = 0; i < iSymCount; i ++)\r
- {\r
- dynsymtab[i].nameOfs += (uintptr_t)dynstrtab;\r
- if( dynsymtab[i].shndx == SHN_UNDEF )\r
- {\r
- LOG("Sym '%s' = UNDEF\n", MKPTR(char,dynsymtab[i].name));\r
- }\r
- else\r
- {\r
- dynsymtab[i].value += iBaseDiff;\r
- LOG("Sym '%s' = 0x%x (relocated)\n", MKPTR(char,dynsymtab[i].name), dynsymtab[i].value);\r
- }\r
- }\r
- \r
- // === Add to loaded list (can be imported now) ===\r
- Binary_SetReadyToUse( Base );\r
-\r
- // === Parse Relocation Data ===\r
- for( j = 0; dynamicTab[j].d_tag != DT_NULL; j++)\r
- {\r
- switch(dynamicTab[j].d_tag)\r
- {\r
- // --- Shared Library Name ---\r
- case DT_SONAME:\r
- LOG(".so Name '%s'\n", dynstrtab + dynamicTab[j].d_val);\r
- break;\r
- // --- Needed Library ---\r
- case DT_NEEDED:\r
- libPath = dynstrtab + dynamicTab[j].d_val;\r
- Binary_LoadLibrary(libPath);\r
- break;\r
- // --- PLT/GOT ---\r
- case DT_PLTGOT: pltgot = (void*)(iBaseDiff+dynamicTab[j].d_val); break;\r
- case DT_JMPREL: plt = (void*)(iBaseDiff+dynamicTab[j].d_val); break;\r
- case DT_PLTREL: pltType = dynamicTab[j].d_val; break;\r
- case DT_PLTRELSZ: pltSz = dynamicTab[j].d_val; break;\r
- \r
- // --- Relocation ---\r
- case DT_REL: rel = (void*)(iBaseDiff + dynamicTab[j].d_val); break;\r
- case DT_RELSZ: relSz = dynamicTab[j].d_val; break;\r
- case DT_RELENT: relEntSz = dynamicTab[j].d_val; break;\r
- \r
- case DT_RELA: rela = (void*)(iBaseDiff + dynamicTab[j].d_val); break;\r
- case DT_RELASZ: relaSz = dynamicTab[j].d_val; break;\r
- case DT_RELAENT: relaEntSz = dynamicTab[j].d_val; break;\r
- }\r
- }\r
- \r
- // Parse Relocation Entries\r
- if(rel && relSz)\r
- {\r
- j = relSz / relEntSz;\r
- for( i = 0; i < j; i++ )\r
- {\r
- ptr = (void*)(iBaseDiff + rel[i].r_offset);\r
- if( !Elf_Int_DoRelocate(rel[i].r_info, ptr, *ptr, dynsymtab, Base) ) {\r
- bFailed = 1;\r
- }\r
- }\r
- }\r
- // Parse Relocation Entries\r
- if(rela && relaSz)\r
- {\r
- j = relaSz / relaEntSz;\r
- for( i = 0; i < j; i++ )\r
- {\r
- ptr = (void*)(iBaseDiff + rela[i].r_offset);\r
- if( !Elf_Int_DoRelocate(rel[i].r_info, ptr, rela[i].r_addend, dynsymtab, Base) ) {\r
- bFailed = 1;\r
- }\r
- }\r
- }\r
- \r
- // === Process PLT (Procedure Linkage Table) ===\r
- if(plt && pltSz)\r
- {\r
- if(pltType == DT_REL)\r
- {\r
- Elf32_Rel *pltRel = plt;\r
- j = pltSz / sizeof(Elf32_Rel);\r
- LOG("PLT Rel - plt = %p, pltSz = %i (%i ents)\n", plt, pltSz, j);\r
- for(i = 0; i < j; i++)\r
- {\r
- ptr = (void*)(iBaseDiff + pltRel[i].r_offset);\r
- if( !Elf_Int_DoRelocate(pltRel[i].r_info, ptr, *ptr, dynsymtab, Base) ) {\r
- bFailed = 1;\r
- }\r
- }\r
- }\r
- else\r
- {\r
- Elf32_Rela *pltRela = plt;\r
- j = pltSz / sizeof(Elf32_Rela);\r
- LOG("PLT RelA - plt = %p, pltSz = %i (%i ents)\n", plt, pltSz, j);\r
- for(i=0;i<j;i++)\r
- {\r
- ptr = (void*)(iBaseDiff + pltRela[i].r_offset);\r
- if( !Elf_Int_DoRelocate(pltRela[i].r_info, ptr, pltRela[i].r_addend, dynsymtab, Base) ) {\r
- bFailed = 1;\r
- }\r
- }\r
- }\r
- }\r
- \r
- if(bFailed) {\r
- LEAVE('i', 0);\r
- return 0;\r
- }\r
- \r
- LEAVE('x', hdr->entrypoint);\r
- return hdr->entrypoint;\r
-}\r
-\r
-/**\r
- * \fn void Elf_Int_DoRelocate(uint32_t r_info, uint32_t *ptr, uint32_t addend, Elf32_Sym *symtab, void *base)\r
- * \brief Performs a relocation\r
- * \param r_info Field from relocation entry\r
- * \param ptr Pointer to location of relocation\r
- * \param addend Value to add to symbol\r
- * \param symtab Symbol Table\r
- * \param base Base of loaded binary\r
- */\r
-int Elf_Int_DoRelocate(uint32_t r_info, uint32_t *ptr, uint32_t addend, Elf32_Sym *symtab, void *base)\r
-{\r
- uintptr_t val;\r
- int type = ELF32_R_TYPE(r_info);\r
- int sym = ELF32_R_SYM(r_info);\r
- char *sSymName = PTRMK(char, symtab[sym].name);\r
- \r
- //LogF("Elf_Int_DoRelocate: (r_info=0x%x, ptr=0x%x, addend=0x%x, .., base=0x%x)\n",\r
- // r_info, ptr, addend, base);\r
- \r
- switch( type )\r
- {\r
- // Standard 32 Bit Relocation (S+A)\r
- case R_386_32:\r
- if( !Elf_GetSymbol( base, sSymName, &val ) && !Binary_GetSymbol( sSymName, &val ) ) {\r
- Warning("Unable to find symbol '%s'", sSymName);\r
- return 0;\r
- }\r
- LOG("%08x R_386_32 *%p += %p('%s')\n", r_info, ptr, (void*)val, sSymName);\r
- *ptr = val + addend;\r
- break;\r
- \r
- // 32 Bit Relocation wrt. Offset (S+A-P)\r
- case R_386_PC32:\r
- if( !Elf_GetSymbol( base, sSymName, &val ) && !Binary_GetSymbol( sSymName, &val ) ) {\r
- Warning("Unable to find symbol '%s'", sSymName);\r
- return 0;\r
- }\r
- LOG("%08x R_386_PC32 *%p = 0x%x + %p('%s') - %p\n", r_info, ptr, *ptr, (void*)val, sSymName, ptr );\r
- // TODO: Check if it needs the true value of ptr or the compiled value\r
- // NOTE: Testing using true value\r
- *ptr = val + addend - (uintptr_t)ptr;\r
- break;\r
-\r
- // Absolute Value of a symbol (S)\r
- case R_386_GLOB_DAT:\r
- if( !Elf_GetSymbol( base, sSymName, &val ) && !Binary_GetSymbol( sSymName, &val ) ) {\r
- Warning("Unable to find symbol '%s'", sSymName);\r
- return 0; \r
- }\r
- LOG("%08x R_386_GLOB_DAT *%p = 0x%x(%s)\n", r_info, ptr, (unsigned int)val, sSymName);\r
- *ptr = val;\r
- break;\r
- \r
- // Absolute Value of a symbol (S)\r
- case R_386_JMP_SLOT:\r
- if( !Elf_GetSymbol( base, sSymName, &val ) && !Binary_GetSymbol( sSymName, &val ) ) {\r
- Warning("Unable to find symbol '%s'", sSymName);\r
- return 0;\r
- }\r
- LOG("%08x R_386_JMP_SLOT *%p = 0x%x (%s)\n", r_info, ptr, (unsigned int)val, sSymName);\r
- *ptr = val;\r
- break;\r
-\r
- // Base Address (B+A)\r
- case R_386_RELATIVE:\r
- LOG("%08x R_386_RELATIVE *%p = %p + 0x%x\n", r_info, ptr, base, addend);\r
- *ptr = (uintptr_t)base + addend;\r
- break;\r
- \r
- default:\r
- LOG("Rel %p: 0x%x,%i\n", ptr, sym, type);\r
- break;\r
- }\r
- return 1;\r
-}\r
-\r
-/**\r
- * \fn int Elf_GetSymbol(void *Base, char *name, uintptr_t *ret)\r
- * \brief Get a symbol from the loaded binary\r
- */\r
-int Elf_GetSymbol(void *Base, char *Name, uintptr_t *ret)\r
-{\r
- Elf32_Ehdr *hdr = (void*)Base;\r
- Elf32_Sym *symtab;\r
- int nbuckets = 0;\r
- int iSymCount = 0;\r
- int i;\r
- uint32_t *pBuckets;\r
- uint32_t *pChains;\r
- uint32_t iNameHash;\r
-\r
- if(!Base) return 0;\r
-\r
- pBuckets = PTR(hdr->misc.HashTable);\r
- symtab = PTR(hdr->misc.SymTable);\r
- \r
- nbuckets = pBuckets[0];\r
- iSymCount = pBuckets[1];\r
- pBuckets = &pBuckets[2];\r
- pChains = &pBuckets[ nbuckets ];\r
- \r
- // Get hash\r
- iNameHash = Elf_Int_HashString(Name);\r
- iNameHash %= nbuckets;\r
-\r
- // Check Bucket\r
- i = pBuckets[ iNameHash ];\r
- if(symtab[i].shndx != SHN_UNDEF && strcmp(MKPTR(char,symtab[i].name), Name) == 0) {\r
- if(ret) *ret = symtab[ i ].value;\r
- return 1;\r
- }\r
- \r
- // Walk Chain\r
- while(pChains[i] != STN_UNDEF)\r
- {\r
- i = pChains[i];\r
- if(symtab[i].shndx != SHN_UNDEF && strcmp(MKPTR(char,symtab[i].name), Name) == 0) {\r
- if(ret) *ret = symtab[ i ].value;\r
- return 1;\r
- }\r
- }\r
- return 0;\r
-}\r
-\r
-/**\r
- * \fn uint32_t Elf_Int_HashString(char *str)\r
- * \brief Hash a string in the ELF format\r
- * \param str String to hash\r
- * \return Hash value\r
- */\r
-uint32_t Elf_Int_HashString(char *str)\r
-{\r
- uint32_t h = 0, g;\r
- while(*str)\r
- {\r
- h = (h << 4) + *str++;\r
- if( (g = h & 0xf0000000) )\r
- h ^= g >> 24;\r
- h &= ~g;\r
- }\r
- return h;\r
-}\r
+++ /dev/null
-/**\r
- * \file elf.h\r
- * \brief ELF Exeutable Loader\r
- */\r
-#ifndef _BIN_ELF_H\r
-#define _BIN_ELF_H\r
-\r
-#include <stdint.h>\r
-\r
-/**\r
- * \brief ELF File Header\r
- */\r
-struct sElf32_Ehdr\r
-{\r
- union {\r
- char ident[16]; //!< Identifier Bytes\r
- struct {\r
- uint32_t Ident1;\r
- uint32_t Ident2;\r
- uint32_t HashTable;\r
- uint32_t SymTable;\r
- } misc;\r
- };\r
- uint16_t filetype; //!< File Type\r
- uint16_t machine; //!< Machine / Arch\r
- uint32_t version; //!< Version (File?)\r
- uint32_t entrypoint; //!< Entry Point\r
- uint32_t phoff; //!< Program Header Offset\r
- uint32_t shoff; //!< Section Header Offset\r
- uint32_t flags; //!< Flags\r
- uint16_t headersize; //!< Header Size\r
- uint16_t phentsize; //!< Program Header Entry Size\r
- uint16_t phentcount; //!< Program Header Entry Count\r
- uint16_t shentsize; //!< Section Header Entry Size\r
- uint16_t shentcount; //!< Section Header Entry Count\r
- uint16_t shstrindex; //!< Section Header String Table Index\r
-} __attribute__ ((packed));\r
-\r
-/**\r
- * \brief Executable Types\r
- */\r
-enum eElf32_ExecTypes\r
-{\r
- ET_NONE = 0, //!< NULL Type\r
- ET_REL = 1, //!< Relocatable (Object)\r
- ET_EXEC = 2, //!< Executable\r
- ET_DYN = 3, //!< Dynamic Library\r
- ET_CORE = 4, //!< Core?\r
- ET_LOPROC = 0xFF00, //!< Low Impl Defined\r
- ET_HIPROC = 0xFFFF //!< High Impl Defined\r
-};\r
-\r
-/**\r
- \name Section IDs\r
- \{\r
-*/\r
-#define SHN_UNDEF 0 //!< Undefined Section\r
-#define SHN_LORESERVE 0xFF00 //!< Low Reserved\r
-#define SHN_LOPROC 0xFF00 //!< Low Impl Defined\r
-#define SHN_HIPROC 0xFF1F //!< High Impl Defined\r
-#define SHN_ABS 0xFFF1 //!< Absolute Address (Base: 0, Size: -1)\r
-#define SHN_COMMON 0xFFF2 //!< Common\r
-#define SHN_HIRESERVE 0xFFFF //!< High Reserved\r
-//! \}\r
-\r
-/**\r
- \enum eElfSectionTypes\r
- \brief ELF Section Types\r
-*/\r
-enum eElfSectionTypes {\r
- SHT_NULL, //0\r
- SHT_PROGBITS, //1\r
- SHT_SYMTAB, //2\r
- SHT_STRTAB, //3\r
- SHT_RELA, //4\r
- SHT_HASH, //5\r
- SHT_DYNAMIC, //6\r
- SHT_NOTE, //7\r
- SHT_NOBITS, //8\r
- SHT_REL, //9\r
- SHT_SHLIB, //A\r
- SHT_DYNSYM, //B\r
- SHT_LAST, //C\r
- SHT_LOPROC = 0x70000000,\r
- SHT_HIPROC = 0x7fffffff,\r
- SHT_LOUSER = 0x80000000,\r
- SHT_HIUSER = 0xffffffff\r
-};\r
-\r
-#define SHF_WRITE 0x1\r
-#define SHF_ALLOC 0x2\r
-#define SHF_EXECINSTR 0x4\r
-#define SHF_MASKPROC 0xf0000000\r
-\r
-struct sElf32_Shent {\r
- uint32_t name;\r
- uint32_t type;\r
- uint32_t flags;\r
- uint32_t address;\r
- uint32_t offset;\r
- uint32_t size;\r
- uint32_t link;\r
- uint32_t info;\r
- uint32_t addralign;\r
- uint32_t entsize;\r
-} __attribute__ ((packed)); //sizeof = 40\r
-\r
-struct elf_sym_s {\r
- union {\r
- uint32_t nameOfs;\r
- uint32_t name;\r
- };\r
- uint32_t value; //Address\r
- uint32_t size;\r
- uint8_t info;\r
- uint8_t other;\r
- uint16_t shndx;\r
-} __attribute__ ((packed));\r
-#define STN_UNDEF 0 // Undefined Symbol\r
-\r
-enum {\r
- PT_NULL, //0\r
- PT_LOAD, //1\r
- PT_DYNAMIC, //2\r
- PT_INTERP, //3\r
- PT_NOTE, //4\r
- PT_SHLIB, //5\r
- PT_PHDR, //6\r
- PT_LOPROC = 0x70000000,\r
- PT_HIPROC = 0x7fffffff\r
-};\r
-\r
-struct sElf32_Phdr {\r
- uint32_t Type;\r
- uint32_t Offset;\r
- uint32_t VAddr;\r
- uint32_t PAddr;\r
- uint32_t FileSize;\r
- uint32_t MemSize;\r
- uint32_t Flags;\r
- uint32_t Align;\r
-} __attribute__ ((packed));\r
-\r
-struct elf32_rel_s {\r
- uint32_t r_offset;\r
- uint32_t r_info;\r
-} __attribute__ ((packed));\r
-\r
-struct elf32_rela_s {\r
- uint32_t r_offset;\r
- uint32_t r_info;\r
- int32_t r_addend;\r
-} __attribute__ ((packed));\r
-\r
-enum {\r
- R_386_NONE = 0, // none\r
- R_386_32, // S+A\r
- R_386_PC32, // S+A-P\r
- R_386_GOT32, // G+A-P\r
- R_386_PLT32, // L+A-P\r
- R_386_COPY, // none\r
- R_386_GLOB_DAT, // S\r
- R_386_JMP_SLOT, // S\r
- R_386_RELATIVE, // B+A\r
- R_386_GOTOFF, // S+A-GOT\r
- R_386_GOTPC, // GOT+A-P\r
- R_386_LAST // none\r
-};\r
-\r
-#define ELF32_R_SYM(i) ((i)>>8) // Takes an info value and returns a symbol index\r
-#define ELF32_R_TYPE(i) ((i)&0xFF) // Takes an info value and returns a type\r
-#define ELF32_R_INFO(s,t) (((s)<<8)+((t)&0xFF)) // Takes a type and symbol index and returns an info value\r
-\r
-struct elf32_dyn_s {\r
- uint32_t d_tag;\r
- uint32_t d_val; //Also d_ptr\r
-} __attribute__ ((packed));\r
-\r
-enum {\r
- DT_NULL, //!< Marks End of list\r
- DT_NEEDED, //!< Offset in strtab to needed library\r
- DT_PLTRELSZ, //!< Size in bytes of PLT\r
- DT_PLTGOT, //!< Address of PLT/GOT\r
- DT_HASH, //!< Address of symbol hash table\r
- DT_STRTAB, //!< String Table address\r
- DT_SYMTAB, //!< Symbol Table address\r
- DT_RELA, //!< Relocation table address\r
- DT_RELASZ, //!< Size of relocation table\r
- DT_RELAENT, //!< Size of entry in relocation table\r
- DT_STRSZ, //!< Size of string table\r
- DT_SYMENT, //!< Size of symbol table entry\r
- DT_INIT, //!< Address of initialisation function\r
- DT_FINI, //!< Address of termination function\r
- DT_SONAME, //!< String table offset of so name\r
- DT_RPATH, //!< String table offset of library path\r
- DT_SYMBOLIC,//!< Reverse order of symbol searching for library, search libs first then executable\r
- DT_REL, //!< Relocation Entries (Elf32_Rel instead of Elf32_Rela)\r
- DT_RELSZ, //!< Size of above table (bytes)\r
- DT_RELENT, //!< Size of entry in above table\r
- DT_PLTREL, //!< Relocation entry of PLT\r
- DT_DEBUG, //!< Debugging Entry - Unknown contents\r
- DT_TEXTREL, //!< Indicates that modifcations to a non-writeable segment may occur\r
- DT_JMPREL, //!< Address of PLT only relocation entries\r
- DT_LOPROC = 0x70000000, //!< Low Definable\r
- DT_HIPROC = 0x7FFFFFFF //!< High Definable\r
-};\r
-\r
-typedef struct sElf32_Ehdr Elf32_Ehdr;\r
-typedef struct sElf32_Phdr Elf32_Phdr;\r
-typedef struct sElf32_Shent Elf32_Shent;\r
-typedef struct elf_sym_s elf_symtab;\r
-typedef struct elf_sym_s Elf32_Sym;\r
-typedef struct elf32_rel_s Elf32_Rel;\r
-typedef struct elf32_rela_s Elf32_Rela;\r
-typedef struct elf32_dyn_s Elf32_Dyn;\r
-\r
-#endif // defined(_EXE_ELF_H)\r
+++ /dev/null
-/*
- */
-#include "common.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdarg.h>
-
-// === 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 <executable> [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");
-}
-
+++ /dev/null
-/*
- */
-#include "common.h"
-#include <stdio.h>
-#include <stdlib.h>
-#if __WIN32__
-# include <windows.h>
-#else
-# include <sys/mman.h>
-# include <errno.h>
-#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
-}
+++ /dev/null
-/*
- */
-#include <stdlib.h>
-#include <string.h>
-#include <stdio.h>
-#ifdef __WIN32__
-# include <windows.h>
-# include <winsock.h>
-#else
-# include <unistd.h>
-# include <sys/socket.h>
-# include <netinet/in.h>
-#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;
-}
+++ /dev/null
-/*
- * 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
+++ /dev/null
-/*
- */
-#include "../../Usermode/include/acess/sys.h"
-#include "common.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <stdarg.h>
-#include <string.h>
-#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)
- * <I: Output long integer
- * <d: Output Buffer (Preceded by valid size)
- * ?d: Bi-directional buffer (Preceded by valid size), buffer contents
- * are returned
- */
-int _Syscall(const char *ArgTypes, ...)
-{
- va_list args;
- int outCount = 0;
- int inCount = 0;
- const char *str;
-
- tOutValue **output;
- tInValue **input;
-
- // Get data size
- va_start(args, ArgTypes);
- str = ArgTypes;
- while(*str)
- {
- int dir;
-
- str = ReadEntry(NULL, NULL, &dir, str, args);
- if( !str ) break;
-
- // Out!
- if( dir & 1 ) outCount ++;
-
- // and.. In!
- if( dir & 2 ) inCount ++;
- }
- va_end(args);
-
- // Allocate buffers
- output = malloc( outCount*sizeof(tOutValue*) );
- input = malloc( inCount*sizeof(tInValue*) );
-
- // - re-zero so they can be used as indicies
- outCount = 0;
- inCount = 0;
-
- // Fill `output` and `input`
- va_start(args, ArgTypes);
- str = ArgTypes;
- while(*str)
- {
- tOutValue *outParam;
- tInValue *inParam;
- int dir;
-
- str = ReadEntry(&outParam, &inParam, &dir, str, args);
- if( !str ) break;
-
- if( dir & 1 )
- output[outCount++] = outParam;
- if( dir & 2 )
- input[inCount++] = inParam;
- }
- va_end(args);
-
- // Send syscall request
-
-
- // Clean up
- while(outCount--) free(output[outCount]);
- free(output);
- while(inCount--) free(input[inCount]);
- free(input);
-
- return 0;
-}
-
-// --- VFS Calls
-int open(const char *Path, int Flags) {
- return _Syscall(">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 <d", FD, Bytes, Bytes, Dest);
-}
-
-size_t write(int FD, size_t Bytes, void *Src) {
- return _Syscall(">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 >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 <d >i", fd, maxacls*sizeof(t_sysFInfo), info, maxacls);
-}
-
-int readdir(int fd, char *dest) {
- return _Syscall(">i <s", fd, dest);
-}
-
-int _SysOpenChild(int fd, char *name, int flags) {
- return _Syscall(">i >s >i", fd, name, flags);
-}
-
-int _SysGetACL(int fd, t_sysACL *dest) {
- return _Syscall(">i <d", fd, sizeof(t_sysACL), dest);
-}
-
-int _SysMount(const char *Device, const char *Directory, const char *Type, const char *Options) {
- return _Syscall(">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]);
-
--- /dev/null
+#
+#
+
+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' > $@
+
--- /dev/null
+/*
+ * AcessNative
+ */
+#include "common.h"
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#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;
+}
--- /dev/null
+/*
+ */
+#ifndef _COMMON_H_
+#define _COMMON_H_
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+
+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
+
--- /dev/null
+/*\r
+ * Acess v0.1\r
+ * ELF Executable Loader Code\r
+ */\r
+#define DEBUG 0\r
+#include <stdlib.h>\r
+#include <stdio.h>\r
+#include <string.h>\r
+#include <unistd.h>\r
+#include "common.h"\r
+#include "elf.h"\r
+\r
+#define DEBUG_WARN 1\r
+\r
+#define MKPTR(_type,_val) ((_type*)(uintptr_t)(_val))\r
+#define PTRMK(_type,_val) MKPTR(_type,_val)\r
+#define PTR(_val) ((void*)(uintptr_t)(_val))\r
+\r
+#if DEBUG\r
+# define ENTER(...)\r
+# define LOG(s, ...) printf("%s: " s, __func__, __VA_ARGS__)\r
+# define LOGS(s) printf("%s: " s, __func__)\r
+# define LEAVE(...)\r
+#else\r
+# define ENTER(...)\r
+# define LOG(...)\r
+# define LOGS(...)\r
+# define LEAVE(...)\r
+#endif\r
+\r
+// === PROTOTYPES ===\r
+void *Elf_Load(FILE *FP);\r
+uintptr_t Elf_Relocate(void *Base);\r
+ int Elf_GetSymbol(void *Base, char *Name, uintptr_t *ret);\r
+ int Elf_Int_DoRelocate(uint32_t r_info, uint32_t *ptr, uint32_t addend, Elf32_Sym *symtab, void *Base);\r
+uint32_t Elf_Int_HashString(char *str);\r
+\r
+// === CODE ===\r
+void *Elf_Load(FILE *FP)\r
+{\r
+ Elf32_Ehdr hdr;\r
+ Elf32_Phdr *phtab;\r
+ int i, j;\r
+ int iPageCount;\r
+ uint32_t max, base = -1;\r
+ uint32_t addr;\r
+ uint32_t baseDiff = 0;\r
+ \r
+ ENTER("pFP", FP);\r
+ \r
+ // Read ELF Header\r
+ fread(&hdr, sizeof(hdr), 1, FP);\r
+ \r
+ // Check the file type\r
+ if(hdr.ident[0] != 0x7F || hdr.ident[1] != 'E' || hdr.ident[2] != 'L' || hdr.ident[3] != 'F') {\r
+ Warning("Non-ELF File was passed to the ELF loader\n");\r
+ LEAVE('n');\r
+ return NULL;\r
+ }\r
+ \r
+ // Check for a program header\r
+ if(hdr.phoff == 0) {\r
+ #if DEBUG_WARN\r
+ Warning("ELF File does not contain a program header\n");\r
+ #endif\r
+ LEAVE('n');\r
+ return NULL;\r
+ }\r
+ \r
+ // Read Program Header Table\r
+ phtab = malloc( sizeof(Elf32_Phdr) * hdr.phentcount );\r
+ if( !phtab ) {\r
+ LEAVE('n');\r
+ return NULL;\r
+ }\r
+ LOG("hdr.phoff = 0x%08x\n", hdr.phoff);\r
+ fseek(FP, hdr.phoff, SEEK_SET);\r
+ fread(phtab, sizeof(Elf32_Phdr), hdr.phentcount, FP);\r
+ \r
+ // Count Pages\r
+ iPageCount = 0;\r
+ LOG("hdr.phentcount = %i\n", hdr.phentcount);\r
+ for( i = 0; i < hdr.phentcount; i++ )\r
+ {\r
+ // Ignore Non-LOAD types\r
+ if(phtab[i].Type != PT_LOAD)\r
+ continue;\r
+ iPageCount += ((phtab[i].VAddr&0xFFF) + phtab[i].MemSize + 0xFFF) >> 12;\r
+ LOG("phtab[%i] = {VAddr:0x%x, MemSize:0x%x}\n", i, phtab[i].VAddr, phtab[i].MemSize);\r
+ }\r
+ \r
+ LOG("iPageCount = %i\n", iPageCount);\r
+ \r
+ // Allocate Information Structure\r
+ //ret = malloc( sizeof(tBinary) + sizeof(tBinaryPage)*iPageCount );\r
+ // Fill Info Struct\r
+ //ret->Entry = hdr.entrypoint;\r
+ //ret->Base = -1; // Set Base to maximum value\r
+ //ret->NumPages = iPageCount;\r
+ //ret->Interpreter = NULL;\r
+\r
+ // Prescan for base and size\r
+ for( i = 0; i < hdr.phentcount; i ++)\r
+ {\r
+ if( phtab[i].Type != PT_LOAD )\r
+ continue;\r
+ if( phtab[i].VAddr < base )\r
+ base = phtab[i].VAddr;\r
+ if( phtab[i].VAddr > max )\r
+ max = phtab[i].VAddr;\r
+ }\r
+\r
+ LOG("base = %08x, max = %08x\n", base, max);\r
+\r
+ if( base == 0 ) {\r
+ // Find a nice space (31 address bits allowed)\r
+ base = FindFreeRange( max, 31 );\r
+ LOG("new base = %08x\n", base);\r
+ if( base == 0 ) return NULL;\r
+ baseDiff = base;\r
+ }\r
+ \r
+ // Load Pages\r
+ j = 0;\r
+ for( i = 0; i < hdr.phentcount; i++ )\r
+ {\r
+ //LOG("phtab[%i].Type = 0x%x", i, phtab[i].Type);\r
+ LOG("phtab[%i] = {\n", i);\r
+ LOG(" .Type = 0x%08x\n", phtab[i].Type);\r
+ LOG(" .Offset = 0x%08x\n", phtab[i].Offset);\r
+ LOG(" .VAddr = 0x%08x\n", phtab[i].VAddr);\r
+ LOG(" .PAddr = 0x%08x\n", phtab[i].PAddr);\r
+ LOG(" .FileSize = 0x%08x\n", phtab[i].FileSize);\r
+ LOG(" .MemSize = 0x%08x\n", phtab[i].MemSize);\r
+ LOG(" .Flags = 0x%08x\n", phtab[i].Flags);\r
+ LOG(" .Align = 0x%08x\n", phtab[i].Align);\r
+ LOGS(" }\n");\r
+ // Get Interpreter Name\r
+ if( phtab[i].Type == PT_INTERP )\r
+ {\r
+ char *tmp;\r
+ //if(ret->Interpreter) continue;\r
+ tmp = malloc(phtab[i].FileSize);\r
+ fseek(FP, phtab[i].Offset, SEEK_SET);\r
+ fread(tmp, phtab[i].FileSize, 1, FP);\r
+ //ret->Interpreter = Binary_RegInterp(tmp);\r
+ LOG("Interpreter '%s'\n", tmp);\r
+ free(tmp);\r
+ continue;\r
+ }\r
+ // Ignore non-LOAD types\r
+ if(phtab[i].Type != PT_LOAD) continue;\r
+ \r
+ LOG("phtab[%i] = {VAddr:0x%x,Offset:0x%x,FileSize:0x%x}\n",\r
+ i, phtab[i].VAddr+baseDiff, phtab[i].Offset, phtab[i].FileSize);\r
+ \r
+ addr = phtab[i].VAddr + baseDiff;\r
+\r
+ if( AllocateMemory( addr, phtab[i].MemSize ) ) {\r
+ return NULL;\r
+ }\r
+ \r
+ fseek(FP, phtab[i].Offset, SEEK_SET);\r
+ fread( PTRMK(void, addr), phtab[i].FileSize, 1, FP );\r
+ memset( PTRMK(char, addr) + phtab[i].FileSize, 0, phtab[i].MemSize - phtab[i].FileSize );\r
+ }\r
+ \r
+ // Clean Up\r
+ free(phtab);\r
+ // Return\r
+ LEAVE('p', base);\r
+ return PTRMK(void, base);\r
+}\r
+\r
+// --- ELF RELOCATION ---\r
+/**\r
+ * \brief Relocates a loaded ELF Executable\r
+ */\r
+uintptr_t Elf_Relocate(void *Base)\r
+{\r
+ Elf32_Ehdr *hdr = Base;\r
+ Elf32_Phdr *phtab;\r
+ int i, j; // Counters\r
+ char *libPath;\r
+ uint32_t iRealBase = -1;\r
+ uintptr_t iBaseDiff;\r
+ int iSegmentCount;\r
+ int iSymCount = 0;\r
+ Elf32_Rel *rel = NULL;\r
+ Elf32_Rela *rela = NULL;\r
+ uint32_t *pltgot = NULL;\r
+ void *plt = NULL;\r
+ uint32_t *ptr;\r
+ int relSz=0, relEntSz=8;\r
+ int relaSz=0, relaEntSz=8;\r
+ int pltSz=0, pltType=0;\r
+ Elf32_Dyn *dynamicTab = NULL; // Dynamic Table Pointer\r
+ char *dynstrtab = NULL; // .dynamic String Table\r
+ Elf32_Sym *dynsymtab = NULL;\r
+ int bFailed = 0;\r
+ \r
+ ENTER("pBase", Base);\r
+ LOG("Base = %p\n", Base);\r
+ \r
+ // Parse Program Header to get Dynamic Table\r
+ phtab = Base + hdr->phoff;\r
+ iSegmentCount = hdr->phentcount;\r
+ for(i = 0; i < iSegmentCount; i ++ )\r
+ {\r
+ // Determine linked base address\r
+ if(phtab[i].Type == PT_LOAD && iRealBase > phtab[i].VAddr)\r
+ iRealBase = phtab[i].VAddr;\r
+ \r
+ // Find Dynamic Section\r
+ if(phtab[i].Type == PT_DYNAMIC) {\r
+ if(dynamicTab) {\r
+ Warning("Elf_Relocate - Multiple PT_DYNAMIC segments\n");\r
+ continue;\r
+ }\r
+ dynamicTab = MKPTR(void, phtab[i].VAddr);\r
+ j = i; // Save Dynamic Table ID\r
+ break;\r
+ }\r
+ }\r
+ \r
+ // Check if a PT_DYNAMIC segement was found\r
+ if(!dynamicTab) {\r
+ Warning("Elf_Relocate: No PT_DYNAMIC segment in image, returning\n");\r
+ LEAVE('x', hdr->entrypoint);\r
+ return hdr->entrypoint;\r
+ }\r
+ \r
+ // Page Align real base\r
+ iRealBase &= ~0xFFF;\r
+ \r
+ LOG("dynamicTab = %p\n", dynamicTab);\r
+ // Adjust "Real" Base\r
+ iBaseDiff = (uintptr_t)Base - iRealBase;\r
+ LOG("iBaseDiff = %p\n", (void*)iBaseDiff);\r
+ // Adjust Dynamic Table\r
+ dynamicTab = PTR( (uintptr_t)dynamicTab + iBaseDiff);\r
+ LOG("dynamicTab = %p\n", dynamicTab);\r
+\r
+ hdr->entrypoint += iBaseDiff;\r
+ \r
+ // === Get Symbol table and String Table ===\r
+ for( j = 0; dynamicTab[j].d_tag != DT_NULL; j++)\r
+ {\r
+ switch(dynamicTab[j].d_tag)\r
+ {\r
+ // --- Symbol Table ---\r
+ case DT_SYMTAB:\r
+ dynamicTab[j].d_val += iBaseDiff;\r
+ dynsymtab = PTRMK(void, dynamicTab[j].d_val);\r
+ hdr->misc.SymTable = dynamicTab[j].d_val; // Saved in unused bytes of ident\r
+ break;\r
+ \r
+ // --- String Table ---\r
+ case DT_STRTAB:\r
+ dynamicTab[j].d_val += iBaseDiff;\r
+ dynstrtab = PTRMK(void, dynamicTab[j].d_val);\r
+ break;\r
+ \r
+ // --- Hash Table --\r
+ case DT_HASH:\r
+ dynamicTab[j].d_val += iBaseDiff;\r
+ iSymCount = (PTRMK(uint32_t, dynamicTab[j].d_val))[1];\r
+ hdr->misc.HashTable = dynamicTab[j].d_val; // Saved in unused bytes of ident\r
+ break;\r
+ }\r
+ }\r
+\r
+\r
+ // Alter Symbols to true base\r
+ for(i = 0; i < iSymCount; i ++)\r
+ {\r
+ dynsymtab[i].nameOfs += (uintptr_t)dynstrtab;\r
+ if( dynsymtab[i].shndx == SHN_UNDEF )\r
+ {\r
+ LOG("Sym '%s' = UNDEF\n", MKPTR(char,dynsymtab[i].name));\r
+ }\r
+ else\r
+ {\r
+ dynsymtab[i].value += iBaseDiff;\r
+ LOG("Sym '%s' = 0x%x (relocated)\n", MKPTR(char,dynsymtab[i].name), dynsymtab[i].value);\r
+ }\r
+ }\r
+ \r
+ // === Add to loaded list (can be imported now) ===\r
+ Binary_SetReadyToUse( Base );\r
+\r
+ // === Parse Relocation Data ===\r
+ for( j = 0; dynamicTab[j].d_tag != DT_NULL; j++)\r
+ {\r
+ switch(dynamicTab[j].d_tag)\r
+ {\r
+ // --- Shared Library Name ---\r
+ case DT_SONAME:\r
+ LOG(".so Name '%s'\n", dynstrtab + dynamicTab[j].d_val);\r
+ break;\r
+ // --- Needed Library ---\r
+ case DT_NEEDED:\r
+ libPath = dynstrtab + dynamicTab[j].d_val;\r
+ Binary_LoadLibrary(libPath);\r
+ break;\r
+ // --- PLT/GOT ---\r
+ case DT_PLTGOT: pltgot = (void*)(iBaseDiff+dynamicTab[j].d_val); break;\r
+ case DT_JMPREL: plt = (void*)(iBaseDiff+dynamicTab[j].d_val); break;\r
+ case DT_PLTREL: pltType = dynamicTab[j].d_val; break;\r
+ case DT_PLTRELSZ: pltSz = dynamicTab[j].d_val; break;\r
+ \r
+ // --- Relocation ---\r
+ case DT_REL: rel = (void*)(iBaseDiff + dynamicTab[j].d_val); break;\r
+ case DT_RELSZ: relSz = dynamicTab[j].d_val; break;\r
+ case DT_RELENT: relEntSz = dynamicTab[j].d_val; break;\r
+ \r
+ case DT_RELA: rela = (void*)(iBaseDiff + dynamicTab[j].d_val); break;\r
+ case DT_RELASZ: relaSz = dynamicTab[j].d_val; break;\r
+ case DT_RELAENT: relaEntSz = dynamicTab[j].d_val; break;\r
+ }\r
+ }\r
+ \r
+ // Parse Relocation Entries\r
+ if(rel && relSz)\r
+ {\r
+ j = relSz / relEntSz;\r
+ for( i = 0; i < j; i++ )\r
+ {\r
+ ptr = (void*)(iBaseDiff + rel[i].r_offset);\r
+ if( !Elf_Int_DoRelocate(rel[i].r_info, ptr, *ptr, dynsymtab, Base) ) {\r
+ bFailed = 1;\r
+ }\r
+ }\r
+ }\r
+ // Parse Relocation Entries\r
+ if(rela && relaSz)\r
+ {\r
+ j = relaSz / relaEntSz;\r
+ for( i = 0; i < j; i++ )\r
+ {\r
+ ptr = (void*)(iBaseDiff + rela[i].r_offset);\r
+ if( !Elf_Int_DoRelocate(rel[i].r_info, ptr, rela[i].r_addend, dynsymtab, Base) ) {\r
+ bFailed = 1;\r
+ }\r
+ }\r
+ }\r
+ \r
+ // === Process PLT (Procedure Linkage Table) ===\r
+ if(plt && pltSz)\r
+ {\r
+ if(pltType == DT_REL)\r
+ {\r
+ Elf32_Rel *pltRel = plt;\r
+ j = pltSz / sizeof(Elf32_Rel);\r
+ LOG("PLT Rel - plt = %p, pltSz = %i (%i ents)\n", plt, pltSz, j);\r
+ for(i = 0; i < j; i++)\r
+ {\r
+ ptr = (void*)(iBaseDiff + pltRel[i].r_offset);\r
+ if( !Elf_Int_DoRelocate(pltRel[i].r_info, ptr, *ptr, dynsymtab, Base) ) {\r
+ bFailed = 1;\r
+ }\r
+ }\r
+ }\r
+ else\r
+ {\r
+ Elf32_Rela *pltRela = plt;\r
+ j = pltSz / sizeof(Elf32_Rela);\r
+ LOG("PLT RelA - plt = %p, pltSz = %i (%i ents)\n", plt, pltSz, j);\r
+ for(i=0;i<j;i++)\r
+ {\r
+ ptr = (void*)(iBaseDiff + pltRela[i].r_offset);\r
+ if( !Elf_Int_DoRelocate(pltRela[i].r_info, ptr, pltRela[i].r_addend, dynsymtab, Base) ) {\r
+ bFailed = 1;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ \r
+ if(bFailed) {\r
+ LEAVE('i', 0);\r
+ return 0;\r
+ }\r
+ \r
+ LEAVE('x', hdr->entrypoint);\r
+ return hdr->entrypoint;\r
+}\r
+\r
+/**\r
+ * \fn void Elf_Int_DoRelocate(uint32_t r_info, uint32_t *ptr, uint32_t addend, Elf32_Sym *symtab, void *base)\r
+ * \brief Performs a relocation\r
+ * \param r_info Field from relocation entry\r
+ * \param ptr Pointer to location of relocation\r
+ * \param addend Value to add to symbol\r
+ * \param symtab Symbol Table\r
+ * \param base Base of loaded binary\r
+ */\r
+int Elf_Int_DoRelocate(uint32_t r_info, uint32_t *ptr, uint32_t addend, Elf32_Sym *symtab, void *base)\r
+{\r
+ uintptr_t val;\r
+ int type = ELF32_R_TYPE(r_info);\r
+ int sym = ELF32_R_SYM(r_info);\r
+ char *sSymName = PTRMK(char, symtab[sym].name);\r
+ \r
+ //LogF("Elf_Int_DoRelocate: (r_info=0x%x, ptr=0x%x, addend=0x%x, .., base=0x%x)\n",\r
+ // r_info, ptr, addend, base);\r
+ \r
+ switch( type )\r
+ {\r
+ // Standard 32 Bit Relocation (S+A)\r
+ case R_386_32:\r
+ if( !Elf_GetSymbol( base, sSymName, &val ) && !Binary_GetSymbol( sSymName, &val ) ) {\r
+ Warning("Unable to find symbol '%s'", sSymName);\r
+ return 0;\r
+ }\r
+ LOG("%08x R_386_32 *%p += %p('%s')\n", r_info, ptr, (void*)val, sSymName);\r
+ *ptr = val + addend;\r
+ break;\r
+ \r
+ // 32 Bit Relocation wrt. Offset (S+A-P)\r
+ case R_386_PC32:\r
+ if( !Elf_GetSymbol( base, sSymName, &val ) && !Binary_GetSymbol( sSymName, &val ) ) {\r
+ Warning("Unable to find symbol '%s'", sSymName);\r
+ return 0;\r
+ }\r
+ LOG("%08x R_386_PC32 *%p = 0x%x + %p('%s') - %p\n", r_info, ptr, *ptr, (void*)val, sSymName, ptr );\r
+ // TODO: Check if it needs the true value of ptr or the compiled value\r
+ // NOTE: Testing using true value\r
+ *ptr = val + addend - (uintptr_t)ptr;\r
+ break;\r
+\r
+ // Absolute Value of a symbol (S)\r
+ case R_386_GLOB_DAT:\r
+ if( !Elf_GetSymbol( base, sSymName, &val ) && !Binary_GetSymbol( sSymName, &val ) ) {\r
+ Warning("Unable to find symbol '%s'", sSymName);\r
+ return 0; \r
+ }\r
+ LOG("%08x R_386_GLOB_DAT *%p = 0x%x(%s)\n", r_info, ptr, (unsigned int)val, sSymName);\r
+ *ptr = val;\r
+ break;\r
+ \r
+ // Absolute Value of a symbol (S)\r
+ case R_386_JMP_SLOT:\r
+ if( !Elf_GetSymbol( base, sSymName, &val ) && !Binary_GetSymbol( sSymName, &val ) ) {\r
+ Warning("Unable to find symbol '%s'", sSymName);\r
+ return 0;\r
+ }\r
+ LOG("%08x R_386_JMP_SLOT *%p = 0x%x (%s)\n", r_info, ptr, (unsigned int)val, sSymName);\r
+ *ptr = val;\r
+ break;\r
+\r
+ // Base Address (B+A)\r
+ case R_386_RELATIVE:\r
+ LOG("%08x R_386_RELATIVE *%p = %p + 0x%x\n", r_info, ptr, base, addend);\r
+ *ptr = (uintptr_t)base + addend;\r
+ break;\r
+ \r
+ default:\r
+ LOG("Rel %p: 0x%x,%i\n", ptr, sym, type);\r
+ break;\r
+ }\r
+ return 1;\r
+}\r
+\r
+/**\r
+ * \fn int Elf_GetSymbol(void *Base, char *name, uintptr_t *ret)\r
+ * \brief Get a symbol from the loaded binary\r
+ */\r
+int Elf_GetSymbol(void *Base, char *Name, uintptr_t *ret)\r
+{\r
+ Elf32_Ehdr *hdr = (void*)Base;\r
+ Elf32_Sym *symtab;\r
+ int nbuckets = 0;\r
+ int iSymCount = 0;\r
+ int i;\r
+ uint32_t *pBuckets;\r
+ uint32_t *pChains;\r
+ uint32_t iNameHash;\r
+\r
+ if(!Base) return 0;\r
+\r
+ pBuckets = PTR(hdr->misc.HashTable);\r
+ symtab = PTR(hdr->misc.SymTable);\r
+ \r
+ nbuckets = pBuckets[0];\r
+ iSymCount = pBuckets[1];\r
+ pBuckets = &pBuckets[2];\r
+ pChains = &pBuckets[ nbuckets ];\r
+ \r
+ // Get hash\r
+ iNameHash = Elf_Int_HashString(Name);\r
+ iNameHash %= nbuckets;\r
+\r
+ // Check Bucket\r
+ i = pBuckets[ iNameHash ];\r
+ if(symtab[i].shndx != SHN_UNDEF && strcmp(MKPTR(char,symtab[i].name), Name) == 0) {\r
+ if(ret) *ret = symtab[ i ].value;\r
+ return 1;\r
+ }\r
+ \r
+ // Walk Chain\r
+ while(pChains[i] != STN_UNDEF)\r
+ {\r
+ i = pChains[i];\r
+ if(symtab[i].shndx != SHN_UNDEF && strcmp(MKPTR(char,symtab[i].name), Name) == 0) {\r
+ if(ret) *ret = symtab[ i ].value;\r
+ return 1;\r
+ }\r
+ }\r
+ return 0;\r
+}\r
+\r
+/**\r
+ * \fn uint32_t Elf_Int_HashString(char *str)\r
+ * \brief Hash a string in the ELF format\r
+ * \param str String to hash\r
+ * \return Hash value\r
+ */\r
+uint32_t Elf_Int_HashString(char *str)\r
+{\r
+ uint32_t h = 0, g;\r
+ while(*str)\r
+ {\r
+ h = (h << 4) + *str++;\r
+ if( (g = h & 0xf0000000) )\r
+ h ^= g >> 24;\r
+ h &= ~g;\r
+ }\r
+ return h;\r
+}\r
--- /dev/null
+/**\r
+ * \file elf.h\r
+ * \brief ELF Exeutable Loader\r
+ */\r
+#ifndef _BIN_ELF_H\r
+#define _BIN_ELF_H\r
+\r
+#include <stdint.h>\r
+\r
+/**\r
+ * \brief ELF File Header\r
+ */\r
+struct sElf32_Ehdr\r
+{\r
+ union {\r
+ char ident[16]; //!< Identifier Bytes\r
+ struct {\r
+ uint32_t Ident1;\r
+ uint32_t Ident2;\r
+ uint32_t HashTable;\r
+ uint32_t SymTable;\r
+ } misc;\r
+ };\r
+ uint16_t filetype; //!< File Type\r
+ uint16_t machine; //!< Machine / Arch\r
+ uint32_t version; //!< Version (File?)\r
+ uint32_t entrypoint; //!< Entry Point\r
+ uint32_t phoff; //!< Program Header Offset\r
+ uint32_t shoff; //!< Section Header Offset\r
+ uint32_t flags; //!< Flags\r
+ uint16_t headersize; //!< Header Size\r
+ uint16_t phentsize; //!< Program Header Entry Size\r
+ uint16_t phentcount; //!< Program Header Entry Count\r
+ uint16_t shentsize; //!< Section Header Entry Size\r
+ uint16_t shentcount; //!< Section Header Entry Count\r
+ uint16_t shstrindex; //!< Section Header String Table Index\r
+} __attribute__ ((packed));\r
+\r
+/**\r
+ * \brief Executable Types\r
+ */\r
+enum eElf32_ExecTypes\r
+{\r
+ ET_NONE = 0, //!< NULL Type\r
+ ET_REL = 1, //!< Relocatable (Object)\r
+ ET_EXEC = 2, //!< Executable\r
+ ET_DYN = 3, //!< Dynamic Library\r
+ ET_CORE = 4, //!< Core?\r
+ ET_LOPROC = 0xFF00, //!< Low Impl Defined\r
+ ET_HIPROC = 0xFFFF //!< High Impl Defined\r
+};\r
+\r
+/**\r
+ \name Section IDs\r
+ \{\r
+*/\r
+#define SHN_UNDEF 0 //!< Undefined Section\r
+#define SHN_LORESERVE 0xFF00 //!< Low Reserved\r
+#define SHN_LOPROC 0xFF00 //!< Low Impl Defined\r
+#define SHN_HIPROC 0xFF1F //!< High Impl Defined\r
+#define SHN_ABS 0xFFF1 //!< Absolute Address (Base: 0, Size: -1)\r
+#define SHN_COMMON 0xFFF2 //!< Common\r
+#define SHN_HIRESERVE 0xFFFF //!< High Reserved\r
+//! \}\r
+\r
+/**\r
+ \enum eElfSectionTypes\r
+ \brief ELF Section Types\r
+*/\r
+enum eElfSectionTypes {\r
+ SHT_NULL, //0\r
+ SHT_PROGBITS, //1\r
+ SHT_SYMTAB, //2\r
+ SHT_STRTAB, //3\r
+ SHT_RELA, //4\r
+ SHT_HASH, //5\r
+ SHT_DYNAMIC, //6\r
+ SHT_NOTE, //7\r
+ SHT_NOBITS, //8\r
+ SHT_REL, //9\r
+ SHT_SHLIB, //A\r
+ SHT_DYNSYM, //B\r
+ SHT_LAST, //C\r
+ SHT_LOPROC = 0x70000000,\r
+ SHT_HIPROC = 0x7fffffff,\r
+ SHT_LOUSER = 0x80000000,\r
+ SHT_HIUSER = 0xffffffff\r
+};\r
+\r
+#define SHF_WRITE 0x1\r
+#define SHF_ALLOC 0x2\r
+#define SHF_EXECINSTR 0x4\r
+#define SHF_MASKPROC 0xf0000000\r
+\r
+struct sElf32_Shent {\r
+ uint32_t name;\r
+ uint32_t type;\r
+ uint32_t flags;\r
+ uint32_t address;\r
+ uint32_t offset;\r
+ uint32_t size;\r
+ uint32_t link;\r
+ uint32_t info;\r
+ uint32_t addralign;\r
+ uint32_t entsize;\r
+} __attribute__ ((packed)); //sizeof = 40\r
+\r
+struct elf_sym_s {\r
+ union {\r
+ uint32_t nameOfs;\r
+ uint32_t name;\r
+ };\r
+ uint32_t value; //Address\r
+ uint32_t size;\r
+ uint8_t info;\r
+ uint8_t other;\r
+ uint16_t shndx;\r
+} __attribute__ ((packed));\r
+#define STN_UNDEF 0 // Undefined Symbol\r
+\r
+enum {\r
+ PT_NULL, //0\r
+ PT_LOAD, //1\r
+ PT_DYNAMIC, //2\r
+ PT_INTERP, //3\r
+ PT_NOTE, //4\r
+ PT_SHLIB, //5\r
+ PT_PHDR, //6\r
+ PT_LOPROC = 0x70000000,\r
+ PT_HIPROC = 0x7fffffff\r
+};\r
+\r
+struct sElf32_Phdr {\r
+ uint32_t Type;\r
+ uint32_t Offset;\r
+ uint32_t VAddr;\r
+ uint32_t PAddr;\r
+ uint32_t FileSize;\r
+ uint32_t MemSize;\r
+ uint32_t Flags;\r
+ uint32_t Align;\r
+} __attribute__ ((packed));\r
+\r
+struct elf32_rel_s {\r
+ uint32_t r_offset;\r
+ uint32_t r_info;\r
+} __attribute__ ((packed));\r
+\r
+struct elf32_rela_s {\r
+ uint32_t r_offset;\r
+ uint32_t r_info;\r
+ int32_t r_addend;\r
+} __attribute__ ((packed));\r
+\r
+enum {\r
+ R_386_NONE = 0, // none\r
+ R_386_32, // S+A\r
+ R_386_PC32, // S+A-P\r
+ R_386_GOT32, // G+A-P\r
+ R_386_PLT32, // L+A-P\r
+ R_386_COPY, // none\r
+ R_386_GLOB_DAT, // S\r
+ R_386_JMP_SLOT, // S\r
+ R_386_RELATIVE, // B+A\r
+ R_386_GOTOFF, // S+A-GOT\r
+ R_386_GOTPC, // GOT+A-P\r
+ R_386_LAST // none\r
+};\r
+\r
+#define ELF32_R_SYM(i) ((i)>>8) // Takes an info value and returns a symbol index\r
+#define ELF32_R_TYPE(i) ((i)&0xFF) // Takes an info value and returns a type\r
+#define ELF32_R_INFO(s,t) (((s)<<8)+((t)&0xFF)) // Takes a type and symbol index and returns an info value\r
+\r
+struct elf32_dyn_s {\r
+ uint32_t d_tag;\r
+ uint32_t d_val; //Also d_ptr\r
+} __attribute__ ((packed));\r
+\r
+enum {\r
+ DT_NULL, //!< Marks End of list\r
+ DT_NEEDED, //!< Offset in strtab to needed library\r
+ DT_PLTRELSZ, //!< Size in bytes of PLT\r
+ DT_PLTGOT, //!< Address of PLT/GOT\r
+ DT_HASH, //!< Address of symbol hash table\r
+ DT_STRTAB, //!< String Table address\r
+ DT_SYMTAB, //!< Symbol Table address\r
+ DT_RELA, //!< Relocation table address\r
+ DT_RELASZ, //!< Size of relocation table\r
+ DT_RELAENT, //!< Size of entry in relocation table\r
+ DT_STRSZ, //!< Size of string table\r
+ DT_SYMENT, //!< Size of symbol table entry\r
+ DT_INIT, //!< Address of initialisation function\r
+ DT_FINI, //!< Address of termination function\r
+ DT_SONAME, //!< String table offset of so name\r
+ DT_RPATH, //!< String table offset of library path\r
+ DT_SYMBOLIC,//!< Reverse order of symbol searching for library, search libs first then executable\r
+ DT_REL, //!< Relocation Entries (Elf32_Rel instead of Elf32_Rela)\r
+ DT_RELSZ, //!< Size of above table (bytes)\r
+ DT_RELENT, //!< Size of entry in above table\r
+ DT_PLTREL, //!< Relocation entry of PLT\r
+ DT_DEBUG, //!< Debugging Entry - Unknown contents\r
+ DT_TEXTREL, //!< Indicates that modifcations to a non-writeable segment may occur\r
+ DT_JMPREL, //!< Address of PLT only relocation entries\r
+ DT_LOPROC = 0x70000000, //!< Low Definable\r
+ DT_HIPROC = 0x7FFFFFFF //!< High Definable\r
+};\r
+\r
+typedef struct sElf32_Ehdr Elf32_Ehdr;\r
+typedef struct sElf32_Phdr Elf32_Phdr;\r
+typedef struct sElf32_Shent Elf32_Shent;\r
+typedef struct elf_sym_s elf_symtab;\r
+typedef struct elf_sym_s Elf32_Sym;\r
+typedef struct elf32_rel_s Elf32_Rel;\r
+typedef struct elf32_rela_s Elf32_Rela;\r
+typedef struct elf32_dyn_s Elf32_Dyn;\r
+\r
+#endif // defined(_EXE_ELF_H)\r
--- /dev/null
+/*
+ */
+#include "common.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+// === 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 <executable> [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");
+}
+
--- /dev/null
+/*
+ */
+#include "common.h"
+#include <stdio.h>
+#include <stdlib.h>
+#if __WIN32__
+# include <windows.h>
+#else
+# include <sys/mman.h>
+# include <errno.h>
+#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
+}
--- /dev/null
+/*
+ */
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#ifdef __WIN32__
+# include <windows.h>
+# include <winsock.h>
+#else
+# include <unistd.h>
+# include <sys/socket.h>
+# include <netinet/in.h>
+#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;
+}
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ */
+#include "../../Usermode/include/acess/sys.h"
+#include "common.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <string.h>
+#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)
+ * <I: Output long integer
+ * <d: Output Buffer (Preceded by valid size)
+ * ?d: Bi-directional buffer (Preceded by valid size), buffer contents
+ * are returned
+ */
+int _Syscall(const char *ArgTypes, ...)
+{
+ va_list args;
+ int outCount = 0;
+ int inCount = 0;
+ const char *str;
+
+ tOutValue **output;
+ tInValue **input;
+
+ // Get data size
+ va_start(args, ArgTypes);
+ str = ArgTypes;
+ while(*str)
+ {
+ int dir;
+
+ str = ReadEntry(NULL, NULL, &dir, str, args);
+ if( !str ) break;
+
+ // Out!
+ if( dir & 1 ) outCount ++;
+
+ // and.. In!
+ if( dir & 2 ) inCount ++;
+ }
+ va_end(args);
+
+ // Allocate buffers
+ output = malloc( outCount*sizeof(tOutValue*) );
+ input = malloc( inCount*sizeof(tInValue*) );
+
+ // - re-zero so they can be used as indicies
+ outCount = 0;
+ inCount = 0;
+
+ // Fill `output` and `input`
+ va_start(args, ArgTypes);
+ str = ArgTypes;
+ while(*str)
+ {
+ tOutValue *outParam;
+ tInValue *inParam;
+ int dir;
+
+ str = ReadEntry(&outParam, &inParam, &dir, str, args);
+ if( !str ) break;
+
+ if( dir & 1 )
+ output[outCount++] = outParam;
+ if( dir & 2 )
+ input[inCount++] = inParam;
+ }
+ va_end(args);
+
+ // Send syscall request
+
+
+ // Clean up
+ while(outCount--) free(output[outCount]);
+ free(output);
+ while(inCount--) free(input[inCount]);
+ free(input);
+
+ return 0;
+}
+
+// --- VFS Calls
+int open(const char *Path, int Flags) {
+ return _Syscall(">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 <d", FD, Bytes, Bytes, Dest);
+}
+
+size_t write(int FD, size_t Bytes, void *Src) {
+ return _Syscall(">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 >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 <d >i", fd, maxacls*sizeof(t_sysFInfo), info, maxacls);
+}
+
+int readdir(int fd, char *dest) {
+ return _Syscall(">i <s", fd, dest);
+}
+
+int _SysOpenChild(int fd, char *name, int flags) {
+ return _Syscall(">i >s >i", fd, name, flags);
+}
+
+int _SysGetACL(int fd, t_sysACL *dest) {
+ return _Syscall(">i <d", fd, sizeof(t_sysACL), dest);
+}
+
+int _SysMount(const char *Device, const char *Directory, const char *Type, const char *Options) {
+ return _Syscall(">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]);
+