Răsfoiți Sursa

added Dolphin's ELF reader to the project

bunnei 12 ani în urmă
părinte
comite
872d9ae87f
3 a modificat fișierele cu 594 adăugiri și 0 ștergeri
  1. 238 0
      src/core/src/elf/elf_reader.cpp
  2. 75 0
      src/core/src/elf/elf_reader.h
  3. 281 0
      src/core/src/elf/elf_types.h

+ 238 - 0
src/core/src/elf/elf_reader.cpp

@@ -0,0 +1,238 @@
+// Copyright 2013 Dolphin Emulator Project
+// Licensed under GPLv2
+// Refer to the license.txt file included.
+
+#include <string>
+
+#include "common.h"
+#include "mem_map.h"
+
+#include "elf/elf_reader.h"
+//#include "Core/Debugger/Debugger_SymbolMap.h"
+//#include "Core/HW/Memmap.h"
+//#include "Core/PowerPC/PPCSymbolDB.h"
+
+//void bswap(Elf32_Word &w) {w = Common::swap32(w);}
+//void bswap(Elf32_Half &w) {w = Common::swap16(w);}
+
+#define bswap(w) w // Dirty bswap disable for now... 3DS is little endian, anyway
+
+static void byteswapHeader(Elf32_Ehdr &ELF_H)
+{
+	bswap(ELF_H.e_type);
+	bswap(ELF_H.e_machine);
+	bswap(ELF_H.e_ehsize);
+	bswap(ELF_H.e_phentsize);
+	bswap(ELF_H.e_phnum);
+	bswap(ELF_H.e_shentsize);
+	bswap(ELF_H.e_shnum);
+	bswap(ELF_H.e_shstrndx);
+	bswap(ELF_H.e_version);
+	bswap(ELF_H.e_entry);
+	bswap(ELF_H.e_phoff);
+	bswap(ELF_H.e_shoff);
+	bswap(ELF_H.e_flags);
+}
+
+static void byteswapSegment(Elf32_Phdr &sec)
+{
+	bswap(sec.p_align);
+	bswap(sec.p_filesz);
+	bswap(sec.p_flags);
+	bswap(sec.p_memsz);
+	bswap(sec.p_offset);
+	bswap(sec.p_paddr);
+	bswap(sec.p_vaddr);
+	bswap(sec.p_type);
+}
+
+static void byteswapSection(Elf32_Shdr &sec)
+{
+	bswap(sec.sh_addr);
+	bswap(sec.sh_addralign);
+	bswap(sec.sh_entsize);
+	bswap(sec.sh_flags);
+	bswap(sec.sh_info);
+	bswap(sec.sh_link);
+	bswap(sec.sh_name);
+	bswap(sec.sh_offset);
+	bswap(sec.sh_size);
+	bswap(sec.sh_type);
+}
+
+ElfReader::ElfReader(void *ptr)
+{
+	base = (char*)ptr;
+	base32 = (u32 *)ptr;
+	header = (Elf32_Ehdr*)ptr;
+	byteswapHeader(*header);
+
+	segments = (Elf32_Phdr *)(base + header->e_phoff);
+	sections = (Elf32_Shdr *)(base + header->e_shoff);
+
+	for (int i = 0; i < GetNumSegments(); i++)
+	{
+		byteswapSegment(segments[i]);
+	}
+
+	for (int i = 0; i < GetNumSections(); i++)
+	{
+		byteswapSection(sections[i]);
+	}
+	entryPoint = header->e_entry;
+}
+
+const char *ElfReader::GetSectionName(int section) const
+{
+	if (sections[section].sh_type == SHT_NULL)
+		return nullptr;
+
+	int nameOffset = sections[section].sh_name;
+	char *ptr = (char*)GetSectionDataPtr(header->e_shstrndx);
+
+	if (ptr)
+		return ptr + nameOffset;
+	else
+		return nullptr;
+}
+
+bool ElfReader::LoadInto(u32 vaddr)
+{
+	DEBUG_LOG(MASTER_LOG,"String section: %i", header->e_shstrndx);
+
+//	sectionOffsets = new u32[GetNumSections()];
+//	sectionAddrs = new u32[GetNumSections()];
+
+	// Should we relocate?
+	bRelocate = (header->e_type != ET_EXEC);
+
+	if (bRelocate)
+	{
+		DEBUG_LOG(MASTER_LOG,"Relocatable module");
+		entryPoint += vaddr;
+	}
+	else
+	{
+		DEBUG_LOG(MASTER_LOG,"Prerelocated executable");
+	}
+
+	INFO_LOG(MASTER_LOG,"%i segments:", header->e_phnum);
+
+	// First pass : Get the bits into RAM
+	u32 segmentVAddr[32];
+
+	u32 baseAddress = bRelocate?vaddr:0;
+	for (int i = 0; i < header->e_phnum; i++)
+	{
+		Elf32_Phdr *p = segments + i;
+
+		INFO_LOG(MASTER_LOG, "Type: %i Vaddr: %08x Filesz: %i Memsz: %i ", p->p_type, p->p_vaddr, p->p_filesz, p->p_memsz);
+
+		if (p->p_type == PT_LOAD)
+		{
+			segmentVAddr[i] = baseAddress + p->p_vaddr;
+			u32 writeAddr = segmentVAddr[i];
+
+			const u8 *src = GetSegmentPtr(i);
+			u8 *dst = Memory::GetPointer(writeAddr);
+			u32 srcSize = p->p_filesz;
+			u32 dstSize = p->p_memsz;
+			u32 *s = (u32*)src;
+			u32 *d = (u32*)dst;
+			for (int j = 0; j < (int)(srcSize + 3) / 4; j++)
+			{
+				*d++ = /*_byteswap_ulong*/(*s++);
+			}
+			if (srcSize < dstSize)
+			{
+				//memset(dst + srcSize, 0, dstSize-srcSize); //zero out bss
+			}
+			INFO_LOG(MASTER_LOG,"Loadable Segment Copied to %08x, size %08x", writeAddr, p->p_memsz);
+		}
+	}
+
+	/*
+	LOG(MASTER_LOG,"%i sections:", header->e_shnum);
+
+	for (int i=0; i<GetNumSections(); i++)
+	{
+		Elf32_Shdr *s = &sections[i];
+		const char *name = GetSectionName(i);
+
+		u32 writeAddr = s->sh_addr + baseAddress;
+		sectionOffsets[i] = writeAddr - vaddr;
+		sectionAddrs[i] = writeAddr;
+
+		if (s->sh_flags & SHF_ALLOC)
+		{
+			LOG(MASTER_LOG,"Data Section found: %s     Sitting at %08x, size %08x", name, writeAddr, s->sh_size);
+
+		}
+		else
+		{
+			LOG(MASTER_LOG,"NonData Section found: %s     Ignoring (size=%08x) (flags=%08x)", name, s->sh_size, s->sh_flags);
+		}
+	}
+*/
+	INFO_LOG(MASTER_LOG,"Done loading.");
+	return true;
+}
+
+SectionID ElfReader::GetSectionByName(const char *name, int firstSection) const
+{
+	for (int i = firstSection; i < header->e_shnum; i++)
+	{
+		const char *secname = GetSectionName(i);
+
+		if (secname != nullptr && strcmp(name, secname) == 0)
+			return i;
+	}
+	return -1;
+}
+
+/* TODO(bunnei): The following is verbatim from Dolphin - needs to be updated for this project:
+
+bool ElfReader::LoadSymbols()
+{
+	bool hasSymbols = false;
+	SectionID sec = GetSectionByName(".symtab");
+	if (sec != -1)
+	{
+		int stringSection = sections[sec].sh_link;
+		const char *stringBase = (const char *)GetSectionDataPtr(stringSection);
+
+		//We have a symbol table!
+		Elf32_Sym *symtab = (Elf32_Sym *)(GetSectionDataPtr(sec));
+		int numSymbols = sections[sec].sh_size / sizeof(Elf32_Sym);
+		for (int sym = 0; sym < numSymbols; sym++)
+		{
+			int size = Common::swap32(symtab[sym].st_size);
+			if (size == 0)
+				continue;
+
+			// int bind = symtab[sym].st_info >> 4;
+			int type = symtab[sym].st_info & 0xF;
+			int sectionIndex = Common::swap16(symtab[sym].st_shndx);
+			int value = Common::swap32(symtab[sym].st_value);
+			const char *name = stringBase + Common::swap32(symtab[sym].st_name);
+			if (bRelocate)
+				value += sectionAddrs[sectionIndex];
+
+			int symtype = Symbol::SYMBOL_DATA;
+			switch (type)
+			{
+			case STT_OBJECT:
+				symtype = Symbol::SYMBOL_DATA; break;
+			case STT_FUNC:
+				symtype = Symbol::SYMBOL_FUNCTION; break;
+			default:
+				continue;
+			}
+			g_symbolDB.AddKnownSymbol(value, size, name, symtype);
+			hasSymbols = true;
+		}
+	}
+	g_symbolDB.Index();
+	return hasSymbols;
+}
+*/

