From c43c05ef3234d6118ce601d299df60383d54ac7b Mon Sep 17 00:00:00 2001
From: John Hodge <tpg@mutabah.net>
Date: Sun, 9 Oct 2011 14:04:45 +0800
Subject: [PATCH] Usermode/ld-acess - Fixing Elf64 support (and incorrect Uint*
 sizes)

---
 Usermode/Libraries/ld-acess.so_src/common.h  |  14 +-
 Usermode/Libraries/ld-acess.so_src/elf.c     | 147 +++++++++++++++++--
 Usermode/Libraries/ld-acess.so_src/elf32.h   |  18 ++-
 Usermode/Libraries/ld-acess.so_src/loadlib.c |  21 +--
 Usermode/Libraries/ld-acess.so_src/main.c    |   2 +-
 5 files changed, 163 insertions(+), 39 deletions(-)

diff --git a/Usermode/Libraries/ld-acess.so_src/common.h b/Usermode/Libraries/ld-acess.so_src/common.h
index 8fa626a7..d44008f1 100644
--- a/Usermode/Libraries/ld-acess.so_src/common.h
+++ b/Usermode/Libraries/ld-acess.so_src/common.h
@@ -9,6 +9,12 @@
 
 #include <stddef.h>
 #include <stdarg.h>
+#include <stdint.h>
+
+typedef	uintptr_t	Uint;
+typedef uint8_t 	Uint8;
+typedef uint16_t	Uint16;
+typedef uint32_t	Uint32;
 
 // HACK: Replace with underscored
 #define SysDebug	_SysDebug
@@ -19,14 +25,6 @@
 #define	SYSTEM_LIB_DIR	"/Acess/Libs/"
 
 // === Types ===
