mirror of
https://github.com/Fennix-Project/Userspace.git
synced 2025-05-28 15:34:26 +00:00
Almost working elf interpreter
This commit is contained in:
parent
fccec5a09e
commit
0b510e10f0
@ -35,21 +35,371 @@ uintptr_t KernelCTL(enum KCtl Command, uint64_t Arg1, uint64_t Arg2, uint64_t Ar
|
|||||||
return syscall5(_KernelCTL, Command, Arg1, Arg2, Arg3, Arg4);
|
return syscall5(_KernelCTL, Command, Arg1, Arg2, Arg3, Arg4);
|
||||||
}
|
}
|
||||||
|
|
||||||
// bool ELFAddLazyResolverToGOT(void *ElfFile, void *MemoryImage, LibAddressCollection *Libs)
|
struct LibAddressCollection
|
||||||
// {
|
{
|
||||||
// struct Elf64_Dyn *Dyn = (struct Elf64_Dyn *)ELFGetDynamicTag(ElfFile, DT_PLTGOT);
|
char Name[32];
|
||||||
// if (!Dyn)
|
__UINTPTR_TYPE__ *ElfFile;
|
||||||
// return false;
|
__UINTPTR_TYPE__ *MemoryImage;
|
||||||
|
__UINTPTR_TYPE__ *ParentElfFile;
|
||||||
|
__UINTPTR_TYPE__ *ParentMemoryImage;
|
||||||
|
struct LibAddressCollection *Next;
|
||||||
|
char Valid;
|
||||||
|
};
|
||||||
|
|
||||||
// Elf64_Addr *GOT = (Elf64_Addr *)Dyn->d_un.d_ptr;
|
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||||
|
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
||||||
|
|
||||||
// for (size_t i = 0; i < 16; i++)
|
static char Lock = 0;
|
||||||
// debug("GOT[%d]: %#lx (val: %#lx)", i, &GOT[i], GOT[i]);
|
|
||||||
|
|
||||||
// GOT[1] = (uintptr_t)Libs;
|
__attribute__((naked, used, no_stack_protector)) void ELF_LAZY_RESOLVE_STUB()
|
||||||
// GOT[2] = (uintptr_t)ElfLazyResolver;
|
{
|
||||||
// return true;
|
while (Lock == 1)
|
||||||
// }
|
;
|
||||||
|
__asm__ __volatile__("mfence\n");
|
||||||
|
Lock = 1;
|
||||||
|
__asm__ __volatile__("pop %r11\n"
|
||||||
|
"pop %r10\n"
|
||||||
|
|
||||||
|
"push %rdi\n"
|
||||||
|
"push %rsi\n"
|
||||||
|
"push %rdx\n"
|
||||||
|
"push %rcx\n"
|
||||||
|
"push %r8\n"
|
||||||
|
"push %r9\n"
|
||||||
|
|
||||||
|
"mov %r11, %rdi\n"
|
||||||
|
"mov %r10, %rsi\n"
|
||||||
|
|
||||||
|
"call ELF_LAZY_RESOLVE_MAIN\n"
|
||||||
|
|
||||||
|
"mov %rax, %r11\n"
|
||||||
|
|
||||||
|
"pop %r9\n"
|
||||||
|
"pop %r8\n"
|
||||||
|
"pop %rcx\n"
|
||||||
|
"pop %rdx\n"
|
||||||
|
"pop %rsi\n"
|
||||||
|
"pop %rdi\n"
|
||||||
|
|
||||||
|
"jmp *%r11\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
long abs(long i) { return i < 0 ? -i : i; }
|
||||||
|
|
||||||
|
void swap(char *x, char *y)
|
||||||
|
{
|
||||||
|
char t = *x;
|
||||||
|
*x = *y;
|
||||||
|
*y = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *reverse(char *Buffer, int i, int j)
|
||||||
|
{
|
||||||
|
while (i < j)
|
||||||
|
swap(&Buffer[i++], &Buffer[j--]);
|
||||||
|
return Buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *ltoa(long Value, char *Buffer, int Base)
|
||||||
|
{
|
||||||
|
if (Base < 2 || Base > 32)
|
||||||
|
return Buffer;
|
||||||
|
|
||||||
|
long n = abs(Value);
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
while (n)
|
||||||
|
{
|
||||||
|
int r = n % Base;
|
||||||
|
if (r >= 10)
|
||||||
|
Buffer[i++] = 65 + (r - 10);
|
||||||
|
else
|
||||||
|
Buffer[i++] = 48 + r;
|
||||||
|
n = n / Base;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == 0)
|
||||||
|
Buffer[i++] = '0';
|
||||||
|
|
||||||
|
if (Value < 0 && Base == 10)
|
||||||
|
Buffer[i++] = '-';
|
||||||
|
|
||||||
|
Buffer[i] = '\0';
|
||||||
|
return reverse(Buffer, 0, i - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void PutCharToKernelConsole(char c)
|
||||||
|
{
|
||||||
|
__asm__ __volatile__("syscall"
|
||||||
|
:
|
||||||
|
: "a"(1), "D"(c), "S"(0)
|
||||||
|
: "rcx", "r11", "memory");
|
||||||
|
}
|
||||||
|
|
||||||
|
void *memcpy(void *dest, const void *src, __SIZE_TYPE__ n)
|
||||||
|
{
|
||||||
|
__UINT8_TYPE__ *d = dest;
|
||||||
|
const __UINT8_TYPE__ *s = src;
|
||||||
|
while (n--)
|
||||||
|
*d++ = *s++;
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
int strcmp(const char *l, const char *r)
|
||||||
|
{
|
||||||
|
for (; *l == *r && *l; l++, r++)
|
||||||
|
;
|
||||||
|
return *(unsigned char *)l - *(unsigned char *)r;
|
||||||
|
}
|
||||||
|
|
||||||
|
Elf64_Sym *ELFGetSymbol(__UINTPTR_TYPE__ *ElfFile, char *SymbolName)
|
||||||
|
{
|
||||||
|
struct Elf64_Dyn *_SymTab = ELFGetDynamicTag(ElfFile, DT_SYMTAB);
|
||||||
|
struct Elf64_Dyn *_StrTab = ELFGetDynamicTag(ElfFile, DT_STRTAB);
|
||||||
|
Elf64_Sym *DynSym = (Elf64_Sym *)(ElfFile + _SymTab->d_un.d_ptr);
|
||||||
|
char *DynStr = (char *)(ElfFile + _StrTab->d_un.d_ptr);
|
||||||
|
|
||||||
|
for (int i = 0; i < _SymTab->d_un.d_val; i++)
|
||||||
|
{
|
||||||
|
if (strcmp(DynStr + DynSym[i].st_name, SymbolName) == 0)
|
||||||
|
return &DynSym[i];
|
||||||
|
}
|
||||||
|
return (Elf64_Sym *)0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Print(char *String)
|
||||||
|
{
|
||||||
|
for (short i = 0; String[i] != '\0'; i++)
|
||||||
|
PutCharToKernelConsole(String[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrintNL(char *String)
|
||||||
|
{
|
||||||
|
for (short i = 0; String[i] != '\0'; i++)
|
||||||
|
PutCharToKernelConsole(String[i]);
|
||||||
|
|
||||||
|
PutCharToKernelConsole('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
void (*ELF_LAZY_RESOLVE_MAIN(struct LibAddressCollection *Info, long RelIndex))()
|
||||||
|
{
|
||||||
|
if (Info)
|
||||||
|
{
|
||||||
|
struct LibAddressCollection *tmp = Info;
|
||||||
|
PrintNL("________________");
|
||||||
|
// The last entry is the null entry (Valid == false) which determines the end of the list.
|
||||||
|
while (tmp->Valid)
|
||||||
|
{
|
||||||
|
Print("-- ");
|
||||||
|
Print(tmp->Name);
|
||||||
|
PrintNL(" --");
|
||||||
|
__UINTPTR_TYPE__ BaseAddress = __UINTPTR_MAX__;
|
||||||
|
|
||||||
|
Elf64_Phdr ItrProgramHeader;
|
||||||
|
|
||||||
|
for (Elf64_Half i = 0; i < ((Elf64_Ehdr *)tmp->ElfFile)->e_phnum; i++)
|
||||||
|
{
|
||||||
|
memcpy(&ItrProgramHeader, (__UINT8_TYPE__ *)tmp->ElfFile + ((Elf64_Ehdr *)tmp->ElfFile)->e_phoff + ((Elf64_Ehdr *)tmp->ElfFile)->e_phentsize * i, sizeof(Elf64_Phdr));
|
||||||
|
BaseAddress = MIN(BaseAddress, ItrProgramHeader.p_vaddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
char LibAddressBuffer[32];
|
||||||
|
ltoa(tmp->MemoryImage, LibAddressBuffer, 16);
|
||||||
|
Print("MemoryImage: 0x");
|
||||||
|
PrintNL(LibAddressBuffer);
|
||||||
|
|
||||||
|
char BaseAddressBuffer[32];
|
||||||
|
ltoa(BaseAddress, BaseAddressBuffer, 16);
|
||||||
|
Print("BaseAddress: 0x");
|
||||||
|
PrintNL(BaseAddressBuffer);
|
||||||
|
|
||||||
|
struct Elf64_Dyn *_JmpRel = ELFGetDynamicTag(tmp->ElfFile, DT_JMPREL);
|
||||||
|
struct Elf64_Dyn *_SymTab = ELFGetDynamicTag(tmp->ElfFile, DT_SYMTAB);
|
||||||
|
struct Elf64_Dyn *_StrTab = ELFGetDynamicTag(tmp->ElfFile, DT_STRTAB);
|
||||||
|
|
||||||
|
if (!_JmpRel)
|
||||||
|
{
|
||||||
|
PrintNL("No DT_JMPREL");
|
||||||
|
goto RetryNextLib;
|
||||||
|
}
|
||||||
|
else if (RelIndex >= _JmpRel->d_un.d_val / sizeof(Elf64_Rela))
|
||||||
|
{
|
||||||
|
PrintNL("RelIndex is greater than the number of relocations");
|
||||||
|
goto RetryNextLib;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_SymTab)
|
||||||
|
{
|
||||||
|
PrintNL("No DT_SYMTAB");
|
||||||
|
goto RetryNextLib;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_StrTab)
|
||||||
|
{
|
||||||
|
PrintNL("No DT_STRTAB");
|
||||||
|
goto RetryNextLib;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_JmpRel && !_SymTab && !_StrTab)
|
||||||
|
goto RetryNextLib;
|
||||||
|
|
||||||
|
char JmpRel_d_ptr[32];
|
||||||
|
ltoa(_JmpRel->d_un.d_ptr, JmpRel_d_ptr, 16);
|
||||||
|
Print("JmpRel_d_ptr: 0x");
|
||||||
|
PrintNL(JmpRel_d_ptr);
|
||||||
|
|
||||||
|
char SymTab_d_ptr[32];
|
||||||
|
ltoa(_SymTab->d_un.d_ptr, SymTab_d_ptr, 16);
|
||||||
|
Print("SymTab_d_ptr: 0x");
|
||||||
|
PrintNL(SymTab_d_ptr);
|
||||||
|
|
||||||
|
char StrTab_d_ptr[32];
|
||||||
|
ltoa(_StrTab->d_un.d_ptr, StrTab_d_ptr, 16);
|
||||||
|
Print("StrTab_d_ptr: 0x");
|
||||||
|
PrintNL(StrTab_d_ptr);
|
||||||
|
|
||||||
|
Elf64_Rela *JmpRel = tmp->MemoryImage + (_JmpRel->d_un.d_ptr - BaseAddress);
|
||||||
|
Elf64_Sym *SymTab = tmp->MemoryImage + (_SymTab->d_un.d_ptr - BaseAddress);
|
||||||
|
char *DynStr = tmp->MemoryImage + (_StrTab->d_un.d_ptr - BaseAddress);
|
||||||
|
|
||||||
|
Elf64_Rela *Rel = JmpRel + RelIndex;
|
||||||
|
// Elf64_Rela *Rel = &JmpRel[RelIndex];
|
||||||
|
Elf64_Addr *GOTEntry = (Elf64_Addr *)(tmp->MemoryImage + Rel->r_offset);
|
||||||
|
|
||||||
|
int RelType = ELF64_R_TYPE(Rel->r_info);
|
||||||
|
|
||||||
|
char RelBuffer[32];
|
||||||
|
ltoa(Rel, RelBuffer, 16);
|
||||||
|
Print("Rel: 0x");
|
||||||
|
PrintNL(RelBuffer);
|
||||||
|
|
||||||
|
char LibRelInfoBuffer[32];
|
||||||
|
ltoa(Rel->r_info, LibRelInfoBuffer, 16);
|
||||||
|
Print(" Rel->r_info: 0x");
|
||||||
|
PrintNL(LibRelInfoBuffer);
|
||||||
|
|
||||||
|
char LibRelOffsetBuffer[32];
|
||||||
|
ltoa(Rel->r_offset, LibRelOffsetBuffer, 16);
|
||||||
|
Print(" Rel->r_offset: 0x");
|
||||||
|
PrintNL(LibRelOffsetBuffer);
|
||||||
|
|
||||||
|
char LibRelAddEntBuffer[32];
|
||||||
|
ltoa(Rel->r_addend, LibRelAddEntBuffer, 16);
|
||||||
|
Print(" Rel->r_addend: 0x");
|
||||||
|
PrintNL(LibRelAddEntBuffer);
|
||||||
|
|
||||||
|
char RelIndexBuffer[32];
|
||||||
|
ltoa(RelIndex, RelIndexBuffer, 16);
|
||||||
|
Print("RelIndex: 0x");
|
||||||
|
PrintNL(RelIndexBuffer);
|
||||||
|
|
||||||
|
char GotAddressBuffer[32];
|
||||||
|
ltoa(GOTEntry, GotAddressBuffer, 16);
|
||||||
|
Print("GOTEntry: 0x");
|
||||||
|
PrintNL(GotAddressBuffer);
|
||||||
|
|
||||||
|
if (GOTEntry && GOTEntry < 0x10000000)
|
||||||
|
{
|
||||||
|
char GotInsideBuffer[32];
|
||||||
|
ltoa(*GOTEntry, GotInsideBuffer, 16);
|
||||||
|
Print("*GOTEntry: 0x");
|
||||||
|
PrintNL(GotInsideBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (RelType)
|
||||||
|
{
|
||||||
|
case R_X86_64_NONE:
|
||||||
|
{
|
||||||
|
PrintNL("R_X86_64_NONE");
|
||||||
|
|
||||||
|
if (*GOTEntry == 0)
|
||||||
|
{
|
||||||
|
PrintNL("GOTEntry is 0");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Lock = 0;
|
||||||
|
return (void (*)()) * GOTEntry;
|
||||||
|
}
|
||||||
|
case R_X86_64_JUMP_SLOT:
|
||||||
|
{
|
||||||
|
PrintNL("R_X86_64_JUMP_SLOT");
|
||||||
|
int SymIndex = ELF64_R_SYM(Rel->r_info);
|
||||||
|
Elf64_Sym *Sym = SymTab + SymIndex;
|
||||||
|
// Elf64_Sym *Sym = &SymTab[SymIndex];
|
||||||
|
|
||||||
|
if (Sym->st_name)
|
||||||
|
{
|
||||||
|
char *SymName = DynStr + Sym->st_name;
|
||||||
|
PrintNL(SymName);
|
||||||
|
|
||||||
|
Elf64_Sym *LibSym = ELFGetSymbol(tmp->ElfFile, SymName);
|
||||||
|
if (LibSym)
|
||||||
|
{
|
||||||
|
*GOTEntry = (Elf64_Addr)(tmp->MemoryImage + LibSym->st_value);
|
||||||
|
Lock = 0;
|
||||||
|
return (void (*)()) * GOTEntry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
char RelTypeBuffer[32];
|
||||||
|
ltoa(RelType, RelTypeBuffer, 10);
|
||||||
|
Print("RelType not supported ");
|
||||||
|
PrintNL(RelTypeBuffer);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RetryNextLib:
|
||||||
|
tmp = tmp->Next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Lock = 0;
|
||||||
|
__asm__ __volatile__("mfence\n");
|
||||||
|
|
||||||
|
char SNotFound[32];
|
||||||
|
Print("Symbol index ");
|
||||||
|
ltoa(RelIndex, SNotFound, 10);
|
||||||
|
Print(SNotFound);
|
||||||
|
PrintNL(" not found");
|
||||||
|
int ExitCode = 0x51801;
|
||||||
|
syscall1(_Exit, ExitCode);
|
||||||
|
__builtin_unreachable();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ELFAddLazyResolverToGOT(void *ElfFile, void *MemoryImage, struct LibAddressCollection *Libs)
|
||||||
|
{
|
||||||
|
struct Elf64_Dyn *Dyn = (struct Elf64_Dyn *)ELFGetDynamicTag(ElfFile, DT_PLTGOT);
|
||||||
|
if (!Dyn)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Elf64_Addr *GOT = (Elf64_Addr *)Dyn->d_un.d_ptr;
|
||||||
|
|
||||||
|
// for (size_t i = 0; i < 16; i++)
|
||||||
|
// {
|
||||||
|
// char Itr[32];
|
||||||
|
// char LibAddressBuffer[32];
|
||||||
|
// char LibValueBuffer[32];
|
||||||
|
// ltoa(i, Itr, 10);
|
||||||
|
// ltoa(&GOT[i], LibAddressBuffer, 16);
|
||||||
|
// ltoa(GOT[i], LibValueBuffer, 16);
|
||||||
|
|
||||||
|
// Print("GOT[");
|
||||||
|
// Print(Itr);
|
||||||
|
// Print("]: 0x");
|
||||||
|
// Print(LibAddressBuffer);
|
||||||
|
// Print(" (val: 0x");
|
||||||
|
// Print(LibValueBuffer);
|
||||||
|
// PrintNL(")");
|
||||||
|
// }
|
||||||
|
|
||||||
|
GOT[1] = (uintptr_t)Libs;
|
||||||
|
GOT[2] = (uintptr_t)ELF_LAZY_RESOLVE_STUB;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/* This function is a mess and needs to be cleaned up. */
|
/* This function is a mess and needs to be cleaned up. */
|
||||||
/*
|
/*
|
||||||
@ -332,8 +682,9 @@ struct InterpreterIPCDataLibrary
|
|||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
char Path[256];
|
char Path[256];
|
||||||
|
void *ElfFile;
|
||||||
void *MemoryImage;
|
void *MemoryImage;
|
||||||
struct InterpreterIPCDataLibrary Libraries[256];
|
struct InterpreterIPCDataLibrary Libraries[64];
|
||||||
} InterpreterIPCData;
|
} InterpreterIPCData;
|
||||||
|
|
||||||
/* Actual load */
|
/* Actual load */
|
||||||
@ -365,5 +716,24 @@ int ld_load(int argc, char *argv[], char *envp[])
|
|||||||
|
|
||||||
IPC(IPC_DELETE, IPC_TYPE_MessagePassing, IPC_ID, 0, NULL, 0);
|
IPC(IPC_DELETE, IPC_TYPE_MessagePassing, IPC_ID, 0, NULL, 0);
|
||||||
FreePages((uintptr_t)IPCBuffer, PagesForStruct);
|
FreePages((uintptr_t)IPCBuffer, PagesForStruct);
|
||||||
return *(int *)IPCBuffer;
|
|
||||||
|
Elf64_Ehdr *ELFHeader = (Elf64_Ehdr *)IPCBuffer->MemoryImage;
|
||||||
|
|
||||||
|
/* ... */
|
||||||
|
|
||||||
|
struct LibAddressCollection *LibsForLazyResolver = (struct LibAddressCollection *)RequestPages(sizeof(struct LibAddressCollection) / PageSize + 1);
|
||||||
|
/*
|
||||||
|
TODO: Add libraries to LibsForLazyResolver
|
||||||
|
This can be done by calling the kernel to load the libraries, and then adding them to the LibsForLazyResolver struct.
|
||||||
|
Kernel has a thread for loading libraries. If the lib is already loaded, it will return the address of the loaded lib.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!ELFAddLazyResolverToGOT(IPCBuffer->ElfFile, IPCBuffer->MemoryImage, LibsForLazyResolver))
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < 35; i++)
|
||||||
|
syscall2(_Print, "Failed to add lazy resolver to GOT\n"[i], 0);
|
||||||
|
return -0xE1F;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ((int (*)(int, char *[], char *[]))ELFHeader->e_entry)(argc, argv, envp);
|
||||||
}
|
}
|
||||||
|
@ -1,344 +0,0 @@
|
|||||||
#include "elf.h"
|
|
||||||
|
|
||||||
struct LibAddressCollection
|
|
||||||
{
|
|
||||||
char Name[32];
|
|
||||||
__UINTPTR_TYPE__ *ElfFile;
|
|
||||||
__UINTPTR_TYPE__ *MemoryImage;
|
|
||||||
__UINTPTR_TYPE__ *ParentElfFile;
|
|
||||||
__UINTPTR_TYPE__ *ParentMemoryImage;
|
|
||||||
struct LibAddressCollection *Next;
|
|
||||||
char Valid;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
|
||||||
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
|
||||||
|
|
||||||
static char Lock = 0;
|
|
||||||
|
|
||||||
__attribute__((naked, used, no_stack_protector)) void ELF_LAZY_RESOLVE_STUB()
|
|
||||||
{
|
|
||||||
while (Lock == 1)
|
|
||||||
;
|
|
||||||
__asm__ __volatile__("mfence\n");
|
|
||||||
Lock = 1;
|
|
||||||
__asm__ __volatile__("pop %r11\n"
|
|
||||||
"pop %r10\n"
|
|
||||||
|
|
||||||
"push %rdi\n"
|
|
||||||
"push %rsi\n"
|
|
||||||
"push %rdx\n"
|
|
||||||
"push %rcx\n"
|
|
||||||
"push %r8\n"
|
|
||||||
"push %r9\n"
|
|
||||||
|
|
||||||
"mov %r11, %rdi\n"
|
|
||||||
"mov %r10, %rsi\n"
|
|
||||||
|
|
||||||
"call ELF_LAZY_RESOLVE_MAIN\n"
|
|
||||||
|
|
||||||
"mov %rax, %r11\n"
|
|
||||||
|
|
||||||
"pop %r9\n"
|
|
||||||
"pop %r8\n"
|
|
||||||
"pop %rcx\n"
|
|
||||||
"pop %rdx\n"
|
|
||||||
"pop %rsi\n"
|
|
||||||
"pop %rdi\n"
|
|
||||||
|
|
||||||
"jmp *%r11\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
long abs(long i) { return i < 0 ? -i : i; }
|
|
||||||
|
|
||||||
void swap(char *x, char *y)
|
|
||||||
{
|
|
||||||
char t = *x;
|
|
||||||
*x = *y;
|
|
||||||
*y = t;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *reverse(char *Buffer, int i, int j)
|
|
||||||
{
|
|
||||||
while (i < j)
|
|
||||||
swap(&Buffer[i++], &Buffer[j--]);
|
|
||||||
return Buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *ltoa(long Value, char *Buffer, int Base)
|
|
||||||
{
|
|
||||||
if (Base < 2 || Base > 32)
|
|
||||||
return Buffer;
|
|
||||||
|
|
||||||
long n = abs(Value);
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
while (n)
|
|
||||||
{
|
|
||||||
int r = n % Base;
|
|
||||||
if (r >= 10)
|
|
||||||
Buffer[i++] = 65 + (r - 10);
|
|
||||||
else
|
|
||||||
Buffer[i++] = 48 + r;
|
|
||||||
n = n / Base;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i == 0)
|
|
||||||
Buffer[i++] = '0';
|
|
||||||
|
|
||||||
if (Value < 0 && Base == 10)
|
|
||||||
Buffer[i++] = '-';
|
|
||||||
|
|
||||||
Buffer[i] = '\0';
|
|
||||||
return reverse(Buffer, 0, i - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void PutCharToKernelConsole(char c)
|
|
||||||
{
|
|
||||||
__asm__ __volatile__("syscall"
|
|
||||||
:
|
|
||||||
: "a"(1), "D"(c), "S"(0)
|
|
||||||
: "rcx", "r11", "memory");
|
|
||||||
}
|
|
||||||
|
|
||||||
void *memcpy(void *dest, const void *src, __SIZE_TYPE__ n)
|
|
||||||
{
|
|
||||||
__UINT8_TYPE__ *d = dest;
|
|
||||||
const __UINT8_TYPE__ *s = src;
|
|
||||||
while (n--)
|
|
||||||
*d++ = *s++;
|
|
||||||
return dest;
|
|
||||||
}
|
|
||||||
|
|
||||||
int strcmp(const char *l, const char *r)
|
|
||||||
{
|
|
||||||
for (; *l == *r && *l; l++, r++)
|
|
||||||
;
|
|
||||||
return *(unsigned char *)l - *(unsigned char *)r;
|
|
||||||
}
|
|
||||||
|
|
||||||
Elf64_Sym *ELFGetSymbol(__UINTPTR_TYPE__ *ElfFile, char *SymbolName)
|
|
||||||
{
|
|
||||||
struct Elf64_Dyn *_SymTab = ELFGetDynamicTag(ElfFile, DT_SYMTAB);
|
|
||||||
struct Elf64_Dyn *_StrTab = ELFGetDynamicTag(ElfFile, DT_STRTAB);
|
|
||||||
Elf64_Sym *DynSym = (Elf64_Sym *)(ElfFile + _SymTab->d_un.d_ptr);
|
|
||||||
char *DynStr = (char *)(ElfFile + _StrTab->d_un.d_ptr);
|
|
||||||
|
|
||||||
for (int i = 0; i < _SymTab->d_un.d_val; i++)
|
|
||||||
{
|
|
||||||
if (strcmp(DynStr + DynSym[i].st_name, SymbolName) == 0)
|
|
||||||
return &DynSym[i];
|
|
||||||
}
|
|
||||||
return (Elf64_Sym *)0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Print(char *String)
|
|
||||||
{
|
|
||||||
for (short i = 0; String[i] != '\0'; i++)
|
|
||||||
PutCharToKernelConsole(String[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PrintNL(char *String)
|
|
||||||
{
|
|
||||||
for (short i = 0; String[i] != '\0'; i++)
|
|
||||||
PutCharToKernelConsole(String[i]);
|
|
||||||
|
|
||||||
PutCharToKernelConsole('\n');
|
|
||||||
}
|
|
||||||
|
|
||||||
long RelTmpIndex = 0xdead;
|
|
||||||
|
|
||||||
void *SymbolNotFound()
|
|
||||||
{
|
|
||||||
// TODO: Print the symbol name and the library name.
|
|
||||||
// TODO: This should go to the stderr.
|
|
||||||
char Buffer[32];
|
|
||||||
|
|
||||||
Print("Symbol index ");
|
|
||||||
ltoa(RelTmpIndex, Buffer, 10);
|
|
||||||
Print(Buffer);
|
|
||||||
PrintNL(" not found");
|
|
||||||
return (void *)0xdeadbeef;
|
|
||||||
}
|
|
||||||
|
|
||||||
void (*ELF_LAZY_RESOLVE_MAIN(struct LibAddressCollection *Info, long RelIndex))()
|
|
||||||
{
|
|
||||||
RelTmpIndex = RelIndex;
|
|
||||||
if (Info)
|
|
||||||
{
|
|
||||||
struct LibAddressCollection *tmp = Info;
|
|
||||||
PrintNL("________________");
|
|
||||||
// The last entry is the null entry (Valid == false) which determines the end of the list.
|
|
||||||
while (tmp->Valid)
|
|
||||||
{
|
|
||||||
Print("-- ");
|
|
||||||
Print(tmp->Name);
|
|
||||||
PrintNL(" --");
|
|
||||||
__UINTPTR_TYPE__ BaseAddress = __UINTPTR_MAX__;
|
|
||||||
|
|
||||||
Elf64_Phdr ItrProgramHeader;
|
|
||||||
|
|
||||||
for (Elf64_Half i = 0; i < ((Elf64_Ehdr *)tmp->ElfFile)->e_phnum; i++)
|
|
||||||
{
|
|
||||||
memcpy(&ItrProgramHeader, (__UINT8_TYPE__ *)tmp->ElfFile + ((Elf64_Ehdr *)tmp->ElfFile)->e_phoff + ((Elf64_Ehdr *)tmp->ElfFile)->e_phentsize * i, sizeof(Elf64_Phdr));
|
|
||||||
BaseAddress = MIN(BaseAddress, ItrProgramHeader.p_vaddr);
|
|
||||||
}
|
|
||||||
|
|
||||||
char LibAddressBuffer[32];
|
|
||||||
ltoa(tmp->MemoryImage, LibAddressBuffer, 16);
|
|
||||||
Print("MemoryImage: 0x");
|
|
||||||
PrintNL(LibAddressBuffer);
|
|
||||||
|
|
||||||
char BaseAddressBuffer[32];
|
|
||||||
ltoa(BaseAddress, BaseAddressBuffer, 16);
|
|
||||||
Print("BaseAddress: 0x");
|
|
||||||
PrintNL(BaseAddressBuffer);
|
|
||||||
|
|
||||||
struct Elf64_Dyn *_JmpRel = ELFGetDynamicTag(tmp->ElfFile, DT_JMPREL);
|
|
||||||
struct Elf64_Dyn *_SymTab = ELFGetDynamicTag(tmp->ElfFile, DT_SYMTAB);
|
|
||||||
struct Elf64_Dyn *_StrTab = ELFGetDynamicTag(tmp->ElfFile, DT_STRTAB);
|
|
||||||
|
|
||||||
if (!_JmpRel)
|
|
||||||
{
|
|
||||||
PrintNL("No DT_JMPREL");
|
|
||||||
goto RetryNextLib;
|
|
||||||
}
|
|
||||||
else if (RelIndex >= _JmpRel->d_un.d_val / sizeof(Elf64_Rela))
|
|
||||||
{
|
|
||||||
PrintNL("RelIndex is greater than the number of relocations");
|
|
||||||
goto RetryNextLib;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_SymTab)
|
|
||||||
{
|
|
||||||
PrintNL("No DT_SYMTAB");
|
|
||||||
goto RetryNextLib;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_StrTab)
|
|
||||||
{
|
|
||||||
PrintNL("No DT_STRTAB");
|
|
||||||
goto RetryNextLib;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_JmpRel && !_SymTab && !_StrTab)
|
|
||||||
goto RetryNextLib;
|
|
||||||
|
|
||||||
char JmpRel_d_ptr[32];
|
|
||||||
ltoa(_JmpRel->d_un.d_ptr, JmpRel_d_ptr, 16);
|
|
||||||
Print("JmpRel_d_ptr: 0x");
|
|
||||||
PrintNL(JmpRel_d_ptr);
|
|
||||||
|
|
||||||
char SymTab_d_ptr[32];
|
|
||||||
ltoa(_SymTab->d_un.d_ptr, SymTab_d_ptr, 16);
|
|
||||||
Print("SymTab_d_ptr: 0x");
|
|
||||||
PrintNL(SymTab_d_ptr);
|
|
||||||
|
|
||||||
char StrTab_d_ptr[32];
|
|
||||||
ltoa(_StrTab->d_un.d_ptr, StrTab_d_ptr, 16);
|
|
||||||
Print("StrTab_d_ptr: 0x");
|
|
||||||
PrintNL(StrTab_d_ptr);
|
|
||||||
|
|
||||||
Elf64_Rela *JmpRel = tmp->MemoryImage + (_JmpRel->d_un.d_ptr - BaseAddress);
|
|
||||||
Elf64_Sym *SymTab = tmp->MemoryImage + (_SymTab->d_un.d_ptr - BaseAddress);
|
|
||||||
char *DynStr = tmp->MemoryImage + (_StrTab->d_un.d_ptr - BaseAddress);
|
|
||||||
|
|
||||||
Elf64_Rela *Rel = JmpRel + RelIndex;
|
|
||||||
// Elf64_Rela *Rel = &JmpRel[RelIndex];
|
|
||||||
Elf64_Addr *GOTEntry = (Elf64_Addr *)(tmp->MemoryImage + Rel->r_offset);
|
|
||||||
|
|
||||||
int RelType = ELF64_R_TYPE(Rel->r_info);
|
|
||||||
|
|
||||||
char RelBuffer[32];
|
|
||||||
ltoa(Rel, RelBuffer, 16);
|
|
||||||
Print("Rel: 0x");
|
|
||||||
PrintNL(RelBuffer);
|
|
||||||
|
|
||||||
char LibRelInfoBuffer[32];
|
|
||||||
ltoa(Rel->r_info, LibRelInfoBuffer, 16);
|
|
||||||
Print(" Rel->r_info: 0x");
|
|
||||||
PrintNL(LibRelInfoBuffer);
|
|
||||||
|
|
||||||
char LibRelOffsetBuffer[32];
|
|
||||||
ltoa(Rel->r_offset, LibRelOffsetBuffer, 16);
|
|
||||||
Print(" Rel->r_offset: 0x");
|
|
||||||
PrintNL(LibRelOffsetBuffer);
|
|
||||||
|
|
||||||
char LibRelAddEntBuffer[32];
|
|
||||||
ltoa(Rel->r_addend, LibRelAddEntBuffer, 16);
|
|
||||||
Print(" Rel->r_addend: 0x");
|
|
||||||
PrintNL(LibRelAddEntBuffer);
|
|
||||||
|
|
||||||
char RelIndexBuffer[32];
|
|
||||||
ltoa(RelIndex, RelIndexBuffer, 16);
|
|
||||||
Print("RelIndex: 0x");
|
|
||||||
PrintNL(RelIndexBuffer);
|
|
||||||
|
|
||||||
char GotAddressBuffer[32];
|
|
||||||
ltoa(GOTEntry, GotAddressBuffer, 16);
|
|
||||||
Print("GOTEntry: 0x");
|
|
||||||
PrintNL(GotAddressBuffer);
|
|
||||||
|
|
||||||
if (GOTEntry && GOTEntry < 0x10000000)
|
|
||||||
{
|
|
||||||
char GotInsideBuffer[32];
|
|
||||||
ltoa(*GOTEntry, GotInsideBuffer, 16);
|
|
||||||
Print("*GOTEntry: 0x");
|
|
||||||
PrintNL(GotInsideBuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (RelType)
|
|
||||||
{
|
|
||||||
case R_X86_64_NONE:
|
|
||||||
{
|
|
||||||
PrintNL("R_X86_64_NONE");
|
|
||||||
|
|
||||||
if (*GOTEntry == 0)
|
|
||||||
{
|
|
||||||
PrintNL("GOTEntry is 0");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Lock = 0;
|
|
||||||
return (void (*)()) * GOTEntry;
|
|
||||||
}
|
|
||||||
case R_X86_64_JUMP_SLOT:
|
|
||||||
{
|
|
||||||
PrintNL("R_X86_64_JUMP_SLOT");
|
|
||||||
int SymIndex = ELF64_R_SYM(Rel->r_info);
|
|
||||||
Elf64_Sym *Sym = SymTab + SymIndex;
|
|
||||||
// Elf64_Sym *Sym = &SymTab[SymIndex];
|
|
||||||
|
|
||||||
if (Sym->st_name)
|
|
||||||
{
|
|
||||||
char *SymName = DynStr + Sym->st_name;
|
|
||||||
PrintNL(SymName);
|
|
||||||
|
|
||||||
Elf64_Sym *LibSym = ELFGetSymbol(tmp->ElfFile, SymName);
|
|
||||||
if (LibSym)
|
|
||||||
{
|
|
||||||
*GOTEntry = (Elf64_Addr)(tmp->MemoryImage + LibSym->st_value);
|
|
||||||
Lock = 0;
|
|
||||||
return (void (*)()) * GOTEntry;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
char RelTypeBuffer[32];
|
|
||||||
ltoa(RelType, RelTypeBuffer, 10);
|
|
||||||
Print("RelType not supported ");
|
|
||||||
PrintNL(RelTypeBuffer);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RetryNextLib:
|
|
||||||
tmp = tmp->Next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Lock = 0;
|
|
||||||
__asm__ __volatile__("mfence\n");
|
|
||||||
return SymbolNotFound;
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user