+ 75 - 0
src/core/src/elf/elf_reader.h

@@ -0,0 +1,75 @@
+// Copyright 2013 Dolphin Emulator Project
+// Licensed under GPLv2
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "elf/elf_types.h"
+
+enum KnownElfTypes
+{
+	KNOWNELF_PSP = 0,
+	KNOWNELF_DS  = 1,
+	KNOWNELF_GBA = 2,
+	KNOWNELF_GC  = 3,
+};
+
+typedef int SectionID;
+
+class ElfReader
+{
+private:
+	char *base;
+	u32 *base32;
+
+	Elf32_Ehdr *header;
+	Elf32_Phdr *segments;
+	Elf32_Shdr *sections;
+
+	u32 *sectionAddrs;
+	bool bRelocate;
+	u32 entryPoint;
+
+public:
+	ElfReader(void *ptr);
+	~ElfReader() { }
+
+	u32 Read32(int off) const { return base32[off>>2]; }
+
+	// Quick accessors
+	ElfType GetType() const { return (ElfType)(header->e_type); }
+	ElfMachine GetMachine() const { return (ElfMachine)(header->e_machine); }
+	u32 GetEntryPoint() const { return entryPoint; }
+	u32 GetFlags() const { return (u32)(header->e_flags); }
+	bool LoadInto(u32 vaddr);
+	bool LoadSymbols();
+
+	int GetNumSegments() const { return (int)(header->e_phnum); }
+	int GetNumSections() const { return (int)(header->e_shnum); }
+	const u8 *GetPtr(int offset) const { return (u8*)base + offset; }
+	const char *GetSectionName(int section) const;
+	const u8 *GetSectionDataPtr(int section) const
+	{
+		if (section < 0 || section >= header->e_shnum)
+			return nullptr;
+		if (sections[section].sh_type != SHT_NOBITS)
+			return GetPtr(sections[section].sh_offset);
+		else
+			return nullptr;
+	}
+	bool IsCodeSection(int section) const
+	{
+		return sections[section].sh_type == SHT_PROGBITS;
+	}
+	const u8 *GetSegmentPtr(int segment)
+	{
+		return GetPtr(segments[segment].p_offset);
+	}
+	u32 GetSectionAddr(SectionID section) const { return sectionAddrs[section]; }
+	int GetSectionSize(SectionID section) const { return sections[section].sh_size; }
+	SectionID GetSectionByName(const char *name, int firstSection = 0) const; //-1 for not found
+
+	bool DidRelocate() {
+		return bRelocate;
+	}
+};