-typedef unsigned int	Uint;
-typedef unsigned char	Uint8;
-typedef unsigned short	Uint16;
-typedef unsigned long	Uint32;
-typedef signed char		Sint8;
-typedef signed short	Sint16;
-typedef signed long		Sint32;
-
 typedef struct {
 	void	*Base;
 	char	*Name;
diff --git a/Usermode/Libraries/ld-acess.so_src/elf.c b/Usermode/Libraries/ld-acess.so_src/elf.c
index 00f2431d..acda5c4d 100644
--- a/Usermode/Libraries/ld-acess.so_src/elf.c
+++ b/Usermode/Libraries/ld-acess.so_src/elf.c
@@ -7,7 +7,7 @@
 #include "elf32.h"
 #include "elf64.h"
 
-#define DEBUG	1
+#define DEBUG	0
 
 #if DEBUG
 # define	DEBUGS(v...)	SysDebug("ld-acess - " v)
@@ -25,6 +25,9 @@ static const char	*csaR_NAMES[] = {"R_386_NONE", "R_386_32", "R_386_PC32", "R_38
 void	*ElfRelocate(void *Base, char **envp, const char *Filename);
 void	*Elf32Relocate(void *Base, char **envp, const char *Filename);
 void	*Elf64Relocate(void *Base, char **envp, const char *Filename);
+ int	ElfGetSymbol(void *Base, const char *Name, void **Ret);
+ int	Elf64GetSymbol(void *Base, const char *Name, void **Ret);
+ int	Elf32GetSymbol(void *Base, const char *Name, void **Ret);
 Uint32	ElfHashString(const char *name);
 
 // === CODE ===
@@ -200,6 +203,12 @@ void *Elf64Relocate(void *Base, char **envp, const char *Filename)
 		case R_X86_64_64:
 			*(uint64_t*)ptr = (uint64_t)GetSymbol(symname) + addend;
 			break;
+		case R_X86_64_GLOB_DAT:
+			*(uint64_t*)ptr = (uint64_t)GetSymbol(symname);
+			break;
+		case R_X86_64_JUMP_SLOT:
+			*(uint64_t*)ptr = (uint64_t)GetSymbol(symname);
+			break;
 		default:
 			SysDebug("ld-acess - _Elf64DoReloc: Unknown relocation type %i", type);
 			break;
@@ -258,8 +267,8 @@ void *Elf32Relocate(void *Base, char **envp, const char *Filename)
 	Elf32_Phdr	*phtab;
 	 int	i, j;	// Counters
 	char	*libPath;
-	Uint	iRealBase = -1;
-	Uint	iBaseDiff;
+	intptr_t	iRealBase = -1;
+	intptr_t	iBaseDiff;
 	 int	iSegmentCount;
 	 int	iSymCount;
 	Elf32_Rel	*rel = NULL;
@@ -310,7 +319,7 @@ void *Elf32Relocate(void *Base, char **envp, const char *Filename)
 	// Check if a PT_DYNAMIC segement was found
 	if(!dynamicTab) {
 		SysDebug(" elf_relocate: No PT_DYNAMIC segment in image %p, returning", Base);
-		return (void *)hdr->entrypoint + iBaseDiff;
+		return (void *)(intptr_t)(hdr->entrypoint + iBaseDiff);
 	}
 	
 	// Adjust Dynamic Table
@@ -339,7 +348,7 @@ void *Elf32Relocate(void *Base, char **envp, const char *Filename)
 		// --- Hash Table --
 		case DT_HASH:
 			if(iBaseDiff != 0)	dynamicTab[j].d_val += iBaseDiff;
-			iSymCount = ((Uint*)(dynamicTab[j].d_val))[1];
+			iSymCount = ((Elf32_Word*)(dynamicTab[j].d_val))[1];
 //			hdr->misc.HashTable = dynamicTab[j].d_val;	// Saved in unused bytes of ident
 			break;
 		}
@@ -419,7 +428,7 @@ void *Elf32Relocate(void *Base, char **envp, const char *Filename)
 	
 	DEBUGS(" elf_relocate: Beginning Relocation");
 	
-	void elf_doRelocate(Uint r_info, Uint32 *ptr, Uint32 addend, Elf32_Sym *symtab)
+	void elf_doRelocate(uint32_t r_info, uint32_t *ptr, Elf32_Addr addend, Elf32_Sym *symtab)
 	{
 		 int	type = ELF32_R_TYPE(r_info);
 		 int	sym = ELF32_R_SYM(r_info);
@@ -530,6 +539,120 @@ void *Elf32Relocate(void *Base, char **envp, const char *Filename)
  * \fn int ElfGetSymbol(Uint Base, const char *name, void **ret)
  */
 int ElfGetSymbol(void *Base, const char *Name, void **ret)
+{
+	Elf32_Ehdr	*hdr = Base;
+
+	switch(hdr->e_ident[4])
+	{
+	case ELFCLASS32:
+		return Elf32GetSymbol(Base, Name, ret);
+	case ELFCLASS64:
+		return Elf64GetSymbol(Base, Name, ret);
+	default:
+		SysDebug("ld-acess - ElfRelocate: Unknown file class %i", hdr->e_ident[4]);
+		return 0;
+	}
+}
+
+int Elf64GetSymbol(void *Base, const char *Name, void **Ret)
+{
+	Elf64_Ehdr	*hdr = Base;
+	Elf64_Sym	*symtab;
+	 int	nbuckets = 0;
+	 int	iSymCount = 0;
+	 int	i;
+	Elf64_Word	*pBuckets;
+	Elf64_Word	*pChains;
+	uint32_t	iNameHash;
+	const char	*dynstrtab;
+	uintptr_t	iBaseDiff = -1;
+
+//	DEBUGS("sizeof(uint32_t) = %i, sizeof(Elf64_Word) = %i", sizeof(uint32_t), sizeof(Elf64_Word));
+
+	dynstrtab = NULL;
+	pBuckets = NULL;
+	symtab = NULL;
+
+	// Catch the current executable
+	if( !pBuckets )
+	{
+		Elf64_Phdr	*phtab;
+		Elf64_Dyn	*dynTab = NULL;
+		 int	j;
+		
+		// Locate the tables
+		phtab = (void*)( Base + hdr->e_phoff );
+		for( i = 0; i < hdr->e_phnum; i ++ )
+		{
+			if(phtab[i].p_type == PT_LOAD && iBaseDiff > phtab[i].p_vaddr)
+				iBaseDiff = phtab[i].p_vaddr;
+			if( phtab[i].p_type == PT_DYNAMIC ) {
+				dynTab = (void*)(intptr_t)phtab[i].p_vaddr;
+			}
+		}
+		if( !dynTab ) {
+			SysDebug("ERROR - Unable to find DYNAMIC segment in %p", Base);
+			return 0;
+		}
+		iBaseDiff = (intptr_t)Base - iBaseDiff;	// Make iBaseDiff actually the diff
+		dynTab = (void*)( (intptr_t)dynTab + iBaseDiff );
+		
+		for( j = 0; dynTab[j].d_tag != DT_NULL; j++)
+		{
+			switch(dynTab[j].d_tag)
+			{
+			// --- Symbol Table ---
+			case DT_SYMTAB:
+				symtab = (void*)(intptr_t) dynTab[j].d_un.d_val;	// Rebased in Relocate
+				break;
+			case DT_STRTAB:
+				dynstrtab = (void*)(intptr_t) dynTab[j].d_un.d_val;
+				break;
+			// --- Hash Table --
+			case DT_HASH:
+				pBuckets = (void*)(intptr_t) dynTab[j].d_un.d_val;
+				break;
+			}
+		}
+	}
+//	DEBUGS("pBuckets = %p", pBuckets);
+
+	nbuckets = pBuckets[0];
+	iSymCount = pBuckets[1];
+	pBuckets = &pBuckets[2];
+//	DEBUGS("nbuckets = %i", nbuckets);
+	pChains = &pBuckets[ nbuckets ];
+	
+	// Get hash
+	iNameHash = ElfHashString(Name);
+	iNameHash %= nbuckets;
+
+	// Walk Chain
+	i = pBuckets[ iNameHash ];
+//	DEBUGS("dynstrtab = %p", dynstrtab);
+//	DEBUGS("symtab = %p, i = %i", symtab, i);
+	if(symtab[i].st_shndx != SHN_UNDEF && strcmp(dynstrtab + symtab[i].st_name, Name) == 0) {
+		*Ret = (void*) (intptr_t) symtab[i].st_value + iBaseDiff;
+		DEBUGS("%s = %p", Name, *Ret);
+		return 1;
+	}
+	
+	while(pChains[i] != STN_UNDEF)
+	{
+		i = pChains[i];
+//		DEBUGS("chains i = %i", i);
+		if(symtab[i].st_shndx != SHN_UNDEF && strcmp(dynstrtab + symtab[i].st_name, Name) == 0) {
+			*Ret = (void*)(intptr_t)symtab[i].st_value + iBaseDiff;
+			DEBUGS("%s = %p", Name, *Ret);
+			return 1;
+		}
+	}
+	
+//	DEBUGS("Elf64GetSymbol: RETURN 0, Symbol '%s' not found", Name);
+	return 0;
+}
+
+int Elf32GetSymbol(void *Base, const char *Name, void **ret)
 {
 	Elf32_Ehdr	*hdr = Base;
 	Elf32_Sym	*symtab;
@@ -538,20 +661,14 @@ int ElfGetSymbol(void *Base, const char *Name, void **ret)
 	 int	i;
 	Uint32	*pBuckets;
 	Uint32	*pChains;
-	Uint	iNameHash;
+	uint32_t	iNameHash;
 	const char	*dynstrtab;
 	uintptr_t	iBaseDiff = -1;
 
 	//DEBUGS("ElfGetSymbol: (Base=0x%x, Name='%s')", Base, Name);
-	#if 0
-	pBuckets = (void *) (intptr_t) hdr->misc.HashTable;
-	symtab = (void *) (intptr_t) hdr->misc.SymTable;
-	dynstrtab = (void *) (intptr_t) hdr->misc.StrTab;
-	#else
 	dynstrtab = NULL;
 	pBuckets = NULL;
 	symtab = NULL;
-	#endif
 
 	// Catch the current executable
 	if( !pBuckets )
@@ -571,7 +688,7 @@ int ElfGetSymbol(void *Base, const char *Name, void **ret)
 			}
 		}
 		if( !dynTab ) {
-			SysDebug("ERROR - Unable to find DYNAMIC segment in %p");
+			SysDebug("ERROR - Unable to find DYNAMIC segment in %p", Base);
 			return 0;
 		}
 		iBaseDiff = (intptr_t)Base - iBaseDiff;	// Make iBaseDiff actually the diff
@@ -596,7 +713,7 @@ int ElfGetSymbol(void *Base, const char *Name, void **ret)
 		}
 		
 		#if 0
