www.pudn.com > potemkin_sourceforPSP.rar > ElfReader.cpp


#include "stdafx.h" 
#include "../MemMap.h" 
#include "../Host.h" 
 
#include "../MIPS/MIPSTables.h" 
#include "ElfReader.h" 
 
#include "../PSP/HLE/sceKernelMemory.h" 
 
 
const char *ElfReader::GetSectionName(int section) 
{ 
	if (sections[section].sh_type == SHT_NULL) 
		return 0; 
 
	int nameOffset = sections[section].sh_name; 
	char *ptr = (char*)GetSectionDataPtr(header->e_shstrndx); 
 
	if (ptr) 
		return ptr + nameOffset; 
	else 
		return 0; 
} 
 
 
 
void addrToHiLo(u32 addr, u16 &hi, s16 &lo) 
{ 
	lo = (addr & 0xFFFF); 
	u32 naddr = addr - lo; 
	hi = naddr>>16; 
	 
	u32 test = (hi<<16) + lo; 
	if (test != addr) 
	{ 
		DebugBreak(); 
	} 
} 
 
 
bool ElfReader::LoadInto(u32 vaddr) 
{ 
	LOG(LOADER,"String section: %i", header->e_shstrndx); 
 
	//TODO - Check header->e_ident here 
	//let's dump string section 
	/* 
	char *ptr = (char*)GetSectionDataPtr(header->e_shstrndx); 
	if (*ptr == 0) 
		ptr++; 
	ptr+=513; 
	while (*ptr != 0) 
	{ 
		int len = strlen(ptr); 
		LOG(LOADER,"XX %s",ptr); 
		ptr+=len; 
		ptr++; 
	}*/ 
 
	sectionOffsets = new u32[GetNumSections()]; 
	sectionAddrs = new u32[GetNumSections()]; 
	 
	// Should we relocate? 
	bRelocate = (header->e_type != ET_EXEC); 
 
	entryPoint = header->e_entry; 
	if (bRelocate) 
	{ 
		LOG(LOADER,"Relocatable module"); 
		entryPoint += vaddr; 
	} 
	else 
	{ 
		LOG(LOADER,"Prerelocated executable"); 
	} 
 
	LOG(LOADER,"%i segments:", header->e_phnum); 
 
	// First pass : Get the damn bits into RAM 
	u32 segmentVAddr[32]; 
 
	u32 baseAddress = bRelocate?vaddr:0; 
	for (int i=0; ie_phnum; i++) 
	{ 
		Elf32_Phdr *p = segments + i; 
 
		LOG(LOADER, "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]; 
 
			u8 *src = GetSegmentPtr(i); 
			u8 *dst = GetMemPointer(writeAddr); 
			u32 srcSize = p->p_filesz; 
			u32 dstSize = p->p_memsz; 
 
			PSPHLE::userMemory.AllocAt(writeAddr, dstSize, "ELF"); 
 
			memcpy(dst, src, srcSize); 
			if (srcSize < dstSize) 
			{ 
				//memset(dst + srcSize, 0, dstSize-srcSize); //zero out bss 
			} 
 
			LOG(LOADER,"Loadable Segment Copied to %08x, size %08x", writeAddr, p->p_memsz); 
		} 
	} 
	PSPHLE::userMemory.ListBlocks(); 
 
	LOG(LOADER,"%i sections:", header->e_shnum); 
 
	for (int i=0; ish_addr + baseAddress; 
		sectionOffsets[i] = writeAddr - vaddr; 
		sectionAddrs[i] = writeAddr; 
 
		if (s->sh_flags & SHF_ALLOC) 
		{ 
			LOG(LOADER,"Data Section found: %s     Sitting at %08x, size %08x", name, writeAddr, s->sh_size); 
	 
		} 
		else 
		{ 
			LOG(LOADER,"NonData Section found: %s     Ignoring (size=%08x) (flags=%08x)", name, s->sh_size, s->sh_flags); 
		} 
	} 
 
	LOG(LOADER,"Relocations:"); 
 
	// Second pass: Do necessary relocations 
	for (int i=0; ish_type == SHT_PSPREL) 
		{ 
			//We have a relocation table! 
			int symbolSection = s->sh_link; 
			int sectionToModify = s->sh_info; 
 
			if (!(sections[sectionToModify].sh_flags & SHF_ALLOC)) 
			{ 
				LOG(LOADER,"Trying to relocate non-loaded section %s",GetSectionName(sectionToModify)); 
				continue; 
			} 
			 
			int numRelocs = s->sh_size / sizeof(Elf32_Rel); 
 
			Elf32_Rel *rels = (Elf32_Rel *)GetSectionDataPtr(i); 
 
			LOG(LOADER,"%s: Performing %i relocations on %s",name,numRelocs,GetSectionName(sectionToModify)); 
 
			for (int r = 0; r < numRelocs; r++) 
			{ 
				u32 info = rels[r].r_info; 
				u32 addr = rels[r].r_offset; 
 
 
				int type = info & 0xf; 
 
				int readwrite = (info>>8) & 0xff;  
				int relative  = (info>>16) & 0xff; 
				 
				//0 = code 
				//1 = data 
				 
				addr += segmentVAddr[readwrite]; 
				 
				u32 op = ReadMem32(addr); 
 
 
				const bool log = false; 
 
 
				//log=true; 
				if (log) 
				{ 
					LOG(LOADER,"rel at: %08x  type: %08x",addr,info); 
				} 
				u32 relocateTo = segmentVAddr[relative]; 
 
#define R_MIPS32 2 
#define R_MIPS26 4 
#define R_MIPS16_HI 5 
#define R_MIPS16_LO 6 
 
				switch (type)  
				{ 
				case R_MIPS32: 
					if (log) 
						LOG(LOADER,"Full address reloc %08x", addr); 
					//full address, no problemo 
					//if (readwrite != 0) 
						op += relocateTo; 
					break; 
 
				case R_MIPS26: //j, jal 
					//add on to put in correct address space 
					if (log) 
						LOG(LOADER,"j/jal reloc %08x", addr); 
					op = op & 0xFC000000 | (((op&0x03FFFFFF)+(relocateTo>>2))&0x03FFFFFFF); 
					break; 
 
				case R_MIPS16_HI: //lui part of lui-addiu pairs 
					{ 
						if (log) 
							LOG(LOADER,"HI reloc %08x", addr); 
 
						u32 cur = (op & 0xFFFF) << 16; 
						u16 hi = 0; 
						s16 lo; 
						bool found = false; 
						for (int t = r + 1; tsh_type == SHT_REL) 
		{ 
			LOG(LOADER, "Traditional relocation section found."); 
			if (bRelocate) 
			{ 
				LOG(LOADER, "Binary is prerelocated. Skipping relocations."); 
			} 
			else 
			{ 
				//We have a relocation table! 
				int symbolSection = s->sh_link; 
				int sectionToModify = s->sh_info; 
				if (!(sections[sectionToModify].sh_flags & SHF_ALLOC)) 
				{ 
					LOG(LOADER,"Trying to relocate non-loaded section %s, ignoring",GetSectionName(sectionToModify)); 
					continue; 
				} 
				LOG(LOADER,"Traditional relocations unsupported."); 
			} 
		} 
	} 
 
	LOG(LOADER,"Done."); 
	return true; 
} 
 
 
SectionID ElfReader::GetSectionByName(const char *name, int firstSection) 
{ 
	for (int i = firstSection; i < header->e_shnum; i++) 
	{ 
		const char *secname = GetSectionName(i); 
 
		if (secname != 0 && strcmp(name, secname) == 0) 
		{ 
			return i; 
		} 
	} 
	return -1; 
} 
 
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> 4; 
			int type = symtab[sym].st_info & 0xF; 
			int sectionIndex = symtab[sym].st_shndx; 
			int value = symtab[sym].st_value; 
			const char *name = stringBase + symtab[sym].st_name; 
 
			if (bRelocate) 
				value += sectionAddrs[sectionIndex]; 
			SymbolType symtype = ST_DATA; 
 
			 
			switch (type) 
			{ 
			case STT_OBJECT: 
				symtype = ST_DATA; break; 
			case STT_FUNC: 
				symtype = ST_FUNCTION; break; 
			default: 
				continue; 
			} 
			host->AddSymbol(name, value, size, symtype); 
			hasSymbols = true; 
			//... 
		} 
	} 
	return hasSymbols; 
}