+ 281 - 0
src/core/src/elf/elf_types.h

@@ -0,0 +1,281 @@
+// Copyright 2013 Dolphin Emulator Project
+// Licensed under GPLv2
+// Refer to the license.txt file included.
+
+#pragma once
+
+// ELF Header Constants
+
+// File type
+enum ElfType
+{
+	ET_NONE   = 0,
+	ET_REL    = 1,
+	ET_EXEC   = 2,
+	ET_DYN    = 3,
+	ET_CORE   = 4,
+	ET_LOPROC = 0xFF00,
+	ET_HIPROC = 0xFFFF,
+};
+
+// Machine/Architecture
+enum ElfMachine
+{
+	EM_NONE  = 0,
+	EM_M32   = 1,
+	EM_SPARC = 2,
+	EM_386   = 3,
+	EM_68K   = 4,
+	EM_88K   = 5,
+	EM_860   = 7,
+	EM_MIPS  = 8
+};
+
+// File version
+#define EV_NONE    0
+#define EV_CURRENT 1
+
+// Identification index
+#define EI_MAG0    0
+#define EI_MAG1    1
+#define EI_MAG2    2
+#define EI_MAG3    3
+#define EI_CLASS   4
+#define EI_DATA    5
+#define EI_VERSION 6
+#define EI_PAD     7
+#define EI_NIDENT 16
+
+// Magic number
+#define ELFMAG0 0x7F
+#define ELFMAG1  'E'
+#define ELFMAG2  'L'
+#define ELFMAG3  'F'
+
+// File class
+#define ELFCLASSNONE 0
+#define ELFCLASS32   1
+#define ELFCLASS64   2
+
+// Encoding
+#define ELFDATANONE 0
+#define ELFDATA2LSB 1
+#define ELFDATA2MSB 2
+
+
+
+// Sections constants
+
+// Section indexes
+#define SHN_UNDEF          0
+#define SHN_LORESERVE 0xFF00
+#define SHN_LOPROC    0xFF00
+#define SHN_HIPROC    0xFF1F
+#define SHN_ABS       0xFFF1
+#define SHN_COMMON    0xFFF2
+#define SHN_HIRESERVE 0xFFFF
+
+// Section types
+#define SHT_NULL            0
+#define SHT_PROGBITS        1
+#define SHT_SYMTAB          2
+#define SHT_STRTAB          3
+#define SHT_RELA            4
+#define SHT_HASH            5
+#define SHT_DYNAMIC         6
+#define SHT_NOTE            7
+#define SHT_NOBITS          8
+#define SHT_REL             9
+#define SHT_SHLIB          10
+#define SHT_DYNSYM         11
+#define SHT_LOPROC 0x70000000
+#define SHT_HIPROC 0x7FFFFFFF
+#define SHT_LOUSER 0x80000000
+#define SHT_HIUSER 0xFFFFFFFF
+
+// Custom section types
+#define SHT_PSPREL 0x700000a0
+
+
+// Section flags
+enum ElfSectionFlags
+{
+	SHF_WRITE     = 0x1,
+	SHF_ALLOC     = 0x2,
+	SHF_EXECINSTR = 0x4,
+	SHF_MASKPROC  = 0xF0000000,
+};
+
+// Symbol binding
+#define STB_LOCAL   0
+#define STB_GLOBAL  1
+#define STB_WEAK    2
+#define STB_LOPROC 13
+#define STB_HIPROC 15
+
+// Symbol types
+#define STT_NOTYPE   0
+#define STT_OBJECT   1
+#define STT_FUNC     2
+#define STT_SECTION  3
+#define STT_FILE     4
+#define STT_LOPROC  13
+#define STT_HIPROC  15
+
+// Undefined name
+#define STN_UNDEF 0
+
+// Relocation types
+#define R_386_NONE      0
+#define R_386_32        1
+#define R_386_PC32      2
+#define R_386_GOT32     3
+#define R_386_PLT32     4
+#define R_386_COPY      5
+#define R_386_GLOB_DAT  6
+#define R_386_JMP_SLOT  7
+#define R_386_RELATIVE  8
+#define R_386_GOTOFF    9
+#define R_386_GOTPC    10
+
+// Segment types
+#define PT_NULL             0
+#define PT_LOAD             1
+#define PT_DYNAMIC          2
+#define PT_INTERP           3
+#define PT_NOTE             4
+#define PT_SHLIB            5
+#define PT_PHDR             6
+#define PT_LOPROC  0x70000000
+#define PT_HIPROC  0x7FFFFFFF
+
+// Segment flags
+#define PF_X 1
+#define PF_W 2
+#define PF_R 4
+
+// Dynamic Array Tags
+#define DT_NULL              0
+#define DT_NEEDED            1
+#define DT_PLTRELSZ          2
+#define DT_PLTGOT            3
+#define DT_HASH              4
+#define DT_STRTAB            5
+#define DT_SYMTAB            6
+#define DT_RELA              7
+#define DT_RELASZ            8
+#define DT_RELAENT           9
+#define DT_STRSZ            10
+#define DT_SYMENT           11
+#define DT_INIT             12
+#define DT_FINI             13
+#define DT_SONAME           14
+#define DT_RPATH            15
+#define DT_SYMBOLIC         16
+#define DT_REL              17
+#define DT_RELSZ            18
+#define DT_RELENT           19
+#define DT_PLTREL           20
+#define DT_DEBUG            21
+#define DT_TEXTREL          22
+#define DT_JMPREL           23
+#define DT_LOPROC   0x70000000
+#define DT_HIPROC   0x7FFFFFFF
+
+typedef unsigned int  Elf32_Addr;
+typedef unsigned short Elf32_Half;
+typedef unsigned int  Elf32_Off;
+typedef signed   int  Elf32_Sword;
+typedef unsigned int  Elf32_Word;
+
+
+// ELF file header
+struct Elf32_Ehdr
+{
+	unsigned char e_ident[EI_NIDENT];
+	Elf32_Half    e_type;
+	Elf32_Half    e_machine;
+	Elf32_Word    e_version;
+	Elf32_Addr    e_entry;
+	Elf32_Off     e_phoff;
+	Elf32_Off     e_shoff;
+	Elf32_Word    e_flags;
+	Elf32_Half    e_ehsize;
+	Elf32_Half    e_phentsize;
+	Elf32_Half    e_phnum;
+	Elf32_Half    e_shentsize;
+	Elf32_Half    e_shnum;
+	Elf32_Half    e_shstrndx;
+};
+
+// Section header
+struct Elf32_Shdr
+{
+	Elf32_Word sh_name;
+	Elf32_Word sh_type;
+	Elf32_Word sh_flags;
+	Elf32_Addr sh_addr;
+	Elf32_Off  sh_offset;
+	Elf32_Word sh_size;
+	Elf32_Word sh_link;
+	Elf32_Word sh_info;
+	Elf32_Word sh_addralign;
+	Elf32_Word sh_entsize;
+};
+
+// Segment header
+struct Elf32_Phdr
+{
+	Elf32_Word p_type;
+	Elf32_Off  p_offset;
+	Elf32_Addr p_vaddr;
+	Elf32_Addr p_paddr;
+	Elf32_Word p_filesz;
+	Elf32_Word p_memsz;
+	Elf32_Word p_flags;
+	Elf32_Word p_align;
+};
+
+// Symbol table entry
+struct Elf32_Sym
+{
+	Elf32_Word    st_name;
+	Elf32_Addr    st_value;
+	Elf32_Word    st_size;
+	unsigned char st_info;
+	unsigned char st_other;
+	Elf32_Half    st_shndx;
+};
+
+#define ELF32_ST_BIND(i)   ((i)>>4)
+#define ELF32_ST_TYPE(i)   ((i)&0xf)
+#define ELF32_ST_INFO(b,t) (((b)<<4)+((t)&0xf))
+
+// Relocation entries
+struct Elf32_Rel
+{
+	Elf32_Addr r_offset;
+	Elf32_Word r_info;
+};
+
+struct Elf32_Rela
+{
+	Elf32_Addr  r_offset;
+	Elf32_Word  r_info;
+	Elf32_Sword r_addend;
+};
+
+#define ELF32_R_SYM(i) ((i)>>8)
+#define ELF32_R_TYPE(i) ((unsigned char)(i))
+#define ELF32_R_INFO(s,t) (((s)<<8 )+(unsigned char)(t))
+
+
+struct Elf32_Dyn
+{
+	Elf32_Sword d_tag;
+	union
+	{
+		Elf32_Word d_val;
+		Elf32_Addr d_ptr;
+	} d_un;
+};