-		hdr->misc.HashTable = pBucktets;
+		hdr->misc.HashTable = pBuckets;
 		hdr->misc.SymTable = symtab;
 		hdr->misc.StrTab = dynstrtab;
 		#endif
diff --git a/Usermode/Libraries/ld-acess.so_src/elf32.h b/Usermode/Libraries/ld-acess.so_src/elf32.h
index 983917bd..580bbb4a 100644
--- a/Usermode/Libraries/ld-acess.so_src/elf32.h
+++ b/Usermode/Libraries/ld-acess.so_src/elf32.h
@@ -6,6 +6,12 @@
 #ifndef _ELF32_H
 #define _ELF32_H
 
+#include <stdint.h>
+
+typedef uint32_t	Elf32_Addr;
+typedef uint32_t	Elf32_Word;
+typedef int32_t 	Elf32_Sword;
+
 #define ELFCLASS32	1
 
 /**
@@ -13,8 +19,8 @@
  \brief ELF File Header
 */
 struct sElf32_Ehdr {
-	Uint8	e_ident[16];	//!< Identifier Bytes
-	Uint16	filetype;	//!< File Type
+	uint8_t	e_ident[16];	//!< Identifier Bytes
+	uint16_t	filetype;	//!< File Type
 	Uint16	machine;	//!< Machine / Arch
 	Uint32	version;	//!< Version (File?)
 	Uint32	entrypoint;	//!< Entry Point
@@ -121,9 +127,9 @@ enum {
 
 struct sElf32_Phdr {
 	Uint32	Type;
-	Uint	Offset;
-	Uint	VAddr;
-	Uint	PAddr;
+	Uint32	Offset;
+	Elf32_Addr	VAddr;
+	Elf32_Addr	PAddr;
 	Uint32	FileSize;
 	Uint32	MemSize;
 	Uint32	Flags;
@@ -138,7 +144,7 @@ struct elf32_rel_s {
 struct elf32_rela_s {
 	Uint32	r_offset;
 	Uint32	r_info;
-	Sint32	r_addend;
+	Elf32_Sword	r_addend;
 };
 
 enum {
diff --git a/Usermode/Libraries/ld-acess.so_src/loadlib.c b/Usermode/Libraries/ld-acess.so_src/loadlib.c
index 9a1bc10d..182109bf 100644
--- a/Usermode/Libraries/ld-acess.so_src/loadlib.c
+++ b/Usermode/Libraries/ld-acess.so_src/loadlib.c
@@ -3,6 +3,7 @@
  By thePowersGang
 */
 #include "common.h"
+#include <stdint.h>
 
 #define DEBUG	1
 
@@ -61,7 +62,7 @@ void *LoadLibrary(const char *SoName, const char *SearchDir, char **envp)
 	void	*base;
 	void	(*fEntry)(void *, int, char *[], char**);
 	
-	DEBUGS("LoadLibrary: (SoName='%s', SearchDir='%s', envp=0x%x)", SoName, SearchDir, envp);
+	DEBUGS("LoadLibrary: (SoName='%s', SearchDir='%s', envp=%p)", SoName, SearchDir, envp);
 	
 	// Create Temp Name
 	filename = FindLibrary(sTmpName, SoName, SearchDir);
@@ -82,13 +83,13 @@ void *LoadLibrary(const char *SoName, const char *SearchDir, char **envp)
 		return 0;
 	}
 	
-	DEBUGS(" LoadLibrary: iArg=%p, iEntry=0x%x", base, fEntry);
+	DEBUGS(" LoadLibrary: iArg=%p, fEntry=%p", base, fEntry);
 	
 	// Load Symbols
 	fEntry = DoRelocate( base, envp, filename );
 	
 	// Call Entrypoint
-	DEBUGS(" LoadLibrary: '%s' Entry 0x%x", SoName, fEntry);
+	DEBUGS(" LoadLibrary: '%s' Entry %p", SoName, fEntry);
 	fEntry(base, 0, NULL, envp);
 	
 	DEBUGS("LoadLibrary: RETURN 1");
@@ -108,7 +109,7 @@ void *IsFileLoaded(const char *file)
 		if(gLoadedLibraries[i].Base == 0)	break;	// Last entry has Base set to NULL
 		DEBUGS(" strcmp('%s', '%s')", gLoadedLibraries[i].Name, file);
 		if(strcmp(gLoadedLibraries[i].Name, file) == 0) {
-			DEBUGS("IsFileLoaded: Found %i (0x%x)", i, gLoadedLibraries[i].Base);
+			DEBUGS("IsFileLoaded: Found %i (%p)", i, gLoadedLibraries[i].Base);
 			return gLoadedLibraries[i].Base;
 		}
 	}
@@ -125,7 +126,7 @@ void AddLoaded(const char *File, void *base)
 	 int	i, length;
 	char	*name = gsNextAvailString;
 	
-	DEBUGS("AddLoaded: (File='%s', base=0x%x)", File, base);
+	DEBUGS("AddLoaded: (File='%s', base=%p)", File, base);
 	
 	// Find a free slot
 	for( i = 0; i < MAX_LOADED_LIBRARIES; i ++ )
@@ -149,7 +150,7 @@ void AddLoaded(const char *File, void *base)
 	strcpy(name, File);
 	gLoadedLibraries[i].Name = name;
 	gsNextAvailString = &name[length+1];
-	DEBUGS("'%s' (0x%x) loaded as %i", name, base, i);
+	DEBUGS("'%s' (%p) loaded as %i", name, base, i);
 	return;
 }
 
@@ -227,11 +228,13 @@ void *GetSymbol(const char *name)
 */
 int GetSymbolFromBase(void *base, const char *name, void **ret)
 {
-	if(*(Uint32*)base == (0x7F|('E'<<8)|('L'<<16)|('F'<<24)))
+	uint8_t	*hdr = base;
+	if(hdr[0] == 0x7F && hdr[1] == 'E' && hdr[2] == 'L' && hdr[3] == 'F')
 		return ElfGetSymbol(base, name, ret);
-	if(*(Uint16*)base == ('M'|('Z'<<8)))
+	if(hdr[0] == 'M' && hdr[1] == 'Z')
 		return PE_GetSymbol(base, name, ret);
-	SysDebug("Unknown type at %p", base);
+	SysDebug("Unknown type at %p (%02x %02x %02x %02x)", base,
+		hdr[0], hdr[1], hdr[2], hdr[3]);
 	return 0;
 }
 
diff --git a/Usermode/Libraries/ld-acess.so_src/main.c b/Usermode/Libraries/ld-acess.so_src/main.c
index 49bbe2de..6ccdc0c1 100644
--- a/Usermode/Libraries/ld-acess.so_src/main.c
+++ b/Usermode/Libraries/ld-acess.so_src/main.c
@@ -62,7 +62,7 @@ void *SoMain(void *base)
 */
 void *DoRelocate(void *base, char **envp, const char *Filename)
 {
-	Uint8	*hdr = base;
+	uint8_t	*hdr = base;
 	// Load Executable
 	if(memcmp(base, "\x7F""ELF", 4) == 0)
 		return ElfRelocate(base, envp, Filename);
-- 
GitLab